./ MultiCS.r82 / th-ecm.c
void clients_check_sendcw(ECM_DATA *ecm)
{
cs_check_sendcw(ecm);
#ifdef MGCAMD_SRV
mg_check_sendcw(ecm);
#endif
#ifdef CCCAM_SRV
cc_check_sendcw(ecm);
#endif
#ifdef FREECCCAM_SRV
freecc_check_sendcw(ecm);
#endif
#ifdef CS378X_SRV
cs378x_check_sendcw(ecm);
#endif
#ifdef CAMD35_SRV
camd35_check_sendcw(ecm);
#endif
}
#include "loadbalance.c"
#include "setdcw.c"
///////////////////////////////////////////////////////////////////////////////
// Check sending ecm to servers
///////////////////////////////////////////////////////////////////////////////
void wakeup_sendecm() // not needed in mono-thread
{
pipe_wakeup( prg.pipe.ecm[1] );
}
void ecm_faileddcw( ECM_DATA *ecm )
{
ecm->dcwstatus = STAT_DCW_FAILED;
ecm->checktime = 0;
ecm->waitserver = 0;
sid_newecm(ecm);
clients_check_sendcw(ecm); // send decode failed to clients
#ifdef TESTCHANNEL
int testchannel = ( (ecm->caid==cfg.testchn.caid) && (ecm->provid==cfg.testchn.provid) && (ecm->sid==cfg.testchn.sid) );
if (testchannel) {
fdebugf(" <Decode_Failed> ch %04x:%06x:%04x/%02x:%08x\n", ecm->caid, ecm->provid, ecm->sid, ecm->ecm[0], ecm->hash);
}
#endif
}
void check_ecm(ECM_DATA *ecm, uint32_t ticks)
{
ecm->checktime = 0; // invalid
ecm->waitserver = 0;
// CACHE(fallowcache = 1)
if (ecm->dcwstatus==STAT_DCW_WAITCACHE) {
struct cardserver_data *cs = ecm->cs;
if (!cs) {
ecm->statusmsg = "Invalid profile id";
ecm_faileddcw( ecm );
return;
}
if (cs->option.fallowcache) {
if (!ecm->waitcache) { // Not done
if (cs->option.fallowcache) {
pipe_cache_find(ecm, cs);
ecm->waitcache = 1;
ecm->checktime = ecm->recvtime + cs->option.cachetimeout; // wait for cache
}
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");
ecm->checktime = ecm->recvtime+cs->option.cachetimeout;
}
}
}
else ecm->dcwstatus = STAT_DCW_WAIT;
}
// SEND ECM
if ( (ecm->dcwstatus==STAT_DCW_WAIT) ) {
// Check Profile
struct cardserver_data *cs = ecm->cs;
if (!cs) {
ecm->statusmsg = "Invalid profile id";
ecm_faileddcw( ecm );
return;
}
//check for decode failed
// Check for Max used Servers
if ( (cs->option.server.max>0) && (ecm->server_totalsent>=cs->option.server.max) ) {
if (!ecm->server_totalwait) {
ecm->statusmsg = "Decode failed, max servers is reached and no more servers to wait";
ecm_faileddcw( ecm );
// 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->recvtime + cs->option.dcw.timeout*ecm->period;
}
// Check for ECM TimeOut
else if ( (ticks-ecm->recvtime) >= cs->option.dcw.timeout*ecm->period ) {
ecm->statusmsg = "Decode failed, dcw timeout";
ecm_faileddcw( ecm );
// 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*ecm->period) ) { // ~ cfg.cardserver.option.dcw.timeout*2/3 is the cardserver timeout
// Check for cache request
if ( (ecm->cachestatus==ECM_CACHE_NONE) && cs->option.fallowcache && cs->option.cachesendreq ) {
pipe_cache_request(ecm,cs);
ecm->cachestatus = ECM_CACHE_REQ;
}
// check for decode failed with no remaining server to wait, send to new cardserver
if ( !ecm->server_totalwait
|| (cs->option.server.first>ecm->server_totalsent)
|| ((ticks-ecm->lastsendtime)>=cs->option.server.interval)
) {
//debugf(" check_sendecm[%s] ch %04x:%06x:%04x\n", cs->name,ecm->caid,ecm->provid,ecm->sid);
struct server_data *newsrv = NULL;
if ( srvtab_arrange(cs, ecm, ecm->server_totalsent > 0 )==-1 ) { // No more servers to decode
//debugf(0," sendecm: no servers found to decode\n");
ecm->checktime = ecm->recvtime + cs->option.dcw.timeout*ecm->period;
return;
}
else if (psrvlist[0] && psrvlist[0]->srv) {
// SEND ECM
newsrv = psrvlist[0]->srv;
newsrv->busycard = psrvlist[0]->card; // dont save pointers!!!
newsrv->busycardid = psrvlist[0]->shareid;
//debugf(0," 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 = ticks;
debugf(getdbgflagpro(DBG_SERVER,0,newsrv->id,cs->id)," -> ecm to Newcamd server%d (%s:%d) ch %04x:%06x:%04x:%08x\n",(1+ecm->server_totalsent),newsrv->host->name,newsrv->port,ecm->caid,ecm->provid,ecm->sid,ecm->hash);
newsrv->lastecmtime = ticks;
newsrv->ecmnb++;
newsrv->busy=1;
newsrv->ecm.request = ecm;
newsrv->ecm.hash = ecm->hash;
newsrv->retry=0;
ecm_addsrv(ecm, newsrv->id);
ecm_addsrvip(ecm, newsrv->host->ip);
}
}
#ifdef CCCAM_CLI
else if (newsrv->type==TYPE_CCCAM) {
if (cc_sendecm_srv(newsrv, ecm)>0) {
ecm->lastsendtime = ticks;
debugf(getdbgflagpro(DBG_SERVER,0,newsrv->id,cs->id)," -> ecm to CCcam server%d (%s:%d) ch %04x:%06x:%04x:%08x\n",(1+ecm->server_totalsent),newsrv->host->name,newsrv->port,ecm->caid,ecm->provid,ecm->sid,ecm->hash);
newsrv->lastecmtime = ticks;
newsrv->ecmnb++;
struct cs_card_data *card = cc_getcardbyid( newsrv, newsrv->busycardid );
if (card) card->ecmnb++;
newsrv->busy=1;
newsrv->ecm.request = ecm;
newsrv->ecm.hash = ecm->hash;
newsrv->retry=0;
ecm_addsrv(ecm, newsrv->id);
ecm_addsrvip(ecm, newsrv->host->ip);
}
}
#endif
#ifdef RADEGAST_CLI
else if (newsrv->type==TYPE_RADEGAST) {
if (rdgd_sendecm_srv(newsrv, ecm)>0) {
ecm->lastsendtime = ticks;
debugf(getdbgflagpro(DBG_SERVER,0,newsrv->id,cs->id)," -> ecm to Radegast server%d (%s:%d) ch %04x:%06x:%04x:%08x\n",(1+ecm->server_totalsent),newsrv->host->name,newsrv->port,ecm->caid,ecm->provid,ecm->sid,ecm->hash);
newsrv->lastecmtime = ticks;
newsrv->ecmnb++;
newsrv->busy=1;
newsrv->ecm.request = ecm;
newsrv->ecm.hash = ecm->hash;
newsrv->retry=0;
ecm_addsrv(ecm, newsrv->id);
ecm_addsrvip(ecm, newsrv->host->ip);
}
}
#endif
#ifdef CAMD35_CLI
else if (newsrv->type==TYPE_CAMD35) {
if (camd35_sendecm_srv(newsrv, ecm)>0) {
ecm->lastsendtime = ticks;
debugf(getdbgflagpro(DBG_SERVER,0,newsrv->id,cs->id)," -> ecm to camd35 server%d (%s:%d) ch %04x:%06x:%04x:%08x\n",(1+ecm->server_totalsent),newsrv->host->name,newsrv->port,ecm->caid,ecm->provid,ecm->sid,ecm->hash);
newsrv->lastecmtime = ticks;
newsrv->ecmnb++;
newsrv->busy=1;
newsrv->ecm.request = ecm;
newsrv->ecm.hash = ecm->hash;
newsrv->retry=0;
ecm_addsrv(ecm, newsrv->id);
ecm_addsrvip(ecm, newsrv->host->ip);
}
}
#endif
#ifdef CS378X_CLI
else if (newsrv->type==TYPE_CS378X) {
if (cs378x_sendecm_srv(newsrv, ecm)>0) {
ecm->lastsendtime = ticks;
debugf(getdbgflagpro(DBG_SERVER,0,newsrv->id,cs->id)," -> ecm to cs378x server%d (%s:%d) ch %04x:%06x:%04x:%08x\n",(1+ecm->server_totalsent),newsrv->host->name,newsrv->port,ecm->caid,ecm->provid,ecm->sid,ecm->hash);
newsrv->lastecmtime = ticks;
newsrv->ecmnb++;
newsrv->busy=1;
newsrv->ecm.request = ecm;
newsrv->ecm.hash = ecm->hash;
newsrv->retry=0;
ecm_addsrv(ecm, newsrv->id);
ecm_addsrvip(ecm, newsrv->host->ip);
}
}
#endif
ecm->statusmsg = "Waiting for servers...";
if ( cs->option.server.first > (ecm->server_totalsent+1) ) ecm->checktime = ticks + 10;
else {
ecm->checktime = ticks + cs->option.server.interval;
if ( (ecm->checktime-ecm->recvtime) > (cs->option.server.timeout*ecm->period) ) ecm->checktime = ecm->recvtime + cs->option.dcw.timeout*ecm->period;
}
}
else {
ecm->statusmsg = "Wait for available servers";
//debugf( getdbgflag(DBG_NEWCAMD,cs->id,0), " check_sendecm[%s] ch %04x:%06x:%04x, Wait for available server...\n", cs->name,ecm->caid,ecm->provid,ecm->sid);
// PROBLEM HERE ??????
ecm->waitserver = 1; // XXX
ecm->checktime = ecm->recvtime + cs->option.dcw.timeout*ecm->period; // till the end if there is no server
#ifdef BUSY_SERVER
if (!ecm->server_totalwait && !ecm->server_totalsent) {
ecm->statusmsg = "Decode failed, no free server";
ecm_faileddcw( ecm );
cs->ecmbusysrv++;
}
#endif
return;
}
}
else {
ecm->checktime = ecm->lastsendtime + cs->option.server.interval;
if ( (ecm->checktime-ecm->recvtime) > (cs->option.server.timeout*ecm->period) ) ecm->checktime = ecm->recvtime + cs->option.dcw.timeout*ecm->period;
}
}
else if (!ecm->server_totalwait) {
ecm->statusmsg = "Decode failed, no server open this channel";
ecm_faileddcw( ecm );
// 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 if ( cs->option.fallowcache && cs->option.cacheresendreq && (ecm->cachestatus==ECM_CACHE_REQ) ) {
pipe_cache_resendreq(ecm, cs);
ecm->cachestatus = ECM_CACHE_REQ2;
ecm->checktime = ecm->recvtime + cs->option.dcw.timeout*ecm->period;
}
else ecm->checktime = ecm->recvtime + cs->option.dcw.timeout*ecm->period;
}
}
inline void check_sendecm(int newserver)
{
uint32_t ticks = GetTickCount();
struct ecm_request *req = ecmdata;
while (req) {
if ( (req->recvtime+TIME_ECMALIVE) < ticks ) break;
if (req->checktime) { // (checktime==0) --> do nothing
if ( (req->checktime < ticks) || (req->waitserver && newserver) ) {
check_ecm(req, ticks);
ticks = GetTickCount();
}
}
req = req->next;
if (req==ecmdata) break;
}
}
/// recalculate ecmcheck wakeup time
uint32_t getecmwakeuptime()
{
uint32_t ticks = GetTickCount();
uint32_t waketime = ticks+10000;
struct ecm_request *req = ecmdata;
while (req) {
if ( (req->recvtime+TIME_ECMALIVE) < ticks ) break;
if ( req->checktime )
if ( waketime > req->checktime ) waketime = req->checktime;
req = req->next;
if (req==ecmdata) break;
}
return waketime;
}
///////////////////////////////////////////////////////////////////////////////
// CACHE PIPE RECV MESSAGES
///////////////////////////////////////////////////////////////////////////////
int newserver = 0;
void recv_ecm_pipe()
{
uint8_t buf[1024];
struct cache_data req;
uint8_t cw[16];
int peerid;
ECM_DATA *ecm;
struct pollfd pfd;
do {
int len = pipe_recv( prg.pipe.ecm[0], buf);
if (len>0) {
switch(buf[0]) {
case PIPE_WAKEUP:
break;
case PIPE_LOCK:
pthread_mutex_lock(&prg.lockmain);
pthread_mutex_unlock(&prg.lockmain);
break;
case PIPE_CACHE_FIND_FAILED:
get_cache2ecm(buf, &req, NULL);
pthread_mutex_lock(&prg.lockecm);
ecm = req.ecm; //search_ecmdata_byhash( req.caid, req.sid, req.hash );
if (ecm) {
if ( (ecm->caid==req.caid)&&(ecm->hash==req.hash)&&(ecm->sid==req.sid)&&(ecm->dcwstatus==STAT_DCW_WAITCACHE) ) {
struct cardserver_data *cs = ecm->cs;
if ( cs && (!cs->option.cachestatic) )
ecm->dcwstatus = STAT_DCW_WAIT;
ecm->checktime = ecm->recvtime;
}
}
pthread_mutex_unlock(&prg.lockecm);
break;
case PIPE_CACHE_FIND_SUCCESS: // SET DCW
peerid = get_cache2ecm(buf, &req, cw);
pthread_mutex_lock(&prg.lockecm);
ecm = req.ecm; //search_ecmdata_byhash( req.caid, req.sid, req.hash );
if (ecm) {
if ( (ecm->caid==req.caid)&&(ecm->hash==req.hash)&&(ecm->sid==req.sid) ) {
struct cardserver_data *cs = ecm->cs;
if (cs) if (cs->option.fallowcache) ecm_setdcw( ecm, cw, DCW_SOURCE_CACHE, peerid );
}
}
pthread_mutex_unlock(&prg.lockecm);
break;
case PIPE_SRV_CONNECTED:
newserver = 1;
#ifdef EPOLL_ECM
struct server_data *srv;
memcpy( &srv, buf+1, sizeof(void*) );
// Add to events
struct epoll_event ev; // epoll event
ev.events = EPOLLIN;
ev.data.fd = srv->handle;
ev.data.ptr = srv;
if ( epoll_ctl(prg.epoll.ecm, EPOLL_CTL_ADD, srv->handle, &ev) == -1 ) debugf(DBG_ERROR,"Err! EPOLL_CTL_ADD %s (%d)\n", srv->user, srv->handle);
//else debugf(0,"EPOLL_CTL_ADD %s (%d)\n", cli->user, cli->handle);
#endif
break;
case PIPE_SRV_AVAILABLE:
newserver = 1;
break;
}
}
pfd.fd = prg.pipe.ecm[0];
pfd.events = POLLIN | POLLPRI;
} while ( poll(&pfd, 1, 0)>0 );
}
///////////////////////////////////////////////////////////////////////////////
// RECEIVE MESSAGES THREAD
///////////////////////////////////////////////////////////////////////////////
inline void srv_recvmsg( struct server_data *srv )
{
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
#ifdef CAMD35_CLI
else if (srv->type==TYPE_CAMD35) camd35_srv_recvmsg(srv);
#endif
#ifdef CS378X_CLI
else if (srv->type==TYPE_CS378X) cs378x_srv_recvmsg(srv);
#endif
}
#ifdef EPOLL_ECM
void *recv_msg_thread(void *param)
{
prg.pid_msg = syscall(SYS_gettid);
prg.tid_msg = pthread_self();
prctl(PR_SET_NAME,"ECM Thread",0,0,0);
struct epoll_event evlist[MAX_EPOLL_EVENTS]; // epoll recv events
prg.epoll.ecm = epoll_create( MAX_EPOLL_EVENTS );
// Add PIPE
struct epoll_event ev; // epoll event
ev.events = EPOLLIN | EPOLLPRI | EPOLLRDHUP;
ev.data.ptr = NULL;
if ( epoll_ctl( prg.epoll.ecm, EPOLL_CTL_ADD, prg.pipe.ecm[0], &ev) == -1 ) printf("epoll_ctl");
while (!prg.restart) {
newserver = 0;
// getmintime
uint32_t mintime = ecm_check_time;
uint32_t ticks = GetTickCount();
uint32_t ms;
if (mintime>(ticks+3)) ms = mintime-ticks; else ms = 3;
int ready = epoll_wait( prg.epoll.ecm, evlist, MAX_EPOLL_EVENTS, ms);
if (ready == -1) {
if ( (errno==EINTR)||(errno==EAGAIN) ) {
usleep(1000);
continue;
}
else {
usleep(99000);
debugf(DBG_ERROR,"Err! epoll_wait (%d)", errno);
}
}
int i;
for (i=0; i < ready; i++) {
if ( evlist[i].events & (EPOLLIN|EPOLLPRI) ) {
if (evlist[i].data.ptr == NULL) recv_ecm_pipe();
else {
pthread_mutex_lock(&prg.locksrv);
srv_recvmsg(evlist[i].data.ptr);
pthread_mutex_unlock(&prg.locksrv);
}
}
else if ( evlist[i].events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR) ) { // EPOLLRDHUP
if (evlist[i].data.ptr == NULL) debugf(DBG_ERROR,"Err! epoll_wait() pipe\n"); // error !!!
else disconnect_srv(evlist[i].data.ptr);
}
}
pthread_mutex_lock(&prg.locksrv);
pthread_mutex_lock(&prg.lockecm);
check_sendecm( newserver );
ecm_check_time = getecmwakeuptime();
pthread_mutex_unlock(&prg.lockecm);
pthread_mutex_unlock(&prg.locksrv);
//usleep(cfg.delay.thread*2);
}
return NULL;
}
#else
void *recv_msg_thread(void *param)
{
struct pollfd pfd[MAX_PFD];
int pfdcount;
prg.pid_msg = syscall(SYS_gettid);
prg.tid_msg = pthread_self();
prctl(PR_SET_NAME,"ECM Thread",0,0,0);
while (!prg.restart) {
// getmintime
uint32_t mintime = ecm_check_time;
newserver = 0;
uint32_t ticks = GetTickCount();
uint32_t ms;
if (mintime>(ticks+3)) ms = mintime-ticks; else ms = 3;
pfdcount = 0;
// Cache Data// Clients/Servers WakeUP
pfd[pfdcount].fd = prg.pipe.ecm[0];
pfd[pfdcount++].events = POLLIN | POLLPRI;
//Servers
struct server_data *srv = cfg.server;
while (srv && (pfdcount<SERVER_MAX_PFD)) {
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;
}
int retval = poll(pfd, pfdcount, ms);
if ( retval>0 ) {
/// SERVERS
pthread_mutex_lock(&prg.locksrv);
struct 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) ) disconnect_srv(srv);
else if ( pfd[srv->ipoll].revents & (POLLIN|POLLPRI) ) srv_recvmsg(srv);
}
srv = srv->next;
}
pthread_mutex_unlock(&prg.locksrv);
//
if ( pfd[0].revents & (POLLIN|POLLPRI) ) recv_ecm_pipe();
}
else if ( (retval<0) && (errno!=EINTR) ) {
debugf(0," thread receive messages: poll error %d(errno=%d)\n", retval, errno);
usleep(91000);
}
pthread_mutex_lock(&prg.locksrv);
pthread_mutex_lock(&prg.lockecm);
check_sendecm( newserver );
ecm_check_time = getecmwakeuptime();
pthread_mutex_unlock(&prg.lockecm);
pthread_mutex_unlock(&prg.locksrv);
usleep(cfg.delay.thread*2);
}
return NULL;
}
#endif
// Check for keepalive with servers/clients
void *thread_keepalive(void *param)
{
while (1) {
sleep(5);
uint32_t ticks = GetTickCount();
// Check Servers
struct server_data *srv = cfg.server;
while (srv) {
if ( !IS_DISABLED(srv->flags)&&(srv->connection.status>0) ) {
if (srv->type==TYPE_NEWCAMD) cs_check_keepalive(srv);
else if (srv->type==TYPE_CCCAM) {
if ( !srv->keepalive.status && ((srv->keepalive.time+75000)<ticks) ) {
srv->keepalive.status = 1; // Sent and waiting for reply
srv->keepalive.time = ticks;
if ( !cc_msg_send( srv->handle, &srv->sendblock, CC_MSG_KEEPALIVE, 0, NULL) ) disconnect_srv( srv );
}
}
#ifdef CAMD35_CLI
else if (srv->type==TYPE_CAMD35) {
if ( !srv->keepalive.status && ((srv->keepalive.time+30000)<ticks) ) {
camd35_send_keepalive(srv);
srv->keepalive.status = 1; // Sent and waiting for reply
srv->keepalive.time = ticks;
}
else if ( (srv->keepalive.status==1) && ((srv->keepalive.time+10000)<ticks) ) {
camd35_send_keepalive(srv);
srv->keepalive.status = 2;
srv->keepalive.time = ticks;
}
else if ( (srv->keepalive.status>1) && ((srv->keepalive.time+10000)<ticks) ) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," ??? no keepalive response from camd35 server (%s:%d)\n",srv->host->name,srv->port);
disconnect_srv( srv );
}
}
#endif
}
srv = srv->next;
}
// Check Cacheex Servers
srv = cfg.cacheexserver;
while (srv) {
if ( !IS_DISABLED(srv->flags)&&(srv->connection.status>0) ) {
if (srv->type==TYPE_CCCAM) {
if ( !srv->keepalive.status && ((srv->keepalive.time+75000)<ticks) ) {
srv->keepalive.status = 1; // Sent and waiting for reply
srv->keepalive.time = ticks;
if ( !cc_msg_send( srv->handle, &srv->sendblock, CC_MSG_KEEPALIVE, 0, NULL) ) disconnect_srv( srv );
}
}
#ifdef CAMD35_CLI
else if (srv->type==TYPE_CAMD35) {
if ( !srv->keepalive.status && ((srv->keepalive.time+30000)<ticks) ) {
camd35_send_keepalive(srv);
srv->keepalive.status = 1; // Sent and waiting for reply
srv->keepalive.time = ticks;
}
else if ( (srv->keepalive.status==1) && ((srv->keepalive.time+10000)<ticks) ) {
camd35_send_keepalive(srv);
srv->keepalive.status = 2;
srv->keepalive.time = ticks;
}
else if ( (srv->keepalive.status>1) && ((srv->keepalive.time+10000)<ticks) ) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," ??? no keepalive response from camd35 server (%s:%d)\n",srv->host->name,srv->port);
disconnect_srv( srv );
}
}
#endif
}
srv = srv->next;
}
#ifdef CAMD35_SRV
sleep(1);
// Check camd35 Clients
ticks = GetTickCount();
struct camd35_server_data *camd35 = cfg.camd35.server;
while (camd35) {
struct camd35_client_data *cli = camd35->client;
while (cli) {
if (cli->connection.status>0) {
if ( (cli->lastactivity+300000) < ticks) {
camd35_disconnect_cli(cli);
}
}
cli = cli->next;
}
camd35 = camd35->next;
}
#endif
}
}
int start_thread_recv_msg()
{
create_thread(&prg.tid_msg, (threadfn)recv_msg_thread,NULL);
create_thread(&prg.tid_msg, (threadfn)thread_keepalive,NULL);
#ifdef THREAD_DCW
create_thread(&prg.tid_msg, (threadfn)setdcw_thread,NULL);
#endif
return 0;
}