Beispiel #1
0
        public async Task GetResponseAsync(HttpListenerContext context, string localBaseUrl, string remoteBaseUrl, CancellationToken ct) {
            string postUri = null;

            if (context.Request.IsWebSocketRequest) {
                UriBuilder ub = new UriBuilder(PostUri) { Scheme = "wss" };
                postUri = ub.Uri.ToString();
            } else {
                postUri = PostUri.ToString();
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUri);
            request.Method = context.Request.HttpMethod;
            request.ServerCertificateValidationCallback += ValidateCertificate;

            if (!context.Request.IsWebSocketRequest) {
                SetRequestHeaders(request, context.Request.Headers, localBaseUrl, remoteBaseUrl);
            }

            // Add RTVS headers
            var remoteUri = GetRemoteUri(context.Request.Url, remoteBaseUrl);
            request.Headers.Add(CustomHttpHeaders.RTVSRequestedURL, remoteUri.ToString());

            if (context.Request.ContentLength64 > 0) {
                using (Stream reqStream = await request.GetRequestStreamAsync()) {
                    await context.Request.InputStream.CopyAndFlushAsync(reqStream, null, ct);
                }
            }

            HttpWebResponse response = null;
            try {
                response = (HttpWebResponse)await request.GetResponseAsync();
                if (response != null) {
                    if (context.Request.IsWebSocketRequest && response.StatusCode == HttpStatusCode.SwitchingProtocols) {
                        Stream respStream = response.GetResponseStream();
                        string subProtocol = response.Headers[Constants.Headers.SecWebSocketProtocol];
                        var remoteWebSocket = CommonWebSocket.CreateClientWebSocket(respStream, subProtocol, TimeSpan.FromMinutes(10), receiveBufferSize: 65335, useZeroMask: true);
                        var websocketContext = await context.AcceptWebSocketAsync(subProtocol, receiveBufferSize: 65335, keepAliveInterval: TimeSpan.FromMinutes(10));
                        await WebSocketHelper.SendReceiveAsync(websocketContext.WebSocket, remoteWebSocket, ct);
                    } else {
                        context.Response.StatusCode = (int)response.StatusCode;
                        SetResponseHeaders(response, context.Response, localBaseUrl, remoteBaseUrl);
                        using (Stream respStream = response.GetResponseStream())
                        using (Stream outStream = context.Response.OutputStream) {
                            await respStream.CopyAndFlushAsync(outStream, null, ct);
                        }
                        response.Close();
                    }
                }
            } catch (WebException wex) when (wex.Status == WebExceptionStatus.ProtocolError) {
                response = wex.Response as HttpWebResponse;
            } catch (OperationCanceledException) {
                WebServer.Stop(remoteUri.Port);
            } catch (Exception ex) when (!ex.IsCriticalException()) {
                _log?.WriteLine(LogVerbosity.Normal, MessageCategory.Error, Resources.Error_RemoteWebServerException.FormatInvariant(ex.Message));
                _console?.WriteErrorLine(Resources.Error_RemoteWebServerException.FormatInvariant(ex.Message));
                WebServer.Stop(remoteUri.Port);
            } finally {
                response?.Close();
            }
        }
