]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
subscription: recode CA check - use timer, fixes #4303
authorJaroslav Kysela <perex@perex.cz>
Wed, 5 Apr 2017 16:08:57 +0000 (18:08 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 5 Apr 2017 16:08:57 +0000 (18:08 +0200)
src/service.c
src/service.h
src/subscriptions.c
src/subscriptions.h

index da036a8cf8af93b5d75eaf8f88f8a89fde39cfd2..d875b334d71588ec26735f8bc7f85aa262255753 100644 (file)
@@ -749,7 +749,7 @@ service_find_instance
     if (flags & SUBSCRIPTION_SWSERVICE) {
       for (next = TAILQ_NEXT(si, si_link); next;
            next = TAILQ_NEXT(next, si_link))
-        if (si->si_s == next->si_s)
+        if (si->si_s == next->si_s && si->si_error)
           next->si_error = si->si_error;
     }
   }
@@ -1392,7 +1392,7 @@ service_set_streaming_status_flags_(service_t *t, int set)
 
   t->s_streaming_status = set;
 
-  tvhdebug(LS_SERVICE, "%s: Status changed to %s%s%s%s%s%s%s%s%s",
+  tvhdebug(LS_SERVICE, "%s: Status changed to %s%s%s%s%s%s%s%s%s%s",
         service_nicename(t),
         set & TSS_INPUT_HARDWARE ? "[Hardware input] " : "",
         set & TSS_INPUT_SERVICE  ? "[Input on service] " : "",
@@ -1400,6 +1400,7 @@ service_set_streaming_status_flags_(service_t *t, int set)
         set & TSS_PACKETS        ? "[Reassembled packets] " : "",
         set & TSS_NO_DESCRAMBLER ? "[No available descrambler] " : "",
         set & TSS_NO_ACCESS      ? "[No access] " : "",
+        set & TSS_CA_CHECK       ? "[CA check] " : "",
         set & TSS_TUNING         ? "[Tuning failed] " : "",
         set & TSS_GRACEPERIOD    ? "[Graceperiod expired] " : "",
         set & TSS_TIMEOUT        ? "[Data timeout] " : "");
index daba9b43dbf9a96f7f7badc16e3b09035300139b..d215f63d5af3409e30303eede0e844c99792ebaa 100644 (file)
@@ -426,6 +426,7 @@ typedef struct service {
 #define TSS_MUX_PACKETS      0x4
 #define TSS_PACKETS          0x8
 #define TSS_NO_ACCESS        0x10
+#define TSS_CA_CHECK         0x20
 
 
   // Errors
index 9c5673f377be90dd3cb6b0ca6d58615c2d59bd9d..9364aacfebc62a110323710be11eb86ff6d426ee 100644 (file)
@@ -291,6 +291,29 @@ subscription_reschedule_cb(void *aux)
   subscription_reschedule();
 }
 
+/**
+ *
+ */
+static void
+subscription_ca_check_cb(void *aux)
+{
+  th_subscription_t *s = aux;
+  service_t *t = s->ths_service;
+  int flags = 0;
+
+  if (t == NULL)
+    return;
+
+  pthread_mutex_lock(&t->s_stream_mutex);
+
+  if(t->s_streaming_status & TSS_NO_ACCESS)
+    flags |= TSS_CA_CHECK;
+  if (flags)
+    service_set_streaming_status_flags(t, flags);
+
+  pthread_mutex_unlock(&t->s_stream_mutex);
+}
+
 /**
  *
  */
@@ -312,8 +335,8 @@ subscription_start_instance
                              s->ths_flags, s->ths_timeout,
                              mclk() > s->ths_postpone_end ?
                                0 : mono2sec(s->ths_postpone_end - mclk()));
-  if (si)
-    s->ths_service_start = mclk();
+  if (si && (s->ths_flags & SUBSCRIPTION_CONTACCESS))
+    mtimer_arm_rel(&s->ths_ca_check_timer, subscription_ca_check_cb, s, s->ths_ca_timeout);
   return s->ths_current_instance = si;
 }
 
