diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | 111 |
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) { } |