public void TestArgumentExceptions()
        {
            Assert.Throws <ArgumentNullException> (() => new DuplexStream(null, Stream.Null));
            Assert.Throws <ArgumentNullException> (() => new DuplexStream(Stream.Null, null));

            using (var stream = new DuplexStream(new DummyNetworkStream(), new DummyNetworkStream())) {
                var buffer = new byte[16];

                Assert.Throws <ArgumentNullException> (() => stream.Read(null, 0, buffer.Length));
                Assert.Throws <ArgumentOutOfRangeException> (() => stream.Read(buffer, -1, buffer.Length));
                Assert.Throws <ArgumentOutOfRangeException> (() => stream.Read(buffer, 0, -1));

                Assert.ThrowsAsync <ArgumentNullException> (async() => await stream.ReadAsync(null, 0, buffer.Length));
                Assert.ThrowsAsync <ArgumentOutOfRangeException> (async() => await stream.ReadAsync(buffer, -1, buffer.Length));
                Assert.ThrowsAsync <ArgumentOutOfRangeException> (async() => await stream.ReadAsync(buffer, 0, -1));

                Assert.Throws <ArgumentNullException> (() => stream.Write(null, 0, buffer.Length));
                Assert.Throws <ArgumentOutOfRangeException> (() => stream.Write(buffer, -1, buffer.Length));
                Assert.Throws <ArgumentOutOfRangeException> (() => stream.Write(buffer, 0, -1));

                Assert.ThrowsAsync <ArgumentNullException> (async() => await stream.WriteAsync(null, 0, buffer.Length));
                Assert.ThrowsAsync <ArgumentOutOfRangeException> (async() => await stream.WriteAsync(buffer, -1, buffer.Length));
                Assert.ThrowsAsync <ArgumentOutOfRangeException> (async() => await stream.WriteAsync(buffer, 0, -1));
            }
        }
Example #2
0
 public WebSocketPair(DuplexStream serverStream, DuplexStream clientStream, WebSocket clientSocket, WebSocket serverSocket)
 {
     ClientStream = clientStream;
     ServerStream = serverStream;
     ClientSocket = clientSocket;
     ServerSocket = serverSocket;
 }
 public void TestSetLength()
 {
     using (var stream = new DuplexStream(new DummyNetworkStream(), new DummyNetworkStream())) {
         Assert.Throws <NotSupportedException> (() => { var x = stream.Length; });
         Assert.Throws <NotSupportedException> (() => stream.SetLength(500));
     }
 }
Example #4
0
        public virtual int Read(DuplexStream stream)
        {
            int  num  = this.ReadHeader(stream);
            bool flag = num < 0;
            int  result;

            if (flag)
            {
                result = -1;
            }
            else
            {
                num = this.ReadData(stream);
                bool flag2 = num < 0;
                if (flag2)
                {
                    result = -2;
                }
                else
                {
                    result = 0;
                }
            }
            return(result);
        }
 public void TestSeek()
 {
     using (var stream = new DuplexStream(new DummyNetworkStream(), new DummyNetworkStream())) {
         Assert.Throws <NotSupportedException> (() => stream.Seek(0, SeekOrigin.Begin));
         Assert.Throws <NotSupportedException> (() => { var x = stream.Position; });
         Assert.Throws <NotSupportedException> (() => stream.Position = 500);
     }
 }
Example #6
0
            public Transport()
            {
                var c_to_s = new InOut();
                var s_to_c = new InOut();

                ServerSide = new DuplexStream(s_to_c.ReadObservable, c_to_s);
                ClientSide = new DuplexStream(c_to_s.ReadObservable, s_to_c);
            }
