/// <inheritdoc /> /// <exception cref="ArgumentNullException">When <paramref name="endPoint"/> is <see langword="null"/>.</exception> public override async ValueTask <Connection> ConnectAsync( EndPoint?endPoint, IConnectionProperties?options = null, CancellationToken cancellationToken = default) { if (endPoint == null) { throw new ArgumentNullException(nameof(endPoint)); } cancellationToken.ThrowIfCancellationRequested(); Socket socket = CreateSocket(_addressFamily, _socketType, _protocolType, endPoint, options); try { await socket.ConnectAsync(endPoint, cancellationToken).ConfigureAwait(false); return(new SocketConnection(socket)); } catch (SocketException socketException) { socket.Dispose(); throw NetworkErrorHelper.MapSocketException(socketException); } catch { socket.Dispose(); throw; } }
public override ValueTask <int> ReadAsync(Memory <byte> buffer, CancellationToken cancellationToken) { bool canRead = CanRead; // Prevent race with Dispose. ThrowIfDisposed(); if (!canRead) { throw new InvalidOperationException(SR.net_writeonlystream); } try { return(_streamSocket.ReceiveAsync( buffer, SocketFlags.None, fromNetworkStream: true, cancellationToken: cancellationToken)); } catch (SocketException socketException) { throw NetworkErrorHelper.MapSocketException(socketException); } catch (Exception exception) when(!(exception is OutOfMemoryException)) { throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } }
public override ValueTask WriteAsync(ReadOnlyMemory <byte> buffer, CancellationToken cancellationToken) { bool canWrite = CanWrite; // Prevent race with Dispose. ThrowIfDisposed(); if (!canWrite) { throw new InvalidOperationException(SR.net_readonlystream); } try { return(_streamSocket.SendAsyncForNetworkStream( buffer, SocketFlags.None, cancellationToken)); } catch (SocketException socketException) { throw NetworkErrorHelper.MapSocketException(socketException); } catch (Exception exception) when(!(exception is OutOfMemoryException)) { throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } }
public override int Read(Span <byte> buffer) { if (GetType() != typeof(NetworkStream)) { // NetworkStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior // to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload // should use the behavior of Read(byte[],int,int) overload. return(base.Read(buffer)); } ThrowIfDisposed(); if (!CanRead) { throw new InvalidOperationException(SR.net_writeonlystream); } int bytesRead = _streamSocket.Receive(buffer, SocketFlags.None, out SocketError errorCode); if (errorCode != SocketError.Success) { var exception = new SocketException((int)errorCode); throw NetworkErrorHelper.MapSocketException(exception); } return(bytesRead); }
/// <summary> /// Establishes a new connection for a request. /// </summary> /// <param name="message">The request causing this connection to be established. Once connected, it may be reused for many subsequent requests.</param> /// <param name="endPoint">The EndPoint to connect to.</param> /// <param name="options">Properties, if any, that might change how the connection is made.</param> /// <param name="cancellationToken">A cancellation token for the asynchronous operation.</param> /// <returns>A new open connection.</returns> public virtual async ValueTask <Connection> EstablishConnectionAsync(HttpRequestMessage message, EndPoint?endPoint, IConnectionProperties options, CancellationToken cancellationToken) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (endPoint == null) { throw new ArgumentNullException(nameof(endPoint)); } Socket socket = CreateSocket(message, endPoint, options); try { using var args = new TaskSocketAsyncEventArgs(); args.RemoteEndPoint = endPoint; if (socket.ConnectAsync(args)) { using (cancellationToken.UnsafeRegister(o => Socket.CancelConnectAsync((SocketAsyncEventArgs)o !), args)) { await args.Task.ConfigureAwait(false); } } if (args.SocketError != SocketError.Success) { Exception ex = args.SocketError == SocketError.OperationAborted && cancellationToken.IsCancellationRequested ? (Exception) new OperationCanceledException(cancellationToken) : new SocketException((int)args.SocketError); throw ex; } socket.NoDelay = true; return(new SocketConnection(socket)); } catch (SocketException socketException) { socket.Dispose(); throw NetworkErrorHelper.MapSocketException(socketException); } catch { socket.Dispose(); throw; } }
// 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) { 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 (SocketException socketException) { throw NetworkErrorHelper.MapSocketException(socketException); } catch (Exception exception) when(!(exception is OutOfMemoryException)) { throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } }
// ReadAsync - provide async read functionality. // // This method provides async read functionality. All we do is // call through to the Begin/EndRead methods. // // Input: // // buffer - Buffer to read into. // offset - Offset into the buffer where we're to read. // size - Number of bytes to read. // cancellationToken - Token used to request cancellation of the operation // // Returns: // // A Task<int> representing the read. public override Task <int> ReadAsync(byte[] buffer, int offset, int size, CancellationToken cancellationToken) { bool canRead = CanRead; // Prevent race with Dispose. ThrowIfDisposed(); if (!canRead) { throw new InvalidOperationException(SR.net_writeonlystream); } // 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 { return(_streamSocket.ReceiveAsync( new Memory <byte>(buffer, offset, size), SocketFlags.None, fromNetworkStream: true, cancellationToken).AsTask()); } catch (SocketException socketException) { throw NetworkErrorHelper.MapSocketException(socketException); } catch (Exception exception) when(!(exception is OutOfMemoryException)) { throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } }
// 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) { 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 { // 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 (SocketException socketException) { throw NetworkErrorHelper.MapSocketException(socketException); } catch (Exception exception) when(!(exception is OutOfMemoryException)) { throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } }
// Handle the end of an asynchronous write. // This method is called when an async write is completed. All we // do is call through to the core socket EndSend functionality. // Returns: The number of bytes read. May throw an exception. public override void EndWrite(IAsyncResult asyncResult) { ThrowIfDisposed(); // Validate input parameters. if (asyncResult == null) { throw new ArgumentNullException(nameof(asyncResult)); } try { _streamSocket.EndSend(asyncResult); } catch (SocketException socketException) { throw NetworkErrorHelper.MapSocketException(socketException); } catch (Exception exception) when(!(exception is OutOfMemoryException)) { throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } }
public override void Write(ReadOnlySpan <byte> buffer) { if (GetType() != typeof(NetworkStream)) { // NetworkStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior // to this Write(ReadOnlySpan<byte>) overload being introduced. In that case, this Write(ReadOnlySpan<byte>) // overload should use the behavior of Write(byte[],int,int) overload. base.Write(buffer); return; } ThrowIfDisposed(); if (!CanWrite) { throw new InvalidOperationException(SR.net_readonlystream); } _streamSocket.Send(buffer, SocketFlags.None, out SocketError errorCode); if (errorCode != SocketError.Success) { var exception = new SocketException((int)errorCode); throw NetworkErrorHelper.MapSocketException(exception); } }
protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(ValueTask.FromCanceled(cancellationToken)); } try { if (method != ConnectionCloseMethod.GracefulShutdown) { // Dispose must be called first in order to cause a connection reset, // as NetworkStream.Dispose() will call Shutdown(Both). _socket.Dispose(); } // Since CreatePipe() calls CreateStream(), so _stream should be present even in the pipe case: _stream?.Dispose(); } catch (SocketException socketException) { return(ValueTask.FromException(ExceptionDispatchInfo.SetCurrentStackTrace(NetworkErrorHelper.MapSocketException(socketException)))); } catch (Exception ex) { return(ValueTask.FromException(ex)); } return(default);