Exemplo n.º 1
0
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">Serialized packet data. If the flags or sequence number
 /// need to be updated, they will be injected directly into this binary buffer</param>
 /// <param name="category">Throttling category for this packet</param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method)
 {
     Client = client;
     Buffer = buffer;
     Category = category;
     UnackedMethod = method;
 }
Exemplo n.º 2
0
        private void AsyncBeginReceive()
        {
            lock (typeof(Constants))
            {
                if (!Constants.isClosing)
                {
                    // allocate a packet buffer
                    UDPPacketBuffer buf = new UDPPacketBuffer();

                    try
                    {
                        // kick off an async read
                        udpSocket.BeginReceiveFrom(
                            buf.Data,
                            0,
                            UDPPacketBuffer.BUFFER_SIZE,
                            SocketFlags.None,
                            ref buf.RemoteEndPoint,
                            new AsyncCallback(AsyncEndReceive),
                            buf);
                    }
                    catch (SocketException se)
                    {
                        txtReceive.Text = se.Message + System.Environment.NewLine + txtReceive.Text;
                    }
                }
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">Serialized packet data. If the flags or sequence number
 /// need to be updated, they will be injected directly into this binary buffer</param>
 /// <param name="category">Throttling category for this packet</param>
 /// <param name="resendMethod">The delegate to be called if this packet is determined to be unacknowledged</param>
 /// <param name="finishedMethod">The delegate to be called when this packet is sent</param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer,
     ThrottleOutPacketType category, UnackedPacketMethod resendMethod,
     UnackedPacketMethod finishedMethod, Packet packet)
 {
     Client = client;
     Buffer = buffer;
     Category = category;
     UnackedMethod = resendMethod;
     FinishedMethod = finishedMethod;
     Packet = packet;
 }
Exemplo n.º 4
0
        private void HandleUseCircuitCode(object o)
        {
            object[]             array  = (object[])o;
            UDPPacketBuffer      buffer = (UDPPacketBuffer)array[0];
            UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1];

            IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;

            // Begin the process of adding the client to the simulator
            AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint);

            // Acknowledge the UseCircuitCode packet
            SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
        }
Exemplo n.º 5
0
        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
                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)
                {
                }
                catch (Exception ex)
                {
                    MainConsole.Instance.Error("[UDPBase]: Hit error: " + ex.ToString());
                }
                finally
                {
                    // Synchronous mode waits until the packet callback completes
                    // before starting the receive to fetch another packet
                    if (!m_asyncPacketHandling)
                    {
                        AsyncBeginReceive();
                    }
                }
            }
        }
Exemplo n.º 6
0
        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 (Exception e)
                {
                    m_log.ErrorFormat("[LLUDP] Exception thrown from UDP EndReceiveFrom: {0}", e);
                }
                finally
                {
                    //wrappedBuffer.Dispose();

                    // Synchronous mode waits until the packet callback completes
                    // before starting the receive to fetch another packet
                    if (!m_asyncPacketHandling)
                    {
                        AsyncBeginReceive();
                    }
                }
            }
        }
Exemplo n.º 7
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) {
         } catch (Exception) {
         }
     }
 }
Exemplo n.º 8
0
        private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
        {
            PacketAckPacket ack = new PacketAckPacket();

            ack.Header.Reliable = false;
            ack.Packets         = new PacketAckPacket.PacketsBlock[1];
            ack.Packets[0]      = new PacketAckPacket.PacketsBlock();
            ack.Packets[0].ID   = sequenceNumber;

            byte[] packetData = ack.ToBytes();
            int    length     = packetData.Length;

            UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length);

            buffer.DataLength = length;

            Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);

            AsyncBeginSend(buffer);
        }
Exemplo n.º 9
0
        private void HandleUseCircuitCode(object o)
        {
            DateTime startTime = DateTime.Now;

            object[]             array  = (object[])o;
            UDPPacketBuffer      buffer = (UDPPacketBuffer)array[0];
            UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1];

            IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;

            // Begin the process of adding the client to the simulator
            if (AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint))
            {
                // Acknowledge the UseCircuitCode packet
                SendAckImmediate(remoteEndPoint, packet.Header.Sequence);

                m_log.InfoFormat(
                    "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
                    remoteEndPoint, (DateTime.Now - startTime).Milliseconds);
            }
        }