Example #7
0
        public static Packet DeriveAndLoadData(Packet p, DuplexStream stream)
        {
            Packet packet = Packet.CreatePacketOfType((int)p.Type);

            packet.Assign(p);
            packet.ReadData(stream);
            return(packet);
        }
 public void TestCanReadWriteSeek()
 {
     using (var stream = new DuplexStream(new DummyNetworkStream(), new DummyNetworkStream())) {
         Assert.IsTrue(stream.CanRead);
         Assert.IsTrue(stream.CanWrite);
         Assert.IsFalse(stream.CanSeek);
         Assert.IsTrue(stream.CanTimeout);
     }
 }
        public void TestGetSetTimeouts()
        {
            using (var stream = new DuplexStream(new DummyNetworkStream(), new DummyNetworkStream())) {
                stream.ReadTimeout = 5;
                Assert.AreEqual(5, stream.ReadTimeout, "ReadTimeout");

                stream.WriteTimeout = 7;
                Assert.AreEqual(7, stream.WriteTimeout, "WriteTimeout");
            }
        }
        public void TestWrite()
        {
            using (var stream = new DuplexStream(new DummyNetworkStream(), new DummyNetworkStream())) {
                var buffer = new byte[1024];

                stream.Write(buffer, 0, buffer.Length);
                stream.Flush();
                Assert.AreEqual(buffer.Length, stream.OutputStream.Position);
            }
        }
Example #11
0
    public static WebSocketPair Create()
    {
        // Create streams
        var serverStream = new DuplexStream();
        var clientStream = serverStream.CreateReverseDuplexStream();

        return(new WebSocketPair(
                   serverStream,
                   clientStream,
                   clientSocket: WebSocket.CreateFromStream(clientStream, isServer: false, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2)),
                   serverSocket: WebSocket.CreateFromStream(serverStream, isServer: true, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2))));
    }
        public async Task TestWriteAsync()
        {
            using (var stream = new DuplexStream(new DummyNetworkStream(), new DummyNetworkStream())) {
                var buffer = new byte[1024];

                await stream.WriteAsync(buffer, 0, buffer.Length);

                await stream.FlushAsync();

                Assert.AreEqual(buffer.Length, stream.OutputStream.Position);
            }
        }
        public void TestRead()
        {
            using (var stream = new DuplexStream(new DummyNetworkStream(), new DummyNetworkStream())) {
                var buffer = new byte[1024];
                int n;

                stream.InputStream.Write(buffer, 0, buffer.Length);
                stream.InputStream.Position = 0;

                n = stream.Read(buffer, 0, buffer.Length);
                Assert.AreEqual(buffer.Length, n);
            }
        }
        public override int ReadData(DuplexStream stream)
        {
            base.ReadData(stream);
            int result;

            try
            {
                this.Result = stream.ReadByte();
            }
            catch (Exception ex)
            {
                Log.Write(ex);
                result = -1;
                return(result);
            }
            result = 0;
            return(result);
        }
Example #15
0
        public virtual int ReadHeader(DuplexStream stream)
        {
            int result;

            try
            {
                this.Header   = stream.ReadBytes((int)Packet.HEADER_SIZE);
                this.Type     = stream.ReadInt16();
                this.DataSize = stream.ReadByte();
            }
            catch (Exception ex)
            {
                Log.Write(ex);
                result = -1;
                return(result);
            }
            result = 0;
            return(result);
        }
Example #16
0
        public override int ReadData(DuplexStream stream)
        {
            base.ReadData(stream);
            int result;

            try
            {
                this.UID        = stream.ReadBytes((int)DiscoverResponsePacket.UID_SIZE);
                this.PortMask   = stream.ReadByte();
                this.IpAddress  = stream.ReadInt32();
                this.PortNumber = stream.ReadByte();
            }
            catch (Exception ex)
            {
                Log.Write(ex);
                result = -1;
                return(result);
            }
            result = 0;
            return(result);
        }
