Exemplo n.º 1
1
        public static SocketError Set(SafeSocketHandle handle, SocketOptionName optionName, int optionValueSeconds)
        {
            IOControlKeepAlive ioControlKeepAlive = s_socketKeepAliveTable.GetOrCreateValue(handle);

            if (optionName == SocketOptionName.TcpKeepAliveTime)
            {
                ioControlKeepAlive._timeMs = SecondsToMilliseconds(optionValueSeconds);
            }
            else
            {
                ioControlKeepAlive._intervalMs = SecondsToMilliseconds(optionValueSeconds);
            }

            byte[] buffer = s_keepAliveValuesBuffer ?? (s_keepAliveValuesBuffer = new byte[3 * sizeof(uint)]);
            ioControlKeepAlive.Fill(buffer);
            int realOptionLength = 0;

            return(SocketPal.WindowsIoctl(handle, unchecked ((int)IOControlCode.KeepAliveValues), buffer, null, out realOptionLength));
        }
Exemplo n.º 2
0
        internal SocketError DoOperationDisconnect(Socket socket, SafeCloseSocket handle)
        {
            SocketError socketError = SocketPal.Disconnect(socket, handle, _disconnectReuseSocket);

            FinishOperationSync(socketError, 0, SocketFlags.None);
            return(socketError);
        }
        // Check the result of the overlapped operation.
        // Handle synchronous success by completing the asyncResult here.
        // Handle synchronous failure by cleaning up and returning a SocketError.
        internal SocketError ProcessOverlappedResult(bool success, int bytesTransferred)
        {
            if (success)
            {
                // Synchronous success.
                Socket socket = (Socket)AsyncObject;
                if (socket.SafeHandle.SkipCompletionPortOnSuccess)
                {
                    // The socket handle is configured to skip completion on success,
                    // so we can complete this asyncResult right now.
                    CompletionCallback(bytesTransferred, SocketError.Success);
                    return(SocketError.Success);
                }

                // Socket handle is going to post a completion to the completion port (may have done so already).
                // Return pending and we will continue in the completion port callback.
                return(SocketError.IOPending);
            }

            // Get the socket error (which may be IOPending)
            SocketError errorCode = SocketPal.GetLastSocketError();

            if (errorCode == SocketError.IOPending)
            {
                // Operation is pending.
                // We will continue when the completion arrives (may have already at this point).
                return(SocketError.IOPending);
            }

            // Synchronous failure.
            // Release overlapped and pinned structures.
            ReleaseUnmanagedStructures();

            return(errorCode);
        }
Exemplo n.º 4
0
        private IAsyncResult BeginSendFileInternal(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
        {
            FileStream fileStream = OpenFile(fileName);

            TransmitFileAsyncResult asyncResult = new TransmitFileAsyncResult(this, state, callback);

            asyncResult.StartPostingAsyncOp(false);

            SocketError errorCode = SocketPal.SendFileAsync(_handle, fileStream, preBuffer, postBuffer, flags, asyncResult);

            // Check for synchronous exception
            if (errorCode != SocketError.Success)
            {
                SocketException socketException = new SocketException((int)errorCode);
                UpdateStatusAfterSocketError(socketException);
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Error(this, socketException);
                }
                throw socketException;
            }

            asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);

            return(asyncResult);
        }
Exemplo n.º 5
0
        private void SendFileInternal(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
        {
            // Open the file, if any
            FileStream fileStream = OpenFile(fileName);

            SocketError errorCode;

            using (fileStream)
            {
                SafeFileHandle fileHandle = fileStream?.SafeFileHandle;

                // This can throw ObjectDisposedException.
                errorCode = SocketPal.SendFile(_handle, fileHandle, preBuffer, postBuffer, flags);
            }

            if (errorCode != SocketError.Success)
            {
                SocketException socketException = new SocketException((int)errorCode);
                UpdateStatusAfterSocketError(socketException);
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Error(this, socketException);
                }
                throw socketException;
            }

            // If the user passed the Disconnect and/or ReuseSocket flags, then TransmitFile disconnected the socket.
            // Update our state to reflect this.
            if ((flags & (TransmitFileOptions.Disconnect | TransmitFileOptions.ReuseSocket)) != 0)
            {
                SetToDisconnected();
                _remoteEndPoint = null;
            }
        }
