]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_httpd.cpp
Tidy up strlens which are not required
[user/henk/code/inspircd.git] / src / modules / m_httpd.cpp
index 8bfe7c6fe07aeee04fd50e4fac944e62c16a696b..189a80b8971788c203ea9a371f2f655dbb94fec2 100644 (file)
@@ -1,4 +1,4 @@
-/*       +------------------------------------+
+/*       +------------------------------------+       
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
 
 using namespace std;
 
-#include <stdio.h>
-#include "users.h"
-#include "channels.h"
+#include <algorithm>
 #include "modules.h"
-#include "inspsocket.h"
 #include "inspircd.h"
 #include "httpd.h"
 
@@ -31,6 +28,8 @@ class ModuleHttp;
 static ModuleHttp* HttpModule;
 static bool claimed;
 
+/** HTTP socket states
+ */
 enum HttpState
 {
        HTTP_LISTEN = 0,
@@ -39,6 +38,30 @@ enum HttpState
        HTTP_SERVE_SEND_DATA = 3
 };
 
+class HttpSocket;
+
+/** This class is used to handle HTTP socket timeouts
+ */
+class HTTPTimeout : public InspTimer
+{
+ private:
+       /** HttpSocket we are attached to
+        */
+       HttpSocket* s;
+       /** Socketengine the file descriptor is in
+        */
+       SocketEngine* SE;
+ public:
+       /** Attach timeout to HttpSocket
+        */
+       HTTPTimeout(HttpSocket* sock, SocketEngine* engine);
+       /** Handle timer tick
+        */
+       void Tick(time_t TIME);
+};
+
+/** A socket used for HTTP transport
+ */
 class HttpSocket : public InspSocket
 {
        FileReader* index;
@@ -49,7 +72,7 @@ class HttpSocket : public InspSocket
        std::string uri;
        std::string http_version;
        unsigned int postsize;
-       unsigned int amount;
+       HTTPTimeout* Timeout;
 
  public:
 
@@ -57,11 +80,29 @@ class HttpSocket : public InspSocket
        {
                SI->Log(DEBUG,"HttpSocket constructor");
                InternalState = HTTP_LISTEN;
+               Timeout = NULL;
        }
 
        HttpSocket(InspIRCd* SI, int newfd, char* ip, FileReader* ind) : InspSocket(SI, newfd, ip), index(ind), postsize(0)
        {
                InternalState = HTTP_SERVE_WAIT_REQUEST;
+               Timeout = new HTTPTimeout(this, Instance->SE);
+               Instance->Timers->AddTimer(Timeout);
+       }
+
+       FileReader* GetIndex()
+       {
+               return index;
+       }
+
+       ~HttpSocket()
+       {
+               if (Instance->Time() < Timeout->GetTimer())
+               {
+                       if (Timeout)
+                               Instance->Timers->DelTimer(Timeout);
+                       Timeout = NULL;
+               }
        }
 
        virtual int OnIncomingConnection(int newsock, char* ip)
@@ -172,7 +213,7 @@ class HttpSocket : public InspSocket
        void SendHeaders(unsigned long size, int response, const std::string &extraheaders)
        {
                time_t local = this->Instance->Time();
-               struct tm *timeinfo = localtime(&local);
+               struct tm *timeinfo = gmtime(&local);
                this->Write("HTTP/1.1 "+ConvToStr(response)+" "+Response(response)+"\r\nDate: ");
                this->Write(asctime(timeinfo));
                if (extraheaders.empty())
@@ -203,13 +244,15 @@ class HttpSocket : public InspSocket
                                        headers >> request_type;
                                        headers >> uri;
                                        headers >> http_version;
+
+                                       std::transform(request_type.begin(), request_type.end(), request_type.begin(), ::toupper);
+                                       std::transform(http_version.begin(), http_version.end(), http_version.begin(), ::toupper);
                                }
 
                                if ((InternalState == HTTP_SERVE_WAIT_REQUEST) && (request_type == "POST"))
                                {
                                        /* Do we need to fetch postdata? */
                                        postdata = "";
-                                       amount = 0;
                                        InternalState = HTTP_SERVE_RECV_POSTDATA;
                                        std::string header_item;
                                        while (headers >> header_item)
@@ -224,13 +267,16 @@ class HttpSocket : public InspSocket
                                        {
                                                InternalState = HTTP_SERVE_SEND_DATA;
                                                SendHeaders(0, 400, "");
+                                               Timeout = new HTTPTimeout(this, Instance->SE);
+                                               Instance->Timers->AddTimer(Timeout);
                                        }
                                        else
                                        {
                                                Instance->Log(DEBUG,"%d bytes to read for POST",postsize);
                                                std::string::size_type x = headers.str().find("\r\n\r\n");
-                                               postdata = headers.str().substr(x+5, headers.str().length());
+                                               postdata = headers.str().substr(x+4, headers.str().length());
                                                /* Get content length and store */
+                                               Instance->Log(DEBUG,"Initial postdata: '%s'", postdata.c_str());
                                                if (postdata.length() >= postsize)
                                                        ServeData();
                                        }
@@ -238,9 +284,8 @@ class HttpSocket : public InspSocket
                                else if (InternalState == HTTP_SERVE_RECV_POSTDATA)
                                {
                                        /* Add postdata, once we have it all, send the event */
-                                       amount += strlen(data);
                                        postdata.append(data);
-                                       if (amount >= postsize)
+                                       if (postdata.length() >= postsize)
                                                ServeData();
                                }
                                else
@@ -261,6 +306,9 @@ class HttpSocket : public InspSocket
        {
                /* Headers are complete */
                InternalState = HTTP_SERVE_SEND_DATA;
+
+               Instance->Timers->DelTimer(Timeout);
+               Timeout = NULL;
        
                if ((http_version != "HTTP/1.1") && (http_version != "HTTP/1.0"))
                {
@@ -286,6 +334,8 @@ class HttpSocket : public InspSocket
                                }
                        }
                }
+               Timeout = new HTTPTimeout(this, Instance->SE);
+               Instance->Timers->AddTimer(Timeout);
        }
 
        void Page(std::stringstream* n, int response, std::string& extraheaders)
