added Streamrelay libdvbcsa - thanks to lpm11 <lpm11@lpm11>, fegol, icb, loka, kitte8...
[oscam.git] / module-streamrelay.c
blob80b10d40230fbe1903d0154a5bd1ad256becfa11
1 #define MODULE_LOG_PREFIX "relay"
3 #include "globals.h"
5 #ifdef MODULE_STREAMRELAY
7 #include "module-streamrelay.h"
8 #include "oscam-config.h"
9 #include "oscam-net.h"
10 #include "oscam-string.h"
11 #include "oscam-time.h"
12 #include "oscam-chk.h"
14 #define STREAM_UNDEFINED 0x00
15 #define STREAM_VIDEO 0x01
16 #define STREAM_AUDIO 0x02
17 #define STREAM_SUBTITLE 0x03
18 #define STREAM_TELETEXT 0x04
20 extern int32_t exit_oscam;
22 typedef struct
24 int32_t connfd;
25 int32_t connid;
26 } stream_client_conn_data;
28 char stream_source_host[256];
29 char *stream_source_auth = NULL;
30 uint32_t cluster_size = 50;
32 static uint8_t stream_server_mutex_init = 0;
33 static pthread_mutex_t stream_server_mutex;
34 static int32_t glistenfd, gconncount = 0, gconnfd[STREAM_SERVER_MAX_CONNECTIONS];
36 static pthread_mutex_t fixed_key_srvid_mutex;
37 static uint16_t stream_cur_srvid[STREAM_SERVER_MAX_CONNECTIONS];
38 static stream_client_key_data key_data[STREAM_SERVER_MAX_CONNECTIONS];
40 #ifdef MODULE_RADEGAST
41 static int32_t gRadegastFd = 0;
43 static bool connect_to_radegast(void)
45 struct SOCKADDR cservaddr;
47 if (gRadegastFd == 0)
48 gRadegastFd = socket(DEFAULT_AF, SOCK_STREAM, 0);
50 if (gRadegastFd < 0)
52 gRadegastFd = 0;
53 return false;
56 int32_t flags = fcntl(gRadegastFd, F_GETFL);
57 fcntl(gRadegastFd, F_SETFL, flags | O_NONBLOCK);
59 bzero(&cservaddr, sizeof(cservaddr));
60 SIN_GET_FAMILY(cservaddr) = DEFAULT_AF;
61 SIN_GET_PORT(cservaddr) = htons(cfg.rad_port);
62 SIN_GET_ADDR(cservaddr) = cfg.rad_srvip;
64 if (connect(gRadegastFd, (struct sockaddr *)&cservaddr, sizeof(cservaddr)) == -1)
66 return false;
69 return true;
72 static void close_radegast_connection(void)
74 close(gRadegastFd);
75 gRadegastFd = 0;
78 static bool send_to_radegast(uint8_t* data, int len)
80 if (send(gRadegastFd, data, len, 0) < 0)
82 cs_log("send_to_radegast: Send failure");
83 return false;
85 return true;
88 static void radegast_client_ecm(stream_client_data *cdata)
90 uint16_t section_length = SCT_LEN(cdata->ecm_data);
91 uint8_t md5tmp[MD5_DIGEST_LENGTH];
92 MD5(cdata->ecm_data, section_length, md5tmp);
94 if (!memcmp(cdata->ecm_md5, md5tmp, MD5_DIGEST_LENGTH)) { return; }
95 memcpy(cdata->ecm_md5, md5tmp, MD5_DIGEST_LENGTH);
97 uint16_t packet_len;
98 static uint8_t header_len = 2;
99 static uint8_t payload_static_len = 12;
101 if (gRadegastFd <= 0)
102 { connect_to_radegast(); }
104 packet_len = header_len + payload_static_len + section_length;
105 uint8_t outgoing_data[packet_len];
106 outgoing_data[0] = 1;
107 outgoing_data[1] = payload_static_len + section_length;
108 outgoing_data[2] = 10; // caid
109 outgoing_data[3] = 2;
110 outgoing_data[4] = cdata->caid >> 8;
111 outgoing_data[5] = cdata->caid & 0xFF;
112 outgoing_data[6] = 9; // srvid
113 outgoing_data[7] = 4;
114 outgoing_data[8] = cdata->srvid & 0xFF;
115 outgoing_data[10] = cdata->srvid >> 8;
116 outgoing_data[12] = 3;
117 outgoing_data[13] = section_length;
119 memcpy(outgoing_data + header_len + payload_static_len, cdata->ecm_data, section_length);
121 if (!send_to_radegast(outgoing_data, packet_len))
123 close_radegast_connection();
124 if (connect_to_radegast())
126 send_to_radegast(outgoing_data, packet_len);
131 void ParseEcmData(stream_client_data *cdata)
133 uint8_t *data = cdata->ecm_data;
134 uint16_t section_length = SCT_LEN(data);
136 if (section_length < 11)
138 return;
141 radegast_client_ecm(cdata);
143 #endif // MODULE_RADEGAST
145 static void write_cw(ECM_REQUEST *er, int32_t connid)
147 const uint8_t ecm = (caid_is_videoguard(er->caid) && (er->ecm[4] != 0 && (er->ecm[2] - er->ecm[4]) == 4)) ? er->ecm[21] : 0;
148 if (memcmp(er->cw, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0)
150 dvbcsa_bs_key_set(er->cw, key_data[connid].key[EVEN]);
153 if (memcmp(er->cw + 8, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0)
155 dvbcsa_bs_key_set(er->cw + 8, key_data[connid].key[ODD]);
159 bool stream_write_cw(ECM_REQUEST *er)
161 int32_t i;
162 if (er->rc == E_FOUND)
164 bool cw_written = false;
165 //SAFE_MUTEX_LOCK(&fixed_key_srvid_mutex);
166 for (i = 0; i < STREAM_SERVER_MAX_CONNECTIONS; i++)
168 if (stream_cur_srvid[i] == er->srvid)
170 write_cw(er, i);
171 cw_written = true;
172 // don't return as there might be more connections for the same channel (e.g. recordings)
175 //SAFE_MUTEX_UNLOCK(&fixed_key_srvid_mutex);
176 return cw_written;
178 return true;
181 static void SearchTsPackets(const uint8_t *buf, const uint32_t bufLength, uint16_t *packetSize, uint16_t *startOffset)
183 uint32_t i;
185 for (i = 0; i < bufLength; i++)
187 if (buf[i] == 0x47)
189 // if three packets align, probably safe to assume correct size
190 if ((buf[i + 188] == 0x47) & (buf[i + 376] == 0x47))
192 (*packetSize) = 188;
193 (*startOffset) = i;
194 return;
196 else if ((buf[i + 204] == 0x47) & (buf[i + 408] == 0x47))
198 (*packetSize) = 204;
199 (*startOffset) = i;
200 return;
202 else if ((buf[i + 208] == 0x47) & (buf[i + 416] == 0x47))
204 (*packetSize) = 208;
205 (*startOffset) = i;
206 return;
211 (*packetSize) = 0;
212 (*startOffset) = 0;
215 typedef void (*ts_data_callback)(stream_client_data *cdata);
217 static void ParseTsData(const uint8_t table_id, const uint8_t table_mask, const uint8_t min_table_length, int8_t *flag,
218 uint8_t *data, const uint16_t data_length, uint16_t *data_pos, const int8_t payloadStart,
219 const uint8_t *buf, const int32_t len, ts_data_callback func, stream_client_data *cdata)
221 int32_t i;
222 uint16_t offset = 0;
223 bool found_start = 0;
225 if (len < 1)
227 return;
230 if (*flag == 0 && !payloadStart)
232 return;
235 if (*flag == 0)
237 *data_pos = 0;
238 offset = 1 + buf[0];
240 else if (payloadStart)
242 offset = 1;
245 if ((len - offset) < 1)
247 return;
250 const int32_t free_data_length = (data_length - *data_pos);
251 const int32_t copySize = (len - offset) > free_data_length ? free_data_length : (len - offset);
253 memcpy(data + *data_pos, buf + offset, copySize);
254 *data_pos += copySize;
256 for (i = 0; i < *data_pos; i++)
258 if ((data[i] & table_mask) == table_id)
260 if (i != 0)
262 if (*data_pos - i > i)
264 memmove(data, &data[i], *data_pos - i);
266 else
268 memcpy(data, &data[i], *data_pos - i);
271 *data_pos -= i;
273 found_start = 1;
274 break;
278 const uint16_t section_length = SCT_LEN(data);
280 if (!found_start || (section_length > data_length) || (section_length < min_table_length))
282 *flag = 0;
283 return;
286 if ((*data_pos < section_length) || (*data_pos < 3))
288 *flag = 2;
289 return;
292 func(cdata);
294 found_start = 0;
295 for (i = section_length; i < *data_pos; i++)
297 if ((data[i] & table_mask) == table_id)
299 if (*data_pos - i > i)
301 memmove(data, &data[i], *data_pos - i);
303 else
305 memcpy(data, &data[i], *data_pos - i);
308 *data_pos -= i;
309 found_start = 1;
310 break;
314 if (!found_start || (data_length < *data_pos + copySize + 1))
316 *data_pos = 0;
319 *flag = 1;
322 static void ParsePatData(stream_client_data *cdata)
324 int32_t i;
325 uint16_t srvid;
326 #ifdef __BISS__
327 cdata->STREAMpidcount = 0;
328 #endif
329 for (i = 8; i + 7 < SCT_LEN(cdata->pat_data); i += 4)
331 srvid = b2i(2, cdata->pat_data + i);
332 if (srvid == 0)
334 continue;
337 if (cdata->srvid == srvid)
339 cdata->pmt_pid = b2i(2, cdata->pat_data + i + 2) & 0x1FFF;
340 cs_log_dbg(D_READER, "Stream client %i found pmt pid: 0x%04X (%i)",
341 cdata->connid, cdata->pmt_pid, cdata->pmt_pid);
342 break;
347 static void ParseDescriptors(const uint8_t *buffer, const uint16_t info_length, uint8_t *type)
349 uint32_t i;
350 uint8_t j, descriptor_length = 0;
352 if (info_length < 1)
354 return;
357 for (i = 0; i + 1 < info_length; i += descriptor_length + 2)
359 descriptor_length = buffer[i + 1];
360 switch (buffer[i]) // descriptor tag
362 case 0x05: // Registration descriptor
364 // "HDMV" format identifier is removed
365 // Cam does not need to know about Blu-ray
366 const char format_identifiers_audio[10][5] =
368 "AC-3", "BSSD", "dmat", "DRA1", "DTS1",
369 "DTS2", "DTS3", "EAC3", "mlpa", "Opus",
371 for (j = 0; j < 10; j++)
373 if (memcmp(buffer + i + 2, format_identifiers_audio[j], 4) == 0)
375 *type = STREAM_AUDIO;
376 break;
379 break;
381 //case 0x09: // CA descriptor
383 // break;
385 case 0x46: // VBI teletext descriptor (DVB)
386 case 0x56: // teletext descriptor (DVB)
388 *type = STREAM_TELETEXT;
389 break;
391 case 0x59: // subtitling descriptor (DVB)
393 *type = STREAM_SUBTITLE;
394 break;
396 case 0x6A: // AC-3 descriptor (DVB)
397 case 0x7A: // enhanced AC-3 descriptor (DVB)
398 case 0x7B: // DTS descriptor (DVB)
399 case 0x7C: // AAC descriptor (DVB)
400 case 0x81: // AC-3 descriptor (ATSC)
401 case 0xCC: // Enhanced AC-3 descriptor (ATSC)
403 *type = STREAM_AUDIO;
404 break;
406 case 0x7F: // extension descriptor (DVB)
408 switch(buffer[i + 2]) // extension descriptor tag
410 case 0x0E: // DTS-HD descriptor (DVB)
411 case 0x0F: // DTS Neural descriptor (DVB)
412 case 0x15: // AC-4 descriptor (DVB)
413 *type = STREAM_AUDIO;
414 break;
416 case 0x20: // TTML subtitling descriptor (DVB)
417 *type = STREAM_SUBTITLE;
418 break;
420 default:
421 *type = STREAM_UNDEFINED;
422 break;
424 break;
426 default:
427 break;
432 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)
434 if (cdata->ecm_pid)
436 return;
439 // parse program descriptors (we are looking only for CA descriptor here)
440 int32_t i;
441 uint16_t caid;
442 uint8_t descriptor_tag, descriptor_length = 0;
444 for (i = offset; i + 1 < offset + info_length; i += descriptor_length + 2)
446 descriptor_tag = data[i + data_pos];
447 descriptor_length = data[i + 1 + data_pos];
448 if (descriptor_length < 1)
450 break;
453 if (i + 1 + descriptor_length >= offset + info_length)
455 break;
458 if (descriptor_tag == 0x09 && descriptor_length >= 4)
460 caid = b2i(2, data + i + 2 + data_pos);
461 if (chk_ctab_ex(caid, &cfg.stream_relay_ctab))
463 if (cdata->caid == NO_CAID_VALUE)
465 cdata->caid = caid;
468 if (cdata->caid != caid)
470 continue;
472 cdata->ecm_pid = b2i(2, data + i + 4 + data_pos) & 0x1FFF;
473 cs_log_dbg(D_READER, "Stream client %i found ecm pid: 0x%04X (%i)",
474 cdata->connid, cdata->ecm_pid, cdata->ecm_pid);
480 static void ParsePmtData(stream_client_data *cdata)
482 int32_t i;
483 uint16_t program_info_length = 0, es_info_length = 0, elementary_pid;
484 const uint16_t section_length = SCT_LEN(cdata->pmt_data);
485 uint8_t offset = 0;
487 cdata->ecm_pid = 0;
488 cdata->pcr_pid = b2i(2, cdata->pmt_data + 8) & 0x1FFF;
490 if (cdata->pcr_pid != 0x1FFF)
492 cs_log_dbg(D_READER, "Stream client %i found pcr pid: 0x%04X (%i)",
493 cdata->connid, cdata->pcr_pid, cdata->pcr_pid);
495 program_info_length = b2i(2, cdata->pmt_data + 10) & 0xFFF;
496 if (!program_info_length)
498 offset = 5;
499 program_info_length = (b2i(2, cdata->pmt_data + 10 + offset) & 0xFFF);
501 if (12 + offset + program_info_length >= section_length) { return; }
502 stream_parse_pmt_ca_descriptor(cdata->pmt_data, 0, 12 + offset, program_info_length, cdata);
504 offset = offset == 5 ? 0 : program_info_length;
505 for (i = 12 + offset; i + 4 < section_length; i += 5 + es_info_length)
507 elementary_pid = b2i(2, cdata->pmt_data + i + 1) & 0x1FFF;
508 es_info_length = b2i(2, cdata->pmt_data + i + 3) & 0xFFF;
509 switch (cdata->pmt_data[i]) // stream type
511 case 0x01:
512 case 0x02:
513 case 0x10:
514 case 0x1B:
515 case 0x20:
516 case 0x24:
517 case 0x25:
518 case 0x42:
519 case 0xD1:
520 case 0xEA:
522 cs_log_dbg(D_READER, "Stream client %i found video pid: 0x%04X (%i)",
523 cdata->connid, elementary_pid, elementary_pid);
524 stream_parse_pmt_ca_descriptor(cdata->pmt_data, i, 5, es_info_length, cdata);
525 break;
527 case 0x03:
528 case 0x04:
529 case 0x0F:
530 case 0x11:
531 case 0x1C:
532 case 0x2D:
533 case 0x2E:
534 case 0x81:
536 cs_log_dbg(D_READER, "Stream client %i found audio pid: 0x%04X (%i)",
537 cdata->connid, elementary_pid, elementary_pid);
538 break;
540 case 0x06:
541 //case 0x81: // some ATSC AC-3 streams do not contain the AC-3 descriptor!
542 case 0x87:
544 uint8_t type = STREAM_UNDEFINED;
545 ParseDescriptors(cdata->pmt_data + i + 5, es_info_length, &type);
546 if (type == STREAM_AUDIO)
548 cs_log_dbg(D_READER, "Stream client %i found audio pid: 0x%04X (%i)",
549 cdata->connid, elementary_pid, elementary_pid);
551 else if (type == STREAM_TELETEXT)
553 cs_log_dbg(D_READER, "Stream client %i found teletext pid: 0x%04X (%i)",
554 cdata->connid, elementary_pid, elementary_pid);
556 break;
559 #ifdef __BISS__
560 cdata->STREAMpids[cdata->STREAMpidcount] = elementary_pid;
561 cdata->STREAMpidcount++;
562 #endif
566 static void ParseTsPackets(stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
568 uint8_t payloadStart;
569 uint16_t pid, offset;
570 uint32_t i, tsHeader;
572 for (i = 0; i < bufLength; i += packetSize)
574 tsHeader = b2i(4, stream_buf + i);
575 pid = (tsHeader & 0x1FFF00) >> 8;
576 payloadStart = (tsHeader & 0x400000) >> 22;
578 if (tsHeader & 0x20)
580 offset = 4 + stream_buf[i + 4] + 1;
582 else
584 offset = 4;
587 if (packetSize - offset < 1)
589 continue;
592 if (pid == 0x0000 && data->have_pat_data != 1) // Search the PAT for the PMT pid
594 ParseTsData(0x00, 0xFF, 16, &data->have_pat_data, data->pat_data, sizeof(data->pat_data),
595 &data->pat_data_pos, payloadStart, stream_buf + i + offset, packetSize - offset, ParsePatData, data);
596 continue;
599 if (pid == data->pmt_pid && data->have_pmt_data != 1) // Search the PMT for PCR, ECM, Video and Audio pids
601 ParseTsData(0x02, 0xFF, 21, &data->have_pmt_data, data->pmt_data, sizeof(data->pmt_data),
602 &data->pmt_data_pos, payloadStart, stream_buf + i + offset, packetSize - offset, ParsePmtData, data);
603 continue;
606 // We have bot PAT and PMT data - No need to search the rest of the packets
607 if (data->have_pat_data == 1 && data->have_pmt_data == 1)
609 break;
614 static void decrypt(struct dvbcsa_bs_batch_s *tsbbatch, uint16_t fill[2], const uint8_t oddeven, const int32_t connid)
616 if (fill[oddeven] > 0)
618 #if 0
619 uint16_t i;
620 for(i = fill[oddeven]; i <= cluster_size; i++)
622 tsbbatch[i].data = NULL;
623 tsbbatch[i].len = 0;
625 #else
626 tsbbatch[fill[oddeven]].data = NULL;
627 #endif
628 //cs_log_dbg(D_READER, "dvbcsa (%s), batch=%d", oddeven == ODD ? "odd" : "even", fill[oddeven]);
630 fill[oddeven] = 0;
632 dvbcsa_bs_decrypt(key_data[connid].key[oddeven], tsbbatch, 184);
635 #define decrypt(a) decrypt(tsbbatch, fill, a, data->connid)
637 static void DescrambleTsPackets(stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize, struct dvbcsa_bs_batch_s *tsbbatch)
639 uint32_t i, tsHeader;
640 uint16_t offset, fill[2] = {0,0};
641 uint8_t oddeven = 0;
642 #ifdef MODULE_RADEGAST
643 uint16_t pid;
644 uint8_t payloadStart;
645 #endif
647 for (i = 0; i < bufLength; i += packetSize)
649 tsHeader = b2i(4, stream_buf + i);
650 #ifdef MODULE_RADEGAST
651 pid = (tsHeader & 0x1FFF00) >> 8;
652 payloadStart = (tsHeader & 0x400000) >> 22;
653 #endif
654 offset = (tsHeader & 0x20) ? 4 + stream_buf[i + 4] + 1 : 4;
655 if (packetSize - offset < 1)
657 continue;
659 #ifdef MODULE_RADEGAST
660 #ifdef __BISS__
661 if(data->ecm_pid == 0x1FFF && caid_is_biss_fixed(data->caid))
663 uint32_t j, n;
664 uint16_t ecm_len = 7;
665 data->ecm_data[0] = 0x80; // to pass the cache check it must be 0x80 or 0x81
666 data->ecm_data[1] = 0x00;
667 data->ecm_data[2] = 0x04;
668 i2b_buf(2, data->srvid, data->ecm_data + 3);
669 i2b_buf(2, data->pmt_pid, data->ecm_data + 5);
670 for(j = 0, n = 7; j < data->STREAMpidcount; j++, n += 2)
672 i2b_buf(2, data->STREAMpids[j], data->ecm_data + n);
673 data->ecm_data[2] += 2;
674 ecm_len += 2;
676 data->ens &= 0x0FFFFFFF; // clear top 4 bits (in case of DVB-T/C or garbage), prepare for flagging
677 data->ens |= 0xA0000000; // flag to emu: this is the namespace, not a pid
678 i2b_buf(2, data->tsid, data->ecm_data + ecm_len); // place tsid after the last stream pid
679 i2b_buf(2, data->onid, data->ecm_data + ecm_len + 2); // place onid right after tsid
680 i2b_buf(4, data->ens, data->ecm_data + ecm_len + 4); // place namespace at the end of the ecm
681 data->ecm_data[2] += 8;
682 ParseEcmData(data);
683 } else
684 #endif // __BISS__
685 if (data->ecm_pid && pid == data->ecm_pid) // Process the ECM data
687 // set to null pid
688 stream_buf[i + 1] |= 0x1F;
689 stream_buf[i + 2] = 0xFF;
690 ParseTsData(0x80, 0xFE, 3, &data->have_ecm_data, data->ecm_data, sizeof(data->ecm_data),
691 &data->ecm_data_pos, payloadStart, stream_buf + i + offset, packetSize - offset, ParseEcmData, data);
692 continue;
694 #endif // MODULE_RADEGAST
695 if ((tsHeader & 0xC0) == 0)
697 continue;
700 stream_buf[i + 3] &= 0x3f; // consider it decrypted now
701 oddeven = (tsHeader & 0xC0) == 0xC0 ? ODD: EVEN;
702 decrypt(oddeven == ODD ? EVEN : ODD);
703 tsbbatch[fill[oddeven]].data = &stream_buf[i + offset];
704 tsbbatch[fill[oddeven]].len = packetSize - offset;
705 fill[oddeven]++;
707 if (fill[oddeven] > cluster_size - 1)
709 decrypt(oddeven);
713 decrypt(oddeven);
716 static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *stream_path)
718 struct SOCKADDR cservaddr;
719 IN_ADDR_T in_addr;
721 int32_t streamfd = socket(DEFAULT_AF, SOCK_STREAM, 0);
722 if (streamfd == -1) { return -1; }
724 struct timeval tv;
725 tv.tv_sec = 2;
726 tv.tv_usec = 0;
727 if (setsockopt(streamfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv))
729 cs_log("ERROR: setsockopt() failed for SO_RCVTIMEO");
730 return -1;
733 bzero(&cservaddr, sizeof(cservaddr));
734 SIN_GET_FAMILY(cservaddr) = DEFAULT_AF;
735 SIN_GET_PORT(cservaddr) = htons(cfg.stream_source_port);
736 cs_resolve(stream_source_host, &in_addr, NULL, NULL);
737 SIN_GET_ADDR(cservaddr) = in_addr;
739 if (connect(streamfd, (struct sockaddr *)&cservaddr, sizeof(cservaddr)) == -1)
741 cs_log("WARNING: Connect to stream source port %d failed", cfg.stream_source_port);
742 return -1;
745 if (stream_source_auth)
747 snprintf(http_buf, http_buf_len, "GET %s HTTP/1.1\nHost: %s:%u\n"
748 "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n"
749 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
750 "Accept-Language: en-US\n"
751 "Authorization: Basic %s\n"
752 "Connection: keep-alive\n\n", stream_path, stream_source_host, cfg.stream_source_port, stream_source_auth);
754 else
756 snprintf(http_buf, http_buf_len, "GET %s HTTP/1.1\nHost: %s:%u\n"
757 "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n"
758 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
759 "Accept-Language: en-US\n"
760 "Connection: keep-alive\n\n", stream_path, stream_source_host, cfg.stream_source_port);
763 if (send(streamfd, http_buf, cs_strlen(http_buf), 0) == -1) { return -1; }
764 return streamfd;
767 static void stream_client_disconnect(stream_client_conn_data *conndata)
769 int32_t i;
771 SAFE_MUTEX_LOCK(&fixed_key_srvid_mutex);
772 stream_cur_srvid[conndata->connid] = NO_SRVID_VALUE;
773 SAFE_MUTEX_UNLOCK(&fixed_key_srvid_mutex);
775 SAFE_MUTEX_LOCK(&stream_server_mutex);
776 for (i = 0; i < STREAM_SERVER_MAX_CONNECTIONS; i++)
778 if (gconnfd[i] == conndata->connfd)
780 gconnfd[i] = -1;
781 gconncount--;
784 SAFE_MUTEX_UNLOCK(&stream_server_mutex);
786 shutdown(conndata->connfd, 2);
787 close(conndata->connfd);
789 cs_log("Stream client %i disconnected",conndata->connid);
791 NULLFREE(conndata);
794 static void *stream_client_handler(void *arg)
796 stream_client_conn_data *conndata = (stream_client_conn_data *)arg;
797 stream_client_data *data;
799 char *http_buf, stream_path[255], stream_path_copy[255];
800 char *saveptr, *token, http_version[4];
802 int8_t streamConnectErrorCount = 0, streamDataErrorCount = 0;
803 int32_t bytesRead = 0, http_status_code = 0;
804 int32_t i, clientStatus, streamStatus, streamfd;
806 uint8_t *stream_buf;
807 uint16_t packetCount = 0, packetSize = 0, startOffset = 0;
808 uint32_t remainingDataPos, remainingDataLength, tmp_pids[4];
810 const int32_t cur_dvb_buffer_size = DVB_BUFFER_SIZE_CSA;
811 const int32_t cur_dvb_buffer_wait = DVB_BUFFER_WAIT_CSA;
813 struct dvbcsa_bs_batch_s *tsbbatch;
815 cs_log("Stream client %i connected", conndata->connid);
817 if (!cs_malloc(&http_buf, 1024))
819 stream_client_disconnect(conndata);
820 return NULL;
823 if (!cs_malloc(&stream_buf, DVB_BUFFER_SIZE))
825 NULLFREE(http_buf);
826 stream_client_disconnect(conndata);
827 return NULL;
830 if (!cs_malloc(&data, sizeof(stream_client_data)))
832 NULLFREE(http_buf);
833 NULLFREE(stream_buf);
834 stream_client_disconnect(conndata);
835 return NULL;
838 clientStatus = recv(conndata->connfd, http_buf, 1024, 0);
839 if (clientStatus < 1)
841 NULLFREE(http_buf);
842 NULLFREE(stream_buf);
843 NULLFREE(data);
844 stream_client_disconnect(conndata);
845 return NULL;
848 http_buf[1023] = '\0';
849 if (sscanf(http_buf, "GET %254s ", stream_path) < 1)
851 NULLFREE(http_buf);
852 NULLFREE(stream_buf);
853 NULLFREE(data);
854 stream_client_disconnect(conndata);
855 return NULL;
858 cs_strncpy(stream_path_copy, stream_path, sizeof(stream_path));
860 token = strtok_r(stream_path_copy, ":", &saveptr); // token 0
861 for (i = 1; token != NULL && i < 7; i++) // tokens 1 to 6
863 token = strtok_r(NULL, ":", &saveptr);
864 if (token == NULL)
866 break;
869 if (i >= 3) // We olny need token 3 (srvid), 4 (tsid), 5 (onid) and 6 (ens)
871 if (sscanf(token, "%x", &tmp_pids[i - 3]) != 1)
873 tmp_pids[i - 3] = 0;
878 data->srvid = tmp_pids[0] & 0xFFFF;
879 data->tsid = tmp_pids[1] & 0xFFFF;
880 data->onid = tmp_pids[2] & 0xFFFF;
881 data->ens = tmp_pids[3];
883 if (data->srvid == 0) // We didn't get a srvid - Exit
885 NULLFREE(http_buf);
886 NULLFREE(stream_buf);
887 NULLFREE(data);
888 stream_client_disconnect(conndata);
889 return NULL;
892 key_data[conndata->connid].key[ODD] = dvbcsa_bs_key_alloc();
893 key_data[conndata->connid].key[EVEN] = dvbcsa_bs_key_alloc();
895 if (!cs_malloc(&tsbbatch, (cluster_size + 1) * sizeof(struct dvbcsa_bs_batch_s)))
897 NULLFREE(http_buf);
898 NULLFREE(stream_buf);
899 NULLFREE(data);
900 stream_client_disconnect(conndata);
901 return NULL;
904 SAFE_MUTEX_LOCK(&fixed_key_srvid_mutex);
905 stream_cur_srvid[conndata->connid] = data->srvid;
906 SAFE_MUTEX_UNLOCK(&fixed_key_srvid_mutex);
908 cs_log("Stream client %i request %s", conndata->connid, stream_path);
910 cs_log_dbg(D_READER, "Stream client %i received srvid: %04X tsid: %04X onid: %04X ens: %08X",
911 conndata->connid, data->srvid, data->tsid, data->onid, data->ens);
913 snprintf(http_buf, 1024, "HTTP/1.0 200 OK\nConnection: Close\nContent-Type: video/mpeg\nServer: stream_enigma2\n\n");
914 clientStatus = send(conndata->connfd, http_buf, cs_strlen(http_buf), 0);
916 data->connid = conndata->connid;
917 data->caid = NO_CAID_VALUE;
918 data->have_pat_data = 0;
919 data->have_pmt_data = 0;
920 data->have_cat_data = 0;
921 data->have_ecm_data = 0;
922 data->have_emm_data = 0;
924 while (!exit_oscam && clientStatus != -1 && streamConnectErrorCount < 3
925 && streamDataErrorCount < 15)
927 streamfd = connect_to_stream(http_buf, 1024, stream_path);
928 if (streamfd == -1)
930 cs_log("WARNING: stream client %i cannot connect to stream source", conndata->connid);
931 streamConnectErrorCount++;
932 cs_sleepms(500);
933 continue;
935 streamStatus = 0;
936 bytesRead = 0;
937 while (!exit_oscam && clientStatus != -1 && streamStatus != -1
938 #if 0
939 && streamConnectErrorCount < 3 && streamDataErrorCount < 15)
940 #else
941 && (streamConnectErrorCount < 3 || streamDataErrorCount < 15))
942 #endif
944 streamStatus = recv(streamfd, stream_buf + bytesRead, cur_dvb_buffer_size - bytesRead, MSG_WAITALL);
945 if (streamStatus == 0) // socket closed
947 cs_log("WARNING: stream client %i - stream source closed connection", conndata->connid);
948 streamConnectErrorCount++;
949 cs_sleepms(100);
950 break;
952 if (streamStatus < 0) // error
954 if ((errno == EWOULDBLOCK) | (errno == EAGAIN))
956 cs_log("WARNING: stream client %i no data from stream source", conndata->connid);
957 streamDataErrorCount++; // 2 sec timeout * 15 = 30 seconds no data -> close
958 cs_sleepms(100);
959 continue;
961 cs_log("WARNING: stream client %i error receiving data from stream source", conndata->connid);
962 streamConnectErrorCount++;
963 cs_sleepms(100);
964 break;
966 if (streamStatus < cur_dvb_buffer_size - bytesRead) // probably just received header but no stream
968 if (!bytesRead && streamStatus > 13 &&
969 sscanf((const char*)stream_buf, "HTTP/%3s %d ", http_version , &http_status_code) == 2 &&
970 http_status_code != 200)
972 cs_log("ERROR: stream client %i got %d response from stream source", conndata->connid, http_status_code);
973 streamConnectErrorCount++;
974 cs_sleepms(100);
975 break;
977 else
979 cs_log_dbg(0, "WARNING: stream client %i non-full buffer from stream source", conndata->connid);
980 streamDataErrorCount++;
981 cs_sleepms(100);
984 else
986 streamDataErrorCount = 0;
989 streamConnectErrorCount = 0;
990 bytesRead += streamStatus;
992 if (bytesRead >= cur_dvb_buffer_wait)
994 startOffset = 0;
996 // only search if not starting on ts packet or unknown packet size
997 if (stream_buf[0] != 0x47 || packetSize == 0)
999 SearchTsPackets(stream_buf, bytesRead, &packetSize, &startOffset);
1002 if (packetSize == 0)
1004 bytesRead = 0;
1006 else
1008 packetCount = ((bytesRead - startOffset) / packetSize);
1010 // We have both PAT and PMT data - We can start descrambling
1011 if (data->have_pat_data == 1 && data->have_pmt_data == 1)
1013 if (chk_ctab_ex(data->caid, &cfg.stream_relay_ctab) && (data->caid != 0xA101 || data->caid == NO_CAID_VALUE))
1015 DescrambleTsPackets(data, stream_buf + startOffset, packetCount * packetSize, packetSize, tsbbatch);
1017 else
1019 cs_log_dbg(D_READER, "Stream client %i caid %04X not enabled in stream relay config",
1020 conndata->connid, data->caid);
1023 else // Search PAT and PMT packets for service information
1025 ParseTsPackets(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
1028 clientStatus = send(conndata->connfd, stream_buf + startOffset, packetCount * packetSize, 0);
1030 remainingDataPos = startOffset + (packetCount * packetSize);
1031 remainingDataLength = bytesRead - remainingDataPos;
1033 if (remainingDataPos < remainingDataLength)
1035 memmove(stream_buf, stream_buf + remainingDataPos, remainingDataLength);
1037 else
1039 memcpy(stream_buf, stream_buf + remainingDataPos, remainingDataLength);
1042 bytesRead = remainingDataLength;
1047 close(streamfd);
1050 NULLFREE(http_buf);
1051 NULLFREE(stream_buf);
1053 dvbcsa_bs_key_free(key_data[conndata->connid].key[ODD]);
1054 dvbcsa_bs_key_free(key_data[conndata->connid].key[EVEN]);
1055 NULLFREE(tsbbatch);
1057 NULLFREE(data);
1059 stream_client_disconnect(conndata);
1060 return NULL;
1063 void *stream_server(void *UNUSED(a))
1065 struct sockaddr_in servaddr, cliaddr;
1066 socklen_t clilen;
1067 int32_t connfd, reuse = 1, i;
1068 int8_t connaccepted;
1069 stream_client_conn_data *conndata;
1071 cluster_size = dvbcsa_bs_batch_size();
1072 cs_log("INFO: "
1073 #if DVBCSA_KEY_ECM > 0
1074 "(ecm) "
1075 #endif
1076 "dvbcsa parallel mode = %d", cluster_size);
1078 if (!stream_server_mutex_init)
1080 SAFE_MUTEX_INIT(&stream_server_mutex, NULL);
1081 stream_server_mutex_init = 1;
1084 SAFE_MUTEX_LOCK(&fixed_key_srvid_mutex);
1085 for (i = 0; i < STREAM_SERVER_MAX_CONNECTIONS; i++)
1087 stream_cur_srvid[i] = NO_SRVID_VALUE;
1089 SAFE_MUTEX_UNLOCK(&fixed_key_srvid_mutex);
1091 for (i = 0; i < STREAM_SERVER_MAX_CONNECTIONS; i++)
1093 gconnfd[i] = -1;
1096 glistenfd = socket(AF_INET, SOCK_STREAM, 0);
1097 if (glistenfd == -1)
1099 cs_log("ERROR: cannot create stream server socket");
1100 return NULL;
1103 bzero(&servaddr,sizeof(servaddr));
1104 servaddr.sin_family = AF_INET;
1105 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
1106 servaddr.sin_port = htons(cfg.stream_relay_port);
1107 setsockopt(glistenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
1109 if (bind(glistenfd,(struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
1111 cs_log("ERROR: cannot bind to stream server socket");
1112 close(glistenfd);
1113 return NULL;
1116 if (listen(glistenfd, 3) == -1)
1118 cs_log("ERROR: cannot listen to stream server socket");
1119 close(glistenfd);
1120 return NULL;
1123 while (!exit_oscam)
1125 clilen = sizeof(cliaddr);
1126 connfd = accept(glistenfd,(struct sockaddr *)&cliaddr, &clilen);
1128 if (connfd == -1)
1130 cs_log("ERROR: accept() failed");
1131 break;
1134 connaccepted = 0;
1136 #ifdef MODULE_RADEGAST
1137 if(cfg.stream_client_source_host)
1139 // Read ip of client who wants to play the stream
1140 unsigned char *ip = (unsigned char *)&cliaddr.sin_addr.s_addr;
1141 cs_log("Stream Client ip is: %d.%d.%d.%d, will fetch stream there\n", ip[0], ip[1], ip[2], ip[3]);
1143 // Store ip of client in stream_source_host variable
1144 snprintf(stream_source_host, sizeof(stream_source_host), "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
1146 #endif
1148 if (cs_malloc(&conndata, sizeof(stream_client_conn_data)))
1150 SAFE_MUTEX_LOCK(&stream_server_mutex);
1151 if (gconncount < STREAM_SERVER_MAX_CONNECTIONS)
1153 for (i = 0; i < STREAM_SERVER_MAX_CONNECTIONS; i++)
1155 if (gconnfd[i] == -1)
1157 gconnfd[i] = connfd;
1158 gconncount++;
1159 connaccepted = 1;
1161 conndata->connfd = connfd;
1162 conndata->connid = i;
1164 break;
1168 SAFE_MUTEX_UNLOCK(&stream_server_mutex);
1171 if (connaccepted)
1173 int on = 1;
1174 if (setsockopt(connfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
1176 cs_log("ERROR: stream client %i setsockopt() failed for TCP_NODELAY", conndata->connid);
1179 start_thread("stream client", stream_client_handler, (void*)conndata, NULL, 1, 0);
1181 else
1183 shutdown(connfd, 2);
1184 close(connfd);
1185 cs_log("ERROR: stream server client dropped because of too many connections (%i)", STREAM_SERVER_MAX_CONNECTIONS);
1188 cs_sleepms(20);
1191 close(glistenfd);
1193 return NULL;
1196 void init_stream_server(void)
1198 char authtmp[128];
1200 if (cfg.stream_relay_enabled)
1203 cs_strncpy(stream_source_host, cfg.stream_source_host, sizeof(stream_source_host));
1205 if (cfg.stream_source_auth_user && cfg.stream_source_auth_password)
1207 snprintf(authtmp, sizeof(authtmp), "%s:%s", cfg.stream_source_auth_user, cfg.stream_source_auth_password);
1208 b64encode(authtmp, cs_strlen(authtmp), &stream_source_auth);
1211 start_thread("stream_server", stream_server, NULL, NULL, 1, 1);
1212 cs_log("Stream Relay server initialized");
1216 void stop_stream_server(void)
1218 int32_t i;
1220 SAFE_MUTEX_LOCK(&stream_server_mutex);
1221 for (i = 0; i < STREAM_SERVER_MAX_CONNECTIONS; i++)
1223 if (gconnfd[i] != -1)
1225 shutdown(gconnfd[i], 2);
1226 close(gconnfd[i]);
1227 gconnfd[i] = -1;
1231 gconncount = 0;
1232 SAFE_MUTEX_UNLOCK(&stream_server_mutex);
1234 #ifdef MODULE_RADEGAST
1235 close_radegast_connection();
1236 #endif
1238 shutdown(glistenfd, 2);
1239 close(glistenfd);
1242 #endif // MODULE_STREAMRELAY