Exemplo n.º 6
0
            public static unsafe InnerSafeCloseSocket CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
            {
                int af   = SocketPal.GetPlatformAddressFamily(addressFamily);
                int sock = SocketPal.GetPlatformSocketType(socketType);
                int pt   = (int)protocolType;

                int fd = Interop.libc.socket(af, sock, pt);

                if (fd != -1)
                {
                    // The socket was created successfully; make it non-blocking and enable
                    // IPV6_V6ONLY by default for AF_INET6 sockets.
                    int err = Interop.Sys.Fcntl.SetIsNonBlocking(fd, 1);
                    if (err != 0)
                    {
                        Interop.Sys.Close(fd);
                        fd = -1;
                    }
                    else if (addressFamily == AddressFamily.InterNetworkV6)
                    {
                        int on = 1;
                        err = Interop.libc.setsockopt(fd, Interop.libc.IPPROTO_IPV6, Interop.libc.IPV6_V6ONLY, &on, (uint)sizeof(int));
                        if (err != 0)
                        {
                            Interop.Sys.Close(fd);
                            fd = -1;
                        }
                    }
                }

                var res = new InnerSafeCloseSocket();

                res.SetHandle((IntPtr)fd);
                return(res);
            }
            private Interop.Error CloseHandle(IntPtr handle)
            {
                Interop.Error errorCode     = Interop.Error.SUCCESS;
                bool          remappedError = false;

                if (Interop.Sys.Close(handle) != 0)
                {
                    errorCode = Interop.Sys.GetLastError();
                    if (errorCode == Interop.Error.ECONNRESET)
                    {
                        // Some Unix platforms (e.g. FreeBSD) non-compliantly return ECONNRESET from close().
                        // For our purposes, we want to ignore such a "failure" and treat it as success.
                        // In such a case, the file descriptor was still closed and there's no corrective
                        // action to take.
                        errorCode     = Interop.Error.SUCCESS;
                        remappedError = true;
                    }
                }

                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, remappedError ?
                                        $"handle:{handle}, close():ECONNRESET, but treating it as SUCCESS" :
                                        $"handle:{handle}, close():{errorCode}");
                }

#if DEBUG
                _closeSocketHandle = handle;
                _closeSocketResult = SocketPal.GetSocketErrorForErrorCode(errorCode);
#endif

                return(errorCode);
            }
        private void TransferCompletionCallback(int bytesTransferred, byte[] socketAddress, int socketAddressSize, int receivedFlags, SocketError socketError)
        {
            Debug.Assert(socketAddress == null || socketAddress == _socketAddress.Buffer);
            _socketAddressSize = socketAddressSize;
            _receivedFlags     = SocketPal.GetSocketFlags(receivedFlags);

            CompletionCallback(bytesTransferred, socketError);
        }
Exemplo n.º 9
0
        internal SocketError DoOperationSendPackets(Socket socket, SafeCloseSocket handle)
        {
            Debug.Assert(_sendPacketsElements != null);
            SendPacketsElement[] elements = (SendPacketsElement[])_sendPacketsElements.Clone();
            FileStream[]         files    = new FileStream[elements.Length];

            // Open all files synchronously ahead of time so that any exceptions are propagated
            // to the caller, to match Windows behavior.
            try
            {
                for (int i = 0; i < elements.Length; i++)
                {
                    string path = elements[i]?.FilePath;
                    if (path != null)
                    {
                        files[i] = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x1000, useAsync: true);
                    }
                }
            }
            catch (Exception exc)
            {
                // Clean up any files that were already opened.
                foreach (FileStream s in files)
                {
                    s?.Dispose();
                }

                // Windows differentiates the directory not being found from the file not being found.
                // Approximate this by checking to see if the directory exists; this is only best-effort,
                // as there are various things that could affect this, e.g. directory creation racing with
                // this check, but it's good enough for most situations.
                if (exc is FileNotFoundException fnfe)
                {
                    string dirname = Path.GetDirectoryName(fnfe.FileName);
                    if (!string.IsNullOrEmpty(dirname) && !Directory.Exists(dirname))
                    {
                        throw new DirectoryNotFoundException(fnfe.Message);
                    }
                }

                // Otherwise propagate the original error.
                throw;
            }

            SocketPal.SendPacketsAsync(socket, SendPacketsFlags, elements, files, (bytesTransferred, error) =>
            {
                if (error == SocketError.Success)
                {
                    FinishOperationAsyncSuccess((int)bytesTransferred, SocketFlags.None);
                }
                else
                {
                    FinishOperationAsyncFailure(error, (int)bytesTransferred, SocketFlags.None);
                }
            });

            return(SocketError.IOPending);
        }
