Exemple #1
0
 public void FreeUDPBuffer(UDPPacketBuffer buf)
 {
     lock (m_udpBuffersPoolLock)
     {
         if (m_udpBuffersPoolPtr < 999)
         {
             buf.RemoteEndPoint = null;
             buf.DataLength     = 0;
             m_udpBuffersPoolPtr++;
             m_udpBuffersPool[m_udpBuffersPoolPtr] = buf;
         }
     }
 }
Exemple #2
0
        /// <summary>
        /// Default constructor
        /// </summary>
        public OutgoingPacket(object client, byte[] buffer, int category, int dataSize, IPEndPoint destination,
                              bool fromBufferPool, Packets.PacketType type)
        {
            SequenceNumber = 0;
            ResendCount    = 0;
            TickCount      = 0;

            Client    = client;
            Category  = category;
            _fromPool = fromBufferPool;
            Type      = type;
            DataSize  = dataSize;
            Buffer    = new UDPPacketBuffer(buffer, dataSize, destination, category, fromBufferPool);
        }
Exemple #3
0
 public UDPPacketBuffer GetNewUDPBuffer(IPEndPoint remoteEndpoint)
 {
     lock (m_udpBuffersPoolLock)
     {
         if (m_udpBuffersPoolPtr >= 0)
         {
             UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr];
             m_udpBuffersPool[m_udpBuffersPoolPtr] = null;
             m_udpBuffersPoolPtr--;
             buf.RemoteEndPoint = remoteEndpoint;
             return(buf);
         }
     }
     return(new UDPPacketBuffer(remoteEndpoint));
 }
