Beispiel #1
0
bool DESC::Setup(LPFDWATCH _fdw, socket_t _fd, const struct sockaddr_in & c_rSockAddr, DWORD _handle, DWORD _handshake)
{
	m_lpFdw		= _fdw;
	m_sock		= _fd;

	m_stHost		= inet_ntoa(c_rSockAddr.sin_addr);
	m_wPort			= c_rSockAddr.sin_port;
	m_dwHandle		= _handle;

	//if (LC_IsEurope() == true || LC_IsNewCIBN())
	//	m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 2);
	//else
	//NOTE: 이걸 나라별로 다르게 잡아야할 이유가 있나?
	m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 2);

	m_iMinInputBufferLen = MAX_INPUT_LEN >> 1;
	m_lpInputBuffer = buffer_new(MAX_INPUT_LEN);

	m_SockAddr = c_rSockAddr;

	fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_READ, false);

	// Ping Event 
	desc_event_info* info = AllocEventInfo<desc_event_info>();

	info->desc = this;
	assert(m_pkPingEvent == NULL);

	m_pkPingEvent = event_create(ping_event, info, ping_event_second_cycle);

#ifndef _IMPROVED_PACKET_ENCRYPTION_
	if (LC_IsEurope())	
	{
		thecore_memcpy(m_adwEncryptionKey, "1234abcd5678efgh", sizeof(DWORD) * 4);
		thecore_memcpy(m_adwDecryptionKey, "1234abcd5678efgh", sizeof(DWORD) * 4);
	}
	else
	{
		thecore_memcpy(m_adwEncryptionKey, "testtesttesttest", sizeof(DWORD) * 4);
		thecore_memcpy(m_adwDecryptionKey, "testtesttesttest", sizeof(DWORD) * 4);
	}
