예제 #1
0
        public override int EndRead(IAsyncResult asyncResult)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User))
            {
#endif
            _negoState.CheckThrow(true);

            if (!_negoState.CanGetSecureStream)
            {
                return(TaskToApm.End <int>(asyncResult));
            }


            if (asyncResult == null)
            {
                throw new ArgumentNullException(nameof(asyncResult));
            }

            BufferAsyncResult bufferResult = asyncResult as BufferAsyncResult;
            if (bufferResult == null)
            {
                throw new ArgumentException(SR.Format(SR.net_io_async_result, asyncResult.GetType().FullName), nameof(asyncResult));
            }

            if (Interlocked.Exchange(ref _NestedRead, 0) == 0)
            {
                throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, "EndRead"));
            }

            // No "artificial" timeouts implemented so far, InnerStream controls timeout.
            bufferResult.InternalWaitForCompletion();

            if (bufferResult.Result is Exception e)
            {
                if (e is IOException)
                {
                    ExceptionDispatchInfo.Throw(e);
                }

                throw new IOException(SR.net_io_read, e);
            }

            return(bufferResult.Int32Result);

#if DEBUG
        }
#endif
        }
예제 #2
0
        // BeginWrite - provide async write functionality.
        //
        // This method provides async write functionality. All we do is
        // call through to the underlying socket async send.
        //
        // Input:
        //
        //     buffer  - Buffer to write into.
        //     offset  - Offset into the buffer where we're to write.
        //     size   - Number of bytes to written.
        //
        // Returns:
        //
        //     An IASyncResult, representing the write.
        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async))
            {
#endif
            bool canWrite = CanWrite;     // Prevent race with Dispose.
            ThrowIfDisposed();
            if (!canWrite)
            {
                throw new InvalidOperationException(SR.net_readonlystream);
            }

            // Validate input parameters.
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if ((uint)offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if ((uint)size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }

            try
            {
                // Call BeginSend on the Socket.
                return(_streamSocket.BeginSend(
                           buffer,
                           offset,
                           size,
                           SocketFlags.None,
                           callback,
                           state));
            }
            catch (Exception exception) when(!(exception is OutOfMemoryException))
            {
                // Some sort of error occurred on the socket call,
                // set the SocketException as InnerException and throw.
                throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
            }
#if DEBUG
        }
#endif
        }
예제 #3
0
        private int _closeTimeout = Socket.DefaultCloseTimeout; // -1 = respect linger options

        public void Close(int timeout)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync))
            {
#endif
            if (timeout < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(timeout));
            }
            _closeTimeout = timeout;
            Dispose();
#if DEBUG
        }
#endif
        }
예제 #4
0
        public NetworkStream(Socket socket, FileAccess access, bool ownsSocket)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User))
            {
#endif
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }
            if (!socket.Blocking)
            {
                throw new IOException(SR.net_sockets_blocking);
            }
            if (!socket.Connected)
            {
                throw new IOException(SR.net_notconnected);
            }
            if (socket.SocketType != SocketType.Stream)
            {
                throw new IOException(SR.net_notstream);
            }

            _streamSocket = socket;
            _ownsSocket   = ownsSocket;

            switch (access)
            {
            case FileAccess.Read:
                _readable = true;
                break;

            case FileAccess.Write:
                _writeable = true;
                break;

            case FileAccess.ReadWrite:
            default:         // assume FileAccess.ReadWrite
                _readable  = true;
                _writeable = true;
                break;
            }
#if DEBUG
        }
#endif
        }
