Example #1
0
        private void WebSocket(IApplicationBuilder app)
        {
            app.Run(async context =>
            {
                var upgradeFeature = context.Features.Get <IHttpUpgradeFeature>();

                // Generate WebSocket response headers
                string key          = context.Request.Headers[Constants.Headers.SecWebSocketKey].ToString();
                var responseHeaders = HandshakeHelpers.GenerateResponseHeaders(key);
                foreach (var headerPair in responseHeaders)
                {
                    context.Response.Headers[headerPair.Key] = headerPair.Value;
                }

                // Upgrade the connection
                Stream opaqueTransport = await upgradeFeature.UpgradeAsync();

                // Get the WebSocket object
                var ws = WebSocketProtocol.CreateFromStream(opaqueTransport, isServer: true, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2));

                var appLifetime = app.ApplicationServices.GetRequiredService <IApplicationLifetime>();

                await Echo(ws, appLifetime.ApplicationStopping);
            });
        }
Example #2
0
        public static async Task ManagedWebSocket_ReceiveUTF8SplitAcrossMultipleBuffers()
        {
            // 1 character - 2 bytes
            byte[] payload = Encoding.UTF8.GetBytes("\u00E6");
            var    frame   = new byte[payload.Length + 2];

            frame[0] = 0x81; // FIN = true, Opcode = Text
            frame[1] = (byte)payload.Length;
            Array.Copy(payload, 0, frame, 2, payload.Length);

            using (var stream = new MemoryStream(frame, writable: true))
            {
                WebSocket websocket = WebSocketProtocol.CreateFromStream(stream, false, "null", Timeout.InfiniteTimeSpan);

                // read first half of the multi-byte character
                var recvBuffer = new byte[1];
                WebSocketReceiveResult result = await websocket.ReceiveAsync(new ArraySegment <byte>(recvBuffer), CancellationToken.None);

                Assert.False(result.EndOfMessage);
                Assert.Equal(1, result.Count);
                Assert.Equal(0xc3, recvBuffer[0]);

                // read second half of the multi-byte character
                result = await websocket.ReceiveAsync(new ArraySegment <byte>(recvBuffer), CancellationToken.None);

                Assert.True(result.EndOfMessage);
                Assert.Equal(1, result.Count);
                Assert.Equal(0xa6, recvBuffer[0]);
            }
        }
        public override async Task ProcessRequestAsync()
        {
            DoUpgrade();

            await Connection.Transport.Output.FlushAsync();

            using (var ws = WebSocketProtocol.CreateFromStream(new DuplexStream(Connection.Transport), isServer: true, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2), new byte[14]))
            {
                await ProcessAsync(ws);
            }
        }
Example #4
0
        public static WebSocketPair Create()
        {
            // Create streams
            var serverStream = new DuplexStream();
            var clientStream = serverStream.CreateReverseDuplexStream();

            return(new WebSocketPair(
                       serverStream,
                       clientStream,
                       clientSocket: WebSocketProtocol.CreateFromStream(clientStream, isServer: false, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2)),
                       serverSocket: WebSocketProtocol.CreateFromStream(serverStream, isServer: true, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2))));
        }