Example #17
0
        private CallContext CreateCallContext()
        {
            _inputStream = new InputStream(() =>
            {
                var sender = new InputSender(_context.Services);
                _messageBody.Subscribe(sender.Push);
                return(sender);
            });
            _outputStream = new OutputStream(OnWrite, OnFlush);
            _duplexStream = new DuplexStream(_inputStream, _outputStream);

            var remoteIpAddress = "127.0.0.1";
            var remotePort      = "0";
            var localIpAddress  = "127.0.0.1";
            var localPort       = "80";
            var isLocal         = false;

            if (_context.Socket != null)
            {
                var remoteEndPoint = _context.Socket.RemoteEndPoint as IPEndPoint;
                if (remoteEndPoint != null)
                {
                    remoteIpAddress = remoteEndPoint.Address.ToString();
                    remotePort      = remoteEndPoint.Port.ToString(CultureInfo.InvariantCulture);
                }

                var localEndPoint = _context.Socket.LocalEndPoint as IPEndPoint;
                if (localEndPoint != null)
                {
                    localIpAddress = localEndPoint.Address.ToString();
                    localPort      = localEndPoint.Port.ToString(CultureInfo.InvariantCulture);
                }

                if (remoteEndPoint != null && localEndPoint != null)
                {
                    isLocal = Equals(remoteEndPoint.Address, localEndPoint.Address);
                }
            }

            var callContext = new CallContext();
            var request     = (IHttpRequestFeature)callContext;
            var response    = (IHttpResponseFeature)callContext;

            //var lifetime = (IHttpRequestLifetimeFeature)callContext;
            request.Protocol    = _httpVersion;
            request.Scheme      = "http";
            request.Method      = _method;
            request.Path        = _path;
            request.PathBase    = "";
            request.QueryString = _queryString;
            request.Headers     = _requestHeaders;
            request.Body        = _inputStream;
            response.Headers    = _responseHeaders;
            response.Body       = _outputStream;

            //var env = new Dictionary<string, object>();
            //env["owin.Version"] = "1.0";
            //env["owin.RequestProtocol"] = _httpVersion;
            //env["owin.RequestScheme"] = "http";
            //env["owin.RequestMethod"] = _method;
            //env["owin.RequestPath"] = _path;
            //env["owin.RequestPathBase"] = "";
            //env["owin.RequestQueryString"] = _queryString;
            //env["owin.RequestHeaders"] = _requestHeaders;
            //env["owin.RequestBody"] = _inputStream;
            //env["owin.ResponseHeaders"] = _responseHeaders;
            //env["owin.ResponseBody"] = _outputStream;
            //env["owin.CallCancelled"] = _cts.Token;
            //env["opaque.Upgrade"] = (Action<IDictionary<string, object>, Func<IDictionary<string, object>, Task>>)Upgrade;
            //env["opaque.Stream"] = _duplexStream;
            //env["server.RemoteIpAddress"] = remoteIpAddress;
            //env["server.RemotePort"] = remotePort;
            //env["server.LocalIpAddress"] = localIpAddress;
            //env["server.LocalPort"] = localPort;
            //env["server.IsLocal"] = isLocal;
            return(callContext);
        }
Example #18
0
 public virtual int ReadData(DuplexStream stream)
 {
     stream.WaitForAvailable(this.SizeOf - this.headerSize, -1);
     return(0);
 }