Beispiel #2
0
        public async Task <WebSocket> ConnectAsync(HttpWebRequest request, CancellationToken cancellationToken)
        {
            HttpWebResponse response;

            using (cancellationToken.Register(request.Abort)) {
                response = (HttpWebResponse)await request.GetResponseAsync();
            }

            InspectResponse?.Invoke(response);

            // TODO: Validate handshake
            HttpStatusCode statusCode = response.StatusCode;

            if (statusCode != HttpStatusCode.SwitchingProtocols)
            {
                response.Dispose();
                throw new InvalidOperationException("Incomplete handshake, invalid status code: " + statusCode);
            }
            // TODO: Validate Sec-WebSocket-Key/Sec-WebSocket-Accept

            string subProtocol = response.Headers[Constants.Headers.SecWebSocketProtocol];

            if (!string.IsNullOrEmpty(subProtocol) && !SubProtocols.Contains(subProtocol, StringComparer.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException("Incomplete handshake, the server specified an unknown sub-protocol: " + subProtocol);
            }

            var stream = response.GetResponseStream();

            return(CommonWebSocket.CreateClientWebSocket(stream, subProtocol, KeepAliveInterval, ReceiveBufferSize, UseZeroMask));
        }
Beispiel #3
0
        // Tests server unmasking with offset masks
        public async Task ServerReceiveOffsetData()
        {
            DuplexStream serverStream = new DuplexStream();
            DuplexStream clientStream = serverStream.CreateReverseDuplexStream();

            WebSocket serverWebSocket = CommonWebSocket.CreateServerWebSocket(serverStream, null, TimeSpan.FromMinutes(2), 1024);
            WebSocket clientWebSocket = CommonWebSocket.CreateClientWebSocket(clientStream, null, TimeSpan.FromMinutes(2), 1024, false);

            byte[] clientBuffer = Encoding.ASCII.GetBytes("abcdefghijklmnopqrstuvwxyz");
            byte[] serverBuffer = new byte[clientBuffer.Length];

            await clientWebSocket.SendAsync(new ArraySegment <byte>(clientBuffer), WebSocketMessageType.Text, true, CancellationToken.None);

            WebSocketReceiveResult serverResult = await serverWebSocket.ReceiveAsync(new ArraySegment <byte>(serverBuffer, 0, 3), CancellationToken.None);

            Assert.False(serverResult.EndOfMessage);
            Assert.Equal(3, serverResult.Count);
            Assert.Equal(WebSocketMessageType.Text, serverResult.MessageType);

            serverResult = await serverWebSocket.ReceiveAsync(new ArraySegment <byte>(serverBuffer, 3, 10), CancellationToken.None);

            Assert.False(serverResult.EndOfMessage);
            Assert.Equal(10, serverResult.Count);
            Assert.Equal(WebSocketMessageType.Text, serverResult.MessageType);

            serverResult = await serverWebSocket.ReceiveAsync(new ArraySegment <byte>(serverBuffer, 13, 13), CancellationToken.None);

            Assert.True(serverResult.EndOfMessage);
            Assert.Equal(13, serverResult.Count);
            Assert.Equal(WebSocketMessageType.Text, serverResult.MessageType);
            Assert.Equal(clientBuffer, serverBuffer);
        }
Beispiel #4
0
        public async Task <WebSocket> ConnectAsync(Uri uri, CancellationToken cancellationToken)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

            CancellationTokenRegistration cancellation = cancellationToken.Register(() => request.Abort());

            request.Headers[Constants.Headers.SecWebSocketVersion] = Constants.Headers.SupportedVersion;
            if (SubProtocols.Count > 0)
            {
                request.Headers[Constants.Headers.SecWebSocketProtocol] = string.Join(", ", SubProtocols);
            }

            if (ConfigureRequest != null)
            {
                ConfigureRequest(request);
            }

            HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();

            cancellation.Dispose();

            if (InspectResponse != null)
            {
                InspectResponse(response);
            }

            // TODO: Validate handshake
            HttpStatusCode statusCode = response.StatusCode;

            if (statusCode != HttpStatusCode.SwitchingProtocols)
            {
                response.Dispose();
                throw new InvalidOperationException("Incomplete handshake, invalid status code: " + statusCode);
            }
            // TODO: Validate Sec-WebSocket-Key/Sec-WebSocket-Accept

            string subProtocol = response.Headers[Constants.Headers.SecWebSocketProtocol];

            if (!string.IsNullOrEmpty(subProtocol) && !SubProtocols.Contains(subProtocol, StringComparer.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException("Incomplete handshake, the server specified an unknown sub-protocol: " + subProtocol);
            }

            Stream stream = response.GetResponseStream();

            return(CommonWebSocket.CreateClientWebSocket(stream, subProtocol, KeepAliveInterval, ReceiveBufferSize, useZeroMask: UseZeroMask));
        }
            public async Task <WebSocket> AcceptAsync(IWebSocketAcceptContext 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 WebSocketAcceptContext;

                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

                return(CommonWebSocket.CreateServerWebSocket(opaqueTransport, subProtocol, keepAliveInterval, receiveBufferSize));
            }
Beispiel #6
0
        public static async Task HandlerAsync(HttpContext context)
        {
            var url = context.Request.Headers[CustomHttpHeaders.RTVSRequestedURL];

            using (var client = new HttpClient()) {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    var ub = new UriBuilder(url)
                    {
                        Scheme = "ws"
                    };
                    var    request      = new HttpRequestMessage(new HttpMethod(context.Request.Method), ub.Uri);
                    string subProtocols = string.Join(", ", context.WebSockets.WebSocketRequestedProtocols);

                    request.Headers.Add(Constants.Headers.SecWebSocketVersion, Constants.Headers.SupportedVersion);
                    if (!string.IsNullOrWhiteSpace(subProtocols))
                    {
                        request.Headers.Add(Constants.Headers.SecWebSocketProtocol, subProtocols);
                    }

                    var response = await client.SendAsync(request);

                    HttpStatusCode statusCode = response.StatusCode;
                    if (statusCode != HttpStatusCode.SwitchingProtocols)
                    {
                        response.Dispose();
                    }
                    else
                    {
                        string respSubProtocol = response.Headers.GetValues(Constants.Headers.SecWebSocketProtocol).FirstOrDefault();
                        // TODO: match sub protocols.

                        var responseStream = await response.Content.ReadAsStreamAsync();

                        var clientWebsocket = CommonWebSocket.CreateClientWebSocket(responseStream, respSubProtocol, TimeSpan.FromMinutes(2), receiveBufferSize: 1024 * 16, useZeroMask: false);
                        var serverWebSocket = await context.WebSockets.AcceptWebSocketAsync();

                        await WebSocketHelper.SendReceiveAsync(serverWebSocket, clientWebsocket, CancellationToken.None);
                    }
                }
                else
                {
                    var request = new HttpRequestMessage(new HttpMethod(context.Request.Method), url);
                    foreach (var requestHeader in context.Request.Headers)
                    {
                        IEnumerable <string> value = requestHeader.Value;
                        request.Headers.Add(requestHeader.Key, value);
                    }

                    if (context.Request.ContentLength > 0)
                    {
                        using (Stream reqStream = await request.Content.ReadAsStreamAsync()) {
                            await context.Request.Body.CopyToAsync(reqStream);

                            await reqStream.FlushAsync();
                        }
                    }

                    using (var response = await client.SendAsync(request)) {
                        context.Response.StatusCode = (int)response.StatusCode;

                        foreach (var responseHeader in context.Response.Headers)
                        {
                            IEnumerable <string> value = responseHeader.Value;
                            response.Headers.Add(responseHeader.Key, value);
                        }

                        using (var respStream = await response.Content.ReadAsStreamAsync()) {
                            await respStream.CopyToAsync(context.Response.Body);

                            await context.Response.Body.FlushAsync();
                        }
                    }
                }
            }
        }
        public async Task GetResponseAsync(HttpListenerContext context, string localBaseUrl, string remoteBaseUrl, CancellationToken ct)
        {
            string postUri = null;

            if (context.Request.IsWebSocketRequest)
            {
                UriBuilder ub = new UriBuilder(PostUri)
                {
                    Scheme = "wss"
                };
                postUri = ub.Uri.ToString();
            }
            else
            {
                postUri = PostUri.ToString();
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUri);

            request.Method = context.Request.HttpMethod;
            request.ServerCertificateValidationCallback += ValidateCertificate;

            if (!context.Request.IsWebSocketRequest)
            {
                SetRequestHeaders(request, context.Request.Headers, localBaseUrl, remoteBaseUrl);
            }

            // Add RTVS headers
            request.Headers.Add(CustomHttpHeaders.RTVSRequestedURL, GetRemoteUrl(context.Request.Url, remoteBaseUrl));

            if (context.Request.InputStream.CanSeek && context.Request.InputStream.Length > 0)
            {
                using (Stream reqStream = await request.GetRequestStreamAsync()) {
                    await context.Request.InputStream.CopyAndFlushAsync(reqStream);
                }
            }

            HttpWebResponse response = null;

            try {
                response = (HttpWebResponse)await request.GetResponseAsync();
            } catch (WebException wex) {
                if (wex.Status == WebExceptionStatus.ProtocolError)
                {
                    response = wex.Response as HttpWebResponse;
                }
                else
                {
                    throw wex;
                }
            } finally {
                if (response != null)
                {
                    if (context.Request.IsWebSocketRequest && response.StatusCode == HttpStatusCode.SwitchingProtocols)
                    {
                        Stream respStream       = response.GetResponseStream();
                        string subProtocol      = response.Headers[Constants.Headers.SecWebSocketProtocol];
                        var    remoteWebSocket  = CommonWebSocket.CreateClientWebSocket(respStream, subProtocol, TimeSpan.FromMinutes(10), receiveBufferSize: 65335, useZeroMask: true);
                        var    websocketContext = await context.AcceptWebSocketAsync(subProtocol, receiveBufferSize : 65335, keepAliveInterval : TimeSpan.FromMinutes(10));

                        await WebSocketHelper.SendReceiveAsync(websocketContext.WebSocket, remoteWebSocket, ct);
                    }
                    else
                    {
                        context.Response.StatusCode = (int)response.StatusCode;
                        SetResponseHeaders(response, context.Response, localBaseUrl, remoteBaseUrl);
                        using (Stream respStream = response.GetResponseStream())
                            using (Stream outStream = context.Response.OutputStream) {
                                await respStream.CopyAndFlushAsync(outStream);
                            }
                        response.Close();
                    }
                }
            }
        }
