static int32_t cc_cacheex_push_chk(struct s_client *cl, struct ecm_request_t *er)
{
	struct cc_data *cc = cl->cc;
	if(chk_is_null_nodeid(cc->peer_node_id,8))
	{
		cs_log_dbg(D_CACHEEX, "cacheex: NO peer_node_id got yet, skip!");
		return 0;
	}

	if(ll_count(er->csp_lastnodes) >= cacheex_maxhop(cl))    //check max 10 nodes to push:
	{
		cs_log_dbg(D_CACHEEX, "cacheex: nodelist reached %d nodes, no push", cacheex_maxhop(cl));
		return 0;
	}

	uint8_t *remote_node = cc->peer_node_id;

	//search existing peer nodes:
	LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
	uint8_t *node;
	while((node = ll_li_next(li)))
	{
		cs_log_dbg(D_CACHEEX, "cacheex: check node %" PRIu64 "X == %" PRIu64 "X ?", cacheex_node_id(node), cacheex_node_id(remote_node));
		if(memcmp(node, remote_node, 8) == 0)
		{
			break;
		}
	}
	ll_li_destroy(li);

	//node found, so we got it from there, do not push:
	if(node)
	{
		cs_log_dbg(D_CACHEEX,
					  "cacheex: node %" PRIu64 "X found in list => skip push!", cacheex_node_id(node));
		return 0;
	}

	if(!cl->cc)
	{
		if(cl->reader && !cl->reader->tcp_connected)
		{
			cc_cli_connect(cl);
		}
	}

	if(!cc || !cl->udp_fd)
	{
		cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
		return 0;
	}

	//check if cw is already pushed
	if(check_is_pushed(er->cw_cache, cl))
		{ return 0; }

	return 1;
}
static int32_t camd35_cacheex_push_chk(struct s_client *cl, ECM_REQUEST *er)
{
	if(ll_count(er->csp_lastnodes) >= cacheex_maxhop(cl))    //check max 10 nodes to push:
	{
		cs_log_dbg(D_CACHEEX, "cacheex: nodelist reached %d nodes, no push", cacheex_maxhop(cl));
		return 0;
	}

	if(cl->reader)
	{
		if(!cl->reader->tcp_connected)
		{
			cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
			return 0;
		}
	}

	//if(chk_is_null_nodeid(remote_node,8)){
	if(!cl->ncd_skey[8])
	{
		cs_log_dbg(D_CACHEEX, "cacheex: NO peer_node_id got yet, skip!");
		return 0;
	}

	uint8_t *remote_node = cl->ncd_skey; //it is sended by reader(mode 2) or client (mode 3) each 30s using keepalive msgs

	//search existing peer nodes:
	LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
	uint8_t *node;
	while((node = ll_li_next(li)))
	{
		cs_log_dbg(D_CACHEEX, "cacheex: check node %" PRIu64 "X == %" PRIu64 "X ?", cacheex_node_id(node), cacheex_node_id(remote_node));
		if(memcmp(node, remote_node, 8) == 0)
		{
			break;
		}
	}
	ll_li_destroy(li);

	//node found, so we got it from there, do not push:
	if(node)
	{
		cs_log_dbg(D_CACHEEX,
					  "cacheex: node %" PRIu64 "X found in list => skip push!", cacheex_node_id(node));
		return 0;
	}

	//check if cw is already pushed
	if(check_is_pushed(er->cw_cache, cl))
		{ return 0; }

	cs_log_dbg(D_CACHEEX, "cacheex: push ok %" PRIu64 "X to %" PRIu64 "X %s", cacheex_node_id(camd35_node_id), cacheex_node_id(remote_node), username(cl));

	return 1;
}
/**
 * send own id
 */