Exemplo n.º 10
0
        public static unsafe SocketError SendFile(SafeCloseSocket handle, SafeFileHandle fileHandle, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
        {
            fixed(byte *prePinnedBuffer = preBuffer)
            fixed(byte *postPinnedBuffer = postBuffer)
            {
                bool success = TransmitFileHelper(handle, fileHandle, SafeNativeOverlapped.Zero, preBuffer, postBuffer, flags);

                return(success ? SocketError.Success : SocketPal.GetLastSocketError());
            }
        }
Exemplo n.º 11
0
        private void ReceiveMessageFromCompletionCallback(int bytesTransferred, byte[] socketAddress, int socketAddressSize, int receivedFlags, IPPacketInformation ipPacketInformation, SocketError errorCode)
        {
            Debug.Assert(_socketAddress != null);
            Debug.Assert(socketAddress == null || _socketAddress.Buffer == socketAddress);

            _socketAddressSize            = socketAddressSize;
            _receivedFlags                = SocketPal.GetSocketFlags(receivedFlags);
            _receiveMessageFromPacketInfo = ipPacketInformation;

            CompletionCallback(bytesTransferred, errorCode);
        }
Exemplo n.º 12
0
        internal unsafe SocketError DoOperationReceiveMessageFrom(Socket socket, SafeCloseSocket handle, out int bytesTransferred)
        {
            int platformFlags = SocketPal.GetPlatformSocketFlags(_socketFlags);

            bool isIPv4, isIPv6;

            Socket.GetIPProtocolInformation(socket.AddressFamily, _socketAddress, out isIPv4, out isIPv6);

            bytesTransferred = 0;
            return(handle.AsyncContext.ReceiveMessageFromAsync(_buffer, _offset, _count, platformFlags, _socketAddress.Buffer, _socketAddress.Size, isIPv4, isIPv6, ReceiveMessageFromCompletionCallback));
        }
Exemplo n.º 13
0
        public void CompletionCallback(int numBytes, byte[] socketAddress, int socketAddressSize, int receivedFlags, IPPacketInformation ipPacketInformation, SocketError errorCode)
        {
            Debug.Assert(_socketAddress != null);
            Debug.Assert(socketAddress == null || _socketAddress.Buffer == socketAddress);

            _socketAddressSize   = socketAddressSize;
            _socketFlags         = SocketPal.GetSocketFlags(receivedFlags);
            _ipPacketInformation = ipPacketInformation;

            base.CompletionCallback(numBytes, errorCode);
        }
        public void CompletionCallback(IntPtr acceptedFileDescriptor, byte[] socketAddress, int socketAddressLen, SocketError errorCode)
        {
            _buffer   = null;
            _numBytes = 0;

            if (errorCode == SocketError.Success)
            {
                Internals.SocketAddress remoteSocketAddress = IPEndPointExtensions.Serialize(_listenSocket._rightEndPoint);
                System.Buffer.BlockCopy(socketAddress, 0, remoteSocketAddress.Buffer, 0, socketAddressLen);

                _acceptedSocket = _listenSocket.CreateAcceptSocket(
                    SocketPal.CreateSocket(acceptedFileDescriptor),
                    _listenSocket._rightEndPoint.Create(remoteSocketAddress));
            }

            base.CompletionCallback(0, errorCode);
        }
Exemplo n.º 15
0
        private void SendFileInternal(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
        {
            CheckTransmitFileOptions(flags);

            // Open the file, if any
            // Open it before we send the preBuffer so that any exception happens first
            FileStream fileStream = OpenFile(fileName);

            SocketError errorCode = SocketError.Success;

            using (fileStream)
            {
                // Send the preBuffer, if any
                // This will throw on error
                if (preBuffer != null && preBuffer.Length > 0)
                {
                    Send(preBuffer);
                }

                // Send the file, if any
                if (fileStream != null)
                {
                    // This can throw ObjectDisposedException.
                    errorCode = SocketPal.SendFile(_handle, fileStream);
                }
            }

            if (errorCode != SocketError.Success)
            {
                SocketException socketException = new SocketException((int)errorCode);
                UpdateStatusAfterSocketError(socketException);
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Error(this, socketException);
                }
                throw socketException;
            }

            // Send the postBuffer, if any
            // This will throw on error
            if (postBuffer != null && postBuffer.Length > 0)
            {
                Send(postBuffer);
            }
        }
Exemplo n.º 16
0
        internal SocketError DoOperationSendTo(SafeCloseSocket handle, out int bytesTransferred)
        {
            int platformFlags = SocketPal.GetPlatformSocketFlags(_socketFlags);

            SocketError errorCode;

            if (_buffer != null)
            {
                errorCode = handle.AsyncContext.SendToAsync(_buffer, _offset, _count, platformFlags, _socketAddress.Buffer, _socketAddress.Size, TransferCompletionCallback);
            }
            else
            {
                errorCode = handle.AsyncContext.SendToAsync(_bufferList, platformFlags, _socketAddress.Buffer, _socketAddress.Size, TransferCompletionCallback);
            }

            bytesTransferred = 0;
            return(errorCode);
        }
Exemplo n.º 17
0
 private unsafe void InitIPPacketInformation()
 {
     if (_controlBuffer.Length == s_controlDataSize)
     {
         // IPv4
         _ipPacketInformation = SocketPal.GetIPPacketInformation((Interop.Winsock.ControlData *)_message->controlBuffer.Pointer);
     }
     else if (_controlBuffer.Length == s_controlDataIPv6Size)
     {
         // IPv6
         _ipPacketInformation = SocketPal.GetIPPacketInformation((Interop.Winsock.ControlDataIPv6 *)_message->controlBuffer.Pointer);
     }
     else
     {
         // Other
         _ipPacketInformation = new IPPacketInformation();
     }
 }
Exemplo n.º 18
0
            public static unsafe InnerSafeCloseSocket Accept(SafeCloseSocket socketHandle, byte[] socketAddress, ref int socketAddressLen, out SocketError errorCode)
            {
                int acceptedFd;

                if (!socketHandle.IsNonBlocking)
                {
                    errorCode = socketHandle.AsyncContext.Accept(socketAddress, ref socketAddressLen, -1, out acceptedFd);
                }
                else
                {
                    SocketPal.TryCompleteAccept(socketHandle, socketAddress, ref socketAddressLen, out acceptedFd, out errorCode);
                }

                var res = new InnerSafeCloseSocket();

                res.SetHandle((IntPtr)acceptedFd);
                return(res);
            }
Exemplo n.º 19
0
            public static unsafe InnerSafeCloseSocket CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SocketError errorCode)
            {
                int fd;

                Interop.Error error = Interop.Sys.Socket(addressFamily, socketType, protocolType, &fd);
                if (error == Interop.Error.SUCCESS)
                {
                    Debug.Assert(fd != -1);

                    errorCode = SocketError.Success;

                    // The socket was created successfully; make it non-blocking and enable
                    // IPV6_V6ONLY by default for AF_INET6 sockets.
                    int err = Interop.Sys.Fcntl.SetIsNonBlocking((IntPtr)fd, 1);
                    if (err != 0)
                    {
                        Interop.Sys.Close((IntPtr)fd);
                        fd        = -1;
                        errorCode = SocketError.SocketError;
                    }
                    else if (addressFamily == AddressFamily.InterNetworkV6)
                    {
                        int on = 1;
                        error = Interop.Sys.SetSockOpt(fd, SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, (byte *)&on, sizeof(int));
                        if (error != Interop.Error.SUCCESS)
                        {
                            Interop.Sys.Close((IntPtr)fd);
                            fd        = -1;
                            errorCode = SocketPal.GetSocketErrorForErrorCode(error);
                        }
                    }
                }
                else
                {
                    Debug.Assert(fd == -1);

                    errorCode = SocketPal.GetSocketErrorForErrorCode(error);
                }

                var res = new InnerSafeCloseSocket();

                res.SetHandle((IntPtr)fd);
                return(res);
            }
