/// <summary>
        /// contructor processes the HTTP response data
        /// </summary>
        /// <param name="messageHandler">external message handler</param>
        /// <param name="supportsGZip">are we supporting GZip compression</param>
        /// <param name="input"></param>
        /// <param name="log"></param>
        public ProxyResponseMessage(IExternalMessageHandler messageHandler, bool supportsGZip, Stream input, LogRequest log)
            : base(messageHandler, supportsGZip, input, log, false)
        {
            if (FirstHeaderLine != null)
            {
                // parse the status result for the response
                string[] parts = FirstHeaderLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length > 1)
                {
                    log.ScStatus = parts[1];
                    log.ScSubstatus = "0";

                    messageHandler.ProcessHeaderLineResponse(log);
                    int status;
                    if ( int.TryParse(log.ScStatus, out status) == false && log.ScStatus.StartsWith("html", StringComparison.InvariantCultureIgnoreCase) )
                        log.ScStatus = "200";
                }
                else
                {
                    // default to a 200 "Success" status
                    log.ScStatus = "200";
                    log.ScSubstatus = "0";
                }

            }
        }
        /// <summary>
        /// contructor processes the HTTP request data
        /// </summary>
        /// <param name="messageHandler">external message handler</param>
        /// <param name="supportsGZip">are we supporting GZip compression</param>
        /// <param name="input"></param>
        /// <param name="log"></param>
        public ProxyRequestMessage(IExternalMessageHandler messageHandler, bool supportsGZip, Stream input, LogRequest log)
            : base(messageHandler, supportsGZip, input, log, true)
        {
            if (FirstHeaderLine != null)
            {
                // parse the first line to get header information
                string[] parts = FirstHeaderLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length > 0)
                {
                    // method is the first token
                    log.CsMethod = parts[0];
                    if (parts.Length > 1)
                    {
                        // parse the query string
                        int index = parts[1].IndexOf('?');
                        if (index == -1)
                            log.CsUriStem = parts[1];
                        else
                        {
                            log.CsUriStem = parts[1].Substring(0, index);
                            log.CsUriQuery = parts[1].Substring(index + 1);
                        }

                        messageHandler.ProcessHeaderLineRequest(log);

                        // get the HTTP version if available
                        if (parts.Length > 2)
                            log.CsVersion = parts[2];
                    }
                }

                if (Authorization != null)
                {
                    // get header authorization infromation
                    int index = Authorization.IndexOf(_basicAuthorization);
                    if (index == 0)
                    {
                        // if basic authentication, get un/domain
                        log.CsUsername = ProcessUserNameAndPassword( Authorization.Substring(index + _basicAuthorization.Length), true, log.CsUsername);
                    }
                }
            }

            // must happen before settings code code below as it depends on username
            UserName = log.CsUsername;

            messageHandler.ProcessRequest(this, UserName);
        }
 void IExternalMessageHandler.ProcessHeaderLineResponse(LogRequest log)
 {
 }
 bool IExternalMessageHandler.OverrideResponseFromRequest(LogRequest log, string userName, string userAgent)
 {
     return false;
 }
Example #5
0
        /// <summary>
        /// IIS like logging factility
        /// </summary>
        /// <param name="proxyIP">The IP of this proxy server</param>
        /// <param name="request">request specific information</param>
        void ILogger.LogRequest(string proxyIP, LogRequest request)
        {
            if (BabaluConfigurationFactory.Instance.LogRequests)
            {
                try
                {
                    StringBuilder output = new StringBuilder(256);
                    foreach (string field in _fields)
                    {
                        string value = null;
                        switch (field)
                        {
                            case _fieldDate:
                                value = DateTime.Now.ToString("yyyy-MM-dd");
                                break;
                            case _fieldTime:
                                value = DateTime.Now.ToString("HH:mm:ss");
                                break;
                            case _fieldServerSitename:
                                value = _siteName;
                                break;
                            case _fieldServerComputername:
                                value = _computerName;
                                break;
                            case _fieldServerIp:
                                value = proxyIP;
                                break;
                            case _fieldCsMethod:
                                value = request.CsMethod;
                                break;
                            case _fieldCsUriStem:
                                value = request.CsUriStem;
                                break;
                            case _fieldCsUriQuery:
                                value = request.CsUriQuery;
                                break;
                            case _fieldServerPort:
                                value = request.ServerPort;
                                break;
                            case _fieldCsUsername:
                                value = request.CsUsername;
                                break;
                            case _fieldClientIp:
                                value = request.ClientIp;
                                break;
                            case _fieldCsVersion:
                                value = request.CsVersion;
                                break;
                            case _fieldCsUserAgent:
                                value = request.CsUserAgent;
                                break;
                            case _fieldScStatus:
                                value = request.ScStatus;
                                break;
                            case _fieldScSubstatus:
                                value = request.ScSubstatus;
                                break;
                            case _fieldDeviceType:
                                value = request.ExternalInfo;
                                break;
                            case _fieldBabaluStatus:
                                value = request.BabaluStatus;
                                break;
                        }

                        if (string.IsNullOrEmpty(value))
                            value = "-";
                        output.AppendFormat("{0} ", value.Replace(" ", ""));
                    }

                    _resultsLogQueue.Enqueue(output.ToString());
                }
                catch (Exception excp)
                {
                    // eat any exception as we do not want to do any harm when logging
                    _me.LogException(excp, "Writting to Request log");
                }
            }
        }
