./ MultiCS.r69 / cli-newcamd.c
static char string_mgcamd[] = "Mgcamd";
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void *cs_disconnect_srv(struct cs_server_data *srv)
{
if (srv->handle>0) {
static char msg[]= "Disconnected";
srv->statmsg = msg;
// Disconnect server
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server (%s:%d) disconnected\n", srv->host->name, srv->port);
close(srv->handle);
srv->handle = INVALID_SOCKET;
if (srv->busy) ecm_setsrvflag(srv->busyecmid, srv->id, ECM_SRV_EXCLUDE);
uint ticks = GetTickCount();
srv->uptime += ticks-srv->connected;
srv->connected = ticks; // Last Seen
srv->keepalivetime = 0;
srv->keepalivesent = 0;
srv->host->checkiptime = 0; // maybe ip changed
// Remove Cards
pthread_mutex_lock( &srv->lock );
free_cardlist(srv->card);
srv->card = NULL;
pthread_mutex_unlock( &srv->lock );
}
return NULL;
}
int cs_connect_srv(struct cs_server_data *srv, int fd)
{
char passwdcrypt[120];
unsigned char keymod[14];
int i,index,len;
unsigned char buf[CWS_NETMSGSIZE];
unsigned char sessionkey[16];
// INIT
srv->progname = NULL;
memset( srv->version, 0, sizeof(srv->version) );
memset( srv->build, 0, 32);
//
if( recv_nonb(fd, keymod, 14,5000) != 14 ) {
static char msg[]= "Server does not return init sequence";
srv->statmsg = msg;
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server does not return init sequence\n");
return -1;
}
int ismultics = 0;
//debugdump(keymod,14,"Recv DES Key: ");
des_login_key_get(keymod, srv->key, 14, sessionkey);
//debugdump(sessionkey,16,"Login Key: ");
// 3. Send login info
struct cs_custom_data clicd; // Custom data
memset( &clicd, 0, sizeof(clicd));
//clicd.sid = 0x4343; // CCcam
clicd.sid = cfg.newcamdclientid; // Mgcamd
index = 3;
buf[0] = MSG_CLIENT_2_SERVER_LOGIN;
buf[1] = 0;
strcpy( (char*)&buf[3], srv->user);
index += strlen(srv->user)+1;
__md5_crypt(srv->pass, "$1$abcdefgh$",passwdcrypt);
//debugf(getdbgflag(DBG_SERVER,0,srv->id)," passwdcrypt = %s\n",passwdcrypt);
strcpy((char*)buf+index, (char*)passwdcrypt);
index+=strlen(passwdcrypt)+1;
if (ismultics) clicd.provid=0x0057484F;
cs_message_send(fd, &clicd, buf, index, sessionkey);
srv->ping = GetTickCount();
// 3.1 Get login answer
len = cs_message_receive(fd, &clicd, buf, sessionkey,5000);
if (len<3) {
static char msg[]= "Login error";
srv->statmsg = msg;
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: login answer length error (%d) from server (%s:%d)\n",len, srv->host->name,srv->port);
return INVALID_SOCKET;
}
if ( buf[0] == MSG_CLIENT_2_SERVER_LOGIN_NAK ) {
static char msg[]= "Invalid user/pass";
srv->statmsg = msg;
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: login failed to server (%s:%d)\n", srv->host->name,srv->port);
return INVALID_SOCKET;
}
else if( buf[0] != MSG_CLIENT_2_SERVER_LOGIN_ACK ) {
static char msg[]= "Login error";
srv->statmsg = msg;
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: Error, expected MSG_CLIENT_2_SERVER_LOGIN_ACK\n");
return INVALID_SOCKET;
}
else debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: connect to server (%s:%d) user '%s'\n", srv->host->name, srv->port, srv->user);
// Ping
srv->ping = GetTickCount()-srv->ping;
// mgcamd protocol version?
if ( (clicd.sid==0x6E73)&&( (clicd.provid>>24)==0x14) ) srv->progname = string_mgcamd;
//
static char msg[]= "Connected";
srv->statmsg = msg;
des_login_key_get( srv->key, (uint8*)passwdcrypt, strlen(passwdcrypt), sessionkey);
//debugdump(sessionkey,16,"sessionkey: ");
memcpy( srv->sessionkey, sessionkey,16);
// 4. Send MSG_CARD_DATA_REQ
memset( &clicd, 0, sizeof(clicd) );
clicd.msgid = 1;
buf[0]=MSG_CARD_DATA_REQ;
buf[1]=0; buf[2]=0;
cs_message_send(fd, &clicd, buf, 3, srv->sessionkey);
len = cs_message_receive( fd, NULL, buf, srv->sessionkey,3000);
if (len==0) {
static char msg[]= "Disconnected";
srv->statmsg = msg;
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: client disconnected\n");
return INVALID_SOCKET;
}
else if (len<0) {
static char msg[]= "failed to receive card data";
srv->statmsg = msg;
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: Error Recv MSG_CARD_DATA (%d)\n",len);
return INVALID_SOCKET;
}
if (buf[0]!=MSG_CARD_DATA) {
static char msg[]= "failed to receive card data";
srv->statmsg = msg;
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: expected MSG_CARD_DATA\n");
return INVALID_SOCKET;
}
else if (len<15) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: MSG_CARD_DATA, length error (%d)\n",len);
//return INVALID_SOCKET;
}
else {
// 5. Parse CAID and PROVID(s)
if ( (buf[14]<CARD_MAXPROV)&&(len>=(6+11*buf[14]))&&(buf[4]||buf[5]) ) { // CAID != 0x0000
struct cs_card_data *pcard = malloc( sizeof(struct cs_card_data) );
if (pcard) {
memset(pcard, 0, sizeof(struct cs_card_data) );
pcard->caid = ((buf[4]<<8) | buf[5]);
pcard->nbprov = buf[14];
pcard->uphops = 1;
//pcard->sids = NULL;
if (pcard->nbprov>CARD_MAXPROV) pcard->nbprov = CARD_MAXPROV;
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: caid %04x providers %d\n", pcard->caid,buf[14]);
for( i=0; i<pcard->nbprov; i++ ) {
pcard->prov[i] = (buf[15+11*i]<<16)|(buf[16+11*i]<<8)|buf[17+11*i];
//debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: provider %02d = %06X\n", i+1, pcard->prov[i]);
}
pcard->next = srv->card;
srv->card = pcard;
}
else printf(" ALLOC ERROR \n");
} else debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: caid 0\n");
}
#ifdef CLI_CSCACHE
/* // Send keepalive Caching Check???
clicd.msgid = 0;
clicd.sid = ('C'<<8) | 'H';
clicd.caid = 0;
clicd.provid = 0;
buf[0] = MSG_KEEPALIVE;
buf[1] = 0;
buf[2] = 0;
cs_message_send(fd, &clicd, buf, 3, srv->sessionkey);
*/
srv->keepalivesent = GetTickCount();
srv->cscached = 0;
#endif
srv->connected = GetTickCount();
srv->keepalivetime = GetTickCount();
srv->busy = 0;
srv->lastecmoktime = 0;
srv->lastecmtime = 0;
srv->lastdcwtime = 0;
srv->chkrecvtime = 0;
srv->handle = fd;
pipe_wakeup( srvsocks[1] );
return 0;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int cs_sendecm_srv(struct cardserver_data *cs, struct cs_server_data *srv, ECM_DATA *ecm)
{
unsigned char buf[CWS_NETMSGSIZE];
struct cs_custom_data srvcd; // Custom data
if (!cs->option.cssendsid) srvcd.sid = 0; else srvcd.sid = ecm->sid;
srvcd.caid = ecm->caid;
srvcd.provid = ecm->provid;
srvcd.msgid = ecm->srvmsgid;
memcpy( &buf[0], &ecm->ecm[0], ecm->ecmlen );
return cs_message_send( srv->handle, &srvcd, buf, ecm->ecmlen, srv->sessionkey);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void cs_srv_recvmsg(struct cs_server_data *srv)
{
struct cs_custom_data srvcd; // Custom data
int len;
ECM_DATA *ecm;
unsigned char buf[CWS_NETMSGSIZE];
if ( (srv->handle<=0)||(srv->type!=TYPE_NEWCAMD) ) return;
len = cs_msg_chkrecv(srv->handle);
if (len==0) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server (%s:%d) read failed %d\n", srv->host->name, srv->port, len);
cs_disconnect_srv(srv);
}
else if (len==-1) {
if (!srv->chkrecvtime) srv->chkrecvtime = GetTickCount();
else if ( (srv->chkrecvtime+300)<GetTickCount() ) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server (%s:%d) wrong data\n", srv->host->name, srv->port);
cs_disconnect_srv(srv);
}
}
else if (len>0) {
srv->chkrecvtime = 0;
len = cs_message_receive(srv->handle, &srvcd, buf, srv->sessionkey,3);
if (len==0) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server (%s:%d) read failed %d\n", srv->host->name, srv->port, len);
cs_disconnect_srv(srv);
}
else if (len<0) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server (%s:%d) read failed %d(%d)\n", srv->host->name, srv->port, len, errno);
cs_disconnect_srv(srv);
}
else if (len>0) {
switch ( buf[0] ) {
case 0x80:
case 0x81:
srv->lastdcwtime = GetTickCount();
if (!srv->busy) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from server (%s:%d), unknown ecm request\n",srv->host->name,srv->port);
break;
}
srv->busy = 0;
if (srvcd.msgid!=srv->busyecmid) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from server (%s:%d), wrong message-id!!!\n",srv->host->name,srv->port);
break;
}
pthread_mutex_lock(&prg.lockecm); //###
ecm = getecmbyid(srv->busyecmid);
if (!ecm) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from server (%s:%d), ecm not found!!!\n",srv->host->name,srv->port);
pthread_mutex_unlock(&prg.lockecm); //###
break;
}
// check for ECM???
if (ecm->hash!=srv->busyecmhash) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from server (%s:%d), ecm deleted!!!\n",srv->host->name,srv->port);
pthread_mutex_unlock(&prg.lockecm); //###
break;
}
if (buf[2]==0x10) {
// Check for DCW
if (!acceptDCW(&buf[3])) {
srv->ecmerrdcw ++;
pthread_mutex_unlock(&prg.lockecm); //###
break;
}
srv->ecmok++;
srv->lastecmoktime = GetTickCount()-srv->lastecmtime;
srv->ecmoktime += srv->lastecmoktime;
ecm_setsrvflagdcw( ecm->srvmsgid, srv->id, ECM_SRV_REPLY_GOOD,&buf[3] );
debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->csid)," <= cw from server (%s:%d) ch %04x:%06x:%04x (%dms)\n", srv->host->name,srv->port, ecm->caid,ecm->provid,ecm->sid, GetTickCount()-srv->lastecmtime);
if (ecm->dcwstatus!=STAT_DCW_SUCCESS) {
static char msg[] = "Good dcw from Newcamd server";
ecm->statusmsg = msg;
// Store ECM Answer
ecm_setdcw( getcsbyid(ecm->csid), ecm, &buf[3], DCW_SOURCE_SERVER, srv->id );
}
else { //TODO: check same dcw between cards
srv->ecmerrdcw ++;
if ( memcmp(&ecm->cw, &buf[3],16) ) debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->csid)," !!! different dcw from server (%s:%d)\n",srv->host->name,srv->port);
}
#ifdef SID_FILTER
// ADD IN SID LIST
struct cardserver_data *cs=getcsbyid(ecm->csid);
if (cs) {
cardsids_update( srv->busycard, ecm->provid, ecm->sid, 1);
srv_cstatadd( srv, cs->id, 1 , srv->lastecmoktime);
}
#endif
}
else {
struct cardserver_data *cs=getcsbyid(ecm->csid);
if ( cs && (ecm->dcwstatus!=STAT_DCW_SUCCESS) && (srv->retry<cs->option.retry.newcamd) ) {
if ( (GetTickCount()-ecm->recvtime)<cs->option.server.timeout )
if (cs_sendecm_srv(cs, srv, ecm)>0) {
srv->retry++;
ecm->lastsendtime = GetTickCount();
debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->csid)," (RE) -> ecm to server (%s:%d) ch %04x:%06x:%04x\n",srv->host->name,srv->port,ecm->caid,ecm->provid,ecm->sid);
srv->lastecmtime = GetTickCount();
srv->ecmnb++;
srv->busy=1;
srv->busyecmid = ecm->srvmsgid;
pthread_mutex_unlock(&prg.lockecm); //###
break;
}
}
ecm_setsrvflag(ecm->srvmsgid, srv->id, ECM_SRV_REPLY_FAIL);
debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->csid)," <| decode failed from server (%s:%d) ch %04x:%06x:%04x (%dms)\n", srv->host->name,srv->port, ecm->caid,ecm->provid,ecm->sid, GetTickCount()-srv->lastecmtime);
#ifdef SID_FILTER
// ADD IN SID LIST
if (cs) {
cardsids_update( srv->busycard, ecm->provid, ecm->sid, -1);
srv_cstatadd( srv, cs->id, 0 , 0);
}
#endif
ecm_check_time = 0;
}
pthread_mutex_unlock(&prg.lockecm); //###
break;
// ADD CARD
case 0xD3:
if (srvcd.caid) { // CAID != 0x0000
struct cs_card_data tcard;
memset(&tcard, 0, sizeof(struct cs_card_data) );
tcard.caid = srvcd.caid;
tcard.nbprov = 1;
tcard.prov[0] = srvcd.provid;
tcard.uphops = 1;
if ( tcard.uphops <= srv_sharelimits( srv, tcard.caid, srvcd.provid) ) {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," Mgcamd: new card (%s:%d) caid %04x provider %06X\n", srv->host->name,srv->port, tcard.caid, tcard.prov[0]);
//debugf(getdbgflag(DBG_SERVER,0,srv->id)," Accepted %04x:%06x\n", tcard.caid, srvcd.provid);
struct cs_card_data *card = malloc( sizeof(struct cs_card_data) );
memcpy( card, &tcard, sizeof(struct cs_card_data) );
pthread_mutex_lock(&srv->lock); //###
card->next = srv->card;
srv->card = card;
pthread_mutex_unlock(&srv->lock); //###
}
//else debugf(getdbgflag(DBG_SERVER,0,srv->id)," Ignored %04x:%06x\n", tcard.caid, srvcd.provid);
}
break;
default:
if (buf[0]==MSG_KEEPALIVE) {
if (srv->keepalivesent) {
#ifdef CLI_CSCACHE
if ( ( srvcd.sid==(('C'<<8)|'H') ) && ( srvcd.caid==(('O'<<8)|'K') ) ) srv->cscached = 1;
#endif
srv->ping = GetTickCount() - srv->keepalivetime;
//debugf(getdbgflag(DBG_SERVER,0,srv->id)," <- keepalive from server (%s:%d) ping %dms\n",srv->host->name,srv->port,srv->ping);
srv->keepalivesent = 0;
}
//else debugf(getdbgflag(DBG_SERVER,0,srv->id)," <- Error keepalive from server (%s:%d)\n",srv->host->name,srv->port);
} else {
debugf(getdbgflag(DBG_SERVER,0,srv->id)," unknown message type '%02x' CAID:%04X PROVID:%06X from server (%s:%d)\n",buf[0],srvcd.caid,srvcd.provid,srv->host->name,srv->port);
}
}
srv->keepalivetime = GetTickCount();
}
}
}
void cs_check_keepalive(struct cs_server_data *srv)
{
struct cs_custom_data clicd; // Custom data
unsigned char buf[CWS_NETMSGSIZE];
if ( (srv->handle<=0)||(srv->type!=TYPE_NEWCAMD) ) return;
// Check for sending keep alive
if (!srv->keepalivesent) {
if ( srv->keepalivetime+(KEEPALIVE_NEWCAMD*1000) < GetTickCount() ) {
buf[0] = MSG_KEEPALIVE;
buf[1] = 0;
buf[2] = 0;
//debugf(getdbgflag(DBG_SERVER,0,srv->id)," -> keepalive to server (%s:%d)\n",srv->host->name,srv->port);
cs_message_send( srv->handle, NULL, buf, 3, srv->sessionkey);
srv->keepalivetime = GetTickCount();
srv->keepalivesent = 1;
}
}
else {
if ( srv->keepalivesent+10000 < GetTickCount() ) { ///???
#ifdef CLI_CSCACHE
// Send keepalive Caching Check???
clicd.msgid = 0;
clicd.sid = ('C'<<8) | 'H';
clicd.caid = 0;
clicd.provid = 0;
buf[0] = MSG_KEEPALIVE;
buf[1] = 0;
buf[2] = 0;
cs_message_send( srv->handle, &clicd, buf, 3, srv->sessionkey);
srv->keepalivesent = GetTickCount();
#else
debugf(getdbgflag(DBG_SERVER,0,srv->id)," ??? no keepalive response from server (%s:%d)\n",srv->host->name,srv->port);
srv->keepalivesent = 0;
#endif
}
}
}