Exemplo n.º 1
0
        public override Boolean ConnectionEstablished()
        {
            //NetworkStream dataStream = null;
            using (var _DataStream = GetStream(TcpClientConnection))
            {
                try
                {
                    #region Wait until new StreamData is available (returns true), timeout or server shutdown

                    if (!WaitForStreamDataAvailable())
                    {
                        return(false);
                    }

                    #endregion

                    #region Get header & body

                    HTTPHeader  requestHeader       = null;
                    Byte[]      requestBody         = null;
                    Byte[]      responseBodyBytes   = new byte[0];
                    Byte[]      responseHeaderBytes = null;
                    HTTPContext _HTTPWebContext     = null;
                    Exception   _LastException      = null;
                    var         _HeaderErrors       = GetHeaderAndBody(_DataStream, out requestHeader, out requestBody);

#if DEBUG
                    if (requestHeader.Destination == null)
                    {
                        return(false);
                    }
                    if (requestHeader.Headers.AllKeys.Contains("SENDER"))
                    {
                        Debug.WriteLine(string.Format("{0} Retrieved a request to resource {1} from {2}", DateTime.Now.TimeOfDay, requestHeader.Destination, requestHeader.Headers["SENDER"]), "HttpHandler");
                    }
                    else
                    {
                        Debug.WriteLine(string.Format("{0} Retrieved a request to resource {1}", DateTime.Now.TimeOfDay, requestHeader.Destination), "HttpHandler");
                    }
#endif
                    if (requestHeader == null || requestBody == null)
                    {
                        return(false);
                    }

                    #endregion

                    #region Trace

                    //System.Diagnostics.Trace.WriteLine("-------------------request started-------------------");
                    //System.Diagnostics.Trace.Indent();
                    //System.Diagnostics.Trace.WriteLine("requestHeader:");
                    //System.Diagnostics.Trace.Indent();
                    //System.Diagnostics.Trace.WriteLine(requestHeader.PlainHeader);
                    //System.Diagnostics.Trace.Unindent();
                    //System.Diagnostics.Trace.WriteLine("requestBody:");
                    //System.Diagnostics.Trace.Indent();
                    //System.Diagnostics.Trace.WriteLine(Encoding.UTF8.GetString(requestBody));
                    //System.Diagnostics.Trace.Unindent();
                    //System.Diagnostics.Trace.Unindent();
                    //System.Diagnostics.Trace.WriteLine("-----------------------------------------------------");

                    #endregion

                    #region Check if a error occurred during header processing...

                    HTTPHeader responseHeader = null;

                    if (requestHeader.HttpStatusCode != HTTPStatusCodes.OK)
                    {
                        responseHeader = new HTTPHeader()
                        {
                            HttpStatusCode = requestHeader.HttpStatusCode,
                        };

                        _HTTPWebContext        = new HTTPContext(requestHeader, requestBody, responseHeader, _DataStream);
                        HTTPServer.HTTPContext = _HTTPWebContext;
                    }

                    #endregion

                    #region ... or process request and create a response header

                    else
                    {
                        responseHeader = new HTTPHeader()
                        {
                            HttpStatusCode = HTTPStatusCodes.OK,
                            ContentType    = new ContentType("text/html")
                        };

                        #region Create and set HTTPContext

                        _HTTPWebContext        = new HTTPContext(requestHeader, requestBody, responseHeader, _DataStream);
                        HTTPServer.HTTPContext = _HTTPWebContext;

                        #endregion

                        // Process request
                        try
                        {
                            // Get Callback
                            var parsedCallback = _Parser.GetCallback(_HTTPWebContext.RequestHeader.RawUrl, _HTTPWebContext.RequestHeader.HttpMethodString);

                            #region Check callback...

                            if (parsedCallback == null || parsedCallback.Item1 == null)
                            {
                                Debug.WriteLine("Could not find a valid handler for url: " + _HTTPWebContext.RequestHeader.RawUrl);
                                responseBodyBytes = Encoding.UTF8.GetBytes("Could not find a valid handler for url: " + _HTTPWebContext.RequestHeader.RawUrl);

                                _HTTPWebContext.ResponseHeader = new HTTPHeader()
                                {
                                    HttpStatusCode = HTTPStatusCodes.NotFound,
                                    ContentType    = new ContentType("text/plain"),
                                    ContentLength  = responseBodyBytes.ULongLength()
                                };

                                responseHeaderBytes = _HTTPWebContext.ResponseHeader.ToBytes();
                            }

                            #endregion

                            #region ...check authentication and invoke method callback

                            else
                            {
                                var authenticated = false;

                                #region Check HTTPSecurity

                                // the server switched on authentication AND the method does not explicit allow not authentication
                                if (HTTPSecurity != null && !(parsedCallback.Item1.NeedsExplicitAuthentication.HasValue && !parsedCallback.Item1.NeedsExplicitAuthentication.Value))
                                {
                                    #region Authentication

                                    //in this case the client is already been authenticated by his certificate
                                    if (HTTPSecurity.CredentialType == HttpClientCredentialType.Certificate)
                                    {
                                        authenticated = true;
                                    }

                                    if (HTTPSecurity.CredentialType == HttpClientCredentialType.Basic)
                                    {
                                        if (requestHeader.Authorization == null)
                                        {
                                            #region No authorisation info was sent

                                            responseHeader      = GetAuthenticationRequiredHeader();
                                            responseHeaderBytes = responseHeader.ToBytes();

                                            #endregion
                                        }
                                        else if (!Authorize(_HTTPWebContext.RequestHeader.Authorization))
                                        {
                                            #region Authorization failed

                                            responseHeader      = GetAuthenticationRequiredHeader();
                                            responseHeaderBytes = responseHeader.ToBytes();

                                            #endregion
                                        }
                                        else
                                        {
                                            authenticated = true;
                                        }
                                    }
                                    else
                                    {
                                        if (HTTPSecurity.CredentialType != HttpClientCredentialType.Certificate)
                                        {
                                            responseBodyBytes = Encoding.UTF8.GetBytes("Authentication other than Basic or Certificate currently not provided");
                                            responseHeader    = new HTTPHeader()
                                            {
                                                HttpStatusCode = HTTPStatusCodes.InternalServerError, ContentLength = responseBodyBytes.ULongLength()
                                            };
                                            responseHeaderBytes = responseHeader.ToBytes();

                                            Debug.WriteLine("------------------------------------------------------------");
                                            Debug.WriteLine("!!!Authentication other than Basic or Certificate currently not provided!!!");
                                        }
                                    }

                                    #endregion
                                }

                                else if (parsedCallback.Item1.NeedsExplicitAuthentication.HasValue && parsedCallback.Item1.NeedsExplicitAuthentication.Value)
                                {
                                    #region The server does not have authentication but the Interface explicitly needs authentication

                                    responseBodyBytes = Encoding.UTF8.GetBytes("Authentication not provided from server");
                                    responseHeader    = new HTTPHeader()
                                    {
                                        HttpStatusCode = HTTPStatusCodes.InternalServerError, ContentLength = responseBodyBytes.ULongLength()
                                    };
                                    responseHeaderBytes = responseHeader.ToBytes();

                                    #endregion

                                    Debug.WriteLine("---------------------------------------------");
                                    Debug.WriteLine("!!!Authentication not provided from server!!!");
                                }
                                else
                                {
                                    authenticated = true;
                                }

                                #endregion

                                if (authenticated)
                                {
                                    InvokeURL(parsedCallback, _HTTPWebContext, ref responseHeaderBytes, ref responseBodyBytes);
                                }
                            }

                            #endregion
                        }

                        #region Handle exceptions occurred during request processing

                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());

                            responseBodyBytes = Encoding.UTF8.GetBytes(ex.ToString());

                            responseHeader = new HTTPHeader()
                            {
                                HttpStatusCode = HTTPStatusCodes.InternalServerError,
                                ContentType    = new ContentType("text/plain"),
                                ContentLength  = responseBodyBytes.ULongLength()
                            };

                            responseHeaderBytes = responseHeader.ToBytes();

                            ExceptionThrowed(this, ex);

                            _LastException = ex;
                        }

                        #endregion
                    }

                    #endregion


                    #region Handle errors...

                    if ((Int32)responseHeader.HttpStatusCode >= 400 && (Int32)responseHeader.HttpStatusCode <= 599)
                    {
                        #region Handle custom error pages...

                        var _CustomErrorPage = _Instance as ICustomErrorPageHandler;

                        if (_CustomErrorPage != null)
                        {
                            responseBodyBytes            = _CustomErrorPage.GetCustomErrorPage(responseHeader.HttpStatusCode, _HTTPWebContext.RequestHeader, _HTTPWebContext.RequestBody, _LastException);
                            responseHeader.ContentLength = responseBodyBytes.ULongLength();
                            responseHeaderBytes          = responseHeader.ToBytes();
                        }

                        #endregion

                        #region ...or generate a generic errorpage!

                        else
                        {
                            var _StringBuilder = new StringBuilder();

                            _StringBuilder.AppendLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
                            _StringBuilder.AppendLine("<html>");
                            _StringBuilder.AppendLine("  <head>");
                            _StringBuilder.Append("    <title>").Append((Int32)responseHeader.HttpStatusCode).Append(" ").Append(HTTPHeader.HttpStatusCodeToSimpleString(responseHeader.HttpStatusCode)).AppendLine("</title>");
                            _StringBuilder.AppendLine("  </head>");
                            _StringBuilder.AppendLine("  <body>");
                            _StringBuilder.Append("    <h1>Error ").Append((Int32)responseHeader.HttpStatusCode).Append(" - ").Append(HTTPHeader.HttpStatusCodeToSimpleString(responseHeader.HttpStatusCode)).AppendLine("</h1>");
                            _StringBuilder.AppendLine("    Your client sent a request which led to an error!<br />");
                            _StringBuilder.AppendLine("  </body>");
                            _StringBuilder.AppendLine("</html>");
                            _StringBuilder.AppendLine();

                            responseBodyBytes            = Encoding.UTF8.GetBytes(_StringBuilder.ToString());
                            responseHeader.ContentLength = responseBodyBytes.ULongLength();
                            responseHeaderBytes          = responseHeader.ToBytes();
                        }

                        #endregion
                    }

                    #endregion

                    #region Send Response

                    // Remove HttpWebContext
                    HTTPServer.HTTPContext = null;

                    if (!_HTTPWebContext.StreamDataAvailable)
                    {
                        // The user did not write into the stream itself - we will add header and the invocation result
                        var BytesToSend = new Byte[responseBodyBytes.Length + responseHeaderBytes.Length];
                        Array.Copy(responseHeaderBytes, BytesToSend, responseHeaderBytes.Length);
                        Array.Copy(responseBodyBytes, 0, BytesToSend, responseHeaderBytes.Length, responseBodyBytes.Length);

                        _DataStream.Write(BytesToSend, 0, BytesToSend.Length);
                    }

                    #endregion
                }
                finally
                {
                    if (_DataStream != null)
                    {
                        _DataStream.Close();
                    }
                    if (TcpClientConnection != null)
                    {
                        TcpClientConnection.Close();
                    }
                }
            }

            #region Trace

            //System.Diagnostics.Trace.WriteLine("-------------------response started-------------------");
            //System.Diagnostics.Trace.Indent();
            //System.Diagnostics.Trace.WriteLine("responseHeader:");
            //System.Diagnostics.Trace.Indent();
            //System.Diagnostics.Trace.WriteLine(responseHeader.ToString());
            //System.Diagnostics.Trace.Unindent();
            //System.Diagnostics.Trace.WriteLine("responseBody:");
            //System.Diagnostics.Trace.Indent();
            //System.Diagnostics.Trace.WriteLine(Encoding.UTF8.GetString(responseBodyBytes));
            //System.Diagnostics.Trace.Unindent();
            //System.Diagnostics.Trace.Unindent();
            //System.Diagnostics.Trace.WriteLine("-----------------------------------------------------");

            #endregion

            return(true);
        }