static ENetProtocolCommand enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint32 reliableSequenceNumber, enet_uint8 channelID) { ENetOutgoingCommand * outgoingCommand; ENetListIterator currentCommand; ENetProtocolCommand commandNumber; for (currentCommand = enet_list_begin (& peer -> sentReliableCommands); currentCommand != enet_list_end (& peer -> sentReliableCommands); currentCommand = enet_list_next (currentCommand)) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber && outgoingCommand -> command.header.channelID == channelID) break; } if (currentCommand == enet_list_end (& peer -> sentReliableCommands)) return ENET_PROTOCOL_COMMAND_NONE; commandNumber = outgoingCommand -> command.header.command; enet_list_remove (& outgoingCommand -> outgoingCommandList); if (outgoingCommand -> packet != NULL) { peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength; -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) enet_packet_destroy (outgoingCommand -> packet); } enet_free (outgoingCommand); if (enet_list_empty (& peer -> sentReliableCommands)) return commandNumber; outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentReliableCommands); peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout; return commandNumber; }
static void enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) { ENetProtocol * command = & host -> commands [host -> commandCount]; ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; ENetAcknowledgement * acknowledgement; ENetListIterator currentAcknowledgement; currentAcknowledgement = enet_list_begin (& peer -> acknowledgements); while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements)) { if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge)) break; acknowledgement = (ENetAcknowledgement *) currentAcknowledgement; currentAcknowledgement = enet_list_next (currentAcknowledgement); buffer -> data = command; buffer -> dataLength = sizeof (ENetProtocolAcknowledge); host -> packetSize += buffer -> dataLength; command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE; command -> header.channelID = acknowledgement -> command.header.channelID; command -> header.flags = 0; command -> header.commandLength = ENET_HOST_TO_NET_32 (sizeof (ENetProtocolAcknowledge)); command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_32 (acknowledgement -> command.header.reliableSequenceNumber); command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_32 (acknowledgement -> sentTime); if (acknowledgement -> command.header.command == ENET_PROTOCOL_COMMAND_DISCONNECT) peer -> state = ENET_PEER_STATE_ZOMBIE; enet_list_remove (& acknowledgement -> acknowledgementList); enet_free (acknowledgement); ++ command; ++ buffer; } host -> commandCount = command - host -> commands; host -> bufferCount = buffer - host -> buffers; }
static void enet_peer_reset_outgoing_commands (ENetList * queue) { ENetOutgoingCommand * outgoingCommand; while (! enet_list_empty (queue)) { outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue)); if (outgoingCommand -> packet != NULL) { -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) enet_packet_destroy (outgoingCommand -> packet); } enet_free (outgoingCommand); } }
static void enet_peer_reset_incoming_commands (ENetList * queue) { ENetIncomingCommand * incomingCommand; while (enet_list_empty (queue) == 0) { incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (queue)); if (incomingCommand -> packet != NULL) { -- incomingCommand -> packet -> referenceCount; if (incomingCommand -> packet -> referenceCount == 0) enet_packet_destroy (incomingCommand -> packet); } enet_free (incomingCommand); } }
/** 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; }
static void enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) { ENetOutgoingCommand * outgoingCommand; while (enet_list_empty (& peer -> sentUnreliableCommands) == 0) { outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands); enet_list_remove (& outgoingCommand -> outgoingCommandList); if (outgoingCommand -> packet != NULL) { -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) enet_packet_destroy (outgoingCommand -> packet); } enet_free (outgoingCommand); } }
/** Free an allocated ENetEvent struct from neko **/ static value free_enetevent( value e ) { val_check_kind(e,k_udprevent); ENetEvent *event = (ENetEvent *)val_data(e); if(e == NULL) neko_error(); // enet_packet_destroy frees the packet itself. #ifdef ENET_DEBUG printf("*** free_enetevent freeing packet\n"); #endif if(event->packet != NULL) enet_packet_destroy (event->packet); #ifdef ENET_DEBUG //printf("*** free_enetevent freeing event\n"); #endif enet_free(event); val_gc(e,NULL); val_kind(e) = NULL; #ifdef ENET_DEBUG //printf("*** free_enetevent done.\n"); #endif return val_true; }
/** Destroys the packet and deallocates its data. @param packet packet to be destroyed */ void enet_packet_destroy (ENetPacket * packet) { enet_free (packet -> data); enet_free (packet); }
/** 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; }
/** Attempts to dequeue any incoming queued packet. @param peer peer to dequeue packets from @param channelID channel on which to receive @returns a pointer to the packet, or NULL if there are no available incoming queued packets */ ENetPacket * enet_peer_receive (ENetPeer * peer, enet_uint8 channelID) { ENetChannel * channel = & peer -> channels [channelID]; ENetIncomingCommand * incomingCommand = NULL; ENetPacket * packet; if (enet_list_empty (& channel -> incomingUnreliableCommands) == 0) { incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingUnreliableCommands); if (incomingCommand -> unreliableSequenceNumber > 0) { if (incomingCommand -> reliableSequenceNumber > channel -> incomingReliableSequenceNumber) incomingCommand = NULL; else channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; } } if (incomingCommand == NULL && enet_list_empty (& channel -> incomingReliableCommands) == 0) { do { incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingReliableCommands); if (incomingCommand -> fragmentsRemaining > 0 || incomingCommand -> reliableSequenceNumber > channel -> incomingReliableSequenceNumber + 1) return NULL; if (incomingCommand -> reliableSequenceNumber <= channel -> incomingReliableSequenceNumber) { -- incomingCommand -> packet -> referenceCount; if (incomingCommand -> packet -> referenceCount == 0) enet_packet_destroy (incomingCommand -> packet); if (incomingCommand -> fragments != NULL) enet_free (incomingCommand -> fragments); enet_list_remove (& incomingCommand -> incomingCommandList); enet_free (incomingCommand); incomingCommand = NULL; } } while (incomingCommand == NULL && enet_list_empty (& channel -> incomingReliableCommands) == 0); if (incomingCommand == NULL) return NULL; channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber; if (incomingCommand -> fragmentCount > 0) channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1; } if (incomingCommand == NULL) return NULL; enet_list_remove (& incomingCommand -> incomingCommandList); packet = incomingCommand -> packet; -- packet -> referenceCount; if (incomingCommand -> fragments != NULL) enet_free (incomingCommand -> fragments); enet_free (incomingCommand); return packet; }
static void enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer) { ENetProtocol * command = & host -> commands [host -> commandCount]; ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; ENetOutgoingCommand * outgoingCommand; ENetListIterator currentCommand; currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands); while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands)) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength || (outgoingCommand -> packet != NULL && peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength + outgoingCommand -> packet -> dataLength)) break; currentCommand = enet_list_next (currentCommand); if (outgoingCommand -> packet != NULL) { peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER; peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE; if (peer -> packetThrottleCounter > peer -> packetThrottle) { -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) enet_packet_destroy (outgoingCommand -> packet); enet_list_remove (& outgoingCommand -> outgoingCommandList); enet_free (outgoingCommand); continue; } } buffer -> data = command; buffer -> dataLength = outgoingCommand -> command.header.commandLength; host -> packetSize += buffer -> dataLength; * command = outgoingCommand -> command; enet_list_remove (& outgoingCommand -> outgoingCommandList); if (outgoingCommand -> packet != NULL) { ++ buffer; buffer -> data = outgoingCommand -> packet -> data; buffer -> dataLength = outgoingCommand -> packet -> dataLength; command -> header.commandLength += buffer -> dataLength; host -> packetSize += buffer -> dataLength; enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand); } else enet_free (outgoingCommand); command -> header.commandLength = ENET_HOST_TO_NET_32 (command -> header.commandLength); ++ command; ++ buffer; } host -> commandCount = command - host -> commands; host -> bufferCount = buffer - host -> buffers; }
/** Forcefully disconnects a peer. @param peer peer to forcefully disconnect @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout on its connection to the local host. */ void enet_peer_reset (ENetPeer * peer) { if (peer -> ownSocket != ENET_SOCKET_NULL) { enet_socket_destroy (peer -> ownSocket); peer -> ownSocket = ENET_SOCKET_NULL; } size_t i; ENetHost * host = peer -> host; for (i = 0; i < host -> peerCount - host -> idlePeers; ++ i) if (host -> busyPeersList [i] == peer -> incomingPeerID) { host -> idlePeersList [host -> idlePeers ++] = peer -> incomingPeerID; host -> busyPeersList [i] = host -> busyPeersList [host -> peerCount - host -> idlePeers]; break; } if (peer -> host -> connectingPeerTimeout && peer -> connectingPeers) { enet_free(peer -> connectingPeers); peer -> connectingPeers = NULL; peer -> host -> connectsWindow -= ENET_PROTOCOL_TOTAL_SESSIONS * (peer -> connectingPeersTimeMask + 1); } enet_peer_on_disconnect (peer); peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID; peer -> connectID = 0; peer -> state = ENET_PEER_STATE_DISCONNECTED; peer -> incomingBandwidth = 0; peer -> outgoingBandwidth = 0; peer -> incomingBandwidthThrottleEpoch = 0; peer -> outgoingBandwidthThrottleEpoch = 0; peer -> incomingDataTotal = 0; peer -> outgoingDataTotal = 0; peer -> lastSendTime = 0; peer -> lastReceiveTime = 0; peer -> nextTimeout = 0; peer -> earliestTimeout = 0; peer -> packetLossEpoch = 0; peer -> packetsSent = 0; peer -> packetsLost = 0; peer -> packetLoss = 0; peer -> packetLossVariance = 0; peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE; peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE; peer -> packetThrottleCounter = 0; peer -> packetThrottleEpoch = 0; peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION; peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION; peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL; peer -> pingInterval = ENET_PEER_PING_INTERVAL; peer -> timeoutLimit = ENET_PEER_TIMEOUT_LIMIT; peer -> timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM; peer -> timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM; peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> lastRoundTripTimeVariance = 0; peer -> highestRoundTripTimeVariance = 0; peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> roundTripTimeVariance = 0; peer -> mtu = peer -> host -> mtu; peer -> reliableDataInTransit = 0; peer -> outgoingReliableSequenceNumber = 0; peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; peer -> incomingUnsequencedGroup = 0; peer -> outgoingUnsequencedGroup = 0; peer -> eventData = 0; peer -> totalWaitingData = 0; memset (& peer -> localAddress, 0, sizeof (ENetAddress)); memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow)); enet_peer_reset_queues (peer); }
char * tftp_get(IPAddr server, char * file, void(*receiver)(Octet *, Uint32)) { UDP *sendBuf = (UDP *)enet_alloc(); UDPPort local = udp_allocPort(NULL); sendBuf->ip.dest = hton(server); sendBuf->udp.dest = htons(tftpPort); sendBuf->udp.srce = htons(local); TFTPHeader * sendHeader = (TFTPHeader *)&(sendBuf->data[0]); sendHeader->op = htons(tftpOpRRQ); Uint32 pos = tftpPosName; appendStr(sendBuf, &pos, file); appendStr(sendBuf, &pos, "octet"); Uint32 blockNum; for (blockNum = 1; ; blockNum++) { Uint32 recvLen; IP * recvBuf; TFTPHeader * recvHeader; Octet * recvData; Uint32 dataLen; int tries; for (tries = 0; ; tries++) { if (tries >= retryLimit) { udp_freePort(local); enet_free((Enet *)sendBuf); return "Timeout"; } udp_send(sendBuf, pos); recvLen = udp_recv(&recvBuf, local, timeout); if (recvBuf) { recvHeader = (TFTPHeader *)udp_payload(recvBuf); recvData = udp_payload(recvBuf) + tftpPosData; dataLen = recvLen - tftpPosData; if (ntohs(recvHeader->op) == tftpOpData) { if (ntohs(recvHeader->block) == blockNum) break; } else if (ntohs(recvHeader->op) == tftpOpError) { recvData[dataLen-1] = 0; // in case server omitted it udp_freePort(local); enet_free((Enet *)sendBuf); int slen = strlen((char *)recvData); char *s = malloc(slen+1); strncpy(s, (char *)recvData, slen+1); udp_recvDone(recvBuf); return s; } else { udp_freePort(local); enet_free((Enet *)sendBuf); udp_recvDone(recvBuf); return "Unknown opcode from server"; } // ignore other stuff - excess retransmissions udp_recvDone(recvBuf); } } // The only way to get here is by receiving the expected data block receiver(recvData, dataLen); UDPHeader *recvUDPHeader = (UDPHeader *)ip_payload(recvBuf); sendBuf->udp.dest = recvUDPHeader->srce; sendHeader->op = htons(tftpOpAck); sendHeader->block = recvHeader->block; pos = tftpPosData; udp_recvDone(recvBuf); if (dataLen < 512) break; } udp_send(sendBuf, pos); // final ACK, sent without retransmissions udp_freePort(local); enet_free((Enet *)sendBuf); return NULL; }
/** 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); if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0)) { if (host -> socket != ENET_SOCKET_NULL) enet_socket_destroy (host -> socket); enet_free (host -> peers); enet_free (host); return NULL; } enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1); enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1); enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE); enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE); 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; }