]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
descrambler: move some of the reader logic to the common code
authorJaroslav Kysela <perex@perex.cz>
Mon, 9 Jun 2014 20:07:20 +0000 (22:07 +0200)
committerJaroslav Kysela <perex@perex.cz>
Tue, 10 Jun 2014 12:02:37 +0000 (14:02 +0200)
src/descrambler.h
src/descrambler/capmt.c
src/descrambler/cwc.c
src/descrambler/descrambler.c

index 26143b3dcd7fb1158e3b3deef051a9bb6ffaf40e..2d21103c163dcb69b92eeafe2c7ae1e8c6587437 100755 (executable)
@@ -37,6 +37,8 @@ struct mpegts_mux;
 typedef struct th_descrambler {
   LIST_ENTRY(th_descrambler) td_service_link;
 
+  char *td_nicename;
+
   enum {
     DS_UNKNOWN,
     DS_RESOLVED,
index 382223f1cd7bf6d3d25f4b6d6378111cef717c02..cdee0a2e7dc58d2d847abbc9243bbbb277472263 100644 (file)
@@ -739,6 +739,7 @@ capmt_service_destroy(th_descrambler_t *td)
   pthread_mutex_unlock(&capmt->capmt_mutex);
 
   tvhcsa_destroy(&ct->ct_csa);
+  free(ct->td_nicename);
   free(ct);
 }
 
@@ -1660,6 +1661,7 @@ capmt_service_start(service_t *s)
   mpegts_service_t *t = (mpegts_service_t*)s;
   elementary_stream_t *st;
   int tuner = -1, i, change;
+  char buf[512];
   
   lock_assert(&global_lock);
 
@@ -1748,6 +1750,10 @@ capmt_service_start(service_t *s)
 
     td = (th_descrambler_t *)ct;
     tvhcsa_init(td->td_csa = &ct->ct_csa);
+    snprintf(buf, sizeof(buf), "capmt-%s-%i",
+                               capmt->capmt_sockfile,
+                               capmt->capmt_port);
+    td->td_nicename    = strdup(buf);
     td->td_service     = s;
     td->td_stop        = capmt_service_destroy;
     td->td_caid_change = capmt_caid_change;
index 9506c877ae5faaaca73361f13393638c4d3629a4..551a9ecf4d3525d636ecb77f8172d6a585629ee7 100755 (executable)
@@ -687,9 +687,8 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg,
                 int len, int seq)
 {
   mpegts_service_t *t = (mpegts_service_t *)ct->td_service;
+  th_descrambler_t *td;
   ecm_pid_t *ep, *epn;
-  cwc_service_t *ct2;
-  cwc_t *cwc2;
   char chaninfo[32];
   int i;
   int64_t delay = (getmonoclock() - es->es_time) / 1000LL; // in ms
@@ -709,25 +708,19 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg,
 
     if (es->es_nok > 2) {
       tvhlog(LOG_DEBUG, "cwc",
-             "Too many NOKs for service \"%s\"%s from %s:%i",
-             t->s_dvb_svcname, chaninfo, ct->cs_cwc->cwc_hostname,
-             ct->cs_cwc->cwc_port);
+             "Too many NOKs for service \"%s\"%s from %s",
+             t->s_dvb_svcname, chaninfo, ct->td_nicename);
       goto forbid;
     }
 
-    TAILQ_FOREACH(cwc2, &cwcs, cwc_link) {
-      LIST_FOREACH(ct2, &cwc2->cwc_services, cs_link) {
-        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,
-           t->s_dvb_svcname, ct2->cs_cwc->cwc_hostname, ct2->cs_cwc->cwc_port);
-          es->es_nok = 3; /* do not send more ECM requests */
-          goto forbid;
-        }
+    LIST_FOREACH(td, &t->s_descramblers, td_service_link)
+      if (td != (th_descrambler_t *)ct && td->td_keystate == DS_RESOLVED) {
+        tvhlog(LOG_DEBUG, "cwc",
+              "NOK from %s: Already has a key for service \"%s\", from %s",
+              ct->td_nicename,  t->s_dvb_svcname, td->td_nicename);
+        es->es_nok = 3; /* do not send more ECM requests */
+        ct->td_keystate = DS_IDLE;
       }
-    }
 
     tvhlog(LOG_DEBUG, "cwc", "Received NOK for service \"%s\"%s (seqno: %d "
           "Req delay: %"PRId64" ms)", t->s_dvb_svcname, chaninfo, seq, delay);
@@ -746,8 +739,8 @@ forbid:
     }
     tvhlog(LOG_ERR, "cwc",
           "Can not descramble service \"%s\", access denied (seqno: %d "
-          "Req delay: %"PRId64" ms)",
-          t->s_dvb_svcname, seq, delay);
+          "Req delay: %"PRId64" ms) from %s",
+          t->s_dvb_svcname, seq, delay, ct->td_nicename);
 
     ct->td_keystate = DS_FORBIDDEN;
     ct->ecm_state = ECM_RESET;
@@ -762,7 +755,8 @@ forbid:
 
     if(t->s_dvb_prefcapid == 0 || t->s_dvb_prefcapid != ct->cs_channel) {
       t->s_dvb_prefcapid = ct->cs_channel;
-      tvhlog(LOG_DEBUG, "cwc", "Saving prefered PID %d", t->s_dvb_prefcapid);
+      tvhlog(LOG_DEBUG, "cwc", "Saving prefered PID %d for %s",
+                               t->s_dvb_prefcapid, ct->td_nicename);
       service_request_save((service_t*)t, 0);
     }
 
