aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs338
1 files changed, 288 insertions, 50 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index d6513c5..b8951d9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,6 +37,7 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 41using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42using OpenMetaverse; 43using OpenMetaverse;
@@ -100,9 +101,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
100 101
101 /// <summary>The measured resolution of Environment.TickCount</summary> 102 /// <summary>The measured resolution of Environment.TickCount</summary>
102 public readonly float TickCountResolution; 103 public readonly float TickCountResolution;
104
103 /// <summary>Number of prim updates to put on the queue each time the 105 /// <summary>Number of prim updates to put on the queue each time the
104 /// OnQueueEmpty event is triggered for updates</summary> 106 /// OnQueueEmpty event is triggered for updates</summary>
105 public readonly int PrimUpdatesPerCallback; 107 public readonly int PrimUpdatesPerCallback;
108
106 /// <summary>Number of texture packets to put on the queue each time the 109 /// <summary>Number of texture packets to put on the queue each time the
107 /// OnQueueEmpty event is triggered for textures</summary> 110 /// OnQueueEmpty event is triggered for textures</summary>
108 public readonly int TextureSendLimit; 111 public readonly int TextureSendLimit;
@@ -124,28 +127,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
124 127
125 /// <summary>Manages authentication for agent circuits</summary> 128 /// <summary>Manages authentication for agent circuits</summary>
126 private AgentCircuitManager m_circuitManager; 129 private AgentCircuitManager m_circuitManager;
130
127 /// <summary>Reference to the scene this UDP server is attached to</summary> 131 /// <summary>Reference to the scene this UDP server is attached to</summary>
128 protected Scene m_scene; 132 protected Scene m_scene;
133
129 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 134 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
130 private Location m_location; 135 private Location m_location;
136
131 /// <summary>The size of the receive buffer for the UDP socket. This value 137 /// <summary>The size of the receive buffer for the UDP socket. This value
132 /// is passed up to the operating system and used in the system networking 138 /// is passed up to the operating system and used in the system networking
133 /// stack. Use zero to leave this value as the default</summary> 139 /// stack. Use zero to leave this value as the default</summary>
134 private int m_recvBufferSize; 140 private int m_recvBufferSize;
141
135 /// <summary>Flag to process packets asynchronously or synchronously</summary> 142 /// <summary>Flag to process packets asynchronously or synchronously</summary>
136 private bool m_asyncPacketHandling; 143 private bool m_asyncPacketHandling;
144
137 /// <summary>Tracks whether or not a packet was sent each round so we know 145 /// <summary>Tracks whether or not a packet was sent each round so we know
138 /// whether or not to sleep</summary> 146 /// whether or not to sleep</summary>
139 private bool m_packetSent; 147 private bool m_packetSent;
140 148
141 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> 149 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
142 private int m_elapsedMSSinceLastStatReport = 0; 150 private int m_elapsedMSSinceLastStatReport = 0;
151
143 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> 152 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
144 private int m_tickLastOutgoingPacketHandler; 153 private int m_tickLastOutgoingPacketHandler;
154
145 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> 155 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
146 private int m_elapsedMSOutgoingPacketHandler; 156 private int m_elapsedMSOutgoingPacketHandler;
157
147 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> 158 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
148 private int m_elapsed100MSOutgoingPacketHandler; 159 private int m_elapsed100MSOutgoingPacketHandler;
160
149 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> 161 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
150 private int m_elapsed500MSOutgoingPacketHandler; 162 private int m_elapsed500MSOutgoingPacketHandler;
151 163
@@ -159,6 +171,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
159 protected bool m_sendPing; 171 protected bool m_sendPing;
160 172
161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 173 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
174 private Pool<IncomingPacket> m_incomingPacketPool;
175
176 private Stat m_incomingPacketPoolStat;
162 177
163 private int m_defaultRTO = 0; 178 private int m_defaultRTO = 0;
164 private int m_maxRTO = 0; 179 private int m_maxRTO = 0;
@@ -180,7 +195,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
180 /// </summary> 195 /// </summary>
181 private IClientAPI m_currentIncomingClient; 196 private IClientAPI m_currentIncomingClient;
182 197
183 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 198 public LLUDPServer(
199 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
200 IConfigSource configSource, AgentCircuitManager circuitManager)
184 : base(listenIP, (int)port) 201 : base(listenIP, (int)port)
185 { 202 {
186 #region Environment.TickCount Measurement 203 #region Environment.TickCount Measurement
@@ -202,6 +219,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 219
203 m_circuitManager = circuitManager; 220 m_circuitManager = circuitManager;
204 int sceneThrottleBps = 0; 221 int sceneThrottleBps = 0;
222 bool usePools = false;
205 223
206 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 224 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
207 if (config != null) 225 if (config != null)
@@ -227,6 +245,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
227 m_pausedAckTimeout = 1000 * 300; // 5 minutes 245 m_pausedAckTimeout = 1000 * 300; // 5 minutes
228 } 246 }
229 247
248 // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers.
249 // However, there is no harm in temporarily doing it multiple times.
250 IConfig packetConfig = configSource.Configs["PacketPool"];
251 if (packetConfig != null)
252 {
253 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
254 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
255 usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools);
256 }
257
230 #region BinaryStats 258 #region BinaryStats
231 config = configSource.Configs["Statistics.Binary"]; 259 config = configSource.Configs["Statistics.Binary"];
232 m_shouldCollectStats = false; 260 m_shouldCollectStats = false;
@@ -254,20 +282,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
254 282
255 m_throttle = new TokenBucket(null, sceneThrottleBps); 283 m_throttle = new TokenBucket(null, sceneThrottleBps);
256 ThrottleRates = new ThrottleRates(configSource); 284 ThrottleRates = new ThrottleRates(configSource);
285
286 if (usePools)
287 EnablePools();
257 } 288 }
258 289
259 public void Start() 290 public void Start()
260 { 291 {
261 if (m_scene == null) 292 StartInbound();
262 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); 293 StartOutbound();
263 294
295 m_elapsedMSSinceLastStatReport = Environment.TickCount;
296 }
297
298 private void StartInbound()
299 {
264 m_log.InfoFormat( 300 m_log.InfoFormat(
265 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", 301 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}",
266 m_asyncPacketHandling ? "asynchronous" : "synchronous"); 302 m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools);
267 303
268 base.Start(m_recvBufferSize, m_asyncPacketHandling); 304 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling);
269 305
270 // Start the packet processing threads 306 // This thread will process the packets received that are placed on the packetInbox
271 Watchdog.StartThread( 307 Watchdog.StartThread(
272 IncomingPacketHandler, 308 IncomingPacketHandler,
273 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), 309 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -276,6 +312,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
276 true, 312 true,
277 GetWatchdogIncomingAlarmData, 313 GetWatchdogIncomingAlarmData,
278 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 314 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
315 }
316
317 private new void StartOutbound()
318 {
319 m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server");
320
321 base.StartOutbound();
279 322
280 Watchdog.StartThread( 323 Watchdog.StartThread(
281 OutgoingPacketHandler, 324 OutgoingPacketHandler,
@@ -285,8 +328,57 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 true, 328 true,
286 GetWatchdogOutgoingAlarmData, 329 GetWatchdogOutgoingAlarmData,
287 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 330 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
331 }
288 332
289 m_elapsedMSSinceLastStatReport = Environment.TickCount; 333 public void Stop()
334 {
335 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
336 base.StopOutbound();
337 base.StopInbound();
338 }
339
340 protected override bool EnablePools()
341 {
342 if (!UsePools)
343 {
344 base.EnablePools();
345
346 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
347
348 m_incomingPacketPoolStat
349 = new Stat(
350 "IncomingPacketPoolCount",
351 "Objects within incoming packet pool",
352 "The number of objects currently stored within the incoming packet pool",
353 "",
354 "clientstack",
355 "packetpool",
356 StatType.Pull,
357 stat => stat.Value = m_incomingPacketPool.Count,
358 StatVerbosity.Debug);
359
360 StatsManager.RegisterStat(m_incomingPacketPoolStat);
361
362 return true;
363 }
364
365 return false;
366 }
367
368 protected override bool DisablePools()
369 {
370 if (UsePools)
371 {
372 base.DisablePools();
373
374 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
375
376 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
377
378 return true;
379 }
380
381 return false;
290 } 382 }
291 383
292 /// <summary> 384 /// <summary>
@@ -311,12 +403,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
311 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); 403 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
312 } 404 }
313 405
314 public new void Stop()
315 {
316 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
317 base.Stop();
318 }
319
320 public void AddScene(IScene scene) 406 public void AddScene(IScene scene)
321 { 407 {
322 if (m_scene != null) 408 if (m_scene != null)
@@ -333,6 +419,117 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 419
334 m_scene = (Scene)scene; 420 m_scene = (Scene)scene;
335 m_location = new Location(m_scene.RegionInfo.RegionHandle); 421 m_location = new Location(m_scene.RegionInfo.RegionHandle);
422
423 MainConsole.Instance.Commands.AddCommand(
424 "Debug",
425 false,
426 "debug lludp start",
427 "debug lludp start <in|out|all>",
428 "Control LLUDP packet processing.",
429 "No effect if packet processing has already started.\n"
430 + "in - start inbound processing.\n"
431 + "out - start outbound processing.\n"
432 + "all - start in and outbound processing.\n",
433 HandleStartCommand);
434
435 MainConsole.Instance.Commands.AddCommand(
436 "Debug",
437 false,
438 "debug lludp stop",
439 "debug lludp stop <in|out|all>",
440 "Stop LLUDP packet processing.",
441 "No effect if packet processing has already stopped.\n"
442 + "in - stop inbound processing.\n"
443 + "out - stop outbound processing.\n"
444 + "all - stop in and outbound processing.\n",
445 HandleStopCommand);
446
447 MainConsole.Instance.Commands.AddCommand(
448 "Debug",
449 false,
450 "debug lludp pool",
451 "debug lludp pool <on|off>",
452 "Turn object pooling within the lludp component on or off.",
453 HandlePoolCommand);
454
455 MainConsole.Instance.Commands.AddCommand(
456 "Debug",
457 false,
458 "debug lludp status",
459 "debug lludp status",
460 "Return status of LLUDP packet processing.",
461 HandleStatusCommand);
462 }
463
464 private void HandleStartCommand(string module, string[] args)
465 {
466 if (args.Length != 4)
467 {
468 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
469 return;
470 }
471
472 string subCommand = args[3];
473
474 if (subCommand == "in" || subCommand == "all")
475 StartInbound();
476
477 if (subCommand == "out" || subCommand == "all")
478 StartOutbound();
479 }
480
481 private void HandleStopCommand(string module, string[] args)
482 {
483 if (args.Length != 4)
484 {
485 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
486 return;
487 }
488
489 string subCommand = args[3];
490
491 if (subCommand == "in" || subCommand == "all")
492 StopInbound();
493
494 if (subCommand == "out" || subCommand == "all")
495 StopOutbound();
496 }
497
498 private void HandlePoolCommand(string module, string[] args)
499 {
500 if (args.Length != 4)
501 {
502 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
503 return;
504 }
505
506 string enabled = args[3];
507
508 if (enabled == "on")
509 {
510 if (EnablePools())
511 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name);
512 }
513 else if (enabled == "off")
514 {
515 if (DisablePools())
516 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name);
517 }
518 else
519 {
520 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
521 }
522 }
523
524 private void HandleStatusCommand(string module, string[] args)
525 {
526 MainConsole.Instance.OutputFormat(
527 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
528
529 MainConsole.Instance.OutputFormat(
530 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
531
532 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
336 } 533 }
337 534
338 public bool HandlesRegion(Location x) 535 public bool HandlesRegion(Location x)
@@ -416,6 +613,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 byte[] data = packet.ToBytes(); 613 byte[] data = packet.ToBytes();
417 SendPacketData(udpClient, data, packet.Type, category, method); 614 SendPacketData(udpClient, data, packet.Type, category, method);
418 } 615 }
616
617 PacketPool.Instance.ReturnPacket(packet);
419 } 618 }
420 619
421 /// <summary> 620 /// <summary>
@@ -700,7 +899,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
700 LLUDPClient udpClient = null; 899 LLUDPClient udpClient = null;
701 Packet packet = null; 900 Packet packet = null;
702 int packetEnd = buffer.DataLength - 1; 901 int packetEnd = buffer.DataLength - 1;
703 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; 902 IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint;
704 903
705 #region Decoding 904 #region Decoding
706 905
@@ -710,7 +909,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
710// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 909// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
711// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 910// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
712 911
713 return; // Drop undersizd packet 912 return; // Drop undersized packet
714 } 913 }
715 914
716 int headerLen = 7; 915 int headerLen = 7;
@@ -733,7 +932,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
733 932
734 try 933 try
735 { 934 {
736 packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 935// packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
936// // Only allocate a buffer for zerodecoding if the packet is zerocoded
937// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
938 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
939 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
940 // bytes are copied out).
941 packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
737 // Only allocate a buffer for zerodecoding if the packet is zerocoded 942 // Only allocate a buffer for zerodecoding if the packet is zerocoded
738 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 943 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
739 } 944 }
@@ -748,11 +953,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
748 953
749 return; // Drop short packet 954 return; // Drop short packet
750 } 955 }
751 catch(Exception e) 956 catch (Exception e)
752 { 957 {
753 if (m_malformedCount < 100) 958 if (m_malformedCount < 100)
754 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 959 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
960
755 m_malformedCount++; 961 m_malformedCount++;
962
756 if ((m_malformedCount % 100000) == 0) 963 if ((m_malformedCount % 100000) == 0)
757 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); 964 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
758 } 965 }
@@ -772,7 +979,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
772 979
773 // If there is already a client for this endpoint, don't process UseCircuitCode 980 // If there is already a client for this endpoint, don't process UseCircuitCode
774 IClientAPI client = null; 981 IClientAPI client = null;
775 if (!m_scene.TryGetClient(address, out client)) 982 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
776 { 983 {
777 // UseCircuitCode handling 984 // UseCircuitCode handling
778 if (packet.Type == PacketType.UseCircuitCode) 985 if (packet.Type == PacketType.UseCircuitCode)
@@ -780,13 +987,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
780 // And if there is a UseCircuitCode pending, also drop it 987 // And if there is a UseCircuitCode pending, also drop it
781 lock (m_pendingCache) 988 lock (m_pendingCache)
782 { 989 {
783 if (m_pendingCache.Contains(address)) 990 if (m_pendingCache.Contains(endPoint))
784 return; 991 return;
785 992
786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60); 993 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
787 } 994 }
788 995
789 object[] array = new object[] { buffer, packet }; 996 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
997 // buffer.
998 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
790 999
791 Util.FireAndForget(HandleUseCircuitCode, array); 1000 Util.FireAndForget(HandleUseCircuitCode, array);
792 1001
@@ -798,7 +1007,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
798 lock (m_pendingCache) 1007 lock (m_pendingCache)
799 { 1008 {
800 Queue<UDPPacketBuffer> queue; 1009 Queue<UDPPacketBuffer> queue;
801 if (m_pendingCache.TryGetValue(address, out queue)) 1010 if (m_pendingCache.TryGetValue(endPoint, out queue))
802 { 1011 {
803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); 1012 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
804 queue.Enqueue(buffer); 1013 queue.Enqueue(buffer);
@@ -834,6 +1043,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
834 // Handle appended ACKs 1043 // Handle appended ACKs
835 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 1044 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
836 { 1045 {
1046// m_log.DebugFormat(
1047// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1048// packet.Header.AckList.Length, client.Name, m_scene.Name);
1049
837 for (int i = 0; i < packet.Header.AckList.Length; i++) 1050 for (int i = 0; i < packet.Header.AckList.Length; i++)
838 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1051 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
839 } 1052 }
@@ -843,6 +1056,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
843 { 1056 {
844 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1057 PacketAckPacket ackPacket = (PacketAckPacket)packet;
845 1058
1059// m_log.DebugFormat(
1060// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1061// ackPacket.Packets.Length, client.Name, m_scene.Name);
1062
846 for (int i = 0; i < ackPacket.Packets.Length; i++) 1063 for (int i = 0; i < ackPacket.Packets.Length; i++)
847 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1064 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
848 1065
@@ -856,6 +1073,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
856 1073
857 if (packet.Header.Reliable) 1074 if (packet.Header.Reliable)
858 { 1075 {
1076// m_log.DebugFormat(
1077// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}",
1078// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name);
1079
859 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 1080 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
860 1081
861 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 1082 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
@@ -902,6 +1123,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
902 1123
903 if (packet.Type == PacketType.StartPingCheck) 1124 if (packet.Type == PacketType.StartPingCheck)
904 { 1125 {
1126// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);
1127
905 // We don't need to do anything else with ping checks 1128 // We don't need to do anything else with ping checks
906 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1129 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
907 CompletePing(udpClient, startPing.PingID.PingID); 1130 CompletePing(udpClient, startPing.PingID.PingID);
@@ -921,13 +1144,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
921 1144
922 #endregion Ping Check Handling 1145 #endregion Ping Check Handling
923 1146
1147 IncomingPacket incomingPacket;
1148
924 // Inbox insertion 1149 // Inbox insertion
925 if (packet.Type == PacketType.AgentUpdate || 1150 if (UsePools)
926 packet.Type == PacketType.ChatFromViewer) 1151 {
927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); 1152 incomingPacket = m_incomingPacketPool.GetObject();
1153 incomingPacket.Client = (LLClientView)client;
1154 incomingPacket.Packet = packet;
1155 }
1156 else
1157 {
1158 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1159 }
1160
1161 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1162 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1163 packetInbox.EnqueueHigh(incomingPacket);
928 else 1164 else
929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); 1165 packetInbox.EnqueueLow(incomingPacket);
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
931 } 1166 }
932 1167
933 #region BinaryStats 1168 #region BinaryStats
@@ -1013,21 +1248,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1013 1248
1014 private void HandleUseCircuitCode(object o) 1249 private void HandleUseCircuitCode(object o)
1015 { 1250 {
1016 IPEndPoint remoteEndPoint = null; 1251 IPEndPoint endPoint = null;
1017 IClientAPI client = null; 1252 IClientAPI client = null;
1018 1253
1019 try 1254 try
1020 { 1255 {
1021 // DateTime startTime = DateTime.Now; 1256 // DateTime startTime = DateTime.Now;
1022 object[] array = (object[])o; 1257 object[] array = (object[])o;
1023 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; 1258 endPoint = (IPEndPoint)array[0];
1024 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1259 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
1025 1260
1026 m_log.DebugFormat( 1261 m_log.DebugFormat(
1027 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1262 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1028 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); 1263 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint);
1029
1030 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
1031 1264
1032 AuthenticateResponse sessionInfo; 1265 AuthenticateResponse sessionInfo;
1033 if (IsClientAuthorized(uccp, out sessionInfo)) 1266 if (IsClientAuthorized(uccp, out sessionInfo))
@@ -1038,13 +1271,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1038 uccp.CircuitCode.Code, 1271 uccp.CircuitCode.Code,
1039 uccp.CircuitCode.ID, 1272 uccp.CircuitCode.ID,
1040 uccp.CircuitCode.SessionID, 1273 uccp.CircuitCode.SessionID,
1041 remoteEndPoint, 1274 endPoint,
1042 sessionInfo); 1275 sessionInfo);
1043 1276
1044 // Send ack straight away to let the viewer know that the connection is active. 1277 // Send ack straight away to let the viewer know that the connection is active.
1045 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1278 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1046 // circuit code to the existing child agent. This is not particularly obvious. 1279 // circuit code to the existing child agent. This is not particularly obvious.
1047 SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); 1280 SendAckImmediate(endPoint, uccp.Header.Sequence);
1048 1281
1049 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1282 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1050 if (client != null) 1283 if (client != null)
@@ -1058,12 +1291,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1058 1291
1059 lock (m_pendingCache) 1292 lock (m_pendingCache)
1060 { 1293 {
1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) 1294 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1062 { 1295 {
1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1296 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1064 return; 1297 return;
1065 } 1298 }
1066 m_pendingCache.Remove(remoteEndPoint); 1299 m_pendingCache.Remove(endPoint);
1067 } 1300 }
1068 1301
1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); 1302 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
@@ -1081,9 +1314,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1081 // Don't create clients for unauthorized requesters. 1314 // Don't create clients for unauthorized requesters.
1082 m_log.WarnFormat( 1315 m_log.WarnFormat(
1083 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1316 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1317 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1085 lock (m_pendingCache) 1318 lock (m_pendingCache)
1086 m_pendingCache.Remove(remoteEndPoint); 1319 m_pendingCache.Remove(endPoint);
1087 } 1320 }
1088 1321
1089 // m_log.DebugFormat( 1322 // m_log.DebugFormat(
@@ -1095,7 +1328,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1095 { 1328 {
1096 m_log.ErrorFormat( 1329 m_log.ErrorFormat(
1097 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", 1330 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1098 remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", 1331 endPoint != null ? endPoint.ToString() : "n/a",
1099 client != null ? client.Name : "unknown", 1332 client != null ? client.Name : "unknown",
1100 client != null ? client.AgentId.ToString() : "unknown", 1333 client != null ? client.AgentId.ToString() : "unknown",
1101 e.Message, 1334 e.Message,
@@ -1160,20 +1393,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1160 { 1393 {
1161 IClientAPI client = null; 1394 IClientAPI client = null;
1162 1395
1163 // In priciple there shouldn't be more than one thread here, ever. 1396 // We currently synchronize this code across the whole scene to avoid issues such as
1164 // But in case that happens, we need to synchronize this piece of code 1397 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
1165 // because it's too important 1398 // consistently, this lock could probably be removed.
1166 lock (this) 1399 lock (this)
1167 { 1400 {
1168 if (!m_scene.TryGetClient(agentID, out client)) 1401 if (!m_scene.TryGetClient(agentID, out client))
1169 { 1402 {
1170 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1403 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1171 1404
1172 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1405 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1173 client.OnLogout += LogoutHandler; 1406 client.OnLogout += LogoutHandler;
1174 1407
1175 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1408 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1176 1409
1177 client.Start(); 1410 client.Start();
1178 } 1411 }
1179 } 1412 }
@@ -1212,7 +1445,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1212 // on to en-US to avoid number parsing issues 1445 // on to en-US to avoid number parsing issues
1213 Culture.SetCurrentCulture(); 1446 Culture.SetCurrentCulture();
1214 1447
1215 while (base.IsRunning) 1448 while (IsRunningInbound)
1216 { 1449 {
1217 m_scene.ThreadAlive(1); 1450 m_scene.ThreadAlive(1);
1218 try 1451 try
@@ -1228,7 +1461,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1228 } 1461 }
1229 1462
1230 if (packetInbox.Dequeue(100, ref incomingPacket)) 1463 if (packetInbox.Dequeue(100, ref incomingPacket))
1464 {
1231 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); 1465 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
1466
1467 if (UsePools)
1468 m_incomingPacketPool.ReturnObject(incomingPacket);
1469 }
1232 } 1470 }
1233 catch (Exception ex) 1471 catch (Exception ex)
1234 { 1472 {
@@ -1255,7 +1493,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1255 // Action generic every round 1493 // Action generic every round
1256 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1494 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1257 1495
1258 while (base.IsRunning) 1496 while (base.IsRunningOutbound)
1259 { 1497 {
1260 m_scene.ThreadAlive(2); 1498 m_scene.ThreadAlive(2);
1261 try 1499 try
@@ -1523,7 +1761,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1523 if (!client.IsLoggingOut) 1761 if (!client.IsLoggingOut)
1524 { 1762 {
1525 client.IsLoggingOut = true; 1763 client.IsLoggingOut = true;
1526 client.Close(false); 1764 client.Close(false, false);
1527 } 1765 }
1528 } 1766 }
1529 } 1767 }