aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDiva Canto2009-10-09 11:32:53 -0700
committerDiva Canto2009-10-09 11:32:53 -0700
commit8231cb22316e9492dd9e295ac9156689bede2ec3 (patch)
tree6d8f0728cffccff5314dc9c9f7cf13a68127ff7a
parentMerge branch 'master' of ssh://melanie@opensimulator.org/var/git/opensim (diff)
downloadopensim-SC_OLD-8231cb22316e9492dd9e295ac9156689bede2ec3.zip
opensim-SC_OLD-8231cb22316e9492dd9e295ac9156689bede2ec3.tar.gz
opensim-SC_OLD-8231cb22316e9492dd9e295ac9156689bede2ec3.tar.bz2
opensim-SC_OLD-8231cb22316e9492dd9e295ac9156689bede2ec3.tar.xz
Putting this to exactly what it was yesterday around this time, so we can do the 100-ppl load test in WP. We need to carefully play with this code in order to understand all the problems.
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs18
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs575
2 files changed, 411 insertions, 182 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
index dbb9861..784426f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
@@ -247,16 +247,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
247 247
248 ////return success; 248 ////return success;
249 249
250 lock (m_sync) 250 //lock (m_sync)
251 return Dictionary2.TryGetValue(key, out value);
252
253 //try
254 //{
255 // return Dictionary2.TryGetValue(key, out value); 251 // return Dictionary2.TryGetValue(key, out value);
256 //} 252
257 //catch { } 253 try
258 //value = null; 254 {
259 //return false; 255 return Dictionary2.TryGetValue(key, out value);
256 }
257 catch { }
258 value = null;
259 return false;
260 260
261 } 261 }
262 262
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
index 218aaac..43a68ec 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
@@ -1,29 +1,30 @@
1/* 1//--------- Modified Version -------------------
2 * Copyright (c) 2006, Clutch, Inc. 2///*
3 * Original Author: Jeff Cesnik 3// * Copyright (c) 2006, Clutch, Inc.
4 * All rights reserved. 4// * Original Author: Jeff Cesnik
5 * 5// * All rights reserved.
6 * - Redistribution and use in source and binary forms, with or without 6// *
7 * modification, are permitted provided that the following conditions are met: 7// * - Redistribution and use in source and binary forms, with or without
8 * 8// * modification, are permitted provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice, this 9// *
10 * list of conditions and the following disclaimer. 10// * - Redistributions of source code must retain the above copyright notice, this
11 * - Neither the name of the openmetaverse.org nor the names 11// * list of conditions and the following disclaimer.
12 * of its contributors may be used to endorse or promote products derived from 12// * - Neither the name of the openmetaverse.org nor the names
13 * this software without specific prior written permission. 13// * of its contributors may be used to endorse or promote products derived from
14 * 14// * this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15// *
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17// * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18// * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19// * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20// * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21// * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22// * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23// * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24// * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * POSSIBILITY OF SUCH DAMAGE. 25// * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 */ 26// * POSSIBILITY OF SUCH DAMAGE.
27// */
27 28
28using System; 29using System;
29using System.Net; 30using System.Net;
@@ -31,6 +32,317 @@ using System.Net.Sockets;
31using System.Threading; 32using System.Threading;
32using OpenMetaverse; 33using OpenMetaverse;
33 34
35//namespace OpenSim.Region.ClientStack.LindenUDP
36//{
37// /// <summary>
38// ///
39// /// </summary>
40// public abstract class OpenSimUDPBase
41// {
42// // these abstract methods must be implemented in a derived class to actually do
43// // something with the packets that are sent and received.
44// protected abstract void PacketReceived(UDPPacketBuffer buffer);
45// protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent);
46
47// // the port to listen on
48// internal int udpPort;
49
50// // the UDP socket
51// private Socket udpSocket;
52
53// // the ReaderWriterLock is used solely for the purposes of shutdown (Stop()).
54// // since there are potentially many "reader" threads in the internal .NET IOCP
55// // thread pool, this is a cheaper synchronization primitive than using
56// // a Mutex object. This allows many UDP socket "reads" concurrently - when
57// // Stop() is called, it attempts to obtain a writer lock which will then
58// // wait until all outstanding operations are completed before shutting down.
59// // this avoids the problem of closing the socket with outstanding operations
60// // and trying to catch the inevitable ObjectDisposedException.
61// private ReaderWriterLock rwLock = new ReaderWriterLock();
62
63// // number of outstanding operations. This is a reference count
64// // which we use to ensure that the threads exit cleanly. Note that
65// // we need this because the threads will potentially still need to process
66// // data even after the socket is closed.
67// private int rwOperationCount = 0;
68
69// // the all important shutdownFlag. This is synchronized through the ReaderWriterLock.
70// private volatile bool shutdownFlag = true;
71
72// // the remote endpoint to communicate with
73// protected IPEndPoint remoteEndPoint = null;
74
75
76// /// <summary>
77// /// Initialize the UDP packet handler in server mode
78// /// </summary>
79// /// <param name="port">Port to listening for incoming UDP packets on</param>
80// public OpenSimUDPBase(int port)
81// {
82// udpPort = port;
83// }
84
85// /// <summary>
86// /// Initialize the UDP packet handler in client mode
87// /// </summary>
88// /// <param name="endPoint">Remote UDP server to connect to</param>
89// public OpenSimUDPBase(IPEndPoint endPoint)
90// {
91// remoteEndPoint = endPoint;
92// udpPort = 0;
93// }
94
95// /// <summary>
96// ///
97// /// </summary>
98// public void Start()
99// {
100// if (shutdownFlag)
101// {
102// if (remoteEndPoint == null)
103// {
104// // Server mode
105
106// // create and bind the socket
107// IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
108// udpSocket = new Socket(
109// AddressFamily.InterNetwork,
110// SocketType.Dgram,
111// ProtocolType.Udp);
112// udpSocket.Bind(ipep);
113// }
114// else
115// {
116// // Client mode
117// IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
118// udpSocket = new Socket(
119// AddressFamily.InterNetwork,
120// SocketType.Dgram,
121// ProtocolType.Udp);
122// udpSocket.Bind(ipep);
123// //udpSocket.Connect(remoteEndPoint);
124// }
125
126// // we're not shutting down, we're starting up
127// shutdownFlag = false;
128
129// // kick off an async receive. The Start() method will return, the
130// // actual receives will occur asynchronously and will be caught in
131// // AsyncEndRecieve().
132// AsyncBeginReceive();
133// }
134// }
135
136// /// <summary>
137// ///
138// /// </summary>
139// public void Stop()
140// {
141// if (!shutdownFlag)
142// {
143// // wait indefinitely for a writer lock. Once this is called, the .NET runtime
144// // will deny any more reader locks, in effect blocking all other send/receive
145// // threads. Once we have the lock, we set shutdownFlag to inform the other
146// // threads that the socket is closed.
147// rwLock.AcquireWriterLock(-1);
148// shutdownFlag = true;
149// udpSocket.Close();
150// rwLock.ReleaseWriterLock();
151
152// // wait for any pending operations to complete on other
153// // threads before exiting.
154// const int FORCE_STOP = 100;
155// int i = 0;
156// while (rwOperationCount > 0 && i < FORCE_STOP)
157// {
158// Thread.Sleep(10);
159// ++i;
160// }
161
162// if (i >= FORCE_STOP)
163// {
164// Logger.Log("UDPBase.Stop() forced shutdown while waiting on pending operations",
165// Helpers.LogLevel.Warning);
166// }
167// }
168// }
169
170// /// <summary>
171// ///
172// /// </summary>
173// public bool IsRunning
174// {
175// get { return !shutdownFlag; }
176// }
177
178// private void AsyncBeginReceive()
179// {
180// // this method actually kicks off the async read on the socket.
181// // we aquire a reader lock here to ensure that no other thread
182// // is trying to set shutdownFlag and close the socket.
183// rwLock.AcquireReaderLock(-1);
184
185// if (!shutdownFlag)
186// {
187// // increment the count of pending operations
188// Interlocked.Increment(ref rwOperationCount);
189
190// // allocate a packet buffer
191// //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
192// UDPPacketBuffer buf = new UDPPacketBuffer();
193
194// try
195// {
196// // kick off an async read
197// udpSocket.BeginReceiveFrom(
198// //wrappedBuffer.Instance.Data,
199// buf.Data,
200// 0,
201// UDPPacketBuffer.BUFFER_SIZE,
202// SocketFlags.None,
203// //ref wrappedBuffer.Instance.RemoteEndPoint,
204// ref buf.RemoteEndPoint,
205// new AsyncCallback(AsyncEndReceive),
206// //wrappedBuffer);
207// buf);
208// }
209// catch (SocketException)
210// {
211// // something bad happened
212// //Logger.Log(
213// // "A SocketException occurred in UDPServer.AsyncBeginReceive()",
214// // Helpers.LogLevel.Error, se);
215
216// // an error occurred, therefore the operation is void. Decrement the reference count.
217// Interlocked.Decrement(ref rwOperationCount);
218// }
219// }
220
221// // we're done with the socket for now, release the reader lock.
222// rwLock.ReleaseReaderLock();
223// }
224
225// private void AsyncEndReceive(IAsyncResult iar)
226// {
227// // Asynchronous receive operations will complete here through the call
228// // to AsyncBeginReceive
229
230// // aquire a reader lock
231// rwLock.AcquireReaderLock(-1);
232
233// if (!shutdownFlag)
234// {
235// // get the buffer that was created in AsyncBeginReceive
236// // this is the received data
237// //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
238// //UDPPacketBuffer buffer = wrappedBuffer.Instance;
239// UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
240
241// try
242// {
243// // get the length of data actually read from the socket, store it with the
244// // buffer
245// buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
246
247// // this operation is now complete, decrement the reference count
248// Interlocked.Decrement(ref rwOperationCount);
249
250// // we're done with the socket, release the reader lock
251// rwLock.ReleaseReaderLock();
252
253// // call the abstract method PacketReceived(), passing the buffer that
254// // has just been filled from the socket read.
255// PacketReceived(buffer);
256// }
257// catch (SocketException)
258// {
259// // an error occurred, therefore the operation is void. Decrement the reference count.
260// Interlocked.Decrement(ref rwOperationCount);
261
262// // we're done with the socket for now, release the reader lock.
263// rwLock.ReleaseReaderLock();
264// }
265// finally
266// {
267// // start another receive - this keeps the server going!
268// AsyncBeginReceive();
269
270// //wrappedBuffer.Dispose();
271// }
272// }
273// else
274// {
275// // nothing bad happened, but we are done with the operation
276// // decrement the reference count and release the reader lock
277// Interlocked.Decrement(ref rwOperationCount);
278// rwLock.ReleaseReaderLock();
279// }
280// }
281
282// public void AsyncBeginSend(UDPPacketBuffer buf)
283// {
284// rwLock.AcquireReaderLock(-1);
285
286// if (!shutdownFlag)
287// {
288// try
289// {
290// Interlocked.Increment(ref rwOperationCount);
291// udpSocket.BeginSendTo(
292// buf.Data,
293// 0,
294// buf.DataLength,
295// SocketFlags.None,
296// buf.RemoteEndPoint,
297// new AsyncCallback(AsyncEndSend),
298// buf);
299// }
300// catch (SocketException)
301// {
302// //Logger.Log(
303// // "A SocketException occurred in UDPServer.AsyncBeginSend()",
304// // Helpers.LogLevel.Error, se);
305// }
306// }
307
308// rwLock.ReleaseReaderLock();
309// }
310
311// private void AsyncEndSend(IAsyncResult iar)
312// {
313// rwLock.AcquireReaderLock(-1);
314
315// if (!shutdownFlag)
316// {
317// UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
318
319// try
320// {
321// int bytesSent = udpSocket.EndSendTo(iar);
322
323// // note that call to the abstract PacketSent() method - we are passing the number
324// // of bytes sent in a separate parameter, since we can't use buffer.DataLength which
325// // is the number of bytes to send (or bytes received depending upon whether this
326// // buffer was part of a send or a receive).
327// PacketSent(buffer, bytesSent);
328// }
329// catch (SocketException)
330// {
331// //Logger.Log(
332// // "A SocketException occurred in UDPServer.AsyncEndSend()",
333// // Helpers.LogLevel.Error, se);
334// }
335// }
336
337// Interlocked.Decrement(ref rwOperationCount);
338// rwLock.ReleaseReaderLock();
339// }
340// }
341//}
342
343//--------- Original Version -------------------
344
345
34namespace OpenSim.Region.ClientStack.LindenUDP 346namespace OpenSim.Region.ClientStack.LindenUDP
35{ 347{
36 /// <summary> 348 /// <summary>
@@ -49,29 +361,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
49 // the UDP socket 361 // the UDP socket
50 private Socket udpSocket; 362 private Socket udpSocket;
51 363
52 // the ReaderWriterLock is used solely for the purposes of shutdown (Stop()). 364 // the all important shutdownFlag.
53 // since there are potentially many "reader" threads in the internal .NET IOCP
54 // thread pool, this is a cheaper synchronization primitive than using
55 // a Mutex object. This allows many UDP socket "reads" concurrently - when
56 // Stop() is called, it attempts to obtain a writer lock which will then
57 // wait until all outstanding operations are completed before shutting down.
58 // this avoids the problem of closing the socket with outstanding operations
59 // and trying to catch the inevitable ObjectDisposedException.
60 private ReaderWriterLock rwLock = new ReaderWriterLock();
61
62 // number of outstanding operations. This is a reference count
63 // which we use to ensure that the threads exit cleanly. Note that
64 // we need this because the threads will potentially still need to process
65 // data even after the socket is closed.
66 private int rwOperationCount = 0;
67
68 // the all important shutdownFlag. This is synchronized through the ReaderWriterLock.
69 private volatile bool shutdownFlag = true; 365 private volatile bool shutdownFlag = true;
70 366
71 // the remote endpoint to communicate with 367 // the remote endpoint to communicate with
72 protected IPEndPoint remoteEndPoint = null; 368 protected IPEndPoint remoteEndPoint = null;
73 369
74
75 /// <summary> 370 /// <summary>
76 /// Initialize the UDP packet handler in server mode 371 /// Initialize the UDP packet handler in server mode
77 /// </summary> 372 /// </summary>
@@ -98,29 +393,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
98 { 393 {
99 if (shutdownFlag) 394 if (shutdownFlag)
100 { 395 {
101 if (remoteEndPoint == null) 396 const int SIO_UDP_CONNRESET = -1744830452;
397
398 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
399 udpSocket = new Socket(
400 AddressFamily.InterNetwork,
401 SocketType.Dgram,
402 ProtocolType.Udp);
403 try
102 { 404 {
103 // Server mode 405 // this udp socket flag is not supported under mono,
104 406 // so we'll catch the exception and continue
105 // create and bind the socket 407 udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
106 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
107 udpSocket = new Socket(
108 AddressFamily.InterNetwork,
109 SocketType.Dgram,
110 ProtocolType.Udp);
111 udpSocket.Bind(ipep);
112 } 408 }
113 else 409 catch (SocketException)
114 { 410 {
115 // Client mode 411 Logger.DebugLog("UDP SIO_UDP_CONNRESET flag not supported on this platform");
116 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
117 udpSocket = new Socket(
118 AddressFamily.InterNetwork,
119 SocketType.Dgram,
120 ProtocolType.Udp);
121 udpSocket.Bind(ipep);
122 //udpSocket.Connect(remoteEndPoint);
123 } 412 }
413 udpSocket.Bind(ipep);
124 414
125 // we're not shutting down, we're starting up 415 // we're not shutting down, we're starting up
126 shutdownFlag = false; 416 shutdownFlag = false;
@@ -143,26 +433,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
143 // will deny any more reader locks, in effect blocking all other send/receive 433 // will deny any more reader locks, in effect blocking all other send/receive
144 // threads. Once we have the lock, we set shutdownFlag to inform the other 434 // threads. Once we have the lock, we set shutdownFlag to inform the other
145 // threads that the socket is closed. 435 // threads that the socket is closed.
146 rwLock.AcquireWriterLock(-1);
147 shutdownFlag = true; 436 shutdownFlag = true;
148 udpSocket.Close(); 437 udpSocket.Close();
149 rwLock.ReleaseWriterLock();
150
151 // wait for any pending operations to complete on other
152 // threads before exiting.
153 const int FORCE_STOP = 100;
154 int i = 0;
155 while (rwOperationCount > 0 && i < FORCE_STOP)
156 {
157 Thread.Sleep(10);
158 ++i;
159 }
160
161 if (i >= FORCE_STOP)
162 {
163 Logger.Log("UDPBase.Stop() forced shutdown while waiting on pending operations",
164 Helpers.LogLevel.Warning);
165 }
166 } 438 }
167 } 439 }
168 440
@@ -176,20 +448,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
176 448
177 private void AsyncBeginReceive() 449 private void AsyncBeginReceive()
178 { 450 {
179 // this method actually kicks off the async read on the socket. 451 // allocate a packet buffer
180 // we aquire a reader lock here to ensure that no other thread 452 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
181 // is trying to set shutdownFlag and close the socket. 453 UDPPacketBuffer buf = new UDPPacketBuffer();
182 rwLock.AcquireReaderLock(-1);
183 454
184 if (!shutdownFlag) 455 if (!shutdownFlag)
185 { 456 {
186 // increment the count of pending operations
187 Interlocked.Increment(ref rwOperationCount);
188
189 // allocate a packet buffer
190 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
191 UDPPacketBuffer buf = new UDPPacketBuffer();
192
193 try 457 try
194 { 458 {
195 // kick off an async read 459 // kick off an async read
@@ -199,38 +463,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP
199 0, 463 0,
200 UDPPacketBuffer.BUFFER_SIZE, 464 UDPPacketBuffer.BUFFER_SIZE,
201 SocketFlags.None, 465 SocketFlags.None,
202 //ref wrappedBuffer.Instance.RemoteEndPoint,
203 ref buf.RemoteEndPoint, 466 ref buf.RemoteEndPoint,
204 new AsyncCallback(AsyncEndReceive), 467 AsyncEndReceive,
205 //wrappedBuffer); 468 //wrappedBuffer);
206 buf); 469 buf);
207 } 470 }
208 catch (SocketException) 471 catch (SocketException e)
209 { 472 {
210 // something bad happened 473 if (e.SocketErrorCode == SocketError.ConnectionReset)
211 //Logger.Log( 474 {
212 // "A SocketException occurred in UDPServer.AsyncBeginReceive()", 475 Logger.Log("SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + udpPort, Helpers.LogLevel.Error);
213 // Helpers.LogLevel.Error, se); 476 bool salvaged = false;
214 477 while (!salvaged)
215 // an error occurred, therefore the operation is void. Decrement the reference count. 478 {
216 Interlocked.Decrement(ref rwOperationCount); 479 try
480 {
481 udpSocket.BeginReceiveFrom(
482 //wrappedBuffer.Instance.Data,
483 buf.Data,
484 0,
485 UDPPacketBuffer.BUFFER_SIZE,
486 SocketFlags.None,
487 ref buf.RemoteEndPoint,
488 AsyncEndReceive,
489 //wrappedBuffer);
490 buf);
491 salvaged = true;
492 }
493 catch (SocketException) { }
494 catch (ObjectDisposedException) { return; }
495 }
496
497 Logger.Log("Salvaged the UDP listener on port " + udpPort, Helpers.LogLevel.Info);
498 }
217 } 499 }
500 catch (ObjectDisposedException) { }
218 } 501 }
219
220 // we're done with the socket for now, release the reader lock.
221 rwLock.ReleaseReaderLock();
222 } 502 }
223 503
224 private void AsyncEndReceive(IAsyncResult iar) 504 private void AsyncEndReceive(IAsyncResult iar)
225 { 505 {
226 // Asynchronous receive operations will complete here through the call 506 // Asynchronous receive operations will complete here through the call
227 // to AsyncBeginReceive 507 // to AsyncBeginReceive
228
229 // aquire a reader lock
230 rwLock.AcquireReaderLock(-1);
231
232 if (!shutdownFlag) 508 if (!shutdownFlag)
233 { 509 {
510 // start another receive - this keeps the server going!
511 AsyncBeginReceive();
512
234 // get the buffer that was created in AsyncBeginReceive 513 // get the buffer that was created in AsyncBeginReceive
235 // this is the received data 514 // this is the received data
236 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState; 515 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
@@ -243,98 +522,48 @@ namespace OpenSim.Region.ClientStack.LindenUDP
243 // buffer 522 // buffer
244 buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); 523 buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
245 524
246 // this operation is now complete, decrement the reference count
247 Interlocked.Decrement(ref rwOperationCount);
248
249 // we're done with the socket, release the reader lock
250 rwLock.ReleaseReaderLock();
251
252 // call the abstract method PacketReceived(), passing the buffer that 525 // call the abstract method PacketReceived(), passing the buffer that
253 // has just been filled from the socket read. 526 // has just been filled from the socket read.
254 PacketReceived(buffer); 527 PacketReceived(buffer);
255 } 528 }
256 catch (SocketException) 529 catch (SocketException) { }
257 { 530 catch (ObjectDisposedException) { }
258 // an error occurred, therefore the operation is void. Decrement the reference count. 531 //finally { wrappedBuffer.Dispose(); }
259 Interlocked.Decrement(ref rwOperationCount);
260
261 // we're done with the socket for now, release the reader lock.
262 rwLock.ReleaseReaderLock();
263 }
264 finally
265 {
266 // start another receive - this keeps the server going!
267 AsyncBeginReceive();
268
269 //wrappedBuffer.Dispose();
270 }
271 }
272 else
273 {
274 // nothing bad happened, but we are done with the operation
275 // decrement the reference count and release the reader lock
276 Interlocked.Decrement(ref rwOperationCount);
277 rwLock.ReleaseReaderLock();
278 } 532 }
279 } 533 }
280 534
281 public void AsyncBeginSend(UDPPacketBuffer buf) 535 public void AsyncBeginSend(UDPPacketBuffer buf)
282 { 536 {
283 rwLock.AcquireReaderLock(-1);
284
285 if (!shutdownFlag) 537 if (!shutdownFlag)
286 { 538 {
287 try 539 try
288 { 540 {
289 Interlocked.Increment(ref rwOperationCount);
290 udpSocket.BeginSendTo( 541 udpSocket.BeginSendTo(
291 buf.Data, 542 buf.Data,
292 0, 543 0,
293 buf.DataLength, 544 buf.DataLength,
294 SocketFlags.None, 545 SocketFlags.None,
295 buf.RemoteEndPoint, 546 buf.RemoteEndPoint,
296 new AsyncCallback(AsyncEndSend), 547 AsyncEndSend,
297 buf); 548 buf);
298 } 549 }
299 catch (SocketException) 550 catch (SocketException) { }
300 { 551 catch (ObjectDisposedException) { }
301 //Logger.Log(
302 // "A SocketException occurred in UDPServer.AsyncBeginSend()",
303 // Helpers.LogLevel.Error, se);
304 }
305 } 552 }
306
307 rwLock.ReleaseReaderLock();
308 } 553 }
309 554
310 private void AsyncEndSend(IAsyncResult iar) 555 void AsyncEndSend(IAsyncResult result)
311 { 556 {
312 rwLock.AcquireReaderLock(-1); 557 try
313
314 if (!shutdownFlag)
315 { 558 {
316 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 559 UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
317 560 int bytesSent = udpSocket.EndSendTo(result);
318 try
319 {
320 int bytesSent = udpSocket.EndSendTo(iar);
321 561
322 // note that call to the abstract PacketSent() method - we are passing the number 562 PacketSent(buf, bytesSent);
323 // of bytes sent in a separate parameter, since we can't use buffer.DataLength which
324 // is the number of bytes to send (or bytes received depending upon whether this
325 // buffer was part of a send or a receive).
326 PacketSent(buffer, bytesSent);
327 }
328 catch (SocketException)
329 {
330 //Logger.Log(
331 // "A SocketException occurred in UDPServer.AsyncEndSend()",
332 // Helpers.LogLevel.Error, se);
333 }
334 } 563 }
335 564 catch (SocketException) { }
336 Interlocked.Decrement(ref rwOperationCount); 565 catch (ObjectDisposedException) { }
337 rwLock.ReleaseReaderLock();
338 } 566 }
339 } 567 }
340} 568}
569