]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_httpd.cpp
Kill ListenSocketBase, use OnAcceptConnection for all new connections
[user/henk/code/inspircd.git] / src / modules / m_httpd.cpp
index 209a71cb01adb06f76476a04544fe0b36944303e..7fc342e04c2ee521e63e9f355cbbef3beeb1f529 100644 (file)
@@ -2,8 +2,8 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
+ *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
  *
  * This program is free but copyrighted software; see
  *            the file COPYING for details.
@@ -26,18 +26,17 @@ static bool claimed;
  */
 enum HttpState
 {
-       HTTP_LISTEN = 0,
-       HTTP_SERVE_WAIT_REQUEST = 1, /* Waiting for a full request */
-       HTTP_SERVE_RECV_POSTDATA = 2, /* Waiting to finish recieving POST data */
-       HTTP_SERVE_SEND_DATA = 3 /* Sending response */
+       HTTP_SERVE_WAIT_REQUEST = 0, /* Waiting for a full request */
+       HTTP_SERVE_RECV_POSTDATA = 1, /* Waiting to finish recieving POST data */
+       HTTP_SERVE_SEND_DATA = 2 /* Sending response */
 };
 
 /** A socket used for HTTP transport
  */
 class HttpServerSocket : public BufferedSocket
 {
-       FileReader* index;
        HttpState InternalState;
+       std::string ip;
 
        HTTPHeaders headers;
        std::string reqbuffer;
@@ -49,35 +48,17 @@ class HttpServerSocket : public BufferedSocket
 
  public:
 
-       HttpServerSocket(InspIRCd* SI, std::string shost, int iport, bool listening, unsigned long maxtime, FileReader* index_page) : BufferedSocket(SI, shost, iport, listening, maxtime), index(index_page), postsize(0)
-       {
-               InternalState = HTTP_LISTEN;
-       }
-
-       HttpServerSocket(InspIRCd* SI, int newfd, char* ip, FileReader* ind) : BufferedSocket(SI, newfd, ip), index(ind), postsize(0)
+       HttpServerSocket(int newfd, const std::string& IP, ListenSocket* via, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
+               : BufferedSocket(newfd), ip(IP), postsize(0)
        {
                InternalState = HTTP_SERVE_WAIT_REQUEST;
-       }
-
-       FileReader* GetIndex()
-       {
-               return index;
-       }
-
-       ~HttpServerSocket()
-       {
-       }
 
-       virtual int OnIncomingConnection(int newsock, char* ip)
-       {
-               if (InternalState == HTTP_LISTEN)
-               {
-                       new HttpServerSocket(this->Instance, newsock, ip, index);
-               }
-               return true;
+               FOREACH_MOD(I_OnHookIO, OnHookIO(this, via));
+               if (GetIOHook())
+                       GetIOHook()->OnStreamSocketAccept(this, client, server);
        }
 
-       virtual void OnClose()
+       virtual void OnError(BufferedSocketError)
        {
        }
 
@@ -179,16 +160,15 @@ class HttpServerSocket : public BufferedSocket
                                   "<small>Powered by <a href='http://www.inspircd.org'>InspIRCd</a></small></body></html>";
 
                SendHeaders(data.length(), response, empty);
-               this->Write(data);
-               this->FlushWriteBuffer();
+               WriteData(data);
        }
 
        void SendHeaders(unsigned long size, int response, HTTPHeaders &rheaders)
        {
 
-               this->Write(http_version + " "+ConvToStr(response)+" "+Response(response)+"\r\n");
+               WriteData(http_version + " "+ConvToStr(response)+" "+Response(response)+"\r\n");
 
-               time_t local = this->Instance->Time();
+               time_t local = ServerInstance->Time();
                struct tm *timeinfo = gmtime(&local);
                char *date = asctime(timeinfo);
                date[strlen(date) - 1] = '\0';
@@ -207,40 +187,32 @@ class HttpServerSocket : public BufferedSocket
                 */
                rheaders.SetHeader("Connection", "Close");
 
-               this->Write(rheaders.GetFormattedHeaders());
-               this->Write("\r\n");
+               WriteData(rheaders.GetFormattedHeaders());
+               WriteData("\r\n");
        }
 
-       virtual bool OnDataReady()
+       void OnDataReady()
        {
-               const char* data = this->Read();
-
-               /* Check that the data read is a valid pointer and it has some content */
-               if (!data || !*data)
-                       return false;
-
                if (InternalState == HTTP_SERVE_RECV_POSTDATA)
                {
-                       postdata.append(data);
+                       postdata.append(recvq);
                        if (postdata.length() >= postsize)
                                ServeData();
                }
                else
                {
-                       reqbuffer.append(data);
+                       reqbuffer.append(recvq);
 
                        if (reqbuffer.length() >= 8192)
                        {
-                               Instance->Logs->Log("m_httpd",DEBUG, "m_httpd dropped connection due to an oversized request buffer");
+                               ServerInstance->Logs->Log("m_httpd",DEBUG, "m_httpd dropped connection due to an oversized request buffer");
                                reqbuffer.clear();
-                               return false;
+                               SetError("Buffer");
                        }
 
                        if (InternalState == HTTP_SERVE_WAIT_REQUEST)
                                CheckRequestBuffer();
                }
-
-               return true;
        }
 
        void CheckRequestBuffer()
@@ -266,7 +238,6 @@ class HttpServerSocket : public BufferedSocket
                                if (request_type.empty() || uri.empty() || http_version.empty())
                                {
                                        SendHTTPError(400);
-                                       SetWrite();
                                        return;
                                }
 
@@ -280,7 +251,6 @@ class HttpServerSocket : public BufferedSocket
                        if ((fieldsep == std::string::npos) || (fieldsep == 0) || (fieldsep == cheader.length() - 1))
                        {
                                SendHTTPError(400);
-                               SetWrite();
                                return;
                        }
 
@@ -297,7 +267,6 @@ class HttpServerSocket : public BufferedSocket
                if ((http_version != "HTTP/1.1") && (http_version != "HTTP/1.0"))
                {
                        SendHTTPError(505);
-                       SetWrite();
                        return;
                }
 
@@ -329,102 +298,54 @@ class HttpServerSocket : public BufferedSocket
        {
                InternalState = HTTP_SERVE_SEND_DATA;
 
-               if ((request_type == "GET") && (uri == "/"))
+               claimed = false;
+               HTTPRequest acl((Module*)HttpModule, "httpd_acl", request_type, uri, &headers, this, ip, postdata);
+               acl.Send();
+               if (!claimed)
                {
-                       HTTPHeaders empty;
-                       SendHeaders(index->ContentSize(), 200, empty);
-                       this->Write(index->Contents());
-                       this->FlushWriteBuffer();
-                       SetWrite();
-               }
-               else
-               {
-                       claimed = false;
-                       HTTPRequest httpr(request_type,uri,&headers,this,this->GetIP(),postdata);
-                       Event acl((char*)&httpr, (Module*)HttpModule, "httpd_acl");
-                       acl.Send(this->Instance);
+                       HTTPRequest url((Module*)HttpModule, "httpd_url", request_type, uri, &headers, this, ip, postdata);
+                       url.Send();
                        if (!claimed)
                        {
-                               Event e((char*)&httpr, (Module*)HttpModule, "httpd_url");
-                               e.Send(this->Instance);
-                               if (!claimed)
-                               {
-                                       SendHTTPError(404);
-                                       SetWrite();
-                               }
+                               SendHTTPError(404);
                        }
                }
        }
 
-
-       bool OnWriteReady()
-       {
-               Instance->Logs->Log("m_httpd",DEBUG,"OnWriteReady()");
-               return false;
-       }
-
        void Page(std::stringstream* n, int response, HTTPHeaders *hheaders)
        {
                SendHeaders(n->str().length(), response, *hheaders);
-               this->Write(n->str());
-               this->FlushWriteBuffer();
-               SetWrite();
-       }
-
-       void SetWrite()
-       {
-               Instance->Logs->Log("m_httpd",DEBUG,"SetWrite()");
-               this->WaitingForWriteEvent = true;
-               Instance->SE->WantWrite(this);
+               WriteData(n->str());
        }
 };
 
 class ModuleHttpServer : public Module
 {
-       std::vector<HttpServerSocket*> httpsocks;
+       std::vector<HttpServerSocket *> httpsocks;
  public:
 
-       void ReadConfig()
-       {
-               int port;
-               std::string host;
-               std::string bindip;
-               std::string indexfile;
-               FileReader* index;
-               HttpServerSocket* http;
-               ConfigReader c(ServerInstance);
-
-               httpsocks.clear();
-
-               for (int i = 0; i < c.Enumerate("http"); i++)
-               {
-                       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);
-                       if (!index->Exists())
-                               throw ModuleException("Can't read index file: "+indexfile);
-                       http = new HttpServerSocket(ServerInstance, bindip, port, true, 0, index);
-                       httpsocks.push_back(http);
-               }
+       ModuleHttpServer()      {
+               HttpModule = this;
        }
 
-       ModuleHttpServer(InspIRCd* Me) : Module(Me)
+       void OnRequest(Request& request)
        {
-               ReadConfig();
-               HttpModule = this;
-               Implementation eventlist[] = { I_OnRequest };
-               ServerInstance->Modules->Attach(eventlist, this, 1);
+               if (strcmp(request.id, "HTTP-DOC") != 0)
+                       return;
+               HTTPDocumentResponse& resp = static_cast<HTTPDocumentResponse&>(request);
+               claimed = true;
+               resp.src.sock->Page(resp.document, resp.responsecode, &resp.headers);
        }
 
-       virtual const char* OnRequest(Request* request)
+       ModResult OnAcceptConnection(int nfd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
        {
-               claimed = true;
-               HTTPDocument* doc = (HTTPDocument*)request->GetData();
-               HttpServerSocket* sock = (HttpServerSocket*)doc->sock;
-               sock->Page(doc->GetDocument(), doc->GetResponseCode(), &doc->headers);
-               return NULL;
+               if (from->bind_tag->getString("type") != "httpd");
+                       return MOD_RES_PASSTHRU;
+               int port;
+               std::string incomingip;
+               irc::sockets::satoap(client, incomingip, port);
+               new HttpServerSocket(nfd, incomingip, from, client, server);
+               return MOD_RES_ALLOW;
        }
 
 
@@ -432,16 +353,14 @@ class ModuleHttpServer : public Module
        {
                for (size_t i = 0; i < httpsocks.size(); i++)
                {
-                       ServerInstance->SE->DelFd(httpsocks[i]);
-                       httpsocks[i]->Close();
-                       delete httpsocks[i]->GetIndex();
+                       httpsocks[i]->cull();
+                       delete httpsocks[i];
                }
-               ServerInstance->BufferedSocketCull();
        }
 
        virtual Version GetVersion()
        {
-               return Version("$Id$", VF_VENDOR | VF_SERVICEPROVIDER, API_VERSION);
+               return Version("Provides HTTP serving facilities to modules", VF_VENDOR);
        }
 };