#endif // _IMPROVED_PACKET_ENCRYPTION_

	// Set Phase to handshake
	SetPhase(PHASE_HANDSHAKE);
	StartHandshake(_handshake);

	sys_log(0, "SYSTEM: new connection from [%s] fd: %d handshake %u output input_len %d, ptr %p",
			m_stHost.c_str(), m_sock, m_dwHandshake, buffer_size(m_lpInputBuffer), this);

	Log("SYSTEM: new connection from [%s] fd: %d handshake %u ptr %p", m_stHost.c_str(), m_sock, m_dwHandshake, this);
	return true;
}
Beispiel #2
0
void Connection::ReceivePacketHandler(connectionPacket* inPacket)
{
	u8* data = inPacket->data;
	u16 dataLength = inPacket->dataLength;
	bool reliable = inPacket->reliable;

	//If it is a packet from the handshake, we keep it, otherwise, we forwared it to the node
	connPacketHeader* packetHeader = (connPacketHeader*) data;

	logt("CONN", "Received packet type %d, len %d", packetHeader->messageType, dataLength);

	/*#################### ROUTING ############################*/

	//We are the last receiver for this packet
	if(
			packetHeader->receiver == node->persistentConfig.nodeId //We are the receiver
			|| packetHeader->receiver == NODE_ID_HOPS_BASE + 1 //The packet was meant to travel only one hop
			|| (packetHeader->receiver == NODE_ID_SHORTEST_SINK && node->persistentConfig.deviceType == deviceTypes::DEVICE_TYPE_SINK) //Packet was meant for the shortest sink and we are a sink
	){

	}
	//The packet should continue to the shortest sink
	else if(packetHeader->receiver == NODE_ID_SHORTEST_SINK)
	{
		Connection* connection = connectionManager->GetConnectionToShortestSink(NULL);

		if(connection){
			connectionManager->SendMessage(connection, data, dataLength, reliable);
		}
		//We could send it as a broadcast or we just drop it if we do not know any sink
		else {

		}
	}
	//This could be either a packet to a specific node, group, with some hops left or a broadcast packet
	else
	{
		//Some packets need to be modified before relaying them

		//We increment the hops to sink so that each node knows how many hops the sink is away
		if(packetHeader->messageType == MESSAGE_TYPE_CLUSTER_INFO_UPDATE){
			//Increment hops to sink
			connPacketClusterInfoUpdate* packet = (connPacketClusterInfoUpdate*)packetHeader;
			if(packet->payload.hopsToSink > -1) packet->payload.hopsToSink++;
		}

		//If the packet should travel a number of hops, we decrement that part
		if(packetHeader->sender > NODE_ID_HOPS_BASE && packetHeader->sender < NODE_ID_HOPS_BASE + 31000){
			packetHeader->sender--;
		}

		//Send to all other connections
		connectionManager->SendMessageOverConnections(this, data, dataLength, reliable);
	}




	/*#################### HANDSHAKE ############################*/

	/******* Cluster welcome *******/
	if (packetHeader->messageType == MESSAGE_TYPE_CLUSTER_WELCOME)
	{
		if (dataLength == SIZEOF_CONN_PACKET_CLUSTER_WELCOME)
		{
			//Now, compare that packet with our data and see if he should join our cluster
			connPacketClusterWelcome* packet = (connPacketClusterWelcome*) data;
			//FIXME: My own cluster size might have changed since I sent my packet, that means,
			//Thatthe other node might decide on different data than I do, which might mean
			//That both think that they are the bigger cluster

			//Save mesh write handle
			writeCharacteristicHandle = packet->payload.meshWriteHandle;


			logt("HANDSHAKE", "############ Handshake starting ###############");


			logt("HANDSHAKE", "IN <= %d CLUSTER_WELCOME clustID:%d, clustSize:%d, toSink:%d", packet->header.sender, packet->payload.clusterId, packet->payload.clusterSize, packet->payload.hopsToSink);

			//PART 1: We do have the same cluster ID. Ouuups, should not have happened, run Forest!
			if (packet->payload.clusterId == node->clusterId)
			{
				logt("HANDSHAKE", "CONN %d disconnected because it had the same clusterID before handshake", connectionId);
				this->Disconnect();
			}
			//PART 2: This is more probable, he's in a different cluster
			else if (packet->payload.clusterSize < node->clusterSize || (packet->payload.clusterSize == node->clusterSize && packet->payload.clusterId < node->clusterId))
			{
				//I am the bigger cluster
				logt("HANDSHAKE", "I am bigger");

				if(direction == CONNECTION_DIRECTION_IN) StartHandshake();

			}
			else
			{

				//I am the smaller cluster
				logt("HANDSHAKE", "I am smaller");

				//Kill other Connections
				connectionManager->DisconnectOtherConnections(this);

				//Update my own information on the connection
				//this->connectedClusterId = packet->payload.clusterId;
				//this->connectedClusterSize += packet->payload.clusterSize;
				this->partnerId = packet->header.sender;
				this->hopsToSink = packet->payload.hopsToSink < 0 ? -1 : packet->payload.hopsToSink + 1;

				logt("HANDSHAKE", "ClusterSize Change from %d to %d", node->clusterSize, this->connectedClusterSize + 1);

				//node->clusterId = this->connectedClusterId;
				//node->clusterSize += this->connectedClusterSize + 1;
				//this->handshakeDone = true;


				//Send an update to the connected cluster to increase the size by one
				//This is also the ACK message for our connecting node
				connPacketClusterAck1 packet;

				packet.header.messageType = MESSAGE_TYPE_CLUSTER_ACK_1;
				packet.header.sender = node->persistentConfig.nodeId;
				packet.header.receiver = this->partnerId;

				packet.payload.hopsToSink = connectionManager->GetHopsToShortestSink(this);
				packet.payload.reserved = 0;

				logt("HANDSHAKE", "OUT => %d CLUSTER_ACK_1, hops:%d", packet.header.receiver, packet.payload.hopsToSink);

				connectionManager->SendMessage(this, (u8*) &packet, SIZEOF_CONN_PACKET_CLUSTER_ACK_1, true);

				//Update advertisement packets
				//node->UpdateJoinMePacket(NULL);



			}
		}
		else
		{
			logt("CONN", "wrong size for CLUSTER_WELCOME");
		}
		/******* Cluster ack 1 (another node confirms that it is joining our cluster) *******/
	}
	else if (packetHeader->messageType == MESSAGE_TYPE_CLUSTER_ACK_1)
	{
		if (dataLength == SIZEOF_CONN_PACKET_CLUSTER_ACK_1)
		{

			connPacketClusterAck1* packet = (connPacketClusterAck1*) data;

			logt("HANDSHAKE", "IN <= %d  CLUSTER_ACK_1, hops:%d", packet->header.sender, packet->payload.hopsToSink);

			//Update node data
			node->clusterSize += 1;
			this->hopsToSink = packet->payload.hopsToSink < 0 ? -1 : packet->payload.hopsToSink + 1;


			logt("HANDSHAKE", "ClusterSize Change from %d to %d", node->clusterSize-1, node->clusterSize);

			//Update connection data
			this->connectedClusterId = node->clusterId;
			this->partnerId = packet->header.sender;
			this->connectedClusterSize += 1;
			this->handshakeDone = true;

			//Broadcast cluster update to other connections
			connPacketClusterInfoUpdate outPacket;
			outPacket.header.messageType = MESSAGE_TYPE_CLUSTER_INFO_UPDATE;
			outPacket.header.sender = node->persistentConfig.nodeId;
			outPacket.header.receiver = 0;

			outPacket.payload.clusterSizeChange = 1;
			outPacket.payload.currentClusterId = node->clusterId;
			outPacket.payload.newClusterId = 0;


			logt("HANDSHAKE", "OUT => ALL MESSAGE_TYPE_CLUSTER_INFO_UPDATE clustChange:1");

			//Send message to all other connections and update the hops to sink accordingly
			for(int i=0; i<Config->meshMaxConnections; i++){
				if(connectionManager->connections[i] == this || !connectionManager->connections[i]->handshakeDone) continue;
				outPacket.payload.hopsToSink = connectionManager->GetHopsToShortestSink(connectionManager->connections[i]);
				connectionManager->SendMessage(connectionManager->connections[i], (u8*) &outPacket, SIZEOF_CONN_PACKET_CLUSTER_INFO_UPDATE, true);
			}

			//Confirm to the new node that it just joined our cluster => send ACK2
			connPacketClusterAck2 outPacket2;
			outPacket2.header.messageType = MESSAGE_TYPE_CLUSTER_ACK_2;
			outPacket2.header.sender = node->persistentConfig.nodeId;
			outPacket2.header.receiver = this->partnerId;

			outPacket2.payload.clusterId = node->clusterId;
			outPacket2.payload.clusterSize = node->clusterSize;


			logt("HANDSHAKE", "OUT => %d CLUSTER_ACK_2 clustId:%d, clustSize:%d", this->partnerId, node->clusterId, node->clusterSize);

			connectionManager->SendMessage(this, (u8*) &outPacket2, SIZEOF_CONN_PACKET_CLUSTER_ACK_2, true);

			//Update our advertisement packet
			node->UpdateJoinMePacket(NULL);


			logt("HANDSHAKE", "############ Handshake done ###############");

			//Notify Node of handshakeDone
			node->HandshakeDoneHandler(this);

		}
		else
		{
			logt("CONN", "wrong size for ACK1");
		}

		/******* Cluster ack 2 *******/
	}
	else if (packetHeader->messageType == MESSAGE_TYPE_CLUSTER_ACK_2)
	{
		if (dataLength == SIZEOF_CONN_PACKET_CLUSTER_ACK_2)
		{

			connPacketClusterAck2* packet = (connPacketClusterAck2*) data;

			logt("HANDSHAKE", "IN <= %d CLUSTER_ACK_2 clusterID:%d, clusterSize:%d", packet->header.sender, packet->payload.clusterId, packet->payload.clusterSize);

			logt("HANDSHAKE", "ClusterSize Change from %d to %d", node->clusterSize, packet->payload.clusterSize);

			this->connectedClusterId = packet->payload.clusterId;
			this->connectedClusterSize += packet->payload.clusterSize - 1; // minus myself

			node->clusterId = packet->payload.clusterId;
			node->clusterSize += packet->payload.clusterSize - 1; // minus myself


			this->handshakeDone = true;

			//Update our advertisement packet
			node->UpdateJoinMePacket(NULL);


			logt("HANDSHAKE", "############ Handshake done ###############");

			//Notify Node of handshakeDone
			node->HandshakeDoneHandler(this);

		}
		else
		{
			logt("CONN", "wrong size for ACK2");
		}

	}


	/*#################### MESSAGE PROCESSING ############################*/
	else
	{
		//Check wether we should care for this packet
		if(
				packetHeader->receiver == node->persistentConfig.nodeId //Directly addressed at us
				|| packetHeader->receiver == NODE_ID_BROADCAST //broadcast packet for all nodes
				|| (packetHeader->receiver >= NODE_ID_HOPS_BASE && packetHeader->receiver < NODE_ID_HOPS_BASE + 1000) //Broadcasted for a number of hops
				|| (packetHeader->receiver == NODE_ID_SHORTEST_SINK && node->persistentConfig.deviceType == deviceTypes::DEVICE_TYPE_SINK)
		){
			//Forward that Packet to the Node
			connectionManager->connectionManagerCallback->messageReceivedCallback(inPacket);
		}
	}

}
Beispiel #3
0
void Connection::ReceivePacketHandler(connectionPacket* inPacket)
{
	if(connectionState == ConnectionState::DISCONNECTED) return;

	u8* data = inPacket->data;
	u16 dataLength = inPacket->dataLength;
	bool reliable = inPacket->reliable;

	//If it is a packet from the handshake, we keep it, otherwise, we forwared it to the node
	connPacketHeader* packetHeader = (connPacketHeader*) data;

	logt("CONN", "Received packet type %d, len %d", packetHeader->messageType, dataLength);

	/*#################### ROUTING ############################*/

	//We are the last receiver for this packet
	if(
			packetHeader->receiver == node->persistentConfig.nodeId //We are the receiver
			|| packetHeader->receiver == NODE_ID_HOPS_BASE + 1 //The packet was meant to travel only one hop
			|| (packetHeader->receiver == NODE_ID_SHORTEST_SINK && node->persistentConfig.deviceType == deviceTypes::DEVICE_TYPE_SINK) //Packet was meant for the shortest sink and we are a sink
	){
		//No packet forwarding needed here.
	}
	//The packet should continue to the shortest sink
	else if(packetHeader->receiver == NODE_ID_SHORTEST_SINK)
	{
		Connection* connection = cm->GetConnectionToShortestSink(NULL);

		if(connection){
			cm->SendMessage(connection, data, dataLength, reliable);
		}
		//We could send it as a broadcast or we just drop it if we do not know any sink
		else {

		}
	}
	//This could be either a packet to a specific node, group, with some hops left or a broadcast packet
	else
	{
		//Some packets need to be modified before relaying them

		//If the packet should travel a number of hops, we decrement that part
		if(packetHeader->sender > NODE_ID_HOPS_BASE && packetHeader->sender < NODE_ID_HOPS_BASE + 31000){
			packetHeader->sender--;
		}

		//Send to all other connections
		if(packetHeader->messageType != MESSAGE_TYPE_CLUSTER_INFO_UPDATE){
			//Do not forward cluster info update packets, these are handeled by the node
			cm->SendMessageOverConnections(this, data, dataLength, reliable);
		}
	}




	/*#################### HANDSHAKE ############################*/

	/******* Cluster welcome *******/
	if (packetHeader->messageType == MESSAGE_TYPE_CLUSTER_WELCOME)
	{
		if (dataLength == SIZEOF_CONN_PACKET_CLUSTER_WELCOME)
		{
			//Now, compare that packet with our data and see if he should join our cluster
			connPacketClusterWelcome* packet = (connPacketClusterWelcome*) data;

			//Save mesh write handle
			writeCharacteristicHandle = packet->payload.meshWriteHandle;

			connectionState = ConnectionState::HANDSHAKING;

			logt("HANDSHAKE", "############ Handshake starting ###############");


			logt("HANDSHAKE", "IN <= %d CLUSTER_WELCOME clustID:%x, clustSize:%d, toSink:%d", packet->header.sender, packet->payload.clusterId, packet->payload.clusterSize, packet->payload.hopsToSink);

			//PART 1: We do have the same cluster ID. Ouuups, should not have happened, run Forest!
			if (packet->payload.clusterId == clusterIDBackup)
			{
				logt("HANDSHAKE", "CONN %u disconnected because it had the same clusterId before handshake", connectionId);
				this->Disconnect();
			}
			//PART 2: This is more probable, he's in a different cluster
			else if (packet->payload.clusterSize < clusterSizeBackup || (packet->payload.clusterSize == clusterSizeBackup && packet->payload.clusterId < clusterIDBackup))
			{
				//I am the bigger cluster
				logt("HANDSHAKE", "I am bigger");

				if(direction == CONNECTION_DIRECTION_IN){
					StartHandshake();
					return;
				}

			}
			else
			{

				//I am the smaller cluster
				logt("HANDSHAKE", "I am smaller");

				//Kill other Connections
				//FIXME: what does the disconnect function do? it should just clear these connections!!!
				cm->ForceDisconnectOtherConnections(this);

				//Because we forcefully killed our connections, we are back at square 1
				//These values will be overwritten by the ACK2 packet that we receive from out partner
				//But if we do never receive an ACK2, this is our new starting point
				node->clusterSize = 1;
				node->clusterId = node->GenerateClusterID();

				//Update my own information on the connection
				this->partnerId = packet->header.sender;

				//Send an update to the connected cluster to increase the size by one
				//This is also the ACK message for our connecting node
				connPacketClusterAck1 packet;

				packet.header.messageType = MESSAGE_TYPE_CLUSTER_ACK_1;
				packet.header.sender = node->persistentConfig.nodeId;
				packet.header.receiver = this->partnerId;

				packet.payload.hopsToSink = -1;

				logt("HANDSHAKE", "OUT => %d CLUSTER_ACK_1, hops:%d", packet.header.receiver, packet.payload.hopsToSink);

				cm->SendHandshakeMessage(this, (u8*) &packet, SIZEOF_CONN_PACKET_CLUSTER_ACK_1, true);

			}
		}
		else
		{
			logt("CONN", "wrong size for CLUSTER_WELCOME");
		}
		/******* Cluster ack 1 (another node confirms that it is joining our cluster, we are bigger) *******/
	}
	else if (packetHeader->messageType == MESSAGE_TYPE_CLUSTER_ACK_1)
	{
		if (dataLength == SIZEOF_CONN_PACKET_CLUSTER_ACK_1)
		{
			//Check if the other node does weird stuff
			if(clusterAck1Packet.header.messageType != 0 || node->currentDiscoveryState != discoveryState::HANDSHAKE){
				//TODO: disconnect
				logt("ERROR", "HANDSHAKE ERROR ACI1 duplicate");
			}

			//Save ACK1 packet for later
			memcpy(&clusterAck1Packet, data, sizeof(connPacketClusterAck1));

			logt("HANDSHAKE", "IN <= %d  CLUSTER_ACK_1, hops:%d", clusterAck1Packet.header.sender, clusterAck1Packet.payload.hopsToSink);


			//Set the master bit for the connection. If the connection would disconnect
			//Then we could keep intact and the other one must dissolve
			this->partnerId = clusterAck1Packet.header.sender;
			this->connectionMasterBit = 1;

			//Confirm to the new node that it just joined our cluster => send ACK2
			connPacketClusterAck2 outPacket2;
			outPacket2.header.messageType = MESSAGE_TYPE_CLUSTER_ACK_2;
			outPacket2.header.sender = node->persistentConfig.nodeId;
			outPacket2.header.receiver = this->partnerId;

			outPacket2.payload.clusterId = clusterIDBackup;
			outPacket2.payload.clusterSize = clusterSizeBackup + 1; // add +1 for the new node itself
			outPacket2.payload.hopsToSink = hopsToSinkBackup;


			logt("HANDSHAKE", "OUT => %d CLUSTER_ACK_2 clustId:%x, clustSize:%d", this->partnerId, outPacket2.payload.clusterId, outPacket2.payload.clusterSize);

			cm->SendHandshakeMessage(this, (u8*) &outPacket2, SIZEOF_CONN_PACKET_CLUSTER_ACK_2, true);

			//Handshake done connection state ist set in fillTransmitbuffers when the packet is queued


		}
		else
		{
			logt("CONN", "wrong size for ACK1");
		}

		/******* Cluster ack 2 *******/
	}
	else if (packetHeader->messageType == MESSAGE_TYPE_CLUSTER_ACK_2)
	{
		if (dataLength == SIZEOF_CONN_PACKET_CLUSTER_ACK_2)
		{
			if(clusterAck2Packet.header.messageType != 0 || node->currentDiscoveryState != discoveryState::HANDSHAKE){
				//TODO: disconnect
				logt("ERROR", "HANDSHAKE ERROR ACK2 duplicate");
			}

			//Save Ack2 packet for later
			memcpy(&clusterAck2Packet, data, sizeof(connPacketClusterAck2));

			logt("HANDSHAKE", "IN <= %d CLUSTER_ACK_2 clusterID:%x, clusterSize:%d", clusterAck2Packet.header.sender, clusterAck2Packet.payload.clusterId, clusterAck2Packet.payload.clusterSize);

			//Notify Node of handshakeDone
			node->HandshakeDoneHandler(this, false);


		}
		else
		{
			logt("CONN", "wrong size for ACK2");
		}

	}


	/*#################### MESSAGE PROCESSING ############################*/
	else
	{
		//Check wether we should care for this packet
		if(
				packetHeader->receiver == node->persistentConfig.nodeId //Directly addressed at us
				|| packetHeader->receiver == NODE_ID_BROADCAST //broadcast packet for all nodes
				|| (packetHeader->receiver >= NODE_ID_HOPS_BASE && packetHeader->receiver < NODE_ID_HOPS_BASE + 1000) //Broadcasted for a number of hops
				|| (packetHeader->receiver == NODE_ID_SHORTEST_SINK && node->persistentConfig.deviceType == deviceTypes::DEVICE_TYPE_SINK)
		){
			//Forward that Packet to the Node
			cm->connectionManagerCallback->messageReceivedCallback(inPacket);
		}
	}

}