Exemple #4
0
        public void SendPacketData(byte[] data, int dataLength, PacketType type, bool doZerocode)
        {
            UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndPoint, Packet.MTU);

            // Zerocode if needed
            if (doZerocode)
            {
                try { dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data); }
                catch (IndexOutOfRangeException)
                {
                    // The packet grew larger than Packet.MTU bytes while zerocoding.
                    // Remove the MSG_ZEROCODED flag and send the unencoded data
                    // instead
                    data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
            }
            else
            {
                Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
            }
            buffer.DataLength = dataLength;

            #region Queue or Send

            NetworkManager.OutgoingPacket outgoingPacket = new NetworkManager.OutgoingPacket(this, buffer);

            // Send ACK and logout packets directly, everything else goes through the queue
            if (Client.Settings.THROTTLE_OUTGOING_PACKETS == false ||
                type == PacketType.PacketAck ||
                type == PacketType.LogoutRequest)
            {
                SendPacketFinal(outgoingPacket);
            }
            else
            {
                Network.PacketOutbox.Enqueue(outgoingPacket);
            }

            #endregion Queue or Send

            #region Stats Tracking
            if (Client.Settings.TRACK_UTILIZATION)
            {
                Client.Stats.Update(type.ToString(), OpenMetaverse.Stats.Type.Packet, dataLength, 0);
            }
            #endregion
        }
        private void AsyncEndReceive(IAsyncResult iar)
        {
            // Asynchronous receive operations will complete here through the call
            // to AsyncBeginReceive
            if (!m_shutdownFlag)
            {
                // Asynchronous mode will start another receive before the
                // callback for this packet is even fired. Very parallel :-)
                if (m_asyncPacketHandling)
                {
                    AsyncBeginReceive();
                }

                // get the buffer that was created in AsyncBeginReceive
                // this is the received data
                //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
                //UDPPacketBuffer buffer = wrappedBuffer.Instance;
                UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;

                try
                {
                    // get the length of data actually read from the socket, store it with the
                    // buffer
                    buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);

                    // call the abstract method PacketReceived(), passing the buffer that
                    // has just been filled from the socket read.
                    PacketReceived(buffer);
                }
                catch (SocketException)
                {
                }
                catch (ObjectDisposedException)
                {
                }
                finally
                {
                    //wrappedBuffer.Dispose();

                    // Synchronous mode waits until the packet callback completes
                    // before starting the receive to fetch another packet
                    if (!m_asyncPacketHandling)
                    {
                        AsyncBeginReceive();
                    }
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Disconnect from this simulator
        /// </summary>
        public void Disconnect(bool sendCloseCircuit)
        {
            if (connected)
            {
                connected = false;

                // Destroy the timers
                if (AckTimer != null)
                {
                    AckTimer.Dispose();
                }
                if (StatsTimer != null)
                {
                    StatsTimer.Dispose();
                }
                if (PingTimer != null)
                {
                    PingTimer.Dispose();
                }

                AckTimer   = null;
                StatsTimer = null;
                PingTimer  = null;

                // Kill the current CAPS system
                if (Caps != null)
                {
                    Caps.Disconnect(true);
                    Caps = null;
                }

                if (sendCloseCircuit)
                {
                    // Try to send the CloseCircuit notice
                    CloseCircuitPacket close = new CloseCircuitPacket();
                    UDPPacketBuffer    buf   = new UDPPacketBuffer(remoteEndPoint);
                    byte[]             data  = close.ToBytes();
                    Buffer.BlockCopy(data, 0, buf.Data, 0, data.Length);
                    buf.DataLength = data.Length;

                    AsyncBeginSend(buf);
                }

                // Shut the socket communication down
                Stop();
            }
        }
 public void FreeUDPBuffer(UDPPacketBuffer buf)
 {
     lock (m_udpBuffersPoolLock)
     {
         if (buf.DataLength < 0)
         {
             return; // avoid duplicated free that may still happen
         }
         if (m_udpBuffersPoolPtr < 999)
         {
             buf.RemoteEndPoint = null;
             buf.DataLength     = -1;
             m_udpBuffersPoolPtr++;
             m_udpBuffersPool[m_udpBuffersPoolPtr] = buf;
         }
     }
 }
Exemple #8
0
        private void AsyncBeginReceive()
        {
            // this method actually kicks off the async read on the socket.
            // we aquire a reader lock here to ensure that no other thread
            // is trying to set shutdownFlag and close the socket.
            rwLock.AcquireReaderLock(-1);

            if (!shutdownFlag)
            {
                // increment the count of pending operations
                Interlocked.Increment(ref rwOperationCount);

                // allocate a packet buffer
                //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
                UDPPacketBuffer buf = new UDPPacketBuffer();

                try
                {
                    // kick off an async read
                    udpSocket.BeginReceiveFrom(
                        //wrappedBuffer.Instance.Data,
                        buf.Data,
                        0,
                        UDPPacketBuffer.BUFFER_SIZE,
                        SocketFlags.None,
                        //ref wrappedBuffer.Instance.RemoteEndPoint,
                        ref buf.RemoteEndPoint,
                        new AsyncCallback(AsyncEndReceive),
                        //wrappedBuffer);
                        buf);
                }
                catch (SocketException)
                {
                    // something bad happened
                    //Logger.Log(
                    //    "A SocketException occurred in UDPServer.AsyncBeginReceive()",
                    //    Helpers.LogLevel.Error, se);

                    // an error occurred, therefore the operation is void.  Decrement the reference count.
                    Interlocked.Decrement(ref rwOperationCount);
                }
            }

            // we're done with the socket for now, release the reader lock.
            rwLock.ReleaseReaderLock();
        }
Exemple #9
0
 public void SyncSend(UDPPacketBuffer buf)
 {
     if (!m_shutdownFlag)
     {
         try
         {
             // well not async but blocking
             m_udpSocket.SendTo(
                 buf.Data,
                 0,
                 buf.DataLength,
                 SocketFlags.None,
                 buf.RemoteEndPoint);
         }
         catch (SocketException) { }
         catch (ObjectDisposedException) { }
     }
 }
Exemple #10
0
        public void AsyncBeginSend(UDPPacketBuffer buf)
        {
//            if (IsRunningOutbound)
//            {
            try
            {
                m_udpSocket.BeginSendTo(
                    buf.Data,
                    0,
                    buf.DataLength,
                    SocketFlags.None,
                    buf.RemoteEndPoint,
                    AsyncEndSend,
                    buf);
            }
            catch (SocketException) { }
            catch (ObjectDisposedException) { }
//            }
        }
Exemple #11
0
 public void SyncSend(UDPPacketBuffer buf)
 {
     try
     {
         m_udpSocket.SendTo(
             buf.Data,
             0,
             buf.DataLength,
             SocketFlags.None,
             buf.RemoteEndPoint
             );
         UdpSends++;
     }
     catch (SocketException e)
     {
         m_log.Warn("[UDPBASE]: sync send SocketException {0} " + e.Message);
     }
     catch (ObjectDisposedException) { }
 }
 public void AsyncBeginSend(UDPPacketBuffer buf)
 {
     if (!m_shutdownFlag)
     {
         try
         {
             m_udpSocket.BeginSendTo(
                 buf.Data,
                 0,
                 buf.DataLength,
                 SocketFlags.None,
                 buf.RemoteEndPoint,
                 AsyncEndSend,
                 buf);
         }
         catch (SocketException) { }
         catch (ObjectDisposedException) { }
     }
 }
/* not in use
 *      public void AsyncBeginSend(UDPPacketBuffer buf)
 *      {
 * //            if (IsRunningOutbound)
 * //            {
 *
 *              // This is strictly for debugging purposes to simulate dropped
 *              // packets when testing throttles & retransmission code
 *              // if (DropOutgoingPacket())
 *              //     return;
 *
 *              try
 *              {
 *                  m_udpSocket.BeginSendTo(
 *                      buf.Data,
 *                      0,
 *                      buf.DataLength,
 *                      SocketFlags.None,
 *                      buf.RemoteEndPoint,
 *                      AsyncEndSend,
 *                      buf);
 *              }
 *              catch (SocketException) { }
 *              catch (ObjectDisposedException) { }
 * //           }
 *      }
 *
 *      void AsyncEndSend(IAsyncResult result)
 *      {
 *          try
 *          {
 * //                UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
 *              m_udpSocket.EndSendTo(result);
 *
 *              UdpSends++;
 *          }
 *          catch (SocketException) { }
 *          catch (ObjectDisposedException) { }
 *      }
 */
        public void SyncSend(UDPPacketBuffer buf)
        {
            if (buf.RemoteEndPoint == null)
            {
                return; // already expired
            }
            try
            {
                m_udpSocket.SendTo(
                    buf.Data,
                    0,
                    buf.DataLength,
                    SocketFlags.None,
                    buf.RemoteEndPoint
                    );
                UdpSends++;
            }
            catch (SocketException e)
            {
                m_log.WarnFormat("[UDPBASE]: sync send SocketException {0} {1}", buf.RemoteEndPoint, e.Message);
            }
            catch (ObjectDisposedException) { }
        }
Exemple #14
0
        /// <summary>
        /// Send a raw byte array payload as a packet
        /// </summary>
        /// <param name="payload">The packet payload</param>
        /// <param name="setSequence">Whether the second, third, and fourth bytes
        /// should be modified to the current stream sequence number</param>
        public void SendPacketUnqueued(byte[] payload, bool setSequence)
        {
            try
            {
                if (setSequence && payload.Length > 3)
                {
                    uint sequence = (uint)Interlocked.Increment(ref Sequence);

                    payload[1] = (byte)(sequence >> 16);
                    payload[2] = (byte)(sequence >> 8);
                    payload[3] = (byte)(sequence % 256);
                }

                Stats.SentBytes += (ulong)payload.Length;
                ++Stats.SentPackets;

                UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint);
                Buffer.BlockCopy(payload, 0, buf.Data, 0, payload.Length);
                buf.DataLength = payload.Length;

                AsyncBeginSend(buf);
            }
            catch (SocketException)
            {
                Logger.Log("Tried to send a " + payload.Length +
                           " byte payload on a closed socket, shutting down " + this.ToString(),
                           Helpers.LogLevel.Info, Client);

                Network.DisconnectSim(this, false);
                return;
            }
            catch (Exception e)
            {
                Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e);
            }
        }