Exemplo n.º 20
0
        internal unsafe SocketError DoOperationReceive(SafeCloseSocket handle, out SocketFlags flags, out int bytesTransferred)
        {
            int platformFlags = SocketPal.GetPlatformSocketFlags(_socketFlags);

            SocketError errorCode;

            if (_buffer != null)
            {
                errorCode = handle.AsyncContext.ReceiveAsync(_buffer, _offset, _count, platformFlags, TransferCompletionCallback);
            }
            else
            {
                errorCode = handle.AsyncContext.ReceiveAsync(_bufferList, platformFlags, TransferCompletionCallback);
            }

            flags            = _socketFlags;
            bytesTransferred = 0;
            return(errorCode);
        }
Exemplo n.º 21
0
        private IAsyncResult BeginSendFileInternal(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
        {
            FileStream fileStream = OpenFile(fileName);

            TransmitFileAsyncResult asyncResult = new TransmitFileAsyncResult(this, state, callback);

            asyncResult.StartPostingAsyncOp(false);

            SocketError errorCode = SocketPal.SendFileAsync(_handle, fileStream, preBuffer, postBuffer, flags, asyncResult);

            // Check for synchronous exception
            if (!CheckErrorAndUpdateStatus(errorCode))
            {
                throw new SocketException((int)errorCode);
            }

            asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);

            return(asyncResult);
        }
