PageRenderTime 267ms CodeModel.GetById 192ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 3ms

/mcs/class/referencesource/System/net/System/Net/Sockets/Socket.cs

http://github.com/mono/mono
C# | 10332 lines | 6761 code | 1552 blank | 2019 comment | 1643 complexity | f3cf07bc4700d0d7e8094627109d65a8 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1//------------------------------------------------------------------------------
   2// <copyright file="Socket.cs" company="Microsoft">
   3//     Copyright (c) Microsoft Corporation.  All rights reserved.
   4// </copyright>
   5//------------------------------------------------------------------------------
   6
   7#if MONO
   8#undef FEATURE_PAL
   9#endif
  10
  11namespace System.Net.Sockets {
  12    using System.Collections;
  13    using System.Collections.Generic;
  14    using System.Diagnostics;
  15    using System.Globalization;
  16    using System.IO;
  17    using System.Net;
  18    using System.Net.Configuration;
  19    using System.Runtime.InteropServices;
  20    using System.Security.Permissions;
  21    using System.Threading;
  22    using System.Runtime.Versioning;
  23    using System.Diagnostics.Contracts;
  24    using System.ComponentModel;
  25
  26    /// <devdoc>
  27    /// <para>The <see cref='Sockets.Socket'/> class implements the Berkeley sockets
  28    ///    interface.</para>
  29    /// </devdoc>
  30
  31    public partial class Socket : IDisposable
  32    {
  33#if !MONO
  34        internal const int DefaultCloseTimeout = -1; // don't change for default, otherwise breaking change
  35
  36        // AcceptQueue - queued list of accept requests for BeginAccept or async Result for Begin Connect
  37        private object m_AcceptQueueOrConnectResult;
  38
  39        // the following 8 members represent the state of the socket
  40        private SafeCloseSocket  m_Handle;
  41
  42        // m_RightEndPoint is null if the socket has not been bound.  Otherwise, it is any EndPoint of the
  43        // correct type (IPEndPoint, etc).
  44        internal EndPoint   m_RightEndPoint;  
  45        internal EndPoint    m_RemoteEndPoint;
  46        // this flags monitor if the socket was ever connected at any time and if it still is.
  47        private bool        m_IsConnected; //  = false;
  48        private bool        m_IsDisconnected; //  = false;
  49
  50        // when the socket is created it will be in blocking mode
  51        // we'll only be able to Accept or Connect, so we only need
  52        // to handle one of these cases at a time
  53        private bool        willBlock = true; // desired state of the socket for the user
  54        private bool        willBlockInternal = true; // actual win32 state of the socket
  55        private bool        isListening = false;
  56
  57        // Our internal state doesn't automatically get updated after a non-blocking connect
  58        // completes.  Keep track of whether we're doing a non-blocking connect, and make sure
  59        // to poll for the real state until we're done connecting.
  60        private bool m_NonBlockingConnectInProgress;
  61
  62        // Keep track of the kind of endpoint used to do a non-blocking connect, so we can set
  63        // it to m_RightEndPoint when we discover we're connected.
  64        private EndPoint m_NonBlockingConnectRightEndPoint;
  65
  66        // These are constants initialized by constructor
  67        private AddressFamily   addressFamily;
  68        private SocketType      socketType;
  69        private ProtocolType    protocolType;
  70
  71        // These caches are one degree off of Socket since they're not used in the sync case/when disabled in config.
  72        private CacheSet m_Caches;
  73
  74        private class CacheSet
  75        {
  76            internal CallbackClosure ConnectClosureCache;
  77            internal CallbackClosure AcceptClosureCache;
  78            internal CallbackClosure SendClosureCache;
  79            internal CallbackClosure ReceiveClosureCache;
  80
  81            internal OverlappedCache SendOverlappedCache;
  82            internal OverlappedCache ReceiveOverlappedCache;
  83        }
  84
  85        //
  86        // Overlapped constants.
  87        //
  88#if !(FEATURE_PAL && !MONO) || CORIOLIS
  89        internal static volatile bool UseOverlappedIO;
  90#else
  91        // Disable the I/O completion port for Rotor
  92        internal static volatile bool UseOverlappedIO = true;
  93#endif // !(FEATURE_PAL && !MONO) || CORIOLIS
  94        private bool useOverlappedIO;
  95
  96        // Bool marked true if the native socket m_Handle was bound to the ThreadPool
  97        private bool        m_BoundToThreadPool; // = false;
  98
  99        // Bool marked true if the native socket option IP_PKTINFO or IPV6_PKTINFO has been set
 100        private bool m_ReceivingPacketInformation;
 101
 102        // Event used for async Connect/Accept calls
 103        private ManualResetEvent m_AsyncEvent;
 104        private RegisteredWaitHandle m_RegisteredWait;
 105        private AsyncEventBits m_BlockEventBits = AsyncEventBits.FdNone;
 106
 107        //These members are to cache permission checks
 108        private SocketAddress   m_PermittedRemoteAddress;
 109
 110        private DynamicWinsockMethods m_DynamicWinsockMethods;
 111#endif // !MONO
 112
 113        private static object s_InternalSyncObject;
 114#if !MONO
 115        private int m_CloseTimeout = Socket.DefaultCloseTimeout;
 116        private int m_IntCleanedUp;                 // 0 if not completed >0 otherwise.
 117        private const int microcnv = 1000000;
 118        private readonly static int protocolInformationSize = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO));
 119#endif // !MONO
 120
 121        internal static volatile bool s_SupportsIPv4;
 122        internal static volatile bool s_SupportsIPv6;
 123        internal static volatile bool s_OSSupportsIPv6;
 124        internal static volatile bool s_Initialized;
 125#if !MONO
 126        private static volatile WaitOrTimerCallback s_RegisteredWaitCallback;
 127#endif
 128        private static volatile bool s_LoggingEnabled;
 129#if !FEATURE_PAL // perfcounter
 130        internal static volatile bool s_PerfCountersEnabled;
 131#endif
 132
 133//************* constructors *************************
 134
 135        //------------------------------------
 136
 137        // Creates a Dual Mode socket for working with both IPv4 and IPv6
 138        public Socket(SocketType socketType, ProtocolType protocolType)
 139            : this(AddressFamily.InterNetworkV6, socketType, protocolType) {
 140            DualMode = true;
 141        }
 142
 143        /// <devdoc>
 144        ///    <para>
 145        ///       Initializes a new instance of the <see cref='Sockets.Socket'/> class.
 146        ///    </para>
 147        /// </devdoc>
 148        public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) {
 149#if WASM
 150            throw new PlatformNotSupportedException ();
 151#else
 152            s_LoggingEnabled = Logging.On;
 153            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Socket", addressFamily);
 154            InitializeSockets();
 155
 156#if MONO
 157            int error;
 158            m_Handle = new SafeSocketHandle (Socket_icall (addressFamily, socketType, protocolType, out error), true);
 159#else
 160            m_Handle = SafeCloseSocket.CreateWSASocket(
 161                    addressFamily,
 162                    socketType,
 163                    protocolType);
 164#endif
 165
 166            if (m_Handle.IsInvalid) {
 167                //
 168                // failed to create the win32 socket, throw
 169                //
 170                throw new SocketException();
 171            }
 172
 173            this.addressFamily = addressFamily;
 174            this.socketType = socketType;
 175            this.protocolType = protocolType;
 176
 177            IPProtectionLevel defaultProtectionLevel = SettingsSectionInternal.Section.IPProtectionLevel;
 178            if (defaultProtectionLevel != IPProtectionLevel.Unspecified) {
 179                SetIPProtectionLevel(defaultProtectionLevel);
 180            }
 181
 182#if MONO
 183            SocketDefaults ();
 184#endif
 185
 186            if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Socket", null);
 187#endif           
 188        }
 189
 190#if !MONO
 191        public Socket(SocketInformation socketInformation) {
 192            s_LoggingEnabled = Logging.On;
 193            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Socket", addressFamily);
 194
 195            ExceptionHelper.UnrestrictedSocketPermission.Demand();
 196
 197            InitializeSockets();
 198            if(socketInformation.ProtocolInformation == null || socketInformation.ProtocolInformation.Length < protocolInformationSize){
 199                throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_socketinformation), "socketInformation.ProtocolInformation");
 200            }
 201
 202            unsafe{
 203                fixed(byte * pinnedBuffer = socketInformation.ProtocolInformation){
 204                    m_Handle = SafeCloseSocket.CreateWSASocket(pinnedBuffer);
 205
 206                    UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO protocolInfo = (UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO)Marshal.PtrToStructure((IntPtr)pinnedBuffer, typeof(UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO));
 207                    addressFamily = protocolInfo.iAddressFamily;
 208                    socketType = (SocketType)protocolInfo.iSocketType;
 209                    protocolType = (ProtocolType)protocolInfo.iProtocol;
 210                }
 211            }
 212
 213            if (m_Handle.IsInvalid) {
 214                SocketException e = new SocketException();
 215                if(e.ErrorCode == (int)SocketError.InvalidArgument){
 216                    throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_socketinformation), "socketInformation");
 217                }
 218                else {
 219                    throw e;
 220                }
 221            }
 222
 223            if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
 224                throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 225            }
 226
 227            m_IsConnected = socketInformation.IsConnected;
 228            willBlock = !socketInformation.IsNonBlocking;
 229            InternalSetBlocking(willBlock);
 230            isListening = socketInformation.IsListening;
 231            UseOnlyOverlappedIO = socketInformation.UseOnlyOverlappedIO;
 232
 233
 234            //are we bound?  if so, what's the local endpoint?
 235
 236            if (socketInformation.RemoteEndPoint != null) {
 237                m_RightEndPoint = socketInformation.RemoteEndPoint;
 238                m_RemoteEndPoint = socketInformation.RemoteEndPoint;
 239            }
 240            else {
 241                EndPoint ep = null;
 242                if (addressFamily == AddressFamily.InterNetwork ) {
 243                    ep = IPEndPoint.Any;
 244                }
 245                else if(addressFamily == AddressFamily.InterNetworkV6) {
 246                    ep = IPEndPoint.IPv6Any;
 247                }
 248
 249                SocketAddress socketAddress = ep.Serialize();
 250                SocketError errorCode;
 251                try
 252                {
 253                    errorCode = UnsafeNclNativeMethods.OSSOCK.getsockname(
 254                        m_Handle,
 255                        socketAddress.m_Buffer,
 256                        ref socketAddress.m_Size);
 257                }
 258                catch (ObjectDisposedException)
 259                {
 260                    errorCode = SocketError.NotSocket;
 261                }
 262
 263                if (errorCode == SocketError.Success) {
 264                    try {
 265                        //we're bound
 266                        m_RightEndPoint = ep.Create(socketAddress);
 267                    }
 268                    catch {
 269                    }
 270                }
 271            }
 272
 273            if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Socket", null);
 274         }
 275
 276
 277        /// <devdoc>
 278        ///    <para>
 279        ///       Called by the class to create a socket to accept an
 280        ///       incoming request.
 281        ///    </para>
 282        /// </devdoc>
 283        private Socket(SafeCloseSocket fd) {
 284            s_LoggingEnabled = Logging.On;
 285            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Socket", null);
 286            InitializeSockets();
 287            // ExceptionHelper.UnmanagedPermission.Demand();
 288            //<
 289
 290
 291
 292
 293
 294            //
 295            // this should never happen, let's check anyway
 296            //
 297            if (fd == null || fd.IsInvalid) {
 298                throw new ArgumentException(SR.GetString(SR.net_InvalidSocketHandle));
 299            }
 300
 301            m_Handle = fd;
 302
 303            addressFamily = Sockets.AddressFamily.Unknown;
 304            socketType = Sockets.SocketType.Unknown;
 305            protocolType = Sockets.ProtocolType.Unknown;
 306            if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Socket", null);
 307        }
 308#endif
 309
 310
 311//************* properties *************************
 312
 313
 314        /// <devdoc>
 315        /// <para>Indicates whether IPv4 support is available and enabled on this machine.</para>
 316        /// </devdoc>
 317        [Obsolete("SupportsIPv4 is obsoleted for this type, please use OSSupportsIPv4 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
 318        public static bool SupportsIPv4 {
 319            get {
 320                InitializeSockets();
 321                return s_SupportsIPv4;
 322            }
 323        }
 324
 325        // Renamed to be consistent with OSSupportsIPv6
 326        public static bool OSSupportsIPv4 {
 327            get {
 328                InitializeSockets();
 329                return s_SupportsIPv4;
 330            }
 331        }
 332
 333        /// <devdoc>
 334        /// <para>Indicates whether IPv6 support is available and enabled on this machine.</para>
 335        /// </devdoc>
 336
 337        [Obsolete("SupportsIPv6 is obsoleted for this type, please use OSSupportsIPv6 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
 338        public static bool SupportsIPv6 {
 339            get {
 340                InitializeSockets();
 341                return s_SupportsIPv6;
 342            }
 343        }
 344
 345        internal static bool LegacySupportsIPv6 {
 346            get {
 347                InitializeSockets();
 348                return s_SupportsIPv6;
 349            }
 350        }
 351
 352        public static bool OSSupportsIPv6 {
 353            get {
 354                InitializeSockets();
 355                return s_OSSupportsIPv6;
 356            }
 357        }
 358
 359#if !MONO
 360        /// <devdoc>
 361        ///    <para>
 362        ///       Gets the amount of data pending in the network's input buffer that can be
 363        ///       read from the socket.
 364        ///    </para>
 365        /// </devdoc>
 366        public int Available {
 367            get {
 368                if (CleanedUp) {
 369                    throw new ObjectDisposedException(this.GetType().FullName);
 370                }
 371
 372                int argp = 0;
 373
 374                // This may throw ObjectDisposedException.
 375                SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(
 376                    m_Handle,
 377                    IoctlSocketConstants.FIONREAD,
 378                    ref argp);
 379
 380                GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Available_get() UnsafeNclNativeMethods.OSSOCK.ioctlsocket returns errorCode:" + errorCode);
 381
 382                //
 383                // if the native call fails we'll throw a SocketException
 384                //
 385                if (errorCode==SocketError.SocketError) {
 386                    //
 387                    // update our internal state after this socket error and throw
 388                    //
 389                    SocketException socketException = new SocketException();
 390                    UpdateStatusAfterSocketError(socketException);
 391                    if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Available", socketException);
 392                    throw socketException;
 393                }
 394
 395                return argp;
 396            }
 397         }
 398
 399
 400
 401
 402
 403        /// <devdoc>
 404        ///    <para>
 405        ///       Gets the local end point.
 406        ///    </para>
 407        /// </devdoc>
 408        public EndPoint LocalEndPoint {
 409            get {
 410                if (CleanedUp) {
 411                    throw new ObjectDisposedException(this.GetType().FullName);
 412                }
 413
 414                if (m_NonBlockingConnectInProgress && Poll(0, SelectMode.SelectWrite))
 415                {
 416                    // update the state if we've become connected after a non-blocking connect
 417                    m_IsConnected = true;
 418                    m_RightEndPoint = m_NonBlockingConnectRightEndPoint;
 419                    m_NonBlockingConnectInProgress = false;
 420                }
 421
 422                if (m_RightEndPoint == null) {
 423                    return null;
 424                }
 425
 426                SocketAddress socketAddress = m_RightEndPoint.Serialize();
 427
 428                // This may throw ObjectDisposedException.
 429                SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockname(
 430                    m_Handle,
 431                    socketAddress.m_Buffer,
 432                    ref socketAddress.m_Size);
 433
 434                if (errorCode!=SocketError.Success) {
 435                    //
 436                    // update our internal state after this socket error and throw
 437                    //
 438                    SocketException socketException = new SocketException();
 439                    UpdateStatusAfterSocketError(socketException);
 440                    if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "LocalEndPoint", socketException);
 441                    throw socketException;
 442                }
 443
 444                return m_RightEndPoint.Create(socketAddress);
 445            }
 446        }
 447
 448        /// <devdoc>
 449        ///    <para>
 450        ///       Gets the remote end point
 451        ///    </para>
 452        /// </devdoc>
 453        public EndPoint RemoteEndPoint {
 454            get {
 455                if (CleanedUp) {
 456                    throw new ObjectDisposedException(this.GetType().FullName);
 457                }
 458
 459                if (m_RemoteEndPoint==null) {
 460
 461                    if (m_NonBlockingConnectInProgress && Poll(0, SelectMode.SelectWrite))
 462                    {
 463                        // update the state if we've become connected after a non-blocking connect
 464                        m_IsConnected = true;
 465                        m_RightEndPoint = m_NonBlockingConnectRightEndPoint;
 466                        m_NonBlockingConnectInProgress = false;
 467                    }
 468
 469                    if (m_RightEndPoint==null) {
 470                        return null;
 471                    }
 472
 473                    SocketAddress socketAddress = m_RightEndPoint.Serialize();
 474
 475                    // This may throw ObjectDisposedException.
 476                    SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getpeername(
 477                        m_Handle,
 478                        socketAddress.m_Buffer,
 479                        ref socketAddress.m_Size);
 480
 481                    if (errorCode!=SocketError.Success) {
 482                        //
 483                        // update our internal state after this socket error and throw
 484                        //
 485                        SocketException socketException = new SocketException();
 486                        UpdateStatusAfterSocketError(socketException);
 487                        if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "RemoteEndPoint", socketException);
 488                        throw socketException;
 489                    }
 490
 491                    try {
 492                        m_RemoteEndPoint = m_RightEndPoint.Create(socketAddress);
 493                    }
 494                    catch {
 495                    }
 496                }
 497
 498                return m_RemoteEndPoint;
 499            }
 500        }
 501#endif // !MONO
 502
 503        /// <devdoc>
 504        ///    <para>
 505        ///       Gets the operating system m_Handle for the socket.
 506        ///YUKON: should we cut this method off, who are the users?
 507        ///    </para>
 508        /// </devdoc>
 509        public IntPtr Handle {
 510            get {
 511#if !MONO
 512                ExceptionHelper.UnmanagedPermission.Demand();
 513#endif
 514                return m_Handle.DangerousGetHandle();
 515            }
 516        }
 517#if !MONO
 518        internal SafeCloseSocket SafeHandle {
 519            get {
 520                return m_Handle;
 521            }
 522        }
 523
 524
 525        // Non-blocking I/O control
 526        /// <devdoc>
 527        ///    <para>
 528        ///       Gets and sets the blocking mode of a socket.
 529        ///    </para>
 530        /// </devdoc>
 531        public bool Blocking {
 532            get {
 533                //
 534                // return the user's desired blocking behaviour (not the actual win32 state)
 535                //
 536                return willBlock;
 537            }
 538            set {
 539                if (CleanedUp) {
 540                    throw new ObjectDisposedException(this.GetType().FullName);
 541                }
 542
 543                GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::set_Blocking() value:" + value.ToString() + " willBlock:" + willBlock.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
 544
 545                bool current;
 546
 547                SocketError errorCode = InternalSetBlocking(value, out current);
 548
 549                if (errorCode!=SocketError.Success) {
 550                    //
 551                    // update our internal state after this socket error and throw
 552                    SocketException socketException = new SocketException(errorCode);
 553                    UpdateStatusAfterSocketError(socketException);
 554                    if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Blocking", socketException);
 555                    throw socketException;
 556                }
 557
 558                //
 559                // win32 call succeeded, update desired state
 560                //
 561                willBlock = current;
 562            }
 563        }
 564#endif // !MONO
 565
 566        public bool UseOnlyOverlappedIO{
 567            get {
 568                //
 569                // return the user's desired blocking behaviour (not the actual win32 state)
 570                //
 571                return useOverlappedIO;
 572
 573            }
 574            set {
 575#if !MONO
 576                if (m_BoundToThreadPool) {
 577                    throw new InvalidOperationException(SR.GetString(SR.net_io_completionportwasbound));
 578                }
 579#endif
 580
 581                useOverlappedIO = value;
 582            }
 583        }
 584
 585#if !MONO
 586        /// <devdoc>
 587        ///    <para>
 588        ///       Gets the connection state of the Socket. This property will return the latest
 589        ///       known state of the Socket. When it returns false, the Socket was either never connected
 590        ///       or it is not connected anymore. When it returns true, though, there's no guarantee that the Socket
 591        ///       is still connected, but only that it was connected at the time of the last IO operation.
 592        ///    </para>
 593        /// </devdoc>
 594        public bool Connected {
 595            get {
 596                GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Connected() m_IsConnected:"+m_IsConnected);
 597
 598                if (m_NonBlockingConnectInProgress && Poll(0, SelectMode.SelectWrite))
 599                {
 600                    // update the state if we've become connected after a non-blocking connect
 601                    m_IsConnected = true;
 602                    m_RightEndPoint = m_NonBlockingConnectRightEndPoint;
 603                    m_NonBlockingConnectInProgress = false;
 604                }
 605
 606                return m_IsConnected;
 607            }
 608        }
 609#endif // !MONO
 610
 611        /// <devdoc>
 612        ///    <para>
 613        ///       Gets the socket's address family.
 614        ///    </para>
 615        /// </devdoc>
 616        public AddressFamily AddressFamily {
 617            get {
 618                return addressFamily;
 619            }
 620        }
 621
 622        /// <devdoc>
 623        ///    <para>
 624        ///       Gets the socket's socketType.
 625        ///    </para>
 626        /// </devdoc>
 627        public SocketType SocketType {
 628            get {
 629                return socketType;
 630            }
 631        }
 632
 633        /// <devdoc>
 634        ///    <para>
 635        ///       Gets the socket's protocol socketType.
 636        ///    </para>
 637        /// </devdoc>
 638        public ProtocolType ProtocolType {
 639            get {
 640                return protocolType;
 641            }
 642        }
 643
 644#if !MONO
 645        public bool IsBound{
 646            get{
 647                return (m_RightEndPoint != null);
 648            }
 649        }
 650#endif // !MONO
 651
 652        public bool ExclusiveAddressUse{
 653            get {
 654                return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse) != 0 ? true : false;
 655            }
 656            set {
 657                if (IsBound) {
 658                    throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotbebound));
 659                }
 660                SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
 661            }
 662        }
 663
 664
 665        public int ReceiveBufferSize {
 666            get {
 667                return (int)GetSocketOption(SocketOptionLevel.Socket,
 668                                     SocketOptionName.ReceiveBuffer);
 669            }
 670            set {
 671                if (value<0) {
 672                    throw new ArgumentOutOfRangeException("value");
 673                }
 674
 675                SetSocketOption(SocketOptionLevel.Socket,
 676                                  SocketOptionName.ReceiveBuffer, value);
 677            }
 678        }
 679
 680        public int SendBufferSize {
 681            get {
 682                return (int)GetSocketOption(SocketOptionLevel.Socket,
 683                                     SocketOptionName.SendBuffer);
 684            }
 685
 686            set {
 687                if (value<0) {
 688                    throw new ArgumentOutOfRangeException("value");
 689                }
 690
 691                SetSocketOption(SocketOptionLevel.Socket,
 692                                  SocketOptionName.SendBuffer, value);
 693            }
 694        }
 695
 696        public int ReceiveTimeout {
 697            get {
 698                return (int)GetSocketOption(SocketOptionLevel.Socket,
 699                                     SocketOptionName.ReceiveTimeout);
 700            }
 701            set {
 702                if (value< -1) {
 703                    throw new ArgumentOutOfRangeException("value");
 704                }
 705                if (value == -1) {
 706                    value = 0;
 707                }
 708
 709                SetSocketOption(SocketOptionLevel.Socket,
 710                                  SocketOptionName.ReceiveTimeout, value);
 711            }
 712        }
 713
 714        public int SendTimeout {
 715            get {
 716                return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
 717            }
 718
 719            set {
 720                if (value< -1) {
 721                    throw new ArgumentOutOfRangeException("value");
 722                }
 723                if (value == -1) {
 724                    value = 0;
 725                }
 726
 727                SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
 728            }
 729        }
 730
 731        public LingerOption LingerState {
 732            get {
 733                return (LingerOption)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger);
 734            }
 735            set {
 736                SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, value);
 737            }
 738        }
 739
 740#if !MONO
 741        public bool NoDelay {
 742            get {
 743                return (int)GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay) != 0 ? true : false;
 744            }
 745            set {
 746                SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
 747            }
 748        }
 749#endif // !MONO
 750
 751        public short Ttl{
 752            get {
 753                if (addressFamily == AddressFamily.InterNetwork) {
 754                    return (short)(int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
 755                }
 756                else if (addressFamily == AddressFamily.InterNetworkV6) {
 757                    return (short)(int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive);
 758                }
 759                else{
 760                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 761                }
 762            }
 763
 764            set {
 765
 766                // valid values are from 0 to 255 since Ttl is really just a byte value on the wire
 767                if (value < 0 || value > 255) {
 768                    throw new ArgumentOutOfRangeException("value");
 769                }
 770
 771                if (addressFamily == AddressFamily.InterNetwork) {
 772                    SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
 773                }
 774
 775                else if (addressFamily == AddressFamily.InterNetworkV6) {
 776                    SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive, value);
 777                }
 778                else{
 779                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 780                }
 781            }
 782        }
 783
 784        public bool DontFragment{
 785            get {
 786                if (addressFamily == AddressFamily.InterNetwork) {
 787                    return (int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment) != 0 ? true : false;
 788                }
 789                else{
 790                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 791                }
 792            }
 793
 794            set {
 795                if (addressFamily == AddressFamily.InterNetwork) {
 796                    SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
 797                }
 798                else{
 799                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 800                }
 801            }
 802        }
 803
 804#if !MONO
 805        public bool MulticastLoopback{
 806            get {
 807                if (addressFamily == AddressFamily.InterNetwork) {
 808                    return (int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback) != 0 ? true : false;
 809                }
 810                else if (addressFamily == AddressFamily.InterNetworkV6) {
 811                    return (int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback) != 0 ? true : false;
 812                }
 813                else{
 814                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 815                }
 816            }
 817
 818            set {
 819                if (addressFamily == AddressFamily.InterNetwork) {
 820                    SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
 821                }
 822
 823                else if (addressFamily == AddressFamily.InterNetworkV6) {
 824                    SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
 825                }
 826                else{
 827                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 828                }
 829            }
 830        }
 831
 832        public bool EnableBroadcast{
 833            get {
 834                return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast) != 0 ? true : false;
 835            }
 836            set {
 837                SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
 838            }
 839        }
 840#endif // !MONO
 841
 842        public bool DualMode {
 843            get {
 844                if (AddressFamily != AddressFamily.InterNetworkV6) {
 845                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 846                }
 847                return ((int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only) == 0);
 848            }
 849            set {
 850                if (AddressFamily != AddressFamily.InterNetworkV6) {
 851                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
 852                }
 853                SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, value ? 0 : 1);
 854            }
 855        }
 856
 857        private bool IsDualMode {
 858            get {
 859                return AddressFamily == AddressFamily.InterNetworkV6 && DualMode;
 860            }
 861        }
 862
 863        internal bool CanTryAddressFamily(AddressFamily family) {
 864            return (family == addressFamily) || (family == AddressFamily.InterNetwork && IsDualMode);
 865        }
 866
 867
 868//************* public methods *************************
 869
 870
 871
 872
 873#if !MONO
 874        /// <devdoc>
 875        ///    <para>Associates a socket with an end point.</para>
 876        /// </devdoc>
 877        public void Bind(EndPoint localEP) {
 878
 879            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Bind", localEP);
 880
 881            if (CleanedUp) {
 882                throw new ObjectDisposedException(this.GetType().FullName);
 883            }
 884            //
 885            // parameter validation
 886            //
 887            if (localEP==null) {
 888                throw new ArgumentNullException("localEP");
 889            }
 890
 891            GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Bind() localEP:" + localEP.ToString());
 892
 893            EndPoint endPointSnapshot = localEP;
 894            IPEndPoint ipSnapshot = localEP as IPEndPoint;
 895
 896            //
 897            // for now security is implemented only on IPEndPoint
 898            // If EndPoint is of other type - unmanaged code permisison is demanded
 899            //
 900            if (ipSnapshot != null)
 901            {
 902                // Take a snapshot that will make it immutable and not derived.
 903                ipSnapshot = ipSnapshot.Snapshot();                                
 904                // DualMode: Do the security check on the users IPv4 address, but map to IPv6 before binding.
 905                endPointSnapshot = RemapIPEndPoint(ipSnapshot);
 906
 907                //
 908                // create the permissions the user would need for the call
 909                //
 910                SocketPermission socketPermission
 911                    = new SocketPermission(
 912                        NetworkAccess.Accept,
 913                        Transport,
 914                        ipSnapshot.Address.ToString(),
 915                        ipSnapshot.Port);
 916                //
 917                // demand for them
 918                //
 919                socketPermission.Demand();
 920
 921                // Here the permission check has succeded.
 922                // NB: if local port is 0, then winsock will assign some>1024,
 923                //     so assuming that this is safe. We will not check the
 924                //     NetworkAccess.Accept permissions in Receive.
 925            }
 926            else {
 927                //<
 928
 929
 930
 931
 932
 933                ExceptionHelper.UnmanagedPermission.Demand();
 934            }
 935
 936            //
 937            // ask the EndPoint to generate a SocketAddress that we
 938            // can pass down to winsock
 939            //
 940            SocketAddress socketAddress = CallSerializeCheckDnsEndPoint(endPointSnapshot);
 941            DoBind(endPointSnapshot, socketAddress);
 942            if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Bind", "");
 943        }
 944
 945        internal void InternalBind(EndPoint localEP)
 946        {
 947            if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "InternalBind", localEP);
 948
 949            if (CleanedUp)
 950            {
 951                throw new ObjectDisposedException(GetType().FullName);
 952            }
 953
 954            GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::InternalBind() localEP:" + localEP.ToString());
 955            GlobalLog.Assert(!(localEP is DnsEndPoint), "Calling InternalBind with a DnsEndPoint, about to get NotImplementedException");
 956
 957            //
 958            // ask the EndPoint to generate a SocketAddress that we
 959            // can pass down to winsock
 960            //
 961            EndPoint endPointSnapshot = localEP;
 962            SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
 963            DoBind(endPointSnapshot, socketAddress);
 964
 965            if (s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "InternalBind", "");
 966        }
 967
 968        private void DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
 969        {
 970            // Mitigation for Blue Screen of Death (Win7, maybe others)
 971            IPEndPoint ipEndPoint = endPointSnapshot as IPEndPoint;
 972            if (!OSSupportsIPv4 && ipEndPoint != null && ipEndPoint.Address.IsIPv4MappedToIPv6)
 973            {
 974                SocketException socketException = new SocketException(SocketError.InvalidArgument);
 975                UpdateStatusAfterSocketError(socketException);
 976                if (s_LoggingEnabled) Logging.Exception(Logging.Sockets, this, "DoBind", socketException);
 977                throw socketException;
 978            }
 979
 980            // This may throw ObjectDisposedException.
 981            SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.bind(
 982                m_Handle,
 983                socketAddress.m_Buffer,
 984                socketAddress.m_Size);
 985
 986#if TRAVE
 987            try
 988            {
 989                GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Bind() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " UnsafeNclNativeMethods.OSSOCK.bind returns errorCode:" + errorCode);
 990            }
 991            catch (ObjectDisposedException) { }
 992#endif
 993
 994            //
 995            // if the native call fails we'll throw a SocketException
 996            //
 997            if (errorCode != SocketError.Success)
 998            {
 999                //
1000                // update our internal state after this socket error and throw
1001                //
1002                SocketException socketException = new SocketException();
1003                UpdateStatusAfterSocketError(socketException);
1004                if (s_LoggingEnabled) Logging.Exception(Logging.Sockets, this, "DoBind", socketException);
1005                throw socketException;
1006            }
1007
1008            if (m_RightEndPoint == null)
1009            {
1010                //
1011                // save a copy of the EndPoint so we can use it for Create()
1012                //
1013                m_RightEndPoint = endPointSnapshot;
1014            }
1015        }
1016
1017
1018        /// <devdoc>
1019        ///    <para>Establishes a connection to a remote system.</para>
1020        /// </devdoc>
1021        public void Connect(EndPoint remoteEP) {
1022            if (CleanedUp) {
1023                throw new ObjectDisposedException(this.GetType().FullName);
1024            }
1025            //
1026            // parameter validation
1027            //
1028            if (remoteEP==null) {
1029                throw new ArgumentNullException("remoteEP");
1030            }
1031
1032            if(m_IsDisconnected){
1033                throw new InvalidOperationException(SR.GetString(SR.net_sockets_disconnectedConnect));
1034            }
1035
1036            if (isListening)
1037            {
1038                throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
1039            }
1040
1041            ValidateBlockingMode();
1042            GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Connect() DST:" + ValidationHelper.ToString(remoteEP));
1043
1044            DnsEndPoint dnsEP = remoteEP as DnsEndPoint;
1045            if (dnsEP != null)
1046            {
1047                if (dnsEP.AddressFamily != AddressFamily.Unspecified && !CanTryAddressFamily(dnsEP.AddressFamily)) 
1048                {
1049                    throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
1050                }
1051
1052                Connect(dnsEP.Host, dnsEP.Port);
1053                return;
1054            }
1055
1056            //This will check the permissions for connect
1057            EndPoint endPointSnapshot = remoteEP;
1058            SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, true);
1059
1060            if (!Blocking)
1061            {
1062                m_NonBlockingConnectRightEndPoint = endPointSnapshot;
1063                m_NonBlockingConnectInProgress = true;
1064            }
1065
1066            DoConnect(endPointSnapshot, socketAddress);
1067        }
1068
1069
1070        public void Connect(IPAddress address, int port){
1071
1072            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Connect", address);
1073
1074            if (CleanedUp){
1075                throw new ObjectDisposedException(this.GetType().FullName);
1076            }
1077            //if address family isn't the socket address family throw
1078            if (address==null) {
1079                throw new ArgumentNullException("address");
1080            }
1081
1082            if (!ValidationHelper.ValidateTcpPort(port)) {
1083                throw new ArgumentOutOfRangeException("port");
1084            }
1085            if (!CanTryAddressFamily(address.AddressFamily)) {
1086                throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
1087            }
1088
1089            IPEndPoint remoteEP = new IPEndPoint(address, port);
1090            Connect(remoteEP);
1091            if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Connect", null);
1092        }
1093
1094
1095        public void Connect(string host, int port){
1096            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Connect", host);
1097
1098            if (CleanedUp){
1099                throw new ObjectDisposedException(this.GetType().FullName);
1100            }
1101            if (host==null) {
1102                throw new ArgumentNullException("host");
1103            }
1104            if (!ValidationHelper.ValidateTcpPort(port)){
1105                throw new ArgumentOutOfRangeException("port");
1106            }
1107            if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
1108                throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
1109            }
1110
1111            IPAddress[] addresses = Dns.GetHostAddresses(host);
1112            Connect(addresses,port);
1113            if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Connect", null);
1114        }
1115#endif // !MONO
1116
1117        public void Connect(IPAddress[] addresses, int port){
1118            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Connect", addresses);
1119
1120            if (CleanedUp){
1121                throw new ObjectDisposedException(this.GetType().FullName);
1122            }
1123            if (addresses==null) {
1124                throw new ArgumentNullException("addresses");
1125            }
1126            if (addresses.Length == 0) {
1127                throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_ipaddress_length), "addresses");
1128            }
1129            if (!ValidationHelper.ValidateTcpPort(port)) {
1130                throw new ArgumentOutOfRangeException("port");
1131            }
1132            if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
1133                throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
1134            }
1135
1136            Exception   lastex = null;
1137            foreach ( IPAddress address in addresses ) {
1138                if (CanTryAddressFamily(address.AddressFamily)) {
1139                    try
1140                    {
1141                        Connect(new IPEndPoint(address,port) );
1142                        lastex = null;
1143                        break;
1144                    }
1145                    catch ( Exception ex )
1146                    {
1147                        if (NclUtilities.IsFatal(ex)) throw;
1148                        lastex = ex;
1149                    }
1150                }
1151            }
1152
1153            if ( lastex != null )
1154                throw lastex;
1155
1156            //if we're not connected, then we didn't get a valid ipaddress in the list
1157            if (!Connected) {
1158                throw new ArgumentException(SR.GetString(SR.net_invalidAddressList), "addresses");
1159            }
1160
1161            if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Connect", null);
1162        }
1163
1164#if !MONO
1165        /// <devdoc>
1166        ///    <para>
1167        ///       Forces a socket connection to close.
1168        ///    </para>
1169        /// </devdoc>
1170        public void Close()
1171        {
1172            GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Close() timeout = " + m_CloseTimeout);
1173            if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "Close", null);
1174            ((IDisposable)this).Dispose();
1175            if (s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "Close", null);
1176        }
1177
1178        public void Close(int timeout)
1179        {
1180            if (timeout < -1)
1181            {
1182                throw new ArgumentOutOfRangeException("timeout");
1183            }
1184            m_CloseTimeout = timeout;
1185            GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Close() timeout = " + m_CloseTimeout);
1186            ((IDisposable)this).Dispose();
1187        }
1188
1189
1190        /// <devdoc>
1191        ///    <para>
1192        ///       Places a socket in a listening state.
1193        ///    </para>
1194        /// </devdoc>
1195        public void Listen(int backlog) {
1196            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Listen", backlog);
1197            if (CleanedUp) {
1198                throw new ObjectDisposedException(this.GetType().FullName);
1199            }
1200
1201            GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Listen() backlog:" + backlog.ToString());
1202
1203            // No access permissions are necessary here because
1204            // the verification is done for Bind
1205
1206            // This may throw ObjectDisposedException.
1207            SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.listen(
1208                m_Handle,
1209                backlog);
1210
1211#if TRAVE
1212            try
1213            {
1214                GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Listen() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " UnsafeNclNativeMethods.OSSOCK.listen returns errorCode:" + errorCode);
1215            }
1216            catch (ObjectDisposedException) { }
1217#endif
1218
1219            //
1220            // if the native call fails we'll throw a SocketException
1221            //
1222            if (errorCode!=SocketError.Success) {
1223                //
1224                // update our internal state after this socket error and throw
1225                //
1226                SocketException socketException = new SocketException();
1227                UpdateStatusAfterSocketError(socketException);
1228                if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Listen", socketException);
1229                throw socketException;
1230            }
1231            isListening = true;
1232            if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Listen", "");
1233        }
1234
1235        /// <devdoc>
1236        ///    <para>
1237        ///       Creates a new <see cref='Sockets.Socket'/> instance to handle an incoming
1238        ///       connection.
1239        ///    </para>
1240        /// </devdoc>
1241        public Socket Accept() {
1242            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Accept", "");
1243
1244            //
1245            // parameter validation
1246            //
1247
1248            if (CleanedUp) {
1249                throw new ObjectDisposedException(this.GetType().FullName);
1250            }
1251
1252            if (m_RightEndPoint==null) {
1253                throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
1254            }
1255
1256            if(!isListening){
1257                throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustlisten));
1258            }
1259
1260            if(m_IsDisconnected){
1261                throw new InvalidOperationException(SR.GetString(SR.net_sockets_disconnectedAccept));
1262            }
1263
1264            ValidateBlockingMode();
1265            GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Accept() SRC:" + ValidationHelper.ToString(LocalEndPoint));
1266
1267            SocketAddress socketAddress = m_RightEndPoint.Serialize();
1268
1269            // This may throw ObjectDisposedException.
1270            SafeCloseSocket acceptedSocketHandle = SafeCloseSocket.Accept(
1271                m_Handle,
1272                socketAddress.m_Buffer,
1273                ref socketAddress.m_Size);
1274
1275            //
1276            // if the native call fails we'll throw a SocketException
1277            //
1278            if (acceptedSocketHandle.IsInvalid) {
1279                //
1280                // update our internal state after this socket error and throw
1281                //
1282                SocketException socketException = new SocketException();
1283                UpdateStatusAfterSocketError(socketException);
1284                if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Accept", socketException);
1285                throw socketException;
1286            }
1287
1288            Socket socket = CreateAcceptSocket(acceptedSocketHandle, m_RightEndPoint.Create(socketAddress), false);
1289            if (s_LoggingEnabled) {
1290                Logging.PrintInfo(Logging.Sockets, socket, SR.GetString(SR.net_log_socket_accepted, socket.RemoteEndPoint, socket.LocalEndPoint));
1291                Logging.Exit(Logging.Sockets, this, "Accept", socket);
1292            }
1293            return socket;
1294        }
1295#endif // !MONO
1296
1297        /// <devdoc>
1298        ///    <para>Sends a data buffer to a connected socket.</para>
1299        /// </devdoc>
1300        public int Send(byte[] buffer, int size, SocketFlags socketFlags) {
1301            return Send(buffer, 0, size, socketFlags);
1302        }
1303        /// <devdoc>
1304        ///    <para>[To be supplied.]</para>
1305        /// </devdoc>
1306        public int Send(byte[] buffer, SocketFlags socketFlags) {
1307            return Send(buffer, 0, buffer!=null ? buffer.Length : 0, socketFlags);
1308        }
1309        /// <devdoc>
1310        ///    <para>[To be supplied.]</para>
1311        /// </devdoc>
1312        public int Send(byte[] buffer) {
1313            return Send(buffer, 0, buffer!=null ? buffer.Length : 0, SocketFlags.None);
1314        }
1315
1316#if !FEATURE_PAL
1317
1318        /// <devdoc>
1319        ///    <para>[To be supplied.]</para>
1320        /// </devdoc>
1321        public int Send(IList<ArraySegment<byte>> buffers) {
1322            return Send(buffers,SocketFlags.None);
1323        }
1324
1325        /// <devdoc>
1326        ///    <para>[To be supplied.]</para>
1327        /// </devdoc>
1328        public int Send(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags) {
1329            SocketError errorCode;
1330            int bytesTransferred = Send(buffers, socketFlags, out errorCode);
1331            if(errorCode != SocketError.Success){
1332                throw new SocketException(errorCode);
1333            }
1334            return bytesTransferred;
1335        }
1336
1337#if !MONO
1338        public int Send(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode) {
1339            if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Send", "");
1340            if (CleanedUp) {
1341                throw new ObjectDisposedException(this.GetType().FullName);
1342            }
1343            if (buffers==null) {
1344               throw 

Large files files are truncated, but you can click here to view the full file