Beispiel #8
0
 protected ClientWebSocketWrapper(string uri)
 {
     _ws  = CommonWebSocket.CreateClientWebSocket(SubProtocol, _keepAliveInterval, ReceiveChunkSize, false);
     _uri = new Uri(uri);
     _cancellationToken = _cancellationTokenSource.Token;
 }
Beispiel #9
0
        public static async Task HandlerAsync(HttpContext context)
        {
            var url = context.Request.Headers[CustomHttpHeaders.RTVSRequestedURL];

            if (context.WebSockets.IsWebSocketRequest)
            {
                UriBuilder ub = new UriBuilder(url)
                {
                    Scheme = "ws"
                };
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(ub.Uri);
                request.Method = context.Request.Method;
                string subProtocols = string.Join(", ", context.WebSockets.WebSocketRequestedProtocols);

                request.Headers[Constants.Headers.SecWebSocketVersion] = Constants.Headers.SupportedVersion;
                if (!string.IsNullOrWhiteSpace(subProtocols))
                {
                    request.Headers[Constants.Headers.SecWebSocketProtocol] = subProtocols;
                }

                HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();

                HttpStatusCode statusCode = response.StatusCode;
                if (statusCode != HttpStatusCode.SwitchingProtocols)
                {
                    response.Dispose();
                }
                else
                {
                    string respSubProtocol = response.Headers[Constants.Headers.SecWebSocketProtocol];
                    // TODO: match sub protocols.

                    CommonWebSocket clientWebsocket = CommonWebSocket.CreateClientWebSocket(response.GetResponseStream(), respSubProtocol, TimeSpan.FromMinutes(2), receiveBufferSize: 1024 * 16, useZeroMask: false);
                    var             serverWebSocket = await context.WebSockets.AcceptWebSocketAsync();

                    await WebSocketHelper.SendReceiveAsync(serverWebSocket, clientWebsocket, CancellationToken.None);
                }
            }
            else
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = context.Request.Method;
                SetRequestHeaders(request, context.Request.Headers);

                if (context.Request.ContentLength > 0)
                {
                    using (Stream reqStream = await request.GetRequestStreamAsync()) {
                        await context.Request.Body.CopyToAsync(reqStream);

                        await reqStream.FlushAsync();
                    }
                }

                HttpWebResponse response = null;
                try {
                    response = (HttpWebResponse)await request.GetResponseAsync();

                    if (response != null)
                    {
                        context.Response.StatusCode = (int)response.StatusCode;
                        SetResponseHeaders(response, context.Response);
                        using (Stream respStream = response.GetResponseStream()) {
                            await respStream.CopyToAsync(context.Response.Body);

                            await context.Response.Body.FlushAsync();
                        }
                    }
                } catch (WebException wex) when(wex.Status == WebExceptionStatus.ProtocolError)
                {
                    response = wex.Response as HttpWebResponse;
                } finally {
                    response?.Close();
                }
            }
        }