예제 #5
0
        public override void EndWrite(IAsyncResult asyncResult)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User))
            {
#endif
            _negoState.CheckThrow(true);

            if (!_negoState.CanGetSecureStream)
            {
                InnerStream.EndWrite(asyncResult);
                return;
            }

            if (asyncResult == null)
            {
                throw new ArgumentNullException(nameof(asyncResult));
            }

            BufferAsyncResult bufferResult = asyncResult as BufferAsyncResult;
            if (bufferResult == null)
            {
                throw new ArgumentException(SR.Format(SR.net_io_async_result, asyncResult.GetType().FullName), nameof(asyncResult));
            }

            if (Interlocked.Exchange(ref _NestedWrite, 0) == 0)
            {
                throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, "EndWrite"));
            }

            // No "artificial" timeouts implemented so far, InnerStream controls timeout.
            bufferResult.InternalWaitForCompletion();

            if (bufferResult.Result is Exception)
            {
                if (bufferResult.Result is IOException)
                {
                    throw (Exception)bufferResult.Result;
                }

                throw new IOException(SR.net_io_write, (Exception)bufferResult.Result);
            }
#if DEBUG
        }
#endif
        }
예제 #6
0
        // Write - provide core Write functionality.
        //
        // Provide core write functionality. All we do is call through to the
        // socket Send method..
        //
        // Input:
        //
        //     Buffer  - Buffer to write from.
        //     Offset  - Offset into the buffer from where we'll start writing.
        //     Count   - Number of bytes to write.
        //
        // Returns:
        //
        //     Number of bytes written. We'll throw an exception if we
        //     can't write everything. It's brutal, but there's no other
        //     way to indicate an error.
        public override void Write(byte[] buffer, int offset, int size)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync))
            {
#endif
            bool canWrite = CanWrite;     // Prevent race with Dispose.
            if (_cleanedUp)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (!canWrite)
            {
                throw new InvalidOperationException(SR.net_readonlystream);
            }

            // Validate input parameters.
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (size < 0 || size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }

            try
            {
                // Since the socket is in blocking mode this will always complete
                // after ALL the requested number of bytes was transferred.
                _streamSocket.Send(buffer, offset, size, SocketFlags.None);
            }
            catch (Exception exception) when(!(exception is OutOfMemoryException))
            {
                // Some sort of error occurred on the socket call,
                // set the SocketException as InnerException and throw.
                throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
            }
#if DEBUG
        }
#endif
        }
예제 #7
0
        protected override void Dispose(bool disposing)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User))
            {
#endif
            try
            {
                _negoState.Close();
            }
            finally
            {
                base.Dispose(disposing);
            }
#if DEBUG
        }
#endif
        }
예제 #8
0
        // Read - provide core Read functionality.
        //
        // Provide core read functionality. All we do is call through to the
        // socket Receive functionality.
        //
        // Input:
        //
        //     Buffer  - Buffer to read into.
        //     Offset  - Offset into the buffer where we're to read.
        //     Count   - Number of bytes to read.
        //
        // Returns:
        //
        //     Number of bytes we read, or 0 if the socket is closed.
        public override int Read(byte[] buffer, int offset, int size)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync))
            {
#endif
            bool canRead = CanRead;      // Prevent race with Dispose.
            if (_cleanedUp)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (!canRead)
            {
                throw new InvalidOperationException(SR.net_writeonlystream);
            }

            // Validate input parameters.
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (size < 0 || size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }

            try
            {
                return(_streamSocket.Receive(buffer, offset, size, 0));
            }
            catch (Exception exception) when(!(exception is OutOfMemoryException))
            {
                // Some sort of error occurred on the socket call,
                // set the SocketException as InnerException and throw.
                throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
            }
#if DEBUG
        }
#endif
        }
예제 #9
0
        public override int Read(byte[] buffer, int offset, int count)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync))
            {
#endif
            _negoState.CheckThrow(true);

            if (!_negoState.CanGetSecureStream)
            {
                return(InnerStream.Read(buffer, offset, count));
            }

            return(ProcessRead(buffer, offset, count, null));

#if DEBUG
        }
#endif
        }
예제 #10
0
        public override void Write(byte[] buffer, int offset, int count)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync))
            {
#endif
            _negoState.CheckThrow(true);

            if (!_negoState.CanGetSecureStream)
            {
                InnerStream.Write(buffer, offset, count);
                return;
            }

            ProcessWrite(buffer, offset, count, null);
#if DEBUG
        }