void camd35_cacheex_push_send_own_id(struct s_client *cl, uint8_t *mbuf)
{
	uint8_t rbuf[32]; //minimal size
	if(!cl->crypted) { return; }
	cs_log_dbg(D_CACHEEX, "cacheex: received id request from node %" PRIu64 "X %s", cacheex_node_id(mbuf + 20), username(cl));
	memset(rbuf, 0, sizeof(rbuf));
	rbuf[0] = 0x3e;
	rbuf[1] = 12;
	rbuf[2] = 0;
	memcpy(rbuf + 20, camd35_node_id, 8);
	cs_log_dbg(D_CACHEEX, "cacheex: sending own id %" PRIu64 "X request %s", cacheex_node_id(camd35_node_id), username(cl));
	camd35_send(cl, rbuf, 12); //send adds +20
}
void cc_cacheex_push_in(struct s_client *cl, uchar *buf)
{
	struct cc_data *cc = cl->cc;
	ECM_REQUEST *er;
	if(!cc) { return; }

	if(cl->reader)
		{ cl->reader->last_s = cl->reader->last_g = time((time_t *)0); }
	if(cl) { cl->last = time(NULL); }

	int8_t rc = buf[14];
	if(rc != E_FOUND && rc != E_UNHANDLED)  //Maybe later we could support other rcs
		{ return; }
	uint16_t size = buf[12] | (buf[13] << 8);
	if(size != sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw))
	{
		cs_log_dbg(D_CACHEEX, "cacheex: %s received old cash-push format! data ignored!", username(cl));
		return;
	}
	if(!(er = get_ecmtask()))
		{ return; }

	er->caid = b2i(2, buf + 0);
	er->prid = b2i(4, buf + 2);
	er->srvid = b2i(2, buf + 10);
	er->ecm[0] = buf[19]!=0x80 && buf[19]!=0x81 ? 0 : buf[19]; //odd/even byte, usefull to send it over CSP and to check cw for swapping
	er->rc = rc;

	er->ecmlen = 0;

	if(buf[18])
	{
		if(buf[18] & (0x01 << 7))
		{
			er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime
			er->cwc_next_cw_cycle = 1;
		}
		else
		{
			er->cwc_cycletime = buf[18];
			er->cwc_next_cw_cycle = 0;
		}
	}

	if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
	{
		if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
			{ cl->account->cwc_info++; }
		else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
			{ cl->cwc_info++; }
		cs_log_dbg(D_CWC, "CWC (CE) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
	}

	uint8_t *ofs = buf + 20;

	//Read ecmd5
	memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); //16
	ofs += sizeof(er->ecmd5);

	if(!check_cacheex_filter(cl, er))
		{ return; }

	//Read csp_hash:
	er->csp_hash = ntohl(b2i(4, ofs));
	ofs += 4;

	//Read cw:
	memcpy(er->cw, ofs, sizeof(er->cw)); //16
	ofs += sizeof(er->cw);

	//Read lastnode count:
	uint8_t count = *ofs;
	ofs++;

	//check max nodes:
	if(count > cacheex_maxhop(cl))
	{
			cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", (int32_t)count, cacheex_maxhop(cl), username(cl));
		NULLFREE(er);
		return;
	}
	cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl));
	//Read lastnodes:
	uint8_t *data;
	if (er){
		er->csp_lastnodes = ll_create("csp_lastnodes");
	}
	while(count)
	{
		if(!cs_malloc(&data, 8))
			{ break; }
		memcpy(data, ofs, 8);
		ofs += 8;
		ll_append(er->csp_lastnodes, data);
		count--;
		cs_log_dbg(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl));
	}

	//for compatibility: add peer node if no node received:
	if(!ll_count(er->csp_lastnodes))
	{
		if(!cs_malloc(&data, 8))
			{ return; }
		memcpy(data, cc->peer_node_id, 8);
		ll_append(er->csp_lastnodes, data);
		cs_log_dbg(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data));
	}

	cacheex_add_to_cache(cl, er);
}
예제 #5
0
static void log_cacheex_cw(ECM_REQUEST *er, char *reason)
{
	uint8_t *data;
	uint8_t remotenodeid[8];
	data = ll_last_element(er->csp_lastnodes);
	if(data)
		{ memcpy(remotenodeid, data, 8); }
	else
		{ memset(remotenodeid, 0 , 8); }
	
	char buf_ecm[109];
	format_ecm(er, buf_ecm, 109);
	cs_log_dbg(D_CACHEEX,"got pushed ecm [%s]: %s - odd/even 0x%x - CSP cw: %s - pushed from %s, at hop %d, origin node-id %" PRIu64 "X",
			reason, buf_ecm, er->ecm[0], (checkECMD5(er)?"NO":"YES"), er->from_csp ? "csp" : username((er->cacheex_src?er->cacheex_src:er->client)), ll_count(er->csp_lastnodes), er->csp_lastnodes ? cacheex_node_id(remotenodeid): 0);
}
/**
 * store received remote id
 */