Example #5
0
        public void CreateFromStream_InvalidArguments_Throws()
        {
            AssertExtensions.Throws <ArgumentNullException>("stream",
                                                            () => WebSocketProtocol.CreateFromStream(null, true, "subProtocol", TimeSpan.FromSeconds(30), default(Memory <byte>)));
            AssertExtensions.Throws <ArgumentException>("stream",
                                                        () => WebSocketProtocol.CreateFromStream(new MemoryStream(new byte[100], writable: false), true, "subProtocol", TimeSpan.FromSeconds(30), default(Memory <byte>)));
            AssertExtensions.Throws <ArgumentException>("stream",
                                                        () => WebSocketProtocol.CreateFromStream(new UnreadableStream(), true, "subProtocol", TimeSpan.FromSeconds(30), default(Memory <byte>)));

            AssertExtensions.Throws <ArgumentException>("subProtocol",
                                                        () => WebSocketProtocol.CreateFromStream(new MemoryStream(), true, "    ", TimeSpan.FromSeconds(30), default(Memory <byte>)));
            AssertExtensions.Throws <ArgumentException>("subProtocol",
                                                        () => WebSocketProtocol.CreateFromStream(new MemoryStream(), true, "\xFF", TimeSpan.FromSeconds(30), default(Memory <byte>)));

            AssertExtensions.Throws <ArgumentOutOfRangeException>("keepAliveInterval", () =>
                                                                  WebSocketProtocol.CreateFromStream(new MemoryStream(), true, "subProtocol", TimeSpan.FromSeconds(-2), default(Memory <byte>)));
        }
            public async Task <WebSocket> AcceptAsync(WebSocketAcceptContext acceptContext)
            {
                if (!IsWebSocketRequest)
                {
                    throw new InvalidOperationException("Not a WebSocket request."); // TODO: LOC
                }

                string subProtocol = null;

                if (acceptContext != null)
                {
                    subProtocol = acceptContext.SubProtocol;
                }

                TimeSpan keepAliveInterval     = _options.KeepAliveInterval;
                int      receiveBufferSize     = _options.ReceiveBufferSize;
                var      advancedAcceptContext = acceptContext as ExtendedWebSocketAcceptContext;

                if (advancedAcceptContext != null)
                {
                    if (advancedAcceptContext.ReceiveBufferSize.HasValue)
                    {
                        receiveBufferSize = advancedAcceptContext.ReceiveBufferSize.Value;
                    }
                    if (advancedAcceptContext.KeepAliveInterval.HasValue)
                    {
                        keepAliveInterval = advancedAcceptContext.KeepAliveInterval.Value;
                    }
                }

                string key = string.Join(", ", _context.Request.Headers[Constants.Headers.SecWebSocketKey]);

                var responseHeaders = HandshakeHelpers.GenerateResponseHeaders(key, subProtocol);

                foreach (var headerPair in responseHeaders)
                {
                    _context.Response.Headers[headerPair.Key] = headerPair.Value;
                }

                Stream opaqueTransport = await _upgradeFeature.UpgradeAsync(); // Sets status code to 101

                // Allocate a buffer for receive (default is 4k)
                var buffer = new byte[receiveBufferSize];

                return(WebSocketProtocol.CreateFromStream(opaqueTransport, isServer: true, subProtocol: subProtocol, keepAliveInterval: keepAliveInterval, buffer: buffer));
            }
        private static async Task <WebSocket> Upgrade(HttpContext context)
        {
            var upgradeFeature = context.Features.Get <IHttpUpgradeFeature>();

            // Generate WebSocket response headers
            string key             = context.Request.Headers[Constants.Headers.SecWebSocketKey].ToString();
            var    responseHeaders = HandshakeHelpers.GenerateResponseHeaders(key);

            foreach (var headerPair in responseHeaders)
            {
                context.Response.Headers[headerPair.Key] = headerPair.Value;
            }

            // Upgrade the connection
            Stream opaqueTransport = await upgradeFeature.UpgradeAsync();

            // Get the WebSocket object
            var ws = WebSocketProtocol.CreateFromStream(opaqueTransport, isServer: true, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2));

            return(ws);
        }
        public async Task WebSocketProtocol_CreateFromConnectedStream_Succeeds(Uri echoUri)
        {
            Uri uri = new UriBuilder(echoUri)
            {
                Scheme = (echoUri.Scheme == "ws") ? "http" : "https"
            }.Uri;
            HttpRequestMessage            request = new HttpRequestMessage(HttpMethod.Get, uri);
            KeyValuePair <string, string> secKeyAndSecWebSocketAccept = CreateSecKeyAndSecWebSocketAccept();

            AddWebSocketHeaders(request, secKeyAndSecWebSocketAccept.Key);
            DirectManagedHttpClientHandler handler = DirectManagedHttpClientHandler.CreateHandler();

            using (HttpResponseMessage response = await handler.SendAsync(request, CancellationToken.None).ConfigureAwait(false))
            {
                Assert.Equal(HttpStatusCode.SwitchingProtocols, response.StatusCode);
                using (Stream connectedStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                {
                    Assert.True(connectedStream.CanRead);
                    Assert.True(connectedStream.CanWrite);
                    using (WebSocket socket = WebSocketProtocol.CreateFromStream(connectedStream, false, null, TimeSpan.FromSeconds(10)))
                    {
                        Assert.NotNull(socket);
                        Assert.Equal(WebSocketState.Open, socket.State);

                        string expected            = "Hello World!";
                        ArraySegment <byte> buffer = new ArraySegment <byte>(Encoding.UTF8.GetBytes(expected));
                        await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);

                        buffer = new ArraySegment <byte>(new byte[buffer.Count]);
                        await socket.ReceiveAsync(buffer, CancellationToken.None);

                        Assert.Equal(expected, Encoding.UTF8.GetString(buffer.Array));
                    }
                }
            }
        }
 protected override WebSocket CreateFromStream(Stream stream, bool isServer, string subProtocol, TimeSpan keepAliveInterval) =>
 WebSocketProtocol.CreateFromStream(stream, isServer, subProtocol, keepAliveInterval);
