Código-fonte CCCam


Código:
* Plugin softcam para VDR (C + +) 
* 
* Este código é um software livre, você pode redistribuí-lo e / ou 
modificá-lo sob os termos da GNU General Public License 
* conforme publicada pela Free Software Foundation, versão 2 
* do Licença, ou (a seu critério) qualquer versão posterior. 
* 
* Este código é distribuído na esperança que será útil, 
mas SEM NENHUMA GARANTIA, nem mesmo a garantia implícita de 
COMERCIALIZAÇÃO OU ADEQUAÇÃO A UM DETERMINADO PROPÓSITO. Veja a 
GNU General Public License para mais detalhes. 
* 
Você deve ter recebido uma cópia da Licença Pública Geral GNU 
* junto com este programa, se não, escreva para a Free Software 
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, EUA. 
* Ou, aponte seu navegador para http://www.gnu.org/copyleft/gpl.html 
* / 

# include 
# include 
# incluem <errno.h> 
# include <unistd.h> 
# include <sys/socket.h> 
# include <sys/un.h> 

# include <vdr/pat.h> 

# include "cc.h" 
# include " network.h " 

# define LIST_ONLY 0x03 / * aplicativo CA deve limpar a lista quando um objeto CAPMT "apenas" é recebido, e começar a trabalhar com o objeto * / 

/ / - cCCcamCard ----------- -------------------------------------------------- - 

cCCcamCard classe: public CMutex { 
private: 
int ccam_fd; 
cardnum int, pid, pmtlen; 
bool newcw; 
cTimeMs timecw; 
unsigned char * capmt, cw [16]; 
const char * caminho; 
cCondVar cwwait; 
público: 
cCCcamCard (void) , 
~ cCCcamCard (); 
Configuração void (int num, const char * Caminho); 
bool Connect (void); 
vazio Disconnect (void); 
bool Conectado (void) {return ccam_fd> = 0;} 
vazio WriteCaPmt (void); 
vazio NewCaPmt (int p, const unsigned char * pgto, int len); 
Pid int (void) {return pid;} 
bool GetCw (unsigned char * Cw, int timeout); 
vazio NewCw (const unsigned char * Cw); 
}; 

cCCcamCard :: cCCcamCard (void) 
{ 
cardnum = -1; path = 0; 
ccam_fd = -1; capmt = 0; newcw = false; pid = -1; 
} 

cCCcamCard :: ~ cCCcamCard () 
{ 
Disconnect (); 
livre (capmt ); 
} 

cCCcamCard vazio :: Setup (int num, const char * Caminho) 
{ 
cardnum = num; = caminho; 
} 

cCCcamCard vazio: isconnect (void) 
{ 
cMutexLock lock (this); 
próximo (ccam_fd); 
ccam_fd = -1 ; newcw = false; 
} 

bool cCCcamCard :: Connect (void) 
{ 
cMutexLock lock (this); 
Disconnect (); 
ccam_fd = socket (AF_LOCAL, SOCK_STRE AM, 0); 
(! ccam_fd) se { 
% (L_CC_CCCAM ", PRINTF d : soquete falhou:% s ", cardnum, strerror (errno)); 
return false; 
} 
sockaddr_un serv_addr_un; 
memset (& serv_addr_un, 0, sizeof (ser v_addr_un)); 
serv_addr_un.sun_family = AF_LOCAL; 
snprintf (serv_addr_un.sun_path, si zeof (serv_addr_un.sun_path), trajeto, cardnum); 
if (connect (ccam_fd, (const sockaddr *) & serv_addr_un, sizeof (SE rv_addr_un)) = 0) {! 
PRINTF (L_CC_CCCAM, "% d: conectar falhou:% s", cardnum, strerror (errno)); 
Disconnect (); 
return false; 
} 
printf (L_CC_CCCAM, "% d: abriu tomada camd", cardnum); 
return true; 
} 

vazio cCCcamCard :: WriteCaPmt (void) 
{ 
cMutexLock lock (this) , 
se (capmt) { 
for (int retry = 2; repetir> 0; repetir -) { 
pausa if (! Connected () && Connect ()); 
int r = write (ccam_fd, capmt, pmtlen); 
if ( r == pmtlen) { 
newcw = false; 
break; 
} 
printf (L_CC_CCCAM, "% d: escrever falhou:% s", cardnum, strerror (errno)); 
Disconnect (); 
} 
} 
} 

vazio cCCcamCard :: NewCaPmt (int p, const unsigned char * pgto, int len) 
{ 
cMutexLock lock (this); 
livre (capmt); pid = 0; newcw = false; 
capmt = malloc (unsigned char, len); 
se (capmt) { 
memcpy (capmt, pgto, len); 
pmtlen = len; 
capmt [6] = LIST_ONLY; 
pid = p; 
; WriteCaPmt () 
} 
} 

vazio cCCcamCard :: NewCw (const unsigned char * Cw) 
{ 
cMutexLock lock (this); 
se (memcmp (cw , Cw, sizeof (cw))) { 
memcpy (cw, Cw, sizeof (cw)); 
newcw = true; 
timecw.Set (); 
cwwait.Broadcast (); 
} 
} 

bool cCCcamCard :: GetCw (unsigned char * Cw , int timeout) 
{ 
cMutexLock lock (this); 
se (&& newcw timecw.Elapsed ()> 3000) 
newcw = false; / / muito velho 
se (newcw)! 
cwwait.TimedWait (* isso, timeout); 
se (newcw) { 
memcpy (CW, cw, sizeof (cw)); 
newcw = false; 
return true; 
} 
return false; 
} 

/ / - cCardClientCCcam -------------------- ------------------------------------- 

