1 // System.Net.Sockets.SocketAsyncEventArgs.cs
4 // Marek Habersack (mhabersack@novell.com)
6 // Copyright (c) 2008 Novell, Inc. (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections.Generic;
32 using System.Threading;
34 namespace System.Net.Sockets
36 public class SocketAsyncEventArgs : EventArgs, IDisposable
38 public event EventHandler<SocketAsyncEventArgs> Completed;
40 IList <ArraySegment <byte>> _bufferList;
42 public Socket AcceptSocket { get; set; }
43 public byte[] Buffer { get; private set; }
45 public IList<ArraySegment<byte>> BufferList {
46 get { return _bufferList; }
49 throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null.");
54 public int BytesTransferred { get; private set; }
55 public int Count { get; private set; }
56 public bool DisconnectReuseSocket { get; set; }
57 public SocketAsyncOperation LastOperation { get; private set; }
58 public int Offset { get; private set; }
59 public IPPacketInformation ReceiveMessageFromPacketInfo { get; private set; }
60 public EndPoint RemoteEndPoint { get; set; }
61 public SendPacketsElement[] SendPacketsElements { get; set; }
62 public TransmitFileOptions SendPacketsFlags { get; set; }
63 public int SendPacketsSendSize { get; set; }
64 public SocketError SocketError { get; set; }
65 public SocketFlags SocketFlags { get; set; }
66 public object UserToken { get; set; }
70 public SocketAsyncEventArgs ()
77 DisconnectReuseSocket = false;
78 LastOperation = SocketAsyncOperation.None;
80 RemoteEndPoint = null;
81 SendPacketsElements = null;
82 SendPacketsFlags = TransmitFileOptions.UseDefaultWorkerThread;
83 SendPacketsSendSize = 0;
84 SocketError = SocketError.Success;
85 SocketFlags = SocketFlags.None;
89 ~SocketAsyncEventArgs ()
94 void Dispose (bool disposing)
96 Socket acceptSocket = AcceptSocket;
97 if (acceptSocket != null)
98 acceptSocket.Close ();
101 GC.SuppressFinalize (this);
104 void IDisposable.Dispose ()
109 protected virtual void OnCompleted (SocketAsyncEventArgs e)
114 if (e.Completed != null)
115 e.Completed (e.curSocket, e);
118 public void SetBuffer (int offset, int count)
120 SetBufferInternal (Buffer, offset, count);
123 public void SetBuffer (byte[] buffer, int offset, int count)
125 SetBufferInternal (buffer, offset, count);
128 void SetBufferInternal (byte[] buffer, int offset, int count)
130 if (buffer != null) {
131 if (BufferList != null)
132 throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null.");
134 int buflen = buffer.Length;
135 if (offset < 0 || offset >= buflen)
136 throw new ArgumentOutOfRangeException ("offset");
138 if (count < 0 || count + offset > buflen)
139 throw new ArgumentOutOfRangeException ("count");
148 void AcceptCallback ()
150 SocketError = SocketError.Success;
151 LastOperation = SocketAsyncOperation.Accept;
153 curSocket.Accept (AcceptSocket);
154 } catch (SocketException ex) {
155 SocketError = ex.SocketErrorCode;
162 void ReceiveCallback ()
164 SocketError = SocketError.Success;
165 LastOperation = SocketAsyncOperation.Receive;
166 SocketError error = SocketError.Success;
169 BytesTransferred = curSocket.Receive_nochecks (Buffer, Offset, Count, SocketFlags, out error);
176 void ConnectCallback ()
178 SocketError = SocketError.Success;
179 LastOperation = SocketAsyncOperation.Connect;
180 SocketError error = SocketError.Success;
183 if (!curSocket.Blocking) {
185 curSocket.Poll (-1, SelectMode.SelectWrite, out success);
186 SocketError = (SocketError)success;
188 curSocket.Connected = true;
192 curSocket.seed_endpoint = RemoteEndPoint;
193 curSocket.Connect (RemoteEndPoint);
194 curSocket.Connected = true;
196 } catch (SocketException se){
197 error = se.SocketErrorCode;
206 SocketError = SocketError.Success;
207 LastOperation = SocketAsyncOperation.Send;
208 SocketError error = SocketError.Success;
211 BytesTransferred = curSocket.Send_nochecks (Buffer, Offset, Count, SocketFlags.None, out error);
218 void DisconnectCallback ()
220 SocketError = SocketError.Success;
221 LastOperation = SocketAsyncOperation.Disconnect;
224 curSocket.Disconnect (DisconnectReuseSocket);
225 } catch (SocketException ex) {
226 SocketError = ex.SocketErrorCode;
233 void ReceiveFromCallback ()
235 SocketError = SocketError.Success;
236 LastOperation = SocketAsyncOperation.ReceiveFrom;
239 EndPoint ep = RemoteEndPoint;
240 BytesTransferred = curSocket.ReceiveFrom_nochecks (Buffer, Offset, Count, SocketFlags, ref ep);
241 } catch (SocketException ex) {
242 SocketError = ex.SocketErrorCode;
249 void SendToCallback ()
251 SocketError = SocketError.Success;
252 LastOperation = SocketAsyncOperation.SendTo;
258 while (total < count)
259 total += curSocket.SendTo_nochecks (Buffer, Offset, count, SocketFlags, RemoteEndPoint);
260 BytesTransferred = total;
261 } catch (SocketException ex) {
262 SocketError = ex.SocketErrorCode;
269 internal void DoOperation (SocketAsyncOperation operation, Socket socket)
271 ThreadStart callback;
275 case SocketAsyncOperation.Accept:
276 callback = new ThreadStart (AcceptCallback);
279 case SocketAsyncOperation.Receive:
280 callback = new ThreadStart (ReceiveCallback);
283 case SocketAsyncOperation.Connect:
284 callback = new ThreadStart (ConnectCallback);
287 case SocketAsyncOperation.Disconnect:
288 callback = new ThreadStart (DisconnectCallback);
291 case SocketAsyncOperation.ReceiveFrom:
292 callback = new ThreadStart (ReceiveFromCallback);
295 case SocketAsyncOperation.Send:
296 callback = new ThreadStart (SendCallback);
299 case SocketAsyncOperation.SendTo:
300 callback = new ThreadStart (SendToCallback);
304 throw new NotSupportedException ();
307 Thread t = new Thread (callback);
308 t.IsBackground = true;