Exemplo n.º 10
0
        private void AsyncBeginReceive()
        {
            // allocate a packet buffer
            //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
            UDPPacketBuffer buf = _recvBufferPool.LeaseObject();

            if (!m_shutdownFlag)
            {
                bool recvFromRunning = false;
                while (!recvFromRunning)
                {
                    try
                    {
                        // kick off an async read
                        m_udpSocket.BeginReceiveFrom(
                            //wrappedBuffer.Instance.Data,
                            buf.Data,
                            0,
                            UDPPacketBuffer.BUFFER_SIZE,
                            SocketFlags.None,
                            ref buf.RemoteEndPoint,
                            AsyncEndReceive,
                            buf);

                        recvFromRunning = true;
                    }
                    catch (SocketException e)
                    {
                        m_log.ErrorFormat("[LLUDP] SocketException thrown from UDP BeginReceiveFrom, retrying: {0}", e);
                    }
                    catch (Exception e)
                    {
                        m_log.ErrorFormat("[LLUDP] Exception thrown from UDP BeginReceiveFrom: {0}", e);
                        //UDP is toast and will not recover. The sim is for all intents and purposes, dead.
                        throw;
                    }
                }
            }
        }
Exemplo n.º 11
0
        void SendPacket(UDPClient client, Packet packet, PacketCategory category, 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 client.CurrentSequence, 0, 0xFFFFFF);
                // Increment and fetch the current sequence number
                uint sequence = (uint)Interlocked.Increment(ref client.CurrentSequence);
                packet.Header.Sequence = sequence;

                if (packet.Header.Reliable)
                {
                    OutgoingPacket outgoing;

                    if (packet.Header.Resent && client.NeedAcks.TryGetValue(packet.Header.Sequence, out outgoing))
                    {
                        // 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
                        // client 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 (client.PendingAcks)
                            {
                                foreach (uint ack in packet.Header.AckList)
                                {
                                    if (!client.PendingAcks.ContainsKey(ack))
                                    {
                                        client.PendingAcks[ack] = ack;
                                    }
                                }
                            }

                            packet.Header.AppendedAcks = false;
                            packet.Header.AckList      = new uint[0];
                        }
                    }
                    else
                    {
                        // Wrap this packet in a struct to track timeouts and resends
                        outgoing = new OutgoingPacket(packet);

                        // Add this packet to the list of ACK responses we are waiting on from this client
                        lock (client.NeedAcks)
                            client.NeedAcks[sequence] = outgoing;

                        // This packet is not a resend, check if the conditions are favorable
                        // to ACK appending
                        if (packet.Type != PacketType.PacketAck)
                        {
                            lock (client.PendingAcks)
                            {
                                int count = client.PendingAcks.Count;

                                if (count > 0 && count < 10)
                                {
                                    // Append all of the queued up outgoing ACKs to this packet
                                    packet.Header.AckList = new uint[count];

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

                                    client.PendingAcks.Clear();
                                    packet.Header.AppendedAcks = true;
                                }
                            }
                        }
                    }

                    // Update the sent time for this packet
                    outgoing.TickCount = Environment.TickCount;
                }
                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(client.Address);

            // 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);
        }
Exemplo n.º 12
0
 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
 {
 }
Exemplo n.º 13
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
        }
Exemplo n.º 14
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);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Used by tests that aren't testing this stage.
        /// </summary>
        private ScenePresence AddClient()
        {
            UUID myAgentUuid   = TestHelpers.ParseTail(0x1);
            UUID mySessionUuid = TestHelpers.ParseTail(0x2);
            uint myCircuitCode = 123456;
            IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);

            UseCircuitCodePacket uccp = new UseCircuitCodePacket();

            UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
                = new UseCircuitCodePacket.CircuitCodeBlock();
            uccpCcBlock.Code = myCircuitCode;
            uccpCcBlock.ID = myAgentUuid;
            uccpCcBlock.SessionID = mySessionUuid;
            uccp.CircuitCode = uccpCcBlock;

            byte[] uccpBytes = uccp.ToBytes();
            UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
            upb.DataLength = uccpBytes.Length;  // God knows why this isn't set by the constructor.
            Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);

            AgentCircuitData acd = new AgentCircuitData();
            acd.AgentID = myAgentUuid;
            acd.SessionID = mySessionUuid;

            m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);

            m_udpServer.PacketReceived(upb);

            return m_scene.GetScenePresence(myAgentUuid);
        }
Exemplo n.º 16
0
        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)
                    {
                        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) { }
            }
        }
Exemplo n.º 17
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 (Network.ThrottleOutgoingPackets == false ||
                type == PacketType.PacketAck ||
                type == PacketType.LogoutRequest)
            {
                SendPacketFinal(outgoingPacket);
            }
            else
            {
                Network.PacketOutbox.Enqueue(outgoingPacket);
            }

            #endregion Queue or Send
        }
Exemplo n.º 18
0
 /// <summary>
 /// This method is called when an incoming packet is received
 /// </summary>
 /// <param name="buffer">Incoming packet buffer</param>
 protected abstract void PacketReceived(UDPPacketBuffer buffer);
