diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 7035e38..48c5b37 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 | ||
@@ -267,6 +301,8 @@ namespace OpenMetaverse | |||
267 | // to AsyncBeginReceive | 301 | // to AsyncBeginReceive |
268 | if (IsRunningInbound) | 302 | if (IsRunningInbound) |
269 | { | 303 | { |
304 | UdpReceives++; | ||
305 | |||
270 | // Asynchronous mode will start another receive before the | 306 | // Asynchronous mode will start another receive before the |
271 | // callback for this packet is even fired. Very parallel :-) | 307 | // callback for this packet is even fired. Very parallel :-) |
272 | if (m_asyncPacketHandling) | 308 | if (m_asyncPacketHandling) |
@@ -278,6 +314,8 @@ namespace OpenMetaverse | |||
278 | 314 | ||
279 | try | 315 | try |
280 | { | 316 | { |
317 | int startTick = Util.EnvironmentTickCount(); | ||
318 | |||
281 | // get the length of data actually read from the socket, store it with the | 319 | // get the length of data actually read from the socket, store it with the |
282 | // buffer | 320 | // buffer |
283 | buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); | 321 | buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); |
@@ -285,6 +323,23 @@ namespace OpenMetaverse | |||
285 | // call the abstract method PacketReceived(), passing the buffer that | 323 | // call the abstract method PacketReceived(), passing the buffer that |
286 | // has just been filled from the socket read. | 324 | // has just been filled from the socket read. |
287 | PacketReceived(buffer); | 325 | PacketReceived(buffer); |
326 | |||
327 | // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler) | ||
328 | // then a particular stat may be inaccurate due to a race condition. We won't worry about this | ||
329 | // since this should be rare and won't cause a runtime problem. | ||
330 | if (m_currentReceiveTimeSamples >= s_receiveTimeSamples) | ||
331 | { | ||
332 | AverageReceiveTicksForLastSamplePeriod | ||
333 | = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples; | ||
334 | |||
335 | m_receiveTicksInCurrentSamplePeriod = 0; | ||
336 | m_currentReceiveTimeSamples = 0; | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick); | ||
341 | m_currentReceiveTimeSamples++; | ||
342 | } | ||
288 | } | 343 | } |
289 | catch (SocketException) { } | 344 | catch (SocketException) { } |
290 | catch (ObjectDisposedException) { } | 345 | catch (ObjectDisposedException) { } |
@@ -298,14 +353,13 @@ namespace OpenMetaverse | |||
298 | if (!m_asyncPacketHandling) | 353 | if (!m_asyncPacketHandling) |
299 | AsyncBeginReceive(); | 354 | AsyncBeginReceive(); |
300 | } | 355 | } |
301 | |||
302 | } | 356 | } |
303 | } | 357 | } |
304 | 358 | ||
305 | public void AsyncBeginSend(UDPPacketBuffer buf) | 359 | public void AsyncBeginSend(UDPPacketBuffer buf) |
306 | { | 360 | { |
307 | if (IsRunningOutbound) | 361 | // if (IsRunningOutbound) |
308 | { | 362 | // { |
309 | try | 363 | try |
310 | { | 364 | { |
311 | m_udpSocket.BeginSendTo( | 365 | m_udpSocket.BeginSendTo( |
@@ -319,7 +373,7 @@ namespace OpenMetaverse | |||
319 | } | 373 | } |
320 | catch (SocketException) { } | 374 | catch (SocketException) { } |
321 | catch (ObjectDisposedException) { } | 375 | catch (ObjectDisposedException) { } |
322 | } | 376 | // } |
323 | } | 377 | } |
324 | 378 | ||
325 | void AsyncEndSend(IAsyncResult result) | 379 | void AsyncEndSend(IAsyncResult result) |
@@ -328,6 +382,8 @@ namespace OpenMetaverse | |||
328 | { | 382 | { |
329 | // UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; | 383 | // UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; |
330 | m_udpSocket.EndSendTo(result); | 384 | m_udpSocket.EndSendTo(result); |
385 | |||
386 | UdpSends++; | ||
331 | } | 387 | } |
332 | catch (SocketException) { } | 388 | catch (SocketException) { } |
333 | catch (ObjectDisposedException) { } | 389 | catch (ObjectDisposedException) { } |