Exemple #15
0
        private void AsyncBeginReceive()
        {
            UDPPacketBuffer buf;

            // FIXME: Disabled for now as this causes issues with reused packet objects interfering with each other
            // on Windows with m_asyncPacketHandling = true, though this has not been seen on Linux.
            // Possibly some unexpected issue with fetching UDP data concurrently with multiple threads.  Requires more investigation.
//            if (UsePools)
//                buf = Pool.GetObject();
//            else
            buf = new UDPPacketBuffer();

            if (IsRunningInbound)
            {
                try
                {
                    // kick off an async read
                    m_udpSocket.BeginReceiveFrom(
                        //wrappedBuffer.Instance.Data,
                        buf.Data,
                        0,
                        UDPPacketBuffer.BUFFER_SIZE,
                        SocketFlags.None,
                        ref buf.RemoteEndPoint,
                        AsyncEndReceive,
                        //wrappedBuffer);
                        buf);
                }
                catch (SocketException e)
                {
                    if (e.SocketErrorCode == SocketError.ConnectionReset)
                    {
                        m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
                        bool salvaged = false;
                        while (!salvaged)
                        {
                            try
                            {
                                m_udpSocket.BeginReceiveFrom(
                                    //wrappedBuffer.Instance.Data,
                                    buf.Data,
                                    0,
                                    UDPPacketBuffer.BUFFER_SIZE,
                                    SocketFlags.None,
                                    ref buf.RemoteEndPoint,
                                    AsyncEndReceive,
                                    //wrappedBuffer);
                                    buf);
                                salvaged = true;
                            }
                            catch (SocketException) { }
                            catch (ObjectDisposedException) { return; }
                        }

                        m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
                    }
                }
                catch (ObjectDisposedException e)
                {
                    m_log.Error(
                        string.Format("[UDPBASE]: Error processing UDP begin receive {0}.  Exception  ", UdpReceives), e);
                }
                catch (Exception e)
                {
                    m_log.Error(
                        string.Format("[UDPBASE]: Error processing UDP begin receive {0}.  Exception  ", UdpReceives), e);
                }
            }
        }