Exemplo n.º 22
0
        private unsafe void InitIPPacketInformation()
        {
            int?controlBufferLength = _controlBuffer?.Length;

            if (controlBufferLength == sizeof(Interop.Winsock.ControlData))
            {
                // IPv4
                _ipPacketInformation = SocketPal.GetIPPacketInformation((Interop.Winsock.ControlData *)_message->controlBuffer.Pointer);
            }
            else if (controlBufferLength == sizeof(Interop.Winsock.ControlDataIPv6))
            {
                // IPv6
                _ipPacketInformation = SocketPal.GetIPPacketInformation((Interop.Winsock.ControlDataIPv6 *)_message->controlBuffer.Pointer);
            }
            else
            {
                // Other
                _ipPacketInformation = default;
            }
        }
Exemplo n.º 23
0
        private void SendFileInternal(string?fileName, byte[]?preBuffer, byte[]?postBuffer, TransmitFileOptions flags)
        {
            CheckTransmitFileOptions(flags);

            // Open the file, if any
            // Open it before we send the preBuffer so that any exception happens first
            FileStream?fileStream = OpenFile(fileName);

            SocketError errorCode = SocketError.Success;

            using (fileStream)
            {
                // Send the preBuffer, if any
                // This will throw on error
                if (preBuffer != null && preBuffer.Length > 0)
                {
                    Send(preBuffer);
                }

                // Send the file, if any
                if (fileStream != null)
                {
                    // This can throw ObjectDisposedException.
                    errorCode = SocketPal.SendFile(_handle, fileStream);
                }
            }

            if (errorCode != SocketError.Success)
            {
                UpdateSendSocketErrorForDisposed(ref errorCode);

                UpdateStatusAfterSocketErrorAndThrowException(errorCode);
            }

            // Send the postBuffer, if any
            // This will throw on error
            if (postBuffer != null && postBuffer.Length > 0)
            {
                Send(postBuffer);
            }
        }
