/// <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; }
/// <summary> /// Converts a <seealso cref="ThrottleCategory"/> integer to a /// flag value /// </summary> /// <param name="i">Throttle category to convert</param> /// <returns>Flag representation of the throttle category</returns> private static ThrottleCategoryFlags CategoryToFlag(int i) { ThrottleCategory category = (ThrottleCategory)i; switch (category) { case ThrottleCategory.Land: return(ThrottleCategoryFlags.Land); case ThrottleCategory.Wind: return(ThrottleCategoryFlags.Wind); case ThrottleCategory.Cloud: return(ThrottleCategoryFlags.Cloud); case ThrottleCategory.Task: return(ThrottleCategoryFlags.Task); case ThrottleCategory.Texture: return(ThrottleCategoryFlags.Texture); case ThrottleCategory.Asset: return(ThrottleCategoryFlags.Asset); default: return(0); } }
public void BroadcastMessage(OSD message, ThrottleCategory category) { byte[] messageData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(message)); byte[] data = BuildMessageBuffer_00(messageData, true); m_clients.ForEach(delegate(WSAgent agent) { SendMessageData(agent, data, category); }); }
/// <summary> /// Default constructor /// </summary> public WSAgent(WebSockets server, TokenBucket parentThrottle, ThrottleRates rates, UUID agentID, UUID sessionID, Socket socket, bool isChildAgent) { m_id = agentID; m_server = server; m_interestList = new InterestList(this, 200); IsChildPresence = isChildAgent; m_localID = m_server.Scene.CreateLocalID(); //TextureEntry = new Primitive.TextureEntry(DEFAULT_AVATAR_TEXTURE); SessionID = sessionID; Socket = socket; // Create a token bucket throttle for this client that has the scene token bucket as a parent m_throttle = new TokenBucket(parentThrottle, rates.ClientTotalLimit, rates.ClientTotal); // Create an array of token buckets for this clients different throttle categories m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) { ThrottleCategory type = (ThrottleCategory)i; // Initialize the message outboxes, where messages sit while they are waiting for tokens m_messageOutboxes[i] = new LocklessQueue <OutgoingMessage>(); // Initialize the token buckets that control the throttling for each category m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); } // Initialize this to a sane value to prevent early disconnects TickLastMessageReceived = Util.TickCount(); }
public void SendMessage(WSAgent agent, OSD message, ThrottleCategory category) { byte[] messageData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(message)); byte[] data = BuildMessageBuffer_00(messageData, true); SendMessageData(agent, data, category); }
public void BroadcastPacket(Packet packet, ThrottleCategory category, bool sendToPausedAgents, 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; } 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]; m_clients.ForEach(delegate(LLAgent agent) { SendPacketData(agent, data, packet.Type, category); }); } } else { byte[] data = packet.ToBytes(); m_clients.ForEach(delegate(LLAgent agent) { SendPacketData(agent, data, packet.Type, category); }); } }
public int GetLimit(ThrottleCategory type) { switch (type) { case ThrottleCategory.Resend: return(ResendLimit); case ThrottleCategory.Land: return(LandLimit); case ThrottleCategory.Wind: return(WindLimit); case ThrottleCategory.Cloud: return(CloudLimit); case ThrottleCategory.Task: return(TaskLimit); case ThrottleCategory.Texture: return(TextureLimit); case ThrottleCategory.Asset: return(AssetLimit); case ThrottleCategory.Unknown: default: return(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()); } }
public void BroadcastPacket(Packet packet, ThrottleCategory category, bool sendToPausedAgents, 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; 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]; m_clients.ForEach(delegate(LLAgent agent) { SendPacketData(agent, data, packet.Type, category); }); } } else { byte[] data = packet.ToBytes(); m_clients.ForEach(delegate(LLAgent agent) { SendPacketData(agent, data, packet.Type, category); }); } }
public void SendPacketData(LLAgent agent, byte[] data, PacketType type, ThrottleCategory category) { m_udpServer.SendPacketData(agent, data, type, category); }
public void SendPacket(LLAgent agent, Packet packet, ThrottleCategory category, bool allowSplitting) { m_udpServer.SendPacket(agent, packet, category, allowSplitting); }
public void BroadcastPacket(Packet packet, ThrottleCategory category, bool sendToPausedAgents, bool allowSplitting) { m_udpServer.BroadcastPacket(packet, category, sendToPausedAgents, allowSplitting); }
public void SendMessage(WSAgent agent, OSDMap message, ThrottleCategory category) { Server.SendMessage(agent, message, category); }
public void SendMessage(WSAgent agent, OSDMap message, ThrottleCategory category) { byte[] messageData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(message)); byte[] data = new byte[messageData.Length + 2]; // Start with 0x00 data[0] = 0x00; // Then the string Buffer.BlockCopy(messageData, 0, data, 1, messageData.Length); // End with 0xFF data[data.Length - 1] = 0xFF; SendMessageData(agent, data, category); }
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 }
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()); } }
private void SendMessageData(WSAgent agent, byte[] data, ThrottleCategory category) { // TODO: Throttling SendMessageFinal(agent.Socket, data); }
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 }
public int GetRate(ThrottleCategory type) { switch (type) { case ThrottleCategory.Resend: return Resend; case ThrottleCategory.Land: return Land; case ThrottleCategory.Wind: return Wind; case ThrottleCategory.Cloud: return Cloud; case ThrottleCategory.Task: return Task; case ThrottleCategory.Texture: return Texture; case ThrottleCategory.Asset: return Asset; case ThrottleCategory.Unknown: default: return 0; } }
/// <summary> /// Default constructor /// </summary> /// <param name="data">Serialized message to send</param> /// <param name="category">Throttling category for this packet</param> public OutgoingMessage(string data, ThrottleCategory category) { Data = data; Category = category; }
public void BroadcastMessage(OSDMap message, ThrottleCategory category) { Server.BroadcastMessage(message, category); }
/// <summary> /// Default constructor /// </summary> /// <param name="server">Reference to the UDP server this client is connected to</param> /// <param name="rates">Default throttling rates and maximum throttle limits</param> /// <param name="parentThrottle">Parent HTB (hierarchical token bucket) /// that the child throttles will be governed by</param> /// <param name="circuitCode">Circuit code for this connection</param> /// <param name="agentID">AgentID for the connected agent</param> /// <param name="sessionID">SessionID for the connected agent</param> /// <param name="secureSessionID">SecureSessionID for the connected agent</param> /// <param name="defaultRTO">Default retransmission timeout, in milliseconds</param> /// <param name="maxRTO">Maximum retransmission timeout, in milliseconds</param> /// <param name="remoteEndPoint">Remote endpoint for this connection</param> /// <param name="isChildAgent">True if this agent is currently simulated by /// another simulator, otherwise false</param> public LLAgent(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, UUID sessionID, UUID secureSessionID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO, bool isChildAgent) { m_id = agentID; m_udpServer = server; m_scene = m_udpServer.Scene; PacketArchive = new IncomingPacketHistoryCollection(200); NeedAcks = new UnackedPacketCollection(); PendingAcks = new LocklessQueue <uint>(); EventQueue = new LLEventQueue(); m_nextOnQueueEmpty = 1; m_defaultRTO = 1000 * 3; m_maxRTO = 1000 * 60; m_packetOutboxes = new LocklessQueue <OutgoingPacket> [THROTTLE_CATEGORY_COUNT]; m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; m_interestList = new InterestList(this, 200); IsChildPresence = isChildAgent; m_localID = m_scene.CreateLocalID(); TextureEntry = new Primitive.TextureEntry(DEFAULT_AVATAR_TEXTURE); SessionID = sessionID; SecureSessionID = secureSessionID; RemoteEndPoint = remoteEndPoint; CircuitCode = circuitCode; if (defaultRTO != 0) { m_defaultRTO = defaultRTO; } if (maxRTO != 0) { m_maxRTO = maxRTO; } // Create a token bucket throttle for this client that has the scene token bucket as a parent m_throttle = new TokenBucket(parentThrottle, rates.ClientTotalLimit, rates.ClientTotal); // Create an array of token buckets for this clients different throttle categories m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) { ThrottleCategory type = (ThrottleCategory)i; // Initialize the packet outboxes, where packets sit while they are waiting for tokens m_packetOutboxes[i] = new LocklessQueue <OutgoingPacket>(); // Initialize the token buckets that control the throttling for each category m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); } // Default the retransmission timeout to three seconds RTO = m_defaultRTO; // Initialize this to a sane value to prevent early disconnects TickLastPacketReceived = Util.TickCount(); IsConnected = true; }