示例#1
0
 /// <summary> Detects acknowledged and lost messages. </summary>
 private void AckDelivered(NetHeader header)
 {
     for (int i = 0; i < sendWindow.Count; i++)
     {
         int seqDist = NetMath.SeqDistance(sendWindow[i], header.AckSequence);
         // This AckSequence is older than the sendWindow's, not useful:
         if (seqDist > 0)
         {
             break;
         }
         // AckHistory has rolled over without acking this message; Ordered reliable is broken:
         if (seqDist <= -64)
         {
             Connection.Disconnect();
         }
         // If the seqDistance corresponds to a true bit in the AckHistory, message delivered/acked:
         else if (IsAcked(header.AckHistory, seqDist))
         {
             MessageDelivered(i, header);
             i--; // Since the sendWindow count will decrease, the index needs to be adjusted.
         }
         // The seqDist is still within the send window, but if too much time has passed, assume lost:
         else if (NetTime.Milliseconds() - sendWindowTime[i] > 333)
         {
             MessageLost(i);
         }
     }
 }
示例#2
0
 /// <summary> Handles connecting status. Tracks attempted connections and (re)sends connection data. </summary>
 private void Connect(IPEndPoint ep, NetStream approvalData)
 {
     if (!connectingEndpoints.Contains(ep))
     {
         // We aren't currently trying to connect to this endpoint, add to lists:
         connectingEndpoints.Add(ep);
         connectingTimes.Add(NetTime.Milliseconds());
         connectingData.Add(approvalData);
         connectingRetriesRemaining.Add(4);
         NetLog.Info("Connecting to: " + ep);
     }
     else
     {
         // We are already trying to connect, update attempt data:
         int index = connectingEndpoints.IndexOf(ep);
         connectingRetriesRemaining[index]--;
         if (connectingRetriesRemaining[index] <= 0)
         {
             // Retried max amount of times, notify failure:
             RemoveFromConnecting(ep, false);
             return;
         }
         connectingTimes[index] = NetTime.Milliseconds();
         NetLog.Info("Retrying connection to: " + ep);
     }
     // Send the connection request data to the endpoint:
     SendStream(ep, approvalData);
 }
示例#3
0
        /// <summary> Resends a lost message, updates its sent time, and increments the Resends stat. </summary>
        private void MessageLost(int index)
        {
            Resends++;
            NetStream strm = reliableWindow[sendWindow[index]];

            sendWindowTime[index] = NetTime.Milliseconds();
            Connection.Socket.SendStream(Connection, strm);
        }
示例#4
0
        /// <summary> Timeouts, disconnects, heartbeats, forced-acks, etc. need to be performed at end of frame. </summary>
        private void EndFrameTasks()
        {
            uint currentTime = NetTime.Milliseconds();

            for (int i = Connections.Count - 1; i >= 0; i--)
            {
                Connections[i].EndOfFrame(currentTime);
            }
            CheckForTimeouts();
        }
示例#5
0
 internal bool FlushStream()
 {
     if (sendStream == null)
     {
         return(false);
     }
     Connection.Socket.SendStream(Connection, sendStream);
     LastReliableSent        = NetTime.Milliseconds();
     Connection.LastSendTime = LastReliableSent;
     sendStream = null;
     return(true);
 }
示例#6
0
 internal NetConnection(bool isServer, bool isPeer, NetSocket socket, IPEndPoint endpoint, uint id = 0)
 {
     IsServer        = isServer;
     IsPeer          = isPeer;
     Socket          = socket;
     Endpoint        = endpoint;
     Id              = id;
     Unreliable      = new NetChannelUnreliable(this);
     Reliable        = new NetChannelReliable(this);
     LastReceiveTime = LastSendTime = Created = NetTime.Milliseconds();
     AddToGroup(0);
 }
示例#7
0
 /// <summary> Iterates through pending connections and retries any timeouts. </summary>
 private void CheckForTimeouts()
 {
     if (connectingEndpoints.Count == 0)
     {
         return;
     }
     for (int i = connectingEndpoints.Count - 1; i >= 0; i--)
     {
         if (NetTime.Milliseconds() - connectingTimes[i] > 2000)
         {
             Connect(connectingEndpoints[i], connectingData[i]);
         }
     }
 }
