1 #define MODULE_LOG_PREFIX "relay"
5 #ifdef MODULE_STREAMRELAY
7 #include "module-streamrelay.h"
8 #include "oscam-config.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
;
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
;
48 gRadegastFd
= socket(DEFAULT_AF
, SOCK_STREAM
, 0);
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)
72 static void close_radegast_connection(void)
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");
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
);
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)
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
)
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
)
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);
181 static void SearchTsPackets(const uint8_t *buf
, const uint32_t bufLength
, uint16_t *packetSize
, uint16_t *startOffset
)
185 for (i
= 0; i
< bufLength
; i
++)
189 // if three packets align, probably safe to assume correct size
190 if ((buf
[i
+ 188] == 0x47) & (buf
[i
+ 376] == 0x47))
196 else if ((buf
[i
+ 204] == 0x47) & (buf
[i
+ 408] == 0x47))
202 else if ((buf
[i
+ 208] == 0x47) & (buf
[i
+ 416] == 0x47))
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
)
223 bool found_start
= 0;
230 if (*flag
== 0 && !payloadStart
)
240 else if (payloadStart
)
245 if ((len
- offset
) < 1)
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
)
262 if (*data_pos
- i
> i
)
264 memmove(data
, &data
[i
], *data_pos
- i
);
268 memcpy(data
, &data
[i
], *data_pos
- i
);
278 const uint16_t section_length
= SCT_LEN(data
);
280 if (!found_start
|| (section_length
> data_length
) || (section_length
< min_table_length
))
286 if ((*data_pos
< section_length
) || (*data_pos
< 3))
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
);
305 memcpy(data
, &data
[i
], *data_pos
- i
);
314 if (!found_start
|| (data_length
< *data_pos
+ copySize
+ 1))
322 static void ParsePatData(stream_client_data
*cdata
)
327 cdata
->STREAMpidcount
= 0;
329 for (i
= 8; i
+ 7 < SCT_LEN(cdata
->pat_data
); i
+= 4)
331 srvid
= b2i(2, cdata
->pat_data
+ i
);
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
);
347 static void ParseDescriptors(const uint8_t *buffer
, const uint16_t info_length
, uint8_t *type
)
350 uint8_t j
, descriptor_length
= 0;
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
;
381 //case 0x09: // CA descriptor
385 case 0x46: // VBI teletext descriptor (DVB)
386 case 0x56: // teletext descriptor (DVB)
388 *type
= STREAM_TELETEXT
;
391 case 0x59: // subtitling descriptor (DVB)
393 *type
= STREAM_SUBTITLE
;
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
;
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
;
416 case 0x20: // TTML subtitling descriptor (DVB)
417 *type
= STREAM_SUBTITLE
;
421 *type
= STREAM_UNDEFINED
;
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
)
439 // parse program descriptors (we are looking only for CA descriptor here)
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)
453 if (i
+ 1 + descriptor_length
>= offset
+ info_length
)
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
)
468 if (cdata
->caid
!= caid
)
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
)
483 uint16_t program_info_length
= 0, es_info_length
= 0, elementary_pid
;
484 const uint16_t section_length
= SCT_LEN(cdata
->pmt_data
);
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
)
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
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
);
536 cs_log_dbg(D_READER
, "Stream client %i found audio pid: 0x%04X (%i)",
537 cdata
->connid
, elementary_pid
, elementary_pid
);
541 //case 0x81: // some ATSC AC-3 streams do not contain the AC-3 descriptor!
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
);
560 cdata
->STREAMpids
[cdata
->STREAMpidcount
] = elementary_pid
;
561 cdata
->STREAMpidcount
++;
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;
580 offset
= 4 + stream_buf
[i
+ 4] + 1;
587 if (packetSize
- offset
< 1)
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
);
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
);
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)
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)
620 for(i
= fill
[oddeven
]; i
<= cluster_size
; i
++)
622 tsbbatch
[i
].data
= NULL
;
626 tsbbatch
[fill
[oddeven
]].data
= NULL
;
628 //cs_log_dbg(D_READER, "dvbcsa (%s), batch=%d", oddeven == ODD ? "odd" : "even", fill[oddeven]);
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};
642 #ifdef MODULE_RADEGAST
644 uint8_t payloadStart
;
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;
654 offset
= (tsHeader
& 0x20) ? 4 + stream_buf
[i
+ 4] + 1 : 4;
655 if (packetSize
- offset
< 1)
659 #ifdef MODULE_RADEGAST
661 if(data
->ecm_pid
== 0x1FFF && caid_is_biss_fixed(data
->caid
))
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;
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;
685 if (data
->ecm_pid
&& pid
== data
->ecm_pid
) // Process the ECM data
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
);
694 #endif // MODULE_RADEGAST
695 if ((tsHeader
& 0xC0) == 0)
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
;
707 if (fill
[oddeven
] > cluster_size
- 1)
716 static int32_t connect_to_stream(char *http_buf
, int32_t http_buf_len
, char *stream_path
)
718 struct SOCKADDR cservaddr
;
721 int32_t streamfd
= socket(DEFAULT_AF
, SOCK_STREAM
, 0);
722 if (streamfd
== -1) { return -1; }
727 if (setsockopt(streamfd
, SOL_SOCKET
, SO_RCVTIMEO
, (char *)&tv
, sizeof tv
))
729 cs_log("ERROR: setsockopt() failed for SO_RCVTIMEO");
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
);
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
);
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; }
767 static void stream_client_disconnect(stream_client_conn_data
*conndata
)
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
)
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
);
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
;
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
);
823 if (!cs_malloc(&stream_buf
, DVB_BUFFER_SIZE
))
826 stream_client_disconnect(conndata
);
830 if (!cs_malloc(&data
, sizeof(stream_client_data
)))
833 NULLFREE(stream_buf
);
834 stream_client_disconnect(conndata
);
838 clientStatus
= recv(conndata
->connfd
, http_buf
, 1024, 0);
839 if (clientStatus
< 1)
842 NULLFREE(stream_buf
);
844 stream_client_disconnect(conndata
);
848 http_buf
[1023] = '\0';
849 if (sscanf(http_buf
, "GET %254s ", stream_path
) < 1)
852 NULLFREE(stream_buf
);
854 stream_client_disconnect(conndata
);
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
);
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)
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
886 NULLFREE(stream_buf
);
888 stream_client_disconnect(conndata
);
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
)))
898 NULLFREE(stream_buf
);
900 stream_client_disconnect(conndata
);
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
);
930 cs_log("WARNING: stream client %i cannot connect to stream source", conndata
->connid
);
931 streamConnectErrorCount
++;
937 while (!exit_oscam
&& clientStatus
!= -1 && streamStatus
!= -1
939 && streamConnectErrorCount
< 3 && streamDataErrorCount
< 15)
941 && (streamConnectErrorCount
< 3 || streamDataErrorCount
< 15))
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
++;
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
961 cs_log("WARNING: stream client %i error receiving data from stream source", conndata
->connid
);
962 streamConnectErrorCount
++;
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
++;
979 cs_log_dbg(0, "WARNING: stream client %i non-full buffer from stream source", conndata
->connid
);
980 streamDataErrorCount
++;
986 streamDataErrorCount
= 0;
989 streamConnectErrorCount
= 0;
990 bytesRead
+= streamStatus
;
992 if (bytesRead
>= cur_dvb_buffer_wait
)
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)
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
);
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
);
1039 memcpy(stream_buf
, stream_buf
+ remainingDataPos
, remainingDataLength
);
1042 bytesRead
= remainingDataLength
;
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
]);
1059 stream_client_disconnect(conndata
);
1063 void *stream_server(void *UNUSED(a
))
1065 struct sockaddr_in servaddr
, cliaddr
;
1067 int32_t connfd
, reuse
= 1, i
;
1068 int8_t connaccepted
;
1069 stream_client_conn_data
*conndata
;
1071 cluster_size
= dvbcsa_bs_batch_size();
1073 #if DVBCSA_KEY_ECM > 0
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
++)
1096 glistenfd
= socket(AF_INET
, SOCK_STREAM
, 0);
1097 if (glistenfd
== -1)
1099 cs_log("ERROR: cannot create stream server socket");
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");
1116 if (listen(glistenfd
, 3) == -1)
1118 cs_log("ERROR: cannot listen to stream server socket");
1125 clilen
= sizeof(cliaddr
);
1126 connfd
= accept(glistenfd
,(struct sockaddr
*)&cliaddr
, &clilen
);
1130 cs_log("ERROR: accept() failed");
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]);
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
;
1161 conndata
->connfd
= connfd
;
1162 conndata
->connid
= i
;
1168 SAFE_MUTEX_UNLOCK(&stream_server_mutex
);
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);
1183 shutdown(connfd
, 2);
1185 cs_log("ERROR: stream server client dropped because of too many connections (%i)", STREAM_SERVER_MAX_CONNECTIONS
);
1196 void init_stream_server(void)
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)
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);
1232 SAFE_MUTEX_UNLOCK(&stream_server_mutex
);
1234 #ifdef MODULE_RADEGAST
1235 close_radegast_connection();
1238 shutdown(glistenfd
, 2);
1242 #endif // MODULE_STREAMRELAY