Exemplo n.º 19
0
        protected override void PacketReceived(UDPPacketBuffer buffer)
        {
            UDPClient  client    = null;
            Packet     packet    = null;
            int        packetEnd = buffer.DataLength - 1;
            IPEndPoint address   = (IPEndPoint)buffer.RemoteEndPoint;

            // Decoding
            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);
                return;
            }

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

            if (packet.Type == PacketType.UseCircuitCode)
            {
                UseCircuitCodePacket useCircuitCode = (UseCircuitCodePacket)packet;

                Agent agent;
                if (CompleteAgentConnection(useCircuitCode.CircuitCode.Code, out agent))
                {
                    AddClient(agent, address);
                    if (clients.TryGetValue(agent.AgentID, out client))
                    {
                        Logger.Log("Activated UDP circuit " + useCircuitCode.CircuitCode.Code, Helpers.LogLevel.Info);
                    }
                    else
                    {
                        Logger.Log("Failed to locate newly created UDPClient", Helpers.LogLevel.Error);
                        return;
                    }
                }
                else
                {
                    Logger.Log("Received a UseCircuitCode packet for an unrecognized circuit: " +
                               useCircuitCode.CircuitCode.Code.ToString(), Helpers.LogLevel.Warning);
                    return;
                }
            }
            else
            {
                // Determine which agent this packet came from
                if (!clients.TryGetValue(address, out client))
                {
                    Logger.Log("Received UDP packet from an unrecognized source: " + address.ToString(),
                               Helpers.LogLevel.Warning);
                    return;
                }
            }

            client.Agent.TickLastPacketReceived = Environment.TickCount;

            // Reliable handling
            if (packet.Header.Reliable)
            {
                // Queue up this sequence number for acknowledgement
                QueueAck(client, (uint)packet.Header.Sequence);
                //if (packet.Header.Resent) ++Stats.ReceivedResends;
            }

            // Inbox insertion
            IncomingPacket incomingPacket;

            incomingPacket.Client = client;
            incomingPacket.Packet = packet;

            // TODO: Prioritize the queue
            packetInbox.Enqueue(incomingPacket);
        }
Exemplo n.º 20
0
 /// <summary>
 /// Called when the packet is built and this buffer is no longer in use
 /// </summary>
 /// <param name="buffer"></param>
 protected void PacketBuildingFinished(UDPPacketBuffer buffer)
 {
     buffer.ResetEndpoint();
     _recvBufferPool.ReturnObject(buffer);
 }
Exemplo n.º 21
0
 protected override void PacketReceived(UDPPacketBuffer buffer)
 {
     UIForm._NetRecvData(buffer);
 }
Exemplo n.º 22
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
        }
Exemplo n.º 23
0
        public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category)
        {
            int  dataLength = data.Length;
            bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
            bool doCopy     = true;

            // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
            // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
            // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
            // to accomodate for both common scenarios and provide ample room for ACK appending in both
            int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;

            UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

            // Zerocode if needed
            if (doZerocode)
            {
                try
                {
                    dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
                    doCopy     = false;
                }
                catch (IndexOutOfRangeException)
                {
                    // The packet grew larger than the bufferSize while zerocoding.
                    // Remove the MSG_ZEROCODED flag and send the unencoded data
                    // instead
                    m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
                                " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
                    data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
                }
            }

            // If the packet data wasn't already copied during zerocoding, copy it now
            if (doCopy)
            {
                if (dataLength <= buffer.Data.Length)
                {
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
                else
                {
                    bufferSize = dataLength;
                    buffer     = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

                    // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                    //     type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);

            if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
            {
                SendPacketFinal(outgoingPacket);
            }

            #endregion Queue or Send
        }
Exemplo n.º 24
0
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">Serialized packet data. If the flags or sequence number
 /// need to be updated, they will be injected directly into this binary buffer</param>
 /// <param name="category">Throttling category for this packet</param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category)
 {
     Client   = client;
     Buffer   = buffer;
     Category = category;
 }
Exemplo n.º 25
0
        /// <summary>
        /// Actually send a packet to a client.
        /// </summary>
        /// <param name="outgoingPacket"></param>
        internal void SendPacketFinal(OutgoingPacket outgoingPacket)
        {
            UDPPacketBuffer buffer      = outgoingPacket.Buffer;
            byte            flags       = buffer.Data[0];
            bool            isResend    = (flags & Helpers.MSG_RESENT) != 0;
            bool            isReliable  = (flags & Helpers.MSG_RELIABLE) != 0;
            bool            isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0;
            LLUDPClient     udpClient   = outgoingPacket.Client;

            if (!udpClient.IsConnected)
            {
                return;
            }

            #region ACK Appending

            int dataLength = buffer.DataLength;

            // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here
            if (!isZerocoded)
            {
                // Keep appending ACKs until there is no room left in the buffer or there are
                // no more ACKs to append
                uint ackCount = 0;
                uint ack;
                while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack))
                {
                    Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
                    dataLength += 4;
                    ++ackCount;
                }

                if (ackCount > 0)
                {
                    // Set the last byte of the packet equal to the number of appended ACKs
                    buffer.Data[dataLength++] = (byte)ackCount;
                    // Set the appended ACKs flag on this packet
                    buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
                }
            }

            buffer.DataLength = dataLength;

            #endregion ACK Appending

            #region Sequence Number Assignment

            if (!isResend)
            {
                // Not a resend, assign a new sequence number
                uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
                Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
                outgoingPacket.SequenceNumber = sequenceNumber;

                if (isReliable)
                {
                    // Add this packet to the list of ACK responses we are waiting on from the server
                    udpClient.NeedAcks.Add(outgoingPacket);
                }
            }

            #endregion Sequence Number Assignment

            // Stats tracking
            Interlocked.Increment(ref udpClient.PacketsSent);
            if (isReliable)
            {
                Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength);
            }

            // Put the UDP payload on the wire
            AsyncBeginSend(buffer);

            // Keep track of when this packet was sent out (right now)
            outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
        }
