📄 cc.cpp
字号:
/*
* Softcam plugin to VDR (C++)
*
* This code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include "stdafx.h"
#include <string.h>
#include "vdr/tools.h"
#include "common.h"
#include "system.h"
#include "cc.h"
#include "network.h"
#include "misc.h"
#include "opts.h"
#define SYSTEM_NAME "Cardclient"
#define SYSTEM_PRI -15
#define CONF_FILE "cardclient.conf"
#define strcasecmp _stricmp
static int immediate=true;
// -- cCardClient --------------------------------------------------------------
cCardClient::cCardClient(const char *Name)
:msECM(32,16)
,msEMM(32,0)
{
name=Name;
emmAllowed=false; emmCaid[0]=0x1700; emmMask[0]=0xFF00; numCaid=1;
}
bool cCardClient::Immediate(void)
{
return immediate;
}
bool cCardClient::ParseStdConfig(const char *config, int *num)
{
int n, emm=0;
if(!num) num=&n;
if(sscanf(config,"%63[^:]:%d:%d%n",hostname,&port,&emm,num)<3) return false;
if(emm>0) emmAllowed=true;
if(config[*num]=='/') {
numCaid=0;
do {
emmMask[numCaid]=0xFFFF;
int start=(*num)+1;
if(sscanf(&config[start],"%x%n/%x%n",&emmCaid[numCaid],num,&emmMask[numCaid],num)<1)
return false;
*num+=start;
numCaid++;
} while(numCaid<MAX_CC_CAID && config[*num]==',');
}
dc(printf("cc: hostname=%s port=%d emm=%d emmCaids",hostname,port,emmAllowed))
for(int i=0; i<numCaid; i++) dc(printf(" %04x/%04x",emmCaid[i],emmMask[i]))
dc(printf("\n"))
return true;
}
bool cCardClient::CanHandle(unsigned short SysId)
{
for(int i=0; i<numCaid; i++)
if((SysId&emmMask[i])==emmCaid[i]) return true;
return false;
}
bool cCardClient::SendMsg(cNetSocket *so, const unsigned char *data, int len)
{
if(!so->Connected() && !Login()) return false;
if(so->Write(data,len)<0) {
dc(printf("cc: send error. reconnecting...\n"));
so->Disconnect();
return false;
}
return true;
}
int cCardClient::RecvMsg(cNetSocket *so, unsigned char *data, int len, int to)
{
if(!so->Connected() && !Login()) return -1;
int n=so->Read(data,len,to);
if(n<0) {
dc(printf("cc: recv error. reconnecting...\n"));
so->Disconnect();
return -1;
}
return n;
}
// -- cCardClients -------------------------------------------------------------
class cCardClients {
friend class cCardClientLink;
private:
static cCardClientLink *first;
//
static void Register(cCardClientLink *ccl);
public:
cCardClientLink *FindByName(const char *name);
};
cCardClientLink *cCardClients::first=0;
static cCardClients cardclients;
void cCardClients::Register(cCardClientLink *ccl)
{
dyn(printf("cardclients: registering cardclient %s\n",ccl->name))
ccl->next=first;
first=ccl;
}
cCardClientLink *cCardClients::FindByName(const char *name)
{
cCardClientLink *ccl=first;
while(ccl) {
if(!strcasecmp(ccl->name,name)) break;
ccl=ccl->next;
}
return ccl;
}
// -- cCardClientLink ----------------------------------------------------------
cCardClientLink::cCardClientLink(const char *Name)
{
name=Name;
cCardClients::Register(this);
}
// -- cSystemLinkCardClient -----------------------------------------------------------
class cSystemLinkCardClient : public cSystemLink, private cConfRead, cSimpleList<cCardClient> {
protected:
virtual bool ParseLine(const char *line, bool fromCache);
public:
cSystemLinkCardClient(void);
virtual bool CanHandle(unsigned short SysId);
virtual cSystem *Create(void);
virtual bool Init(const char *cfgdir);
virtual void Clean(void);
cCardClient *FindBySysId(unsigned short id, cCardClient *cc);
};
static cSystemLinkCardClient staticCcl;
// -- cSystemCardClient ---------------------------------------------------------------
class cSystemCardClient : public cSystem {
private:
cCardClient *cc;
public:
cSystemCardClient(void);
virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);
};
cSystemCardClient::cSystemCardClient(void)
:cSystem(SYSTEM_NAME,SYSTEM_PRI)
{
cc=0;
expensive=true; hasLogger=true;
}
bool cSystemCardClient::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
{
cCardClient *startCc=cc;
do {
if(cc) {
#ifdef DEBUG_CC
cTimeMs start;
#endif
int id=cc->msECM.Get(data,SCT_LEN(data),cw);
if(id==0 || (id>0 && cc->ProcessECM(ecm,data,cw))) {
#ifdef DEBUG_CC
int dur=start.Elapsed();
if(dur>2000) {
char bb[32];
time_t now=time(0);
ctime_r(&now,bb); stripspace(bb);
printf("cc: %s: lagged cw %d ms (%s)\n",bb,dur,cc->Name());
}
#endif
char buff[32];
_snprintf(buff,sizeof(buff),"CC %s",cc->Name());
KeyOK(buff);
if(id>0) cc->msECM.Cache(id,true,cw);
return true;
}
if(id>0) {
dc(printf("cc: client %s (%s:%d) ECM failed (%d ms)\n",cc->Name(),cc->hostname,cc->port,(int)start.Elapsed()))
cc->msECM.Cache(id,false,cw);
}
}
if(!cc) dc(printf("cc: cc-loop\n"))
cc=staticCcl.FindBySysId(ecm->caId,cc);
if(cc && cc!=startCc) dc(printf("cc: now trying client %s (%s:%d)\n",cc->Name(),cc->hostname,cc->port))
} while(cc!=startCc);
return false;
}
// -- cSystemLinkCardClient -----------------------------------------------------------
cSystemLinkCardClient::cSystemLinkCardClient(void)
:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
{
opts=new cOpts(SYSTEM_NAME,1);
opts->Add(new cOptBool("Immediate","Cardclient: connect immediately",&immediate));
}
cCardClient *cSystemLinkCardClient::FindBySysId(unsigned short id, cCardClient *cc)
{
if(cc) cc=Next(cc); else cc=First();
while(cc) {
if(cc->CanHandle(id)) return cc;
cc=Next(cc);
}
return 0;
}
bool cSystemLinkCardClient::CanHandle(unsigned short SysId)
{
return FindBySysId(SysId,0)!=0;
}
cSystem *cSystemLinkCardClient::Create(void)
{
return new cSystemCardClient();
}
bool cSystemLinkCardClient::Init(const char *cfgdir)
{
Clear();
ConfRead("cardclient config",AddDirectory(cfgdir,CONF_FILE));
d(printf("cc-link: created %d client(s)\n",Count()))
return true;
}
bool cSystemLinkCardClient::ParseLine(const char *line, bool fromCache)
{
char name[32];
int num;
if(sscanf(line,"%31[^:]:%n",name,&num)==1) {
cCardClientLink *ccl=cardclients.FindByName(name);
if(ccl) {
cCardClient *cc=ccl->Create();
if(cc) {
if(cc->Init(&line[num])) {
Add(cc);
dc(printf("cc-link: client '%s' ready\n",cc->Name()))
return true;
}
else {
delete cc;
d(printf("cc-link: init of client '%s' failed\n",name))
}
}
else d(printf("cc-link: failed to create client '%s'\n",name))
}
else d(printf("cc-link: no client found for server type '%s'\n",name))
}
return false;
}
void cSystemLinkCardClient::Clean(void)
{
Clear();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -