static int enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) { ENetPeer * currentPeer = host -> lastServicedPeer; ENetChannel * channel; do { ++ currentPeer; if (currentPeer >= & host -> peers [host -> peerCount]) currentPeer = host -> peers; if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED) continue; if (currentPeer -> state == ENET_PEER_STATE_ZOMBIE) { host -> recalculateBandwidthLimits = 1; event -> type = ENET_EVENT_TYPE_DISCONNECT; event -> peer = currentPeer; enet_peer_reset (currentPeer); host -> lastServicedPeer = currentPeer; return 1; } for (channel = currentPeer -> channels; channel < & currentPeer -> channels [currentPeer -> channelCount]; ++ channel) { if (enet_list_empty (& channel -> incomingReliableCommands) && enet_list_empty (& channel -> incomingUnreliableCommands)) continue; event -> packet = enet_peer_receive (currentPeer, (enet_uint8)(channel - currentPeer -> channels)); if (event -> packet == NULL) continue; event -> type = ENET_EVENT_TYPE_RECEIVE; event -> peer = currentPeer; event -> channelID = (enet_uint8) (channel - currentPeer -> channels); host -> lastServicedPeer = currentPeer; return 1; } } while (currentPeer != host -> lastServicedPeer); return 0; }
/** Request a disconnection from a peer, but only after all queued outgoing packets are sent. @param peer peer to request a disconnection @param data data describing the disconnection @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service() once the disconnection is complete. */ void enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data) { if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) && ! (enet_list_empty (& peer -> outgoingReliableCommands) && enet_list_empty (& peer -> outgoingUnreliableCommands) && enet_list_empty (& peer -> sentReliableCommands))) { peer -> state = ENET_PEER_STATE_DISCONNECT_LATER; peer -> disconnectData = data; } else enet_peer_disconnect (peer, data); }
/** 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)) { incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingUnreliableCommands); if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE) { if (incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber) incomingCommand = NULL; } } if (incomingCommand == NULL && ! enet_list_empty (& channel -> incomingReliableCommands)) { incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingReliableCommands); if (incomingCommand -> fragmentsRemaining > 0 || incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1)) 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; }
void enet_peer_reset_queues (ENetPeer * peer) { ENetChannel * channel; while (enet_list_empty (& peer -> acknowledgements) == 0) enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements))); enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands); enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands); enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands); enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands); if (peer -> channels != NULL && peer -> channelCount > 0) { for (channel = peer -> channels; channel < & peer -> channels [peer -> channelCount]; ++ channel) { enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands); enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands); } enet_free (peer -> channels); } peer -> channels = NULL; peer -> channelCount = 0; }
/** Attempts to dequeue any incoming queued packet. @param peer peer to dequeue packets from @param channelID holds the channel ID of the channel the packet was received on success @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) { ENetIncomingCommand * incomingCommand; ENetPacket * packet; if (enet_list_empty (& peer -> dispatchedCommands)) return NULL; incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (& peer -> dispatchedCommands)); if (channelID != NULL) * channelID = incomingCommand -> command.header.channelID; packet = incomingCommand -> packet; -- packet -> referenceCount; if (incomingCommand -> fragments != NULL) enet_free (incomingCommand -> fragments); enet_free (incomingCommand); return packet; }
static int enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event) { ENetOutgoingCommand * outgoingCommand; ENetListIterator currentCommand; currentCommand = enet_list_begin (& peer -> sentReliableCommands); while (currentCommand != enet_list_end (& peer -> sentReliableCommands)) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; currentCommand = enet_list_next (currentCommand); if (ENET_TIME_DIFFERENCE (timeCurrent, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout) continue; if (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit) { event -> type = ENET_EVENT_TYPE_DISCONNECT; event -> peer = peer; enet_peer_reset (peer); return 1; } if (outgoingCommand -> packet != NULL) peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength; ++ peer -> packetsLost; outgoingCommand -> roundTripTimeout *= 2; enet_list_insert (enet_list_begin (& peer -> outgoingReliableCommands), enet_list_remove (& outgoingCommand -> outgoingCommandList)); if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) && enet_list_empty (& peer -> sentReliableCommands) == 0) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout; } } return 0; }
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_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); } }
void enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel) { enet_uint16 oldReliableSequenceNumber = channel -> incomingReliableSequenceNumber; ENetListIterator currentCommand; for (currentCommand = enet_list_begin (& channel -> incomingReliableCommands); currentCommand != enet_list_end (& channel -> incomingReliableCommands); currentCommand = enet_list_next (currentCommand)) { ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand; if (incomingCommand -> fragmentsRemaining > 0 || incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1)) break; channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber; if (incomingCommand -> fragmentCount > 0) channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1; } if (currentCommand == enet_list_begin (& channel -> incomingReliableCommands)) return; channel -> incomingUnreliableSequenceNumber = 0; enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand)); if (! peer -> needsDispatch) { enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); peer -> needsDispatch = 1; } if (! enet_list_empty (& channel -> incomingUnreliableCommands)) enet_peer_dispatch_incoming_unreliable_commands (peer, channel); }
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); } }
/** 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 Tunneld::promiseChannelCleanup(ToxTunChannel *chan) { qDebug()<<chan<<sender(); QObject *snderobj = (QObject*)sender(); QTimer *repeat_timer = NULL; qDebug()<<snderobj->objectName()<<snderobj->metaObject()->className(); if (chan == NULL) { repeat_timer = (QTimer*)snderobj; assert(repeat_timer != NULL); int conid = repeat_timer->property("conid").toInt(); if (!m_conid_chans.contains(conid)) { qDebug()<<"maybe too late repeat check self sock close timer event"; repeat_timer->deleteLater(); return; } chan = m_conid_chans[conid]; assert(chan != NULL); } else { // snderobj is ENetPoll or QTcpSocket } QTcpSocket *sock = chan->m_sock; ENetPeer *enpeer = chan->m_enpeer; ////////// QHash<QString, bool> promise_results; promise_results["sock_closed"] = chan->sock_closed; // promise_results["enet_closed"] = chan->enet_closed; promise_results["peer_sock_closed"] = chan->peer_sock_closed; bool promise_result = true; for (auto it = promise_results.begin(); it != promise_results.end(); it ++) { QString key = it.key(); bool val = it.value(); promise_result = promise_result && val; } if (true) { // 检测对方最近的回包情况 if (!promise_result && repeat_timer == NULL && promise_results["peer_sock_closed"] && !promise_results["sock_closed"]) { qDebug()<<"here"; if (chan->last_recv_peer_pkt_time == QDateTime()) { qDebug()<<"maybe can close socket right now, because recv nothing forever"; } QTimer *t = new QTimer(); t->setInterval(500); t->setSingleShot(true); t->setProperty("conid", QVariant(chan->m_conid)); // // QObject::connect(t, &QTimer::timeout, this, &Tunneld::promiseChannelCleanup, Qt::QueuedConnection); QObject::connect(t, SIGNAL(timeout()), this, SLOT(promiseChannelCleanup()), Qt::QueuedConnection); qDebug()<<"start repeat check sock close timer:"; t->start(); } if (!promise_result && repeat_timer != NULL && promise_results["peer_sock_closed"] && !promise_results["sock_closed"]) { // QDateTime now_time = QDateTime::currentDateTime(); uint32_t last_recv_to_now_time = chan->last_recv_peer_pkt_time.msecsTo(now_time); qDebug()<<"here:"<<last_recv_to_now_time<<enpeer->lastReceiveTime; if (last_recv_to_now_time > 7000) { qDebug()<<"last recv to now, force close self socket:"<<last_recv_to_now_time <<enpeer->incomingPeerID<<enpeer->outgoingPeerID; // 不能直接关闭,要在当前函数执行完后,即下一次事件的时候开始执行。 QTimer::singleShot(1, sock, &QTcpSocket::close); // QTimer *t = new QTimer(); // t->setSingleShot(true); // QObject::connect(t, &QTimer::timeout, sock, &QTcpSocket::close, Qt::QueuedConnection); // t->start(1); repeat_timer->deleteLater(); } else { repeat_timer->start(); } } } if (!promise_result) { qDebug()<<"promise nooooot satisfied:"<<promise_results<<chan->m_conid; return; } chan->promise_close_time = QDateTime::currentDateTime(); qDebug()<<"promise satisfied."<<chan->m_conid; ///// do cleanup bool force_closed = chan->force_closed; // enpeer->toxchan = NULL; // cleanup peerRemoveChan(enpeer, chan); this->m_sock_chans.remove(sock); // this->m_enpeer_chans.remove(enpeer); this->m_conid_chans.remove(chan->m_conid); delete chan; sock->disconnect(); sock->deleteLater(); if (repeat_timer != NULL) repeat_timer->deleteLater(); qDebug()<<"curr chan size:"<<this->m_sock_chans.count()<<this->m_conid_chans.count(); if (force_closed) { return; } // 延时关闭enet_peer QTimer *t = new QTimer(); auto later_close_timeout = [enpeer, t]() { qDebug()<<enpeer<<enpeer->state; if (enpeer->state != ENET_PEER_STATE_CONNECTED) { qDebug()<<"warning, peer currently not connected:"<<enpeer->incomingPeerID; } if (! (enet_list_empty (& enpeer -> outgoingReliableCommands) && enet_list_empty (& enpeer -> outgoingUnreliableCommands) && enet_list_empty (& enpeer -> sentReliableCommands))) { qDebug()<<"warning, maybe has unsent packet:"<<enpeer->incomingPeerID; } qDebug()<<"last recv time:"<<enpeer->incomingPeerID <<enetx_time_diff(enpeer->lastReceiveTime, enet_time_get()); qDebug()<<"restore peer timeout, ping interval"; enet_peer_timeout(enpeer, ENET_PEER_TIMEOUT_LIMIT*2, ENET_PEER_TIMEOUT_MINIMUM*2, ENET_PEER_TIMEOUT_MAXIMUM*2); enet_peer_ping_interval(enpeer, ENET_PEER_PING_INTERVAL*2); // enet_peer_disconnect_now(enpeer, qrand()); enet_peer_disconnect_later(enpeer, qrand()); t->deleteLater(); }; qDebug()<<"last recv time:"<<enpeer->incomingPeerID <<enetx_time_diff(enpeer->lastReceiveTime, enet_time_get()); // QTimer::singleShot(5678, later_close_timeout); t->setInterval(5678); t->setSingleShot(true); QObject::connect(t, &QTimer::timeout, later_close_timeout); t->start(); }
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; }
/** 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_reliable_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 -> outgoingReliableCommands); while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands)) { 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) break; currentCommand = enet_list_next (currentCommand); if (outgoingCommand -> packet != NULL) { if ((enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (outgoingCommand -> command.header.commandLength + outgoingCommand -> fragmentLength) || peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > peer -> windowSize) break; } if (outgoingCommand -> roundTripTimeout == 0) { outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance; outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout; } if (enet_list_empty (& peer -> sentReliableCommands)) peer -> nextTimeout = timeCurrent + outgoingCommand -> roundTripTimeout; enet_list_insert (enet_list_end (& peer -> sentReliableCommands), enet_list_remove (& outgoingCommand -> outgoingCommandList)); outgoingCommand -> sentTime = timeCurrent; buffer -> data = command; buffer -> dataLength = outgoingCommand -> command.header.commandLength; host -> packetSize += buffer -> dataLength; * command = outgoingCommand -> command; if (outgoingCommand -> packet != NULL) { ++ buffer; buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset; buffer -> dataLength = outgoingCommand -> fragmentLength; command -> header.commandLength += outgoingCommand -> fragmentLength; host -> packetSize += outgoingCommand -> fragmentLength; peer -> reliableDataInTransit += outgoingCommand -> fragmentLength; } command -> header.commandLength = ENET_HOST_TO_NET_32 (command -> header.commandLength); ++ peer -> packetsSent; ++ command; ++ buffer; } host -> commandCount = command - host -> commands; host -> bufferCount = buffer - host -> buffers; }
static int enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command) { enet_uint32 roundTripTime, receivedSentTime, receivedReliableSequenceNumber; if (command -> header.commandLength < sizeof (ENetProtocolAcknowledge)) return 0; receivedSentTime = ENET_NET_TO_HOST_32 (command -> acknowledge.receivedSentTime); if (ENET_TIME_LESS (timeCurrent, receivedSentTime)) return 0; peer -> lastReceiveTime = timeCurrent; roundTripTime = ENET_TIME_DIFFERENCE (timeCurrent, receivedSentTime); peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4; if (roundTripTime >= peer -> roundTripTime) { peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8; peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4; } else { peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8; peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4; } if (peer -> packetThrottleEpoch == 0 || ENET_TIME_DIFFERENCE(timeCurrent, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval) { peer -> bestRoundTripTime = peer -> roundTripTime; peer -> packetThrottleEpoch = timeCurrent; } else if (peer -> roundTripTime < peer -> bestRoundTripTime) peer -> bestRoundTripTime = peer -> roundTripTime; enet_peer_throttle (peer, roundTripTime); receivedReliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> acknowledge.receivedReliableSequenceNumber); enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID); switch (peer -> state) { case ENET_PEER_STATE_CONNECTING: host -> recalculateBandwidthLimits = 1; peer -> state = ENET_PEER_STATE_CONNECTED; event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; return 1; case ENET_PEER_STATE_DISCONNECTING: if (enet_list_empty (& peer -> sentReliableCommands) == 0) return 0; host -> recalculateBandwidthLimits = 1; event -> type = ENET_EVENT_TYPE_DISCONNECT; event -> peer = peer; enet_peer_reset (peer); return 1; default: break; } return 0; }