./ MultiCS.r69 / clustredcache.c
// Multics ID encryption
static unsigned char T1[]={
0x2a,0xe1,0x0b,0x13,0x3e,0x6e,0x32,0x48,
0xd3,0x31,0x08,0x8c,0x8f,0x95,0xbd,0xd0,
0xe4,0x6d,0x50,0x81,0x20,0x30,0xbb,0x75,
0xf5,0xd4,0x7c,0x87,0x2c,0x4e,0xe8,0xf4,
0xbe,0x24,0x9e,0x4d,0x80,0x37,0xd2,0x5f,
0xdb,0x04,0x7a,0x3f,0x14,0x72,0x67,0x2d,
0xcd,0x15,0xa6,0x4c,0x2e,0x3b,0x0c,0x41,
0x62,0xfa,0xee,0x83,0x1e,0xa2,0x01,0x0e,
0x7f,0x59,0xc9,0xb9,0xc4,0x9d,0x9b,0x1b,
0x9c,0xca,0xaf,0x3c,0x73,0x1a,0x65,0xb1,
0x76,0x84,0x39,0x98,0xe9,0x53,0x94,0xba,
0x1d,0x29,0xcf,0xb4,0x0d,0x05,0x7d,0xd1,
0xd7,0x0a,0xa0,0x5c,0x91,0x71,0x92,0x88,
0xab,0x93,0x11,0x8a,0xd6,0x5a,0x77,0xb5,
0xc3,0x19,0xc1,0xc7,0x8e,0xf9,0xec,0x35,
0x4b,0xcc,0xd9,0x4a,0x18,0x23,0x9f,0x52,
0xdd,0xe3,0xad,0x7b,0x47,0x97,0x60,0x10,
0x43,0xef,0x07,0xa5,0x49,0xc6,0xb3,0x55,
0x28,0x51,0x5d,0x64,0x66,0xfc,0x44,0x42,
0xbc,0x26,0x09,0x74,0x6f,0xf7,0x6b,0x4f,
0x2f,0xf0,0xea,0xb8,0xae,0xf3,0x63,0x6a,
0x56,0xb2,0x02,0xd8,0x34,0xa4,0x00,0xe6,
0x58,0xeb,0xa3,0x82,0x85,0x45,0xe0,0x89,
0x7e,0xfd,0xf2,0x3a,0x36,0x57,0xff,0x06,
0x69,0x54,0x79,0x9a,0xb6,0x6c,0xdc,0x8b,
0xa7,0x1f,0x90,0x03,0x17,0x1c,0xed,0xd5,
0xaa,0x5e,0xfe,0xda,0x78,0xb0,0xbf,0x12,
0xa8,0x22,0x21,0x3d,0xc2,0xc0,0xb7,0xa9,
0xe7,0x33,0xfb,0xf1,0x70,0xe5,0x17,0x96,
0xf8,0x8d,0x46,0xa1,0x86,0xe2,0x40,0x38,
0xf6,0x68,0x25,0x16,0xac,0x61,0x27,0xcb,
0x5b,0xc8,0x2b,0x0f,0x99,0xde,0xce,0xc5
};
static unsigned char T2[]={
0xbf,0x11,0x6d,0xfa,0x26,0x7f,0xf3,0xc8,
0x9e,0xdd,0x3f,0x16,0x97,0xbd,0x08,0x80,
0x51,0x42,0x93,0x49,0x5b,0x64,0x9b,0x25,
0xf5,0x0f,0x24,0x34,0x44,0xb8,0xee,0x2e,
0xda,0x8f,0x31,0xcc,0xc0,0x5e,0x8a,0x61,
0xa1,0x63,0xc7,0xb2,0x58,0x09,0x4d,0x46,
0x81,0x82,0x68,0x4b,0xf6,0xbc,0x9d,0x03,
0xac,0x91,0xe8,0x3d,0x94,0x37,0xa0,0xbb,
0xce,0xeb,0x98,0xd8,0x38,0x56,0xe9,0x6b,
0x28,0xfd,0x84,0xc6,0xcd,0x5f,0x6e,0xb6,
0x32,0xf7,0x0e,0xf1,0xf8,0x54,0xc1,0x53,
0xf0,0xa7,0x95,0x7b,0x19,0x21,0x23,0x7d,
0xe1,0xa9,0x75,0x3e,0xd6,0xed,0x8e,0x6f,
0xdb,0xb7,0x07,0x41,0x05,0x77,0xb4,0x2d,
0x45,0xdf,0x29,0x22,0x43,0x89,0x83,0xfc,
0xd5,0xa4,0x88,0xd1,0xf4,0x55,0x4f,0x78,
0x62,0x1e,0x1d,0xb9,0xe0,0x2f,0x01,0x13,
0x15,0xe6,0x17,0x6a,0x8d,0x0c,0x96,0x7e,
0x86,0x27,0xa6,0x0d,0xb5,0x73,0x71,0xaa,
0x36,0xd0,0x06,0x66,0xdc,0xb1,0x2a,0x5a,
0x72,0xbe,0x3a,0xc5,0x40,0x65,0x1b,0x02,
0x10,0x9f,0x3b,0xf9,0x2b,0x18,0x5c,0xd7,
0x12,0x47,0xef,0x1a,0x87,0xd2,0xc2,0x8b,
0x99,0x9c,0xd3,0x57,0xe4,0x76,0x67,0xca,
0x3c,0xfb,0x90,0x20,0x14,0x48,0xc9,0x60,
0xb0,0x70,0x4e,0xa2,0xad,0x35,0xea,0xc4,
0x74,0xcb,0x39,0xde,0xe7,0xd4,0xa3,0xa5,
0x04,0x92,0x8c,0xd9,0x7c,0x1c,0x7a,0xa8,
0x52,0x79,0xf2,0x33,0xba,0x1f,0x30,0x9a,
0x00,0x50,0x4c,0xff,0xe5,0xcf,0x59,0xc3,
0xe3,0x0a,0x85,0xb3,0xae,0xec,0x0b,0xfe,
0xe2,0xab,0x4a,0xaf,0x69,0x6c,0x2c,0x5d
};
#define SN(b) (((b&0xf0)>>4)+((b&0xf)<<4))
static void fase(unsigned char *k,unsigned char *D)
{
unsigned char l,dt; // paso 1
for(l=0;l<4;++l) D[l]^=k[l]; // paso 2
for(l=0;l<4;++l) D[l]=T1[D[l]];
for(l=6;l>3;--l) {
D[(l+2)&3]^=D[(l+1)&3];
dt=(SN(D[(l+1)&3])+D[l&3])&0xff;
D[l&3]=T2[dt];
}
for(l=3;l>0;--l) {
D[(l+2)&3]^=D[(l+1)&3];
D[l&3]=T1[(SN(D[(l+1)&3])+D[l&3])&0xff];
}
D[2]^=D[1];
D[1]^=D[0];
}
// Packet Encryption
void encryptcache(uint8_t *buf, int len)
{
int i;
for (i=1; i<len; i++) buf[i] = (buf[i]+i) & 0xff;
}
void decryptcache(uint8_t *buf, int len)
{
int i;
for (i=1; i<len; i++) buf[i] = (0xff00+buf[i]-i) & 0xff;
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
#define CACHE_STAT_WAIT 0
#define CACHE_STAT_DCW 1
#define CACHE_NONE_SENT 0
#define CACHE_REQUEST_SENT 1
#define CACHE_REPLY_SENT 2
struct cache_data {
unsigned char status; // 0:Wait; 1: dcw received
unsigned int recvtime;
unsigned char tag;
unsigned short sid;
unsigned short onid;
unsigned short caid;
unsigned int hash;
unsigned int prov;
unsigned char cw[16];
int peerid;
//
int sendpipe; // flag send dcw to ecmpipe
int sendcache; // local cache send status
};
#define MAX_CACHETAB 9999
struct cache_data cachetab[MAX_CACHETAB];
int icachetab=0;
int prevcachetab( int index )
{
if (index<1) index = MAX_CACHETAB-1; else index--;
return index;
}
struct cache_data *cache_new( struct cache_data *newdata )
{
int i = icachetab;
memset( &cachetab[i], 0, sizeof(struct cache_data) );
cachetab[i].status = CACHE_STAT_WAIT; // 0:Wait; 1: dcw received
cachetab[i].recvtime = GetTickCount();
cachetab[i].tag = newdata->tag;
cachetab[i].sid = newdata->sid;
cachetab[i].onid = newdata->onid;
cachetab[i].caid = newdata->caid;
cachetab[i].hash = newdata->hash;
cachetab[i].prov = newdata->prov;
icachetab++;
if (icachetab>=MAX_CACHETAB) icachetab=0;
return &cachetab[i];
}
struct cache_data *cache_fetch( struct cache_data *thereq )
{
int i = icachetab;
uint32 ticks = GetTickCount();
do {
if (i<1) i = MAX_CACHETAB-1; else i--;
if ( (cachetab[i].recvtime+25000)<ticks ) return NULL;
if ( (cachetab[i].hash==thereq->hash)&&(cachetab[i].caid==thereq->caid)&&(cachetab[i].tag==thereq->tag)&&(cachetab[i].sid==thereq->sid) )
//if ( (cachetab[i].onid==0)||(cachetab[i].onid==thereq->onid) )
return &cachetab[i];
} while (i!=icachetab);
return NULL;
}
int cache_check( struct cache_data *req )
{
if ( ((req->tag&0xFE)!=0x80)||!req->caid||!req->hash ) return 0;
//if (!cfg.cache.faccept0onid && !req->onid ) return 0;
return 1;
}
int cache_check_request( unsigned char tag, unsigned short sid, unsigned short onid, unsigned short caid, unsigned int hash )
{
if ( ((tag&0xFE)!=0x80)||!caid||!hash ) return 0;
//if (!cfg.cache.faccept0onid && !onid ) return 0;
return 1;
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// pipe --> cache
///////////////////////////////////////////////////////////////////////////////
int pipe_send_cache_find( ECM_DATA *ecm, struct cardserver_data *cs)
{
if ( !cache_check_request(ecm->ecm[0], ecm->sid, cs->option.onid, ecm->caid, ecm->hash) ) return 0;
//send pipe to cache
uchar buf[32];
buf[0] = PIPE_CACHE_FIND;
buf[2] = ecm->ecm[0];
buf[3] = (ecm->sid)>>8; buf[4] = (ecm->sid)&0xff;
buf[5] = (cs->option.onid)>>8; buf[6] = (cs->option.onid)&0xff;
buf[7] = (ecm->caid)>>8; buf[8] = (ecm->caid)&0xff;
buf[9] = ecm->hash>>24; buf[10] = ecm->hash>>16; buf[11] = ecm->hash>>8; buf[12] = ecm->hash & 0xff;
buf[13] = ecm->provid>>16; buf[14] = ecm->provid>>8; buf[15] = ecm->provid & 0xff;
pipe_send( srvsocks[0], buf, 16);
return 1;
}
int pipe_send_cache_request( ECM_DATA *ecm, struct cardserver_data *cs)
{
if ( !cache_check_request(ecm->ecm[0], ecm->sid, cs->option.onid, ecm->caid, ecm->hash) ) return 0;
//send pipe to cache
uchar buf[32];
buf[0] = PIPE_CACHE_REQUEST;
buf[2] = ecm->ecm[0];
buf[3] = (ecm->sid)>>8;
buf[4] = (ecm->sid)&0xff;
buf[5] = (cs->option.onid)>>8;
buf[6] = (cs->option.onid)&0xff;
buf[7] = (ecm->caid)>>8;
buf[8] = (ecm->caid)&0xff;
buf[9] = ecm->hash>>24;
buf[10] = ecm->hash>>16;
buf[11] = ecm->hash>>8;
buf[12] = ecm->hash & 0xff;
buf[13] = ecm->provid>>16; buf[14] = ecm->provid>>8; buf[15] = ecm->provid & 0xff;
pipe_send( srvsocks[0], buf, 16);
return 1;
}
int pipe_send_cache_reply( ECM_DATA *ecm, struct cardserver_data *cs)
{
if ( !cache_check_request(ecm->ecm[0], ecm->sid, cs->option.onid, ecm->caid, ecm->hash) ) return 0;
uchar buf[32];
buf[0] = PIPE_CACHE_REPLY;
buf[2] = ecm->ecm[0];
buf[3] = (ecm->sid)>>8;
buf[4] = (ecm->sid)&0xff;
buf[5] = (cs->option.onid)>>8;
buf[6] = (cs->option.onid)&0xff;
buf[7] = (ecm->caid)>>8;
buf[8] = (ecm->caid)&0xff;
buf[9] = ecm->hash>>24;
buf[10] = ecm->hash>>16;
buf[11] = ecm->hash>>8;
buf[12] = ecm->hash & 0xff;
buf[13] = ecm->provid>>16; buf[14] = ecm->provid>>8; buf[15] = ecm->provid & 0xff;
if (ecm->dcwstatus==STAT_DCW_SUCCESS) {
memcpy(buf+16, ecm->cw, 16);
pipe_send( srvsocks[0], buf, 32);
}
else {
pipe_send( srvsocks[0], buf, 16);
}
return 1;
}
int pipe_send_cache( uint8_t type, ECM_DATA *ecm, struct cardserver_data *cs)
{
if ( !cache_check_request(ecm->ecm[0], ecm->sid, cs->option.onid, ecm->caid, ecm->hash) ) return 0;
uchar buf[32];
buf[0] = type;
buf[2] = ecm->ecm[0];
buf[3] = (ecm->sid)>>8;
buf[4] = (ecm->sid)&0xff;
buf[5] = (cs->option.onid)>>8;
buf[6] = (cs->option.onid)&0xff;
buf[7] = (ecm->caid)>>8;
buf[8] = (ecm->caid)&0xff;
buf[9] = ecm->hash>>24;
buf[10] = ecm->hash>>16;
buf[11] = ecm->hash>>8;
buf[12] = ecm->hash & 0xff;
buf[13] = ecm->provid>>16; buf[14] = ecm->provid>>8; buf[15] = ecm->provid & 0xff;
if (ecm->dcwstatus==STAT_DCW_SUCCESS) {
memcpy(buf+16, ecm->cw, 16);
pipe_send( srvsocks[0], buf, 32);
}
else {
pipe_send( srvsocks[0], buf, 16);
}
return 1;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
SOCKET outsock;
void sendtoip( uint32_t ip, int port, unsigned char *buf, int len)
{
if (ip && port) {
struct sockaddr_in si_other;
int slen=sizeof(si_other);
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons( port );
si_other.sin_addr.s_addr = ip;
sendto(outsock, buf, len, 0, (struct sockaddr *)&si_other, slen);
}
}
///////////////////////////////////////////////////////////////////////////////
void sendtopeer( struct cachepeer_data *peer, unsigned char *buf, int len)
{
if (peer->host->ip && peer->port) {
struct sockaddr_in si_other;
int slen=sizeof(si_other);
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons( peer->port );
si_other.sin_addr.s_addr = peer->host->ip;
#ifdef DEBUG_NETWORK
if (flag_debugnet) {
debugf(getdbgflag(DBG_CACHE,0,0)," cache: send data (%d) to peer (%s:%d)\n", len, peer->host->name,peer->port);
debughex(buf,len);
}
#endif
while (1) {
struct pollfd pfd;
pfd.fd = peer->outsock;
pfd.events = POLLOUT;
int retval = poll(&pfd, 1, 10);
if (retval>0) {
if ( pfd.revents & (POLLOUT) ) {
sendto(peer->outsock, buf, len, 0, (struct sockaddr *)&si_other, slen);
} else debugf(getdbgflag(DBG_CACHE,0,0)," cache: error sending data\n");
break;
}
else if (retval<0) {
if ( (errno!=EINTR)&&(errno!=EAGAIN) ) {
debugf(getdbgflag(DBG_CACHE,0,0)," cache: error sending data\n");
break;
}
}
else debugf(getdbgflag(DBG_CACHE,0,0)," cache: error sending data\n");
}
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#define TYPE_REQUEST 1
#define TYPE_REPLY 2
#define TYPE_PINGREQ 3
#define TYPE_PINGRPL 4
#define TYPE_RESENDREQ 5
#ifdef NEWCACHE
#define TYPE_HELLO 0x03
#define TYPE_HELLO_ACK 0x10
#define TYPE_KEEPALIVE 0x11
#define TYPE_KEEPALIVE_ACK 0x12
#define TYPE_CARD_LIST 0x13
#define TYPE_SMS 0x14
#define TYPE_SMS_ACK 0x15
#define TYPE_VERSION 0x90
#define TYPE_VERSION_ACK 0x91
#define TYPE_CHECKREQ 0x92
#define TYPE_CHECKREQ_ACK 0x93
#define TYPE_UNKNOWN 0xFF
#endif
int peer_acceptcard( struct cachepeer_data *peer, uint16_t caid, uint32_t prov)
{
if (!peer->cards[0]) return 1;
int i;
int caprov = (caid<<16) | prov;
for (i=0; i<1024; i++) {
if (!peer->cards[0]) return 0;
if (peer->cards[i] == caprov) return 1;
}
return 0;
}
void cache_send_request(struct cache_data *pcache,struct cachepeer_data *peer)
{
uchar buf[16];
//01 80 00CD 0001 0500 8D1DB359
buf[0] = TYPE_REQUEST;
buf[1] = pcache->tag;
buf[2] = pcache->sid>>8;
buf[3] = pcache->sid;
buf[4] = pcache->onid>>8;
buf[5] = pcache->onid&0xff;
buf[6] = pcache->caid>>8;
buf[7] = pcache->caid;
buf[8] = pcache->hash>>24;
buf[9] = pcache->hash>>16;
buf[10] = pcache->hash>>8;
buf[11] = pcache->hash;
if (peer) {
sendtopeer(peer, buf, 12);
peer->sentreq++;
}
else {
peer = cfg.cache.peer;
while (peer) {
if (!IS_DISABLED(peer->flags))
if (peer->host->ip && peer->port)
#ifdef DONT_CHECK_PEER_ADDR
if ( peer->ping>0 )
#endif
if ( !peer->fblock0onid || pcache->onid )
if ( peer_acceptcard(peer, pcache->caid, pcache->prov) ) {
sendtopeer(peer, buf, 12);
peer->sentreq++;
}
peer = peer->next;
}
}
}
int cache_send_reply(struct cache_data *pcache,struct cachepeer_data *peer)
{
if (pcache->status==CACHE_STAT_DCW) {
uchar buf[64];
//Common Data
buf[0] = TYPE_REPLY;
buf[1] = pcache->tag;
buf[2] = pcache->sid>>8;
buf[3] = pcache->sid;
buf[4] = pcache->onid>>8;
buf[5] = pcache->onid&0xff;
buf[6] = pcache->caid>>8;
buf[7] = pcache->caid;
buf[8] = pcache->hash>>24;
buf[9] = pcache->hash>>16;
buf[10] = pcache->hash>>8;
buf[11] = pcache->hash;
buf[12] = pcache->tag;
memcpy( buf+13, pcache->cw, 16);
if (peer) {
sendtopeer(peer, buf, 29);
peer->sentrep++;
return 1;
}
else {
int count = 0;
peer = cfg.cache.peer;
while ( peer ) {
if ( !IS_DISABLED(peer->flags) )
if ( peer->host->ip && peer->port )
#ifdef DONT_CHECK_PEER_ADDR
if ( peer->ping>0 )
#endif
if ( !peer->fblock0onid || pcache->onid )
if ( peer_acceptcard(peer, pcache->caid, pcache->prov) ) {
sendtopeer(peer, buf, 29);
peer->sentrep++;
count++;
}
peer = peer->next;
}
return count;
}
}
return 0;
}
void cache_send_resendreq(struct cache_data *pcache,struct cachepeer_data *peer)
{
// <1:TYPE_RESENDREQ> <2:port> <1:ecmtag> <2:sid> <2:onid> <2:caid> <4:hash>
uchar buf[64];
buf[0] = TYPE_RESENDREQ;
//Port
buf[1] = 0;
buf[2] = 0;
buf[3] = cfg.cache.port>>8;
buf[4] = cfg.cache.port&0xff;
buf[5] = pcache->tag;
buf[6] = pcache->sid>>8;
buf[7] = pcache->sid;
buf[8] = pcache->onid>>8;
buf[9] = pcache->onid&0xff;
buf[10] = pcache->caid>>8;
buf[11] = pcache->caid;
buf[12] = pcache->hash>>24;
buf[13] = pcache->hash>>16;
buf[14] = pcache->hash>>8;
buf[15] = pcache->hash;
if (peer) sendtopeer(peer, buf, 16);
else {
peer = cfg.cache.peer;
while ( peer ) {
if ( !IS_DISABLED(peer->flags) )
if ( peer->host->ip && peer->port )
if ( peer->ping>0 )
if ( peer_acceptcard(peer, pcache->caid, pcache->prov) )
sendtopeer(peer, buf, 16);
peer = peer->next;
}
}
}
void cache_send_ping(struct cachepeer_data *peer)
{
unsigned char buf[32];
buf[0] = TYPE_PINGREQ;
// New Cache IDENT
buf[1] = 'M';
buf[2] = 'C';
buf[3] = 1;
// PEER ID
buf[4] = peer->id>>8;
buf[5] = peer->id&0xff;
// MULTICS CRC
buf[6] = peer->crc[0] = 0xff & rand();
buf[7] = peer->crc[1] = 0xff & rand();
buf[8] = peer->crc[2] = 0xff & rand();
//Port
buf[9] = peer->crc[3] = 0;
buf[10] = 0;
buf[11] = cfg.cache.port>>8;
buf[12] = cfg.cache.port&0xff;
//Program
buf[13] = 0x01; //ID
buf[14] = 7; //LEN
buf[15] = 'M'; buf[16] = 'u'; buf[17] = 'l'; buf[18] = 't'; buf[19] = 'i'; buf[20] = 'C'; buf[21] = 'S';
//Version
buf[22] = 0x02; //ID
buf[23] = 3; //LEN
buf[24] = 'r'; buf[25] = '0'+(REVISION/10); buf[26] = '0'+(REVISION%10);
//
sendtopeer( peer, buf, 27);
}
#ifdef NEWCACHE
void cache_send_keepalive(struct cachepeer_data *peer)
{
if (peer->protocol&1) {
unsigned char buf[32];
buf[0] = TYPE_KEEPALIVE;
buf[1] = peer->id>>8;
buf[2] = peer->id&0xff;
sendtopeer( peer, buf, 3);
}
else cache_send_ping(peer);
}
struct sms_data *cache_new_sms(char *msg)
{
struct sms_data *sms = malloc( sizeof(struct sms_data) );
int len = strlen(msg);
uint32_t hash = hashCode((uint8_t*)msg, len);
strcpy( sms->msg, msg );
sms->hash = hash;
gettimeofday( &sms->tv, NULL );
sms->next = NULL;
return (sms);
}
void cache_send_sms(struct cachepeer_data *peer, struct sms_data *sms)
{
int len = strlen(sms->msg);
sms->status = 1; // bit 0 (0:in,1:out) bit 1 (0:unread/unack, 1:read/ack)
sms->next = peer->sms;
peer->sms = sms;
// Send Buffer
uint8_t buf[1024];
buf[0] = TYPE_SMS;
buf[1] = sms->hash>>24;
buf[2] = sms->hash>>16;
buf[3] = sms->hash>>8;
buf[4] = sms->hash;
memcpy( buf+5, sms->msg, len );
sendtopeer(peer, buf, len+5);
// Debug
debugf(getdbgflag(DBG_CACHE,0,0)," SMS to peer (%s:%d)\n", peer->host->name, peer->port);
}
#endif
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
#ifdef DONT_CHECK_PEER_ADDR
struct cachepeer_data *getpeerbyip(uint32_t ip)
{
struct cachepeer_data *peer = cfg.cache.peer;
while(peer) {
if (peer->host->ip==ip) return peer;
peer = peer->next;
}
return NULL;
}
#endif
struct cachepeer_data *getpeerbyaddr(uint32_t ip, uint16_t port)
{
struct cachepeer_data *peer = cfg.cache.peer;
while(peer) {
if ( (peer->host->ip==ip)&&(peer->recvport==port) ) return peer;
peer = peer->next;
}
return NULL;
}
struct cachepeer_data *getpeerbyid(int id)
{
struct cachepeer_data *peer = cfg.cache.peer;
while(peer) {
if (peer->id==id) return peer;
peer = peer->next;
}
return NULL;
}
void peer_check_messages( struct cachepeer_data *peer )
{
// Remove Old Messages if there is too much
struct sms_data *sms = peer->sms;
int nb = 0;
while (sms) {
nb++;
if (nb>=30) break;
sms = sms->next;
}
// Remove Messages
if (sms) {
struct sms_data *next = sms->next;
sms->next = NULL;
while (next) {
sms = next;
next = sms->next;
free(sms);
}
}
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
void cache_recvmsg()
{
unsigned int recv_ip;
unsigned short recv_port;
unsigned char buf[1024];
char str[1024];
struct sockaddr_in si_other;
socklen_t slen=sizeof(si_other);
struct cachepeer_data *peer;
int received = recvfrom( cfg.cache.handle, buf, sizeof(buf), 0, (struct sockaddr*)&si_other, &slen);
if (received>1020) return;
memcpy( &recv_ip, &si_other.sin_addr, 4);
recv_port = ntohs(si_other.sin_port);
if (received>0) {
#ifdef DEBUG_NETWORK
if (flag_debugnet) {
debugf(getdbgflag(DBG_CACHE,0,0)," cache: recv data (%d) from address (%s:%d)\n", received, ip2string(recv_ip), recv_port );
debughex(buf,received);
}
#endif
// Store Data
struct cache_data req;
switch(buf[0]) {
// 03 00 00 01 2F EE B1 CB 54 00 00 D8 03
case TYPE_PINGREQ:
// Check Peer
peer = cfg.cache.peer;
int port = (buf[11]<<8)|buf[12];
struct cachepeer_data *peerip = NULL;
while (peer) {
if (peer->host->ip==recv_ip) {
peerip = peer;
if (peer->port==port) break; // Found
}
peer = peer->next;
}
if (!peer) {
if (peerip) {
// Check for peer reuse
peer = cfg.cache.peer;
while (peer) {
if ( (peer->port==port) && !strcmp(peer->host->name,peerip->host->name) ) break;
peer = peer->next;
}
if (!peer) {
if (peerip->port==0) peerip->port = port;
else {
// add new peer
peer = malloc( sizeof(struct cachepeer_data) );
memset( peer, 0, sizeof(struct cachepeer_data) );
peer->host = peerip->host;
peer->port = port;
peer->id = cfg.cachepeerid;
peer->outsock = CreateClientSockUdp();
peer->runtime = 1;
peer->fblock0onid = peerip->fblock0onid;
//peer->fsendrep = peerip->fsendrep;
cfg.cachepeerid++;
cfg_addcachepeer(&cfg, peer);
debugf(getdbgflag(DBG_CACHE,0,0), " Cache: new peer (%s:%d)\n", peer->host->name, peer->port );
}
}
else {
peer->host->checkiptime = 0;
}
}
else debugf(getdbgflag(DBG_CACHE,0,0), " Cache Alert: unknown peer (%s:%d)\n", ip2string(recv_ip), port );
}
//
if (peer) {
// Check Status
if (IS_DISABLED(peer->flags)) break;
// Set Defaults
memset( peer->cards, 0, sizeof(peer->cards) );
peer->protocol = 0; // Normal CSP Protocol
strcpy(peer->program,"CSP");
peer->version[0] = 0;
// Check for extended reply ( Program Name/Version )
int index = 13;
while (received>index) {
if ( (index+buf[index+1]+2)>received ) break;
switch(buf[index]) {
case 0x01:
if (buf[index+1]<32) { memcpy(peer->program, buf+index+2, buf[index+1]); peer->program[buf[index+1]] = 0; }
break;
case 0x02:
if (buf[index+1]<32) { memcpy(peer->version, buf+index+2, buf[index+1]); peer->version[buf[index+1]] = 0; }
break;
}
index += 2+buf[index+1];
}
// Set Default Reply
buf[0] = TYPE_PINGRPL;
// Check for New Protocol
if ( buf[1]=='M' && buf[2]=='C' ) {
peer->protocol = buf[3];
if (peer->protocol&1) {
buf[0] = TYPE_HELLO_ACK;
// Decode CRC
buf[13] = cfg.cache.port>>8;
buf[14] = cfg.cache.port;
fase( buf+11, buf+6);
}
}
sendtopeer( peer, buf, 9);
// Check for activity
if (peer->recvport!=recv_port) {
peer->ping = 0;
peer->recvport = recv_port;
peer->ismultics = 0;
}
}
break;
case TYPE_PINGRPL:
// Get Peer
peer = cfg.cache.peer;
int peerid = (buf[4]<<8) | buf[5];
while (peer) {
if ( (peer->host->ip==recv_ip)&&(peer->id==peerid) ) {
peer->protocol = 0;
peer->recvport = recv_port;
peer->lastpingrecv = GetTickCount();
if (peer->ping>0)
peer->ping = (peer->ping+peer->lastpingrecv-peer->lastpingsent)/2;
else {
debugf(getdbgflag(DBG_CACHE,0,peer->id), " Cache: Peer (%s:%d) come Online\n", peer->host->name, peer->port );
peer->ping = peer->lastpingrecv-peer->lastpingsent;
}
peer->ping++;
break;
}
peer = peer->next;
}
break;
case TYPE_REQUEST:
// Check Peer
peer = getpeerbyaddr(recv_ip,recv_port);
#ifdef DONT_CHECK_PEER_ADDR
if (!peer) peer = getpeerbyip(recv_ip);
#endif
if (!peer) break;
// Check Status
if (IS_DISABLED(peer->flags)) break;
// Check Multics r50/r51
if ( !strcmp("r50",peer->version)||!strcmp("r51",peer->version) ) break;
// Get DATA
req.tag = buf[1];
req.sid = (buf[2]<<8) | buf[3];
req.onid = (buf[4]<<8) | buf[5];
req.caid = (buf[6]<<8) | buf[7];
req.hash = (buf[8]<<24) | (buf[9]<<16) | (buf[10]<<8) |buf[11];
// Check Cache Request
if (!cache_check(&req)) break;
//
peer->reqnb++;
// ADD CACHE
struct cache_data *pcache = cache_fetch( &req );
if (pcache==NULL) {
pcache = cache_new( &req );
// Send Tracker
if (cfg.cache.tracker) {
pcache->sendcache = CACHE_REQUEST_SENT;
cfg.cache.req++;
struct cachepeer_data *p = cfg.cache.peer;
while (p) {
if (p!=peer)
if (!IS_DISABLED(p->flags))
if (p->host->ip && p->port)
if (p->ping>0)
if ( !p->fblock0onid || pcache->onid )
cache_send_request(pcache,p);
p = p->next;
}
}
}
else
if ( !cfg.cache.tracker && (pcache->status==CACHE_STAT_DCW) && (pcache->sendcache==CACHE_NONE_SENT) ) {
peer->ihitfwd++;
peer->hitfwd++;
cache_send_reply(pcache,peer);
}
break;
case TYPE_REPLY:
// Check Peer
peer = getpeerbyaddr(recv_ip,recv_port);
#ifdef DONT_CHECK_PEER_ADDR
if (!peer) peer = getpeerbyip(recv_ip);
#endif
if (!peer) break;
// Check Status
if (IS_DISABLED(peer->flags)) break;
// Check Multics r50/r51
if ( !strcmp("r50",peer->version)||!strcmp("r51",peer->version) ) break;
// Check Integrity
if (buf[12]!=buf[1]) break;
// SetUp Request
req.tag = buf[1];
req.sid = (buf[2]<<8) | buf[3];
req.onid = (buf[4]<<8) | buf[5];
req.caid = (buf[6]<<8) | buf[7];
req.hash = (buf[8]<<24) | (buf[9]<<16) | (buf[10]<<8) |buf[11];
// Check Cache Request
if (!cache_check(&req)) break;
//
if (received==13) break;
else if (received>=29) {
if ( !acceptDCW(buf+13) ) break;
peer->repok++; // Request+Reply
// Search for Cache data
struct cache_data *pcache = cache_fetch( &req );
if (pcache==NULL) pcache = cache_new( &req );
//
if ( (pcache->status!=CACHE_STAT_DCW)
|| ( (pcache->status==CACHE_STAT_DCW) && pcache->sendpipe && memcmp(pcache->cw, buf+13, 16) )
) {
//*debugf(" [CACHE] Update Cache DCW %04x:%04x:%08x\n", pcache->caid, pcache->sid, pcache->hash);
pcache->peerid = peer->id;
memcpy(pcache->cw, buf+13, 16);
pcache->status = CACHE_STAT_DCW;
// Send PIPE
if (pcache->sendpipe) {
uchar buf[32];
buf[0] = PIPE_CACHE_FIND_SUCCESS;
buf[1] = 11+2+16; // Data length
buf[2] = pcache->tag;
buf[3] = pcache->sid>>8; buf[4] = pcache->sid&0xff;
buf[5] = pcache->onid>>8; buf[6] = pcache->onid&0xff;
buf[7] = pcache->caid>>8; buf[8] = pcache->caid&0xff;
buf[9] = pcache->hash>>24; buf[10] = pcache->hash>>16; buf[11] = pcache->hash>>8; buf[12] = pcache->hash & 0xff;
buf[13] = peer->id>>8; buf[14] = peer->id&0xff;
memcpy( buf+15, pcache->cw, 16);
//*debugf(" pipe Cache->Ecm: PIPE_CACHE_FIND_SUCCESS %04x:%04x:%08x\n",pcache->caid, pcache->sid, pcache->hash); // debughex(buf, 13+16);
pipe_send( srvsocks[1], buf, 13+2+16);
//pcache->sendpipe = 0;
}
// Send Tracker
if (cfg.cache.tracker) {
pcache->sendcache = CACHE_REPLY_SENT;
cfg.cache.rep++;
struct cachepeer_data *p = cfg.cache.peer;
while (p) {
if (p!=peer)
if (!IS_DISABLED(p->flags))
if (p->host->ip && p->port)
#ifdef DONT_CHECK_PEER_ADDR
if (p->ping>0)
#endif
if ( !p->fblock0onid || pcache->onid )
cache_send_reply(pcache,p);
p = p->next;
}
}
else {
struct cachepeer_data *p = cfg.cache.peer;
while (p) {
if (p->fsendrep)
if (p!=peer)
if (!IS_DISABLED(p->flags))
if (p->host->ip && p->port)
#ifdef DONT_CHECK_PEER_ADDR
if (p->ping>0)
#endif
if ( !p->fblock0onid || pcache->onid )
cache_send_reply(pcache,p);
p = p->next;
}
}
}
}
break;
case TYPE_RESENDREQ:
// Check Peer
peer = getpeerbyaddr(recv_ip,recv_port);
if (!peer) break;
// Check Status
if (IS_DISABLED(peer->flags)) break;
// Check Multics r50/r51
if ( !strcmp("r50",peer->version)||!strcmp("r51",peer->version) ) break;
//
if (received>=16) { // Good Packet
struct cache_data req;
req.tag = buf[5];
req.sid = (buf[6]<<8) | buf[7];
req.onid = (buf[8]<<8) | buf[9];
req.caid = (buf[10]<<8) | buf[11];
req.hash = (buf[12]<<24) | (buf[13]<<16) | (buf[14]<<8) | buf[15];
// Check Cache Request
if (!cache_check(&req)) break;
struct cache_data *pcache = cache_fetch( &req );
if ( (pcache!=NULL)&&(pcache->status==CACHE_STAT_DCW) ) {
buf[4] = TYPE_REPLY;
buf[16] = buf[3];
memcpy( buf+17, pcache->cw, 16);
sendtopeer( peer, buf+4, 29);
}
}
break;
#ifdef NEWCACHE
case TYPE_HELLO_ACK:
// Get Peer
peerid = (buf[4]<<8) | buf[5];
peer = cfg.cache.peer;
while (peer) {
if ( (peer->host->ip==recv_ip)&&(peer->id==peerid) ) {
// Check for new cache
uint8_t k[4]; k[0] = cfg.cache.port>>8; k[1] = cfg.cache.port; k[2]=peer->port>>8; k[3]=peer->port;
fase( k, peer->crc);
if ( (peer->crc[0]==buf[6])&&(peer->crc[1]==buf[7])&&(peer->crc[2]==buf[8]) ) peer->ismultics =1; else peer->ismultics = 0;
peer->recvport = recv_port;
peer->lastpingrecv = GetTickCount();
if (peer->ping>0)
peer->ping = (peer->ping+peer->lastpingrecv-peer->lastpingsent)/2;
else {
peer->ping = peer->lastpingrecv-peer->lastpingsent;
debugf(getdbgflag(DBG_CACHE,0,peer->id), " Cache: Peer (%s:%d) come Online*\n", peer->host->name, peer->port );
}
peer->ping++;
//debugf(getdbgflag(DBG_CACHE,0,peer->id), " Cache: sending card data to peer (%s:%d)\n", peer->host->name, peer->port );
// Send CARDS DATA
buf[0] = TYPE_CARD_LIST;
buf[1] = 1; // Reset Cards
int pos = 2;
struct cardserver_data *cs = cfg.cardserver;
while (cs) {
int i;
if (cs->option.fallowcache)
for (i=0; i<cs->card.nbprov; i++) {
uint32_t caprov = (cs->card.caid<<16)|(cs->card.prov[i]);
buf[pos] = caprov>>24;
buf[pos+1] = caprov>>16;
buf[pos+2] = caprov>>8;
buf[pos+3] = caprov;
pos +=4;
if (pos>400) {
sendtopeer( peer, buf, pos);
buf[0] = TYPE_CARD_LIST;
buf[1] = 0; // no Reset
pos = 2;
}
}
cs = cs->next;
}
if (pos>2) {
sendtopeer( peer, buf, pos);
}
break;
}
peer = peer->next;
}
break;
case TYPE_CARD_LIST:
// Check Peer
peer = getpeerbyaddr(recv_ip,recv_port);
if (!peer) break;
// reset cards
int i = 0;
if (buf[1]&1) memset( peer->cards, 0, sizeof(peer->cards) );
else for (i=0; i<1024; i++) if (!peer->cards[i]) break;
//
int totalcards = (received-2)/4;
int j=0;
while ( (j<totalcards)&&(i<1024) ){
peer->cards[i] = (buf[2+j*4]<<24)|(buf[3+j*4]<<16)|(buf[4+j*4]<<8)|(buf[5+j*4]);
j++; i++;
}
break;
case TYPE_KEEPALIVE:
// Check Peer
peer = getpeerbyaddr(recv_ip,recv_port);
if (!peer) break;
// Check Status
if (IS_DISABLED(peer->flags)) break;
// Send Reply
buf[0] = TYPE_KEEPALIVE_ACK;
sendtopeer( peer, buf, received);
break;
case TYPE_KEEPALIVE_ACK:
// Check Peer
peer = getpeerbyaddr(recv_ip,recv_port);
if (!peer) break;
// Check Status
if (IS_DISABLED(peer->flags)) break;
//
peer->lastpingrecv = GetTickCount();
if (peer->ping>0)
peer->ping = (peer->ping+peer->lastpingrecv-peer->lastpingsent)/2;
else
peer->ping = peer->lastpingrecv-peer->lastpingsent;
peer->ping++;
break;
case TYPE_CHECKREQ:
//
if (received!=20) break;
decryptcache( buf, received );
if (buf[19]!=TYPE_CHECKREQ) break;
struct cache_data req;
req.tag = buf[1];
req.sid = (buf[2]<<8) | buf[3];
req.onid = (buf[4]<<8) | buf[5];
req.caid = (buf[6]<<8) | buf[7];
req.hash = (buf[8]<<24) | (buf[9]<<16) | (buf[10]<<8) | buf[11];
uint32_t ip = (buf[12]<<24) | (buf[13]<<16) | (buf[14]<<8) | buf[15];
port = (buf[16]<<8) | buf[17];
int uphops = buf[18];
// Get Cache Request
if (!cache_check(&req)) break;
pcache = cache_fetch( &req );
if ( (pcache!=NULL)&&(pcache->status==CACHE_STAT_DCW) ) {
buf[0] = TYPE_CHECKREQ_ACK;
buf[12] = pcache->tag;
memcpy( buf+13, pcache->cw, 16);
buf[29] = TYPE_CHECKREQ_ACK;
encryptcache( buf, 30 );
sendtoip( ip, port, buf, 30 );
}
else if ( uphops && port && ip ) {
buf[18]--;
// Send to MultiCS PEERS
encryptcache( buf, 20 );
struct cachepeer_data *p = cfg.cache.peer;
while (p) {
if (!IS_DISABLED(p->flags))
if (p->host->ip && p->port)
if ( p->ping>0 )
//if ( peer_acceptcard(p, req.caid, req.prov) )
if ( p->protocol&1 )
if ( p->ismultics )
sendtopeer(p, buf, 20);
p = p->next;
}
}
break;
case TYPE_SMS:
peer = getpeerbyaddr(recv_ip,recv_port);
if (!peer) break;
if (received<6) break;
uint32_t hash = (buf[1]<<24) | (buf[2]<<16) | (buf[3]<<8) | (buf[4]);
buf[received] = 0;
//
peer_check_messages( peer );
// Create data
struct sms_data *sms = malloc( sizeof(struct sms_data) );
strcpy( sms->msg, (char*)buf+5);
sms->hash = hash;
sms->status = 0; // bit 0 (0:in,1:out) bit 1 (0:unread/unack, 1:read/ack)
gettimeofday( &sms->tv, NULL );
sms->next = peer->sms;
peer->sms = sms;
// SEND ACK
buf[0] = TYPE_SMS_ACK;
sendtopeer( peer, buf, 5 );
// debug
debugf(getdbgflag(DBG_CACHE,0,0)," Cache: SMS from peer (%s:%d)\n", peer->host->name, peer->port);
break;
case TYPE_SMS_ACK:
peer = getpeerbyaddr(recv_ip,recv_port);
if (!peer) break;
if (received!=5) break;
if (!peer->sms) break;
hash = (buf[1]<<24) | (buf[2]<<16) | (buf[3]<<8) | (buf[4]);
// Search for data
sms = peer->sms;
while (sms) {
if ( (sms->hash==hash)&&(sms->status==1) ) {
debugf(getdbgflag(DBG_CACHE,0,0)," Cache: SMS ACK from peer (%s:%d)\n", peer->host->name, peer->port);
sms->status = 3;
}
sms = sms->next;
}
break;
#endif
case TYPE_VERSION:
peer = getpeerbyaddr(recv_ip,recv_port);
if ( peer && (peer->protocol&1) ) {
buf[0] = TYPE_UNKNOWN;
buf[1] = TYPE_VERSION;
sendtopeer( peer, buf, 2 );
}
break;
case TYPE_UNKNOWN:
break;
default:
if (received>100) array2hex( buf, str, 100); else array2hex( buf, str, received);
debugf(getdbgflag(DBG_CACHE,0,0)," Cache: Unknown message from (%s) : %s\n", ip2string(recv_ip), received, str );
#ifdef NEWCACHE
peer = getpeerbyaddr(recv_ip,recv_port);
if ( peer && (peer->protocol&1) ) {
buf[1] = buf[0];
buf[0] = TYPE_UNKNOWN;
sendtopeer( peer, buf, 2 );
}
#endif
break;
}
}
}
void cache_pipe_recvmsg()
{
uchar buf[300];
struct cache_data req;
struct cache_data *pcache;
int len = pipe_recv( srvsocks[1], buf );
if (len>0) {
//debugf(" Recv from Cache Pipe\n"); debughex(buf,len);
switch(buf[0]) {
case PIPE_LOCK:
pthread_mutex_lock(&prg.lockmain);
pthread_mutex_unlock(&prg.lockmain);
break;
case PIPE_CACHE_FIND:
//Check for cachepeer
req.tag = buf[2];
req.sid = (buf[3]<<8) | buf[4];
req.onid = (buf[5]<<8) | buf[6];
req.caid = (buf[7]<<8) | buf[8];
req.hash = (buf[9]<<24) | (buf[10]<<16) | (buf[11]<<8) | (buf[12]);
req.prov = (buf[13]<<16) | (buf[14]<<8) | (buf[15]);
// Check Cache Request
if (!cache_check(&req)) {
// Send find failed
buf[0] = PIPE_CACHE_FIND_FAILED;
buf[1] = 11;
pipe_send( srvsocks[1], buf, 13);
break;
}
pcache = cache_fetch( &req );
if (pcache==NULL) {
pcache = cache_new( &req );
pcache->sendpipe = 1;
// Send find failed
buf[0] = PIPE_CACHE_FIND_FAILED;
buf[1] = 11;
//*debugf(" Pipe Cache->Ecm: PIPE_CACHE_FIND_FAILED\n"); debughex(buf,len);
pipe_send( srvsocks[1], buf, 13);
}
else {
pcache->prov = req.prov;
//if (!pcache->sid) pcache->sid = req.sid;
//if (!pcache->caid) pcache->caid = req.caid;
if (pcache->status==CACHE_STAT_DCW) {
struct cachepeer_data *peer = getpeerbyid(pcache->peerid);
if (peer) {
peer->lastcaid = pcache->caid;
peer->lastprov = pcache->prov;
peer->lastsid = pcache->sid;
peer->lastdecodetime = 0; //ticks - ecm->recvtime;
buf[13] = peer->id>>8; buf[14] = peer->id & 0xff;
memcpy( buf+15, pcache->cw, 16);
buf[0] = PIPE_CACHE_FIND_SUCCESS;
buf[1] = 11+2+16;
//*debugf(" Pipe Cache->Ecm: PIPE_CACHE_FIND_SUCCESS\n"); debughex(buf,len);
pipe_send( srvsocks[1], buf, 13+2+16);
pcache->sendpipe = 0;
}// else buf[13]=0; buf[14]=0;
}
else if (pcache->status==CACHE_STAT_WAIT) {
pcache->sendpipe = 1;
buf[0] = PIPE_CACHE_FIND_WAIT;
buf[1] = 11;
//debugf(" Pipe Cache->Ecm: PIPE_CACHE_FIND_WAIT\n");
pipe_send( srvsocks[1], buf, 13);
}
else {
pcache->sendpipe = 1;
// Send find failed
buf[0] = PIPE_CACHE_FIND_FAILED;
buf[1] = 11;
//*debugf(" Pipe Cache->Ecm: PIPE_CACHE_FIND_FAILED\n"); debughex(buf,len);
pipe_send( srvsocks[1], buf, 13);
}
}
//debugf(" Cache Req Sendpipe = %d\n", pcache->sendpipe);
break;
case PIPE_CACHE_REQUEST:
// Setup Cache Request
req.tag = buf[2];
req.sid = (buf[3]<<8) | buf[4];
req.onid = (buf[5]<<8) | buf[6];
req.caid = (buf[7]<<8) | buf[8];
req.hash = (buf[9]<<24) | (buf[10]<<16) | (buf[11]<<8) |buf[12];
req.prov = (buf[13]<<16) | (buf[14]<<8) | (buf[15]);
// Check Cache Request
if (!cache_check(&req)) break;
//
pcache = cache_fetch( &req );
if (pcache==NULL) pcache = cache_new( &req );
// Send Request if not sent
if (pcache->sendcache==CACHE_NONE_SENT) {
pcache->sendcache = CACHE_REQUEST_SENT;
cfg.cache.req++;
cache_send_request(pcache,NULL);
}
break;
case PIPE_CACHE_REPLY:
// Setup Cache Request
req.tag = buf[2];
req.sid = (buf[3]<<8) | buf[4];
req.onid = (buf[5]<<8) | buf[6];
req.caid = (buf[7]<<8) | buf[8];
req.hash = (buf[9]<<24) | (buf[10]<<16) | (buf[11]<<8) |buf[12];
req.prov = (buf[13]<<16) | (buf[14]<<8) | (buf[15]);
// Check Cache Request
if (!cache_check(&req)) break;
//
pcache = cache_fetch( &req );
if (pcache==NULL) pcache = cache_new( &req );
// Send Reply
if (pcache->sendcache!=CACHE_REPLY_SENT) {
//Set DCW
if (len==32) {
if (pcache->status!=CACHE_STAT_DCW) { // already sent
memcpy( pcache->cw, buf+16, 16); //dcw
pcache->status = CACHE_STAT_DCW;
pcache->peerid = 0; // from local
}
}
pcache->sendcache = CACHE_REPLY_SENT;
if (pcache->status==CACHE_STAT_DCW) cfg.cache.rep++;
cache_send_reply(pcache,NULL);
}
break;
}//switch
}//if
}
void cache_check_peers()
{
struct cachepeer_data *peer = cfg.cache.peer;
while (peer) {
if ( (peer->host->ip)&&(peer->port) ) {
uint ticks = GetTickCount();
if (peer->ping==0) { // inactive
if ( (!peer->lastpingsent)||((peer->lastpingsent+5000)<ticks) ) { // send every 15s
cache_send_ping(peer);
peer->lastpingsent = ticks;
peer->lastpingrecv = 0;
peer->ping = -1;
}
}
else if (peer->ping==-1) { // inactive
if ( (!peer->lastpingsent)||((peer->lastpingsent+10000)<ticks) ) { // send every 15s
cache_send_ping(peer);
peer->lastpingsent = ticks;
peer->lastpingrecv = 0;
peer->ping = -2;
}
}
else if (peer->ping==-2) { // inactive
if ( (!peer->lastpingsent)||((peer->lastpingsent+20000)<ticks) ) { // send every 15s
cache_send_ping(peer);
peer->lastpingsent = ticks;
peer->lastpingrecv = 0;
peer->ping = -3;
}
}
else if (peer->ping<=-3) { // inactive
if ( (!peer->lastpingsent)||((peer->lastpingsent+60000)<ticks) ) { // send every 15s
cache_send_ping(peer);
peer->lastpingsent = ticks;
peer->lastpingrecv = 0;
}
}
else if (peer->ping>0) {
if ( (!peer->lastpingrecv)&&((peer->lastpingsent+5000)<ticks) ) {
cache_send_ping(peer);
peer->lastpingsent = ticks;
peer->lastpingrecv = 0;
peer->ping = 0;
peer->host->checkiptime = 0; // maybe ip changed
}
else if ( (peer->lastpingsent+60000)<ticks ) { // send every 75s
#ifdef NEWCACHE
cache_send_keepalive(peer);
#else
cache_send_ping(peer);
#endif
peer->lastpingsent = ticks;
peer->lastpingrecv = 0;
}
}
}
peer = peer->next;
}
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
void *cache_thread(void *param)
{
prg.pid_cache = syscall(SYS_gettid);
prg.tid_cache = pthread_self();
uint32 chkticks = 0;
while(1) {
if (cfg.cache.handle>0) {
// Check Peers Ping
if ( GetTickCount()>(chkticks+3000) ) {
cache_check_peers();
chkticks = GetTickCount();
}
struct pollfd pfd;
pfd.fd = cfg.cache.handle;
pfd.events = POLLIN | POLLPRI;
int retval = poll(&pfd, 1, 3000);
if ( retval>0 ) {
if ( pfd.revents & (POLLIN|POLLPRI) ) {
pthread_mutex_lock( &prg.lockcache );
cache_recvmsg();
/*
do {
cache_recvmsg();
pfd.fd = cfg.cache.handle;
pfd.events = POLLIN | POLLPRI;
if ( poll(&pfd, 1, 0) <1 ) break;
} while (pfd.revents & (POLLIN|POLLPRI));
*/
pthread_mutex_unlock( &prg.lockcache );
}
}
} else usleep( 30000 );
}
close(cfg.cache.handle);
}
void *cachepipe_thread(void *param)
{
while(1) {
struct pollfd pfd;
pfd.fd = srvsocks[1];
pfd.events = POLLIN | POLLPRI;
int retval = poll(&pfd, 1, 3000);
if ( retval>0 ) {
if ( pfd.revents & (POLLIN|POLLPRI) ) {
pthread_mutex_lock( &prg.lockcache );
cache_pipe_recvmsg();
pthread_mutex_unlock( &prg.lockcache );
}
}
}
}
int start_thread_cache()
{
// Default outsock
outsock = CreateClientSockUdp();
create_prio_thread(&prg.tid_cache, (threadfn)cachepipe_thread,NULL, 50);
create_prio_thread(&prg.tid_cache, (threadfn)cache_thread,NULL, 50);
return 0;
}