1 // System.Net.Sockets.Socket.cs
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)
10 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
11 // http://www.myelin.co.nz
12 // (c) 2004-2006 Novell, Inc. (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 using System.Collections;
39 using System.Collections.Generic;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
42 using System.Threading;
43 using System.Reflection;
45 using System.Net.Configuration;
49 using System.Net.NetworkInformation;
52 namespace System.Net.Sockets
54 public partial class Socket : IDisposable
56 private bool islistening;
57 private bool useoverlappedIO;
59 static void AddSockets (List<Socket> sockets, IList list, string name)
62 foreach (Socket sock in list) {
63 if (sock == null) // MS throws a NullRef
64 throw new ArgumentNullException ("name", "Contains a null element");
72 [MethodImplAttribute(MethodImplOptions.InternalCall)]
73 private extern static void Select_internal (ref Socket [] sockets,
77 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
79 var list = new List<Socket> ();
80 AddSockets (list, checkRead, "checkRead");
81 AddSockets (list, checkWrite, "checkWrite");
82 AddSockets (list, checkError, "checkError");
84 if (list.Count == 3) {
85 throw new ArgumentNullException ("checkRead, checkWrite, checkError",
86 "All the lists are null or empty.");
91 * The 'sockets' array contains: READ socket 0-n, null,
92 * WRITE socket 0-n, null,
93 * ERROR socket 0-n, null
95 Socket [] sockets = list.ToArray ();
96 Select_internal (ref sockets, microSeconds, out error);
99 throw new SocketException (error);
101 if (sockets == null) {
102 if (checkRead != null)
104 if (checkWrite != null)
106 if (checkError != null)
112 int count = sockets.Length;
113 IList currentList = checkRead;
115 for (int i = 0; i < count; i++) {
116 Socket sock = sockets [i];
117 if (sock == null) { // separator
118 if (currentList != null) {
119 // Remove non-signaled sockets after the current one
120 int to_remove = currentList.Count - currentIdx;
121 for (int k = 0; k < to_remove; k++)
122 currentList.RemoveAt (currentIdx);
124 currentList = (mode == 0) ? checkWrite : checkError;
130 if (mode == 1 && currentList == checkWrite && !sock.connected) {
131 if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
132 sock.connected = true;
135 // Remove non-signaled sockets before the current one
136 //int max = currentList.Count;
137 while (((Socket) currentList [currentIdx]) != sock) {
138 currentList.RemoveAt (currentIdx);
144 // private constructor used by Accept, which already
145 // has a socket handle to use
146 internal Socket(AddressFamily family, SocketType type,
147 ProtocolType proto, IntPtr sock)
149 address_family=family;
157 private void SocketDefaults ()
160 if (address_family == AddressFamily.InterNetwork /* Need to test IPv6 further ||
161 address_family == AddressFamily.InterNetworkV6 */) {
162 /* This is the default, but it
163 * probably has nasty side
164 * effects on Linux, as the
165 * socket option is kludged by
166 * turning on or off PMTU
169 this.DontFragment = false;
173 // Microsoft sets these to 8192, but we are going to keep them
174 // both to the OS defaults as these have a big performance impact.
175 // on WebClient performance.
177 //this.ReceiveBufferSize = 8192;
178 //this.SendBufferSize = 8192;
179 } catch (SocketException) {
184 public Socket (SocketInformation socketInformation)
186 var options = socketInformation.Options;
187 islistening = (options & SocketInformationOptions.Listening) != 0;
188 connected = (options & SocketInformationOptions.Connected) != 0;
189 blocking = (options & SocketInformationOptions.NonBlocking) == 0;
190 useoverlappedIO = (options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
192 var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
194 address_family = (AddressFamily) (int) result [0];
195 socket_type = (SocketType) (int) result [1];
196 protocol_type = (ProtocolType) (int) result [2];
197 isbound = (ProtocolType) (int) result [3] != 0;
198 socket = (IntPtr) (long) result [4];
204 // Returns the amount of data waiting to be read on socket
205 [MethodImplAttribute(MethodImplOptions.InternalCall)]
206 private extern static int Available_internal(IntPtr socket, out int error);
209 public int Available {
211 if (disposed && closed)
212 throw new ObjectDisposedException (GetType ().ToString ());
216 ret = Available_internal(socket, out error);
219 throw new SocketException (error);
226 public bool DontFragment {
228 if (disposed && closed) {
229 throw new ObjectDisposedException (GetType ().ToString ());
234 if (address_family == AddressFamily.InterNetwork) {
235 dontfragment = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
236 } else if (address_family == AddressFamily.InterNetworkV6) {
237 dontfragment = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
239 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
242 return(dontfragment);
245 if (disposed && closed) {
246 throw new ObjectDisposedException (GetType ().ToString ());
249 if (address_family == AddressFamily.InterNetwork) {
250 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value?1:0);
251 } else if (address_family == AddressFamily.InterNetworkV6) {
252 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value?1:0);
254 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
259 public bool EnableBroadcast {
261 if (disposed && closed) {
262 throw new ObjectDisposedException (GetType ().ToString ());
265 if (protocol_type != ProtocolType.Udp) {
266 throw new SocketException ((int)SocketError.ProtocolOption);
269 return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0);
272 if (disposed && closed) {
273 throw new ObjectDisposedException (GetType ().ToString ());
276 if (protocol_type != ProtocolType.Udp) {
277 throw new SocketException ((int)SocketError.ProtocolOption);
280 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value?1:0);
284 public bool ExclusiveAddressUse {
286 if (disposed && closed) {
287 throw new ObjectDisposedException (GetType ().ToString ());
290 return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0);
293 if (disposed && closed) {
294 throw new ObjectDisposedException (GetType ().ToString ());
297 throw new InvalidOperationException ("Bind has already been called for this socket");
300 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value?1:0);
304 public bool IsBound {
310 public LingerOption LingerState {
312 if (disposed && closed) {
313 throw new ObjectDisposedException (GetType ().ToString ());
316 return((LingerOption)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger));
319 if (disposed && closed) {
320 throw new ObjectDisposedException (GetType ().ToString ());
323 SetSocketOption (SocketOptionLevel.Socket,
324 SocketOptionName.Linger,
329 public bool MulticastLoopback {
331 if (disposed && closed) {
332 throw new ObjectDisposedException (GetType ().ToString ());
335 /* Even though this option can be set
336 * for TCP sockets on Linux, throw
337 * this exception anyway to be
338 * compatible (the MSDN docs say
339 * "Setting this property on a
340 * Transmission Control Protocol (TCP)
341 * socket will have no effect." but
342 * the MS runtime throws the
345 if (protocol_type == ProtocolType.Tcp) {
346 throw new SocketException ((int)SocketError.ProtocolOption);
349 bool multicastloopback;
351 if (address_family == AddressFamily.InterNetwork) {
352 multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
353 } else if (address_family == AddressFamily.InterNetworkV6) {
354 multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
356 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
359 return(multicastloopback);
362 if (disposed && closed) {
363 throw new ObjectDisposedException (GetType ().ToString ());
366 /* Even though this option can be set
367 * for TCP sockets on Linux, throw
368 * this exception anyway to be
369 * compatible (the MSDN docs say
370 * "Setting this property on a
371 * Transmission Control Protocol (TCP)
372 * socket will have no effect." but
373 * the MS runtime throws the
376 if (protocol_type == ProtocolType.Tcp) {
377 throw new SocketException ((int)SocketError.ProtocolOption);
380 if (address_family == AddressFamily.InterNetwork) {
381 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value?1:0);
382 } else if (address_family == AddressFamily.InterNetworkV6) {
383 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value?1:0);
385 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
391 [MonoTODO ("This doesn't do anything on Mono yet")]
392 public bool UseOnlyOverlappedIO {
394 return(useoverlappedIO);
397 useoverlappedIO = value;
401 public IntPtr Handle {
408 // Returns the local endpoint details in addr and port
409 [MethodImplAttribute(MethodImplOptions.InternalCall)]
410 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, int family, out int error);
413 // Wish: support non-IP endpoints.
414 public EndPoint LocalEndPoint {
416 if (disposed && closed)
417 throw new ObjectDisposedException (GetType ().ToString ());
420 * If the seed EndPoint is null, Connect, Bind,
421 * etc has not yet been called. MS returns null
424 if (seed_endpoint == null)
430 sa=LocalEndPoint_internal(socket, (int) address_family, out error);
433 throw new SocketException (error);
435 return seed_endpoint.Create (sa);
439 public SocketType SocketType {
445 public int SendTimeout {
447 if (disposed && closed)
448 throw new ObjectDisposedException (GetType ().ToString ());
450 return (int)GetSocketOption(
451 SocketOptionLevel.Socket,
452 SocketOptionName.SendTimeout);
455 if (disposed && closed)
456 throw new ObjectDisposedException (GetType ().ToString ());
459 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
461 /* According to the MSDN docs we
462 * should adjust values between 1 and
463 * 499 to 500, but the MS runtime
470 SocketOptionLevel.Socket,
471 SocketOptionName.SendTimeout, value);
475 public int ReceiveTimeout {
477 if (disposed && closed)
478 throw new ObjectDisposedException (GetType ().ToString ());
480 return (int)GetSocketOption(
481 SocketOptionLevel.Socket,
482 SocketOptionName.ReceiveTimeout);
485 if (disposed && closed)
486 throw new ObjectDisposedException (GetType ().ToString ());
489 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
496 SocketOptionLevel.Socket,
497 SocketOptionName.ReceiveTimeout, value);
502 public bool AcceptAsync (SocketAsyncEventArgs e)
504 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
506 if (disposed && closed)
507 throw new ObjectDisposedException (GetType ().ToString ());
509 throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
511 throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
512 if (e.BufferList != null)
513 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
515 throw new ArgumentOutOfRangeException ("e.Count");
517 Socket acceptSocket = e.AcceptSocket;
518 if (acceptSocket != null) {
519 if (acceptSocket.IsBound || acceptSocket.Connected)
520 throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
525 w.Init (this, null, e.AcceptCallback, SocketOperation.Accept);
526 socket_pool_queue (w.Accept, w.result);
530 // Creates a new system socket, returning the handle
531 [MethodImplAttribute(MethodImplOptions.InternalCall)]
532 private extern static IntPtr Accept_internal(IntPtr sock, out int error, bool blocking);
534 public Socket Accept() {
535 if (disposed && closed)
536 throw new ObjectDisposedException (GetType ().ToString ());
539 IntPtr sock = (IntPtr) (-1);
540 blocking_thread = Thread.CurrentThread;
542 sock = Accept_internal(socket, out error, blocking);
543 } catch (ThreadAbortException) {
545 Thread.ResetAbort ();
546 error = (int) SocketError.Interrupted;
549 blocking_thread = null;
553 throw new SocketException (error);
555 Socket accepted = new Socket(this.AddressFamily, this.SocketType,
556 this.ProtocolType, sock);
558 accepted.seed_endpoint = this.seed_endpoint;
559 accepted.Blocking = this.Blocking;
563 internal void Accept (Socket acceptSocket)
565 if (disposed && closed)
566 throw new ObjectDisposedException (GetType ().ToString ());
569 IntPtr sock = (IntPtr)(-1);
570 blocking_thread = Thread.CurrentThread;
573 sock = Accept_internal (socket, out error, blocking);
574 } catch (ThreadAbortException) {
576 Thread.ResetAbort ();
577 error = (int)SocketError.Interrupted;
580 blocking_thread = null;
584 throw new SocketException (error);
586 acceptSocket.address_family = this.AddressFamily;
587 acceptSocket.socket_type = this.SocketType;
588 acceptSocket.protocol_type = this.ProtocolType;
589 acceptSocket.socket = sock;
590 acceptSocket.connected = true;
591 acceptSocket.seed_endpoint = this.seed_endpoint;
592 acceptSocket.Blocking = this.Blocking;
594 /* FIXME: figure out what if anything else
599 public IAsyncResult BeginAccept(AsyncCallback callback, object state)
601 if (disposed && closed)
602 throw new ObjectDisposedException (GetType ().ToString ());
604 if (!isbound || !islistening)
605 throw new InvalidOperationException ();
607 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
608 Worker worker = new Worker (req);
609 socket_pool_queue (worker.Accept, req);
613 public IAsyncResult BeginAccept (int receiveSize,
614 AsyncCallback callback,
617 if (disposed && closed)
618 throw new ObjectDisposedException (GetType ().ToString ());
621 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
623 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
624 Worker worker = new Worker (req);
625 req.Buffer = new byte[receiveSize];
627 req.Size = receiveSize;
628 req.SockFlags = SocketFlags.None;
629 socket_pool_queue (worker.AcceptReceive, req);
633 public IAsyncResult BeginAccept (Socket acceptSocket,
635 AsyncCallback callback,
638 if (disposed && closed)
639 throw new ObjectDisposedException (GetType ().ToString ());
642 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
644 if (acceptSocket != null) {
645 if (acceptSocket.disposed && acceptSocket.closed)
646 throw new ObjectDisposedException (acceptSocket.GetType ().ToString ());
648 if (acceptSocket.IsBound)
649 throw new InvalidOperationException ();
651 /* For some reason the MS runtime
652 * barfs if the new socket is not TCP,
653 * even though it's just about to blow
654 * away all those parameters
656 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
657 throw new SocketException ((int)SocketError.InvalidArgument);
660 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
661 Worker worker = new Worker (req);
662 req.Buffer = new byte[receiveSize];
664 req.Size = receiveSize;
665 req.SockFlags = SocketFlags.None;
666 req.AcceptSocket = acceptSocket;
667 socket_pool_queue (worker.AcceptReceive, req);
671 public IAsyncResult BeginConnect(EndPoint end_point,
672 AsyncCallback callback,
675 if (disposed && closed)
676 throw new ObjectDisposedException (GetType ().ToString ());
678 if (end_point == null)
679 throw new ArgumentNullException ("end_point");
681 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
682 req.EndPoint = end_point;
684 // Bug #75154: Connect() should not succeed for .Any addresses.
685 if (end_point is IPEndPoint) {
686 IPEndPoint ep = (IPEndPoint) end_point;
687 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
688 req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
695 SocketAddress serial = end_point.Serialize ();
696 Connect_internal (socket, serial, out error);
701 } else if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
704 req.Complete (new SocketException (error), true);
708 if (blocking || error == (int) SocketError.InProgress || error == (int) SocketError.WouldBlock) {
711 Worker worker = new Worker (req);
712 socket_pool_queue (worker.Connect, req);
718 public IAsyncResult BeginConnect (IPAddress address, int port,
719 AsyncCallback callback,
722 if (disposed && closed)
723 throw new ObjectDisposedException (GetType ().ToString ());
726 throw new ArgumentNullException ("address");
728 if (address.ToString ().Length == 0)
729 throw new ArgumentException ("The length of the IP address is zero");
732 throw new InvalidOperationException ();
734 IPEndPoint iep = new IPEndPoint (address, port);
735 return(BeginConnect (iep, callback, state));
738 public IAsyncResult BeginConnect (IPAddress[] addresses,
740 AsyncCallback callback,
743 if (disposed && closed)
744 throw new ObjectDisposedException (GetType ().ToString ());
746 if (addresses == null)
747 throw new ArgumentNullException ("addresses");
749 if (this.AddressFamily != AddressFamily.InterNetwork &&
750 this.AddressFamily != AddressFamily.InterNetworkV6)
751 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
754 throw new InvalidOperationException ();
756 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
757 req.Addresses = addresses;
761 Worker worker = new Worker (req);
762 socket_pool_queue (worker.Connect, req);
767 public IAsyncResult BeginConnect (string host, int port,
768 AsyncCallback callback,
771 if (disposed && closed)
772 throw new ObjectDisposedException (GetType ().ToString ());
775 throw new ArgumentNullException ("host");
777 if (address_family != AddressFamily.InterNetwork &&
778 address_family != AddressFamily.InterNetworkV6)
779 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
782 throw new InvalidOperationException ();
784 IPAddress [] addresses = Dns.GetHostAddresses (host);
785 return (BeginConnect (addresses, port, callback, state));
788 public IAsyncResult BeginDisconnect (bool reuseSocket,
789 AsyncCallback callback,
792 if (disposed && closed)
793 throw new ObjectDisposedException (GetType ().ToString ());
795 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
796 req.ReuseSocket = reuseSocket;
798 Worker worker = new Worker (req);
799 socket_pool_queue (worker.Disconnect, req);
804 public IAsyncResult BeginReceive(byte[] buffer, int offset,
806 SocketFlags socket_flags,
807 AsyncCallback callback,
810 if (disposed && closed)
811 throw new ObjectDisposedException (GetType ().ToString ());
814 throw new ArgumentNullException ("buffer");
816 if (offset < 0 || offset > buffer.Length)
817 throw new ArgumentOutOfRangeException ("offset");
819 if (size < 0 || offset + size > buffer.Length)
820 throw new ArgumentOutOfRangeException ("size");
822 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
826 req.SockFlags = socket_flags;
827 Worker worker = new Worker (req);
830 readQ.Enqueue (worker);
834 socket_pool_queue (worker.Receive, req);
838 public IAsyncResult BeginReceive (byte[] buffer, int offset,
839 int size, SocketFlags flags,
840 out SocketError error,
841 AsyncCallback callback,
844 /* As far as I can tell from the docs and from
845 * experimentation, a pointer to the
846 * SocketError parameter is not supposed to be
847 * saved for the async parts. And as we don't
848 * set any socket errors in the setup code, we
849 * just have to set it to Success.
851 error = SocketError.Success;
852 return (BeginReceive (buffer, offset, size, flags, callback, state));
855 [CLSCompliant (false)]
856 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
857 SocketFlags socketFlags,
858 AsyncCallback callback,
861 if (disposed && closed)
862 throw new ObjectDisposedException (GetType ().ToString ());
865 throw new ArgumentNullException ("buffers");
867 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
868 req.Buffers = buffers;
869 req.SockFlags = socketFlags;
870 Worker worker = new Worker (req);
873 readQ.Enqueue (worker);
877 socket_pool_queue (worker.ReceiveGeneric, req);
881 [CLSCompliant (false)]
882 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
883 SocketFlags socketFlags,
884 out SocketError errorCode,
885 AsyncCallback callback,
888 /* I assume the same SocketError semantics as
891 errorCode = SocketError.Success;
892 return (BeginReceive (buffers, socketFlags, callback, state));
895 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
897 SocketFlags socket_flags,
898 ref EndPoint remote_end,
899 AsyncCallback callback,
901 if (disposed && closed)
902 throw new ObjectDisposedException (GetType ().ToString ());
905 throw new ArgumentNullException ("buffer");
907 if (remote_end == null)
908 throw new ArgumentNullException ("remote_end");
911 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
914 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
916 if (offset + size > buffer.Length)
917 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
919 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
923 req.SockFlags = socket_flags;
924 req.EndPoint = remote_end;
925 Worker worker = new Worker (req);
928 readQ.Enqueue (worker);
932 socket_pool_queue (worker.ReceiveFrom, req);
937 public IAsyncResult BeginReceiveMessageFrom (
938 byte[] buffer, int offset, int size,
939 SocketFlags socketFlags, ref EndPoint remoteEP,
940 AsyncCallback callback, object state)
942 if (disposed && closed)
943 throw new ObjectDisposedException (GetType ().ToString ());
946 throw new ArgumentNullException ("buffer");
948 if (remoteEP == null)
949 throw new ArgumentNullException ("remoteEP");
951 if (offset < 0 || offset > buffer.Length)
952 throw new ArgumentOutOfRangeException ("offset");
954 if (size < 0 || offset + size > buffer.Length)
955 throw new ArgumentOutOfRangeException ("size");
957 throw new NotImplementedException ();
960 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
961 AsyncCallback callback, object state)
963 if (disposed && closed)
964 throw new ObjectDisposedException (GetType ().ToString ());
967 throw new ArgumentNullException ("buffer");
970 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
973 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
975 if (offset + size > buffer.Length)
976 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
979 throw new SocketException ((int)SocketError.NotConnected);
981 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
985 req.SockFlags = socket_flags;
986 Worker worker = new Worker (req);
989 writeQ.Enqueue (worker);
990 count = writeQ.Count;
993 socket_pool_queue (worker.Send, req);
997 public IAsyncResult BeginSend (byte[] buffer, int offset,
999 SocketFlags socketFlags,
1000 out SocketError errorCode,
1001 AsyncCallback callback,
1005 errorCode = SocketError.NotConnected;
1006 throw new SocketException ((int)errorCode);
1009 errorCode = SocketError.Success;
1011 return (BeginSend (buffer, offset, size, socketFlags, callback,
1015 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
1016 SocketFlags socketFlags,
1017 AsyncCallback callback,
1020 if (disposed && closed)
1021 throw new ObjectDisposedException (GetType ().ToString ());
1023 if (buffers == null)
1024 throw new ArgumentNullException ("buffers");
1027 throw new SocketException ((int)SocketError.NotConnected);
1029 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
1030 req.Buffers = buffers;
1031 req.SockFlags = socketFlags;
1032 Worker worker = new Worker (req);
1035 writeQ.Enqueue (worker);
1036 count = writeQ.Count;
1039 socket_pool_queue (worker.SendGeneric, req);
1043 [CLSCompliant (false)]
1044 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
1045 SocketFlags socketFlags,
1046 out SocketError errorCode,
1047 AsyncCallback callback,
1051 errorCode = SocketError.NotConnected;
1052 throw new SocketException ((int)errorCode);
1055 errorCode = SocketError.Success;
1056 return (BeginSend (buffers, socketFlags, callback, state));
1059 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
1061 sealed class SendFileAsyncResult : IAsyncResult {
1065 public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
1071 public object AsyncState {
1072 get { return ares.AsyncState; }
1075 public WaitHandle AsyncWaitHandle {
1076 get { return ares.AsyncWaitHandle; }
1079 public bool CompletedSynchronously {
1080 get { return ares.CompletedSynchronously; }
1083 public bool IsCompleted {
1084 get { return ares.IsCompleted; }
1087 public SendFileHandler Delegate {
1091 public IAsyncResult Original {
1092 get { return ares; }
1096 public IAsyncResult BeginSendFile (string fileName,
1097 AsyncCallback callback,
1100 if (disposed && closed)
1101 throw new ObjectDisposedException (GetType ().ToString ());
1104 throw new NotSupportedException ();
1106 if (!File.Exists (fileName))
1107 throw new FileNotFoundException ();
1109 return BeginSendFile (fileName, null, null, 0, callback, state);
1112 public IAsyncResult BeginSendFile (string fileName,
1115 TransmitFileOptions flags,
1116 AsyncCallback callback,
1119 if (disposed && closed)
1120 throw new ObjectDisposedException (GetType ().ToString ());
1123 throw new NotSupportedException ();
1125 if (!File.Exists (fileName))
1126 throw new FileNotFoundException ();
1128 SendFileHandler d = new SendFileHandler (SendFile);
1129 return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, callback, state));
1132 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
1134 SocketFlags socket_flags,
1135 EndPoint remote_end,
1136 AsyncCallback callback,
1138 if (disposed && closed)
1139 throw new ObjectDisposedException (GetType ().ToString ());
1142 throw new ArgumentNullException ("buffer");
1145 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1148 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1150 if (offset + size > buffer.Length)
1151 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
1153 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
1154 req.Buffer = buffer;
1155 req.Offset = offset;
1157 req.SockFlags = socket_flags;
1158 req.EndPoint = remote_end;
1159 Worker worker = new Worker (req);
1162 writeQ.Enqueue (worker);
1163 count = writeQ.Count;
1166 socket_pool_queue (worker.SendTo, req);
1170 // Creates a new system socket, returning the handle
1171 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1172 private extern static void Bind_internal(IntPtr sock,
1176 public void Bind(EndPoint local_end) {
1177 if (disposed && closed)
1178 throw new ObjectDisposedException (GetType ().ToString ());
1180 if (local_end == null)
1181 throw new ArgumentNullException("local_end");
1185 Bind_internal(socket, local_end.Serialize(), out error);
1187 throw new SocketException (error);
1191 seed_endpoint = local_end;
1195 public bool ConnectAsync (SocketAsyncEventArgs e)
1197 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1199 if (disposed && closed)
1200 throw new ObjectDisposedException (GetType ().ToString ());
1202 throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1203 if (e.RemoteEndPoint == null)
1204 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1205 if (e.BufferList != null)
1206 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
1208 e.DoOperation (SocketAsyncOperation.Connect, this);
1210 // We always return true for now
1215 public void Connect (IPAddress address, int port)
1217 Connect (new IPEndPoint (address, port));
1220 public void Connect (IPAddress[] addresses, int port)
1222 if (disposed && closed)
1223 throw new ObjectDisposedException (GetType ().ToString ());
1225 if (addresses == null)
1226 throw new ArgumentNullException ("addresses");
1228 if (this.AddressFamily != AddressFamily.InterNetwork &&
1229 this.AddressFamily != AddressFamily.InterNetworkV6)
1230 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1233 throw new InvalidOperationException ();
1235 /* FIXME: do non-blocking sockets Poll here? */
1237 foreach (IPAddress address in addresses) {
1238 IPEndPoint iep = new IPEndPoint (address, port);
1239 SocketAddress serial = iep.Serialize ();
1241 Connect_internal (socket, serial, out error);
1245 seed_endpoint = iep;
1247 } else if (error != (int)SocketError.InProgress &&
1248 error != (int)SocketError.WouldBlock) {
1253 Poll (-1, SelectMode.SelectWrite);
1254 error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1258 seed_endpoint = iep;
1264 throw new SocketException (error);
1267 public void Connect (string host, int port)
1269 IPAddress [] addresses = Dns.GetHostAddresses (host);
1270 Connect (addresses, port);
1274 public bool DisconnectAsync (SocketAsyncEventArgs e)
1276 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1277 if (disposed && closed)
1278 throw new ObjectDisposedException (GetType ().ToString ());
1281 e.Worker.Init (this, null, e.DisconnectCallback, SocketOperation.Disconnect);
1282 socket_pool_queue (e.Worker.Disconnect, e.Worker.result);
1287 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1288 extern static void Disconnect_internal(IntPtr sock, bool reuse, out int error);
1290 /* According to the docs, the MS runtime will throw
1291 * PlatformNotSupportedException if the platform is
1292 * newer than w2k. We should be able to cope...
1294 public void Disconnect (bool reuseSocket)
1296 if (disposed && closed)
1297 throw new ObjectDisposedException (GetType ().ToString ());
1301 Disconnect_internal (socket, reuseSocket, out error);
1305 /* ERROR_NOT_SUPPORTED */
1306 throw new PlatformNotSupportedException ();
1308 throw new SocketException (error);
1315 /* Do managed housekeeping here... */
1320 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
1321 public SocketInformation DuplicateAndClose (int targetProcessId)
1323 var si = new SocketInformation ();
1325 (islistening ? SocketInformationOptions.Listening : 0) |
1326 (connected ? SocketInformationOptions.Connected : 0) |
1327 (blocking ? 0 : SocketInformationOptions.NonBlocking) |
1328 (useoverlappedIO ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
1330 si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, isbound ? 1 : 0, (long)socket);
1331 socket = (IntPtr) (-1);
1337 public Socket EndAccept (IAsyncResult result)
1342 return(EndAccept (out buffer, out bytes, result));
1345 public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
1348 return(EndAccept (out buffer, out bytes, asyncResult));
1351 public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
1353 if (disposed && closed)
1354 throw new ObjectDisposedException (GetType ().ToString ());
1356 if (asyncResult == null)
1357 throw new ArgumentNullException ("asyncResult");
1359 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1361 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1363 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1364 throw InvalidAsyncOp ("EndAccept");
1365 if (!asyncResult.IsCompleted)
1366 asyncResult.AsyncWaitHandle.WaitOne ();
1368 req.CheckIfThrowDelayedException ();
1370 buffer = req.Buffer;
1371 bytesTransferred = req.Total;
1376 public void EndConnect (IAsyncResult result)
1378 if (disposed && closed)
1379 throw new ObjectDisposedException (GetType ().ToString ());
1382 throw new ArgumentNullException ("result");
1384 SocketAsyncResult req = result as SocketAsyncResult;
1386 throw new ArgumentException ("Invalid IAsyncResult", "result");
1388 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1389 throw InvalidAsyncOp ("EndConnect");
1390 if (!result.IsCompleted)
1391 result.AsyncWaitHandle.WaitOne();
1393 req.CheckIfThrowDelayedException();
1397 public void EndDisconnect (IAsyncResult asyncResult)
1399 if (disposed && closed)
1400 throw new ObjectDisposedException (GetType ().ToString ());
1402 if (asyncResult == null)
1403 throw new ArgumentNullException ("asyncResult");
1405 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1407 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1409 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1410 throw InvalidAsyncOp ("EndDisconnect");
1411 if (!asyncResult.IsCompleted)
1412 asyncResult.AsyncWaitHandle.WaitOne ();
1414 req.CheckIfThrowDelayedException ();
1419 public int EndReceiveMessageFrom (IAsyncResult asyncResult,
1420 ref SocketFlags socketFlags,
1421 ref EndPoint endPoint,
1422 out IPPacketInformation ipPacketInformation)
1424 if (disposed && closed)
1425 throw new ObjectDisposedException (GetType ().ToString ());
1427 if (asyncResult == null)
1428 throw new ArgumentNullException ("asyncResult");
1430 if (endPoint == null)
1431 throw new ArgumentNullException ("endPoint");
1433 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1435 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1437 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1438 throw InvalidAsyncOp ("EndReceiveMessageFrom");
1439 throw new NotImplementedException ();
1442 public void EndSendFile (IAsyncResult asyncResult)
1444 if (disposed && closed)
1445 throw new ObjectDisposedException (GetType ().ToString ());
1447 if (asyncResult == null)
1448 throw new ArgumentNullException ("asyncResult");
1450 SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
1452 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1454 ares.Delegate.EndInvoke (ares.Original);
1458 public int EndSendTo (IAsyncResult result)
1460 if (disposed && closed)
1461 throw new ObjectDisposedException (GetType ().ToString ());
1464 throw new ArgumentNullException ("result");
1466 SocketAsyncResult req = result as SocketAsyncResult;
1468 throw new ArgumentException ("Invalid IAsyncResult", "result");
1470 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1471 throw InvalidAsyncOp ("EndSendTo");
1472 if (!result.IsCompleted)
1473 result.AsyncWaitHandle.WaitOne();
1475 req.CheckIfThrowDelayedException();
1480 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1481 private extern static void GetSocketOption_arr_internal(IntPtr socket,
1482 SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
1485 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
1487 if (disposed && closed)
1488 throw new ObjectDisposedException (GetType ().ToString ());
1490 if (optionValue == null)
1491 throw new SocketException ((int) SocketError.Fault,
1492 "Error trying to dereference an invalid pointer");
1496 GetSocketOption_arr_internal (socket, optionLevel, optionName, ref optionValue,
1499 throw new SocketException (error);
1502 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
1504 if (disposed && closed)
1505 throw new ObjectDisposedException (GetType ().ToString ());
1507 byte[] byte_val=new byte[length];
1510 GetSocketOption_arr_internal (socket, optionLevel, optionName, ref byte_val,
1513 throw new SocketException (error);
1518 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1519 // common options between UNIX and Winsock are FIONREAD,
1520 // FIONBIO and SIOCATMARK. Anything else will depend on the
1521 // system except SIO_KEEPALIVE_VALS which is properly handled
1522 // on both windows and linux.
1523 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1524 extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
1525 byte [] output, out int error);
1527 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1530 throw new ObjectDisposedException (GetType ().ToString ());
1533 int result = WSAIoctl (socket, ioctl_code, in_value, out_value,
1537 throw new SocketException (error);
1540 throw new InvalidOperationException ("Must use Blocking property instead.");
1545 public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
1547 return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
1550 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1551 private extern static void Listen_internal(IntPtr sock, int backlog, out int error);
1553 public void Listen (int backlog)
1555 if (disposed && closed)
1556 throw new ObjectDisposedException (GetType ().ToString ());
1559 throw new SocketException ((int)SocketError.InvalidArgument);
1562 Listen_internal(socket, backlog, out error);
1565 throw new SocketException (error);
1570 public bool Poll (int time_us, SelectMode mode)
1572 if (disposed && closed)
1573 throw new ObjectDisposedException (GetType ().ToString ());
1575 if (mode != SelectMode.SelectRead &&
1576 mode != SelectMode.SelectWrite &&
1577 mode != SelectMode.SelectError)
1578 throw new NotSupportedException ("'mode' parameter is not valid.");
1581 bool result = Poll_internal (socket, mode, time_us, out error);
1583 throw new SocketException (error);
1585 if (mode == SelectMode.SelectWrite && result && !connected) {
1586 /* Update the connected state; for
1587 * non-blocking Connect()s this is
1588 * when we can find out that the
1589 * connect succeeded.
1591 if ((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
1599 public int Receive (byte [] buffer)
1601 if (disposed && closed)
1602 throw new ObjectDisposedException (GetType ().ToString ());
1605 throw new ArgumentNullException ("buffer");
1609 int ret = Receive_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
1611 if (error != SocketError.Success)
1612 throw new SocketException ((int) error);
1617 public int Receive (byte [] buffer, SocketFlags flags)
1619 if (disposed && closed)
1620 throw new ObjectDisposedException (GetType ().ToString ());
1623 throw new ArgumentNullException ("buffer");
1627 int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
1629 if (error != SocketError.Success) {
1630 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1631 throw new SocketException ((int) error, "Operation timed out.");
1632 throw new SocketException ((int) error);
1638 public int Receive (byte [] buffer, int size, SocketFlags flags)
1640 if (disposed && closed)
1641 throw new ObjectDisposedException (GetType ().ToString ());
1644 throw new ArgumentNullException ("buffer");
1646 if (size < 0 || size > buffer.Length)
1647 throw new ArgumentOutOfRangeException ("size");
1651 int ret = Receive_nochecks (buffer, 0, size, flags, out error);
1653 if (error != SocketError.Success) {
1654 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1655 throw new SocketException ((int) error, "Operation timed out.");
1656 throw new SocketException ((int) error);
1662 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
1664 if (disposed && closed)
1665 throw new ObjectDisposedException (GetType ().ToString ());
1668 throw new ArgumentNullException ("buffer");
1670 if (offset < 0 || offset > buffer.Length)
1671 throw new ArgumentOutOfRangeException ("offset");
1673 if (size < 0 || offset + size > buffer.Length)
1674 throw new ArgumentOutOfRangeException ("size");
1678 int ret = Receive_nochecks (buffer, offset, size, flags, out error);
1680 if (error != SocketError.Success) {
1681 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1682 throw new SocketException ((int) error, "Operation timed out.");
1683 throw new SocketException ((int) error);
1689 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
1691 if (disposed && closed)
1692 throw new ObjectDisposedException (GetType ().ToString ());
1695 throw new ArgumentNullException ("buffer");
1697 if (offset < 0 || offset > buffer.Length)
1698 throw new ArgumentOutOfRangeException ("offset");
1700 if (size < 0 || offset + size > buffer.Length)
1701 throw new ArgumentOutOfRangeException ("size");
1703 return Receive_nochecks (buffer, offset, size, flags, out error);
1707 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
1709 if (disposed && closed)
1710 throw new ObjectDisposedException (GetType ().ToString ());
1712 // We do not support recv into multiple buffers yet
1713 if (e.BufferList != null)
1714 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1715 if (e.RemoteEndPoint == null)
1716 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1719 e.Worker.Init (this, null, e.ReceiveFromCallback, SocketOperation.ReceiveFrom);
1720 SocketAsyncResult res = e.Worker.result;
1721 res.Buffer = e.Buffer;
1722 res.Offset = e.Offset;
1724 res.EndPoint = e.RemoteEndPoint;
1725 res.SockFlags = e.SocketFlags;
1726 Worker worker = new Worker (e);
1729 readQ.Enqueue (worker);
1730 count = readQ.Count;
1733 socket_pool_queue (e.Worker.ReceiveFrom, res);
1738 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
1740 if (disposed && closed)
1741 throw new ObjectDisposedException (GetType ().ToString ());
1744 throw new ArgumentNullException ("buffer");
1746 if (remoteEP == null)
1747 throw new ArgumentNullException ("remoteEP");
1749 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
1752 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
1754 if (disposed && closed)
1755 throw new ObjectDisposedException (GetType ().ToString ());
1758 throw new ArgumentNullException ("buffer");
1760 if (remoteEP == null)
1761 throw new ArgumentNullException ("remoteEP");
1763 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
1766 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags,
1767 ref EndPoint remoteEP)
1769 if (disposed && closed)
1770 throw new ObjectDisposedException (GetType ().ToString ());
1773 throw new ArgumentNullException ("buffer");
1775 if (remoteEP == null)
1776 throw new ArgumentNullException ("remoteEP");
1778 if (size < 0 || size > buffer.Length)
1779 throw new ArgumentOutOfRangeException ("size");
1781 return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
1784 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1785 private extern static int RecvFrom_internal(IntPtr sock,
1790 ref SocketAddress sockaddr,
1793 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags,
1794 ref EndPoint remoteEP)
1796 if (disposed && closed)
1797 throw new ObjectDisposedException (GetType ().ToString ());
1800 throw new ArgumentNullException ("buffer");
1802 if (remoteEP == null)
1803 throw new ArgumentNullException ("remoteEP");
1805 if (offset < 0 || offset > buffer.Length)
1806 throw new ArgumentOutOfRangeException ("offset");
1808 if (size < 0 || offset + size > buffer.Length)
1809 throw new ArgumentOutOfRangeException ("size");
1811 return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
1814 internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
1815 ref EndPoint remote_end)
1818 return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
1821 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags,
1822 ref EndPoint remote_end, bool throwOnError, out int error)
1824 SocketAddress sockaddr = remote_end.Serialize();
1825 int cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
1826 SocketError err = (SocketError) error;
1828 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
1830 else if (err == SocketError.WouldBlock && blocking) { // This might happen when ReceiveTimeout is set
1832 throw new SocketException ((int) SocketError.TimedOut, "Operation timed out");
1833 error = (int) SocketError.TimedOut;
1838 throw new SocketException (error);
1845 // If sockaddr is null then we're a connection
1846 // oriented protocol and should ignore the
1847 // remote_end parameter (see MSDN
1848 // documentation for Socket.ReceiveFrom(...) )
1850 if ( sockaddr != null ) {
1851 // Stupidly, EndPoint.Create() is an
1853 remote_end = remote_end.Create (sockaddr);
1856 seed_endpoint = remote_end;
1861 [MonoTODO ("Not implemented")]
1862 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
1864 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1865 if (disposed && closed)
1866 throw new ObjectDisposedException (GetType ().ToString ());
1868 throw new NotImplementedException ();
1871 [MonoTODO ("Not implemented")]
1872 public int ReceiveMessageFrom (byte[] buffer, int offset,
1874 ref SocketFlags socketFlags,
1875 ref EndPoint remoteEP,
1876 out IPPacketInformation ipPacketInformation)
1878 if (disposed && closed)
1879 throw new ObjectDisposedException (GetType ().ToString ());
1882 throw new ArgumentNullException ("buffer");
1884 if (remoteEP == null)
1885 throw new ArgumentNullException ("remoteEP");
1887 if (offset < 0 || offset > buffer.Length)
1888 throw new ArgumentOutOfRangeException ("offset");
1890 if (size < 0 || offset + size > buffer.Length)
1891 throw new ArgumentOutOfRangeException ("size");
1893 /* FIXME: figure out how we get hold of the
1894 * IPPacketInformation
1896 throw new NotImplementedException ();
1899 [MonoTODO ("Not implemented")]
1900 public bool SendPacketsAsync (SocketAsyncEventArgs e)
1902 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1904 if (disposed && closed)
1905 throw new ObjectDisposedException (GetType ().ToString ());
1907 throw new NotImplementedException ();
1910 public int Send (byte [] buf)
1912 if (disposed && closed)
1913 throw new ObjectDisposedException (GetType ().ToString ());
1916 throw new ArgumentNullException ("buf");
1920 int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
1922 if (error != SocketError.Success)
1923 throw new SocketException ((int) error);
1928 public int Send (byte [] buf, SocketFlags flags)
1930 if (disposed && closed)
1931 throw new ObjectDisposedException (GetType ().ToString ());
1934 throw new ArgumentNullException ("buf");
1938 int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
1940 if (error != SocketError.Success)
1941 throw new SocketException ((int) error);
1946 public int Send (byte [] buf, int size, SocketFlags flags)
1948 if (disposed && closed)
1949 throw new ObjectDisposedException (GetType ().ToString ());
1952 throw new ArgumentNullException ("buf");
1954 if (size < 0 || size > buf.Length)
1955 throw new ArgumentOutOfRangeException ("size");
1959 int ret = Send_nochecks (buf, 0, size, flags, out error);
1961 if (error != SocketError.Success)
1962 throw new SocketException ((int) error);
1967 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
1969 if (disposed && closed)
1970 throw new ObjectDisposedException (GetType ().ToString ());
1973 throw new ArgumentNullException ("buffer");
1975 if (offset < 0 || offset > buf.Length)
1976 throw new ArgumentOutOfRangeException ("offset");
1978 if (size < 0 || offset + size > buf.Length)
1979 throw new ArgumentOutOfRangeException ("size");
1983 int ret = Send_nochecks (buf, offset, size, flags, out error);
1985 if (error != SocketError.Success)
1986 throw new SocketException ((int) error);
1991 public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1993 if (disposed && closed)
1994 throw new ObjectDisposedException (GetType ().ToString ());
1997 throw new ArgumentNullException ("buffer");
1999 if (offset < 0 || offset > buf.Length)
2000 throw new ArgumentOutOfRangeException ("offset");
2002 if (size < 0 || offset + size > buf.Length)
2003 throw new ArgumentOutOfRangeException ("size");
2005 return Send_nochecks (buf, offset, size, flags, out error);
2008 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2009 private extern static bool SendFile (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
2011 public void SendFile (string fileName)
2013 if (disposed && closed)
2014 throw new ObjectDisposedException (GetType ().ToString ());
2017 throw new NotSupportedException ();
2020 throw new InvalidOperationException ();
2022 SendFile (fileName, null, null, 0);
2025 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
2027 if (disposed && closed)
2028 throw new ObjectDisposedException (GetType ().ToString ());
2031 throw new NotSupportedException ();
2034 throw new InvalidOperationException ();
2036 if (!SendFile (socket, fileName, preBuffer, postBuffer, flags)) {
2037 SocketException exc = new SocketException ();
2038 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
2039 throw new FileNotFoundException ();
2045 public bool SendToAsync (SocketAsyncEventArgs e)
2047 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2049 if (disposed && closed)
2050 throw new ObjectDisposedException (GetType ().ToString ());
2051 if (e.BufferList != null)
2052 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2053 if (e.RemoteEndPoint == null)
2054 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2057 e.Worker.Init (this, null, e.SendToCallback, SocketOperation.SendTo);
2058 SocketAsyncResult res = e.Worker.result;
2059 res.Buffer = e.Buffer;
2060 res.Offset = e.Offset;
2062 res.SockFlags = e.SocketFlags;
2063 res.EndPoint = e.RemoteEndPoint;
2064 Worker worker = new Worker (e);
2067 writeQ.Enqueue (worker);
2068 count = writeQ.Count;
2071 socket_pool_queue (e.Worker.SendTo, res);
2076 public int SendTo (byte [] buffer, EndPoint remote_end)
2078 if (disposed && closed)
2079 throw new ObjectDisposedException (GetType ().ToString ());
2082 throw new ArgumentNullException ("buffer");
2084 if (remote_end == null)
2085 throw new ArgumentNullException ("remote_end");
2087 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
2090 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
2092 if (disposed && closed)
2093 throw new ObjectDisposedException (GetType ().ToString ());
2096 throw new ArgumentNullException ("buffer");
2098 if (remote_end == null)
2099 throw new ArgumentNullException ("remote_end");
2101 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
2104 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2106 if (disposed && closed)
2107 throw new ObjectDisposedException (GetType ().ToString ());
2110 throw new ArgumentNullException ("buffer");
2112 if (remote_end == null)
2113 throw new ArgumentNullException ("remote_end");
2115 if (size < 0 || size > buffer.Length)
2116 throw new ArgumentOutOfRangeException ("size");
2118 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
2121 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2122 private extern static int SendTo_internal(IntPtr sock,
2130 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
2131 EndPoint remote_end)
2133 if (disposed && closed)
2134 throw new ObjectDisposedException (GetType ().ToString ());
2137 throw new ArgumentNullException ("buffer");
2139 if (remote_end == null)
2140 throw new ArgumentNullException("remote_end");
2142 if (offset < 0 || offset > buffer.Length)
2143 throw new ArgumentOutOfRangeException ("offset");
2145 if (size < 0 || offset + size > buffer.Length)
2146 throw new ArgumentOutOfRangeException ("size");
2148 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
2151 internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
2152 EndPoint remote_end)
2154 SocketAddress sockaddr = remote_end.Serialize ();
2158 ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
2160 SocketError err = (SocketError) error;
2162 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2165 throw new SocketException (error);
2170 seed_endpoint = remote_end;
2175 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2177 if (disposed && closed)
2178 throw new ObjectDisposedException (GetType ().ToString ());
2180 // I'd throw an ArgumentNullException, but this is what MS does.
2181 if (optionValue == null)
2182 throw new SocketException ((int) SocketError.Fault,
2183 "Error trying to dereference an invalid pointer");
2187 SetSocketOption_internal (socket, optionLevel, optionName, null,
2188 optionValue, 0, out error);
2191 if (error == (int) SocketError.InvalidArgument)
2192 throw new ArgumentException ();
2193 throw new SocketException (error);
2197 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
2199 if (disposed && closed)
2200 throw new ObjectDisposedException (GetType ().ToString ());
2202 // NOTE: if a null is passed, the byte[] overload is used instead...
2203 if (optionValue == null)
2204 throw new ArgumentNullException("optionValue");
2208 if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
2209 LingerOption linger = optionValue as LingerOption;
2211 throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
2212 SetSocketOption_internal (socket, optionLevel, optionName, linger, null, 0, out error);
2213 } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2214 MulticastOption multicast = optionValue as MulticastOption;
2215 if (multicast == null)
2216 throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
2217 SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
2218 } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2219 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
2220 if (multicast == null)
2221 throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
2222 SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
2224 throw new ArgumentException ("Invalid value specified.", "optionValue");
2228 if (error == (int) SocketError.InvalidArgument)
2229 throw new ArgumentException ();
2230 throw new SocketException (error);
2234 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
2236 if (disposed && closed)
2237 throw new ObjectDisposedException (GetType ().ToString ());
2240 int int_val = (optionValue) ? 1 : 0;
2241 SetSocketOption_internal (socket, optionLevel, optionName, null, null, int_val, out error);
2243 if (error == (int) SocketError.InvalidArgument)
2244 throw new ArgumentException ();
2245 throw new SocketException (error);