From: Jaroslav Kysela Date: Sun, 14 Oct 2018 15:53:17 +0000 (+0200) Subject: descrambler: improve EMM handling - add provider id checks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ea7c385a37e49f798ca637d44b985eadd075c3f;p=thirdparty%2Ftvheadend.git descrambler: improve EMM handling - add provider id checks --- diff --git a/src/descrambler/caclient.c b/src/descrambler/caclient.c index f28020fc8..d3f4b0fca 100644 --- a/src/descrambler/caclient.c +++ b/src/descrambler/caclient.c @@ -365,7 +365,7 @@ caclient_cat_update void caclient_caid_update - ( struct mpegts_mux *mux, uint16_t caid, uint16_t pid, int valid ) + ( struct mpegts_mux *mux, uint16_t caid, uint32_t provid, uint16_t pid, int valid ) { caclient_t *cac; @@ -374,7 +374,7 @@ caclient_caid_update pthread_mutex_lock(&caclients_mutex); TAILQ_FOREACH(cac, &caclients, cac_link) if (cac->cac_caid_update && cac->cac_enabled) - cac->cac_caid_update(cac, mux, caid, pid, valid); + cac->cac_caid_update(cac, mux, caid, provid, pid, valid); pthread_mutex_unlock(&caclients_mutex); } diff --git a/src/descrambler/caclient.h b/src/descrambler/caclient.h index c9199ea0c..397c86ac1 100644 --- a/src/descrambler/caclient.h +++ b/src/descrambler/caclient.h @@ -68,7 +68,8 @@ typedef struct caclient { const uint8_t *data, int len); void (*cac_caid_update)(struct caclient *cac, struct mpegts_mux *mux, - uint16_t caid, uint16_t pid, int valid); + uint16_t caid, uint32_t prov, + uint16_t pid, int valid); } caclient_t; caclient_t *caclient_create @@ -76,7 +77,8 @@ caclient_t *caclient_create void caclient_start( struct service *t ); void caclient_caid_update(struct mpegts_mux *mux, - uint16_t caid, uint16_t pid, int valid); + uint16_t caid, uint32_t prov, + uint16_t pid, int valid); void caclient_cat_update(struct mpegts_mux *mux, const uint8_t *data, int len); diff --git a/src/descrambler/cclient.c b/src/descrambler/cclient.c index c503a30dd..6cca85353 100644 --- a/src/descrambler/cclient.c +++ b/src/descrambler/cclient.c @@ -80,8 +80,16 @@ cc_service_ecm_pid_free(cc_service_t *ct) static void cc_free_card(cc_card_data_t *cd) { + emm_provider_t *emmp; + int i; + LIST_REMOVE(cd, cs_card); - descrambler_close_emm(cd->cs_mux, cd, cd->cs_ra.caid); + + descrambler_close_emm(cd->cs_mux, cd, cd->cs_ra.caid, 0); + emmp = cd->cs_ra.providers; + for (i = 0; i < cd->cs_ra.providers_count; i++, emmp++) + descrambler_close_emm(cd->cs_mux, cd, cd->cs_ra.caid, emmp->id); + emm_reass_done(&cd->cs_ra); free(cd); } @@ -1185,26 +1193,33 @@ cc_free(caclient_t *cac) * */ void -cc_caid_update(caclient_t *cac, mpegts_mux_t *mux, uint16_t caid, uint16_t pid, int valid) +cc_caid_update(caclient_t *cac, mpegts_mux_t *mux, uint16_t caid, uint32_t prov, uint16_t pid, int valid) { cclient_t *cc = (cclient_t *)cac;; cc_card_data_t *pcard; + emm_provider_t *emmp; + int i; tvhtrace(cc->cc_subsys, - "%s: caid update event - client %s mux %p caid %04x (%i) pid %04x (%i) valid %i", - cc->cc_name, cac->cac_name, mux, caid, caid, pid, pid, valid); + "%s: caid update event - client %s mux %p caid %04x (%i) prov %06x (%i) pid %04x (%i) valid %i", + cc->cc_name, cac->cac_name, mux, caid, caid, prov, prov, pid, pid, valid); pthread_mutex_lock(&cc->cc_mutex); if (valid < 0 || cc->cc_running) { LIST_FOREACH(pcard, &cc->cc_cards, cs_card) { if (valid < 0 || pcard->cs_ra.caid == caid) { if (pcard->cs_mux && pcard->cs_mux != mux) continue; - if (valid > 0) { - pcard->cs_client = cc; - pcard->cs_mux = mux; - descrambler_open_emm(mux, pcard, caid, cc_emm); - } else { - pcard->cs_mux = NULL; - descrambler_close_emm(mux, pcard, caid); + emmp = pcard->cs_ra.providers; + for (i = 0; i < pcard->cs_ra.providers_count; i++, emmp++) { + if (prov == emmp->id) { + if (valid > 0) { + pcard->cs_client = cc; + pcard->cs_mux = mux; + descrambler_open_emm(mux, pcard, caid, prov, cc_emm); + } else { + pcard->cs_mux = NULL; + descrambler_close_emm(mux, pcard, caid, prov); + } + } } } } diff --git a/src/descrambler/cclient.h b/src/descrambler/cclient.h index c9d913c44..8accc403c 100644 --- a/src/descrambler/cclient.h +++ b/src/descrambler/cclient.h @@ -213,5 +213,5 @@ int cc_read(cclient_t *cc, void *buf, size_t len, int timeout); void cc_service_start(caclient_t *cac, service_t *t); void cc_free(caclient_t *cac); -void cc_caid_update(caclient_t *cac, mpegts_mux_t *mux, uint16_t caid, uint16_t pid, int valid); +void cc_caid_update(caclient_t *cac, mpegts_mux_t *mux, uint16_t caid, uint32_t provid, uint16_t pid, int valid); void cc_conf_changed(caclient_t *cac); diff --git a/src/descrambler/descrambler.c b/src/descrambler/descrambler.c index fcbbaab8d..506e464b0 100644 --- a/src/descrambler/descrambler.c +++ b/src/descrambler/descrambler.c @@ -1505,7 +1505,7 @@ descrambler_flush_tables( mpegts_mux_t *mux ) if (mux == NULL) return; tvhtrace(LS_DESCRAMBLER, "mux %p - flush tables", mux); - caclient_caid_update(mux, 0, 0, -1); + caclient_caid_update(mux, 0, 0, 0, -1); pthread_mutex_lock(&mux->mm_descrambler_lock); mux->mm_descrambler_flush = 1; while ((dt = TAILQ_FIRST(&mux->mm_descrambler_tables)) != NULL) { @@ -1531,13 +1531,67 @@ descrambler_flush_tables( mpegts_mux_t *mux ) pthread_mutex_unlock(&mux->mm_descrambler_lock); } +static void descrambler_cat_entry + ( mpegts_mux_t *mux, uint16_t caid, uint32_t prov, uint16_t pid ) +{ + descrambler_emm_t *emm; + caclient_caid_update(mux, caid, prov, pid, 1); + pthread_mutex_lock(&mux->mm_descrambler_lock); + TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link) + if (emm->caid == caid && emm->prov == prov) { + emm->to_be_removed = 0; + if (emm->pid == EMM_PID_UNKNOWN) { + tvhtrace(LS_DESCRAMBLER, "attach emm caid %04X (%i) prov %06X (%i) pid %04X (%i)", + caid, caid, prov, prov, pid, pid); + emm->pid = pid; + descrambler_open_pid_(mux, emm->opaque, pid, emm->callback, NULL); + break; // Only open a PID once + } + } + pthread_mutex_unlock(&mux->mm_descrambler_lock); +} + +static void descrambler_cat_clean( mpegts_mux_t *mux ) +{ + descrambler_emm_t *emm; + TAILQ_HEAD(,descrambler_emm) removing; + uint16_t caid = 0, pid = 0; + uint32_t prov; + + TAILQ_INIT(&removing); + pthread_mutex_lock(&mux->mm_descrambler_lock); + TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link) + if (emm->to_be_removed) { + if (emm->pid != EMM_PID_UNKNOWN) { + caid = emm->caid; + prov = emm->prov; + pid = emm->pid; + tvhtrace(LS_DESCRAMBLER, "close emm caid %04X (%i) prov %06X (%i) pid %04X (%i)", + caid, caid, prov, prov, pid, pid); + descrambler_close_pid_(mux, emm->opaque, pid); + } + TAILQ_REMOVE(&mux->mm_descrambler_emms, emm, link); + TAILQ_INSERT_TAIL(&removing, emm, link); + } + pthread_mutex_unlock(&mux->mm_descrambler_lock); + while ((emm = TAILQ_FIRST(&removing)) != NULL) { + if (emm->pid != EMM_PID_UNKNOWN) + caclient_caid_update(mux, emm->caid, emm->prov, emm->pid, 0); + TAILQ_REMOVE(&removing, emm, link); + free(emm); + } +} + void descrambler_cat_data( mpegts_mux_t *mux, const uint8_t *data, int len ) { descrambler_emm_t *emm; - uint8_t dtag, dlen; + uint8_t dtag, dlen, dlen2; uint16_t caid = 0, pid = 0; - TAILQ_HEAD(,descrambler_emm) removing; + uint32_t prov; + const uint8_t *data2; + int len2; + card_type_t ctype; tvhtrace(LS_DESCRAMBLER, "CAT data (len %d)", len); tvhlog_hexdump(LS_DESCRAMBLER, data, len); @@ -1554,48 +1608,33 @@ descrambler_cat_data( mpegts_mux_t *mux, const uint8_t *data, int len ) goto next; caid = (data[0] << 8) | data[1]; pid = ((data[2] << 8) | data[3]) & 0x1fff; - if (pid == 0) - goto next; - caclient_caid_update(mux, caid, pid, 1); - pthread_mutex_lock(&mux->mm_descrambler_lock); - TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link) - if (emm->caid == caid) { - emm->to_be_removed = 0; - if (emm->pid == EMM_PID_UNKNOWN) { - tvhtrace(LS_DESCRAMBLER, "attach emm caid %04X (%i) pid %04X (%i)", caid, caid, pid, pid); - emm->pid = pid; - descrambler_open_pid_(mux, emm->opaque, pid, emm->callback, NULL); + if (pid > 0) { + ctype = detect_card_type(caid); + descrambler_cat_entry(mux, caid, 0, pid); + if (ctype == CARD_SECA) { + dlen2 = dlen - 5; + data2 = data + 5; + len2 = len - 5; + while (dlen2 >= 4 && len2 >= 4) { + pid = ((data2[0] << 8) | data2[1]) & 0xfff; + prov = (data2[2] << 8) | data2[3]; + descrambler_cat_entry(mux, caid, prov, pid); + data2 += 4; + len2 -= 4; + dlen2 -= 4; } } - pthread_mutex_unlock(&mux->mm_descrambler_lock); + } next: data += dlen; len -= dlen; } - TAILQ_INIT(&removing); - pthread_mutex_lock(&mux->mm_descrambler_lock); - TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link) - if (emm->to_be_removed) { - if (emm->pid != EMM_PID_UNKNOWN) { - caid = emm->caid; - pid = emm->pid; - tvhtrace(LS_DESCRAMBLER, "close emm caid %04X (%i) pid %04X (%i)", caid, caid, pid, pid); - descrambler_close_pid_(mux, emm->opaque, pid); - } - TAILQ_REMOVE(&mux->mm_descrambler_emms, emm, link); - TAILQ_INSERT_TAIL(&removing, emm, link); - } - pthread_mutex_unlock(&mux->mm_descrambler_lock); - while ((emm = TAILQ_FIRST(&removing)) != NULL) { - if (emm->pid != EMM_PID_UNKNOWN) - caclient_caid_update(mux, emm->caid, emm->pid, 0); - TAILQ_REMOVE(&removing, emm, link); - free(emm); - } + descrambler_cat_clean(mux); } int -descrambler_open_emm( mpegts_mux_t *mux, void *opaque, int caid, +descrambler_open_emm( mpegts_mux_t *mux, void *opaque, + int caid, int prov, descrambler_section_callback_t callback ) { descrambler_emm_t *emm; @@ -1608,7 +1647,7 @@ descrambler_open_emm( mpegts_mux_t *mux, void *opaque, int caid, if (mux->mm_descrambler_flush) goto unlock; TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link) { - if (emm->caid == caid && emm->opaque == opaque) { + if (emm->caid == caid && emm->prov == prov && emm->opaque == opaque) { unlock: pthread_mutex_unlock(&mux->mm_descrambler_lock); return 0; @@ -1616,11 +1655,12 @@ unlock: } emm = calloc(1, sizeof(*emm)); emm->caid = caid; + emm->prov = prov; emm->pid = EMM_PID_UNKNOWN; emm->opaque = opaque; emm->callback = callback; LIST_FOREACH(c, &mux->mm_descrambler_caids, link) { - if (c->caid == caid) { + if (c->caid == caid && c->providerid == prov) { emm->pid = pid = c->pid; break; } @@ -1637,7 +1677,7 @@ unlock: } int -descrambler_close_emm( mpegts_mux_t *mux, void *opaque, int caid ) +descrambler_close_emm( mpegts_mux_t *mux, void *opaque, int caid, int prov ) { descrambler_emm_t *emm; int pid; @@ -1646,7 +1686,7 @@ descrambler_close_emm( mpegts_mux_t *mux, void *opaque, int caid ) return 0; pthread_mutex_lock(&mux->mm_descrambler_lock); TAILQ_FOREACH(emm, &mux->mm_descrambler_emms, link) - if (emm->caid == caid && emm->opaque == opaque) + if (emm->caid == caid && emm->prov == prov && emm->opaque == opaque) break; if (!emm) { pthread_mutex_unlock(&mux->mm_descrambler_lock); @@ -1656,7 +1696,9 @@ descrambler_close_emm( mpegts_mux_t *mux, void *opaque, int caid ) pid = emm->pid; if (pid != EMM_PID_UNKNOWN) { caid = emm->caid; - tvhtrace(LS_DESCRAMBLER, "close emm caid %04X (%i) pid %04X (%i) - direct", caid, caid, pid, pid); + prov = emm->prov; + tvhtrace(LS_DESCRAMBLER, "close emm caid %04X (%i) prov %06X (%i) pid %04X (%i) - direct", + caid, caid, prov, prov, pid, pid); descrambler_close_pid_(mux, opaque, pid); } pthread_mutex_unlock(&mux->mm_descrambler_lock); diff --git a/src/descrambler/descrambler.h b/src/descrambler/descrambler.h index b0af578d0..ac5ff312c 100644 --- a/src/descrambler/descrambler.h +++ b/src/descrambler/descrambler.h @@ -170,6 +170,7 @@ typedef struct descrambler_emm { TAILQ_ENTRY(descrambler_emm) link; uint16_t caid; + uint32_t prov; uint16_t pid; unsigned int to_be_removed:1; @@ -210,9 +211,11 @@ int descrambler_open_pid ( struct mpegts_mux *mux, void *opaque, int pid, int descrambler_close_pid ( struct mpegts_mux *mux, void *opaque, int pid ); void descrambler_flush_tables ( struct mpegts_mux *mux ); void descrambler_cat_data ( struct mpegts_mux *mux, const uint8_t *data, int len ); -int descrambler_open_emm ( struct mpegts_mux *mux, void *opaque, int caid, +int descrambler_open_emm ( struct mpegts_mux *mux, void *opaque, + int caid, int provid, descrambler_section_callback_t callback ); -int descrambler_close_emm ( struct mpegts_mux *mux, void *opaque, int caid ); +int descrambler_close_emm ( struct mpegts_mux *mux, void *opaque, + int caid, int provid ); #endif /* __TVH_DESCRAMBLER_H__ */ diff --git a/src/descrambler/emm_reass.c b/src/descrambler/emm_reass.c index 8f66edcf2..5cf3be1f7 100644 --- a/src/descrambler/emm_reass.c +++ b/src/descrambler/emm_reass.c @@ -151,7 +151,7 @@ emm_seca if (len >= 8) { /* XXX this part is untested but should do no harm */ PROVIDERS_FOREACH(ra, i, ep) - if (memcmp(&data[5], &ep->sa[5], 3) == 0) { + if (memcmp(&data[5], &ep->sa[4], 3) == 0) { match = 1; break; }