Exemplo n.º 26
0
 /// <summary>
 /// Called when the packet is built and this buffer is no longer in use
 /// </summary>
 /// <param name="buffer"></param>
 protected void PacketBuildingFinished(UDPPacketBuffer buffer)
 {
     buffer.ResetEndpoint();
     _recvBufferPool.ReturnObject(buffer);
 }
Exemplo n.º 27
0
        protected override void PacketReceived(UDPPacketBuffer buffer)
        {
            // Debugging/Profiling
            //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
            //catch (Exception) { }

            LLUDPClient udpClient = null;
            Packet      packet    = null;
            int         packetEnd = buffer.DataLength - 1;
            IPEndPoint  address   = (IPEndPoint)buffer.RemoteEndPoint;

            #region Decoding

            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[4096] : null);
            }
            catch (MalformedDataException)
            {
            }

            // Fail-safe check
            if (packet == null)
            {
                m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:",
                                  buffer.DataLength, buffer.RemoteEndPoint);
                m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
                return;
            }

            #endregion Decoding

            #region Packet to Client Mapping

            // UseCircuitCode handling
            if (packet.Type == PacketType.UseCircuitCode)
            {
                object[] array = new object[] { buffer, packet };

                if (m_asyncPacketHandling)
                {
                    Util.FireAndForget(HandleUseCircuitCode, array);
                }
                else
                {
                    HandleUseCircuitCode(array);
                }

                return;
            }

            // Determine which agent this packet came from
            IClientAPI client;
            if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
            {
                //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
                return;
            }

            udpClient = ((LLClientView)client).UDPClient;

            if (!udpClient.IsConnected)
            {
                return;
            }

            #endregion Packet to Client Mapping

            // Stats tracking
            Interlocked.Increment(ref udpClient.PacketsReceived);

            int now = Environment.TickCount & Int32.MaxValue;
            udpClient.TickLastPacketReceived = now;

            #region ACK Receiving

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

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

                for (int i = 0; i < ackPacket.Packets.Length; i++)
                {
                    udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent);
                }

                // We don't need to do anything else with PacketAck packets
                return;
            }

            #endregion ACK Receiving

            #region ACK Sending

            if (packet.Header.Reliable)
            {
                udpClient.PendingAcks.Enqueue(packet.Header.Sequence);

                // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
                // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
                // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
                // client.BytesSinceLastACK. Lockless thread safety
                int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
                bytesSinceLastACK += buffer.DataLength;
                if (bytesSinceLastACK > LLUDPServer.MTU * 2)
                {
                    bytesSinceLastACK -= LLUDPServer.MTU * 2;
                    SendAcks(udpClient);
                }
                Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
            }

            #endregion ACK Sending

            #region Incoming Packet Accounting

            // Check the archive of received reliable packet IDs to see whether we already received this packet
            if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
            {
                if (packet.Header.Resent)
                {
                    m_log.DebugFormat(
                        "[LLUDPSERVER]: Received a resend of already processed packet #{0}, type {1} from {2}",
                        packet.Header.Sequence, packet.Type, client.Name);
                }
                else
                {
                    m_log.WarnFormat(
                        "[LLUDPSERVER]: Received a duplicate (not marked as resend) of packet #{0}, type {1} from {2}",
                        packet.Header.Sequence, packet.Type, client.Name);
                }

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

            #endregion Incoming Packet Accounting

            #region BinaryStats
            LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
            #endregion BinaryStats

            #region Ping Check Handling

            if (packet.Type == PacketType.StartPingCheck)
            {
                // We don't need to do anything else with ping checks
                StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
                CompletePing(udpClient, startPing.PingID.PingID);

                if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000)
                {
                    udpClient.SendPacketStats();
                    m_elapsedMSSinceLastStatReport = Environment.TickCount;
                }
                return;
            }
            else if (packet.Type == PacketType.CompletePingCheck)
            {
                // We don't currently track client ping times
                return;
            }

            #endregion Ping Check Handling

            // Inbox insertion
            packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
        }
Exemplo n.º 28
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) { }
     }
 }