Exemple #16
0
 protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent);
Exemple #17
0
 // these abstract methods must be implemented in a derived class to actually do
 // something with the packets that are sent and received.
 protected abstract void PacketReceived(UDPPacketBuffer buffer);
Exemple #18
0
 public OutgoingPacket(Simulator simulator, UDPPacketBuffer buffer, PacketType type)
 {
     Client    = simulator;
     Buffer    = buffer;
     this.Type = type;
 }
Exemple #19
0
        protected override void PacketReceived(UDPPacketBuffer buffer)
        {
            Packet packet = null;

            // Check if this packet came from the server we expected it to come from
            if (!remoteEndPoint.Address.Equals(((IPEndPoint)buffer.RemoteEndPoint).Address))
            {
                Logger.Log("Received " + buffer.DataLength + " bytes of data from unrecognized source " +
                           ((IPEndPoint)buffer.RemoteEndPoint).ToString(), Helpers.LogLevel.Warning, Client);
                return;
            }

            // Update the disconnect flag so this sim doesn't time out
            DisconnectCandidate = false;

            #region Packet Decoding

            int packetEnd = buffer.DataLength - 1;

            try
            {
                packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
                                            // Only allocate a buffer for zerodecoding if the packet is zerocoded
                                            ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[8192] : null);
            }
            catch (MalformedDataException)
            {
                Logger.Log(String.Format("Malformed data, cannot parse packet:\n{0}",
                                         Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)), Helpers.LogLevel.Error);
            }

            // Fail-safe check
            if (packet == null)
            {
                Logger.Log("Couldn't build a message from the incoming data", Helpers.LogLevel.Warning, Client);
                return;
            }

            Interlocked.Add(ref Stats.RecvBytes, buffer.DataLength);
            Interlocked.Increment(ref Stats.RecvPackets);

            #endregion Packet Decoding

            if (packet.Header.Resent)
            {
                Interlocked.Increment(ref Stats.ReceivedResends);
            }

            #region ACK Receiving

            // Handle appended ACKs
            if (packet.Header.AppendedAcks && packet.Header.AckList != null)
            {
                lock (NeedAck)
                {
                    for (int i = 0; i < packet.Header.AckList.Length; i++)
                    {
                        NeedAck.Remove(packet.Header.AckList[i]);
                    }
                }
            }

            // Handle PacketAck packets
            if (packet.Type == PacketType.PacketAck)
            {
                PacketAckPacket ackPacket = (PacketAckPacket)packet;

                lock (NeedAck)
                {
                    for (int i = 0; i < ackPacket.Packets.Length; i++)
                    {
                        NeedAck.Remove(ackPacket.Packets[i].ID);
                    }
                }
            }

            #endregion ACK Receiving

            if (packet.Header.Reliable)
            {
                #region ACK Sending

                // Add this packet to the list of ACKs that need to be sent out
                uint sequence = (uint)packet.Header.Sequence;
                PendingAcks.Enqueue(sequence);

                // Send out ACKs if we have a lot of them
                if (PendingAcks.Count >= Client.Settings.MAX_PENDING_ACKS)
                {
                    SendAcks();
                }

                #endregion ACK Sending

                // Check the archive of received packet IDs to see whether we already received this packet
                if (!PacketArchive.TryEnqueue(packet.Header.Sequence))
                {
                    if (packet.Header.Resent)
                    {
                        Logger.DebugLog("Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type);
                    }
                    else
                    {
                        Logger.Log("Received a duplicate (not marked as resend) of packet #" + packet.Header.Sequence + ", type: " + packet.Type,
                                   Helpers.LogLevel.Warning);
                    }

                    // Avoid firing a callback twice for the same packet
                    return;
                }
            }

            #region Inbox Insertion

            NetworkManager.IncomingPacket incomingPacket;
            incomingPacket.Simulator = this;
            incomingPacket.Packet    = packet;

            Network.PacketInbox.Enqueue(incomingPacket);

            #endregion Inbox Insertion

            #region Stats Tracking
            if (Client.Settings.TRACK_UTILIZATION)
            {
                Client.Stats.Update(packet.Type.ToString(), OpenMetaverse.Stats.Type.Packet, 0, packet.Length);
            }
            #endregion
        }
        private void AsyncBeginReceive()
        {
            // allocate a packet buffer
            //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
            UDPPacketBuffer buf = new UDPPacketBuffer();

            if (!m_shutdownFlag)
            {
                try
                {
                    // kick off an async read
                    m_udpSocket.BeginReceiveFrom(
                        //wrappedBuffer.Instance.Data,
                        buf.Data,
                        0,
                        UDPPacketBuffer.BUFFER_SIZE,
                        SocketFlags.None,
                        ref buf.RemoteEndPoint,
                        AsyncEndReceive,
                        //wrappedBuffer);
                        buf);
                }
                catch (SocketException e)
                {
                    if (e.SocketErrorCode == SocketError.ConnectionReset)
                    {
                        MainConsole.Instance.Warn(
                            "[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " +
                            m_udpPort);
                        bool salvaged = false;
                        while (!salvaged)
                        {
                            try
                            {
                                m_udpSocket.BeginReceiveFrom(
                                    //wrappedBuffer.Instance.Data,
                                    buf.Data,
                                    0,
                                    UDPPacketBuffer.BUFFER_SIZE,
                                    SocketFlags.None,
                                    ref buf.RemoteEndPoint,
                                    AsyncEndReceive,
                                    //wrappedBuffer);
                                    buf);
                                salvaged = true;
                            }
                            catch (SocketException)
                            {
                            }
                            catch (ObjectDisposedException)
                            {
                                return;
                            }
                        }

                        MainConsole.Instance.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
                    }
                }
                catch (ObjectDisposedException)
                {
                }
            }
        }
