diff options
Diffstat (limited to 'protocol.c')
-rw-r--r-- | protocol.c | 198 |
1 files changed, 137 insertions, 61 deletions
@@ -48,6 +48,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; + event -> data = peer -> eventData; return 1; @@ -56,7 +57,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) event -> type = ENET_EVENT_TYPE_DISCONNECT; event -> peer = peer; - event -> data = peer -> disconnectData; + event -> data = peer -> eventData; enet_peer_reset (peer); @@ -111,6 +112,7 @@ enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * even event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; + event -> data = peer -> eventData; } else enet_protocol_dispatch_state (host, peer, peer -> state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING); @@ -134,7 +136,11 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e enet_peer_reset (peer); } else + { + peer -> eventData = 0; + enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); + } } static void @@ -238,31 +244,13 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl static ENetPeer * enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENetProtocol * command) { - enet_uint16 mtu; - enet_uint32 windowSize; + enet_uint8 incomingSessionID, outgoingSessionID; + enet_uint32 mtu, windowSize; ENetChannel * channel; size_t channelCount; ENetPeer * currentPeer; ENetProtocol verifyCommand; - if (host -> checksum != NULL) - { - enet_uint32 checksum = header -> checksum; - ENetBuffer buffer; - - command -> header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (command -> header.reliableSequenceNumber); - - header -> checksum = command -> connect.sessionID; - - buffer.data = host -> receivedData; - buffer.dataLength = host -> receivedDataLength; - - if (host -> checksum (& buffer, 1) != checksum) - return NULL; - - command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber); - } - channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount); if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || @@ -276,7 +264,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED && currentPeer -> address.host == host -> receivedAddress.host && currentPeer -> address.port == host -> receivedAddress.port && - currentPeer -> sessionID == command -> connect.sessionID) + currentPeer -> connectID == command -> connect.connectID) return NULL; } @@ -298,7 +286,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet return NULL; currentPeer -> channelCount = channelCount; currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; - currentPeer -> sessionID = command -> connect.sessionID; + currentPeer -> connectID = command -> connect.connectID; currentPeer -> address = host -> receivedAddress; currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); @@ -306,6 +294,19 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval); currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration); currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration); + currentPeer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data); + + incomingSessionID = command -> connect.incomingSessionID == 0xFF ? currentPeer -> outgoingSessionID : command -> connect.incomingSessionID; + incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); + if (incomingSessionID == currentPeer -> outgoingSessionID) + incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); + currentPeer -> outgoingSessionID = incomingSessionID; + + outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? currentPeer -> incomingSessionID : command -> connect.outgoingSessionID; + outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); + if (outgoingSessionID == currentPeer -> incomingSessionID) + outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); + currentPeer -> incomingSessionID = outgoingSessionID; for (channel = currentPeer -> channels; channel < & currentPeer -> channels [channelCount]; @@ -322,7 +323,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows)); } - mtu = ENET_NET_TO_HOST_16 (command -> connect.mtu); + mtu = ENET_NET_TO_HOST_32 (command -> connect.mtu); if (mtu < ENET_PROTOCOL_MINIMUM_MTU) mtu = ENET_PROTOCOL_MINIMUM_MTU; @@ -370,6 +371,8 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; verifyCommand.header.channelID = 0xFF; verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); + verifyCommand.verifyConnect.incomingSessionID = incomingSessionID; + verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID; verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu); verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize); verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount); @@ -378,6 +381,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval); verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration); verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration); + verifyCommand.verifyConnect.connectID = currentPeer -> connectID; enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0); @@ -657,7 +661,9 @@ enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetPro else enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); - peer -> disconnectData = ENET_NET_TO_HOST_32 (command -> disconnect.data); + if (peer -> state != ENET_PEER_STATE_DISCONNECTED) + peer -> eventData = ENET_NET_TO_HOST_32 (command -> disconnect.data); + return 0; } @@ -737,7 +743,7 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * if (enet_list_empty (& peer -> outgoingReliableCommands) && enet_list_empty (& peer -> outgoingUnreliableCommands) && enet_list_empty (& peer -> sentReliableCommands)) - enet_peer_disconnect (peer, peer -> disconnectData); + enet_peer_disconnect (peer, peer -> eventData); break; } @@ -747,8 +753,7 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * static int enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command) { - enet_uint16 mtu; - enet_uint32 windowSize; + enet_uint32 mtu, windowSize; size_t channelCount; if (peer -> state != ENET_PEER_STATE_CONNECTING) @@ -759,8 +764,11 @@ enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPee if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT || ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval || ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleAcceleration) != peer -> packetThrottleAcceleration || - ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration) + ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration || + command -> verifyConnect.connectID != peer -> connectID) { + peer -> eventData = 0; + enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); return -1; @@ -772,8 +780,10 @@ enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPee peer -> channelCount = channelCount; peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID); + peer -> incomingSessionID = command -> verifyConnect.incomingSessionID; + peer -> outgoingSessionID = command -> verifyConnect.outgoingSessionID; - mtu = ENET_NET_TO_HOST_16 (command -> verifyConnect.mtu); + mtu = ENET_NET_TO_HOST_32 (command -> verifyConnect.mtu); if (mtu < ENET_PROTOCOL_MINIMUM_MTU) mtu = ENET_PROTOCOL_MINIMUM_MTU; @@ -811,15 +821,21 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) enet_uint8 * currentData; size_t headerSize; enet_uint16 peerID, flags; + enet_uint8 sessionID; - if (host -> receivedDataLength < sizeof (ENetProtocolHeader)) + if (host -> receivedDataLength < (size_t) & ((ENetProtocolHeader *) 0) -> sentTime) return 0; header = (ENetProtocolHeader *) host -> receivedData; peerID = ENET_NET_TO_HOST_16 (header -> peerID); + sessionID = (peerID & ENET_PROTOCOL_HEADER_SESSION_MASK) >> ENET_PROTOCOL_HEADER_SESSION_SHIFT; flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK; - peerID &= ~ ENET_PROTOCOL_HEADER_FLAG_MASK; + peerID &= ~ (ENET_PROTOCOL_HEADER_FLAG_MASK | ENET_PROTOCOL_HEADER_SESSION_MASK); + + headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof (ENetProtocolHeader) : (size_t) & ((ENetProtocolHeader *) 0) -> sentTime); + if (host -> checksum != NULL) + headerSize += sizeof (enet_uint32); if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID) peer = NULL; @@ -831,34 +847,55 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) peer = & host -> peers [peerID]; if (peer -> state == ENET_PEER_STATE_DISCONNECTED || - peer -> state == ENET_PEER_STATE_ZOMBIE || + peer -> state == ENET_PEER_STATE_ZOMBIE || (host -> receivedAddress.host != peer -> address.host && - peer -> address.host != ENET_HOST_BROADCAST)) + peer -> address.host != ENET_HOST_BROADCAST) || + (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID && + sessionID != peer -> incomingSessionID)) return 0; + } + + if (flags & ENET_PROTOCOL_HEADER_FLAG_COMPRESSED) + { + size_t originalSize; + if (host -> compressor.context == NULL || host -> compressor.decompress == NULL) + return 0; + + originalSize = host -> compressor.decompress (host -> compressor.context, + host -> receivedData + headerSize, + host -> receivedDataLength - headerSize, + host -> packetData [1] + headerSize, + sizeof (host -> packetData [1]) - headerSize); + if (originalSize <= 0 || originalSize > sizeof (host -> packetData [1]) - headerSize) + return 0; + + memcpy (host -> packetData [1], header, headerSize); + host -> receivedData = host -> packetData [1]; + host -> receivedDataLength = headerSize + originalSize; + } - if (host -> checksum != NULL) - { - enet_uint32 checksum = header -> checksum; - ENetBuffer buffer; - - header -> checksum = peer -> sessionID; + if (host -> checksum != NULL) + { + enet_uint32 * checksum = (enet_uint32 *) & host -> receivedData [headerSize - sizeof (enet_uint32)], + desiredChecksum = * checksum; + ENetBuffer buffer; - buffer.data = host -> receivedData; - buffer.dataLength = host -> receivedDataLength; + * checksum = peer != NULL ? peer -> connectID : 0; - if (host -> checksum (& buffer, 1) != checksum) - return 0; - } - else - if (header -> checksum != peer -> sessionID) - return 0; + buffer.data = host -> receivedData; + buffer.dataLength = host -> receivedDataLength; + if (host -> checksum (& buffer, 1) != desiredChecksum) + return 0; + } + + if (peer != NULL) + { peer -> address.host = host -> receivedAddress.host; peer -> address.port = host -> receivedAddress.port; peer -> incomingDataTotal += host -> receivedDataLength; } - headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof (ENetProtocolHeader) : (size_t) & ((ENetProtocolHeader *) 0) -> sentTime); currentData = host -> receivedData + headerSize; while (currentData < & host -> receivedData [host -> receivedDataLength]) @@ -991,8 +1028,8 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event) int receivedLength; ENetBuffer buffer; - buffer.data = host -> receivedData; - buffer.dataLength = sizeof (host -> receivedData); + buffer.data = host -> packetData [0]; + buffer.dataLength = sizeof (host -> packetData [0]); receivedLength = enet_socket_receive (host -> socket, & host -> receivedAddress, @@ -1005,6 +1042,7 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event) if (receivedLength == 0) return 0; + host -> receivedData = host -> packetData [0]; host -> receivedDataLength = receivedLength; host -> totalReceivedData += receivedLength; @@ -1158,7 +1196,7 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee enet_list_empty (& peer -> outgoingReliableCommands) && enet_list_empty (& peer -> outgoingUnreliableCommands) && enet_list_empty (& peer -> sentReliableCommands)) - enet_peer_disconnect (peer, peer -> disconnectData); + enet_peer_disconnect (peer, peer -> eventData); } static int @@ -1321,10 +1359,12 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) static int enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts) { - ENetProtocolHeader header; + enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)]; + ENetProtocolHeader * header = (ENetProtocolHeader *) headerData; ENetPeer * currentPeer; int sentLength; - + size_t shouldCompress = 0; + host -> continueSending = 1; while (host -> continueSending) @@ -1403,21 +1443,57 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch currentPeer -> packetsLost = 0; } - header.checksum = currentPeer -> sessionID; - header.peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags); - - host -> buffers -> data = & header; + host -> buffers -> data = headerData; if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME) { - header.sentTime = ENET_HOST_TO_NET_16 (host -> serviceTime & 0xFFFF); + header -> sentTime = ENET_HOST_TO_NET_16 (host -> serviceTime & 0xFFFF); host -> buffers -> dataLength = sizeof (ENetProtocolHeader); } else host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime; - + + shouldCompress = 0; + if (host -> compressor.context != NULL && host -> compressor.compress != NULL) + { + size_t originalSize = host -> packetSize - sizeof(ENetProtocolHeader), + compressedSize = host -> compressor.compress (host -> compressor.context, + & host -> buffers [1], host -> bufferCount - 1, + originalSize, + host -> packetData [1], + originalSize); + if (compressedSize > 0 && compressedSize < originalSize) + { + host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED; + shouldCompress = compressedSize; +#ifdef ENET_DEBUG_COMPRESS +#ifdef WIN32 + printf ( +#else + fprintf (stderr, +#endif + "peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize); +#endif + } + } + + if (currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID) + host -> headerFlags |= currentPeer -> outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT; + header -> peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags); if (host -> checksum != NULL) - header.checksum = host -> checksum (host -> buffers, host -> bufferCount); + { + enet_uint32 * checksum = (enet_uint32 *) & headerData [host -> buffers -> dataLength]; + * checksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0; + host -> buffers -> dataLength += sizeof (enet_uint32); + * checksum = host -> checksum (host -> buffers, host -> bufferCount); + } + + if (shouldCompress > 0) + { + host -> buffers [1].data = host -> packetData [1]; + host -> buffers [1].dataLength = shouldCompress; + host -> bufferCount = 2; + } currentPeer -> lastSendTime = host -> serviceTime; |