Exemplo n.º 29
0
        public void SendPacketData(LLUDPClient udpClient, byte[] data, Packet packet, ThrottleOutPacketType category, UnackedPacketMethod resendMethod, UnackedPacketMethod finishedMethod)
        {
            int dataLength = data.Length;
            bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
            bool doCopy = true;

            // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
            // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
            // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
            // to accomodate for both common scenarios and provide ample room for ACK appending in both
            int bufferSize = dataLength * 2;

            UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

            // Zerocode if needed
            if (doZerocode)
            {
                try
                {
                    dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
                    doCopy = false;
                }
                catch (IndexOutOfRangeException)
                {
                    // The packet grew larger than the bufferSize while zerocoding.
                    // Remove the MSG_ZEROCODED flag and send the unencoded data
                    // instead
                    m_log.Info("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + packet.Type + ". DataLength=" + dataLength +
                        " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
                    data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
                }
            }

            // If the packet data wasn't already copied during zerocoding, copy it now
            if (doCopy)
            {
                if (dataLength <= buffer.Data.Length)
                {
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
                else
                {
                    bufferSize = dataLength;
                    buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

                    // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                    //     type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, resendMethod, finishedMethod, packet);

            if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
                SendPacketFinal(outgoingPacket);

            #endregion Queue or Send
        }
Exemplo n.º 30
0
        public void TestAddClient()
        {
            TestHelpers.InMethod();
//            TestHelpers.EnableLogging();

            AddUdpServer();

            UUID myAgentUuid   = TestHelpers.ParseTail(0x1);
            UUID mySessionUuid = TestHelpers.ParseTail(0x2);
            uint myCircuitCode = 123456;
            IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);

            UseCircuitCodePacket uccp = new UseCircuitCodePacket();

            UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
                = new UseCircuitCodePacket.CircuitCodeBlock();
            uccpCcBlock.Code = myCircuitCode;
            uccpCcBlock.ID = myAgentUuid;
            uccpCcBlock.SessionID = mySessionUuid;
            uccp.CircuitCode = uccpCcBlock;

            byte[] uccpBytes = uccp.ToBytes();
            UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
            upb.DataLength = uccpBytes.Length;  // God knows why this isn't set by the constructor.
            Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);

            m_udpServer.PacketReceived(upb);

            // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
            Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null);

            AgentCircuitData acd = new AgentCircuitData();
            acd.AgentID = myAgentUuid;
            acd.SessionID = mySessionUuid;

            m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);

            m_udpServer.PacketReceived(upb);

            // Should succeed now
            ScenePresence sp = m_scene.GetScenePresence(myAgentUuid);
            Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));

            Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1));

            Packet packet = m_udpServer.PacketsSent[0];
            Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));

            PacketAckPacket ackPacket = packet as PacketAckPacket;
            Assert.That(ackPacket.Packets.Length, Is.EqualTo(1));
            Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
        }
Exemplo n.º 31
0
        private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
        {
            PacketAckPacket ack = new PacketAckPacket();
            ack.Header.Reliable = false;
            ack.Packets = new PacketAckPacket.PacketsBlock[1];
            ack.Packets[0] = new PacketAckPacket.PacketsBlock();
            ack.Packets[0].ID = sequenceNumber;

            byte[] packetData = ack.ToBytes();
            int length = packetData.Length;

            UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length);
            buffer.DataLength = length;

            Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);

            //            AsyncBeginSend(buffer);
            SyncSend(buffer);

        }
Exemplo n.º 32
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);
            }
        }
Exemplo n.º 33
0
        public virtual void SendAckImmediate(IPEndPoint remoteEndpoint, PacketAckPacket ack)
        {
            byte[] packetData = ack.ToBytes();
            int length = packetData.Length;

            UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length);
            buffer.DataLength = length;

            Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);

            AsyncBeginSend(buffer);
        }
Exemplo n.º 34
0
 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
 {
 }
Exemplo n.º 35
0
        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)
                {
                }
            }
        }