Example #19
0
        /// <summary>
        /// Establishes a connection to the specified POP3 server.
        /// </summary>
        /// <remarks>
        /// <para>Establishes a connection to an POP3 or POP3/S server. If the schema
        /// in the uri is "pop", a clear-text connection is made and defaults to using
        /// port 110 if no port is specified in the URI. However, if the schema in the
        /// uri is "pops", an SSL connection is made using the
        /// <see cref="ClientCertificates"/> and defaults to port 995 unless a port
        /// is specified in the URI.</para>
        /// <para>It should be noted that when using a clear-text POP3 connection,
        /// if the server advertizes support for the STLS extension, the client
        /// will automatically switch into TLS mode before authenticating unless
        /// the <paramref name="uri"/> contains a query string to disable it.</para>
        /// If a successful connection is made, the <see cref="AuthenticationMechanisms"/>
        /// and <see cref="Capabilities"/> properties will be populated.
        /// </remarks>
        /// <param name="uri">The server URI. The <see cref="System.Uri.Scheme"/> should either
        /// be "pop" to make a clear-text connection or "pops" to make an SSL connection.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <exception cref="System.ArgumentNullException">
        /// The <paramref name="uri"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// The <paramref name="uri"/> is not an absolute URI.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">
        /// The <see cref="Pop3Client"/> has been disposed.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// The <see cref="Pop3Client"/> is already connected.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        /// <exception cref="Pop3CommandException">
        /// A POP3 command failed.
        /// </exception>
        /// <exception cref="Pop3ProtocolException">
        /// A POP3 protocol error occurred.
        /// </exception>
        public void Connect(Uri uri, CancellationToken cancellationToken)
        {
            CheckDisposed ();

            if (uri == null)
                throw new ArgumentNullException ("uri");

            if (!uri.IsAbsoluteUri)
                throw new ArgumentException ("The uri must be absolute.", "uri");

            if (IsConnected)
                throw new InvalidOperationException ("The Pop3Client is already connected.");

            var scheme = uri.Scheme.ToLowerInvariant ();
            var pops = scheme == "pops" || scheme == "pop3s";
            var port = uri.Port > 0 ? uri.Port : (pops ? 995 : 110);
            var query = uri.ParsedQuery ();
            #if !NETFX_CORE && !WINDOWS_APP && !WINDOWS_PHONE_APP
            var ipAddresses = Dns.GetHostAddresses (uri.DnsSafeHost);
            Socket socket = null;
            #endif
            Stream stream;
            string value;

            var starttls = !pops && (!query.TryGetValue ("starttls", out value) || Convert.ToBoolean (value));

            #if !NETFX_CORE && !WINDOWS_APP && !WINDOWS_PHONE_APP
            for (int i = 0; i < ipAddresses.Length; i++) {
                socket = new Socket (ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                cancellationToken.ThrowIfCancellationRequested ();

                try {
                    socket.Connect (ipAddresses[i], port);
                    break;
                } catch (Exception) {
                    if (i + 1 == ipAddresses.Length)
                        throw;
                }
            }

            if (pops) {
                var ssl = new SslStream (new NetworkStream (socket, true), false, ValidateRemoteCertificate);
                ssl.AuthenticateAsClient (uri.Host, ClientCertificates, SslProtocols.Default, true);
                stream = ssl;
            } else {
                stream = new NetworkStream (socket, true);
            }
            #else
            socket = new StreamSocket ();

            cancellationToken.ThrowIfCancellationRequested ();
            socket.ConnectAsync (new HostName (uri.DnsSafeHost), port.ToString (), pops ? SocketProtectionLevel.Tls12 : SocketProtectionLevel.PlainSocket)
                .AsTask (cancellationToken)
                .GetAwaiter ()
                .GetResult ();

            stream = new DuplexStream (socket.InputStream.AsStreamForRead (), socket.OutputStream.AsStreamForWrite ());
            #endif

            probed = ProbedCapabilities.None;
            host = uri.Host;

            logger.LogConnect (uri);

            engine.Connect (new Pop3Stream (stream, logger), cancellationToken);
            engine.QueryCapabilities (cancellationToken);

            if (starttls && (engine.Capabilities & Pop3Capabilities.StartTLS) != 0) {
                SendCommand (cancellationToken, "STLS");

            #if !NETFX_CORE && !WINDOWS_APP && !WINDOWS_PHONE_APP
                var tls = new SslStream (stream, false, ValidateRemoteCertificate);
                tls.AuthenticateAsClient (uri.Host, ClientCertificates, SslProtocols.Tls, true);
                engine.Stream.Stream = tls;
            #else
                socket.UpgradeToSslAsync (SocketProtectionLevel.Tls12, new HostName (uri.DnsSafeHost))
                    .AsTask (cancellationToken)
                    .GetAwaiter ()
                    .GetResult ();
            #endif

                // re-issue a CAPA command
                engine.QueryCapabilities (cancellationToken);
            }
        }
Example #20
0
		/// <summary>
		/// Establishes a connection to the specified SMTP or SMTP/S server.
		/// </summary>
		/// <remarks>
		/// <para>Establishes a connection to the specified SMTP or SMTP/S server.</para>
		/// <para>If the <paramref name="port"/> has a value of <c>0</c>, then the
		/// <paramref name="options"/> parameter is used to determine the default port to
		/// connect to. The default port used with <see cref="SecureSocketOptions.SslOnConnect"/>
		/// is <c>465</c>. All other values will use a default port of <c>25</c>.</para>
		/// <para>If the <paramref name="options"/> has a value of
		/// <see cref="SecureSocketOptions.Auto"/>, then the <paramref name="port"/> is used
		/// to determine the default security options. If the <paramref name="port"/> has a value
		/// of <c>465</c>, then the default options used will be
		/// <see cref="SecureSocketOptions.SslOnConnect"/>. All other values will use
		/// <see cref="SecureSocketOptions.StartTlsWhenAvailable"/>.</para>
		/// <para>Once a connection is established, properties such as
		/// <see cref="AuthenticationMechanisms"/> and <see cref="Capabilities"/> will be
		/// populated.</para>
		/// <para>Note: The connection established by any of the
		/// <a href="Overload_MailKit_Net_Smtp_SmtpClient_Connect.htm">Connect</a>
		/// methods may be re-used if an application wishes to send multiple messages
		/// to the same SMTP server. Since connecting and authenticating can be expensive
		/// operations, re-using a connection can significantly improve performance when
		/// sending a large number of messages to the same SMTP server over a short
		/// period of time.</para>
		/// </remarks>
		/// <example>
		/// <code language="c#" source="Examples\SmtpExamples.cs" region="SendMessage"/>
		/// </example>
		/// <param name="host">The host name to connect to.</param>
		/// <param name="port">The port to connect to. If the specified port is <c>0</c>, then the default port will be used.</param>
		/// <param name="options">The secure socket options to when connecting.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="host"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// <paramref name="port"/> is not between <c>0</c> and <c>65535</c>.
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// The <paramref name="host"/> is a zero-length string.
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="SmtpClient"/> has been disposed.
		/// </exception>
		/// <exception cref="System.InvalidOperationException">
		/// The <see cref="SmtpClient"/> is already connected.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <paramref name="options"/> was set to
		/// <see cref="MailKit.Security.SecureSocketOptions.StartTls"/>
		/// and the SMTP server does not support the STARTTLS extension.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="SmtpCommandException">
		/// An SMTP command failed.
		/// </exception>
		/// <exception cref="SmtpProtocolException">
		/// An SMTP protocol error occurred.
		/// </exception>
		public override void Connect (string host, int port = 0, SecureSocketOptions options = SecureSocketOptions.Auto, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (host == null)
				throw new ArgumentNullException ("host");

			if (host.Length == 0)
				throw new ArgumentException ("The host name cannot be empty.", "host");

			if (port < 0 || port > 65535)
				throw new ArgumentOutOfRangeException ("port");
			
			CheckDisposed ();

			if (IsConnected)
				throw new InvalidOperationException ("The SmtpClient is already connected.");

			capabilities = SmtpCapabilities.None;
			AuthenticationMechanisms.Clear ();
			MaxSize = 0;

			SmtpResponse response;
			Stream stream;
			bool starttls;
			Uri uri;

			ComputeDefaultValues (host, ref port, ref options, out uri, out starttls);

#if !NETFX_CORE
			var ipAddresses = Dns.GetHostAddresses (host);
			Socket socket = null;

			for (int i = 0; i < ipAddresses.Length; i++) {
				socket = new Socket (ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp);

				try {
					cancellationToken.ThrowIfCancellationRequested ();

					if (LocalEndPoint != null)
						socket.Bind (LocalEndPoint);

					socket.Connect (ipAddresses[i], port);
					break;
				} catch (OperationCanceledException) {
					socket.Dispose ();
					socket = null;
					throw;
				} catch {
					socket.Dispose ();
					socket = null;

					if (i + 1 == ipAddresses.Length)
						throw;
				}
			}

			if (socket == null)
				throw new IOException (string.Format ("Failed to resolve host: {0}", host));

			this.host = host;

			if (options == SecureSocketOptions.SslOnConnect) {
				var ssl = new SslStream (new NetworkStream (socket, true), false, ValidateRemoteCertificate);
				ssl.AuthenticateAsClient (host, ClientCertificates, SslProtocols, true);
				stream = ssl;
			} else {
				stream = new NetworkStream (socket, true);
			}
#else
			var protection = options == SecureSocketOptions.SslOnConnect ? SocketProtectionLevel.Tls12 : SocketProtectionLevel.PlainSocket;
			var socket = new StreamSocket ();

			try {
				cancellationToken.ThrowIfCancellationRequested ();
				socket.ConnectAsync (new HostName (host), port.ToString (), protection)
					.AsTask (cancellationToken)
					.GetAwaiter ()
					.GetResult ();
			} catch {
				socket.Dispose ();
				throw;
			}

			stream = new DuplexStream (socket.InputStream.AsStreamForRead (0), socket.OutputStream.AsStreamForWrite (0));
#endif

			if (stream.CanTimeout) {
				stream.WriteTimeout = timeout;
				stream.ReadTimeout = timeout;
			}

			ProtocolLogger.LogConnect (uri);

			Stream = new SmtpStream (stream, socket, ProtocolLogger);

			try {
				// read the greeting
				response = Stream.ReadResponse (cancellationToken);

				if (response.StatusCode != SmtpStatusCode.ServiceReady)
					throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);

				// Send EHLO and get a list of supported extensions
				Ehlo (cancellationToken);

				if (options == SecureSocketOptions.StartTls && (capabilities & SmtpCapabilities.StartTLS) == 0)
					throw new NotSupportedException ("The SMTP server does not support the STARTTLS extension.");

				if (starttls && (capabilities & SmtpCapabilities.StartTLS) != 0) {
					response = SendCommand ("STARTTLS", cancellationToken);
					if (response.StatusCode != SmtpStatusCode.ServiceReady)
						throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);

#if !NETFX_CORE
					var tls = new SslStream (stream, false, ValidateRemoteCertificate);
					tls.AuthenticateAsClient (host, ClientCertificates, SslProtocols, true);
					Stream.Stream = tls;
#else
					socket.UpgradeToSslAsync (SocketProtectionLevel.Tls12, new HostName (host))
						.AsTask (cancellationToken)
						.GetAwaiter ()
						.GetResult ();
#endif

					// Send EHLO again and get the new list of supported extensions
					Ehlo (cancellationToken);
				}

				connected = true;
			} catch {
				Stream.Dispose ();
				Stream = null;
				throw;
			}

			OnConnected ();
		}
