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-2011 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, e, SocketOperation.Accept);
526 socket_pool_queue (Worker.Dispatcher, 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 socket_pool_queue (Worker.Dispatcher, req);
612 public IAsyncResult BeginAccept (int receiveSize,
613 AsyncCallback callback,
616 if (disposed && closed)
617 throw new ObjectDisposedException (GetType ().ToString ());
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];
625 req.Size = receiveSize;
626 req.SockFlags = SocketFlags.None;
627 socket_pool_queue (Worker.Dispatcher, req);
631 public IAsyncResult BeginAccept (Socket acceptSocket,
633 AsyncCallback callback,
636 if (disposed && closed)
637 throw new ObjectDisposedException (GetType ().ToString ());
640 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
642 if (acceptSocket != null) {
643 if (acceptSocket.disposed && acceptSocket.closed)
644 throw new ObjectDisposedException (acceptSocket.GetType ().ToString ());
646 if (acceptSocket.IsBound)
647 throw new InvalidOperationException ();
649 /* For some reason the MS runtime
650 * barfs if the new socket is not TCP,
651 * even though it's just about to blow
652 * away all those parameters
654 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
655 throw new SocketException ((int)SocketError.InvalidArgument);
658 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
659 req.Buffer = new byte[receiveSize];
661 req.Size = receiveSize;
662 req.SockFlags = SocketFlags.None;
663 req.AcceptSocket = acceptSocket;
664 socket_pool_queue (Worker.Dispatcher, req);
668 public IAsyncResult BeginConnect (IPAddress address, int port,
669 AsyncCallback callback,
672 if (disposed && closed)
673 throw new ObjectDisposedException (GetType ().ToString ());
676 throw new ArgumentNullException ("address");
678 if (address.ToString ().Length == 0)
679 throw new ArgumentException ("The length of the IP address is zero");
681 if (port <= 0 || port > 65535)
682 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
685 throw new InvalidOperationException ();
687 IPEndPoint iep = new IPEndPoint (address, port);
688 return(BeginConnect (iep, callback, state));
691 public IAsyncResult BeginConnect (string host, int port,
692 AsyncCallback callback,
695 if (disposed && closed)
696 throw new ObjectDisposedException (GetType ().ToString ());
699 throw new ArgumentNullException ("host");
701 if (address_family != AddressFamily.InterNetwork &&
702 address_family != AddressFamily.InterNetworkV6)
703 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
705 if (port <= 0 || port > 65535)
706 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
709 throw new InvalidOperationException ();
711 return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
714 public IAsyncResult BeginDisconnect (bool reuseSocket,
715 AsyncCallback callback,
718 if (disposed && closed)
719 throw new ObjectDisposedException (GetType ().ToString ());
721 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
722 req.ReuseSocket = reuseSocket;
723 socket_pool_queue (Worker.Dispatcher, req);
727 public IAsyncResult BeginReceive(byte[] buffer, int offset,
729 SocketFlags socket_flags,
730 AsyncCallback callback,
733 if (disposed && closed)
734 throw new ObjectDisposedException (GetType ().ToString ());
737 throw new ArgumentNullException ("buffer");
739 if (offset < 0 || offset > buffer.Length)
740 throw new ArgumentOutOfRangeException ("offset");
742 if (size < 0 || offset + size > buffer.Length)
743 throw new ArgumentOutOfRangeException ("size");
745 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
749 req.SockFlags = socket_flags;
752 readQ.Enqueue (req.Worker);
756 socket_pool_queue (Worker.Dispatcher, req);
760 public IAsyncResult BeginReceive (byte[] buffer, int offset,
761 int size, SocketFlags flags,
762 out SocketError error,
763 AsyncCallback callback,
766 /* As far as I can tell from the docs and from
767 * experimentation, a pointer to the
768 * SocketError parameter is not supposed to be
769 * saved for the async parts. And as we don't
770 * set any socket errors in the setup code, we
771 * just have to set it to Success.
773 error = SocketError.Success;
774 return (BeginReceive (buffer, offset, size, flags, callback, state));
777 [CLSCompliant (false)]
778 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
779 SocketFlags socketFlags,
780 AsyncCallback callback,
783 if (disposed && closed)
784 throw new ObjectDisposedException (GetType ().ToString ());
787 throw new ArgumentNullException ("buffers");
789 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
790 req.Buffers = buffers;
791 req.SockFlags = socketFlags;
794 readQ.Enqueue (req.Worker);
798 socket_pool_queue (Worker.Dispatcher, req);
802 [CLSCompliant (false)]
803 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
804 SocketFlags socketFlags,
805 out SocketError errorCode,
806 AsyncCallback callback,
809 /* I assume the same SocketError semantics as
812 errorCode = SocketError.Success;
813 return (BeginReceive (buffers, socketFlags, callback, state));
816 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
818 SocketFlags socket_flags,
819 ref EndPoint remote_end,
820 AsyncCallback callback,
822 if (disposed && closed)
823 throw new ObjectDisposedException (GetType ().ToString ());
826 throw new ArgumentNullException ("buffer");
828 if (remote_end == null)
829 throw new ArgumentNullException ("remote_end");
832 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
835 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
837 if (offset + size > buffer.Length)
838 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
840 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
844 req.SockFlags = socket_flags;
845 req.EndPoint = remote_end;
848 readQ.Enqueue (req.Worker);
852 socket_pool_queue (Worker.Dispatcher, req);
857 public IAsyncResult BeginReceiveMessageFrom (
858 byte[] buffer, int offset, int size,
859 SocketFlags socketFlags, ref EndPoint remoteEP,
860 AsyncCallback callback, object state)
862 if (disposed && closed)
863 throw new ObjectDisposedException (GetType ().ToString ());
866 throw new ArgumentNullException ("buffer");
868 if (remoteEP == null)
869 throw new ArgumentNullException ("remoteEP");
871 if (offset < 0 || offset > buffer.Length)
872 throw new ArgumentOutOfRangeException ("offset");
874 if (size < 0 || offset + size > buffer.Length)
875 throw new ArgumentOutOfRangeException ("size");
877 throw new NotImplementedException ();
880 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
881 AsyncCallback callback, object state)
883 if (disposed && closed)
884 throw new ObjectDisposedException (GetType ().ToString ());
887 throw new ArgumentNullException ("buffer");
890 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
893 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
895 if (offset + size > buffer.Length)
896 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
899 throw new SocketException ((int)SocketError.NotConnected);
901 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
905 req.SockFlags = socket_flags;
908 writeQ.Enqueue (req.Worker);
909 count = writeQ.Count;
912 socket_pool_queue (Worker.Dispatcher, req);
916 public IAsyncResult BeginSend (byte[] buffer, int offset,
918 SocketFlags socketFlags,
919 out SocketError errorCode,
920 AsyncCallback callback,
924 errorCode = SocketError.NotConnected;
925 throw new SocketException ((int)errorCode);
928 errorCode = SocketError.Success;
930 return (BeginSend (buffer, offset, size, socketFlags, callback,
934 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
935 SocketFlags socketFlags,
936 AsyncCallback callback,
939 if (disposed && closed)
940 throw new ObjectDisposedException (GetType ().ToString ());
943 throw new ArgumentNullException ("buffers");
946 throw new SocketException ((int)SocketError.NotConnected);
948 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
949 req.Buffers = buffers;
950 req.SockFlags = socketFlags;
953 writeQ.Enqueue (req.Worker);
954 count = writeQ.Count;
957 socket_pool_queue (Worker.Dispatcher, req);
961 [CLSCompliant (false)]
962 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
963 SocketFlags socketFlags,
964 out SocketError errorCode,
965 AsyncCallback callback,
969 errorCode = SocketError.NotConnected;
970 throw new SocketException ((int)errorCode);
973 errorCode = SocketError.Success;
974 return (BeginSend (buffers, socketFlags, callback, state));
977 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
979 sealed class SendFileAsyncResult : IAsyncResult {
983 public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
989 public object AsyncState {
990 get { return ares.AsyncState; }
993 public WaitHandle AsyncWaitHandle {
994 get { return ares.AsyncWaitHandle; }
997 public bool CompletedSynchronously {
998 get { return ares.CompletedSynchronously; }
1001 public bool IsCompleted {
1002 get { return ares.IsCompleted; }
1005 public SendFileHandler Delegate {
1009 public IAsyncResult Original {
1010 get { return ares; }
1014 public IAsyncResult BeginSendFile (string fileName,
1015 AsyncCallback callback,
1018 if (disposed && closed)
1019 throw new ObjectDisposedException (GetType ().ToString ());
1022 throw new NotSupportedException ();
1024 if (!File.Exists (fileName))
1025 throw new FileNotFoundException ();
1027 return BeginSendFile (fileName, null, null, 0, callback, state);
1030 public IAsyncResult BeginSendFile (string fileName,
1033 TransmitFileOptions flags,
1034 AsyncCallback callback,
1037 if (disposed && closed)
1038 throw new ObjectDisposedException (GetType ().ToString ());
1041 throw new NotSupportedException ();
1043 if (!File.Exists (fileName))
1044 throw new FileNotFoundException ();
1046 SendFileHandler d = new SendFileHandler (SendFile);
1047 return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, callback, state));
1050 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
1052 SocketFlags socket_flags,
1053 EndPoint remote_end,
1054 AsyncCallback callback,
1056 if (disposed && closed)
1057 throw new ObjectDisposedException (GetType ().ToString ());
1060 throw new ArgumentNullException ("buffer");
1063 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1066 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1068 if (offset + size > buffer.Length)
1069 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
1071 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
1072 req.Buffer = buffer;
1073 req.Offset = offset;
1075 req.SockFlags = socket_flags;
1076 req.EndPoint = remote_end;
1079 writeQ.Enqueue (req.Worker);
1080 count = writeQ.Count;
1083 socket_pool_queue (Worker.Dispatcher, req);
1087 // Creates a new system socket, returning the handle
1088 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1089 private extern static void Bind_internal(IntPtr sock,
1093 public void Bind(EndPoint local_end) {
1094 if (disposed && closed)
1095 throw new ObjectDisposedException (GetType ().ToString ());
1097 if (local_end == null)
1098 throw new ArgumentNullException("local_end");
1102 Bind_internal(socket, local_end.Serialize(), out error);
1104 throw new SocketException (error);
1108 seed_endpoint = local_end;
1111 public void Connect (IPAddress address, int port)
1113 Connect (new IPEndPoint (address, port));
1116 public void Connect (IPAddress[] addresses, int port)
1118 if (disposed && closed)
1119 throw new ObjectDisposedException (GetType ().ToString ());
1121 if (addresses == null)
1122 throw new ArgumentNullException ("addresses");
1124 if (this.AddressFamily != AddressFamily.InterNetwork &&
1125 this.AddressFamily != AddressFamily.InterNetworkV6)
1126 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1129 throw new InvalidOperationException ();
1131 /* FIXME: do non-blocking sockets Poll here? */
1133 foreach (IPAddress address in addresses) {
1134 IPEndPoint iep = new IPEndPoint (address, port);
1135 SocketAddress serial = iep.Serialize ();
1137 Connect_internal (socket, serial, out error);
1141 seed_endpoint = iep;
1143 } else if (error != (int)SocketError.InProgress &&
1144 error != (int)SocketError.WouldBlock) {
1149 Poll (-1, SelectMode.SelectWrite);
1150 error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1154 seed_endpoint = iep;
1160 throw new SocketException (error);
1163 public void Connect (string host, int port)
1165 IPAddress [] addresses = Dns.GetHostAddresses (host);
1166 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 ());
1177 e.Worker.Init (this, e, SocketOperation.Disconnect);
1178 socket_pool_queue (Worker.Dispatcher, e.Worker.result);
1183 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1184 extern static void Disconnect_internal(IntPtr sock, bool reuse, out int error);
1186 /* According to the docs, the MS runtime will throw
1187 * PlatformNotSupportedException if the platform is
1188 * newer than w2k. We should be able to cope...
1190 public void Disconnect (bool reuseSocket)
1192 if (disposed && closed)
1193 throw new ObjectDisposedException (GetType ().ToString ());
1197 Disconnect_internal (socket, reuseSocket, out error);
1201 /* ERROR_NOT_SUPPORTED */
1202 throw new PlatformNotSupportedException ();
1204 throw new SocketException (error);
1211 /* Do managed housekeeping here... */
1216 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
1217 public SocketInformation DuplicateAndClose (int targetProcessId)
1219 var si = new SocketInformation ();
1221 (islistening ? SocketInformationOptions.Listening : 0) |
1222 (connected ? SocketInformationOptions.Connected : 0) |
1223 (blocking ? 0 : SocketInformationOptions.NonBlocking) |
1224 (useoverlappedIO ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
1226 si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, isbound ? 1 : 0, (long)socket);
1227 socket = (IntPtr) (-1);
1233 public Socket EndAccept (IAsyncResult result)
1238 return(EndAccept (out buffer, out bytes, result));
1241 public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
1244 return(EndAccept (out buffer, out bytes, asyncResult));
1247 public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
1249 if (disposed && closed)
1250 throw new ObjectDisposedException (GetType ().ToString ());
1252 if (asyncResult == null)
1253 throw new ArgumentNullException ("asyncResult");
1255 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1257 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1259 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1260 throw InvalidAsyncOp ("EndAccept");
1261 if (!asyncResult.IsCompleted)
1262 asyncResult.AsyncWaitHandle.WaitOne ();
1264 req.CheckIfThrowDelayedException ();
1266 buffer = req.Buffer;
1267 bytesTransferred = req.Total;
1272 public void EndConnect (IAsyncResult result)
1274 if (disposed && closed)
1275 throw new ObjectDisposedException (GetType ().ToString ());
1278 throw new ArgumentNullException ("result");
1280 SocketAsyncResult req = result as SocketAsyncResult;
1282 throw new ArgumentException ("Invalid IAsyncResult", "result");
1284 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1285 throw InvalidAsyncOp ("EndConnect");
1286 if (!result.IsCompleted)
1287 result.AsyncWaitHandle.WaitOne();
1289 req.CheckIfThrowDelayedException();
1293 public void EndDisconnect (IAsyncResult asyncResult)
1295 if (disposed && closed)
1296 throw new ObjectDisposedException (GetType ().ToString ());
1298 if (asyncResult == null)
1299 throw new ArgumentNullException ("asyncResult");
1301 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1303 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1305 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1306 throw InvalidAsyncOp ("EndDisconnect");
1307 if (!asyncResult.IsCompleted)
1308 asyncResult.AsyncWaitHandle.WaitOne ();
1310 req.CheckIfThrowDelayedException ();
1315 public int EndReceiveMessageFrom (IAsyncResult asyncResult,
1316 ref SocketFlags socketFlags,
1317 ref EndPoint endPoint,
1318 out IPPacketInformation ipPacketInformation)
1320 if (disposed && closed)
1321 throw new ObjectDisposedException (GetType ().ToString ());
1323 if (asyncResult == null)
1324 throw new ArgumentNullException ("asyncResult");
1326 if (endPoint == null)
1327 throw new ArgumentNullException ("endPoint");
1329 SocketAsyncResult req = asyncResult as SocketAsyncResult;
1331 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1333 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1334 throw InvalidAsyncOp ("EndReceiveMessageFrom");
1335 throw new NotImplementedException ();
1338 public void EndSendFile (IAsyncResult asyncResult)
1340 if (disposed && closed)
1341 throw new ObjectDisposedException (GetType ().ToString ());
1343 if (asyncResult == null)
1344 throw new ArgumentNullException ("asyncResult");
1346 SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
1348 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1350 ares.Delegate.EndInvoke (ares.Original);
1354 public int EndSendTo (IAsyncResult result)
1356 if (disposed && closed)
1357 throw new ObjectDisposedException (GetType ().ToString ());
1360 throw new ArgumentNullException ("result");
1362 SocketAsyncResult req = result as SocketAsyncResult;
1364 throw new ArgumentException ("Invalid IAsyncResult", "result");
1366 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1367 throw InvalidAsyncOp ("EndSendTo");
1368 if (!result.IsCompleted)
1369 result.AsyncWaitHandle.WaitOne();
1371 req.CheckIfThrowDelayedException();
1376 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1377 private extern static void GetSocketOption_arr_internal(IntPtr socket,
1378 SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
1381 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
1383 if (disposed && closed)
1384 throw new ObjectDisposedException (GetType ().ToString ());
1386 if (optionValue == null)
1387 throw new SocketException ((int) SocketError.Fault,
1388 "Error trying to dereference an invalid pointer");
1392 GetSocketOption_arr_internal (socket, optionLevel, optionName, ref optionValue,
1395 throw new SocketException (error);
1398 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
1400 if (disposed && closed)
1401 throw new ObjectDisposedException (GetType ().ToString ());
1403 byte[] byte_val=new byte[length];
1406 GetSocketOption_arr_internal (socket, optionLevel, optionName, ref byte_val,
1409 throw new SocketException (error);
1414 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1415 // common options between UNIX and Winsock are FIONREAD,
1416 // FIONBIO and SIOCATMARK. Anything else will depend on the
1417 // system except SIO_KEEPALIVE_VALS which is properly handled
1418 // on both windows and linux.
1419 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1420 extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
1421 byte [] output, out int error);
1423 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1426 throw new ObjectDisposedException (GetType ().ToString ());
1429 int result = WSAIoctl (socket, ioctl_code, in_value, out_value,
1433 throw new SocketException (error);
1436 throw new InvalidOperationException ("Must use Blocking property instead.");
1441 public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
1443 return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
1446 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1447 private extern static void Listen_internal(IntPtr sock, int backlog, out int error);
1449 public void Listen (int backlog)
1451 if (disposed && closed)
1452 throw new ObjectDisposedException (GetType ().ToString ());
1455 throw new SocketException ((int)SocketError.InvalidArgument);
1458 Listen_internal(socket, backlog, out error);
1461 throw new SocketException (error);
1466 public bool Poll (int time_us, SelectMode mode)
1468 if (disposed && closed)
1469 throw new ObjectDisposedException (GetType ().ToString ());
1471 if (mode != SelectMode.SelectRead &&
1472 mode != SelectMode.SelectWrite &&
1473 mode != SelectMode.SelectError)
1474 throw new NotSupportedException ("'mode' parameter is not valid.");
1477 bool result = Poll_internal (socket, mode, time_us, out error);
1479 throw new SocketException (error);
1481 if (mode == SelectMode.SelectWrite && result && !connected) {
1482 /* Update the connected state; for
1483 * non-blocking Connect()s this is
1484 * when we can find out that the
1485 * connect succeeded.
1487 if ((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
1495 public int Receive (byte [] buffer)
1497 if (disposed && closed)
1498 throw new ObjectDisposedException (GetType ().ToString ());
1501 throw new ArgumentNullException ("buffer");
1505 int ret = Receive_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
1507 if (error != SocketError.Success)
1508 throw new SocketException ((int) error);
1513 public int Receive (byte [] buffer, SocketFlags flags)
1515 if (disposed && closed)
1516 throw new ObjectDisposedException (GetType ().ToString ());
1519 throw new ArgumentNullException ("buffer");
1523 int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
1525 if (error != SocketError.Success) {
1526 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1527 throw new SocketException ((int) error, "Operation timed out.");
1528 throw new SocketException ((int) error);
1534 public int Receive (byte [] buffer, int size, SocketFlags flags)
1536 if (disposed && closed)
1537 throw new ObjectDisposedException (GetType ().ToString ());
1540 throw new ArgumentNullException ("buffer");
1542 if (size < 0 || size > buffer.Length)
1543 throw new ArgumentOutOfRangeException ("size");
1547 int ret = Receive_nochecks (buffer, 0, size, flags, out error);
1549 if (error != SocketError.Success) {
1550 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1551 throw new SocketException ((int) error, "Operation timed out.");
1552 throw new SocketException ((int) error);
1558 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
1560 if (disposed && closed)
1561 throw new ObjectDisposedException (GetType ().ToString ());
1564 throw new ArgumentNullException ("buffer");
1566 if (offset < 0 || offset > buffer.Length)
1567 throw new ArgumentOutOfRangeException ("offset");
1569 if (size < 0 || offset + size > buffer.Length)
1570 throw new ArgumentOutOfRangeException ("size");
1574 int ret = Receive_nochecks (buffer, offset, size, flags, out error);
1576 if (error != SocketError.Success) {
1577 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1578 throw new SocketException ((int) error, "Operation timed out.");
1579 throw new SocketException ((int) error);
1585 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
1587 if (disposed && closed)
1588 throw new ObjectDisposedException (GetType ().ToString ());
1591 throw new ArgumentNullException ("buffer");
1593 if (offset < 0 || offset > buffer.Length)
1594 throw new ArgumentOutOfRangeException ("offset");
1596 if (size < 0 || offset + size > buffer.Length)
1597 throw new ArgumentOutOfRangeException ("size");
1599 return Receive_nochecks (buffer, offset, size, flags, out error);
1603 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
1605 if (disposed && closed)
1606 throw new ObjectDisposedException (GetType ().ToString ());
1608 // We do not support recv into multiple buffers yet
1609 if (e.BufferList != null)
1610 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1611 if (e.RemoteEndPoint == null)
1612 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1615 e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
1616 SocketAsyncResult res = e.Worker.result;
1617 res.Buffer = e.Buffer;
1618 res.Offset = e.Offset;
1620 res.EndPoint = e.RemoteEndPoint;
1621 res.SockFlags = e.SocketFlags;
1622 Worker worker = new Worker (e);
1625 readQ.Enqueue (worker);
1626 count = readQ.Count;
1629 socket_pool_queue (Worker.Dispatcher, res);
1634 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
1636 if (disposed && closed)
1637 throw new ObjectDisposedException (GetType ().ToString ());
1640 throw new ArgumentNullException ("buffer");
1642 if (remoteEP == null)
1643 throw new ArgumentNullException ("remoteEP");
1645 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
1648 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
1650 if (disposed && closed)
1651 throw new ObjectDisposedException (GetType ().ToString ());
1654 throw new ArgumentNullException ("buffer");
1656 if (remoteEP == null)
1657 throw new ArgumentNullException ("remoteEP");
1659 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
1662 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags,
1663 ref EndPoint remoteEP)
1665 if (disposed && closed)
1666 throw new ObjectDisposedException (GetType ().ToString ());
1669 throw new ArgumentNullException ("buffer");
1671 if (remoteEP == null)
1672 throw new ArgumentNullException ("remoteEP");
1674 if (size < 0 || size > buffer.Length)
1675 throw new ArgumentOutOfRangeException ("size");
1677 return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
1680 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1681 private extern static int RecvFrom_internal(IntPtr sock,
1686 ref SocketAddress sockaddr,
1689 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags,
1690 ref EndPoint remoteEP)
1692 if (disposed && closed)
1693 throw new ObjectDisposedException (GetType ().ToString ());
1696 throw new ArgumentNullException ("buffer");
1698 if (remoteEP == null)
1699 throw new ArgumentNullException ("remoteEP");
1701 if (offset < 0 || offset > buffer.Length)
1702 throw new ArgumentOutOfRangeException ("offset");
1704 if (size < 0 || offset + size > buffer.Length)
1705 throw new ArgumentOutOfRangeException ("size");
1707 return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
1710 internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
1711 ref EndPoint remote_end)
1714 return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
1717 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags,
1718 ref EndPoint remote_end, bool throwOnError, out int error)
1720 SocketAddress sockaddr = remote_end.Serialize();
1721 int cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
1722 SocketError err = (SocketError) error;
1724 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
1726 else if (err == SocketError.WouldBlock && blocking) { // This might happen when ReceiveTimeout is set
1728 throw new SocketException ((int) SocketError.TimedOut, "Operation timed out");
1729 error = (int) SocketError.TimedOut;
1734 throw new SocketException (error);
1741 // If sockaddr is null then we're a connection
1742 // oriented protocol and should ignore the
1743 // remote_end parameter (see MSDN
1744 // documentation for Socket.ReceiveFrom(...) )
1746 if ( sockaddr != null ) {
1747 // Stupidly, EndPoint.Create() is an
1749 remote_end = remote_end.Create (sockaddr);
1752 seed_endpoint = remote_end;
1757 [MonoTODO ("Not implemented")]
1758 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
1760 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1761 if (disposed && closed)
1762 throw new ObjectDisposedException (GetType ().ToString ());
1764 throw new NotImplementedException ();
1767 [MonoTODO ("Not implemented")]
1768 public int ReceiveMessageFrom (byte[] buffer, int offset,
1770 ref SocketFlags socketFlags,
1771 ref EndPoint remoteEP,
1772 out IPPacketInformation ipPacketInformation)
1774 if (disposed && closed)
1775 throw new ObjectDisposedException (GetType ().ToString ());
1778 throw new ArgumentNullException ("buffer");
1780 if (remoteEP == null)
1781 throw new ArgumentNullException ("remoteEP");
1783 if (offset < 0 || offset > buffer.Length)
1784 throw new ArgumentOutOfRangeException ("offset");
1786 if (size < 0 || offset + size > buffer.Length)
1787 throw new ArgumentOutOfRangeException ("size");
1789 /* FIXME: figure out how we get hold of the
1790 * IPPacketInformation
1792 throw new NotImplementedException ();
1795 [MonoTODO ("Not implemented")]
1796 public bool SendPacketsAsync (SocketAsyncEventArgs e)
1798 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1800 if (disposed && closed)
1801 throw new ObjectDisposedException (GetType ().ToString ());
1803 throw new NotImplementedException ();
1806 public int Send (byte [] buf)
1808 if (disposed && closed)
1809 throw new ObjectDisposedException (GetType ().ToString ());
1812 throw new ArgumentNullException ("buf");
1816 int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
1818 if (error != SocketError.Success)
1819 throw new SocketException ((int) error);
1824 public int Send (byte [] buf, SocketFlags flags)
1826 if (disposed && closed)
1827 throw new ObjectDisposedException (GetType ().ToString ());
1830 throw new ArgumentNullException ("buf");
1834 int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
1836 if (error != SocketError.Success)
1837 throw new SocketException ((int) error);
1842 public int Send (byte [] buf, int size, SocketFlags flags)
1844 if (disposed && closed)
1845 throw new ObjectDisposedException (GetType ().ToString ());
1848 throw new ArgumentNullException ("buf");
1850 if (size < 0 || size > buf.Length)
1851 throw new ArgumentOutOfRangeException ("size");
1855 int ret = Send_nochecks (buf, 0, size, flags, out error);
1857 if (error != SocketError.Success)
1858 throw new SocketException ((int) error);
1863 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
1865 if (disposed && closed)
1866 throw new ObjectDisposedException (GetType ().ToString ());
1869 throw new ArgumentNullException ("buffer");
1871 if (offset < 0 || offset > buf.Length)
1872 throw new ArgumentOutOfRangeException ("offset");
1874 if (size < 0 || offset + size > buf.Length)
1875 throw new ArgumentOutOfRangeException ("size");
1879 int ret = Send_nochecks (buf, offset, size, flags, out error);
1881 if (error != SocketError.Success)
1882 throw new SocketException ((int) error);
1887 public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1889 if (disposed && closed)
1890 throw new ObjectDisposedException (GetType ().ToString ());
1893 throw new ArgumentNullException ("buffer");
1895 if (offset < 0 || offset > buf.Length)
1896 throw new ArgumentOutOfRangeException ("offset");
1898 if (size < 0 || offset + size > buf.Length)
1899 throw new ArgumentOutOfRangeException ("size");
1901 return Send_nochecks (buf, offset, size, flags, out error);
1904 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1905 private extern static bool SendFile (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
1907 public void SendFile (string fileName)
1909 if (disposed && closed)
1910 throw new ObjectDisposedException (GetType ().ToString ());
1913 throw new NotSupportedException ();
1916 throw new InvalidOperationException ();
1918 SendFile (fileName, null, null, 0);
1921 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
1923 if (disposed && closed)
1924 throw new ObjectDisposedException (GetType ().ToString ());
1927 throw new NotSupportedException ();
1930 throw new InvalidOperationException ();
1932 if (!SendFile (socket, fileName, preBuffer, postBuffer, flags)) {
1933 SocketException exc = new SocketException ();
1934 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
1935 throw new FileNotFoundException ();
1941 public bool SendToAsync (SocketAsyncEventArgs e)
1943 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1945 if (disposed && closed)
1946 throw new ObjectDisposedException (GetType ().ToString ());
1947 if (e.BufferList != null)
1948 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1949 if (e.RemoteEndPoint == null)
1950 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1953 e.Worker.Init (this, e, SocketOperation.SendTo);
1954 SocketAsyncResult res = e.Worker.result;
1955 res.Buffer = e.Buffer;
1956 res.Offset = e.Offset;
1958 res.SockFlags = e.SocketFlags;
1959 res.EndPoint = e.RemoteEndPoint;
1960 Worker worker = new Worker (e);
1963 writeQ.Enqueue (worker);
1964 count = writeQ.Count;
1967 socket_pool_queue (Worker.Dispatcher, res);
1972 public int SendTo (byte [] buffer, EndPoint remote_end)
1974 if (disposed && closed)
1975 throw new ObjectDisposedException (GetType ().ToString ());
1978 throw new ArgumentNullException ("buffer");
1980 if (remote_end == null)
1981 throw new ArgumentNullException ("remote_end");
1983 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
1986 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
1988 if (disposed && closed)
1989 throw new ObjectDisposedException (GetType ().ToString ());
1992 throw new ArgumentNullException ("buffer");
1994 if (remote_end == null)
1995 throw new ArgumentNullException ("remote_end");
1997 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
2000 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2002 if (disposed && closed)
2003 throw new ObjectDisposedException (GetType ().ToString ());
2006 throw new ArgumentNullException ("buffer");
2008 if (remote_end == null)
2009 throw new ArgumentNullException ("remote_end");
2011 if (size < 0 || size > buffer.Length)
2012 throw new ArgumentOutOfRangeException ("size");
2014 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
2017 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2018 private extern static int SendTo_internal(IntPtr sock,
2026 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
2027 EndPoint remote_end)
2029 if (disposed && closed)
2030 throw new ObjectDisposedException (GetType ().ToString ());
2033 throw new ArgumentNullException ("buffer");
2035 if (remote_end == null)
2036 throw new ArgumentNullException("remote_end");
2038 if (offset < 0 || offset > buffer.Length)
2039 throw new ArgumentOutOfRangeException ("offset");
2041 if (size < 0 || offset + size > buffer.Length)
2042 throw new ArgumentOutOfRangeException ("size");
2044 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
2047 internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
2048 EndPoint remote_end)
2050 SocketAddress sockaddr = remote_end.Serialize ();
2054 ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
2056 SocketError err = (SocketError) error;
2058 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2061 throw new SocketException (error);
2066 seed_endpoint = remote_end;
2071 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2073 if (disposed && closed)
2074 throw new ObjectDisposedException (GetType ().ToString ());
2076 // I'd throw an ArgumentNullException, but this is what MS does.
2077 if (optionValue == null)
2078 throw new SocketException ((int) SocketError.Fault,
2079 "Error trying to dereference an invalid pointer");
2083 SetSocketOption_internal (socket, optionLevel, optionName, null,
2084 optionValue, 0, out error);
2087 if (error == (int) SocketError.InvalidArgument)
2088 throw new ArgumentException ();
2089 throw new SocketException (error);
2093 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
2095 if (disposed && closed)
2096 throw new ObjectDisposedException (GetType ().ToString ());
2098 // NOTE: if a null is passed, the byte[] overload is used instead...
2099 if (optionValue == null)
2100 throw new ArgumentNullException("optionValue");
2104 if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
2105 LingerOption linger = optionValue as LingerOption;
2107 throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
2108 SetSocketOption_internal (socket, optionLevel, optionName, linger, null, 0, out error);
2109 } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2110 MulticastOption multicast = optionValue as MulticastOption;
2111 if (multicast == null)
2112 throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
2113 SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
2114 } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2115 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
2116 if (multicast == null)
2117 throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
2118 SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
2120 throw new ArgumentException ("Invalid value specified.", "optionValue");
2124 if (error == (int) SocketError.InvalidArgument)
2125 throw new ArgumentException ();
2126 throw new SocketException (error);
2130 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
2132 if (disposed && closed)
2133 throw new ObjectDisposedException (GetType ().ToString ());
2136 int int_val = (optionValue) ? 1 : 0;
2137 SetSocketOption_internal (socket, optionLevel, optionName, null, null, int_val, out error);
2139 if (error == (int) SocketError.InvalidArgument)
2140 throw new ArgumentException ();
2141 throw new SocketException (error);