Esempio n. 1
0
        private int HandleIncomingCommands(Event evnt, Address receivedAddress, Buffer buffer)
        {
            uint receivedDataLength = buffer.DataLength;

            var header = ProtocolHeader.Create(buffer, Version);

            if (header == null)
            {
                return(0);
            }

            ushort peerID = header.PeerID;
            Peer   peer   = null;

            if (peerID != Version.MaxPeerID)
            {
                if (peerID > PeerCount)
                {
                    return(0);
                }

                peer = Peers[peerID];

                if (peer.State == PeerState.DISCONNECTED ||
                    peer.State == PeerState.ZOMBIE)
                {
                    return(0);
                }

                if ((receivedAddress.Host != peer.Address.Host ||
                     receivedAddress.Port != peer.Address.Port) &&
                    peer.Address.Host != Address.Broadcast)
                {
                    return(0);
                }

                if (header.SessionID != peer.SessionID)
                {
                    return(0);
                }

                peer.Address            = receivedAddress;
                peer.IncomingDataTotal += receivedDataLength;
            }

            while (buffer.BytesLeft > 0)
            {
                var command = Protocol.Create(buffer, Version);

                if (command == null || command is Protocol.None)
                {
                    break;
                }

                if (peer == null && !(command is Protocol.Connect))
                {
                    break;
                }

                int result;
                switch (command)
                {
                case Protocol.Acknowledge c: result = HandleAcknowledge(evnt, peer, c); break;

                case Protocol.Connect c: result = HandleConnect(receivedAddress, ref peer, c); break;

                case Protocol.VerifyConnect c: result = HandleVerifyConnect(evnt, peer, c); break;

                case Protocol.Disconnect c: result = HandleDisconnect(peer, c); break;

                case Protocol.Ping _: result = 0; break;

                case Protocol.Send.Reliable c: result = HandleSendReliable(peer, c, buffer); break;

                case Protocol.Send.Unreliable c: result = HandleSendUnreliable(peer, c, buffer); break;

                case Protocol.Send.Unsequenced c: result = HandleSendUnsequenced(peer, c, buffer); break;

                case Protocol.Send.Fragment c: result = HandleSendFragment(peer, c, buffer); break;

                case Protocol.BandwidthLimit c: result = HandleBandwidthLimit(peer, c); break;

                case Protocol.ThrottleConfigure c: result = HandleThrottleConfigure(peer, c); break;

                default: result = -1; break;
                }
                ;

                if (result != 0)
                {
                    break;
                }

                if (peer != null && command.Flags.HasFlag(ProtocolFlag.ACKNOWLEDGE))
                {
                    if (header.TimeSent is ushort sentTime)
                    {
                        switch (peer.State)
                        {
                        case PeerState.DISCONNECTING:
                        case PeerState.ACKNOWLEDGING_CONNECT:
                            break;

                        case PeerState.ACKNOWLEDGING_DISCONNECT:
                            if (command is Protocol.Disconnect)
                            {
                                peer.QueueAcknowledgement(command, sentTime);
                            }
                            break;

                        default:
                            peer.QueueAcknowledgement(command, sentTime);
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (evnt != null && evnt.Type != EventType.NONE)
            {
                return(1);
            }
            return(0);
        }
Esempio n. 2
0
        private int SendOutgoingCommands(Event evnt, bool checkForTimeout)
        {
            var buffer = new Buffer(MAXIMUM_MTU);

            bool continueSending = true;


            while (continueSending)
            {
                continueSending = false;

                foreach (var currentPeer in Peers)
                {
                    if (currentPeer.State == PeerState.DISCONNECTED || currentPeer.State == PeerState.ZOMBIE)
                    {
                        continue;
                    }

                    bool hasSentTime = false;
                    buffer.Position   = Version.MaxHeaderSizeSend;
                    buffer.DataLength = currentPeer.MTU;

                    if (!currentPeer.Acknowledgements.Empty)
                    {
                        SendAcknowledgements(currentPeer, buffer, ref continueSending);
                    }

                    if (checkForTimeout &&
                        !currentPeer.SentReliableCommands.Empty &&
                        !Utils.TimeLess(ServiceTime, currentPeer.NextTimeout))
                    {
                        if (CheckTimeouts(currentPeer, evnt) == 1)
                        {
                            return(1);
                        }
                    }

                    if (!currentPeer.OutgoingReliableCommands.Empty)
                    {
                        SendReliableOutgoingCommands(currentPeer, buffer, ref continueSending, ref hasSentTime);
                    }
                    else if (currentPeer.SentReliableCommands.Empty &&
                             Utils.TimeDiff(ServiceTime, currentPeer.LastReceiveTime) >= Peer.PING_INTERVAL)
                    {
                        if (Protocol.Ping.SIZE <= buffer.BytesLeft)
                        {
                            currentPeer.Ping();
                            SendReliableOutgoingCommands(currentPeer, buffer, ref continueSending, ref hasSentTime);
                        }
                    }

                    if (!currentPeer.OutgoingUnreliableCommands.Empty)
                    {
                        SendUnreliableOutgoingCommands(currentPeer, buffer, ref continueSending);
                    }

                    if (buffer.Position <= Version.MaxHeaderSizeSend)
                    {
                        continue;
                    }

                    if (currentPeer.PacketLossEpoch == 0u)
                    {
                        currentPeer.PacketLossEpoch = ServiceTime;
                    }
                    else if (Utils.TimeDiff(ServiceTime, currentPeer.PacketLossEpoch) >= Version.PacketLossInterval &&
                             currentPeer.PacketsSent > 0u)
                    {
                        uint packetLoss = currentPeer.PacketsLost * Peer.PACKET_LOSS_SCALE / currentPeer.PacketsSent;

                        currentPeer.PacketLossVariance -= currentPeer.PacketLossVariance / 4u;

                        if (packetLoss >= currentPeer.PacketLoss)
                        {
                            currentPeer.PacketLoss         += (packetLoss - currentPeer.PacketLoss) / 8u;
                            currentPeer.PacketLossVariance += (packetLoss - currentPeer.PacketLoss) / 4u;
                        }
                        else
                        {
                            currentPeer.PacketLoss         -= (currentPeer.PacketLoss - packetLoss) / 8u;
                            currentPeer.PacketLossVariance += (currentPeer.PacketLoss - packetLoss) / 4u;
                        }

                        currentPeer.PacketLossEpoch = ServiceTime;
                        currentPeer.PacketsSent     = 0;
                        currentPeer.PacketsLost     = 0;
                    }


                    uint bufferLength = buffer.Position;
                    uint bufferOffset = 0;

                    var header = new ProtocolHeader
                    {
                        SessionID = currentPeer.SessionID,
                        PeerID    = currentPeer.OutgoingPeerID,
                    };
                    if (hasSentTime)
                    {
                        header.TimeSent = (ushort)ServiceTime;
                    }
                    else
                    {
                        header.TimeSent = null;
                        bufferOffset   += 2;
                        bufferLength   -= 2;
                    }
                    buffer.Position = bufferOffset;
                    header.Write(buffer, Version);

                    currentPeer.LastSendTime = ServiceTime;

                    int sentLength = Socket.SendTo(currentPeer.Address, buffer.Data, bufferOffset, bufferLength);

                    RemoveSentUnreliableCommands(currentPeer);

                    if (sentLength < 0)
                    {
                        return(-1);
                    }

                    TotalSentData += (uint)sentLength;
                    TotalSentPackets++;
                }
            }

            return(0);
        }