SASC-NG
DVBSoftCAM

cDeCSA Class Reference

#include <cam.h>

List of all members.

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)

Detailed Description

Definition at line 241 of file cam.h.


Constructor & Destructor Documentation

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);
}

Member Function Documentation

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;
}

The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines