예제 #1
0
        public void Reset()
        {
            m_TimeOut       = 10;
            m_URL           = "";
            m_ProxyHost     = "";
            m_ProxyPort     = "";
            m_ProxyUser     = "";
            m_ProxyPassword = "";

            m_UserAgent = "Mozilla/4.0";
            m_Accept    = "text/*";

            m_Content       = "";
            m_PlainText     = "";
            m_ReplyCode     = 0;
            m_LastModified  = null;
            m_ContentLength = 0;
            m_ContentType   = "";


            m_nBytesSent     = 0;
            m_nBytesReceived = 0;
            m_AllowRedirect  = true;
            m_State          = HttpStates.idle;

            bCancel = false;

            FireStateChanged(m_State);
        }
예제 #2
0
        internal void Close()
        {
            State = HttpStates.Closed;

            owner.Logger.LogTrace($"{this} - Closing connection after { requestCount} requests");
            try
            {
                client.Close();
            }
            catch (Exception)
            {
                // ignored
            }
            owner.RemoveClient(this);
            if (stream != null)
            {
                try
                {
                    stream.Dispose();
                }
                catch (ObjectDisposedException)
                {
                }
            }
        }
예제 #3
0
 private void FireStateChanged(HttpStates State)
 {
     if (StateChangedEvent != null)
     {
         StateChangedEvent(State);
     }
 }
예제 #4
0
        private void SetupResponse()
        {
            State = HttpStates.WriteBegin;
            try
            {
                if (!owner.AuthorizeClient(this))
                {
                    throw new HttpStatusException(HttpCode.Denied);
                }
                if (string.IsNullOrEmpty(Path))
                {
                    throw new HttpStatusException(HttpCode.NotFound);
                }
                var handler = owner.FindHandler(Path);
                if (handler == null)
                {
                    throw new HttpStatusException(HttpCode.NotFound);
                }
                response = handler.HandleRequest(this);
                if (response == null)
                {
                    throw new ArgumentException("Handler did not return a response");
                }
            }
            catch (HttpStatusException ex)
            {
                owner.Logger.LogTrace($"{this} - Got a {ex.Code}: {Path}");

                switch (ex.Code)
                {
                case HttpCode.NotFound:
                    response = error404.HandleRequest(this);
                    break;

                case HttpCode.Denied:
                    response = error403.HandleRequest(this);
                    break;

                case HttpCode.InternalError:
                    response = error500.HandleRequest(this);
                    break;

                default:
                    response = new StaticHandler(new StringResponse(
                                                     ex.Code,
                                                     "text/plain",
                                                     ex.Message
                                                     )).HandleRequest(this);
                    break;
                }
            }
            catch (Exception ex)
            {
                owner.Logger.LogTrace($"{this} - Failed to process response Ex [{ ex }]");
                response = error500.HandleRequest(this);
            }
            SendResponse();
        }
예제 #5
0
        private void SendResponse()
        {
            var statusCode     = response.Status;
            var responseBody   = ProcessRanges(response, ref statusCode);
            var responseStream = new ConcatenatedStream();

            try {
                var headerBlock = new StringBuilder();
                headerBlock.AppendFormat(
                    "HTTP/1.1 {0} {1}\r\n",
                    (uint)statusCode,
                    HttpPhrases.Phrases[statusCode]
                    );
                headerBlock.Append(response.Headers.HeaderBlock);
                headerBlock.Append(CRLF);

                var headerStream = new MemoryStream(
                    Encoding.ASCII.GetBytes(headerBlock.ToString()));
                responseStream.AddStream(headerStream);
                if (Method != "HEAD" && responseBody != null)
                {
                    responseStream.AddStream(responseBody);
                    responseBody = null;
                }
                DebugFormat("{0} - {1} response for {2}", this, (uint)statusCode, Path);
                state = HttpStates.Writing;
                var sp = new StreamPump(responseStream, stream, BUFFER_SIZE);
                sp.Pump((pump, result) =>
                {
                    pump.Input.Close();
                    pump.Input.Dispose();
                    if (result == StreamPumpResult.Delivered)
                    {
                        DebugFormat("{0} - Done writing response", this);

                        string conn;
                        if (Headers.TryGetValue("connection", out conn) &&
                            conn.ToUpperInvariant() == "KEEP-ALIVE")
                        {
                            ReadNext();
                            return;
                        }
                    }
                    else
                    {
                        DebugFormat("{0} - Client aborted connection", this);
                    }
                    Close();
                });
            }
            catch (Exception) {
                responseStream.Dispose();
                throw;
            }
            finally {
                responseBody?.Dispose();
            }
        }