Exemple #21
0
 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
 {
 }
Exemple #22
0
        protected override void PacketReceived(UDPPacketBuffer buffer)
        {
            Packet packet = null;

            // Check if this packet came from the server we expected it to come from
            if (!ipEndPoint.Address.Equals(((IPEndPoint)buffer.RemoteEndPoint).Address))
            {
                Logger.Log("Received " + buffer.DataLength + " bytes of data from unrecognized source " +
                           ((IPEndPoint)buffer.RemoteEndPoint).ToString(), Helpers.LogLevel.Warning, Client);
                return;
            }

            // Update the disconnect flag so this sim doesn't time out
            DisconnectCandidate = false;

            #region Packet Decoding

            int packetEnd = buffer.DataLength - 1;

            try
            {
                packet = Packet.BuildPacket(buffer.Data, ref packetEnd, buffer.ZeroData);
            }
            catch (MalformedDataException)
            {
                Logger.Log(String.Format("Malformed data, cannot parse packet:\n{0}",
                                         Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)), Helpers.LogLevel.Error);
            }

            // Fail-safe check
            if (packet == null)
            {
                Logger.Log("Couldn't build a message from the incoming data", Helpers.LogLevel.Warning, Client);
                return;
            }

            Stats.RecvBytes += (ulong)buffer.DataLength;
            ++Stats.RecvPackets;

            #endregion Packet Decoding

            #region Reliable Handling

            if (packet.Header.Reliable)
            {
                // Add this packet to the list of ACKs that need to be sent out
                lock (PendingAcks)
                {
                    uint sequence = (uint)packet.Header.Sequence;
                    if (!PendingAcks.ContainsKey(sequence))
                    {
                        PendingAcks[sequence] = sequence;
                    }
                }

                // Send out ACKs if we have a lot of them
                if (PendingAcks.Count >= Client.Settings.MAX_PENDING_ACKS)
                {
                    SendAcks();
                }

                if (packet.Header.Resent)
                {
                    ++Stats.ReceivedResends;
                }
            }

            #endregion Reliable Handling

            #region Inbox Insertion

            NetworkManager.IncomingPacket incomingPacket;
            incomingPacket.Simulator = this;
            incomingPacket.Packet    = packet;

            // TODO: Prioritize the queue
            Network.PacketInbox.Enqueue(incomingPacket);

            #endregion Inbox Insertion
        }
