ENetSocket enet_socket_create (ENetSocketType type, const ENetAddress * address) { ENetSocket newSocket = socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); struct sockaddr_in sin; if (newSocket == ENET_SOCKET_NULL) return ENET_SOCKET_NULL; memset (& sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; if (address != NULL) { sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; } else { sin.sin_port = 0; sin.sin_addr.s_addr = INADDR_ANY; } if (bind (newSocket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)) == SOCKET_ERROR || (type == ENET_SOCKET_TYPE_STREAM && address != NULL && address -> port != ENET_PORT_ANY && listen (newSocket, SOMAXCONN) == SOCKET_ERROR)) { closesocket (newSocket); return ENET_SOCKET_NULL; } return newSocket; }
int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; int result; memset (& sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); if (result == -1 && errno == EINPROGRESS) return 0; return result; }
int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; int result; memset (& sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK) return -1; return 0; }
int enet_socket_send (ENetSocket socket, const ENetAddress * address, const ENetBuffer * buffers, size_t bufferCount) { struct msghdr msgHdr; struct sockaddr_in sin; int sentLength; memset (& msgHdr, 0, sizeof (struct msghdr)); if (address != NULL) { memset (& sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; msgHdr.msg_name = & sin; msgHdr.msg_namelen = sizeof (struct sockaddr_in); } msgHdr.msg_iov = (struct iovec *) buffers; msgHdr.msg_iovlen = bufferCount; sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL); if (sentLength == -1) { if (errno == EWOULDBLOCK) return 0; return -1; } return sentLength; }
void send_welcome(int n) { auto packet = enet_packet_create(NULL, MAXTRANS, ENET_PACKET_FLAG_RELIABLE); u8 *start = packet->data; u8 *p = start+2; putint(p, SV_INITS2C); putint(p, n); putint(p, PROTOCOL_VERSION); putint(p, smapname[0]); sendstring(serverpassword, p); putint(p, clients.size()>maxclients); if (smapname[0]) { putint(p, SV_MAPCHANGE); sendstring(smapname.c_str(), p); putint(p, mode); putint(p, SV_ITEMLIST); loopv(sents) if (sents[i].spawned) putint(p, i); putint(p, -1); } *(u16 *)start = ENET_HOST_TO_NET_16(int(p-start)); enet_packet_resize(packet, p-start); send(n, packet); }
int enet_socket_send (ENetSocket socket, const ENetAddress * address, const ENetBuffer * buffers, size_t bufferCount) { struct msghdr msgHdr; ENetAddress address_clone; int sentLength; memset (& msgHdr, 0, sizeof (struct msghdr)); if (address != NULL) { msgHdr.msg_name = & address_clone; msgHdr.msg_namelen = enet_address_get_size (address); memcopy (& address_clone, address, msgHdr.msg_namelen); address_clone.port = ENET_HOST_TO_NET_16 (address -> port); } msgHdr.msg_iov = (struct iovec *) buffers; msgHdr.msg_iovlen = bufferCount; sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL); if (sentLength == -1) { if (errno == EWOULDBLOCK) return 0; return -1; } return sentLength; }
int enet_socket_send (ENetSocket socket, const ENetAddress * address, const ENetBuffer * buffers, size_t bufferCount) { struct sockaddr_in sin; DWORD sentLength; if (address != NULL) { memset (& sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; } if (WSASendTo (socket, (LPWSABUF) buffers, (DWORD) bufferCount, & sentLength, 0, address != NULL ? (struct sockaddr *) & sin : NULL, address != NULL ? sizeof (struct sockaddr_in) : 0, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError () == WSAEWOULDBLOCK) return 0; return -1; } return (int) sentLength; }
int enet_socket_bind (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; memset (& sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; if (address != NULL) { sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; } else { sin.sin_port = 0; sin.sin_addr.s_addr = INADDR_ANY; } return bind (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 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; }
void enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand) { ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID]; peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength; if (outgoingCommand -> command.header.channelID == 0xFF) { ++ peer -> outgoingReliableSequenceNumber; outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = 0; } else if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { ++ channel -> outgoingReliableSequenceNumber; channel -> outgoingUnreliableSequenceNumber = 0; outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = 0; } else if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED) { ++ peer -> outgoingUnsequencedGroup; outgoingCommand -> reliableSequenceNumber = 0; outgoingCommand -> unreliableSequenceNumber = 0; } else { if (outgoingCommand -> fragmentOffset == 0) ++ channel -> outgoingUnreliableSequenceNumber; outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber; } outgoingCommand -> sendAttempts = 0; outgoingCommand -> sentTime = 0; outgoingCommand -> roundTripTimeout = 0; outgoingCommand -> roundTripTimeoutLimit = 0; outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber); switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) { case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: outgoingCommand -> command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> unreliableSequenceNumber); break; case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: outgoingCommand -> command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup); break; default: break; } if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand); else enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand); }
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; }
static int enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts) { size_t packetsSent = 1; ENetProtocolHeader header; ENetPeer * currentPeer; int sentLength; while (packetsSent > 0) for (currentPeer = host -> peers, packetsSent = 0; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED || currentPeer -> state == ENET_PEER_STATE_ZOMBIE) continue; host -> commandCount = 0; host -> bufferCount = 1; host -> packetSize = sizeof (ENetProtocolHeader); if (enet_list_empty (& currentPeer -> acknowledgements) == 0) enet_protocol_send_acknowledgements (host, currentPeer); if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol)) { if (checkForTimeouts != 0 && enet_list_empty (& currentPeer -> sentReliableCommands) == 0 && ENET_TIME_GREATER_EQUAL (timeCurrent, currentPeer -> nextTimeout) && enet_protocol_check_timeouts (host, currentPeer, event) == 1) return 1; } if (enet_list_empty (& currentPeer -> outgoingReliableCommands) == 0) enet_protocol_send_reliable_outgoing_commands (host, currentPeer); else if (enet_list_empty (& currentPeer -> sentReliableCommands) && ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL && currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing)) { enet_peer_ping (currentPeer); enet_protocol_send_reliable_outgoing_commands (host, currentPeer); } if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol) && enet_list_empty (& currentPeer -> outgoingUnreliableCommands) == 0) enet_protocol_send_unreliable_outgoing_commands (host, currentPeer); if (host -> commandCount == 0) continue; if (currentPeer -> packetLossEpoch == 0) currentPeer -> packetLossEpoch = timeCurrent; else if (ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL && currentPeer -> packetsSent > 0) { enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent; #ifdef ENET_DEBUG #ifdef WIN32 printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands)); #else fprintf (stderr, "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands)); #endif #endif currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4; if (packetLoss >= currentPeer -> packetLoss) { currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8; currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4; } else { currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8; currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4; } currentPeer -> packetLossEpoch = timeCurrent; currentPeer -> packetsSent = 0; currentPeer -> packetsLost = 0; } header.peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID); header.flags = 0; header.commandCount = host -> commandCount; header.sentTime = ENET_HOST_TO_NET_32 (timeCurrent); header.challenge = currentPeer -> challenge; host -> buffers -> data = & header; host -> buffers -> dataLength = sizeof (ENetProtocolHeader); currentPeer -> lastSendTime = timeCurrent; ++ packetsSent; sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount); enet_protocol_remove_sent_unreliable_commands (currentPeer); if (sentLength < 0) return -1; } return 0; }
/** 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; packet -> flags |= ENET_PACKET_FLAG_RELIABLE; packet -> flags &= ~ENET_PACKET_FLAG_UNSEQUENCED; for (fragmentNumber = 0, fragmentOffset = 0; fragmentOffset < packet -> dataLength; ++ fragmentNumber, fragmentOffset += fragmentLength) { if (packet -> dataLength - fragmentOffset < fragmentLength) fragmentLength = packet -> dataLength - fragmentOffset; command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.header.channelID = channelID; command.sendFragment.startSequenceNumber = startSequenceNumber; command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength); command.sendFragment.fragmentCount = fragmentCount; command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber); command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength); command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset); enet_peer_queue_outgoing_command (peer, & command, packet, fragmentOffset, fragmentLength); } return 0; } command.header.channelID = channelID; if (! (packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) && channel -> outgoingUnreliableSequenceNumber >= 0xFFFF) packet -> flags |= ENET_PACKET_FLAG_RELIABLE; 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 { 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); } enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength); return 0; }
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 += enet_protocol_command_size (command -> header.command) + 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.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { ++ channel -> outgoingReliableSequenceNumber; channel -> outgoingUnreliableSequenceNumber = 0; outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = 0; } else if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED) { ++ peer -> outgoingUnsequencedGroup; outgoingCommand -> reliableSequenceNumber = 0; outgoingCommand -> unreliableSequenceNumber = 0; } else { ++ channel -> outgoingUnreliableSequenceNumber; outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber; } outgoingCommand -> sendAttempts = 0; 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_16 (outgoingCommand -> reliableSequenceNumber); if (packet != NULL) ++ packet -> referenceCount; if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand); else enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand); return outgoingCommand; }