Exemple #1
0
        /// <summary>
        /// Resend unacknowledged packets
        /// </summary>
        private void ResendUnacked()
        {
            int now = Environment.TickCount;

            lock (NeedAck)
            {
                foreach (Packet packet in NeedAck.Values)
                {
                    if (now - packet.TickCount > Client.Settings.RESEND_TIMEOUT)
                    {
                        try
                        {
                            if (Client.Settings.LOG_RESENDS)
                            {
                                Client.DebugLog(String.Format("Resending packet #{0} ({1}), {2}ms have passed",
                                                              packet.Header.Sequence, packet.GetType(), now - packet.TickCount));
                            }

                            packet.Header.Resent = true;
                            packet.TickCount     = now;
                            ++Stats.ResentPackets;
                            SendPacket(packet, false);
                        }
                        catch (Exception ex)
                        {
                            Client.DebugLog("Exception trying to resend packet: " + ex.ToString());
                        }
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Fire the events registered for this event type synchronously
        /// </summary>
        /// <param name="capsEvent">Capability name</param>
        /// <param name="body">Decoded event body</param>
        /// <param name="simulator">Reference to the simulator that
        /// generated this event</param>
        internal void RaiseEvent(string capsEvent, StructuredData.LLSD body, Simulator simulator)
        {
            bool specialHandler = false;

            Caps.EventQueueCallback callback;

            // Default handler first, if one exists
            if (_EventTable.TryGetValue(capsEvent, out callback))
            {
                if (callback != null)
                {
                    try { callback(capsEvent, body, simulator); }
                    catch (Exception ex) { Client.Log("CAPS Event Handler: " + ex.ToString(), Helpers.LogLevel.Error); }
                }
            }

            // Generic parser next
            if (body.Type == StructuredData.LLSDType.Map)
            {
                StructuredData.LLSDMap map = (StructuredData.LLSDMap)body;
                Packet packet = Packet.BuildPacket(capsEvent, map);
                if (packet != null)
                {
                    NetworkManager.IncomingPacket incomingPacket;
                    incomingPacket.Simulator = simulator;
                    incomingPacket.Packet    = packet;

                    Client.DebugLog("Serializing " + packet.Type.ToString() + " capability with generic handler");

                    Client.Network.PacketInbox.Enqueue(incomingPacket);
                    specialHandler = true;
                }
            }

            // Explicit handler next
            if (_EventTable.TryGetValue(capsEvent, out callback) && callback != null)
            {
                try { callback(capsEvent, body, simulator); }
                catch (Exception ex) { Client.Log("CAPS Event Handler: " + ex.ToString(), Helpers.LogLevel.Error); }

                specialHandler = true;
            }

            if (!specialHandler)
            {
                Client.Log("Unhandled CAPS event " + capsEvent, Helpers.LogLevel.Warning);
            }
        }
Exemple #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="simulator"></param>
        private void TeleportHandler(Packet packet, Simulator simulator)
        {
            if (packet.Type == PacketType.TeleportStart)
            {
                TeleportMessage = "Teleport started";
                TeleportStat    = TeleportStatus.Start;

                if (OnBeginTeleport != null)
                {
                    OnBeginTeleport(TeleportMessage, TeleportStat);
                }
            }
            else if (packet.Type == PacketType.TeleportProgress)
            {
                TeleportMessage = Helpers.FieldToString(((TeleportProgressPacket)packet).Info.Message);
                TeleportStat    = TeleportStatus.Progress;

                if (OnBeginTeleport != null)
                {
                    OnBeginTeleport(TeleportMessage, TeleportStat);
                }
            }
            else if (packet.Type == PacketType.TeleportFailed)
            {
                TeleportMessage = Helpers.FieldToString(((TeleportFailedPacket)packet).Info.Reason);
                TeleportStat    = TeleportStatus.Failed;

                if (OnBeginTeleport != null)
                {
                    OnBeginTeleport(TeleportMessage, TeleportStat);
                }

                OnBeginTeleport = null;
            }
            else if (packet.Type == PacketType.TeleportFinish)
            {
                TeleportFinishPacket finish = (TeleportFinishPacket)packet;

                // Connect to the new sim
                Simulator sim = Client.Network.Connect(new IPAddress((long)finish.Info.SimIP), finish.Info.SimPort,
                                                       simulator.CircuitCode, true);

                if (sim != null)
                {
                    TeleportMessage = "Teleport finished";
                    TeleportStat    = TeleportStatus.Finished;

                    // Move the avatar in to the new sim
                    CompleteAgentMovementPacket move = new CompleteAgentMovementPacket();

                    move.AgentData.AgentID     = Client.Network.AgentID;
                    move.AgentData.SessionID   = Client.Network.SessionID;
                    move.AgentData.CircuitCode = simulator.CircuitCode;

                    Client.Network.SendPacket((Packet)move);

                    Client.DebugLog(move.ToString());

                    Client.Log("Moved to new sim " + Client.Network.CurrentSim.Region.Name + "(" +
                               Client.Network.CurrentSim.IPEndPoint.ToString() + ")",
                               Helpers.LogLevel.Info);

                    if (OnBeginTeleport != null)
                    {
                        OnBeginTeleport(TeleportMessage, TeleportStat);
                    }
                    else
                    {
                        // Sleep a little while so we can collect parcel information
                        System.Threading.Thread.Sleep(1000);
                    }
                }
                else
                {
                    TeleportMessage = "Failed to connect to the new sim after a teleport";
                    TeleportStat    = TeleportStatus.Failed;

                    Client.Log(TeleportMessage, Helpers.LogLevel.Warning);

                    if (OnBeginTeleport != null)
                    {
                        OnBeginTeleport(TeleportMessage, TeleportStat);
                    }
                }

                OnBeginTeleport = null;
            }
        }
Exemple #4
0
        private void PacketHandler()
        {
            IncomingPacket incomingPacket = new IncomingPacket();
            Packet         packet         = null;
            Simulator      simulator      = null;

            while (connected)
            {
                // Reset packet to null for the check below
                packet = null;

                if (PacketInbox.Dequeue(200, ref incomingPacket))
                {
                    packet    = incomingPacket.Packet;
                    simulator = incomingPacket.Simulator;

                    if (packet != null)
                    {
                        // Skip the ACK handling on packets synthesized from CAPS messages
                        if (packet.Header.Sequence != 0)
                        {
                            #region ACK accounting
                            // TODO: Replace PacketArchive Queue<> with something more efficient

                            // Check the archives to see whether we already received this packet
                            lock (simulator.PacketArchive)
                            {
                                if (simulator.PacketArchive.Contains(packet.Header.Sequence))
                                {
                                    if (packet.Header.Resent)
                                    {
                                        Client.DebugLog("Received resent packet #" + packet.Header.Sequence);
                                    }
                                    else
                                    {
                                        Client.Log(String.Format("Received a duplicate of packet #{0}, current type: {1}",
                                                                 packet.Header.Sequence, packet.Type), Helpers.LogLevel.Warning);
                                    }

                                    // Avoid firing a callback twice for the same packet
                                    continue;
                                }
                                else
                                {
                                    // Keep the PacketArchive size within a certain capacity
                                    while (simulator.PacketArchive.Count >= Settings.PACKET_ARCHIVE_SIZE)
                                    {
                                        simulator.PacketArchive.Dequeue(); simulator.PacketArchive.Dequeue();
                                        simulator.PacketArchive.Dequeue(); simulator.PacketArchive.Dequeue();
                                    }

                                    simulator.PacketArchive.Enqueue(packet.Header.Sequence);
                                }
                            }

                            #endregion ACK accounting

                            #region ACK handling

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

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

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

                            #endregion ACK handling
                        }

                        #region FireCallbacks

                        if (Client.Settings.SYNC_PACKETCALLBACKS)
                        {
                            PacketEvents.RaiseEvent(PacketType.Default, packet, simulator);
                            PacketEvents.RaiseEvent(packet.Type, packet, simulator);
                        }
                        else
                        {
                            PacketEvents.BeginRaiseEvent(PacketType.Default, packet, simulator);
                            PacketEvents.BeginRaiseEvent(packet.Type, packet, simulator);
                        }

                        #endregion FireCallbacks
                    }
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Updates the state of the InventoryNode and inventory data structure that
        /// is responsible for the InventoryObject. If the item was previously not added to inventory,
        /// it adds the item, and updates structure accordingly. If it was, it updates the
        /// InventoryNode, changing the parent node if <code>item.parentUUID</code> does
        /// not match <code>node.Parent.Data.UUID</code>.
        ///
        /// You can not set the inventory root folder using this method
        /// </summary>
        /// <param name="item">The InventoryObject to store</param>
        public void UpdateNodeFor(InventoryBase item)
        {
            lock (Items)
            {
                InventoryNode itemParent = null;
                if (item.ParentUUID != LLUUID.Zero && !Items.TryGetValue(item.ParentUUID, out itemParent))
                {
                    // OK, we have no data on the parent, let's create a fake one.
                    InventoryFolder fakeParent = new InventoryFolder(item.ParentUUID);
                    fakeParent.DescendentCount = 1; // Dear god, please forgive me.
                    itemParent             = new InventoryNode(fakeParent);
                    Items[item.ParentUUID] = itemParent;
                    // Unfortunately, this breaks the nice unified tree
                    // while we're waiting for the parent's data to come in.
                    // As soon as we get the parent, the tree repairs itself.
                    Client.DebugLog("Attempting to update inventory child of " +
                                    item.ParentUUID.ToString() +
                                    " when we have no local reference to that folder");

                    if (Client.Settings.FETCH_MISSING_INVENTORY)
                    {
                        // Fetch the parent
                        List <LLUUID> fetchreq = new List <LLUUID>(1);
                        fetchreq.Add(item.ParentUUID);
                        //Manager.FetchInventory(fetchreq); // we cant fetch folder data! :-O
                    }
                }

                InventoryNode itemNode;
                if (Items.TryGetValue(item.UUID, out itemNode)) // We're updating.
                {
                    InventoryNode oldParent = itemNode.Parent;
                    // Handle parent change
                    if (oldParent == null || itemParent == null || itemParent.Data.UUID != oldParent.Data.UUID)
                    {
                        if (oldParent != null)
                        {
                            lock (oldParent.Nodes.SyncRoot)
                                oldParent.Nodes.Remove(item.UUID);
                        }
                        if (itemParent != null)
                        {
                            lock (itemParent.Nodes.SyncRoot)
                                itemParent.Nodes[item.UUID] = itemNode;
                        }
                    }

                    itemNode.Parent = itemParent;

                    if (item != itemNode.Data)
                    {
                        FireOnInventoryObjectUpdated(itemNode.Data, item);
                    }

                    itemNode.Data = item;
                }
                else // We're adding.
                {
                    itemNode = new InventoryNode(item, itemParent);
                    Items.Add(item.UUID, itemNode);
                }
            }
        }
        private void TransferPacketHandler(Packet packet, Simulator simulator)
        {
            TransferPacketPacket asset = (TransferPacketPacket)packet;
            Transfer             transfer;
            AssetDownload        download;

            if (Transfers.TryGetValue(asset.TransferData.TransferID, out transfer))
            {
                download = (AssetDownload)transfer;

                if (download.Size == 0)
                {
                    Client.DebugLog("TransferPacket received ahead of the transfer header, blocking...");

                    // We haven't received the header yet, block until it's received or times out
                    download.HeaderReceivedEvent.WaitOne(1000 * 20, false);

                    if (download.Size == 0)
                    {
                        Client.Log("Timed out while waiting for the asset header to download for " +
                                   download.ID.ToString(), Helpers.LogLevel.Warning);

                        // Abort the transfer
                        TransferAbortPacket abort = new TransferAbortPacket();
                        abort.TransferInfo.ChannelType = (int)download.Channel;
                        abort.TransferInfo.TransferID  = download.ID;
                        Client.Network.SendPacket(abort, download.Simulator);

                        download.Success = false;
                        lock (Transfers) Transfers.Remove(download.ID);

                        // Fire the event with our transfer that contains Success = false
                        if (OnAssetReceived != null)
                        {
                            try { OnAssetReceived(download, null); }
                            catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
                        }

                        return;
                    }
                }

                // This assumes that every transfer packet except the last one is exactly 1000 bytes,
                // hopefully that is a safe assumption to make
                Buffer.BlockCopy(asset.TransferData.Data, 0, download.AssetData, 1000 * asset.TransferData.Packet,
                                 asset.TransferData.Data.Length);
                download.Transferred += asset.TransferData.Data.Length;

                //Client.DebugLog(String.Format("Transfer packet {0}, received {1}/{2}/{3} bytes for asset {4}",
                //    asset.TransferData.Packet, asset.TransferData.Data.Length, transfer.Transferred, transfer.Size,
                //    transfer.AssetID.ToString()));

                // Check if we downloaded the full asset
                if (download.Transferred >= download.Size)
                {
                    Client.DebugLog("Transfer for asset " + download.AssetID.ToString() + " completed");

                    download.Success = true;
                    lock (Transfers) Transfers.Remove(download.ID);

                    if (OnAssetReceived != null)
                    {
                        try { OnAssetReceived(download, WrapAsset(download)); }
                        catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
                    }
                }
            }
        }