Example #1
0
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="agent">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="type">Packet type</param>
 public OutgoingPacket(LLAgent agent, UDPPacketBuffer buffer, ThrottleCategory category, PacketType type)
 {
     Agent = agent;
     Buffer = buffer;
     Category = category;
     Type = type;
 }
Example #2
0
        public void SendAcks(LLAgent agent)
        {
            const int MAX_ACKS_PER_PACKET = Byte.MaxValue;

            uint ack;

            if (agent.PendingAcks.TryDequeue(out ack))
            {
                List <PacketAckPacket.PacketsBlock> blocks = new List <PacketAckPacket.PacketsBlock>(agent.PendingAcks.Count);
                PacketAckPacket.PacketsBlock        block  = new PacketAckPacket.PacketsBlock();
                block.ID = ack;
                blocks.Add(block);

                int count = 1;

                while (count < MAX_ACKS_PER_PACKET && agent.PendingAcks.TryDequeue(out ack))
                {
                    block    = new PacketAckPacket.PacketsBlock();
                    block.ID = ack;
                    blocks.Add(block);

                    ++count;
                }

                PacketAckPacket packet = new PacketAckPacket();
                packet.Header.Reliable = false;
                packet.Packets         = blocks.ToArray();

                SendPacket(agent, packet, ThrottleCategory.Unknown, false);
            }
        }
Example #3
0
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="agent">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="type">Packet type</param>
 public OutgoingPacket(LLAgent agent, UDPPacketBuffer buffer, ThrottleCategory category, PacketType type)
 {
     Agent    = agent;
     Buffer   = buffer;
     Category = category;
     Type     = type;
 }
Example #4
0
        private bool CheckForCameraMovement(ISceneEntity entity)
        {
            const float CAMERA_MOVE_THRESHOLD = 10f;

            if (entity is LLAgent)
            {
                LLAgent agent = (LLAgent)entity;

                // Calculate the center of the far frustum plane
                Vector3 camPosition = agent.CameraPosition + agent.CameraAtAxis * agent.DrawDistance;

                lock (m_lastCameraPositions)
                {
                    Vector3 lastCamPos;
                    if (!m_lastCameraPositions.TryGetValue(agent.LocalID, out lastCamPos))
                    {
                        lastCamPos = Vector3.Zero;
                    }

                    if (Vector3.DistanceSquared(camPosition, lastCamPos) > CAMERA_MOVE_THRESHOLD * CAMERA_MOVE_THRESHOLD)
                    {
                        m_lastCameraPositions[entity.LocalID] = camPosition;
                        return(true);
                    }
                }
            }

            return(false);
        }
Example #5
0
        private void ChildAvatarUpdateHandler(IHttpClientContext context, IHttpRequest request, IHttpResponse response)
        {
            OSDMap requestMap = null;

            try { requestMap = OSDParser.Deserialize(request.Body) as OSDMap; }
            catch { }

            if (requestMap != null)
            {
                IScenePresence child;
                if (m_scene.TryGetPresence(requestMap["agent_id"].AsUUID(), out child) && child.IsChildPresence)
                {
                    child.RelativePosition = requestMap["position"].AsVector3();
                    child.RelativeRotation = requestMap["rotation"].AsQuaternion();

                    if (child is LLAgent)
                    {
                        LLAgent childAgent = (LLAgent)child;

                        childAgent.CameraPosition = requestMap["camera_center"].AsVector3();
                        childAgent.CameraAtAxis   = requestMap["camera_at"].AsVector3();
                        childAgent.CameraLeftAxis = requestMap["camera_left"].AsVector3();
                        childAgent.CameraUpAxis   = requestMap["camera_up"].AsVector3();
                        childAgent.DrawDistance   = (float)requestMap["draw_distance"].AsReal();
                    }
                }
            }
        }
Example #6
0
        private void ClientOutgoingPacketHandler(LLAgent agent)
        {
            try
            {
                if (agent.IsConnected && agent.RemoteEndPoint != null)
                {
                    if (m_resendUnacked)
                    {
                        ResendUnacked(agent);
                    }

                    if (m_sendAcks)
                    {
                        SendAcks(agent);
                    }

                    if (m_sendPing)
                    {
                        SendPing(agent);
                    }

                    // Dequeue any outgoing packets that are within the throttle limits
                    if (agent.DequeueOutgoing())
                    {
                        m_packetSent = true;
                    }
                }
            }
            catch (Exception ex)
            {
                m_log.Error("OutgoingPacketHandler iteration for " + agent.ID +
                            " threw an exception: " + ex.Message, ex);
            }
        }
Example #7
0
        private void PresenceAddHandler(object sender, PresenceArgs e)
        {
            m_scheduler.FireAndForget(
                delegate(object o)
            {
                // The default search distance (in every direction) for child agent connections
                const float NEIGHBOR_SEARCH_MARGIN = 256.0f;

                // HACK: Attempted fix for the viewer hanging indefinitely at login. It seems like
                // a client race condition when establishing neighbor connections too quickly
                System.Threading.Thread.Sleep(1000 * 5);

                if (e.Presence is LLAgent && !e.Presence.IsChildPresence)
                {
                    LLAgent agent = (LLAgent)e.Presence;

                    // Fetch nearby neighbors for the new presence
                    // TODO: We should be doing this later, based off draw distance
                    Vector3d globalPosition   = e.Presence.Scene.MinPosition + new Vector3d(e.Presence.ScenePosition);
                    SceneInfo[] nearNeighbors = m_scene.GetNeighborsNear(globalPosition, e.Presence.InterestRadius + NEIGHBOR_SEARCH_MARGIN);

                    // Iterate over all of the given neighbors and send each a rez_avatar/request to create a child agent
                    for (int i = 0; i < nearNeighbors.Length; i++)
                    {
                        SendRezAvatarRequest(agent, nearNeighbors[i], true);
                    }
                }
            }, null
                );
        }
