public SocketConnection(Socket socket, EndPoint localEndPoint) { #pragma warning disable 168 // unused local variable if (socket == null) { throw new ArgumentNullException(nameof(socket)); } this.closeState = STATE_OPEN; try { this.LocalEndPoint = socket.LocalEndPoint; } catch (ArgumentException getLocalEndPointError) // Mono B_ug he AddressFamily InterNetworkV6 is not valid for the System.Net.IPEndPoint end point, use InterNetwork instead. { #if DEBUG System.Diagnostics.Debug.WriteLine($"An error occurred while trying to get '{nameof(socket.LocalEndPoint)}' property of established connection." + getLocalEndPointError.Unwrap()); #endif this.LocalEndPoint = localEndPoint; } try { this.RemoteEndPoint = socket.RemoteEndPoint; } catch (ArgumentException getRemoteEndPointError) // Mono B_ug he AddressFamily InterNetworkV6 is not valid for the System.Net.IPEndPoint end point, use InterNetwork instead. { #if DEBUG System.Diagnostics.Debug.WriteLine($"An error occurred while trying to get '{nameof(socket.RemoteEndPoint)}' property of established connection." + getRemoteEndPointError.Unwrap()); #endif if (UnixSocketTransport.IsUnixEndPoint(localEndPoint)) { this.RemoteEndPoint = localEndPoint; } else { this.RemoteEndPoint = null; } } this.socket = socket; this.networkStream = new NetworkStream(socket, true); this.socketEvents = new SocketAsyncEventArgs[EVENT_COUNT]; for (var i = 0; i < this.socketEvents.Length; i++) { var socketEvent = new SocketAsyncEventArgs(); socketEvent.Completed += this.OnSocketOperationCompleted; this.socketEvents[i] = socketEvent; } #pragma warning restore 168 }
/// <inheritdoc /> internal override async Task <NetworkConnection> ConnectAsync(Uri address, WebSocketListenerOptions options, CancellationToken cancellation) { if (address == null) { throw new ArgumentNullException(nameof(address)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } var remoteEndPoint = this.GetRemoteEndPoint(address); var protocolType = this.GetProtocolType(address, remoteEndPoint); // prepare socket var socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Stream, protocolType); this.SetupClientSocket(socket, remoteEndPoint); try { // prepare connection var socketConnectedCondition = new AsyncConditionSource { ContinueOnCapturedContext = false }; var socketAsyncEventArgs = new SocketAsyncEventArgs { RemoteEndPoint = remoteEndPoint, UserToken = socketConnectedCondition }; // connect socketAsyncEventArgs.Completed += (_, e) => ((AsyncConditionSource)e.UserToken).Set(); // interrupt connection when cancellation token is set var connectInterruptRegistration = cancellation.CanBeCanceled ? cancellation.Register(s => ((AsyncConditionSource)s).Interrupt(new OperationCanceledException()), socketConnectedCondition) : default(CancellationTokenRegistration); using (connectInterruptRegistration) { if (socket.ConnectAsync(socketAsyncEventArgs) == false) { socketConnectedCondition.Set(); } await socketConnectedCondition; } cancellation.ThrowIfCancellationRequested(); // check connection result if (socketAsyncEventArgs.ConnectByNameError != null) { throw socketAsyncEventArgs.ConnectByNameError; } if (socketAsyncEventArgs.SocketError != SocketError.Success) { throw new WebSocketException($"Failed to open socket to '{address}' due error '{socketAsyncEventArgs.SocketError}'.", new SocketException((int)socketAsyncEventArgs.SocketError)); } var localEndPoint = default(EndPoint); try { localEndPoint = socket.LocalEndPoint; } catch { if (UnixSocketTransport.IsUnixEndPoint(remoteEndPoint)) { localEndPoint = remoteEndPoint; } } var connection = new SocketConnection(socket, localEndPoint); socket = null; return(connection); } finally { if (socket != null) { SafeEnd.Dispose(socket, options.Logger); } } }