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; }
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); } } }
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); } } }