Example #8
0
        private LLAgent CreateLLAgent(UserSession session, Vector3 startPosition, Vector3 lookAt, bool isChildAgent)
        {
            LLAgent client = new LLAgent(this, m_throttleRates, m_throttle, session.GetField("CircuitCode").AsUInteger(),
                                         session.User.ID, session.SessionID, session.SecureSessionID, null, m_defaultRTO, m_maxRTO, isChildAgent);

            // Set the verified flag
            client.IsVerified = (session.User.AccessLevel > 0);
            // Set the agent name
            client.Name = session.User.Name;
            // Set the starting position
            client.RelativePosition = startPosition;
            // Set the starting rotation
            lookAt.Z = 0.0f;
            Matrix4 lookAtMatrix = Matrix4.CreateLookAt(Vector3.Zero, lookAt, Vector3.UnitZ);

            client.RelativeRotation = lookAtMatrix.GetQuaternion();

            m_clients.Add(client.ID, client.RemoteEndPoint, client);

            // Create a seed capability
            if (m_httpServer != null)
            {
                client.SeedCapability = this.Scene.Capabilities.AddCapability(session.User.ID, true, this.Scene.ID, "region_seed_capability");
            }
            else
            {
                client.SeedCapability = new Uri("http://localhost:0");
            }

            return(client);
        }
Example #9
0
        private void SendChildUpdate(IScenePresence presence)
        {
            const float DEFAULT_DRAW_DISTANCE = 128.0f;

            // Build the template child_avatar/update message
            OSDMap childUpdate = new OSDMap();

            childUpdate["agent_id"] = OSD.FromUUID(presence.ID);
            childUpdate["rotation"] = OSD.FromQuaternion(presence.SceneRotation);

            float drawDistance = DEFAULT_DRAW_DISTANCE;

            if (presence is LLAgent)
            {
                LLAgent agent = (LLAgent)presence;
                drawDistance = agent.DrawDistance;

                childUpdate["camera_center"] = OSD.FromVector3(agent.CameraPosition);
                childUpdate["camera_at"]     = OSD.FromVector3(agent.CameraAtAxis);
                childUpdate["camera_left"]   = OSD.FromVector3(agent.CameraLeftAxis);
                childUpdate["camera_up"]     = OSD.FromVector3(agent.CameraUpAxis);
            }

            childUpdate["draw_distance"] = OSD.FromReal(drawDistance);

            // Get a list of neighbors to send this update to based on the draw distance
            SceneInfo[] neighbors = m_scene.GetNeighborsNear(m_scene.MinPosition + new Vector3d(presence.ScenePosition), drawDistance);
            for (int i = 0; i < neighbors.Length; i++)
            {
                SceneInfo neighbor = neighbors[i];

                // Find the presence position relative to this neighbor
                Vector3 relativePosition = presence.ScenePosition - new Vector3(neighbor.MinPosition - presence.Scene.MinPosition);
                childUpdate["position"] = OSD.FromVector3(relativePosition);

                Uri childUpdateCap;
                if (neighbor.TryGetCapability("child_avatar/update", out childUpdateCap))
                {
                    try
                    {
                        // Send the message
                        //m_log.Debug("Sending child agent update for " + presence.Name);
                        string message = OSDParser.SerializeJsonString(childUpdate);
                        UntrustedHttpWebRequest.PostToUntrustedUrl(childUpdateCap, message);
                    }
                    catch (Exception ex)
                    {
                        m_log.Warn("child_avatar/update from " + m_scene.Name + " to " + neighbor.Name + " for agent " +
                                   presence.Name + " failed: " + ex.Message);
                    }
                }
                else
                {
                    // This shouldn't happen since we check for the child_avatar/update capability
                    // before adding this agent/neighbor pair to the queue
                    throw new InvalidOperationException("child_avatar/update capability not found in SendChildUpdate handler");
                }
            }
        }
Example #10
0
        public void CompletePing(LLAgent agent, byte pingID)
        {
            CompletePingCheckPacket completePing = new CompletePingCheckPacket();

            completePing.Header.Reliable = false;
            completePing.PingID.PingID   = pingID;
            SendPacket(agent, completePing, ThrottleCategory.Unknown, false);
        }
Example #11
0
        private bool SendRezAvatarRequest(LLAgent agent, SceneInfo neighbor, bool isChild)
        {
            IPAddress simHost;
            int       simPort;
            Uri       seedCapability;

            return(SendRezAvatarRequest(agent, neighbor, isChild, out simHost, out simPort, out seedCapability));
        }
Example #12
0
        public void FireQueueEmpty(LLAgent agent, ThrottleCategoryFlags categories)
        {
            QueueEmptyCallback callback = OnQueueEmpty;

            if (callback != null)
            {
                callback(agent, categories);
            }
        }
Example #13
0
        private bool SendRezAvatarRequest(LLAgent agent, SceneInfo neighbor, bool isChild, out IPAddress simHost, out int simPort, out Uri seedCapability)
        {
            simHost        = null;
            simPort        = 0;
            seedCapability = null;

            Uri rezAvatarRequestCap;

            if (neighbor.TryGetCapability("rez_avatar/request", out rezAvatarRequestCap))
            {
                string firstName, lastName;
                Util.GetFirstLastName(agent.Name, out firstName, out lastName);

                // Find the presence position relative to this neighbor
                Vector3 relativePosition = agent.ScenePosition - new Vector3(neighbor.MinPosition - m_scene.MinPosition);
                // Calculate the direction this agent is currently facing
                Vector3 lookAt = Vector3.UnitY * agent.RelativeRotation;

                // Create the template rez_avatar/request message
                OSDMap rezAvatarRequest = new OSDMap
                {
                    { "agent_id", OSD.FromUUID(agent.ID) },
                    { "session_id", OSD.FromUUID(agent.SessionID) },
                    { "position", OSD.FromVector3(relativePosition) },
                    { "look_at", OSD.FromVector3(lookAt) },
                    { "velocity", OSD.FromVector3(agent.Velocity) },
                    { "child", OSD.FromBoolean(isChild) }
                };

                OSDMap rezAvatarResponse = null;
                try
                {
                    // Send the message and get a response
                    rezAvatarResponse = OSDParser.Deserialize(UntrustedHttpWebRequest.PostToUntrustedUrl(
                                                                  rezAvatarRequestCap, OSDParser.SerializeJsonString(rezAvatarRequest))) as OSDMap;
                }
                catch { }

                if (rezAvatarResponse != null)
                {
                    return(RezChildAgentReplyHandler(agent, rezAvatarResponse, out simHost, out simPort, out seedCapability));
                }
                else
                {
                    m_log.Warn(m_scene.Name + " failed to create a child agent on " + neighbor.Name +
                               ", rez_avatar/request failed");
                }
            }
            else
            {
                m_log.Warn(neighbor.Name + " does not have a rez_avatar/request capability");
            }

            return(false);
        }
