]> www.vanbest.org Git - sasc-ng.git/commitdiff
cardclient-CCcam: rewrite camd socket handling
authorleslie <unknown>
Mon, 9 Jun 2008 06:40:53 +0000 (14:40 +0800)
committerleslie <unknown>
Mon, 9 Jun 2008 06:40:53 +0000 (14:40 +0800)
systems/cardclient/cccam.c

index 2b933b7af301a930314f0baec7becc4ceffc53a5..f37389c1539040f93c13e315895d9a9fe25ce58c 100644 (file)
 \r
 #define LIST_ONLY 0x03   /* CA application should clear the list when an 'ONLY' CAPMT object is received, and start working with the object */\r
 \r
+static char *socketPath="/var/emu/chroot%d/tmp/camd.socket";\r
+\r
+// -- cCCcamCard ---------------------------------------------------------------\r
+\r
+class cCCcamCard : public cMutex {\r
+private:\r
+  int ccam_fd;\r
+  int cardnum, pid, pmtlen;\r
+  bool newcw;\r
+  cTimeMs timecw;\r
+  unsigned char *capmt, cw[16];\r
+  const char *path;\r
+  cCondVar cwwait;\r
+public:\r
+  cCCcamCard(void);\r
+  ~cCCcamCard();\r
+  void Setup(int num, const char *Path);\r
+  bool Connect(void);\r
+  void Disconnect(void);\r
+  bool Connected(void) { return ccam_fd>=0; }\r
+  void WriteCaPmt(void);\r
+  void NewCaPmt(int p, const unsigned char *pmt, int len);\r
+  int Pid(void) { return pid; }\r
+  bool GetCw(unsigned char *Cw, int timeout);\r
+  void NewCw(const unsigned char *Cw);\r
+  };\r
+\r
+cCCcamCard::cCCcamCard(void)\r
+{\r
+  cardnum=-1; path=0;\r
+  ccam_fd=-1; capmt=0; newcw=false; pid=-1;\r
+}\r
+\r
+cCCcamCard::~cCCcamCard()\r
+{\r
+  Disconnect();\r
+  free(capmt);\r
+}\r
+\r
+void cCCcamCard::Setup(int num, const char *Path)\r
+{\r
+  cardnum=num; path=Path;\r
+}\r
+\r
+void cCCcamCard::Disconnect(void)\r
+{\r
+  cMutexLock lock(this);\r
+  close(ccam_fd);\r
+  ccam_fd=-1; newcw=false;\r
+}\r
+\r
+bool cCCcamCard::Connect(void)\r
+{\r
+  cMutexLock lock(this);\r
+  Disconnect();\r
+  ccam_fd=socket(AF_LOCAL,SOCK_STREAM,0);\r
+  if(!ccam_fd) {\r
+    PRINTF(L_CC_CCCAM,"%d: socket failed: %s",cardnum,strerror(errno));\r
+    return false;\r
+    }\r
+  sockaddr_un serv_addr_un;\r
+  memset(&serv_addr_un,0,sizeof(serv_addr_un));\r
+  serv_addr_un.sun_family=AF_LOCAL;\r
+  snprintf(serv_addr_un.sun_path,sizeof(serv_addr_un.sun_path),path,cardnum);\r
+  if(connect(ccam_fd,(const sockaddr*)&serv_addr_un,sizeof(serv_addr_un))!=0) {\r
+    PRINTF(L_CC_CCCAM,"%d: connect failed: %s",cardnum,strerror(errno));\r
+    Disconnect();\r
+    return false;\r
+    }\r
+  PRINTF(L_CC_CCCAM,"%d: opened camd socket",cardnum);\r
+  return true;\r
+}\r
+\r
+void cCCcamCard::WriteCaPmt(void)\r
+{\r
+  cMutexLock lock(this);\r
+  if(capmt) {\r
+    for(int retry=2; retry>0; retry--) {\r
+      if(!Connected() && !Connect()) break;\r
+      int r=write(ccam_fd,capmt,pmtlen);\r
+      if(r==pmtlen) {\r
+        newcw=false;\r
+        break;\r
+        }\r
+      PRINTF(L_CC_CCCAM,"%d: write failed: %s",cardnum,strerror(errno));\r
+      Disconnect();\r
+      }\r
+    }\r
+}\r
+\r
+void cCCcamCard::NewCaPmt(int p, const unsigned char *pmt, int len)\r
+{\r
+  cMutexLock lock(this);\r
+  free(capmt); pid=0; newcw=false;\r
+  capmt=MALLOC(unsigned char,len);\r
+  if(capmt) {\r
+    memcpy(capmt,pmt,len);\r
+    pmtlen=len;\r
+    capmt[6]=LIST_ONLY;\r
+    pid=p;\r
+    WriteCaPmt();\r
+    }\r
+}\r
+\r
+void cCCcamCard::NewCw(const unsigned char *Cw)\r
+{\r
+  cMutexLock lock(this);\r
+  if(memcmp(cw,Cw,sizeof(cw))) {\r
+    memcpy(cw,Cw,sizeof(cw));\r
+    newcw=true;\r
+    timecw.Set();\r
+    cwwait.Broadcast();\r
+    }\r
+}\r
+\r
+bool cCCcamCard::GetCw(unsigned char *Cw, int timeout)\r
+{\r
+  cMutexLock lock(this);\r
+  if(newcw && timecw.Elapsed()>3000)\r
+    newcw=false; // too old\r
+  if(!newcw)\r
+    cwwait.TimedWait(*this,timeout);\r
+  if(newcw) {\r
+    memcpy(Cw,cw,sizeof(cw));\r
+    newcw=false;\r
+    return true;\r
+    }\r
+  return false;\r
+}\r
+\r
 // -- cCardClientCCcam ---------------------------------------------------------\r
 \r
 class cCardClientCCcam : public cCardClient , private cThread {\r
 private:\r
   cNetSocket so;\r
-  //\r
+  cCCcamCard card[4];\r
   int pmtversion;\r
-  unsigned char sacapmt[4][2048];\r
-  unsigned char savedcw[4][16];\r
-  int pids[4];\r
-  int newcw[4];\r
-  uint64_t timecw[4];\r
-  int ccam_fd[4];\r
-  int lastcard;\r
-  int lastpid;\r
   int failedcw;\r
-  //\r
-  void Writecapmt(int j);\r
 protected:\r
-  virtual bool lLogin(int cardnum);\r
+  virtual bool Login(void);\r
   virtual void Action(void);\r
 public:\r
   cCardClientCCcam(const char *Name);\r
@@ -74,14 +194,13 @@ cCardClientCCcam::cCardClientCCcam(const char *Name)
 ,so(DEFAULT_CONNECT_TIMEOUT,2,3600,true)\r
 {\r
   pmtversion=0;\r
-  ccam_fd[0]=-1; ccam_fd[1]=-1; ccam_fd[2]=-1; ccam_fd[3]=-1;\r
+  for(int i=0; i<4; i++) card[i].Setup(i,socketPath);\r
 }\r
 \r
 bool cCardClientCCcam::Init(const char *config)\r
 {\r
   cMutexLock lock(this);\r
   int num=0;\r
-  signal(SIGPIPE,SIG_IGN);\r
   if(!ParseStdConfig(config,&num)) return false;\r
   return true;\r
 }\r
@@ -92,27 +211,8 @@ bool cCardClientCCcam::CanHandle(unsigned short SysId)
   return false;\r
 }\r
 \r
