diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
7 files changed, 264 insertions, 152 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs index 90b3ede..1b8535c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs | |||
@@ -39,7 +39,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
39 | public sealed class IncomingPacket | 39 | public sealed class IncomingPacket |
40 | { | 40 | { |
41 | /// <summary>Client this packet came from</summary> | 41 | /// <summary>Client this packet came from</summary> |
42 | public LLUDPClient Client; | 42 | public LLClientView Client; |
43 | |||
43 | /// <summary>Packet data that has been received</summary> | 44 | /// <summary>Packet data that has been received</summary> |
44 | public Packet Packet; | 45 | public Packet Packet; |
45 | 46 | ||
@@ -48,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
48 | /// </summary> | 49 | /// </summary> |
49 | /// <param name="client">Reference to the client this packet came from</param> | 50 | /// <param name="client">Reference to the client this packet came from</param> |
50 | /// <param name="packet">Packet data</param> | 51 | /// <param name="packet">Packet data</param> |
51 | public IncomingPacket(LLUDPClient client, Packet packet) | 52 | public IncomingPacket(LLClientView client, Packet packet) |
52 | { | 53 | { |
53 | Client = client; | 54 | Client = client; |
54 | Packet = packet; | 55 | Packet = packet; |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9c96b52..3461971 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -515,6 +515,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
515 | /// </summary> | 515 | /// </summary> |
516 | public void Close(bool sendStop) | 516 | public void Close(bool sendStop) |
517 | { | 517 | { |
518 | IsActive = false; | ||
519 | |||
518 | m_log.DebugFormat( | 520 | m_log.DebugFormat( |
519 | "[CLIENT]: Close has been called for {0} attached to scene {1}", | 521 | "[CLIENT]: Close has been called for {0} attached to scene {1}", |
520 | Name, m_scene.RegionInfo.RegionName); | 522 | Name, m_scene.RegionInfo.RegionName); |
@@ -3902,7 +3904,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3902 | canUseImproved = false; | 3904 | canUseImproved = false; |
3903 | } | 3905 | } |
3904 | } | 3906 | } |
3905 | 3907 | ||
3906 | #endregion UpdateFlags to packet type conversion | 3908 | #endregion UpdateFlags to packet type conversion |
3907 | 3909 | ||
3908 | #region Block Construction | 3910 | #region Block Construction |
@@ -11866,7 +11868,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11866 | if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) | 11868 | if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) |
11867 | logPacket = false; | 11869 | logPacket = false; |
11868 | 11870 | ||
11869 | if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) | 11871 | if (DebugPacketLevel <= 50 |
11872 | & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) | ||
11870 | logPacket = false; | 11873 | logPacket = false; |
11871 | 11874 | ||
11872 | if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) | 11875 | if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) |
@@ -12076,10 +12079,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12076 | return string.Empty; | 12079 | return string.Empty; |
12077 | } | 12080 | } |
12078 | 12081 | ||
12079 | public void KillEndDone() | ||
12080 | { | ||
12081 | } | ||
12082 | |||
12083 | #region IClientCore | 12082 | #region IClientCore |
12084 | 12083 | ||
12085 | private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>(); | 12084 | private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>(); |
@@ -12167,21 +12166,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12167 | protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) | 12166 | protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) |
12168 | { | 12167 | { |
12169 | UUID requestID = UUID.Zero; | 12168 | UUID requestID = UUID.Zero; |
12170 | if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) | 12169 | int sourceType = transferRequest.TransferInfo.SourceType; |
12170 | |||
12171 | if (sourceType == (int)SourceType.Asset) | ||
12171 | { | 12172 | { |
12172 | requestID = new UUID(transferRequest.TransferInfo.Params, 0); | 12173 | requestID = new UUID(transferRequest.TransferInfo.Params, 0); |
12173 | } | 12174 | } |
12174 | else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) | 12175 | else if (sourceType == (int)SourceType.SimInventoryItem) |
12175 | { | 12176 | { |
12176 | requestID = new UUID(transferRequest.TransferInfo.Params, 80); | 12177 | requestID = new UUID(transferRequest.TransferInfo.Params, 80); |
12177 | } | 12178 | } |
12178 | else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimEstate) | 12179 | else if (sourceType == (int)SourceType.SimEstate) |
12179 | { | 12180 | { |
12180 | requestID = taskID; | 12181 | requestID = taskID; |
12181 | } | 12182 | } |
12182 | 12183 | ||
12183 | 12184 | // m_log.DebugFormat( | |
12184 | // m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); | 12185 | // "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", |
12186 | // requestID, taskID, (SourceType)sourceType, Name); | ||
12185 | 12187 | ||
12186 | 12188 | ||
12187 | //Note, the bool returned from the below function is useless since it is always false. | 12189 | //Note, the bool returned from the below function is useless since it is always false. |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index bd8273d..754d9d2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -147,21 +147,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
147 | private int m_elapsed500MSOutgoingPacketHandler; | 147 | private int m_elapsed500MSOutgoingPacketHandler; |
148 | 148 | ||
149 | /// <summary>Flag to signal when clients should check for resends</summary> | 149 | /// <summary>Flag to signal when clients should check for resends</summary> |
150 | private bool m_resendUnacked; | 150 | protected bool m_resendUnacked; |
151 | |||
151 | /// <summary>Flag to signal when clients should send ACKs</summary> | 152 | /// <summary>Flag to signal when clients should send ACKs</summary> |
152 | private bool m_sendAcks; | 153 | protected bool m_sendAcks; |
154 | |||
153 | /// <summary>Flag to signal when clients should send pings</summary> | 155 | /// <summary>Flag to signal when clients should send pings</summary> |
154 | private bool m_sendPing; | 156 | protected bool m_sendPing; |
155 | 157 | ||
156 | private int m_defaultRTO = 0; | 158 | private int m_defaultRTO = 0; |
157 | private int m_maxRTO = 0; | 159 | private int m_maxRTO = 0; |
158 | 160 | private int m_ackTimeout = 0; | |
161 | private int m_pausedAckTimeout = 0; | ||
159 | private bool m_disableFacelights = false; | 162 | private bool m_disableFacelights = false; |
160 | 163 | ||
161 | public Socket Server { get { return null; } } | 164 | public Socket Server { get { return null; } } |
162 | 165 | ||
163 | private int m_malformedCount = 0; // Guard against a spamming attack | 166 | private int m_malformedCount = 0; // Guard against a spamming attack |
164 | 167 | ||
168 | /// <summary> | ||
169 | /// Record current outgoing client for monitoring purposes. | ||
170 | /// </summary> | ||
171 | private IClientAPI m_currentOutgoingClient; | ||
172 | |||
173 | /// <summary> | ||
174 | /// Recording current incoming client for monitoring purposes. | ||
175 | /// </summary> | ||
176 | private IClientAPI m_currentIncomingClient; | ||
177 | |||
165 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) | 178 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) |
166 | : base(listenIP, (int)port) | 179 | : base(listenIP, (int)port) |
167 | { | 180 | { |
@@ -198,11 +211,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
198 | m_defaultRTO = config.GetInt("DefaultRTO", 0); | 211 | m_defaultRTO = config.GetInt("DefaultRTO", 0); |
199 | m_maxRTO = config.GetInt("MaxRTO", 0); | 212 | m_maxRTO = config.GetInt("MaxRTO", 0); |
200 | m_disableFacelights = config.GetBoolean("DisableFacelights", false); | 213 | m_disableFacelights = config.GetBoolean("DisableFacelights", false); |
214 | m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60); | ||
215 | m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300); | ||
201 | } | 216 | } |
202 | else | 217 | else |
203 | { | 218 | { |
204 | PrimUpdatesPerCallback = 100; | 219 | PrimUpdatesPerCallback = 100; |
205 | TextureSendLimit = 20; | 220 | TextureSendLimit = 20; |
221 | m_ackTimeout = 1000 * 60; // 1 minute | ||
222 | m_pausedAckTimeout = 1000 * 300; // 5 minutes | ||
206 | } | 223 | } |
207 | 224 | ||
208 | #region BinaryStats | 225 | #region BinaryStats |
@@ -239,19 +256,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
239 | if (m_scene == null) | 256 | if (m_scene == null) |
240 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); | 257 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); |
241 | 258 | ||
242 | m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode"); | 259 | m_log.InfoFormat( |
260 | "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", | ||
261 | m_asyncPacketHandling ? "asynchronous" : "synchronous"); | ||
243 | 262 | ||
244 | base.Start(m_recvBufferSize, m_asyncPacketHandling); | 263 | base.Start(m_recvBufferSize, m_asyncPacketHandling); |
245 | 264 | ||
246 | // Start the packet processing threads | 265 | // Start the packet processing threads |
247 | Watchdog.StartThread( | 266 | Watchdog.StartThread( |
248 | IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true); | 267 | IncomingPacketHandler, |
268 | string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), | ||
269 | ThreadPriority.Normal, | ||
270 | false, | ||
271 | true, | ||
272 | GetWatchdogIncomingAlarmData, | ||
273 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | ||
274 | |||
249 | Watchdog.StartThread( | 275 | Watchdog.StartThread( |
250 | OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true); | 276 | OutgoingPacketHandler, |
277 | string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), | ||
278 | ThreadPriority.Normal, | ||
279 | false, | ||
280 | true, | ||
281 | GetWatchdogOutgoingAlarmData, | ||
282 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | ||
251 | 283 | ||
252 | m_elapsedMSSinceLastStatReport = Environment.TickCount; | 284 | m_elapsedMSSinceLastStatReport = Environment.TickCount; |
253 | } | 285 | } |
254 | 286 | ||
287 | /// <summary> | ||
288 | /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. | ||
289 | /// </summary> | ||
290 | /// <returns></returns> | ||
291 | private string GetWatchdogIncomingAlarmData() | ||
292 | { | ||
293 | return string.Format( | ||
294 | "Client is {0}", | ||
295 | m_currentIncomingClient != null ? m_currentIncomingClient.Name : "none"); | ||
296 | } | ||
297 | |||
298 | /// <summary> | ||
299 | /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. | ||
300 | /// </summary> | ||
301 | /// <returns></returns> | ||
302 | private string GetWatchdogOutgoingAlarmData() | ||
303 | { | ||
304 | return string.Format( | ||
305 | "Client is {0}", | ||
306 | m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); | ||
307 | } | ||
308 | |||
255 | public new void Stop() | 309 | public new void Stop() |
256 | { | 310 | { |
257 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | 311 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); |
@@ -485,19 +539,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
485 | SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); | 539 | SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); |
486 | } | 540 | } |
487 | 541 | ||
488 | public void HandleUnacked(LLUDPClient udpClient) | 542 | public void HandleUnacked(LLClientView client) |
489 | { | 543 | { |
544 | LLUDPClient udpClient = client.UDPClient; | ||
545 | |||
490 | if (!udpClient.IsConnected) | 546 | if (!udpClient.IsConnected) |
491 | return; | 547 | return; |
492 | 548 | ||
493 | // Disconnect an agent if no packets are received for some time | 549 | // Disconnect an agent if no packets are received for some time |
494 | //FIXME: Make 60 an .ini setting | 550 | int timeoutTicks = m_ackTimeout; |
495 | if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60) | 551 | |
552 | // Allow more slack if the client is "paused" eg file upload dialogue is open | ||
553 | // Some sort of limit is needed in case the client crashes, loses its network connection | ||
554 | // or some other disaster prevents it from sendung the AgentResume | ||
555 | if (udpClient.IsPaused) | ||
556 | timeoutTicks = m_pausedAckTimeout; | ||
557 | |||
558 | if (client.IsActive && | ||
559 | (Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks) | ||
496 | { | 560 | { |
497 | m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); | 561 | // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even |
498 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); | 562 | // though it's set later on by LLClientView.Close() |
563 | client.IsActive = false; | ||
564 | |||
565 | // Fire this out on a different thread so that we don't hold up outgoing packet processing for | ||
566 | // everybody else if this is being called due to an ack timeout. | ||
567 | // This is the same as processing as the async process of a logout request. | ||
568 | Util.FireAndForget(o => DeactivateClientDueToTimeout(client)); | ||
499 | 569 | ||
500 | RemoveClient(udpClient); | ||
501 | return; | 570 | return; |
502 | } | 571 | } |
503 | 572 | ||
@@ -823,7 +892,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
823 | #endregion Ping Check Handling | 892 | #endregion Ping Check Handling |
824 | 893 | ||
825 | // Inbox insertion | 894 | // Inbox insertion |
826 | packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); | 895 | packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); |
827 | } | 896 | } |
828 | 897 | ||
829 | #region BinaryStats | 898 | #region BinaryStats |
@@ -919,7 +988,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
919 | UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; | 988 | UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; |
920 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; | 989 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; |
921 | 990 | ||
922 | m_log.DebugFormat("[LLUDPSERVER]: Handling UseCircuitCode request from {0}", buffer.RemoteEndPoint); | 991 | m_log.DebugFormat( |
992 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", | ||
993 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); | ||
923 | 994 | ||
924 | remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; | 995 | remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; |
925 | 996 | ||
@@ -948,8 +1019,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
948 | { | 1019 | { |
949 | // Don't create clients for unauthorized requesters. | 1020 | // Don't create clients for unauthorized requesters. |
950 | m_log.WarnFormat( | 1021 | m_log.WarnFormat( |
951 | "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", | 1022 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
952 | uccp.CircuitCode.ID, uccp.CircuitCode.Code, remoteEndPoint); | 1023 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); |
953 | } | 1024 | } |
954 | 1025 | ||
955 | // m_log.DebugFormat( | 1026 | // m_log.DebugFormat( |
@@ -1047,15 +1118,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1047 | return client; | 1118 | return client; |
1048 | } | 1119 | } |
1049 | 1120 | ||
1050 | private void RemoveClient(LLUDPClient udpClient) | 1121 | /// <summary> |
1122 | /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds). | ||
1123 | /// </summary> | ||
1124 | /// <remarks> | ||
1125 | /// If a connection is active then we will always receive packets even if nothing else is happening, due to | ||
1126 | /// regular client pings. | ||
1127 | /// </remarks> | ||
1128 | /// <param name='client'></param> | ||
1129 | private void DeactivateClientDueToTimeout(IClientAPI client) | ||
1051 | { | 1130 | { |
1052 | // Remove this client from the scene | 1131 | // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even |
1053 | IClientAPI client; | 1132 | // though it's set later on by LLClientView.Close() |
1054 | if (m_scene.TryGetClient(udpClient.AgentID, out client)) | 1133 | client.IsActive = false; |
1055 | { | 1134 | |
1056 | client.IsLoggingOut = true; | 1135 | m_log.WarnFormat( |
1057 | client.Close(false); | 1136 | "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", |
1058 | } | 1137 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); |
1138 | |||
1139 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); | ||
1140 | |||
1141 | if (!client.SceneAgent.IsChildAgent) | ||
1142 | client.Kick("Simulator logged you out due to connection timeout"); | ||
1143 | |||
1144 | Util.FireAndForget(o => client.Close()); | ||
1059 | } | 1145 | } |
1060 | 1146 | ||
1061 | private void IncomingPacketHandler() | 1147 | private void IncomingPacketHandler() |
@@ -1164,6 +1250,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1164 | // client. m_packetSent will be set to true if a packet is sent | 1250 | // client. m_packetSent will be set to true if a packet is sent |
1165 | m_scene.ForEachClient(clientPacketHandler); | 1251 | m_scene.ForEachClient(clientPacketHandler); |
1166 | 1252 | ||
1253 | m_currentOutgoingClient = null; | ||
1254 | |||
1167 | // If nothing was sent, sleep for the minimum amount of time before a | 1255 | // If nothing was sent, sleep for the minimum amount of time before a |
1168 | // token bucket could get more tokens | 1256 | // token bucket could get more tokens |
1169 | if (!m_packetSent) | 1257 | if (!m_packetSent) |
@@ -1180,18 +1268,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1180 | Watchdog.RemoveThread(); | 1268 | Watchdog.RemoveThread(); |
1181 | } | 1269 | } |
1182 | 1270 | ||
1183 | private void ClientOutgoingPacketHandler(IClientAPI client) | 1271 | protected void ClientOutgoingPacketHandler(IClientAPI client) |
1184 | { | 1272 | { |
1273 | m_currentOutgoingClient = client; | ||
1274 | |||
1185 | try | 1275 | try |
1186 | { | 1276 | { |
1187 | if (client is LLClientView) | 1277 | if (client is LLClientView) |
1188 | { | 1278 | { |
1189 | LLUDPClient udpClient = ((LLClientView)client).UDPClient; | 1279 | LLClientView llClient = (LLClientView)client; |
1280 | LLUDPClient udpClient = llClient.UDPClient; | ||
1190 | 1281 | ||
1191 | if (udpClient.IsConnected) | 1282 | if (udpClient.IsConnected) |
1192 | { | 1283 | { |
1193 | if (m_resendUnacked) | 1284 | if (m_resendUnacked) |
1194 | HandleUnacked(udpClient); | 1285 | HandleUnacked(llClient); |
1195 | 1286 | ||
1196 | if (m_sendAcks) | 1287 | if (m_sendAcks) |
1197 | SendAcks(udpClient); | 1288 | SendAcks(udpClient); |
@@ -1207,8 +1298,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1207 | } | 1298 | } |
1208 | catch (Exception ex) | 1299 | catch (Exception ex) |
1209 | { | 1300 | { |
1210 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + | 1301 | m_log.Error( |
1211 | " threw an exception: " + ex.Message, ex); | 1302 | string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex); |
1212 | } | 1303 | } |
1213 | } | 1304 | } |
1214 | 1305 | ||
@@ -1234,11 +1325,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1234 | { | 1325 | { |
1235 | nticks++; | 1326 | nticks++; |
1236 | watch1.Start(); | 1327 | watch1.Start(); |
1328 | m_currentOutgoingClient = client; | ||
1329 | |||
1237 | try | 1330 | try |
1238 | { | 1331 | { |
1239 | if (client is LLClientView) | 1332 | if (client is LLClientView) |
1240 | { | 1333 | { |
1241 | LLUDPClient udpClient = ((LLClientView)client).UDPClient; | 1334 | LLClientView llClient = (LLClientView)client; |
1335 | LLUDPClient udpClient = llClient.UDPClient; | ||
1242 | 1336 | ||
1243 | if (udpClient.IsConnected) | 1337 | if (udpClient.IsConnected) |
1244 | { | 1338 | { |
@@ -1247,7 +1341,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1247 | nticksUnack++; | 1341 | nticksUnack++; |
1248 | watch2.Start(); | 1342 | watch2.Start(); |
1249 | 1343 | ||
1250 | HandleUnacked(udpClient); | 1344 | HandleUnacked(llClient); |
1251 | 1345 | ||
1252 | watch2.Stop(); | 1346 | watch2.Stop(); |
1253 | avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); | 1347 | avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); |
@@ -1318,23 +1412,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1318 | 1412 | ||
1319 | #endregion | 1413 | #endregion |
1320 | 1414 | ||
1321 | private void ProcessInPacket(object state) | 1415 | private void ProcessInPacket(IncomingPacket incomingPacket) |
1322 | { | 1416 | { |
1323 | IncomingPacket incomingPacket = (IncomingPacket)state; | ||
1324 | Packet packet = incomingPacket.Packet; | 1417 | Packet packet = incomingPacket.Packet; |
1325 | LLUDPClient udpClient = incomingPacket.Client; | 1418 | LLClientView client = incomingPacket.Client; |
1326 | IClientAPI client; | ||
1327 | 1419 | ||
1328 | // Sanity check | 1420 | if (client.IsActive) |
1329 | if (packet == null || udpClient == null) | ||
1330 | { | 1421 | { |
1331 | m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"", | 1422 | m_currentIncomingClient = client; |
1332 | packet, udpClient); | ||
1333 | } | ||
1334 | 1423 | ||
1335 | // Make sure this client is still alive | ||
1336 | if (m_scene.TryGetClient(udpClient.AgentID, out client)) | ||
1337 | { | ||
1338 | try | 1424 | try |
1339 | { | 1425 | { |
1340 | // Process this packet | 1426 | // Process this packet |
@@ -1349,21 +1435,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1349 | catch (Exception e) | 1435 | catch (Exception e) |
1350 | { | 1436 | { |
1351 | // Don't let a failure in an individual client thread crash the whole sim. | 1437 | // Don't let a failure in an individual client thread crash the whole sim. |
1352 | m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type); | 1438 | m_log.Error( |
1353 | m_log.Error(e.Message, e); | 1439 | string.Format( |
1440 | "[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ", | ||
1441 | client.Name, packet.Type), | ||
1442 | e); | ||
1443 | } | ||
1444 | finally | ||
1445 | { | ||
1446 | m_currentIncomingClient = null; | ||
1354 | } | 1447 | } |
1355 | } | 1448 | } |
1356 | else | 1449 | else |
1357 | { | 1450 | { |
1358 | m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID); | 1451 | m_log.DebugFormat( |
1452 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | ||
1453 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | ||
1359 | } | 1454 | } |
1360 | } | 1455 | } |
1361 | 1456 | ||
1362 | protected void LogoutHandler(IClientAPI client) | 1457 | protected void LogoutHandler(IClientAPI client) |
1363 | { | 1458 | { |
1364 | client.SendLogoutPacket(); | 1459 | client.SendLogoutPacket(); |
1365 | if (client.IsActive) | 1460 | |
1366 | RemoveClient(((LLClientView)client).UDPClient); | 1461 | if (!client.IsLoggingOut) |
1462 | { | ||
1463 | client.IsLoggingOut = true; | ||
1464 | client.Close(); | ||
1465 | } | ||
1367 | } | 1466 | } |
1368 | } | 1467 | } |
1369 | } | 1468 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index a575e36..109a8e1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs | |||
@@ -45,6 +45,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
45 | [TestFixture] | 45 | [TestFixture] |
46 | public class BasicCircuitTests | 46 | public class BasicCircuitTests |
47 | { | 47 | { |
48 | private Scene m_scene; | ||
49 | private TestLLUDPServer m_udpServer; | ||
50 | |||
48 | [TestFixtureSetUp] | 51 | [TestFixtureSetUp] |
49 | public void FixtureInit() | 52 | public void FixtureInit() |
50 | { | 53 | { |
@@ -61,83 +64,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
61 | Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; | 64 | Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; |
62 | } | 65 | } |
63 | 66 | ||
64 | // /// <summary> | 67 | [SetUp] |
65 | // /// Add a client for testing | 68 | public void SetUp() |
66 | // /// </summary> | 69 | { |
67 | // /// <param name="scene"></param> | 70 | m_scene = new SceneHelpers().SetupScene(); |
68 | // /// <param name="testLLUDPServer"></param> | 71 | } |
69 | // /// <param name="testPacketServer"></param> | ||
70 | // /// <param name="acm">Agent circuit manager used in setting up the stack</param> | ||
71 | // protected void SetupStack( | ||
72 | // IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer, | ||
73 | // out AgentCircuitManager acm) | ||
74 | // { | ||
75 | // IConfigSource configSource = new IniConfigSource(); | ||
76 | // ClientStackUserSettings userSettings = new ClientStackUserSettings(); | ||
77 | // testLLUDPServer = new TestLLUDPServer(); | ||
78 | // acm = new AgentCircuitManager(); | ||
79 | // | ||
80 | // uint port = 666; | ||
81 | // testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm); | ||
82 | // testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings); | ||
83 | // testLLUDPServer.LocalScene = scene; | ||
84 | // } | ||
85 | |||
86 | // /// <summary> | ||
87 | // /// Set up a client for tests which aren't concerned with this process itself and where only one client is being | ||
88 | // /// tested | ||
89 | // /// </summary> | ||
90 | // /// <param name="circuitCode"></param> | ||
91 | // /// <param name="epSender"></param> | ||
92 | // /// <param name="testLLUDPServer"></param> | ||
93 | // /// <param name="acm"></param> | ||
94 | // protected void AddClient( | ||
95 | // uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm) | ||
96 | // { | ||
97 | // UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); | ||
98 | // UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); | ||
99 | // | ||
100 | // AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm); | ||
101 | // } | ||
102 | |||
103 | // /// <summary> | ||
104 | // /// Set up a client for tests which aren't concerned with this process itself | ||
105 | // /// </summary> | ||
106 | // /// <param name="circuitCode"></param> | ||
107 | // /// <param name="epSender"></param> | ||
108 | // /// <param name="agentId"></param> | ||
109 | // /// <param name="sessionId"></param> | ||
110 | // /// <param name="testLLUDPServer"></param> | ||
111 | // /// <param name="acm"></param> | ||
112 | // protected void AddClient( | ||
113 | // uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId, | ||
114 | // TestLLUDPServer testLLUDPServer, AgentCircuitManager acm) | ||
115 | // { | ||
116 | // AgentCircuitData acd = new AgentCircuitData(); | ||
117 | // acd.AgentID = agentId; | ||
118 | // acd.SessionID = sessionId; | ||
119 | // | ||
120 | // UseCircuitCodePacket uccp = new UseCircuitCodePacket(); | ||
121 | // | ||
122 | // UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock | ||
123 | // = new UseCircuitCodePacket.CircuitCodeBlock(); | ||
124 | // uccpCcBlock.Code = circuitCode; | ||
125 | // uccpCcBlock.ID = agentId; | ||
126 | // uccpCcBlock.SessionID = sessionId; | ||
127 | // uccp.CircuitCode = uccpCcBlock; | ||
128 | // | ||
129 | // acm.AddNewCircuit(circuitCode, acd); | ||
130 | // | ||
131 | // testLLUDPServer.LoadReceive(uccp, epSender); | ||
132 | // testLLUDPServer.ReceiveData(null); | ||
133 | // } | ||
134 | 72 | ||
135 | /// <summary> | 73 | /// <summary> |
136 | /// Build an object name packet for test purposes | 74 | /// Build an object name packet for test purposes |
137 | /// </summary> | 75 | /// </summary> |
138 | /// <param name="objectLocalId"></param> | 76 | /// <param name="objectLocalId"></param> |
139 | /// <param name="objectName"></param> | 77 | /// <param name="objectName"></param> |
140 | protected ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName) | 78 | private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName) |
141 | { | 79 | { |
142 | ObjectNamePacket onp = new ObjectNamePacket(); | 80 | ObjectNamePacket onp = new ObjectNamePacket(); |
143 | ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock(); | 81 | ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock(); |
@@ -148,6 +86,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
148 | 86 | ||
149 | return onp; | 87 | return onp; |
150 | } | 88 | } |
89 | |||
90 | private void AddUdpServer() | ||
91 | { | ||
92 | AddUdpServer(new IniConfigSource()); | ||
93 | } | ||
94 | |||
95 | private void AddUdpServer(IniConfigSource configSource) | ||
96 | { | ||
97 | uint port = 0; | ||
98 | AgentCircuitManager acm = m_scene.AuthenticateHandler; | ||
99 | |||
100 | m_udpServer = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, configSource, acm); | ||
101 | m_udpServer.AddScene(m_scene); | ||
102 | } | ||
103 | |||
104 | /// <summary> | ||
105 | /// Used by tests that aren't testing this stage. | ||
106 | /// </summary> | ||
107 | private ScenePresence AddClient() | ||
108 | { | ||
109 | UUID myAgentUuid = TestHelpers.ParseTail(0x1); | ||
110 | UUID mySessionUuid = TestHelpers.ParseTail(0x2); | ||
111 | uint myCircuitCode = 123456; | ||
112 | IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); | ||
113 | |||
114 | UseCircuitCodePacket uccp = new UseCircuitCodePacket(); | ||
115 | |||
116 | UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock | ||
117 | = new UseCircuitCodePacket.CircuitCodeBlock(); | ||
118 | uccpCcBlock.Code = myCircuitCode; | ||
119 | uccpCcBlock.ID = myAgentUuid; | ||
120 | uccpCcBlock.SessionID = mySessionUuid; | ||
121 | uccp.CircuitCode = uccpCcBlock; | ||
122 | |||
123 | byte[] uccpBytes = uccp.ToBytes(); | ||
124 | UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length); | ||
125 | upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. | ||
126 | Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); | ||
127 | |||
128 | AgentCircuitData acd = new AgentCircuitData(); | ||
129 | acd.AgentID = myAgentUuid; | ||
130 | acd.SessionID = mySessionUuid; | ||
131 | |||
132 | m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd); | ||
133 | |||
134 | m_udpServer.PacketReceived(upb); | ||
135 | |||
136 | return m_scene.GetScenePresence(myAgentUuid); | ||
137 | } | ||
151 | 138 | ||
152 | /// <summary> | 139 | /// <summary> |
153 | /// Test adding a client to the stack | 140 | /// Test adding a client to the stack |
@@ -158,19 +145,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
158 | TestHelpers.InMethod(); | 145 | TestHelpers.InMethod(); |
159 | // XmlConfigurator.Configure(); | 146 | // XmlConfigurator.Configure(); |
160 | 147 | ||
161 | TestScene scene = SceneHelpers.SetupScene(); | 148 | AddUdpServer(); |
162 | uint myCircuitCode = 123456; | 149 | |
163 | UUID myAgentUuid = TestHelpers.ParseTail(0x1); | 150 | UUID myAgentUuid = TestHelpers.ParseTail(0x1); |
164 | UUID mySessionUuid = TestHelpers.ParseTail(0x2); | 151 | UUID mySessionUuid = TestHelpers.ParseTail(0x2); |
152 | uint myCircuitCode = 123456; | ||
165 | IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); | 153 | IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); |
166 | 154 | ||
167 | uint port = 0; | ||
168 | AgentCircuitManager acm = scene.AuthenticateHandler; | ||
169 | |||
170 | TestLLUDPServer llUdpServer | ||
171 | = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm); | ||
172 | llUdpServer.AddScene(scene); | ||
173 | |||
174 | UseCircuitCodePacket uccp = new UseCircuitCodePacket(); | 155 | UseCircuitCodePacket uccp = new UseCircuitCodePacket(); |
175 | 156 | ||
176 | UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock | 157 | UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock |
@@ -185,26 +166,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
185 | upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. | 166 | upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. |
186 | Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); | 167 | Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); |
187 | 168 | ||
188 | llUdpServer.PacketReceived(upb); | 169 | m_udpServer.PacketReceived(upb); |
189 | 170 | ||
190 | // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet | 171 | // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet |
191 | Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null); | 172 | Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null); |
192 | 173 | ||
193 | AgentCircuitData acd = new AgentCircuitData(); | 174 | AgentCircuitData acd = new AgentCircuitData(); |
194 | acd.AgentID = myAgentUuid; | 175 | acd.AgentID = myAgentUuid; |
195 | acd.SessionID = mySessionUuid; | 176 | acd.SessionID = mySessionUuid; |
196 | 177 | ||
197 | acm.AddNewCircuit(myCircuitCode, acd); | 178 | m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd); |
198 | 179 | ||
199 | llUdpServer.PacketReceived(upb); | 180 | m_udpServer.PacketReceived(upb); |
200 | 181 | ||
201 | // Should succeed now | 182 | // Should succeed now |
202 | ScenePresence sp = scene.GetScenePresence(myAgentUuid); | 183 | ScenePresence sp = m_scene.GetScenePresence(myAgentUuid); |
203 | Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); | 184 | Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); |
204 | 185 | ||
205 | Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1)); | 186 | Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1)); |
206 | 187 | ||
207 | Packet packet = llUdpServer.PacketsSent[0]; | 188 | Packet packet = m_udpServer.PacketsSent[0]; |
208 | Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); | 189 | Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); |
209 | 190 | ||
210 | PacketAckPacket ackPacket = packet as PacketAckPacket; | 191 | PacketAckPacket ackPacket = packet as PacketAckPacket; |
@@ -212,6 +193,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
212 | Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0)); | 193 | Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0)); |
213 | } | 194 | } |
214 | 195 | ||
196 | [Test] | ||
197 | public void TestLogoutClientDueToAck() | ||
198 | { | ||
199 | TestHelpers.InMethod(); | ||
200 | // TestHelpers.EnableLogging(); | ||
201 | |||
202 | IniConfigSource ics = new IniConfigSource(); | ||
203 | IConfig config = ics.AddConfig("ClientStack.LindenUDP"); | ||
204 | config.Set("AckTimeout", -1); | ||
205 | AddUdpServer(ics); | ||
206 | |||
207 | ScenePresence sp = AddClient(); | ||
208 | m_udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false); | ||
209 | |||
210 | ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); | ||
211 | Assert.That(spAfterAckTimeout, Is.Null); | ||
212 | |||
213 | // TestHelpers.DisableLogging(); | ||
214 | } | ||
215 | |||
215 | // /// <summary> | 216 | // /// <summary> |
216 | // /// Test removing a client from the stack | 217 | // /// Test removing a client from the stack |
217 | // /// </summary> | 218 | // /// </summary> |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs index 1b68d68..5fcf376 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs | |||
@@ -79,7 +79,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
79 | 79 | ||
80 | J2KDecoderModule j2kdm = new J2KDecoderModule(); | 80 | J2KDecoderModule j2kdm = new J2KDecoderModule(); |
81 | 81 | ||
82 | scene = SceneHelpers.SetupScene(); | 82 | SceneHelpers sceneHelpers = new SceneHelpers(); |
83 | scene = sceneHelpers.SetupScene(); | ||
83 | SceneHelpers.SetupSceneModules(scene, j2kdm); | 84 | SceneHelpers.SetupSceneModules(scene, j2kdm); |
84 | 85 | ||
85 | tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); | 86 | tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs index d76927b..119a677 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs | |||
@@ -44,9 +44,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
44 | } | 44 | } |
45 | protected int m_objectNameCallsReceived; | 45 | protected int m_objectNameCallsReceived; |
46 | 46 | ||
47 | public MockScene() | 47 | public MockScene() : base(new RegionInfo(1000, 1000, null, null)) |
48 | { | 48 | { |
49 | m_regInfo = new RegionInfo(1000, 1000, null, null); | ||
50 | m_regStatus = RegionStatus.Up; | 49 | m_regStatus = RegionStatus.Up; |
51 | } | 50 | } |
52 | 51 | ||
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs index 0302385..27b9e5b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs | |||
@@ -59,6 +59,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
59 | PacketsSent.Add(packet); | 59 | PacketsSent.Add(packet); |
60 | } | 60 | } |
61 | 61 | ||
62 | public void ClientOutgoingPacketHandler(IClientAPI client, bool resendUnacked, bool sendAcks, bool sendPing) | ||
63 | { | ||
64 | m_resendUnacked = resendUnacked; | ||
65 | m_sendAcks = sendAcks; | ||
66 | m_sendPing = sendPing; | ||
67 | |||
68 | ClientOutgoingPacketHandler(client); | ||
69 | } | ||
70 | |||
62 | //// /// <summary> | 71 | //// /// <summary> |
63 | //// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive | 72 | //// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive |
64 | //// /// </summary> | 73 | //// /// </summary> |