Example #14
0
        public void SendPing(LLAgent agent)
        {
            StartPingCheckPacket pc = new StartPingCheckPacket();

            pc.Header.Reliable = false;

            pc.PingID.PingID = (byte)agent.CurrentPingSequence++;
            // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
            pc.PingID.OldestUnacked = 0;

            SendPacket(agent, pc, ThrottleCategory.Unknown, false);
        }
Example #15
0
        private void EventQueueManagerThread()
        {
            while (m_running)
            {
                bool doSleep = true;

                m_scene.ForEachPresence(
                    delegate(IScenePresence presence)
                {
                    if (!(presence is LLAgent) || presence.InterestList == null)
                    {
                        return;
                    }
                    LLAgent agent = (LLAgent)presence;

                    if (agent.EventQueue.ConnectionOpen)
                    {
                        if (agent.EventQueue.EventQueue.Count > 0)
                        {
                            // Set ConnectionOpen to false early so we don't try to send
                            // events on this EQ again before the first call finishes
                            agent.EventQueue.ConnectionOpen = false;
                            m_scheduler.FireAndForget(agent.EventQueue.SendEvents, null);
                            doSleep = false;
                        }
                        else
                        {
                            // Check for a timeout
                            int elapsed = Util.TickCount() - agent.EventQueue.StartTime;
                            if (elapsed >= CONNECTION_TIMEOUT)
                            {
                                //m_log.DebugFormat("{0}ms passed without an event, timing out the event queue", elapsed);

                                agent.EventQueue.SendResponse(null);
                                doSleep = false;
                            }
                        }
                    }
                }
                    );

                if (doSleep)
                {
                    Thread.Sleep(Simian.LONG_SLEEP_INTERVAL);
                }

                m_scheduler.ThreadKeepAlive();
            }

            m_scheduler.RemoveThread();
        }
Example #16
0
        public void ResendUnacked(LLAgent agent)
        {
            //FIXME: Make this an .ini setting
            const int AGENT_TIMEOUT_MS = 1000 * 60;

            // Disconnect an agent if no packets are received for some time
            if (Util.TickCount() - agent.TickLastPacketReceived > AGENT_TIMEOUT_MS)
            {
                m_log.Warn("Ack timeout, disconnecting " + agent.ID);

                ShutdownClient(agent);
                return;
            }

            // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
            List <OutgoingPacket> expiredPackets = agent.NeedAcks.GetExpiredPackets(agent.RTO);

            if (expiredPackets != null)
            {
                //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);

                // Exponential backoff of the retransmission timeout
                agent.BackoffRTO();

                // Resend packets
                for (int i = 0; i < expiredPackets.Count; i++)
                {
                    OutgoingPacket outgoingPacket = expiredPackets[i];

                    //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
                    //    outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);

                    // Set the resent flag
                    outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
                    outgoingPacket.Category       = ThrottleCategory.Resend;

                    // Bump up the resend count on this packet
                    Interlocked.Increment(ref outgoingPacket.ResendCount);
                    Interlocked.Increment(ref m_packetsResent);

                    // Requeue or resend the packet
                    if (!agent.EnqueueOutgoing(outgoingPacket))
                    {
                        SendPacketFinal(outgoingPacket);
                    }
                }
            }
        }
Example #17
0
        private void PacketDelegate(object state)
        {
            PacketCallbackWrapper wrapper        = (PacketCallbackWrapper)state;
            IncomingPacket        incomingPacket = wrapper.IncomingPacket;
            LLAgent agent = wrapper.IncomingPacket.Agent;

            if (!agent.IsConnected)
            {
                m_log.DebugFormat("Dropping incoming {0} packet (#{1}) for dead client {2}",
                                  incomingPacket.Packet.Type, incomingPacket.Packet.Header.ID, agent.ID);
                return;
            }

            try
            {
                wrapper.Callback(incomingPacket.Packet, agent);
            }
            catch (Exception ex)
            {
                m_log.Error("Async Packet Event Handler: " + ex.Message, ex);
            }

            // TODO: Optionally log timing info for this packet
            int now = Util.TickCount();

            int recvTime = incomingPacket.StartedHandling - incomingPacket.Received;

            if (recvTime > 1000)
            {
                m_log.Warn("Spent " + recvTime + "ms receiving " + incomingPacket.Packet.Type +
                           " packet for " + wrapper.IncomingPacket.Agent);
            }

            int processTime = now - incomingPacket.StartedHandling;

            if (processTime > 1000)
            {
                m_log.Warn("Spent " + processTime + "ms processing " + incomingPacket.Packet.Type +
                           " packet for " + incomingPacket.Agent);
            }
        }