Exemplo n.º 36
0
        protected override void PacketReceived(UDPPacketBuffer buffer)
        {
            // Debugging/Profiling
            //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
            //catch (Exception) { }

            LLUDPClient udpClient = null;
            Packet packet = null;
            int packetEnd = buffer.DataLength - 1;
            IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;

            #region Decoding

            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[4096] : null);
            }
            catch (MalformedDataException)
            {
            }

            // Fail-safe check
            if (packet == null)
            {
                m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:",
                    buffer.DataLength, buffer.RemoteEndPoint);
                m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
                return;
            }

            #endregion Decoding

            #region Packet to Client Mapping

            // UseCircuitCode handling
            if (packet.Type == PacketType.UseCircuitCode)
            {
                object[] array = new object[] { buffer, packet };

                if (m_asyncPacketHandling)
                    Util.FireAndForget(HandleUseCircuitCode, array);
                else
                    HandleUseCircuitCode(array);

                return;
            }

            // Determine which agent this packet came from
            IClientAPI client;
            if (!m_scene.ClientManager.TryGetValue (address, out client) || !(client is LLClientView))
            {
                if(client != null)
                    m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
                return;
            }

            udpClient = ((LLClientView)client).UDPClient;

            if (!udpClient.IsConnected)
                return;

            #endregion Packet to Client Mapping

            // Stats tracking
            Interlocked.Increment(ref udpClient.PacketsReceived);

            int now = Environment.TickCount & Int32.MaxValue;
            udpClient.TickLastPacketReceived = now;

            #region ACK Receiving

            // Handle appended ACKs
            if (packet.Header.AppendedAcks && packet.Header.AckList != null)
            {
                for (int i = 0; i < packet.Header.AckList.Length; i++)
                    udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
            }

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

                for (int i = 0; i < ackPacket.Packets.Length; i++)
                    udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);

                // We don't need to do anything else with PacketAck packets
                return;
            }

            #endregion ACK Receiving

            #region ACK Sending

            if (packet.Header.Reliable)
            {
                udpClient.PendingAcks.Enqueue(packet.Header.Sequence);

                // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
                // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
                // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
                // client.BytesSinceLastACK. Lockless thread safety
                int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
                bytesSinceLastACK += buffer.DataLength;
                if (bytesSinceLastACK > LLUDPServer.MTU * 2)
                {
                    bytesSinceLastACK -= LLUDPServer.MTU * 2;
                    SendAcks(udpClient);
                }
                Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
            }

            #endregion ACK Sending

            #region Incoming Packet Accounting

            // Check the archive of received reliable packet IDs to see whether we already received this packet
            if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
            {
                //if (packet.Header.Resent)
                //    m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type);
                //else
                //    m_log.Warn("[LLUDPSERVER]: Received a duplicate (not marked as resend) of packet #" + packet.Header.Sequence + ", type: " + packet.Type);

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

            #endregion Incoming Packet Accounting

            #region BinaryStats
            LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
            #endregion BinaryStats

            #region Ping Check Handling

            if (packet.Type == PacketType.StartPingCheck)
            {
                // We don't need to do anything else with ping checks
                StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
                CompletePing(udpClient, startPing.PingID.PingID);

                if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000)
                {
                    udpClient.SendPacketStats();
                    m_elapsedMSSinceLastStatReport = Environment.TickCount;
                }
                return;
            }
            else if (packet.Type == PacketType.CompletePingCheck)
            {
                // We don't currently track client ping times
                return;
            }

            #endregion Ping Check Handling

            // Inbox insertion
            packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
        }
Exemplo n.º 37
0
        public void AsyncBeginSend(UDPPacketBuffer buf)
        {
            rwLock.AcquireReaderLock(-1);

            if (!shutdownFlag)
            {
                try
                {
                    Interlocked.Increment(ref rwOperationCount);
                    udpSocket.BeginSendTo(
                        buf.Data,
                        0,
                        buf.DataLength,
                        SocketFlags.None,
                        buf.RemoteEndPoint,
                        new AsyncCallback(AsyncEndSend),
                        buf);
                }
                catch (SocketException)
                {
                    //Logger.Log(
                    //    "A SocketException occurred in UDPServer.AsyncBeginSend()",
                    //    Helpers.LogLevel.Error, se);
                }
            }

            rwLock.ReleaseReaderLock();
        }