Example #21
0
        public async Task ProxyAsync_UpgradableRequest_Works()
        {
            // Arrange
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method      = "GET";
            httpContext.Request.Scheme      = "https";
            httpContext.Request.Host        = new HostString("example.com");
            httpContext.Request.Path        = "/api/test";
            httpContext.Request.QueryString = new QueryString("?a=b&c=d");
            httpContext.Request.Headers.Add(":host", "example.com");
            httpContext.Request.Headers.Add("x-ms-request-test", "request");

            var downstreamStream = new DuplexStream(
                readStream: StringToStream("request content"),
                writeStream: new MemoryStream());
            DuplexStream upstreamStream = null;

            var upgradeFeatureMock = new Mock <IHttpUpgradeFeature>();

            upgradeFeatureMock.SetupGet(u => u.IsUpgradableRequest).Returns(true);
            upgradeFeatureMock.Setup(u => u.UpgradeAsync()).ReturnsAsync(downstreamStream);
            httpContext.Features.Set(upgradeFeatureMock.Object);

            var targetUri = new Uri("https://localhost:123/a/b/api/test?a=b&c=d");
            var sut       = Create <HttpProxy>();
            var client    = MockHttpHandler.CreateClient(
                async(HttpRequestMessage request, CancellationToken cancellationToken) =>
            {
                await Task.Yield();

                request.Version.Should().BeEquivalentTo(new Version(1, 1));
                request.Method.Should().Be(HttpMethod.Get);
                request.RequestUri.Should().Be(targetUri);
                request.Headers.GetValues("x-ms-request-test").Should().BeEquivalentTo("request");

                request.Content.Should().BeNull();

                var response = new HttpResponseMessage(HttpStatusCode.SwitchingProtocols);
                response.Headers.TryAddWithoutValidation("x-ms-response-test", "response");
                upstreamStream = new DuplexStream(
                    readStream: StringToStream("response content"),
                    writeStream: new MemoryStream());
                response.Content = new RawStreamContent(upstreamStream);
                return(response);
            });
            var factoryMock = new Mock <IProxyHttpClientFactory>();

            factoryMock.Setup(f => f.CreateUpgradableClient()).Returns(client);

            var proxyTelemetryContext = new ProxyTelemetryContext(
                backendId: "be1",
                routeId: "rt1",
                endpointId: "ep1");

            // Act
            await sut.ProxyAsync(httpContext, targetUri, factoryMock.Object, proxyTelemetryContext, CancellationToken.None, CancellationToken.None);

            // Assert
            httpContext.Response.StatusCode.Should().Be(StatusCodes.Status101SwitchingProtocols);
            httpContext.Response.Headers["x-ms-response-test"].Should().BeEquivalentTo("response");

            downstreamStream.WriteStream.Position = 0;
            var returnedToDownstream = StreamToString(downstreamStream.WriteStream);

            returnedToDownstream.Should().Be("response content");

            upstreamStream.Should().NotBeNull();
            upstreamStream.WriteStream.Position = 0;
            var sentToUpstream = StreamToString(upstreamStream.WriteStream);

            sentToUpstream.Should().Be("request content");
        }
