private async void AddToCacheAsync(ReadoutState State)
        {
            try
            {
                if (State.TempOutput != null)
                {
                    State.TempOutput.Position = 0;

                    await this.httpxCache.AddToCache(State.BareJid, State.LocalResource, State.ContentType, State.ETag,
                                                     State.LastModified.Value, State.Expires, State.TempOutput);
                }
            }
            catch (Exception ex)
            {
                Log.Critical(ex);
            }
            finally
            {
                try
                {
                    State.Dispose();
                }
                catch (Exception ex2)
                {
                    Log.Critical(ex2);
                }
            }
        }
 internal void StartReadout()
 {
     this.readoutState = ReadoutState.Started;
     this.totalFields.Clear();
     this.recentFields.Clear();
     this.totalReadoutErrors.Clear();
     this.recentReadoutErrors.Clear();
 }
        internal void Receiving()
        {
            if (this.done)
            {
                this.StartReadout();
            }

            this.readoutState = this.done ? ReadoutState.Received : ReadoutState.Receiving;
            this.recentFields.Clear();
            this.recentReadoutErrors.Clear();
        }
        private void BinaryDataReceived(ReadoutState State2, bool Last, byte[] Data)
        {
            try
            {
                State2.Response.Write(Data);
            }
            catch (Exception)
            {
                State2.Dispose();
                return;
            }

            if (State2.TempOutput != null)
            {
                State2.TempOutput.Write(Data, 0, Data.Length);
            }

            if (Last)
            {
                State2.Response.SendResponse();
                this.AddToCacheAsync(State2);
            }
        }
        private void ResponseData(object Sender, HttpxResponseDataEventArgs e)
        {
            ReadoutState State2 = (ReadoutState)e.State;

            this.BinaryDataReceived(State2, e.Last, e.Data);
        }
        private void RequestResponse(object Sender, HttpxResponseEventArgs e)
        {
            ReadoutState State2 = (ReadoutState)e.State;

            State2.Response.StatusCode    = e.StatusCode;
            State2.Response.StatusMessage = e.StatusMessage;

            if (e.HttpResponse != null)
            {
                foreach (KeyValuePair <string, string> Field in e.HttpResponse.GetHeaders())
                {
                    switch (Field.Key.ToLower())
                    {
                    case "cookie":
                    case "set-cookie":
                        // Do not forward cookies.
                        break;

                    case "content-type":
                        State2.ContentType = Field.Value;
                        State2.Response.SetHeader(Field.Key, Field.Value);
                        break;

                    case "etag":
                        State2.ETag = Field.Value;
                        State2.Response.SetHeader(Field.Key, Field.Value);
                        break;

                    case "last-modified":
                        DateTimeOffset TP;
                        if (CommonTypes.TryParseRfc822(Field.Value, out TP))
                        {
                            State2.LastModified = TP;
                        }
                        State2.Response.SetHeader(Field.Key, Field.Value);
                        break;

                    case "expires":
                        if (CommonTypes.TryParseRfc822(Field.Value, out TP))
                        {
                            State2.Expires = TP;
                        }
                        State2.Response.SetHeader(Field.Key, Field.Value);
                        break;

                    case "cache-control":
                        State2.CacheControl = Field.Value;
                        State2.Response.SetHeader(Field.Key, Field.Value);
                        break;

                    case "pragma":
                        State2.Pragma = Field.Value;
                        State2.Response.SetHeader(Field.Key, Field.Value);
                        break;

                    default:
                        State2.Response.SetHeader(Field.Key, Field.Value);
                        break;
                    }
                }
            }

            if (!e.HasData)
            {
                State2.Response.SendResponse();
            }
            else
            {
                if (e.StatusCode == 200 && State2.Cacheable && State2.CanCache &&
                    this.httpxCache.CanCache(State2.BareJid, State2.LocalResource, State2.ContentType))
                {
                    State2.TempOutput = new TemporaryFile();
                }

                if (e.Data != null)
                {
                    this.BinaryDataReceived(State2, true, e.Data);
                }
            }
        }
        private void SendRequest(HttpxClient HttpxClient, string To, string Method, string BareJID, string LocalUrl,
                                 HttpRequest Request, HttpResponse Response)
        {
            LinkedList <HttpField> Headers = new LinkedList <HttpField>();

            foreach (HttpField Header in Request.Header)
            {
                switch (Header.Key.ToLower())
                {
                case "host":
                    Headers.AddLast(new HttpField("Host", BareJID));
                    break;

                case "cookie":
                case "set-cookie":
                    // Do not forward cookies.
                    break;

                default:
                    Headers.AddLast(Header);
                    break;
                }
            }

            ReadoutState State = new ReadoutState(Response, BareJID, LocalUrl)
            {
                Cacheable = (Method == "GET" && this.httpxCache != null)
            };

            string s = LocalUrl;
            int    i = s.IndexOf('.');

            if (i > 0)
            {
                s = s.Substring(i + 1);
                i = s.IndexOfAny(new char[] { '?', '#' });
                if (i > 0)
                {
                    s = s.Substring(0, i);
                }

                if (this.httpxCache.CanCache(BareJID, LocalUrl, InternetContent.GetContentType(s)))
                {
                    LinkedListNode <HttpField> Loop = Headers.First;
                    LinkedListNode <HttpField> Next;

                    while (Loop != null)
                    {
                        Next = Loop.Next;

                        switch (Loop.Value.Key.ToLower())
                        {
                        case "if-match":
                        case "if-modified-since":
                        case "if-none-match":
                        case "if-range":
                        case "if-unmodified-since":
                            Headers.Remove(Loop);
                            break;
                        }

                        Loop = Next;
                    }
                }
            }

            HttpxClient.Request(To, Method, LocalUrl, Request.Header.HttpVersion, Headers, Request.HasData ? Request.DataStream : null,
                                this.RequestResponse, this.ResponseData, State);
        }
 internal void SetError(string ErrorMessage)
 {
     this.readoutState = ReadoutState.Error;
     this.errorMessage = ErrorMessage;
     this.done         = true;
 }