Exemple #23
0
        private void AsyncEndReceive(IAsyncResult iar)
        {
            // Asynchronous receive operations will complete here through the call
            // to AsyncBeginReceive
            if (IsRunningInbound)
            {
                UdpReceives++;

                // Asynchronous mode will start another receive before the
                // callback for this packet is even fired. Very parallel :-)
                if (m_asyncPacketHandling)
                {
                    AsyncBeginReceive();
                }

                try
                {
                    // get the buffer that was created in AsyncBeginReceive
                    // this is the received data
                    UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;

                    int startTick = Util.EnvironmentTickCount();

                    // get the length of data actually read from the socket, store it with the
                    // buffer
                    buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);

                    // call the abstract method PacketReceived(), passing the buffer that
                    // has just been filled from the socket read.
                    PacketReceived(buffer);

                    // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler)
                    // then a particular stat may be inaccurate due to a race condition.  We won't worry about this
                    // since this should be rare and  won't cause a runtime problem.
                    if (m_currentReceiveTimeSamples >= s_receiveTimeSamples)
                    {
                        AverageReceiveTicksForLastSamplePeriod
                            = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples;

                        m_receiveTicksInCurrentSamplePeriod = 0;
                        m_currentReceiveTimeSamples         = 0;
                    }
                    else
                    {
                        m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick);
                        m_currentReceiveTimeSamples++;
                    }
                }
                catch (SocketException se)
                {
                    m_log.Error(
                        string.Format(
                            "[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}.  Exception  ",
                            UdpReceives, se.ErrorCode),
                        se);
                }
                catch (ObjectDisposedException e)
                {
                    m_log.Error(
                        string.Format("[UDPBASE]: Error processing UDP end receive {0}.  Exception  ", UdpReceives), e);
                }
                catch (Exception e)
                {
                    m_log.Error(
                        string.Format("[UDPBASE]: Error processing UDP end receive {0}.  Exception  ", UdpReceives), e);
                }
                finally
                {
//                    if (UsePools)
//                        Pool.ReturnObject(buffer);

                    // Synchronous mode waits until the packet callback completes
                    // before starting the receive to fetch another packet
                    if (!m_asyncPacketHandling)
                    {
                        AsyncBeginReceive();
                    }
                }
            }
        }