#endif
        }
예제 #11
0
        public int EndRead(IAsyncResult asyncResult)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User))
            {
#endif
            if (_cleanedUp)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }

            // Validate input parameters.
            if (asyncResult == null)
            {
                throw new ArgumentNullException(nameof(asyncResult));
            }

            Socket chkStreamSocket = _streamSocket;
            if (chkStreamSocket == null)
            {
                throw new IOException(SR.Format(SR.net_io_readfailure, SR.net_io_connectionclosed));
            }

            try
            {
                int bytesTransferred = chkStreamSocket.EndReceive(asyncResult);
                return(bytesTransferred);
            }
            catch (Exception exception)
            {
                if (exception is OutOfMemoryException)
                {
                    throw;
                }

                // Some sort of error occurred on the socket call,
                // set the SocketException as InnerException and throw.
                throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
            }
#if DEBUG
        }
#endif
        }
예제 #12
0
        protected override void Dispose(bool disposing)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User))
            {
#endif
            // Mark this as disposed before changing anything else.
            bool cleanedUp = _cleanedUp;
            _cleanedUp = true;
            if (!cleanedUp && disposing)
            {
                // The only resource we need to free is the network stream, since this
                // is based on the client socket, closing the stream will cause us
                // to flush the data to the network, close the stream and (in the
                // NetoworkStream code) close the socket as well.
                if (_streamSocket != null)
                {
                    _readable  = false;
                    _writeable = false;
                    if (_ownsSocket)
                    {
                        // If we own the Socket (false by default), close it
                        // ignoring possible exceptions (eg: the user told us
                        // that we own the Socket but it closed at some point of time,
                        // here we would get an ObjectDisposedException)
                        Socket chkStreamSocket = _streamSocket;
                        if (chkStreamSocket != null)
                        {
                            chkStreamSocket.InternalShutdown(SocketShutdown.Both);
                            chkStreamSocket.Close(_closeTimeout);
                        }
                    }
                }
            }
#if DEBUG
        }
#endif
            base.Dispose(disposing);
        }
예제 #13
0
        public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback?asyncCallback, object?asyncState)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async))
            {
#endif
            _negoState.CheckThrow(true);

            if (!_negoState.CanGetSecureStream)
            {
                return(TaskToApm.Begin(InnerStream.ReadAsync(buffer, offset, count), asyncCallback, asyncState));
            }

            BufferAsyncResult bufferResult    = new BufferAsyncResult(this, buffer, offset, count, asyncState, asyncCallback);
            AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(bufferResult);
            ProcessRead(buffer, offset, count, asyncRequest);
            return(bufferResult);

#if DEBUG
        }
#endif
        }
예제 #14
0
        public virtual IAsyncResult BeginAuthenticateAsServer(
            NetworkCredential credential,
            ExtendedProtectionPolicy?policy,
            ProtectionLevel requiredProtectionLevel,
            TokenImpersonationLevel requiredImpersonationLevel,
            AsyncCallback?asyncCallback,
            object?asyncState)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async))
            {
#endif
            _negoState.ValidateCreateContext(_package, credential, string.Empty, policy, requiredProtectionLevel, requiredImpersonationLevel);

            LazyAsyncResult result = new LazyAsyncResult(_negoState, asyncState, asyncCallback);
            _negoState.ProcessAuthentication(result);

            return(result);

#if DEBUG
        }
#endif
        }
예제 #15
0
        public virtual IAsyncResult BeginAuthenticateAsClient(
            NetworkCredential credential,
            ChannelBinding?binding,
            string targetName,
            ProtectionLevel requiredProtectionLevel,
            TokenImpersonationLevel allowedImpersonationLevel,
            AsyncCallback?asyncCallback,
            object?asyncState)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async))
            {
#endif
            _negoState.ValidateCreateContext(_package, false, credential, targetName, binding, requiredProtectionLevel, allowedImpersonationLevel);

            LazyAsyncResult result = new LazyAsyncResult(_negoState, asyncState, asyncCallback);
            _negoState.ProcessAuthentication(result);

            return(result);

#if DEBUG
        }