Exemplo n.º 24
0
        private async Task SendFileInternalAsync(FileStream?fileStream, byte[]?preBuffer, byte[]?postBuffer)
        {
            SocketError errorCode = SocketError.Success;

            using (fileStream)
            {
                // Send the preBuffer, if any
                // This will throw on error
                if (preBuffer != null && preBuffer.Length > 0)
                {
                    // Using "this." makes the extension method kick in
                    await this.SendAsync(new ArraySegment <byte>(preBuffer), SocketFlags.None).ConfigureAwait(false);
                }

                // Send the file, if any
                if (fileStream != null)
                {
                    var tcs = new TaskCompletionSource <SocketError>();
                    errorCode = SocketPal.SendFileAsync(_handle, fileStream, (_, socketError) => tcs.SetResult(socketError));
                    if (errorCode == SocketError.IOPending)
                    {
                        errorCode = await tcs.Task.ConfigureAwait(false);
                    }
                }
            }

            if (errorCode != SocketError.Success)
            {
                UpdateSendSocketErrorForDisposed(ref errorCode);
                UpdateStatusAfterSocketErrorAndThrowException(errorCode);
            }

            // Send the postBuffer, if any
            // This will throw on error
            if (postBuffer != null && postBuffer.Length > 0)
            {
                // Using "this." makes the extension method kick in
                await this.SendAsync(new ArraySegment <byte>(postBuffer), SocketFlags.None).ConfigureAwait(false);
            }
        }
            internal static unsafe InnerSafeCloseSocket Accept(SafeSocketHandle socketHandle, byte[] socketAddress, ref int socketAddressLen, out SocketError errorCode)
            {
                IntPtr acceptedFd;

                if (!socketHandle.IsNonBlocking)
                {
                    errorCode = socketHandle.AsyncContext.Accept(socketAddress, ref socketAddressLen, out acceptedFd);
                }
                else
                {
                    bool completed = SocketPal.TryCompleteAccept(socketHandle, socketAddress, ref socketAddressLen, out acceptedFd, out errorCode);
                    if (!completed)
                    {
                        errorCode = SocketError.WouldBlock;
                    }
                }

                var res = new InnerSafeCloseSocket();

                res.SetHandle(acceptedFd);
                return(res);
            }
            internal static unsafe InnerSafeCloseSocket CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SocketError errorCode)
            {
                IntPtr fd;

                Interop.Error error = Interop.Sys.Socket(addressFamily, socketType, protocolType, &fd);
                if (error == Interop.Error.SUCCESS)
                {
                    Debug.Assert(fd != (IntPtr)(-1), "fd should not be -1");

                    errorCode = SocketError.Success;

                    // The socket was created successfully; enable IPV6_V6ONLY by default for normal AF_INET6 sockets.
                    // This fails on raw sockets so we just let them be in default state.
                    if (addressFamily == AddressFamily.InterNetworkV6 && socketType != SocketType.Raw)
                    {
                        int on = 1;
                        error = Interop.Sys.SetSockOpt(fd, SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, (byte *)&on, sizeof(int));
                        if (error != Interop.Error.SUCCESS)
                        {
                            Interop.Sys.Close(fd);
                            fd        = (IntPtr)(-1);
                            errorCode = SocketPal.GetSocketErrorForErrorCode(error);
                        }
                    }
                }
                else
                {
                    Debug.Assert(fd == (IntPtr)(-1), $"Unexpected fd: {fd}");

                    errorCode = SocketPal.GetSocketErrorForErrorCode(error);
                }

                var res = new InnerSafeCloseSocket();

                res.SetHandle(fd);
                return(res);
            }
        // This method is called by base.CompletionPortCallback base.OverlappedCallback as part of IO completion
        internal override object PostCompletion(int numBytes)
        {
            SocketError errorCode = (SocketError)ErrorCode;
            Socket      socket    = (Socket)AsyncObject;

            if (errorCode == SocketError.Success)
            {
                // Set the socket context.
                try
                {
                    errorCode = Interop.Winsock.setsockopt(
                        socket.SafeHandle,
                        SocketOptionLevel.Socket,
                        SocketOptionName.UpdateConnectContext,
                        null,
                        0);
                    if (errorCode == SocketError.SocketError)
                    {
                        errorCode = SocketPal.GetLastSocketError();
                    }
                }
                catch (ObjectDisposedException)
                {
                    errorCode = SocketError.OperationAborted;
                }

                ErrorCode = (int)errorCode;
            }

            if (errorCode == SocketError.Success)
            {
                socket.SetToConnected();
                return(socket);
            }

            return(null);
        }
Exemplo n.º 28
0
            public static unsafe InnerSafeCloseSocket CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SocketError errorCode)
            {
                int fd;

                Interop.Error error = Interop.Sys.Socket(addressFamily, socketType, protocolType, &fd);
                if (error == Interop.Error.SUCCESS)
                {
                    Debug.Assert(fd != -1, "fd should not be -1");

                    errorCode = SocketError.Success;

                    // The socket was created successfully; enable IPV6_V6ONLY by default for AF_INET6 sockets.
                    if (addressFamily == AddressFamily.InterNetworkV6)
                    {
                        int on = 1;
                        error = Interop.Sys.DangerousSetSockOpt(fd, SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, (byte *)&on, sizeof(int));
                        if (error != Interop.Error.SUCCESS)
                        {
                            Interop.Sys.Close((IntPtr)fd);
                            fd        = -1;
                            errorCode = SocketPal.GetSocketErrorForErrorCode(error);
                        }
                    }
                }
                else
                {
                    Debug.Assert(fd == -1, $"Unexpected fd: {fd}");

                    errorCode = SocketPal.GetSocketErrorForErrorCode(error);
                }

                var res = new InnerSafeCloseSocket();

                res.SetHandle((IntPtr)fd);
                return(res);
            }
            private unsafe SocketError InnerReleaseHandle()
            {
                Interop.Error errorCode = Interop.Error.SUCCESS;

                // If _abortive was set to false in Close, it's safe to block here, which means
                // we can honor the linger options set on the socket.  It also means closesocket() might return WSAEWOULDBLOCK, in which
                // case we need to do some recovery.
                if (!_abortive)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, $"handle:{handle} Following 'non-abortive' branch.");
                    }

                    // Close, and if its errno is other than EWOULDBLOCK, there's nothing more to do - we either succeeded or failed.
                    errorCode = CloseHandle(handle);
                    if (errorCode != Interop.Error.EWOULDBLOCK)
                    {
                        return(SocketPal.GetSocketErrorForErrorCode(errorCode));
                    }

                    // The socket must be non-blocking with a linger timeout set.
                    // We have to set the socket to blocking.
                    if (Interop.Sys.Fcntl.DangerousSetIsNonBlocking(handle, 0) == 0)
                    {
                        // The socket successfully made blocking; retry the close().
                        return(SocketPal.GetSocketErrorForErrorCode(CloseHandle(handle)));
                    }

                    // The socket could not be made blocking; fall through to the regular abortive close.
                }

                // By default or if the non-abortive path failed, set linger timeout to zero to get an abortive close (RST).
                var linger = new Interop.Sys.LingerOption
                {
                    OnOff   = 1,
                    Seconds = 0
                };

                errorCode = Interop.Sys.SetLingerOption(handle, &linger);