classe cCardClientCCcam: public cThread, cCardClient privado { 
privado: 
assim cNetSocket ; 
cartão cCCcamCard [4]; 
pmtversion int; 
failedcw int; 
char * socketpath; 
protegida: 
Entrar bool virtual (void); 
Ação virtual void (void); 
público: 
cCardClientCCcam (const char * nome); 
~ cCardClientCCcam (); 
virtual bool Init (const char * CfgDir); 
virtual bool ProcessECM (const cEcmInfo * ecm, const unsigned char * data, unsigned char * Cw, int cardnum); 
}; 

estática cCardClientLinkReg <cCardClientCCc am> __ ncd ("cccam"); 

​​cCardClientCCcam :: cCardClientCCca m (const char * Nome) 
: cCardClient (Name) 
, cThread ("ouvinte CCcam") 
, então (DEFAULT_CONNECT_TIMEOUT, 2360 0, true) 
{ 
pmtversion = 0; socketpath = 0; 
} 

cCardClientCCcam :: ~ cCardClientCCc am () 
{ 
Cancelar (3); 
livre (socketpath); 
} 

bool cCardClientCCcam :: Init (const char * config) 
{ 
cMutexLock lock (this); 
int num = 0; 
caminho char [256]; 
! se (ParseStdConfig (config, & num) 
| | | sscanf (& config [num] ":% 255 [^:]" caminho,) = 1) return false; 
PRINTF (L_CC_CORE, "% s: socket =% s", nome, caminho); 
socketpath = strdup ( caminho); 
for (int i = 0; i <4; i + +) card.Setup (i, socketpath); 
retorno imediato ()? Login (): true; 
} 

bool cCardClientCCcam :: Login (void) 
{ 
cMutexLock lock (this); 
so.Disconnect (); 
se return false; (so.Bind ("127.0.0.1", porta)!) 
printf (L_CC_CCCAM , "obrigado a porta% d, começando UDP ouvinte", porta); 
Iniciar (); 
return true; 
} 

bool cCardClientCCcam :: ProcessECM (cEcmInfo t contras * ecm, const unsigned char * data, unsigned char * cw, int cardnum) 
{ 
cMutexLock lock (this); 
if ((so.Connected () && login ()) | CanHandle (ECM-> Caid) |!) return false; 

static const unsigned char pmt [] = { 
0x9f, 0x80, 0x32 , 0x82, 0xFF, 0xFF, 
0x01, 
# define PRG_POS 7 
0xFF, 0xFF, / / prg-nr 
# define VERS_POS 9 
0xFF, / / versão 
# define LEN_POS 10 
0xFF, 0xFF, / / prg-info-len 
0x01, / / ca comando pmt 
# define PRIV_POS 13 
0x81, 0x08, 0x00, 0x00, 0xFF, 0x00, 0xF F, 0xFF, 0xFF, 0xFF, descr / / privado 
# define DMX_POS 23 
0x82, 0x02, 0xFF, 0xFF, / / demuxer coisas 
# define PID_POS 27 
0x84, 0x02, 0xFF, 0xFF / / pmt pid 
}; 
unsigned char capmt [2048]; 
memcpy (capmt, pgto, sizeof (PMT)); 
int wp = sizeof (PMT); 
int 
; 
capmt [DMX_POS 3] = cardnum; 
capmt [PID_POS 2] = ecm-> ecm_pid **** 8; 
capmt [PID_POS 3] = ecm-> ecm_pid &0xFF; 
bool streamflag = 1; 
# se APIVERSNUM> = 10500 
int casys [2]; 
# else 
não assinados casys curtos [2]; 
# endif 
casys [0] = ecm-> Caid; 
casys [1] = 0; 
int 
{ 
printf (L_CC_CCCAM, "nenhum descritor CA para caid% 04x sid% d% prov 04x", ecm-> CAID, ecm-> prgId, ecm-> Provid); 
return false; 
} 
len + = n; wp + = n; 
capmt [wp + +] = 0x01; 
capmt [wp + +] = 0x0f; 
capmt [wp + +] = cardnum / / cccam usa este como PID para o programa ca0 
capmt [wp + +] = 0x00 / / es_length 
capmt [wp + +] = 0x06 / / es 
* C = & cartão [cardnum]; 
int timeout = 700; 
if (! ECM-> ecm_pid = c-> Pid () | | c-> Conectado ()) mudança de canal {/ / 
printf (L_CC_CCCAM ", enviando capmts" ); 
c-> NewCaPmt (ECM-> ecm_pid, capmt, wp); 
timeout = 3000; 
} 
! se (c-> GetCw (cw, tempo limite)) { 
. / / algumas coisas para cima, por isso vamos enviar capmt novamente 
c- > WriteCaPmt (); 
se {(c-> GetCw (cw, 1000)!) 
printf (L_CC_CCCAM, "% d!: FAILED ECM", cardnum); 
c-> Disconnect (); 
failedcw + +; 
se (failedcw> = 10 ) { 
/ / CCcam está tendo problemas permite que marcá-lo para um reinício .... 
FILE * f = fopen ("/ tmp / killCCcam", "w +"); 
fclose (f); 
failedcw = 0; 
} 
return false; 
} 
} 
printf (L_CC_CCCAM, "% d:! GOT CW", cardnum); 
failedcw = 0; 
return true; 
} 
cCardClientCCcam vazio :: Ação (void) 
{ 
unsigned char cw [18]; 
enquanto (Running ()) { 
if ( so.Read (cw, sizeof (cw)) == sizeof (cw)) { 
LDUMP (L_CC_CCCAM, cw +2,16 ", tem:% 02x% 02x", cw [0], cw [1]); 
se (CW [1] == 0x0f && cw [0] <4) 
. cartão [cw [0]] NewCw (cw +2); 
} 
} 
}