Fixed few warnings
[mono.git] / mcs / class / System / System.Net.Sockets / SocketAsyncEventArgs.cs
1 // System.Net.Sockets.SocketAsyncEventArgs.cs
2 //
3 // Authors:
4 //      Marek Habersack (mhabersack@novell.com)
5 //
6 // Copyright (c) 2008 Novell, Inc. (http://www.novell.com)
7 //
8
9 //
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:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
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.
28 //
29 #if NET_2_0
30 using System;
31 using System.Collections.Generic;
32 using System.Threading;
33
34 namespace System.Net.Sockets
35 {
36         public class SocketAsyncEventArgs : EventArgs, IDisposable
37         {
38                 public event EventHandler<SocketAsyncEventArgs> Completed;
39
40                 IList <ArraySegment <byte>> _bufferList;
41                 
42                 public Socket AcceptSocket { get; set; }
43                 public byte[] Buffer { get; private set; }
44
45                 public IList<ArraySegment<byte>> BufferList {
46                         get { return _bufferList; }
47                         set {
48                                 if (Buffer != null)
49                                         throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null.");
50                                 _bufferList = value;
51                         }
52                 }
53
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; }
67
68                 Socket curSocket;
69                 
70                 public SocketAsyncEventArgs ()
71                 {
72                         AcceptSocket = null;
73                         Buffer = null;
74                         BufferList = null;
75                         BytesTransferred = 0;
76                         Count = 0;
77                         DisconnectReuseSocket = false;
78                         LastOperation = SocketAsyncOperation.None;
79                         Offset = 0;
80                         RemoteEndPoint = null;
81                         SendPacketsElements = null;
82                         SendPacketsFlags = TransmitFileOptions.UseDefaultWorkerThread;
83                         SendPacketsSendSize = 0;
84                         SocketError = SocketError.Success;
85                         SocketFlags = SocketFlags.None;
86                         UserToken = null;
87                 }
88
89                 ~SocketAsyncEventArgs ()
90                 {
91                         Dispose (false);
92                 }
93
94                 void Dispose (bool disposing)
95                 {
96                         Socket acceptSocket = AcceptSocket;
97                         if (acceptSocket != null)
98                                 acceptSocket.Close ();
99
100                         if (disposing)
101                                 GC.SuppressFinalize (this);
102                 }               
103
104                 void IDisposable.Dispose ()
105                 {
106                         Dispose (true);
107                 }
108                 
109                 protected virtual void OnCompleted (SocketAsyncEventArgs e)
110                 {
111                         if (e == null)
112                                 return;
113                         
114                         if (e.Completed != null)
115                                 e.Completed (e.curSocket, e);
116                 }
117
118                 public void SetBuffer (int offset, int count)
119                 {
120                         SetBufferInternal (Buffer, offset, count);
121                 }
122
123                 public void SetBuffer (byte[] buffer, int offset, int count)
124                 {
125                         SetBufferInternal (buffer, offset, count);
126                 }
127
128                 void SetBufferInternal (byte[] buffer, int offset, int count)
129                 {
130                         if (buffer != null) {
131                                 if (BufferList != null)
132                                         throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null.");
133                                 
134                                 int buflen = buffer.Length;
135                                 if (offset < 0 || offset >= buflen)
136                                         throw new ArgumentOutOfRangeException ("offset");
137
138                                 if (count < 0 || count + offset > buflen)
139                                         throw new ArgumentOutOfRangeException ("count");
140                         }
141
142                         Count = count;
143                         Offset = offset;
144                         Buffer = buffer;
145                 }
146
147 #region Internals
148                 void AcceptCallback ()
149                 {
150                         SocketError = SocketError.Success;
151                         LastOperation = SocketAsyncOperation.Accept;
152                         try {
153                                 curSocket.Accept (AcceptSocket);
154                         } catch (SocketException ex) {
155                                 SocketError = ex.SocketErrorCode;
156                                 throw;
157                         } finally {
158                                 OnCompleted (this);
159                         }
160                 }
161
162                 void ReceiveCallback ()
163                 {
164                         SocketError = SocketError.Success;
165                         LastOperation = SocketAsyncOperation.Receive;
166                         SocketError error = SocketError.Success;
167                         
168                         try {
169                                 BytesTransferred = curSocket.Receive_nochecks (Buffer, Offset, Count, SocketFlags, out error);
170                         } finally {
171                                 SocketError = error;
172                                 OnCompleted (this);
173                         }
174                 }
175
176                 void ConnectCallback ()
177                 {
178                         SocketError = SocketError.Success;
179                         LastOperation = SocketAsyncOperation.Connect;
180                         SocketError error = SocketError.Success;
181
182                         try {
183                                 if (!curSocket.Blocking) {
184                                         int success;
185                                         curSocket.Poll (-1, SelectMode.SelectWrite, out success);
186                                         SocketError = (SocketError)success;
187                                         if (success == 0)
188                                                 curSocket.Connected = true;
189                                         else
190                                                 return;
191                                 } else {
192                                         curSocket.seed_endpoint = RemoteEndPoint;
193                                         curSocket.Connect (RemoteEndPoint);
194                                         curSocket.Connected = true;
195                                 }
196                         } catch (SocketException se){
197                                 error = se.SocketErrorCode;
198                         } finally {
199                                 SocketError = error;
200                                 OnCompleted (this);
201                         }
202                 }
203
204                 void SendCallback ()
205                 {
206                         SocketError = SocketError.Success;
207                         LastOperation = SocketAsyncOperation.Send;
208                         SocketError error = SocketError.Success;
209
210                         try {
211                                 BytesTransferred = curSocket.Send_nochecks (Buffer, Offset, Count, SocketFlags.None, out error);
212                         } finally {
213                                 SocketError = error;
214                                 OnCompleted (this);
215                         }
216                 }
217
218                 void DisconnectCallback ()
219                 {
220                         SocketError = SocketError.Success;
221                         LastOperation = SocketAsyncOperation.Disconnect;
222
223                         try {
224                                 curSocket.Disconnect (DisconnectReuseSocket);
225                         } catch (SocketException ex) {
226                                 SocketError = ex.SocketErrorCode;
227                                 throw;
228                         } finally {
229                                 OnCompleted (this);
230                         }
231                 }
232
233                 void ReceiveFromCallback ()
234                 {
235                         SocketError = SocketError.Success;
236                         LastOperation = SocketAsyncOperation.ReceiveFrom;
237
238                         try {
239                                 EndPoint ep = RemoteEndPoint;
240                                 BytesTransferred = curSocket.ReceiveFrom_nochecks (Buffer, Offset, Count, SocketFlags, ref ep);
241                         } catch (SocketException ex) {
242                                 SocketError = ex.SocketErrorCode;
243                                 throw;
244                         } finally {
245                                 OnCompleted (this);
246                         }
247                 }
248
249                 void SendToCallback ()
250                 {
251                         SocketError = SocketError.Success;
252                         LastOperation = SocketAsyncOperation.SendTo;
253                         int total = 0;
254                         
255                         try {
256                                 int count = Count;
257
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;
263                                 throw;
264                         } finally {
265                                 OnCompleted (this);
266                         }
267                 }
268                 
269                 internal void DoOperation (SocketAsyncOperation operation, Socket socket)
270                 {
271                         ThreadStart callback;
272                         curSocket = socket;
273                         
274                         switch (operation) {
275                                 case SocketAsyncOperation.Accept:
276                                         callback = new ThreadStart (AcceptCallback);
277                                         break;
278
279                                 case SocketAsyncOperation.Receive:
280                                         callback = new ThreadStart (ReceiveCallback);
281                                         break;
282
283                                 case SocketAsyncOperation.Connect:
284                                         callback = new ThreadStart (ConnectCallback);
285                                         break;
286
287                                 case SocketAsyncOperation.Disconnect:
288                                         callback = new ThreadStart (DisconnectCallback);
289                                         break;
290
291                                 case SocketAsyncOperation.ReceiveFrom:
292                                         callback = new ThreadStart (ReceiveFromCallback);
293                                         break;
294                                         
295                                 case SocketAsyncOperation.Send:
296                                         callback = new ThreadStart (SendCallback);
297                                         break;
298
299                                 case SocketAsyncOperation.SendTo:
300                                         callback = new ThreadStart (SendToCallback);
301                                         break;
302                                         
303                                 default:
304                                         throw new NotSupportedException ();
305                         }
306
307                         Thread t = new Thread (callback);
308                         t.IsBackground = true;
309                         t.Start ();
310                 }
311 #endregion
312         }
313 }
314 #endif