#if DEBUG
                _closeSocketLinger = SocketPal.GetSocketErrorForErrorCode(errorCode);
#endif
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, $"handle:{handle}, setsockopt():{errorCode}");
                }

                switch (errorCode)
                {
                case Interop.Error.SUCCESS:
                case Interop.Error.EINVAL:
                case Interop.Error.ENOPROTOOPT:
                    errorCode = CloseHandle(handle);
                    break;

                    // For other errors, it's too dangerous to try closesocket() - it might block!
                }

                return(SocketPal.GetSocketErrorForErrorCode(errorCode));
            }
Exemplo n.º 30
0
            private unsafe SocketError InnerReleaseHandle()
            {
                int errorCode;

                // If _blockable was set in BlockingRelease, it's safe to block here, which means
                // we can honor the linger options set on the socket.  It also means closesocket() might return WSAEWOULDBLOCK, in which
                // case we need to do some recovery.
                if (_blockable)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, $"handle:{handle} Following 'blockable' branch.");
                    }

                    errorCode = Interop.Sys.Close(handle);
                    if (errorCode == -1)
                    {
                        errorCode = (int)Interop.Sys.GetLastError();
                    }

                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, $"handle:{handle}, close()#1:{errorCode}");
                    }
#if DEBUG
                    _closeSocketHandle = handle;
                    _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode);
#endif

                    // If it's not EWOULDBLOCK, there's no more recourse - we either succeeded or failed.
                    if (errorCode != (int)Interop.Error.EWOULDBLOCK)
                    {
                        return(SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode));
                    }

                    // The socket must be non-blocking with a linger timeout set.
                    // We have to set the socket to blocking.
                    errorCode = Interop.Sys.Fcntl.DangerousSetIsNonBlocking(handle, 0);
                    if (errorCode == 0)
                    {
                        // The socket successfully made blocking; retry the close().
                        errorCode = Interop.Sys.Close(handle);

                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(this, $"handle:{handle}, close()#2:{errorCode}");
                        }
#if DEBUG
                        _closeSocketHandle = handle;
                        _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode);
#endif
                        return(SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode));
                    }

                    // The socket could not be made blocking; fall through to the regular abortive close.
                }

                // By default or if CloseAsIs() path failed, set linger timeout to zero to get an abortive close (RST).
                var linger = new Interop.Sys.LingerOption {
                    OnOff   = 1,
                    Seconds = 0
                };

                errorCode = (int)Interop.Sys.SetLingerOption(handle, &linger);
#if DEBUG
                _closeSocketLinger = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode);
#endif
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, $"handle:{handle}, setsockopt():{errorCode}");
                }

                if (errorCode != 0 && errorCode != (int)Interop.Error.EINVAL && errorCode != (int)Interop.Error.ENOPROTOOPT)
                {
                    // Too dangerous to try closesocket() - it might block!
                    return(SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode));
                }

                errorCode = Interop.Sys.Close(handle);
#if DEBUG
                _closeSocketHandle = handle;
                _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode);
#endif
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, $"handle:{handle}, close#3():{(errorCode == -1 ? (int)Interop.Sys.GetLastError() : errorCode)}");
                }

                return(SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode));
            }