Example #22
0
        public async Task ProxyAsync_UpgradableRequest_Works()
        {
            // Arrange
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method      = "GET";
            httpContext.Request.Scheme      = "http";
            httpContext.Request.Host        = new HostString("example.com:3456");
            httpContext.Request.Path        = "/api/test";
            httpContext.Request.QueryString = new QueryString("?a=b&c=d");
            httpContext.Request.Headers.Add(":authority", "example.com:3456");
            httpContext.Request.Headers.Add("x-ms-request-test", "request");
            httpContext.Connection.RemoteIpAddress = IPAddress.Loopback;

            var downstreamStream = new DuplexStream(
                readStream: StringToStream("request content"),
                writeStream: new MemoryStream());
            DuplexStream upstreamStream = null;

            var upgradeFeatureMock = new Mock <IHttpUpgradeFeature>();

            upgradeFeatureMock.SetupGet(u => u.IsUpgradableRequest).Returns(true);
            upgradeFeatureMock.Setup(u => u.UpgradeAsync()).ReturnsAsync(downstreamStream);
            httpContext.Features.Set(upgradeFeatureMock.Object);

            var targetUri = new Uri("https://localhost:123/a/b/api/test?a=b&c=d");
            var sut       = Create <HttpProxy>();
            var client    = MockHttpHandler.CreateClient(
                async(HttpRequestMessage request, CancellationToken cancellationToken) =>
            {
                await Task.Yield();

                Assert.Equal(new Version(1, 1), request.Version);
                Assert.Equal(HttpMethod.Get, request.Method);
                Assert.Equal(targetUri, request.RequestUri);
                Assert.Contains("request", request.Headers.GetValues("x-ms-request-test"));
                Assert.Null(request.Headers.Host);
                Assert.False(request.Headers.TryGetValues(":authority", out var value));
                Assert.Equal("127.0.0.1", request.Headers.GetValues("x-forwarded-for").Single());
                Assert.Equal("example.com:3456", request.Headers.GetValues("x-forwarded-host").Single());
                Assert.Equal("http", request.Headers.GetValues("x-forwarded-proto").Single());

                Assert.Null(request.Content);

                var response = new HttpResponseMessage(HttpStatusCode.SwitchingProtocols);
                response.Headers.TryAddWithoutValidation("x-ms-response-test", "response");
                upstreamStream = new DuplexStream(
                    readStream: StringToStream("response content"),
                    writeStream: new MemoryStream());
                response.Content = new RawStreamContent(upstreamStream);
                return(response);
            });
            var factoryMock = new Mock <IProxyHttpClientFactory>();

            factoryMock.Setup(f => f.CreateUpgradableClient()).Returns(client);

            var proxyTelemetryContext = new ProxyTelemetryContext(
                backendId: "be1",
                routeId: "rt1",
                destinationId: "d1");

            // Act
            await sut.ProxyAsync(httpContext, targetUri, factoryMock.Object, proxyTelemetryContext, CancellationToken.None, CancellationToken.None);

            // Assert
            Assert.Equal(StatusCodes.Status101SwitchingProtocols, httpContext.Response.StatusCode);
            Assert.Contains("response", httpContext.Response.Headers["x-ms-response-test"].ToArray());

            downstreamStream.WriteStream.Position = 0;
            var returnedToDownstream = StreamToString(downstreamStream.WriteStream);

            Assert.Equal("response content", returnedToDownstream);

            Assert.NotNull(upstreamStream);
            upstreamStream.WriteStream.Position = 0;
            var sentToUpstream = StreamToString(upstreamStream.WriteStream);

            Assert.Equal("request content", sentToUpstream);
        }
Example #23
0
 public virtual void Setup(IPEndPoint localAddress)
 {
     this.LocalAddress = localAddress;
     this.socket       = new UdpClient(localAddress);
     this.Stream       = new DuplexStream(-1, 32768);
 }