/// <summary> /// Create a secure <see cref="IHttpClientContext"/>. /// </summary> /// <param name="socket">Client socket (accepted by the <see cref="HttpListener"/>).</param> /// <param name="certificate">HTTPS certificate to use.</param> /// <param name="protocol">Kind of HTTPS protocol. Usually TLS or SSL.</param> /// <param name="requireClientCert">Require an SSL client certificate</param> /// <returns> /// A created <see cref="IHttpClientContext"/>. /// </returns> public IHttpClientContext CreateSecureContext(Socket socket, X509Certificate certificate, SslProtocols protocol, bool requireClientCert) { var networkStream = new ReusableSocketNetworkStream(socket, true); var remoteEndPoint = (IPEndPoint)socket.RemoteEndPoint; ClientCertificate clientCertificate = null; SslStream sslStream = new SslStream(networkStream, false, delegate(object sender, X509Certificate receivedCertificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { clientCertificate = new ClientCertificate(receivedCertificate, chain, sslPolicyErrors); return(!(requireClientCert && receivedCertificate == null)); } ); try { sslStream.AuthenticateAsServer(certificate, requireClientCert, protocol, false); return(CreateContext(true, remoteEndPoint, clientCertificate, sslStream, socket)); } catch (IOException err) { if (UseTraceLogs) { _logWriter.Write(this, LogPrio.Trace, err.Message); } } catch (ObjectDisposedException err) { if (UseTraceLogs) { _logWriter.Write(this, LogPrio.Trace, err.Message); } } catch (AuthenticationException err) { _logWriter.Write(this, LogPrio.Warning, (err.InnerException != null) ? err.InnerException.Message : err.Message); } return(null); }
/// <summary> /// Initializes a new instance of the <see cref="HttpClientContext"/> class. /// </summary> /// <param name="secured">true if the connection is secured (SSL/TLS)</param> /// <param name="remoteEndPoint">client that connected.</param> /// <param name="stream">Stream used for communication</param> /// <param name="clientCertificate">Client security certificate</param> /// <param name="parserFactory">Used to create a <see cref="IHttpRequestParser"/>.</param> /// <param name="bufferSize">Size of buffer to use when reading data. Must be at least 4096 bytes.</param> /// <param name="socket">Client socket</param> /// <exception cref="SocketException">If <see cref="Socket.BeginReceive(byte[],int,int,SocketFlags,AsyncCallback,object)"/> fails</exception> /// <exception cref="ArgumentException">Stream must be writable and readable.</exception> public HttpClientContext(bool secured, IPEndPoint remoteEndPoint, Stream stream, ClientCertificate clientCertificate, IRequestParserFactory parserFactory, int bufferSize, Socket socket) { Check.Require(remoteEndPoint, "remoteEndPoint"); Check.NotEmpty(remoteEndPoint.Address.ToString(), "remoteEndPoint.Address"); Check.Require(stream, "stream"); Check.Require(parserFactory, "parser"); Check.Min(4096, bufferSize, "bufferSize"); Check.Require(socket, "socket"); if (!stream.CanWrite || !stream.CanRead) { throw new ArgumentException("Stream must be writable and readable."); } _bufferSize = bufferSize; RemoteAddress = remoteEndPoint.Address.ToString(); RemotePort = remoteEndPoint.Port.ToString(); _log = NullLogWriter.Instance; _parser = parserFactory.CreateParser(_log); _parser.RequestCompleted += OnRequestCompleted; _parser.RequestLineReceived += OnRequestLine; _parser.HeaderReceived += OnHeaderReceived; _parser.BodyBytesReceived += OnBodyBytesReceived; _localEndPoint = (IPEndPoint)socket.LocalEndPoint; HttpRequest request = new HttpRequest(); request._remoteEndPoint = remoteEndPoint; request.Secure = secured; _currentRequest = request; IsSecured = secured; _stream = stream; _clientCertificate = clientCertificate; _buffer = new byte[bufferSize]; }
/// <summary> /// Create a new context. /// </summary> /// <param name="isSecured">true if HTTPS is used.</param> /// <param name="endPoint">Remote client</param> /// <param name="clientCertificate">Client security certificate</param> /// <param name="stream">Network stream, <see cref="HttpClientContext"/> uses <see cref="ReusableSocketNetworkStream"/>.</param> /// <param name="socket">Client socket</param> /// <returns>A new context (always).</returns> protected virtual HttpClientContext CreateNewContext(bool isSecured, IPEndPoint endPoint, ClientCertificate clientCertificate, Stream stream, Socket socket) { return(new HttpClientContext(isSecured, endPoint, stream, clientCertificate, _factory, _bufferSize, socket)); }
/// <summary> /// Create a new context. /// </summary> /// <param name="isSecured">true if socket is running HTTPS.</param> /// <param name="endPoint">Client that connected</param> /// <param name="clientCertificate">Client security certificate</param> /// <param name="stream">Network/SSL stream.</param> /// <param name="socket">Client socket</param> /// <returns>A context.</returns> protected HttpClientContext CreateContext(bool isSecured, IPEndPoint endPoint, ClientCertificate clientCertificate, Stream stream, Socket socket) { HttpClientContext context; lock (_contextQueue) { if (_contextQueue.Count > 0) { context = _contextQueue.Dequeue(); if (!context.IsAvailable) { context = CreateNewContext(isSecured, endPoint, clientCertificate, stream, socket); context.Disconnected += OnFreeContext; context.RequestReceived += OnRequestReceived; context.EndWhenDone = true; } } else { context = CreateNewContext(isSecured, endPoint, clientCertificate, stream, socket); context.Disconnected += OnFreeContext; context.RequestReceived += OnRequestReceived; } } context.Assign(stream, (IPEndPoint)socket.LocalEndPoint); context.IsSecured = isSecured; context.RemotePort = endPoint.Port.ToString(); context.RemoteAddress = endPoint.Address.ToString(); context.Start(); return(context); }