diff --git a/docs/html/config_services.html b/docs/html/config_services.html index 7975687e..d48355cc 100644 --- a/docs/html/config_services.html +++ b/docs/html/config_services.html @@ -51,6 +51,17 @@
Pref. CA PID
The Preferred Conditional Access Packet Identifier. Used for decrypting scrambled streams. +
Lock Pref. CA PID +
The locking mechanism selection for The Preferred Conditional Access Packet Identifier. +
+
Off +
Automatic Preferred Conditional Access Packet Identifier selection. +
On +
Keep Preferred Conditional Access Packet Identifier selection (no automatic modifications allowed). +
Only Pref. CA PID +
Filter mode - use only Preferred Conditional Access Packet Identifier for the streams decryption. +
+
Character Set
The character encoding for this service (e.g. UTF-8). diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index e60ce7a4..babd1a81 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -1530,6 +1530,9 @@ capmt_caid_change(th_descrambler_t *td) lock_assert(&t->s_stream_mutex); TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) { + if (t->s_dvb_prefcapid_lock == 2 && + t->s_dvb_prefcapid != st->es_pid) + continue; LIST_FOREACH(c, &st->es_caids, link) { /* search ecmpid in list */ LIST_FOREACH(cce, &ct->ct_caid_ecm, cce_link) @@ -1809,6 +1812,9 @@ capmt_service_start(service_t *s) pthread_mutex_lock(&t->s_stream_mutex); TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) { caid_t *c; + if (t->s_dvb_prefcapid_lock == 2 && + t->s_dvb_prefcapid != st->es_pid) + continue; LIST_FOREACH(c, &st->es_caids, link) { if(c == NULL || c->use == 0) continue; diff --git a/src/descrambler/cwc.c b/src/descrambler/cwc.c index 36d70cea..af9f64c4 100755 --- a/src/descrambler/cwc.c +++ b/src/descrambler/cwc.c @@ -101,6 +101,7 @@ typedef struct ecm_section { uint16_t es_seq; char es_nok; char es_pending; + char es_resolved; int64_t es_time; // time request was sent size_t es_ecmsize; uint8_t es_ecm[4070]; @@ -711,10 +712,12 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, { mpegts_service_t *t = (mpegts_service_t *)ct->td_service; th_descrambler_t *td; - ecm_pid_t *ep, *epn; + ecm_pid_t *ep; + ecm_section_t *es2; char chaninfo[32]; - int i; + int i, j; int64_t delay = (getmonoclock() - es->es_time) / 1000LL; // in ms + es->es_pending = 0; snprintf(chaninfo, sizeof(chaninfo), " (PID %d)", es->es_channel); @@ -749,17 +752,20 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, "Req delay: %"PRId64" ms)", t->s_dvb_svcname, chaninfo, seq, delay); forbid: + j = 0; LIST_FOREACH(ep, &ct->cs_pids, ep_link) { - for(i = 0; i <= ep->ep_last_section; i++) - if(ep->ep_sections[i] == NULL) { - if(es->es_nok < 2) /* only first hit is allowed */ - return; - } else { - if(ep->ep_sections[i]->es_pending || - ep->ep_sections[i]->es_nok == 0) + for(i = 0; i <= ep->ep_last_section; i++) { + es2 = ep->ep_sections[i]; + if(es2 && es2 != es && es2->es_nok == 0) { + if (es2->es_pending) return; + j++; } + } } + if (j && es->es_nok < 2) /* only first hit is allowed */ + return; + tvhlog(LOG_ERR, "cwc", "Can not descramble service \"%s\", access denied (seqno: %d " "Req delay: %"PRId64" ms) from %s", @@ -776,7 +782,9 @@ forbid: ct->cs_channel = es->es_channel; ct->ecm_state = ECM_VALID; - if(t->s_dvb_prefcapid == 0 || t->s_dvb_prefcapid != ct->cs_channel) { + if(t->s_dvb_prefcapid == 0 || + (t->s_dvb_prefcapid != ct->cs_channel && + t->s_dvb_prefcapid_lock == 0)) { t->s_dvb_prefcapid = ct->cs_channel; tvhlog(LOG_DEBUG, "cwc", "Saving prefered PID %d for %s", t->s_dvb_prefcapid, ct->td_nicename); @@ -802,20 +810,13 @@ forbid: descrambler_keys((th_descrambler_t *)ct, msg + 3, msg + 3 + 8); - ep = LIST_FIRST(&ct->cs_pids); - while(ep != NULL) { - if (ct->cs_channel == ep->ep_pid) { - ep = LIST_NEXT(ep, ep_link); - } - else { - epn = LIST_NEXT(ep, ep_link); - 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\" from %s", - ep->ep_pid, t->s_dvb_svcname, ct->td_nicename); - free(ep); - ep = epn; + LIST_FOREACH(ep, &ct->cs_pids, ep_link) { + for(i = 0; i < ep->ep_last_section; i++) { + es2 = ep->ep_sections[i]; + if (es2) { + es2->es_resolved = 1; + es2->es_pending = 0; + } } } } @@ -848,9 +849,19 @@ cwc_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len) for(i = 0; i <= ep->ep_last_section; i++) { es = ep->ep_sections[i]; if(es != NULL) { - if(es->es_seq == seq && es->es_pending) { - handle_ecm_reply(ct, es, msg, len, seq); - return 0; + if(es->es_seq == seq) { + if (es->es_resolved) { + mpegts_service_t *t = (mpegts_service_t *)ct->td_service; + tvhlog(LOG_WARNING, "cwc", + "Ignore %sECM (PID %d) for service \"%s\" from %s (seq %i)", + es->es_pending ? "duplicate " : "", + ep->ep_pid, 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; + } } } } @@ -1194,8 +1205,8 @@ cwc_thread(void *aux) ts.tv_nsec = 0; tvhlog(LOG_INFO, "cwc", - "%s:%i: Automatic connection attempt in in %d seconds", - cwc->cwc_hostname, cwc->cwc_port, d); + "%s:%i: Automatic connection attempt in %d seconds", + cwc->cwc_hostname, cwc->cwc_port, d-1); pthread_cond_timedwait(&cwc_config_changed, &cwc_mutex, &ts); } @@ -1735,6 +1746,7 @@ cwc_table_input(void *opaque, int pid, const uint8_t *data, int len) es->es_channel = channel; es->es_section = section; es->es_pending = 1; + es->es_resolved = 0; memcpy(es->es_ecm, data, len); es->es_ecmsize = len; @@ -1980,6 +1992,9 @@ cwc_service_start(service_t *t) LIST_FOREACH(pcard, &cwc->cwc_cards, cs_card) { if (pcard->cwc_caid == 0) continue; TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) { + if (((mpegts_service_t *)t)->s_dvb_prefcapid_lock == 2 && + ((mpegts_service_t *)t)->s_dvb_prefcapid != st->es_pid) + continue; LIST_FOREACH(c, &st->es_caids, link) { if (c->use && c->caid == pcard->cwc_caid) break; diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 292d2527..791e56be 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -428,6 +428,7 @@ struct mpegts_service uint16_t s_dvb_servicetype; char *s_dvb_charset; uint16_t s_dvb_prefcapid; + int s_dvb_prefcapid_lock; /* * EIT/EPG control diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index ed41eaf6..e4dc026b 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -55,6 +55,17 @@ mpegts_service_class_get_network ( void *ptr ) return &s; } +static htsmsg_t * +mpegts_service_pref_capid_lock_list ( void *o ) +{ + static const struct strtab tab[] = { + { "Off", 0 }, + { "On", 1 }, + { "Only Pref. CA PID", 2 }, + }; + return strtab2htsmsg(tab); +} + const idclass_t mpegts_service_class = { .ic_super = &service_class, @@ -133,6 +144,14 @@ const idclass_t mpegts_service_class = .off = offsetof(mpegts_service_t, s_dvb_prefcapid), .opts = PO_ADVANCED, }, + { + .type = PT_INT, + .id = "prefcapid_lock", + .name = "Lock Pref. CA PID", + .off = offsetof(mpegts_service_t, s_dvb_prefcapid_lock), + .opts = PO_ADVANCED, + .list = mpegts_service_pref_capid_lock_list, + }, {}, } }; diff --git a/src/service.c b/src/service.c index 65be059f..d1d1dcfb 100644 --- a/src/service.c +++ b/src/service.c @@ -405,9 +405,9 @@ filter: ca = NULL; if ((esf->esf_caid != (uint16_t)-1 || esf->esf_caprovider != -1)) { LIST_FOREACH(ca, &st->es_caids, link) { - if (esf->esf_caid != -1 && ca->caid != esf->esf_caid) + if (esf->esf_caid != (uint16_t)-1 && ca->caid != esf->esf_caid) continue; - if (esf->esf_caprovider != -1 && ca->providerid != esf->esf_caprovider) + if (esf->esf_caprovider != (uint32_t)-1 && ca->providerid != esf->esf_caprovider) continue; break; }