aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs111
1 files changed, 96 insertions, 15 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 7035e38..881e768 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -78,6 +78,36 @@ namespace OpenMetaverse
78 public bool IsRunningOutbound { get; private set; } 78 public bool IsRunningOutbound { get; private set; }
79 79
80 /// <summary> 80 /// <summary>
81 /// Number of UDP receives.
82 /// </summary>
83 public int UdpReceives { get; private set; }
84
85 /// <summary>
86 /// Number of UDP sends
87 /// </summary>
88 public int UdpSends { get; private set; }
89
90 /// <summary>
91 /// Number of receives over which to establish a receive time average.
92 /// </summary>
93 private readonly static int s_receiveTimeSamples = 500;
94
95 /// <summary>
96 /// Current number of samples taken to establish a receive time average.
97 /// </summary>
98 private int m_currentReceiveTimeSamples;
99
100 /// <summary>
101 /// Cumulative receive time for the sample so far.
102 /// </summary>
103 private int m_receiveTicksInCurrentSamplePeriod;
104
105 /// <summary>
106 /// The average time taken for each require receive in the last sample.
107 /// </summary>
108 public float AverageReceiveTicksForLastSamplePeriod { get; private set; }
109
110 /// <summary>
81 /// Default constructor 111 /// Default constructor
82 /// </summary> 112 /// </summary>
83 /// <param name="bindAddress">Local IP address to bind the server to</param> 113 /// <param name="bindAddress">Local IP address to bind the server to</param>
@@ -111,6 +141,8 @@ namespace OpenMetaverse
111 141
112 if (!IsRunningInbound) 142 if (!IsRunningInbound)
113 { 143 {
144 m_log.DebugFormat("[UDPBASE]: Starting inbound UDP loop");
145
114 const int SIO_UDP_CONNRESET = -1744830452; 146 const int SIO_UDP_CONNRESET = -1744830452;
115 147
116 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 148 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
@@ -151,6 +183,8 @@ namespace OpenMetaverse
151 /// </summary> 183 /// </summary>
152 public void StartOutbound() 184 public void StartOutbound()
153 { 185 {
186 m_log.DebugFormat("[UDPBASE]: Starting outbound UDP loop");
187
154 IsRunningOutbound = true; 188 IsRunningOutbound = true;
155 } 189 }
156 190
@@ -158,10 +192,8 @@ namespace OpenMetaverse
158 { 192 {
159 if (IsRunningInbound) 193 if (IsRunningInbound)
160 { 194 {
161 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 195 m_log.DebugFormat("[UDPBASE]: Stopping inbound UDP loop");
162 // will deny any more reader locks, in effect blocking all other send/receive 196
163 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other
164 // threads that the socket is closed.
165 IsRunningInbound = false; 197 IsRunningInbound = false;
166 m_udpSocket.Close(); 198 m_udpSocket.Close();
167 } 199 }
@@ -169,6 +201,8 @@ namespace OpenMetaverse
169 201
170 public void StopOutbound() 202 public void StopOutbound()
171 { 203 {
204 m_log.DebugFormat("[UDPBASE]: Stopping outbound UDP loop");
205
172 IsRunningOutbound = false; 206 IsRunningOutbound = false;
173 } 207 }
174 208
@@ -257,7 +291,16 @@ namespace OpenMetaverse
257 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); 291 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
258 } 292 }
259 } 293 }
260 catch (ObjectDisposedException) { } 294 catch (ObjectDisposedException e)
295 {
296 m_log.Error(
297 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
298 }
299 catch (Exception e)
300 {
301 m_log.Error(
302 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
303 }
261 } 304 }
262 } 305 }
263 306
@@ -267,17 +310,21 @@ namespace OpenMetaverse
267 // to AsyncBeginReceive 310 // to AsyncBeginReceive
268 if (IsRunningInbound) 311 if (IsRunningInbound)
269 { 312 {
313 UdpReceives++;
314
270 // Asynchronous mode will start another receive before the 315 // Asynchronous mode will start another receive before the
271 // callback for this packet is even fired. Very parallel :-) 316 // callback for this packet is even fired. Very parallel :-)
272 if (m_asyncPacketHandling) 317 if (m_asyncPacketHandling)
273 AsyncBeginReceive(); 318 AsyncBeginReceive();
274 319
275 // get the buffer that was created in AsyncBeginReceive
276 // this is the received data
277 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
278
279 try 320 try
280 { 321 {
322 // get the buffer that was created in AsyncBeginReceive
323 // this is the received data
324 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
325
326 int startTick = Util.EnvironmentTickCount();
327
281 // get the length of data actually read from the socket, store it with the 328 // get the length of data actually read from the socket, store it with the
282 // buffer 329 // buffer
283 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); 330 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
@@ -285,9 +332,42 @@ namespace OpenMetaverse
285 // call the abstract method PacketReceived(), passing the buffer that 332 // call the abstract method PacketReceived(), passing the buffer that
286 // has just been filled from the socket read. 333 // has just been filled from the socket read.
287 PacketReceived(buffer); 334 PacketReceived(buffer);
335
336 // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler)
337 // then a particular stat may be inaccurate due to a race condition. We won't worry about this
338 // since this should be rare and won't cause a runtime problem.
339 if (m_currentReceiveTimeSamples >= s_receiveTimeSamples)
340 {
341 AverageReceiveTicksForLastSamplePeriod
342 = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples;
343
344 m_receiveTicksInCurrentSamplePeriod = 0;
345 m_currentReceiveTimeSamples = 0;
346 }
347 else
348 {
349 m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick);
350 m_currentReceiveTimeSamples++;
351 }
352 }
353 catch (SocketException se)
354 {
355 m_log.Error(
356 string.Format(
357 "[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}. Exception ",
358 UdpReceives, se.ErrorCode),
359 se);
360 }
361 catch (ObjectDisposedException e)
362 {
363 m_log.Error(
364 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
365 }
366 catch (Exception e)
367 {
368 m_log.Error(
369 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
288 } 370 }
289 catch (SocketException) { }
290 catch (ObjectDisposedException) { }
291 finally 371 finally
292 { 372 {
293// if (UsePools) 373// if (UsePools)
@@ -298,14 +378,13 @@ namespace OpenMetaverse
298 if (!m_asyncPacketHandling) 378 if (!m_asyncPacketHandling)
299 AsyncBeginReceive(); 379 AsyncBeginReceive();
300 } 380 }
301
302 } 381 }
303 } 382 }
304 383
305 public void AsyncBeginSend(UDPPacketBuffer buf) 384 public void AsyncBeginSend(UDPPacketBuffer buf)
306 { 385 {
307 if (IsRunningOutbound) 386// if (IsRunningOutbound)
308 { 387// {
309 try 388 try
310 { 389 {
311 m_udpSocket.BeginSendTo( 390 m_udpSocket.BeginSendTo(
@@ -319,7 +398,7 @@ namespace OpenMetaverse
319 } 398 }
320 catch (SocketException) { } 399 catch (SocketException) { }
321 catch (ObjectDisposedException) { } 400 catch (ObjectDisposedException) { }
322 } 401// }
323 } 402 }
324 403
325 void AsyncEndSend(IAsyncResult result) 404 void AsyncEndSend(IAsyncResult result)
@@ -328,6 +407,8 @@ namespace OpenMetaverse
328 { 407 {
329// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; 408// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
330 m_udpSocket.EndSendTo(result); 409 m_udpSocket.EndSendTo(result);
410
411 UdpSends++;
331 } 412 }
332 catch (SocketException) { } 413 catch (SocketException) { }
333 catch (ObjectDisposedException) { } 414 catch (ObjectDisposedException) { }