示例#8
0
        /// <summary> Removes acked messages from the send window, releases the stream, updates connection ping, and
        /// increments the Delivered stat. </summary>
        private void MessageDelivered(int index, NetHeader header)
        {
            Delivered++;
            NetStream strm = reliableWindow[sendWindow[index]];

            if (header.AckTime > 0)
            {
                Connection.UpdatePing(NetTime.Milliseconds(), sendWindowTime[index], header.AckTime);
            }
            reliableWindow.Remove(sendWindow[index]);
            sendWindow.RemoveAt(index);
            sendWindowTime.RemoveAt(index);
            strm.Release();
        }
示例#9
0
        /// <summary> Prepares the outgoing reliable stream: Writes the reliable bit & reliable header,
        /// sets stream parameters, and updates send stats. </summary>
        private NetHeader WriteHeader()
        {
            sendStream.Connection = Connection;
            sendStream.Socket     = Connection.Socket;

            sendStream.WriteBool(true);
            var header = NetHeader.Create(this, NetTime.Milliseconds());

            header.ToStream(sendStream);

            ReceivedSinceLastSend = 0;
            Sent++;

            return(header);
        }
示例#10
0
        /// <summary> Updates receive time and forwards stream to proper channel for deserialization. </summary>
        internal void ReceiveStream(NetStream stream)
        {
            stream.Connection = this;
            LastReceiveTime   = NetTime.Milliseconds();
            bool reliable = stream.ReadBool();

            if (!reliable)
            {
                Unreliable.DeserializeStream(stream);
            }
            else
            {
                Reliable.RouteIncomingStream(stream);
            }
        }
示例#11
0
        /// <summary>
        /// Starts the socket using the supplied endpoint.
        /// If the port is taken, the given port will be incremented to a free port.
        /// </summary>
        public void StartSocket(IPEndPoint endpoint)
        {
            Self   = new NetConnection(false, false, this, endpoint);
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            try {
                const uint IOC_IN            = 0x80000000;
                const uint IOC_VENDOR        = 0x18000000;
                uint       SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
                socket.IOControl((int)SIO_UDP_CONNRESET, new[] { Convert.ToByte(false) }, null);
            } catch {
                NetLog.Warning("Failed to set control code for ignoring ICMP port unreachable.");
            }

            socket.ReceiveBufferSize = 4194304;
            if (socket.ReceiveBufferSize != 4194304)
            {
                NetLog.Warning("ReceiveBufferSize restricted by OS.");
            }
            socket.SendBufferSize = 1048576;
            socket.Blocking       = false;

            try {
                socket.Bind(endpoint);
            } catch (SocketException e) {
                if (e.ErrorCode == 10048)
                {
                    var newEp = new IPEndPoint(endpoint.Address, endpoint.Port + 1);
                    NetLog.Warning("Port in use. Incrementing and retrying...");
                    StartSocket(newEp);
                }
                else
                {
                    NetLog.Error(e.Message);
                }
                return;
            }

            NetLog.Info(NetTime.StartDateTime() + " | Socket Started. Bound to: " + endpoint);
            NetTime.Milliseconds();

            if (ProtocolAuthority)
            {
                Rpc.AssignLocalRpcs();
            }
            Events.SocketStart();
        }
示例#12
0
        /// <summary> Checks all sent and unacked messages for timeout. Messages exceeding timeout are considered lost. </summary>
        internal void CheckTimeouts(uint currentTime)
        {
            if (currentTime - lastCheckTime < 333)
            {
                return;
            }

            lastCheckTime = currentTime;

            for (int i = 0; i < sendWindow.Count; i++)
            {
                if (NetTime.Milliseconds() - sendWindowTime[i] > 333)
                {
                    MessageLost(i);
                }
            }
        }
示例#13
0
        /// <summary> Acknowledges and updates the remote sequence. </summary>
        private void AckReceived(NetHeader header)
        {
            int newestDist = NetMath.SeqDistance(header.ObjSequence, NewestRemoteSequence);

            // If the sequence is newest, shift the buffer and apply ack bit:
            if (newestDist > 0)
            {
                AckHistory           = (AckHistory << newestDist) | 1UL;
                NewestRemoteSequence = header.ObjSequence;
            }
            // Else, shift the ack bit and apply to buffer:
            else
            {
                AckHistory |= 1UL << -newestDist;
            }

            LastReceiveTime = NetTime.Milliseconds();

            ReceivedSinceLastSend++;
            Received++;
        }