2 // This file is part of the LWES .NET Binding (LWES.net)
4 // COPYRIGHT© 2009, Phillip Clark (phillip[at*flitbit[dot*org)
5 // original .NET implementation
7 // LWES.net is free software: you can redistribute it and/or modify
8 // it under the terms of the Lesser GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
12 // LWES.net is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // Lesser GNU General Public License for more details.
17 // You should have received a copy of the Lesser GNU General Public License
18 // along with LWES.net. If not, see <http://www.gnu.org/licenses/>.
25 using System
.Net
.Sockets
;
28 /// Encapsulates the state of an operation that occurred
29 /// in parallel on an EndPoint.
31 internal struct EndPointOpState
35 internal Func
<EndPointOpState
, bool> Callback
;
36 internal SocketAsyncEventArgs SocketArgs
;
44 internal EndPointOpState(SocketAsyncEventArgs args
, Func
<EndPointOpState
, bool> cb
, object hb
)
51 #endregion Constructors
56 /// Accesses the raw byte buffer containing data. For SendXXX operations this
57 /// is the data sent; for ReceiveXXX operations this is the data received.
61 get { return SocketArgs.Buffer; }
65 /// Number of bytes used in the operation.
67 public int BytesTransferred
69 get { return SocketArgs.BytesTransferred; }
73 /// Handback object given by the initiator of the operation.
75 public object Handback
77 get { return _handback; }
81 /// Offset within the buffer where valid data begins. WARNING: May not be the beginning of the buffer.
85 get { return SocketArgs.Offset; }
89 /// Identifies the operation that was performed.
91 /// <see cref="System.Net.Sockets.SocketAsyncOperation"/>
92 public SocketAsyncOperation Operation
94 get { return SocketArgs.LastOperation; }
98 /// Identifies the remote side of the communication.
100 public EndPoint RemoteEndPoint
102 get { return SocketArgs.RemoteEndPoint; }
106 /// Identifies the socket error. NOTE: SocketError.Success indicates no error occurred!
108 public SocketError SocketError
110 get { return SocketArgs.SocketError; }
113 #endregion Properties
117 /// Socket endpoint adapter for working with UDP.
119 internal class UdpEndpoint
: IDisposable
123 IPEndPoint _endpoint
;
131 /// Creates a new instance.
133 /// <param name="endpoint">endpoint to be adapted</param>
134 public UdpEndpoint(IPEndPoint endpoint
)
136 if (endpoint
== null) throw new ArgumentNullException("endpoint");
138 _endpoint
= endpoint
;
146 #endregion Constructors
150 public EndPoint EndPoint
152 get { return _endpoint; }
155 #endregion Properties
159 public void ContinueReceiveFromAsync(EndPointOpState state
, int offset
, int count
)
161 state
.SocketArgs
.SetBuffer(state
.SocketArgs
.Buffer
, offset
, count
);
162 if (!_socket
.ReceiveFromAsync(state
.SocketArgs
))
164 // If the callback reuses the args (indicated by return value of true)
165 // then we return without queuing the args.
166 if (state
.Callback
!= null
167 && state
.Callback(new EndPointOpState(state
.SocketArgs
175 public void ContinueReceiveFromAsync(EndPointOpState state
, byte[] buffer
)
177 state
.SocketArgs
.SetBuffer(buffer
, 0, buffer
.Length
);
178 if (!_socket
.ReceiveFromAsync(state
.SocketArgs
))
180 // If the callback reuses the args (indicated by return value of true)
181 // then we return without queuing the args.
182 if (state
.Callback
!= null
183 && state
.Callback(new EndPointOpState(state
.SocketArgs
191 public void ContinueSendToAsync(EndPointOpState state
, int offset
, int count
)
193 state
.SocketArgs
.SetBuffer(state
.SocketArgs
.Buffer
, offset
, count
);
194 if (!_socket
.SendToAsync(state
.SocketArgs
))
196 // If the callback reuses the args (indicated by return value of true)
197 // then we return without queuing the args.
198 if (state
.Callback
!= null
199 && state
.Callback(new EndPointOpState(state
.SocketArgs
207 public void Dispose()
210 GC
.SuppressFinalize(this);
213 public UdpEndpoint
Initialize(Action
<Socket
, IPEndPoint
> finishSocket
)
215 if (finishSocket
== null) throw new ArgumentNullException("finishSocket");
217 _socket
= new Socket(_endpoint
.AddressFamily
, SocketType
.Dgram
, ProtocolType
.Udp
);
218 finishSocket(_socket
, _endpoint
);
222 public int ReceiveFrom(ref EndPoint endpoint
, byte[] data
, int offset
, int count
)
224 return _socket
.ReceiveFrom(data
, offset
, count
, SocketFlags
.None
, ref endpoint
);
227 public void ReceiveFromAsync(EndPoint endpoint
, byte[] data
, int offset
, int count
, Func
<EndPointOpState
, bool> callback
, object handback
)
229 SocketAsyncEventArgs args
= InitArgs();
230 args
.RemoteEndPoint
= endpoint
;
231 args
.SetBuffer(data
, offset
, count
);
232 args
.UserToken
= new Completion(callback
, handback
);
233 if (!_socket
.ReceiveFromAsync(args
))
235 // If the callback reuses the args (indicated by return value of true)
236 // then we return without queuing the args.
238 && callback(new EndPointOpState(args
246 public void SendTo(EndPoint endpoint
, byte[] data
)
248 _socket
.SendTo(data
, endpoint
);
251 public void SendTo(EndPoint endpoint
, byte[] data
, int count
)
253 _socket
.SendTo(data
, count
, SocketFlags
.None
, endpoint
);
256 public void SendTo(EndPoint endpoint
, byte[] data
, int offset
, int count
, SocketFlags flags
)
258 _socket
.SendTo(data
, offset
, count
, flags
, endpoint
);
261 public void SendToAsync(EndPoint endpoint
, byte[] data
, int count
, Func
<EndPointOpState
, bool> callback
)
263 SendToAsync(endpoint
, data
, 0, count
, callback
, null);
266 public void SendToAsync(EndPoint endpoint
, byte[] data
, int count
, Func
<EndPointOpState
, bool> callback
, object handback
)
268 SendToAsync(endpoint
, data
, 0, count
, callback
, handback
);
271 public void SendToAsync(EndPoint endpoint
, byte[] data
, int offset
, int count
, Func
<EndPointOpState
, bool> callback
, object handback
)
273 SocketAsyncEventArgs args
= InitArgs();
274 args
.RemoteEndPoint
= endpoint
;
275 args
.SetBuffer(data
, offset
, count
);
276 args
.UserToken
= new Completion(callback
, handback
);
277 if (!_socket
.SendToAsync(args
))
279 // If the callback reuses the args (indicated by return value of true)
280 // then we return without queuing the args.
282 && callback(new EndPointOpState(args
290 void BackgroundCompletedCallback(object sender
, SocketAsyncEventArgs e
)
292 Completion c
= (Completion
)e
.UserToken
;
293 if (c
.Callback
!= null)
295 // If the callback reuses the args (indicated by return value of true)
296 // then we return without queuing the args.
297 if (!c
.Callback(new EndPointOpState(e
, c
.Callback
, c
.Handback
)))
302 private void Dispose(bool disposing
)
306 if (_socket
.Connected
)
312 catch (IOException
) { /* error eaten on purpose; may be called from the GC */ }
315 Util
.Dispose(ref _socket
);
319 private SocketAsyncEventArgs
InitArgs()
321 SocketAsyncEventArgs args
= new SocketAsyncEventArgs();
322 args
.Completed
+= new EventHandler
<SocketAsyncEventArgs
>(BackgroundCompletedCallback
);
334 public Func
<EndPointOpState
, bool> Callback
;
335 public Object Handback
;
341 internal Completion(Func
<EndPointOpState
, bool> cb
, Object hb
)
347 #endregion Constructors
350 #endregion Nested Types