Exemplo n.º 38
0
        public override void PacketReceived(UDPPacketBuffer buffer)
        {
            // Debugging/Profiling
            //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
            //catch (Exception) { }
//            m_log.DebugFormat(
//                "[LLUDPSERVER]: Packet received from {0} in {1}", buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);

            LLUDPClient udpClient = null;
            Packet packet = null;
            int packetEnd = buffer.DataLength - 1;
            IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint;

            #region Decoding

            if (buffer.DataLength < 7)
            {
//                m_log.WarnFormat(
//                    "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
//                    buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);

                RecordMalformedInboundPacket(endPoint);

                return; // Drop undersized packet
            }

            int headerLen = 7;
            if (buffer.Data[6] == 0xFF)
            {
                if (buffer.Data[7] == 0xFF)
                    headerLen = 10;
                else
                    headerLen = 8;
            }

            if (buffer.DataLength < headerLen)
            {
//                m_log.WarnFormat(
//                    "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}",
//                    buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);

                RecordMalformedInboundPacket(endPoint);

                return; // Malformed header
            }

            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[4096] : null);
                // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
                // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
                // bytes are copied out).
                packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
                    // Only allocate a buffer for zerodecoding if the packet is zerocoded
                    ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
            }
            catch (Exception e)
            {
                if (IncomingMalformedPacketCount < 100)
                    m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
            }

            // Fail-safe check
            if (packet == null)
            {
                if (IncomingMalformedPacketCount < 100)
                {
                    m_log.WarnFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}, data {2}:",
                        buffer.DataLength, buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
                }

                RecordMalformedInboundPacket(endPoint);

                return;
            }

            #endregion Decoding

            #region Packet to Client Mapping

            // UseCircuitCode handling
            if (packet.Type == PacketType.UseCircuitCode)
            {
                // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
                // buffer.
                object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };

                Util.FireAndForget(HandleUseCircuitCode, array);

                return;
            }
            else if (packet.Type == PacketType.CompleteAgentMovement)
            {
                // Send ack straight away to let the viewer know that we got it.
                SendAckImmediate(endPoint, packet.Header.Sequence);

                // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
                // buffer.
                object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };

                Util.FireAndForget(HandleCompleteMovementIntoRegion, array);

                return;
            }

            // Determine which agent this packet came from
            IClientAPI client;
            if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
            {
                //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);

                IncomingOrphanedPacketCount++;

                if ((IncomingOrphanedPacketCount % 10000) == 0)
                    m_log.WarnFormat(
                        "[LLUDPSERVER]: Received {0} orphaned packets so far.  Last was from {1}", 
                        IncomingOrphanedPacketCount, endPoint);

                return;
            }

            udpClient = ((LLClientView)client).UDPClient;

            if (!udpClient.IsConnected)
                return;

            #endregion Packet to Client Mapping

            // Stats tracking
            Interlocked.Increment(ref udpClient.PacketsReceived);

            int now = Environment.TickCount & Int32.MaxValue;
            udpClient.TickLastPacketReceived = now;

            #region ACK Receiving

            // Handle appended ACKs
            if (packet.Header.AppendedAcks && packet.Header.AckList != null)
            {
//                m_log.DebugFormat(
//                    "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
//                    packet.Header.AckList.Length, client.Name, m_scene.Name);

                for (int i = 0; i < packet.Header.AckList.Length; i++)
                    udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
            }

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

//                m_log.DebugFormat(
//                    "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
//                    ackPacket.Packets.Length, client.Name, m_scene.Name);

                for (int i = 0; i < ackPacket.Packets.Length; i++)
                    udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);

                // We don't need to do anything else with PacketAck packets
                return;
            }

            #endregion ACK Receiving

            #region ACK Sending

            if (packet.Header.Reliable)
            {
//                m_log.DebugFormat(
//                    "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}",
//                    packet.Type, packet.Header.Sequence, client.Name, m_scene.Name);

                udpClient.PendingAcks.Enqueue(packet.Header.Sequence);

                // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
                // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
                // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
                // client.BytesSinceLastACK. Lockless thread safety
                int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
                bytesSinceLastACK += buffer.DataLength;
                if (bytesSinceLastACK > LLUDPServer.MTU * 2)
                {
                    bytesSinceLastACK -= LLUDPServer.MTU * 2;
                    SendAcks(udpClient);
                }
                Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
            }

            #endregion ACK Sending

            #region Incoming Packet Accounting

            // Check the archive of received reliable packet IDs to see whether we already received this packet
            if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
            {
                if (packet.Header.Resent)
                    m_log.DebugFormat(
                        "[LLUDPSERVER]: Received a resend of already processed packet #{0}, type {1} from {2}", 
                        packet.Header.Sequence, packet.Type, client.Name);
                 else
                    m_log.WarnFormat(
                        "[LLUDPSERVER]: Received a duplicate (not marked as resend) of packet #{0}, type {1} from {2}",
                        packet.Header.Sequence, packet.Type, client.Name);

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

            #endregion Incoming Packet Accounting

            #region BinaryStats
            LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
            #endregion BinaryStats

            if (packet.Type == PacketType.AgentUpdate)
            {
                if (m_discardAgentUpdates)
                    return;

                ((LLClientView)client).TotalAgentUpdates++;

                AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;

                LLClientView llClient = client as LLClientView;
                if (agentUpdate.AgentData.SessionID != client.SessionId 
                    || agentUpdate.AgentData.AgentID != client.AgentId
                    || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) )
                {
                    PacketPool.Instance.ReturnPacket(packet);
                    return;
                }
            }

            #region Ping Check Handling

            if (packet.Type == PacketType.StartPingCheck)
            {
//                m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);

                // We don't need to do anything else with ping checks
                StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
                CompletePing(udpClient, startPing.PingID.PingID);

                if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000)
                {
                    udpClient.SendPacketStats();
                    m_elapsedMSSinceLastStatReport = Environment.TickCount;
                }
                return;
            }
            else if (packet.Type == PacketType.CompletePingCheck)
            {
                // We don't currently track client ping times
                return;
            }

            #endregion Ping Check Handling

            IncomingPacket incomingPacket;

            // Inbox insertion
            if (UsePools)
            {
                incomingPacket = m_incomingPacketPool.GetObject();
                incomingPacket.Client = (LLClientView)client;
                incomingPacket.Packet = packet;
            }
            else
            {
                incomingPacket = new IncomingPacket((LLClientView)client, packet);
            }

            packetInbox.Enqueue(incomingPacket);
        }
