Exemple #1
0
        static void Main()
        {
            Server server = new Server(null, 9000, false, RequestReceived, true);

            bool runForever = true;

            while (runForever)
            {
                string userInput = WatsonCommon.InputString("Command [? for help] >", null, false);
                switch (userInput.ToLower())
                {
                case "?":
                    Menu();
                    break;

                case "q":
                    runForever = false;
                    break;

                case "c":
                case "cls":
                    Console.Clear();
                    break;

                case "state":
                    Console.WriteLine("Listening: " + server.IsListening);
                    break;

                case "dispose":
                    server.Dispose();
                    break;
                }
            }
        }
Exemple #2
0
        static HttpResponse RequestHandler(HttpRequest req)
        {
            Console.WriteLine(req.Method + " " + req.RawUrlWithoutQuery);

            FileStream fs = null;

            try
            {
                switch (req.Method)
                {
                case HttpMethod.GET:
                    long len = new System.IO.FileInfo("watson.jpg").Length;
                    fs = new FileStream("watson.jpg", FileMode.Open, FileAccess.Read);
                    return(new HttpResponse(req, 200, null, "image/jpeg", len, fs));

                case HttpMethod.POST:
                    if (req.RawUrlEntries == null || req.RawUrlEntries.Count != 1)
                    {
                        return(new HttpResponse(req, 400, null, "text/plain", Encoding.UTF8.GetBytes("Bad request")));
                    }
                    else if (req.DataStream == null || !req.DataStream.CanRead)
                    {
                        return(new HttpResponse(req, 400, null, "text/plain", Encoding.UTF8.GetBytes("Bad request")));
                    }
                    else
                    {
                        fs = new FileStream(_Directory + "/" + req.RawUrlEntries[0], FileMode.OpenOrCreate);
                        int    bytesRead = 0;
                        byte[] buffer    = new byte[2048];
                        while ((bytesRead = req.DataStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            fs.Write(buffer, 0, bytesRead);
                        }
                        fs.Close();
                        fs.Dispose();
                        return(new HttpResponse(req, 201, null, "text/plain", null));
                    }

                default:
                    return(new HttpResponse(req, 400, null, "text/plain", Encoding.UTF8.GetBytes("Bad request")));
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(WatsonCommon.SerializeJson(e));
                return(new HttpResponse(req, 500, null, "text/plain", Encoding.UTF8.GetBytes("Internal server error")));
            }
            finally
            {
            }
        }
Exemple #3
0
        static void Main()
        {
            List <string> hostnames = new List <string>();

            hostnames.Add("127.0.0.1");

            Server server = new Server(hostnames, 9000, false, RequestReceived);

            // server.AccessControl.Mode = AccessControlMode.DefaultDeny;
            // server.AccessControl.Whitelist.Add("127.0.0.1", "255.255.255.255");
            // server.AccessControl.Whitelist.Add("127.0.0.1", "255.255.255.255");

            bool runForever = true;

            while (runForever)
            {
                string userInput = WatsonCommon.InputString("Command [? for help] >", null, false);
                switch (userInput.ToLower())
                {
                case "?":
                    Menu();
                    break;

                case "q":
                    runForever = false;
                    break;

                case "c":
                case "cls":
                    Console.Clear();
                    break;

                case "state":
                    Console.WriteLine("Listening: " + server.IsListening);
                    break;

                case "dispose":
                    server.Dispose();
                    break;
                }
            }
        }
Exemple #4
0
        static HttpResponse RequestHandler(HttpRequest req)
        {
            DateTime     startTime = DateTime.Now;
            HttpResponse resp      = null;
            bool         connAdded = false;

            try
            {
                #region Unauthenticated-APIs

                switch (req.Method)
                {
                case HttpMethod.GET:
                    if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/loopback", false))
                    {
                        resp = new HttpResponse(req, true, 200, null, "application/json", "Hello from CryptoServer!", false);
                        return(resp);
                    }
                    break;

                case HttpMethod.PUT:
                case HttpMethod.POST:
                case HttpMethod.DELETE:
                default:
                    break;
                }

                #endregion

                #region Add-to-Connection-List

                _Connections.Add(Thread.CurrentThread.ManagedThreadId, req);
                connAdded = true;

                #endregion

                #region APIs

                if (!String.IsNullOrEmpty(req.RetrieveHeaderValue(_Settings.Auth.ApiKeyHeader)))
                {
                    if (req.RetrieveHeaderValue(_Settings.Auth.ApiKeyHeader).Equals(_Settings.Auth.AdminApiKey))
                    {
                        #region Admin-API-Key

                        _Logging.Log(LoggingModule.Severity.Info, "RequestHandler use of admin API key detected for: " + req.RawUrlWithoutQuery);

                        switch (req.Method)
                        {
                        case HttpMethod.GET:
                            if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_cryptoserver/connections", false))
                            {
                                resp = new HttpResponse(req, true, 200, null, "application/json", _Connections.GetActiveConnections(), false);
                                return(resp);
                            }

                            if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_cryptoserver/config", false))
                            {
                                resp = new HttpResponse(req, true, 200, null, "application/json", _Settings, false);
                                return(resp);
                            }

                            break;

                        case HttpMethod.PUT:
                        case HttpMethod.POST:
                        case HttpMethod.DELETE:
                        default:
                            break;
                        }

                        _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unknown admin API endpoint: " + req.RawUrlWithoutQuery);
                        resp = new HttpResponse(req, false, 400, null, "application/json", "Unknown API endpoint or verb", false);
                        return(resp);

                        #endregion
                    }
                    else if (req.RetrieveHeaderValue(_Settings.Auth.ApiKeyHeader).Equals(_Settings.Auth.CryptoApiKey))
                    {
                        #region Crypto-API-Key

                        string failureReason;
                        byte[] responseData;
                        Obj    responseObj;

                        switch (req.Method)
                        {
                        case HttpMethod.POST:
                            if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/decrypt", false))
                            {
                                Obj reqObj = Common.DeserializeJson <Obj>(req.Data);
                                if (!_Crypto.Decrypt(reqObj, out responseData, out failureReason))
                                {
                                    _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unable to decrypt: " + failureReason);
                                    resp = new HttpResponse(req, false, 500, null, "application/json", failureReason, false);
                                    return(resp);
                                }
                                else
                                {
                                    _Logging.Log(LoggingModule.Severity.Debug, "RequestHandler encrypt returning " + responseData.Length + " bytes");
                                    resp = new HttpResponse(req, true, 200, null, "application/octet-stream", responseData, true);
                                    return(resp);
                                }
                            }

                            if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/encrypt", false))
                            {
                                if (!_Crypto.Encrypt(req.Data, out responseObj, out failureReason))
                                {
                                    _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unable to encrypt: " + failureReason);
                                    resp = new HttpResponse(req, false, 500, null, "application/json", failureReason, false);
                                    return(resp);
                                }
                                else
                                {
                                    resp = new HttpResponse(req, true, 200, null, "application/json", Common.SerializeJson(responseObj), true);
                                    return(resp);
                                }
                            }

                            break;

                        case HttpMethod.GET:
                        case HttpMethod.PUT:
                        case HttpMethod.DELETE:
                        default:
                            break;
                        }

                        _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unknown crypto API endpoint: " + req.RawUrlWithoutQuery);
                        resp = new HttpResponse(req, false, 400, null, "application/json", "Unknown API endpoint or verb", false);
                        return(resp);

                        #endregion
                    }
                    else
                    {
                        #region Invalid-Auth-Material

                        _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler invalid API key supplied: " + req.RetrieveHeaderValue(_Settings.Auth.ApiKeyHeader));
                        resp = new HttpResponse(req, false, 401, null, "application/json", "Invalid API key", false);
                        return(resp);

                        #endregion
                    }
                }

                resp = new HttpResponse(req, false, 401, null, "application/json", "No authentication material", false);
                return(resp);

                #endregion
            }
            catch (Exception e)
            {
                _Logging.LogException("CryptoServer", "RequestHandler", e);
                resp = new HttpResponse(req, false, 500, null, "application/json", "Internal server error", false);
                return(resp);
            }
            finally
            {
                if (resp != null)
                {
                    string message = "RequestHandler " + req.SourceIp + ":" + req.SourcePort + " " + req.Method + " " + req.RawUrlWithoutQuery;
                    message += " " + resp.StatusCode + " " + Common.TotalMsFrom(startTime) + "ms";
                    _Logging.Log(LoggingModule.Severity.Debug, message);
                }

                if (connAdded)
                {
                    _Connections.Close(Thread.CurrentThread.ManagedThreadId);
                }
            }
        }
Exemple #5
0
 static HttpResponse DefaultRoute(HttpRequest req)
 {
     return(ResponseBuilder(req, WatsonCommon.SerializeJson(req)));
 }
Exemple #6
0
        static HttpResponse RequestHandler(HttpRequest req)
        {
            DateTime     startTime = DateTime.Now;
            HttpResponse resp      = null;
            Host         currHost  = null;
            Node         currNode  = null;
            string       hostKey   = null;
            bool         connAdded = false;

            try
            {
                #region Unauthenticated-APIs

                switch (req.Method)
                {
                case HttpMethod.GET:
                    if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_loadbalancer/loopback", false))
                    {
                        resp = new HttpResponse(req, true, 200, null, "application/json", "Hello from LoadBalancer!", false);
                        return(resp);
                    }
                    break;

                case HttpMethod.PUT:
                case HttpMethod.POST:
                case HttpMethod.DELETE:
                default:
                    break;
                }

                #endregion

                #region Add-to-Connection-List

                _Connections.Add(Thread.CurrentThread.ManagedThreadId, req);
                connAdded = true;

                #endregion

                #region Authenticate-and-Admin-APIs

                if (!String.IsNullOrEmpty(req.RetrieveHeaderValue(_Settings.Auth.AdminApiKeyHeader)))
                {
                    if (req.RetrieveHeaderValue(_Settings.Auth.AdminApiKeyHeader).Equals(_Settings.Auth.AdminApiKey))
                    {
                        #region Admin-APIs

                        _Logging.Log(LoggingModule.Severity.Info, "RequestHandler use of admin API key detected for: " + req.RawUrlWithoutQuery);

                        switch (req.Method)
                        {
                        case HttpMethod.GET:
                            if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_loadbalancer/connections", false))
                            {
                                resp = new HttpResponse(req, true, 200, null, "application/json", _Connections.GetActiveConnections(), false);
                                return(resp);
                            }

                            if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_loadbalancer/config", false))
                            {
                                resp = new HttpResponse(req, true, 200, null, "application/json", _Settings, false);
                                return(resp);
                            }

                            if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_loadbalancer/hosts", false))
                            {
                                resp = new HttpResponse(req, true, 200, null, "application/json", _Hosts.Get(), false);
                                return(resp);
                            }
                            break;

                        case HttpMethod.PUT:
                        case HttpMethod.POST:
                        case HttpMethod.DELETE:
                        default:
                            break;
                        }

                        _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unknown admin API endpoint: " + req.RawUrlWithoutQuery);
                        resp = new HttpResponse(req, false, 400, null, "application/json", "Unknown API endpoint or verb", false);
                        return(resp);

                        #endregion
                    }
                    else
                    {
                        #region Failed-Auth

                        _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler invalid admin API key supplied: " + req.RetrieveHeaderValue(_Settings.Auth.AdminApiKeyHeader));
                        resp = new HttpResponse(req, false, 401, null, "application/json", "Authentication failed", false);
                        return(resp);

                        #endregion
                    }
                }

                #endregion

                #region Find-Host-and-Node

                if (req.Headers.ContainsKey("Host"))
                {
                    hostKey = req.RetrieveHeaderValue("Host");
                }

                if (String.IsNullOrEmpty(hostKey))
                {
                    _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler no host header supplied for " + req.SourceIp + ":" + req.SourceIp + " " + req.Method + " " + req.RawUrlWithoutQuery);
                    resp = new HttpResponse(req, false, 400, null, "application/json", "No host header supplied", false);
                    return(resp);
                }

                if (!_Hosts.SelectNodeForHost(hostKey, out currHost, out currNode))
                {
                    _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler host or node not found for " + req.SourceIp + ":" + req.SourceIp + " " + req.Method + " " + req.RawUrlWithoutQuery);
                    resp = new HttpResponse(req, false, 400, null, "application/json", "Host or node not found", false);
                    return(resp);
                }
                else
                {
                    if (currHost == null || currHost == default(Host))
                    {
                        _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler host not found for " + req.SourceIp + ":" + req.SourceIp + " " + req.Method + " " + req.RawUrlWithoutQuery);
                        resp = new HttpResponse(req, false, 400, null, "application/json", "Host not found", false);
                        return(resp);
                    }

                    if (currNode == null || currNode == default(Node))
                    {
                        _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler node not found for " + req.SourceIp + ":" + req.SourceIp + " " + req.Method + " " + req.RawUrlWithoutQuery);
                        resp = new HttpResponse(req, false, 400, null, "application/json", "No node found for host", false);
                        return(resp);
                    }

                    _Connections.Update(Thread.CurrentThread.ManagedThreadId, hostKey, currHost.Name, currNode.Hostname);
                }

                #endregion

                #region Process-Connection

                if (currHost.HandlingMode == HandlingMode.Redirect)
                {
                    #region Redirect

                    string redirectUrl = BuildProxyUrl(currNode, req);

                    // add host header
                    Dictionary <string, string> requestHeaders = new Dictionary <string, string>();

                    // add other headers
                    if (req.Headers != null && req.Headers.Count > 0)
                    {
                        List <string> matchHeaders = new List <string> {
                            "host", "connection", "user-agent"
                        };

                        foreach (KeyValuePair <string, string> currHeader in req.Headers)
                        {
                            if (matchHeaders.Contains(currHeader.Key.ToLower().Trim()))
                            {
                                continue;
                            }
                            else
                            {
                                requestHeaders.Add(currHeader.Key, currHeader.Value);
                            }
                        }
                    }

                    // process REST request
                    RestResponse restResp = RestRequest.SendRequestSafe(
                        redirectUrl,
                        req.ContentType,
                        req.Method.ToString(),
                        null, null, false,
                        Common.IsTrue(currHost.AcceptInvalidCerts),
                        requestHeaders,
                        req.Data);

                    if (restResp == null)
                    {
                        _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler null proxy response from " + redirectUrl);
                        resp = new HttpResponse(req, false, 500, null, "application/json", "Unable to contact node", false);
                        return(resp);
                    }
                    else
                    {
                        resp = new HttpResponse(req, true, restResp.StatusCode, restResp.Headers, restResp.ContentType, restResp.Data, true);
                        return(resp);
                    }

                    #endregion
                }
                else if (currHost.HandlingMode == HandlingMode.Proxy)
                {
                    #region Proxy

                    string redirectUrl = BuildProxyUrl(currNode, req);

                    Dictionary <string, string> redirectHeaders = new Dictionary <string, string>();
                    redirectHeaders.Add("location", redirectUrl);

                    resp = new HttpResponse(req, true, _Settings.RedirectStatusCode, redirectHeaders, "text/plain", _Settings.RedirectStatusString, true);
                    return(resp);

                    #endregion
                }
                else
                {
                    #region Unknown-Handling-Mode

                    _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler invalid handling mode " + currHost.HandlingMode + " for host " + currHost.Name);
                    resp = new HttpResponse(req, false, 500, null, "application/json", "Invalid handling mode '" + currHost.HandlingMode + "'", false);
                    return(resp);

                    #endregion
                }

                #endregion
            }
            catch (Exception e)
            {
                _Logging.LogException("LoadBalancer", "RequestHandler", e);
                resp = new HttpResponse(req, false, 500, null, "application/json", "Internal server error", false);
                return(resp);
            }
            finally
            {
                if (resp != null)
                {
                    string message = "RequestHandler " + req.SourceIp + ":" + req.SourcePort + " " + req.Method + " " + req.RawUrlWithoutQuery;
                    if (currNode != null)
                    {
                        message += " " + hostKey + " to " + currNode.Hostname + ":" + currNode.Port + " " + currHost.HandlingMode;
                    }
                    message += " " + resp.StatusCode + " " + Common.TotalMsFrom(startTime) + "ms";
                    _Logging.Log(LoggingModule.Severity.Debug, message);
                }

                if (connAdded)
                {
                    _Connections.Close(Thread.CurrentThread.ManagedThreadId);
                }
            }
        }