예제 #6
0
        public HttpClient(HttpServer aOwner, TcpClient aClient)
        {
            State        = HttpStates.Accepted;
            lastActivity = DateTime.Now;

            owner  = aOwner;
            client = aClient;
            stream = client.GetStream();
            client.Client.UseOnlyOverlappedIO = true;

            RemoteEndpoint = client.Client.RemoteEndPoint as IPEndPoint;
            LocalEndPoint  = client.Client.LocalEndPoint as IPEndPoint;
        }
예제 #7
0
        private void ReadNext()
        {
            Method = null;
            Headers.Clear();
            hasHeaders = false;
            Body       = null;
            bodyBytes  = 0;
            readStream = StreamManager.GetStream();

            ++requestCount;
            State = HttpStates.ReadBegin;

            Read();
        }
예제 #8
0
 private void SetupResponse()
 {
     State = HttpStates.WRITEBEGIN;
       try {
     var handler = owner.FindHandler(path);
     if (handler == null) {
       throw new Http404Exception();
     }
     response = handler.HandleRequest(this);
     if (response == null) {
       throw new ArgumentException("Handler did not return a response");
     }
       }
       catch (Http404Exception ex) {
     Warn(String.Format("{0} - Got a 404: {1}", this, path), ex);
     response = Error404.HandleRequest(this);
       }
       catch (Exception ex) {
     Warn(String.Format("{0} - Failed to process response", this), ex);
     response = Error500.HandleRequest(this);
       }
       SendResponse();
 }
예제 #9
0
        private void SendResponse()
        {
            var responseBody = ProcessRanges(response);
              var statusCode = response.Status;

              var headerBlock = new StringBuilder();
              headerBlock.AppendFormat("HTTP/1.1 {0} {1}\r\n", (uint)statusCode, HttpPhrases.Phrases[statusCode]);
              headerBlock.Append(response.Headers.HeaderBlock);
              headerBlock.Append(CRLF);

              var responseStream = new ConcatenatedStream();
              try {
            var headerStream = new MemoryStream(Encoding.ASCII.GetBytes(headerBlock.ToString()));
            responseStream.AddStream(headerStream);
            if (method != "HEAD" && responseBody != null) {
              responseStream.AddStream(responseBody);
            }
            InfoFormat("{0} - {1} response for {2}", this, (uint)statusCode, path);
            state = HttpStates.WRITING;
            new StreamPump(responseStream, stream, (pump, result) =>
            {
              pump.Input.Close();
              pump.Input.Dispose();
              if (result == StreamPumpResult.Delivered) {
            DebugFormat("{0} - Done writing response", this);

            string conn;
            if (headers.TryGetValue("connection", out conn) && conn.ToLower() == "keep-alive") {
              ReadNext();
              return;
            }
              }
              Close();
            }, BUFFER_SIZE);
              }
              catch (Exception) {
            responseStream.Dispose();
            throw;
              }
        }
예제 #10
0
        private void ReadNext()
        {
            method = null;
              headers.Clear();
              hasHeaders = false;
              body = null;
              bodyBytes = 0;
              readStream = new MemoryStream();

              ++requestCount;
              State = HttpStates.READBEGIN;

              Read();
        }