@@ -296,45 +346,49 @@ class HttpSocket : public InspSocket
        }
 };
 
-class ModuleHttp : public Module
+HTTPTimeout::HTTPTimeout(HttpSocket* sock, SocketEngine* engine) : InspTimer(60, time(NULL)), s(sock), SE(engine)
 {
-       int port;
-       std::string host;
-       std::string bindip;
-       std::string indexfile;
-
-       FileReader* index;
+}
 
-       HttpSocket* http;
+void HTTPTimeout::Tick(time_t TIME)
+{
+       SE->DelFd(s);
+       s->Close();
+       delete s;
+}
 
+class ModuleHttp : public Module
+{
+       std::vector<HttpSocket*> httpsocks;
  public:
 
        void ReadConfig()
        {
+               int port;
+               std::string host;
+               std::string bindip;
+               std::string indexfile;
+               FileReader* index;
+               HttpSocket* http;
                ConfigReader c(ServerInstance);
-               this->host = c.ReadValue("http", "host", 0);
-               this->bindip = c.ReadValue("http", "ip", 0);
-               this->port = c.ReadInteger("http", "port", 0, true);
-               this->indexfile = c.ReadValue("http", "index", 0);
 
-               if (index)
+               httpsocks.clear();
+
+               for (int i = 0; i < c.Enumerate("http"); i++)
                {
-                       delete index;
-                       index = NULL;
+                       host = c.ReadValue("http", "host", i);
+                       bindip = c.ReadValue("http", "ip", i);
+                       port = c.ReadInteger("http", "port", i, true);
+                       indexfile = c.ReadValue("http", "index", i);
+                       index = new FileReader(ServerInstance, indexfile);
+                       http = new HttpSocket(ServerInstance, bindip, port, true, 0, index);
+                       httpsocks.push_back(http);
                }
-               index = new FileReader(ServerInstance, this->indexfile);
-       }
-
-       void CreateListener()
-       {
-               http = new HttpSocket(ServerInstance, this->bindip, this->port, true, 0, index);
        }
 
        ModuleHttp(InspIRCd* Me) : Module::Module(Me)
        {
-               index = NULL;
                ReadConfig();
-               CreateListener();
        }
 
        void OnEvent(Event* event)
@@ -358,12 +412,17 @@ class ModuleHttp : public Module
 
        virtual ~ModuleHttp()
        {
-               ServerInstance->SE->DelFd(http);
+               for (size_t i = 0; i < httpsocks.size(); i++)
+               {
+                       ServerInstance->SE->DelFd(httpsocks[i]);
+                       delete httpsocks[i]->GetIndex();
+                       delete httpsocks[i];
+               }
        }
 
        virtual Version GetVersion()
        {
-               return Version(1,0,0,0,VF_STATIC|VF_VENDOR|VF_SERVICEPROVIDER);
+               return Version(1,0,0,0,VF_VENDOR|VF_SERVICEPROVIDER,API_VERSION);
        }
 };