./ MultiCS.r69 / th-ecm.c
#define MAXSRVTAB 255 struct srvtab_data { struct cs_server_data *srv; struct cs_card_data *card; // selected card uint32_t shareid; // Selected Card ShareID int uphops; int val; // sid value unsigned int ecmtime; // Card Ecmtime uint32 ecmperhr; }; struct srvtab_data srvlist[MAXSRVTAB]; struct srvtab_data *psrvlist[MAXSRVTAB]; struct srvtab_data *srvtemp; int srvtab_arrange(struct cardserver_data *cs, int ecmid, int bestone ) { ECM_DATA *ecm = getecmbyid(ecmid); int i,j; int nbsrv = 0; struct cs_server_data *srv; memset( srvlist, 0 , sizeof(srvlist) ); nbsrv = 0; // MULTICARD Servers Selection (Newcamd,CCcam,Mgcamd...) ;) unsigned int ticks = GetTickCount(); srv = cfg.server; while ( srv && (nbsrv<MAXSRVTAB) ) { if ( !IS_DISABLED(srv->flags)&&(srv->handle>0) ) if ( ( cs->option.fallownewcamd&&(srv->type==TYPE_NEWCAMD) ) || ( cs->option.fallowcccam&&(srv->type==TYPE_CCCAM) ) || ( cs->option.fallowradegast&&(srv->type==TYPE_RADEGAST) ) ) // Remove Circular request: check for client ip & srv ip if ( (srv->host->ip==0x0100007F) || !ecm_checkip(ecmid, srv->host->ip) ) { // Check for CS PORTS for(i=0; i<MAX_CSPORTS; i++ ) { if (!srv->csport[i]) break; if (srv->csport[i]==cs->newcamd.port) { i=0; break; } } if (i==0) { // ADD TO PROFILE //Check for used servers, dont reuse for (i=0; i<20;i++) { if (!ecm->server[i].srvid) break; if (ecm->server[i].srvid==srv->id) break; } if ( (i>=20)||(ecm->server[i].srvid!=srv->id) ) { // Check for ECM TIMEOUT if ( (srv->busy)&&((srv->lastecmtime+20000)<ticks) ) { // timeout debugf(getdbgflag(DBG_SERVER,0,srv->id)," ??? server (%s:%d) doesnt send ecm answer\n", srv->host->name,srv->port); srv->ecmtimeout++; srv->busy = 0; if (srv->type==TYPE_CCCAM) cc_disconnect_srv(srv); else if (srv->type==TYPE_NEWCAMD) cs_disconnect_srv(srv); } else { // Check for newcamd server sids i = 0; if ( srv->sids && (srv->type==TYPE_NEWCAMD) ) { struct sid_chid_data *sid = srv->sids; for(i=0; i<MAX_SIDS; i++,sid++) { if ( sid->sid==0 ) break; if (sid->sid==ecm->sid) if (!sid->chid || (sid->chid==ecm->chid) ) { i=0; break; } } } if (i==0) { // check for any card to decode pthread_mutex_lock(&srv->lock); struct cs_card_data *pcard = srv_findcard( srv, cs, ecm->caid, ecm->provid ); // check if isthere any available card if ( pcard ) { srvlist[nbsrv].srv = srv; srvlist[nbsrv].card = pcard; // default card srvlist[nbsrv].shareid = pcard->shareid; // default card srvlist[nbsrv].uphops = pcard->uphops; srvlist[nbsrv].val = 0; psrvlist[nbsrv] = &srvlist[nbsrv]; nbsrv++; } pthread_mutex_unlock(&srv->lock); } } } } } srv = srv->next; } // ARRANGE BY SID/TIME FILTER #ifdef SID_FILTER //Check FAILED SIDS struct cs_card_data *card=NULL; i=0; for(j=0; j<nbsrv; j++) { pthread_mutex_lock(&psrvlist[j]->srv->lock); // best card to decode is selected, it may there is only worst one but is returned psrvlist[j]->val = sidata_getval( psrvlist[j]->srv, cs, ecm->caid, ecm->provid, ecm->sid, &card); // if ( psrvlist[j]->val > -100 ) if ( !cs->option.maxfailedecm || (psrvlist[j]->val > -cs->option.maxfailedecm) ) { // available card+sid : block card that have decode failed on sid if (card) { psrvlist[j]->card = card; psrvlist[j]->shareid = card->shareid; psrvlist[j]->uphops = card->uphops; if (psrvlist[j]->srv->type==TYPE_CCCAM) if (card->ecmok>10) psrvlist[j]->ecmtime = card->ecmoktime/card->ecmok; else psrvlist[j]->ecmtime = 0; else if (psrvlist[j]->srv->ecmok>10) psrvlist[j]->ecmtime = psrvlist[j]->srv->ecmoktime/psrvlist[j]->srv->ecmok; else psrvlist[j]->ecmtime = 0; if ( !cs->option.server.validecmtime || (psrvlist[j]->ecmtime<cs->option.server.validecmtime) ) { if (psrvlist[j]->srv->type==TYPE_CCCAM) { if (card) { if (i<j) psrvlist[i] = psrvlist[j]; i++; } } else { if (i<j) psrvlist[i] = psrvlist[j]; i++; } } } } pthread_mutex_unlock(&psrvlist[j]->srv->lock); } psrvlist[i] = NULL; nbsrv = i; #endif //Remove Cardservers with delay time if (cs->option.server.timeperecm) { i=0; for(j=0; j<nbsrv; j++) { //if ( (psrvlist[j]->srv->host->ip!=0x0100007F)&&(psrvlist[j]->srv->type==TYPE_NEWCAMD) ) if ( (psrvlist[j]->srv->type==TYPE_NEWCAMD) ) { unsigned int msperecm = ( (ticks-psrvlist[j]->srv->connected) + psrvlist[j]->srv->uptime ) / (psrvlist[j]->srv->ecmnb+1); unsigned int tim; if ( msperecm > (2*cs->option.server.timeperecm) ) tim = 0; else if ( msperecm > cs->option.server.timeperecm ) tim = (2*cs->option.server.timeperecm)-msperecm; else tim = cs->option.server.timeperecm; if ( (psrvlist[j]->srv->lastecmtime+tim)<=ticks ) { if (i<j) psrvlist[i] = psrvlist[j]; i++; } } else { if (i<j) psrvlist[i] = psrvlist[j]; i++; } } psrvlist[i] = NULL; nbsrv = i; } //debugf(" srvtab_arrange(%04x:%06x:%04x) %d\n", ecm->caid, ecm->provid, ecm->sid, nbsrv); if (!nbsrv) return -1; // Remove Busy Servers i=0; for(j=0; j<nbsrv; j++) { if (!psrvlist[j]->srv->busy) { if (i<j) psrvlist[i] = psrvlist[j]; i++; } } psrvlist[i] = NULL; nbsrv = i; //// ARRANGE // Arrange by ECM LAST SENT TIME for(i=0; i<nbsrv-1; i++) for(j=i+1; j<nbsrv; j++) if ( psrvlist[i]->srv->lastecmtime > psrvlist[j]->srv->lastecmtime ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } #ifdef SID_FILTER ticks=GetTickCount(); for(i=0; i<nbsrv; i++) psrvlist[i]->ecmperhr = (psrvlist[i]->srv->ecmnb*3600*1000) / ( 1+ (ticks-psrvlist[i]->srv->connected)+psrvlist[i]->srv->uptime ); if (!bestone) // Arrange by ECM LAST SENT TIME && unbusy state & sid ok for(i=0; i<nbsrv-1; i++) for(j=i+1; j<nbsrv; j++) if (psrvlist[i]->srv->busy == psrvlist[j]->srv->busy ) { if ( (psrvlist[j]->val>=0)&&(psrvlist[j]->srv->priority==1)&&(psrvlist[i]->srv->priority==0) ) { // check if using local card srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } else if (psrvlist[i]->val>=0) { if (psrvlist[j]->val>=0) { // Check for card uphops if (psrvlist[i]->uphops > psrvlist[j]->uphops) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } else if ( psrvlist[i]->ecmperhr > psrvlist[j]->ecmperhr ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } } } else if (psrvlist[i]->val==-1) { if (psrvlist[j]->val>=0) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } else if (psrvlist[j]->val==-1) { if ( psrvlist[i]->ecmperhr > psrvlist[j]->ecmperhr ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } } } else { if (psrvlist[j]->val>=-1) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } else { if ( psrvlist[i]->ecmperhr > psrvlist[j]->ecmperhr ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } } } } else { if ( psrvlist[i]->srv->busy ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } } else for(i=0; i<nbsrv-1; i++) for(j=i+1; j<nbsrv; j++) if (psrvlist[i]->srv->busy == psrvlist[j]->srv->busy ) { if (psrvlist[i]->val>0) { if (psrvlist[j]->val>0) { if ( ( psrvlist[i]->ecmperhr > psrvlist[j]->ecmperhr ) ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } } } else if (psrvlist[i]->val==0) { if (psrvlist[j]->val>0) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } else if (psrvlist[j]->val==0) { if ( ( psrvlist[i]->ecmperhr > psrvlist[j]->ecmperhr ) ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } } } else { if (psrvlist[j]->val>=0) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } else { if ( psrvlist[i]->val < psrvlist[j]->val ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } } } } else { if ( psrvlist[i]->srv->busy ) { srvtemp = psrvlist[i]; psrvlist[i] = psrvlist[j]; psrvlist[j] = srvtemp; } } #endif return nbsrv; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // SELECT & SEND ECM TO servers /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Check sending ecm to servers /////////////////////////////////////////////////////////////////////////////// uint32 check_sendecm() { // Send priority // 1.Send to all ecm's that wasnt send yet // 2.Send to all ecm's that having send only once // 3.Send to all ecm's that having send only twice //XXX ... uint restime = GetTickCount() + 10000; uint ecmtime = restime; struct cs_server_data *newsrv; int lastecmid = nextecmid(srvmsgid); int ecmid = lastecmid; while ( (ecmid=prevecmid(ecmid)) != lastecmid ) { ECM_DATA *ecm = getecmbyid(ecmid); uint32 ticks = GetTickCount(); ecm->checktime = 0; // CACHE(fallowcache = 1) if (ecm->dcwstatus==STAT_DCW_WAITCACHE) { struct cardserver_data *cs = getcsbyid( ecm->csid ); if (!cs) { ecm->statusmsg = "Invalid profile id"; ecm->dcwstatus = STAT_DCW_FAILED; continue; } if (cs->option.fallowcache) { if (!ecm->waitcache) { // Not done //debugf(" send pipe cache\n"); if (cs->option.fallowcache && pipe_send_cache_find( ecm, cs)) { ecm->waitcache = 1; ecmtime = ecm->recvtime+cs->option.cachetimeout; ecm->checktime = ecm->recvtime+cs->option.cachetimeout; } else ecm->dcwstatus = STAT_DCW_WAIT; } else { if ( ( (ecm->recvtime+cs->option.cachetimeout)<=ticks ) ) ecm->dcwstatus = STAT_DCW_WAIT; else { //debugf(" Wait for cache\n"); ecmtime = ecm->recvtime+cs->option.cachetimeout; ecm->checktime = ecm->recvtime+cs->option.cachetimeout; } } } else ecm->dcwstatus = STAT_DCW_WAIT; if (restime>ecmtime) restime = ecmtime; } // SEND ECM if ( (ecm->dcwstatus==STAT_DCW_WAIT) ) { // Check Profile struct cardserver_data *cs = getcsbyid( ecm->csid ); if (!cs) { ecm->statusmsg = "Invalid profile id"; ecm->dcwstatus = STAT_DCW_FAILED; cs_dcw_check_time=0; #ifdef MGCAMD_SRV mg_dcw_check_time = 0; #endif #ifdef CCCAM_SRV cc_dcw_check_time = 0; #endif #ifdef FREECCCAM_SRV frcc_dcw_check_time = 0; #endif #ifdef RADEGAST_SRV rdgd_dcw_check_time = 0; #endif continue; } //check for decode failed int nbservers = ecm_nbsentsrv(ecm); int waitsrv = ecm_nbwaitsrv(ecm); // Check for Max used Servers if ( (cs->option.server.max>0) && (nbservers>=cs->option.server.max) ) { if (!waitsrv) { ecm->statusmsg = "Decode failed, max servers is reached and no more servers to wait"; ecm->dcwstatus = STAT_DCW_FAILED; cs_dcw_check_time=0; #ifdef MGCAMD_SRV mg_dcw_check_time = 0; #endif #ifdef CCCAM_SRV cc_dcw_check_time = 0; #endif #ifdef FREECCCAM_SRV frcc_dcw_check_time = 0; #endif #ifdef RADEGAST_SRV rdgd_dcw_check_time = 0; #endif // Send DCW to Cache if not sent if ( cs->option.fallowcache && cs->option.cachesendrep && (ecm->cachestatus!=ECM_CACHE_REP) ) { //pipe_send_cache_reply(ecm,cs); // Send failed Cache Reply ecm->cachestatus = ECM_CACHE_REP; } } } // Check for ECM TimeOut else if ( (ticks-ecm->recvtime) >= cs->option.dcw.timeout ) { if (!waitsrv) { ecm->statusmsg = "Decode failed, dcw timeout"; ecm->dcwstatus = STAT_DCW_FAILED; cs_dcw_check_time=0; #ifdef MGCAMD_SRV mg_dcw_check_time = 0; #endif #ifdef CCCAM_SRV cc_dcw_check_time = 0; #endif #ifdef FREECCCAM_SRV frcc_dcw_check_time = 0; #endif #ifdef RADEGAST_SRV rdgd_dcw_check_time = 0; #endif // Send DCW to Cache if not sent if ( cs->option.fallowcache && cs->option.cachesendrep && (ecm->cachestatus!=ECM_CACHE_REP) ) { //pipe_send_cache_reply(ecm,cs); // Send failed Cache Reply ecm->cachestatus = ECM_CACHE_REP; } } } // Check for ECM sending else if ((ticks-ecm->recvtime)<=cs->option.server.timeout) { // ~ cfg.cardserver.option.dcw.timeout*2/3 is the cardserver timeout // check for decode failed with no remaining server to wait, send to new cardserver if ( !waitsrv || (cs->option.server.first>nbservers) || ((ticks-ecm->lastsendtime)>=cs->option.server.interval) ) { //debugf(" check_sendecm(): ECM -> CardServer '%s' ch %04x:%06x:%04x\n", cs->name,ecm->caid,ecm->provid,ecm->sid); newsrv = NULL; if ( srvtab_arrange(cs, ecmid, nbservers > 0 )==-1 ) { // No more servers to decode //debugf(" sendecm: no servers found to decode\n"); if (!waitsrv) { ecm->statusmsg = "Decode failed, No servers found to decode"; ecm->dcwstatus = STAT_DCW_FAILED; cs_dcw_check_time=0; #ifdef MGCAMD_SRV mg_dcw_check_time = 0; #endif #ifdef CCCAM_SRV cc_dcw_check_time = 0; #endif #ifdef FREECCCAM_SRV frcc_dcw_check_time = 0; #endif #ifdef RADEGAST_SRV rdgd_dcw_check_time = 0; #endif // Send DCW to Cache if not sent if ( cs->option.fallowcache && cs->option.cachesendrep && (ecm->cachestatus!=ECM_CACHE_REP) ) { //pipe_send_cache_reply(ecm,cs); //Send Failed Cache Reply ecm->cachestatus=ECM_CACHE_REP; } } else { ecm->checktime = ecm->lastrecvtime+cs->option.server.timeout; ecmtime = ecm->lastrecvtime+cs->option.server.timeout; if (restime>ecmtime) restime = ecmtime; } continue; } else if (psrvlist[0] && psrvlist[0]->srv) { newsrv = psrvlist[0]->srv; newsrv->busycard = psrvlist[0]->card; // dont save pointers!!! newsrv->busycardid = psrvlist[0]->shareid; } else { ecm->statusmsg = "Wait for available servers"; #ifdef BUSY_SERVER if (!waitsrv && !nbservers) { ecm->statusmsg = "Decode failed, no free server"; ecm->dcwstatus = STAT_DCW_FAILED; cs_dcw_check_time=0; #ifdef MGCAMD_SRV mg_dcw_check_time = 0; #endif #ifdef CCCAM_SRV cc_dcw_check_time = 0; #endif #ifdef FREECCCAM_SRV frcc_dcw_check_time = 0; #endif #ifdef RADEGAST_SRV rdgd_dcw_check_time = 0; #endif cs->ecmbusysrv++; } #endif continue; } // SEND ECM if ( newsrv && !newsrv->busy ) {// time to send ecm if ((ticks-ecm->lastrecvtime+cs->option.server.interval)<cs->option.server.timeout) { ecm->checktime = ecm->lastsendtime+cs->option.server.interval; ecmtime = ecm->lastsendtime+cs->option.server.interval; } else { ecm->checktime = ecm->lastrecvtime+cs->option.dcw.timeout; ecmtime = ecm->lastrecvtime+cs->option.dcw.timeout; } //debugf(" sendecm: selected server to decode (%s:%d)\n", newsrv->host->name, newsrv->port); if (newsrv->type==TYPE_NEWCAMD) { if (cs_sendecm_srv(cs, newsrv, ecm)>0) { ecm->lastsendtime = GetTickCount(); debugf(getdbgflagpro(DBG_SERVER,0,newsrv->id,cs->id)," -> ecm to server%d (%s:%d) ch %04x:%06x:%04x\n",nbservers,newsrv->host->name,newsrv->port,ecm->caid,ecm->provid,ecm->sid); newsrv->lastecmtime = GetTickCount(); newsrv->ecmnb++; newsrv->busy=1; newsrv->busyecmid = ecmid; newsrv->busyecmhash = ecm->hash; newsrv->retry=0; ecm_addsrv(ecm, newsrv->id); if ( cs->option.fallowcache && cs->option.cachesendreq && !nbservers && (ecm->cachestatus==ECM_CACHE_NONE) ) pipe_send_cache_request(ecm,cs); ecm->cachestatus = ECM_CACHE_REQ; } } #ifdef CCCAM_CLI else if (newsrv->type==TYPE_CCCAM) { if (cc_sendecm_srv(newsrv, ecm)>0) { ecm->lastsendtime = GetTickCount(); debugf(getdbgflagpro(DBG_SERVER,0,newsrv->id,cs->id)," -> ecm to CCcam server%d (%s:%d) ch %04x:%06x:%04x\n",nbservers,newsrv->host->name,newsrv->port,ecm->caid,ecm->provid,ecm->sid); newsrv->lastecmtime = GetTickCount(); newsrv->ecmnb++; struct cs_card_data *card = cc_getcardbyid( newsrv, newsrv->busycardid ); if (card) card->ecmnb++; newsrv->busy=1; newsrv->busyecmid = ecmid; newsrv->busyecmhash = ecm->hash; newsrv->retry=0; ecm_addsrv(ecm, newsrv->id); if ( cs->option.fallowcache && cs->option.cachesendreq && !nbservers && (ecm->cachestatus==ECM_CACHE_NONE) ) pipe_send_cache_request(ecm,cs); ecm->cachestatus = ECM_CACHE_REQ; } } #endif #ifdef RADEGAST_CLI else if (newsrv->type==TYPE_RADEGAST) { if (rdgd_sendecm_srv(newsrv, ecm)>0) { ecm->lastsendtime = GetTickCount(); debugf(getdbgflagpro(DBG_SERVER,0,newsrv->id,cs->id)," -> ecm to Radegast server%d (%s:%d) ch %04x:%06x:%04x\n",nbservers,newsrv->host->name,newsrv->port,ecm->caid,ecm->provid,ecm->sid); newsrv->lastecmtime = GetTickCount(); newsrv->ecmnb++; newsrv->busy=1; newsrv->busyecmid = ecmid; newsrv->busyecmhash = ecm->hash; newsrv->retry=0; ecm_addsrv(ecm, newsrv->id); if ( cs->option.fallowcache && cs->option.cachesendreq && !nbservers && (ecm->cachestatus==ECM_CACHE_NONE) ) pipe_send_cache_request(ecm,cs); ecm->cachestatus = ECM_CACHE_REQ; } } #endif ecm->statusmsg = "Waiting for servers..."; if (restime>ecmtime) restime = ecmtime; } } } else if (!waitsrv) { ecm->statusmsg = "Decode failed, no server open this channel"; ecm->dcwstatus = STAT_DCW_FAILED; cs_dcw_check_time=0; #ifdef MGCAMD_SRV mg_dcw_check_time = 0; #endif #ifdef CCCAM_SRV cc_dcw_check_time = 0; #endif #ifdef FREECCCAM_SRV frcc_dcw_check_time = 0; #endif #ifdef RADEGAST_SRV rdgd_dcw_check_time = 0; #endif // Send DCW to Cache if not sent if ( cs->option.fallowcache && cs->option.cachesendrep && (ecm->cachestatus!=ECM_CACHE_REP) ) { //pipe_send_cache_reply(ecm,cs); //Send Failed Cache Reply ecm->cachestatus = ECM_CACHE_REP; } } } } return (restime+1); } /////////////////////////////////////////////////////////////////////////////// // SEND ECM THREAD /////////////////////////////////////////////////////////////////////////////// void recv_ecm_pipe() { uint16 sid; uint16 caid; uint32 hash; uchar buf[1024]; int ecmid; struct pollfd pfd[2]; do { int len = pipe_recv( srvsocks[0], buf); if (len>0) { switch(buf[0]) { case PIPE_LOCK: pthread_mutex_lock(&prg.lockmain); pthread_mutex_unlock(&prg.lockmain); break; case PIPE_CACHE_FIND_FAILED: //debugf(" ecm check PIPE_CACHE_FIND_FAILED\n"); //Search for ecm sid = (buf[3]<<8) | buf[4]; caid = (buf[7]<<8) | buf[8]; hash = (buf[9]<<24) | (buf[10]<<16) | (buf[11]<<8) | (buf[12]); pthread_mutex_lock(&prg.lockecm); //### ecmid = search_ecmdata_byhash( hash ); if (ecmid!=-1) { ECM_DATA *ecm = getecmbyid(ecmid); if ( (ecm->caid==caid)&&(ecm->hash==hash)&&(ecm->sid==sid)&&(ecm->dcwstatus==STAT_DCW_WAITCACHE) ) { ecm->dcwstatus = STAT_DCW_WAIT; } } // else debugf(" pipe: ecm not found (%08X)\n",hash); pthread_mutex_unlock(&prg.lockecm); //### break; case PIPE_CACHE_FIND_SUCCESS: // SET DCW //Search for ecm sid = (buf[3]<<8) | buf[4]; caid = (buf[7]<<8) | buf[8]; hash = (buf[9]<<24) | (buf[10]<<16) | (buf[11]<<8) | (buf[12]); int peerid = (buf[13]<<8) | buf[14]; //debugf(" ecm check PIPE_CACHE_FIND_SUCCESS %04x:%04x:%08x\n",caid, sid, hash); debughex(buf,len); pthread_mutex_lock(&prg.lockecm); //### int ecmid = search_ecmdata_byhash( hash ); if (ecmid!=-1) { ECM_DATA *ecm = getecmbyid(ecmid); if ( (ecm->caid==caid)&&(ecm->hash==hash)&&(ecm->sid==sid)&&(ecm->dcwstatus!= STAT_DCW_SUCCESS) ) { struct cardserver_data *cs = getcsbyid(ecm->csid); struct cachepeer_data *peer = getpeerbyid(peerid); if (cs&&peer) if (cs->option.fallowcache) ecm_setdcw( cs, ecm, buf+15, DCW_SOURCE_CACHE, peer->id); } } // else debugf(" pipe: ecm not found (%08X)\n",hash); pthread_mutex_unlock(&prg.lockecm); //### break; } } pfd[0].fd = srvsocks[0]; pfd[0].events = POLLIN | POLLPRI; } while (poll(pfd, 1, 0)>0); } char *src2string(int srctype, int srcid, char *ret) { static char ss1[] = "server"; static char ss2[] = "cache peer"; static char ss3[] = "newcamd client"; if (srctype==DCW_SOURCE_SERVER) { struct cs_server_data *srv = getsrvbyid(srcid); if (srv) sprintf( ret,"server (%s:%d)", srv->host->name, srv->port); else sprintf( ret,"Unknow server (id=%d)", srcid); return ss1; } else if (srctype==DCW_SOURCE_CACHE) { struct cachepeer_data *peer = getpeerbyid(srcid); if (peer) sprintf( ret,"cache peer (%s:%d)", peer->host->name, peer->port); else sprintf( ret,"Unknown cache peer (id=%d)", srcid); return ss2; } #ifdef SRV_CSCACHE else if (srctype==DCW_SOURCE_CSCLIENT) { // srcid = (csid<<16)|cliid; struct cardserver_data *cs = getcsbyid( srcid>>16 ); if (cs) { struct cs_client_data *cli = getnewcamdclientbyid( srcid&0xffff ); if (cli) { sprintf( ret,"newcamd client '%s'", cli->user); return ss3; } } sprintf( ret,"Unknown newcamd client (id=%x)", srcid); return ss3; } else if (srctype==DCW_SOURCE_MGCLIENT) { // srcid = (csid<<16)|cliid; struct mg_client_data *cli = getmgcamdclientbyid( srcid ); if (cli) sprintf( ret,"mgcamd client '%s'", cli->user); else sprintf( ret,"Unknown mgcamd client (id=%d)", srcid); return ss3; } #endif else { sprintf( ret,"Unknown Source (%d/%d)", srctype, srcid); } return NULL; } void ecm_setdcw( struct cardserver_data *cs, ECM_DATA *ecm, uchar dcw[16], int srctype, int srcid) { pthread_mutex_lock(&prg.lockdcw); if (ecm->dcwstatus!=STAT_DCW_SUCCESS) { // Search for SAME DCW int ecmid = search_ecmdata_bycw( dcw, ecm->hash, ecm->sid, ecm->caid, ecm->provid); if (ecmid==-1) { #ifdef CHECK_NEXTDCW if (cs && cs->option.dcw.check) if ( !checkfreeze_setdcw(ecm->srvmsgid,dcw) ) { pthread_mutex_unlock(&prg.lockdcw); return; } #endif ecm->statusmsg = "Decode Success"; int instant = (ecm->dcwstatus==STAT_DCW_WAITCACHE); ecm->dcwsrctype = srctype; ecm->dcwsrcid = srcid; ecm->dcwstatus = STAT_DCW_SUCCESS; memcpy( ecm->cw, dcw, 16 ); if (cs) { uint ecmtime = GetTickCount()-ecm->recvtime; if (ecmtime<cs->option.dcw.timeout) { cs->ecmok++; cs->ecmoktime += ecmtime; int time = (ecmtime+50)/100; if (time<100) cs->ttime[time]++; else cs->ttime[100]++; if (srctype==DCW_SOURCE_CACHE) { struct cachepeer_data *peer = getpeerbyid(srcid); if (peer) { // setup peer last used cache peer->lastcaid = ecm->caid; peer->lastprov = ecm->provid; peer->lastsid = ecm->sid; peer->lastdecodetime = ecmtime; peer->hitnb++; cs->cachehits++; cfg.cache.hits++; if (instant) { peer->ihitnb++; cs->cacheihits++; cfg.cache.ihits++; } } if (time<100) cs->ttimecache[time]++; else cs->ttimecache[100]++; } else if (srctype==DCW_SOURCE_SERVER) { if (time<100) cs->ttimecards[time]++; else cs->ttimecards[100]++; } #ifdef SRV_CSCACHE else if (srctype==DCW_SOURCE_CSCLIENT) { // srcid = (csid<<16)|cliid; struct cardserver_data *cs = getcsbyid( srcid>>16 ); if (cs) { struct cs_client_data *cli = getnewcamdclientbyid( srcid&0xffff ); if (cli) cli->cachedcw++; } // if (time<100) cs->ttimeclients[time]++; else cs->ttimeclients[100]++; } else if (srctype==DCW_SOURCE_MGCLIENT) { struct mg_client_data *cli = getmgcamdclientbyid(srcid); if (cli) cli->cachedcw++; if (time<100) cs->ttimeclients[time]++; else cs->ttimeclients[100]++; } #endif // Send DCW to Cache if not sent if ( cs->option.fallowcache && cs->option.cachesendrep && ecm->cachestatus!=ECM_CACHE_REP ) { pipe_send_cache_reply(ecm,cs); //Send Good Cache Reply ecm->cachestatus = ECM_CACHE_REP; } } } // Send DCW to clients cs_dcw_check_time=0; #ifdef MGCAMD_SRV mg_dcw_check_time = 0; #endif #ifdef CCCAM_SRV cc_dcw_check_time = 0; #endif #ifdef FREECCCAM_SRV frcc_dcw_check_time = 0; #endif #ifdef RADEGAST_SRV rdgd_dcw_check_time = 0; #endif #ifdef CLI_CSCACHE // Send to Newcamd Cached Servers int i; for( i=0; i<20; i++ ) { if (!ecm->server[i].srvid) break; if (ecm->server[i].flag==ECM_SRV_REQUEST) { struct cs_server_data *srv = getsrvbyid(ecm->server[i].srvid); if (!srv) continue; if (!srv->busy) continue; if ( (srv->type==TYPE_NEWCAMD)&&(srv->cscached) ) { // Send DCW to server struct cs_custom_data srvcd; unsigned char buf[32]; srvcd.msgid = srv->busyecmid; srvcd.caid = ecm->caid; srvcd.sid = ecm->sid; srvcd.provid = ecm->provid; buf[0] = ecm->ecm[0] | 0x40; // 0xC0 | 0xC1 buf[2] = 0x10; memcpy(&buf[3], &ecm->cw,16); cs_message_send( srv->handle, &srvcd, buf, 19, srv->sessionkey); } } } #endif } } pthread_mutex_unlock(&prg.lockdcw); } #ifdef MSGTHREAD #define TYPE_SERVER 1 #define TYPE_CLIENT_NEWCAMD 2 #define TYPE_CLIENT_CCCAM 3 #define TYPE_CLIENT_MGCAMD 4 struct recvmsg_data { int type; union { struct cs_server_data *srv; struct cc_client_data *cccli; struct mg_client_data *mgcli; struct cs_client_data *cscli; }; struct cardserver_data *cs; pthread_t lastthreadid; }; void *recv_msg(struct recvmsg_data *data) { if (data->type==TYPE_SERVER) { if (data->srv->type==TYPE_NEWCAMD) cs_srv_recvmsg(data->srv); #ifdef CCCAM_CLI else if (data->srv->type==TYPE_CCCAM) cc_srv_recvmsg(data->srv); #endif #ifdef RADEGAST_CLI else if (data->srv->type==TYPE_RADEGAST) rdgd_srv_recvmsg(data->srv); #endif } else if (data->type==TYPE_CLIENT_CCCAM) { cc_cli_recvmsg(data->cccli); } else if (data->type==TYPE_CLIENT_MGCAMD) { mg_cli_recvmsg(data->mgcli); } else if (data->type==TYPE_CLIENT_NEWCAMD) { cs_cli_recvmsg(data->cscli,data->cs); } if ( !pthread_equal(data->lastthreadid, prg.tid_msg) ) { pthread_join(data->lastthreadid, NULL); } free( data ); return NULL; } #endif /////////////////////////////////////////////////////////////////////////////// // RECEIVE MESSAGES THREAD /////////////////////////////////////////////////////////////////////////////// struct pollfd pfd[4000]; int pfdcount = 0; void *recv_msg_thread(void *param) { prg.pid_msg = syscall(SYS_gettid); prg.tid_msg = pthread_self(); uint32 katicks = GetTickCount()+ 20000; // KeepAlive for servers while(1) { pthread_t lastthreadid = pthread_self(); // getmintime uint32 mintime = cs_dcw_check_time; #ifdef MGCAMD_SRV if (mintime>mg_dcw_check_time) mintime=mg_dcw_check_time; #endif #ifdef CCCAM_SRV if (mintime>cc_dcw_check_time) mintime=cc_dcw_check_time; #endif #ifdef FREECCCAM_SRV if (mintime>frcc_dcw_check_time) mintime=frcc_dcw_check_time; #endif #ifdef RADEGAST_SRV if (mintime>rdgd_dcw_check_time) mintime=rdgd_dcw_check_time; #endif if (mintime>ecm_check_time) mintime=ecm_check_time; uint ticks = GetTickCount(); uint ms; if (mintime>(ticks+3)) ms = mintime-ticks; else ms = 3; pfdcount = 0; // PIPE pfd[pfdcount].fd = srvsocks[0]; pfd[pfdcount++].events = POLLIN | POLLPRI; //Servers struct cs_server_data *srv = cfg.server; while (srv) { if ( !IS_DISABLED(srv->flags)&&(srv->handle>0) ) { srv->ipoll = pfdcount; pfd[pfdcount].fd = srv->handle; pfd[pfdcount++].events = POLLIN | POLLPRI; } else srv->ipoll = -1; srv = srv->next; } // Check KA for newcamd Servers if (katicks<ticks) { struct cs_server_data *srv = cfg.server; while (srv) { if ( !IS_DISABLED(srv->flags)&&(srv->handle>0)&&(srv->type==TYPE_NEWCAMD) ) cs_check_keepalive(srv); srv = srv->next; } katicks = ticks + 10000; } #ifdef CCCAM_SRV struct cccamserver_data *cccam = cfg.cccam.server; while (cccam) { if ( !IS_DISABLED(cccam->flags)&&(cccam->handle>0) ) { struct cc_client_data *cccli = cccam->client; while (cccli) { if ( !IS_DISABLED(cccli->flags)&&(cccli->handle>0) ) { cccli->ipoll = pfdcount; pfd[pfdcount].fd = cccli->handle; pfd[pfdcount++].events = POLLIN | POLLPRI; } else cccli->ipoll = -1; cccli = cccli->next; } } cccam = cccam->next; } #endif #ifdef FREECCCAM_SRV // srv-cccam if ( !IS_DISABLED(cfg.freecccam.server.flags)&&(cfg.freecccam.server.handle>0) ) { struct cc_client_data *fcccli = cfg.freecccam.server.client; while (fcccli) { if ( !IS_DISABLED(fcccli->flags)&&(fcccli->handle>0) ) { fcccli->ipoll = pfdcount; pfd[pfdcount].fd = fcccli->handle; pfd[pfdcount++].events = POLLIN | POLLPRI; } else fcccli->ipoll = -1; fcccli = fcccli->next; } } #endif #ifdef MGCAMD_SRV struct mgcamdserver_data *mgcamd = cfg.mgcamd.server; while (mgcamd) { if ( !IS_DISABLED(mgcamd->flags)&&(mgcamd->handle>0) ) { struct mg_client_data *cli = mgcamd->client; while (cli) { if ( !IS_DISABLED(cli->flags)&&(cli->handle>0) ) { cli->ipoll = pfdcount; pfd[pfdcount].fd = cli->handle; pfd[pfdcount++].events = POLLIN | POLLPRI; } else cli->ipoll = -1; cli = cli->next; } } mgcamd = mgcamd->next; } #endif struct cs_client_data *cscli; struct cardserver_data *cs = cfg.cardserver; while (cs) { if ( !IS_DISABLED(cs->newcamd.flags)&&(cs->newcamd.handle>0) ) { cscli = cs->newcamd.client; while (cscli) { if ( !IS_DISABLED(cscli->flags)&&(cscli->handle>0) ) { cscli->ipoll = pfdcount; pfd[pfdcount].fd = cscli->handle; pfd[pfdcount++].events = POLLIN | POLLPRI; } else cscli->ipoll = -1; cscli = cscli->next; } } cs = cs->next; } #ifdef RADEGAST_SRV cs = cfg.cardserver; while (cs) { if ( !IS_DISABLED(cs->flags)&&(cs->rdgd.handle>0) ) { pthread_mutex_lock(&prg.lockrdgdcli); struct rdgd_client_data *rdgdcli = cs->rdgd.client; while (rdgdcli) { if ( !IS_DISABLED(rdgdcli->flags)&&(rdgdcli->handle>0) ) { rdgdcli->ipoll = pfdcount; pfd[pfdcount].fd = rdgdcli->handle; pfd[pfdcount++].events = POLLIN | POLLPRI; } else rdgdcli->ipoll = -1; rdgdcli = rdgdcli->next; } pthread_mutex_unlock(&prg.lockrdgdcli); } cs = cs->next; } #endif int retval = poll(pfd, pfdcount, ms); if ( retval>0 ) { usleep(1000); /// SERVERS pthread_mutex_lock(&prg.locksrv); struct cs_server_data *srv = cfg.server; while (srv) { if ( !IS_DISABLED(srv->flags)&&(srv->handle>0)&&(srv->ipoll>=0)&&(srv->handle==pfd[srv->ipoll].fd) ) { if ( pfd[srv->ipoll].revents & (POLLHUP|POLLNVAL) ) { if (srv->type==TYPE_NEWCAMD) cs_disconnect_srv(srv); #ifdef CCCAM_CLI else if (srv->type==TYPE_CCCAM) cc_disconnect_srv(srv); #endif #ifdef RADEGAST_CLI else if (srv->type==TYPE_RADEGAST) rdgd_disconnect_srv(srv); #endif } else if ( pfd[srv->ipoll].revents & (POLLIN|POLLPRI) ) { #ifdef MSGTHREAD struct recvmsg_data *data = malloc( sizeof(struct recvmsg_data) ); data->type = TYPE_SERVER; data->cs = NULL; data->srv = srv; data->lastthreadid = lastthreadid; pthread_create(&lastthreadid , NULL, (threadfn)recv_msg, data);//recv_msg (data); #else if (srv->type==TYPE_NEWCAMD) cs_srv_recvmsg(srv); #ifdef CCCAM_CLI else if (srv->type==TYPE_CCCAM) cc_srv_recvmsg(srv); #endif #ifdef RADEGAST_CLI else if (srv->type==TYPE_RADEGAST) rdgd_srv_recvmsg(srv); #endif #endif } } srv = srv->next; } pthread_mutex_unlock(&prg.locksrv); /// CLIENTS // Newcamd Clients cs = cfg.cardserver; while (cs) { if ( !IS_DISABLED(cs->newcamd.flags)&&(cs->newcamd.handle>0) ) { pthread_mutex_lock(&prg.lockcli); cscli = cs->newcamd.client; while (cscli) { if ( !IS_DISABLED(cscli->flags)&&(cscli->handle>0) && (cscli->ipoll>=0) && (cscli->handle==pfd[cscli->ipoll].fd) ) { if ( pfd[cscli->ipoll].revents & (POLLHUP|POLLNVAL) ) cs_disconnect_cli(cscli); else if ( pfd[cscli->ipoll].revents & (POLLIN|POLLPRI) ) { #ifdef MSGTHREAD struct recvmsg_data *data = malloc( sizeof(struct recvmsg_data) ); data->type = TYPE_CLIENT_NEWCAMD; data->cs = cs; data->cscli = cscli; data->lastthreadid = lastthreadid; pthread_create(&lastthreadid , NULL, (threadfn)recv_msg, data);//recv_msg (data); #else cs_cli_recvmsg(cscli,cs); #endif } //else if ( (GetTickCount()-cscli->lastactivity) > 600000 ) cs_disconnect_cli(cscli); } cscli = cscli->next; } pthread_mutex_unlock(&prg.lockcli); } cs = cs->next; } #ifdef RADEGAST_SRV // Radegast Clients cs = cfg.cardserver; while (cs) { if ( !IS_DISABLED(cs->flags)&&(cs->rdgd.handle>0) ) { pthread_mutex_lock(&prg.lockrdgdcli); struct rdgd_client_data *rdgdcli = cs->rdgd.client; while (rdgdcli) { if ( !IS_DISABLED(rdgdcli->flags)&&(rdgdcli->handle>0)&&(rdgdcli->ipoll>=0)&&(rdgdcli->handle==pfd[rdgdcli->ipoll].fd) ) { if ( pfd[rdgdcli->ipoll].revents & (POLLHUP|POLLNVAL) ) rdgd_disconnect_cli(cs,rdgdcli); else if ( pfd[rdgdcli->ipoll].revents & (POLLIN|POLLPRI) ) rdgd_cli_recvmsg(rdgdcli,cs); } rdgdcli = rdgdcli->next; } pthread_mutex_unlock(&prg.lockrdgdcli); } cs = cs->next; } #endif #ifdef MGCAMD_SRV // CCcam Clients struct mgcamdserver_data *mgcamd = cfg.mgcamd.server; while (mgcamd) { if ( !IS_DISABLED(mgcamd->flags)&&(mgcamd->handle>0) ) { pthread_mutex_lock(&prg.lockclimg); struct mg_client_data *mgcli = mgcamd->client; while (mgcli) { if ( !IS_DISABLED(mgcli->flags)&&(mgcli->handle>0)&&(mgcli->ipoll>=0)&&(mgcli->handle==pfd[mgcli->ipoll].fd) ) { if ( pfd[mgcli->ipoll].revents & (POLLHUP|POLLNVAL) ) mg_disconnect_cli(mgcli); else if ( pfd[mgcli->ipoll].revents & (POLLIN|POLLPRI) ) { #ifdef MSGTHREAD struct recvmsg_data *data = malloc( sizeof(struct recvmsg_data) ); data->type = TYPE_CLIENT_MGCAMD; data->cs = NULL; data->mgcli = mgcli; data->lastthreadid = lastthreadid; pthread_create(&lastthreadid , NULL, (threadfn)recv_msg, data);//recv_msg (data); #else mg_cli_recvmsg(mgcli); #endif } ///else if ( (GetTickCount()-mgcli->lastactivity) > 600000 ) mg_disconnect_cli(mgcli); } mgcli = mgcli->next; } pthread_mutex_unlock(&prg.lockclimg); } mgcamd = mgcamd->next; } #endif #ifdef CCCAM_SRV // CCcam Clients struct cccamserver_data *cccam = cfg.cccam.server; while (cccam) { if ( !IS_DISABLED(cccam->flags)&&(cccam->handle>0) ) { pthread_mutex_lock(&prg.lockcccli); struct cc_client_data *cccli = cccam->client; while (cccli) { if ( !IS_DISABLED(cccli->flags)&&(cccli->handle>0)&&(cccli->ipoll>=0)&&(cccli->handle==pfd[cccli->ipoll].fd) ) { if ( pfd[cccli->ipoll].revents & (POLLHUP|POLLNVAL) ) cc_disconnect_cli(cccli); else if ( pfd[cccli->ipoll].revents & (POLLIN|POLLPRI) ) { #ifdef MSGTHREAD struct recvmsg_data *data = malloc( sizeof(struct recvmsg_data) ); data->type = TYPE_CLIENT_CCCAM; data->cs = NULL; data->cccli = cccli; data->lastthreadid = lastthreadid; pthread_create(&lastthreadid , NULL, (threadfn)recv_msg, data);//recv_msg (data); #else cc_cli_recvmsg(cccli); #endif } ///else if ( (GetTickCount()-cccli->lastactivity) > 600000 ) cc_disconnect_cli(cccli); } cccli = cccli->next; } pthread_mutex_unlock(&prg.lockcccli); } cccam = cccam->next; } #endif #ifdef FREECCCAM_SRV // FreeCCcam Clients if ( !IS_DISABLED(cfg.freecccam.server.flags)&&(cfg.freecccam.server.handle>0) ) { pthread_mutex_lock(&prg.lockfreecccli); struct cc_client_data *fcccli = cfg.freecccam.server.client; while (fcccli) { if ( (fcccli->handle>0)&&(fcccli->ipoll>=0)&&(fcccli->handle==pfd[fcccli->ipoll].fd) ) { if ( pfd[fcccli->ipoll].revents & (POLLHUP|POLLNVAL) ) cc_disconnect_cli(fcccli); else if ( pfd[fcccli->ipoll].revents & (POLLIN|POLLPRI) ) freecc_cli_recvmsg(fcccli); } fcccli = fcccli->next; } pthread_mutex_unlock(&prg.lockfreecccli); } #endif // if ( pfd[0].revents & (POLLIN|POLLPRI) ) recv_ecm_pipe(); } else if ( retval<0 ) { debugf(0," thread receive messages: poll error %d(errno=%d)\n", retval, errno); } if ( !pthread_equal(lastthreadid, prg.tid_msg) ) { // debugf(" Wait for thread...\n"); pthread_join(lastthreadid, NULL); } ///// // CHECK SEND ECM/DCW ///// ticks = GetTickCount()+3; /// SERVERS if (ecm_check_time<ticks) { pthread_mutex_lock(&prg.locksrv); ecm_check_time = check_sendecm(); pthread_mutex_unlock(&prg.locksrv); } /// CLIENTS // Newcamd Clients if (cs_dcw_check_time<ticks) { pthread_mutex_lock(&prg.lockcli); cs_dcw_check_time = cs_check_sendcw(); //debugf(" cs_dcw_check_time = %dms\n",cs_dcw_check_time-ticks); pthread_mutex_unlock(&prg.lockcli); } #ifdef RADEGAST_SRV // Radegast Clients if (rdgd_dcw_check_time<ticks) { pthread_mutex_lock(&prg.lockrdgdcli); rdgd_dcw_check_time = rdgd_check_sendcw(); pthread_mutex_unlock(&prg.lockrdgdcli); } #endif #ifdef MGCAMD_SRV if (mg_dcw_check_time<ticks) { if (cfg.mgcamd.server) { pthread_mutex_lock(&prg.lockclimg); mg_dcw_check_time = mg_check_sendcw(); pthread_mutex_unlock(&prg.lockclimg); } else mg_dcw_check_time = 0xffffffff; } #endif #ifdef CCCAM_SRV // CCcam Clients if (cc_dcw_check_time<ticks) { if (cfg.cccam.server) { pthread_mutex_lock(&prg.lockcccli); cc_dcw_check_time = cc_check_sendcw(); pthread_mutex_unlock(&prg.lockcccli); } else cc_dcw_check_time = 0xffffffff; } #endif #ifdef FREECCCAM_SRV // FreeCCcam Clients if (frcc_dcw_check_time<ticks) { if (cfg.freecccam.server.handle>0) { pthread_mutex_lock(&prg.lockfreecccli); frcc_dcw_check_time = freecc_check_sendcw(); pthread_mutex_unlock(&prg.lockfreecccli); } else frcc_dcw_check_time = 0xffffffff; } #endif } } int start_thread_recv_msg() { create_prio_thread(&prg.tid_msg, (threadfn)recv_msg_thread,NULL, 50); return 0; }