|
SASC-NG
DVBSoftCAM
|
#include <cam.h>
Public Member Functions | |
| cDeCSA (const char *DevId) | |
| ~cDeCSA () | |
| bool | Decrypt (unsigned char *data, int len, bool force) |
| bool | SetDescr (ca_descr_t *ca_descr, bool initial) |
| bool | SetCaPid (ca_pid_t *ca_pid) |
| void | SetActive (bool on) |
| cDeCSA::cDeCSA | ( | const char * | DevId | ) |
Definition at line 2721 of file cam.c.
References cs, get_suggested_cluster_size(), keys, L_CORE_CSA, MALLOC, PRINTF, and range.
:stall(MAX_STALL_MS) { devId=DevId; cs=get_suggested_cluster_size(); PRINTF(L_CORE_CSA,"%s: clustersize=%d rangesize=%d",devId,cs,cs*2+5); range=MALLOC(unsigned char *,(cs*2+5)); memset(keys,0,sizeof(keys)); memset(pidmap,0,sizeof(pidmap)); ResetState(); }
| cDeCSA::~cDeCSA | ( | ) |
Definition at line 2733 of file cam.c.
References free, free_key_struct(), keys, MAX_CSA_IDX, and range.
{
for(int i=0; i<MAX_CSA_IDX; i++)
if(keys[i]) free_key_struct(keys[i]);
free(range);
}
| bool cDeCSA::Decrypt | ( | unsigned char * | data, |
| int | len, | ||
| bool | force | ||
| ) |
Definition at line 2801 of file cam.c.
References cCondVar::Broadcast(), cs, data, decrypt_packets(), FL_ACTIVITY, FL_EVEN_GOOD, FL_ODD_GOOD, flags, keys, L_CORE_CSA, L_CORE_CSAVERB, LBEND, LBPUT, LBSTART, TPDU::len, MAX_CSA_PIDS, MAX_KEY_WAIT, MAX_STALL_MS, PRINTF, range, cTimeMs::Set(), cTimeMs::TimedOut(), cCondVar::TimedWait(), TS_SIZE, and TS_SYNC_BYTE.
Referenced by cDeCsaTSBuffer::Get().
{
cMutexLock lock(&mutex);
int r=-2, ccs=0, currIdx=-1;
bool newRange=true;
range[0]=0;
len-=(TS_SIZE-1);
int l;
for(l=0; l<len; l+=TS_SIZE) {
if(data[l]!=TS_SYNC_BYTE) { // let higher level cope with that
PRINTF(L_CORE_CSA,"%s: garbage in TS buffer",devId);
if(ccs) force=true; // prevent buffer stall
break;
}
unsigned int ev_od=data[l+3]&0xC0;
if(ev_od==0x80 || ev_od==0xC0) { // encrypted
int idx=pidmap[((data[l+1]<<8)+data[l+2])&(MAX_CSA_PIDS-1)];
if(currIdx<0 || idx==currIdx) { // same or no index
currIdx=idx;
if(ccs==0 && ev_od!=even_odd[idx]) {
even_odd[idx]=ev_od;
wait.Broadcast();
PRINTF(L_CORE_CSA,"%s.%d: change to %s key",devId,idx,(ev_od&0x40)?"odd":"even");
bool doWait=false;
if(ev_od&0x40) {
flags[idx]&=~FL_EVEN_GOOD;
if(!(flags[idx]&FL_ODD_GOOD)) doWait=true;
}
else {
flags[idx]&=~FL_ODD_GOOD;
if(!(flags[idx]&FL_EVEN_GOOD)) doWait=true;
}
if(doWait) {
PRINTF(L_CORE_CSA,"%s.%d: %s key not ready (%d ms)",devId,idx,(ev_od&0x40)?"odd":"even",MAX_KEY_WAIT);
if(flags[idx]&FL_ACTIVITY) {
flags[idx]&=~FL_ACTIVITY;
if(wait.TimedWait(mutex,MAX_KEY_WAIT)) PRINTF(L_CORE_CSA,"%s.%d: successfully waited for key",devId,idx);
else PRINTF(L_CORE_CSA,"%s.%d: timed out. proceeding anyways",devId,idx);
}
else PRINTF(L_CORE_CSA,"%s.%d: not active. wait skipped",devId,idx);
}
}
if(newRange) {
r+=2; newRange=false;
range[r]=&data[l];
range[r+2]=0;
}
range[r+1]=&data[l+TS_SIZE];
if(++ccs>=cs) break;
}
else newRange=true; // other index, create hole
}
else { // unencrypted
// nothing, we don't create holes for unencrypted packets
}
}
int scanTS=l/TS_SIZE;
int stallP=ccs*100/scanTS;
LBSTART(L_CORE_CSAVERB);
LBPUT("%s: %s-%d-%d : %d-%d-%d stall=%d :: ",
devId,data==lastData?"SAME":"MOVE",(len+(TS_SIZE-1))/TS_SIZE,force,
currIdx,ccs,scanTS,stallP);
for(int l=0; l<len; l+=TS_SIZE) {
if(data[l]!=TS_SYNC_BYTE) break;
unsigned int ev_od=data[l+3]&0xC0;
if(ev_od&0x80) {
int pid=(data[l+1]<<8)+data[l+2];
int idx=pidmap[pid&(MAX_CSA_PIDS-1)];
LBPUT("%s/%x/%d ",(ev_od&0x40)?"o":"e",pid,idx);
}
else {
LBPUT("*/%x ",(data[l+1]<<8)+data[l+2]);
}
}
LBEND();
if(r>=0 && ccs<cs && !force) {
if(lastData==data && stall.TimedOut()) {
PRINTF(L_CORE_CSAVERB,"%s: stall timeout -> forced",devId);
force=true;
}
else if(stallP<=10 && scanTS>=cs) {
PRINTF(L_CORE_CSAVERB,"%s: flow factor stall -> forced",devId);
force=true;
}
}
lastData=data;
if(r>=0) { // we have some range
if(ccs>=cs || force) {
if(GetKeyStruct(currIdx)) {
int n=decrypt_packets(keys[currIdx],range);
PRINTF(L_CORE_CSAVERB,"%s.%d: decrypting ccs=%3d cs=%3d %s -> %3d decrypted",devId,currIdx,ccs,cs,ccs>=cs?"OK ":"INC",n);
if(n>0) {
stall.Set(MAX_STALL_MS);
return true;
}
}
}
else PRINTF(L_CORE_CSAVERB,"%s.%d: incomplete ccs=%3d cs=%3d",devId,currIdx,ccs,cs);
}
return false;
}
| void cDeCSA::SetActive | ( | bool | on | ) |
Definition at line 2748 of file cam.c.
References L_CORE_CSA, and PRINTF.
Referenced by cDeCsaTSBuffer::cDeCsaTSBuffer(), and cDeCsaTSBuffer::~cDeCsaTSBuffer().
{
if(!on && active) ResetState();
active=on;
PRINTF(L_CORE_CSA,"%s: set active %s",devId,active?"on":"off");
}
| bool cDeCSA::SetCaPid | ( | ca_pid_t * | ca_pid | ) |
Definition at line 2791 of file cam.c.
References L_CORE_CSA, MAX_CSA_IDX, MAX_CSA_PIDS, and PRINTF.
Referenced by cCam::SetCaPid().
{
cMutexLock lock(&mutex);
if(ca_pid->index<MAX_CSA_IDX && ca_pid->pid<MAX_CSA_PIDS) {
pidmap[ca_pid->pid]=ca_pid->index;
PRINTF(L_CORE_CSA,"%s.%d: set pid %04x",devId,ca_pid->index,ca_pid->pid);
}
return true;
}
| bool cDeCSA::SetDescr | ( | ca_descr_t * | ca_descr, |
| bool | initial | ||
| ) |
Definition at line 2761 of file cam.c.
References cCondVar::Broadcast(), CheckNull(), FL_ACTIVITY, FL_EVEN_GOOD, FL_ODD_GOOD, flags, keys, L_CORE_CSA, LDUMP, MAX_CSA_IDX, MAX_REL_WAIT, PRINTF, set_even_control_word(), set_odd_control_word(), and cCondVar::TimedWait().
Referenced by cCam::SetCaDescr().
{
cMutexLock lock(&mutex);
int idx=ca_descr->index;
if(idx<MAX_CSA_IDX && GetKeyStruct(idx)) {
if(!initial && active && ca_descr->parity==(even_odd[idx]&0x40)>>6) {
if(flags[idx] & (ca_descr->parity?FL_ODD_GOOD:FL_EVEN_GOOD)) {
PRINTF(L_CORE_CSA,"%s.%d: %s key in use (%d ms)",devId,idx,ca_descr->parity?"odd":"even",MAX_REL_WAIT);
if(wait.TimedWait(mutex,MAX_REL_WAIT)) PRINTF(L_CORE_CSA,"%s.%d: successfully waited for release",devId,idx);
else PRINTF(L_CORE_CSA,"%s.%d: timed out. setting anyways",devId,idx);
}
else PRINTF(L_CORE_CSA,"%s.%d: late key set...",devId,idx);
}
LDUMP(L_CORE_CSA,ca_descr->cw,8,"%s.%d: %4s key set",devId,idx,ca_descr->parity?"odd":"even");
if(ca_descr->parity==0) {
set_even_control_word(keys[idx],ca_descr->cw);
if(!CheckNull(ca_descr->cw,8)) flags[idx]|=FL_EVEN_GOOD|FL_ACTIVITY;
else PRINTF(L_CORE_CSA,"%s.%d: zero even CW",devId,idx);
wait.Broadcast();
}
else {
set_odd_control_word(keys[idx],ca_descr->cw);
if(!CheckNull(ca_descr->cw,8)) flags[idx]|=FL_ODD_GOOD|FL_ACTIVITY;
else PRINTF(L_CORE_CSA,"%s.%d: zero odd CW",devId,idx);
wait.Broadcast();
}
}
return true;
}