Example #18
0
        private bool BorderCrossLLAgent(LLAgent agent, SceneInfo neighbor)
        {
            IPAddress simHost;
            int       simPort;
            Uri       seedCapability;

            // Send a rez_avatar/request message to create a root agent or upgrade a child agent
            if (SendRezAvatarRequest(agent, neighbor, false, out simHost, out simPort, out seedCapability))
            {
                // Demote this agent to a child agent
                agent.IsChildPresence = true;

                // Calculate our position relative to the new region
                Vector3 relativePosition = agent.ScenePosition - new Vector3(neighbor.MinPosition - m_scene.MinPosition);

                // Send the CrossedRegion message over the event queue to the client
                CrossedRegionMessage crossed = new CrossedRegionMessage();
                crossed.AgentID        = agent.ID;
                crossed.SessionID      = agent.SessionID;
                crossed.RegionHandle   = Util.PositionToRegionHandle(neighbor.MinPosition);
                crossed.IP             = simHost;
                crossed.Port           = simPort;
                crossed.Position       = relativePosition;
                crossed.LookAt         = agent.CameraAtAxis; // TODO: Get LookAt from the agent's rotation
                crossed.SeedCapability = seedCapability;

                m_log.Info("Sending CrossedRegion to " + agent.Name + " from " + m_scene.Name + " to " + neighbor.Name +
                           ", pos=" + relativePosition + ", vel=" + agent.Velocity);
                agent.EventQueue.QueueEvent("CrossedRegion", crossed.Serialize());

                return(true);
            }
            else
            {
                m_log.Warn("Border crossing " + agent.Name + " from " + m_scene.Name + " to " + neighbor.Name +
                           " failed, rez_avatar/request did not succeed");

                return(false);
            }
        }
Example #19
0
        private void PresenceRemoveHandler(object sender, PresenceArgs e)
        {
            if (e.Presence is LLAgent)
            {
                // Remove all capabilities associated with this client
                if (m_httpServer != null)
                {
                    this.Scene.Capabilities.RemoveCapabilities(e.Presence.ID);
                }

                // Remove the UDP client reference
                LLAgent agent = (LLAgent)e.Presence;
                if (m_clients.Remove(agent.ID, agent.RemoteEndPoint))
                {
                    m_log.Debug("Removed client reference from the LLUDP server");
                }
            }
            else
            {
                m_log.Warn("PresenceRemoveHandler called for non-LLAgent: " + e.Presence);
            }
        }
Example #20
0
        public void SendPacket(LLAgent agent, Packet packet, ThrottleCategory category, bool allowSplitting)
        {
            // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
            if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
            {
                allowSplitting = false;
            }

            try
            {
                if (allowSplitting && packet.HasVariableBlocks)
                {
                    byte[][] datas       = packet.ToBytesMultiple();
                    int      packetCount = datas.Length;

                    if (packetCount < 1)
                    {
                        m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
                    }

                    for (int i = 0; i < packetCount; i++)
                    {
                        byte[] data = datas[i];
                        SendPacketData(agent, data, packet.Type, category);
                    }
                }
                else
                {
                    byte[] data = packet.ToBytes();
                    SendPacketData(agent, data, packet.Type, category);
                }
            }
            catch (NullReferenceException)
            {
                System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true);
                m_log.Error("An invalid " + packet.Type + " packet was built in:" + Environment.NewLine + trace.ToString());
            }
        }
Example #21
0
 public void SendPacket(LLAgent agent, Packet packet, ThrottleCategory category, bool allowSplitting)
 {
     m_udpServer.SendPacket(agent, packet, category, allowSplitting);
 }
Example #22
0
        private bool SendRezAvatarRequest(LLAgent agent, SceneInfo neighbor, bool isChild)
        {
            IPAddress simHost;
            int simPort;
            Uri seedCapability;

            return SendRezAvatarRequest(agent, neighbor, isChild, out simHost, out simPort, out seedCapability);
        }
Example #23
0
        private bool BorderCrossLLAgent(LLAgent agent, SceneInfo neighbor)
        {
            IPAddress simHost;
            int simPort;
            Uri seedCapability;

            // Send a rez_avatar/request message to create a root agent or upgrade a child agent
            if (SendRezAvatarRequest(agent, neighbor, false, out simHost, out simPort, out seedCapability))
            {
                // Demote this agent to a child agent
                agent.IsChildPresence = true;

                // Calculate our position relative to the new region
                Vector3 relativePosition = agent.ScenePosition - new Vector3(neighbor.MinPosition - m_scene.MinPosition);

                // Send the CrossedRegion message over the event queue to the client
                CrossedRegionMessage crossed = new CrossedRegionMessage();
                crossed.AgentID = agent.ID;
                crossed.SessionID = agent.SessionID;
                crossed.RegionHandle = Util.PositionToRegionHandle(neighbor.MinPosition);
                crossed.IP = simHost;
                crossed.Port = simPort;
                crossed.Position = relativePosition;
                crossed.LookAt = agent.CameraAtAxis; // TODO: Get LookAt from the agent's rotation
                crossed.SeedCapability = seedCapability;

                m_log.Info("Sending CrossedRegion to " + agent.Name + " from " + m_scene.Name + " to " + neighbor.Name +
                    ", pos=" + relativePosition + ", vel=" + agent.Velocity);
                agent.EventQueue.QueueEvent("CrossedRegion", crossed.Serialize());

                return true;
            }
            else
            {
                m_log.Warn("Border crossing " + agent.Name + " from " + m_scene.Name + " to " + neighbor.Name +
                    " failed, rez_avatar/request did not succeed");

                return false;
            }
        }
Example #24
0
        private LLAgent CreateLLAgent(UserSession session, Vector3 startPosition, Vector3 lookAt, bool isChildAgent)
        {
            LLAgent client = new LLAgent(this, m_throttleRates, m_throttle, session.GetField("CircuitCode").AsUInteger(),
                    session.User.ID, session.SessionID, session.SecureSessionID, null, m_defaultRTO, m_maxRTO, isChildAgent);

            // Set the verified flag
            client.IsVerified = (session.User.AccessLevel > 0);
            // Set the agent name
            client.Name = session.User.Name;
            // Set the starting position
            client.RelativePosition = startPosition;
            // Set the starting rotation
            lookAt.Z = 0.0f;
            Matrix4 lookAtMatrix = Matrix4.CreateLookAt(Vector3.Zero, lookAt, Vector3.UnitZ);
            client.RelativeRotation = lookAtMatrix.GetQuaternion();

            m_clients.Add(client.ID, client.RemoteEndPoint, client);

            // Create a seed capability
            if (m_httpServer != null)
                client.SeedCapability = this.Scene.Capabilities.AddCapability(session.User.ID, true, this.Scene.ID, "region_seed_capability");
            else
                client.SeedCapability = new Uri("http://localhost:0");

            return client;
        }
