From 87833f0191771e1dca9d898931ba00468297e596 Mon Sep 17 00:00:00 2001 From: Lee Salzman Date: Sat, 18 Feb 2012 11:35:27 +0000 Subject: [PATCH] enet updates git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@6761 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/enet/include/enet/enet.h | 4 +++- source/enet/include/enet/protocol.h | 4 +++- source/enet/packet.c | 6 ++++- source/enet/peer.c | 13 ++++++---- source/enet/protocol.c | 36 +++++++++++++++++++--------- source/enet/unix.c | 8 +++++++ source/enet/win32.c | 8 +++++++ source/lib/enet.lib | Bin 46372 -> 46528 bytes 8 files changed, 61 insertions(+), 18 deletions(-) diff --git a/source/enet/include/enet/enet.h b/source/enet/include/enet/enet.h index d73655f8..14f93820 100755 --- a/source/enet/include/enet/enet.h +++ b/source/enet/include/enet/enet.h @@ -50,7 +50,9 @@ typedef enum _ENetSocketOption ENET_SOCKOPT_BROADCAST = 2, ENET_SOCKOPT_RCVBUF = 3, ENET_SOCKOPT_SNDBUF = 4, - ENET_SOCKOPT_REUSEADDR = 5 + ENET_SOCKOPT_REUSEADDR = 5, + ENET_SOCKOPT_RCVTIMEO = 6, + ENET_SOCKOPT_SNDTIMEO = 7 } ENetSocketOption; enum diff --git a/source/enet/include/enet/protocol.h b/source/enet/include/enet/protocol.h index faef9179..f8a27d8e 100755 --- a/source/enet/include/enet/protocol.h +++ b/source/enet/include/enet/protocol.h @@ -16,7 +16,9 @@ enum ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 32768, ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, - ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF + ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF, + ENET_PROTOCOL_MAXIMUM_PACKET_SIZE = 1024 * 1024 * 1024, + ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024 }; typedef enum _ENetProtocolCommand diff --git a/source/enet/packet.c b/source/enet/packet.c index 2fc9a10e..fd59b14c 100755 --- a/source/enet/packet.c +++ b/source/enet/packet.c @@ -26,6 +26,9 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) packet -> data = (enet_uint8 *) data; else + if (dataLength <= 0) + packet -> data = NULL; + else { packet -> data = (enet_uint8 *) enet_malloc (dataLength); if (packet -> data == NULL) @@ -54,7 +57,8 @@ enet_packet_destroy (ENetPacket * packet) { if (packet -> freeCallback != NULL) (* packet -> freeCallback) (packet); - if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) + if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) && + packet -> data != NULL) enet_free (packet -> data); enet_free (packet); } diff --git a/source/enet/peer.c b/source/enet/peer.c index 44b0bc5a..38839b14 100755 --- a/source/enet/peer.c +++ b/source/enet/peer.c @@ -104,7 +104,8 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) size_t fragmentLength; if (peer -> state != ENET_PEER_STATE_CONNECTED || - channelID >= peer -> channelCount) + channelID >= peer -> channelCount || + packet -> dataLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE) return -1; fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment); @@ -113,7 +114,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) if (packet -> dataLength > fragmentLength) { - enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength), + enet_uint32 fragmentCount = (packet -> dataLength + fragmentLength - 1) / fragmentLength, fragmentNumber, fragmentOffset; enet_uint8 commandNumber; @@ -121,6 +122,9 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) ENetList fragments; ENetOutgoingCommand * fragment; + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) + return -1; + if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && channel -> outgoingUnreliableSequenceNumber < 0xFFFF) { @@ -164,7 +168,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) fragment -> command.header.channelID = channelID; fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber; fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength); - fragment -> command.sendFragment.fragmentCount = fragmentCount; + fragment -> command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32 (fragmentCount); fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber); fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength); fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset); @@ -832,7 +836,8 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (fragmentCount > 0) { - incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); + if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) + incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); if (incomingCommand -> fragments == NULL) { enet_free (incomingCommand); diff --git a/source/enet/protocol.c b/source/enet/protocol.c index 2e111a89..6d4618c7 100755 --- a/source/enet/protocol.c +++ b/source/enet/protocol.c @@ -406,7 +406,9 @@ enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENet dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), @@ -432,7 +434,9 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup); @@ -480,7 +484,9 @@ enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const EN dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), @@ -513,7 +519,9 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); * currentData += fragmentLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (fragmentLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; channel = & peer -> channels [command -> header.channelID]; @@ -532,9 +540,11 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset); totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength); - if (fragmentOffset >= totalLength || - fragmentOffset + fragmentLength > totalLength || - fragmentNumber >= fragmentCount) + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset) return -1; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); @@ -622,7 +632,9 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); * currentData += fragmentLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (fragmentLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; channel = & peer -> channels [command -> header.channelID]; @@ -647,9 +659,11 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset); totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength); - if (fragmentOffset >= totalLength || - fragmentOffset + fragmentLength > totalLength || - fragmentNumber >= fragmentCount) + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset) return -1; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); diff --git a/source/enet/unix.c b/source/enet/unix.c index 69715413..a225b57d 100755 --- a/source/enet/unix.c +++ b/source/enet/unix.c @@ -219,6 +219,14 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_SNDTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); + break; + default: break; } diff --git a/source/enet/win32.c b/source/enet/win32.c index 7b23cddc..0a213e7a 100755 --- a/source/enet/win32.c +++ b/source/enet/win32.c @@ -166,6 +166,14 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_SNDTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); + break; + default: break; } diff --git a/source/lib/enet.lib b/source/lib/enet.lib index 22d8c5b908c804c8a241da20b09c4938fc01224d..fd25efc86e354e83186cf0e25a4888084d20677f 100644 GIT binary patch delta 10071 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 delta 9906 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 DiOYw1