diff options
author | Lars Heer <l.heer@gmx.de> | 2013-09-18 05:50:03 +0200 |
---|---|---|
committer | Lars Heer <l.heer@gmx.de> | 2013-09-18 05:50:03 +0200 |
commit | ccf6e0f9c6b0481ed13e0f4794e3fbead750f385 (patch) | |
tree | ed86efb54f7ee41edfba5c89ca519b5fd10aa0d5 /mcast/common/.svn | |
download | vdr-plugin-mcli-ccf6e0f9c6b0481ed13e0f4794e3fbead750f385.tar.gz vdr-plugin-mcli-ccf6e0f9c6b0481ed13e0f4794e3fbead750f385.tar.bz2 |
added vdr-plugin-mcli-0.0.1+svn20120927
Diffstat (limited to 'mcast/common/.svn')
25 files changed, 8334 insertions, 0 deletions
diff --git a/mcast/common/.svn/entries b/mcast/common/.svn/entries new file mode 100644 index 0000000..158235c --- /dev/null +++ b/mcast/common/.svn/entries @@ -0,0 +1,847 @@ +10 + +dir +18963 +svn://reelbox.org/testing/src/vdr-plugins/src/mcli-1/mcast/common +svn://reelbox.org + + + +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + +12be777f-adf9-0310-842f-e37ecc4c7426 + +darwin +dir + +recv_ccpp.c +file + + + + +2012-09-27T17:22:49.630848Z +3088282b10ec5b66a5edbbd1da7bb364 +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + + + + + + + + +49800 + +input.h +file + + + + +2012-09-27T17:22:49.630848Z +14ae9dfd7385824644e7f41891e4431a +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +701 + +tools.h +file + + + + +2012-09-27T17:22:49.634848Z +3b18ae738d8c2f2be127479e3d332d13 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +3001 + +mcast.c +file + + + + +2012-09-27T17:22:49.634848Z +372fb40dbd41035d414020df3c1aedc1 +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + + + + + + + + +19168 + +ciparser.c +file + + + + +2012-09-27T17:22:49.634848Z +1b02f18bba452905d60a1829dbbb8abd +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + + + + + + + + +17272 + +recv_ccpp.h +file + + + + +2012-09-27T17:22:49.634848Z +b9f6b18254b50dfe7956532de35a15bf +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +2358 + +mld_client.c +file + + + + +2012-09-27T17:22:49.634848Z +322113266b07500ca0f71e5565889090 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +8945 + +satlists.h +file + + + + +2012-09-27T17:22:49.634848Z +eb22a7df1560514879ab880a04d71e96 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +2273 + +crc32.c +file + + + + +2012-09-27T17:22:49.634848Z +980e8b3fd7efed5f9d560d02685ce653 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +3829 + +mcast.h +file + + + + +2012-09-27T17:22:49.634848Z +197fd7134d088c87a4735f4526d6b584 +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + + + + + + + + +2165 + +.indent.pro +file + + + + +2012-09-27T17:22:49.634848Z +536d6397e801893325c24ec292dee74f +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +22 + +ciparser.h +file + + + + +2012-09-27T17:22:49.634848Z +d9404810159811a969622947f61d7d72 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +2898 + +list.h +file + + + + +2012-09-27T17:22:49.634848Z +f5c2a2b3d49871370bd06133ecda42ca +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +7470 + +mld.h +file + + + + +2012-09-27T17:22:49.634848Z +2bcbbcdc985f98caf098b8e8e497c2c0 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +8620 + +crc32.h +file + + + + +2012-09-27T17:22:49.634848Z +35c6650ae24801e91dcd2db610364391 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +490 + +interfaces.c +file + + + + +2012-09-27T17:22:49.634848Z +fffc315c72a40a84dcb8154954e91633 +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + + + + + + + + +10873 + +dvb_ca_wrapper.h +file + + + + +2012-09-27T17:22:49.634848Z +bbd78f2a51fdda538e017905d73fe87f +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +546 + +mld_common.c +file + + + + +2012-09-27T17:22:49.634848Z +5ffbd26840cb83a21c509ce0346c7d94 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +7550 + +defs.h +file + + + + +2012-09-27T17:22:49.634848Z +22e61c4d81f14dce61fcf598f6caf402 +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + + + + + + + + +10220 + +interfaces.h +file + + + + +2012-09-27T17:22:49.634848Z +6be8ad42834e22c1b5785d0f2525d1d3 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +1611 + +siparser.c +file + + + + +2012-09-27T17:22:49.634848Z +d8bd70909b3ce29323833a53c83febd1 +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + + + + + + + + +36549 + +version.h +file + + + + +2012-09-27T17:22:49.634848Z +c4bfaad7e6177b714740dcc479f289e5 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +437 + +siparser.h +file + + + + +2012-09-27T17:22:49.634848Z +d52dd1d53b4730204b6edc37ad121d99 +2011-07-12T13:36:23.313379Z +16905 +rollercoaster + + + + + + + + + + + + + + + + + + + + + +12062 + +tools.c +file + + + + +2012-09-27T17:22:49.630848Z +14b8ecc113fb224ca7e655ffe5b4890f +2011-08-18T10:09:14.813360Z +17158 +dirk + + + + + + + + + + + + + + + + + + + + + +22386 + diff --git a/mcast/common/.svn/text-base/.indent.pro.svn-base b/mcast/common/.svn/text-base/.indent.pro.svn-base new file mode 100644 index 0000000..2faef85 --- /dev/null +++ b/mcast/common/.svn/text-base/.indent.pro.svn-base @@ -0,0 +1 @@ +-i8 -br -l0 -ce -npsl diff --git a/mcast/common/.svn/text-base/ciparser.c.svn-base b/mcast/common/.svn/text-base/ciparser.c.svn-base new file mode 100644 index 0000000..5ce563d --- /dev/null +++ b/mcast/common/.svn/text-base/ciparser.c.svn-base @@ -0,0 +1,702 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +//#define TESTING +#ifdef TESTING +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <netinet/in.h> +#include <stdlib.h> + +#include "ciparser.h" +static unsigned char ll[] = { 0x00, 0x01, 0xA0, 0x28, 0x01, 0x90, 0x02, 0x00, 0x05, 0x9F, 0x80, 0x32, 0x1F, 0x03, 0x32, 0xC9, 0x01, 0x00, 0x0F, 0x01, 0x09, 0x06, 0x17, 0x62, 0xE0, 0x65, 0x00, 0x09, 0x09, 0x04, 0x17, 0x02, 0xE1, 0x2D, 0x02, 0x00, 0xA0, 0x00, 0x00, 0x04, 0x00, 0xA1, 0x00, 0x00 }; +static unsigned char lr[] = { 0x00, 0x01, 0x80, 0x02, 0x01, 0x80 }; +static unsigned char la[] = { 0x00, 0x01, 0xA0, 0x07, 0x01, 0x91, 0x04, 0x00, 0x01, 0x00, 0x41, 0x80, 0x02, 0x01, 0x00 }; +static unsigned char lb[] = { 0x00, 0x01, 0xA0, 0x82, 0x00, 0x17, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x31, 0x0E, 0x06, 0x02, 0x06, 0x02, 0x17, 0x02, 0x17, 0x62, 0x01, 0x00, 0x05, 0x00, 0x18, 0x00, 0x80, 0x02, 0x01, 0x00 }; +static unsigned char lc[] = { 0x01, 0x02, 0xA0, 0x5F, 0x02, 0x90, 0x02, 0x00, 0x06, 0x9F, 0x80, 0x32, 0x56, 0x03, 0x03, 0x8B, 0x01, 0x00, 0x00, 0x02, 0x00, 0xA3, 0x00, 0x23, 0x01, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xC3, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x00, 0x94, 0x0D, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xCD, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x02, 0x38, 0x08, 0x04, 0x00, 0x5C, 0x00, 0x23, 0x01, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xC3, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x00, 0x94, 0x0D, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xCD, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x02, 0x38, 0x08 }; +static unsigned char ld[] = { 0x00, 0x01, 0xA0, 0x82, 0x00, 0x10, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x33, 0x07, 0x2D, 0xB9, 0x01, 0x81, 0x00, 0x08, 0x00, 0x80, 0x02, 0x01, 0x00 }; +static unsigned char le[] = { 0x00, 0x01, 0xA0, 0x34, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x32, 0x2B, 0x03, 0x00, 0x0B, 0x01, 0x00, 0x11, 0x01, 0x09, 0x06, 0x17, 0x22, 0xF0, 0x0B, 0x00, 0x0B, 0x09, 0x06, 0x17, 0x02, 0xF0, 0x0B, 0x00, 0x0B, 0x02, 0x06, 0xFF, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x04, 0x07, 0x01, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00}; + +#define dbg(format, arg...) printf("%s:%d " format , __FILE__ , __LINE__ , ## arg) +#define err(format, arg...) {printf("err:%s:%d: %s (%d): " format , __FILE__ , __LINE__ ,strerror(errno), errno, ## arg);print_trace();abort();} +#define info(format, arg...) printf("%s:%d: " format , __FILE__ , __LINE__ ,## arg) +#define warn(format, arg...) printf("%s:%d: " format , __FILE__ , __LINE__ ,## arg) +#define STATIC +#else +//#define DEBUG +#include "headers.h" +#endif + +#define CA_MAX_CAIDS 16 +#define CA_MAX_PIDS 16 +#ifndef CA_MAX_SLOTS +#define CA_MAX_SLOTS 3 +#endif +typedef struct +{ + u_int16_t caid[CA_MAX_CAIDS]; + u_int16_t pid[CA_MAX_PIDS]; + u_int16_t capid[CA_MAX_PIDS]; +} caid_pid_list_t; + +static caid_pid_list_t cpl[CA_MAX_SLOTS]; + +STATIC void dump(u_int8_t *data, int len) +{ +#ifdef DEBUG + int j; + printf("Dump: "); + for(j=0;j<len;j++) { + printf("%02x ",data[j]); + } + printf("\n"); +#endif +} + +STATIC int ci_cpl_find_pid (int slot, int pid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (pid == cpl[slot].pid[i]) + return 1; + } + return 0; +} + +STATIC int ci_cpl_find_caid (int slot, int caid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + int i; + for (i = 0; i < CA_MAX_CAIDS; i++) { + if (caid == cpl[slot].caid[i]) + return 1; + } + return 0; +} + +STATIC int ci_cpl_find_capid (int slot, int pid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (pid == cpl[slot].capid[i]) + return 1; + } + return 0; +} + +STATIC int ci_cpl_delete_pid (int slot, int pid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (cpl[slot].pid[i]==pid) { + cpl[slot].pid[i] = 0; + dbg ("-------> Slot: %d Deleted pid: %04x\n", slot, pid); + return 1; + } + } + return 0; +} + +STATIC int ci_cpl_update_pid (int slot, int pid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + if (!ci_cpl_find_pid (slot, pid)) { + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (!cpl[slot].pid[i]) { + cpl[slot].pid[i] = pid; + dbg ("-------> Slot: %d Added pid: %04x\n", slot, pid); + return 1; + } + } + } + return 0; +} + +STATIC int ci_cpl_update_caid (int slot, int caid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + if (!ci_cpl_find_caid (slot, caid)) { + int i; + for (i = 0; i < CA_MAX_CAIDS; i++) { + if (!cpl[slot].caid[i]) { + cpl[slot].caid[i] = caid; + dbg ("-------> Slot: %d Added caid: %04x\n", slot, caid); + return 1; + } + } + } + return 0; +} + +STATIC int ci_cpl_update_capid (int slot, int capid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + if (!ci_cpl_find_capid (slot, capid)) { + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (!cpl[slot].capid[i]) { + cpl[slot].capid[i] = capid; + dbg ("-------> Slot: %d Added capid: %04x\n", slot, capid); + return 1; + } + } + } + return 0; +} + +int ci_cpl_find_caid_by_pid (int pid) +{ + int i; + int slot; + + if(!pid) { + return 0; + } + for (slot = 0; slot < CA_MAX_SLOTS; slot++) { + for (i = 0; i < CA_MAX_PIDS; i++) { + if (pid == cpl[slot].pid[i]) { + return cpl[slot].caid[0]; + } + } + } + return 0; +} + +int ci_cpl_find_slot_by_caid_and_pid (int caid, int pid) +{ + int slot; + for (slot = 0; slot < CA_MAX_SLOTS; slot++) { + if (ci_cpl_find_pid (slot, pid) && ci_cpl_find_caid (slot, caid)) { + return slot; + } + } + return -1; +} + +int ci_cpl_clear (int slot) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + memset (&cpl[slot], 0, sizeof (caid_pid_list_t)); + return 0; +} + +int ci_cpl_clear_pids (int slot) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + memset (cpl[slot].pid, 0, sizeof (u_int16_t) * CA_MAX_PIDS); + return 0; +} + +int ci_cpl_clear_caids (int slot) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + memset (cpl[slot].caid, 0, sizeof (u_int16_t) * CA_MAX_CAIDS); + return 0; +} + +int ci_cpl_clear_capids (int slot) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + memset (cpl[slot].capid, 0, sizeof (u_int16_t) * CA_MAX_PIDS); + return 0; +} + +STATIC int ci_decode_length (unsigned int *len, u_int8_t * v) +{ + int ret = 0; + + if (*v & LENGTH_SIZE_INDICATOR) { + int l = *v & 0x7f; + if (l > 4) { + return -1; + } + ret = l + 1; + *len = 0; + while (l--) { + v++; + *len <<= 8; + *len |= *v; + } + } else { + *len = *v; + ret = 1; + } + return ret; +} + +#if 0 +STATIC int ci_decode_al_ca_info (ci_al_t * al) +{ + int i = 0; + u_int8_t *data = al->data; + int len = al->length; + + if (len & 1) { + dbg ("ci_decode_al_ca_info: invalid length %d\n", len); + } + + len >>= 1; + + u_int16_t *caid = (u_int16_t *) malloc (sizeof (u_int16_t) * len); + ci_cpl_clear_caids (al->sl->tl->ll->slot); + while (i < len) { + caid[i++] = ntohs16 (data); + data += 2; + ci_cpl_update_caid (al->sl->tl->ll->slot, caid[i - 1]); + dbg ("CAID[%d]: %04x\n", i - 1, caid[i - 1]); + } + if (caid) { + free (caid); + } + return data - al->data; +} +#endif + +STATIC int ca_decode_ca_descr (ca_desc_t ** cadescr, int count, u_int8_t * data, int len, int *magic) +{ + *cadescr = (ca_desc_t *) realloc (*cadescr, sizeof (ca_desc_t *) * (count + 1)); + if (!*cadescr) { + err ("ca_decode_ca_descr: out of memory\n"); + } + ca_desc_t *c = *cadescr + count; + +// u_int8_t descriptor_tag = *data; + data++; + u_int8_t descriptor_length = *data; + data++; + c->ca_id = ntohs16 (data); + data += 2; + c->ca_pid = ntohs16 (data); + data += 2; + dbg ("cadescr: %p %d ca_id: %04x ca_pid: %04x\n", cadescr, count, c->ca_id, c->ca_pid); + if(magic && c->ca_id > 0 && c->ca_id < 3 && c->ca_pid > 0 && c->ca_pid < 3 && c->ca_id == c->ca_pid){ + *magic = c->ca_id; + } + return descriptor_length + 2; +} + + +STATIC int ci_decode_al_ca_pmt (ci_al_t * al) +{ + ca_pmt_t p; + int magic = 0; + int slot = 0; + int cleared = 0; + + memset (&p, 0, sizeof (ca_pmt_t)); + + int ret; + u_int8_t *data = al->data; + int len; + + p.ca_pmt_list_management = *data; + data++; + + p.program_number = ntohs16 (data); + data += 2; + + p.version_number = *data; + data++; + + p.program_info_length = (u_int16_t) ntohs16 (data); + data += 2; + + dbg ("ci_decode_al_ca_pmt: ca_pmt_list_management:%02x program_number:%04x version_number:%02x program_info_length:%04x\n", p.ca_pmt_list_management, p.program_number, p.version_number, p.program_info_length); + if (p.program_info_length) { + int ca_descr_count = 0; + len = p.program_info_length - 1; + p.ca_pmt_cmd_id = *data; + dbg ("p.ca_pmt_cmd_id:%02x\n", p.ca_pmt_cmd_id); + data++; + while (len>0) { + ret = ca_decode_ca_descr (&p.cadescr, ca_descr_count, data, len, &magic); + if (magic) + slot = magic - 1; + else + slot = al->sl->tl->ll->slot; + if (!cleared) { + if(p.ca_pmt_list_management == CPLM_ONLY || p.ca_pmt_list_management == CPLM_FIRST || p.ca_pmt_list_management == CPLM_UPDATE) { + ci_cpl_clear_pids(slot); + ci_cpl_clear_capids(slot); + ci_cpl_clear_caids(slot); + cleared = 1; + } + } + if (ret < 0) { + warn ("error decoding ca_descriptor\n"); + break; + } + if((magic != p.cadescr[ca_descr_count].ca_id) || (magic != p.cadescr[ca_descr_count].ca_pid)){ + ci_cpl_update_caid (slot, p.cadescr[ca_descr_count].ca_id); + ci_cpl_update_capid (slot, p.cadescr[ca_descr_count].ca_pid); + } + ca_descr_count++; + data += ret; + len -= ret; + } + if (p.cadescr) { + free (p.cadescr); + } + } + + len = al->length - (data - al->data); + int pidn = 0; + + while (len>0) { + p.pidinfo = (pidinfo_t *) realloc (p.pidinfo, sizeof (pidinfo_t) * (pidn + 1)); + if (!p.pidinfo) { + err ("ci_decode_al_ca_pmt: out of memory"); + } + memset (&p.pidinfo[pidn], 0, sizeof (pidinfo_t)); + p.pidinfo[pidn].stream_type = *data; + data++; + len--; + p.pidinfo[pidn].pid = ntohs16 (data); + data += 2; + len -= 2; + p.pidinfo[pidn].es_info_length = ntohs16 (data); + data += 2; + len -= 2; + + dbg ("len: %d count: %d, stream_type: %02x, pid: %04x es_info_length: %04x\n", len, pidn, p.pidinfo[pidn].stream_type, p.pidinfo[pidn].pid, p.pidinfo[pidn].es_info_length); + if (p.pidinfo[pidn].es_info_length) { + int pi_len = p.pidinfo[pidn].es_info_length - 1; + p.pidinfo[pidn].ca_pmt_cmd_id = *data; + data++; + len--; + int pid_ca_descr_count = 0; + while (pi_len>0) { + ret = ca_decode_ca_descr (&p.pidinfo[pidn].cadescr, pid_ca_descr_count, data, pi_len, NULL); + if (!cleared) { + if(p.ca_pmt_list_management == CPLM_ONLY || p.ca_pmt_list_management == CPLM_FIRST || p.ca_pmt_list_management == CPLM_UPDATE) { + ci_cpl_clear_pids(slot); + ci_cpl_clear_capids(slot); + ci_cpl_clear_caids(slot); + cleared = 1; + } + } + if (ret < 0) { + warn ("error decoding ca_descriptor\n"); + break; + } + if((magic != p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_id) || (magic != p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_pid)){ + ci_cpl_update_pid (slot, p.pidinfo[pidn].pid); + ci_cpl_update_caid (slot, p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_id); + ci_cpl_update_capid (slot, p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_pid); + } + pid_ca_descr_count++; + data += ret; + pi_len -= ret; + len -= ret; + } + } + if (p.pidinfo[pidn].cadescr) { + free (p.pidinfo[pidn].cadescr); + } + pidn++; + } + if (p.pidinfo) { + free (p.pidinfo); + } + return 0; +} + +STATIC int ci_decode_al_ca_pmt_reply (ci_al_t * al) +{ + ca_pmt_reply_t p; + + memset (&p, 0, sizeof (ca_pmt_reply_t)); + + u_int8_t *data = al->data; + int len; + + p.program_number = ntohs16 (data); + data += 2; + + p.version_number = *data; + data++; + + p.ca_enable = *data; + data++; + + len = al->length - (data - al->data); + int pidn = 0; + + dbg ("ci_decode_al_ca_pmt_reply: program_number: %04x ca_enable: %02x\n", p.program_number, p.ca_enable); + + while (len>0) { + p.pidcaenable = (pid_ca_enable_t *) realloc (p.pidcaenable, sizeof (pid_ca_enable_t) * (pidn + 1)); + if (!p.pidcaenable) { + err ("ci_decode_al_ca_pmt_reply: out of memory\n"); + } + memset (&p.pidcaenable[pidn], 0, sizeof (pid_ca_enable_t)); + p.pidcaenable[pidn].pid = ntohs16 (data); + data += 2; + p.pidcaenable[pidn].ca_enable = *data; + data++; + len -= 3; + if ((p.pidcaenable[pidn].ca_enable == CPCI_OK_DESCRAMBLING) || (p.pidcaenable[pidn].ca_enable == CPCI_OK_MMI) || (p.pidcaenable[pidn].ca_enable == CPCI_QUERY)) { + ci_cpl_update_pid (al->sl->tl->ll->slot, p.pidcaenable[pidn].pid); + } else { + ci_cpl_delete_pid (al->sl->tl->ll->slot, p.pidcaenable[pidn].pid); + } + dbg ("count: %d pid: %04x pid_ca_enable: %02x\n", pidn, p.pidcaenable[pidn].pid, p.pidcaenable[pidn].ca_enable); + pidn++; + } + if (p.pidcaenable) { + free (p.pidcaenable); + } + return 0; +} + +STATIC int ci_decode_al (ci_sl_t * sl) +{ + int ret = 0; + int done = 0; + int len = 3; + ci_al_t al; + u_int8_t *data = sl->data; + al.sl = sl; + + al.tag = 0; + while (len--) { + al.tag <<= 8; + al.tag |= *data; + data++; + } + done += 3; + ret = ci_decode_length (&al.length, data); + if (ret < 0) { + warn ("ci_decode_al ci_decode_length failed\n"); + return ret; + } + + data += ret; + done += ret; + //Fake + al.data = data; + + dbg ("ci_decode_al: tag:%03x length: %02x data[0]:%02x done: %02x\n", al.tag, al.length, al.data[0], done); + + switch (al.tag) { + case AOT_CA_INFO: +// ci_decode_al_ca_info (&al); + break; + case AOT_CA_PMT: + ci_decode_al_ca_pmt (&al); + break; + case AOT_CA_PMT_REPLY: + ci_decode_al_ca_pmt_reply (&al); + break; + } + + done += al.length; + + dbg ("ci_decode_al: done %02x\n", done); + return done; +} + +STATIC int ci_decode_sl (ci_tl_t * tl) +{ + int ret = 0; + int done = 0; + unsigned int len; + ci_sl_t sl; + u_int8_t *data = tl->data; + sl.tl = tl; + + sl.tag = *data; + data++; + done++; + + if(sl.tag != ST_SESSION_NUMBER) { + return tl->length; + } + + ret = ci_decode_length (&len, data); + if (ret < 0) { + warn ("ci_decode_sl ci_decode_length failed\n"); + return ret; + } + data += ret; + done += ret; + + if (len > 4) { + warn ("invalid length (%d) for session_object_value\n", len); + return -1; + } + + sl.object_value = 0; + while (len--) { + sl.object_value <<= 8; + sl.object_value |= *data; + data++; + done++; + } + + sl.data = data; + sl.length = tl->length - done; + + while (sl.length>0) { + dbg ("ci_decode_sl: object_value:%02x length: %02x done: %02x\n", sl.object_value, sl.length, done); + ret = ci_decode_al (&sl); + if (ret < 0) { + warn ("ci_decode_al failed\n"); + return ret; + } + sl.length -= ret; + sl.data += ret; + done += ret; + } + dbg ("ci_decode_sl: done %02x\n", done); + return done; +} + +STATIC int ci_decode_tl (ci_ll_t * ll) +{ + int ret = 0; + int done = 0; + ci_tl_t tl; + u_int8_t *data = ll->data; + tl.ll = ll; + + tl.c_tpdu_tag = *data; + data++; + done++; + + ret = ci_decode_length (&tl.length, data); + if (ret < 0) { + warn ("ci_decode_tl ci_decode_length failed\n"); + return ret; + } + + data += ret; + done += ret; + + tl.tcid = *data; + data++; + done++; + + if (tl.tcid != ll->tcid) { + warn ("Error: redundant tcid mismatch %02x %02x\n",tl.tcid, ll->tcid); + return -1; + } + + tl.data = data; + + //According to A.4.1.1 + tl.length--; + + while (tl.length>0) { + dbg ("ci_decode_tl: c_tpdu_tag:%02x tcid:%02x length: %02x done: %02x\n", tl.c_tpdu_tag, tl.tcid, tl.length, done); + if (tl.c_tpdu_tag == T_DATA_LAST || tl.c_tpdu_tag == T_DATA_MORE) { + ret = ci_decode_sl (&tl); + if (ret < 0) { + warn ("ci_decode_sl failed\n"); + return ret; + } + } else { + ret = tl.length; + } + tl.length -= ret; + tl.data += ret; + done += ret; + } + dbg ("ci_decode_tl: done %02x\n", done); + return done; +} + +int ci_decode_ll (uint8_t * tpdu, int len) +{ + int ret = 0; + int done = 0; + u_int8_t *data=tpdu; + ci_ll_t ll; + dump(tpdu,len); + + ll.slot = *data; + data++; + + ll.tcid = *data; + data++; + + ll.data = data; + ll.length = len - (data-tpdu); + + while (ll.length) { + + dbg ("ci_decode_ll: slot:%02x tcid:%02x length: %02x\n", ll.slot, ll.tcid, ll.length); + ret = ci_decode_tl (&ll); + if (ret < 0) { + warn ("ci_decode_tl failed\n"); + return ret; + } + ll.length -= ret; + ll.data += ret; + } + dbg ("ci_decode_ll: done %02x\n", len); + return done; +} + +#ifdef TESTING +int main (int argc, char **argv) +{ + int ret; + + printf ("ci_decode_ll len: %02x\n", sizeof (lb)); + ret = ci_decode_ll (lb, sizeof (lb)); + printf ("ci_decode_ll ret: %02x\n", ret); + + printf ("ci_decode_ll len: %02x\n", sizeof (ll)); + ret = ci_decode_ll (ll, sizeof (ll)); + printf ("ci_decode_ll ret: %02x\n", ret); + + + printf ("ci_decode_ll len: %02x\n", sizeof (ld)); + ret = ci_decode_ll (ld, sizeof (ld)); + printf ("ci_decode_ll ret: %02x\n", ret); + + printf ("ci_decode_ll len: %02x\n", sizeof (lc)); + ret = ci_decode_ll (lc, sizeof (lc)); + printf ("ci_decode_ll ret: %02x\n", ret); + + printf ("ci_decode_ll len: %02x\n", sizeof (le)); + ret = ci_decode_ll (le, sizeof (le)); + printf ("ci_decode_ll ret: %02x\n", ret); + +// printf ("caid %04x for pid %04x\n", ci_cpl_find_caid_by_pid (0x5c), 0x5c); + return 0; +} +#endif diff --git a/mcast/common/.svn/text-base/ciparser.h.svn-base b/mcast/common/.svn/text-base/ciparser.h.svn-base new file mode 100644 index 0000000..44cb810 --- /dev/null +++ b/mcast/common/.svn/text-base/ciparser.h.svn-base @@ -0,0 +1,140 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#define ntohs16(data) ((u_int16_t)data[0]<<8 | (u_int16_t)data[1]) +typedef struct { + u_int16_t len; + u_int8_t *data; +} ci_pdu_t; + +typedef struct +{ + u_int8_t slot; + u_int8_t tcid; + u_int32_t length; + u_int8_t *data; +} ci_ll_t; + +typedef struct +{ + ci_ll_t *ll; + u_int8_t c_tpdu_tag; + u_int32_t length; + u_int8_t tcid; + u_int8_t *data; +} ci_tl_t; + +typedef struct +{ + ci_tl_t *tl; + u_int8_t tag; + u_int32_t length; + u_int32_t object_value; + u_int8_t *data; +} ci_sl_t; + +typedef struct +{ + ci_sl_t *sl; + u_int32_t tag; + u_int32_t length; + u_int8_t *data; +} ci_al_t; + +typedef struct +{ + u_int16_t ca_id; + u_int16_t ca_pid; +} ca_desc_t; + +typedef struct +{ + u_int8_t stream_type; + u_int16_t pid; + u_int16_t es_info_length; + u_int8_t ca_pmt_cmd_id; + ca_desc_t *cadescr; +} pidinfo_t; + +typedef struct +{ + u_int8_t ca_pmt_list_management; + u_int16_t program_number; + u_int8_t version_number; + u_int8_t current_next; + u_int16_t program_info_length; + u_int8_t ca_pmt_cmd_id; + ca_desc_t *cadescr; + pidinfo_t *pidinfo; +} ca_pmt_t; + +typedef struct +{ + u_int16_t pid; + u_int8_t ca_enable; +} pid_ca_enable_t; + +typedef struct +{ + u_int16_t program_number; + u_int8_t version_number; + u_int8_t current_next; + u_int8_t ca_enable; + pid_ca_enable_t *pidcaenable; +} ca_pmt_reply_t; + + +#define LENGTH_SIZE_INDICATOR 0x80 + +#define CPLM_MORE 0x00 +#define CPLM_FIRST 0x01 +#define CPLM_LAST 0x02 +#define CPLM_ONLY 0x03 +#define CPLM_ADD 0x04 +#define CPLM_UPDATE 0x05 + +#define CPCI_OK_DESCRAMBLING 0x01 +#define CPCI_OK_MMI 0x02 +#define CPCI_QUERY 0x03 +#define CPCI_NOT_SELECTED 0x04 + +#define AOT_CA_INFO_ENQ 0x9F8030 +#define AOT_CA_INFO 0x9F8031 +#define AOT_CA_PMT 0x9F8032 +#define AOT_CA_PMT_REPLY 0x9F8033 + +#define ST_SESSION_NUMBER 0x90 +#define ST_OPEN_SESSION_REQUEST 0x91 +#define ST_OPEN_SESSION_RESPONSE 0x92 +#define ST_CREATE_SESSION 0x93 +#define ST_CREATE_SESSION_RESPONSE 0x94 +#define ST_CLOSE_SESSION_REQUEST 0x95 +#define ST_CLOSE_SESSION_RESPONSE 0x96 + +#define DATA_INDICATOR 0x80 + +#define T_SB 0x80 +#define T_RCV 0x81 +#define T_CREATE_TC 0x82 +#define T_CTC_REPLY 0x83 +#define T_DELETE_TC 0x84 +#define T_DTC_REPLY 0x85 +#define T_REQUEST_TC 0x86 +#define T_NEW_TC 0x87 +#define T_TC_ERROR 0x88 +#define T_DATA_LAST 0xA0 +#define T_DATA_MORE 0xA1 + + +DLL_SYMBOL int ci_cpl_find_caid_by_pid (int pid); +DLL_SYMBOL int ci_cpl_find_slot_by_caid_and_pid (int caid, int pid); +DLL_SYMBOL int ci_cpl_clear (int slot); +DLL_SYMBOL int ci_cpl_clear_pids (int slot); +DLL_SYMBOL int ci_cpl_clear_caids (int slot); +DLL_SYMBOL int ci_cpl_clear_capids (int slot); +DLL_SYMBOL int ci_decode_ll (uint8_t * data, int len); diff --git a/mcast/common/.svn/text-base/crc32.c.svn-base b/mcast/common/.svn/text-base/crc32.c.svn-base new file mode 100644 index 0000000..65f08ac --- /dev/null +++ b/mcast/common/.svn/text-base/crc32.c.svn-base @@ -0,0 +1,88 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +/* +$Id: crc32.c,v 1.2 2006/01/02 18:24:04 rasc Exp $ + + + DVBSNOOP + + a dvb sniffer and mpeg2 stream analyzer tool + http://dvbsnoop.sourceforge.net/ + + (c) 2001-2006 Rainer.Scherg@gmx.de (rasc) + + + -- Code Module CRC32 taken von linuxtv.org +*/ + + + + +#include "defs.h" +#include "crc32.h" + + + +// CRC32 lookup table for polynomial 0x04c11db7 + +static u_long crc_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; + +uint32_t dvb_crc32 (char *data, int len) +{ + register int i; + u_long crc = 0xffffffff; + + for (i=0; i<len; i++) + crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *data++) & 0xff]; + + return crc; +} diff --git a/mcast/common/.svn/text-base/crc32.h.svn-base b/mcast/common/.svn/text-base/crc32.h.svn-base new file mode 100644 index 0000000..f4bef5e --- /dev/null +++ b/mcast/common/.svn/text-base/crc32.h.svn-base @@ -0,0 +1,35 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +/* +$Id: crc32.h,v 1.2 2006/01/02 18:24:04 rasc Exp $ + + + DVBSNOOP + + a dvb sniffer and mpeg2 stream analyzer tool + http://dvbsnoop.sourceforge.net/ + + (c) 2001-2006 Rainer.Scherg@gmx.de (rasc) + + + -- Code Module CRC32 taken von linuxtv.org + +*/ + + + +#ifndef __CRC32_H +#define __CRC32_H + + +uint32_t dvb_crc32 (char *data, int len); + + +#endif + diff --git a/mcast/common/.svn/text-base/defs.h.svn-base b/mcast/common/.svn/text-base/defs.h.svn-base new file mode 100644 index 0000000..979b339 --- /dev/null +++ b/mcast/common/.svn/text-base/defs.h.svn-base @@ -0,0 +1,389 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#ifndef __DEFS_H__ +#define __DEFS_H__ + +#ifdef WIN32 + #ifdef __CYGWIN__ + #include <cygwin/version.h> + #include <cygwin/in.h> + #include <cygwin/socket.h> + #else + #define _CRT_SECURE_NO_WARNINGS + #define _WIN32_WINNT 0x0502 + #include <winsock2.h> + #include <WS2tcpip.h> + #include <iphlpapi.h> + + #define _SOTYPE char* + #define IFNAMSIZ 1024 + #define CA_TPDU_MAX 2048 + #define _POSIX_PATH_MAX MAX_PATH + #define usleep(useconds) Sleep((useconds+500)/1000) + #define sleep(seconds) Sleep((seconds)*1000) + #define EAFNOSUPPORT WSAEAFNOSUPPORT + #ifndef IP_ADAPTER_IPV6_ENABLED + #define IP_ADAPTER_IPV6_ENABLED 0x0100 + #endif + + int inet_pton(int af, const char *src, void *dst); + const char *inet_ntop(int af, const void *src, char *dst, size_t size); + int inet_aton(const char *cp, struct in_addr *addr); + #ifndef __MINGW32__ + int getopt(int nargc, char **nargv, char *ostr); + extern int opterr, optind, optopt, optreset; + extern char *optarg; + #define inline __inline + #endif + + typedef struct + { + DWORD thread; + HANDLE threadH; /* Win32 thread handle - POSIX thread is invalid if threadH == 0 */ + } ptw32_thread_t; + + typedef unsigned int uint32_t; + typedef uint32_t __u32; + typedef uint32_t u_int32_t; + typedef unsigned short uint16_t; + typedef uint16_t __u16; + typedef uint16_t u_int16_t; + typedef unsigned char uint8_t; + typedef uint8_t __u8; + typedef uint8_t u_int8_t; + #ifndef s6_addr16 + #define s6_addr16 s6_words + #endif + #if ! defined _GNU_SOURCE && defined __cplusplus + #define CALLCONV extern "C" + #else + #define CALLCONV + #endif + #ifdef LIBRARY + #define DLL_SYMBOL CALLCONV __declspec( dllexport ) + #else + #ifdef STATICLIB + #define DLL_SYMBOL CALLCONV + #else + #define DLL_SYMBOL CALLCONV __declspec( dllimport ) + #endif + #endif + + #define pthread_exist(x) (x).p + #define pthread_null(x) (x).p=NULL + #define _SOTYPE char* + #define INET6 + #define API_WIN + #define LIBXML_STATIC + #define PTW32_STATIC_LIB + #define MULTI_THREAD_RECEIVER + + #include <poll.h> + #endif +#else + #if defined __cplusplus + #define CALLCONV extern "C" + #else + #define CALLCONV + #endif + #define DLL_SYMBOL CALLCONV + #define pthread_exist(x) x + #define pthread_null(x) x=0 + #define _SOTYPE void* + #define SOCKET int + + #if ! (defined __uClinux__ || defined APPLE || defined MIPSEL) + #include <mcheck.h> + #include <ifaddrs.h> + #endif + #include <pwd.h> + #include <sched.h> + #include <syslog.h> + #include <unistd.h> + #include <getopt.h> + #include <stdint.h> + #include <termios.h> + + #include <arpa/inet.h> + #ifndef APPLE + #include <linux/version.h> + #include <netpacket/packet.h> + #include <sys/sysinfo.h> + #else + typedef unsigned int uint32_t; + typedef uint32_t __u32; + typedef uint32_t u_int32_t; + typedef unsigned short uint16_t; + typedef uint16_t __u16; + typedef uint16_t u_int16_t; + typedef unsigned char uint8_t; + typedef uint8_t __u8; + typedef uint8_t u_int8_t; + + #define CA_TPDU_MAX 2048 + + #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP + #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP + #ifndef s6_addr16 + #define s6_addr16 __u6_addr.__u6_addr16 + #endif + #endif + + #include <netdb.h> + + #include <net/if.h> + #ifdef APPLE + #include <ifaddrs.h> + #include <net/if_types.h> + #endif + #include <netinet/in.h> + #include <netinet/ip.h> + #include <netinet/icmp6.h> + #include <netinet/ip_icmp.h> + #include <netinet/if_ether.h> + #include <netinet/ip6.h> + #include <netinet/tcp.h> + #include <netinet/udp.h> + + #include <sys/ioctl.h> + #include <sys/mman.h> + #include <sys/poll.h> + #include <sys/resource.h> + #include <sys/socket.h> + #include <sys/types.h> + #include <sys/uio.h> /* for iovec{} and readv/writev */ + #include <sys/un.h> /* for Unix domain sockets */ + #include <sys/utsname.h> + #include <sys/wait.h> + + #if defined __uClinux__ + #include <mathf.h> + #endif + #define closesocket close +#endif + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <math.h> +#include <pthread.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <zlib.h> + +#include <sys/stat.h> + +//---------------------------------------------------------------------- +#ifndef __uClinux__ + //DVBAPI + #include <linux/dvb/version.h> + #include <linux/dvb/frontend.h> + #include <linux/dvb/ca.h> + #if ! (defined WIN32 || defined APPLE) + #include <linux/dvb/dmx.h> + #endif +// #else +// #endif + + #define dvb_ioctl ioctl + #define dvb_close close +#else + #include <dvb/frontend.h> + #include <ci/ca.h> +#endif + +#define CA_TPDU_MAX 2048 + +typedef struct recv_sec +{ + struct dvb_diseqc_master_cmd diseqc_cmd; + fe_sec_mini_cmd_t mini_cmd; + fe_sec_tone_mode_t tone_mode; + fe_sec_voltage_t voltage; +} recv_sec_t; + +#define CA_MAX_SLOTS 16 +typedef struct { + ca_caps_t cap; + ca_slot_info_t info[CA_MAX_SLOTS]; +} recv_cacaps_t; + +typedef struct recv_festatus +{ + fe_status_t st; + uint32_t ber; + uint16_t strength; + uint16_t snr; + uint32_t ucblocks; +} recv_festatus_t; + +//XML +#include <libxml/encoding.h> +#include <libxml/xmlwriter.h> +#include <libxml/xmlmemory.h> +#include <libxml/parser.h> +#include <libxml/xpath.h> + +#ifdef DMALLOC + #include <dmalloc.h> +#endif + +#if ! defined GETTID && ! defined WIN32 && ! defined APPLE + #include <asm/unistd.h> + #define gettid() syscall (__NR_gettid) +#else + #define gettid pthread_self +#endif + +#define UUID_SIZE 256 +#ifndef WIN32 + +#ifdef SYSLOG +extern char *_logstr; +extern pthread_mutex_t _loglock; + + #ifdef DEBUG + #define dbg(format, arg...) { pthread_mutex_lock (&_loglock); sprintf(_logstr, "%s:%d " format , __FILE__ , __LINE__ , ## arg); syslog_write(_logstr); pthread_mutex_unlock (&_loglock);} + #else + #define dbg(format, arg...) do {} while (0) + #endif + #define err(format, arg...) {pthread_mutex_lock (&_loglock); sprintf(_logstr, "err:%s:%d: %s (%d): " format , __FILE__ , __LINE__ ,strerror(errno), errno, ## arg); fprintf(stdout, "%s", _logstr); syslog_write(_logstr);abort(); pthread_mutex_unlock (&_loglock);} + #define info(format, arg...){pthread_mutex_lock (&_loglock); sprintf(_logstr, format ,## arg); fprintf(stdout, "%s", _logstr); syslog_write(_logstr); pthread_mutex_unlock (&_loglock);} + #define warn(format, arg...){pthread_mutex_lock (&_loglock); sprintf(_logstr, format ,## arg); fprintf(stdout, "%s", _logstr); syslog_write(_logstr); pthread_mutex_unlock (&_loglock);} + #define sys(format, arg...){pthread_mutex_lock (&_loglock); sprintf(_logstr, format ,## arg); syslog_write(_logstr); pthread_mutex_unlock (&_loglock);} +#elif defined DEBUG + #define dbg(format, arg...) {printf("%s:%d " format , __FILE__ , __LINE__ , ## arg)} + #define err(format, arg...) {fprintf(stderr,"err:%s:%d: %s (%d): " format , __FILE__ , __LINE__ ,strerror(errno), errno, ## arg);print_trace();abort();} + #define info(format, arg...) printf("%s:%d: " format , __FILE__ , __LINE__ ,## arg) + #define warn(format, arg...) fprintf(stderr,"%s:%d: " format , __FILE__ , __LINE__ ,## arg) +#else + #define dbg(format, arg...) do {} while (0) + #define err(format, arg...) {fprintf(stderr,"%s (%d): " format, strerror(errno), errno, ## arg);exit(-1);} + #define info(format, arg...) printf(format , ## arg) + #define warn(format, arg...) fprintf(stderr, format , ## arg) + #define sys(format, arg...) printf(format, ## arg) +#endif // SYSLOG + +#else // !WIN32 + #ifdef DEBUG + static void inline dbg (char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf (buffer, format, args); + printf("%s:%d %s", __FILE__ , __LINE__ , buffer); + va_end (args); + } + static void inline err (char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf(buffer, format , args); + fprintf(stderr, "err:%s:%d: %s (%d): %s " , __FILE__ , __LINE__ ,strerror(errno), errno, buffer); + va_end (args); + abort(); + } + static void inline info(const char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf(buffer, format , args); + printf("%s:%d: %s" , __FILE__ , __LINE__ , buffer); + va_end (args); + } + static void inline warn(const char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf(buffer, format , args); + fprintf(stderr, "%s:%d: %s", __FILE__ , __LINE__ , buffer ); + va_end (args); + } + static void inline sys(const char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf(buffer, format , args); + printf("%s:%d: %s", __FILE__ , __LINE__ , buffer ); + va_end (args); + } + #else + static void inline dbg (char *format, ...) + { + } + static void inline err (char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf(buffer, format, args); + fprintf(stderr, "err:%s:%d: %s",strerror(errno), errno, buffer); + va_end (args); + abort(); + } + static void inline info(const char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf(buffer, format, args); + puts(buffer); + va_end (args); + } + static void inline warn(const char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf(buffer, format, args); + fputs(buffer, stderr); + va_end (args); + } + static void inline sys(const char *format, ...) + { + char buffer[1024]; + va_list args; + va_start (args, format); + vsprintf(buffer, format, args); + fputs(buffer, stdout); + va_end (args); + } + + #endif //DEBUG +#endif // WIN32 + +#ifndef MICROBLAZE + #define FE_DVBS2 (FE_ATSC+1) +#endif + +// RMM S2 Extension +#define FEC_1_4 10 +#define FEC_1_3 11 +#define FEC_2_5 12 +#define FEC_3_5 13 +#define FEC_9_10 14 +#define QPSK_S2 9 +#define PSK8 10 + +#ifdef MICROBLAZE + #define STATIC +#else + #define STATIC static +#endif +#endif diff --git a/mcast/common/.svn/text-base/dvb_ca_wrapper.h.svn-base b/mcast/common/.svn/text-base/dvb_ca_wrapper.h.svn-base new file mode 100644 index 0000000..d0873aa --- /dev/null +++ b/mcast/common/.svn/text-base/dvb_ca_wrapper.h.svn-base @@ -0,0 +1,18 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#ifndef __DVB_CA_WRAPPER_H +#define __user +unsigned int dvb_cam_poll(struct pollfd *pfd, int fdnum, int timeout_ms); +ssize_t dvb_cam_read(int dummy, char __user * buf, size_t count); +ssize_t dvb_cam_write(int dummy, char __user * buf, size_t count); +int dvb_cam_ioctl(int dummy, unsigned int cmd, void *parg); +int dvb_cam_open(const char* dummy, int dummy1); +int dvb_cam_close(int fd); + +#endif diff --git a/mcast/common/.svn/text-base/input.h.svn-base b/mcast/common/.svn/text-base/input.h.svn-base new file mode 100644 index 0000000..fbda65b --- /dev/null +++ b/mcast/common/.svn/text-base/input.h.svn-base @@ -0,0 +1,38 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#ifndef __INPUT_H__ +#define __INPUT_H__ +typedef struct +{ + int port; + char iface[IFNAMSIZ]; + time_t start_time; +#ifdef SERVER + int tuner_number; + char cfgpath[_POSIX_PATH_MAX]; + int verbose; +#endif +#ifdef CLIENT + char disec_conf_path[_POSIX_PATH_MAX]; + char rotor_conf_path[_POSIX_PATH_MAX]; + char cmd_sock_path[_POSIX_PATH_MAX]; + int tuner_type_limit[FE_DVBS2+1]; + int mld_start; + int ca_enable; + int ci_timeout; + int vdrdiseqcmode; + int reelcammode; +#endif +} cmdline_t; + +extern cmdline_t cmd; + +void get_options (int argc, char *argv[]); + +#endif diff --git a/mcast/common/.svn/text-base/interfaces.c.svn-base b/mcast/common/.svn/text-base/interfaces.c.svn-base new file mode 100644 index 0000000..bd19c8d --- /dev/null +++ b/mcast/common/.svn/text-base/interfaces.c.svn-base @@ -0,0 +1,347 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#include "headers.h" + +void int_destroy (struct intnode *intn) +{ + dbg ("Destroying interface %s\n", intn->name); + + /* Resetting the MTU to zero disabled the interface */ + intn->mtu = 0; +} + +struct intnode *int_find (unsigned int ifindex) +{ + unsigned int i; + for (i = 0; i < g_conf->maxinterfaces; i++) { + if(g_conf->ints[i].ifindex == ifindex) { + return g_conf->ints+i; + } + } + return NULL; +} + +struct intnode *int_find_name (char *ifname) +{ + unsigned int i; + for (i = 0; i < g_conf->maxinterfaces; i++) { + if (!strcmp (ifname, g_conf->ints[i].name) && g_conf->ints[i].mtu != 0) { + return g_conf->ints+i; + } + } + return NULL; +} + + +struct intnode *int_find_first (void) +{ + unsigned int i; + for (i = 0; i < g_conf->maxinterfaces; i++) { + dbg("int: %d %s\n",i, g_conf->ints[i].name); + if (g_conf->ints[i].mtu != 0) { + return g_conf->ints+i; + } + } + return NULL; +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +#if ! (defined WIN32 || defined APPLE) || defined __CYGWIN__ + +/* Initiliaze interfaces */ +void update_interfaces (struct intnode *intn) +{ + struct in6_addr addr; + + FILE *file; + unsigned int prefixlen, scope, flags, ifindex; + char devname[IFNAMSIZ]; + + /* Only update every 5 seconds to avoid rerunning it every packet */ + if (g_conf->maxinterfaces) + return; + + dbg ("Updating Interfaces\n"); + + /* Get link local addresses from /proc/net/if_inet6 */ + file = fopen ("/proc/net/if_inet6", "r"); + + /* We can live without it though */ + if (!file) { + err ("Cannot open /proc/net/if_inet6\n"); + return; + } + + char buf[255]; + /* Format "fe80000000000000029027fffe24bbab 02 0a 20 80 eth0" */ + while (fgets (buf, sizeof (buf), file)) { + if (21 != sscanf (buf, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx %x %x %x %x %8s", &addr.s6_addr[0], &addr.s6_addr[1], &addr.s6_addr[2], &addr.s6_addr[3], &addr.s6_addr[4], &addr.s6_addr[5], &addr.s6_addr[6], &addr.s6_addr[7], &addr.s6_addr[8], &addr.s6_addr[9], &addr.s6_addr[10], &addr.s6_addr[11], &addr.s6_addr[12], &addr.s6_addr[13], &addr.s6_addr[14], &addr.s6_addr[15], &ifindex, &prefixlen, &scope, &flags, devname)) { + + warn ("/proc/net/if_inet6 in wrong format!\n"); + continue; + } + if (!IN6_IS_ADDR_LINKLOCAL (&addr) && (IN6_IS_ADDR_UNSPECIFIED (&addr) || IN6_IS_ADDR_LOOPBACK (&addr) || IN6_IS_ADDR_MULTICAST (&addr))) { + continue; + } + + if((intn=int_find(ifindex))==NULL) { + g_conf->ints=(struct intnode*)realloc(g_conf->ints, sizeof(struct intnode)*(++g_conf->maxinterfaces)); + if (!g_conf->ints) { + err ("Cannot get memory for interface structures.\n"); + } + intn=g_conf->ints+g_conf->maxinterfaces-1; + memset(intn, 0, sizeof(struct intnode)); + } +#ifdef WIN32 + // Ugly WINXP workaround + if(scope==0x20 && flags==0x80) { + intn->mtu=1480; + } else { + intn->mtu=0; + } +#else + intn->ifindex = ifindex; + strcpy(intn->name, devname); + + struct ifreq ifreq; + int sock; + sock = socket (AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) { + err ("Cannot get socket for setup\n"); + } + + memcpy (&ifreq.ifr_name, &intn->name, sizeof (ifreq.ifr_name)); + /* Get the MTU size of this interface */ + /* We will use that for fragmentation */ + if (ioctl (sock, SIOCGIFMTU, &ifreq) != 0) { + warn ("Cannot get MTU size for %s index %d: %s\n", intn->name, intn->ifindex, strerror (errno)); + } + intn->mtu = ifreq.ifr_mtu; + + /* Get hardware address + type */ + if (ioctl (sock, SIOCGIFHWADDR, &ifreq) != 0) { + warn ("Cannot get hardware address for %s, interface index %d : %s\n", intn->name, intn->ifindex, strerror (errno)); + } + intn->hwaddr = ifreq.ifr_hwaddr; + close (sock); +#endif + /* Link Local IPv6 address ? */ + if (IN6_IS_ADDR_LINKLOCAL (&addr)) { + /* Update the linklocal address */ + intn->linklocal = addr; + } else { + intn->global = addr; + } + + dbg ("Available interface %s index %u hardware %s/%u MTU %d\n", intn->name, intn->ifindex, (intn->hwaddr.sa_family == ARPHRD_ETHER ? "Ethernet" : (intn->hwaddr.sa_family == ARPHRD_SIT ? "sit" : "Unknown")), intn->hwaddr.sa_family, intn->mtu); + } + + fclose (file); +} +#endif +#if defined WIN32 && ! defined __CYGWIN__ + +unsigned int if_nametoindex (const char *ifname) +{ + unsigned int ifindex; + for (ifindex = 0; ifindex < g_conf->maxinterfaces; ifindex++) { + if (!strcmp (ifname, g_conf->ints[ifindex].name) && g_conf->ints[ifindex].mtu != 0) { + return g_conf->ints[ifindex].ifindex; + } + } + return 0; +} + +void update_interfaces (struct intnode *intn) +{ + + /* Declare and initialize variables */ + + DWORD dwRetVal = 0; + + int i = 0; + + // Set the flags to pass to GetAdaptersAddresses + ULONG flags = GAA_FLAG_INCLUDE_PREFIX; + + // default to unspecified address family (both) + ULONG family = AF_INET6; + + PIP_ADAPTER_ADDRESSES pAddresses = NULL; + ULONG outBufLen = 0; + + PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; + PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; + + outBufLen = sizeof (IP_ADAPTER_ADDRESSES); + pAddresses = (IP_ADAPTER_ADDRESSES *) malloc (outBufLen); + if (pAddresses == NULL) { + printf ("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n"); + exit (1); + } + // Make an initial call to GetAdaptersAddresses to get the + // size needed into the outBufLen variable + if (GetAdaptersAddresses (family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) { + free (pAddresses); + pAddresses = (IP_ADAPTER_ADDRESSES *) malloc (outBufLen); + } + + if (pAddresses == NULL) { + printf ("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n"); + exit (1); + } + + dwRetVal = GetAdaptersAddresses (family, flags, NULL, pAddresses, &outBufLen); + + if (dwRetVal == NO_ERROR) { + // If successful, output some information from the data we received + pCurrAddresses = pAddresses; + g_conf->maxinterfaces=0; + + while (pCurrAddresses) { + + if( /* pCurrAddresses->Flags & IP_ADAPTER_IPV6_ENABLED && */ (pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD || pCurrAddresses->IfType == IF_TYPE_IEEE80211) && pCurrAddresses->OperStatus == IfOperStatusUp ) { + g_conf->ints=(struct intnode*)realloc(g_conf->ints, sizeof(struct intnode)*(g_conf->maxinterfaces+1)); + if (!g_conf->ints) { + err ("update_interfaces: out of memory\n"); + } + intn=g_conf->ints+g_conf->maxinterfaces; + memset(intn, 0, sizeof(struct intnode)); + +#ifndef __MINGW32__ + printf ("Interface: %s (%wS)\n", pCurrAddresses->AdapterName, pCurrAddresses->Description); + dbg ("\tFriendly name: %wS\n", pCurrAddresses->FriendlyName); +#else + printf ("Interface: %s (%ls)\n", pCurrAddresses->AdapterName, pCurrAddresses->Description); + dbg ("\tFriendly name: %ls\n", pCurrAddresses->FriendlyName); +#endif + dbg ("\tFlags: %x\n", pCurrAddresses->Flags); + dbg ("\tIfType: %ld\n", pCurrAddresses->IfType); + dbg ("\tOperStatus: %ld\n", pCurrAddresses->OperStatus); + dbg ("\tMtu: %lu\n", pCurrAddresses->Mtu); + dbg ("\tIpv6IfIndex (IPv6 interface): %u\n", pCurrAddresses->Ipv6IfIndex); + + strncpy(intn->name, pCurrAddresses->AdapterName, IFNAMSIZ-1); + + intn->mtu = pCurrAddresses->Mtu; + intn->ifindex= pCurrAddresses->Ipv6IfIndex; + + pUnicast = pCurrAddresses->FirstUnicastAddress; + if (pUnicast != NULL) { + for (i = 0; pUnicast != NULL; i++) { + char host[80]; + inet_ntop (AF_INET6, ((struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr))->sin6_addr.s6_addr, host, sizeof(host)); + dbg("\tIP:%s LL:%d\n",host, IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr))->sin6_addr)); + if(IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr))->sin6_addr)) { + intn->linklocal=((struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr))->sin6_addr; + } else { + intn->global=((struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr))->sin6_addr; + } + pUnicast = pUnicast->Next; + } + dbg ("\tNumber of Unicast Addresses: %d\n", i); + } +#ifdef DEBUG + if (pCurrAddresses->PhysicalAddressLength != 0) { + dbg ("\tPhysical address: "); + for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) { + if (i == (pCurrAddresses->PhysicalAddressLength - 1)) + printf ("%.2X\n", (int) pCurrAddresses->PhysicalAddress[i]); + else + printf ("%.2X:", (int) pCurrAddresses->PhysicalAddress[i]); + } + } +#endif + g_conf->maxinterfaces++; + } + pCurrAddresses = pCurrAddresses->Next; + } + } + + free (pAddresses); +} + +#endif +#ifdef APPLE +void update_interfaces (struct intnode *intn) +{ + struct ifaddrs *myaddrs, *ifa; + struct sockaddr_in *s4; + struct sockaddr_in6 *s6; + int if_index; + /* + * buf must be big enough for an IPv6 address (e.g. + * 3ffe:2fa0:1010:ca22:020a:95ff:fe8a:1cf8) + */ + char buf[64]; + + if (getifaddrs(&myaddrs)) { + err ("getifaddrs"); + } + + for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) + continue; + if ((ifa->ifa_flags & IFF_UP) == 0) + continue; + + if_index=if_nametoindex(ifa->ifa_name); + dbg("%s(%d): ", ifa->ifa_name,if_index); + + if(!if_index) { + warn("cannot get interface index for %s\n",ifa->ifa_name); + continue; + } + + if((intn=int_find(if_index))==NULL) { + g_conf->ints=(struct intnode*)realloc(g_conf->ints, sizeof(struct intnode)*(++g_conf->maxinterfaces)); + if (!g_conf->ints) { + err ("Cannot get memory for interface structures.\n"); + } + intn=g_conf->ints+g_conf->maxinterfaces-1; + memset(intn, 0, sizeof(struct intnode)); + } + + intn->ifindex=if_index; + strcpy(intn->name,ifa->ifa_name); + + if(ifa->ifa_addr->sa_family == AF_LINK && ((struct if_data *)ifa->ifa_data)->ifi_type != IFT_LOOP && ifa->ifa_data) { + dbg("MTU: %d\n", ((struct if_data *)ifa->ifa_data)->ifi_mtu); + intn->mtu=((struct if_data *)ifa->ifa_data)->ifi_mtu; + memcpy(&intn->hwaddr, ifa->ifa_addr, sizeof(struct sockaddr_in)); + } + + if (ifa->ifa_addr->sa_family == AF_INET) { + s4 = (struct sockaddr_in *) (ifa->ifa_addr); + if (inet_ntop(ifa->ifa_addr->sa_family, (void *) &(s4->sin_addr), buf, sizeof(buf)) == NULL) { + warn("%s: inet_ntop failed!\n", ifa->ifa_name); + } else { + dbg("%s\n", buf); + } + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + s6 = (struct sockaddr_in6 *) (ifa->ifa_addr); + /* Link Local IPv6 address ? */ + if (IN6_IS_ADDR_LINKLOCAL (&s6->sin6_addr)) { + /* Update the linklocal address */ + intn->linklocal = s6->sin6_addr; + } else { + intn->global = s6->sin6_addr; + } + if (inet_ntop(ifa->ifa_addr->sa_family, (void *) &(s6->sin6_addr), buf, sizeof(buf)) == NULL) { + warn("%s: inet_ntop failed!\n", ifa->ifa_name); + } else { + dbg("%s\n", buf); + } + } + } + + freeifaddrs(myaddrs); +} + +#endif diff --git a/mcast/common/.svn/text-base/interfaces.h.svn-base b/mcast/common/.svn/text-base/interfaces.h.svn-base new file mode 100644 index 0000000..8ef942c --- /dev/null +++ b/mcast/common/.svn/text-base/interfaces.h.svn-base @@ -0,0 +1,52 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#ifndef __INTERFACES_H +#define __INTERFACES_H + +#define INTNODE_MAXIPV4 4 /* Maximum number of IPv4 aliases */ +#define bool int + +/* + * The list of interfaces we do multicast on + * These are discovered on the fly, very handy ;) + */ +struct intnode +{ + unsigned int ifindex; /* The ifindex */ + char name[IFNAMSIZ]; /* Name of the interface */ + unsigned int groupcount; /* Number of groups this interface joined */ + unsigned int mtu; /* The MTU of this interface (mtu = 0 -> invalid interface) */ + + struct sockaddr hwaddr; /* Hardware bytes */ + + struct in6_addr linklocal; /* Link local address */ + struct in6_addr global; /* Global unicast address */ + + /* Per interface statistics */ + uint32_t stat_packets_received; /* Number of packets received */ + uint32_t stat_packets_sent; /* Number of packets sent */ + uint32_t stat_bytes_received; /* Number of bytes received */ + uint32_t stat_bytes_sent; /* Number of bytes sent */ + uint32_t stat_icmp_received; /* Number of ICMP's received */ + uint32_t stat_icmp_sent; /* Number of ICMP's sent */ +}; + +/* Node functions */ +struct intnode *int_create (unsigned int ifindex); +void int_destroy (struct intnode *intn); +void update_interfaces (struct intnode *intn); + +/* List functions */ +struct intnode *int_find (unsigned int ifindex); +struct intnode *int_find_name (char *ifname); +struct intnode *int_find_first (void); +#if defined WIN32 || ! defined __CYGWIN__ +unsigned if_nametoindex (const char *ifname); +#endif +#endif diff --git a/mcast/common/.svn/text-base/list.h.svn-base b/mcast/common/.svn/text-base/list.h.svn-base new file mode 100644 index 0000000..4bb50a4 --- /dev/null +++ b/mcast/common/.svn/text-base/list.h.svn-base @@ -0,0 +1,238 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +/* + * Linked lists support + * + * Copyright (C) 2002 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_SERVER_DVBMC_LIST_H +#define __WINE_SERVER_DVBMC_LIST_H + +struct list +{ + struct list *next; + struct list *prev; +}; + +/* Define a list like so: + * + * struct gadget + * { + * struct list entry; <-- doesn't have to be the first item in the struct + * int a, b; + * }; + * + * static struct list global_gadgets = DVBMC_LIST_INIT( global_gadgets ); + * + * or + * + * struct some_global_thing + * { + * struct list gadgets; + * }; + * + * dvbmc_list_init( &some_global_thing->gadgets ); + * + * Manipulate it like this: + * + * dvbmc_list_add_head( &global_gadgets, &new_gadget->entry ); + * dvbmc_list_remove( &new_gadget->entry ); + * dvbmc_list_add_after( &some_random_gadget->entry, &new_gadget->entry ); + * + * And to iterate over it: + * + * struct gadget *gadget; + * DVBMC_LIST_FOR_EACH_ENTRY( gadget, &global_gadgets, struct gadget, entry ) + * { + * ... + * } + * + */ + +/* add an element after the specified one */ +static inline void dvbmc_list_add_after( struct list *elem, struct list *to_add ) +{ + to_add->next = elem->next; + to_add->prev = elem; + elem->next->prev = to_add; + elem->next = to_add; +} + +/* add an element before the specified one */ +static inline void dvbmc_list_add_before( struct list *elem, struct list *to_add ) +{ + to_add->next = elem; + to_add->prev = elem->prev; + elem->prev->next = to_add; + elem->prev = to_add; +} + +/* add element at the head of the list */ +static inline void dvbmc_list_add_head( struct list *list, struct list *elem ) +{ + dvbmc_list_add_after( list, elem ); +} + +/* add element at the tail of the list */ +static inline void dvbmc_list_add_tail( struct list *list, struct list *elem ) +{ + dvbmc_list_add_before( list, elem ); +} + +/* remove an element from its list */ +static inline void dvbmc_list_remove( struct list *elem ) +{ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; +} + +/* get the next element */ +static inline struct list *dvbmc_list_next( const struct list *list, const struct list *elem ) +{ + struct list *ret = elem->next; + if (elem->next == list) ret = NULL; + return ret; +} + +/* get the previous element */ +static inline struct list *dvbmc_list_prev( const struct list *list, const struct list *elem ) +{ + struct list *ret = elem->prev; + if (elem->prev == list) ret = NULL; + return ret; +} + +/* get the first element */ +static inline struct list *dvbmc_list_head( const struct list *list ) +{ + return dvbmc_list_next( list, list ); +} + +/* get the last element */ +static inline struct list *dvbmc_list_tail( const struct list *list ) +{ + return dvbmc_list_prev( list, list ); +} + +/* check if a list is empty */ +static inline int dvbmc_list_empty( const struct list *list ) +{ + return list->next == list; +} + +/* initialize a list */ +static inline void dvbmc_list_init( struct list *list ) +{ + list->next = list->prev = list; +} + +/* count the elements of a list */ +static inline unsigned int dvbmc_list_count( const struct list *list ) +{ + unsigned count = 0; + const struct list *ptr; + for (ptr = list->next; ptr != list; ptr = ptr->next) count++; + return count; +} + +/* move all elements from src to the tail of dst */ +static inline void dvbmc_list_move_tail( struct list *dst, struct list *src ) +{ + if (dvbmc_list_empty(src)) return; + + dst->prev->next = src->next; + src->next->prev = dst->prev; + dst->prev = src->prev; + src->prev->next = dst; + dvbmc_list_init(src); +} + +/* move all elements from src to the head of dst */ +static inline void dvbmc_list_move_head( struct list *dst, struct list *src ) +{ + if (dvbmc_list_empty(src)) return; + + dst->next->prev = src->prev; + src->prev->next = dst->next; + dst->next = src->next; + src->next->prev = dst; + dvbmc_list_init(src); +} + +/* iterate through the list */ +#define DVBMC_LIST_FOR_EACH(cursor,list) \ + for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next) + +/* iterate through the list, with safety against removal */ +#define DVBMC_LIST_FOR_EACH_SAFE(cursor, cursor2, list) \ + for ((cursor) = (list)->next, (cursor2) = (cursor)->next; \ + (cursor) != (list); \ + (cursor) = (cursor2), (cursor2) = (cursor)->next) + +/* iterate through the list using a list entry */ +#define DVBMC_LIST_FOR_EACH_ENTRY(elem, list, type, field) \ + for ((elem) = DVBMC_LIST_ENTRY((list)->next, type, field); \ + &(elem)->field != (list); \ + (elem) = DVBMC_LIST_ENTRY((elem)->field.next, type, field)) + +/* iterate through the list using a list entry, with safety against removal */ +#define DVBMC_LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field) \ + for ((cursor) = DVBMC_LIST_ENTRY((list)->next, type, field), \ + (cursor2) = DVBMC_LIST_ENTRY((cursor)->field.next, type, field); \ + &(cursor)->field != (list); \ + (cursor) = (cursor2), \ + (cursor2) = DVBMC_LIST_ENTRY((cursor)->field.next, type, field)) + +/* iterate through the list in reverse order */ +#define DVBMC_LIST_FOR_EACH_REV(cursor,list) \ + for ((cursor) = (list)->prev; (cursor) != (list); (cursor) = (cursor)->prev) + +/* iterate through the list in reverse order, with safety against removal */ +#define DVBMC_LIST_FOR_EACH_SAFE_REV(cursor, cursor2, list) \ + for ((cursor) = (list)->prev, (cursor2) = (cursor)->prev; \ + (cursor) != (list); \ + (cursor) = (cursor2), (cursor2) = (cursor)->prev) + +/* iterate through the list in reverse order using a list entry */ +#define DVBMC_LIST_FOR_EACH_ENTRY_REV(elem, list, type, field) \ + for ((elem) = DVBMC_LIST_ENTRY((list)->prev, type, field); \ + &(elem)->field != (list); \ + (elem) = DVBMC_LIST_ENTRY((elem)->field.prev, type, field)) + +/* iterate through the list in reverse order using a list entry, with safety against removal */ +#define DVBMC_LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, list, type, field) \ + for ((cursor) = DVBMC_LIST_ENTRY((list)->prev, type, field), \ + (cursor2) = DVBMC_LIST_ENTRY((cursor)->field.prev, type, field); \ + &(cursor)->field != (list); \ + (cursor) = (cursor2), \ + (cursor2) = DVBMC_LIST_ENTRY((cursor)->field.prev, type, field)) + +/* macros for statically initialized lists */ +//#define DVBMC_LIST_INIT(list) { &(list), &(list) } + +/* get pointer to object containing list element */ +#define DVBMC_LIST_ENTRY(elem, type, field) \ + ((type *)((char *)(elem) - (unsigned long)(&((type *)0)->field))) + +#endif /* __WINE_SERVER_DVBMC_LIST_H */ diff --git a/mcast/common/.svn/text-base/mcast.c.svn-base b/mcast/common/.svn/text-base/mcast.c.svn-base new file mode 100644 index 0000000..41991cf --- /dev/null +++ b/mcast/common/.svn/text-base/mcast.c.svn-base @@ -0,0 +1,674 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + * modified by Reel Multimedia, http://www.reel-multimedia.com, info@reel-multimedia.com + * 01042010 DL: use a single thread for reading from network layer (uses less resources) + * + */ + +#include "headers.h" +//---------------------------------------------------------------------------------------------------------------------------------- +STATIC int udp_ipv6_is_multicast_address (const struct sockaddr *addr) +{ +#ifdef IPV4 + if (addr->sa_family == AF_INET) + return IN_MULTICAST (ntohl (((struct sockaddr_in *) addr)->sin_addr.s_addr)); +#endif + if (addr->sa_family == AF_INET6) + return IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) addr)->sin6_addr); + return -1; +} + +//--------------------------------------------------------------------------------------------------------------------------------- +STATIC int udp_ipv6_set_multicast_ttl (SOCKET sockfd, int mcastTTL, struct sockaddr *addr) +{ +#ifdef IPV4 + if (addr->sa_family == AF_INET) { + if (setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof (mcastTTL)) < 0) { + perror ("setsockopt(IP_MULTICAST_TTL)"); + return -1; + } + } +#endif + if (addr->sa_family == AF_INET6) { + if (setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (_SOTYPE)&mcastTTL, sizeof (mcastTTL)) < 0) { + perror ("setsockopt(IPV6_MULTICAST_HOPS)"); + return -1; + } + } + return 0; +} + +//--------------------------------------------------------------------------------------------------------------------------------- +int udp_ipv6_join_multicast_group (SOCKET sockfd, int iface, struct sockaddr *addr) +{ +#ifdef IPV4 + if (addr->sa_family == AF_INET) { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; + mreq.imr_interface.s_addr = INADDR_ANY; + if (setsockopt (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *) &mreq, sizeof (mreq)) < 0) { + perror ("setsockopt(IP_ADD_MEMBERSHIP)"); + return -1; + } + } +#endif + if (addr->sa_family == AF_INET6) { + struct ipv6_mreq mreq6; + memcpy (&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *) addr)->sin6_addr), sizeof (struct in6_addr)); + mreq6.ipv6mr_interface = iface; + if (setsockopt (sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (_SOTYPE)&mreq6, sizeof (mreq6)) < 0) { + perror ("setsockopt(IPV6_ADD_MEMBERSHIP)"); + return -1; + } + } + return 0; +} + +//--------------------------------------------------------------------------------------------------------------------------------- +int udp_ipv6_leave_multicast_group (SOCKET sockfd, int iface, struct sockaddr *addr) +{ +#ifdef IPV4 + if (addr->sa_family == AF_INET) { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; + mreq.imr_interface.s_addr = INADDR_ANY; + if (setsockopt (sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *) &mreq, sizeof (mreq)) < 0) { + perror ("setsockopt(IP_DROP_MEMBERSHIP)"); + return -1; + } + } +#endif + if (addr->sa_family == AF_INET6) { + struct ipv6_mreq mreq6; + memcpy (&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *) addr)->sin6_addr), sizeof (struct in6_addr)); + mreq6.ipv6mr_interface = iface; + if (setsockopt (sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (_SOTYPE)&mreq6, sizeof (mreq6)) < 0) { + perror ("setsockopt(IPV6_DROP_MEMBERSHIP)"); + return -1; + } + } + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------- +STATIC int sockfd_to_family (SOCKET sockfd) +{ + struct sockaddr_storage ss; + socklen_t len; + + len = sizeof (ss); + if (getsockname (sockfd, (SA *) & ss, &len) < 0) + return (-1); + return (ss.ss_family); +} + +/* end sockfd_to_family */ +//---------------------------------------------------------------------------------------------------------------------------------- +int mcast_set_if (SOCKET sockfd, const char *ifname, u_int ifindex) +{ + switch (sockfd_to_family (sockfd)) { +#ifdef IPV4 + case AF_INET:{ + struct in_addr inaddr; + struct ifreq ifreq; + + if (ifindex > 0) { + if (if_indextoname (ifindex, ifreq.ifr_name) == NULL) { + errno = ENXIO; /* i/f index not found */ + return (-1); + } + goto doioctl; + } else if (ifname != NULL) { + memset(&ifreq, 0, sizeof(struct ifreq)); + strncpy (ifreq.ifr_name, ifname, IFNAMSIZ-1); + doioctl: + if (ioctl (sockfd, SIOCGIFADDR, &ifreq) < 0) + return (-1); + memcpy (&inaddr, &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr, sizeof (struct in_addr)); + } else + inaddr.s_addr = htonl (INADDR_ANY); /* remove prev. set default */ + + return (setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_IF, &inaddr, sizeof (struct in_addr))); + } +#endif + case AF_INET6:{ + u_int idx; +// printf("Changing interface IPV6...\n"); + if ((idx = ifindex) == 0) { + if (ifname == NULL) { + errno = EINVAL; /* must supply either index or name */ + return (-1); + } + if ((idx = if_nametoindex (ifname)) == 0) { + errno = ENXIO; /* i/f name not found */ + return (-1); + } + } + return (setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (_SOTYPE)&idx, sizeof (idx))); + } + + default: +// errno = EAFNOSUPPORT; + return (-1); + } +} + +//-------------------------------------------------------------------------------------------------------------------------------------------- +UDPContext *server_udp_open (const struct in6_addr *mcg, int port, const char *ifname) +{ + UDPContext *s; + int sendfd; + int n; + + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + + s = (UDPContext *) calloc (1, sizeof (UDPContext)); + if (!s) { + err ("Cannot allocate memory !\n"); + goto error; + } + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) &s->dest_addr; + + addr->sin6_addr=*mcg;; + addr->sin6_family = AF_INET6; + addr->sin6_port = htons (port); + s->dest_addr_len = sizeof (struct sockaddr_in6); + + sendfd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (sendfd < 0) { + err ("cannot get socket\n"); + } + + s->dest_addr_len = sizeof (struct sockaddr_in6); + + if ((udp_ipv6_is_multicast_address ((struct sockaddr *) &s->dest_addr))) { + if (ifname && strlen (ifname) && (mcast_set_if (sendfd, ifname, 0) < 0)) { + warn ("mcast_set_if error\n"); + goto error; + } + if (udp_ipv6_set_multicast_ttl (sendfd, MCAST_TTL, (struct sockaddr *) &s->dest_addr) < 0) { + warn ("udp_ipv6_set_multicast_ttl"); + } + } + + n = UDP_TX_BUF_SIZE; + if (setsockopt (sendfd, SOL_SOCKET, SO_SNDBUF, (_SOTYPE)&n, sizeof (n)) < 0) { + warn ("setsockopt sndbuf"); + } + s->is_multicast = 0; //server + s->udp_fd = sendfd; + s->local_port = port; + + dbg ("Multicast streamer initialized successfully ! \n"); + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + return s; + error: + err ("Cannot init udp_server !\n"); + if (s) { + free (s); + } + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + return NULL; +} + +UDPContext *server_udp_open_host (const char *host, int port, const char *ifname) +{ + struct in6_addr addr; + + inet_pton (AF_INET6, host, &addr); + + return server_udp_open (&addr, port, ifname); +} + +//-------------------------------------------------------------------------------------------------------------------------------------------- +UDPContext *client_udp_open (const struct in6_addr *mcg, int port, const char *ifname) +{ + UDPContext *s; + int recvfd; + int n; + + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + + s = (UDPContext *) calloc (1, sizeof (UDPContext)); + if (!s) { + err ("Cannot allocate memory !\n"); + goto error; + } + + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) &s->dest_addr; +#ifndef WIN32 + addr->sin6_addr=*mcg; +#else + struct in6_addr any; + memset(&any,0,sizeof(any)); + addr->sin6_addr=any; +#endif + addr->sin6_family = AF_INET6; + addr->sin6_port = htons (port); + s->dest_addr_len = sizeof (struct sockaddr_in6); + + recvfd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (recvfd < 0) { + err ("cannot get socket\n"); + } +#ifdef WIN32 +# ifndef IPV6_PROTECTION_LEVEL +# define IPV6_PROTECTION_LEVEL 23 +# endif + n = 10 /*PROTECTION_LEVEL_UNRESTRICTED*/; + if(setsockopt( recvfd, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (_SOTYPE)&n, sizeof(n) ) < 0 ) { + warn ("setsockopt IPV6_PROTECTION_LEVEL\n"); + } +#endif + n = 1; + if (setsockopt (recvfd, SOL_SOCKET, SO_REUSEADDR, (_SOTYPE)&n, sizeof (n)) < 0) { + warn ("setsockopt REUSEADDR\n"); + } + +#if ! (defined WIN32 || defined APPLE) + if (ifname && strlen (ifname) && setsockopt (recvfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen (ifname) + 1)) { + dbg ("setsockopt SO_BINDTODEVICE %s failed\n", ifname); + } +#endif + if (bind (recvfd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len) < 0) { + warn ("bind failed\n"); + goto error; + } +#ifdef WIN32 + addr->sin6_addr=*mcg; +#endif + if (udp_ipv6_is_multicast_address ((struct sockaddr *) &s->dest_addr)) { +#if 0 + if (ifname && strlen (ifname) && (mcast_set_if (recvfd, ifname, 0) < 0)) { + warn ("mcast_set_if error \n"); + goto error; + } +#endif + if (ifname) { + if ((s->idx = if_nametoindex (ifname)) == 0) { + s->idx = 0; + } else { + dbg("Selecting interface %s (%d)", ifname, s->idx); + } + } else { + s->idx = 0; + } + + if (udp_ipv6_join_multicast_group (recvfd, s->idx, (struct sockaddr *) &s->dest_addr) < 0) { + warn ("Cannot join multicast group !\n"); + goto error; + } + s->is_multicast = 1; + } + + n = UDP_RX_BUF_SIZE; + if (setsockopt (recvfd, SOL_SOCKET, SO_RCVBUF, (_SOTYPE)&n, sizeof (n)) < 0) { + warn ("setsockopt rcvbuf"); + goto error; + } + + s->udp_fd = recvfd; + s->local_port = port; + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + + return s; + error: + warn ("socket error !\n"); + if (s) { + free (s); + } + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + return NULL; +} + +UDPContext *client_udp_open_host (const char *host, int port, const char *ifname) +{ + struct in6_addr addr; + + inet_pton (AF_INET6, host, &addr); + + return client_udp_open (&addr, port, ifname); +} + +//-------------------------------------------------------------------------------------------------------------------------------------------- +int udp_read (UDPContext * s, uint8_t * buf, int size, int timeout, struct sockaddr_storage *from) +{ + socklen_t from_len = sizeof (struct sockaddr_storage); + struct sockaddr_storage from_local; + + if(!from) { + from=&from_local; + } + + struct pollfd p; + p.fd = s->udp_fd; + p.events = POLLIN; + + if(poll(&p,1,(timeout+999)>>10)>0) { + return recvfrom (s->udp_fd, (char *)buf, size, 0, (struct sockaddr *) from, &from_len); + } + return -1; +} + +//-------------------------------------------------------------------------------------------------------------------------------------------------- +int udp_write (UDPContext * s, uint8_t * buf, int size) +{ + int ret; + + for (;;) { + ret = sendto (s->udp_fd, (char *) buf, size, 0, (struct sockaddr *) &s->dest_addr, s->dest_addr_len); + + if (ret < 0) { + if (errno != EINTR && errno != EAGAIN) + return -1; + } else { + break; + } + } + return size; +} + +//---------------------------------------------------------------------------------------------------------------------------------------------------- +int udp_close (UDPContext * s) +{ + if (s->is_multicast) + udp_ipv6_leave_multicast_group (s->udp_fd, s->idx, (struct sockaddr *) &s->dest_addr); + + closesocket (s->udp_fd); + free (s); + + return 0; +} + +//-------------------------------------------------------------------------------------------------------------------------------------------- + +#ifndef MULTI_THREAD_RECEIVER + +#define MAX_BUFF_SIZE 0x10000 +#define MAX_CON_LIST 128 +UDPContext *gConList[MAX_CON_LIST]; +pthread_mutex_t gConListLock = PTHREAD_MUTEX_INITIALIZER; +static int gConListInit=0; +static int gConListModified; +static UDPContext *gConChain; + +STATIC void client_upd_cleanup (void *arg) { + if(!gConListInit) return; + pthread_mutex_lock(&gConListLock); + memset(&gConList, 0, sizeof(gConList)); + gConListInit=0; + pthread_mutex_unlock(&gConListLock); +} // client_upd_cleanup + +void *client_upd_process(void *arg) { +#ifdef RT +#if 1 + if (setpriority (PRIO_PROCESS, 0, -15) == -1) +#else + if (pthread_setschedprio (p->recv_ts_thread, -15)) +#endif + { + dbg ("Cannot raise priority to -15\n"); + } +#endif + unsigned char buff[MAX_BUFF_SIZE]; + socklen_t from_len = sizeof (struct sockaddr_storage); + struct sockaddr_storage from_local; + struct pollfd fds[MAX_CON_LIST]; + + pthread_cleanup_push (client_upd_cleanup, 0); + int max_fd=0; + while(1) { + UDPContext *e; + pthread_mutex_lock(&gConListLock); + + if(gConListModified) { + gConListModified=0; + max_fd=0; + for(e=gConChain;e;e=e->next) { + fds[max_fd].fd = e->udp_fd; + fds[max_fd].events = POLLIN; + fds[max_fd].revents = 0; + e->pfd = &fds[max_fd]; + max_fd++; + } // for + } // if + pthread_mutex_unlock(&gConListLock); + int rs = poll(fds, max_fd, 1000); + if(rs>0) { + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + pthread_mutex_lock(&gConListLock); + for(e=gConChain;e;e=e->next) { + if(e->pfd && (e->pfd->revents & POLLIN)) { + if(e->cb) { + int ret = recvfrom (e->udp_fd, (char *)buff, MAX_BUFF_SIZE, 0, 0, 0/*(struct sockaddr *) &from_local, &from_len*/); + if(ret>0) + e->cb(buff, ret, e->arg); + } else if(e->buff && !e->bufflen) { + pthread_mutex_lock(&e->bufflock); + int ret = recvfrom (e->udp_fd, (char *)e->buff, e->buffmax, 0, (struct sockaddr *) &from_local, &from_len); + if(ret>0) + e->bufflen = ret; + pthread_mutex_unlock(&e->bufflock); + } // if + } // if + } // for + pthread_mutex_unlock(&gConListLock); + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + } // if + pthread_testcancel(); + } // while + pthread_cleanup_pop (1); + return NULL; +} + +static int client_upd_init() { + pthread_mutex_lock(&gConListLock); + if(gConListInit) { + pthread_mutex_unlock(&gConListLock); + return 1; + } // if + memset(&gConList, 0, sizeof(gConList)); + gConListModified = 0; + gConChain = NULL; + pthread_t client_upd_thread; + if(0==pthread_create (&client_upd_thread, NULL, client_upd_process, 0)) { + gConListInit = 1; + pthread_detach(client_upd_thread); + } // if + pthread_mutex_unlock(&gConListLock); + return gConListInit; +} // client_upd_init + +UDPContext *client_udp_open_buff (const struct in6_addr *mcg, int port, const char *ifname, int buff_size) { + UDPContext *ret = client_udp_open_cb (mcg, port, ifname, 0, 0); + if(ret) { + ret->buff = (unsigned char *)malloc(buff_size); + ret->buffmax = buff_size; + ret->bufflen = 0; + if (!ret->buff) { + err ("client_udp_open_buff: out of memory\n"); + } + } // if + return ret; +} // client_udp_open_buff + +UDPContext *client_udp_open_cb (const struct in6_addr *mcg, int port, const char *ifname, client_udp_cb cb, void *arg) +{ + if(!client_upd_init()) return NULL; + + UDPContext *s; + int recvfd = -1; + int n; + + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + + s = (UDPContext *) calloc (1, sizeof (UDPContext)); + if (!s) { + err ("Cannot allocate memory !\n"); + goto error; + } + + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) &s->dest_addr; +#ifndef WIN32 + addr->sin6_addr=*mcg; +#else + struct in6_addr any=IN6ADDR_ANY_INIT; + addr->sin6_addr=any; +#endif + addr->sin6_family = AF_INET6; + addr->sin6_port = htons (port); + s->dest_addr_len = sizeof (struct sockaddr_in6); + + recvfd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (recvfd < 0) { + err ("cannot get socket\n"); + } +#ifdef WIN32 +# ifndef IPV6_PROTECTION_LEVEL +# define IPV6_PROTECTION_LEVEL 23 +# endif + n = 10 /*PROTECTION_LEVEL_UNRESTRICTED*/; + if(setsockopt( recvfd, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (_SOTYPE)&n, sizeof(n) ) < 0 ) { + warn ("setsockopt IPV6_PROTECTION_LEVEL\n"); + } +#endif + n = 1; + if (setsockopt (recvfd, SOL_SOCKET, SO_REUSEADDR, (_SOTYPE)&n, sizeof (n)) < 0) { + warn ("setsockopt REUSEADDR\n"); + } + +#if ! (defined WIN32 || defined APPLE) + if (ifname && strlen (ifname) && setsockopt (recvfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen (ifname) + 1)) { + dbg ("setsockopt SO_BINDTODEVICE %s failed\n", ifname); + } +#endif + if (bind (recvfd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len) < 0) { + warn ("bind failed\n"); + goto error; + } +#ifdef WIN32 + addr->sin6_addr=*mcg; +#endif + if (udp_ipv6_is_multicast_address ((struct sockaddr *) &s->dest_addr)) { +#if 0 + if (ifname && strlen (ifname) && (mcast_set_if (recvfd, ifname, 0) < 0)) { + warn ("mcast_set_if error \n"); + goto error; + } +#endif + if (ifname) { + if ((s->idx = if_nametoindex (ifname)) == 0) { + s->idx = 0; + } else { + dbg("Selecting interface %s (%d)", ifname, s->idx); + } + } else { + s->idx = 0; + } + + if (udp_ipv6_join_multicast_group (recvfd, s->idx, (struct sockaddr *) &s->dest_addr) < 0) { + warn ("Cannot join multicast group !\n"); + goto error; + } + s->is_multicast = 1; + } + + n = cb ? UDP_PID_BUF_SIZE : UDP_RX_BUF_SIZE; + if (setsockopt (recvfd, SOL_SOCKET, SO_RCVBUF, (_SOTYPE)&n, sizeof (n)) < 0) { + warn ("setsockopt rcvbuf"); + goto error; + } + + s->udp_fd = recvfd; + s->local_port = port; + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + + s->cb = cb; + s->arg = arg; + pthread_mutex_init(&s->bufflock, NULL); + int i; + pthread_mutex_lock(&gConListLock); + for(i=0;i<MAX_CON_LIST;i++) { + if(!gConList[i]) { + gConList[i]=s; + gConListModified=1; + s->next=gConChain; + gConChain=s; + break; + } // if + } // for + pthread_mutex_unlock(&gConListLock); + if(i>=MAX_CON_LIST) + warn("---------------------------------------------No slot found!\n"); + + return s; + error: + warn ("socket error !\n"); + if (s) { + free (s); + } + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + return NULL; +} + +UDPContext *client_udp_open_host_buff (const char *host, int port, const char *ifname, int buff_size) +{ + struct in6_addr addr; + + inet_pton (AF_INET6, host, &addr); + + return client_udp_open_buff (&addr, port, ifname, buff_size); +} + +//-------------------------------------------------------------------------------------------------------------------------------------------- +int udp_read_buff (UDPContext * s, uint8_t * buf, int size, int timeout, struct sockaddr_storage *from) +{ + pthread_mutex_lock(&s->bufflock); + int ret = s->bufflen>size ? size : s->bufflen; + if(ret>0) { + memcpy(buf, s->buff, ret); + s->bufflen-=ret; + } + pthread_mutex_unlock(&s->bufflock); + return ret; +} +//---------------------------------------------------------------------------------------------------------------------------------------------------- +int udp_close_buff (UDPContext * s) +{ + int i; + pthread_mutex_lock(&gConListLock); + for(i=0;i<MAX_CON_LIST;i++) { + if(gConList[i] == s) { + gConList[i]=0; + gConListModified=1; + UDPContext **e; + for(e=&gConChain;*e;e=&(*e)->next) { + if(*e == s) { + *e=(*e)->next; + break; + } + } + break; + } + } + pthread_mutex_unlock(&gConListLock); + if (s->is_multicast) + udp_ipv6_leave_multicast_group (s->udp_fd, s->idx, (struct sockaddr *) &s->dest_addr); + + closesocket (s->udp_fd); + free(s->buff); + pthread_mutex_destroy(&s->bufflock); + free (s); + + return 0; +} +#endif diff --git a/mcast/common/.svn/text-base/mcast.h.svn-base b/mcast/common/.svn/text-base/mcast.h.svn-base new file mode 100644 index 0000000..33a6ed5 --- /dev/null +++ b/mcast/common/.svn/text-base/mcast.h.svn-base @@ -0,0 +1,64 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + * modified by Reel Multimedia, http://www.reel-multimedia.com, info@reel-multimedia.com + * 01042010 DL: use a single thread for reading from network layer (uses less resources) + * + */ + +#ifndef __MCAST_H__ +#define __MCAST_H__ + +typedef void (*client_udp_cb)(unsigned char *buf, int n, void *arg); + +typedef struct _UDPContext +{ + struct _UDPContext *next; + SOCKET udp_fd; + int ttl; + int idx; + int is_multicast; + int local_port; + int reuse_socket; + struct sockaddr_storage dest_addr; + size_t dest_addr_len; + + client_udp_cb cb; + void *arg; + unsigned char *buff; + int buffmax; + int bufflen; + pthread_mutex_t bufflock; + struct pollfd *pfd; +} UDPContext; + +#define SA struct sockaddr + +#define UDP_TX_BUF_SIZE 131072 +#define UDP_RX_BUF_SIZE 131072 +#define UDP_PID_BUF_SIZE 1048576 +#define MCAST_TTL 16 + +UDPContext *server_udp_open_host (const char *host, int port, const char *ifname); +UDPContext *server_udp_open (const struct in6_addr *mcg, int port, const char *ifname); +UDPContext *client_udp_open (const struct in6_addr *mcg, int port, const char *ifname); +UDPContext *client_udp_open_host (const char *host, int port, const char *ifname); + +int udp_read (UDPContext * s, uint8_t * buf, int size, int timeout, struct sockaddr_storage *from); +int udp_write (UDPContext * s, uint8_t * buf, int size); +int udp_close (UDPContext * s); + +#ifndef MULTI_THREAD_RECEIVER +UDPContext *client_udp_open_host_buff (const char *host, int port, const char *ifname, int buff_size); +UDPContext *client_udp_open_cb (const struct in6_addr *mcg, int port, const char *ifname, client_udp_cb cb, void *arg); +UDPContext *client_udp_open_buff (const struct in6_addr *mcg, int port, const char *ifname, int buff_size); +int udp_read_buff (UDPContext * s, uint8_t * buf, int size, int timeout, struct sockaddr_storage *from); +int udp_close_buff (UDPContext * s); +#endif + +int udp_ipv6_join_multicast_group (SOCKET sockfd, int iface, struct sockaddr *addr); +int udp_ipv6_leave_multicast_group (SOCKET sockfd, int iface, struct sockaddr *addr); +#endif diff --git a/mcast/common/.svn/text-base/mld.h.svn-base b/mcast/common/.svn/text-base/mld.h.svn-base new file mode 100644 index 0000000..93d2bd6 --- /dev/null +++ b/mcast/common/.svn/text-base/mld.h.svn-base @@ -0,0 +1,339 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#ifndef __MLD_H__ +#define __MLD_H__ + +/* Wrappers so we don't have to change the copied stuff ;) */ +#define __u8 uint8_t +#define __u16 uint16_t +/* Booleans */ +#define false 0 +#define true (!false) + + +/* Determine Endianness */ +#if ! defined __LITTLE_ENDIAN_BITFIELD && ! defined __BIG_ENDIAN_BITFIELD + #if BYTE_ORDER == LITTLE_ENDIAN + /* 1234 machines */ + #define __LITTLE_ENDIAN_BITFIELD 1 + #elif BYTE_ORDER == BIG_ENDIAN + /* 4321 machines */ + #define __BIG_ENDIAN_BITFIELD 1 + # define WORDS_BIGENDIAN 1 + #elif BYTE_ORDER == PDP_ENDIAN + /* 3412 machines */ + #error PDP endianness not supported yet! + #else + #error unknown endianness! + #endif +#endif + +/* Per RFC */ +struct mld1 +{ + __u8 type; + __u8 code; + __u16 csum; + __u16 mrc; + __u16 resv1; + struct in6_addr mca; +}; + +/* The timeout for queries */ +/* as per RFC3810 MLDv2 "9.2. Query Interval" */ +#define ECMH_SUBSCRIPTION_TIMEOUT 15 + +/* Robustness Factor, per RFC3810 MLDv2 "9.1. Robustness Variable" */ +#define ECMH_ROBUSTNESS_FACTOR 2 + + +/* MLDv2 Report */ +#ifndef ICMP6_V2_MEMBERSHIP_REPORT +#define ICMP6_V2_MEMBERSHIP_REPORT 143 +#endif +/* MLDv2 Report - Experimental Code */ +#ifndef ICMP6_V2_MEMBERSHIP_REPORT_EXP +#define ICMP6_V2_MEMBERSHIP_REPORT_EXP 206 +#endif + +/* MLDv2 Exclude/Include */ + +#ifndef MLD2_MODE_IS_INCLUDE +#define MLD2_MODE_IS_INCLUDE 1 +#endif +#ifndef MLD2_MODE_IS_EXCLUDE +#define MLD2_MODE_IS_EXCLUDE 2 +#endif +#ifndef MLD2_CHANGE_TO_INCLUDE +#define MLD2_CHANGE_TO_INCLUDE 3 +#endif +#ifndef MLD2_CHANGE_TO_EXCLUDE +#define MLD2_CHANGE_TO_EXCLUDE 4 +#endif +#ifndef MLD2_ALLOW_NEW_SOURCES +#define MLD2_ALLOW_NEW_SOURCES 5 +#endif +#ifndef MLD2_BLOCK_OLD_SOURCES +#define MLD2_BLOCK_OLD_SOURCES 6 +#endif + +#ifndef MLD2_ALL_MCR_INIT +#define MLD2_ALL_MCR_INIT { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x16 } } } +#endif + +#ifndef ICMP6_ROUTER_RENUMBERING +#define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */ +#endif +#ifndef ICMP6_NI_QUERY +#define ICMP6_NI_QUERY 139 /* node information request */ +#endif +#ifndef ICMP6_NI_REPLY +#define ICMP6_NI_REPLY 140 /* node information reply */ +#endif +#ifndef MLD_MTRACE_RESP +#define MLD_MTRACE_RESP 200 /* Mtrace response (to sender) */ +#endif +#ifndef MLD_MTRACE +#define MLD_MTRACE 201 /* Mtrace messages */ +#endif + +#ifndef ICMP6_DST_UNREACH_BEYONDSCOPE +#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* Beyond scope of source address */ +#endif + +#ifndef ICMP6_NI_SUCCESS +#define ICMP6_NI_SUCCESS 0 /* node information successful reply */ +#endif +#ifndef ICMP6_NI_REFUSED +#define ICMP6_NI_REFUSED 1 /* node information request is refused */ +#endif +#ifndef ICMP6_NI_UNKNOWN +#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */ +#endif + +#ifndef ICMP6_ROUTER_RENUMBERING_COMMAND +#define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */ +#endif +#ifndef ICMP6_ROUTER_RENUMBERING_RESULT +#define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */ +#endif +#ifndef ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET +#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */ +#endif + +#ifndef ICMP6_MEMBERSHIP_QUERY +#define ICMP6_MEMBERSHIP_QUERY 130 +#endif + +#ifndef ICMP6_MEMBERSHIP_REPORT +#define ICMP6_MEMBERSHIP_REPORT 131 +#endif + +#ifndef ICMP6_MEMBERSHIP_REDUCTION +#define ICMP6_MEMBERSHIP_REDUCTION 132 +#endif + +#ifndef ICMP6_DST_UNREACH_NOTNEIGHBOR +#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor */ +#endif + +#ifdef __UCLIBC__ + +#ifndef IP6OPT_PADN +#define IP6OPT_PADN 1 +#endif + +#ifndef ip6_ext +struct ip6_ext +{ + uint8_t ip6e_nxt; + uint8_t ip6e_len; +}; +#endif +#endif + +#ifdef WIN32 +struct ip6_hdr + { + union + { + struct ip6_hdrctl + { + uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, + 20 bits flow-ID */ + uint16_t ip6_un1_plen; /* payload length */ + uint8_t ip6_un1_nxt; /* next header */ + uint8_t ip6_un1_hlim; /* hop limit */ + } ip6_un1; + uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */ + } ip6_ctlun; + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ + }; +#define ICMP6_DST_UNREACH 1 +#define ICMP6_TIME_EXCEEDED 3 +#define ICMP6_PARAM_PROB 4 + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim + +#define IP6OPT_PADN 1 + +/* Hop-by-Hop options header. */ +struct ip6_hbh + { + uint8_t ip6h_nxt; /* next header. */ + uint8_t ip6h_len; /* length in units of 8 octets. */ + /* followed by options */ + }; + +#endif + + +/* From linux/net/ipv6/mcast.c */ + +/* + * These header formats should be in a separate include file, but icmpv6.h + * doesn't have in6_addr defined in all cases, there is no __u128, and no + * other files reference these. + * + * +-DLS 4/14/03 + * + * Multicast Listener Discovery version 2 headers + * Modified as they are where not ANSI C compliant + */ +struct mld2_grec +{ + __u8 grec_type; + __u8 grec_auxwords; + __u16 grec_nsrcs; + struct in6_addr grec_mca; +/* struct in6_addr grec_src[0]; */ +}; + +struct mld2_report +{ + __u8 type; + __u8 resv1; + __u16 csum; + __u16 resv2; + __u16 ngrec; +/* struct mld2_grec grec[0]; */ +}; + +struct mld2_query +{ + __u8 type; + __u8 code; + __u16 csum; + __u16 mrc; + __u16 resv1; + struct in6_addr mca; +#if defined(__LITTLE_ENDIAN_BITFIELD) + uint32_t qrv:3, suppress:1, resv2:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + uint32_t resv2:4, suppress:1, qrv:3; +#else +#error "Please fix <asm/byteorder.h>" +#endif + __u8 qqic; + __u16 nsrcs; +/* struct in6_addr srcs[0]; */ +}; + +#define IGMP6_UNSOLICITED_IVAL (10*HZ) +#define MLD_QRV_DEFAULT 2 + +#define MLD_V1_SEEN(idev) ((idev)->mc_v1_seen && \ + time_before(jiffies, (idev)->mc_v1_seen)) + +#define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) +#define MLDV2_EXP(thresh, nbmant, nbexp, value) \ + ((value) < (thresh) ? (value) : \ + ((MLDV2_MASK(value, nbmant) | (1<<(nbmant+nbexp))) << \ + (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) + +#define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) +#define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) + +#define bool int + +#define RAW_RX_BUF_SIZE 1024*1024 + +struct lookup +{ + unsigned int num; + const char *desc; +}; + +/* Our configuration structure */ +struct conf +{ + unsigned int maxinterfaces; /* The max number of interfaces the array can hold */ + struct intnode *ints; /* The interfaces we are watching */ + + struct mc_group *groups; + + bool quit; /* Global Quit signal */ + + bool promisc; /* Make interfaces promisc? (To be sure to receive all MLD's) */ + bool mode; /* Streamer 0 /Client mode 1 */ + + uint8_t *buffer; /* Our buffer */ + unsigned int bufferlen; /* Length of the buffer */ + + int rawsocket; /* Single RAW socket for sending and receiving everything */ + + unsigned int stat_packets_received; /* Number of packets received */ + unsigned int stat_packets_sent; /* Number of packets forwarded */ + unsigned int stat_bytes_received; /* Number of bytes received */ + unsigned int stat_bytes_sent; /* Number of bytes forwarded */ + unsigned int stat_icmp_received; /* Number of ICMP's received */ + unsigned int stat_icmp_sent; /* Number of ICMP's sent */ + + unsigned int mca_groups; + unsigned int subscribers; + cmdline_t *cmd; +#ifdef SERVER + tuner_t *tuner_parms; + int tuner_number; + + satellite_list_t *sat_list; + int sat_list_num; + int readconfig; + pthread_t mld_timer_thread; + pthread_t collect_stats_thread; + pthread_t stream_tca_thread; + pthread_t stream_tra_thread; + + int tca_id; +#endif + + pthread_mutex_t lock; +}; + +/* Global Stuff */ +extern struct conf *g_conf; +extern struct lookup mld2_grec_types[]; + + +const char *lookup (struct lookup *l, unsigned int num); +const char *icmpv6_type (unsigned int type); +const char *icmpv6_code (unsigned int type, unsigned int code); + +uint16_t ipv6_checksum (const struct ip6_hdr *ip6, uint8_t protocol, const void *data, const uint16_t length); +void sendpacket6 (struct intnode *intn, const struct ip6_hdr *iph, const uint16_t len); +//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + +int send_mldv2_report (struct intnode *intn, int grec_number, struct in6_addr *mcas, int srcn, struct in6_addr *sources, int mode); +int start_mld_daemon (void); + +#endif diff --git a/mcast/common/.svn/text-base/mld_client.c.svn-base b/mcast/common/.svn/text-base/mld_client.c.svn-base new file mode 100644 index 0000000..d291466 --- /dev/null +++ b/mcast/common/.svn/text-base/mld_client.c.svn-base @@ -0,0 +1,244 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#undef DEBUG +#include "headers.h" + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +int send_mldv2_report (struct intnode *intn, int grec_number, struct in6_addr *mcas, int srcn, struct in6_addr *sources, int mode) +{ + unsigned int length; + struct mld_report_packet + { + struct ip6_hdr ip6; + struct ip6_hbh hbh; + struct + { + uint8_t type; + uint8_t length; + uint16_t value; + uint8_t optpad[2]; + } routeralert; + struct mld2_report mld2r; + } *packet; + struct mld2_grec *grec = NULL; + struct in6_addr *src = NULL; + int mca_index, src_index; + int count = 0; + + bool any = false; + + + //printf("creating multicast listener report packet....\n"); + //printf("size src = %d size grec = %d \n",sizeof(*src),sizeof(*grec)); + if (intn->mtu < sizeof (*packet)) { + /* + * MTU is too small to support this type of packet + * Should not happen though + */ + dbg ("MTU too small for packet while sending MLDv2 report on interface %s/%u mtu=%u!?\n", intn->name, intn->ifindex, intn->mtu); + return -1; + } + + /* Allocate a buffer matching the MTU size of this interface */ + packet = (struct mld_report_packet *) malloc (intn->mtu); + + if (!packet) { + err ("Cannot get memory for MLD2 report packet, aborting\n"); + } +// printf("addr packet = %u \n",packet); + memset (packet, 0, intn->mtu); + + + /* Create the IPv6 packet */ + packet->ip6.ip6_vfc = 0x60; + packet->ip6.ip6_plen = ntohs (sizeof (*packet) - sizeof (packet->ip6)); + packet->ip6.ip6_nxt = IPPROTO_HOPOPTS; + packet->ip6.ip6_hlim = 1; + + /* + * The source address must be the link-local address + * of the interface we are sending on + */ + memcpy (&packet->ip6.ip6_src, &intn->linklocal, sizeof (packet->ip6.ip6_src)); + + /* MLDv2 Report -> All IPv6 Multicast Routers (ff02::16) */ + packet->ip6.ip6_dst.s6_addr[0] = 0xff; + packet->ip6.ip6_dst.s6_addr[1] = 0x02; + packet->ip6.ip6_dst.s6_addr[15] = 0x16; + + /* HopByHop Header Extension */ + packet->hbh.ip6h_nxt = IPPROTO_ICMPV6; + packet->hbh.ip6h_len = 0; + + /* Router Alert Option */ + packet->routeralert.type = 5; + packet->routeralert.length = sizeof (packet->routeralert.value); + packet->routeralert.value = 0; /* MLD ;) */ + + /* Option Padding */ + packet->routeralert.optpad[0] = IP6OPT_PADN; + packet->routeralert.optpad[1] = 0; + + /* ICMPv6 MLD Report */ + packet->mld2r.type = ICMP6_V2_MEMBERSHIP_REPORT; + //number of multi cast address reocrds + packet->mld2r.ngrec = 0; //grec_number;//htons(1); + length = 0; + count = 0; + for (mca_index = 0; mca_index < grec_number; mca_index++) { + src = NULL; + if (!grec) { + length = sizeof (*packet) + sizeof (*grec) - sizeof (packet->ip6); + //fprintf(stdout,"(grec = %02d) %02d. current report length = %04d MTU: %04d)\n",packet->mld2r.ngrec,mca_index,length+sizeof(packet->ip6),intn->mtu); + + if (length + sizeof (packet->ip6) > intn->mtu) { + /* Should not happen! Would mean the MTU is smaller than a standard mld report */ + dbg ("No grec and MTU too small for packet while sending MLDv2 report on interface %s/%u mtu=%u!?\n", intn->name, intn->ifindex, intn->mtu); + free (packet); + return (-1); + } else + grec = (struct mld2_grec *) (((char *) packet) + sizeof (*packet)); + + packet->mld2r.ngrec++; + } else { + if (!src) + length = ((((char *) grec) - ((char *) packet)) + sizeof (*grec) + (sizeof (*src) * (grec->grec_nsrcs))) - sizeof (packet->ip6); + + //fprintf(stdout,"\nloop1:(grec = %02d) %02d.length = %04d (Total : %04d MTU: %04d)\n\n", packet->mld2r.ngrec , mca_index,length,(length + sizeof(packet->ip6)), intn->mtu); + + if (((length + sizeof (packet->ip6) + sizeof (*grec)) > intn->mtu)) { + + /* Take care of endianess */ + //fprintf(stdout,"next grec record does not fit... sending... \n"); + + packet->mld2r.ngrec = htons (packet->mld2r.ngrec); + grec->grec_nsrcs = htons (grec->grec_nsrcs); + + /* Calculate and fill in the checksum */ + packet->ip6.ip6_plen = htons (length); + packet->mld2r.csum = htons (0); + packet->mld2r.csum = ipv6_checksum (&packet->ip6, IPPROTO_ICMPV6, (uint8_t *) & packet->mld2r, length - sizeof (struct ip6_hbh) - sizeof (packet->routeralert)); + count++; +#ifdef DEBUG + dbg ("%04d.Sending2 MLDv2 Report on %s/%u, ngrec=%u, length=%u sources=%u (in last grec)\n", count, intn->name, intn->ifindex, ntohs (packet->mld2r.ngrec), length, ntohs (grec->grec_nsrcs)); + sendpacket6 (intn, (const struct ip6_hdr *) packet, length + sizeof (packet->ip6)); +#endif + /* Increase ICMP sent statistics */ + g_conf->stat_icmp_sent++; + intn->stat_icmp_sent++; + + /* Reset the MLDv2 struct */ + packet->mld2r.ngrec = 0; + grec = (struct mld2_grec *) (((char *) packet) + sizeof (*packet)); + } else { + //next grec + grec->grec_nsrcs = htons (grec->grec_nsrcs); + grec = (struct mld2_grec *) (((char *) grec) + sizeof (*grec) + (sizeof (*src) * ntohs (grec->grec_nsrcs))); + + } + packet->mld2r.ngrec++; + } + //Copy MCA to record + memcpy (&grec->grec_mca, mcas + mca_index, sizeof (grec->grec_mca)); + + /* Zero sources upto now */ + grec->grec_nsrcs = 0; + /* 0 Sources -> Exclude those */ + grec->grec_type = MLD2_MODE_IS_EXCLUDE; + if (mode) { + grec->grec_type = mode; + } + + /* Nothing added yet */ + any = false; + + for (src_index = 0; src_index < srcn || (!srcn && src_index == 0); src_index++) { + + //check for duplicate source reocrds and any address + + /* Packet with at least one grec and one or more src's, excluding ip6 header */ + + length = (((char *) grec) - ((char *) packet)) + sizeof (*grec) + (sizeof (*src) * (grec->grec_nsrcs)) - sizeof (packet->ip6); + + //fprintf(stdout,"loop2:(grec = %02d) %02d.length = %04d (Total : %04d MTU: %04d)\n", packet->mld2r.ngrec,mca_index,length,(length + sizeof(packet->ip6)),intn->mtu); + /* Would adding it not fit? -> Send it out */ + if (((length + sizeof (packet->ip6) + sizeof (*src)) > (intn->mtu)) && srcn) { + //fprintf(stdout,"next source addr. does not fit... sending... \n"); + //fprintf(stdout,"src_index = %d grec->grec_nsrcs = %d \n",src_index,grec->grec_nsrcs); + + /* Take care of endianess */ + packet->mld2r.ngrec = htons (packet->mld2r.ngrec); + grec->grec_nsrcs = htons (grec->grec_nsrcs); + /* Calculate and fill in the checksum */ + + packet->ip6.ip6_plen = htons (length); + packet->mld2r.csum = htons (0); + packet->mld2r.csum = ipv6_checksum (&packet->ip6, IPPROTO_ICMPV6, (uint8_t *) & packet->mld2r, length - sizeof (struct ip6_hbh) - sizeof (packet->routeralert)); + + count++; + dbg ("%04d.Sending2 MLDv2 Report on %s/%u, ngrec=%u, length=%u sources=%u (in last grec)\n", count, intn->name, intn->ifindex, ntohs (packet->mld2r.ngrec), length, ntohs (grec->grec_nsrcs)); + sendpacket6 (intn, (const struct ip6_hdr *) packet, length + sizeof (packet->ip6)); + + /* Increase ICMP sent statistics */ + g_conf->stat_icmp_sent++; + intn->stat_icmp_sent++; + + /* Reset the MLDv2 struct */ + packet->mld2r.ngrec = 0; + src = NULL; + grec = NULL; + //if not IS_EX or TO EXCLUDE_MODE splitting must be done + break; + } + + /* Only add non-:: addresses */ + if (!srcn) + break; + if (!IN6_IS_ADDR_UNSPECIFIED (sources + src_index) && srcn) { + /* First/Next address */ + src = (struct in6_addr *) (((char *) grec) + sizeof (*grec) + (sizeof (*src) * grec->grec_nsrcs)); + /* An additional source */ + grec->grec_nsrcs++; + if (mode) { + grec->grec_type = mode; //MLD2_MODE_IS_EXCLUDE; + } + /* Append the source address */ + memcpy (src, sources + src_index, sizeof (*src)); + } + } + } + + //fprintf(stdout,"done\n"); + if (packet->mld2r.ngrec == 0) { + //fprintf(stdout,"All data sent !!!!!!\n"); + free (packet); + packet = NULL; + return (1); + } + /* Take care of endianess */ + length = (((char *) grec) - ((char *) packet) + sizeof (*grec) + (sizeof (*src) * (grec->grec_nsrcs)) - sizeof (packet->ip6)); + packet->mld2r.ngrec = htons (packet->mld2r.ngrec); + grec->grec_nsrcs = htons (grec->grec_nsrcs); + + /* Calculate and fill in the checksum */ + packet->ip6.ip6_plen = htons (length); + packet->mld2r.csum = htons (0); + packet->mld2r.csum = ipv6_checksum (&packet->ip6, IPPROTO_ICMPV6, (uint8_t *) & packet->mld2r, length - sizeof (struct ip6_hbh) - sizeof (packet->routeralert)); + count++; + dbg ("%04d.Sending2 MLDv2 Report on %s/%u, ngrec=%u, length=%u sources=%u (in last grec)\n", count, intn->name, intn->ifindex, ntohs (packet->mld2r.ngrec), length, ntohs (grec->grec_nsrcs)); + sendpacket6 (intn, (const struct ip6_hdr *) packet, length + sizeof (packet->ip6)); + + /* Increase ICMP sent statistics */ + g_conf->stat_icmp_sent++; + intn->stat_icmp_sent++; + + free (packet); + //fprintf(stdout,"Total ICMP packets sent = %llu\n", intn->stat_icmp_sent ); + return 0; +} diff --git a/mcast/common/.svn/text-base/mld_common.c.svn-base b/mcast/common/.svn/text-base/mld_common.c.svn-base new file mode 100644 index 0000000..77e05bd --- /dev/null +++ b/mcast/common/.svn/text-base/mld_common.c.svn-base @@ -0,0 +1,243 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#include "headers.h" +struct conf *g_conf=NULL; + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +#ifdef DEBUG +struct lookup icmpv6_types[] = { + {ICMP6_DST_UNREACH, "Destination Unreachable"}, + {ICMP6_PACKET_TOO_BIG, "Packet too big"}, + {ICMP6_TIME_EXCEEDED, "Time Exceeded"}, + {ICMP6_PARAM_PROB, "Parameter Problem"}, + {ICMP6_ECHO_REQUEST, "Echo Request"}, + {ICMP6_ECHO_REPLY, "Echo Reply"}, + {ICMP6_MEMBERSHIP_QUERY, "Membership Query"}, + {ICMP6_MEMBERSHIP_REPORT, "Membership Report"}, + {ICMP6_MEMBERSHIP_REDUCTION, "Membership Reduction"}, + {ICMP6_V2_MEMBERSHIP_REPORT, "Membership Report (V2)"}, + {ICMP6_V2_MEMBERSHIP_REPORT_EXP, "Membership Report (V2) - Experimental"}, + {ND_ROUTER_SOLICIT, "ND Router Solicitation"}, + {ND_ROUTER_ADVERT, "ND Router Advertisement"}, + {ND_NEIGHBOR_SOLICIT, "ND Neighbour Solicitation"}, + {ND_NEIGHBOR_ADVERT, "ND Neighbour Advertisement"}, + {ND_REDIRECT, "ND Redirect"}, + {ICMP6_ROUTER_RENUMBERING, "Router Renumbering",}, + {ICMP6_NI_QUERY, "Node Information Query"}, + {ICMP6_NI_REPLY, "Node Information Reply"}, + {MLD_MTRACE_RESP, "Mtrace Response"}, + {MLD_MTRACE, "Mtrace Message"}, + {0, NULL}, +}, icmpv6_codes_unreach[] = { + {ICMP6_DST_UNREACH_NOROUTE, "No route to destination"}, + {ICMP6_DST_UNREACH_ADMIN, "Administratively prohibited"}, + {ICMP6_DST_UNREACH_NOTNEIGHBOR, "Not a neighbor (obsolete)"}, + {ICMP6_DST_UNREACH_BEYONDSCOPE, "Beyond scope of source address"}, + {ICMP6_DST_UNREACH_ADDR, "Address Unreachable"}, + {ICMP6_DST_UNREACH_NOPORT, "Port Unreachable"}, +}, icmpv6_codes_ttl[] = { + + {ICMP6_TIME_EXCEED_TRANSIT, "Time Exceeded during Transit",}, + {ICMP6_TIME_EXCEED_REASSEMBLY, "Time Exceeded during Reassembly"}, +}, icmpv6_codes_param[] = { + + {ICMP6_PARAMPROB_HEADER, "Erroneous Header Field"}, + {ICMP6_PARAMPROB_NEXTHEADER, "Unrecognized Next Header"}, + {ICMP6_PARAMPROB_OPTION, "Unrecognized Option"}, +}, icmpv6_codes_ni[] = { + + {ICMP6_NI_SUCCESS, "Node Information Successful Reply"}, + {ICMP6_NI_REFUSED, "Node Information Request Is Refused"}, + {ICMP6_NI_UNKNOWN, "Unknown Qtype"}, +}, icmpv6_codes_renumber[] = { + + {ICMP6_ROUTER_RENUMBERING_COMMAND, "Router Renumbering Command"}, + {ICMP6_ROUTER_RENUMBERING_RESULT, "Router Renumbering Result"}, + {ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "Router Renumbering Sequence Number Reset"}, +}, mld2_grec_types[] = { + + {MLD2_MODE_IS_INCLUDE, "MLDv2 Mode Is Include"}, + {MLD2_MODE_IS_EXCLUDE, "MLDv2 Mode Is Exclude"}, + {MLD2_CHANGE_TO_INCLUDE, "MLDv2 Change to Include"}, + {MLD2_CHANGE_TO_EXCLUDE, "MLDv2 Change to Exclude"}, + {MLD2_ALLOW_NEW_SOURCES, "MLDv2 Allow New Source"}, + {MLD2_BLOCK_OLD_SOURCES, "MLDv2 Block Old Sources"}, +}; +#endif + +//---------------------------------------------------------------------------------------------------------------- +const char *lookup (struct lookup *l, unsigned int num) +{ + unsigned int i; + for (i = 0; l && l[i].desc; i++) { + if (l[i].num != num) + continue; + return l[i].desc; + } + return "Unknown"; +} + +const char *icmpv6_type (unsigned int type) +{ +#ifdef DEBUG + return lookup (icmpv6_types, type); +#else + return ""; +#endif +} + +const char *icmpv6_code (unsigned int type, unsigned int code) +{ +#ifdef DEBUG + struct lookup *l = NULL; + switch (type) { + case ICMP6_DST_UNREACH: + l = icmpv6_codes_unreach; + break; + case ICMP6_TIME_EXCEEDED: + l = icmpv6_codes_ttl; + break; + case ICMP6_PARAM_PROB: + l = icmpv6_codes_param; + break; + case ICMP6_NI_QUERY: + case ICMP6_NI_REPLY: + l = icmpv6_codes_ni; + break; + case ICMP6_ROUTER_RENUMBERING: + l = icmpv6_codes_renumber; + break; + } + return lookup (l, code); +#else + return ""; +#endif +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +uint16_t inchksum (const void *data, uint32_t length) +{ + register long sum = 0; + register const uint16_t *wrd = (const uint16_t *) data; + register long slen = (long) length; + + while (slen >= 2) { + sum += *wrd++; + slen -= 2; + } + + if (slen > 0) + sum += *(const uint8_t *) wrd; + + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + + return (uint16_t) sum; +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +uint16_t ipv6_checksum (const struct ip6_hdr * ip6, uint8_t protocol, const void *data, const uint16_t length) +{ + struct + { + uint16_t length; + uint16_t zero1; + uint8_t zero2; + uint8_t next; + } pseudo; + register uint32_t chksum = 0; + + pseudo.length = htons (length); + pseudo.zero1 = 0; + pseudo.zero2 = 0; + pseudo.next = protocol; + + /* IPv6 Source + Dest */ + chksum = inchksum (&ip6->ip6_src, sizeof (ip6->ip6_src) + sizeof (ip6->ip6_dst)); + chksum += inchksum (&pseudo, sizeof (pseudo)); + chksum += inchksum (data, length); + + /* Wrap in the carries to reduce chksum to 16 bits. */ + chksum = (chksum >> 16) + (chksum & 0xffff); + chksum += (chksum >> 16); + + /* Take ones-complement and replace 0 with 0xFFFF. */ + chksum = (uint16_t) ~ chksum; + if (chksum == 0UL) + chksum = 0xffffUL; + return (uint16_t) chksum; +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +void sendpacket6 (struct intnode *intn, const struct ip6_hdr *iph, const uint16_t len) +{ + int sent; +#if ! (defined WIN32 || defined APPLE) + struct sockaddr_ll sa; + + memset (&sa, 0, sizeof (sa)); + + sa.sll_family = AF_PACKET; + sa.sll_protocol = htons (ETH_P_IPV6); + sa.sll_ifindex = intn->ifindex; + sa.sll_hatype = intn->hwaddr.sa_family; + sa.sll_pkttype = 0; + sa.sll_halen = 6; + + /* + * Construct a Ethernet MAC address from the IPv6 destination multicast address. + * Per RFC2464 + */ + sa.sll_addr[0] = 0x33; + sa.sll_addr[1] = 0x33; + sa.sll_addr[2] = iph->ip6_dst.s6_addr[12]; + sa.sll_addr[3] = iph->ip6_dst.s6_addr[13]; + sa.sll_addr[4] = iph->ip6_dst.s6_addr[14]; + sa.sll_addr[5] = iph->ip6_dst.s6_addr[15]; + + /* Send the packet */ + errno = 0; + +#else +// info("Send on Interface %s@%d len:%d\n",intn->name, intn->ifindex, len); + struct sockaddr_in6 sa; + memset (&sa, 0, sizeof (sa)); + + sa.sin6_family = AF_INET6; + sa.sin6_addr = iph->ip6_dst; +#endif +#ifdef APPLE + unsigned char *x=(unsigned char *)iph; + sent = sendto (g_conf->rawsocket, (_SOTYPE)x+40, len-40, 0, (struct sockaddr *) &sa, sizeof (sa)); +#else + sent = sendto (g_conf->rawsocket, (_SOTYPE)iph, len, 0, (struct sockaddr *) &sa, sizeof (sa)); +#endif + if (sent < 0) { + /* + * Remove the device if it doesn't exist anymore, + * can happen with dynamic tunnels etc + */ + if (errno == ENXIO) { + warn ("Cannot send %u bytes on interface %s received ENXIO, interface %u no longer usable\n", len, intn->name, intn->ifindex); + /* Destroy the interface itself */ + int_destroy (intn); + } else + warn ("Cannot send %u bytes on interface %s (%d) failed with a mtu of %u: %s (errno %d)\n", len, intn->name, intn->ifindex, intn->mtu, strerror (errno), errno); + return; + } + + /* Update the global statistics */ + g_conf->stat_packets_sent++; + g_conf->stat_bytes_sent += len; + + /* Update interface statistics */ + intn->stat_bytes_sent += len; + intn->stat_packets_sent++; + return; +} diff --git a/mcast/common/.svn/text-base/recv_ccpp.c.svn-base b/mcast/common/.svn/text-base/recv_ccpp.c.svn-base new file mode 100644 index 0000000..ce15e4c --- /dev/null +++ b/mcast/common/.svn/text-base/recv_ccpp.c.svn-base @@ -0,0 +1,1333 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#undef DEBUG +#include "headers.h" + +extern int port; +extern char iface[IFNAMSIZ]; + +typedef struct +{ + xmlDocPtr doc; + xmlChar *str, *key; +} xml_parser_context_t; + +STATIC void clean_xml_parser_thread (void *arg) +{ + xml_parser_context_t *c = (xml_parser_context_t *) arg; + if (c->str) { + xmlFree (c->str); + } + if (c->key) { + xmlFree (c->key); + } + if (c->doc) { + xmlFreeDoc (c->doc); + } + dbg ("Free XML parser structures!\n"); +} + +int get_tra_data (xmlChar * xmlbuff, int buffersize, tra_info_t * tra_info) +{ + xml_parser_context_t c; + xmlNode *root_element = NULL, *cur_node = NULL; + +// xmlKeepBlanksDefault (0); //reomve this f. "text" nodes +// c.doc = xmlParseMemory ((char *) xmlbuff, buffersize); +// xmlKeepBlanksDefault doesn't work after patching cam flags + c.doc = xmlReadMemory((char *) xmlbuff, buffersize, NULL, "UTF-8", XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS ); + root_element = xmlDocGetRootElement (c.doc); + pthread_cleanup_push (clean_xml_parser_thread, &c); + time_t t=time(NULL); + + if (root_element != NULL) { + + cur_node = root_element->children; + + if (!xmlStrcmp (cur_node->name, (xmlChar *) "Description")) { + + root_element = cur_node->children; + while (root_element != NULL) { + c.key = NULL; + c.str = NULL; + if ((xmlStrcmp (root_element->name, (const xmlChar *) "component"))) { + warn ("Cannot parse XML data\n"); + root_element = root_element->next; + continue; + } + + cur_node = root_element->children; + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Description"))) { + c.str = xmlGetProp (cur_node, (unsigned char *) "about"); +// fprintf(stdout,"\n%s:\n",c.str); +// fprintf(stdout,"-----------------------------------------------------------\n"); + } else { + warn ("Cannot parse XML data\n"); + root_element = root_element->next; + continue; + } +#ifdef P2P + if (c.str && (!xmlStrcmp (c.str, (const xmlChar *) "P2P_Data"))) { + cur_node = cur_node->children; + while (cur_node != NULL) { + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Quit"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Quit: %s\n", c.key); + tra_info->quit = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "TCA_ID"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("TCA_ID: %s\n", c.key); + tra_info->tca_id = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "MC_Groups"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("MC_Groups: %s\n", c.key); + tra_info->mca_grps = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "IP"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("IP: %s\n", c.key); + inet_pton (AF_INET6, (char *) c.key, &tra_info->ipv6); + xmlFree (c.key); + } + } + cur_node = cur_node->next; + } + } else if (c.str && (!xmlStrcmp (c.str, (const xmlChar *) "Tuner_Status"))) { +#else + if (c.str && (!xmlStrcmp (c.str, (const xmlChar *) "Tuner_Status"))) { +#endif + cur_node = cur_node->children; + tra_info->tra = (tra_t *) realloc (tra_info->tra, (tra_info->tra_num + 1) * sizeof (tra_t)); + if (!tra_info->tra) { + err ("Cannot get memory for tra_t\n"); + } + tra_t *tra = tra_info->tra + tra_info->tra_num; + memset(tra, 0, sizeof (tra_t)); + tra->magic=MCLI_MAGIC; + tra->version=MCLI_VERSION; + + while (cur_node != NULL) { + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Status"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Status: %s\n", c.key); + tra->s.st = (fe_status_t) atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Signal"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Signal: %s\n", c.key); + tra->s.strength = (u_int16_t) atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "SNR"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("SNR: %s\n", c.key); + tra->s.snr = (u_int16_t) atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "BER"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("BER: %s\n", c.key); + tra->s.ber = (u_int32_t) atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "UNC"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("UNC: %s\n", c.key); + tra->s.ucblocks = (u_int32_t) atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Slot"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Slot: %s\n", c.key); + tra->slot = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "RotorStatus"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Rotor: %s\n", c.key); + tra->rotor_status = (u_int32_t) atoi ((char *) c.key); + xmlFree (c.key); + } + + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "RotorDiff"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Rotor: %s\n", c.key); + tra->rotor_diff = (u_int32_t) atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "UUID"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("UUID: %s\n", c.key); + strncpy (tra->uuid, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "MCG"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("MCG: %s\n", c.key); + inet_pton (AF_INET6, (char *) c.key, &tra->mcg); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Redirect"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Redirect: %s\n", c.key); + tra->redirect = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "NIMCurrent"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("NIMCurrent: %s\n", c.key); + tra->NIMCurrent = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "InUse"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("InUse: %s\n", c.key); + tra->InUse = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Frequency"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Frequency: %s\n", c.key); + tra->fep.frequency = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Inversion"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Inversion: %s\n", c.key); + tra->fep.inversion = (fe_spectral_inversion_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Type"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Type: %s\n", c.key); + tra->fe_type = (fe_type_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } +#ifdef P2P + else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Token"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Token: %s\n", c.key); + tra->token = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Preference"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Preference: %s\n", c.key); + tra->preference = atoi ((char *) c.key); + xmlFree (c.key); + } + } +#endif + else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "SymbolRate"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("SymbolRate: %s\n", c.key); + int val=atoi ((char *) c.key); + switch((int)tra->fe_type) { + case FE_DVBS2: + case FE_QPSK: + tra->fep.u.qpsk.symbol_rate=val; + break; + case FE_QAM: + tra->fep.u.qam.symbol_rate=val; + break; + case FE_OFDM: + default: + break; + } + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "FecInner"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("FecInner: %s\n", c.key); + int val=atoi ((char *) c.key); + switch((int)tra->fe_type) { + case FE_DVBS2: + case FE_QPSK: + tra->fep.u.qpsk.fec_inner=(fe_code_rate_t)val; + break; + case FE_QAM: + tra->fep.u.qam.fec_inner=(fe_code_rate_t)val; + break; + case FE_OFDM: + default: + break; + } + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Modulation"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Modulation: %s\n", c.key); + int val=atoi ((char *) c.key); + switch((int)tra->fe_type) { + case FE_QAM: + tra->fep.u.qam.modulation=(fe_modulation_t)val; + break; + case FE_ATSC: + tra->fep.u.vsb.modulation=(fe_modulation_t)val; + break; + case FE_DVBS2: + case FE_QPSK: + case FE_OFDM: + default: + break; + + } + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Bandwidth"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Bandwidth: %s\n", c.key); + tra->fep.u.ofdm.bandwidth=(fe_bandwidth_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "CodeRateHP"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("CodeRateHP: %s\n", c.key); + tra->fep.u.ofdm.code_rate_HP=(fe_code_rate_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "CodeRateLP"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("CodeRateLP: %s\n", c.key); + tra->fep.u.ofdm.code_rate_LP=(fe_code_rate_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Constellation"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Constellation: %s\n", c.key); + tra->fep.u.ofdm.constellation=(fe_modulation_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "TransmissionMode"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("TransmissionMode: %s\n", c.key); + tra->fep.u.ofdm.transmission_mode=(fe_transmit_mode_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "GuardInterval"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("GuardInterval: %s\n", c.key); + tra->fep.u.ofdm.guard_interval=(fe_guard_interval_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "HierarchyInformation"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("HierarchyInformation: %s\n", c.key); + tra->fep.u.ofdm.hierarchy_information=(fe_hierarchy_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } + cur_node = cur_node->next; + } + tra->lastseen=t; + tra_info->tra_num++; + } else if (c.str && (!xmlStrcmp (c.str, (const xmlChar *) "CAM"))) { + cur_node = cur_node->children; + cam_info_t *cam = tra_info->cam + tra_info->cam_num; + while(cur_node) { + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Slot"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->slot = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Status"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->status = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "MenuString"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + strncpy(cam->menu_string, (char *) c.key, MAX_MENU_STR_LEN-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Flags"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->flags = (nc_ca_caps_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "MaxSids"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->max_sids = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "UseSids"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->use_sids = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "PmtFlag"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->capmt_flag = atoi ((char *) c.key); + xmlFree (c.key); + } + } + cur_node = cur_node->next; + } + tra_info->cam_num++; + } + xmlFree (c.str); + root_element = root_element->next; + } + } + } + xmlFreeDoc (c.doc); + pthread_cleanup_pop (0); + return (1); +} + +#ifdef CLIENT +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +typedef struct ccpp_thread_context +{ + UDPContext *s; + xmlChar *buf; + xmlChar *dst; + int run; +} ccpp_thread_context_t; + + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +STATIC void clean_ccpp_thread (void *arg) +{ + ccpp_thread_context_t *c = (ccpp_thread_context_t *) arg; + if (c->s) { +#ifdef MULTI_THREAD_RECEIVER + udp_close (c->s); +#else + udp_close_buff (c->s); +#endif + } + if(c->buf) { + free (c->buf); + } + if(c->dst) { + free (c->dst); + } + dbg ("CCPP thread data buffer for tid %d freed !\n", gettid ()); +} + +void *recv_ten (void *arg) +{ + recv_info_t *r = (recv_info_t *) arg; + ccpp_thread_context_t c; + struct in6_addr ten = r->mcg; + int n; + tra_info_t tra_info; + unsigned int dstlen; + clock_t lastrecv=0; + int donetimeout=0; + + pthread_cleanup_push (clean_ccpp_thread, &c); + memset (&c, 0, sizeof (ccpp_thread_context_t)); + + c.buf=(xmlChar *)malloc(XML_BUFLEN); + if (!c.buf) { + err ("Cannot get memory for TEN buffer\n"); + } + c.dst=(xmlChar *)malloc(XML_BUFLEN * 5); + if (!c.dst) { + err ("Cannot get memory for TEN destination buffer\n"); + } + +#ifdef FE_STATUS_CLEAR + memset (&r->fe_status, 0, sizeof(recv_festatus_t)); + ioctl (r->fd, DVBLO_SET_FRONTEND_STATUS, &r->fe_status); +#endif + memset (&tra_info, 0, sizeof (tra_info_t)); + tra_info.magic=MCLI_MAGIC; + tra_info.version=MCLI_VERSION; + + mcg_set_streaming_group (&ten, STREAMING_TEN); +#ifdef MULTI_THREAD_RECEIVER + c.s = client_udp_open (&ten, port, iface); +#else + c.s = client_udp_open_buff (&ten, port, iface, XML_BUFLEN); +#endif + if (!c.s) { + warn ("client_udp_open error !\n"); + } else { +#ifdef DEBUG + char host[INET6_ADDRSTRLEN]; + inet_ntop (AF_INET6, &ten, (char *) host, INET6_ADDRSTRLEN); + dbg ("Start receive TEN for tid %d receiver %p at %s port %d %s\n", gettid (), r, host, port, iface); +#endif + r->ten_run = 1; + while (r->ten_run) { +#ifdef MULTI_THREAD_RECEIVER + if ((n = udp_read (c.s, c.buf, XML_BUFLEN, 1000, NULL)) > 0) { +#else + usleep(100000); // 10 times per seconds should be enough + if ((n = udp_read_buff (c.s, c.buf, XML_BUFLEN, 1000, NULL)) > 0) { +#endif + dstlen = XML_BUFLEN*5; + if (!gunzip (c.dst, &dstlen, c.buf, n)) { + memset (&tra_info, 0, sizeof (tra_info_t)); + tra_info.magic=MCLI_MAGIC; + tra_info.version=MCLI_VERSION; + + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + if (get_tra_data (c.dst, dstlen, &tra_info)) { + lastrecv=clock(); + donetimeout=0; + if (tra_info.tra_num) { + r->fe_status = tra_info.tra->s; + if(r->handle_ten) { + r->handle_ten (tra_info.tra, r->handle_ten_context); + } + + if (tra_info.tra->redirect) { +#ifdef DEBUG + char hostname[INET6_ADDRSTRLEN]; + inet_ntop (AF_INET6, &tra_info.tra->mcg, hostname, INET6_ADDRSTRLEN); + dbg ("Redirect for receiver %p: MCG is at %s\n", r, hostname); +#endif + int ret = recv_redirect (r, tra_info.tra->mcg); + + if (ret) { + printf("New MCG for recv_ten !\n"); +#ifdef MULTI_THREAD_RECEIVER + udp_close (c.s); +#else + udp_close_buff (c.s); +#endif + struct in6_addr ten = r->mcg; + mcg_set_streaming_group (&ten, STREAMING_TEN); +#ifdef MULTI_THREAD_RECEIVER + c.s = client_udp_open (&ten, port, iface); +#else + c.s = client_udp_open_buff (&ten, port, iface, XML_BUFLEN); +#endif + if (!c.s) { + warn ("client_udp_open error !\n"); + break; + } + } + } + } + free (tra_info.tra); + tra_info.tra=NULL; + } + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + } else { + dbg ("uncompress failed\n"); + } + } else { + if (!donetimeout && (clock()-lastrecv)>(TEN_TIMEOUT*CLOCKS_PER_SEC)) { + donetimeout=1; + memset (&r->fe_status, 0, sizeof(recv_festatus_t)); + if(r->handle_ten) { + r->handle_ten (NULL, r->handle_ten_context); + } + dbg ("Signal Timeout on receiver %p!\n", r); + } + } + pthread_testcancel(); + } +#ifdef DEBUG + dbg ("Stop receive TEN on receiver %p %s %d %s\n", r, host, port, iface); +#endif + } + pthread_cleanup_pop (1); + r->ten_run = 1; + return NULL; +} + +int register_ten_handler (recv_info_t * r, int (*p) (tra_t *, void *c), void *c) +{ + r->handle_ten=p; + r->handle_ten_context=c; + return 0; +} + +void *recv_tra (void *arg) +{ + ccpp_thread_context_t c; + int n; + tra_info_t tra_info; + unsigned int dstlen; + struct in6_addr tra; + + pthread_cleanup_push (clean_ccpp_thread, &c); + memset (&c, 0, sizeof (ccpp_thread_context_t)); + + c.buf=(xmlChar *)malloc(XML_BUFLEN); + if (!c.buf) { + err ("Cannot get memory for TRA buffer\n"); + } + c.dst=(xmlChar *)malloc(XML_BUFLEN * 5); + if (!c.dst) { + err ("Cannot get memory for TRA destination buffer\n"); + } + + mcg_init_streaming_group (&tra, STREAMING_TRA); + +#ifdef MULTI_THREAD_RECEIVER + c.s = client_udp_open (&tra, port, iface); +#else + c.s = client_udp_open_buff (&tra, port, iface, XML_BUFLEN); +#endif + if (!c.s) { + warn ("client_udp_open error !\n"); + } else { + c.run=1; +#ifdef DEBUG + char host[INET6_ADDRSTRLEN]; + inet_ntop (AF_INET6, &tra, (char *) host, INET6_ADDRSTRLEN); + dbg ("Start receive TRA at %s port %d %s\n", host, port, iface); +#endif + while (c.run) { +#ifdef MULTI_THREAD_RECEIVER + if ((n = udp_read (c.s, c.buf, XML_BUFLEN, 500000, NULL)) > 0) { +#else + usleep(100000); // 10 times per seconds should be enough + if ((n = udp_read_buff (c.s, c.buf, XML_BUFLEN, 500000, NULL)) > 0) { +#endif + dstlen = XML_BUFLEN*5; + if (!gunzip (c.dst, &dstlen, c.buf, n)) { + memset (&tra_info, 0, sizeof (tra_info_t)); + tra_info.magic=MCLI_MAGIC; + tra_info.version=MCLI_VERSION; + + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + if (get_tra_data (c.dst, dstlen, &tra_info)) { + handle_tra (&tra_info); + } + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + } else { + dbg ("uncompress failed\n"); + } + } +#ifdef DEBUG + dbg ("Stop receive TRA on %s %d %s len:%d\n", host, port, iface, n); +#endif + pthread_testcancel(); + } + } + pthread_cleanup_pop (1); + return NULL; +} +#endif + +//-------------------------------------------------------------------------------------------------------------------------- +int get_tca_data (xmlChar * xmlbuff, int buffersize, netceiver_info_t * nc_info) +{ + xml_parser_context_t c; + xmlNode *root_element, *cur_node; + +// xmlKeepBlanksDefault (0); //reomve this f. "text" nodes +// c.doc = xmlParseMemory ((char *) xmlbuff, buffersize); +// xmlKeepBlanksDefault doesn't work after patching cam flags + c.doc = xmlReadMemory((char *) xmlbuff, buffersize, NULL, "UTF-8", XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS ); + root_element = xmlDocGetRootElement (c.doc); + pthread_cleanup_push (clean_xml_parser_thread, &c); + nc_info->magic=MCLI_MAGIC; + nc_info->version=MCLI_VERSION; + + if (root_element != NULL) { + cur_node = root_element->children; + + if (!xmlStrcmp (cur_node->name, (xmlChar *) "Description")) { + + root_element = cur_node->children; + while (root_element != NULL) { + c.key = NULL; + c.str = NULL; + if ((xmlStrcmp (root_element->name, (const xmlChar *) "component"))) { + warn ("Cannot parse XML data\n"); + root_element = root_element->next; + continue; + } + + cur_node = root_element->children; + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Description"))) { + c.str = xmlGetProp (cur_node, (unsigned char *) "about"); + } else { + warn ("Cannot parse XML data\n"); + root_element = root_element->next; + continue; + } + if (c.str && (!xmlStrcmp (c.str, (const xmlChar *) "Platform"))) { + cur_node = cur_node->children; + while (cur_node != NULL) { + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "OSVersion"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("OSVersion: %s\n", c.key); + strncpy (nc_info->OSVersion, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "AppVersion"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("AppVersion: %s\n", c.key); + strncpy (nc_info->AppVersion, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "FirmwareVersion"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("FirmwareVersion: %s\n", c.key); + strncpy (nc_info->FirmwareVersion, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "HardwareVersion"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("HardwareVersion: %s\n", c.key); + strncpy (nc_info->HardwareVersion, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Serial"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Serial: %s\n", c.key); + strncpy (nc_info->Serial, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Vendor"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Vendor: %s\n", c.key); + strncpy (nc_info->Vendor, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "DefCon"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("DefCon: %s\n", c.key); + nc_info->DefCon = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "UUID"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("UUID: %s\n", c.key); + strncpy (nc_info->uuid, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Description"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("Description: %s\n", c.key); + strncpy (nc_info->Description, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "IP"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("IP: %s\n", c.key); + inet_pton (AF_INET6, (char *) c.key, &nc_info->ip); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "ProcessUptime"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("ProcessUptime: %s\n", c.key); + nc_info->ProcessUptime=atoi((char *)c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "SystemUptime"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("SystemUptime: %s\n", c.key); + nc_info->SystemUptime=atoi((char *)c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "TunerTimeout"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("TunerTimeout: %s\n", c.key); + nc_info->TunerTimeout=atoi((char *)c.key); + xmlFree (c.key); + } + } + cur_node = cur_node->next; + } + } else if (c.str && (!xmlStrcmp (c.str, (const xmlChar *) "Tuner"))) { + cur_node = cur_node->children; + nc_info->tuner = (tuner_info_t *) realloc (nc_info->tuner, (nc_info->tuner_num + 1) * sizeof (tuner_info_t)); + if (!nc_info->tuner) { + err ("Cannot get memory for tuner_info\n"); + } + + tuner_info_t *t = nc_info->tuner + nc_info->tuner_num; + memset (t, 0, sizeof (tuner_info_t)); + t->magic=MCLI_MAGIC; + t->version=MCLI_VERSION; + + while (cur_node != NULL) { + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Name"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + strncpy (t->fe_info.name, (char *) c.key, 127); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Type"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + if ((!xmlStrcmp (c.key, (const xmlChar *) "DVB-S"))) + t->fe_info.type = FE_QPSK; + if ((!xmlStrcmp (c.key, (const xmlChar *) "DVB-S2"))) + t->fe_info.type = (fe_type_t)FE_DVBS2; + if ((!xmlStrcmp (c.key, (const xmlChar *) "DVB-C"))) + t->fe_info.type = FE_QAM; + if ((!xmlStrcmp (c.key, (const xmlChar *) "DVB-T"))) + t->fe_info.type = FE_OFDM; + if ((!xmlStrcmp (c.key, (const xmlChar *) "ATSC"))) + t->fe_info.type = FE_ATSC; + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "FrequencyMin"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->fe_info.frequency_min = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "FrequencyMax"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->fe_info.frequency_max = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "FrequencyStepSize"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->fe_info.frequency_stepsize = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "FrequencyTolerance"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->fe_info.frequency_tolerance = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "SymbolRateMin"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->fe_info.symbol_rate_min = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "SymbolRateMax"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->fe_info.symbol_rate_max = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "SymbolRateTolerance"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->fe_info.symbol_rate_tolerance = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Caps"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->fe_info.caps = (fe_caps_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Slot"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->slot = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Preference"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + t->preference = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "UUID"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + strncpy (t->uuid, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "SatelliteListName"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + strncpy (t->SatelliteListName, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } + cur_node = cur_node->next; + } + nc_info->tuner_num++; + } else if (c.str && !(xmlStrcmp (c.str, (xmlChar *) "CI"))) { + cur_node = cur_node->children; + recv_cacaps_t *ci=&nc_info->ci; + while(cur_node) { + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "component"))) { + xmlNode *l2_node = cur_node->children; + if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "Description"))) { + c.key = xmlGetProp (l2_node, (unsigned char *) "about"); + dbg ("Parsing CI-Description: %s\n", c.key); + if (c.key && !xmlStrcmp (c.key, (xmlChar *) "Capabilities")) { + xmlFree (c.key); + xmlNode * l3_node = l2_node->children; + while (l3_node != NULL) { + dbg ("Capability-Element: %s\n", l3_node->name); + if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "SlotNum"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("SlotNum: %s\n", c.key); + ci->cap.slot_num=atoi((char*)c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "SlotType"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("SlotType: %s\n", c.key); + ci->cap.slot_type=atoi((char*)c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "DescrNum"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("DescrNum: %s\n", c.key); + ci->cap.descr_num=atoi((char*)c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "DescrType"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("DescrType: %s\n", c.key); + ci->cap.descr_type=atoi((char*)c.key); + xmlFree (c.key); + } + } + l3_node = l3_node->next; + } + } else if (c.key && !xmlStrcmp (c.key, (xmlChar *) "Slot")) { + xmlFree (c.key); + xmlNode *l3_node = l2_node->children; + int slot=-1; + while (l3_node != NULL) { + dbg ("Slot-Element: %s\n", l3_node->name); + if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "Num"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Num: %s\n", c.key); + int x=atoi((char*)c.key); + if( (x < 0) || (x >= CA_MAX_SLOTS) ) { + continue; + } + slot=x; + ci->info[slot].num=slot; + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "Type"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Type: %s\n", c.key); + if(slot>=0) { + ci->info[slot].type=atoi((char*)c.key); + } + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "Flags"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Flags: %s\n", c.key); + if(slot>=0) { + ci->info[slot].flags=atoi((char*)c.key); + } + xmlFree (c.key); + } + } + l3_node = l3_node->next; + } + } + } + } + cur_node = cur_node->next; + } + //CAM start + } else if (c.str && !(xmlStrcmp (c.str, (xmlChar *) "CAM"))) { + cur_node = cur_node->children; + cam_info_t *cam = nc_info->cam + nc_info->cam_num; + while(cur_node) { + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Slot"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->slot = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Status"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->status = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "MenuString"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + strncpy(cam->menu_string, (char *) c.key, MAX_MENU_STR_LEN-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "Flags"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->flags = (nc_ca_caps_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "MaxSids"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->max_sids = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "UseSids"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->use_sids = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "PmtFlag"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + cam->capmt_flag = atoi ((char *) c.key); + xmlFree (c.key); + } + } + cur_node = cur_node->next; + } + nc_info->cam_num++; + //CAM end + } else if (c.str && !(xmlStrcmp (c.str, (xmlChar *) "SatelliteList"))) { + cur_node = cur_node->children; + nc_info->sat_list = (satellite_list_t *) realloc (nc_info->sat_list, (nc_info->sat_list_num + 1) * sizeof (satellite_list_t)); + if (!nc_info->sat_list) { + err ("Cannot get memory for sat_list\n"); + } + + satellite_list_t *sat_list = nc_info->sat_list + nc_info->sat_list_num; + memset (sat_list, 0, sizeof (satellite_list_t)); + sat_list->magic=MCLI_MAGIC; + sat_list->version=MCLI_VERSION; + + while (cur_node != NULL) { + if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "SatelliteListName"))) { + c.key = xmlNodeListGetString (c.doc, cur_node->xmlChildrenNode, 1); + if (c.key) { + dbg ("SatelliteListName: %s\n", c.key); + strncpy (sat_list->Name, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (cur_node->name, (const xmlChar *) "component"))) { + xmlNode *l2_node = cur_node->children; + if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "Description"))) { + c.key = xmlGetProp (l2_node, (unsigned char *) "about"); + dbg ("Parsing L2-Description: %s\n", c.key); + if (c.key && !xmlStrcmp (c.key, (xmlChar *) "Satellite")) { + xmlFree (c.key); + l2_node = l2_node->children; + sat_list->sat = (satellite_info_t *) realloc (sat_list->sat, (sat_list->sat_num + 1) * sizeof (satellite_info_t)); + if (!sat_list->sat) { + err ("Cannot get memory for sat\n"); + } + + satellite_info_t *sat = sat_list->sat + sat_list->sat_num; + memset (sat, 0, sizeof (satellite_info_t)); + sat->magic=MCLI_MAGIC; + sat->version=MCLI_VERSION; + + while (l2_node != NULL) { + dbg ("L2-Element: %s\n", l2_node->name); + if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "Name"))) { + c.key = xmlNodeListGetString (c.doc, l2_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Name: %s\n", c.key); + strncpy (sat->Name, (char *) c.key, UUID_SIZE-1); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "Position"))) { + c.key = xmlNodeListGetString (c.doc, l2_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Position: %s\n", c.key); + sat->SatPos = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "PositionMin"))) { + c.key = xmlNodeListGetString (c.doc, l2_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("PositionMin: %s\n", c.key); + sat->SatPosMin = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "PositionMax"))) { + c.key = xmlNodeListGetString (c.doc, l2_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("PositionMax: %s\n", c.key); + sat->SatPosMax = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "AutoFocus"))) { + c.key = xmlNodeListGetString (c.doc, l2_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("AutoFocus: %s\n", c.key); + sat->AutoFocus = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "Latitude"))) { + c.key = xmlNodeListGetString (c.doc, l2_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Latitude: %s\n", c.key); + sat->Latitude = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "Longitude"))) { + c.key = xmlNodeListGetString (c.doc, l2_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Longitude: %s\n", c.key); + sat->Longitude = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "Type"))) { + c.key = xmlNodeListGetString (c.doc, l2_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Type: %s\n", c.key); + sat->type = (satellite_source_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l2_node->name, (const xmlChar *) "component"))) { + xmlNode *l3_node = l2_node->children; + + if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "Description"))) { + c.key = xmlGetProp (l3_node, (unsigned char *) "about"); + dbg ("Parsing L3-Description: %s\n", c.key); + if (c.key && !xmlStrcmp (c.key, (xmlChar *) "SatelliteComponent")) { + xmlFree (c.key); + l3_node = l3_node->children; + dbg ("Now checking for SatelliteCompontents\n"); + sat->comp = (satellite_component_t *) realloc (sat->comp, (sat->comp_num + 1) * sizeof (satellite_component_t)); + if (!sat->comp) { + err ("Cannot get memory for comp\n"); + } + + satellite_component_t *comp = sat->comp + sat->comp_num; + memset (comp, 0, sizeof (satellite_component_t)); + comp->magic=MCLI_MAGIC; + comp->version=MCLI_VERSION; + + while (l3_node != NULL) { + dbg ("L3-Element: %s\n", l3_node->name); + if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "Polarisation"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Polarisation: %s\n", c.key); + comp->Polarisation = (polarisation_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "RangeMin"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("RangeMin: %s\n", c.key); + comp->RangeMin = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "RangeMax"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("RangeMax: %s\n", c.key); + comp->RangeMax = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "LOF"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("LOF: %s\n", c.key); + comp->LOF = atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "Voltage"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Voltage: %s\n", c.key); + comp->sec.voltage = (fe_sec_voltage_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "Tone"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("Tone: %s\n", c.key); + comp->sec.tone_mode = (fe_sec_tone_mode_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "MiniCmd"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + if(c.key) { + dbg ("MiniCmd: %s\n", c.key); + comp->sec.mini_cmd = (fe_sec_mini_cmd_t)atoi ((char *) c.key); + xmlFree (c.key); + } + } else if ((!xmlStrcmp (l3_node->name, (const xmlChar *) "DiSEqC_Cmd"))) { + c.key = xmlNodeListGetString (c.doc, l3_node->xmlChildrenNode, 1); + dbg ("DiSEqC_Cmd: %s\n", c.key); + if(c.key) { + int v[6], i, n=0; + char *s= (char *)c.key; + struct dvb_diseqc_master_cmd *diseqc_cmd=&comp->sec.diseqc_cmd; + do { + dbg("Parsing: %s\n",s); + diseqc_cmd->msg_len = sscanf (s, "%x %x %x %x %x %x", v, v + 1, v + 2, v + 3, v + 4, v + 5); + for (i = 0; i < diseqc_cmd->msg_len; i++) { + diseqc_cmd->msg[i] = v[i]; + } + s=strchr(s,','); + if(s) { + s++; + } + diseqc_cmd=comp->diseqc_cmd+n; + n++; + } while(s && n<=DISEQC_MAX_EXTRA); + xmlFree (c.key); + comp->diseqc_cmd_num=n; + } + } + l3_node = l3_node->next; + } + sat->comp_num++; + } else { + xmlFree (c.key); + } + } + } + l2_node = l2_node->next; + } + sat_list->sat_num++; + } else { + xmlFree (c.key); + } + } + } + cur_node = cur_node->next; + } + nc_info->sat_list_num++; + } + xmlFree (c.str); + root_element = root_element->next; + } + } + } + + xmlFreeDoc (c.doc); + pthread_cleanup_pop (0); + return (1); +} + +#ifdef CLIENT + +void *recv_tca (void *arg) +{ + int n; + ccpp_thread_context_t c; + unsigned int dstlen; + netceiver_info_t nc_info; + struct in6_addr tca; + + pthread_cleanup_push (clean_ccpp_thread, &c); + + c.buf=(xmlChar *)malloc(XML_BUFLEN); + if (!c.buf) { + err ("Cannot get memory for TRA buffer\n"); + } + c.dst=(xmlChar *)malloc(XML_BUFLEN * 5); + if (!c.dst) { + err ("Cannot get memory for TRA destination buffer\n"); + } + + mcg_init_streaming_group (&tca, STREAMING_TCA); + +#ifdef MULTI_THREAD_RECEIVER + c.s = client_udp_open (&tca, port, iface); +#else + c.s = client_udp_open_buff (&tca, port, iface, XML_BUFLEN); +#endif + if (!c.s) { + warn ("client_udp_open error !\n"); + } else { + c.run=1; +#ifdef DEBUG + char host[INET6_ADDRSTRLEN]; + inet_ntop (AF_INET6, &tca, (char *) host, INET6_ADDRSTRLEN); + dbg ("Start Receive TCA on interface %s port %d\n", iface, port); +#endif + while (c.run) { +#ifdef MULTI_THREAD_RECEIVER + if ((n = udp_read (c.s, c.buf, XML_BUFLEN, 500000, NULL)) > 0) { +#else + usleep(100000); // 10 times per seconds should be enough + if ((n = udp_read_buff (c.s, c.buf, XML_BUFLEN, 500000, NULL)) > 0) { +#endif + dstlen = XML_BUFLEN * 5; + if (!gunzip (c.dst, &dstlen, c.buf, n)) { + memset (&nc_info, 0, sizeof (netceiver_info_t)); + + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + get_tca_data (c.dst, dstlen, &nc_info); + handle_tca (&nc_info); + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + } else { + dbg ("uncompress failed\n"); + } + } + pthread_testcancel(); + } + } + pthread_cleanup_pop (1); + return NULL; +} +#endif diff --git a/mcast/common/.svn/text-base/recv_ccpp.h.svn-base b/mcast/common/.svn/text-base/recv_ccpp.h.svn-base new file mode 100644 index 0000000..78e1b83 --- /dev/null +++ b/mcast/common/.svn/text-base/recv_ccpp.h.svn-base @@ -0,0 +1,129 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#ifndef __RECV_CCPP_H +#define __RECV_CCPP_H + +#define XML_BUFLEN 65536 +#define TEN_TIMEOUT 2 +#define MAX_MENU_STR_LEN 64 +#define MAX_CAMS 2 + + +typedef struct tuner_info +{ + int magic; + int version; + + struct dvb_frontend_info fe_info; + int slot; + int preference; + char uuid[UUID_SIZE]; + char SatelliteListName[UUID_SIZE]; +} tuner_info_t; + +typedef enum { CA_SINGLE, CA_MULTI_SID, CA_MULTI_TRANSPONDER} nc_ca_caps_t; +enum { DVBCA_CAMSTATE_MISSING, DVBCA_CAMSTATE_INITIALISING, DVBCA_CAMSTATE_READY}; + +typedef struct cam_info { + + uint8_t slot; + uint8_t status; + int max_sids; + int use_sids; + int capmt_flag; + int reserved; + nc_ca_caps_t flags; + + char menu_string[MAX_MENU_STR_LEN]; + +} cam_info_t; + +typedef struct netceiver_info +{ + int magic; + int version; + + char OSVersion[UUID_SIZE]; + char AppVersion[UUID_SIZE]; + char FirmwareVersion[UUID_SIZE]; + char HardwareVersion[UUID_SIZE]; + char Serial[UUID_SIZE]; + char Vendor[UUID_SIZE]; + char uuid[UUID_SIZE]; + char Description[UUID_SIZE]; + int TunerTimeout; + struct in6_addr ip; + int DefCon; + time_t SystemUptime; + time_t ProcessUptime; + + time_t lastseen; + + tuner_info_t *tuner; + recv_cacaps_t ci; + satellite_list_t *sat_list; + cam_info_t cam[MAX_CAMS]; + + + int tuner_num; + int sat_list_num; + int cam_num; +} netceiver_info_t; + +typedef struct tra +{ + int magic; + int version; + + recv_festatus_t s; + fe_type_t fe_type; + struct dvb_frontend_parameters fep; + struct in6_addr mcg; + int slot; + char uuid[UUID_SIZE]; + int redirect; + int NIMCurrent; + int InUse; + int rotor_status; + time_t lastseen; + int rotor_diff; +#ifdef P2P + int preference; + int token; +#endif + +} tra_t; + +typedef struct tra_info +{ + int magic; + int version; + + tra_t *tra; + int tra_num; + cam_info_t cam[MAX_CAMS]; + int cam_num; +#ifdef P2P + int quit; + int tca_id; + int mca_grps; + struct in6_addr ipv6; +#endif + +} tra_info_t; + +typedef struct recv_info recv_info_t; + +void *recv_ten (void *arg); +void *recv_tca (void *arg); +void *recv_tra (void *arg); +int get_tca_data (xmlChar * xmlbuff, int buffersize, netceiver_info_t * nc_info); +int get_tra_data (xmlChar * xmlbuff, int buffersize, tra_info_t * tra_info); +DLL_SYMBOL int register_ten_handler (recv_info_t * r, int (*p)(tra_t *, void *), void *c); +#endif diff --git a/mcast/common/.svn/text-base/satlists.h.svn-base b/mcast/common/.svn/text-base/satlists.h.svn-base new file mode 100644 index 0000000..ad95889 --- /dev/null +++ b/mcast/common/.svn/text-base/satlists.h.svn-base @@ -0,0 +1,92 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#define DISEQC_MAX_EXTRA 8 +#define MAX_EXTRA_DATA 16 + +typedef enum +{ +//the defines for circular polarisation are taken from official DiSEqC-Spec at +//http://www.eutelsat.com/satellites/pdf/Diseqc/Reference%20docs/bus_spec.pdf + POL_V = SEC_VOLTAGE_13, + POL_H = SEC_VOLTAGE_18, + POL_R = SEC_VOLTAGE_13, + POL_L = SEC_VOLTAGE_18, +} polarisation_t; + +typedef struct +{ + int magic; + int version; + + polarisation_t Polarisation; // H/V/L/R + int RangeMin; // 11700 + int RangeMax; // 12750 + +// SEC Settings to be used for the specification above + int LOF; // 9750 + recv_sec_t sec; + struct dvb_diseqc_master_cmd diseqc_cmd[DISEQC_MAX_EXTRA]; + int diseqc_cmd_num; +} satellite_component_t; + +typedef enum +{ + SAT_SRC_LNB=0, + SAT_SRC_ROTOR=1, + SAT_SRC_UNI=2, // !!! match DISEQC_* values in dvb_server.h !!! +} satellite_source_t; + +typedef struct +{ + int magic; + int version; + +// Specification of satellite parameters + char Name[UUID_SIZE]; // Astra 19,2 + int SatPos; // 1920 + int SatPosMin; // Only used for SAT_SRC_ROTOR + int SatPosMax; // Only used for SAT_SRC_ROTOR + satellite_source_t type; // see above + + satellite_component_t *comp; // What to do for polarisation and range for SEC? + int comp_num; // Number of components + int AutoFocus; + int Latitude; + int Longitude; + int num_extra_data; + int extra_data[MAX_EXTRA_DATA]; // reserved +} satellite_info_t; + +typedef struct satellite_list +{ + int magic; + int version; + + char Name[UUID_SIZE]; // Magic unique identifier + satellite_info_t *sat; + int sat_num; +} satellite_list_t; + +typedef struct +{ + int magic; + int version; + + int netceiver; + int sat_list; + int sat; + int comp; + int position; // for rotor +} satellite_reference_t; + +DLL_SYMBOL int satellite_find_by_diseqc (satellite_reference_t * ref, recv_sec_t *sec, struct dvb_frontend_parameters *fep, int mode); +DLL_SYMBOL int satellite_get_pos_by_ref (satellite_reference_t * ref); +DLL_SYMBOL int satellite_get_lof_by_ref (satellite_reference_t * ref); +DLL_SYMBOL polarisation_t satellite_find_pol_by_ref (satellite_reference_t * ref); +DLL_SYMBOL recv_sec_t *satellite_find_sec_by_ref (satellite_reference_t * ref); diff --git a/mcast/common/.svn/text-base/siparser.c.svn-base b/mcast/common/.svn/text-base/siparser.c.svn-base new file mode 100644 index 0000000..4ce7032 --- /dev/null +++ b/mcast/common/.svn/text-base/siparser.c.svn-base @@ -0,0 +1,1049 @@ +#include "headers.h" + +//#define DBG 1 +#define CRC32_CHECK 1 + +enum ca_desc_type { EMM, ECM }; + +//----------------------------------------------------------------------------------- +void printhex_buf(char *msg,unsigned char *buf,int len) +{ + int i,j,k; + int width=8; + + i=k=0; + sys ("%s: %d bytes (0x%04x)\n",msg,len,len); + sys ("---------------------------------------------------------------\n"); + while(len) { + sys ("%04x ",k++*width*2); + j=i; + for(;i < j + width ; i++){ + if (i >= len) break; + sys ("%02x ",buf[i]); + } + if (i >= len) { + sys ("\n"); + break; + } + sys(" "); + j=i; + for(;i < j + width ; i++){ + if (i >= len) break; + sys("%02x ",buf[i]); + } + sys("\n"); + if (i >= len) break; + } + sys("---------------------------------------------------------------\n"); +} +//----------------------------------------------------------------------------------- +void writehex_buf(FILE *f, char *msg,unsigned char *buf,int len) +{ + int i,j,k; + int width=8; + + i=k=0; + fprintf(f,"%s: %d bytes (0x%04x)\n",msg,len,len); + fprintf(f,"---------------------------------------------------------------\n"); + while(len) { + fprintf(f,"%04x ",k++*width*2); + j=i; + for(;i < j + width ; i++){ + if (i >= len) break; + fprintf(f,"%02x ",buf[i]); + } + if (i >= len) { + fprintf(f,"\n"); + break; + } + fprintf(f," "); + j=i; + for(;i < j + width ; i++){ + if (i >= len) break; + fprintf(f,"%02x ",buf[i]); + } + fprintf(f,"\n"); + if (i >= len) break; + } + fprintf(f,"---------------------------------------------------------------\n"); + + +} +//----------------------------------------------------------------------------------- +void print_ts_header(ts_packet_hdr_t *p) +{ + info("--------------------------------------------------------------\n"); + info("TS header data:\n"); + info("Sync-byte : 0x%04x\n",p->sync_byte); + info("Transport error indicator : 0x%04x\n",p->transport_error_indicator); + info("Payload unit start indicator : 0x%04x\n",p->payload_unit_start_indicator); + info("Transport priority : 0x%04x\n",p->transport_priority); + info("PID : 0x%04x\n",p->pid); + info("Transport scrambling control : 0x%04x\n",p->transport_scrambling_control); + info("Adaptation field control : 0x%04x\n",p->adaptation_field_control); + info("Continuity_counter : 0x%04x\n",p->continuity_counter); + +} +//----------------------------------------------------------------------------------- +void print_pmt(pmt_t *p) +{ + info("--------------------------------------------------------------\n"); + info("PMT section:\n"); + info("Table ID : %-5d (0x%04x)\n",p->table_id,p->table_id); + info("(fixed): : %-5d (0x%04x)\n",0,0); + info("Section syntax indicator : %-5d (0x%04x)\n",p->section_syntax_indicator,p->section_syntax_indicator); + info("Reserved 1 : %-5d (0x%04x)\n",p->reserved_1,p->reserved_1); + info("Section length : %-5d (0x%04x)\n",p->section_length,p->section_length); + info("Program number : %-5d (0x%04x)\n",p->program_number,p->program_number); + info("Reserved 2 : %-5d (0x%04x)\n",p->reserved_2,p->reserved_2); + info("Version number : %-5d (0x%04x)\n",p->version_number,p->version_number); + info("Current next indicator : %-5d (0x%04x)\n",p->current_next_indicator,p->current_next_indicator); + info("Section number : %-5d (0x%04x)\n",p->section_number,p->section_number); + info("Last section number : %-5d (0x%04x)\n",p->last_section_number,p->last_section_number); + info("Reserved 3 : %-5d (0x%04x)\n",p->reserved_3,p->reserved_3); + info("PCR pid : %-5d (0x%04x)\n",p->pcr_pid,p->pcr_pid); + info("Reserved 4 : %-5d (0x%04x)\n",p->reserved_4,p->reserved_4); + info("Program info length : %-5d (0x%04x)\n",p->program_info_length,p->program_info_length); + + + + info("CRC32 : 0x%04x\n",p->crc32); +} +//----------------------------------------------------------------------------------- +void print_pat(pat_t *p, pat_list_t *pl, int pmt_num) +{ + info("--------------------------------------------------------------\n"); + info("PAT section:\n"); + info("Table_id : %-5d (0x%04x)\n",p->table_id,p->table_id); + info("(fixed): : %-5d (0x%04x)\n",0,0); + info("Section syntax indicator : %-5d (0x%04x)\n",p->section_syntax_indicator,p->section_syntax_indicator); + info("Reserved_1 : %-5d (0x%04x)\n",p->reserved_1,p->reserved_1); + info("Section length : %-5d (0x%04x)\n",p->section_length,p->section_length); + info("Transport stream id : %-5d (0x%04x)\n",p->transport_stream_id,p->transport_stream_id); + info("Reserved 2 : %-5d (0x%04x)\n",p->reserved_2,p->reserved_2); + info("Version number : %-5d (0x%04x)\n",p->version_number,p->version_number); + info("Current next indicator : %-5d (0x%04x)\n",p->current_next_indicator,p->current_next_indicator); + info("Section number : %-5d (0x%04x)\n",p->section_number,p->section_number); + info("Last section number : %-5d (0x%04x)\n",p->last_section_number,p->last_section_number); + + if (pl && pmt_num){ + int i; + info("Number of PMTs in PAT : %-5d \n", pmt_num); + for(i=0;i<pmt_num;i++) { + pat_list_t *pat = pl + i; + info("\nProgram number : %-5d (0x%04x)\n",pat->program_number,pat->program_number); + info("Reserved : %-5d (0x%04x)\n",pat->reserved,pat->reserved); + info("Network PMT PID : %-5d (0x%04x)\n",pat->network_pmt_pid,pat->network_pmt_pid); + } + } + + info("CRC32 : 0x%04x\n",p->crc32); + + +} +//----------------------------------------------------------------------------------- +char *si_caid_to_name(unsigned int caid) +{ + + str_table table[] = { + // -- updated from dvb.org 2003-10-16 + { 0x0000, 0x0000, "Reserved" }, + { 0x0001, 0x00FF, "Standardized Systems" }, + { 0x0100, 0x01FF, "Canal Plus (Seca/MediaGuard)" }, + { 0x0200, 0x02FF, "CCETT" }, + { 0x0300, 0x03FF, "MSG MediaServices GmbH" }, + { 0x0400, 0x04FF, "Eurodec" }, + { 0x0500, 0x05FF, "France Telecom (Viaccess)" }, + { 0x0600, 0x06FF, "Irdeto" }, + { 0x0700, 0x07FF, "Jerrold/GI/Motorola" }, + { 0x0800, 0x08FF, "Matra Communication" }, + { 0x0900, 0x09FF, "News Datacom (Videoguard)" }, + { 0x0A00, 0x0AFF, "Nokia" }, + { 0x0B00, 0x0BFF, "Norwegian Telekom (Conax)" }, + { 0x0C00, 0x0CFF, "NTL" }, + { 0x0D00, 0x0DFF, "Philips (Cryptoworks)" }, + { 0x0E00, 0x0EFF, "Scientific Atlanta (Power VU)" }, + { 0x0F00, 0x0FFF, "Sony" }, + { 0x1000, 0x10FF, "Tandberg Television" }, + { 0x1100, 0x11FF, "Thompson" }, + { 0x1200, 0x12FF, "TV/COM" }, + { 0x1300, 0x13FF, "HPT - Croatian Post and Telecommunications" }, + { 0x1400, 0x14FF, "HRT - Croatian Radio and Television" }, + { 0x1500, 0x15FF, "IBM" }, + { 0x1600, 0x16FF, "Nera" }, + { 0x1700, 0x17FF, "Beta Technik (Betacrypt)" }, + { 0x1800, 0x18FF, "Kudelski SA"}, + { 0x1900, 0x19FF, "Titan Information Systems"}, + { 0x2000, 0x20FF, "TelefXnica Servicios Audiovisuales"}, + { 0x2100, 0x21FF, "STENTOR (France Telecom, CNES and DGA)"}, + { 0x2200, 0x22FF, "Scopus Network Technologies"}, + { 0x2300, 0x23FF, "BARCO AS"}, + { 0x2400, 0x24FF, "StarGuide Digital Networks "}, + { 0x2500, 0x25FF, "Mentor Data System, Inc."}, + { 0x2600, 0x26FF, "European Broadcasting Union"}, + { 0x4700, 0x47FF, "General Instrument"}, + { 0x4800, 0x48FF, "Telemann"}, + { 0x4900, 0x49FF, "Digital TV Industry Alliance of China"}, + { 0x4A00, 0x4A0F, "Tsinghua TongFang"}, + { 0x4A10, 0x4A1F, "Easycas"}, + { 0x4A20, 0x4A2F, "AlphaCrypt"}, + { 0x4A30, 0x4A3F, "DVN Holdings"}, + { 0x4A40, 0x4A4F, "Shanghai Advanced Digital Technology Co. Ltd. (ADT)"}, + { 0x4A50, 0x4A5F, "Shenzhen Kingsky Company (China) Ltd"}, + { 0x4A60, 0x4A6F, "@SKY"}, + { 0x4A70, 0x4A7F, "DreamCrypt"}, + { 0x4A80, 0x4A8F, "THALESCrypt"}, + { 0x4A90, 0x4A9F, "Runcom Technologies"}, + { 0x4AA0, 0x4AAF, "SIDSA"}, + { 0x4AB0, 0x4ABF, "Beijing Comunicate Technology Inc."}, + { 0x4AC0, 0x4ACF, "Latens Systems Ltd"}, + { 0,0, NULL } + }; + + int i = 0; + while (table[i].str) { + if (table[i].from <= caid && table[i].to >= caid) + return (char *) table[i].str; + i++; + } + + return (char *) "ERROR: Undefined!"; +} +//----------------------------------------------------------------------------------- +void get_time_mjd (unsigned long mjd, long *year , long *month, long *day) +{ + if (mjd > 0) { + long y,m,d ,k; + + // algo: ETSI EN 300 468 - ANNEX C + + y = (long) ((mjd - 15078.2) / 365.25); + m = (long) ((mjd - 14956.1 - (long)(y * 365.25) ) / 30.6001); + d = (long) (mjd - 14956 - (long)(y * 365.25) - (long)(m * 30.6001)); + k = (m == 14 || m == 15) ? 1 : 0; + y = y + k + 1900; + m = m - 1 - k*12; + *year = y; + *month = m; + *day = d; + + } else { + *year = 0; + *month = 0; + *day = 0; + } + +} +//----------------------------------------------------------------------------------- +void print_tdt(tdt_sect_t *tdt, uint16_t mjd, uint32_t utc) +{ + info("--------------------------------------------------------------\n"); + info("TDT section:\n"); + info("Table_id : %-5d (0x%04x)\n",tdt->table_id,tdt->table_id); + info("Reserved : %-5d (0x%04x)\n",tdt->reserved,tdt->reserved); + info("Reserved_1 : %-5d (0x%04x)\n",tdt->reserved_1,tdt->reserved_1); + info("Section length : %-5d (0x%04x)\n",tdt->section_length,tdt->section_length); + info("UTC_time : 0x%2x%2x%2x%2x%2x\n",tdt->dvbdate[0],tdt->dvbdate[1],tdt->dvbdate[2],tdt->dvbdate[3],tdt->dvbdate[4]); + + long y,m,d; + get_time_mjd(mjd, &y, &m, &d); + info("TIME: [= %02ld-%02ld-%02ld %02x:%02x:%02x (UTC) ]\n\n",y,m,d,(utc>>16) &0xFF, (utc>>8) &0xFF, (utc) &0xFF); + info("--------------------------------------------------------------\n"); + +} +//----------------------------------------------------------------------------------- +void print_ca_desc(si_desc_t *p) +{ + info("CA desc. tag : %d (%#x)\n",p->descriptor_tag,p->descriptor_tag); + info("CA desc. length : %d (%#x)\n",p->descriptor_length,p->descriptor_length); + info("CA system id : %d (%#x)\n",p->ca_system_id,p->ca_system_id); + info("Reserverd : %d (%#x)\n",p->reserved,p->reserved); + info("CA pid : %d (%#x)\n",p->ca_pid,p->ca_pid); + + printhex_buf((char *)"Private data",p->private_data,p->descriptor_length-4); + +} +//----------------------------------------------------------------------------------- +void print_ca_bytes(si_desc_t *p) +{ + unsigned int i; + info("%x %x %x %x %x ",p->descriptor_tag, p->descriptor_length, p->ca_system_id, p->reserved, p->ca_pid); + for (i = 0; i < p->descriptor_length - 4; i++) + info("%x ",p->private_data[i]); + info(";"); + +} +//----------------------------------------------------------------------------------- +void print_cad_lst(si_cad_t *l, int ts_id) +{ + int i; + + for (i = 0; i < l->cads; i++) { + print_ca_desc(&l->cad[i]); + } + info("Total CA desc. for TS ID %d : %d\n",ts_id,l->cads); +} +//----------------------------------------------------------------------------------- +int parse_ca_descriptor(unsigned char *desc, si_desc_t *t) +{ + unsigned char *ptr=desc; + int tag=0,len=0; + + tag=ptr[0]; + len=ptr[1]; + + if (len > MAX_DESC_LEN) { + info("descriptor():Descriptor too long !\n"); + return -1; + } + + switch(tag){ + case 0x09: { + t->descriptor_tag=tag; + t->descriptor_length=len; //??? + t->ca_system_id=((ptr[2] << 8) | ptr[3]); + t->reserved=(ptr[4] >> 5) & 7; + t->ca_pid=((ptr[4] << 8) | ptr[5]) & 0x1fff; + //header 4 bytes + 2 bytes + memcpy(t->private_data,ptr+6,len-4); + + //print_ca_desc(t); + + break; + } + default: + break; + } + + return len + 2; //2 bytes tag + length +} +//-------------------------------------------------------------------------------------------- +int ca_free_cpl_desc(ca_pmt_list_t *cpl) +{ + if (cpl->pm.size > 0 && cpl->pm.cad) + free(cpl->pm.cad); + if (cpl->es.size > 0 && cpl->es.cad) + free(cpl->es.cad); + + memset(cpl,0,sizeof(ca_pmt_list_t)); + + return 0; +} +//-------------------------------------------------------------------------------------------- +int descriptor(unsigned char *desc, si_cad_t *c) +{ + unsigned char *ptr=desc; + int tag=0,len=0; + + tag=ptr[0]; + len=ptr[1]; + + if (len > MAX_DESC_LEN) { + info("descriptor():Descriptor too long !\n"); + return -1; + } + + switch(tag){ + case 0x09: { + c->cads++; + c->cad = (si_desc_t*)realloc(c->cad,sizeof(si_desc_t)*c->cads); + if (!c->cad) { + c->cads--; + info("descriptor():realloc error\n"); + return -1; + } + si_desc_t *t = c->cad + c->cads - 1; + t->descriptor_tag=tag; + t->descriptor_length=len; //??? + t->ca_system_id=((ptr[2] << 8) | ptr[3]); + t->reserved=(ptr[4] >> 5) & 7; + t->ca_pid=((ptr[4] << 8) | ptr[5]) & 0x1fff; + //header 4 bytes + 2 bytes + if (len - 4 > 0) + memcpy(t->private_data,ptr+6,len-4); + + //print_ca_desc(t); + break; + } + default: { +#if 0 + other_desc_t d; + d.descriptor_tag=tag; + d.descriptor_length=len; + memcpy(d.data,ptr+2,len); + //print_desc(d); +#endif + } + } + + return len + 2; //2 bytes tag + length +} + +//----------------------------------------------------------------------------------- +int si_get_video_pid(unsigned char *esi_buf, int size, int *vpid) +{ + int index, pid_num, es_len; + unsigned char *ptr = esi_buf; + + index = pid_num = 0; + while(index < size) { + //ptr[0] //stream type + if (ptr[0] == 2 || ptr[0] == 0x1b) + { + *vpid = ((ptr[1] << 8) | ptr[2]) & 0x1fff; + return 1; + } + es_len = ((ptr[3] << 8) | ptr[4]) & 0x0fff; + index += 5 + es_len; + ptr += 5 + es_len; + } + + *vpid = -1; + return 0; + +} +//----------------------------------------------------------------------------------- +int si_get_audio_pid(unsigned char *esi_buf, int size, int *apid) +{ + int index, pid_num, es_len; + unsigned char *ptr = esi_buf; + + index = pid_num = 0; + while(index < size) { + //ptr[0] //stream type + if (ptr[0] == 0x1 || ptr[0] == 0x3 || ptr[0] == 0x4) + { + *apid = ((ptr[1] << 8) | ptr[2]) & 0x1fff; + return 1; + } + es_len = ((ptr[3] << 8) | ptr[4]) & 0x0fff; + index += 5 + es_len; + ptr += 5 + es_len; + } + + *apid = -1; + return 0; + +} +//----------------------------------------------------------------------------------- +int si_get_private_pids(unsigned char *esi_buf, int size, int *upids) +{ + + int index, pid_num, es_len; + unsigned char *ptr = esi_buf; + + index = pid_num = 0; + while(index < size) { + if (ptr[0] == 0x6) + { + upids[pid_num] = ((ptr[1] << 8) | ptr[2]) & 0x1fff; + pid_num++; + if (pid_num >= MAX_ES_PIDS) { + info ("error: ES pids number out of bounds !\n"); + return -1; + } + } + es_len = ((ptr[3] << 8) | ptr[4]) & 0x0fff; + index += 5 + es_len; + ptr += 5 + es_len; + } + + return pid_num; + +} +//----------------------------------------------------------------------------------- +int get_pmt_es_pids(unsigned char *esi_buf, int size, int *es_pids, int all) +{ + int index, pid_num, es_len; + unsigned char *ptr = esi_buf; + + index = pid_num = 0; + while(index < size) { + //ptr[0] //stream type + //int pid = ((ptr[1] << 8) | ptr[2]) & 0x1fff; + //printf("Stream type: %d (%#x) pid = %d (%#x)\n",ptr[0], ptr[0], pid, pid); + if (ptr[0] == 0x1 || ptr[0] == 0x2 || ptr[0] == 0x3 || ptr[0] == 0x4 || ptr[0] == 0x6 || ptr[0] == 0x1b || all) + { + es_pids[pid_num] = ((ptr[1] << 8) | ptr[2]) & 0x1fff; + pid_num++; + if (pid_num >= MAX_ES_PIDS) { + info ("error: ES pids number out of bounds !\n"); + return -1; + } + } + es_len = ((ptr[3] << 8) | ptr[4]) & 0x0fff; + index += 5 + es_len; + ptr += 5 + es_len; + } + + return pid_num; +} +//----------------------------------------------------------------------------------- +int parse_pmt_ca_desc(unsigned char *buf, int size, int sid, si_ca_pmt_t *pm_cads, si_ca_pmt_t *es_cads, pmt_t *pmt_hdr, int *fta, ca_es_pid_info_t *espids, int *es_pid_num) +{ + unsigned char *ptr=buf, tmp[PSI_BUF_SIZE]; //sections can be only 12 bit long + + memset(pm_cads,0,sizeof(si_ca_pmt_t)); + memset(es_cads,0,sizeof(si_ca_pmt_t)); + memset(pmt_hdr,0,sizeof(pmt_hdr)); + + pmt_hdr->table_id=ptr[0]; + pmt_hdr->section_syntax_indicator=(ptr[1] >> 7) & 1; + pmt_hdr->reserved_1=(ptr[1] >> 4) & 3; + pmt_hdr->section_length=((ptr[1] << 8) | ptr[2]) & 0xfff; + + if (pmt_hdr->section_length < 13 || pmt_hdr->section_length > 1021 || (int)pmt_hdr->section_length > size) { + info("#####\nERROR: Invalid section length!\n"); + return -1; + } + + u_long crc = dvb_crc32 ((char *)buf,pmt_hdr->section_length+3); + +#ifdef DBG + info("CRCcc: 0x%lx\n",crc); + info("len = %d\n", pmt_hdr->section_length+3); +#endif + if (crc & 0xffffffff) { //FIXME: makr arch flags + info("#####\nPMT -> ERROR: parse_pmt_ca_desc() : CRC err. crc = 0x%lx\n", crc); + return -1; + } + + pmt_hdr->program_number=(ptr[3] << 8) | ptr[4]; + if ((int)pmt_hdr->program_number != sid) { + info("#####\nERROR: Invalid SID in PMT !!!\n"); + return -1; + } + pmt_hdr->program_info_length=((ptr[10] << 8) | ptr[11]) & 0x0fff; + if (pmt_hdr->program_info_length < 0 || pmt_hdr->program_info_length > 1021 - 9 || (int)pmt_hdr->program_info_length > size - 9) { + info("#####\nERROR: Invalid PI length in PMT!\n"); + return -1; + } + + pmt_hdr->reserved_2=(ptr[5] >> 6) & 3; + pmt_hdr->version_number=(ptr[5] >> 1) & 0x1f; + pmt_hdr->current_next_indicator=ptr[5] & 1; + pmt_hdr->section_number=ptr[6]; + pmt_hdr->last_section_number=ptr[7]; + pmt_hdr->reserved_3=(ptr[8] >> 5) & 7; + pmt_hdr->pcr_pid=((ptr[8] << 8) | ptr[9]) & 0x1fff; + pmt_hdr->reserved_4=(ptr[10] >> 4) & 0xf; + + //pmt_hdr->program_info_length=((ptr[10] << 8) | ptr[11]) & 0x0fff; + //print_pmt(pmt_hdr); + + int buf_len=0,len=0; + unsigned int i=0; + + buf_len = pmt_hdr->section_length - 9; + ptr += 12; // 12 byte header + + pm_cads->size = pm_cads->cads = 0; + for (i = 0; i < pmt_hdr->program_info_length;) { + int dtag = ptr[0]; + int dlen = ptr[1] + 2; + if (dlen > size || dlen > MAX_DESC_LEN) { + info("PMT: Invalide CA desc. length!\n"); + return -1; + } + if (dtag == 0x09) { //we have CA descriptor + memcpy(tmp + pm_cads->size, ptr, dlen); + pm_cads->size+=dlen; + pm_cads->cads++; + *fta=0; + } + i+=dlen; + if (i > pmt_hdr->program_info_length) { + info("PMT: Index out of bounds!\n"); + return -1; + } + + ptr+=dlen; //desc. length plus 2 bytes for tag and header; + if (ptr >= buf + size) { + info("PMT: Invalid Buffer offset !\n"); + return -1; + } + + buf_len-=dlen; + if (buf_len < 0) { + info("PMT: Index out of bounds!\n"); + return -1; + + } + } + + //parsing ok we can take this program level descriptors + if (pm_cads->size && pm_cads->cads) { + pm_cads->cad = (unsigned char*)malloc(sizeof(unsigned char)*pm_cads->size); + if (!pm_cads->cad) { + info("ERROR: parse_ca_desc() : out of memory\n"); + return -1; + } + memcpy(pm_cads->cad, tmp, pm_cads->size); + } + +#ifdef DBG + info("%d bytes remaining (program info len = %d bytes)\n",buf_len,i); +#endif + + int err = 0; + es_pmt_info_t esi; + es_cads->size = es_cads->cads = 0; + *es_pid_num = 0; + while (buf_len > 4) { //end of section crc32 is 4 bytes + esi.stream_type=ptr[0]; + esi.reserved_1=(ptr[1] >> 5) & 7; + esi.elementary_pid=((ptr[1] << 8) | ptr[2]) & 0x1fff; + esi.reserved_2=(ptr[3] >> 4) & 0xf; + esi.es_info_length=((ptr[3] << 8) | ptr[4]) & 0x0fff; + + if ((int)esi.es_info_length > buf_len) { + info("PMT: Invalid ES info length !\n"); + err = -1; + break; + } + + if (espids) { + switch(esi.stream_type) { + case VIDEO_11172_STREAM_TYPE: + case VIDEO_13818_STREAM_TYPE: + case VISUAL_MPEG4_STREAM_TYPE: + case VIDEO_H264_STREAM_TYPE: + case AUDIO_11172_STREAM_TYPE: + case AUDIO_13818_STREAM_TYPE: + espids[*es_pid_num].pid = esi.elementary_pid; + espids[*es_pid_num].type = esi.stream_type; + break; + default: + espids[*es_pid_num].pid = esi.elementary_pid; + espids[*es_pid_num].type = 0; + + } + } + memcpy(tmp + es_cads->size, ptr, 5); + tmp[es_cads->size+1] &= 0x1f; //remove reserved value ??? + tmp[es_cads->size+3] &= 0x0f; //remove reserved value ??? + + int es_info_len_pos = es_cads->size+3; //mark length position to set it later + int cur_len = 0; //current ES stream descriptor length + + es_cads->size += 5; + ptr += 5; + buf_len -= 5; + len=esi.es_info_length; + while(len > 0) { + int dtag = ptr[0]; + int dlen = ptr[1] + 2; //2 bytes for tag and len + + if (dlen > len || dlen > MAX_DESC_LEN) { + info("PMT: Invalide CA desc. length!\n"); + err = -1; + break; + } + + if (dtag == 0x09) { //we have CA descriptor + memcpy(tmp + es_cads->size, ptr, dlen); + es_cads->size += dlen; + es_cads->cads++; + cur_len += dlen; + *fta=0; + } + if (espids) { + if (espids[*es_pid_num].type == 0) { + switch(dtag) { + case TeletextDescriptorTag: + case SubtitlingDescriptorTag: + case AC3DescriptorTag: + case EnhancedAC3DescriptorTag: + case DTSDescriptorTag: + case AACDescriptorTag: + espids[*es_pid_num].type = dtag; + //go to next pid + } + } + } + + ptr += dlen; + if (ptr >= buf + size) { + info("PMT: Invalid Buffer offset !\n"); + err = -1; + break; + } + + len -= dlen; + buf_len -= dlen; + } + if (err == -1) { + break; + } + tmp[es_info_len_pos] = (cur_len >> 8) & 0xff; + tmp[es_info_len_pos+1] = cur_len & 0xff; + if (espids) { + if (espids[*es_pid_num].type) { + //go to next pid + (*es_pid_num)++; + if (*es_pid_num >= MAX_ES_PIDS) { + info ("ERROR: ES pids array index out bounds (pids %d sid %d)!\n", *es_pid_num, pmt_hdr->program_number); + break; + } + } + } + } + + //parsing ok we can take this ES level descriptors + if (((es_cads->cads && es_cads->size) || (pm_cads->cads && es_cads->size)) || *fta) { //take ES stream info if we have PM or ES desc. + es_cads->cad = (unsigned char*)malloc(sizeof(unsigned char)*es_cads->size); + if (!es_cads->cad) { + info("ERROR: parse_ca_desc() : out of memory\n"); + if (pm_cads->cad) + free(pm_cads->cad); + return -1; + } + memcpy(es_cads->cad, tmp, es_cads->size); + + } + +#ifdef DBG + info("%d bytes remaining\n",buf_len); +#endif + + pmt_hdr->crc32=(ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; + + if (len < 0 || err == -1) { + info("ERROR: parse_ca_desc() : section index out of bounds %d or (CRC err.) crc in sec. = 0x%x crc calc. = 0x%lx\n", buf_len,pmt_hdr->crc32, crc); +#ifdef DBG + print_pmt(&pmt_hdr); +#endif + //cleanup ... + if (pm_cads->cad) + free(pm_cads->cad); + if (es_cads->cad) + free(es_cads->cad); + *es_pid_num = 0; + memset(pm_cads,0,sizeof(si_ca_pmt_t)); + memset(es_cads,0,sizeof(si_ca_pmt_t)); + return -1; + } + +#ifdef DBG + info("#####################################\n"); + info("parse_ca_desc(): section parsed: OK !\n"); +#endif + return 0; +} +//----------------------------------------------------------------------------------- +int parse_cat_sect(unsigned char *buf, int size, si_cad_t *emm) +{ + unsigned char *ptr=buf; + int len,i,ret; + cat_t c; + + c.table_id = ptr[0]; + c.section_syntax_indicator = (ptr[1] >> 7) & 1; + c.reserved_1 = (ptr[1] >> 4) & 3; + c.section_length = ((ptr[1] << 8) | ptr[2]) & 0xfff; + + if (c.section_length < 9 || c.section_length > 1021 || (int)c.section_length > size) { + info("CAT: Invalid section length!\n"); + return -1; + } + +#ifdef CRC32_CHECK + u_long crc = dvb_crc32 ((char *)buf,c.section_length+3); +#ifdef DBG + info("CRCcc: 0x%lx\n",crc); +#endif + if (crc & 0xffffffff) { + info("CAT:CRC32 error (0x%lx)!\n",crc); + return -1; + } +#endif + + c.reserved_2 = (ptr[3] << 10) | (ptr[4] << 2) | ((ptr[5] >> 6) & 3); + c.version_number = (ptr[5] >> 1) & 0x1f; + c.current_next_indicator = ptr[5] & 1; + c.section_number = ptr[6]; + c.last_section_number = ptr[7]; + + + //do desc. here + len = c.section_length - 5; + ptr+=8; //go after hdr. + + i = len; + while(i > 4) { //crc32 4 bytes + ret = descriptor(ptr, emm); + if (ret < 0) { + info ("cannot parse CA descriptor in CAT !\n"); + return -1; + } + i-=ret; + ptr+=ret; + if (ptr >= buf + size) { + info("CAT: Invalid Buffer offset !\n"); + break; + } + } + if (i != 4) { + info("CAT: index out of bounds !\n"); + return -1; + } +#ifdef DBG + info("%d bytes remaining (program info len = %d bytes)\n",len-i,len); +#endif + c.crc32 = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; + + + return 0; +} +//----------------------------------------------------------------------------------- +int parse_pat_sect(unsigned char *buf, int size, pmt_pid_list_t *pmt) +{ + unsigned char *ptr=buf; + pat_t p; + pat_list_t *pat_info = NULL; + + memset(&p,0,sizeof(p)); + + p.table_id=ptr[0]; + p.section_syntax_indicator=(ptr[1] & 0x80) >> 7; + p.reserved_1=(ptr[1] & 0x30) >> 4; + p.section_length=((ptr[1] << 8) | ptr[2]) & 0x0fff; + + if (p.section_length < 9 || p.section_length > 1021 || (int)p.section_length > size) { + info("PAT: Invalid section length !\n"); + return -1; + + } + +#ifdef CRC32_CHECK + u_long crc = dvb_crc32 ((char *)buf,p.section_length+3); + //FIXME: is it the right way ? + if (crc & 0xffffffff) { + info("PAT:CRC32 error (0x%lx)!\n",crc); + return -1; + } +#endif + + p.transport_stream_id=(ptr[3] << 8) | ptr[4]; + p.reserved_2=(ptr[5] & 0xc0) >> 6; + p.version_number=(ptr[5] & 0x3e) >> 1; + p.current_next_indicator=(ptr[5] & 1); + p.section_number=ptr[6]; + p.last_section_number=ptr[7]; + + int n,i,pmt_num; + + n = p.section_length - 5 - 4; //bytes following section_length field + crc32 chk_sum + + ptr+=8; + pmt_num=0; + if (n > 0 && ((ptr + n) < (buf + size))) { + pat_info=(pat_list_t *)malloc(sizeof(pat_list_t)*n/4); + if (!pat_info) { + info ("PAT: out of memory\n"); + return -1; + } + for(i=0;i<n;i+=4) { + pat_list_t *pat = pat_info + pmt_num; + pat->program_number=(ptr[0] << 8) | (ptr[1]); + pat->reserved=(ptr[2] & 0xe0) >> 5; + pat->network_pmt_pid=((ptr[2] << 8) | ptr[3]) & 0x1fff; + if (pat->network_pmt_pid != 0x10) { //NIT => FIXME: remove other known pids + // memset(&pat->desc,0,sizeof(pmt_desc_list_t)); + pmt_num++; + } + ptr+=4; + } + + p.crc32=(ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; + if (n != pmt_num) + pat_info=(pat_list_t *)realloc(pat_info,sizeof(pat_list_t)*pmt_num); + if (!pat_info) { + info("parse_pat_sect():realloc error\n"); + return -1; + } + } + if (pmt) { + pmt->p=p; + pmt->pl=pat_info; + pmt->pmt_pids=pmt_num; + } + + return 0; +} +int parse_tdt_sect(unsigned char *buf, int size, tdt_sect_t *tdt) +{ + unsigned char *ptr = buf; + + tdt->table_id=ptr[0]; + tdt->section_syntax_indicator=(ptr[1] & 0x80) >> 7; + tdt->reserved_1=(ptr[1] >> 4) >> 3; + tdt->section_length=((ptr[1] << 8) | ptr[2]) & 0x0fff; + + if (tdt->section_length != 5) { + info("TDT: Invalid section length !\n"); + return -1; + } + + //copy UTC time MJD + UTC + memcpy(tdt->dvbdate, ptr + 3, 5); + + return 0; + +} +//----------------------------------------------------------------------------------- +//TS packets handling +int get_ts_packet_hdr(unsigned char *buf, ts_packet_hdr_t *p) +{ + unsigned char *ptr=buf; + + memset(p,0,sizeof(p)); + + p->sync_byte=ptr[0]; + p->transport_error_indicator=(ptr[1] & 0x80) >> 7; + p->payload_unit_start_indicator=(ptr[1] & 0x40) >> 6; + p->transport_priority=(ptr[1] & 0x20) >> 5; + p->pid=((ptr[1] << 8) | ptr[2]) & 0x1fff; + p->transport_scrambling_control=(ptr[3] & 0xC0) >> 6; + p->adaptation_field_control=(ptr[3] & 0x30) >> 4; + p->continuity_counter=(ptr[3] & 0xf); + +#ifdef DBG + print_ts_header(p); +#endif + + return 0; + +} +//----------------------------------------------------------------------------------- +int ts2psi_data(unsigned char *buf,psi_buf_t *p,int len, int pid_req) +{ + unsigned char *b=buf; + ts_packet_hdr_t h; + + + get_ts_packet_hdr(buf,&h); + + b+=4; + len-=4; + + if (h.sync_byte != 0x47) { +#ifdef SERVER + sys("%s:No sync byte in header !\n",__FUNCTION__); +#endif + return -1; + } + + + if (pid_req != (int)h.pid) { +#ifdef DBG + info("%s:pids mismatch (pid req = %#x ts pid = %#x )!\n", __FUNCTION__,pid_req, h.pid); +#endif + return -1; + } + + //FIXME:Handle adaptation field if present/needed + if (h.adaptation_field_control & 0x2) { + int n; + + n=b[0]+1; + b+=n; + len-=n; + + } + + if (h.adaptation_field_control & 0x1) { + if (h.transport_error_indicator) { +#ifdef DBG + info("Transport error flag set !\n"); +#endif + return -1; + } + if (h.transport_scrambling_control) { +#ifdef DBG + info("Transport scrambling flag set !\n"); +#endif + //return -1; + } + + if (h.payload_unit_start_indicator && p->start) { //whole section new begin packet +#ifdef DBG + info("%s:section read !\n",__FUNCTION__); +#endif + return 1; + } + + if (h.payload_unit_start_indicator && !p->start) { //packet beginning + int si_offset=b[0]+1; //always pointer field in first byte of TS packet payload with start indicator set + b+=si_offset; + len-=si_offset; + if (len < 0 || len > 184) { +#ifdef DBG + info("WARNING 1: TS Packet damaged !\n"); +#endif + return -1; + } + //move to buffer + memcpy(p->buf,b,len); + p->len=len; + p->start=((b[1] << 8) | b[2]) & 0x0fff; //get section length, using start for length + p->pid=h.pid; + p->continuity=h.continuity_counter; + + } + + if (!h.payload_unit_start_indicator && p->start) { //packet continuation + //duplicate packet + if ((p->pid == (int)h.pid) && (p->continuity == (int)h.continuity_counter)){ +#ifdef DBG + info("Packet duplicate ???\n"); +#endif + return -1; + } + //new packet + if (p->pid != (int)h.pid) { +#ifdef DBG + info("New pid buf start %d len %d bytes (pid in buf = %d pid in ts = %d) !\n", p->start,p->len, p->pid, h.pid); +#endif + return -1; + } + //discontinuity of packets + if (((++p->continuity)%16) != (int)h.continuity_counter) { +#ifdef DBG + info("Discontinuity of ts stream !!!\n"); +#endif + return -1; + } + p->continuity=h.continuity_counter; + if (len < 0 || len > 184) { + info("WARNING 2: TS Packet damaged !\n"); + return -1; + } + //move to buffer + memcpy(p->buf+p->len,b,len); + p->len+=len; //FIXME: circular buffer + if (p->len + 188 > PSI_BUF_SIZE) { + info("Error: Buffer full !\n"); + return -1; + //FIXME:realloc + } + } + } + +#if 1 + //3 bytes for bytes containing table id and section length + TS_SECT_LEN(b); + if (slen+3 <= len && h.payload_unit_start_indicator) //len = 188 bytes - 4 bytes ts hdr. - adapt. field bytes - 1 byte offset - offset + return 1; +#else //possible opt. + /*if (p->start+3 == len) + return 1;*/ +#endif + + return 0; +} +//TS packets handling end +//----------------------------------------------------------------------------------- + + + diff --git a/mcast/common/.svn/text-base/siparser.h.svn-base b/mcast/common/.svn/text-base/siparser.h.svn-base new file mode 100644 index 0000000..255ebe0 --- /dev/null +++ b/mcast/common/.svn/text-base/siparser.h.svn-base @@ -0,0 +1,369 @@ +#ifndef __SIPARSER_H__ +#define __SIPARSER_H__ + +#define TS_SECT_LEN(buf) \ + unsigned char *ptr = buf; \ + int slen = (((ptr[1] << 8) | ptr[2]) & 0x0fff); + + +#define TS_PACKET_LEN (188) /* TS RDSIZE is fixed !! */ +#define TS_SYNC_BYTE (0x47) /* SyncByte for TS ISO 138181-1 */ +#define TS_BUF_SIZE (256 * 1024) /* default DMX_Buffer Size for TS */ +#define PSI_BUF_SIZE (2 * 4096) /* Section length max. 12 bits */ +#define READ_BUF_SIZE (256*TS_PACKET_LEN) /* min. 2x TS_PACKET_LEN!!! */ +#define BILLION 1000000000L; +#define MAX_DESC_LEN 255 //descriptor_length field 8-bit ISO/IEC 13818-1 +#define MAX_ES_PIDS 32 + + +#define VIDEO_11172_STREAM_TYPE 0x1 // STREAMTYPE_11172_VIDEO +#define VIDEO_13818_STREAM_TYPE 0x2 // STREAMTYPE_13818_VIDEO +#define VISUAL_MPEG4_STREAM_TYPE 0x10 // 14496-2 Visual MPEG-4 +#define VIDEO_H264_STREAM_TYPE 0x1b // 14496-10 Video h.264 +#define AUDIO_11172_STREAM_TYPE 0x3 // STREAMTYPE_11172_AUDIO +#define AUDIO_13818_STREAM_TYPE 0x4 // STREAMTYPE_13818_AUDIO +#define PRIVATE_13818_STREAM_TYPE 0x5 // STREAMTYPE_13818_PRIVATE +#define PRIVATE_13818_PES_STREAM_TYPE 0x6 // STREAMTYPE_13818_PES_PRIVATE + +enum DescriptorTag { + // defined by ISO/IEC 13818-1 + VideoStreamDescriptorTag = 0x02, + AudioStreamDescriptorTag = 0x03, + HierarchyDescriptorTag = 0x04, + RegistrationDescriptorTag = 0x05, + DataStreamAlignmentDescriptorTag = 0x06, + TargetBackgroundGridDescriptorTag = 0x07, + VideoWindowDescriptorTag = 0x08, + CaDescriptorTag = 0x09, + ISO639LanguageDescriptorTag = 0x0A, + SystemClockDescriptorTag = 0x0B, + MultiplexBufferUtilizationDescriptorTag = 0x0C, + CopyrightDescriptorTag = 0x0D, + MaximumBitrateDescriptorTag = 0x0E, + PrivateDataIndicatorDescriptorTag = 0x0F, + SmoothingBufferDescriptorTag = 0x10, + STDDescriptorTag = 0x11, + IBPDescriptorTag = 0x12, + // defined by ISO-13818-6 (DSM-CC) + CarouselIdentifierDescriptorTag = 0x13, + // 0x14 - 0x3F Reserved + // defined by ETSI (EN 300 468) + NetworkNameDescriptorTag = 0x40, + ServiceListDescriptorTag = 0x41, + StuffingDescriptorTag = 0x42, + SatelliteDeliverySystemDescriptorTag = 0x43, + CableDeliverySystemDescriptorTag = 0x44, + VBIDataDescriptorTag = 0x45, + VBITeletextDescriptorTag = 0x46, + BouquetNameDescriptorTag = 0x47, + ServiceDescriptorTag = 0x48, + CountryAvailabilityDescriptorTag = 0x49, + LinkageDescriptorTag = 0x4A, + NVODReferenceDescriptorTag = 0x4B, + TimeShiftedServiceDescriptorTag = 0x4C, + ShortEventDescriptorTag = 0x4D, + ExtendedEventDescriptorTag = 0x4E, + TimeShiftedEventDescriptorTag = 0x4F, + ComponentDescriptorTag = 0x50, + MocaicDescriptorTag = 0x51, + StreamIdentifierDescriptorTag = 0x52, + CaIdentifierDescriptorTag = 0x53, + ContentDescriptorTag = 0x54, + ParentalRatingDescriptorTag = 0x55, + TeletextDescriptorTag = 0x56, + TelephoneDescriptorTag = 0x57, + LocalTimeOffsetDescriptorTag = 0x58, + SubtitlingDescriptorTag = 0x59, + TerrestrialDeliverySystemDescriptorTag = 0x5A, + MultilingualNetworkNameDescriptorTag = 0x5B, + MultilingualBouquetNameDescriptorTag = 0x5C, + MultilingualServiceNameDescriptorTag = 0x5D, + MultilingualComponentDescriptorTag = 0x5E, + PrivateDataSpecifierDescriptorTag = 0x5F, + ServiceMoveDescriptorTag = 0x60, + ShortSmoothingBufferDescriptorTag = 0x61, + FrequencyListDescriptorTag = 0x62, + PartialTransportStreamDescriptorTag = 0x63, + DataBroadcastDescriptorTag = 0x64, + ScramblingDescriptorTag = 0x65, + DataBroadcastIdDescriptorTag = 0x66, + TransportStreamDescriptorTag = 0x67, + DSNGDescriptorTag = 0x68, + PDCDescriptorTag = 0x69, + AC3DescriptorTag = 0x6A, + AncillaryDataDescriptorTag = 0x6B, + CellListDescriptorTag = 0x6C, + CellFrequencyLinkDescriptorTag = 0x6D, + AnnouncementSupportDescriptorTag = 0x6E, + ApplicationSignallingDescriptorTag = 0x6F, + AdaptationFieldDataDescriptorTag = 0x70, + ServiceIdentifierDescriptorTag = 0x71, + ServiceAvailabilityDescriptorTag = 0x72, + // defined by ETSI (EN 300 468) v 1.7.1 + DefaultAuthorityDescriptorTag = 0x73, + RelatedContentDescriptorTag = 0x74, + TVAIdDescriptorTag = 0x75, + ContentIdentifierDescriptorTag = 0x76, + TimeSliceFecIdentifierDescriptorTag = 0x77, + ECMRepetitionRateDescriptorTag = 0x78, + S2SatelliteDeliverySystemDescriptorTag = 0x79, + EnhancedAC3DescriptorTag = 0x7A, + DTSDescriptorTag = 0x7B, + AACDescriptorTag = 0x7C, + ExtensionDescriptorTag = 0x7F, + + // Defined by ETSI TS 102 812 (MHP) + // They once again start with 0x00 (see page 234, MHP specification) + MHP_ApplicationDescriptorTag = 0x00, + MHP_ApplicationNameDescriptorTag = 0x01, + MHP_TransportProtocolDescriptorTag = 0x02, + MHP_DVBJApplicationDescriptorTag = 0x03, + MHP_DVBJApplicationLocationDescriptorTag = 0x04, + // 0x05 - 0x0A is unimplemented this library + MHP_ExternalApplicationAuthorisationDescriptorTag = 0x05, + MHP_IPv4RoutingDescriptorTag = 0x06, + MHP_IPv6RoutingDescriptorTag = 0x07, + MHP_DVBHTMLApplicationDescriptorTag = 0x08, + MHP_DVBHTMLApplicationLocationDescriptorTag = 0x09, + MHP_DVBHTMLApplicationBoundaryDescriptorTag = 0x0A, + MHP_ApplicationIconsDescriptorTag = 0x0B, + MHP_PrefetchDescriptorTag = 0x0C, + MHP_DelegatedApplicationDescriptorTag = 0x0E, + MHP_ApplicationStorageDescriptorTag = 0x10, + // Premiere private Descriptor Tags + PremiereContentTransmissionDescriptorTag = 0xF2, + + //a descriptor currently unimplemented in this library + //the actual value 0xFF is "forbidden" according to the spec. + UnimplementedDescriptorTag = 0xFF +}; + + + +typedef struct ts_packet_hdr +{ + unsigned int sync_byte; + unsigned int transport_error_indicator; + unsigned int payload_unit_start_indicator; + unsigned int transport_priority; + unsigned int pid; + unsigned int transport_scrambling_control; + unsigned int adaptation_field_control; + unsigned int continuity_counter; +} ts_packet_hdr_t; + +typedef struct pat { + unsigned int table_id; + unsigned int section_syntax_indicator; + unsigned int reserved_1; + unsigned int section_length; + unsigned int transport_stream_id; + unsigned int reserved_2; + unsigned int version_number; + unsigned int current_next_indicator; + unsigned int section_number; + unsigned int last_section_number; + + // FIXME: list of programs + + unsigned int crc32; +} pat_t; + +typedef struct _pat_list { + unsigned int program_number; //SID + unsigned int reserved; + unsigned int network_pmt_pid; + + int cads_present; + int cads_num; + +} pat_list_t; + +typedef struct pmt_pid_list { + + pat_t p; + pat_list_t *pl; + unsigned int pmt_pids; + +} pmt_pid_list_t; + +typedef struct psi_buf { + + unsigned char *buf; + unsigned int len;//used for offset + unsigned int start; + + int pid; + int continuity; + +} psi_buf_t; + +typedef struct pmt { + unsigned int table_id; + unsigned int section_syntax_indicator; + unsigned int reserved_1; + unsigned int section_length; + unsigned int program_number; + unsigned int reserved_2; + unsigned int version_number; + unsigned int current_next_indicator; + unsigned int section_number; + unsigned int last_section_number; + unsigned int reserved_3; + unsigned int pcr_pid; + unsigned int reserved_4; + unsigned int program_info_length; + + // N descriptors + + // N1 stream types and descriptors + + unsigned int crc32; +} pmt_t; + +typedef struct es_pmt_info { + unsigned int stream_type; + unsigned int reserved_1; + unsigned int elementary_pid; + unsigned int reserved_2; + unsigned int es_info_length; + + // N2 descriptor + +} es_pmt_info_t; + +typedef struct ca_descriptor { + + unsigned int descriptor_tag; + unsigned int descriptor_length; + unsigned int ca_system_id; + unsigned int reserved; + unsigned int ca_pid; + unsigned char private_data[MAX_DESC_LEN]; + +} si_desc_t; + +typedef struct pmt_descriptor { + + pmt_t pmt_hdr; + + int cas; + si_desc_t *cad; + +} si_pmt_desc_t; + +typedef struct ca_descriptor_list { + + int cads; + si_desc_t *cad; + +} si_cad_t; + +typedef struct ca_sid_info { + + int sid; + int version; + int offset; + int len; + +} ca_sid_t; + +typedef struct ca_pmt_descriptors { + + int cads; + int size; + unsigned char *cad; + +} si_ca_pmt_t; + +typedef struct ca_es_pid_info { + + int pid; + uint8_t type; + +} ca_es_pid_info_t; + +typedef struct ca_pmt_list { + + int sid; + int pmt_pid; + + pmt_t p; + si_ca_pmt_t pm; + si_ca_pmt_t es; + + ca_es_pid_info_t espids[MAX_ES_PIDS]; + int es_pid_num; + +} ca_pmt_list_t; + + +typedef struct ca_sid_list { + + int tc; //total number of CA desc. + int num; + ca_pmt_list_t *l; + +} ca_sid_list_t; + +typedef struct _cat { + unsigned int table_id; + unsigned int section_syntax_indicator; + unsigned int reserved_1; + unsigned int section_length; + unsigned int reserved_2; + unsigned int version_number; + unsigned int current_next_indicator; + unsigned int section_number; + unsigned int last_section_number; + + // private section + + unsigned int crc32; +} cat_t; + +typedef struct tdt_sect { + + uint8_t table_id; + uint8_t section_syntax_indicator; + uint8_t reserved; //0 future use + uint8_t reserved_1; + uint16_t section_length; + uint8_t dvbdate[5]; +} tdt_sect_t; + +typedef struct _str_table { + unsigned int from; + unsigned int to; + const char *str; +} str_table; + + +int parse_ca_descriptor(unsigned char *desc, si_desc_t *t); + +int ts2psi_data(unsigned char *buf,psi_buf_t *p,int len, int pid_req); +int parse_pat_sect(unsigned char *buf, int size, pmt_pid_list_t *pmt); +int parse_pmt_ca_desc(unsigned char *buf, int size, int sid, si_ca_pmt_t *pm_cads, si_ca_pmt_t *es_cads, pmt_t *pmt_hdr, int *fta, ca_es_pid_info_t *espid, int *es_pid_num); +int parse_cat_sect(unsigned char *buf, int size, si_cad_t *emm); +int parse_tdt_sect(unsigned char *buf, int size, tdt_sect_t *tdt); +int get_ts_packet_hdr(unsigned char *buf, ts_packet_hdr_t *p); +int si_get_video_pid(unsigned char *esi_buf, int size, int *vpid); +int si_get_audio_pid(unsigned char *esi_buf, int size, int *apid); +int si_get_private_pids(unsigned char *esi_buf, int size, int *upids); +int get_pmt_es_pids(unsigned char *esi_buf, int size, int *es_pids, int all); +void print_pat(pat_t *p, pat_list_t *pl, int pmt_num); +void printhex_buf(char *msg,unsigned char *buf,int len); +void writehex_buf(FILE *f,char *msg,unsigned char *buf,int len); +void print_cad_lst(si_cad_t *l, int ts_id); +void print_ca_bytes(si_desc_t *p); +void get_time_mjd (unsigned long mjd, long *year , long *month, long *day); +void print_tdt(tdt_sect_t *tdt, uint16_t mjd, uint32_t utc); +int ca_free_cpl_desc(ca_pmt_list_t *cpl); +char *si_caid_to_name(unsigned int caid); + +#endif + + + + + diff --git a/mcast/common/.svn/text-base/tools.c.svn-base b/mcast/common/.svn/text-base/tools.c.svn-base new file mode 100644 index 0000000..9e05a10 --- /dev/null +++ b/mcast/common/.svn/text-base/tools.c.svn-base @@ -0,0 +1,777 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#define DEBUG 1 +#include "headers.h" + +#ifdef DEBUG +const Param inversion_list[] = { + {"INVERSION_OFF", INVERSION_OFF}, + {"INVERSION_ON", INVERSION_ON}, + {"INVERSION_AUTO", INVERSION_AUTO} +}; + +const Param bw_list[] = { + {"BANDWIDTH_6_MHZ", BANDWIDTH_6_MHZ}, + {"BANDWIDTH_7_MHZ", BANDWIDTH_7_MHZ}, + {"BANDWIDTH_8_MHZ", BANDWIDTH_8_MHZ} +}; + +const Param fec_list[] = { + {"FEC_1_2", FEC_1_2}, + {"FEC_2_3", FEC_2_3}, + {"FEC_3_4", FEC_3_4}, + {"FEC_4_5", FEC_4_5}, + {"FEC_5_6", FEC_5_6}, + {"FEC_6_7", FEC_6_7}, + {"FEC_7_8", FEC_7_8}, + {"FEC_8_9", FEC_8_9}, + {"FEC_AUTO", FEC_AUTO}, + {"FEC_NONE", FEC_NONE}, + {"FEC_1_4", FEC_1_4}, // RMM S2 Extension + {"FEC_1_3", FEC_1_3}, + {"FEC_2_5", FEC_2_5}, + {"FEC_9_10", FEC_9_10} +}; + +const Param guard_list[] = { + {"GUARD_INTERVAL_1_16", GUARD_INTERVAL_1_16}, + {"GUARD_INTERVAL_1_32", GUARD_INTERVAL_1_32}, + {"GUARD_INTERVAL_1_4", GUARD_INTERVAL_1_4}, + {"GUARD_INTERVAL_1_8", GUARD_INTERVAL_1_8} +}; + +const Param hierarchy_list[] = { + {"HIERARCHY_1", HIERARCHY_1}, + {"HIERARCHY_2", HIERARCHY_2}, + {"HIERARCHY_4", HIERARCHY_4}, + {"HIERARCHY_NONE", HIERARCHY_NONE} +}; + +const Param constellation_list[] = { + {"QPSK", QPSK}, + {"QAM_128", QAM_128}, + {"QAM_16", QAM_16}, + {"QAM_256", QAM_256}, + {"QAM_32", QAM_32}, + {"QAM_64", QAM_64}, + {"QPSK_S2", QPSK_S2}, // RMM S2 Extension + {"PSK8", PSK8} +}; + +const Param transmissionmode_list[] = { + {"TRANSMISSION_MODE_2K", TRANSMISSION_MODE_2K}, + {"TRANSMISSION_MODE_8K", TRANSMISSION_MODE_8K}, +}; + +const Param capabilities_list[] = { + {"Stupid: ", FE_IS_STUPID}, + {"FE_CAN_INVERSION_AUTO: ", FE_CAN_INVERSION_AUTO}, + {"CAN_FEC_1_2: ", FE_CAN_FEC_1_2}, + {"CAN_FEC_2_3: ", FE_CAN_FEC_2_3}, + {"CAN_FEC_3_4: ", FE_CAN_FEC_3_4}, + {"CAN_FEC_4_5: ", FE_CAN_FEC_4_5}, + {"CAN_FEC_6_7: ", FE_CAN_FEC_6_7}, + {"CAN_FEC_7_8: ", FE_CAN_FEC_7_8}, + {"CAN_FEC_8_9: ", FE_CAN_FEC_8_9}, + {"CAN_FEC_AUTO: ", FE_CAN_FEC_AUTO}, + {"FE_CAN_QPSK: ", FE_CAN_QPSK}, + {"FE_CAN_QAM_16: ", FE_CAN_QAM_16}, + {"FE_CAN_QAM_32: ", FE_CAN_QAM_32}, + {"FE_CAN_QAM_64: ", FE_CAN_QAM_64}, + {"FE_CAN_QAM_128: ", FE_CAN_QAM_128}, + {"FE_CAN_QAM_256: ", FE_CAN_QAM_256}, + {"FE_CAN_QAM_AUTO: ", FE_CAN_QAM_AUTO}, + {"FE_CAN_TRANSMISSION_MODE_AUTO: ", FE_CAN_TRANSMISSION_MODE_AUTO}, + {"FE_CAN_BANDWIDTH_AUTO: ", FE_CAN_BANDWIDTH_AUTO}, + {"FE_CAN_GUARD_INTERVAL_AUTO: ", FE_CAN_GUARD_INTERVAL_AUTO}, + {"FE_CAN_HIERARCHY_AUTO: ", FE_CAN_HIERARCHY_AUTO}, + {"FE_CAN_MUTE_TS: ", FE_CAN_MUTE_TS} +// {"FE_CAN_CLEAN_SETUP: ",FE_CAN_CLEAN_SETUP} +}; + +#define LIST_SIZE(x) sizeof(x)/sizeof(Param) + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +void print_fe_info (struct dvb_frontend_info *fe_info) +{ + fprintf (stdout, "-------------------------------------------\n"); + fprintf (stdout, "Tuner name: %s\n", fe_info->name); + fprintf (stdout, "Tuner type: %u\n", (unsigned int) fe_info->type); + fprintf (stdout, "Frequency min.: %u\n", fe_info->frequency_min); + fprintf (stdout, "Frequency max.: %u\n", fe_info->frequency_max); + fprintf (stdout, "Frequency stepsize: %u\n", fe_info->frequency_stepsize); + fprintf (stdout, "Frequency tolerance: %u\n", fe_info->frequency_tolerance); + fprintf (stdout, "Symbol rate min: %u\n", fe_info->symbol_rate_min); + fprintf (stdout, "Symbol rate max: %u\n", fe_info->symbol_rate_max); + fprintf (stdout, "Symbol rate tolerance: %u\n", fe_info->symbol_rate_tolerance); + fprintf (stdout, "Notifier delay: %u\n", fe_info->notifier_delay); + fprintf (stdout, "Cpas: 0x%x\n", (unsigned int) fe_info->caps); + + fprintf (stdout, "-------------------------------------------\n"); + fprintf (stdout, "Frontend Capabilities:\n"); + int i; + + for (i = 0; i < LIST_SIZE (capabilities_list); i++) { + if (fe_info->caps & capabilities_list[i].value) + fprintf (stdout, "%syes\n", capabilities_list[i].name); + else + fprintf (stdout, "%sno\n", capabilities_list[i].name); + } + fprintf (stdout, "-------------------------------------------\n"); +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +void print_frontend_settings (struct dvb_frontend_parameters *frontend_param) +{ + int i; + fprintf (stdout, "\n----- Front End Settings ----- "); + fprintf (stdout, "\nFrequency : %u \n", frontend_param->frequency); + for (i = 0; i < LIST_SIZE (inversion_list); i++) { + if (inversion_list[i].value == frontend_param->inversion) + fprintf (stdout, "Inversion : %s\n", inversion_list[i].name); + + } + // + for (i = 0; i < LIST_SIZE (bw_list); i++) { + if (frontend_param->u.ofdm.bandwidth == bw_list[i].value) + fprintf (stdout, "Bandwidth : %s\n", bw_list[i].name); + + } + for (i = 0; i < LIST_SIZE (fec_list); i++) { + if (fec_list[i].value == frontend_param->u.ofdm.code_rate_HP) + fprintf (stdout, "Code Rate HP : %s\n", fec_list[i].name); + + } + for (i = 0; i < LIST_SIZE (fec_list); i++) { + if (fec_list[i].value == frontend_param->u.ofdm.code_rate_LP) + fprintf (stdout, "Code Rate LP : %s\n", fec_list[i].name); + + } + + for (i = 0; i < LIST_SIZE (constellation_list); i++) { + if (constellation_list[i].value == frontend_param->u.ofdm.constellation) + fprintf (stdout, "Modulation : %s\n", constellation_list[i].name); + + } + + for (i = 0; i < LIST_SIZE (transmissionmode_list); i++) { + if (transmissionmode_list[i].value == frontend_param->u.ofdm.transmission_mode) + fprintf (stdout, "Transmission mode : %s\n", transmissionmode_list[i].name); + + } + + for (i = 0; i < LIST_SIZE (guard_list); i++) { + if (guard_list[i].value == frontend_param->u.ofdm.guard_interval) + fprintf (stdout, "Guard interval : %s\n", guard_list[i].name); + + } + + for (i = 0; i < LIST_SIZE (hierarchy_list); i++) { + if (hierarchy_list[i].value == frontend_param->u.ofdm.hierarchy_information) + fprintf (stdout, "Hierarchy Information : %s\n", hierarchy_list[i].name); + + } + +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +void print_mcg (struct in6_addr *mcg) +{ + char host[80]; + unsigned int freq; + struct in6_addr mc; + int i; + + for (i = 0; i < 8; i++) { + mc.s6_addr16[i] = ntohs (mcg->s6_addr16[i]); + } + + freq = mc.s6_addr16[6] | (mc.s6_addr16[7] & NOPID_MASK) << 3; + + inet_ntop (AF_INET6, mcg->s6_addr, (char *) host, INET6_ADDRSTRLEN); + fprintf (stdout, "MCG: %s\n", host); + + fprintf (stdout, "\n"); + fprintf (stdout, "TS-Streaming group\n"); + fprintf (stdout, "-----------------------------\n"); + fprintf (stdout, "Streaming Group - 0x%x \n", (mc.s6_addr16[1] >> 12) & 0xf); + fprintf (stdout, "Priority - 0x%x \n", (mc.s6_addr16[1] >> 8) & 0xf); + fprintf (stdout, "Reception System - 0x%x \n", mc.s6_addr16[1] & 0xff); + fprintf (stdout, "CAM Handling - 0x%x \n", mc.s6_addr16[2]); + fprintf (stdout, "Polarisation - 0x%x \n", (mc.s6_addr16[3] >> 12) & 0xf); + fprintf (stdout, "SATPosition - 0x%x \n", mc.s6_addr16[3] & 0xfff); + fprintf (stdout, "Symbol Rate - 0x%x \n", mc.s6_addr16[4]); + fprintf (stdout, "Modulation - 0x%x \n", mc.s6_addr16[5]); + fprintf (stdout, "Frequency (0x%x) - %d / %d\n\n", freq, freq * (16667 / 8), freq * (250 / 8)); + + fprintf (stdout, "PID - 0x%x \n", mc.s6_addr16[7] & PID_MASK); +} +#endif +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +/* Frequency 19Bit + DVB-T/DVB-C 524288 Steps * (25/12)kHz = 0...1092MHz in 2.083333kHz steps + DVB-S 524288 Steps * (1/20) MHz = 0...26.2GHz in 50kHz steps +*/ +void fe_parms_to_mcg (struct in6_addr *mcg, streaming_group_t StreamingGroup, fe_type_t type, recv_sec_t * sec, struct dvb_frontend_parameters *fep, int vpid) +{ + int i; + unsigned int Priority = 0; + unsigned int ReceptionSystem = 0; + unsigned int CAMHandling = 0; + unsigned int Polarisation = 0; + unsigned int SATPosition = NO_SAT_POS; + unsigned int Symbolrate = 0; + unsigned int Modulation = 0; + unsigned int TransmissionMode = 0; + unsigned int Frequency; + double fmul; + + // Default for DVB-T and DVB-C + fmul = 12.0 * (((double) fep->frequency) + 1041); + Frequency = (unsigned int) (fmul / 25000.0); + + switch ((int)type) { + case FE_QPSK: + case FE_DVBS2: + Frequency = (fep->frequency + 24) / 50; + //sec->diseqc_cmd currently not used + // Fixme: Translation Diseqc->position/LOF-frequency + Polarisation = (sec->mini_cmd << 3) | (sec->tone_mode << 2) | sec->voltage; + Symbolrate = fep->u.qpsk.symbol_rate / 1000; + Modulation |= (fep->u.qpsk.fec_inner) & 0xf; + + // RMM S2 extension: Put Modulation in 23:16 and rolloff in 31:24 + if (((fep->u.qpsk.fec_inner >> 16) & 0xff) == PSK8) + Modulation |= 2 << 4; + if (((fep->u.qpsk.fec_inner >> 16) & 0xff) == QPSK_S2) + Modulation |= 1 << 4; + Modulation |= fep->inversion << 14; + break; + case FE_QAM: + Symbolrate = fep->u.qam.symbol_rate / 200; + Modulation |= fep->u.qam.modulation; + Modulation |= fep->inversion << 14; + break; + case FE_OFDM: + TransmissionMode = fep->u.ofdm.transmission_mode; + Symbolrate = (TransmissionMode & 0x7) << 8 | (fep->u.ofdm.code_rate_HP << 4) | fep->u.ofdm.code_rate_LP; + Modulation |= (fep->u.ofdm.constellation & 0xf) | (fep->u.ofdm.hierarchy_information & 3) << 4 | (fep->u.ofdm.bandwidth & 3) << 7 | (fep->u.ofdm.guard_interval & 7) << 9 | (fep->inversion & 3) << 14; + break; + case FE_ATSC: + Modulation |= fep->u.vsb.modulation; + Modulation |= fep->inversion << 14; + break; + } + + if (type == FE_DVBS2 && !(Modulation & 0x30) ){ + type=FE_QPSK; + } + + ReceptionSystem = type; + + mcg->s6_addr16[0] = MC_PREFIX; + mcg->s6_addr16[1] = ((StreamingGroup & 0xf) << 12) | ((Priority & 0xf) << 8) | (ReceptionSystem & 0xff); + mcg->s6_addr16[2] = CAMHandling; + mcg->s6_addr16[3] = ((Polarisation & 0xf) << 12) | (SATPosition & 0xfff); + mcg->s6_addr16[4] = Symbolrate; + mcg->s6_addr16[5] = Modulation; + mcg->s6_addr16[6] = Frequency; + mcg->s6_addr16[7] = (vpid & PID_MASK) | ((Frequency >> 16) << 13); + + for (i = 0; i < 8; i++) { + mcg->s6_addr16[i] = htons (mcg->s6_addr16[i]); + } +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +int mcg_to_all_parms(struct in6_addr *mcg, struct mcg_data * mcd) +{ + int ret; + mcd->mcg=*mcg; + int n; + + ret=mcg_to_fe_parms(mcg, &mcd->type, &mcd->sec, &mcd->fep, &mcd->vpid); + + if (ret) + return ret; + mcg_get_satpos(mcg, &mcd->satpos); + + for(n=0;n<MAX_TUNER_CACHE;n++) { + mcd->sat_cache[n].resolved=NOT_RESOLVED; + mcd->sat_cache[n].num=0; + mcd->sat_cache[n].component=0; + } + + return 0; +} +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +int mcg_to_fe_parms (struct in6_addr *mcg, fe_type_t * type, recv_sec_t * sec, struct dvb_frontend_parameters *fep, int *vpid) +{ + struct in6_addr mc = *mcg; + streaming_group_t StreamingGroup; + unsigned int freq; + double fmul; + fe_type_t fetype; + + int i; + for (i = 0; i < 8; i++) { + mc.s6_addr16[i] = ntohs (mc.s6_addr16[i]); + } + + StreamingGroup = (streaming_group_t)((mc.s6_addr16[1] >> 12) & 0xf); + + if (StreamingGroup != STREAMING_PID) { + return -1; + } + + if (fep) { + memset (fep, 0, sizeof (struct dvb_frontend_parameters)); + } + if (sec) { + memset (sec, 0, sizeof (recv_sec_t)); + } + + + freq = mc.s6_addr16[6] | ((mc.s6_addr16[7] & NOPID_MASK) << 3); + + fmul = 25000.0 * (double) freq; + + fep->frequency = (unsigned int) (fmul / 12.0); + fep->inversion = (fe_spectral_inversion_t)((mc.s6_addr16[5] >> 14) & 3); + fetype = (fe_type_t)(mc.s6_addr16[1] & 0xff); + + if (type) { + *type = fetype; + } + switch ((int)fetype) { + case FE_QPSK: + case FE_DVBS2: + { + int Polarisation = mc.s6_addr16[3] >> 12; + fep->frequency = freq * 50; + sec->mini_cmd = (fe_sec_mini_cmd_t)((Polarisation >> 3) & 1); + sec->tone_mode = (fe_sec_tone_mode_t)((Polarisation >> 2) & 1); + sec->voltage = (fe_sec_voltage_t)(Polarisation & 3); + + fep->u.qpsk.symbol_rate = mc.s6_addr16[4] * 1000; + fep->u.qpsk.fec_inner = (fe_code_rate_t)(mc.s6_addr16[5] & 0xf); + + unsigned int fec_inner=(unsigned int)fep->u.qpsk.fec_inner; + + // RMM S2 Extension + switch (mc.s6_addr16[5] & 0x30) { + case 0x10: + fec_inner |= QPSK_S2 << 16; + fep->u.qpsk.fec_inner=(fe_code_rate_t)fec_inner; + *type = (fe_type_t) FE_DVBS2; // force FE type + break; + case 0x20: + fec_inner |= PSK8 << 16; + fep->u.qpsk.fec_inner=(fe_code_rate_t)fec_inner; + *type = (fe_type_t) FE_DVBS2; + break; + default: + *type = FE_QPSK; + } + } + break; + case FE_QAM: + fep->u.qam.symbol_rate = mc.s6_addr16[4] * 200; + fep->u.qam.modulation = (fe_modulation_t)(mc.s6_addr16[5] & 0xf); + // Ignore inversion + break; + case FE_OFDM: + fep->u.ofdm.transmission_mode = (fe_transmit_mode_t)((mc.s6_addr16[4] >> 8) & 3); + fep->u.ofdm.code_rate_HP = (fe_code_rate_t)((mc.s6_addr16[4] >> 4) & 0xf); + fep->u.ofdm.code_rate_LP = (fe_code_rate_t)(mc.s6_addr16[4] & 0xf); + + fep->u.ofdm.constellation = (fe_modulation_t) (mc.s6_addr16[5] & 0xf); + fep->u.ofdm.hierarchy_information = (fe_hierarchy_t)((mc.s6_addr16[5] >> 4) & 3); + fep->u.ofdm.bandwidth = (fe_bandwidth_t)((mc.s6_addr16[5] >> 7) & 3); + fep->u.ofdm.guard_interval = (fe_guard_interval_t)((mc.s6_addr16[5] >> 9) & 7); + break; + case FE_ATSC: + fep->u.vsb.modulation = (fe_modulation_t)(mc.s6_addr16[5] & 0xf); + break; + } + + if (vpid) { + *vpid = mc.s6_addr16[7] & PID_MASK; + } + //print_frontend_settings(fep); + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +void mcg_set_streaming_group (struct in6_addr *mcg, streaming_group_t StreamingGroup) +{ + int i; + + for (i = 0; i < 8; i++) { + mcg->s6_addr16[i] = ntohs (mcg->s6_addr16[i]); + } + + // Change StreamingGroup + mcg->s6_addr16[1] = ((StreamingGroup & 0xf) << 12) | (mcg->s6_addr16[1] & 0x0fff); + + // Remove PID + mcg->s6_addr16[7] &= NOPID_MASK; + + // Remove CAID + mcg->s6_addr16[2] = 0; + + for (i = 0; i < 8; i++) { + mcg->s6_addr16[i] = htons (mcg->s6_addr16[i]); + } +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +void mcg_get_streaming_group (struct in6_addr *mcg, streaming_group_t *StreamingGroup) +{ + if(StreamingGroup) { + *StreamingGroup=(streaming_group_t)((ntohs (mcg->s6_addr16[1]) >> 12) & 0xf); + } +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +void mcg_set_pid (struct in6_addr *mcg, int pid) +{ + + mcg->s6_addr16[7] = ntohs (mcg->s6_addr16[7]); + + // Remove PID + mcg->s6_addr16[7] &= NOPID_MASK; + + // Set new PID + mcg->s6_addr16[7] |= pid; + + mcg->s6_addr16[7] = htons (mcg->s6_addr16[7]); +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +void mcg_get_pid (struct in6_addr *mcg, int *pid) +{ + if (pid) { + *pid=ntohs (mcg->s6_addr16[7]) & PID_MASK; + } +} + +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +void mcg_init_streaming_group (struct in6_addr *mcg, streaming_group_t StreamingGroup) +{ + unsigned int Priority = 1; + mcg->s6_addr16[0] = MC_PREFIX; + mcg->s6_addr16[1] = ((StreamingGroup & 0xf) << 12) | ((Priority & 0xf) << 8) | (0 & 0xff); + mcg->s6_addr16[2] = 0; + mcg->s6_addr16[3] = 0; + mcg->s6_addr16[4] = 0; + mcg->s6_addr16[5] = 0; + mcg->s6_addr16[6] = 0; + mcg->s6_addr16[7] = 0; + int i; + for (i = 0; i < 8; i++) { + mcg->s6_addr16[i] = htons (mcg->s6_addr16[i]); + } + +} + +void mcg_get_priority (struct in6_addr *mcg, int *priority) +{ + if (priority) { + *priority = (ntohs (mcg->s6_addr16[1])>>8) & 0xf; + } +} + +void mcg_set_priority (struct in6_addr *mcg, int priority) +{ + mcg->s6_addr16[1] = ntohs (mcg->s6_addr16[1]); + mcg->s6_addr16[1] &= 0xf0ff; + mcg->s6_addr16[1] |= (priority & 0xf) << 8; + mcg->s6_addr16[1] = htons (mcg->s6_addr16[1]); +} + +void mcg_get_satpos (struct in6_addr *mcg, int *satpos) +{ + if (satpos) { + *satpos = ntohs (mcg->s6_addr16[3]) & 0xfff; + } +} + +void mcg_set_satpos (struct in6_addr *mcg, int satpos) +{ + mcg->s6_addr16[3] = ntohs (mcg->s6_addr16[3]); + + // Remove SatPos + mcg->s6_addr16[3] &= ~NO_SAT_POS; + + // Set new SatPos + mcg->s6_addr16[3] |= (satpos & NO_SAT_POS); + + mcg->s6_addr16[3] = htons (mcg->s6_addr16[3]); +} + +void mcg_get_id (struct in6_addr *mcg, int *id) +{ + if (id) { + *id = ntohs (mcg->s6_addr16[2]); + } +} + +void mcg_set_id (struct in6_addr *mcg, int id) +{ + mcg->s6_addr16[2] = htons(id); +} + +#if defined LIBRARY || defined SERVER +#ifndef OS_CODE + #define OS_CODE 3 +#endif +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +static unsigned char gzip_hdr[] = { 0x1f, 0x8b, Z_DEFLATED, 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /*xflags */ , OS_CODE }; + +int check_header (const Bytef * buf, unsigned int buflen) +{ + if (buflen <= 10) + return 0; + + if (buf[0] != gzip_hdr[0] || buf[1] != gzip_hdr[1]) { + return -1; + } + + if (memcmp (buf, gzip_hdr, sizeof (gzip_hdr))) { + return -2; + } + return 10; +} + +unsigned int get32_lsb_first (unsigned char *ptr) +{ + int i; + unsigned int val = 0; + for (i = 3; i >= 0; i--) { + val <<= 8; + val |= (ptr[i] & 0xff); + } + return val; +} + +void put32_lsb_first (unsigned char *ptr, unsigned int val) +{ + int i; + for (i = 0; i < 4; i++) { + ptr[i] = val & 0xff; + val >>= 8; + } +} + +int gzip_ (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen, int level) +{ + unsigned int crc = crc32 (0L, Z_NULL, 0); + z_stream stream; + int err; + + if (*destLen <= 10) { + return Z_BUF_ERROR; + } + memcpy (dest, gzip_hdr, sizeof (gzip_hdr)); + + stream.next_in = (Bytef *) source; + stream.avail_in = sourceLen; + + stream.next_out = dest + 10; + stream.avail_out = *destLen - 10; + + stream.zalloc = (alloc_func) 0; + stream.zfree = (free_func) 0; + stream.opaque = (voidpf) 0; + + err = deflateInit2 (&stream, level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + + if (err != Z_OK) + return err; + + err = deflate (&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd (&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out + 10; + + err = deflateEnd (&stream); + crc = crc32 (crc, source, sourceLen); + + put32_lsb_first ((unsigned char *) (dest + *destLen), crc); + put32_lsb_first ((unsigned char *) (dest + *destLen + 4), sourceLen); + + *destLen += 8; + return err; +} + +int gzip (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen, int level) +{ + if (!level) { + memcpy (dest, source, sourceLen); + *destLen = sourceLen; + return 0; + } + return gzip_ (dest, destLen, source, sourceLen,level); +} + +int gunzip_ (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen) +{ + unsigned int crc = crc32 (0L, Z_NULL, 0); + z_stream stream; + int err; + int ret = check_header (source, sourceLen); + if (ret < 0) { + return ret; + } + + stream.next_in = (Bytef *) source + ret; + stream.avail_in = sourceLen - ret; + + stream.next_out = dest; + stream.avail_out = *destLen; + + stream.zalloc = (alloc_func) 0; + stream.zfree = (free_func) 0; + + err = inflateInit2 (&stream, -MAX_WBITS); + if (err != Z_OK) + return err; + + err = inflate (&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd (&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd (&stream); + crc = crc32 (crc, dest, stream.total_out); + + int crc_found = get32_lsb_first ((unsigned char *) (stream.next_in)); + int len_found = get32_lsb_first ((unsigned char *) (stream.next_in + 4)); + + if (crc_found == crc && len_found == stream.total_out) { + return err; + } + + return Z_DATA_ERROR; +} + +int gunzip (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen) +{ + int ret = gunzip_ (dest, destLen, source, sourceLen); + if (ret == -1) { + memcpy (dest, source, sourceLen); + *destLen = sourceLen; + return 0; + } else if (ret < 0) { + return -1; + } + return 0; +} +#endif +#ifndef BACKTRACE + void print_trace (void) + { + } +#else +#include <execinfo.h> +/* Obtain a backtrace and print it to stdout. */ +void print_trace (void) +{ + void *array[10]; + size_t size; + char **strings; + size_t i; + + size = backtrace (array, 10); + strings = backtrace_symbols (array, size); + + printf ("Obtained %zd stack frames.\n", size); + + for (i = 0; i < size; i++) { + printf ("%s\n", strings[i]); + } + free (strings); +} + + +void SignalHandlerCrash(int signum) +{ + void *array[15]; + size_t size; + char **strings; + size_t i; + FILE *f; + char dtstr[16]; + time_t t=time(NULL); + struct tm *tm=localtime(&t); + + signal(signum,SIG_DFL); // Allow core dump + + f=fopen("/var/log/mcli.crashlog","a"); + if (f) { + strftime(dtstr, sizeof(dtstr), "%b %e %T", tm); + size = backtrace (array, 15); + strings = backtrace_symbols (array, size); + fprintf(f,"%s ### Crash signal %i ###\n",dtstr, signum); + for (i = 0; i < size; i++) + fprintf (f, "%s Backtrace %i: %s\n", dtstr, i, strings[i]); + free (strings); + fclose(f); + } +} +#endif + +#ifdef SYSLOG +pthread_mutex_t _loglock = PTHREAD_MUTEX_INITIALIZER; + +UDPContext * syslog_fd = NULL; +char *_logstr = NULL; + +int syslog_init(void) +{ + struct in6_addr mcglog; + mcg_init_streaming_group (&mcglog, STREAMING_LOG); + syslog_fd = server_udp_open (&mcglog, 23000, NULL); + if(syslog_fd) { + _logstr=(char *)malloc(10240); + } + + return syslog_fd?0:-1; +} + +int syslog_write(char *s) +{ + return udp_write (syslog_fd, (uint8_t *)s, strlen(s)); +} + +void syslog_exit(void) +{ + if(syslog_fd) { + udp_close(syslog_fd); + free(_logstr); + } +} +#endif diff --git a/mcast/common/.svn/text-base/tools.h.svn-base b/mcast/common/.svn/text-base/tools.h.svn-base new file mode 100644 index 0000000..bdcdf69 --- /dev/null +++ b/mcast/common/.svn/text-base/tools.h.svn-base @@ -0,0 +1,108 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#ifndef __TOOLS_H__ +#define __TOOLS_H__ + +#define PID_MASK 0x1fff +#define NOPID_MASK 0xe000 + +#define MC_PREFIX 0xff18 + +#define NO_SAT_POS 0xfff + +// value from sat_resolved +#define NOT_RESOLVED -1 // Not run through mcg_is_equivalent/satellite_resolver +#define NOT_SUPPORTED -2 // requested position not available +#define LEGACY_DISEQC -3 + + +#define COMPRESSION_ON 1 +#define COMPRESSION_OFF 0 + +struct lookup_dvb_t_fec +{ + int fec_hp; + int fec_lp; + int val; +}; + +typedef struct +{ + char *name; + int value; +} Param; + +typedef enum +{ + STREAMING_TCA = 1, + STREAMING_TRA = 2, + STREAMING_PID = 3, + STREAMING_TEN = 4, + STREAMING_LOG = 5, +} streaming_group_t; + + +// 8=max. tuner slots (some safety) +#define MAX_TUNER_CACHE 8 + +// contains parsed/cached FE params + + +struct sat_cache { + int resolved; // -1=not resolved + int num; + int component; +}; + +struct mcg_data { + struct in6_addr mcg; + fe_type_t type; + recv_sec_t sec; + int vpid; + struct dvb_frontend_parameters fep; + int satpos; + // Small temporary cache for SAT-resolution + struct sat_cache sat_cache[MAX_TUNER_CACHE]; +}; + +void print_fe_info (struct dvb_frontend_info *fe_info); +void print_mcg (struct in6_addr *mcg); +void print_frontend_settings (struct dvb_frontend_parameters *fe_parms); + +DLL_SYMBOL void fe_parms_to_mcg (struct in6_addr *mcg, streaming_group_t StreamingGroup, fe_type_t type, recv_sec_t * sec, struct dvb_frontend_parameters *fep, int vpid); +DLL_SYMBOL int mcg_to_fe_parms (struct in6_addr *mcg, fe_type_t * type, recv_sec_t * sec, struct dvb_frontend_parameters *fep, int *vpid); +DLL_SYMBOL int mcg_to_all_parms(struct in6_addr *mcg, struct mcg_data * mcd); + +DLL_SYMBOL void mcg_set_streaming_group (struct in6_addr *mcg, streaming_group_t StreamingGroup); +DLL_SYMBOL void mcg_get_streaming_group (struct in6_addr *mcg, streaming_group_t *StreamingGroup); +DLL_SYMBOL void mcg_init_streaming_group (struct in6_addr *mcg, streaming_group_t StreamingGroup); + +DLL_SYMBOL void mcg_set_pid (struct in6_addr *mcg, int pid); +DLL_SYMBOL void mcg_get_pid (struct in6_addr *mcg, int *pid); + +DLL_SYMBOL void mcg_get_priority (struct in6_addr *mcg, int *priority); +DLL_SYMBOL void mcg_set_priority (struct in6_addr *mcg, int priority); + +DLL_SYMBOL void mcg_get_satpos (struct in6_addr *mcg, int *satpos); +DLL_SYMBOL void mcg_set_satpos (struct in6_addr *mcg, int satpos); + +DLL_SYMBOL void mcg_get_id (struct in6_addr *mcg, int *id); +DLL_SYMBOL void mcg_set_id (struct in6_addr *mcg, int id); + + +int gzip (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen, int level); +int gunzip (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen); +void print_trace (void); +void SignalHandlerCrash(int signum); + +int syslog_init(void); +int syslog_write(char *s); +void syslog_exit(void); + +#endif diff --git a/mcast/common/.svn/text-base/version.h.svn-base b/mcast/common/.svn/text-base/version.h.svn-base new file mode 100644 index 0000000..e7aea47 --- /dev/null +++ b/mcast/common/.svn/text-base/version.h.svn-base @@ -0,0 +1,18 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +#ifdef P2P + #define MCLI_P2PSTR "-P2P" +#else + #define MCLI_P2PSTR "" +#endif +#define MCLI_APP_VERSION "0.99.33"MCLI_P2PSTR +#define MCLI_COMPILED __DATE__" "__TIME__ +#define MCLI_VERSION_STR MCLI_APP_VERSION" ("MCLI_COMPILED")" +#define MCLI_MAGIC 0xDEADBEEF +#define MCLI_VERSION 0x14 |