Added initial documentation tree using doxygen. More tweaks on the license text ensur...
[lwes-dotnet/github-mirror.git] / Org.Lwes / UdpEndpoint.cs
blobe6c2515e40e35280dc20d8da1232ca44cf95b2f5
1 //
2 // This file is part of the LWES .NET Binding (LWES.net)
3 //
4 // COPYRIGHT© 2009, Phillip Clark (cerebralkungfu[at*g mail[dot*com)
5 // original .NET implementation
6 //
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/>.
20 namespace Org.Lwes
22 using System;
23 using System.IO;
24 using System.Net;
25 using System.Net.Sockets;
27 /// <summary>
28 /// Encapsulates the state of an operation that occurred
29 /// in parallel on an EndPoint.
30 /// </summary>
31 internal struct EndPointOpState
33 #region Fields
35 internal Func<EndPointOpState, bool> Callback;
36 internal SocketAsyncEventArgs SocketArgs;
38 object _handback;
40 #endregion Fields
42 #region Constructors
44 internal EndPointOpState(SocketAsyncEventArgs args, Func<EndPointOpState, bool> cb, object hb)
46 SocketArgs = args;
47 Callback = cb;
48 _handback = hb;
51 #endregion Constructors
53 #region Properties
55 /// <summary>
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.
58 /// </summary>
59 public byte[] Buffer
61 get { return SocketArgs.Buffer; }
64 /// <summary>
65 /// Number of bytes used in the operation.
66 /// </summary>
67 public int BytesTransferred
69 get { return SocketArgs.BytesTransferred; }
72 /// <summary>
73 /// Handback object given by the initiator of the operation.
74 /// </summary>
75 public object Handback
77 get { return _handback; }
80 /// <summary>
81 /// Offset within the buffer where valid data begins. WARNING: May not be the beginning of the buffer.
82 /// </summary>
83 public int Offset
85 get { return SocketArgs.Offset; }
88 /// <summary>
89 /// Identifies the operation that was performed.
90 /// </summary>
91 /// <see cref="System.Net.Sockets.SocketAsyncOperation"/>
92 public SocketAsyncOperation Operation
94 get { return SocketArgs.LastOperation; }
97 /// <summary>
98 /// Identifies the remote side of the communication.
99 /// </summary>
100 public EndPoint RemoteEndPoint
102 get { return SocketArgs.RemoteEndPoint; }
105 /// <summary>
106 /// Identifies the socket error. NOTE: SocketError.Success indicates no error occurred!
107 /// </summary>
108 public SocketError SocketError
110 get { return SocketArgs.SocketError; }
113 #endregion Properties
116 /// <summary>
117 /// Socket endpoint adapter for working with UDP.
118 /// </summary>
119 internal class UdpEndpoint : IDisposable
121 #region Fields
123 IPEndPoint _endpoint;
124 Socket _socket;
126 #endregion Fields
128 #region Constructors
130 /// <summary>
131 /// Creates a new instance.
132 /// </summary>
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;
141 ~UdpEndpoint()
143 Dispose(false);
146 #endregion Constructors
148 #region Properties
150 public EndPoint EndPoint
152 get { return _endpoint; }
155 #endregion Properties
157 #region Methods
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
168 , state.Callback
169 , state.Handback
171 return;
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
184 , state.Callback
185 , state.Handback
187 return;
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
200 , state.Callback
201 , state.Handback
203 return;
207 public void Dispose()
209 Dispose(true);
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);
219 return this;
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.
237 if (callback != null
238 && callback(new EndPointOpState(args
239 , callback
240 , handback
241 ))) return;
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.
281 if (callback != null
282 && callback(new EndPointOpState(args
283 , callback
284 , handback
285 ))) return;
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)))
298 return;
302 private void Dispose(bool disposing)
304 if (_socket != null)
306 if (_socket.Connected)
310 _socket.Close();
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);
323 return args;
326 #endregion Methods
328 #region Nested Types
330 class Completion
332 #region Fields
334 public Func<EndPointOpState, bool> Callback;
335 public Object Handback;
337 #endregion Fields
339 #region Constructors
341 internal Completion(Func<EndPointOpState, bool> cb, Object hb)
343 Callback = cb;
344 Handback = hb;
347 #endregion Constructors
350 #endregion Nested Types