aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs18
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs680
2 files changed, 349 insertions, 349 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
index f6ccf01..dbb9861 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
@@ -224,16 +224,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
224 224
225 ////return success; 225 ////return success;
226 226
227 //lock (m_sync) 227 lock (m_sync)
228 // return Dictionary1.TryGetValue(key, out value); 228 return Dictionary1.TryGetValue(key, out value);
229 229
230 try 230 //try
231 { 231 //{
232 return Dictionary1.TryGetValue(key, out value); 232 // return Dictionary1.TryGetValue(key, out value);
233 } 233 //}
234 catch { } 234 //catch { }
235 value = null; 235 //value = null;
236 return false; 236 //return false;
237 } 237 }
238 238
239 public bool TryGetValue(IPEndPoint key, out LLUDPClient value) 239 public bool TryGetValue(IPEndPoint key, out LLUDPClient value)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
index aaefbc6..218aaac 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
@@ -1,340 +1,340 @@
1/* 1/*
2 * Copyright (c) 2006, Clutch, Inc. 2 * Copyright (c) 2006, Clutch, Inc.
3 * Original Author: Jeff Cesnik 3 * Original Author: Jeff Cesnik
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * - Redistribution and use in source and binary forms, with or without 6 * - Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 7 * modification, are permitted provided that the following conditions are met:
8 * 8 *
9 * - Redistributions of source code must retain the above copyright notice, this 9 * - Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer. 10 * list of conditions and the following disclaimer.
11 * - Neither the name of the openmetaverse.org nor the names 11 * - Neither the name of the openmetaverse.org nor the names
12 * of its contributors may be used to endorse or promote products derived from 12 * of its contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission. 13 * this software without specific prior written permission.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE. 25 * POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Net; 29using System.Net;
30using System.Net.Sockets; 30using System.Net.Sockets;
31using System.Threading; 31using System.Threading;
32using OpenMetaverse; 32using OpenMetaverse;
33 33
34namespace OpenSim.Region.ClientStack.LindenUDP 34namespace OpenSim.Region.ClientStack.LindenUDP
35{ 35{
36 /// <summary> 36 /// <summary>
37 /// 37 ///
38 /// </summary> 38 /// </summary>
39 public abstract class OpenSimUDPBase 39 public abstract class OpenSimUDPBase
40 { 40 {
41 // these abstract methods must be implemented in a derived class to actually do 41 // these abstract methods must be implemented in a derived class to actually do
42 // something with the packets that are sent and received. 42 // something with the packets that are sent and received.
43 protected abstract void PacketReceived(UDPPacketBuffer buffer); 43 protected abstract void PacketReceived(UDPPacketBuffer buffer);
44 protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent); 44 protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent);
45 45
46 // the port to listen on 46 // the port to listen on
47 internal int udpPort; 47 internal int udpPort;
48 48
49 // the UDP socket 49 // the UDP socket
50 private Socket udpSocket; 50 private Socket udpSocket;
51 51
52 // the ReaderWriterLock is used solely for the purposes of shutdown (Stop()). 52 // the ReaderWriterLock is used solely for the purposes of shutdown (Stop()).
53 // since there are potentially many "reader" threads in the internal .NET IOCP 53 // since there are potentially many "reader" threads in the internal .NET IOCP
54 // thread pool, this is a cheaper synchronization primitive than using 54 // thread pool, this is a cheaper synchronization primitive than using
55 // a Mutex object. This allows many UDP socket "reads" concurrently - when 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 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. 57 // wait until all outstanding operations are completed before shutting down.
58 // this avoids the problem of closing the socket with outstanding operations 58 // this avoids the problem of closing the socket with outstanding operations
59 // and trying to catch the inevitable ObjectDisposedException. 59 // and trying to catch the inevitable ObjectDisposedException.
60 private ReaderWriterLock rwLock = new ReaderWriterLock(); 60 private ReaderWriterLock rwLock = new ReaderWriterLock();
61 61
62 // number of outstanding operations. This is a reference count 62 // number of outstanding operations. This is a reference count
63 // which we use to ensure that the threads exit cleanly. Note that 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 64 // we need this because the threads will potentially still need to process
65 // data even after the socket is closed. 65 // data even after the socket is closed.
66 private int rwOperationCount = 0; 66 private int rwOperationCount = 0;
67 67
68 // the all important shutdownFlag. This is synchronized through the ReaderWriterLock. 68 // the all important shutdownFlag. This is synchronized through the ReaderWriterLock.
69 private volatile bool shutdownFlag = true; 69 private volatile bool shutdownFlag = true;
70 70
71 // the remote endpoint to communicate with 71 // the remote endpoint to communicate with
72 protected IPEndPoint remoteEndPoint = null; 72 protected IPEndPoint remoteEndPoint = null;
73 73
74 74
75 /// <summary> 75 /// <summary>
76 /// Initialize the UDP packet handler in server mode 76 /// Initialize the UDP packet handler in server mode
77 /// </summary> 77 /// </summary>
78 /// <param name="port">Port to listening for incoming UDP packets on</param> 78 /// <param name="port">Port to listening for incoming UDP packets on</param>
79 public OpenSimUDPBase(int port) 79 public OpenSimUDPBase(int port)
80 { 80 {
81 udpPort = port; 81 udpPort = port;
82 } 82 }
83 83
84 /// <summary> 84 /// <summary>
85 /// Initialize the UDP packet handler in client mode 85 /// Initialize the UDP packet handler in client mode
86 /// </summary> 86 /// </summary>
87 /// <param name="endPoint">Remote UDP server to connect to</param> 87 /// <param name="endPoint">Remote UDP server to connect to</param>
88 public OpenSimUDPBase(IPEndPoint endPoint) 88 public OpenSimUDPBase(IPEndPoint endPoint)
89 { 89 {
90 remoteEndPoint = endPoint; 90 remoteEndPoint = endPoint;
91 udpPort = 0; 91 udpPort = 0;
92 } 92 }
93 93
94 /// <summary> 94 /// <summary>
95 /// 95 ///
96 /// </summary> 96 /// </summary>
97 public void Start() 97 public void Start()
98 { 98 {
99 if (shutdownFlag) 99 if (shutdownFlag)
100 { 100 {
101 if (remoteEndPoint == null) 101 if (remoteEndPoint == null)
102 { 102 {
103 // Server mode 103 // Server mode
104 104
105 // create and bind the socket 105 // create and bind the socket
106 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort); 106 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
107 udpSocket = new Socket( 107 udpSocket = new Socket(
108 AddressFamily.InterNetwork, 108 AddressFamily.InterNetwork,
109 SocketType.Dgram, 109 SocketType.Dgram,
110 ProtocolType.Udp); 110 ProtocolType.Udp);
111 udpSocket.Bind(ipep); 111 udpSocket.Bind(ipep);
112 } 112 }
113 else 113 else
114 { 114 {
115 // Client mode 115 // Client mode
116 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort); 116 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
117 udpSocket = new Socket( 117 udpSocket = new Socket(
118 AddressFamily.InterNetwork, 118 AddressFamily.InterNetwork,
119 SocketType.Dgram, 119 SocketType.Dgram,
120 ProtocolType.Udp); 120 ProtocolType.Udp);
121 udpSocket.Bind(ipep); 121 udpSocket.Bind(ipep);
122 //udpSocket.Connect(remoteEndPoint); 122 //udpSocket.Connect(remoteEndPoint);
123 } 123 }
124 124
125 // we're not shutting down, we're starting up 125 // we're not shutting down, we're starting up
126 shutdownFlag = false; 126 shutdownFlag = false;
127 127
128 // kick off an async receive. The Start() method will return, the 128 // kick off an async receive. The Start() method will return, the
129 // actual receives will occur asynchronously and will be caught in 129 // actual receives will occur asynchronously and will be caught in
130 // AsyncEndRecieve(). 130 // AsyncEndRecieve().
131 AsyncBeginReceive(); 131 AsyncBeginReceive();
132 } 132 }
133 } 133 }
134 134
135 /// <summary> 135 /// <summary>
136 /// 136 ///
137 /// </summary> 137 /// </summary>
138 public void Stop() 138 public void Stop()
139 { 139 {
140 if (!shutdownFlag) 140 if (!shutdownFlag)
141 { 141 {
142 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 142 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
143 // will deny any more reader locks, in effect blocking all other send/receive 143 // 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 144 // threads. Once we have the lock, we set shutdownFlag to inform the other
145 // threads that the socket is closed. 145 // threads that the socket is closed.
146 rwLock.AcquireWriterLock(-1); 146 rwLock.AcquireWriterLock(-1);
147 shutdownFlag = true; 147 shutdownFlag = true;
148 udpSocket.Close(); 148 udpSocket.Close();
149 rwLock.ReleaseWriterLock(); 149 rwLock.ReleaseWriterLock();
150 150
151 // wait for any pending operations to complete on other 151 // wait for any pending operations to complete on other
152 // threads before exiting. 152 // threads before exiting.
153 const int FORCE_STOP = 100; 153 const int FORCE_STOP = 100;
154 int i = 0; 154 int i = 0;
155 while (rwOperationCount > 0 && i < FORCE_STOP) 155 while (rwOperationCount > 0 && i < FORCE_STOP)
156 { 156 {
157 Thread.Sleep(10); 157 Thread.Sleep(10);
158 ++i; 158 ++i;
159 } 159 }
160 160
161 if (i >= FORCE_STOP) 161 if (i >= FORCE_STOP)
162 { 162 {
163 Logger.Log("UDPBase.Stop() forced shutdown while waiting on pending operations", 163 Logger.Log("UDPBase.Stop() forced shutdown while waiting on pending operations",
164 Helpers.LogLevel.Warning); 164 Helpers.LogLevel.Warning);
165 } 165 }
166 } 166 }
167 } 167 }
168 168
169 /// <summary> 169 /// <summary>
170 /// 170 ///
171 /// </summary> 171 /// </summary>
172 public bool IsRunning 172 public bool IsRunning
173 { 173 {
174 get { return !shutdownFlag; } 174 get { return !shutdownFlag; }
175 } 175 }
176 176
177 private void AsyncBeginReceive() 177 private void AsyncBeginReceive()
178 { 178 {
179 // this method actually kicks off the async read on the socket. 179 // this method actually kicks off the async read on the socket.
180 // we aquire a reader lock here to ensure that no other thread 180 // we aquire a reader lock here to ensure that no other thread
181 // is trying to set shutdownFlag and close the socket. 181 // is trying to set shutdownFlag and close the socket.
182 rwLock.AcquireReaderLock(-1); 182 rwLock.AcquireReaderLock(-1);
183 183
184 if (!shutdownFlag) 184 if (!shutdownFlag)
185 { 185 {
186 // increment the count of pending operations 186 // increment the count of pending operations
187 Interlocked.Increment(ref rwOperationCount); 187 Interlocked.Increment(ref rwOperationCount);
188 188
189 // allocate a packet buffer 189 // allocate a packet buffer
190 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); 190 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
191 UDPPacketBuffer buf = new UDPPacketBuffer(); 191 UDPPacketBuffer buf = new UDPPacketBuffer();
192 192
193 try 193 try
194 { 194 {
195 // kick off an async read 195 // kick off an async read
196 udpSocket.BeginReceiveFrom( 196 udpSocket.BeginReceiveFrom(
197 //wrappedBuffer.Instance.Data, 197 //wrappedBuffer.Instance.Data,
198 buf.Data, 198 buf.Data,
199 0, 199 0,
200 UDPPacketBuffer.BUFFER_SIZE, 200 UDPPacketBuffer.BUFFER_SIZE,
201 SocketFlags.None, 201 SocketFlags.None,
202 //ref wrappedBuffer.Instance.RemoteEndPoint, 202 //ref wrappedBuffer.Instance.RemoteEndPoint,
203 ref buf.RemoteEndPoint, 203 ref buf.RemoteEndPoint,
204 new AsyncCallback(AsyncEndReceive), 204 new AsyncCallback(AsyncEndReceive),
205 //wrappedBuffer); 205 //wrappedBuffer);
206 buf); 206 buf);
207 } 207 }
208 catch (SocketException) 208 catch (SocketException)
209 { 209 {
210 // something bad happened 210 // something bad happened
211 //Logger.Log( 211 //Logger.Log(
212 // "A SocketException occurred in UDPServer.AsyncBeginReceive()", 212 // "A SocketException occurred in UDPServer.AsyncBeginReceive()",
213 // Helpers.LogLevel.Error, se); 213 // Helpers.LogLevel.Error, se);
214 214
215 // an error occurred, therefore the operation is void. Decrement the reference count. 215 // an error occurred, therefore the operation is void. Decrement the reference count.
216 Interlocked.Decrement(ref rwOperationCount); 216 Interlocked.Decrement(ref rwOperationCount);
217 } 217 }
218 } 218 }
219 219
220 // we're done with the socket for now, release the reader lock. 220 // we're done with the socket for now, release the reader lock.
221 rwLock.ReleaseReaderLock(); 221 rwLock.ReleaseReaderLock();
222 } 222 }
223 223
224 private void AsyncEndReceive(IAsyncResult iar) 224 private void AsyncEndReceive(IAsyncResult iar)
225 { 225 {
226 // Asynchronous receive operations will complete here through the call 226 // Asynchronous receive operations will complete here through the call
227 // to AsyncBeginReceive 227 // to AsyncBeginReceive
228 228
229 // aquire a reader lock 229 // aquire a reader lock
230 rwLock.AcquireReaderLock(-1); 230 rwLock.AcquireReaderLock(-1);
231 231
232 if (!shutdownFlag) 232 if (!shutdownFlag)
233 { 233 {
234 // get the buffer that was created in AsyncBeginReceive 234 // get the buffer that was created in AsyncBeginReceive
235 // this is the received data 235 // this is the received data
236 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState; 236 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
237 //UDPPacketBuffer buffer = wrappedBuffer.Instance; 237 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
238 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 238 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
239 239
240 try 240 try
241 { 241 {
242 // get the length of data actually read from the socket, store it with the 242 // get the length of data actually read from the socket, store it with the
243 // buffer 243 // buffer
244 buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); 244 buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
245 245
246 // this operation is now complete, decrement the reference count 246 // this operation is now complete, decrement the reference count
247 Interlocked.Decrement(ref rwOperationCount); 247 Interlocked.Decrement(ref rwOperationCount);
248 248
249 // we're done with the socket, release the reader lock 249 // we're done with the socket, release the reader lock
250 rwLock.ReleaseReaderLock(); 250 rwLock.ReleaseReaderLock();
251 251
252 // call the abstract method PacketReceived(), passing the buffer that 252 // call the abstract method PacketReceived(), passing the buffer that
253 // has just been filled from the socket read. 253 // has just been filled from the socket read.
254 PacketReceived(buffer); 254 PacketReceived(buffer);
255 } 255 }
256 catch (SocketException) 256 catch (SocketException)
257 { 257 {
258 // an error occurred, therefore the operation is void. Decrement the reference count. 258 // an error occurred, therefore the operation is void. Decrement the reference count.
259 Interlocked.Decrement(ref rwOperationCount); 259 Interlocked.Decrement(ref rwOperationCount);
260 260
261 // we're done with the socket for now, release the reader lock. 261 // we're done with the socket for now, release the reader lock.
262 rwLock.ReleaseReaderLock(); 262 rwLock.ReleaseReaderLock();
263 } 263 }
264 finally 264 finally
265 { 265 {
266 // start another receive - this keeps the server going! 266 // start another receive - this keeps the server going!
267 AsyncBeginReceive(); 267 AsyncBeginReceive();
268 268
269 //wrappedBuffer.Dispose(); 269 //wrappedBuffer.Dispose();
270 } 270 }
271 } 271 }
272 else 272 else
273 { 273 {
274 // nothing bad happened, but we are done with the operation 274 // nothing bad happened, but we are done with the operation
275 // decrement the reference count and release the reader lock 275 // decrement the reference count and release the reader lock
276 Interlocked.Decrement(ref rwOperationCount); 276 Interlocked.Decrement(ref rwOperationCount);
277 rwLock.ReleaseReaderLock(); 277 rwLock.ReleaseReaderLock();
278 } 278 }
279 } 279 }
280 280
281 public void AsyncBeginSend(UDPPacketBuffer buf) 281 public void AsyncBeginSend(UDPPacketBuffer buf)
282 { 282 {
283 rwLock.AcquireReaderLock(-1); 283 rwLock.AcquireReaderLock(-1);
284 284
285 if (!shutdownFlag) 285 if (!shutdownFlag)
286 { 286 {
287 try 287 try
288 { 288 {
289 Interlocked.Increment(ref rwOperationCount); 289 Interlocked.Increment(ref rwOperationCount);
290 udpSocket.BeginSendTo( 290 udpSocket.BeginSendTo(
291 buf.Data, 291 buf.Data,
292 0, 292 0,
293 buf.DataLength, 293 buf.DataLength,
294 SocketFlags.None, 294 SocketFlags.None,
295 buf.RemoteEndPoint, 295 buf.RemoteEndPoint,
296 new AsyncCallback(AsyncEndSend), 296 new AsyncCallback(AsyncEndSend),
297 buf); 297 buf);
298 } 298 }
299 catch (SocketException) 299 catch (SocketException)
300 { 300 {
301 //Logger.Log( 301 //Logger.Log(
302 // "A SocketException occurred in UDPServer.AsyncBeginSend()", 302 // "A SocketException occurred in UDPServer.AsyncBeginSend()",
303 // Helpers.LogLevel.Error, se); 303 // Helpers.LogLevel.Error, se);
304 } 304 }
305 } 305 }
306 306
307 rwLock.ReleaseReaderLock(); 307 rwLock.ReleaseReaderLock();
308 } 308 }
309 309
310 private void AsyncEndSend(IAsyncResult iar) 310 private void AsyncEndSend(IAsyncResult iar)
311 { 311 {
312 rwLock.AcquireReaderLock(-1); 312 rwLock.AcquireReaderLock(-1);
313 313
314 if (!shutdownFlag) 314 if (!shutdownFlag)
315 { 315 {
316 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 316 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
317 317
318 try 318 try
319 { 319 {
320 int bytesSent = udpSocket.EndSendTo(iar); 320 int bytesSent = udpSocket.EndSendTo(iar);
321 321
322 // note that call to the abstract PacketSent() method - we are passing the number 322 // note that call to the abstract PacketSent() method - we are passing the number
323 // of bytes sent in a separate parameter, since we can't use buffer.DataLength which 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 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). 325 // buffer was part of a send or a receive).
326 PacketSent(buffer, bytesSent); 326 PacketSent(buffer, bytesSent);
327 } 327 }
328 catch (SocketException) 328 catch (SocketException)
329 { 329 {
330 //Logger.Log( 330 //Logger.Log(
331 // "A SocketException occurred in UDPServer.AsyncEndSend()", 331 // "A SocketException occurred in UDPServer.AsyncEndSend()",
332 // Helpers.LogLevel.Error, se); 332 // Helpers.LogLevel.Error, se);
333 } 333 }
334 } 334 }
335 335
336 Interlocked.Decrement(ref rwOperationCount); 336 Interlocked.Decrement(ref rwOperationCount);
337 rwLock.ReleaseReaderLock(); 337 rwLock.ReleaseReaderLock();
338 } 338 }
339 } 339 }
340} 340}