-bool cCardClientCCcam::lLogin(int cardnum)\r
+bool cCardClientCCcam::Login(void)\r
 {\r
-  sockaddr_un serv_addr_un;\r
-  char camdsock[256];\r
-  int res;\r
-\r
-  close(ccam_fd[cardnum]);\r
-  sprintf(camdsock,"/var/emu/chroot%d/tmp/camd.socket",cardnum);\r
-  printf(" socket = %s\n",camdsock);\r
-  ccam_fd[cardnum]=socket(AF_LOCAL, SOCK_STREAM, 0);\r
-  bzero(&serv_addr_un, sizeof(serv_addr_un));\r
-  serv_addr_un.sun_family = AF_LOCAL;\r
-  strcpy(serv_addr_un.sun_path, camdsock);\r
-  res=connect(ccam_fd[cardnum], (const sockaddr*)&serv_addr_un, sizeof(serv_addr_un));\r
-  if (res !=0) {\r
-    PRINTF(L_CC_CCCAM,"Couldnt open camd.socket..... errno = %d Aggg",errno);\r
-    close(ccam_fd[cardnum]);\r
-    ccam_fd[cardnum] = -1;\r
-    }\r
-  PRINTF(L_CC_CCCAM,"Opened camd.socket..... ccamd_fd  = %d ",ccam_fd[cardnum]);\r
-\r
   if(!so.Connected()) {\r
     so.Disconnect();\r
     if(!so.Bind("127.0.0.1",port)) return false;\r
@@ -129,7 +229,6 @@ bool cCardClientCCcam::ProcessECM(const cEcmInfo *ecm, const unsigned char *data
   //  cMutexLock lock(this);\r
   //newcw[cardnum] =0;\r
   unsigned char capmt[2048];\r
-  PRINTF(L_CC_CCCAM,"Processing ECM.... for card %d",cardnum);\r
   const int caid=ecm->caId;\r
   const int pid =ecm->ecm_pid;\r
   int lenpos=10;\r
@@ -186,90 +285,37 @@ bool cCardClientCCcam::ProcessECM(const cEcmInfo *ecm, const unsigned char *data
   capmt[lenpos+1]=(len & 0xff);\r
   capmt[4]=((wp-6)>>8) & 0xff;\r
   capmt[5]=(wp-6) & 0xff;\r
-  if (newcw[cardnum]) {\r
-    if ((cTimeMs::Now() - timecw[cardnum]) > 3000)\r
-      // just too old lets bin em...\r
-      newcw[cardnum] = 0;\r
-    }\r
-  if ((pid != pids[cardnum]) || (ccam_fd[cardnum] == -1)) { // channel change\r
+\r
+  cCCcamCard *c=&card[cardnum];\r
+\r
+  int timeout=700;\r
+  if(pid!=c->Pid() || !c->Connected()) { // channel change\r
     PRINTF(L_CC_CCCAM,"sending capmts ");\r
-    pids[cardnum] = pid;\r
-    newcw[cardnum] =0;\r
-    memcpy(sacapmt[cardnum],capmt,2048);\r
-    lLogin(cardnum);\r
-    Writecapmt(cardnum);\r
-    usleep(300000);\r
+    c->NewCaPmt(pid,capmt,wp);\r
+    timeout=3000;\r
     }\r
-  lastcard = cardnum;\r
-  lastpid = pid;\r
-  failedcw=0;\r
-  int u=0;\r
-  while ((newcw[cardnum] == 0) && (u++<700))\r
-    usleep(1000);      // give the card a chance to decode it...\r
-  if (newcw[cardnum] == 0) {\r
+  if(!c->GetCw(cw,timeout)) {\r
     // somethings up, so we will send capmt again.\r
-    pids[cardnum] = pid;\r
-    //  memcpy(capmt,sacapmt[cardnum],2048);\r
-    Writecapmt(cardnum);\r
-    }\r
-  u=0;\r
-  while ((newcw[cardnum] == 0) && (u++<1000))\r
-    usleep(1000);\r
-  if (newcw[cardnum] == 0) {\r
-    PRINTF(L_CC_CCCAM,"FAILED ECM FOR CARD %d !!!!!!!!!!!!!!!!!!",cardnum);\r
-    sacapmt[cardnum][9]=pmtversion;     //reserved - version - current/next\r
-    pmtversion++;\r
-    pmtversion%=32;\r
-    failedcw++;\r
-    if (failedcw == 10) {\r
-      // CCcam is having problems lets mark it for a restart....\r
-      FILE *i = fopen("/tmp/killCCcam","w+");\r
-      fclose(i);\r
+    c->WriteCaPmt();\r
+    timeout=1000;\r
+    if(!c->GetCw(cw,timeout)) {\r
+      PRINTF(L_CC_CCCAM,"%d: FAILED ECM !",cardnum);\r
+      c->Disconnect();\r
+      failedcw++;\r
+      if(failedcw>=10) {\r
+        // CCcam is having problems lets mark it for a restart....\r
+        FILE *f=fopen("/tmp/killCCcam","w+");\r
+        fclose(f);\r
+        failedcw=0;\r
+        }\r
+      return false;\r
       }\r
-    return false;\r
     }\r
-  memcpy(cw,savedcw[cardnum],16);\r
-  newcw[cardnum] =0;\r
-  PRINTF(L_CC_CCCAM," GOT CW FOR CARD %d !!!!!!!!!!!!!!!!!!",cardnum);\r
-  sacapmt[cardnum][9]=pmtversion;     //reserved - version - current/next\r
-  pmtversion++;\r
-  pmtversion%=32;\r
+  PRINTF(L_CC_CCCAM,"%d: GOT CW !",cardnum);\r
   failedcw=0;\r
-  Writecapmt(cardnum);\r
   return true;\r
 }\r
 \r
-void cCardClientCCcam::Writecapmt(int n)\r
-{\r
-  int len;\r
-  int list_management ;\r
-  list_management = LIST_ONLY;\r
-  sacapmt[n][6] = list_management;\r
-  len = sacapmt[n][4] << 8;\r
-  len |= sacapmt[n][5];\r
-  len += 6;\r
-  int retry = 1;\r
-  while (retry) {\r
-    PRINTF(L_CC_CCCAM,"Writing capmt for card %d %d =================================================",n, sacapmt[n][6]);\r
-    if (ccam_fd[n]==-1)\r
-      lLogin(n);\r
-    if (ccam_fd[n]==-1)\r
-      return ;\r
-\r
-    int r = write(ccam_fd[n], &sacapmt[n],len );\r
-    if (r != len) {\r
-      PRINTF(L_CC_CCCAM,"CCcam probably has crashed or been killed...");\r
-      close(ccam_fd[n]);\r
-      ccam_fd[n]=-1;\r
-      retry++;\r
-      if (retry > 2)\r
-        retry =0;\r
-      }\r
-    else\r
-      retry =0;\r
-    }\r
-}\r
-\r
 void cCardClientCCcam::Action()\r
 {\r
   unsigned char cw[18];\r
@@ -280,19 +326,8 @@ void cCardClientCCcam::Action()
         cw[2],cw[3],cw[4],cw[5],cw[6],cw[7],cw[8],cw[9],\r
         cw[10],cw[11],cw[12],cw[13],cw[14],cw[15],cw[16],cw[17]);\r
 \r
-      if (cw[1] == 0x0f) {\r
-        int n = cw[0];\r
-        if (memcmp(savedcw[n],cw+2,16)) {\r
-          if (newcw[n] == 1) {\r
-            close(ccam_fd[n]);\r
-            ccam_fd[n]=-1;\r
-            }\r
-          memcpy(savedcw[n],cw+2,16);\r
-          newcw[n] =1;\r
-          timecw[n]= cTimeMs::Now();\r
-          PRINTF(L_CC_CCCAM,"SAVING KEYS USING PID FROM CCCAM  %d !!!!!!!!!!!", n);\r
-          }\r
-        }\r
+      if(cw[1]==0x0f && cw[0]<4)\r
+        card[cw[0]].NewCw(cw+2);\r
       }\r
     }\r
 }\r