/** Creates a host for communicating to peers. @param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host. @param peerCount the maximum number of peers that should be allocated for the host. @param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth. @param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth. @returns the host on success and NULL on failure @remarks ENet will strategically drop packets on specific sides of a connection between hosts to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. */ ENetHost * enet_host_create (const ENetAddress * address, size_t peerCount, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) { ENetHost * host = (ENetHost *) enet_malloc (sizeof (ENetHost)); ENetPeer * currentPeer; if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID) return NULL; host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer)); memset (host -> peers, 0, peerCount * sizeof (ENetPeer)); host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM, address); if (host -> socket == ENET_SOCKET_NULL) { enet_free (host -> peers); enet_free (host); return NULL; } if (address != NULL) host -> address = * address; host -> incomingBandwidth = incomingBandwidth; host -> outgoingBandwidth = outgoingBandwidth; host -> bandwidthThrottleEpoch = 0; host -> recalculateBandwidthLimits = 0; host -> mtu = ENET_HOST_DEFAULT_MTU; host -> peerCount = peerCount; host -> lastServicedPeer = host -> peers; host -> commandCount = 0; host -> bufferCount = 0; host -> receivedAddress.host = ENET_HOST_ANY; host -> receivedAddress.port = 0; host -> receivedDataLength = 0; for (currentPeer = host -> peers; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { currentPeer -> host = host; currentPeer -> incomingPeerID = currentPeer - host -> peers; currentPeer -> data = NULL; enet_list_clear (& currentPeer -> acknowledgements); enet_list_clear (& currentPeer -> sentReliableCommands); enet_list_clear (& currentPeer -> sentUnreliableCommands); enet_list_clear (& currentPeer -> outgoingReliableCommands); enet_list_clear (& currentPeer -> outgoingUnreliableCommands); enet_peer_reset (currentPeer); } return host; }
/** Creates a packet that may be sent to a peer. @param dataContents initial contents of the packet's data; the packet's data will remain uninitialized if dataContents is NULL. @param dataLength size of the data allocated for this packet @param flags flags for this packet as described for the ENetPacket structure. @returns the packet on success, NULL on failure */ ENetPacket * enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) { ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket)); packet -> data = (enet_uint8 *) enet_malloc (dataLength); if (data != NULL) memcpy (packet -> data, data, dataLength); packet -> referenceCount = 0; packet -> flags = flags; packet -> dataLength = dataLength; return packet; }
ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime) { ENetAcknowledgement * acknowledgement; if (command -> header.channelID < peer -> channelCount) { ENetChannel * channel = & peer -> channels [command -> header.channelID]; enet_uint16 reliableWindow = command -> header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE, currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber) reliableWindow += ENET_PEER_RELIABLE_WINDOWS; if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS) return NULL; } acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement)); if (acknowledgement == NULL) return NULL; peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge); acknowledgement -> sentTime = sentTime; acknowledgement -> command = * command; enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement); return acknowledgement; }
ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length) { ENetChannel * channel = & peer -> channels [command -> header.channelID]; ENetOutgoingCommand * outgoingCommand; peer -> outgoingDataTotal += command -> header.commandLength + length; outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand)); if (command -> header.channelID == 0xFF) { ++ peer -> outgoingReliableSequenceNumber; outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = 0; } else if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE) { ++ channel -> outgoingReliableSequenceNumber; outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = 0; } else if (command -> header.flags & ENET_PROTOCOL_FLAG_UNSEQUENCED) { ++ peer -> outgoingUnsequencedGroup; outgoingCommand -> reliableSequenceNumber = 0; outgoingCommand -> unreliableSequenceNumber = 0; } else { ++ channel -> outgoingUnreliableSequenceNumber; outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber; } outgoingCommand -> sentTime = 0; outgoingCommand -> roundTripTimeout = 0; outgoingCommand -> roundTripTimeoutLimit = 0; outgoingCommand -> fragmentOffset = offset; outgoingCommand -> fragmentLength = length; outgoingCommand -> packet = packet; outgoingCommand -> command = * command; outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_32 (outgoingCommand -> reliableSequenceNumber); if (packet != NULL) ++ packet -> referenceCount; if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE) enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand); else enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand); return outgoingCommand; }
void * enet_range_coder_create (void) { ENetRangeCoder * rangeCoder = (ENetRangeCoder *) enet_malloc (sizeof (ENetRangeCoder)); if (rangeCoder == NULL) return NULL; return rangeCoder; }
/** Returns the ENetPeer that generated an event, with the Event allocated pointer in Peer->data. The returned ENetPeer must not be destroyed, since it's a copy of an existing peer pointer. Timeout is float number of seconds (0.001 == 1 ms) **/ static value udpr_poll(value h, value timeout) { //ENetPeerHandle hndPeer = enet_host_peer_to_handle(host, event->peer); ENetEvent *event; int res; if( !val_is_abstract(h) || !val_is_kind(h,k_udprhost) ) neko_error(); val_check(timeout,number); enet_uint32 tout = (enet_uint32)(val_number(timeout)*1000); event = (ENetEvent *) enet_malloc (sizeof (ENetEvent)); // Wait up to timeout milliseconds for an event. res = enet_host_service ((ENetHost *)val_data(h), event, tout); if(res <= 0) { if(res == 0) return val_null; neko_error(); } switch (event->type) { case ENET_EVENT_TYPE_NONE: //if(event->peer != NULL) //free_peer_event(event->peer); enet_free(event); return val_null; break; default: // auto frees any existing unhandled event, add this event. #ifdef ENET_DEBUG_FULL if(event->type == ENET_EVENT_TYPE_RECEIVE) fprintf(stderr, "udpr_poll: event type %s %0.*s\n", event_to_string(event->type), event->packet->dataLength, event->packet->data); else fprintf(stderr, "udpr_poll: event type %s\n", event_to_string(event->type)); #endif break; } value v = alloc_abstract(k_udprevent,event); val_gc(v, destroy_enetevent); return v; #ifdef ENET_DEBUG //fprintf(stderr, "udpr_poll: returning peer %x\n", event->peer); #endif //value v = alloc_abstract(k_udprpeer, event->peer); //return v; }
ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint32 sentTime) { ENetAcknowledgement * acknowledgement; peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge); acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement)); acknowledgement -> sentTime = sentTime; acknowledgement -> command = * command; enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement); return acknowledgement; }
ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length) { ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand)); if (outgoingCommand == NULL) return NULL; outgoingCommand -> command = * command; outgoingCommand -> fragmentOffset = offset; outgoingCommand -> fragmentLength = length; outgoingCommand -> packet = packet; if (packet != NULL) ++ packet -> referenceCount; enet_peer_setup_outgoing_command (peer, outgoingCommand); return outgoingCommand; }
/** Attempts to resize the data in the packet to length specified in the dataLength parameter @param packet packet to resize @param dataLength new size for the packet data @returns 0 on success, < 0 on failure */ int enet_packet_resize (ENetPacket * packet, size_t dataLength) { enet_uint8 * newData; if (dataLength <= packet -> dataLength) { packet -> dataLength = dataLength; return 0; } newData = (enet_uint8 *) enet_malloc (dataLength); memcpy (newData, packet -> data, packet -> dataLength); enet_free (packet -> data); packet -> data = newData; packet -> dataLength = dataLength; return 0; }
/** Initiates a connection to a foreign host. @param host host seeking the connection @param address destination for the connection @param channelCount number of channels to allocate @returns a peer representing the foreign host on success, NULL on failure @remarks The peer returned will have not completed the connection until enet_host_service() notifies of an ENET_EVENT_TYPE_CONNECT event for the peer. */ ENetPeer * enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount) { ENetPeer * currentPeer; ENetChannel * channel; ENetProtocol command; if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; else if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; for (currentPeer = host -> peers; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED) break; } if (currentPeer >= & host -> peers [host -> peerCount]) return NULL; currentPeer -> state = ENET_PEER_STATE_CONNECTING; currentPeer -> address = * address; currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); currentPeer -> channelCount = channelCount; currentPeer -> challenge = (enet_uint32) rand (); if (host -> outgoingBandwidth == 0) currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else currentPeer -> windowSize = (host -> outgoingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; for (channel = currentPeer -> channels; channel < & currentPeer -> channels [channelCount]; ++ channel) { channel -> outgoingReliableSequenceNumber = 0; channel -> outgoingUnreliableSequenceNumber = 0; channel -> incomingReliableSequenceNumber = 0; channel -> incomingUnreliableSequenceNumber = 0; enet_list_clear (& channel -> incomingReliableCommands); enet_list_clear (& channel -> incomingUnreliableCommands); } command.header.command = ENET_PROTOCOL_COMMAND_CONNECT; command.header.channelID = 0xFF; command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; command.header.commandLength = sizeof (ENetProtocolConnect); command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); command.connect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu); command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize); command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount); command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth); command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth); command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval); command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration); command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration); enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0); return currentPeer; }
/** Queues a packet to be sent. @param peer destination for the packet @param channelID channel on which to send @param packet packet to send @retval 0 on success @retval < 0 on failure */ int enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) { ENetChannel * channel = & peer -> channels [channelID]; ENetProtocol command; size_t fragmentLength; if (peer -> state != ENET_PEER_STATE_CONNECTED || channelID >= peer -> channelCount) return -1; fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment); if (packet -> dataLength > fragmentLength) { enet_uint16 startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1); enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength), fragmentNumber, fragmentOffset; ENetList fragments; ENetOutgoingCommand * fragment; enet_list_clear (& fragments); for (fragmentNumber = 0, fragmentOffset = 0; fragmentOffset < packet -> dataLength; ++ fragmentNumber, fragmentOffset += fragmentLength) { if (packet -> dataLength - fragmentOffset < fragmentLength) fragmentLength = packet -> dataLength - fragmentOffset; fragment = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand)); if (fragment == NULL) { while (! enet_list_empty (& fragments)) { fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments)); enet_free (fragment); } return -1; } fragment -> fragmentOffset = fragmentOffset; fragment -> fragmentLength = fragmentLength; fragment -> packet = packet; fragment -> command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; 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.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); enet_list_insert (enet_list_end (& fragments), fragment); } packet -> referenceCount += fragmentNumber; while (! enet_list_empty (& fragments)) { fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments)); enet_peer_setup_outgoing_command (peer, fragment); } return 0; } command.header.channelID = channelID; if (packet -> flags & ENET_PACKET_FLAG_RELIABLE) { command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); } else if (packet -> flags & ENET_PACKET_FLAG_UNSEQUENCED) { command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup + 1); command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); } else if (channel -> outgoingUnreliableSequenceNumber >= 0xFFFF) { command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); } else { command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE; command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1); command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); } if (enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength) == NULL) return -1; return 0; }
ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount) { static ENetIncomingCommand dummyCommand; ENetChannel * channel = & peer -> channels [command -> header.channelID]; enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber; enet_uint16 reliableWindow, currentWindow; ENetIncomingCommand * incomingCommand; ENetListIterator currentCommand; if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) goto freePacket; if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { reliableSequenceNumber = command -> header.reliableSequenceNumber; reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber) reliableWindow += ENET_PEER_RELIABLE_WINDOWS; if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) goto freePacket; } switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) { case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber) goto freePacket; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); currentCommand != enet_list_end (& channel -> incomingReliableCommands); currentCommand = enet_list_previous (currentCommand)) { incomingCommand = (ENetIncomingCommand *) currentCommand; if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) { if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) continue; } else if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) break; if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber) { if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) break; goto freePacket; } } break; case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber); if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber && unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber) goto freePacket; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); currentCommand = enet_list_previous (currentCommand)) { incomingCommand = (ENetIncomingCommand *) currentCommand; if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE) continue; if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) { if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) continue; } else if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) break; if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) break; if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber) continue; if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber) { if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber) break; goto freePacket; } } break; case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: currentCommand = enet_list_end (& channel -> incomingUnreliableCommands); break; default: goto freePacket; } incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand)); if (incomingCommand == NULL) goto notifyError; incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber; incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF; incomingCommand -> command = * command; incomingCommand -> fragmentCount = fragmentCount; incomingCommand -> fragmentsRemaining = fragmentCount; incomingCommand -> packet = packet; incomingCommand -> fragments = NULL; if (fragmentCount > 0) { incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); if (incomingCommand -> fragments == NULL) { enet_free (incomingCommand); goto notifyError; } memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32)); } if (packet != NULL) ++ packet -> referenceCount; enet_list_insert (enet_list_next (currentCommand), incomingCommand); switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) { case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: enet_peer_dispatch_incoming_reliable_commands (peer, channel); break; default: enet_peer_dispatch_incoming_unreliable_commands (peer, channel); break; } return incomingCommand; freePacket: if (fragmentCount > 0) goto notifyError; if (packet != NULL && packet -> referenceCount == 0) enet_packet_destroy (packet); return & dummyCommand; notifyError: if (packet != NULL && packet -> referenceCount == 0) enet_packet_destroy (packet); return NULL; }
ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount) { ENetChannel * channel = & peer -> channels [command -> header.channelID]; enet_uint32 unreliableSequenceNumber = 0; ENetIncomingCommand * incomingCommand; ENetListIterator currentCommand; switch (command -> header.command) { case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); currentCommand != enet_list_end (& channel -> incomingReliableCommands); currentCommand = enet_list_previous (currentCommand)) { incomingCommand = (ENetIncomingCommand *) currentCommand; if (incomingCommand -> reliableSequenceNumber <= command -> header.reliableSequenceNumber) { if (incomingCommand -> reliableSequenceNumber < command -> header.reliableSequenceNumber) break; goto freePacket; } } break; case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: unreliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> sendUnreliable.unreliableSequenceNumber); if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber) goto freePacket; if (unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber) goto freePacket; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); currentCommand = enet_list_previous (currentCommand)) { incomingCommand = (ENetIncomingCommand *) currentCommand; if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber) { if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber) break; goto freePacket; } } break; case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: currentCommand = enet_list_end (& channel -> incomingUnreliableCommands); break; default: goto freePacket; } incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand)); incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber; incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber; incomingCommand -> command = * command; incomingCommand -> fragmentCount = fragmentCount; incomingCommand -> fragmentsRemaining = fragmentCount; incomingCommand -> packet = packet; incomingCommand -> fragments = NULL; if (fragmentCount > 0) { incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32)); } if (packet != NULL) ++ packet -> referenceCount; enet_list_insert (enet_list_next (currentCommand), incomingCommand); return incomingCommand; freePacket: if (packet != NULL) { if (packet -> referenceCount == 0) enet_packet_destroy (packet); } return NULL; }
static ENetPeer * enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header, const ENetProtocol * command) { enet_uint16 mtu; enet_uint32 windowSize; ENetChannel * channel; size_t channelCount; ENetPeer * currentPeer; ENetProtocol verifyCommand; if (command -> header.commandLength < sizeof (ENetProtocolConnect)) return NULL; channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount); if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) return NULL; for (currentPeer = host -> peers; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED && currentPeer -> address.host == host -> receivedAddress.host && currentPeer -> address.port == host -> receivedAddress.port && currentPeer -> challenge == header -> challenge) return NULL; } for (currentPeer = host -> peers; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED) break; } if (currentPeer >= & host -> peers [host -> peerCount]) return NULL; currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; currentPeer -> challenge = header -> challenge; currentPeer -> address = host -> receivedAddress; currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth); 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 -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); currentPeer -> channelCount = channelCount; for (channel = currentPeer -> channels; channel < & currentPeer -> channels [channelCount]; ++ channel) { channel -> outgoingReliableSequenceNumber = 0; channel -> outgoingUnreliableSequenceNumber = 0; channel -> incomingReliableSequenceNumber = 0; channel -> incomingUnreliableSequenceNumber = 0; enet_list_clear (& channel -> incomingReliableCommands); enet_list_clear (& channel -> incomingUnreliableCommands); } mtu = ENET_NET_TO_HOST_16 (command -> connect.mtu); if (mtu < ENET_PROTOCOL_MINIMUM_MTU) mtu = ENET_PROTOCOL_MINIMUM_MTU; else if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) mtu = ENET_PROTOCOL_MAXIMUM_MTU; currentPeer -> mtu = mtu; if (host -> outgoingBandwidth == 0 && currentPeer -> incomingBandwidth == 0) currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; if (host -> incomingBandwidth == 0) windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else windowSize = (host -> incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; if (windowSize > ENET_NET_TO_HOST_32 (command -> connect.windowSize)) windowSize = ENET_NET_TO_HOST_32 (command -> connect.windowSize); if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT; verifyCommand.header.channelID = 0xFF; verifyCommand.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; verifyCommand.header.commandLength = sizeof (ENetProtocolVerifyConnect); verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); 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); verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth); verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth); 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); enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0); return currentPeer; }