aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
diff options
context:
space:
mode:
authorMelanie Thielker2008-07-22 17:58:42 +0000
committerMelanie Thielker2008-07-22 17:58:42 +0000
commitf112cebde2c1bc06108839acac82bc8addd7c506 (patch)
tree7f1e7fabf2fec74171d5982f09d847b47e20d7ca /OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
parent* refactor: move new inventory service call by user server to OGS1 with all t... (diff)
downloadopensim-SC_OLD-f112cebde2c1bc06108839acac82bc8addd7c506.zip
opensim-SC_OLD-f112cebde2c1bc06108839acac82bc8addd7c506.tar.gz
opensim-SC_OLD-f112cebde2c1bc06108839acac82bc8addd7c506.tar.bz2
opensim-SC_OLD-f112cebde2c1bc06108839acac82bc8addd7c506.tar.xz
Refactor the packet scheduling out of ClientView. Add intelligent
resending, timeouts, packet discarding. Add notification event for packet discarding. Add priority scheduling for packet queues. Add outgoing duplicate detection facility. Correct packet sequencing. Make provisions for automatic server side throttle adjustments (comes in next installment)
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs567
1 files changed, 41 insertions, 526 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index c9fc83a..41ac657 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -50,20 +50,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
50 50
51 51
52 /// <summary> 52 /// <summary>
53 /// Class that keeps track of past packets so that they don't get
54 /// duplicated when the client doesn't get back an ack
55 /// </summary>
56 public class PacketDupeLimiter
57 {
58 public PacketType pktype;
59 public int timeIn;
60 public uint packetId;
61 public PacketDupeLimiter()
62 {
63 }
64 }
65
66 /// <summary>
67 /// Handles new client connections 53 /// Handles new client connections
68 /// Constructor takes a single Packet and authenticates everything 54 /// Constructor takes a single Packet and authenticates everything
69 /// </summary> 55 /// </summary>
@@ -79,7 +65,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
79 /* static variables */ 65 /* static variables */
80 public static TerrainManager TerrainManager = new TerrainManager(new SecondLife()); 66 public static TerrainManager TerrainManager = new TerrainManager(new SecondLife());
81 67
82 public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, LLUUID agentID, ThrottleOutPacketType throttlePacketType);
83 public static SynchronizeClientHandler SynchronizeClient = null; 68 public static SynchronizeClientHandler SynchronizeClient = null;
84 /* private variables */ 69 /* private variables */
85 private readonly LLUUID m_sessionId; 70 private readonly LLUUID m_sessionId;
@@ -93,15 +78,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
93 78
94 private bool m_clientBlocked = false; 79 private bool m_clientBlocked = false;
95 80
96 // for sim stats
97 private int m_packetsReceived = 0;
98 private int m_lastPacketsReceivedSentToScene = 0;
99 private int m_unAckedBytes = 0;
100
101 private int m_packetsSent = 0;
102 private int m_lastPacketsSentSentToScene = 0;
103 private int m_clearDuplicatePacketTrackingOlderThenXSeconds = 30;
104
105 private int m_probesWithNoIngressPackets = 0; 81 private int m_probesWithNoIngressPackets = 0;
106 private int m_lastPacketsReceived = 0; 82 private int m_lastPacketsReceived = 0;
107 private byte[] ZeroOutBuffer = new byte[4096]; 83 private byte[] ZeroOutBuffer = new byte[4096];
@@ -109,8 +85,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
109 private readonly LLUUID m_agentId; 85 private readonly LLUUID m_agentId;
110 private readonly uint m_circuitCode; 86 private readonly uint m_circuitCode;
111 private int m_moneyBalance; 87 private int m_moneyBalance;
112 88 private IPacketHandler m_PacketHandler;
113 private Dictionary<uint, PacketDupeLimiter> m_dupeLimiter = new Dictionary<uint, PacketDupeLimiter>();
114 89
115 private int m_animationSequenceNumber = 1; 90 private int m_animationSequenceNumber = 1;
116 91
@@ -118,8 +93,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
118 93
119 private Dictionary<string, LLUUID> m_defaultAnimations = new Dictionary<string, LLUUID>(); 94 private Dictionary<string, LLUUID> m_defaultAnimations = new Dictionary<string, LLUUID>();
120 95
121 private LLPacketTracker m_packetTracker;
122
123 /* protected variables */ 96 /* protected variables */
124 97
125 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = 98 protected static Dictionary<PacketType, PacketMethod> PacketHandlers =
@@ -130,17 +103,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
130 protected IScene m_scene; 103 protected IScene m_scene;
131 protected AgentCircuitManager m_authenticateSessionsHandler; 104 protected AgentCircuitManager m_authenticateSessionsHandler;
132 105
133 protected LLPacketQueue m_packetQueue;
134
135 protected Dictionary<uint, uint> m_pendingAcks = new Dictionary<uint, uint>();
136 protected Dictionary<uint, Packet> m_needAck = new Dictionary<uint, Packet>();
137
138 protected Timer m_ackTimer;
139 protected uint m_sequence = 0;
140 protected object m_sequenceLock = new object();
141 protected const int MAX_APPENDED_ACKS = 10;
142 protected const int RESEND_TIMEOUT = 4000;
143 protected const int MAX_SEQUENCE = 0xFFFFFF;
144 protected LLPacketServer m_networkServer; 106 protected LLPacketServer m_networkServer;
145 107
146 /* public variables */ 108 /* public variables */
@@ -263,7 +225,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
263 private UpdateVector handlerUpdateVector = null; //OnUpdatePrimGroupPosition; 225 private UpdateVector handlerUpdateVector = null; //OnUpdatePrimGroupPosition;
264 private UpdatePrimRotation handlerUpdatePrimRotation = null; //OnUpdatePrimGroupRotation; 226 private UpdatePrimRotation handlerUpdatePrimRotation = null; //OnUpdatePrimGroupRotation;
265 // private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation = null; //OnUpdatePrimGroupMouseRotation; 227 // private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation = null; //OnUpdatePrimGroupMouseRotation;
266 private PacketStats handlerPacketStats = null; // OnPacketStats;#
267 // private RequestAsset handlerRequestAsset = null; // OnRequestAsset; 228 // private RequestAsset handlerRequestAsset = null; // OnRequestAsset;
268 private UUIDNameRequest handlerTeleportHomeRequest = null; 229 private UUIDNameRequest handlerTeleportHomeRequest = null;
269 230
@@ -378,13 +339,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
378 get { return m_animationSequenceNumber++; } 339 get { return m_animationSequenceNumber++; }
379 } 340 }
380 341
342 public IPacketHandler PacketHandler
343 {
344 get { return m_PacketHandler; }
345 }
346
347 bool m_IsActive = true;
348
349 public bool IsActive
350 {
351 get { return m_IsActive; }
352 set { m_IsActive = value; }
353 }
354
381 /* METHODS */ 355 /* METHODS */
382 356
383 public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer, 357 public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer,
384 AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP) 358 AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP)
385 { 359 {
386 m_packetTracker = new LLPacketTracker(this);
387
388 m_moneyBalance = 1000; 360 m_moneyBalance = 1000;
389 361
390 m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion()); 362 m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion());
@@ -414,7 +386,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
414 // in it to process. It's an on-purpose threadlock though because 386 // in it to process. It's an on-purpose threadlock though because
415 // without it, the clientloop will suck up all sim resources. 387 // without it, the clientloop will suck up all sim resources.
416 388
417 m_packetQueue = new LLPacketQueue(agentId); 389 m_PacketHandler = new LLPacketHandler(this);
390 m_PacketHandler.SynchronizeClient = SynchronizeClient;
418 391
419 RegisterLocalPacketHandlers(); 392 RegisterLocalPacketHandlers();
420 393
@@ -423,7 +396,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
423 m_clientThread.Name = "ClientThread"; 396 m_clientThread.Name = "ClientThread";
424 m_clientThread.IsBackground = true; 397 m_clientThread.IsBackground = true;
425 m_clientThread.Start(); 398 m_clientThread.Start();
426 ThreadTracker.Add(m_clientThread);
427 } 399 }
428 400
429 public void SetDebug(int newDebug) 401 public void SetDebug(int newDebug)
@@ -444,12 +416,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
444 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 416 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
445 OutPacket(disable, ThrottleOutPacketType.Unknown); 417 OutPacket(disable, ThrottleOutPacketType.Unknown);
446 418
447 m_packetQueue.Close();
448
449 Thread.Sleep(2000); 419 Thread.Sleep(2000);
450 420
451 // Shut down timers 421 // Shut down timers
452 m_ackTimer.Stop();
453 m_clientPingTimer.Stop(); 422 m_clientPingTimer.Stop();
454 423
455 // This is just to give the client a reasonable chance of 424 // This is just to give the client a reasonable chance of
@@ -479,7 +448,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
479 { 448 {
480 // Pull Client out of Region 449 // Pull Client out of Region
481 m_log.Info("[CLIENT]: Close has been called"); 450 m_log.Info("[CLIENT]: Close has been called");
482 m_packetQueue.Flush(); 451 m_PacketHandler.Flush();
483 452
484 //raiseevent on the packet server to Shutdown the circuit 453 //raiseevent on the packet server to Shutdown the circuit
485 if (shutdownCircuit) 454 if (shutdownCircuit)
@@ -509,20 +478,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
509 public void Stop() 478 public void Stop()
510 { 479 {
511 // Shut down timers 480 // Shut down timers
512 m_ackTimer.Stop();
513 m_clientPingTimer.Stop(); 481 m_clientPingTimer.Stop();
514 } 482 }
515 483
516 public void Restart() 484 public void Restart()
517 { 485 {
518 // re-construct 486 // re-construct
519 m_pendingAcks = new Dictionary<uint, uint>(); 487 m_PacketHandler.Clear();
520 m_needAck = new Dictionary<uint, Packet>();
521 m_sequence += 1000000;
522
523 m_ackTimer = new Timer(750);
524 m_ackTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
525 m_ackTimer.Start();
526 488
527 m_clientPingTimer = new Timer(5000); 489 m_clientPingTimer = new Timer(5000);
528 m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity); 490 m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity);
@@ -531,8 +493,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
531 493
532 public void Terminate() 494 public void Terminate()
533 { 495 {
534 // disable blocking queue 496 m_PacketHandler.Stop();
535 m_packetQueue.Enqueue(null);
536 497
537 // wait for thread stoped 498 // wait for thread stoped
538 m_clientThread.Join(); 499 m_clientThread.Join();
@@ -638,7 +599,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
638 m_log.Info("[CLIENT]: Entered loop"); 599 m_log.Info("[CLIENT]: Entered loop");
639 while (true) 600 while (true)
640 { 601 {
641 LLQueItem nextPacket = m_packetQueue.Dequeue(); 602 LLQueItem nextPacket = m_PacketHandler.PacketQueue.Dequeue();
642 if (nextPacket == null) 603 if (nextPacket == null)
643 { 604 {
644 m_log.Error("Got a NULL packet in Client Loop, bailing out of our client loop"); 605 m_log.Error("Got a NULL packet in Client Loop, bailing out of our client loop");
@@ -646,12 +607,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
646 } 607 }
647 if (nextPacket.Incoming) 608 if (nextPacket.Incoming)
648 { 609 {
649 if (nextPacket.Packet.Type != PacketType.AgentUpdate)
650 {
651 m_packetsReceived++;
652 }
653 DebugPacket("IN", nextPacket.Packet); 610 DebugPacket("IN", nextPacket.Packet);
654 ProcessInPacket(nextPacket.Packet); 611 m_PacketHandler.ProcessInPacket(nextPacket.Packet);
655 } 612 }
656 else 613 else
657 { 614 {
@@ -672,7 +629,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
672 /// <param name="e"></param> 629 /// <param name="e"></param>
673 protected void CheckClientConnectivity(object sender, ElapsedEventArgs e) 630 protected void CheckClientConnectivity(object sender, ElapsedEventArgs e)
674 { 631 {
675 if (m_packetsReceived == m_lastPacketsReceived) 632 if (m_PacketHandler.PacketsReceived == m_PacketHandler.PacketsReceivedReported)
676 { 633 {
677 m_probesWithNoIngressPackets++; 634 m_probesWithNoIngressPackets++;
678 if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) || (m_probesWithNoIngressPackets > 90 && m_clientBlocked)) 635 if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) || (m_probesWithNoIngressPackets > 90 && m_clientBlocked))
@@ -693,19 +650,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
693 { 650 {
694 // Something received in the meantime - we can reset the counters 651 // Something received in the meantime - we can reset the counters
695 m_probesWithNoIngressPackets = 0; 652 m_probesWithNoIngressPackets = 0;
696 m_lastPacketsReceived = m_packetsReceived;
697 } 653 }
698 654
699 //SendPacketStats();
700 m_packetTracker.Process();
701
702 if (m_terrainCheckerCount >= 4)
703 {
704 m_packetTracker.TerrainPacketCheck();
705 // m_packetTracker.PrimPacketCheck();
706 m_terrainCheckerCount = -1;
707 }
708 m_terrainCheckerCount++;
709 } 655 }
710 656
711 # region Setup 657 # region Setup
@@ -719,9 +665,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
719 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); 665 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
720 666
721 // Establish our two timers. We could probably get this down to one 667 // Establish our two timers. We could probably get this down to one
722 m_ackTimer = new Timer(750);
723 m_ackTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
724 m_ackTimer.Start();
725 668
726 m_clientPingTimer = new Timer(5000); 669 m_clientPingTimer = new Timer(5000);
727 m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity); 670 m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity);
@@ -754,7 +697,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
754 "[CLIENT]: New user request denied to avatar {0} connecting with circuit code {1} from {2}", 697 "[CLIENT]: New user request denied to avatar {0} connecting with circuit code {1} from {2}",
755 m_agentId, m_circuitCode, m_userEndPoint); 698 m_agentId, m_circuitCode, m_userEndPoint);
756 699
757 m_packetQueue.Close(); 700 m_PacketHandler.Stop();
758 m_clientThread.Abort(); 701 m_clientThread.Abort();
759 } 702 }
760 else 703 else
@@ -920,7 +863,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
920 public event FriendActionDelegate OnApproveFriendRequest; 863 public event FriendActionDelegate OnApproveFriendRequest;
921 public event FriendActionDelegate OnDenyFriendRequest; 864 public event FriendActionDelegate OnDenyFriendRequest;
922 public event FriendshipTermination OnTerminateFriendship; 865 public event FriendshipTermination OnTerminateFriendship;
923 public event PacketStats OnPacketStats;
924 public event MoneyTransferRequest OnMoneyTransferRequest; 866 public event MoneyTransferRequest OnMoneyTransferRequest;
925 public event EconomyDataRequest OnEconomyDataRequest; 867 public event EconomyDataRequest OnEconomyDataRequest;
926 public event MoneyBalanceRequest OnMoneyBalanceRequest; 868 public event MoneyBalanceRequest OnMoneyBalanceRequest;
@@ -1105,7 +1047,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1105 public virtual void SendLayerData(float[] map) 1047 public virtual void SendLayerData(float[] map)
1106 { 1048 {
1107 ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendLayerData), (object)map); 1049 ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendLayerData), (object)map);
1108
1109 } 1050 }
1110 1051
1111 /// <summary> 1052 /// <summary>
@@ -1166,11 +1107,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1166 /// <param name="map">heightmap</param> 1107 /// <param name="map">heightmap</param>
1167 public void SendLayerData(int px, int py, float[] map) 1108 public void SendLayerData(int px, int py, float[] map)
1168 { 1109 {
1169 SendLayerData(px, py, map, true);
1170 }
1171
1172 public void SendLayerData(int px, int py, float[] map, bool track)
1173 {
1174 try 1110 try
1175 { 1111 {
1176 int[] patches = new int[1]; 1112 int[] patches = new int[1];
@@ -1183,12 +1119,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1183 LayerDataPacket layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1119 LayerDataPacket layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
1184 layerpack.Header.Zerocoded = true; 1120 layerpack.Header.Zerocoded = true;
1185 1121
1186 if (track)
1187 {
1188 layerpack.Header.Sequence = NextSeqNum();
1189 m_packetTracker.TrackTerrainPacket(layerpack.Header.Sequence, px, py);
1190 }
1191
1192 OutPacket(layerpack, ThrottleOutPacketType.Land); 1122 OutPacket(layerpack, ThrottleOutPacketType.Land);
1193 } 1123 }
1194 catch (Exception e) 1124 catch (Exception e)
@@ -2309,14 +2239,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2309 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, 2239 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
2310 LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, 2240 LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel,
2311 uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, 2241 uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color,
2312 uint parentID, byte[] particleSystem, byte clickAction, bool track) 2242 uint parentID, byte[] particleSystem, byte clickAction)
2313 { 2243 {
2314 byte[] textureanim = new byte[0]; 2244 byte[] textureanim = new byte[0];
2315 2245
2316 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, 2246 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel,
2317 acc, rotation, rvel, flags, 2247 acc, rotation, rvel, flags,
2318 objectID, ownerID, text, color, parentID, particleSystem, 2248 objectID, ownerID, text, color, parentID, particleSystem,
2319 clickAction, textureanim, false, (uint)0, LLUUID.Zero, LLUUID.Zero, 0, 0, 0, track); 2249 clickAction, textureanim, false, (uint)0, LLUUID.Zero, LLUUID.Zero, 0, 0, 0);
2320 } 2250 }
2321 2251
2322 public void SendPrimitiveToClient( 2252 public void SendPrimitiveToClient(
@@ -2324,7 +2254,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2324 LLVector3 pos, LLVector3 velocity, LLVector3 acceleration, LLQuaternion rotation, LLVector3 rotational_velocity, 2254 LLVector3 pos, LLVector3 velocity, LLVector3 acceleration, LLQuaternion rotation, LLVector3 rotational_velocity,
2325 uint flags, 2255 uint flags,
2326 LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, 2256 LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
2327 byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius, bool track) 2257 byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius)
2328 { 2258 {
2329 2259
2330 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 2260 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
@@ -2410,13 +2340,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2410 } 2340 }
2411 outPacket.Header.Zerocoded = true; 2341 outPacket.Header.Zerocoded = true;
2412 2342
2413 if (track) 2343 OutPacket(outPacket, ThrottleOutPacketType.LowpriorityTask);
2414 {
2415 outPacket.Header.Sequence = NextSeqNum();
2416 m_packetTracker.TrackPrimPacket(outPacket.Header.Sequence, objectID);
2417 }
2418
2419 OutPacket(outPacket, ThrottleOutPacketType.Task);
2420 } 2344 }
2421 2345
2422 /// <summary> 2346 /// <summary>
@@ -2440,7 +2364,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2440 terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); // AssetID should fall into here probably somehow... 2364 terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); // AssetID should fall into here probably somehow...
2441 terse.Header.Reliable = false; 2365 terse.Header.Reliable = false;
2442 terse.Header.Zerocoded = true; 2366 terse.Header.Zerocoded = true;
2443 OutPacket(terse, ThrottleOutPacketType.Task); 2367 OutPacket(terse, ThrottleOutPacketType.LowpriorityTask);
2444 } 2368 }
2445 2369
2446 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, 2370 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position,
@@ -2456,7 +2380,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2456 terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, 0); 2380 terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, 0);
2457 terse.Header.Reliable = false; 2381 terse.Header.Reliable = false;
2458 terse.Header.Zerocoded = true; 2382 terse.Header.Zerocoded = true;
2459 OutPacket(terse, ThrottleOutPacketType.Task); 2383 OutPacket(terse, ThrottleOutPacketType.LowpriorityTask);
2460 } 2384 }
2461 2385
2462 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, LLUUID AssetFullID) 2386 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, LLUUID AssetFullID)
@@ -3736,7 +3660,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3736 /// <returns></returns> 3660 /// <returns></returns>
3737 public byte[] GetThrottlesPacked(float multiplier) 3661 public byte[] GetThrottlesPacked(float multiplier)
3738 { 3662 {
3739 return m_packetQueue.GetThrottlesPacked(multiplier); 3663 return m_PacketHandler.PacketQueue.GetThrottlesPacked(multiplier);
3740 } 3664 }
3741 /// <summary> 3665 /// <summary>
3742 /// sets the throttles from values supplied by the client 3666 /// sets the throttles from values supplied by the client
@@ -3744,86 +3668,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3744 /// <param name="throttles"></param> 3668 /// <param name="throttles"></param>
3745 public void SetChildAgentThrottle(byte[] throttles) 3669 public void SetChildAgentThrottle(byte[] throttles)
3746 { 3670 {
3747 m_packetQueue.SetThrottleFromClient(throttles); 3671 m_PacketHandler.PacketQueue.SetThrottleFromClient(throttles);
3748 } 3672 }
3749 3673
3750 // Previously ClientView.m_packetQueue 3674 // Previously ClientView.m_packetQueue
3751 3675
3752 // A thread safe sequence number allocator.
3753 protected uint NextSeqNum()
3754 {
3755 // Set the sequence number
3756 uint seq = 1;
3757 lock (m_sequenceLock)
3758 {
3759 if (m_sequence >= MAX_SEQUENCE)
3760 {
3761 m_sequence = 1;
3762 }
3763 else
3764 {
3765 m_sequence++;
3766 }
3767 seq = m_sequence;
3768 }
3769 return seq;
3770 }
3771
3772 protected void AddAck(Packet Pack)
3773 {
3774 lock (m_needAck)
3775 {
3776 if (!m_needAck.ContainsKey(Pack.Header.Sequence))
3777 {
3778 try
3779 {
3780 m_needAck.Add(Pack.Header.Sequence, Pack);
3781 m_unAckedBytes += Pack.ToBytes().Length;
3782 }
3783 //BUG: severity=major - This looks like a framework bug!?
3784 catch (Exception) // HACKY
3785 {
3786 // Ignore
3787 // Seems to throw a exception here occasionally
3788 // of 'duplicate key' despite being locked.
3789 // !?!?!?
3790 }
3791 }
3792 else
3793 {
3794 // Client.Log("Attempted to add a duplicate sequence number (" +
3795 // packet.Header.m_sequence + ") to the m_needAck dictionary for packet type " +
3796 // packet.Type.ToString(), Helpers.LogLevel.Warning);
3797 }
3798 }
3799 }
3800 /// <summary>
3801 /// Append any ACKs that need to be sent out to this packet
3802 /// </summary>
3803 /// <param name="Pack"></param>
3804 protected virtual void SetPendingAcks(ref Packet Pack)
3805 {
3806
3807 lock (m_pendingAcks)
3808 {
3809 // TODO: If we are over MAX_APPENDED_ACKS we should drain off some of these
3810 if (m_pendingAcks.Count > 0 && m_pendingAcks.Count < MAX_APPENDED_ACKS)
3811 {
3812 Pack.Header.AckList = new uint[m_pendingAcks.Count];
3813 int i = 0;
3814
3815 foreach (uint ack in m_pendingAcks.Values)
3816 {
3817 Pack.Header.AckList[i] = ack;
3818 i++;
3819 }
3820
3821 m_pendingAcks.Clear();
3822 Pack.Header.AppendedAcks = true;
3823 }
3824 }
3825 }
3826
3827 /// <summary> 3676 /// <summary>
3828 /// Helper routine to prepare the packet for sending to UDP client 3677 /// Helper routine to prepare the packet for sending to UDP client
3829 /// This converts it to bytes and puts it on the outgoing buffer 3678 /// This converts it to bytes and puts it on the outgoing buffer
@@ -3834,24 +3683,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3834 // Keep track of when this packet was sent out 3683 // Keep track of when this packet was sent out
3835 Pack.TickCount = System.Environment.TickCount; 3684 Pack.TickCount = System.Environment.TickCount;
3836 3685
3837 if (!Pack.Header.Resent)
3838 {
3839 if (Pack.Header.Sequence == 0)
3840 {
3841 Pack.Header.Sequence = NextSeqNum();
3842 }
3843
3844 if (Pack.Header.Reliable) //DIRTY HACK
3845 {
3846 AddAck(Pack); // this adds the need to ack this packet later
3847
3848 if (Pack.Type != PacketType.PacketAck && Pack.Type != PacketType.LogoutRequest)
3849 {
3850 SetPendingAcks(ref Pack);
3851 }
3852 }
3853 }
3854
3855 // Actually make the byte array and send it 3686 // Actually make the byte array and send it
3856 try 3687 try
3857 { 3688 {
@@ -3886,249 +3717,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3886 /// <param name="NewPack"></param> 3717 /// <param name="NewPack"></param>
3887 public virtual void InPacket(Packet NewPack) 3718 public virtual void InPacket(Packet NewPack)
3888 { 3719 {
3889 if (!m_packetProcessingEnabled && NewPack.Type != PacketType.LogoutRequest) 3720 m_PacketHandler.InPacket(NewPack);
3890 {
3891 PacketPool.Instance.ReturnPacket(NewPack);
3892 return;
3893 }
3894
3895 // Handle appended ACKs
3896 if (NewPack != null)
3897 {
3898 if (NewPack.Header.AppendedAcks)
3899 {
3900 lock (m_needAck)
3901 {
3902 foreach (uint ackedPacketId in NewPack.Header.AckList)
3903 {
3904 RemovePacketFromNeedAckList(ackedPacketId);
3905 }
3906 }
3907 }
3908
3909 // Handle PacketAck packets
3910 if (NewPack.Type == PacketType.PacketAck)
3911 {
3912 PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
3913
3914 lock (m_needAck)
3915 {
3916 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
3917 {
3918 uint ackedPackId = block.ID;
3919 RemovePacketFromNeedAckList(ackedPackId);
3920 }
3921 }
3922 }
3923 else if ((NewPack.Type == PacketType.StartPingCheck))
3924 {
3925 //reply to pingcheck
3926 StartPingCheckPacket startPing = (StartPingCheckPacket)NewPack;
3927 CompletePingCheckPacket endPing = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck);
3928 endPing.PingID.PingID = startPing.PingID.PingID;
3929 OutPacket(endPing, ThrottleOutPacketType.Task);
3930 }
3931 else
3932 {
3933 LLQueItem item = new LLQueItem();
3934 item.Packet = NewPack;
3935 item.Incoming = true;
3936 m_packetQueue.Enqueue(item);
3937 }
3938 }
3939 }
3940
3941 private void RemovePacketFromNeedAckList(uint ackedPackId)
3942 {
3943 Packet ackedPacket;
3944 if (m_needAck.TryGetValue(ackedPackId, out ackedPacket))
3945 {
3946 m_unAckedBytes -= ackedPacket.ToBytes().Length;
3947 m_needAck.Remove(ackedPackId);
3948
3949 m_packetTracker.PacketAck(ackedPackId);
3950 }
3951 } 3721 }
3952 3722
3953 /// <summary> 3723 /// <summary>
3954 /// The dreaded OutPacket. This should only be called from withink the ClientStack itself right now 3724 /// The dreaded OutPacket. This should only be called from within
3955 /// This is the entry point for simulator packets to go out to the client. 3725 /// the ClientStack itself right now
3726 /// This is the entry point for simulator packets to go out to
3727 /// the client.
3956 /// </summary> 3728 /// </summary>
3957 /// <param name="NewPack"></param> 3729 /// <param name="NewPack"></param>
3958 /// <param name="throttlePacketType">Corresponds to the type of data that is going out. Enum</param> 3730 /// <param name="throttlePacketType">Corresponds to the type of data that is going out. Enum</param>
3959 public virtual void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) 3731 public virtual void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType)
3960 { 3732 {
3961 if ((SynchronizeClient != null) && (!IsActive)) 3733 m_PacketHandler.OutPacket(NewPack, throttlePacketType);
3962 {
3963 // Sending packet to active client's server.
3964 if (SynchronizeClient(m_scene, NewPack, m_agentId, throttlePacketType))
3965 {
3966 return;
3967 }
3968 }
3969
3970 LLQueItem item = new LLQueItem();
3971 item.Packet = NewPack;
3972 item.Incoming = false;
3973 item.throttleType = throttlePacketType; // Packet throttle type
3974 m_packetQueue.Enqueue(item);
3975 m_packetsSent++;
3976 }
3977
3978 # region Low Level Packet Methods
3979
3980 protected void ack_pack(Packet Pack)
3981 {
3982 if (Pack.Header.Reliable)
3983 {
3984 PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
3985 // TODO: don't create new blocks if recycling an old packet
3986 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
3987 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
3988 ack_it.Packets[0].ID = Pack.Header.Sequence;
3989 ack_it.Header.Reliable = false;
3990
3991 OutPacket(ack_it, ThrottleOutPacketType.Unknown);
3992 }
3993 /*
3994 if (Pack.Header.Reliable)
3995 {
3996 lock (m_pendingAcks)
3997 {
3998 uint sequence = (uint)Pack.Header.m_sequence;
3999 if (!m_pendingAcks.ContainsKey(sequence)) { m_pendingAcks[sequence] = sequence; }
4000 }
4001 }*/
4002 }
4003
4004 protected void ResendUnacked()
4005 {
4006 int now = System.Environment.TickCount;
4007
4008 lock (m_needAck)
4009 {
4010 foreach (Packet packet in m_needAck.Values)
4011 {
4012 if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
4013 {
4014 //m_log.Debug("[NETWORK]: Resending " + packet.Type.ToString() + " packet, " +
4015 //(now - packet.TickCount) + "ms have passed");
4016
4017 packet.Header.Resent = true;
4018 OutPacket(packet, ThrottleOutPacketType.Resend);
4019 }
4020 }
4021 }
4022 } 3734 }
4023 3735
4024 protected void SendAcks()
4025 {
4026 lock (m_pendingAcks)
4027 {
4028 if (m_pendingAcks.Count > 0)
4029 {
4030 if (m_pendingAcks.Count > 250)
4031 {
4032 // FIXME: Handle the odd case where we have too many pending ACKs queued up
4033 m_log.Info("[NETWORK]: Too many ACKs queued up!");
4034 return;
4035 }
4036
4037 //m_log.Info("[NETWORK]: Sending PacketAck");
4038
4039 int i = 0;
4040 PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
4041 // TODO: don't create new blocks if recycling an old packet
4042 acks.Packets = new PacketAckPacket.PacketsBlock[m_pendingAcks.Count];
4043
4044 foreach (uint ack in m_pendingAcks.Values)
4045 {
4046 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
4047 acks.Packets[i].ID = ack;
4048 i++;
4049 }
4050
4051 acks.Header.Reliable = false;
4052 OutPacket(acks, ThrottleOutPacketType.Unknown);
4053
4054 m_pendingAcks.Clear();
4055 }
4056 }
4057 }
4058
4059 protected void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
4060 {
4061 SendAcks();
4062 ResendUnacked();
4063 SendPacketStats();
4064 // TerrainPacketTrack();
4065 }
4066
4067 /// <summary>
4068 /// Keeps track of the packet stats for the simulator stats reporter
4069 /// </summary>
4070 protected void SendPacketStats()
4071 {
4072 handlerPacketStats = OnPacketStats;
4073 if (handlerPacketStats != null)
4074 {
4075 handlerPacketStats(m_packetsReceived - m_lastPacketsReceivedSentToScene, m_packetsSent - m_lastPacketsSentSentToScene, m_unAckedBytes);
4076 m_lastPacketsReceivedSentToScene = m_packetsReceived;
4077 m_lastPacketsSentSentToScene = m_packetsSent;
4078 }
4079 }
4080
4081
4082 /// <summary>
4083 /// Emties out the old packets in the packet duplication tracking table.
4084 /// </summary>
4085 protected void ClearOldPacketDupeTracking()
4086 {
4087 lock (m_dupeLimiter)
4088 {
4089 List<uint> toEliminate = new List<uint>();
4090 try
4091 {
4092 foreach (uint seq in m_dupeLimiter.Keys)
4093 {
4094 PacketDupeLimiter pkdata = null;
4095 m_dupeLimiter.TryGetValue(seq, out pkdata);
4096 if (pkdata != null)
4097 {
4098 // doing a foreach loop, so we don't want to modify the dictionary while we're searching it
4099 if (Util.UnixTimeSinceEpoch() - pkdata.timeIn > m_clearDuplicatePacketTrackingOlderThenXSeconds)
4100 toEliminate.Add(seq);
4101 }
4102 }
4103 }
4104 catch (InvalidOperationException)
4105 {
4106 m_log.Info("[PACKET]: Unable to clear dupe check packet data");
4107 }
4108
4109 // remove the dupe packets that we detected in the loop above.
4110 uint[] seqsToRemove = toEliminate.ToArray();
4111 for (int i = 0; i < seqsToRemove.Length; i++)
4112 {
4113 if (m_dupeLimiter.ContainsKey(seqsToRemove[i]))
4114 m_dupeLimiter.Remove(seqsToRemove[i]);
4115 }
4116 }
4117 }
4118
4119 #endregion
4120
4121 public void TriggerTerrainUnackedEvent(int patchX, int patchY)
4122 {
4123 handlerUnackedTerrain = OnUnackedTerrain;
4124 if (handlerUnackedTerrain != null)
4125 {
4126 handlerUnackedTerrain(this, patchX, patchY);
4127 }
4128 }
4129
4130 // Previously ClientView.ProcessPackets
4131
4132 public bool AddMoney(int debit) 3736 public bool AddMoney(int debit)
4133 { 3737 {
4134 if (m_moneyBalance + debit >= 0) 3738 if (m_moneyBalance + debit >= 0)
@@ -4143,14 +3747,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4143 } 3747 }
4144 } 3748 }
4145 3749
4146 private bool m_packetProcessingEnabled = true;
4147
4148 public bool IsActive
4149 {
4150 get { return m_packetProcessingEnabled; }
4151 set { m_packetProcessingEnabled = value; }
4152 }
4153
4154 /// <summary> 3750 /// <summary>
4155 /// Breaks down the genericMessagePacket into specific events 3751 /// Breaks down the genericMessagePacket into specific events
4156 /// </summary> 3752 /// </summary>
@@ -4206,31 +3802,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4206 /// all UDP packets from the client will end up here 3802 /// all UDP packets from the client will end up here
4207 /// </summary> 3803 /// </summary>
4208 /// <param name="Pack">libsecondlife.packet</param> 3804 /// <param name="Pack">libsecondlife.packet</param>
4209 protected void ProcessInPacket(Packet Pack) 3805 public void ProcessInPacket(Packet Pack)
4210 { 3806 {
4211 // always ack the packet!
4212 ack_pack(Pack);
4213
4214 // check for duplicate packets.. packets that the client is
4215 // resending because it didn't receive our ack
4216
4217 lock (m_dupeLimiter)
4218 {
4219 if (m_dupeLimiter.ContainsKey(Pack.Header.Sequence))
4220 {
4221 //m_log.Info("[CLIENT]: Warning Duplicate packet detected" + Pack.Type.ToString() + " Dropping.");
4222 return;
4223 }
4224 else
4225 {
4226 PacketDupeLimiter pkdedupe = new PacketDupeLimiter();
4227 pkdedupe.packetId = Pack.Header.ID;
4228 pkdedupe.pktype = Pack.Type;
4229 pkdedupe.timeIn = Util.UnixTimeSinceEpoch();
4230 m_dupeLimiter.Add(Pack.Header.Sequence, pkdedupe);
4231 }
4232 }
4233
4234 // check if we've got a local packet handler for this packet.type. See RegisterLocalPacketHandlers() 3807 // check if we've got a local packet handler for this packet.type. See RegisterLocalPacketHandlers()
4235 if (ProcessPacketMethod(Pack)) 3808 if (ProcessPacketMethod(Pack))
4236 { 3809 {
@@ -4702,7 +4275,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4702 4275
4703 case PacketType.AgentThrottle: 4276 case PacketType.AgentThrottle:
4704 AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; 4277 AgentThrottlePacket atpack = (AgentThrottlePacket)Pack;
4705 m_packetQueue.SetThrottleFromClient(atpack.Throttle.Throttles); 4278 m_PacketHandler.PacketQueue.SetThrottleFromClient(atpack.Throttle.Throttles);
4706 break; 4279 break;
4707 4280
4708 case PacketType.AgentPause: 4281 case PacketType.AgentPause:
@@ -6648,76 +6221,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6648 6221
6649 public ClientInfo GetClientInfo() 6222 public ClientInfo GetClientInfo()
6650 { 6223 {
6651 //MainLog.Instance.Verbose("CLIENT", "GetClientInfo BGN"); 6224 ClientInfo info = m_PacketHandler.GetClientInfo();
6652 6225
6653 ClientInfo info = new ClientInfo();
6654 info.userEP = this.m_userEndPoint; 6226 info.userEP = this.m_userEndPoint;
6655 info.proxyEP = this.m_proxyEndPoint; 6227 info.proxyEP = this.m_proxyEndPoint;
6656 info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); 6228 info.agentcircuit = new sAgentCircuitData(RequestClientInfo());
6657 6229
6658 info.pendingAcks = m_pendingAcks;
6659
6660 info.needAck = new Dictionary<uint, byte[]>();
6661
6662 lock (m_needAck)
6663 {
6664 foreach (uint key in m_needAck.Keys)
6665 {
6666 info.needAck.Add(key, m_needAck[key].ToBytes());
6667 }
6668 }
6669
6670 /* pending
6671 QueItem[] queitems = m_packetQueue.GetQueueArray();
6672
6673 MainLog.Instance.Verbose("CLIENT", "Queue Count : [{0}]", queitems.Length);
6674
6675 for (int i = 0; i < queitems.Length; i++)
6676 {
6677 if (queitems[i].Incoming == false)
6678 {
6679 info.out_packets.Add(queitems[i].Packet.ToBytes());
6680 MainLog.Instance.Verbose("CLIENT", "Add OutPacket [{0}]", queitems[i].Packet.Type.ToString());
6681 }
6682 }
6683 */
6684
6685 info.sequence = m_sequence;
6686
6687 //MainLog.Instance.Verbose("CLIENT", "GetClientInfo END");
6688
6689 return info; 6230 return info;
6690 } 6231 }
6691 6232
6692 public void SetClientInfo(ClientInfo info) 6233 public void SetClientInfo(ClientInfo info)
6693 { 6234 {
6694 m_pendingAcks = info.pendingAcks; 6235 m_PacketHandler.SetClientInfo(info);
6695
6696 m_needAck = new Dictionary<uint, Packet>();
6697
6698 Packet packet = null;
6699 int packetEnd = 0;
6700 byte[] zero = new byte[3000];
6701
6702 foreach (uint key in info.needAck.Keys)
6703 {
6704 byte[] buff = info.needAck[key];
6705
6706 packetEnd = buff.Length - 1;
6707
6708 try
6709 {
6710 packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero);
6711 }
6712 catch (Exception)
6713 {
6714
6715 }
6716
6717 m_needAck.Add(key, packet);
6718 }
6719
6720 m_sequence = info.sequence;
6721 } 6236 }
6722 6237
6723 #region Media Parcel Members 6238 #region Media Parcel Members