#endif
        }
        private static unsafe void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
#if DEBUG
            DebugThreadTracking.SetThreadSource(ThreadKinds.CompletionPort);
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.System))
            {
#endif
            BaseOverlappedAsyncResult asyncResult = (BaseOverlappedAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);

            object returnObject = null;

            if (asyncResult.InternalPeekCompleted)
            {
                NetEventSource.Fail(null, $"asyncResult.IsCompleted: {asyncResult}");
            }
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Info(null, $"errorCode:{errorCode} numBytes:{numBytes} nativeOverlapped:{(IntPtr)nativeOverlapped}");
            }

            // Complete the IO and invoke the user's callback.
            SocketError socketError = (SocketError)errorCode;

            if (socketError != SocketError.Success && socketError != SocketError.OperationAborted)
            {
                // There are cases where passed errorCode does not reflect the details of the underlined socket error.
                // "So as of today, the key is the difference between WSAECONNRESET and ConnectionAborted,
                //  .e.g remote party or network causing the connection reset or something on the local host (e.g. closesocket
                // or receiving data after shutdown (SD_RECV)).  With Winsock/TCP stack rewrite in longhorn, there may
                // be other differences as well."

                Socket socket = asyncResult.AsyncObject as Socket;
                if (socket == null)
                {
                    socketError = SocketError.NotSocket;
                }
                else if (socket.CleanedUp)
                {
                    socketError = SocketError.OperationAborted;
                }
                else
                {
                    try
                    {
                        // The async IO completed with a failure.
                        // Here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
                        SocketFlags ignore;
                        bool        success = Interop.Winsock.WSAGetOverlappedResult(
                            socket.SafeHandle,
                            asyncResult.NativeOverlapped,
                            out numBytes,
                            false,
                            out ignore);
                        if (!success)
                        {
                            socketError = (SocketError)Marshal.GetLastWin32Error();
                            if (socketError == 0)
                            {
                                NetEventSource.Fail(asyncResult, $"socketError:0 numBytes:{numBytes}");
                            }
                        }
                        if (success)
                        {
                            NetEventSource.Fail(asyncResult, $"Unexpectedly succeeded. errorCode:{errorCode} numBytes:{numBytes}");
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        // CleanedUp check above does not always work since this code is subject to race conditions
                        socketError = SocketError.OperationAborted;
                    }
                }
            }
            asyncResult.ErrorCode = (int)socketError;
            returnObject          = asyncResult.PostCompletion((int)numBytes);
            asyncResult.ReleaseUnmanagedStructures();
            asyncResult.InvokeCallback(returnObject);
#if DEBUG
        }
#endif
        }
예제 #17
0
        public IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, Object state)
        {
#if DEBUG
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async))
            {
#endif
            bool canWrite = CanWrite;     // Prevent race with Dispose.
            if (_cleanedUp)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (!canWrite)
            {
                throw new InvalidOperationException(SR.net_readonlystream);
            }

            // Validate input parameters.
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (size < 0 || size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }

            Socket chkStreamSocket = _streamSocket;
            if (chkStreamSocket == null)
            {
                throw new IOException(SR.Format(SR.net_io_writefailure, SR.net_io_connectionclosed));
            }

            try
            {
                // Call BeginSend on the Socket.
                IAsyncResult asyncResult =
                    chkStreamSocket.BeginSend(
                        buffer,
                        offset,
                        size,
                        SocketFlags.None,
                        callback,
                        state);

                return(asyncResult);
            }
            catch (Exception exception)
            {
                if (exception is OutOfMemoryException)
                {
                    throw;
                }

                // Some sort of error occurred on the socket call,
                // set the SocketException as InnerException and throw.
                throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
            }
#if DEBUG
        }
#endif
        }