Example #25
0
 public bool TryGetAgent(UUID agentID, out LLAgent agent)
 {
     return m_clients.TryGetValue(agentID, out agent);
 }
Example #26
0
 private void ShutdownClient(LLAgent agent)
 {
     // Remove this client from the scene
     agent.Shutdown();
     m_clients.Remove(agent.ID, agent.RemoteEndPoint);
 }
Example #27
0
 public void SendPacketData(LLAgent agent, byte[] data, PacketType type, ThrottleCategory category)
 {
     m_udpServer.SendPacketData(agent, data, type, category);
 }
Example #28
0
 private void ShutdownClient(LLAgent agent)
 {
     // Remove this client from the scene
     agent.Shutdown();
     m_clients.Remove(agent.ID, agent.RemoteEndPoint);
 }
Example #29
0
 public bool TryGetAgent(UUID agentID, out LLAgent agent)
 {
     return(m_clients.TryGetValue(agentID, out agent));
 }
Example #30
0
        private void EventQueueHandler(Capability cap, IHttpClientContext context, IHttpRequest request, IHttpResponse response)
        {
            // Decode the request
            OSD osdRequest = null;

            try { osdRequest = OSDParser.Deserialize(request.Body); }
            catch (Exception) { }

            if (request != null && osdRequest.Type == OSDType.Map)
            {
                OSDMap requestMap = (OSDMap)osdRequest;
                int    ack        = requestMap["ack"].AsInteger();
                bool   done       = requestMap["done"].AsBoolean();

                LLAgent agent = null;

                // Fetch an agent reference from either the scene or the LLUDP stack (since the
                // presence might not exist in the scene yet)
                IScenePresence presence;
                if (m_scene.TryGetPresence(cap.OwnerID, out presence) && presence is LLAgent)
                {
                    agent = (LLAgent)presence;
                }
                else
                {
                    m_udp.TryGetAgent(cap.OwnerID, out agent);
                }

                if (agent != null)
                {
                    if (agent.EventQueue.ConnectionOpen)
                    {
                        m_log.Debug("New connection opened to the event queue for " + agent.Name + " while a previous connection is open. Closing old connection");

                        // If the old connection is still open, queue a signal to close it. Otherwise, just wait for the closed
                        // connection to be detected by the handler thread
                        if (agent.EventQueue.Response != null)
                        {
                            agent.EventQueue.EventQueue.Enqueue(null);
                        }

                        while (agent.EventQueue.ConnectionOpen)
                        {
                            Thread.Sleep(50);
                        }

                        m_log.Debug("Old event queue connection closed for " + agent.Name);
                    }

                    if (!done)
                    {
                        //m_log.Debug("Opening event queue connection for " + agent.Name);

                        agent.EventQueue.Context        = context;
                        agent.EventQueue.Request        = request;
                        agent.EventQueue.Response       = response;
                        agent.EventQueue.StartTime      = Util.TickCount();
                        agent.EventQueue.ConnectionOpen = true;

                        // ACK sanity checking
                        if (ack != agent.EventQueue.CurrentID - 1 && ack != 0)
                        {
                            m_log.WarnFormat("Received an ack for id {0}, last id sent was {1}", ack, agent.EventQueue.CurrentID - 1);
                        }
                    }
                    else
                    {
                        m_log.DebugFormat("Shutting down the event queue {0} for {1} at the client's request", request.Uri, agent.Name);
                        agent.EventQueue.SendEvents(50);
                    }
                }
                else
                {
                    m_log.Warn("Received an event queue connection from client " + cap.OwnerID + " that does not have a presence in scene " + m_scene.Name);
                }
            }
            else
            {
                m_log.Warn("Received a request with invalid or missing data at " + request.Uri + ", closing the connection");

                response.Connection = request.Connection;
                response.Status     = System.Net.HttpStatusCode.BadRequest;
                response.Send();
            }
        }
