From e888e4e5ff71413596844d8e196c5532443f23dc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 5 Apr 2017 18:08:57 +0200 Subject: [PATCH] subscription: recode CA check - use timer, fixes #4303 --- src/service.c | 5 ++-- src/service.h | 1 + src/subscriptions.c | 71 +++++++++++++++++++++++++++++---------------- src/subscriptions.h | 2 +- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/service.c b/src/service.c index da036a8cf..d875b334d 100644 --- a/src/service.c +++ b/src/service.c @@ -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] " : ""); diff --git a/src/service.h b/src/service.h index daba9b43d..d215f63d5 100644 --- a/src/service.h +++ b/src/service.h @@ -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 diff --git a/src/subscriptions.c b/src/subscriptions.c index 9c5673f37..9364aacfe 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -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) diff --git a/src/subscriptions.h b/src/subscriptions.h index 4915841c8..330f3bddb 100644 --- a/src/subscriptions.h +++ b/src/subscriptions.h @@ -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 */ -- 2.47.2