Exemplo n.º 1
0
        public static SocketError CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SafeSocketHandle socket)
        {
            Interop.Winsock.EnsureInitialized();

            IntPtr handle = Interop.Winsock.WSASocketW(addressFamily, socketType, protocolType, IntPtr.Zero, 0, Interop.Winsock.SocketConstructorFlags.WSA_FLAG_OVERLAPPED |
                                                       Interop.Winsock.SocketConstructorFlags.WSA_FLAG_NO_HANDLE_INHERIT);

            socket = new SafeSocketHandle(handle, ownsHandle: true);
            if (socket.IsInvalid)
            {
                SocketError error = GetLastSocketError();
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Error(null, $"WSASocketW failed with error {error}");
                }
                socket.Dispose();
                return(error);
            }

            if (NetEventSource.Log.IsEnabled())
            {
                NetEventSource.Info(null, socket);
            }
            return(SocketError.Success);
        }
Exemplo n.º 2
0
        public static unsafe SocketError CreateSocket(
            SocketInformation socketInformation,
            out SafeSocketHandle socket,
            ref AddressFamily addressFamily,
            ref SocketType socketType,
            ref ProtocolType protocolType)
        {
            if (socketInformation.ProtocolInformation == null || socketInformation.ProtocolInformation.Length < sizeof(Interop.Winsock.WSAPROTOCOL_INFOW))
            {
                throw new ArgumentException(SR.net_sockets_invalid_socketinformation, nameof(socketInformation));
            }

            Interop.Winsock.EnsureInitialized();

            fixed(byte *protocolInfoBytes = socketInformation.ProtocolInformation)
            {
                // Sockets are non-inheritable in .NET Core.
                // Handle properties like HANDLE_FLAG_INHERIT are not cloned with socket duplication, therefore
                // we need to disable handle inheritance when constructing the new socket handle from Protocol Info.
                // Additionally, it looks like WSA_FLAG_NO_HANDLE_INHERIT has no effect when being used with the Protocol Info
                // variant of WSASocketW, so it is being passed to that call only for consistency.
                // Inheritance is being disabled with SetHandleInformation(...) after the WSASocketW call.
                IntPtr handle = Interop.Winsock.WSASocketW(
                    (AddressFamily)(-1),
                    (SocketType)(-1),
                    (ProtocolType)(-1),
                    (IntPtr)protocolInfoBytes,
                    0,
                    Interop.Winsock.SocketConstructorFlags.WSA_FLAG_OVERLAPPED |
                    Interop.Winsock.SocketConstructorFlags.WSA_FLAG_NO_HANDLE_INHERIT);

                socket = new SafeSocketHandle(handle, ownsHandle: true);

                if (socket.IsInvalid)
                {
                    SocketError error = GetLastSocketError();
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(null, $"WSASocketW failed with error {error}");
                    }
                    socket.Dispose();
                    return(error);
                }

                if (!Interop.Kernel32.SetHandleInformation(socket, Interop.Kernel32.HandleFlags.HANDLE_FLAG_INHERIT, 0))
                {
                    // Returning SocketError for consistency, since the call site can deal with conversion, and
                    // the most common SetHandleInformation error (AccessDenied) is included in SocketError anyways:
                    SocketError error = GetLastSocketError();
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(null, $"SetHandleInformation failed with error {error}");
                    }
                    socket.Dispose();

                    return(error);
                }

                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Info(null, socket);
                }

                Interop.Winsock.WSAPROTOCOL_INFOW *protocolInfo = (Interop.Winsock.WSAPROTOCOL_INFOW *)protocolInfoBytes;
                addressFamily = protocolInfo->iAddressFamily;
                socketType    = protocolInfo->iSocketType;
                protocolType  = protocolInfo->iProtocol;

                return(SocketError.Success);
            }
        }
Exemplo n.º 3
0
        internal SocketError ReplaceHandle()
        {
            // Copy out values from key options. The copied values should be kept in sync with the
            // handling in SafeSocketHandle.TrackOption.  Note that we copy these values out first, before
            // we change _handle, so that we can use the helpers on Socket which internally access _handle.
            // Then once _handle is switched to the new one, we can call the setters to propagate the retrieved
            // values back out to the new underlying socket.
            bool         broadcast = false, dontFragment = false, noDelay = false;
            int          receiveSize = -1, receiveTimeout = -1, sendSize = -1, sendTimeout = -1;
            short        ttl    = -1;
            LingerOption?linger = null;

            if (_handle.IsTrackedOption(TrackedSocketOptions.DontFragment))
            {
                dontFragment = DontFragment;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.EnableBroadcast))
            {
                broadcast = EnableBroadcast;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.LingerState))
            {
                linger = LingerState;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.NoDelay))
            {
                noDelay = NoDelay;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.ReceiveBufferSize))
            {
                receiveSize = ReceiveBufferSize;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.ReceiveTimeout))
            {
                receiveTimeout = ReceiveTimeout;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.SendBufferSize))
            {
                sendSize = SendBufferSize;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.SendTimeout))
            {
                sendTimeout = SendTimeout;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.Ttl))
            {
                ttl = Ttl;
            }

            // Then replace the handle with a new one
            SafeSocketHandle oldHandle = _handle;
            SocketError      errorCode = SocketPal.CreateSocket(_addressFamily, _socketType, _protocolType, out _handle);

            oldHandle.TransferTrackedState(_handle);
            oldHandle.Dispose();
            if (errorCode != SocketError.Success)
            {
                return(errorCode);
            }

            // And put back the copied settings.  For DualMode, we use the value stored in the _handle
            // rather than querying the socket itself, as on Unix stacks binding a dual-mode socket to
            // an IPv6 address may cause the IPv6Only setting to revert to true.
            if (_handle.IsTrackedOption(TrackedSocketOptions.DualMode))
            {
                DualMode = _handle.DualMode;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.DontFragment))
            {
                DontFragment = dontFragment;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.EnableBroadcast))
            {
                EnableBroadcast = broadcast;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.LingerState))
            {
                LingerState = linger !;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.NoDelay))
            {
                NoDelay = noDelay;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.ReceiveBufferSize))
            {
                ReceiveBufferSize = receiveSize;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.ReceiveTimeout))
            {
                ReceiveTimeout = receiveTimeout;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.SendBufferSize))
            {
                SendBufferSize = sendSize;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.SendTimeout))
            {
                SendTimeout = sendTimeout;
            }
            if (_handle.IsTrackedOption(TrackedSocketOptions.Ttl))
            {
                Ttl = ttl;
            }

            return(SocketError.Success);
        }