]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
descrambler: improve EMM handling - add provider id checks
authorJaroslav Kysela <perex@perex.cz>
Sun, 14 Oct 2018 15:53:17 +0000 (17:53 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 19 Nov 2018 13:04:21 +0000 (14:04 +0100)
src/descrambler/caclient.c
src/descrambler/caclient.h
src/descrambler/cclient.c
src/descrambler/cclient.h
src/descrambler/descrambler.c
src/descrambler/descrambler.h
src/descrambler/emm_reass.c

index f28020fc83177668ff020d16cea33ca22cb35714..d3f4b0fcadfec75c9135da19776913261245d70e 100644 (file)
@@ -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);
 }
 
index c9199ea0c86de03a10b2e5991ea25a87b9e7841d..397c86ac199ad68aa6b7d2dd1fc3f4929d43aa59 100644 (file)
@@ -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);
 
index c503a30ddb3ade8faaea7dc49f93e199267049f6..6cca85353712ac81b7f5d11b5d89ba1b840a8758 100644 (file)
@@ -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);
+                   }
+          }
         }
       }
     }
index c9d913c445869f3fab59ce28a4067417d299c1ca..8accc403cfe5d55e30c28a2918d47d757a23b504 100644 (file)
@@ -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);
index fcbbaab8dd2c71d324cf06686712f539a6f1cf2e..506e464b05f9025c2f64925c2378cd11535e74d3 100644 (file)
@@ -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);
index b0af578d05689115f355ea1399e559d1e9c3d8ef..ac5ff312c962c92d716b1a4a062ccd390f4cd533 100644 (file)
@@ -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__ */
 
index 8f66edcf24ab300f073c1b97e513fbf74c38ce00..5cf3be1f7f651c15df9dd226b10530b127124f4d 100644 (file)
@@ -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;
         }