Пример #1
0
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;
}
Пример #2
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);
}
Пример #3
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))
   {
      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;
}
Пример #4
0
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;
}
Пример #5
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;
}
Пример #6
0
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;
}
Пример #7
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;
}
Пример #8
0
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);
    }
}
Пример #9
0
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);
    }
}
Пример #10
0
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);
}
Пример #11
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);
    }
}
Пример #12
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;
      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;
}
Пример #13
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();
}
Пример #14
0
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;
}
Пример #15
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;
}
Пример #16
0
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;
}
Пример #17
0
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;
}