Example #10
0
        public async Task WebSocketProtocol_CreateFromConnectedStream_Succeeds(Uri echoUri)
        {
            using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                bool secure = echoUri.Scheme == "wss";
                client.Connect(echoUri.Host, secure ? 443 : 80);

                Stream stream = new NetworkStream(client, ownsSocket: false);
                if (secure)
                {
                    SslStream ssl = new SslStream(stream, leaveInnerStreamOpen: true, delegate { return(true); });
                    await ssl.AuthenticateAsClientAsync(echoUri.Host);

                    stream = ssl;
                }

                using (stream)
                {
                    using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize: 1, leaveOpen: true))
                    {
                        await writer.WriteAsync($"GET {echoUri.PathAndQuery} HTTP/1.1\r\n");

                        await writer.WriteAsync($"Host: {echoUri.Host}\r\n");

                        await writer.WriteAsync($"Upgrade: websocket\r\n");

                        await writer.WriteAsync($"Connection: Upgrade\r\n");

                        await writer.WriteAsync($"Sec-WebSocket-Version: 13\r\n");

                        await writer.WriteAsync($"Sec-WebSocket-Key: {Convert.ToBase64String(Guid.NewGuid().ToByteArray())}\r\n");

                        await writer.WriteAsync($"\r\n");
                    }

                    using (var reader = new StreamReader(stream, Encoding.ASCII, detectEncodingFromByteOrderMarks: false, bufferSize: 1, leaveOpen: true))
                    {
                        string statusLine = await reader.ReadLineAsync();

                        Assert.NotEmpty(statusLine);
                        Assert.Equal("HTTP/1.1 101 Switching Protocols", statusLine);
                        while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                        {
                            ;
                        }
                    }

                    using (WebSocket socket = WebSocketProtocol.CreateFromStream(stream, false, null, TimeSpan.FromSeconds(10)))
                    {
                        Assert.NotNull(socket);
                        Assert.Equal(WebSocketState.Open, socket.State);

                        string expected            = "Hello World!";
                        ArraySegment <byte> buffer = new ArraySegment <byte>(Encoding.UTF8.GetBytes(expected));
                        await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);

                        buffer = new ArraySegment <byte>(new byte[buffer.Count]);
                        await socket.ReceiveAsync(buffer, CancellationToken.None);

                        Assert.Equal(expected, Encoding.UTF8.GetString(buffer.Array));
                    }
                }
            }
        }
Example #11
0
 public void CreateFromStream_ValidBufferSizes_Succeed(int bufferSize)
 {
     Assert.NotNull(WebSocketProtocol.CreateFromStream(new MemoryStream(), false, null, Timeout.InfiniteTimeSpan, new Memory <byte>(new byte[bufferSize])));
     Assert.NotNull(WebSocketProtocol.CreateFromStream(new MemoryStream(), true, null, Timeout.InfiniteTimeSpan, new Memory <byte>(new byte[bufferSize])));
 }