/// <summary> /// Starts the connection /// </summary> public virtual void Start() { _stop = false; try { if (_isSecure) { if (!TrySecureStream()) { return; } } // Keep on reading IAsyncResult result = ClientStreamWrapper.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(OnRead), ClientStreamWrapper); if (result == null) { ClientStreamWrapper.Close(); } } catch (Exception ex) { HttpServerConsole.Instance.WriteLine("Error starting proxy connection: {0}", ex.Message); } }
/// <summary> /// Process a CONNECT request /// </summary> protected void ProcessConnect() { // Reset request _requestBuilder = new ByteArrayBuilder(); try { // got a connect string response = _requestInfo.HttpVersion + " 200 Connection established\r\nContent-length: 0\r\nProxy-Agent: Traffic Viewer Proxy\r\n\r\n"; byte[] line = Constants.DefaultEncoding.GetBytes(response); HttpServerConsole.Instance.WriteLine(LogMessageType.Information, "Sending response: 200 Connection established for request: {0}", _requestInfo.RequestLine); // Give the OK if (!TryWriteToStream(line)) { return; } if (!TrySecureStream()) { return; } // Keep reading on this now encrypted stream ClientStreamWrapper.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(OnRead), ClientStreamWrapper); } catch (Exception ex) { HttpServerConsole.Instance.WriteLine(LogMessageType.Error, "SSL Connect failed: {0}", ex.Message); ClientStreamWrapper.Close(); } }
/// <summary> /// Stops the proxy /// </summary> public void Stop() { _stop = true; if (ClientStreamWrapper != null) { ClientStreamWrapper.Close(); } }
public void Close() { HttpServerConsole.Instance.WriteLine(LogMessageType.Information, "Closing upstream and downstream connections"); ClientStreamWrapper.Close(); _upStreamConnection.Close(); _isReading = false; IsBusy = false; }
/// <summary> /// Attempts to write to the network stream /// </summary> /// <param name="bytes"></param> /// <returns>true on success</returns> private bool TryWriteToStream(byte[] bytes) { bool success = ClientStreamWrapper.Write(bytes, 0, bytes.Length); if (!success) { ClientStreamWrapper.Close(); } return(success); }
/// <summary> /// Secures the current connection stream /// </summary> /// <returns>True if the operation is successful</returns> protected override bool TrySecureStream() { bool success = ClientStreamWrapper.SecureStream(_fwHost); if (!success) { ClientStreamWrapper.Close(); } return(success); }
/// <summary> /// Override to change the OnRead behavior /// </summary> /// <param name="ar"></param> protected virtual void OnRead(IAsyncResult ar) { try { if (_stop || Closed) { return; } _isBusy = true; HttpProxyClientStreamWrapper wrapper = (HttpProxyClientStreamWrapper)ar.AsyncState; int bytesRead = 0; bytesRead = wrapper.EndRead(ar); //we are still connected and we read more bytes if (bytesRead > 0) { // Append data to the request _requestBuilder.AddChunkReference(Buffer, bytesRead); _requestInfo = new HttpRequestInfo(_requestBuilder.ToArray(), false); if (!_requestInfo.IsFullRequest) { // not finished keep on reading! wrapper.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(OnRead), wrapper); } else { lock (_proxyLock) { // Done reading, process the request ProcessRequest(); } } } else { //we read 0 bytes _isBusy = _requestBuilder.Length > 0; } } catch (Exception ex) { ClientStreamWrapper.Close(); HttpServerConsole.Instance.WriteLine(ex); } }
/// <summary> /// Secures the current connection stream /// </summary> /// <returns>True if the operation is successful</returns> protected virtual bool TrySecureStream() { string host = null; if (_requestInfo != null) { host = _requestInfo.Host; } bool success = ClientStreamWrapper.SecureStream(host); if (!success) { ClientStreamWrapper.Close(); } return(success); }
/// <summary> /// Writes a CRWAE message to the client when response is not available from server /// </summary> /// <param name="statusCode">HTTP status code for the response</param> /// <param name="reason">Brief explanation of error</param> /// <param name="serviceCode">ID of the CRAWE message</param> /// <param name="args">Message args</param> protected virtual void ReturnHttpErrorResponse(HttpStatusCode statusCode, string reason, ServiceCode serviceCode, params object [] args) { byte[] messageBytes = HttpErrorResponse.GenerateHttpErrorResponse(statusCode, reason, serviceCode, args); if (!TryWriteToStream(messageBytes)) { return; } //add the response if we are adding requests to the data source if (_currDataStoreRequestInfo != null) { _currDataStoreRequestInfo.ResponseStatus = statusCode.ToString(); _currDataStoreRequestInfo.ResponseTime = DateTime.Now; TrafficDataStore.SaveResponse(_currDataStoreRequestInfo.Id, messageBytes); _currDataStoreRequestInfo = null; } ClientStreamWrapper.Close(); }
/// <summary> /// Writes a response to the client stream /// </summary> /// <param name="responseInfo"></param> protected virtual void ReturnResponse(HttpResponseInfo responseInfo) { HttpServerConsole.Instance.WriteLine(LogMessageType.Information, "Sending response: {0} for request: {1}", responseInfo.StatusLine, _requestInfo.RequestLine); if (_currDataStoreRequestInfo != null) { _currDataStoreRequestInfo.ResponseStatus = responseInfo.Status.ToString(); _currDataStoreRequestInfo.ResponseTime = DateTime.Now; } //process response headers if (responseInfo.Status == 401) { //we need to send the proxy support header/ or overwrite the existing proxy support header responseInfo.Headers["Proxy-Support"] = "Session-Based-Authentication"; } //if connection is close disconnect, or if the client sent us a connection close message if (String.Compare(responseInfo.Headers[CONNECTION_HEADER], "close", true) == 0 || String.Compare(_requestInfo.Headers[CONNECTION_HEADER], "close", true) == 0) { _isClose = true; } byte[] responseHead = HandleResponseByteChunk(responseInfo.ResponseHead); if (!TryWriteToStream(responseHead)) { return; } ; // Return the substitute response body if (responseInfo.ResponseBody.IsChunked) { byte[] chunk; byte[] chunkBuf; while ((chunk = responseInfo.ResponseBody.ReadChunk()) != null) { //write the chunk size line chunkBuf = Constants.DefaultEncoding.GetBytes(String.Format("{0:x}\r\n", chunk.Length)); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } //write the chunk chunk = HandleResponseByteChunk(chunk); if (!TryWriteToStream(chunk)) { return; } chunkBuf = Constants.DefaultEncoding.GetBytes("\r\n"); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } } //write a last chunk with the value 0 // write the last chunk size chunkBuf = Constants.DefaultEncoding.GetBytes("0\r\n\r\n"); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } } else { byte[] buffer = responseInfo.ResponseBody.ToArray(); if (buffer != null) { buffer = HandleResponseByteChunk(buffer); if (!TryWriteToStream(buffer)) { return; } } } //cleanup the request info _requestBuilder = new ByteArrayBuilder(); if (_currDataStoreRequestInfo != null) { TrafficDataStore.SaveResponse(_currDataStoreRequestInfo.Id, _currentRequestResponseBytes); } _currDataStoreRequestInfo = null; _currentRequestResponseBytes = null; //close the connection if the request had a connection close header if (_isClose) { ClientStreamWrapper.Close(); } else { _isBusy = false; ClientStreamWrapper.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(OnRead), ClientStreamWrapper); } }