]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
cccam: more cleanups for the extended mode
authorJaroslav Kysela <perex@perex.cz>
Thu, 4 Jan 2018 07:53:34 +0000 (08:53 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 4 Jan 2018 14:03:22 +0000 (15:03 +0100)
src/descrambler/cccam.c
src/descrambler/cclient.c
src/descrambler/cclient.h
src/descrambler/cwc.c

index cda961aa0e22b96352bf024efb1d8d844803c91d..c60b3434d04eac5613291f69fadc07221af26037 100644 (file)
@@ -99,10 +99,13 @@ typedef struct cccam {
   int cccam_extended_conf;
   int cccam_extended;
   int cccam_version;
+
   uint8_t cccam_oscam;
   uint8_t cccam_sendsleep;
   uint8_t cccam_cansid;
 
+  uint8_t cccam_busy;
+
   struct cccam_crypt_block sendblock;
   struct cccam_crypt_block recvblock;
 
@@ -131,6 +134,27 @@ static inline const char *cccam_get_build_str(cccam_t *cccam)
   return cccam_build_str[ver];
 }
 
+/**
+ *
+ */
+static inline int cccam_set_busy(cccam_t *cccam)
+{
+  if (cccam->cccam_extended)
+    return 0;
+  if (cccam->cccam_busy)
+    return 1;
+  cccam->cccam_busy = 1;
+  return 0;
+}
+
+/**
+ *
+ */
+static inline void cccam_unset_busy(cccam_t *cccam)
+{
+  cccam->cccam_busy = 0;
+}
+
 /**
  *
  */
@@ -360,8 +384,6 @@ cccam_handle_partner(cccam_t *cccam, uint8_t *msg)
 {
   char *saveptr;
   char *p;
-  tvhtrace(cccam->cc_subsys, "%s: partner string: '%s'\n",
-           cccam->cc_name, (char *)msg);
   p = strtok_r((char *)msg, "[", &saveptr);
   while (p) {
     if ((p = strtok_r(NULL, ",]", &saveptr)) == NULL)
@@ -373,6 +395,10 @@ cccam_handle_partner(cccam_t *cccam, uint8_t *msg)
     else if (strncmp(p, "SLP", 3) == 0)
       cccam->cccam_sendsleep = 1;
   }
+  tvhinfo(cccam->cc_subsys, "server supports extended capabilities%s%s%s",
+           cccam->cccam_extended ? " EXT" : "",
+           cccam->cccam_cansid ? " SID" : "",
+           cccam->cccam_sendsleep ? " SLP" : "");
 }
 
 /**
@@ -383,7 +409,6 @@ static int
 cccam_running_reply(cccam_t *cccam, uint8_t *buf, int len)
 {
   cc_service_t *ct;
-  cc_ecm_pid_t *ep;
   cc_ecm_section_t *es;
   uint8_t seq;
 
@@ -407,14 +432,16 @@ cccam_running_reply(cccam_t *cccam, uint8_t *buf, int len)
       tvhtrace(cccam->cc_subsys, "%s: keepalive", cccam->cc_name);
       break;
     case MSG_EMM_REQUEST:   /* emm ack */
-      //cccam_send_msg(cccam, MSG_EMM_REQUEST, NULL, 0, 0, 0, 0);
-      //sem_post(&cccam->ecm_mutex);
       tvhtrace(cccam->cc_subsys, "%s: EMM message ACK received", cccam->cc_name);
+      cccam_unset_busy(cccam);
+      break;
+    case MSG_SLEEPSEND:
+      tvhtrace(cccam->cc_subsys, "%s: Sleep send received", cccam->cc_name);
+      if (len >= 5) goto req;
       break;
     case MSG_ECM_NOK1:      /* retry */
     case MSG_ECM_NOK2:      /* decode failed */
-      if (len >= 2 && len < 8)
-        goto req;
+      if (len >= 2 && len < 8) goto req;
       if (len > 5) {
         /* partner detection */
         if (len >= 12 && strncmp((char *)buf + 4, "PARTNER:", 8) == 0) {
@@ -427,29 +454,12 @@ cccam_running_reply(cccam_t *cccam, uint8_t *buf, int len)
     //case MSG_CMD_05:      /* ? */
     case MSG_ECM_REQUEST: { /* request reply */
 req:
-      seq = buf[0];
-      LIST_FOREACH(ct, &cccam->cc_services, cs_link)
-        LIST_FOREACH(ep, &ct->cs_pids, ep_link)
-          LIST_FOREACH(es, &ep->ep_sections, es_link)
-            if(es->es_seq == seq) {
-              if (es->es_resolved) {
-                mpegts_service_t *t = (mpegts_service_t *)ct->td_service;
-                tvhdebug(cccam->cc_subsys,
-                         "%s: Ignore %sECM (PID %d) for service \"%s\" from %s (seq %i)",
-                         cccam->cc_name,
-                         es->es_pending ? "duplicate " : "",
-                         ep->ep_capid, t->s_dvb_svcname, ct->td_nicename, es->es_seq);
-                return 0;
-              }
-              if (es->es_pending) {
-                cccam_handle_keys(cccam, ct, es, buf, len, seq);
-                return 0;
-              }
-            }
-      tvhwarn(cccam->cc_subsys, "%s: Got unexpected ECM reply (seqno: %d)",
-              cccam->cc_name, seq);
-      break;
-
+      seq = cccam->cccam_extended ? buf[0] : 1;
+      es = cc_find_pending_section((cclient_t *)cccam, seq, &ct);
+      if (es)
+        cccam_handle_keys(cccam, ct, es, buf, len, seq);
+      cccam_unset_busy(cccam);
+      return 0;
     }
     case MSG_SRV_DATA:
       if (len == 0x4c) {
@@ -523,7 +533,7 @@ cccam_send_msg(cccam_t *cccam, cccam_msg_type_t cmd,
   if (cmd == MSG_NO_HEADER) {
     memcpy(netbuf, buf, len);
   } else {
-    netbuf[0] = seq;
+    netbuf[0] = cccam->cccam_extended ? seq : 0;
     netbuf[1] = cmd;
     netbuf[2] = len >> 8;
     netbuf[3] = len;
@@ -696,6 +706,7 @@ cccam_init_session(void *cc)
   uint8_t buf[256];
   int r;
 
+  cccam->cccam_oscam = 0;
   cccam->cccam_extended = 0;
   cccam->cccam_sendsleep = 0;
   cccam->cccam_cansid = 0;
@@ -744,6 +755,12 @@ cccam_send_ecm(void *cc, cc_service_t *ct, cc_ecm_section_t *es,
     return 0;
   }
 
+  if (cccam_set_busy(cccam)) {
+    tvhinfo(cccam->cc_subsys, "%s: Ignore ECM request %02X (server is busy)",
+            cccam->cc_name, msg[0]);
+    return 0;
+  }
+
   seq = atomic_add(&cccam->cc_seq, 1);
   caid = es->es_caid;
   provid = es->es_provid;
@@ -789,6 +806,12 @@ cccam_send_emm(void *cc, cc_service_t *ct, cc_card_data_t *pcard,
     return;
   }
 
+  if (cccam_set_busy(cccam)) {
+    tvhinfo(cccam->cc_subsys, "%s: Ignore EMM request %02X (server is busy)",
+            cccam->cc_name, msg[0]);
+    return;
+  }
+
   seq = atomic_add(&cccam->cc_seq, 1);
   caid = pcard->cs_ra.caid;
   card_id = pcard->cccam.cs_id;  
@@ -807,6 +830,9 @@ cccam_send_emm(void *cc, cc_service_t *ct, cc_card_data_t *pcard,
   buf[10] = card_id & 0xff;
   buf[11] = len;
   memcpy(buf + 12, msg, len);
+
+  cccam_set_busy(cccam);
+
   cccam_send_msg(cccam, MSG_EMM_REQUEST, buf, 12 + len, 1, seq, card_id);
 }
 
index 6a36a93934d8c1121671179a91eeee8d5ca55a8c..b0921feb34cd0576875ef8c051cd0575329e654a 100644 (file)
@@ -293,6 +293,41 @@ forbid:
   }
 }
 
+/**
+ *
+ */
+cc_ecm_section_t *
+cc_find_pending_section(cclient_t *cc, uint32_t seq, cc_service_t **_ct)
+{
+  cc_service_t *ct;
+  cc_ecm_pid_t *ep;
+  cc_ecm_section_t *es;
+
+  if (_ct) *_ct = NULL;
+  LIST_FOREACH(ct, &cc->cc_services, cs_link)
+    LIST_FOREACH(ep, &ct->cs_pids, ep_link)
+      LIST_FOREACH(es, &ep->ep_sections, es_link)
+        if(es->es_seq == seq) {
+          if (es->es_resolved) {
+            mpegts_service_t *t = (mpegts_service_t *)ct->td_service;
+            tvhdebug(cc->cc_subsys,
+                     "%s: Ignore %sECM (PID %d) for service \"%s\" from %s (seq %i)",
+                     cc->cc_name,
+                     es->es_pending ? "duplicate " : "",
+                     ep->ep_capid, t->s_dvb_svcname, ct->td_nicename, es->es_seq);
+            if (_ct) *_ct = ct;
+            return NULL;
+          }
+          if (es->es_pending) {
+            if (_ct) *_ct = ct;
+            return es;
+          }
+        }
+  tvhwarn(cc->cc_subsys, "%s: Got unexpected ECM reply (seqno: %d)",
+          cc->cc_name, seq);
+  return NULL;
+}
+
 /**
  *
  */
index b7144c86a344deafac37c8cf48781ada271de962..389d0a31b3947f7054adf99645e96ed9348d2fe9 100644 (file)
@@ -203,6 +203,9 @@ void cc_ecm_reply
   (cc_service_t *ct, cc_ecm_section_t *es, int key_type,
    uint8_t *key_even, uint8_t *key_odd, int seq);
 
+cc_ecm_section_t *cc_find_pending_section
+  (cclient_t *cc, uint32_t seq, cc_service_t **ct);
+
 void cc_write_message(cclient_t *cc, cc_message_t *msg, int enq);
 int cc_read(cclient_t *cc, void *buf, size_t len, int timeout);
 
index 24f54245420cbf5d79ba6de2f6f492989529c18e..917f40a8089f6d70e111e8872a7cd3a56c772075 100644 (file)
@@ -415,7 +415,6 @@ static int
 cwc_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len)
 {
   cc_service_t *ct;
-  cc_ecm_pid_t *ep;
   cc_ecm_section_t *es;
   uint16_t seq;
   int plen;
@@ -433,26 +432,9 @@ cwc_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len)
       seq = (msg[2] << 8) | msg[3];
       len -= 12;
       msg += 12;
-      LIST_FOREACH(ct, &cwc->cc_services, cs_link)
-        LIST_FOREACH(ep, &ct->cs_pids, ep_link)
-          LIST_FOREACH(es, &ep->ep_sections, es_link)
-            if(es->es_seq == seq) {
-              if (es->es_resolved) {
-                mpegts_service_t *t = (mpegts_service_t *)ct->td_service;
-                tvhdebug(cwc->cc_subsys,
-                         "%s: Ignore %sECM (PID %d) for service \"%s\" from %s (seq %i)",
-                         cwc->cc_name,
-                         es->es_pending ? "duplicate " : "",
-                         ep->ep_capid, t->s_dvb_svcname, ct->td_nicename, es->es_seq);
-                return 0;
-              }
-              if (es->es_pending) {
-                handle_ecm_reply(ct, es, msg, len, seq);
-                return 0;
-              }
-            }
-      tvhwarn(cwc->cc_subsys, "%s: Got unexpected ECM reply (seqno: %d, len: %d)",
-              cwc->cc_name, seq, len);
+      es = cc_find_pending_section((cclient_t *)cwc, seq, &ct);
+      if (es)
+        handle_ecm_reply(ct, es, msg, len, seq);
       break;
 
     case 0xD3: