1 #define MODULE_LOG_PREFIX "relay"
5 #ifdef MODULE_STREAMRELAY
10 #include "module-streamrelay.h"
11 #include "oscam-config.h"
12 #include "oscam-net.h"
13 #include "oscam-string.h"
14 #include "oscam-time.h"
15 #include "oscam-chk.h"
17 #define STREAM_UNDEFINED 0x00
18 #define STREAM_VIDEO 0x01
19 #define STREAM_AUDIO 0x02
20 #define STREAM_SUBTITLE 0x03
21 #define STREAM_TELETEXT 0x04
23 extern int32_t exit_oscam
;
29 } stream_client_conn_data
;
31 char stream_source_host
[256];
32 char *stream_source_auth
= NULL
;
33 uint32_t cluster_size
= 50;
34 bool has_dvbcsa_ecm
= 0, is_dvbcsa_static
= 1;
36 static uint8_t stream_server_mutex_init
= 0;
37 static pthread_mutex_t stream_server_mutex
;
38 static int32_t glistenfd
, gconncount
= 0, gconnfd
[STREAM_SERVER_MAX_CONNECTIONS
];
40 static pthread_mutex_t fixed_key_srvid_mutex
;
41 static uint16_t stream_cur_srvid
[STREAM_SERVER_MAX_CONNECTIONS
];
42 static stream_client_key_data key_data
[STREAM_SERVER_MAX_CONNECTIONS
];
44 #ifdef MODULE_RADEGAST
45 static int32_t gRadegastFd
= 0;
47 static bool connect_to_radegast(void)
49 struct SOCKADDR cservaddr
;
52 gRadegastFd
= socket(DEFAULT_AF
, SOCK_STREAM
, 0);
60 int32_t flags
= fcntl(gRadegastFd
, F_GETFL
);
61 fcntl(gRadegastFd
, F_SETFL
, flags
| O_NONBLOCK
);
63 bzero(&cservaddr
, sizeof(cservaddr
));
64 SIN_GET_FAMILY(cservaddr
) = DEFAULT_AF
;
65 SIN_GET_PORT(cservaddr
) = htons(cfg
.rad_port
);
66 SIN_GET_ADDR(cservaddr
) = cfg
.rad_srvip
;
68 if (connect(gRadegastFd
, (struct sockaddr
*)&cservaddr
, sizeof(cservaddr
)) == -1)
76 static void close_radegast_connection(void)
82 static bool send_to_radegast(uint8_t* data
, int len
)
84 if (send(gRadegastFd
, data
, len
, 0) < 0)
86 cs_log("send_to_radegast: Send failure");
92 static void radegast_client_ecm(stream_client_data
*cdata
)
94 uint16_t section_length
= SCT_LEN(cdata
->ecm_data
);
95 uint8_t md5tmp
[MD5_DIGEST_LENGTH
];
96 MD5(cdata
->ecm_data
, section_length
, md5tmp
);
98 if (!memcmp(cdata
->ecm_md5
, md5tmp
, MD5_DIGEST_LENGTH
)) { return; }
99 memcpy(cdata
->ecm_md5
, md5tmp
, MD5_DIGEST_LENGTH
);
102 static uint8_t header_len
= 2;
103 static uint8_t payload_static_len
= 12;
105 if (gRadegastFd
<= 0)
106 { connect_to_radegast(); }
108 packet_len
= header_len
+ payload_static_len
+ section_length
;
109 uint8_t outgoing_data
[packet_len
];
110 outgoing_data
[0] = 1;
111 outgoing_data
[1] = payload_static_len
+ section_length
;
112 outgoing_data
[2] = 10; // caid
113 outgoing_data
[3] = 2;
114 outgoing_data
[4] = cdata
->caid
>> 8;
115 outgoing_data
[5] = cdata
->caid
& 0xFF;
116 outgoing_data
[6] = 9; // srvid
117 outgoing_data
[7] = 4;
118 outgoing_data
[8] = cdata
->srvid
& 0xFF;
119 outgoing_data
[10] = cdata
->srvid
>> 8;
120 outgoing_data
[12] = 3;
121 outgoing_data
[13] = section_length
;
123 memcpy(outgoing_data
+ header_len
+ payload_static_len
, cdata
->ecm_data
, section_length
);
125 if (!send_to_radegast(outgoing_data
, packet_len
))
127 close_radegast_connection();
128 if (connect_to_radegast())
130 send_to_radegast(outgoing_data
, packet_len
);
135 void ParseEcmData(stream_client_data
*cdata
)
137 uint8_t *data
= cdata
->ecm_data
;
138 uint16_t section_length
= SCT_LEN(data
);
140 if (section_length
< 11)
145 radegast_client_ecm(cdata
);
147 #endif // MODULE_RADEGAST
149 static void write_cw(ECM_REQUEST
*er
, int32_t connid
)
152 const uint8_t ecm
= (caid_is_videoguard(er
->caid
) && (er
->ecm
[4] != 0 && (er
->ecm
[2] - er
->ecm
[4]) == 4)) ? 4 : 0;
154 if (memcmp(er
->cw
, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0)
158 dvbcsa_bs_key_set(er
->cw
, key_data
[connid
].key
[EVEN
]);
162 if (memcmp(er
->cw
+ 8, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0)
166 dvbcsa_bs_key_set(er
->cw
+ 8, key_data
[connid
].key
[ODD
]);
171 bool stream_write_cw(ECM_REQUEST
*er
)
174 if (er
->rc
== E_FOUND
)
176 bool cw_written
= false;
177 //SAFE_MUTEX_LOCK(&fixed_key_srvid_mutex);
178 for (i
= 0; i
< STREAM_SERVER_MAX_CONNECTIONS
; i
++)
180 if (stream_cur_srvid
[i
] == er
->srvid
)
184 // don't return as there might be more connections for the same channel (e.g. recordings)
187 //SAFE_MUTEX_UNLOCK(&fixed_key_srvid_mutex);
193 static void SearchTsPackets(const uint8_t *buf
, const uint32_t bufLength
, uint16_t *packetSize
, uint16_t *startOffset
)
197 for (i
= 0; i
< bufLength
; i
++)
201 // if three packets align, probably safe to assume correct size
202 if ((buf
[i
+ 188] == 0x47) & (buf
[i
+ 376] == 0x47))
208 else if ((buf
[i
+ 204] == 0x47) & (buf
[i
+ 408] == 0x47))
214 else if ((buf
[i
+ 208] == 0x47) & (buf
[i
+ 416] == 0x47))
227 typedef void (*ts_data_callback
)(stream_client_data
*cdata
);
229 static void ParseTsData(const uint8_t table_id
, const uint8_t table_mask
, const uint8_t min_table_length
, int8_t *flag
,
230 uint8_t *data
, const uint16_t data_length
, uint16_t *data_pos
, const int8_t payloadStart
,
231 const uint8_t *buf
, const int32_t len
, ts_data_callback func
, stream_client_data
*cdata
)
235 bool found_start
= 0;
242 if (*flag
== 0 && !payloadStart
)
252 else if (payloadStart
)
257 if ((len
- offset
) < 1)
262 const int32_t free_data_length
= (data_length
- *data_pos
);
263 const int32_t copySize
= (len
- offset
) > free_data_length
? free_data_length
: (len
- offset
);
265 memcpy(data
+ *data_pos
, buf
+ offset
, copySize
);
266 *data_pos
+= copySize
;
268 for (i
= 0; i
< *data_pos
; i
++)
270 if ((data
[i
] & table_mask
) == table_id
)
274 if (*data_pos
- i
> i
)
276 memmove(data
, &data
[i
], *data_pos
- i
);
280 memcpy(data
, &data
[i
], *data_pos
- i
);
290 const uint16_t section_length
= SCT_LEN(data
);
292 if (!found_start
|| (section_length
> data_length
) || (section_length
< min_table_length
))
298 if ((*data_pos
< section_length
) || (*data_pos
< 3))
307 for (i
= section_length
; i
< *data_pos
; i
++)
309 if ((data
[i
] & table_mask
) == table_id
)
311 if (*data_pos
- i
> i
)
313 memmove(data
, &data
[i
], *data_pos
- i
);
317 memcpy(data
, &data
[i
], *data_pos
- i
);
326 if (!found_start
|| (data_length
< *data_pos
+ copySize
+ 1))
334 static void ParsePatData(stream_client_data
*cdata
)
339 cdata
->STREAMpidcount
= 0;
341 for (i
= 8; i
+ 7 < SCT_LEN(cdata
->pat_data
); i
+= 4)
343 srvid
= b2i(2, cdata
->pat_data
+ i
);
349 if (cdata
->srvid
== srvid
)
351 cdata
->pmt_pid
= b2i(2, cdata
->pat_data
+ i
+ 2) & 0x1FFF;
352 cs_log_dbg(D_READER
, "Stream client %i found pmt pid: 0x%04X (%i)",
353 cdata
->connid
, cdata
->pmt_pid
, cdata
->pmt_pid
);
359 static void ParseDescriptors(const uint8_t *buffer
, const uint16_t info_length
, uint8_t *type
)
362 uint8_t j
, descriptor_length
= 0;
369 for (i
= 0; i
+ 1 < info_length
; i
+= descriptor_length
+ 2)
371 descriptor_length
= buffer
[i
+ 1];
372 switch (buffer
[i
]) // descriptor tag
374 case 0x05: // Registration descriptor
376 // "HDMV" format identifier is removed
377 // Cam does not need to know about Blu-ray
378 const char format_identifiers_audio
[10][5] =
380 "AC-3", "BSSD", "dmat", "DRA1", "DTS1",
381 "DTS2", "DTS3", "EAC3", "mlpa", "Opus",
383 for (j
= 0; j
< 10; j
++)
385 if (memcmp(buffer
+ i
+ 2, format_identifiers_audio
[j
], 4) == 0)
387 *type
= STREAM_AUDIO
;
393 //case 0x09: // CA descriptor
397 case 0x46: // VBI teletext descriptor (DVB)
398 case 0x56: // teletext descriptor (DVB)
400 *type
= STREAM_TELETEXT
;
403 case 0x59: // subtitling descriptor (DVB)
405 *type
= STREAM_SUBTITLE
;
408 case 0x6A: // AC-3 descriptor (DVB)
409 case 0x7A: // enhanced AC-3 descriptor (DVB)
410 case 0x7B: // DTS descriptor (DVB)
411 case 0x7C: // AAC descriptor (DVB)
412 case 0x81: // AC-3 descriptor (ATSC)
413 case 0xCC: // Enhanced AC-3 descriptor (ATSC)
415 *type
= STREAM_AUDIO
;
418 case 0x7F: // extension descriptor (DVB)
420 switch(buffer
[i
+ 2]) // extension descriptor tag
422 case 0x0E: // DTS-HD descriptor (DVB)
423 case 0x0F: // DTS Neural descriptor (DVB)
424 case 0x15: // AC-4 descriptor (DVB)
425 *type
= STREAM_AUDIO
;
428 case 0x20: // TTML subtitling descriptor (DVB)
429 *type
= STREAM_SUBTITLE
;
433 *type
= STREAM_UNDEFINED
;
444 static void stream_parse_pmt_ca_descriptor(const uint8_t *data
, const int32_t data_pos
, const int32_t offset
, const uint16_t info_length
, stream_client_data
*cdata
)
451 // parse program descriptors (we are looking only for CA descriptor here)
454 uint8_t descriptor_tag
, descriptor_length
= 0;
456 for (i
= offset
; i
+ 1 < offset
+ info_length
; i
+= descriptor_length
+ 2)
458 descriptor_tag
= data
[i
+ data_pos
];
459 descriptor_length
= data
[i
+ 1 + data_pos
];
460 if (descriptor_length
< 1)
465 if (i
+ 1 + descriptor_length
>= offset
+ info_length
)
470 if (descriptor_tag
== 0x09 && descriptor_length
>= 4)
472 caid
= b2i(2, data
+ i
+ 2 + data_pos
);
473 if (chk_ctab_ex(caid
, &cfg
.stream_relay_ctab
))
475 if (cdata
->caid
== NO_CAID_VALUE
)
480 if (cdata
->caid
!= caid
)
484 cdata
->ecm_pid
= b2i(2, data
+ i
+ 4 + data_pos
) & 0x1FFF;
485 cs_log_dbg(D_READER
, "Stream client %i found ecm pid: 0x%04X (%i)",
486 cdata
->connid
, cdata
->ecm_pid
, cdata
->ecm_pid
);
492 static void ParsePmtData(stream_client_data
*cdata
)
495 uint16_t program_info_length
= 0, es_info_length
= 0, elementary_pid
;
496 const uint16_t section_length
= SCT_LEN(cdata
->pmt_data
);
500 cdata
->pcr_pid
= b2i(2, cdata
->pmt_data
+ 8) & 0x1FFF;
502 if (cdata
->pcr_pid
!= 0x1FFF)
504 cs_log_dbg(D_READER
, "Stream client %i found pcr pid: 0x%04X (%i)",
505 cdata
->connid
, cdata
->pcr_pid
, cdata
->pcr_pid
);
507 program_info_length
= b2i(2, cdata
->pmt_data
+ 10) & 0xFFF;
508 if (!program_info_length
)
511 program_info_length
= (b2i(2, cdata
->pmt_data
+ 10 + offset
) & 0xFFF);
513 if (12 + offset
+ program_info_length
>= section_length
) { return; }
514 stream_parse_pmt_ca_descriptor(cdata
->pmt_data
, 0, 12 + offset
, program_info_length
, cdata
);
516 offset
= offset
== 5 ? 0 : program_info_length
;
517 for (i
= 12 + offset
; i
+ 4 < section_length
; i
+= 5 + es_info_length
)
519 elementary_pid
= b2i(2, cdata
->pmt_data
+ i
+ 1) & 0x1FFF;
520 es_info_length
= b2i(2, cdata
->pmt_data
+ i
+ 3) & 0xFFF;
521 switch (cdata
->pmt_data
[i
]) // stream type
534 cs_log_dbg(D_READER
, "Stream client %i found video pid: 0x%04X (%i)",
535 cdata
->connid
, elementary_pid
, elementary_pid
);
536 stream_parse_pmt_ca_descriptor(cdata
->pmt_data
, i
, 5, es_info_length
, cdata
);
548 cs_log_dbg(D_READER
, "Stream client %i found audio pid: 0x%04X (%i)",
549 cdata
->connid
, elementary_pid
, elementary_pid
);
553 //case 0x81: // some ATSC AC-3 streams do not contain the AC-3 descriptor!
556 uint8_t type
= STREAM_UNDEFINED
;
557 ParseDescriptors(cdata
->pmt_data
+ i
+ 5, es_info_length
, &type
);
558 if (type
== STREAM_AUDIO
)
560 cs_log_dbg(D_READER
, "Stream client %i found audio pid: 0x%04X (%i)",
561 cdata
->connid
, elementary_pid
, elementary_pid
);
563 else if (type
== STREAM_TELETEXT
)
565 cs_log_dbg(D_READER
, "Stream client %i found teletext pid: 0x%04X (%i)",
566 cdata
->connid
, elementary_pid
, elementary_pid
);
572 cdata
->STREAMpids
[cdata
->STREAMpidcount
] = elementary_pid
;
573 cdata
->STREAMpidcount
++;
578 static void ParseTsPackets(stream_client_data
*data
, uint8_t *stream_buf
, uint32_t bufLength
, uint16_t packetSize
)
580 uint8_t payloadStart
;
581 uint16_t pid
, offset
;
582 uint32_t i
, tsHeader
;
584 for (i
= 0; i
< bufLength
; i
+= packetSize
)
586 tsHeader
= b2i(4, stream_buf
+ i
);
587 pid
= (tsHeader
& 0x1FFF00) >> 8;
588 payloadStart
= (tsHeader
& 0x400000) >> 22;
592 offset
= 4 + stream_buf
[i
+ 4] + 1;
599 if (packetSize
- offset
< 1)
604 if (pid
== 0x0000 && data
->have_pat_data
!= 1) // Search the PAT for the PMT pid
606 ParseTsData(0x00, 0xFF, 16, &data
->have_pat_data
, data
->pat_data
, sizeof(data
->pat_data
),
607 &data
->pat_data_pos
, payloadStart
, stream_buf
+ i
+ offset
, packetSize
- offset
, ParsePatData
, data
);
611 if (pid
== data
->pmt_pid
&& data
->have_pmt_data
!= 1) // Search the PMT for PCR, ECM, Video and Audio pids
613 ParseTsData(0x02, 0xFF, 21, &data
->have_pmt_data
, data
->pmt_data
, sizeof(data
->pmt_data
),
614 &data
->pmt_data_pos
, payloadStart
, stream_buf
+ i
+ offset
, packetSize
- offset
, ParsePmtData
, data
);
618 // We have bot PAT and PMT data - No need to search the rest of the packets
619 if (data
->have_pat_data
== 1 && data
->have_pmt_data
== 1)
626 static void decrypt(struct dvbcsa_bs_batch_s
*tsbbatch
, uint16_t fill
[2], const uint8_t oddeven
, const int32_t connid
)
628 if (fill
[oddeven
] > 0)
632 for(i
= fill
[oddeven
]; i
<= cluster_size
; i
++)
634 tsbbatch
[i
].data
= NULL
;
638 tsbbatch
[fill
[oddeven
]].data
= NULL
;
640 //cs_log_dbg(D_READER, "dvbcsa (%s), batch=%d", oddeven == ODD ? "odd" : "even", fill[oddeven]);
644 dvbcsa_bs_decrypt(key_data
[connid
].key
[oddeven
], tsbbatch
, 184);
647 #define decrypt(a) decrypt(tsbbatch, fill, a, data->connid)
649 static void DescrambleTsPackets(stream_client_data
*data
, uint8_t *stream_buf
, uint32_t bufLength
, uint16_t packetSize
, struct dvbcsa_bs_batch_s
*tsbbatch
)
651 uint32_t i
, tsHeader
;
652 uint16_t offset
, fill
[2] = {0,0};
654 #ifdef MODULE_RADEGAST
656 uint8_t payloadStart
;
659 for (i
= 0; i
< bufLength
; i
+= packetSize
)
661 tsHeader
= b2i(4, stream_buf
+ i
);
662 #ifdef MODULE_RADEGAST
663 pid
= (tsHeader
& 0x1FFF00) >> 8;
664 payloadStart
= (tsHeader
& 0x400000) >> 22;
666 offset
= (tsHeader
& 0x20) ? 4 + stream_buf
[i
+ 4] + 1 : 4;
667 if (packetSize
- offset
< 1)
671 #ifdef MODULE_RADEGAST
673 if(data
->ecm_pid
== 0x1FFF && caid_is_biss_fixed(data
->caid
))
676 uint16_t ecm_len
= 7;
677 data
->ecm_data
[0] = 0x80; // to pass the cache check it must be 0x80 or 0x81
678 data
->ecm_data
[1] = 0x00;
679 data
->ecm_data
[2] = 0x04;
680 i2b_buf(2, data
->srvid
, data
->ecm_data
+ 3);
681 i2b_buf(2, data
->pmt_pid
, data
->ecm_data
+ 5);
682 for(j
= 0, n
= 7; j
< data
->STREAMpidcount
; j
++, n
+= 2)
684 i2b_buf(2, data
->STREAMpids
[j
], data
->ecm_data
+ n
);
685 data
->ecm_data
[2] += 2;
688 data
->ens
&= 0x0FFFFFFF; // clear top 4 bits (in case of DVB-T/C or garbage), prepare for flagging
689 data
->ens
|= 0xA0000000; // flag to emu: this is the namespace, not a pid
690 i2b_buf(2, data
->tsid
, data
->ecm_data
+ ecm_len
); // place tsid after the last stream pid
691 i2b_buf(2, data
->onid
, data
->ecm_data
+ ecm_len
+ 2); // place onid right after tsid
692 i2b_buf(4, data
->ens
, data
->ecm_data
+ ecm_len
+ 4); // place namespace at the end of the ecm
693 data
->ecm_data
[2] += 8;
697 if (data
->ecm_pid
&& pid
== data
->ecm_pid
) // Process the ECM data
700 stream_buf
[i
+ 1] |= 0x1F;
701 stream_buf
[i
+ 2] = 0xFF;
702 ParseTsData(0x80, 0xFE, 3, &data
->have_ecm_data
, data
->ecm_data
, sizeof(data
->ecm_data
),
703 &data
->ecm_data_pos
, payloadStart
, stream_buf
+ i
+ offset
, packetSize
- offset
, ParseEcmData
, data
);
706 #endif // MODULE_RADEGAST
707 if ((tsHeader
& 0xC0) == 0)
712 stream_buf
[i
+ 3] &= 0x3f; // consider it decrypted now
713 oddeven
= (tsHeader
& 0xC0) == 0xC0 ? ODD
: EVEN
;
714 decrypt(oddeven
== ODD
? EVEN
: ODD
);
715 tsbbatch
[fill
[oddeven
]].data
= &stream_buf
[i
+ offset
];
716 tsbbatch
[fill
[oddeven
]].len
= packetSize
- offset
;
719 if (fill
[oddeven
] > cluster_size
- 1)
728 static int32_t connect_to_stream(char *http_buf
, int32_t http_buf_len
, char *stream_path
)
730 struct SOCKADDR cservaddr
;
733 int32_t streamfd
= socket(DEFAULT_AF
, SOCK_STREAM
, 0);
734 if (streamfd
== -1) { return -1; }
739 if (setsockopt(streamfd
, SOL_SOCKET
, SO_RCVTIMEO
, (char *)&tv
, sizeof tv
))
741 cs_log("ERROR: setsockopt() failed for SO_RCVTIMEO");
745 bzero(&cservaddr
, sizeof(cservaddr
));
746 SIN_GET_FAMILY(cservaddr
) = DEFAULT_AF
;
747 SIN_GET_PORT(cservaddr
) = htons(cfg
.stream_source_port
);
748 cs_resolve(stream_source_host
, &in_addr
, NULL
, NULL
);
749 SIN_GET_ADDR(cservaddr
) = in_addr
;
751 if (connect(streamfd
, (struct sockaddr
*)&cservaddr
, sizeof(cservaddr
)) == -1)
753 cs_log("WARNING: Connect to stream source port %d failed", cfg
.stream_source_port
);
757 if (stream_source_auth
)
759 snprintf(http_buf
, http_buf_len
, "GET %s HTTP/1.1\nHost: %s:%u\n"
760 "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n"
761 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
762 "Accept-Language: en-US\n"
763 "Authorization: Basic %s\n"
764 "Connection: keep-alive\n\n", stream_path
, stream_source_host
, cfg
.stream_source_port
, stream_source_auth
);
768 snprintf(http_buf
, http_buf_len
, "GET %s HTTP/1.1\nHost: %s:%u\n"
769 "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n"
770 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
771 "Accept-Language: en-US\n"
772 "Connection: keep-alive\n\n", stream_path
, stream_source_host
, cfg
.stream_source_port
);
775 if (send(streamfd
, http_buf
, cs_strlen(http_buf
), 0) == -1) { return -1; }
779 static void stream_client_disconnect(stream_client_conn_data
*conndata
)
783 SAFE_MUTEX_LOCK(&fixed_key_srvid_mutex
);
784 stream_cur_srvid
[conndata
->connid
] = NO_SRVID_VALUE
;
785 SAFE_MUTEX_UNLOCK(&fixed_key_srvid_mutex
);
787 SAFE_MUTEX_LOCK(&stream_server_mutex
);
788 for (i
= 0; i
< STREAM_SERVER_MAX_CONNECTIONS
; i
++)
790 if (gconnfd
[i
] == conndata
->connfd
)
796 SAFE_MUTEX_UNLOCK(&stream_server_mutex
);
798 shutdown(conndata
->connfd
, 2);
799 close(conndata
->connfd
);
801 cs_log("Stream client %i disconnected",conndata
->connid
);
806 static void *stream_client_handler(void *arg
)
808 stream_client_conn_data
*conndata
= (stream_client_conn_data
*)arg
;
809 stream_client_data
*data
;
811 char *http_buf
, stream_path
[255], stream_path_copy
[255];
812 char *saveptr
, *token
, http_version
[4];
814 int8_t streamConnectErrorCount
= 0, streamDataErrorCount
= 0;
815 int32_t bytesRead
= 0, http_status_code
= 0;
816 int32_t i
, clientStatus
, streamStatus
, streamfd
;
819 uint16_t packetCount
= 0, packetSize
= 0, startOffset
= 0;
820 uint32_t remainingDataPos
, remainingDataLength
, tmp_pids
[4];
821 uint8_t descrambling
= 0;
823 const int32_t cur_dvb_buffer_size
= DVB_BUFFER_SIZE_CSA
;
824 const int32_t cur_dvb_buffer_wait
= DVB_BUFFER_WAIT_CSA
;
826 struct dvbcsa_bs_batch_s
*tsbbatch
;
828 cs_log("Stream client %i connected", conndata
->connid
);
830 if (!cs_malloc(&http_buf
, 1024))
832 stream_client_disconnect(conndata
);
836 if (!cs_malloc(&stream_buf
, DVB_BUFFER_SIZE
))
839 stream_client_disconnect(conndata
);
843 if (!cs_malloc(&data
, sizeof(stream_client_data
)))
846 NULLFREE(stream_buf
);
847 stream_client_disconnect(conndata
);
851 clientStatus
= recv(conndata
->connfd
, http_buf
, 1024, 0);
852 if (clientStatus
< 1)
855 NULLFREE(stream_buf
);
857 stream_client_disconnect(conndata
);
861 http_buf
[1023] = '\0';
862 if (sscanf(http_buf
, "GET %254s ", stream_path
) < 1)
865 NULLFREE(stream_buf
);
867 stream_client_disconnect(conndata
);
871 cs_strncpy(stream_path_copy
, stream_path
, sizeof(stream_path
));
873 token
= strtok_r(stream_path_copy
, ":", &saveptr
); // token 0
874 for (i
= 1; token
!= NULL
&& i
< 7; i
++) // tokens 1 to 6
876 token
= strtok_r(NULL
, ":", &saveptr
);
882 if (i
>= 3) // We olny need token 3 (srvid), 4 (tsid), 5 (onid) and 6 (ens)
884 if (sscanf(token
, "%x", &tmp_pids
[i
- 3]) != 1)
891 data
->srvid
= tmp_pids
[0] & 0xFFFF;
892 data
->tsid
= tmp_pids
[1] & 0xFFFF;
893 data
->onid
= tmp_pids
[2] & 0xFFFF;
894 data
->ens
= tmp_pids
[3];
896 if (data
->srvid
== 0) // We didn't get a srvid - Exit
899 NULLFREE(stream_buf
);
901 stream_client_disconnect(conndata
);
905 key_data
[conndata
->connid
].key
[ODD
] = dvbcsa_bs_key_alloc();
906 key_data
[conndata
->connid
].key
[EVEN
] = dvbcsa_bs_key_alloc();
908 if (!cs_malloc(&tsbbatch
, (cluster_size
+ 1) * sizeof(struct dvbcsa_bs_batch_s
)))
911 NULLFREE(stream_buf
);
913 stream_client_disconnect(conndata
);
917 SAFE_MUTEX_LOCK(&fixed_key_srvid_mutex
);
918 stream_cur_srvid
[conndata
->connid
] = data
->srvid
;
919 SAFE_MUTEX_UNLOCK(&fixed_key_srvid_mutex
);
921 cs_log("Stream client %i request %s", conndata
->connid
, stream_path
);
923 cs_log_dbg(D_READER
, "Stream client %i received srvid: %04X tsid: %04X onid: %04X ens: %08X",
924 conndata
->connid
, data
->srvid
, data
->tsid
, data
->onid
, data
->ens
);
926 snprintf(http_buf
, 1024, "HTTP/1.0 200 OK\nConnection: Close\nContent-Type: video/mpeg\nServer: stream_enigma2\n\n");
927 clientStatus
= send(conndata
->connfd
, http_buf
, cs_strlen(http_buf
), 0);
929 data
->connid
= conndata
->connid
;
930 data
->caid
= NO_CAID_VALUE
;
931 data
->have_pat_data
= 0;
932 data
->have_pmt_data
= 0;
933 data
->have_cat_data
= 0;
934 data
->have_ecm_data
= 0;
935 data
->have_emm_data
= 0;
937 while (!exit_oscam
&& clientStatus
!= -1 && streamConnectErrorCount
< 3
938 && streamDataErrorCount
< 15)
940 streamfd
= connect_to_stream(http_buf
, 1024, stream_path
);
943 cs_log("WARNING: stream client %i cannot connect to stream source", conndata
->connid
);
944 streamConnectErrorCount
++;
950 while (!exit_oscam
&& clientStatus
!= -1 && streamStatus
!= -1
952 && streamConnectErrorCount
< 3 && streamDataErrorCount
< 15)
954 && (streamConnectErrorCount
< 3 || streamDataErrorCount
< 15))
957 streamStatus
= recv(streamfd
, stream_buf
+ bytesRead
, cur_dvb_buffer_size
- bytesRead
, MSG_WAITALL
);
958 if (streamStatus
== 0) // socket closed
960 cs_log("WARNING: stream client %i - stream source closed connection", conndata
->connid
);
961 streamConnectErrorCount
++;
965 if (streamStatus
< 0) // error
967 if ((errno
== EWOULDBLOCK
) | (errno
== EAGAIN
))
969 cs_log("WARNING: stream client %i no data from stream source", conndata
->connid
);
970 streamDataErrorCount
++; // 2 sec timeout * 15 = 30 seconds no data -> close
974 cs_log("WARNING: stream client %i error receiving data from stream source", conndata
->connid
);
975 streamConnectErrorCount
++;
979 if (streamStatus
< cur_dvb_buffer_size
- bytesRead
) // probably just received header but no stream
981 if (!bytesRead
&& streamStatus
> 13 &&
982 sscanf((const char*)stream_buf
, "HTTP/%3s %d ", http_version
, &http_status_code
) == 2 &&
983 http_status_code
!= 200)
985 cs_log("ERROR: stream client %i got %d response from stream source", conndata
->connid
, http_status_code
);
986 streamConnectErrorCount
++;
992 cs_log_dbg(0, "WARNING: stream client %i non-full buffer from stream source", conndata
->connid
);
993 streamDataErrorCount
++;
999 streamDataErrorCount
= 0;
1002 streamConnectErrorCount
= 0;
1003 bytesRead
+= streamStatus
;
1005 if (bytesRead
>= cur_dvb_buffer_wait
)
1009 // only search if not starting on ts packet or unknown packet size
1010 if (stream_buf
[0] != 0x47 || packetSize
== 0)
1012 SearchTsPackets(stream_buf
, bytesRead
, &packetSize
, &startOffset
);
1015 if (packetSize
== 0)
1021 packetCount
= ((bytesRead
- startOffset
) / packetSize
);
1023 // We have both PAT and PMT data - We can start descrambling
1024 if (data
->have_pat_data
== 1 && data
->have_pmt_data
== 1)
1026 if (chk_ctab_ex(data
->caid
, &cfg
.stream_relay_ctab
) && (data
->caid
!= 0xA101 || data
->caid
== NO_CAID_VALUE
))
1028 DescrambleTsPackets(data
, stream_buf
+ startOffset
, packetCount
* packetSize
, packetSize
, tsbbatch
);
1029 if (!descrambling
&& cfg
.stream_relay_buffer_time
) {
1030 cs_sleepms(cfg
.stream_relay_buffer_time
);
1036 cs_log_dbg(D_READER
, "Stream client %i caid %04X not enabled in stream relay config",
1037 conndata
->connid
, data
->caid
);
1040 else // Search PAT and PMT packets for service information
1042 ParseTsPackets(data
, stream_buf
+ startOffset
, packetCount
* packetSize
, packetSize
);
1045 clientStatus
= send(conndata
->connfd
, stream_buf
+ startOffset
, packetCount
* packetSize
, 0);
1047 remainingDataPos
= startOffset
+ (packetCount
* packetSize
);
1048 remainingDataLength
= bytesRead
- remainingDataPos
;
1050 if (remainingDataPos
< remainingDataLength
)
1052 memmove(stream_buf
, stream_buf
+ remainingDataPos
, remainingDataLength
);
1056 memcpy(stream_buf
, stream_buf
+ remainingDataPos
, remainingDataLength
);
1059 bytesRead
= remainingDataLength
;
1068 NULLFREE(stream_buf
);
1070 dvbcsa_bs_key_free(key_data
[conndata
->connid
].key
[ODD
]);
1071 dvbcsa_bs_key_free(key_data
[conndata
->connid
].key
[EVEN
]);
1076 stream_client_disconnect(conndata
);
1080 void *stream_server(void *UNUSED(a
))
1083 struct sockaddr_in6 servaddr
, cliaddr
;
1085 struct sockaddr_in servaddr
, cliaddr
;
1088 int32_t connfd
, reuse
= 1, i
;
1089 int8_t connaccepted
;
1090 stream_client_conn_data
*conndata
;
1092 cluster_size
= dvbcsa_bs_batch_size();
1093 has_dvbcsa_ecm
= (DVBCSA_HEADER_ECM
);
1096 #pragma message "WARNING: Streamrelay is compiled without dvbcsa ecm headers! ECM processing via Streamrelay will not work!"
1098 #if !STATIC_LIBDVBCSA
1099 has_dvbcsa_ecm
= (dlsym(RTLD_DEFAULT
, "dvbcsa_bs_key_set_ecm"));
1100 is_dvbcsa_static
= 0;
1103 cs_log("%s: (%s) %s dvbcsa parallel mode = %d (relay buffer time: %d ms)%s%s",
1104 (!DVBCSA_HEADER_ECM
|| !has_dvbcsa_ecm
) ? "WARNING" : "INFO",
1105 (!has_dvbcsa_ecm
) ? "wrong" : "ecm",
1106 (!is_dvbcsa_static
) ? "dynamic" : "static",
1108 cfg
.stream_relay_buffer_time
,
1109 (!DVBCSA_HEADER_ECM
|| !has_dvbcsa_ecm
) ? "! ECM processing via Streamrelay does not work!" : "",
1110 (!DVBCSA_HEADER_ECM
) ? " Missing dvbcsa ecm headers during build!" : "");
1112 if (!stream_server_mutex_init
)
1114 SAFE_MUTEX_INIT(&stream_server_mutex
, NULL
);
1115 stream_server_mutex_init
= 1;
1118 SAFE_MUTEX_LOCK(&fixed_key_srvid_mutex
);
1119 for (i
= 0; i
< STREAM_SERVER_MAX_CONNECTIONS
; i
++)
1121 stream_cur_srvid
[i
] = NO_SRVID_VALUE
;
1123 SAFE_MUTEX_UNLOCK(&fixed_key_srvid_mutex
);
1125 for (i
= 0; i
< STREAM_SERVER_MAX_CONNECTIONS
; i
++)
1130 glistenfd
= socket(AF_INET6
, SOCK_STREAM
, 0);
1131 if (glistenfd
== -1)
1133 cs_log("ERROR: cannot create stream server socket");
1137 bzero(&servaddr
,sizeof(servaddr
));
1138 servaddr
.sin6_family
= AF_INET6
;
1139 servaddr
.sin6_addr
= in6addr_any
;
1140 servaddr
.sin6_port
= htons(cfg
.stream_relay_port
);
1142 glistenfd
= socket(AF_INET
, SOCK_STREAM
, 0);
1143 if (glistenfd
== -1)
1145 cs_log("ERROR: cannot create stream server socket");
1149 bzero(&servaddr
,sizeof(servaddr
));
1150 servaddr
.sin_family
= AF_INET
;
1151 servaddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
1152 servaddr
.sin_port
= htons(cfg
.stream_relay_port
);
1154 setsockopt(glistenfd
, SOL_SOCKET
, SO_REUSEADDR
, &reuse
, sizeof(reuse
));
1156 if (bind(glistenfd
,(struct sockaddr
*)&servaddr
, sizeof(servaddr
)) == -1)
1158 cs_log("ERROR: cannot bind to stream server socket");
1163 if (listen(glistenfd
, 3) == -1)
1165 cs_log("ERROR: cannot listen to stream server socket");
1172 clilen
= sizeof(cliaddr
);
1173 connfd
= accept(glistenfd
,(struct sockaddr
*)&cliaddr
, &clilen
);
1177 cs_log("ERROR: accept() failed");
1183 #ifdef MODULE_RADEGAST
1184 if(cfg
.stream_client_source_host
)
1187 // Read ip of client who wants to play the stream
1188 unsigned char *ip
= (unsigned char *)&cliaddr
.sin6_addr
;
1189 cs_log("Stream Client ip is: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x, will fetch stream there\n", ip
[0], ip
[1], ip
[2], ip
[3], ip
[4], ip
[5], ip
[6], ip
[7], ip
[8], ip
[9], ip
[10], ip
[11], ip
[12], ip
[13], ip
[14], ip
[15]);
1191 // Store ip of client in stream_source_host variable
1192 snprintf(stream_source_host
, sizeof(stream_source_host
), "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", ip
[0], ip
[1], ip
[2], ip
[3], ip
[4], ip
[5], ip
[6], ip
[7], ip
[8], ip
[9], ip
[10], ip
[11], ip
[12], ip
[13], ip
[14], ip
[15]);
1194 // Read ip of client who wants to play the stream
1195 unsigned char *ip
= (unsigned char *)&cliaddr
.sin_addr
.s_addr
;
1196 cs_log("Stream Client ip is: %d.%d.%d.%d, will fetch stream there\n", ip
[0], ip
[1], ip
[2], ip
[3]);
1198 // Store ip of client in stream_source_host variable
1199 snprintf(stream_source_host
, sizeof(stream_source_host
), "%d.%d.%d.%d", ip
[0], ip
[1], ip
[2], ip
[3]);
1204 if (cs_malloc(&conndata
, sizeof(stream_client_conn_data
)))
1206 SAFE_MUTEX_LOCK(&stream_server_mutex
);
1207 if (gconncount
< STREAM_SERVER_MAX_CONNECTIONS
)
1209 for (i
= 0; i
< STREAM_SERVER_MAX_CONNECTIONS
; i
++)
1211 if (gconnfd
[i
] == -1)
1213 gconnfd
[i
] = connfd
;
1217 conndata
->connfd
= connfd
;
1218 conndata
->connid
= i
;
1224 SAFE_MUTEX_UNLOCK(&stream_server_mutex
);
1230 if (setsockopt(connfd
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1232 cs_log("ERROR: stream client %i setsockopt() failed for TCP_NODELAY", conndata
->connid
);
1235 start_thread("stream client", stream_client_handler
, (void*)conndata
, NULL
, 1, 0);
1239 shutdown(connfd
, 2);
1241 cs_log("ERROR: stream server client dropped because of too many connections (%i)", STREAM_SERVER_MAX_CONNECTIONS
);
1252 void init_stream_server(void)
1256 if (cfg
.stream_relay_enabled
)
1259 cs_strncpy(stream_source_host
, cfg
.stream_source_host
, sizeof(stream_source_host
));
1261 if (cfg
.stream_source_auth_user
&& cfg
.stream_source_auth_password
)
1263 snprintf(authtmp
, sizeof(authtmp
), "%s:%s", cfg
.stream_source_auth_user
, cfg
.stream_source_auth_password
);
1264 b64encode(authtmp
, cs_strlen(authtmp
), &stream_source_auth
);
1267 start_thread("stream_server", stream_server
, NULL
, NULL
, 1, 1);
1268 cs_log("Stream Relay server initialized");
1272 void stop_stream_server(void)
1276 SAFE_MUTEX_LOCK(&stream_server_mutex
);
1277 for (i
= 0; i
< STREAM_SERVER_MAX_CONNECTIONS
; i
++)
1279 if (gconnfd
[i
] != -1)
1281 shutdown(gconnfd
[i
], 2);
1288 SAFE_MUTEX_UNLOCK(&stream_server_mutex
);
1290 #ifdef MODULE_RADEGAST
1291 close_radegast_connection();
1294 shutdown(glistenfd
, 2);
1298 #endif // MODULE_STREAMRELAY