From 7425d43a23723a183608bfdc5e7d5a78e1e1be08 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 29 May 2014 16:08:02 +0200 Subject: [PATCH] descrambler: Merge the common descrambler code - tvhcsa_descramble() calls --- Makefile | 2 +- src/descrambler.h | 27 +++++--- src/descrambler/capmt.c | 85 ++++++++--------------- src/descrambler/cwc.c | 124 +++++++++------------------------- src/descrambler/descrambler.c | 16 +++++ src/descrambler/tvhcsa.c | 5 +- src/descrambler/tvhcsa.h | 2 +- src/input/mpegts/tsdemux.c | 4 +- 8 files changed, 99 insertions(+), 166 deletions(-) diff --git a/Makefile b/Makefile index e02c89d4..5c22f0b1 100644 --- a/Makefile +++ b/Makefile @@ -125,7 +125,6 @@ SRCS = src/version.c \ src/lang_str.c \ src/imagecache.c \ src/tvhtime.c \ - src/descrambler/descrambler.c \ src/service_mapper.c \ src/input.c \ src/httpc.c \ @@ -193,6 +192,7 @@ SRCS += src/muxer.c \ # MPEGTS core SRCS-$(CONFIG_MPEGTS) += \ + src/descrambler/descrambler.c \ src/input/mpegts.c \ src/input/mpegts/mpegts_input.c \ src/input/mpegts/mpegts_network.c \ diff --git a/src/descrambler.h b/src/descrambler.h index 9608db44..094a7f2e 100755 --- a/src/descrambler.h +++ b/src/descrambler.h @@ -20,11 +20,11 @@ #define __TVH_DESCRAMBLER_H__ #include - #include "queue.h" struct service; struct elementary_stream; +struct tvhcsa; /** * Descrambler superclass @@ -34,12 +34,18 @@ struct elementary_stream; typedef struct th_descrambler { LIST_ENTRY(th_descrambler) td_service_link; - void (*td_table)(struct th_descrambler *d, struct service *t, - struct elementary_stream *st, - const uint8_t *section, int section_len); + enum { + DS_UNKNOWN, + DS_RESOLVED, + DS_FORBIDDEN, + DS_IDLE + } td_keystate; - int (*td_descramble)(struct th_descrambler *d, struct service *t, - struct elementary_stream *st, const uint8_t *tsb); + struct service *td_service; + struct tvhcsa *td_csa; + + void (*td_table)(struct th_descrambler *d, struct elementary_stream *st, + const uint8_t *section, int section_len); void (*td_stop)(struct th_descrambler *d); @@ -79,9 +85,12 @@ LIST_HEAD(caid_list, caid); void descrambler_init ( void ); void descrambler_done ( void ); void descrambler_service_start ( struct service *t ); -const char *descrambler_caid2name(uint16_t caid); -uint16_t descrambler_name2caid(const char *str); -card_type_t detect_card_type(const uint16_t caid); +int descrambler_descramble ( th_descrambler_t *td, + struct elementary_stream *st, + const uint8_t *tsb ); +const char *descrambler_caid2name( uint16_t caid ); +uint16_t descrambler_name2caid ( const char *str ); +card_type_t detect_card_type ( const uint16_t caid ); #endif /* __TVH_DESCRAMBLER_H__ */ diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index b7908e41..55828cad 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -38,6 +38,7 @@ #include "tvheadend.h" #include "input.h" +#include "service.h" #include "tcp.h" #include "capmt.h" @@ -148,9 +149,7 @@ typedef struct capmt_caid_ecm { * */ typedef struct capmt_service { - th_descrambler_t ct_head; - - mpegts_service_t *ct_service; + th_descrambler_t; struct capmt *ct_capmt; @@ -159,15 +158,6 @@ typedef struct capmt_service { /* list of used ca-systems with ids and last ecm */ struct capmt_caid_ecm_list ct_caid_ecm; - /** - * Status of the key(s) in ct_keys - */ - enum { - CT_UNKNOWN, - CT_RESOLVED, - CT_FORBIDDEN - } ct_keystate; - tvhcsa_t ct_csa; /* current sequence number */ @@ -336,11 +326,13 @@ capmt_send_msg(capmt_t *capmt, int sid, const uint8_t *buf, size_t len) static void capmt_send_stop(capmt_service_t *t) { + mpegts_service_t *s = (mpegts_service_t *)t->td_service; + if (t->ct_capmt->capmt_oscam) { int i; // searching for socket to close for (i = 0; i < MAX_SOCKETS; i++) - if (t->ct_capmt->sids[i] == t->ct_service->s_dvb_service_id) + if (t->ct_capmt->sids[i] == s->s_dvb_service_id) break; if (i == MAX_SOCKETS) { @@ -362,7 +354,7 @@ capmt_send_stop(capmt_service_t *t) capmt_header_t head = { .capmt_indicator = { 0x9F, 0x80, 0x32, 0x82, 0x00, 0x00 }, .capmt_list_management = CAPMT_LIST_ONLY, - .program_number = t->ct_service->s_dvb_service_id, + .program_number = s->s_dvb_service_id, .version_number = 0, .current_next_indicator = 0, .program_info_length = 0, @@ -377,13 +369,13 @@ capmt_send_stop(capmt_service_t *t) pos += sizeof(end); buf[4] = ((pos - 6) >> 8); buf[5] = ((pos - 6) & 0xFF); - buf[7] = t->ct_service->s_dvb_service_id >> 8; - buf[8] = t->ct_service->s_dvb_service_id & 0xFF; + buf[7] = s->s_dvb_service_id >> 8; + buf[8] = s->s_dvb_service_id & 0xFF; buf[9] = 1; buf[10] = ((pos - 5 - 12) & 0xF00) >> 8; buf[11] = ((pos - 5 - 12) & 0xFF); - capmt_send_msg(t->ct_capmt, t->ct_service->s_dvb_service_id, buf, pos); + capmt_send_msg(t->ct_capmt, s->s_dvb_service_id, buf, pos); } } @@ -501,8 +493,8 @@ handle_ca0(capmt_t* capmt) { // we are not connected any more - set services as unavailable LIST_FOREACH(ct, &capmt->capmt_services, ct_link) { - if (ct->ct_keystate != CT_FORBIDDEN) { - ct->ct_keystate = CT_FORBIDDEN; + if (ct->td_keystate != DS_FORBIDDEN) { + ct->td_keystate = DS_FORBIDDEN; } } @@ -581,13 +573,13 @@ handle_ca0(capmt_t* capmt) { // processing key if (process_key) { LIST_FOREACH(ct, &capmt->capmt_services, ct_link) { - t = ct->ct_service; + t = (mpegts_service_t *)ct->td_service; if (!capmt->capmt_oscam && ret < bufsize) { - if(ct->ct_keystate != CT_FORBIDDEN) { + if(ct->td_keystate != DS_FORBIDDEN) { tvhlog(LOG_ERR, "capmt", "Can not descramble service \"%s\", access denied", t->s_dvb_svcname); - ct->ct_keystate = CT_FORBIDDEN; + ct->td_keystate = DS_FORBIDDEN; } continue; @@ -601,10 +593,10 @@ handle_ca0(capmt_t* capmt) { if (memcmp(odd, invalid, 8)) tvhcsa_set_key_odd(&ct->ct_csa, odd); - if(ct->ct_keystate != CT_RESOLVED) + if(ct->td_keystate != DS_RESOLVED) tvhlog(LOG_DEBUG, "capmt", "Obtained key for service \"%s\"",t->s_dvb_svcname); - ct->ct_keystate = CT_RESOLVED; + ct->td_keystate = DS_RESOLVED; } } } @@ -738,19 +730,19 @@ capmt_thread(void *aux) * */ static void -capmt_table_input(struct th_descrambler *td, struct service *s, +capmt_table_input(struct th_descrambler *td, struct elementary_stream *st, const uint8_t *data, int len) { extern const idclass_t mpegts_service_class; extern const idclass_t linuxdvb_frontend_class; capmt_service_t *ct = (capmt_service_t *)td; capmt_t *capmt = ct->ct_capmt; - mpegts_service_t *t = (mpegts_service_t*)s; + mpegts_service_t *t = (mpegts_service_t*)td->td_service; linuxdvb_frontend_t *lfe; int total_caids = 0, current_caid = 0; /* Validate */ - if (!idnode_is_instance(&s->s_id, &mpegts_service_class)) + if (!idnode_is_instance(&td->td_service->s_id, &mpegts_service_class)) return; if (!t->s_dvb_active_input) return; lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input; @@ -805,7 +797,7 @@ capmt_table_input(struct th_descrambler *td, struct service *s, if(!capmt->capmt_oscam && capmt->capmt_sock[0] == 0) { /* New key, but we are not connected (anymore), can not descramble */ - ct->ct_keystate = CT_UNKNOWN; + ct->td_keystate = DS_UNKNOWN; break; } @@ -833,7 +825,7 @@ static void capmt_send_request(capmt_service_t *ct, int es_pid, int lm) { capmt_t *capmt = ct->ct_capmt; - mpegts_service_t *t = ct->ct_service; + mpegts_service_t *t = (mpegts_service_t *)ct->td_service; uint16_t sid = t->s_dvb_service_id; uint16_t ecmpid = es_pid; uint16_t transponder = t->s_dvb_mux->mm_tsid; @@ -946,7 +938,7 @@ capmt_send_request(capmt_service_t *ct, int es_pid, int lm) buf[8] = sid & 0xFF; - if(ct->ct_keystate != CT_RESOLVED) + if(ct->td_keystate != DS_RESOLVED) tvhlog(LOG_DEBUG, "capmt", "Trying to obtain key for service \"%s\"",t->s_dvb_svcname); @@ -967,7 +959,7 @@ capmt_enumerate_services(capmt_t *capmt, int es_pid, int force) capmt_service_t *ct; LIST_FOREACH(ct, &capmt->capmt_services, ct_link) { all_srv_count++; - if (ct->ct_keystate == CT_RESOLVED) + if (ct->td_keystate == DS_RESOLVED) res_srv_count++; } @@ -991,28 +983,6 @@ capmt_enumerate_services(capmt_t *capmt, int es_pid, int force) } } - -/** - * - */ -static int -capmt_descramble - (th_descrambler_t *td, service_t *t, struct elementary_stream *st, - const uint8_t *tsb) -{ - capmt_service_t *ct = (capmt_service_t *)td; - - if(ct->ct_keystate == CT_FORBIDDEN) - return 1; - - if(ct->ct_keystate != CT_RESOLVED) - return -1; - - tvhcsa_descramble(&ct->ct_csa, (mpegts_service_t*)t, st, tsb, 0); - - return 0; -} - /** * Check if our CAID's matches, and if so, link * @@ -1045,7 +1015,7 @@ capmt_service_start(service_t *s) TAILQ_FOREACH(capmt, &capmts, capmt_link) { LIST_FOREACH(ct, &capmt->capmt_services, ct_link) { /* skip, if we already have this service */ - if (ct->ct_service == t) + if (ct->td_service == (service_t *)t) return; } } @@ -1063,9 +1033,7 @@ capmt_service_start(service_t *s) /* create new capmt service */ ct = calloc(1, sizeof(capmt_service_t)); - tvhcsa_init(&ct->ct_csa); ct->ct_capmt = capmt; - ct->ct_service = t; ct->ct_seq = capmt->capmt_seq++; @@ -1092,10 +1060,11 @@ capmt_service_start(service_t *s) } } - td = &ct->ct_head; + td = (th_descrambler_t *)ct; + tvhcsa_init(td->td_csa = &ct->ct_csa); + td->td_service = s; td->td_stop = capmt_service_destroy; td->td_table = capmt_table_input; - td->td_descramble = capmt_descramble; LIST_INSERT_HEAD(&t->s_descramblers, td, td_service_link); LIST_INSERT_HEAD(&capmt->capmt_services, ct, ct_link); diff --git a/src/descrambler/cwc.c b/src/descrambler/cwc.c index 97e8e879..71d8b8fe 100755 --- a/src/descrambler/cwc.c +++ b/src/descrambler/cwc.c @@ -124,9 +124,7 @@ typedef struct ecm_pid { * */ typedef struct cwc_service { - th_descrambler_t cs_head; - - mpegts_service_t *cs_service; + th_descrambler_t; struct cwc *cs_cwc; @@ -143,19 +141,6 @@ typedef struct cwc_service { ECM_RESET } ecm_state; - /** - * Status of the key(s) in cs_keys - */ - enum { - CS_UNKNOWN, - CS_RESOLVED, - CS_FORBIDDEN, - CS_IDLE - } cs_keystate; - - uint8_t cs_cw[16]; - int cs_pending_cw_update; - tvhcsa_t cs_csa; LIST_HEAD(, ecm_pid) cs_pids; @@ -696,7 +681,7 @@ static void handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, int len, int seq) { - mpegts_service_t *t = ct->cs_service; + mpegts_service_t *t = (mpegts_service_t *)ct->td_service; ecm_pid_t *ep, *epn; cwc_service_t *ct2; cwc_t *cwc2; @@ -714,7 +699,7 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, if (es->es_nok < 3) es->es_nok++; - if(ct->cs_keystate == CS_FORBIDDEN) + if(ct->td_keystate == DS_FORBIDDEN) return; // We already know it's bad if (es->es_nok > 2) { @@ -727,8 +712,8 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, TAILQ_FOREACH(cwc2, &cwcs, cwc_link) { LIST_FOREACH(ct2, &cwc2->cwc_services, cs_link) { - if (ct != ct2 && ct2->cs_service == t && - ct2->cs_keystate == CS_RESOLVED) { + if (ct != ct2 && ct2->td_service == (service_t *)t && + ct2->td_keystate == DS_RESOLVED) { tvhlog(LOG_DEBUG, "cwc", "NOK from %s:%i: Already has a key for service \"%s\", from %s:%i", ct->cs_cwc->cwc_hostname, ct->cs_cwc->cwc_port, @@ -759,7 +744,7 @@ forbid: "Req delay: %"PRId64" ms)", t->s_dvb_svcname, seq, delay); - ct->cs_keystate = CS_FORBIDDEN; + ct->td_keystate = DS_FORBIDDEN; ct->ecm_state = ECM_RESET; return; @@ -790,9 +775,9 @@ forbid: TAILQ_FOREACH(cwc2, &cwcs, cwc_link) { LIST_FOREACH(ct2, &cwc2->cwc_services, cs_link) { - if (ct != ct2 && ct2->cs_service == t && - ct2->cs_keystate == CS_RESOLVED) { - ct->cs_keystate = CS_IDLE; + if (ct != ct2 && ct2->td_service == (service_t *)t && + ct2->td_keystate == DS_RESOLVED) { + ct->td_keystate = DS_IDLE; tvhlog(LOG_DEBUG, "cwc", "Already has a key for service \"%s\", from %s:%i", t->s_dvb_svcname, ct2->cs_cwc->cwc_hostname, ct2->cs_cwc->cwc_port); @@ -801,15 +786,23 @@ forbid: } } - if(ct->cs_keystate != CS_RESOLVED) + if(ct->td_keystate != DS_RESOLVED) tvhlog(LOG_DEBUG, "cwc", "Obtained key for service \"%s\" in %"PRId64" ms, from %s:%i", t->s_dvb_svcname, delay, ct->cs_cwc->cwc_hostname, ct->cs_cwc->cwc_port); - ct->cs_keystate = CS_RESOLVED; - memcpy(ct->cs_cw, msg + 3, 16); - ct->cs_pending_cw_update = 1; + ct->td_keystate = DS_RESOLVED; + for (i = 3; i < 3 + 8; i++) + if (msg[i]) { + tvhcsa_set_key_even(&ct->cs_csa, msg + 3); + break; + } + for (i = 3 + 8; i < 3 + 8 + 8; i++) + if (msg[i]) { + tvhcsa_set_key_odd(&ct->cs_csa, msg + 3 + 8); + break; + } ep = LIST_FIRST(&ct->cs_pids); while(ep != NULL) { @@ -1210,9 +1203,9 @@ cwc_thread(void *aux) cwc->cwc_hostname, cwc->cwc_port); while((ct = LIST_FIRST(&cwc->cwc_services)) != NULL) { - t = ct->cs_service; + t = (mpegts_service_t *)ct->td_service; pthread_mutex_lock(&t->s_stream_mutex); - cwc_service_destroy(&ct->cs_head); + cwc_service_destroy((th_descrambler_t *)&ct); pthread_mutex_unlock(&t->s_stream_mutex); } @@ -1601,11 +1594,11 @@ cwc_emm_viaccess(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int mlen * t->s_streaming_mutex is held */ static void -cwc_table_input(struct th_descrambler *td, service_t *s, +cwc_table_input(struct th_descrambler *td, struct elementary_stream *st, const uint8_t *data, int len) { cwc_service_t *ct = (cwc_service_t *)td; - mpegts_service_t *t = (mpegts_service_t*)s; + mpegts_service_t *t = (mpegts_service_t*)td->td_service; uint16_t sid = t->s_dvb_service_id; cwc_t *cwc = ct->cs_cwc; int channel; @@ -1615,7 +1608,7 @@ cwc_table_input(struct th_descrambler *td, service_t *s, char chaninfo[32]; caid_t *c; - if (ct->cs_keystate == CS_IDLE) + if (ct->td_keystate == DS_IDLE) return; if(len > 4096) @@ -1708,7 +1701,7 @@ cwc_table_input(struct th_descrambler *td, service_t *s, if(cwc->cwc_fd == -1) { // New key, but we are not connected (anymore), can not descramble - ct->cs_keystate = CS_UNKNOWN; + ct->td_keystate = DS_UNKNOWN; break; } es->es_channel = channel; @@ -1897,56 +1890,6 @@ cwc_emm_bulcrypt(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int len) cwc_send_msg(cwc, data, len, 0, 1, 0, 0); } -/** - * - */ -static void -update_keys(cwc_service_t *ct) -{ - int i; - ct->cs_pending_cw_update = 0; - for(i = 0; i < 8; i++) - if(ct->cs_cw[i]) { - tvhcsa_set_key_even(&ct->cs_csa, ct->cs_cw); - break; - } - - for(i = 0; i < 8; i++) - if(ct->cs_cw[8 + i]) { - tvhcsa_set_key_odd(&ct->cs_csa, ct->cs_cw+8); - break; - } -} - - -/** - * - */ -static int -cwc_descramble - (th_descrambler_t *td, service_t *t, struct elementary_stream *st, - const uint8_t *tsb) -{ - cwc_service_t *ct = (cwc_service_t *)td; - - if(ct->cs_keystate == CS_FORBIDDEN) - return 1; - - if(ct->cs_keystate != CS_RESOLVED) - return -1; - - if(ct->cs_csa.csa_fill == 0 && ct->cs_pending_cw_update) - update_keys(ct); - - tvhcsa_descramble(&ct->cs_csa, (mpegts_service_t*)t, st, tsb, - ct->cs_pending_cw_update); - - if(ct->cs_pending_cw_update) - update_keys(ct); - - return 0; -} - /** * cwc_mutex is held * s_stream_mutex is held @@ -2012,7 +1955,7 @@ cwc_service_start(service_t *t) pthread_mutex_lock(&cwc_mutex); TAILQ_FOREACH(cwc, &cwcs, cwc_link) { LIST_FOREACH(ct, &cwc->cwc_services, cs_link) { - if (ct->cs_service == (mpegts_service_t*)t && ct->cs_cwc == cwc) + if (ct->td_service == t && ct->cs_cwc == cwc) break; } LIST_FOREACH(pcard,&cwc->cwc_cards, cs_card) { @@ -2029,16 +1972,15 @@ cwc_service_start(service_t *t) mpegts_table_register_caid(((mpegts_service_t *)t)->s_dvb_mux, pcard->cwc_caid); ct = calloc(1, sizeof(cwc_service_t)); - tvhcsa_init(&ct->cs_csa); ct->cs_cwc = cwc; - ct->cs_service = (mpegts_service_t*)t; ct->cs_channel = -1; ct->ecm_state = ECM_INIT; - td = &ct->cs_head; - td->td_stop = cwc_service_destroy; - td->td_table = cwc_table_input; - td->td_descramble = cwc_descramble; + td = (th_descrambler_t *)ct; + tvhcsa_init(td->td_csa = &ct->cs_csa); + td->td_service = t; + td->td_stop = cwc_service_destroy; + td->td_table = cwc_table_input; LIST_INSERT_HEAD(&t->s_descramblers, td, td_service_link); LIST_INSERT_HEAD(&cwc->cwc_services, ct, cs_link); diff --git a/src/descrambler/descrambler.c b/src/descrambler/descrambler.c index 0728bfc3..2e6753b3 100755 --- a/src/descrambler/descrambler.c +++ b/src/descrambler/descrambler.c @@ -21,6 +21,7 @@ #include "capmt.h" #include "ffdecsa/FFdecsa.h" #include "service.h" +#include "tvhcsa.h" static struct strtab caidnametab[] = { { "Seca", 0x0100 }, @@ -133,6 +134,21 @@ descrambler_service_start ( service_t *t ) #endif } +int +descrambler_descramble ( th_descrambler_t *td, + struct elementary_stream *st, + const uint8_t *tsb ) +{ + if (td->td_keystate == DS_FORBIDDEN) + return 1; + if (td->td_keystate != DS_RESOLVED) + return -1; + tvhcsa_descramble(td->td_csa, + (struct mpegts_service *)td->td_service, + st, tsb); + return 0; +} + // TODO: might actually put const char* into caid_t const char * descrambler_caid2name(uint16_t caid) diff --git a/src/descrambler/tvhcsa.c b/src/descrambler/tvhcsa.c index cd883cb1..3886d5cd 100644 --- a/src/descrambler/tvhcsa.c +++ b/src/descrambler/tvhcsa.c @@ -27,7 +27,7 @@ void tvhcsa_descramble ( tvhcsa_t *csa, struct mpegts_service *s, struct elementary_stream *st, - const uint8_t *tsb, int cw_update_pending ) + const uint8_t *tsb ) { #if ENABLE_DVBCSA uint8_t *pkt; @@ -134,9 +134,6 @@ tvhcsa_descramble if(r > 0) memmove(csa->csa_tsbcluster, t0, r * 188); csa->csa_fill = r; - - if(cw_update_pending && r > 0) - continue; } else { csa->csa_fill = 0; } diff --git a/src/descrambler/tvhcsa.h b/src/descrambler/tvhcsa.h index a302fc05..e0e4f7c9 100644 --- a/src/descrambler/tvhcsa.h +++ b/src/descrambler/tvhcsa.h @@ -76,7 +76,7 @@ typedef struct tvhcsa void tvhcsa_descramble ( tvhcsa_t *csa, struct mpegts_service *s, struct elementary_stream *st, - const uint8_t *tsb, int cw_update_pending ); + const uint8_t *tsb ); void tvhcsa_init ( tvhcsa_t *csa ); void tvhcsa_destroy ( tvhcsa_t *csa ); diff --git a/src/input/mpegts/tsdemux.c b/src/input/mpegts/tsdemux.c index 06b4ee2f..00f2210d 100644 --- a/src/input/mpegts/tsdemux.c +++ b/src/input/mpegts/tsdemux.c @@ -56,7 +56,7 @@ got_ca_section(const uint8_t *data, size_t len, void *opaque) mpegts_service_t *t = (mpegts_service_t*)st->es_service; LIST_FOREACH(td, &t->s_descramblers, td_service_link) - td->td_table(td, (service_t*)t, st, data, len); + td->td_table(td, st, data, len); } /** @@ -249,7 +249,7 @@ ts_recv_packet1 LIST_FOREACH(td, &t->s_descramblers, td_service_link) { n++; - r = td->td_descramble(td, (service_t*)t, st, tsb); + r = descrambler_descramble(td, st, tsb); if(r == 0) { pthread_mutex_unlock(&t->s_stream_mutex); return 1;