diff options
added experimental packet tracker (LLPacketTracker.cs), which can be told to track a packet and if it hasn't been acked within a set time, trigger a IClientAPI event, that the application/scene can handle. Currently only terrain packet tracking is finished, Tracking for initial Prim packets (first full update for a prim) is being worked on. Future improvements would be to make it a more generic packet tracker with callback delegates instead of events.
Add a test event handler (which would fire after a minute if a terrain packet hadn't been acked) to scene to handle the OnUnackedTerrain event, which currently just resends the terrain patch.
The idea of this packet tracking is for the region level application to be able to know if the client stack gave up on sending a packet.
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 115 |
1 files changed, 75 insertions, 40 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2c05097..c9fc83a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -118,6 +118,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
118 | 118 | ||
119 | private Dictionary<string, LLUUID> m_defaultAnimations = new Dictionary<string, LLUUID>(); | 119 | private Dictionary<string, LLUUID> m_defaultAnimations = new Dictionary<string, LLUUID>(); |
120 | 120 | ||
121 | private LLPacketTracker m_packetTracker; | ||
122 | |||
121 | /* protected variables */ | 123 | /* protected variables */ |
122 | 124 | ||
123 | protected static Dictionary<PacketType, PacketMethod> PacketHandlers = | 125 | protected static Dictionary<PacketType, PacketMethod> PacketHandlers = |
@@ -282,6 +284,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
282 | private SetScriptRunning handlerSetScriptRunning = null; | 284 | private SetScriptRunning handlerSetScriptRunning = null; |
283 | private UpdateVector handlerAutoPilotGo = null; | 285 | private UpdateVector handlerAutoPilotGo = null; |
284 | 286 | ||
287 | private TerrainUnacked handlerUnackedTerrain = null; | ||
288 | |||
289 | //** | ||
290 | |||
285 | /* Properties */ | 291 | /* Properties */ |
286 | 292 | ||
287 | public LLUUID SecureSessionId | 293 | public LLUUID SecureSessionId |
@@ -377,6 +383,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
377 | public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer, | 383 | public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer, |
378 | AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP) | 384 | AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP) |
379 | { | 385 | { |
386 | m_packetTracker = new LLPacketTracker(this); | ||
387 | |||
380 | m_moneyBalance = 1000; | 388 | m_moneyBalance = 1000; |
381 | 389 | ||
382 | m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion()); | 390 | m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion()); |
@@ -410,6 +418,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
410 | 418 | ||
411 | RegisterLocalPacketHandlers(); | 419 | RegisterLocalPacketHandlers(); |
412 | 420 | ||
421 | |||
413 | m_clientThread = new Thread(new ThreadStart(AuthUser)); | 422 | m_clientThread = new Thread(new ThreadStart(AuthUser)); |
414 | m_clientThread.Name = "ClientThread"; | 423 | m_clientThread.Name = "ClientThread"; |
415 | m_clientThread.IsBackground = true; | 424 | m_clientThread.IsBackground = true; |
@@ -654,6 +663,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
654 | 663 | ||
655 | # endregion | 664 | # endregion |
656 | 665 | ||
666 | protected int m_terrainCheckerCount = 0; | ||
657 | /// <summary> | 667 | /// <summary> |
658 | /// Event handler for check client timer | 668 | /// Event handler for check client timer |
659 | /// checks to ensure that the client is still connected | 669 | /// checks to ensure that the client is still connected |
@@ -685,7 +695,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
685 | m_probesWithNoIngressPackets = 0; | 695 | m_probesWithNoIngressPackets = 0; |
686 | m_lastPacketsReceived = m_packetsReceived; | 696 | m_lastPacketsReceived = m_packetsReceived; |
687 | } | 697 | } |
698 | |||
688 | //SendPacketStats(); | 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++; | ||
689 | } | 709 | } |
690 | 710 | ||
691 | # region Setup | 711 | # region Setup |
@@ -934,6 +954,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
934 | public event SetScriptRunning OnSetScriptRunning; | 954 | public event SetScriptRunning OnSetScriptRunning; |
935 | public event UpdateVector OnAutoPilotGo; | 955 | public event UpdateVector OnAutoPilotGo; |
936 | 956 | ||
957 | public event TerrainUnacked OnUnackedTerrain; | ||
958 | |||
937 | #region Scene/Avatar to Client | 959 | #region Scene/Avatar to Client |
938 | 960 | ||
939 | /// <summary> | 961 | /// <summary> |
@@ -1083,29 +1105,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1083 | public virtual void SendLayerData(float[] map) | 1105 | public virtual void SendLayerData(float[] map) |
1084 | { | 1106 | { |
1085 | ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendLayerData), (object)map); | 1107 | ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendLayerData), (object)map); |
1086 | //try | 1108 | |
1087 | //{ | ||
1088 | // int[] patches = new int[4]; | ||
1089 | |||
1090 | // for (int y = 0; y < 16; y++) | ||
1091 | // { | ||
1092 | // for (int x = 0; x < 16; x += 4) | ||
1093 | // { | ||
1094 | // patches[0] = x + 0 + y * 16; | ||
1095 | // patches[1] = x + 1 + y * 16; | ||
1096 | // patches[2] = x + 2 + y * 16; | ||
1097 | // patches[3] = x + 3 + y * 16; | ||
1098 | |||
1099 | // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); | ||
1100 | // OutPacket(layerpack, ThrottleOutPacketType.Land); | ||
1101 | // } | ||
1102 | // } | ||
1103 | //} | ||
1104 | //catch (Exception e) | ||
1105 | //{ | ||
1106 | // m_log.Warn("[client]: " + | ||
1107 | // "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); | ||
1108 | //} | ||
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | /// <summary> | 1111 | /// <summary> |
@@ -1166,6 +1166,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1166 | /// <param name="map">heightmap</param> | 1166 | /// <param name="map">heightmap</param> |
1167 | public void SendLayerData(int px, int py, float[] map) | 1167 | public void SendLayerData(int px, int py, float[] map) |
1168 | { | 1168 | { |
1169 | SendLayerData(px, py, map, true); | ||
1170 | } | ||
1171 | |||
1172 | public void SendLayerData(int px, int py, float[] map, bool track) | ||
1173 | { | ||
1169 | try | 1174 | try |
1170 | { | 1175 | { |
1171 | int[] patches = new int[1]; | 1176 | int[] patches = new int[1]; |
@@ -1177,6 +1182,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1177 | 1182 | ||
1178 | LayerDataPacket layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); | 1183 | LayerDataPacket layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); |
1179 | layerpack.Header.Zerocoded = true; | 1184 | layerpack.Header.Zerocoded = true; |
1185 | |||
1186 | if (track) | ||
1187 | { | ||
1188 | layerpack.Header.Sequence = NextSeqNum(); | ||
1189 | m_packetTracker.TrackTerrainPacket(layerpack.Header.Sequence, px, py); | ||
1190 | } | ||
1191 | |||
1180 | OutPacket(layerpack, ThrottleOutPacketType.Land); | 1192 | OutPacket(layerpack, ThrottleOutPacketType.Land); |
1181 | } | 1193 | } |
1182 | catch (Exception e) | 1194 | catch (Exception e) |
@@ -2297,14 +2309,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2297 | ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, | 2309 | ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, |
2298 | LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, | 2310 | LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, |
2299 | uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, | 2311 | uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, |
2300 | uint parentID, byte[] particleSystem, byte clickAction) | 2312 | uint parentID, byte[] particleSystem, byte clickAction, bool track) |
2301 | { | 2313 | { |
2302 | byte[] textureanim = new byte[0]; | 2314 | byte[] textureanim = new byte[0]; |
2303 | 2315 | ||
2304 | SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, | 2316 | SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, |
2305 | acc, rotation, rvel, flags, | 2317 | acc, rotation, rvel, flags, |
2306 | objectID, ownerID, text, color, parentID, particleSystem, | 2318 | objectID, ownerID, text, color, parentID, particleSystem, |
2307 | clickAction, textureanim, false, (uint)0, LLUUID.Zero, LLUUID.Zero, 0, 0, 0); | 2319 | clickAction, textureanim, false, (uint)0, LLUUID.Zero, LLUUID.Zero, 0, 0, 0, track); |
2308 | } | 2320 | } |
2309 | 2321 | ||
2310 | public void SendPrimitiveToClient( | 2322 | public void SendPrimitiveToClient( |
@@ -2312,8 +2324,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2312 | LLVector3 pos, LLVector3 velocity, LLVector3 acceleration, LLQuaternion rotation, LLVector3 rotational_velocity, | 2324 | LLVector3 pos, LLVector3 velocity, LLVector3 acceleration, LLQuaternion rotation, LLVector3 rotational_velocity, |
2313 | uint flags, | 2325 | uint flags, |
2314 | LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, | 2326 | LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, |
2315 | byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) | 2327 | byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius, bool track) |
2316 | { | 2328 | { |
2329 | |||
2317 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) | 2330 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) |
2318 | rotation = LLQuaternion.Identity; | 2331 | rotation = LLQuaternion.Identity; |
2319 | 2332 | ||
@@ -2396,6 +2409,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2396 | outPacket.ObjectData[0].TextureAnim = textureanim; | 2409 | outPacket.ObjectData[0].TextureAnim = textureanim; |
2397 | } | 2410 | } |
2398 | outPacket.Header.Zerocoded = true; | 2411 | outPacket.Header.Zerocoded = true; |
2412 | |||
2413 | if (track) | ||
2414 | { | ||
2415 | outPacket.Header.Sequence = NextSeqNum(); | ||
2416 | m_packetTracker.TrackPrimPacket(outPacket.Header.Sequence, objectID); | ||
2417 | } | ||
2418 | |||
2399 | OutPacket(outPacket, ThrottleOutPacketType.Task); | 2419 | OutPacket(outPacket, ThrottleOutPacketType.Task); |
2400 | } | 2420 | } |
2401 | 2421 | ||
@@ -3816,7 +3836,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3816 | 3836 | ||
3817 | if (!Pack.Header.Resent) | 3837 | if (!Pack.Header.Resent) |
3818 | { | 3838 | { |
3819 | Pack.Header.Sequence = NextSeqNum(); | 3839 | if (Pack.Header.Sequence == 0) |
3840 | { | ||
3841 | Pack.Header.Sequence = NextSeqNum(); | ||
3842 | } | ||
3820 | 3843 | ||
3821 | if (Pack.Header.Reliable) //DIRTY HACK | 3844 | if (Pack.Header.Reliable) //DIRTY HACK |
3822 | { | 3845 | { |
@@ -3878,13 +3901,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3878 | { | 3901 | { |
3879 | foreach (uint ackedPacketId in NewPack.Header.AckList) | 3902 | foreach (uint ackedPacketId in NewPack.Header.AckList) |
3880 | { | 3903 | { |
3881 | Packet ackedPacket; | 3904 | RemovePacketFromNeedAckList(ackedPacketId); |
3882 | |||
3883 | if (m_needAck.TryGetValue(ackedPacketId, out ackedPacket)) | ||
3884 | { | ||
3885 | m_unAckedBytes -= ackedPacket.ToBytes().Length; | ||
3886 | m_needAck.Remove(ackedPacketId); | ||
3887 | } | ||
3888 | } | 3905 | } |
3889 | } | 3906 | } |
3890 | } | 3907 | } |
@@ -3899,12 +3916,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3899 | foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) | 3916 | foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) |
3900 | { | 3917 | { |
3901 | uint ackedPackId = block.ID; | 3918 | uint ackedPackId = block.ID; |
3902 | Packet ackedPacket; | 3919 | RemovePacketFromNeedAckList(ackedPackId); |
3903 | if (m_needAck.TryGetValue(ackedPackId, out ackedPacket)) | ||
3904 | { | ||
3905 | m_unAckedBytes -= ackedPacket.ToBytes().Length; | ||
3906 | m_needAck.Remove(ackedPackId); | ||
3907 | } | ||
3908 | } | 3920 | } |
3909 | } | 3921 | } |
3910 | } | 3922 | } |
@@ -3926,6 +3938,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3926 | } | 3938 | } |
3927 | } | 3939 | } |
3928 | 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 | } | ||
3952 | |||
3929 | /// <summary> | 3953 | /// <summary> |
3930 | /// The dreaded OutPacket. This should only be called from withink the ClientStack itself right now | 3954 | /// The dreaded OutPacket. This should only be called from withink the ClientStack itself right now |
3931 | /// This is the entry point for simulator packets to go out to the client. | 3955 | /// This is the entry point for simulator packets to go out to the client. |
@@ -4037,6 +4061,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4037 | SendAcks(); | 4061 | SendAcks(); |
4038 | ResendUnacked(); | 4062 | ResendUnacked(); |
4039 | SendPacketStats(); | 4063 | SendPacketStats(); |
4064 | // TerrainPacketTrack(); | ||
4040 | } | 4065 | } |
4041 | 4066 | ||
4042 | /// <summary> | 4067 | /// <summary> |
@@ -4053,6 +4078,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4053 | } | 4078 | } |
4054 | } | 4079 | } |
4055 | 4080 | ||
4081 | |||
4056 | /// <summary> | 4082 | /// <summary> |
4057 | /// Emties out the old packets in the packet duplication tracking table. | 4083 | /// Emties out the old packets in the packet duplication tracking table. |
4058 | /// </summary> | 4084 | /// </summary> |
@@ -4092,6 +4118,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4092 | 4118 | ||
4093 | #endregion | 4119 | #endregion |
4094 | 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 | |||
4095 | // Previously ClientView.ProcessPackets | 4130 | // Previously ClientView.ProcessPackets |
4096 | 4131 | ||
4097 | public bool AddMoney(int debit) | 4132 | public bool AddMoney(int debit) |