/// <summary> /// Connect with options specified /// </summary> /// <param name="uri">The WebSocket uri to connect to (e.g. ws://example.com or wss://example.com for SSL)</param> /// <param name="options">The WebSocket client options</param> /// <param name="token">The optional cancellation token</param> /// <returns>A connected web socket instance</returns> public async Task <WebSocket> ConnectAsync(Uri uri, WebSocketClientOptions options, CancellationToken token = default(CancellationToken)) { Guid guid = Guid.NewGuid(); string host = uri.Host; int port = uri.Port; var tcpClient = new TcpClient(host, port); tcpClient.NoDelay = options.NoDelay; // removed this because it throws unsupported in Unity. //tcpClient.Client.DualMode = true; string uriScheme = uri.Scheme.ToLower(); bool useSsl = uriScheme == "wss" || uriScheme == "https"; // removed this because the TcpClient connects when it is constructed. //IPAddress ipAddress; //if (IPAddress.TryParse(host, out ipAddress)) //{ // Events.Log.ClientConnectingToIpAddress(guid, ipAddress.ToString(), port); // await tcpClient.ConnectAsync(ipAddress, port); //} //else //{ // Events.Log.ClientConnectingToHost(guid, host, port); // await tcpClient.ConnectAsync(host, port); //} token.ThrowIfCancellationRequested(); Stream stream = GetStream(guid, tcpClient, useSsl, host); return(await PerformHandshake(guid, uri, stream, options, token)); }
/// <summary> /// Connect with options specified /// </summary> /// <param name="uri">The WebSocket uri to connect to (e.g. ws://example.com or wss://example.com for SSL)</param> /// <param name="options">The WebSocket client options</param> /// <param name="token">The optional cancellation token</param> /// <returns>A connected web socket instance</returns> public async Task <WebSocket> ConnectAsync(Uri uri, WebSocketClientOptions options, CancellationToken token = default(CancellationToken)) { Guid guid = Guid.NewGuid(); string host = uri.Host; int port = uri.Port; var tcpClient = new TcpClient(); tcpClient.NoDelay = options.NoDelay; string uriScheme = uri.Scheme.ToLower(); bool useSsl = uriScheme == "wss" || uriScheme == "https"; IPAddress ipAddress; if (IPAddress.TryParse(host, out ipAddress)) { Events.Log.ClientConnectingToIpAddress(guid, ipAddress.ToString(), port); await tcpClient.ConnectAsync(ipAddress, port); } else { Events.Log.ClientConnectingToHost(guid, host, port); await tcpClient.ConnectAsync(host, port); } token.ThrowIfCancellationRequested(); Stream stream = GetStream(guid, tcpClient, useSsl, host); return(await PerformHandshake(guid, uri, stream, options, token)); }
private async Task <WebSocket> PerformHandshake(Guid guid, Uri uri, Stream stream, WebSocketClientOptions options, CancellationToken token) { var rand = new Random(); var keyAsBytes = new byte[16]; rand.NextBytes(keyAsBytes); var secWebSocketKey = Convert.ToBase64String(keyAsBytes); var additionalHeaders = GetAdditionalHeaders(options.AdditionalHttpHeaders); var handshakeHttpRequest = $"GET {uri.PathAndQuery} HTTP/1.1\r\n" + $"Host: {uri.Host}:{uri.Port}\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + $"Sec-WebSocket-Key: {secWebSocketKey}\r\n" + $"Origin: http://{uri.Host}:{uri.Port}\r\n" + $"Sec-WebSocket-Protocol: {options.SecWebSocketProtocol}\r\n" + additionalHeaders + "Sec-WebSocket-Version: 13\r\n\r\n"; var httpRequest = Encoding.UTF8.GetBytes(handshakeHttpRequest); stream.Write(httpRequest, 0, httpRequest.Length); Events.Log.HandshakeSent(guid, handshakeHttpRequest); return(await ConnectAsync(stream, secWebSocketKey, options, token)); }
/// <summary> /// Connect with options specified /// </summary> /// <param name="uri">The WebSocket uri to connect to (e.g. ws://example.com or wss://example.com for SSL)</param> /// <param name="options">The WebSocket client options</param> /// <param name="token">The optional cancellation token</param> /// <returns>A connected web socket instance</returns> public async Task <WebSocket> ConnectAsync(Uri uri, WebSocketClientOptions options, CancellationToken token = default(CancellationToken)) { var guid = Guid.NewGuid(); string host = uri.Host; int port = uri.Port; var tcpClient = new TcpClient(AddressFamily.InterNetworkV6); tcpClient.NoDelay = options.NoDelay; tcpClient.Client.DualMode = true; string uriScheme = uri.Scheme.ToLower(); bool useSsl = uriScheme == "wss" || uriScheme == "https"; if (IPAddress.TryParse(host, out IPAddress ipAddress)) { Events.Log.ClientConnectingToIpAddress(guid, ipAddress.ToString(), port); await tcpClient.ConnectAsync(ipAddress, port); } else { Events.Log.ClientConnectingToHost(guid, host, port); await tcpClient.ConnectAsync(host, port); } token.ThrowIfCancellationRequested(); Stream stream = GetStream(guid, tcpClient, useSsl, host); var websocket = await PerformHandshake(guid, uri, stream, options, token) as WebSocketImplementation; websocket.TcpClient = tcpClient; return(websocket); }
/// <summary> /// Connect with a stream that has already been opened and HTTP websocket upgrade request sent /// This function will check the handshake response from the server and proceed if successful /// Use this function if you have specific requirements to open a conenction like using special http headers and cookies /// You will have to build your own HTTP websocket upgrade request /// You may not even choose to use TCP/IP and this function will allow you to do that /// </summary> /// <param name="responseStream">The full duplex response stream from the server</param> /// <param name="secWebSocketKey">The secWebSocketKey you used in the handshake request</param> /// <param name="options">The WebSocket client options</param> /// <param name="token">The optional cancellation token</param> /// <returns></returns> public async Task <WebSocket> ConnectAsync(Stream responseStream, string secWebSocketKey, WebSocketClientOptions options, CancellationToken token = default(CancellationToken)) { var guid = Guid.NewGuid(); return(await ConnectAsync(guid, responseStream, secWebSocketKey, options.KeepAliveInterval, options.SecWebSocketExtensions, options.IncludeExceptionInCloseResponse, token)); }
/// <summary> /// Connect with options specified /// </summary> /// <param name="uri">The WebSocket uri to connect to (e.g. ws://example.com or wss://example.com for SSL)</param> /// <param name="options">The WebSocket client options</param> /// <param name="token">The optional cancellation token</param> /// <returns>A connected web socket instance</returns> public async Task <WebSocket> ConnectAsync(Uri uri, WebSocketClientOptions options, CancellationToken token = default(CancellationToken)) { Guid guid = Guid.NewGuid(); string host = uri.Host; int port = uri.Port; string uriScheme = uri.Scheme.ToLower(); bool useSsl = uriScheme == "wss" || uriScheme == "https"; Stream stream = await GetStream(guid, useSsl, options.NoDelay, host, port, token); return(await PerformHandshake(guid, uri, stream, options, token)); }