@@ -542,14 +565,9 @@ static streaming_ops_t subscription_input_direct_ops = {
 static void
 subscription_input(void *opaque, streaming_message_t *sm)
 {
-  int error, mask2 = 0;
+  int error;
   th_subscription_t *s = opaque;
 
-  /* handle NO_ACCESS condition with some delay */
-  if(sm->sm_code & TSS_NO_ACCESS &&
-     s->ths_service_start + s->ths_ca_timeout < mclk())
-    mask2 |= TSS_NO_ACCESS;
-
   if(subgetstate(s) == SUBSCRIPTION_TESTING_SERVICE) {
     // We are just testing if this service is good
 
@@ -565,19 +583,20 @@ subscription_input(void *opaque, streaming_message_t *sm)
     }
 
     if(sm->sm_type == SMT_SERVICE_STATUS &&
-       (sm->sm_code & (TSS_ERRORS|mask2))) {
+       (sm->sm_code & (TSS_ERRORS|TSS_CA_CHECK))) {
       // No, mark our subscription as bad_service
       // the scheduler will take care of things
       error = tss2errcode(sm->sm_code);
-      if (error != SM_CODE_NO_ACCESS ||
-          (s->ths_flags & SUBSCRIPTION_CONTACCESS) == 0) {
-        if (error > s->ths_testing_error)
-          s->ths_testing_error = error;
-        subsetstate(s, SUBSCRIPTION_BAD_SERVICE);
-        streaming_msg_free(sm);
-        return;
-      }
-    }
+      if (error != SM_CODE_OK)
+        if (error != SM_CODE_NO_ACCESS ||
+            (s->ths_flags & SUBSCRIPTION_CONTACCESS) == 0) {
+          if (error > s->ths_testing_error)
+            s->ths_testing_error = error;
+          subsetstate(s, SUBSCRIPTION_BAD_SERVICE);
+          streaming_msg_free(sm);
+          return;
+        }
+  }
 
     if(sm->sm_type == SMT_SERVICE_STATUS &&
        (sm->sm_code & TSS_PACKETS)) {
@@ -597,14 +616,15 @@ subscription_input(void *opaque, streaming_message_t *sm)
   }
 
   if (sm->sm_type == SMT_SERVICE_STATUS &&
-      (sm->sm_code & (TSS_TUNING|TSS_TIMEOUT|mask2))) {
+      (sm->sm_code & (TSS_TUNING|TSS_TIMEOUT|TSS_CA_CHECK))) {
     error = tss2errcode(sm->sm_code);
-    if (error != SM_CODE_NO_ACCESS ||
-        (s->ths_flags & SUBSCRIPTION_CONTACCESS) == 0) {
-      if (error > s->ths_testing_error)
-        s->ths_testing_error = error;
-      s->ths_state = SUBSCRIPTION_BAD_SERVICE;
-    }
+    if (error != SM_CODE_OK)
+      if (error != SM_CODE_NO_ACCESS ||
+          (s->ths_flags & SUBSCRIPTION_CONTACCESS) == 0) {
+        if (error > s->ths_testing_error)
+          s->ths_testing_error = error;
+        s->ths_state = SUBSCRIPTION_BAD_SERVICE;
+      }
   }
 
   /* Pass to direct handler to log traffic */
@@ -714,6 +734,7 @@ subscription_unsubscribe(th_subscription_t *s, int flags)
   service_instance_list_clear(&s->ths_instances);
 
   mtimer_disarm(&s->ths_remove_timer);
+  mtimer_disarm(&s->ths_ca_check_timer);
 
   if ((flags & UNSUBSCRIBE_FINAL) != 0 ||
       (s->ths_flags & SUBSCRIPTION_ONESHOT) != 0)
index 4915841c8b330a27974bfcb0ae2ba2aa3476c802..330f3bddb013b987457569aeda778ea74b7fb1a6 100644 (file)
@@ -83,6 +83,7 @@ typedef struct th_subscription {
   int ths_testing_error;
 
   mtimer_t ths_remove_timer;
+  mtimer_t ths_ca_check_timer;
 
   LIST_ENTRY(th_subscription) ths_channel_link;
   struct channel *ths_channel;          /* May be NULL if channel has been
@@ -97,7 +98,6 @@ typedef struct th_subscription {
 
   char *ths_title; /* display title */
   time_t ths_start;  /* time when subscription started */
-  int64_t ths_service_start; /* time when service started */
   int ths_total_err; /* total errors during entire subscription */
   uint64_t ths_total_bytes_in; /* total bytes since the subscription started */
   uint64_t ths_total_bytes_out; /* total bytes since the subscription started */