Example #31
0
        public void SendPacketData(LLAgent agent, byte[] data, PacketType type, ThrottleCategory 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(agent.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("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)
                {
                    m_log.Error("Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                                type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
                    buffer.Data = new byte[dataLength];
                }

                Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(agent, buffer, category, type);

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

            #endregion Queue or Send
        }
Example #32
0
        internal void SendPacketFinal(OutgoingPacket outgoingPacket)
        {
            const int MAX_APPENDED_ACKS = 250;

            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;
            LLAgent         agent       = outgoingPacket.Agent;

            if (!agent.IsConnected || buffer.RemoteEndPoint == null)
            {
                m_log.Debug("Dropping " + buffer.DataLength + " byte packet to client we have no route to");
                return;
            }

            int dataLength = buffer.DataLength;

            #region ACK Appending

            // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here
            if (!isZerocoded && outgoingPacket.Type != PacketType.PacketAck)
            {
                // Keep appending ACKs until there is no room left in the buffer or there are
                // no more ACKs to append
                byte ackCount = 0;
                uint ack;
                while (dataLength + 5 < buffer.Data.Length && ackCount < MAX_APPENDED_ACKS && agent.PendingAcks.TryDequeue(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++] = ackCount;
                    // Set the appended ACKs flag on this packet
                    buffer.Data[0] |= Helpers.MSG_APPENDED_ACKS;
                }
            }

            #endregion ACK Appending

            buffer.DataLength = dataLength;

            #region Sequence Number Assignment

            if (!isResend)
            {
                // Not a resend, assign a new sequence number
                uint sequenceNumber = (uint)Interlocked.Increment(ref agent.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
                    agent.NeedAcks.Add(outgoingPacket);
                }
            }

            #endregion Sequence Number Assignment

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

            if (LoggingEnabled)
            {
                m_log.Debug("<-- (" + buffer.RemoteEndPoint + ") " + outgoingPacket.Type);
            }

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

            // Keep track of when this packet was sent out (right now)
            outgoingPacket.TickCount = Util.TickCount();

            //m_log.Debug("Sent " + outgoingPacket.Buffer.DataLength + " byte " + outgoingPacket.Category + " packet");
        }
Example #33
0
 public void SendPacketData(LLAgent agent, byte[] data, PacketType type, ThrottleCategory category)
 {
     m_udpServer.SendPacketData(agent, data, type, category);
 }
Example #34
0
        public void SendPing(LLAgent agent)
        {
            StartPingCheckPacket pc = new StartPingCheckPacket();
            pc.Header.Reliable = false;

            pc.PingID.PingID = (byte)agent.CurrentPingSequence++;
            // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
            pc.PingID.OldestUnacked = 0;

            SendPacket(agent, pc, ThrottleCategory.Unknown, false);
        }
Example #35
0
 public bool TryGetAgent(UUID agentID, out LLAgent agent)
 {
     return m_udpServer.TryGetAgent(agentID, out agent);
 }
Example #36
0
        private void ClientOutgoingPacketHandler(LLAgent agent)
        {
            try
            {
                if (agent.IsConnected && agent.RemoteEndPoint != null)
                {
                    if (m_resendUnacked)
                        ResendUnacked(agent);

                    if (m_sendAcks)
                        SendAcks(agent);

                    if (m_sendPing)
                        SendPing(agent);

                    // Dequeue any outgoing packets that are within the throttle limits
                    if (agent.DequeueOutgoing())
                        m_packetSent = true;
                }
            }
            catch (Exception ex)
            {
                m_log.Error("OutgoingPacketHandler iteration for " + agent.ID +
                    " threw an exception: " + ex.Message, ex);
            }
        }
Example #37
0
 public void CompletePing(LLAgent agent, byte pingID)
 {
     CompletePingCheckPacket completePing = new CompletePingCheckPacket();
     completePing.Header.Reliable = false;
     completePing.PingID.PingID = pingID;
     SendPacket(agent, completePing, ThrottleCategory.Unknown, false);
 }
Example #38
0
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="agent">Reference to the client this packet came from</param>
 /// <param name="packet">Packet data</param>
 /// <param name="received">Tick count when this packet was received</param>
 public IncomingPacket(LLAgent agent, Packet packet, int received)
 {
     Agent = agent;
     Packet = packet;
     Received = received;
 }
Example #39
0
 public void FireQueueEmpty(LLAgent agent, ThrottleCategoryFlags categories)
 {
     m_udp.FireQueueEmpty(agent, categories);
 }
Example #40
0
        private bool RezChildAgentReplyHandler(LLAgent agent, OSDMap map, out IPAddress simHost, out int simPort, out Uri seedCapability)
        {
            simHost = null;
            simPort = 0;
            seedCapability = null;

            if (map["connect"].AsBoolean())
            {
                #region Response Parsing

                string simHostStr = map["sim_host"].AsString();
                if (!IPAddress.TryParse(simHostStr, out simHost))
                {
                    m_log.Warn("rez_avatar/response had an invalid sim_host: " + simHostStr);
                    return false;
                }

                simPort = map["sim_port"].AsInteger();
                UUID regionID = map["region_id"].AsUUID();

                uint regionX = map["region_x"].AsUInteger();
                uint regionY = map["region_y"].AsUInteger();
                ulong regionHandle = Utils.UIntsToLong(regionX, regionY);

                seedCapability = map["region_seed_capability"].AsUri();
                if (seedCapability == null)
                {
                    m_log.Warn("rez_avatar/response had an invalid region_seed_capability: " + map["region_seed_capability"].AsString());
                    return false;
                }

                #endregion Response Parsing

                #region EnableSimulator

                EnableSimulatorMessage.SimulatorInfoBlock block = new EnableSimulatorMessage.SimulatorInfoBlock();
                block.IP = simHost;
                block.Port = simPort;
                block.RegionHandle = regionHandle;

                EnableSimulatorMessage enable = new EnableSimulatorMessage();
                enable.Simulators = new EnableSimulatorMessage.SimulatorInfoBlock[1];
                enable.Simulators[0] = block;

                m_log.Debug("Sending EnableSimulator message for scene " + regionID + " to " + agent.Name);
                agent.EventQueue.QueueEvent("EnableSimulator", enable.Serialize());

                #endregion EnableSimulator

                #region EstablishAgentCommunication

                // Send an EstablishAgentCommunication event down to the client to get the neighbor event queue established
                EstablishAgentCommunicationMessage eacMessage = new EstablishAgentCommunicationMessage();
                eacMessage.AgentID = regionID;
                eacMessage.Address = simHost;
                eacMessage.Port = simPort;
                eacMessage.SeedCapability = seedCapability;

                m_log.Debug("Sending EstablishAgentCommunication message for seedcap " + seedCapability + " to " + agent.Name);
                agent.EventQueue.QueueEvent("EstablishAgentCommunication", eacMessage.Serialize());

                #endregion EstablishAgentCommunication

                return true;
            }
            else
            {
                m_log.Warn("rez_avatar/request from " + m_scene.Name + " for child agent " + agent.Name +
                    " failed: " + map["message"].AsString());
                return false;
            }
        }
Example #41
0
        public void ResendUnacked(LLAgent agent)
        {
            //FIXME: Make this an .ini setting
            const int AGENT_TIMEOUT_MS = 1000 * 60;

            // Disconnect an agent if no packets are received for some time
            if (Util.TickCount() - agent.TickLastPacketReceived > AGENT_TIMEOUT_MS)
            {
                m_log.Warn("Ack timeout, disconnecting " + agent.ID);

                ShutdownClient(agent);
                return;
            }

            // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
            List<OutgoingPacket> expiredPackets = agent.NeedAcks.GetExpiredPackets(agent.RTO);

            if (expiredPackets != null)
            {
                //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);

                // Exponential backoff of the retransmission timeout
                agent.BackoffRTO();

                // Resend packets
                for (int i = 0; i < expiredPackets.Count; i++)
                {
                    OutgoingPacket outgoingPacket = expiredPackets[i];

                    //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
                    //    outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);

                    // Set the resent flag
                    outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
                    outgoingPacket.Category = ThrottleCategory.Resend;

                    // Bump up the resend count on this packet
                    Interlocked.Increment(ref outgoingPacket.ResendCount);
                    Interlocked.Increment(ref m_packetsResent);

                    // Requeue or resend the packet
                    if (!agent.EnqueueOutgoing(outgoingPacket))
                        SendPacketFinal(outgoingPacket);
                }
            }
        }
Example #42
0
        private bool SendRezAvatarRequest(LLAgent agent, SceneInfo neighbor, bool isChild, out IPAddress simHost, out int simPort, out Uri seedCapability)
        {
            simHost = null;
            simPort = 0;
            seedCapability = null;

            Uri rezAvatarRequestCap;
            if (neighbor.TryGetCapability("rez_avatar/request", out rezAvatarRequestCap))
            {
                string firstName, lastName;
                Util.GetFirstLastName(agent.Name, out firstName, out lastName);

                // Find the presence position relative to this neighbor
                Vector3 relativePosition = agent.ScenePosition - new Vector3(neighbor.MinPosition - m_scene.MinPosition);
                // Calculate the direction this agent is currently facing
                Vector3 lookAt = Vector3.UnitY * agent.RelativeRotation;

                // Create the template rez_avatar/request message
                OSDMap rezAvatarRequest = new OSDMap
                {
                    { "agent_id", OSD.FromUUID(agent.ID) },
                    { "session_id", OSD.FromUUID(agent.SessionID) },
                    { "position", OSD.FromVector3(relativePosition) },
                    { "look_at", OSD.FromVector3(lookAt) },
                    { "velocity", OSD.FromVector3(agent.Velocity) },
                    { "child", OSD.FromBoolean(isChild) }
                };

                OSDMap rezAvatarResponse = null;
                try
                {
                    // Send the message and get a response
                    rezAvatarResponse = OSDParser.Deserialize(UntrustedHttpWebRequest.PostToUntrustedUrl(
                        rezAvatarRequestCap, OSDParser.SerializeJsonString(rezAvatarRequest))) as OSDMap;
                }
                catch { }

                if (rezAvatarResponse != null)
                {
                    return RezChildAgentReplyHandler(agent, rezAvatarResponse, out simHost, out simPort, out seedCapability);
                }
                else
                {
                    m_log.Warn(m_scene.Name + " failed to create a child agent on " + neighbor.Name +
                        ", rez_avatar/request failed");
                }
            }
            else
            {
                m_log.Warn(neighbor.Name + " does not have a rez_avatar/request capability");
            }

            return false;
        }
Example #43
0
        public void SendAcks(LLAgent agent)
        {
            const int MAX_ACKS_PER_PACKET = Byte.MaxValue;

            uint ack;
            if (agent.PendingAcks.TryDequeue(out ack))
            {
                List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(agent.PendingAcks.Count);
                PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock();
                block.ID = ack;
                blocks.Add(block);

                int count = 1;

                while (count < MAX_ACKS_PER_PACKET && agent.PendingAcks.TryDequeue(out ack))
                {
                    block = new PacketAckPacket.PacketsBlock();
                    block.ID = ack;
                    blocks.Add(block);

                    ++count;
                }

                PacketAckPacket packet = new PacketAckPacket();
                packet.Header.Reliable = false;
                packet.Packets = blocks.ToArray();

                SendPacket(agent, packet, ThrottleCategory.Unknown, false);
            }
        }
Example #44
0
 public bool TryGetAgent(UUID agentID, out LLAgent agent)
 {
     return(m_udpServer.TryGetAgent(agentID, out agent));
 }
Example #45
0
        public void SendPacket(LLAgent agent, Packet packet, ThrottleCategory category, bool allowSplitting)
        {
            // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
            if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
                allowSplitting = false;

            try
            {
                if (allowSplitting && packet.HasVariableBlocks)
                {
                    byte[][] datas = packet.ToBytesMultiple();
                    int packetCount = datas.Length;

                    if (packetCount < 1)
                        m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);

                    for (int i = 0; i < packetCount; i++)
                    {
                        byte[] data = datas[i];
                        SendPacketData(agent, data, packet.Type, category);
                    }
                }
                else
                {
                    byte[] data = packet.ToBytes();
                    SendPacketData(agent, data, packet.Type, category);
                }
            }
            catch (NullReferenceException)
            {
                System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true);
                m_log.Error("An invalid " + packet.Type + " packet was built in:" + Environment.NewLine + trace.ToString());
            }
        }
Example #46
0
        private void PacketHandler()
        {
            Action <LLAgent> clientPacketHandler = ClientOutgoingPacketHandler;

            while (base.IsRunning)
            {
                try
                {
                    // Time keeping
                    int now     = Util.TickCount();
                    int elapsed = now - m_tickLastOutgoingPacketHandler;
                    m_tickLastOutgoingPacketHandler = now;

                    // Maximum time to wait dequeuing an incoming packet. Used
                    // to put this thread to sleep when there is little or no
                    // activity
                    int dequeueTimeout = 0;

                    #region Outgoing Packets

                    m_packetSent = false;

                    #region Update Timers

                    m_resendUnacked = false;
                    m_sendAcks      = false;
                    m_sendPing      = false;

                    m_resendTimer.Elapsed += elapsed;
                    m_ackTimer.Elapsed    += elapsed;
                    m_pingTimer.Elapsed   += elapsed;

                    if (m_resendTimer.Elapsed >= m_resendTimer.Interval)
                    {
                        m_resendUnacked       = true;
                        m_resendTimer.Elapsed = 0;
                    }
                    if (m_ackTimer.Elapsed >= m_ackTimer.Interval)
                    {
                        m_sendAcks         = true;
                        m_ackTimer.Elapsed = 0;
                    }
                    if (m_pingTimer.Elapsed >= m_pingTimer.Interval)
                    {
                        m_sendPing          = true;
                        m_pingTimer.Elapsed = 0;
                    }

                    #endregion Update Timers

                    // Handle outgoing packets, resends, acknowledgements, and pings for each
                    // client. m_packetSent will be set to true if a packet is sent
                    m_clients.ForEach(clientPacketHandler);

                    // If nothing was sent, wait up to the minimum amount of time before a
                    // token bucket could get more tokens, if we have clients connected.
                    // Otherwise, do a long wait
                    if (!m_packetSent)
                    {
                        if (m_clients.Count > 0)
                        {
                            dequeueTimeout = (int)Scene.Simian.TickCountResolution;
                        }
                        else
                        {
                            dequeueTimeout = Simian.LONG_SLEEP_INTERVAL;
                        }
                    }

                    #endregion Outgoing Packets

                    #region Incoming Packets

                    IncomingPacket incomingPacket = null;

                    if (m_packetInbox.Dequeue(dequeueTimeout, ref incomingPacket))
                    {
                        Packet  packet = incomingPacket.Packet;
                        LLAgent agent  = incomingPacket.Agent;

                        // Record the time we started processing this packet
                        incomingPacket.StartedHandling = Util.TickCount();

                        // Sanity check
                        if (packet == null || agent == null)
                        {
                            m_log.WarnFormat("Processing a packet with incomplete state. Packet=\"{0}\", LLAgent=\"{1}\"",
                                             packet, agent);
                        }

                        PacketEvents.BeginRaiseEvent(incomingPacket);
                    }

                    #endregion Incoming Packets
                }
                catch (Exception ex)
                {
                    m_log.Error("Error in the packet handler loop: " + ex.Message, ex);
                }

                Scheduler.ThreadKeepAlive();
            }

            if (m_packetInbox.Count > 0)
            {
                m_log.Warn("IncomingPacketHandler is shutting down, dropping " + m_packetInbox.Count + " packets");
            }
            m_packetInbox.Clear();

            Scheduler.RemoveThread();
        }
Example #47
0
        public void SendPacketData(LLAgent agent, byte[] data, PacketType type, ThrottleCategory 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(agent.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("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)
                {
                    m_log.Error("Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                        type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
                    buffer.Data = new byte[dataLength];
                }

                Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(agent, buffer, category, type);

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

            #endregion Queue or Send
        }
Example #48
0
 public void FireQueueEmpty(LLAgent agent, ThrottleCategoryFlags categories)
 {
     QueueEmptyCallback callback = OnQueueEmpty;
     if (callback != null)
         callback(agent, categories);
 }
Example #49
0
 public void FireQueueEmpty(LLAgent agent, ThrottleCategoryFlags categories)
 {
     m_udp.FireQueueEmpty(agent, categories);
 }
Example #50
0
        private bool RezChildAgentReplyHandler(LLAgent agent, OSDMap map, out IPAddress simHost, out int simPort, out Uri seedCapability)
        {
            simHost        = null;
            simPort        = 0;
            seedCapability = null;

            if (map["connect"].AsBoolean())
            {
                #region Response Parsing

                string simHostStr = map["sim_host"].AsString();
                if (!IPAddress.TryParse(simHostStr, out simHost))
                {
                    m_log.Warn("rez_avatar/response had an invalid sim_host: " + simHostStr);
                    return(false);
                }

                simPort = map["sim_port"].AsInteger();
                UUID regionID = map["region_id"].AsUUID();

                uint  regionX      = map["region_x"].AsUInteger();
                uint  regionY      = map["region_y"].AsUInteger();
                ulong regionHandle = Utils.UIntsToLong(regionX, regionY);

                seedCapability = map["region_seed_capability"].AsUri();
                if (seedCapability == null)
                {
                    m_log.Warn("rez_avatar/response had an invalid region_seed_capability: " + map["region_seed_capability"].AsString());
                    return(false);
                }

                #endregion Response Parsing

                #region EnableSimulator

                EnableSimulatorMessage.SimulatorInfoBlock block = new EnableSimulatorMessage.SimulatorInfoBlock();
                block.IP           = simHost;
                block.Port         = simPort;
                block.RegionHandle = regionHandle;

                EnableSimulatorMessage enable = new EnableSimulatorMessage();
                enable.Simulators    = new EnableSimulatorMessage.SimulatorInfoBlock[1];
                enable.Simulators[0] = block;

                m_log.Debug("Sending EnableSimulator message for scene " + regionID + " to " + agent.Name);
                agent.EventQueue.QueueEvent("EnableSimulator", enable.Serialize());

                #endregion EnableSimulator

                #region EstablishAgentCommunication

                // Send an EstablishAgentCommunication event down to the client to get the neighbor event queue established
                EstablishAgentCommunicationMessage eacMessage = new EstablishAgentCommunicationMessage();
                eacMessage.AgentID        = regionID;
                eacMessage.Address        = simHost;
                eacMessage.Port           = simPort;
                eacMessage.SeedCapability = seedCapability;

                m_log.Debug("Sending EstablishAgentCommunication message for seedcap " + seedCapability + " to " + agent.Name);
                agent.EventQueue.QueueEvent("EstablishAgentCommunication", eacMessage.Serialize());

                #endregion EstablishAgentCommunication

                return(true);
            }
            else
            {
                m_log.Warn("rez_avatar/request from " + m_scene.Name + " for child agent " + agent.Name +
                           " failed: " + map["message"].AsString());
                return(false);
            }
        }
Example #51
0
 public void SendPacket(LLAgent agent, Packet packet, ThrottleCategory category, bool allowSplitting)
 {
     m_udpServer.SendPacket(agent, packet, category, allowSplitting);
 }