descrambler_change_keystate((th_descrambler_t *)ct, DS_FORBIDDEN, 1);
ct->ecm_state = ECM_RESET;
/* this pid is not valid, force full scan */
- if (t->s_dvb_prefcapid == ct->cs_capid && t->s_dvb_prefcapid_lock == PREFCAPID_OFF)
+ if (t->s_dvb_prefcapid == ct->cs_capid &&
+ t->s_dvb_prefcapid_lock == PREFCAPID_OFF)
t->s_dvb_prefcapid = 0;
}
return;
if (cc_must_break(cc))
return ECONNABORTED;
+ tvhtrace(cc->cc_subsys, "%s: read len %zd", cc->cc_name, len);
+ tvhlog_hexdump(cc->cc_subsys, buf, len);
return r;
}
void
cc_write_message(cclient_t *cc, cc_message_t *msg, int enq)
{
- tvhtrace(cc->cc_subsys, "%s: sending message len %u enq %d",
- cc->cc_name, msg->cm_len, enq);
- tvhlog_hexdump(cc->cc_subsys, msg->cm_data, msg->cm_len);
-
if (enq) {
- pthread_mutex_lock(&cc->cc_mutex);
+ lock_assert(&cc->cc_mutex);
if (cc->cc_write_running) {
TAILQ_INSERT_TAIL(&cc->cc_writeq, msg, cm_link);
tvh_nonblock_write(cc->cc_pipe.wr, "w", 1);
} else {
free(msg);
}
- pthread_mutex_unlock(&cc->cc_mutex);
} else {
+ tvhtrace(cc->cc_subsys, "%s: sending message len %u",
+ cc->cc_name, msg->cm_len);
+ tvhlog_hexdump(cc->cc_subsys, msg->cm_data, msg->cm_len);
if (tvh_write(cc->cc_fd, msg->cm_data, msg->cm_len))
- tvhinfo(cc->cc_subsys, "%s: write error %s",
+ tvhinfo(cc->cc_subsys, "%s: write error: %s",
cc->cc_name, strerror(errno));
free(msg);
}
pthread_mutex_unlock(&cc->cc_mutex);
r = tvhpoll_wait(poll, &ev, 1, 1000);
pthread_mutex_lock(&cc->cc_mutex);
+ if (r == 0)
+ continue;
if (r < 0 && ERRNO_AGAIN(errno))
continue;
- if (ev.ptr == &cc->cc_pipe)
+ if (r < 0)
+ break;
+ if (ev.ptr == &cc->cc_pipe) {
read(cc->cc_pipe.rd, buf, sizeof(buf));
- else if (ev.ptr == &cc->cc_fd) {
+ } else if (ev.ptr == &cc->cc_fd) {
+ sbuf_alloc(&rbuf, 1024);
len = sbuf_read(&rbuf, cc->cc_fd);
- if (len > 0 && cc->cc_read(cc, &rbuf))
- break;
+ if (len > 0) {
+ tvhtrace(cc->cc_subsys, "%s: read len %zd", cc->cc_name, len);
+ tvhlog_hexdump(cc->cc_subsys, rbuf.sb_data + rbuf.sb_ptr - len, len);
+ if (cc->cc_read(cc, &rbuf))
+ break;
+ }
} else {
abort();
}
if ((cm = TAILQ_FIRST(&cc->cc_writeq)) != NULL) {
- if (tvh_nonblock_write(cc->cc_fd, cm->cm_data, cm->cm_len))
+ TAILQ_REMOVE(&cc->cc_writeq, cm, cm_link);
+ tvhtrace(cc->cc_subsys, "%s: sending queued message len %u",
+ cc->cc_name, cm->cm_len);
+ tvhlog_hexdump(cc->cc_subsys, cm->cm_data, cm->cm_len);
+ if (tvh_nonblock_write(cc->cc_fd, cm->cm_data, cm->cm_len)) {
+ free(cm);
break;
+ }
+ free(cm);
}
if (mono < mclk()) {
mono = mclk();
tvhinfo(cc->cc_subsys, "%s: Inactive, thread exit", cc->cc_name);
cc_free_cards(cc);
+ cc->cc_name = NULL;
pthread_mutex_unlock(&cc->cc_mutex);
return NULL;
}
if (data == NULL)
return;
- if(len > 4096)
+ if (len > 4096)
return;
pthread_mutex_lock(&cc->cc_mutex);
cc_service_pid_free(ct);
/* move to init state */
ct->ecm_state = ECM_INIT;
- ct->cs_capid = -1;
+ ct->cs_capid = 0xffff;
t->s_dvb_prefcapid = 0;
tvhdebug(cc->cc_subsys, "%s: Reset after unexpected or no reply for service \"%s\"",
cc->cc_name, t->s_dvb_svcname);
caid = c->caid;
provid = c->providerid;
- ecm = data[0] == 0x80 || data[1] == 0x81;
+ ecm = data[0] == 0x80 || data[0] == 0x81;
if (pcard->cs_ra.caid == 0x4a30) ecm |= data[0] == 0x50; /* DVN */
if (ecm) {
es->es_pending = 1;
es->es_resolved = 0;
- if(ct->cs_capid >= 0 && capid > 0 && ct->cs_capid != capid) {
- tvhdebug(cc->cc_subsys, "%s: Filtering ECM (PID %d)",
- cc->cc_name, capid);
+ if (ct->cs_capid != 0xffff && ct->cs_capid > 0 &&
+ capid > 0 && ct->cs_capid != capid) {
+ tvhdebug(cc->cc_subsys, "%s: Filtering ECM (PID %d), using PID %d",
+ cc->cc_name, capid, ct->cs_capid);
goto end;
}
es->es_seq = cc->cc_send_ecm(cc, ct, es, pcard, data, len);
tvhdebug(cc->cc_subsys,
- "%s: Sending ECM%s section=%d/%d, for service \"%s\" (seqno: %d)",
+ "%s: Sending ECM%s section=%d/%d for service \"%s\" (seqno: %d)",
cc->cc_name, chaninfo, section,
ep->ep_last_section, t->s_dvb_svcname, es->es_seq);
es->es_time = getfastmonoclock();
for (i = 0; i < ct->cs_epids.count; i++)
descrambler_close_pid(ct->cs_mux, ct, ct->cs_epids.pids[i].pid);
+ mpegts_pid_done(&ct->cs_epids);
cc_service_pid_free(ct);
ct = calloc(1, sizeof(*ct));
}
ct->cs_client = cc;
- ct->cs_capid = -1;
+ ct->cs_capid = 0xffff;
ct->cs_mux = ((mpegts_service_t *)t)->s_dvb_mux;
ct->ecm_state = ECM_INIT;
cc_table_input, t);
if (reuse & 2) {
- ct->cs_capid = -1;
+ ct->cs_capid = 0xffff;
ct->ecm_state = ECM_INIT;
}
{
cclient_t *cc = (cclient_t *)cac;
pthread_t tid;
+ cc_message_t *cm;
if (cac->cac_enabled) {
if (cc->cc_hostname == NULL || cc->cc_hostname[0] == '\0') {
pthread_join(tid, NULL);
tvh_pipe_close(&cc->cc_pipe);
caclient_set_status(cac, CACLIENT_STATUS_NONE);
- pthread_mutex_lock(&cc->cc_mutex);
- free(cc->cc_name);
- cc->cc_name = NULL;
- pthread_mutex_unlock(&cc->cc_mutex);
+ while ((cm = TAILQ_FIRST(&cc->cc_writeq)) != NULL) {
+ TAILQ_REMOVE(&cc->cc_writeq, cm, cm_link);
+ free(cm);
+ }
}
}
static int
des_encrypt(uint8_t *buffer, int len, cwc_t *cwc)
{
- uint8_t checksum = 0;
- uint8_t noPadBytes;
- uint8_t padBytes[7];
+ uint8_t checksum = 0, *ptr, noPadBytes, padBytes[7];
DES_cblock ivec;
- uint16_t i;
+ int i;
noPadBytes = (8 - ((len - 1) % 8)) % 8;
if (len + noPadBytes + 1 >= CWS_NETMSGSIZE-8) return -1;
uuid_random((uint8_t *)ivec, 8);
memcpy(buffer+len, ivec, 8);
for (i = 2; i < len; i += 8) {
- DES_ncbc_encrypt(buffer+i, buffer+i, 8, &cwc->cwc_k1, &ivec, 1);
-
- DES_ecb_encrypt((DES_cblock *)(buffer+i), (DES_cblock *)(buffer+i),
- &cwc->cwc_k2, 0);
-
- DES_ecb_encrypt((DES_cblock *)(buffer+i), (DES_cblock *)(buffer+i),
- &cwc->cwc_k1, 1);
- memcpy(ivec, buffer+i, 8);
+ ptr = buffer + i;
+ DES_ncbc_encrypt(ptr, ptr, 8, &cwc->cwc_k1, &ivec, 1);
+ DES_ecb_encrypt((DES_cblock *)ptr, (DES_cblock *)ptr, &cwc->cwc_k2, 0);
+ DES_ecb_encrypt((DES_cblock *)ptr, (DES_cblock *)ptr, &cwc->cwc_k1, 1);
+ memcpy(ivec, ptr, 8);
}
- len += 8;
- return len;
+ return len + 8;
}
/**
static int
des_decrypt(uint8_t *buffer, int len, cwc_t *cwc)
{
- DES_cblock ivec;
- DES_cblock nextIvec;
+ DES_cblock ivec, nextIvec;
+ uint8_t *ptr, checksum = 0;;
int i;
- uint8_t checksum = 0;
if ((len-2) % 8 || (len-2) < 16) return -1;
len -= 8;
memcpy(nextIvec, buffer+len, 8);
- for (i = 2; i < len; i += 8)
- {
- memcpy(ivec, nextIvec, 8);
- memcpy(nextIvec, buffer+i, 8);
-
- DES_ecb_encrypt((DES_cblock *)(buffer+i), (DES_cblock *)(buffer+i),
- &cwc->cwc_k1, 0);
- DES_ecb_encrypt((DES_cblock *)(buffer+i), (DES_cblock *)(buffer+i),
- &cwc->cwc_k2, 1);
-
- DES_ncbc_encrypt(buffer+i, buffer+i, 8, &cwc->cwc_k1, &ivec, 0);
- }
+ for (i = 2; i < len; i += 8) {
+ ptr = buffer + i;
+ memcpy(ivec, nextIvec, 8);
+ memcpy(nextIvec, ptr, 8);
+ DES_ecb_encrypt((DES_cblock *)ptr, (DES_cblock *)ptr, &cwc->cwc_k1, 0);
+ DES_ecb_encrypt((DES_cblock *)ptr, (DES_cblock *)ptr, &cwc->cwc_k2, 1);
+ DES_ncbc_encrypt(ptr, ptr, 8, &cwc->cwc_k1, &ivec, 0);
+ }
+ tvhlog_hexdump(cwc->cc_subsys, buffer, len);
for (i = 2; i < len; i++) checksum ^= buffer[i];
if (checksum) return -1;
return len;
if (len < 3)
return -1;
- cm = malloc(sizeof(cc_message_t) + 12 + len);
+ /* note: the last 10 bytes is pad/checksum for des_encrypt() */
+ cm = malloc(sizeof(cc_message_t) + 12 + len + 10);
if (cm == NULL)
return -1;
cc_ecm_reply(ct, es, DESCRAMBLER_NONE, NULL, NULL, seq);
} else {
type = DESCRAMBLER_CSA_CBC;
- if (len == 3 + 8 + 8) {
+ if (len <= 22) {
off = 8;
- } else if (len == 3 + 16 + 16) {
+ } else if (len <= 40) {
off = 16;
type = DESCRAMBLER_AES128_ECB;
} else {
*/
static int
cwc_read_message0
- (cwc_t *cwc, const char *state, sbuf_t *rbuf, int timeout)
+ (cwc_t *cwc, const char *state, sbuf_t *rbuf, int *rsize, int timeout)
{
int msglen;
if(rbuf->sb_ptr < 2 + msglen)
return 0;
+ *rsize = msglen + 2;
if((msglen = des_decrypt(rbuf->sb_data, msglen + 2, cwc)) < 15) {
tvhinfo(cwc->cc_subsys, "%s: %s: Decrypt failed",
cwc->cc_name, state);
return -1;
}
+ tvhtrace(LS_CWC, "%s: decrypted message", cwc->cc_name);
+ tvhlog_hexdump(cwc->cc_subsys, rbuf->sb_data, msglen + 2);
+
return msglen;
}
return -1;
}
+ tvhtrace(LS_CWC, "%s: decrypted message", cwc->cc_name);
+ tvhlog_hexdump(cwc->cc_subsys, buf, msglen + 2);
+
return msglen;
}
{
cwc_t *cwc = cc;
const int ka_interval = cwc->cc_keepalive_interval * 2 * 1000;
- int r = cwc_read_message0(cwc, "DecoderLoop", rbuf, ka_interval);
- if (r < 0)
- return -1;
- if (r > 12) {
- int ret = cwc_running_reply(cwc, rbuf->sb_data[12], rbuf->sb_data, r);
- if (ret > 0)
- sbuf_cut(rbuf, r);
- if (ret < 0)
+ int r, rsize;
+
+ while (1) {
+ r = cwc_read_message0(cwc, "DecoderLoop", rbuf, &rsize, ka_interval);
+ if (r == 0)
+ break;
+ if (r < 0)
return -1;
- return 0;
+ if (r > 12) {
+ if (cwc_running_reply(cwc, rbuf->sb_data[12], rbuf->sb_data, r) < 0)
+ return -1;
+ sbuf_cut(rbuf, rsize);
+ } else if (r > 0) {
+ return -1;
+ }
}
- if (r > 0)
- return -1;
return 0;
}