예제 #11
0
        private void ReadCallback(IAsyncResult result)
        {
            if (state == HttpStates.CLOSED) {
            return;
              }

              State = HttpStates.READING;

              var read = 0;
              try {
            read = stream.EndRead(result);
            if (read < 0) {
              throw new HttpException("Client did not send anything");
            }
            DebugFormat("{0} - Read {1} bytes", this, read);
            readStream.Write(buffer, 0, read);
            lastActivity = DateTime.Now;
              }
              catch (Exception) {
            if (!IsATimeout) {
              WarnFormat("{0} - Failed to read data", this);
              Close();
            }
            return;
              }

              try {
            if (!hasHeaders) {
              readStream.Seek(0, SeekOrigin.Begin);
              var reader = new StreamReader(readStream);
              for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) {
            line = line.Trim();
            if (string.IsNullOrEmpty(line)) {
              hasHeaders = true;
              readStream = new MemoryStream();
              if (headers.ContainsKey("content-length") && uint.TryParse(headers["content-length"], out bodyBytes)) {
                if (bodyBytes > (1 << 20)) {
                  throw new IOException("Body too long");
                }
                var bytes = Encoding.ASCII.GetBytes(reader.ReadToEnd());
                readStream.Write(bytes, 0, bytes.Length);
                DebugFormat("Must read body bytes {0}", bodyBytes);
              }
              else {
                readStream = new MemoryStream();
              }
              break;
            }
            if (method == null) {
              var parts = line.Split(new char[] { ' ' }, 3);
              method = parts[0].Trim().ToUpper();
              path = parts[1].Trim();
              DebugFormat("{0} - {1} request for {2}", this, method, path);
            }
            else {
              var parts = line.Split(new char[] { ':' }, 2);
              headers[parts[0]] = Uri.UnescapeDataString(parts[1]).Trim();
            }
              }
            }
            if (bodyBytes != 0 && bodyBytes > readStream.Length) {
              DebugFormat("{0} - Bytes to go {1}", this, bodyBytes - readStream.Length);
              Read();
              return;
            }
            using (readStream) {
              body = Encoding.UTF8.GetString(readStream.ToArray());
              Debug(body);
              Debug(headers);
            }
            SetupResponse();
              }
              catch (Exception ex) {
            Warn(String.Format("{0} - Failed to process request", this), ex);
            response = Error500.HandleRequest(this);
            SendResponse();
              }
        }
예제 #12
0
        internal void Close()
        {
            State = HttpStates.CLOSED;

              DebugFormat("{0} - Closing connection after {1} requests", this, requestCount);
              try {
            client.Close();
              }
              catch (Exception) {
              }
              owner.RemoveClient(this);
              if (stream != null) {
            try {
              stream.Dispose();
            }
            catch (ObjectDisposedException) {
            }
              }
        }
예제 #13
0
 private void SetupResponse()
 {
     State = HttpStates.WRITEBEGIN;
       try {
     if (!owner.AuthorizeClient(this)) {
       throw new HttpStatusException(HttpCode.Denied);
     }
     if (string.IsNullOrEmpty(path)) {
       throw new HttpStatusException(HttpCode.NotFound);
     }
     var handler = owner.FindHandler(path);
     if (handler == null) {
       throw new HttpStatusException(HttpCode.NotFound);
     }
     response = handler.HandleRequest(this);
     if (response == null) {
       throw new ArgumentException("Handler did not return a response");
     }
       }
       catch (HttpStatusException ex) {
     #if DEBUG
      Warn(String.Format("{0} - Got a {2}: {1}", this, path, ex.Code), ex);
     #else
     InfoFormat("{0} - Got a {2}: {1}", this, path, ex.Code);
     #endif
     switch (ex.Code) {
       case HttpCode.NotFound:
     response = Error404.HandleRequest(this);
     break;
       case HttpCode.Denied:
     response = Error403.HandleRequest(this);
     break;
       case HttpCode.InternalError:
     response = Error500.HandleRequest(this);
     break;
       default:
     response = new StaticHandler(new StringResponse(ex.Code, "text/plain", ex.Message)).HandleRequest(this);
     break;
     }
       }
       catch (Exception ex) {
     Warn(String.Format("{0} - Failed to process response", this), ex);
     response = Error500.HandleRequest(this);
       }
       SendResponse();
 }
