From 87c553ea368d41d3bb14e07d687249323db6b23b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20=C3=96man?= <andreas@lonelycoder.com>
Date: Fri, 2 May 2008 14:18:56 +0000
Subject: [PATCH] Add framework for notifying subscribers if a transports gets
 in trouble.

Currently only implemented for access denied in code word client.
---
 cwc.c          |  7 +++++--
 serviceprobe.c | 17 ++++++++++++++++-
 transports.c   | 12 ++++++++++++
 transports.h   |  2 ++
 tvhead.h       | 12 ++++++++++++
 5 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/cwc.c b/cwc.c
index 304efcae..a60364e9 100644
--- a/cwc.c
+++ b/cwc.c
@@ -34,6 +34,7 @@
 #include "tsdemux.h"
 #include "ffdecsa/FFdecsa.h"
 #include "dispatch.h"
+#include "transports.h"
 
 #define CWC_KEEPALIVE_INTERVAL 600
 
@@ -497,12 +498,14 @@ cwc_dispatch_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len)
 
     if(len < 19) {
 
-      if(ct->ct_keystate != CT_FORBIDDEN) 
+      if(ct->ct_keystate != CT_FORBIDDEN) {
+	transport_signal_error(t, TRANSPORT_ERROR_NO_ACCESS);
 	syslog(LOG_ERR, 
 	       "Can not descramble \"%s\" for service \"%s\", access denied",
 	       t->tht_identifier, t->tht_servicename);
+	ct->ct_keystate = CT_FORBIDDEN;
+      }
 
-      ct->ct_keystate = CT_FORBIDDEN;
       return 0;
     }
 
diff --git a/serviceprobe.c b/serviceprobe.c
index 1343f11e..84cf430d 100644
--- a/serviceprobe.c
+++ b/serviceprobe.c
@@ -111,6 +111,18 @@ sp_packet_input(void *opaque, th_muxstream_t *tms, th_pkt_t *pkt)
   }
 }
 
+/**
+ * Callback when transport hits an error
+ */
+static void
+sp_err_callback(struct th_subscription *s, int errorcode, void *opaque)
+{
+  sp_t *sp = opaque;
+
+  sp->sp_ok = 0;
+  dtimer_arm(&sp->sp_timer, sp_timeout, sp, 0);
+}
+
 
 /**
  * Setup IPTV (TS over UDP) output
@@ -132,7 +144,8 @@ serviceprobe_engage(void)
   sp->sp_s = s = calloc(1, sizeof(th_subscription_t));
   s->ths_title     = "probe";
   s->ths_weight    = INT32_MAX;
-  
+  s->ths_opaque    = sp;
+
   if(t->tht_status != TRANSPORT_RUNNING)
     transport_start(t, INT32_MAX);
 
@@ -142,6 +155,8 @@ serviceprobe_engage(void)
   sp->sp_muxer = tm = muxer_init(s, sp_packet_input, sp);
   muxer_play(tm, AV_NOPTS_VALUE);
 
+  s->ths_err_callback = sp_err_callback;
+
   dtimer_arm(&sp->sp_timer, sp_timeout, sp, 4);
 }
 
diff --git a/transports.c b/transports.c
index 657e86af..cddbd61f 100644
--- a/transports.c
+++ b/transports.c
@@ -586,3 +586,15 @@ transport_is_available(th_transport_t *t)
 {
   return transport_servicetype_txt(t) && LIST_FIRST(&t->tht_streams);
 }
+
+/**
+ *
+ */
+void
+transport_signal_error(th_transport_t *t, int errorcode)
+{
+  th_subscription_t *s;
+  LIST_FOREACH(s, &t->tht_subscriptions, ths_transport_link)
+    if(s->ths_err_callback != NULL)
+      s->ths_err_callback(s, errorcode, s->ths_opaque);
+}
diff --git a/transports.h b/transports.h
index f528b5b9..4c750c49 100644
--- a/transports.h
+++ b/transports.h
@@ -53,4 +53,6 @@ int transport_is_available(th_transport_t *t);
 
 void transport_destroy(th_transport_t *t);
 
+void transport_signal_error(th_transport_t *t, int errorcode);
+
 #endif /* TRANSPORTS_H */
diff --git a/tvhead.h b/tvhead.h
index 471662a8..a314a2d9 100644
--- a/tvhead.h
+++ b/tvhead.h
@@ -809,6 +809,16 @@ typedef void (subscription_raw_input_t)(struct th_subscription *s,
 					th_stream_t *st,
 					void *opaque);
 
+
+#define TRANSPORT_ERROR_NO_DESCRAMBLER 1
+#define TRANSPORT_ERROR_NO_ACCESS      2
+#define TRANSPORT_ERROR_MUX_ERROR      3
+
+
+typedef void (subscription_err_callback_t)(struct th_subscription *s,
+					   int errorcode,
+					   void *opaque);
+
 typedef struct th_subscription {
   LIST_ENTRY(th_subscription) ths_global_link;
   int ths_weight;
@@ -834,6 +844,8 @@ typedef struct th_subscription {
 
   th_muxer_t *ths_muxer;
 
+  subscription_err_callback_t *ths_err_callback;
+
 } th_subscription_t;
 
 /**