aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs120
1 files changed, 86 insertions, 34 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 545a0bc..74175d0 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -89,6 +89,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
89 /// </summary> 89 /// </summary>
90 public class LLUDPServer : OpenSimUDPBase 90 public class LLUDPServer : OpenSimUDPBase
91 { 91 {
92 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
93 public const int MTU = 1400;
94
92 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 95 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
93 96
94 /// <summary>Handlers for incoming packets</summary> 97 /// <summary>Handlers for incoming packets</summary>
@@ -104,7 +107,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
104 /// <summary>Manages authentication for agent circuits</summary> 107 /// <summary>Manages authentication for agent circuits</summary>
105 private AgentCircuitManager m_circuitManager; 108 private AgentCircuitManager m_circuitManager;
106 /// <summary>Reference to the scene this UDP server is attached to</summary> 109 /// <summary>Reference to the scene this UDP server is attached to</summary>
107 private IScene m_scene; 110 private Scene m_scene;
108 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 111 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
109 private Location m_location; 112 private Location m_location;
110 /// <summary>The measured resolution of Environment.TickCount</summary> 113 /// <summary>The measured resolution of Environment.TickCount</summary>
@@ -181,15 +184,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 184
182 public void AddScene(IScene scene) 185 public void AddScene(IScene scene)
183 { 186 {
184 if (m_scene == null) 187 if (m_scene != null)
185 { 188 {
186 m_scene = scene; 189 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
187 m_location = new Location(m_scene.RegionInfo.RegionHandle); 190 return;
188 } 191 }
189 else 192
193 if (!(scene is Scene))
190 { 194 {
191 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); 195 m_log.Error("[LLUDPSERVER]: AddScene() called with an unrecognized scene type " + scene.GetType());
196 return;
192 } 197 }
198
199 m_scene = (Scene)scene;
200 m_location = new Location(m_scene.RegionInfo.RegionHandle);
193 } 201 }
194 202
195 public bool HandlesRegion(Location x) 203 public bool HandlesRegion(Location x)
@@ -267,38 +275,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP
267 { 275 {
268 int dataLength = data.Length; 276 int dataLength = data.Length;
269 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; 277 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
278 bool doCopy = true;
270 279
271 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. 280 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
272 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting 281 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
273 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here 282 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
274 // to accomodate for both common scenarios and provide ample room for ACK appending in both 283 // to accomodate for both common scenarios and provide ample room for ACK appending in both
275 int bufferSize = (dataLength > 180) ? Packet.MTU : 200; 284 int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
276 285
277 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 286 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
278 287
279 // Zerocode if needed 288 // Zerocode if needed
280 if (doZerocode) 289 if (doZerocode)
281 { 290 {
282 try { dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data); } 291 try
292 {
293 dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
294 doCopy = false;
295 }
283 catch (IndexOutOfRangeException) 296 catch (IndexOutOfRangeException)
284 { 297 {
285 // The packet grew larger than the bufferSize while zerocoding. 298 // The packet grew larger than the bufferSize while zerocoding.
286 // Remove the MSG_ZEROCODED flag and send the unencoded data 299 // Remove the MSG_ZEROCODED flag and send the unencoded data
287 // instead 300 // instead
288 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". Removing MSG_ZEROCODED flag"); 301 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
302 " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
289 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); 303 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
290 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
291 } 304 }
292 } 305 }
293 else 306
307 // If the packet data wasn't already copied during zerocoding, copy it now
308 if (doCopy)
294 { 309 {
295 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 310 if (dataLength <= buffer.Data.Length)
311 {
312 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
313 }
314 else
315 {
316 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
317 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
318 return;
319 }
296 } 320 }
321
297 buffer.DataLength = dataLength; 322 buffer.DataLength = dataLength;
298 323
299 #region Queue or Send 324 #region Queue or Send
300 325
301 // Look up the UDPClient this is going to
302 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); 326 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
303 327
304 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 328 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
@@ -513,7 +537,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 IClientAPI client; 537 IClientAPI client;
514 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView)) 538 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView))
515 { 539 {
516 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + 540 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address +
517 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients"); 541 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients");
518 return; 542 return;
519 } 543 }
@@ -553,6 +577,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
553 for (int i = 0; i < ackPacket.Packets.Length; i++) 577 for (int i = 0; i < ackPacket.Packets.Length; i++)
554 AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent); 578 AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent);
555 } 579 }
580
581 // We don't need to do anything else with PacketAck packets
582 return;
556 } 583 }
557 584
558 #endregion ACK Receiving 585 #endregion ACK Receiving
@@ -560,20 +587,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
560 #region ACK Sending 587 #region ACK Sending
561 588
562 if (packet.Header.Reliable) 589 if (packet.Header.Reliable)
590 {
563 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 591 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
564 592
565 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 593 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
566 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove 594 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
567 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to 595 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
568 // client.BytesSinceLastACK. Lockless thread safety 596 // client.BytesSinceLastACK. Lockless thread safety
569 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); 597 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
570 bytesSinceLastACK += buffer.DataLength; 598 bytesSinceLastACK += buffer.DataLength;
571 if (bytesSinceLastACK > Packet.MTU * 2) 599 if (bytesSinceLastACK > LLUDPServer.MTU * 2)
572 { 600 {
573 bytesSinceLastACK -= Packet.MTU * 2; 601 bytesSinceLastACK -= LLUDPServer.MTU * 2;
574 SendAcks(udpClient); 602 SendAcks(udpClient);
603 }
604 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
575 } 605 }
576 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
577 606
578 #endregion ACK Sending 607 #endregion ACK Sending
579 608
@@ -593,12 +622,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
593 622
594 #endregion Incoming Packet Accounting 623 #endregion Incoming Packet Accounting
595 624
596 // Don't bother clogging up the queue with PacketAck packets that are already handled here 625 #region Ping Check Handling
597 if (packet.Type != PacketType.PacketAck) 626
627 if (packet.Type == PacketType.StartPingCheck)
628 {
629 // We don't need to do anything else with ping checks
630 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
631
632 CompletePingCheckPacket completePing = new CompletePingCheckPacket();
633 completePing.PingID.PingID = startPing.PingID.PingID;
634 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false);
635 return;
636 }
637 else if (packet.Type == PacketType.CompletePingCheck)
598 { 638 {
599 // Inbox insertion 639 // We don't currently track client ping times
600 packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); 640 return;
601 } 641 }
642
643 #endregion Ping Check Handling
644
645 // Inbox insertion
646 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
602 } 647 }
603 648
604 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent) 649 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
@@ -693,12 +738,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
693 // on to en-US to avoid number parsing issues 738 // on to en-US to avoid number parsing issues
694 Culture.SetCurrentCulture(); 739 Culture.SetCurrentCulture();
695 740
696 IncomingPacket incomingPacket = null;
697
698 while (base.IsRunning) 741 while (base.IsRunning)
699 { 742 {
700 if (packetInbox.Dequeue(100, ref incomingPacket)) 743 IncomingPacket incomingPacket = null;
701 Util.FireAndForget(ProcessInPacket, incomingPacket); 744
745 try
746 {
747 if (packetInbox.Dequeue(100, ref incomingPacket))
748 Util.FireAndForget(ProcessInPacket, incomingPacket);
749 }
750 catch (Exception ex)
751 {
752 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
753 }
702 } 754 }
703 755
704 if (packetInbox.Count > 0) 756 if (packetInbox.Count > 0)
@@ -747,7 +799,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
747 elapsed500MS = 0; 799 elapsed500MS = 0;
748 } 800 }
749 801
750 m_scene.ClientManager.ForEach( 802 m_scene.ClientManager.ForEachSync(
751 delegate(IClientAPI client) 803 delegate(IClientAPI client)
752 { 804 {
753 if (client is LLClientView) 805 if (client is LLClientView)