@@ -778,24 +772,10 @@ forbid:
           msg[3 + 10],msg[3 + 11],msg[3 + 12],msg[3 + 13],msg[3 + 14],
           msg[3 + 15], seq, delay);
 
-    TAILQ_FOREACH(cwc2, &cwcs, cwc_link) {
-      LIST_FOREACH(ct2, &cwc2->cwc_services, cs_link) {
-        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);
-          return;
-        }
-      }
-    }
-    
     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);
+            "Obtained key for service \"%s\" in %"PRId64" ms, from %s",
+            t->s_dvb_svcname, delay, ct->td_nicename);
 
     descrambler_keys((th_descrambler_t *)ct, msg + 3, msg + 3 + 8);
 
@@ -809,7 +789,8 @@ forbid:
         for(i = 0; i < 256; i++)
           free(ep->ep_sections[i]);
         LIST_REMOVE(ep, ep_link);
-        tvhlog(LOG_WARNING, "cwc", "Delete ECM (PID %d) for service \"%s\"", ep->ep_pid, t->s_dvb_svcname);
+        tvhlog(LOG_WARNING, "cwc", "Delete ECM (PID %d) for service \"%s\" from %s",
+                                   ep->ep_pid, t->s_dvb_svcname, ct->td_nicename);
         free(ep);
         ep = epn;
       }
@@ -1920,6 +1901,7 @@ cwc_service_destroy(th_descrambler_t *td)
   LIST_REMOVE(ct, cs_link);
 
   tvhcsa_destroy(&ct->cs_csa);
+  free(ct->td_nicename);
   free(ct);
 }
 
@@ -1937,6 +1919,7 @@ cwc_service_start(service_t *t)
   elementary_stream_t *st;
   caid_t *c;
   struct cs_card_data *pcard;
+  char buf[512];
 
   extern const idclass_t mpegts_service_class;
   if (!idnode_is_instance(&t->s_id, &mpegts_service_class))
@@ -1975,6 +1958,8 @@ cwc_service_start(service_t *t)
 
     td                   = (th_descrambler_t *)ct;
     tvhcsa_init(td->td_csa = &ct->cs_csa);
+    snprintf(buf, sizeof(buf), "cwc-%s-%i", cwc->cwc_hostname, cwc->cwc_port);
+    td->td_nicename      = strdup(buf);
     td->td_service       = t;
     td->td_stop          = cwc_service_destroy;
     LIST_INSERT_HEAD(&t->s_descramblers, td, td_service_link);
index 32eed8309b34c35ef6b3f9a9a86d8a21c8b2c9da..964dcf7e2487ceb9c7893d6ec3aa5ab45afdafe6 100755 (executable)
@@ -176,9 +176,29 @@ void
 descrambler_keys ( th_descrambler_t *td,
                    const uint8_t *even, const uint8_t *odd )
 {
-  th_descrambler_runtime_t *dr = td->td_service->s_descramble;
+  service_t *t = td->td_service;
+  th_descrambler_runtime_t *dr;
+  th_descrambler_t *td2;
   int i, j = 0;
 
+  if (t == NULL || (dr = t->s_descramble) == NULL) {
+    td->td_keystate = DS_FORBIDDEN;
+    return;
+  }
+
+  pthread_mutex_lock(&t->s_stream_mutex);
+
+  LIST_FOREACH(td2, &t->s_descramblers, td_service_link)
+    if (td2 != td && td->td_keystate == DS_RESOLVED) {
+      tvhlog(LOG_DEBUG, "descrambler",
+                        "Already has a key from %s for service \"%s\", ignoring %s",
+                        td->td_nicename,
+                        ((mpegts_service_t *)td2->td_service)->s_dvb_svcname,
+                        ((mpegts_service_t *)t)->s_dvb_svcname);
+      td->td_keystate = DS_IDLE;
+      goto fin;
+    }
+
   for (i = 0; i < 8; i++)
     if (even[i]) {
       j++;
@@ -192,18 +212,23 @@ descrambler_keys ( th_descrambler_t *td,
       break;
     }
 
-  if (j == 0) {
-    tvhlog(LOG_DEBUG, "descrambler", "Empty keys received for service \"%s\"",
-                      ((mpegts_service_t *)td->td_service)->s_dvb_svcname);
-    return;
+  if (j > 0) {
+    if (td->td_keystate != DS_RESOLVED)
+      tvhlog(LOG_DEBUG, "descrambler",
+                        "Obtained key from %s for service \"%s\"",
+                        td->td_nicename,
+                        ((mpegts_service_t *)t)->s_dvb_svcname);
+    dr->dr_ecm_key_time = dispatch_clock;
+    td->td_keystate = DS_RESOLVED;
+  } else {
+    tvhlog(LOG_DEBUG, "descrambler",
+                      "Empty keys received from %s for service \"%s\"",
+                      td->td_nicename,
+                      ((mpegts_service_t *)t)->s_dvb_svcname);
   }
 
-  if (td->td_keystate != DS_RESOLVED)
-    tvhlog(LOG_DEBUG, "descrambler", "Obtained key for service \"%s\"",
-                      ((mpegts_service_t *)td->td_service)->s_dvb_svcname);
-
-  dr->dr_ecm_key_time = dispatch_clock;
-  td->td_keystate = DS_RESOLVED;
+fin:
+  pthread_mutex_unlock(&t->s_stream_mutex);
 }
 
 static inline void
@@ -224,6 +249,8 @@ descrambler_descramble ( service_t *t,
   int count, failed, off, size;
   uint8_t *tsb2;
 
+  lock_assert(&t->s_stream_mutex);
+
   if (dr == NULL)
     return -1;
   count = failed = 0;