예제 #14
0
        private void SendResponse()
        {
            var responseBody = response.Body;
              var st = response.Status;

              var contentLength = GetContentLengthFromStream(responseBody);

              string ar;
              if (st == HttpCodes.OK && contentLength > 0 && headers.TryGetValue("Range", out ar)) {
            try {
              var m = bytes.Match(ar);
              if (!m.Success) {
            throw new InvalidDataException("Not parsed!");
              }
              var totalLength = contentLength;
              var start = 0L;
              var end = totalLength - 1;
              if (!long.TryParse(m.Groups[1].Value, out start) || start < 0) {
            throw new InvalidDataException("Not parsed");
              }
              if (m.Groups.Count != 3 || !long.TryParse(m.Groups[2].Value, out end) || end <= start || end >= totalLength) {
            end = totalLength - 1;
              }
              if (start >= end) {
            responseBody.Close();
            response = Error416.HandleRequest(this);
            SendResponse();
            return;
              }

              if (start > 0) {
            responseBody.Seek(start, SeekOrigin.Current);
              }
              contentLength = end - start + 1;
              response.Headers["Content-Length"] = contentLength.ToString();
              response.Headers.Add("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, totalLength));
              st = HttpCodes.PARTIAL;
            }
            catch (Exception ex) {
              Warn(String.Format("{0} - Failed to process range request!", this), ex);
            }
              }

              var hb = new StringBuilder();
              hb.AppendFormat("HTTP/1.1 {0} {1}\r\n", (uint)st, HttpPhrases.Phrases[st]);
              hb.Append(response.Headers.HeaderBlock);
              hb.Append("\r\n");

              var rs = new ConcatenatedStream();
              try {
            var headerStream = new MemoryStream(Encoding.ASCII.GetBytes(hb.ToString()));
            rs.AddStream(headerStream);
            if (method != "HEAD" && responseBody != null) {
              rs.AddStream(responseBody);
            }
            InfoFormat("{0} - {1} response for {2}", this, (uint)st, path);
            state = HttpStates.WRITING;
            new StreamPump(rs, stream, (pump, result) =>
            {
              pump.Input.Close();
              pump.Input.Dispose();
              if (result == StreamPumpResult.Delivered) {
            DebugFormat("{0} - Done writing response", this);

            string conn;
            if (headers.TryGetValue("connection", out conn) && conn.ToLower() == "keep-alive") {
              ReadNext();
              return;
            }
              }
              Close();
            }, BUFFER_SIZE);
              }
              catch (Exception) {
            rs.Dispose();
            throw;
              }
        }
예제 #15
0
        private void SendResponse()
        {
            var responseBody = response.Body;
            var st           = response.Status;

            var contentLength = GetContentLengthFromStream(responseBody);

            string ar;

            if (st == HttpCodes.OK && contentLength > 0 && headers.TryGetValue("Range", out ar))
            {
                try {
                    var m = bytes.Match(ar);
                    if (!m.Success)
                    {
                        throw new InvalidDataException("Not parsed!");
                    }
                    var totalLength = contentLength;
                    var start       = 0L;
                    var end         = totalLength - 1;
                    if (!long.TryParse(m.Groups[1].Value, out start) || start < 0)
                    {
                        throw new InvalidDataException("Not parsed");
                    }
                    if (m.Groups.Count != 3 || !long.TryParse(m.Groups[2].Value, out end) || end <= start || end >= totalLength)
                    {
                        end = totalLength - 1;
                    }
                    if (start >= end)
                    {
                        responseBody.Close();
                        response = Error416.HandleRequest(this);
                        SendResponse();
                        return;
                    }

                    if (start > 0)
                    {
                        responseBody.Seek(start, SeekOrigin.Current);
                    }
                    contentLength = end - start + 1;
                    response.Headers["Content-Length"] = contentLength.ToString();
                    response.Headers.Add("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, totalLength));
                    st = HttpCodes.PARTIAL;
                }
                catch (Exception ex) {
                    Warn(String.Format("{0} - Failed to process range request!", this), ex);
                }
            }

            var hb = new StringBuilder();

            hb.AppendFormat("HTTP/1.1 {0} {1}\r\n", (uint)st, HttpPhrases.Phrases[st]);
            hb.Append(response.Headers.HeaderBlock);
            hb.Append("\r\n");

            var rs = new ConcatenatedStream();

            try {
                var headerStream = new MemoryStream(Encoding.ASCII.GetBytes(hb.ToString()));
                rs.AddStream(headerStream);
                if (method != "HEAD" && responseBody != null)
                {
                    rs.AddStream(responseBody);
                }
                InfoFormat("{0} - {1} response for {2}", this, (uint)st, path);
                state = HttpStates.WRITING;
                new StreamPump(rs, stream, (pump, result) =>
                {
                    pump.Input.Close();
                    pump.Input.Dispose();
                    if (result == StreamPumpResult.Delivered)
                    {
                        DebugFormat("{0} - Done writing response", this);

                        string conn;
                        if (headers.TryGetValue("connection", out conn) && conn.ToLower() == "keep-alive")
                        {
                            ReadNext();
                            return;
                        }
                    }
                    Close();
                }, BUFFER_SIZE);
            }
            catch (Exception) {
                rs.Dispose();
                throw;
            }
        }
예제 #16
0
        private void ReadCallback(IAsyncResult result)
        {
            if (state == HttpStates.Closed)
            {
                return;
            }

            State = HttpStates.Reading;

            try
            {
                var read = stream.EndRead(result);
                if (read < 0)
                {
                    throw new HttpException("Client did not send anything");
                }
                owner.Logger.LogTrace($"{this} - Read {read} bytes");
                readStream.Write(buffer, 0, read);
                lastActivity = DateTime.Now;
            }
            catch (Exception)
            {
                if (!IsATimeout)
                {
                    owner.Logger.LogTrace($"{this} - Failed to read data");
                    Close();
                }
                return;
            }

            try
            {
                if (!hasHeaders)
                {
                    readStream.Seek(0, SeekOrigin.Begin);
                    var reader = new StreamReader(readStream);
                    for (var line = reader.ReadLine();
                         line != null;
                         line = reader.ReadLine())
                    {
                        line = line.Trim();
                        if (string.IsNullOrEmpty(line))
                        {
                            hasHeaders = true;
                            readStream = StreamManager.GetStream();
                            if (Headers.ContainsKey("content-length") &&
                                uint.TryParse(Headers["content-length"], out bodyBytes))
                            {
                                if (bodyBytes > 1 << 20)
                                {
                                    throw new IOException("Body too long");
                                }
                                var ascii = Encoding.ASCII.GetBytes(reader.ReadToEnd());
                                readStream.Write(ascii, 0, ascii.Length);
                                owner.Logger.LogTrace($"Must read body bytes {bodyBytes}");
                            }
                            break;
                        }
                        if (Method == null)
                        {
                            var parts = line.Split(new[] { ' ' }, 3);
                            Method = parts[0].Trim().ToUpperInvariant();
                            Path   = parts[1].Trim();
                            owner.Logger.LogTrace($"{this} - {Method} request for {Path}");
                        }
                        else
                        {
                            var parts = line.Split(new[] { ':' }, 2);
                            Headers[parts[0]] = Uri.UnescapeDataString(parts[1]).Trim();
                        }
                    }
                }
                if (bodyBytes != 0 && bodyBytes > readStream.Length)
                {
                    owner.Logger.LogTrace($"{this} - Bytes to go { (bodyBytes - readStream.Length) }");
                    Read();
                    return;
                }
                using (readStream)
                {
                    Body = Encoding.UTF8.GetString(readStream.ToArray());
                }
                SetupResponse();
            }
            catch (Exception ex)
            {
                owner.Logger.LogTrace($"{this} - Failed to process request Ex [{ ex }]");
                response = error500.HandleRequest(this);
                SendResponse();
            }
        }
예제 #17
0
        public string PostHtmlPage(string url, string rparams)
        {
            m_URL = url;
            string result = "";

            System.IO.StreamWriter Writer     = null;
            System.IO.StreamReader readStream = null;

            m_State = HttpStates.sending;
            FireStateChanged(m_State);

            System.Net.HttpWebRequest Request;

            try
            {
                Request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
            }
            catch (Exception ex)
            {
                throw ex;
                //modGlobal.ErrMsgBox(ex.Message);
                //return "";
            }

            System.Text.Encoding Enc = System.Text.Encoding.GetEncoding(1252);

            SetProxy(ref Request);
            Request.KeepAlive       = false;
            Request.ProtocolVersion = System.Net.HttpVersion.Version10;
            Request.Method          = "POST";
            Request.ContentType     = "application/x-www-form-urlencoded";
            Request.ContentLength   = rparams.Length;

            Request.AllowAutoRedirect            = m_AllowRedirect;
            Request.MaximumAutomaticRedirections = 10;
            Request.Timeout   = this.m_TimeOut * 1000;
            Request.UserAgent = this.m_UserAgent;

            try
            {
                Writer = new System.IO.StreamWriter(Request.GetRequestStream(), Enc);
                Writer.Write(rparams);
                Writer.Flush();
            }
            catch (Exception ex)
            {
                throw ex;
                //modGlobal.ErrMsgBox(ex.Message);
                //return "";
            }
            finally
            {
                try
                {
                    if (Writer != null)
                    {
                        Writer.Close();
                        Writer = null;
                    }
                }
                catch (Exception)
                {
                }
            }

            try
            {
                System.Net.HttpWebResponse Response = (System.Net.HttpWebResponse)Request.GetResponse();
                m_nBytesSent += Request.ContentLength;

                m_ReplyCode     = (int)Response.StatusCode;
                m_LastModified  = Response.LastModified;
                m_ContentLength = Response.ContentLength;
                m_ContentType   = Response.ContentType;

                System.IO.Stream responseStream = Response.GetResponseStream();
                readStream = new System.IO.StreamReader(responseStream, Enc);

                // ----- Read Results ...
                m_State = HttpStates.fetching;
                FireStateChanged(m_State);

                System.Text.StringBuilder SB = new System.Text.StringBuilder();

                char[] read = new char[257];
                // Reads 256 characters at a time.
                int count = readStream.Read(read, 0, 256);
                m_nBytesReceived += count;

                //Console.WriteLine("HTML..." + ControlChars.Lf + ControlChars.Cr)
                while (count > 0 && !bCancel)
                {
                    // Dumps the 256 characters to a string and displays the string to the console.
                    string str = new string(read, 0, count);

                    SB.Append(str);
                    //Console.Write(str)
                    count             = readStream.Read(read, 0, 256);
                    m_nBytesReceived += count;
                }

                result = SB.ToString();
                // ----- /Read Results ...
            }
            catch (Exception ex)
            {
                throw ex;
                //modGlobal.ErrMsgBox(ex.Message);
                //result = "";
            }
            finally
            {
                try
                {
                    if (readStream != null)
                    {
                        readStream.Close();
                        readStream = null;
                    }
                }
                catch (Exception)
                {
                }

                m_State = HttpStates.idle;
                FireStateChanged(m_State);
            }

            return(result);
        }
예제 #18
0
        private void SendResponse()
        {
            var statusCode = response.Status;
              var responseBody = ProcessRanges(response, ref statusCode);
              var responseStream = new ConcatenatedStream();
              try {
            var headerBlock = new StringBuilder();
            headerBlock.AppendFormat(
              "HTTP/1.1 {0} {1}\r\n",
              (uint)statusCode,
              HttpPhrases.Phrases[statusCode]
              );
            headerBlock.Append(response.Headers.HeaderBlock);
            headerBlock.Append(CRLF);

            var headerStream = new MemoryStream(
              Encoding.ASCII.GetBytes(headerBlock.ToString()));
            responseStream.AddStream(headerStream);
            if (Method != "HEAD" && responseBody != null) {
              responseStream.AddStream(responseBody);
              responseBody = null;
            }
            InfoFormat("{0} - {1} response for {2}", this, (uint)statusCode, Path);
            state = HttpStates.Writing;
            var sp = new StreamPump(responseStream, stream, BUFFER_SIZE);
            sp.Pump((pump, result) =>
            {
              pump.Input.Close();
              pump.Input.Dispose();
              if (result == StreamPumpResult.Delivered) {
            DebugFormat("{0} - Done writing response", this);

            string conn;
            if (Headers.TryGetValue("connection", out conn) &&
                conn.ToUpperInvariant() == "KEEP-ALIVE") {
              ReadNext();
              return;
            }
              }
              else {
            DebugFormat("{0} - Client aborted connection", this);
              }
              Close();
            });
              }
              catch (Exception) {
            responseStream.Dispose();
            throw;
              }
              finally {
            responseBody?.Dispose();
              }
        }
예제 #19
0
        private void ReadNext()
        {
            Method = null;
              Headers.Clear();
              hasHeaders = false;
              Body = null;
              bodyBytes = 0;
              readStream = StreamManager.GetStream();

              ++requestCount;
              State = HttpStates.ReadBegin;

              Read();
        }