Example #1
0
        public virtual void InPacket(Packet NewPack)
        {
            // Handle appended ACKs
            if (NewPack.Header.AppendedAcks)
            {
                lock (NeedAck)
                {
                    foreach (uint ack in NewPack.Header.AckList)
                    {
                        NeedAck.Remove(ack);
                    }
                }
            }

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

                lock (NeedAck)
                {
                    foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
                    {
                        NeedAck.Remove(block.ID);
                    }
                }
            }
            else if ((NewPack.Type == PacketType.StartPingCheck))
            {
                //reply to pingcheck
                libsecondlife.Packets.StartPingCheckPacket    startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
                libsecondlife.Packets.CompletePingCheckPacket endPing   = new CompletePingCheckPacket();
                endPing.PingID.PingID = startPing.PingID.PingID;
                OutPacket(endPing);
            }
            else
            {
                QueItem item = new QueItem();
                item.Packet   = NewPack;
                item.Incoming = true;
                this.PacketQueue.Enqueue(item);
            }
        }
        /// <summary>
        /// Callback handler for incomming data
        /// </summary>
        /// <param name="result"></param>
        private void OnReceivedData(IAsyncResult result)
        {
            ipeSender = new IPEndPoint(IPAddress.Any, 0);
            epSender  = (EndPoint)ipeSender;
            Packet packet = null;
            int    numBytes;

            // If we're receiving data the sim connection is open
            connected = true;

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

            lock (RecvBuffer)
            {
                // Retrieve the incoming packet
                try
                {
                    numBytes = Connection.EndReceiveFrom(result, ref epSender);

                    //find user_agent_info

                    int packetEnd = numBytes - 1;
                    packet = Packet.BuildPacket(RecvBuffer, ref packetEnd, ZeroBuffer);


                    //should check if login/useconnection packet first
                    if (packet.Type == PacketType.UseCircuitCode)
                    {
                        //new connection
                        //TODO check that this circuit and session is expected
                        UseCircuitCodePacket cir_pack = (UseCircuitCodePacket)packet;
                        NetworkInfo          new_user = new NetworkInfo();
                        new_user.CircuitCode        = cir_pack.CircuitCode.Code;
                        new_user.User.AgentID       = cir_pack.CircuitCode.ID;
                        new_user.User.SessionID     = cir_pack.CircuitCode.SessionID;
                        new_user.endpoint           = epSender;
                        new_user.Inbox              = new Queue <uint>(Settings.INBOX_SIZE);
                        new_user.Connection         = new ClientConnection();
                        new_user.Connection.NetInfo = new_user;
                        new_user.Connection.Start();

                        //this.CallbackObject.NewUserCallback(new_user);
                        this.User_agents.Add(new_user);
                    }

                    NetworkInfo temp_agent = null;
                    IPEndPoint  send_ip    = (IPEndPoint)epSender;
                    //	this.callback_object.error("incoming: address is "+send_ip.Address +"port number is: "+send_ip.Port.ToString());

                    for (int ii = 0; ii < this.User_agents.Count; ii++)
                    {
                        temp_agent = (NetworkInfo)this.User_agents[ii];
                        IPEndPoint ag_ip = (IPEndPoint)temp_agent.endpoint;
                        //this.callback_object.error("searching: address is "+ag_ip.Address +"port number is: "+ag_ip.Port.ToString());

                        if ((ag_ip.Address.ToString() == send_ip.Address.ToString()) && (ag_ip.Port.ToString() == send_ip.Port.ToString()))
                        {
                            //this.callback_object.error("found user");
                            User_info = temp_agent;
                            break;
                        }
                    }

                    Connection.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
                }
                catch (SocketException)
                {
                    // Client.Log(endPoint.ToString() + " socket is closed, shutting down " + this.Region.Name,
                    //     Helpers.LogLevel.Info);

                    connected = false;
                    //Network.DisconnectSim(this);
                    return;
                }
            }
            if (User_info == null)
            {
                //error finding agent
                //this.CallbackObject.ErrorCallback("no user found");
                return;
            }

            // Fail-safe check
            if (packet == null)
            {
                //this.CallbackObject.ErrorCallback("couldn't build packet");
                // Client.Log("Couldn't build a message from the incoming data", Helpers.LogLevel.Warning);
                return;
            }
            //this.callback_object.error("past tests");
            // Track the sequence number for this packet if it's marked as reliable
            if (packet.Header.Reliable)
            {
                if (User_info.PendingAcks.Count > Settings.MAX_PENDING_ACKS)
                {
                    SendAcks(User_info);
                }

                // Check if we already received this packet
                if (User_info.Inbox.Contains(packet.Header.Sequence))
                {
                    //Client.Log("Received a duplicate " + packet.Type.ToString() + ", sequence=" +
                    //    packet.Header.Sequence + ", resent=" + ((packet.Header.Resent) ? "Yes" : "No") +
                    //    ", Inbox.Count=" + Inbox.Count + ", NeedAck.Count=" + NeedAck.Count,
                    //    Helpers.LogLevel.Info);

                    // Send an ACK for this packet immediately
                    //SendAck(packet.Header.Sequence);

                    // TESTING: Try just queuing up ACKs for resent packets instead of immediately triggering an ACK
                    lock (User_info.PendingAcks)
                    {
                        uint sequence = (uint)packet.Header.Sequence;
                        if (!User_info.PendingAcks.ContainsKey(sequence))
                        {
                            User_info.PendingAcks[sequence] = sequence;
                        }
                    }

                    // Avoid firing a callback twice for the same packet
                    // this.callback_object.error("avoiding callback");
                    return;
                }
                else
                {
                    lock (User_info.PendingAcks)
                    {
                        uint sequence = (uint)packet.Header.Sequence;
                        if (!User_info.PendingAcks.ContainsKey(sequence))
                        {
                            User_info.PendingAcks[sequence] = sequence;
                        }
                    }
                }
            }

            // Add this packet to our inbox
            lock (User_info.Inbox)
            {
                while (User_info.Inbox.Count >= Settings.INBOX_SIZE)
                {
                    User_info.Inbox.Dequeue();
                }
                User_info.Inbox.Enqueue(packet.Header.Sequence);
            }

            // Handle appended ACKs
            if (packet.Header.AppendedAcks)
            {
                lock (User_info.NeedAck)
                {
                    foreach (uint ack in packet.Header.AckList)
                    {
                        User_info.NeedAck.Remove(ack);
                    }
                }
            }

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

                lock (User_info.NeedAck)
                {
                    foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
                    {
                        User_info.NeedAck.Remove(block.ID);
                    }
                }
            }

            //if it is a ping check send return
            if ((packet.Type == PacketType.StartPingCheck))
            {
                //reply to pingcheck
                libsecondlife.Packets.StartPingCheckPacket    startPing = (libsecondlife.Packets.StartPingCheckPacket)packet;
                libsecondlife.Packets.CompletePingCheckPacket endPing   = new CompletePingCheckPacket();
                endPing.PingID.PingID = startPing.PingID.PingID;
                SendPacket(endPing, true, User_info);
            }
            else if (packet.Type != PacketType.PacketAck)
            {
                User_info.Connection.InQueue.Enqueue(packet);
            }
        }