static void camd35_cacheex_push_receive_remote_id(struct s_client *cl, uint8_t *buf)
{

	memcpy(cl->ncd_skey, buf + 20, 8);
	cl->ncd_skey[8] = 1;
	cs_log_dbg(D_CACHEEX, "cacheex: received id answer from %s: %" PRIu64 "X", username(cl), cacheex_node_id(cl->ncd_skey));
}
static void camd35_cacheex_push_in(struct s_client *cl, uchar *buf)
{
	int8_t rc = buf[3];
	if(rc != E_FOUND && rc != E_UNHANDLED)  //Maybe later we could support other rcs
		{ return; }

	ECM_REQUEST *er;
	uint16_t size = buf[1] | (buf[2] << 8);
	if(size < sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw))
	{
		cs_log_dbg(D_CACHEEX, "cacheex: %s received old cash-push format! data ignored!", username(cl));
		return;
	}

	if(!(er = get_ecmtask()))
		{ return; }

	er->srvid = b2i(2, buf + 8);
	er->caid = b2i(2, buf + 10);
	er->prid = b2i(4, buf + 12);
	er->pid  = b2i(2, buf + 16);
	er->ecm[0] = buf[19]!=0x80 && buf[19]!=0x81 ? 0 : buf[19]; //odd/even byte, usefull to send it over CSP and to check cw for swapping
	er->rc = rc;

	er->ecmlen = 0;

	if(buf[18])
	{
		if(buf[18] & (0x01 << 7))
		{
			er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime
			er->cwc_next_cw_cycle = 1;
		}
		else
		{
			er->cwc_cycletime = buf[18];
			er->cwc_next_cw_cycle = 0;
		}
	}

	if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
	{
		if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
			{ cl->account->cwc_info++; }
		else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
			{ cl->cwc_info++; }
		cs_log_dbg(D_CWC, "CWC (CE) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
	}

	uint8_t *ofs = buf + 20;

	//Read ecmd5
	memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); //16
	ofs += sizeof(er->ecmd5);

	if(!check_cacheex_filter(cl, er))
		{ return; }

	//Read csp_hash:
	er->csp_hash = ntohl(b2i(4, ofs));
	ofs += 4;

	//Read cw:
	memcpy(er->cw, ofs, sizeof(er->cw)); //16
	ofs += sizeof(er->cw);

	//Check auf neues Format:
	uint8_t *data;
	if(size > (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)))
	{

		//Read lastnodes:
		uint8_t count = *ofs;
		ofs++;

		//check max nodes:
		if(count > cacheex_maxhop(cl))
		{
			cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", (int32_t)count, cacheex_maxhop(cl), username(cl));
			NULLFREE(er);
			return;
		}
		cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl));
		if (er){
			er->csp_lastnodes = ll_create("csp_lastnodes");
		}
		while(count)
		{
			if(!cs_malloc(&data, 8))
				{ break; }
			memcpy(data, ofs, 8);
			ofs += 8;
			ll_append(er->csp_lastnodes, data);
			count--;
			cs_log_dbg(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl));
		}
	}
	else
	{
		cs_log_dbg(D_CACHEEX, "cacheex: received old cachex from %s", username(cl));
		er->csp_lastnodes = ll_create("csp_lastnodes");
	}

	//store remote node id if we got one. The remote node is the first node in the node list
	data = ll_has_elements(er->csp_lastnodes);
	if(data && !cl->ncd_skey[8])    //Ok, this is tricky, we use newcamd key storage for saving the remote node
	{
		memcpy(cl->ncd_skey, data, 8);
		cl->ncd_skey[8] = 1; //Mark as valid node
	}
	cs_log_dbg(D_CACHEEX, "cacheex: received cacheex from remote node id %" PRIu64 "X", cacheex_node_id(cl->ncd_skey));

	//for compatibility: add peer node if no node received (not working now, maybe later):
	if(!ll_count(er->csp_lastnodes) && cl->ncd_skey[8])
	{
		if(!cs_malloc(&data, 8))
			{ return; }
		memcpy(data, cl->ncd_skey, 8);
		ll_append(er->csp_lastnodes, data);
		cs_log_dbg(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data));
	}

	cacheex_add_to_cache(cl, er);
}