Example #6
0
        /// <summary>
        /// socket input from client or server to process
        /// </summary>
        /// <param name="messageHandler">external message handler</param>
        /// <param name="supportsGZip">are we supporting GZip compression</param>
        /// <param name="input">the client for server HTTP stream</param>
        /// <param name="log">request log structure</param>
        /// <param name="checkPreHttp">is this the request and a pre http 1.1 request</param>
        protected ProxyMessage(IExternalMessageHandler messageHandler, bool supportsGZip, Stream input, LogRequest log, bool checkPreHttp)
        {
            _messageHandler = messageHandler;

            _supportsGZip = supportsGZip;
            _rawRead = new byte[BufferSize];
            _header = new List<byte>(BufferSize);
            _content = new List<byte>(BufferSize);

            int bytes = 0;
            bool headerDone = false;
            bool contentDone = false;
            int contentLength = 0;
            // loop until we have read al the input (no bytes returned, header end character or content length reached)
            do
            {
                bytes = input.Read(_rawRead, 0, BufferSize);

                if (bytes != 0)
                {
                    if (headerDone == false)
                    {
                        // add all bytes read to the header
                        _header.AddRange(_rawRead.Take(bytes));

                        // parse the header information
                        HeaderPositions match = ParseHeader();

                        // if we read the entire HTTP header process it
                        if (match.HeaderEnd != -1)
                        {
                            // find the end of the list line
                            _firstHeaderLineEnd = match.FirstLineEnd;

                            // add any content we may have read into the content buffer based on the header end characters
                            _content.AddRange(_header.Skip(match.HeaderEnd));
                            // trim the header of any content information
                            _header.RemoveRange(match.HeaderEnd, _header.Count - match.HeaderEnd);
                            headerDone = true;

                            // if the header did not contain a content length tag, content is done
                            if (match.ContentLength == -1)
                                contentDone = true;
                            else
                            {
                                // get the "real" content length from the header
                                int pos = match.ContentLength;
                                while (_header[pos] != '\r')
                                {
                                    char c = (char)_header[pos];
                                    if (char.IsNumber(c))
                                        contentLength = ((contentLength * 10) + (c - '0'));
                                    ++pos;
                                }

                                // see if we have alread read in all the content
                                if (contentLength == 0 || _content.Count == contentLength)
                                    contentDone = true;
                            }

                            // get misc. header values
                            _contentType = ParseHeaderValue(match.ContentType);
                            _contentEncoding = ParseHeaderValue(match.ContentEncoding);
                            _cacheControl = ParseHeaderValue(match.CacheControl);

                            string transferEncoding = ParseHeaderValue(match.TransferEncoding);
                            if (transferEncoding != null && transferEncoding.IndexOf(_transferEncodingChunkedToken, StringComparison.InvariantCultureIgnoreCase) != -1)
                            {
                                _transferEncodingChunked = true;
                                contentDone = ReadChunkedContent();
                            }

                            if (match.Host != -1)
                                Host = ParseHeaderValue(match.Host, ':');

                            // have logging values
                            if (match.UserAgent != -1)
                                UserAgent = log.CsUserAgent = ParseHeaderValue(match.UserAgent);
                            if (match.Authorization != -1)
                                Authorization = ParseHeaderValue(match.Authorization);
                        }
                        else if ( match.FirstLineEnd != -1 && checkPreHttp )
                        {
                            // check pre http 1.1 headers
                            string []parts = Encoding.UTF8.GetString(_header.ToArray()).Split( new char[] { ' ', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries );
                            if (parts.Length == 2 && string.Compare(parts[0], "GET", true) == 0)
                            {
                                headerDone = true;
                                contentDone = true;
                            }
                        }
                    }
                    else
                    {
                        // if the header is complete, read the content (if specified in Content-Length)
                        _content.AddRange(_rawRead.Take(bytes));
                        if (_transferEncodingChunked)
                            contentDone = ReadChunkedContent();
                        else
                            contentDone = (_content.Count == contentLength);
                    }
                }
            }
            while (bytes != 0 && (headerDone == false || contentDone == false));

            if (_transferEncodingChunked)
                DeChunkData();

            LogHeaderContent();
        }
Example #7
0
 /// <summary>
 /// log this request
 /// </summary>
 /// <param name="proxyIP"></param>
 /// <param name="request"></param>
 public static void LogRequest(string proxyIP, LogRequest request)
 {
     if (_logger != null)
         _logger.LogRequest(proxyIP, request);
 }
        /// <summary>
        ///  thread method to handle http request
        /// </summary>
        /// <param name="stateInfo">the TcpClient from the listener</param>
        private void HandleAsyncConnection(object stateInfo)
        {
            BabaluCounters.DecrementPendingThread();

            // initialize log information class
            LogRequest log = new LogRequest();

            Guid? activity = null;
            try
            {
                // increment the gateway call count
                activity = BabaluCounters.IncrementAllRequest();

                using (TcpClient realClient = stateInfo as TcpClient)
                {
                    // get client information for logging
                    IPEndPoint localIp = realClient.Client.LocalEndPoint as IPEndPoint;
                    if (localIp != null)
                        log.ServerPort = localIp.Port.ToString();
                    IPEndPoint remoteIp = realClient.Client.RemoteEndPoint as IPEndPoint;
                    if (remoteIp != null)
                        log.ClientIp = remoteIp.Address.ToString();

                    // get client stream
                    using (NetworkStream realClientStream = realClient.GetStream())
                    {
                        // get specific implementation of client stream
                        using (Stream realClientStreamImpl = GetRealClientStream(realClientStream))
                        {
                            // process the client stream
                            IExternalMessageHandler messageHandler = ExtensionConfig.BabaluExtension.MessageHandler(_proxiedServer.ServerType);
                            ProxyRequestMessage request = new ProxyRequestMessage(messageHandler, _proxiedServer.SupportGZip, realClientStreamImpl, log);

                            if (messageHandler.OverrideResponseFromRequest(log, request.UserName, request.UserAgent))
                            {
                                realClientStreamImpl.Write(messageHandler.ResponseBuffer, 0, messageHandler.ResponseBuffer.Length);
                                log.ScStatus = messageHandler.ResponseCode;
                                log.ScSubstatus = "0";
                            }
                            else if (request.HasData && _proxiedServer.ProxiedServers.ContainsKey(request.Host.ToLower()))
                            {
                                Tuple<string, int, bool> proxied = _proxiedServer.ProxiedServers[request.Host.ToLower()];
                                string proxiedServer = proxied.Item1;
                                int proxiedPort = proxied.Item2;
                                bool proxiedSsl = proxied.Item3;

                                // see if this request is cached on the server
                                byte[] buffer = (_proxiedServer.CacheContent ? RequestCache.GetCache(request.Host, request.RequestUrl) : null);

                                if (buffer != null)
                                {
                                    // write out cache result, no need to ask proxied server for data
                                    realClientStreamImpl.Write(buffer, 0, buffer.Length);
                                    log.ScStatus = "200";
                                    log.ScSubstatus = "0";

                                    LogFactory.LogDebug("Cache hit {0}", request.RequestUrl);
                                    log.BabaluStatus = "Cache";
                                }
                                else
                                {
                                    // create a connection to the proxied server and pass client request to that server
                                    using (TcpClient proxyClient = new TcpClient(proxiedServer, proxiedPort))
                                    {
                                        // change all ip/dns information from proxy server to proxied server
                                        byte[] data = request.Tranform(request.Host, proxiedServer);

                                        // get proxied client stream
                                        using (NetworkStream proxyClientStream = proxyClient.GetStream())
                                        {
                                            // get specific implementation of proxied client stream
                                            using (Stream proxyClientImpl = GetProxyClientStream(proxyClientStream, proxiedServer, proxiedSsl))
                                            {
                                                // Send the message to the connected proxied server
                                                proxyClientImpl.Write(data, 0, data.Length);

                                                // read the response from the proxied server
                                                ProxyResponseMessage response = new ProxyResponseMessage(messageHandler, _proxiedServer.SupportGZip, proxyClientImpl, log);
                                                if (response.HasData)
                                                {
                                                    if ( messageHandler.OverrideResponseFromResponse(response, request.UserName))
                                                    {
                                                        realClientStreamImpl.Write(messageHandler.ResponseBuffer, 0, messageHandler.ResponseBuffer.Length);
                                                        log.ScStatus = messageHandler.ResponseCode;
                                                        log.ScSubstatus = "0";

                                                        LogFactory.LogInformation("Response Overridden from Response: {0} User: {1}", log.ScStatus, request.UserName);
                                                    }
                                                    else
                                                    {
                                                        // change all ip/dns information from proxied server to proxy server - if provisional and it is a sync command special tranform processing
                                                        buffer = response.Tranform(proxiedServer, request.Host);
                                                        // write response back to the original client
                                                        realClientStreamImpl.Write(buffer, 0, buffer.Length);

                                                        // add request to server cache if possible
                                                        if (_proxiedServer.CacheContent)
                                                            response.ProcessCacheItem(request, buffer);
                                                    }
                                                }
                                                else
                                                    LogFactory.LogDebug("response has no data");

                                                ProxyMessage.RawLog(  request, response );
                                            }
                                        }
                                    }
                                }
                            }
                            else
                                LogFactory.LogDebug("request has no data");
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                LogFactory.LogException(excp, "Processing to Request: {0}", log);
                log.ScSubstatus = "-1";
                BabaluCounters.IncrementException();
            }
            finally
            {
                LogFactory.LogRequest(_proxiedServer.ProxyIP, log);
                BabaluCounters.DecrementAllRequest(activity);
            }
        }