Exemplo n.º 39
0
 protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent);
Exemplo n.º 40
0
        /// <summary>
        /// Start the process of sending a packet to the client.
        /// </summary>
        /// <param name="udpClient"></param>
        /// <param name="data"></param>
        /// <param name="type"></param>
        /// <param name="category"></param>
        /// <param name="method">
        /// The method to call if the packet is not acked by the client.  If null, then a standard
        /// resend of the packet is done.
        /// </param>
        public void SendPacketData(
            LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
        {
            int dataLength = data.Length;
            bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
            bool doCopy = true;

            // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
            // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
            // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
            // to accomodate for both common scenarios and provide ample room for ACK appending in both
            int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;

            UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

            // Zerocode if needed
            if (doZerocode)
            {
                try
                {
                    dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
                    doCopy = false;
                }
                catch (IndexOutOfRangeException)
                {
                    // The packet grew larger than the bufferSize while zerocoding.
                    // Remove the MSG_ZEROCODED flag and send the unencoded data
                    // instead
                    m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
                        " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
                    data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
                }
            }

            // If the packet data wasn't already copied during zerocoding, copy it now
            if (doCopy)
            {
                if (dataLength <= buffer.Data.Length)
                {
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
                else
                {
                    bufferSize = dataLength;
                    buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

                    // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                    //     type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
            // If we were not provided a method for handling unacked, use the UDPServer default method
            outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);

            // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 
            // continue to display the deleted object until relog.  Therefore, we need to always queue a kill object
            // packet so that it isn't sent before a queued update packet.
            bool requestQueue = type == PacketType.KillObject;
            if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue))
                SendPacketFinal(outgoingPacket);

            #endregion Queue or Send
        }
Exemplo n.º 41
0
 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
 {
     // Stats tracking
     Interlocked.Add(ref Stats.SentBytes, bytesSent);
     Interlocked.Increment(ref Stats.SentPackets);
     
     Client.Network.RaisePacketSentEvent(buffer.Data, bytesSent, this);
 }
Exemplo n.º 42
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);
Exemplo n.º 43
0
 public void FreeUDPBuffer(UDPPacketBuffer buf)
 {
     m_udpServer.FreeUDPBuffer(buf);
 }
Exemplo n.º 44
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();
        }
Exemplo n.º 45
0
 public OutgoingPacket(Simulator simulator, UDPPacketBuffer buffer, PacketType type)
 {
     Simulator = simulator;
     Buffer = buffer;
     this.Type = type;
 }
Exemplo n.º 46
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();
            }
        }
Exemplo n.º 47
0
 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) { }
     }
 }
Exemplo n.º 48
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

            #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);
            int pendingAckCount = Interlocked.Increment(ref PendingAckCount);

            // Send out ACKs if we have a lot of them
            if (pendingAckCount >= 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 (packet.Header.Reliable && !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
        }
        public void TestAddClient()
        {
            TestHelpers.InMethod();
//            XmlConfigurator.Configure();

            TestScene  scene         = SceneHelpers.SetupScene();
            uint       myCircuitCode = 123456;
            UUID       myAgentUuid   = TestHelpers.ParseTail(0x1);
            UUID       mySessionUuid = TestHelpers.ParseTail(0x2);
            IPEndPoint testEp        = new IPEndPoint(IPAddress.Loopback, 999);

            uint port = 0;
            AgentCircuitManager acm = scene.AuthenticateHandler;

            TestLLUDPServer llUdpServer
                = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);

            llUdpServer.AddScene(scene);

            UseCircuitCodePacket uccp = new UseCircuitCodePacket();

            UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
                = new UseCircuitCodePacket.CircuitCodeBlock();
            uccpCcBlock.Code      = myCircuitCode;
            uccpCcBlock.ID        = myAgentUuid;
            uccpCcBlock.SessionID = mySessionUuid;
            uccp.CircuitCode      = uccpCcBlock;

            byte[]          uccpBytes = uccp.ToBytes();
            UDPPacketBuffer upb       = new UDPPacketBuffer(testEp, uccpBytes.Length);

            upb.DataLength = uccpBytes.Length;  // God knows why this isn't set by the constructor.
            Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);

            llUdpServer.PacketReceived(upb);

            // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
            Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null);

            AgentCircuitData acd = new AgentCircuitData();

            acd.AgentID   = myAgentUuid;
            acd.SessionID = mySessionUuid;

            acm.AddNewCircuit(myCircuitCode, acd);

            llUdpServer.PacketReceived(upb);

            // Should succeed now
            ScenePresence sp = scene.GetScenePresence(myAgentUuid);

            Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));

            Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1));

            Packet packet = llUdpServer.PacketsSent[0];

            Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));

            PacketAckPacket ackPacket = packet as PacketAckPacket;

            Assert.That(ackPacket.Packets.Length, Is.EqualTo(1));
            Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
        }