[Cleanup] Removed TARGET_JVM
[mono-project.git] / mcs / class / System / System.Net.Sockets / Socket.cs
blobcecabd1e18aa111cba12ffdab425d75263071dd7
1 // System.Net.Sockets.Socket.cs
2 //
3 // Authors:
4 // Phillip Pearson (pp@myelin.co.nz)
5 // Dick Porter <dick@ximian.com>
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Sridhar Kulkarni (sridharkulkarni@gmail.com)
8 // Brian Nickel (brian.nickel@gmail.com)
9 //
10 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
11 // http://www.myelin.co.nz
12 // (c) 2004-2011 Novell, Inc. (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 //
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System;
36 using System.Net;
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Threading;
42 using System.Reflection;
43 using System.IO;
44 using System.Net.Configuration;
45 using System.Text;
46 using System.Timers;
47 using System.Net.NetworkInformation;
49 namespace System.Net.Sockets
51 public partial class Socket : IDisposable
53 private bool islistening;
54 private bool useoverlappedIO;
55 private const int SOCKET_CLOSED = 10004;
57 private static readonly string timeout_exc_msg = "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond";
59 static void AddSockets (List<Socket> sockets, IList list, string name)
61 if (list != null) {
62 foreach (Socket sock in list) {
63 if (sock == null) // MS throws a NullRef
64 throw new ArgumentNullException ("name", "Contains a null element");
65 sockets.Add (sock);
69 sockets.Add (null);
71 [MethodImplAttribute(MethodImplOptions.InternalCall)]
72 private extern static void Select_internal (ref Socket [] sockets,
73 int microSeconds,
74 out int error);
75 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
77 var list = new List<Socket> ();
78 AddSockets (list, checkRead, "checkRead");
79 AddSockets (list, checkWrite, "checkWrite");
80 AddSockets (list, checkError, "checkError");
82 if (list.Count == 3) {
83 throw new ArgumentNullException ("checkRead, checkWrite, checkError",
84 "All the lists are null or empty.");
87 int error;
89 * The 'sockets' array contains: READ socket 0-n, null,
90 * WRITE socket 0-n, null,
91 * ERROR socket 0-n, null
93 Socket [] sockets = list.ToArray ();
94 Select_internal (ref sockets, microSeconds, out error);
96 if (error != 0)
97 throw new SocketException (error);
99 if (sockets == null) {
100 if (checkRead != null)
101 checkRead.Clear ();
102 if (checkWrite != null)
103 checkWrite.Clear ();
104 if (checkError != null)
105 checkError.Clear ();
106 return;
109 int mode = 0;
110 int count = sockets.Length;
111 IList currentList = checkRead;
112 int currentIdx = 0;
113 for (int i = 0; i < count; i++) {
114 Socket sock = sockets [i];
115 if (sock == null) { // separator
116 if (currentList != null) {
117 // Remove non-signaled sockets after the current one
118 int to_remove = currentList.Count - currentIdx;
119 for (int k = 0; k < to_remove; k++)
120 currentList.RemoveAt (currentIdx);
122 currentList = (mode == 0) ? checkWrite : checkError;
123 currentIdx = 0;
124 mode++;
125 continue;
128 if (mode == 1 && currentList == checkWrite && !sock.connected) {
129 if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
130 sock.connected = true;
133 // Remove non-signaled sockets before the current one
134 //int max = currentList.Count;
135 while (((Socket) currentList [currentIdx]) != sock) {
136 currentList.RemoveAt (currentIdx);
138 currentIdx++;
142 // private constructor used by Accept, which already
143 // has a socket handle to use
144 internal Socket(AddressFamily family, SocketType type,
145 ProtocolType proto, IntPtr sock)
147 address_family=family;
148 socket_type=type;
149 protocol_type=proto;
151 socket=sock;
152 connected=true;
155 private void SocketDefaults ()
157 try {
158 if (address_family == AddressFamily.InterNetwork /* Need to test IPv6 further ||
159 address_family == AddressFamily.InterNetworkV6 */) {
160 /* This is the default, but it
161 * probably has nasty side
162 * effects on Linux, as the
163 * socket option is kludged by
164 * turning on or off PMTU
165 * discovery...
167 this.DontFragment = false;
171 // Microsoft sets these to 8192, but we are going to keep them
172 // both to the OS defaults as these have a big performance impact.
173 // on WebClient performance.
175 //this.ReceiveBufferSize = 8192;
176 //this.SendBufferSize = 8192;
177 } catch (SocketException) {
181 #if !MOBILE
182 public Socket (SocketInformation socketInformation)
184 var options = socketInformation.Options;
185 islistening = (options & SocketInformationOptions.Listening) != 0;
186 connected = (options & SocketInformationOptions.Connected) != 0;
187 blocking = (options & SocketInformationOptions.NonBlocking) == 0;
188 useoverlappedIO = (options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
190 var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
192 address_family = (AddressFamily) (int) result [0];
193 socket_type = (SocketType) (int) result [1];
194 protocol_type = (ProtocolType) (int) result [2];
195 isbound = (ProtocolType) (int) result [3] != 0;
196 socket = (IntPtr) (long) result [4];
197 SocketDefaults ();
199 #endif
201 // Returns the amount of data waiting to be read on socket
202 [MethodImplAttribute(MethodImplOptions.InternalCall)]
203 private extern static int Available_internal(IntPtr socket, out int error);
205 public int Available {
206 get {
207 if (disposed && closed)
208 throw new ObjectDisposedException (GetType ().ToString ());
210 int ret, error;
212 ret = Available_internal(socket, out error);
214 if (error != 0)
215 throw new SocketException (error);
217 return(ret);
222 public bool DontFragment {
223 get {
224 if (disposed && closed) {
225 throw new ObjectDisposedException (GetType ().ToString ());
228 bool dontfragment;
230 if (address_family == AddressFamily.InterNetwork) {
231 dontfragment = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
232 } else if (address_family == AddressFamily.InterNetworkV6) {
233 dontfragment = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
234 } else {
235 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
238 return(dontfragment);
240 set {
241 if (disposed && closed) {
242 throw new ObjectDisposedException (GetType ().ToString ());
245 if (address_family == AddressFamily.InterNetwork) {
246 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value?1:0);
247 } else if (address_family == AddressFamily.InterNetworkV6) {
248 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value?1:0);
249 } else {
250 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
255 public bool EnableBroadcast {
256 get {
257 if (disposed && closed) {
258 throw new ObjectDisposedException (GetType ().ToString ());
261 if (protocol_type != ProtocolType.Udp) {
262 throw new SocketException ((int)SocketError.ProtocolOption);
265 return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0);
267 set {
268 if (disposed && closed) {
269 throw new ObjectDisposedException (GetType ().ToString ());
272 if (protocol_type != ProtocolType.Udp) {
273 throw new SocketException ((int)SocketError.ProtocolOption);
276 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value?1:0);
280 public bool ExclusiveAddressUse {
281 get {
282 if (disposed && closed) {
283 throw new ObjectDisposedException (GetType ().ToString ());
286 return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0);
288 set {
289 if (disposed && closed) {
290 throw new ObjectDisposedException (GetType ().ToString ());
292 if (isbound) {
293 throw new InvalidOperationException ("Bind has already been called for this socket");
296 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value?1:0);
300 public bool IsBound {
301 get {
302 return(isbound);
306 public LingerOption LingerState {
307 get {
308 if (disposed && closed) {
309 throw new ObjectDisposedException (GetType ().ToString ());
312 return((LingerOption)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger));
314 set {
315 if (disposed && closed) {
316 throw new ObjectDisposedException (GetType ().ToString ());
319 SetSocketOption (SocketOptionLevel.Socket,
320 SocketOptionName.Linger,
321 value);
325 public bool MulticastLoopback {
326 get {
327 if (disposed && closed) {
328 throw new ObjectDisposedException (GetType ().ToString ());
331 /* Even though this option can be set
332 * for TCP sockets on Linux, throw
333 * this exception anyway to be
334 * compatible (the MSDN docs say
335 * "Setting this property on a
336 * Transmission Control Protocol (TCP)
337 * socket will have no effect." but
338 * the MS runtime throws the
339 * exception...)
341 if (protocol_type == ProtocolType.Tcp) {
342 throw new SocketException ((int)SocketError.ProtocolOption);
345 bool multicastloopback;
347 if (address_family == AddressFamily.InterNetwork) {
348 multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
349 } else if (address_family == AddressFamily.InterNetworkV6) {
350 multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
351 } else {
352 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
355 return(multicastloopback);
357 set {
358 if (disposed && closed) {
359 throw new ObjectDisposedException (GetType ().ToString ());
362 /* Even though this option can be set
363 * for TCP sockets on Linux, throw
364 * this exception anyway to be
365 * compatible (the MSDN docs say
366 * "Setting this property on a
367 * Transmission Control Protocol (TCP)
368 * socket will have no effect." but
369 * the MS runtime throws the
370 * exception...)
372 if (protocol_type == ProtocolType.Tcp) {
373 throw new SocketException ((int)SocketError.ProtocolOption);
376 if (address_family == AddressFamily.InterNetwork) {
377 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value?1:0);
378 } else if (address_family == AddressFamily.InterNetworkV6) {
379 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value?1:0);
380 } else {
381 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
387 [MonoTODO ("This doesn't do anything on Mono yet")]
388 public bool UseOnlyOverlappedIO {
389 get {
390 return(useoverlappedIO);
392 set {
393 useoverlappedIO = value;
397 public IntPtr Handle {
398 get {
399 return(socket);
403 // Returns the local endpoint details in addr and port
404 [MethodImplAttribute(MethodImplOptions.InternalCall)]
405 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, int family, out int error);
407 // Wish: support non-IP endpoints.
408 public EndPoint LocalEndPoint {
409 get {
410 if (disposed && closed)
411 throw new ObjectDisposedException (GetType ().ToString ());
414 * If the seed EndPoint is null, Connect, Bind,
415 * etc has not yet been called. MS returns null
416 * in this case.
418 if (seed_endpoint == null)
419 return null;
421 SocketAddress sa;
422 int error;
424 sa=LocalEndPoint_internal(socket, (int) address_family, out error);
426 if (error != 0)
427 throw new SocketException (error);
429 return seed_endpoint.Create (sa);
433 public SocketType SocketType {
434 get {
435 return(socket_type);
439 public int SendTimeout {
440 get {
441 if (disposed && closed)
442 throw new ObjectDisposedException (GetType ().ToString ());
444 return (int)GetSocketOption(
445 SocketOptionLevel.Socket,
446 SocketOptionName.SendTimeout);
448 set {
449 if (disposed && closed)
450 throw new ObjectDisposedException (GetType ().ToString ());
452 if (value < -1)
453 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
455 /* According to the MSDN docs we
456 * should adjust values between 1 and
457 * 499 to 500, but the MS runtime
458 * doesn't do this.
460 if (value == -1)
461 value = 0;
463 SetSocketOption(
464 SocketOptionLevel.Socket,
465 SocketOptionName.SendTimeout, value);
469 public int ReceiveTimeout {
470 get {
471 if (disposed && closed)
472 throw new ObjectDisposedException (GetType ().ToString ());
474 return (int)GetSocketOption(
475 SocketOptionLevel.Socket,
476 SocketOptionName.ReceiveTimeout);
478 set {
479 if (disposed && closed)
480 throw new ObjectDisposedException (GetType ().ToString ());
482 if (value < -1)
483 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
485 if (value == -1) {
486 value = 0;
489 SetSocketOption(
490 SocketOptionLevel.Socket,
491 SocketOptionName.ReceiveTimeout, value);
495 public bool AcceptAsync (SocketAsyncEventArgs e)
497 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
499 if (disposed && closed)
500 throw new ObjectDisposedException (GetType ().ToString ());
501 if (!IsBound)
502 throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
503 if (!islistening)
504 throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
505 if (e.BufferList != null)
506 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
507 if (e.Count < 0)
508 throw new ArgumentOutOfRangeException ("e.Count");
510 Socket acceptSocket = e.AcceptSocket;
511 if (acceptSocket != null) {
512 if (acceptSocket.IsBound || acceptSocket.Connected)
513 throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
516 e.curSocket = this;
517 Worker w = e.Worker;
518 w.Init (this, e, SocketOperation.Accept);
519 int count;
520 lock (readQ) {
521 readQ.Enqueue (e.Worker);
522 count = readQ.Count;
524 if (count == 1)
525 socket_pool_queue (Worker.Dispatcher, w.result);
526 return true;
528 // Creates a new system socket, returning the handle
529 [MethodImplAttribute(MethodImplOptions.InternalCall)]
530 private extern static IntPtr Accept_internal(IntPtr sock, out int error, bool blocking);
532 public Socket Accept() {
533 if (disposed && closed)
534 throw new ObjectDisposedException (GetType ().ToString ());
536 int error = 0;
537 IntPtr sock = (IntPtr) (-1);
538 try {
539 RegisterForBlockingSyscall ();
540 sock = Accept_internal(socket, out error, blocking);
541 } finally {
542 UnRegisterForBlockingSyscall ();
545 if (error != 0) {
546 if (closed)
547 error = SOCKET_CLOSED;
548 throw new SocketException(error);
551 Socket accepted = new Socket(this.AddressFamily, this.SocketType,
552 this.ProtocolType, sock);
554 accepted.seed_endpoint = this.seed_endpoint;
555 accepted.Blocking = this.Blocking;
556 return(accepted);
559 internal void Accept (Socket acceptSocket)
561 if (disposed && closed)
562 throw new ObjectDisposedException (GetType ().ToString ());
564 int error = 0;
565 IntPtr sock = (IntPtr)(-1);
567 try {
568 RegisterForBlockingSyscall ();
569 sock = Accept_internal (socket, out error, blocking);
570 } finally {
571 UnRegisterForBlockingSyscall ();
574 if (error != 0) {
575 if (closed)
576 error = SOCKET_CLOSED;
577 throw new SocketException (error);
580 acceptSocket.address_family = this.AddressFamily;
581 acceptSocket.socket_type = this.SocketType;
582 acceptSocket.protocol_type = this.ProtocolType;
583 acceptSocket.socket = sock;
584 acceptSocket.connected = true;
585 acceptSocket.seed_endpoint = this.seed_endpoint;
586 acceptSocket.Blocking = this.Blocking;
588 /* FIXME: figure out what if anything else
589 * needs to be reset
593 public IAsyncResult BeginAccept(AsyncCallback callback, object state)
595 if (disposed && closed)
596 throw new ObjectDisposedException (GetType ().ToString ());
598 if (!isbound || !islistening)
599 throw new InvalidOperationException ();
601 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
602 int count;
603 lock (readQ) {
604 readQ.Enqueue (req.Worker);
605 count = readQ.Count;
607 if (count == 1)
608 socket_pool_queue (Worker.Dispatcher, req);
609 return req;
612 public IAsyncResult BeginAccept (int receiveSize,
613 AsyncCallback callback,
614 object state)
616 if (disposed && closed)
617 throw new ObjectDisposedException (GetType ().ToString ());
619 if (receiveSize < 0)
620 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
622 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
623 req.Buffer = new byte[receiveSize];
624 req.Offset = 0;
625 req.Size = receiveSize;
626 req.SockFlags = SocketFlags.None;
627 int count;
628 lock (readQ) {
629 readQ.Enqueue (req.Worker);
630 count = readQ.Count;
632 if (count == 1)
633 socket_pool_queue (Worker.Dispatcher, req);
634 return req;
637 public IAsyncResult BeginAccept (Socket acceptSocket,
638 int receiveSize,
639 AsyncCallback callback,
640 object state)
642 if (disposed && closed)
643 throw new ObjectDisposedException (GetType ().ToString ());
645 if (receiveSize < 0)
646 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
648 if (acceptSocket != null) {
649 if (acceptSocket.disposed && acceptSocket.closed)
650 throw new ObjectDisposedException (acceptSocket.GetType ().ToString ());
652 if (acceptSocket.IsBound)
653 throw new InvalidOperationException ();
655 /* For some reason the MS runtime
656 * barfs if the new socket is not TCP,
657 * even though it's just about to blow
658 * away all those parameters
660 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
661 throw new SocketException ((int)SocketError.InvalidArgument);
664 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
665 req.Buffer = new byte[receiveSize];
666 req.Offset = 0;
667 req.Size = receiveSize;
668 req.SockFlags = SocketFlags.None;
669 req.AcceptSocket = acceptSocket;
670 int count;
671 lock (readQ) {
672 readQ.Enqueue (req.Worker);
673 count = readQ.Count;
675 if (count == 1)
676 socket_pool_queue (Worker.Dispatcher, req);
677 return(req);
680 public IAsyncResult BeginConnect (IPAddress address, int port,
681 AsyncCallback callback,
682 object state)
684 if (disposed && closed)
685 throw new ObjectDisposedException (GetType ().ToString ());
687 if (address == null)
688 throw new ArgumentNullException ("address");
690 if (address.ToString ().Length == 0)
691 throw new ArgumentException ("The length of the IP address is zero");
693 if (port <= 0 || port > 65535)
694 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
696 if (islistening)
697 throw new InvalidOperationException ();
699 IPEndPoint iep = new IPEndPoint (address, port);
700 return(BeginConnect (iep, callback, state));
703 public IAsyncResult BeginConnect (string host, int port,
704 AsyncCallback callback,
705 object state)
707 if (disposed && closed)
708 throw new ObjectDisposedException (GetType ().ToString ());
710 if (host == null)
711 throw new ArgumentNullException ("host");
713 if (address_family != AddressFamily.InterNetwork &&
714 address_family != AddressFamily.InterNetworkV6)
715 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
717 if (port <= 0 || port > 65535)
718 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
720 if (islistening)
721 throw new InvalidOperationException ();
723 return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
726 public IAsyncResult BeginDisconnect (bool reuseSocket,
727 AsyncCallback callback,
728 object state)
730 if (disposed && closed)
731 throw new ObjectDisposedException (GetType ().ToString ());
733 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
734 req.ReuseSocket = reuseSocket;
735 socket_pool_queue (Worker.Dispatcher, req);
736 return(req);
739 void CheckRange (byte[] buffer, int offset, int size)
741 if (offset < 0)
742 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
744 if (offset > buffer.Length)
745 throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
747 if (size < 0)
748 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
750 if (size > buffer.Length - offset)
751 throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
754 public IAsyncResult BeginReceive(byte[] buffer, int offset,
755 int size,
756 SocketFlags socket_flags,
757 AsyncCallback callback,
758 object state) {
760 if (disposed && closed)
761 throw new ObjectDisposedException (GetType ().ToString ());
763 if (buffer == null)
764 throw new ArgumentNullException ("buffer");
766 CheckRange (buffer, offset, size);
768 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
769 req.Buffer = buffer;
770 req.Offset = offset;
771 req.Size = size;
772 req.SockFlags = socket_flags;
773 int count;
774 lock (readQ) {
775 readQ.Enqueue (req.Worker);
776 count = readQ.Count;
778 if (count == 1)
779 socket_pool_queue (Worker.Dispatcher, req);
780 return req;
783 public IAsyncResult BeginReceive (byte[] buffer, int offset,
784 int size, SocketFlags flags,
785 out SocketError error,
786 AsyncCallback callback,
787 object state)
789 /* As far as I can tell from the docs and from
790 * experimentation, a pointer to the
791 * SocketError parameter is not supposed to be
792 * saved for the async parts. And as we don't
793 * set any socket errors in the setup code, we
794 * just have to set it to Success.
796 error = SocketError.Success;
797 return (BeginReceive (buffer, offset, size, flags, callback, state));
800 [CLSCompliant (false)]
801 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
802 SocketFlags socketFlags,
803 AsyncCallback callback,
804 object state)
806 if (disposed && closed)
807 throw new ObjectDisposedException (GetType ().ToString ());
809 if (buffers == null)
810 throw new ArgumentNullException ("buffers");
812 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
813 req.Buffers = buffers;
814 req.SockFlags = socketFlags;
815 int count;
816 lock(readQ) {
817 readQ.Enqueue (req.Worker);
818 count = readQ.Count;
820 if (count == 1)
821 socket_pool_queue (Worker.Dispatcher, req);
822 return req;
825 [CLSCompliant (false)]
826 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
827 SocketFlags socketFlags,
828 out SocketError errorCode,
829 AsyncCallback callback,
830 object state)
832 /* I assume the same SocketError semantics as
833 * above
835 errorCode = SocketError.Success;
836 return (BeginReceive (buffers, socketFlags, callback, state));
839 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
840 int size,
841 SocketFlags socket_flags,
842 ref EndPoint remote_end,
843 AsyncCallback callback,
844 object state) {
845 if (disposed && closed)
846 throw new ObjectDisposedException (GetType ().ToString ());
848 if (buffer == null)
849 throw new ArgumentNullException ("buffer");
851 if (remote_end == null)
852 throw new ArgumentNullException ("remote_end");
854 CheckRange (buffer, offset, size);
856 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
857 req.Buffer = buffer;
858 req.Offset = offset;
859 req.Size = size;
860 req.SockFlags = socket_flags;
861 req.EndPoint = remote_end;
862 int count;
863 lock (readQ) {
864 readQ.Enqueue (req.Worker);
865 count = readQ.Count;
867 if (count == 1)
868 socket_pool_queue (Worker.Dispatcher, req);
869 return req;
872 [MonoTODO]
873 public IAsyncResult BeginReceiveMessageFrom (
874 byte[] buffer, int offset, int size,
875 SocketFlags socketFlags, ref EndPoint remoteEP,
876 AsyncCallback callback, object state)
878 if (disposed && closed)
879 throw new ObjectDisposedException (GetType ().ToString ());
881 if (buffer == null)
882 throw new ArgumentNullException ("buffer");
884 if (remoteEP == null)
885 throw new ArgumentNullException ("remoteEP");
887 CheckRange (buffer, offset, size);
889 throw new NotImplementedException ();
892 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
893 AsyncCallback callback, object state)
895 if (disposed && closed)
896 throw new ObjectDisposedException (GetType ().ToString ());
898 if (buffer == null)
899 throw new ArgumentNullException ("buffer");
901 CheckRange (buffer, offset, size);
903 if (!connected)
904 throw new SocketException ((int)SocketError.NotConnected);
906 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
907 req.Buffer = buffer;
908 req.Offset = offset;
909 req.Size = size;
910 req.SockFlags = socket_flags;
911 int count;
912 lock (writeQ) {
913 writeQ.Enqueue (req.Worker);
914 count = writeQ.Count;
916 if (count == 1)
917 socket_pool_queue (Worker.Dispatcher, req);
918 return req;
921 public IAsyncResult BeginSend (byte[] buffer, int offset,
922 int size,
923 SocketFlags socketFlags,
924 out SocketError errorCode,
925 AsyncCallback callback,
926 object state)
928 if (!connected) {
929 errorCode = SocketError.NotConnected;
930 throw new SocketException ((int)errorCode);
933 errorCode = SocketError.Success;
935 return (BeginSend (buffer, offset, size, socketFlags, callback,
936 state));
939 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
940 SocketFlags socketFlags,
941 AsyncCallback callback,
942 object state)
944 if (disposed && closed)
945 throw new ObjectDisposedException (GetType ().ToString ());
947 if (buffers == null)
948 throw new ArgumentNullException ("buffers");
950 if (!connected)
951 throw new SocketException ((int)SocketError.NotConnected);
953 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
954 req.Buffers = buffers;
955 req.SockFlags = socketFlags;
956 int count;
957 lock (writeQ) {
958 writeQ.Enqueue (req.Worker);
959 count = writeQ.Count;
961 if (count == 1)
962 socket_pool_queue (Worker.Dispatcher, req);
963 return req;
966 [CLSCompliant (false)]
967 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
968 SocketFlags socketFlags,
969 out SocketError errorCode,
970 AsyncCallback callback,
971 object state)
973 if (!connected) {
974 errorCode = SocketError.NotConnected;
975 throw new SocketException ((int)errorCode);
978 errorCode = SocketError.Success;
979 return (BeginSend (buffers, socketFlags, callback, state));
982 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
984 sealed class SendFileAsyncResult : IAsyncResult {
985 IAsyncResult ares;
986 SendFileHandler d;
988 public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
990 this.d = d;
991 this.ares = ares;
994 public object AsyncState {
995 get { return ares.AsyncState; }
998 public WaitHandle AsyncWaitHandle {
999 get { return ares.AsyncWaitHandle; }
1002 public bool CompletedSynchronously {
1003 get { return ares.CompletedSynchronously; }
1006 public bool IsCompleted {
1007 get { return ares.IsCompleted; }
1010 public SendFileHandler Delegate {
1011 get { return d; }
1014 public IAsyncResult Original {
1015 get { return ares; }
1019 public IAsyncResult BeginSendFile (string fileName,
1020 AsyncCallback callback,
1021 object state)
1023 if (disposed && closed)
1024 throw new ObjectDisposedException (GetType ().ToString ());
1026 if (!connected)
1027 throw new NotSupportedException ();
1029 if (!File.Exists (fileName))
1030 throw new FileNotFoundException ();
1032 return BeginSendFile (fileName, null, null, 0, callback, state);
1035 public IAsyncResult BeginSendFile (string fileName,
1036 byte[] preBuffer,
1037 byte[] postBuffer,
1038 TransmitFileOptions flags,
1039 AsyncCallback callback,
1040 object state)
1042 if (disposed && closed)
1043 throw new ObjectDisposedException (GetType ().ToString ());
1045 if (!connected)
1046 throw new NotSupportedException ();
1048 if (!File.Exists (fileName))
1049 throw new FileNotFoundException ();
1051 SendFileHandler d = new SendFileHandler (SendFile);
1052 return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => {
1053 SendFileAsyncResult sfar = new SendFileAsyncResult (d, ar);
1054 callback (sfar);
1055 }, state));
1058 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
1059 int size,
1060 SocketFlags socket_flags,
1061 EndPoint remote_end,
1062 AsyncCallback callback,
1063 object state) {
1064 if (disposed && closed)
1065 throw new ObjectDisposedException (GetType ().ToString ());
1067 if (buffer == null)
1068 throw new ArgumentNullException ("buffer");
1070 CheckRange (buffer, offset, size);
1072 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
1073 req.Buffer = buffer;
1074 req.Offset = offset;
1075 req.Size = size;
1076 req.SockFlags = socket_flags;
1077 req.EndPoint = remote_end;
1078 int count;
1079 lock (writeQ) {
1080 writeQ.Enqueue (req.Worker);
1081 count = writeQ.Count;
1083 if (count == 1)
1084 socket_pool_queue (Worker.Dispatcher, req);
1085 return req;
1088 // Creates a new system socket, returning the handle
1089 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1090 private extern static void Bind_internal(IntPtr sock,
1091 SocketAddress sa,
1092 out int error);
1094 public void Bind(EndPoint local_end) {
1095 if (disposed && closed)
1096 throw new ObjectDisposedException (GetType ().ToString ());
1098 if (local_end == null)
1099 throw new ArgumentNullException("local_end");
1101 int error;
1103 Bind_internal(socket, local_end.Serialize(), out error);
1104 if (error != 0)
1105 throw new SocketException (error);
1106 if (error == 0)
1107 isbound = true;
1109 seed_endpoint = local_end;
1112 public void Connect (IPAddress address, int port)
1114 Connect (new IPEndPoint (address, port));
1117 public void Connect (IPAddress[] addresses, int port)
1119 if (disposed && closed)
1120 throw new ObjectDisposedException (GetType ().ToString ());
1122 if (addresses == null)
1123 throw new ArgumentNullException ("addresses");
1125 if (this.AddressFamily != AddressFamily.InterNetwork &&
1126 this.AddressFamily != AddressFamily.InterNetworkV6)
1127 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1129 if (islistening)
1130 throw new InvalidOperationException ();
1132 /* FIXME: do non-blocking sockets Poll here? */
1133 int error = 0;
1134 foreach (IPAddress address in addresses) {
1135 IPEndPoint iep = new IPEndPoint (address, port);
1136 SocketAddress serial = iep.Serialize ();
1138 Connect_internal (socket, serial, out error);
1139 if (error == 0) {
1140 connected = true;
1141 isbound = true;
1142 seed_endpoint = iep;
1143 return;
1144 } else if (error != (int)SocketError.InProgress &&
1145 error != (int)SocketError.WouldBlock) {
1146 continue;
1149 if (!blocking) {
1150 Poll (-1, SelectMode.SelectWrite);
1151 error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1152 if (error == 0) {
1153 connected = true;
1154 isbound = true;
1155 seed_endpoint = iep;
1156 return;
1160 if (error != 0)
1161 throw new SocketException (error);
1164 public void Connect (string host, int port)
1166 IPAddress [] addresses = Dns.GetHostAddresses (host);
1167 Connect (addresses, port);
1170 public bool DisconnectAsync (SocketAsyncEventArgs e)
1172 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1173 if (disposed && closed)
1174 throw new ObjectDisposedException (GetType ().ToString ());
1176 e.curSocket = this;
1177 e.Worker.Init (this, e, SocketOperation.Disconnect);
1178 socket_pool_queue (Worker.Dispatcher, e.Worker.result);
1179 return true;
1182 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1183 extern static void Disconnect_internal(IntPtr sock, bool reuse, out int error);
1185 /* According to the docs, the MS runtime will throw
1186 * PlatformNotSupportedException if the platform is
1187 * newer than w2k. We should be able to cope...
1189 public void Disconnect (bool reuseSocket)
1191 if (disposed && closed)
1192 throw new ObjectDisposedException (GetType ().ToString ());
1194 int error = 0;
1196 Disconnect_internal (socket, reuseSocket, out error);
1198 if (error != 0) {
1199 if (error == 50) {
1200 /* ERROR_NOT_SUPPORTED */
1201 throw new PlatformNotSupportedException ();
1202 } else {
1203 throw new SocketException (error);
1207 connected = false;
1209 if (reuseSocket) {
1210 /* Do managed housekeeping here... */
1214 #if !MOBILE
1215 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
1216 public SocketInformation DuplicateAndClose (int targetProcessId)
1218 var si = new SocketInformation ();
1219 si.Options =
1220 (islistening ? SocketInformationOptions.Listening : 0) |
1221 (connected ? SocketInformationOptions.Connected : 0) |
1222 (blocking ? 0 : SocketInformationOptions.NonBlocking) |
1223 (useoverlappedIO ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
1225 si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, isbound ? 1 : 0, (long)socket);
1226 socket = (IntPtr) (-1);
1228 return si;
1230 #endif
1232 public Socket EndAccept (IAsyncResult result)
1234 int bytes;
1235 byte[] buffer;
1237 return(EndAccept (out buffer, out bytes, result));
1240 public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
1242 int bytes;
1243 return(EndAccept (out buffer, out bytes, asyncResult));
1246 public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
1248 if (disposed && closed)
1249 throw new ObjectDisposedException (GetType ().ToString ());
1251 if (asyncResult == null)
1252 throw new ArgumentNullException ("asyncResult");
1254 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1255 if (req == null)
1256 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1258 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1259 throw InvalidAsyncOp ("EndAccept");
1260 if (!asyncResult.IsCompleted)
1261 asyncResult.AsyncWaitHandle.WaitOne ();
1263 req.CheckIfThrowDelayedException ();
1265 buffer = req.Buffer;
1266 bytesTransferred = req.Total;
1268 return(req.Socket);
1271 public void EndConnect (IAsyncResult result)
1273 if (disposed && closed)
1274 throw new ObjectDisposedException (GetType ().ToString ());
1276 if (result == null)
1277 throw new ArgumentNullException ("result");
1279 SocketAsyncResult req = result as SocketAsyncResult;
1280 if (req == null)
1281 throw new ArgumentException ("Invalid IAsyncResult", "result");
1283 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1284 throw InvalidAsyncOp ("EndConnect");
1285 if (!result.IsCompleted)
1286 result.AsyncWaitHandle.WaitOne();
1288 req.CheckIfThrowDelayedException();
1291 public void EndDisconnect (IAsyncResult asyncResult)
1293 if (disposed && closed)
1294 throw new ObjectDisposedException (GetType ().ToString ());
1296 if (asyncResult == null)
1297 throw new ArgumentNullException ("asyncResult");
1299 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1300 if (req == null)
1301 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1303 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1304 throw InvalidAsyncOp ("EndDisconnect");
1305 if (!asyncResult.IsCompleted)
1306 asyncResult.AsyncWaitHandle.WaitOne ();
1308 req.CheckIfThrowDelayedException ();
1311 [MonoTODO]
1312 public int EndReceiveMessageFrom (IAsyncResult asyncResult,
1313 ref SocketFlags socketFlags,
1314 ref EndPoint endPoint,
1315 out IPPacketInformation ipPacketInformation)
1317 if (disposed && closed)
1318 throw new ObjectDisposedException (GetType ().ToString ());
1320 if (asyncResult == null)
1321 throw new ArgumentNullException ("asyncResult");
1323 if (endPoint == null)
1324 throw new ArgumentNullException ("endPoint");
1326 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1327 if (req == null)
1328 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1330 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1331 throw InvalidAsyncOp ("EndReceiveMessageFrom");
1332 throw new NotImplementedException ();
1335 public void EndSendFile (IAsyncResult asyncResult)
1337 if (disposed && closed)
1338 throw new ObjectDisposedException (GetType ().ToString ());
1340 if (asyncResult == null)
1341 throw new ArgumentNullException ("asyncResult");
1343 SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
1344 if (ares == null)
1345 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1347 ares.Delegate.EndInvoke (ares.Original);
1350 public int EndSendTo (IAsyncResult result)
1352 if (disposed && closed)
1353 throw new ObjectDisposedException (GetType ().ToString ());
1355 if (result == null)
1356 throw new ArgumentNullException ("result");
1358 SocketAsyncResult req = result as SocketAsyncResult;
1359 if (req == null)
1360 throw new ArgumentException ("Invalid IAsyncResult", "result");
1362 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1363 throw InvalidAsyncOp ("EndSendTo");
1364 if (!result.IsCompleted)
1365 result.AsyncWaitHandle.WaitOne();
1367 req.CheckIfThrowDelayedException();
1368 return req.Total;
1371 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1372 private extern static void GetSocketOption_arr_internal(IntPtr socket,
1373 SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
1374 out int error);
1376 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
1378 if (disposed && closed)
1379 throw new ObjectDisposedException (GetType ().ToString ());
1381 if (optionValue == null)
1382 throw new SocketException ((int) SocketError.Fault,
1383 "Error trying to dereference an invalid pointer");
1385 int error;
1387 GetSocketOption_arr_internal (socket, optionLevel, optionName, ref optionValue,
1388 out error);
1389 if (error != 0)
1390 throw new SocketException (error);
1393 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
1395 if (disposed && closed)
1396 throw new ObjectDisposedException (GetType ().ToString ());
1398 byte[] byte_val=new byte[length];
1399 int error;
1401 GetSocketOption_arr_internal (socket, optionLevel, optionName, ref byte_val,
1402 out error);
1403 if (error != 0)
1404 throw new SocketException (error);
1406 return(byte_val);
1409 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1410 // common options between UNIX and Winsock are FIONREAD,
1411 // FIONBIO and SIOCATMARK. Anything else will depend on the
1412 // system except SIO_KEEPALIVE_VALS which is properly handled
1413 // on both windows and linux.
1414 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1415 extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
1416 byte [] output, out int error);
1418 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1420 if (disposed)
1421 throw new ObjectDisposedException (GetType ().ToString ());
1423 int error;
1424 int result = WSAIoctl (socket, ioctl_code, in_value, out_value,
1425 out error);
1427 if (error != 0)
1428 throw new SocketException (error);
1430 if (result == -1)
1431 throw new InvalidOperationException ("Must use Blocking property instead.");
1433 return result;
1436 public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
1438 return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
1441 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1442 private extern static void Listen_internal(IntPtr sock, int backlog, out int error);
1444 public void Listen (int backlog)
1446 if (disposed && closed)
1447 throw new ObjectDisposedException (GetType ().ToString ());
1449 if (!isbound)
1450 throw new SocketException ((int)SocketError.InvalidArgument);
1452 int error;
1453 Listen_internal(socket, backlog, out error);
1455 if (error != 0)
1456 throw new SocketException (error);
1458 islistening = true;
1461 public bool Poll (int time_us, SelectMode mode)
1463 if (disposed && closed)
1464 throw new ObjectDisposedException (GetType ().ToString ());
1466 if (mode != SelectMode.SelectRead &&
1467 mode != SelectMode.SelectWrite &&
1468 mode != SelectMode.SelectError)
1469 throw new NotSupportedException ("'mode' parameter is not valid.");
1471 int error;
1472 bool result = Poll_internal (socket, mode, time_us, out error);
1473 if (error != 0)
1474 throw new SocketException (error);
1476 if (mode == SelectMode.SelectWrite && result && !connected) {
1477 /* Update the connected state; for
1478 * non-blocking Connect()s this is
1479 * when we can find out that the
1480 * connect succeeded.
1482 if ((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
1483 connected = true;
1487 return result;
1490 public int Receive (byte [] buffer)
1492 return Receive (buffer, SocketFlags.None);
1495 public int Receive (byte [] buffer, SocketFlags flags)
1497 if (disposed && closed)
1498 throw new ObjectDisposedException (GetType ().ToString ());
1500 if (buffer == null)
1501 throw new ArgumentNullException ("buffer");
1503 SocketError error;
1505 int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
1507 if (error != SocketError.Success) {
1508 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1509 throw new SocketException ((int) error, timeout_exc_msg);
1510 throw new SocketException ((int) error);
1513 return ret;
1516 public int Receive (byte [] buffer, int size, SocketFlags flags)
1518 if (disposed && closed)
1519 throw new ObjectDisposedException (GetType ().ToString ());
1521 if (buffer == null)
1522 throw new ArgumentNullException ("buffer");
1524 CheckRange (buffer, 0, size);
1526 SocketError error;
1528 int ret = Receive_nochecks (buffer, 0, size, flags, out error);
1530 if (error != SocketError.Success) {
1531 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1532 throw new SocketException ((int) error, timeout_exc_msg);
1533 throw new SocketException ((int) error);
1536 return ret;
1539 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
1541 if (disposed && closed)
1542 throw new ObjectDisposedException (GetType ().ToString ());
1544 if (buffer == null)
1545 throw new ArgumentNullException ("buffer");
1547 CheckRange (buffer, offset, size);
1549 SocketError error;
1551 int ret = Receive_nochecks (buffer, offset, size, flags, out error);
1553 if (error != SocketError.Success) {
1554 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1555 throw new SocketException ((int) error, timeout_exc_msg);
1556 throw new SocketException ((int) error);
1559 return ret;
1562 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
1564 if (disposed && closed)
1565 throw new ObjectDisposedException (GetType ().ToString ());
1567 if (buffer == null)
1568 throw new ArgumentNullException ("buffer");
1570 CheckRange (buffer, offset, size);
1572 return Receive_nochecks (buffer, offset, size, flags, out error);
1575 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
1577 if (disposed && closed)
1578 throw new ObjectDisposedException (GetType ().ToString ());
1580 // We do not support recv into multiple buffers yet
1581 if (e.BufferList != null)
1582 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1583 if (e.RemoteEndPoint == null)
1584 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1586 e.curSocket = this;
1587 e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
1588 SocketAsyncResult res = e.Worker.result;
1589 res.Buffer = e.Buffer;
1590 res.Offset = e.Offset;
1591 res.Size = e.Count;
1592 res.EndPoint = e.RemoteEndPoint;
1593 res.SockFlags = e.SocketFlags;
1594 int count;
1595 lock (readQ) {
1596 readQ.Enqueue (e.Worker);
1597 count = readQ.Count;
1599 if (count == 1)
1600 socket_pool_queue (Worker.Dispatcher, res);
1601 return true;
1604 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
1606 if (disposed && closed)
1607 throw new ObjectDisposedException (GetType ().ToString ());
1609 if (buffer == null)
1610 throw new ArgumentNullException ("buffer");
1612 if (remoteEP == null)
1613 throw new ArgumentNullException ("remoteEP");
1615 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
1618 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
1620 if (disposed && closed)
1621 throw new ObjectDisposedException (GetType ().ToString ());
1623 if (buffer == null)
1624 throw new ArgumentNullException ("buffer");
1626 if (remoteEP == null)
1627 throw new ArgumentNullException ("remoteEP");
1629 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
1632 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags,
1633 ref EndPoint remoteEP)
1635 if (disposed && closed)
1636 throw new ObjectDisposedException (GetType ().ToString ());
1638 if (buffer == null)
1639 throw new ArgumentNullException ("buffer");
1641 if (remoteEP == null)
1642 throw new ArgumentNullException ("remoteEP");
1644 if (size < 0 || size > buffer.Length)
1645 throw new ArgumentOutOfRangeException ("size");
1647 return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
1650 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1651 private extern static int RecvFrom_internal(IntPtr sock,
1652 byte[] buffer,
1653 int offset,
1654 int count,
1655 SocketFlags flags,
1656 ref SocketAddress sockaddr,
1657 out int error);
1659 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags,
1660 ref EndPoint remoteEP)
1662 if (disposed && closed)
1663 throw new ObjectDisposedException (GetType ().ToString ());
1665 if (buffer == null)
1666 throw new ArgumentNullException ("buffer");
1668 if (remoteEP == null)
1669 throw new ArgumentNullException ("remoteEP");
1671 CheckRange (buffer, offset, size);
1673 return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
1676 internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
1677 ref EndPoint remote_end)
1679 int error;
1680 return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
1683 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags,
1684 ref EndPoint remote_end, bool throwOnError, out int error)
1686 SocketAddress sockaddr = remote_end.Serialize();
1687 int cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
1688 SocketError err = (SocketError) error;
1689 if (err != 0) {
1690 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
1691 connected = false;
1692 else if (err == SocketError.WouldBlock && blocking) { // This might happen when ReceiveTimeout is set
1693 if (throwOnError)
1694 throw new SocketException ((int) SocketError.TimedOut, timeout_exc_msg);
1695 error = (int) SocketError.TimedOut;
1696 return 0;
1699 if (throwOnError)
1700 throw new SocketException (error);
1701 return 0;
1704 connected = true;
1705 isbound = true;
1707 // If sockaddr is null then we're a connection
1708 // oriented protocol and should ignore the
1709 // remote_end parameter (see MSDN
1710 // documentation for Socket.ReceiveFrom(...) )
1712 if ( sockaddr != null ) {
1713 // Stupidly, EndPoint.Create() is an
1714 // instance method
1715 remote_end = remote_end.Create (sockaddr);
1718 seed_endpoint = remote_end;
1720 return cnt;
1723 [MonoTODO ("Not implemented")]
1724 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
1726 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1727 if (disposed && closed)
1728 throw new ObjectDisposedException (GetType ().ToString ());
1730 throw new NotImplementedException ();
1733 [MonoTODO ("Not implemented")]
1734 public int ReceiveMessageFrom (byte[] buffer, int offset,
1735 int size,
1736 ref SocketFlags socketFlags,
1737 ref EndPoint remoteEP,
1738 out IPPacketInformation ipPacketInformation)
1740 if (disposed && closed)
1741 throw new ObjectDisposedException (GetType ().ToString ());
1743 if (buffer == null)
1744 throw new ArgumentNullException ("buffer");
1746 if (remoteEP == null)
1747 throw new ArgumentNullException ("remoteEP");
1749 CheckRange (buffer, offset, size);
1751 /* FIXME: figure out how we get hold of the
1752 * IPPacketInformation
1754 throw new NotImplementedException ();
1757 [MonoTODO ("Not implemented")]
1758 public bool SendPacketsAsync (SocketAsyncEventArgs e)
1760 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1762 if (disposed && closed)
1763 throw new ObjectDisposedException (GetType ().ToString ());
1765 throw new NotImplementedException ();
1768 public int Send (byte [] buf)
1770 if (disposed && closed)
1771 throw new ObjectDisposedException (GetType ().ToString ());
1773 if (buf == null)
1774 throw new ArgumentNullException ("buf");
1776 SocketError error;
1778 int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
1780 if (error != SocketError.Success)
1781 throw new SocketException ((int) error);
1783 return ret;
1786 public int Send (byte [] buf, SocketFlags flags)
1788 if (disposed && closed)
1789 throw new ObjectDisposedException (GetType ().ToString ());
1791 if (buf == null)
1792 throw new ArgumentNullException ("buf");
1794 SocketError error;
1796 int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
1798 if (error != SocketError.Success)
1799 throw new SocketException ((int) error);
1801 return ret;
1804 public int Send (byte [] buf, int size, SocketFlags flags)
1806 if (disposed && closed)
1807 throw new ObjectDisposedException (GetType ().ToString ());
1809 if (buf == null)
1810 throw new ArgumentNullException ("buf");
1812 CheckRange (buf, 0, size);
1814 SocketError error;
1816 int ret = Send_nochecks (buf, 0, size, flags, out error);
1818 if (error != SocketError.Success)
1819 throw new SocketException ((int) error);
1821 return ret;
1824 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
1826 if (disposed && closed)
1827 throw new ObjectDisposedException (GetType ().ToString ());
1829 if (buf == null)
1830 throw new ArgumentNullException ("buffer");
1832 CheckRange (buf, offset, size);
1834 SocketError error;
1836 int ret = Send_nochecks (buf, offset, size, flags, out error);
1838 if (error != SocketError.Success)
1839 throw new SocketException ((int) error);
1841 return ret;
1844 public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1846 if (disposed && closed)
1847 throw new ObjectDisposedException (GetType ().ToString ());
1849 if (buf == null)
1850 throw new ArgumentNullException ("buffer");
1852 CheckRange (buf, offset, size);
1854 return Send_nochecks (buf, offset, size, flags, out error);
1857 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1858 private extern static bool SendFile (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
1860 public void SendFile (string fileName)
1862 if (disposed && closed)
1863 throw new ObjectDisposedException (GetType ().ToString ());
1865 if (!connected)
1866 throw new NotSupportedException ();
1868 if (!blocking)
1869 throw new InvalidOperationException ();
1871 SendFile (fileName, null, null, 0);
1874 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
1876 if (disposed && closed)
1877 throw new ObjectDisposedException (GetType ().ToString ());
1879 if (!connected)
1880 throw new NotSupportedException ();
1882 if (!blocking)
1883 throw new InvalidOperationException ();
1885 if (!SendFile (socket, fileName, preBuffer, postBuffer, flags)) {
1886 SocketException exc = new SocketException ();
1887 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
1888 throw new FileNotFoundException ();
1889 throw exc;
1893 public bool SendToAsync (SocketAsyncEventArgs e)
1895 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1897 if (disposed && closed)
1898 throw new ObjectDisposedException (GetType ().ToString ());
1899 if (e.BufferList != null)
1900 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1901 if (e.RemoteEndPoint == null)
1902 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1904 e.curSocket = this;
1905 e.Worker.Init (this, e, SocketOperation.SendTo);
1906 SocketAsyncResult res = e.Worker.result;
1907 res.Buffer = e.Buffer;
1908 res.Offset = e.Offset;
1909 res.Size = e.Count;
1910 res.SockFlags = e.SocketFlags;
1911 res.EndPoint = e.RemoteEndPoint;
1912 int count;
1913 lock (writeQ) {
1914 writeQ.Enqueue (e.Worker);
1915 count = writeQ.Count;
1917 if (count == 1)
1918 socket_pool_queue (Worker.Dispatcher, res);
1919 return true;
1922 public int SendTo (byte [] buffer, EndPoint remote_end)
1924 if (disposed && closed)
1925 throw new ObjectDisposedException (GetType ().ToString ());
1927 if (buffer == null)
1928 throw new ArgumentNullException ("buffer");
1930 if (remote_end == null)
1931 throw new ArgumentNullException ("remote_end");
1933 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
1936 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
1938 if (disposed && closed)
1939 throw new ObjectDisposedException (GetType ().ToString ());
1941 if (buffer == null)
1942 throw new ArgumentNullException ("buffer");
1944 if (remote_end == null)
1945 throw new ArgumentNullException ("remote_end");
1947 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
1950 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
1952 if (disposed && closed)
1953 throw new ObjectDisposedException (GetType ().ToString ());
1955 if (buffer == null)
1956 throw new ArgumentNullException ("buffer");
1958 if (remote_end == null)
1959 throw new ArgumentNullException ("remote_end");
1961 CheckRange (buffer, 0, size);
1963 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
1966 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1967 private extern static int SendTo_internal(IntPtr sock,
1968 byte[] buffer,
1969 int offset,
1970 int count,
1971 SocketFlags flags,
1972 SocketAddress sa,
1973 out int error);
1975 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
1976 EndPoint remote_end)
1978 if (disposed && closed)
1979 throw new ObjectDisposedException (GetType ().ToString ());
1981 if (buffer == null)
1982 throw new ArgumentNullException ("buffer");
1984 if (remote_end == null)
1985 throw new ArgumentNullException("remote_end");
1987 CheckRange (buffer, offset, size);
1989 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
1992 internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
1993 EndPoint remote_end)
1995 SocketAddress sockaddr = remote_end.Serialize ();
1997 int ret, error;
1999 ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
2001 SocketError err = (SocketError) error;
2002 if (err != 0) {
2003 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2004 connected = false;
2006 throw new SocketException (error);
2009 connected = true;
2010 isbound = true;
2011 seed_endpoint = remote_end;
2013 return ret;
2016 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2018 if (disposed && closed)
2019 throw new ObjectDisposedException (GetType ().ToString ());
2021 // I'd throw an ArgumentNullException, but this is what MS does.
2022 if (optionValue == null)
2023 throw new SocketException ((int) SocketError.Fault,
2024 "Error trying to dereference an invalid pointer");
2026 int error;
2028 SetSocketOption_internal (socket, optionLevel, optionName, null,
2029 optionValue, 0, out error);
2031 if (error != 0) {
2032 if (error == (int) SocketError.InvalidArgument)
2033 throw new ArgumentException ();
2034 throw new SocketException (error);
2038 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
2040 if (disposed && closed)
2041 throw new ObjectDisposedException (GetType ().ToString ());
2043 // NOTE: if a null is passed, the byte[] overload is used instead...
2044 if (optionValue == null)
2045 throw new ArgumentNullException("optionValue");
2047 int error;
2049 if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
2050 LingerOption linger = optionValue as LingerOption;
2051 if (linger == null)
2052 throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
2053 SetSocketOption_internal (socket, optionLevel, optionName, linger, null, 0, out error);
2054 } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2055 MulticastOption multicast = optionValue as MulticastOption;
2056 if (multicast == null)
2057 throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
2058 SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
2059 } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2060 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
2061 if (multicast == null)
2062 throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
2063 SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
2064 } else {
2065 throw new ArgumentException ("Invalid value specified.", "optionValue");
2068 if (error != 0) {
2069 if (error == (int) SocketError.InvalidArgument)
2070 throw new ArgumentException ();
2071 throw new SocketException (error);
2075 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
2077 if (disposed && closed)
2078 throw new ObjectDisposedException (GetType ().ToString ());
2080 int error;
2081 int int_val = (optionValue) ? 1 : 0;
2082 SetSocketOption_internal (socket, optionLevel, optionName, null, null, int_val, out error);
2083 if (error != 0) {
2084 if (error == (int) SocketError.InvalidArgument)
2085 throw new ArgumentException ();
2086 throw new SocketException (error);