Exemple #24
0
 /// <summary>
 /// This method is called when an incoming packet is received
 /// </summary>
 /// <param name="buffer">Incoming packet buffer</param>
 public abstract void PacketReceived(UDPPacketBuffer buffer);
Exemple #25
0
        /// <summary>
        /// Sends a packet directly to the simulator without queuing
        /// </summary>
        /// <param name="packet">Packet to be sent</param>
        /// <param name="setSequence">True to set the sequence number, false to
        /// leave it as is</param>
        public void SendPacketUnqueued(Packet packet, bool setSequence)
        {
            byte[] buffer;
            int    bytes;

            // Set sequence implies that this is not a resent packet
            if (setSequence)
            {
                // Reset to zero if we've hit the upper sequence number limit
                Interlocked.CompareExchange(ref Sequence, 0, Settings.MAX_SEQUENCE);
                // Increment and fetch the current sequence number
                packet.Header.Sequence = (uint)Interlocked.Increment(ref Sequence);

                if (packet.Header.Reliable)
                {
                    // Wrap this packet in a struct to track timeouts and resends
                    NetworkManager.OutgoingPacket outgoing = new NetworkManager.OutgoingPacket(this, packet, true);
                    // Keep track of when this packet was first sent out (right now)
                    outgoing.TickCount = Environment.TickCount;

                    // Add this packet to the list of ACK responses we are waiting on from the server
                    lock (NeedAck)
                    {
                        NeedAck[packet.Header.Sequence] = outgoing;
                    }

                    if (packet.Header.Resent)
                    {
                        // This packet has already been sent out once, strip any appended ACKs
                        // off it and reinsert them into the outgoing ACK queue under the
                        // assumption that this packet will continually be rejected from the
                        // server or that the appended ACKs are possibly making the delivery fail
                        if (packet.Header.AckList.Length > 0)
                        {
                            Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
                                                          packet.Header.Sequence, packet.GetType()));

                            lock (PendingAcks)
                            {
                                foreach (uint sequence in packet.Header.AckList)
                                {
                                    if (!PendingAcks.ContainsKey(sequence))
                                    {
                                        PendingAcks[sequence] = sequence;
                                    }
                                }
                            }

                            packet.Header.AppendedAcks = false;
                            packet.Header.AckList      = new uint[0];
                        }

                        // Update the sent time for this packet
                        SetResentTime(packet.Header.Sequence);
                    }
                    else
                    {
                        // This packet is not a resend, check if the conditions are favorable
                        // to ACK appending
                        if (packet.Type != PacketType.PacketAck &&
                            packet.Type != PacketType.LogoutRequest)
                        {
                            lock (PendingAcks)
                            {
                                if (PendingAcks.Count > 0 &&
                                    PendingAcks.Count < Client.Settings.MAX_APPENDED_ACKS)
                                {
                                    // Append all of the queued up outgoing ACKs to this packet
                                    packet.Header.AckList = new uint[PendingAcks.Count];

                                    for (int i = 0; i < PendingAcks.Count; i++)
                                    {
                                        packet.Header.AckList[i] = PendingAcks.Values[i];
                                    }

                                    PendingAcks.Clear();
                                    packet.Header.AppendedAcks = true;
                                }
                            }
                        }
                    }
                }
                else if (packet.Header.AckList.Length > 0)
                {
                    // Sanity check for ACKS appended on an unreliable packet, this is bad form
                    Logger.Log("Sending appended ACKs on an unreliable packet", Helpers.LogLevel.Warning);
                }
            }

            // Serialize the packet
            buffer           = packet.ToBytes();
            bytes            = buffer.Length;
            Stats.SentBytes += (ulong)bytes;
            ++Stats.SentPackets;

            UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint);

            // Zerocode if needed
            if (packet.Header.Zerocoded)
            {
                bytes = Helpers.ZeroEncode(buffer, bytes, buf.Data);
            }
            else
            {
                Buffer.BlockCopy(buffer, 0, buf.Data, 0, bytes);
            }

            buf.DataLength = bytes;

            AsyncBeginSend(buf);
        }