]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_http_client.cpp
Header update: 2007 -> 2008
[user/henk/code/inspircd.git] / src / modules / m_http_client.cpp
index 7e1b94f11f04f36eb784931bc6583cfa0dc5a19f..a2a6d9014db8fe4199df4a4a79be3b942796c2da 100644 (file)
@@ -2,7 +2,7 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
  * See: http://www.inspircd.org/wiki/index.php/Credits
  *
  * This program is free but copyrighted software; see
@@ -24,7 +24,7 @@ class URL
        int port;
 };
 
-class HTTPSocket : public InspSocket
+class HTTPSocket : public BufferedSocket
 {
  private:
        InspIRCd *Server;
@@ -35,6 +35,7 @@ class HTTPSocket : public InspSocket
        enum { HTTP_CLOSED, HTTP_REQSENT, HTTP_HEADERS, HTTP_DATA } status;
        std::string data;
        std::string buffer;
+       bool closed;
 
  public:
        HTTPSocket(InspIRCd *Instance, class ModuleHTTPClient *Mod);
@@ -51,20 +52,27 @@ class HTTPResolver : public Resolver
 {
  private:
        HTTPSocket *socket;
+       std::string orig;
  public:
-       HTTPResolver(HTTPSocket *socket, InspIRCd *Instance, const string &hostname, bool &cached, Module* me) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, cached, me), socket(socket)
+       HTTPResolver(HTTPSocket *s, InspIRCd *Instance, const string &hostname, bool &cached, Module* me) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, cached, me), socket(s)
        {
+               ServerInstance->Log(DEBUG,">>>>>>>>>>>>>>>>>> HTTPResolver::HTTPResolver <<<<<<<<<<<<<<<");
+               orig = hostname;
        }
        
        void OnLookupComplete(const string &result, unsigned int ttl, bool cached, int resultnum = 0)
        {
+               ServerInstance->Log(DEBUG,"************* HTTPResolver::OnLookupComplete ***************");
                if (!resultnum)
                        socket->Connect(result);
+               else
+                       socket->OnClose();
        }
        
        void OnError(ResolverError e, const string &errmsg)
        {
-               delete socket;
+               ServerInstance->Log(DEBUG,"!!!!!!!!!!!!!!!! HTTPResolver::OnError: %s", errmsg.c_str());
+               socket->OnClose();
        }
 };
 
@@ -78,12 +86,15 @@ class ModuleHTTPClient : public Module
        ModuleHTTPClient(InspIRCd *Me)
                : Module(Me)
        {
+               Implementation eventlist[] = { I_OnRequest };
+               ServerInstance->Modules->Attach(eventlist, this, 1);
        }
        
        virtual ~ModuleHTTPClient()
        {
                for (HTTPList::iterator i = sockets.begin(); i != sockets.end(); i++)
-                       delete *i;
+                       (*i)->Close();
+               ServerInstance->BufferedSocketCull();
        }
        
        virtual Version GetVersion()
@@ -91,10 +102,6 @@ class ModuleHTTPClient : public Module
                return Version(1, 0, 0, 0, VF_SERVICEPROVIDER | VF_VENDOR, API_VERSION);
        }
 
-       void Implements(char* List)
-       {
-               List[I_OnRequest] = 1;
-       }
 
        char* OnRequest(Request *req)
        {
@@ -110,10 +117,13 @@ class ModuleHTTPClient : public Module
 };
 
 HTTPSocket::HTTPSocket(InspIRCd *Instance, ModuleHTTPClient *Mod)
-               : InspSocket(Instance), Server(Instance), Mod(Mod), status(HTTP_CLOSED)
+               : BufferedSocket(Instance), Server(Instance), Mod(Mod), status(HTTP_CLOSED)
 {
-       this->ClosePending = false;
+       Instance->Log(DEBUG,"HTTPSocket::HTTPSocket");
        this->port = 80;
+       response = NULL;
+       closed = false;
+       timeout_val = 10;
 }
 
 HTTPSocket::~HTTPSocket()
@@ -131,6 +141,7 @@ HTTPSocket::~HTTPSocket()
 
 bool HTTPSocket::DoRequest(HTTPClientRequest *req)
 {
+       Instance->Log(DEBUG,"HTTPSocket::DoRequest");
        /* Tweak by brain - we take a copy of this,
         * so that the caller doesnt need to leave
         * pointers knocking around, less chance of
@@ -144,29 +155,27 @@ bool HTTPSocket::DoRequest(HTTPClientRequest *req)
        this->port = url.port;
        strlcpy(this->host, url.domain.c_str(), MAXBUF);
 
-       in_addr addy1;
-#ifdef IPV6
-       in6_addr addy2;
-       if ((inet_aton(this->host, &addy1) > 0) || (inet_pton(AF_INET6, this->host, &addy2) > 0))
-#else
-       if (inet_aton(this->host, &addy1) > 0)
-#endif
+       Instance->Log(DEBUG,"Doing request for %s", url.url.c_str());
+
+       in6_addr s6;
+       in_addr s4;
+       /* Doesnt look like an ipv4 or an ipv6 address */
+       if ((inet_pton(AF_INET6, url.domain.c_str(), &s6) < 1) && (inet_pton(AF_INET, url.domain.c_str(), &s4) < 1))
        {
                bool cached;
                HTTPResolver* r = new HTTPResolver(this, Server, url.domain, cached, (Module*)Mod);
                Instance->AddResolver(r, cached);
-               return true;
+               Instance->Log(DEBUG,"Resolver added, cached=%d", cached);
        }
        else
-       {
-               this->Connect(url.domain);
-       }
+               Connect(url.domain);
        
        return true;
 }
 
 bool HTTPSocket::ParseURL(const std::string &iurl)
 {
+       Instance->Log(DEBUG,"HTTPSocket::ParseURL %s", iurl.c_str());
        url.url = iurl;
        url.port = 80;
        url.protocol = "http";
@@ -175,10 +184,10 @@ bool HTTPSocket::ParseURL(const std::string &iurl)
        
        for (int p = 0;; p++)
        {
-               std::string part = tokenizer.GetToken();
-               if (part.empty() && tokenizer.StreamEnd())
+               std::string part;
+               if (!tokenizer.GetToken(part))
                        break;
-               
+
                if ((p == 0) && (part[part.length() - 1] == ':'))
                {
                        // Protocol ('http:')
@@ -249,16 +258,23 @@ bool HTTPSocket::ParseURL(const std::string &iurl)
 
 void HTTPSocket::Connect(const string &ip)
 {
+       this->response = new HTTPClientResponse((Module*)Mod, req.GetSource() , url.url, 0, "");
+
+       Instance->Log(DEBUG,"HTTPSocket::Connect(%s) response=%08lx", ip.c_str(), response);
        strlcpy(this->IP, ip.c_str(), MAXBUF);
-       
+       strlcpy(this->host, ip.c_str(), MAXBUF);
+
        if (!this->DoConnect())
        {
-               delete this;
+               Instance->Log(DEBUG,"DoConnect failed, bailing");
+               this->Close();
        }
 }
 
 bool HTTPSocket::OnConnected()
 {
+       Instance->Log(DEBUG,"HTTPSocket::OnConnected");
+
        std::string request = "GET " + url.request + " HTTP/1.1\r\n";
 
        // Dump headers into the request
@@ -281,13 +297,11 @@ bool HTTPSocket::OnConnected()
 
 bool HTTPSocket::OnDataReady()
 {
+       Instance->Log(DEBUG,"HTTPSocket::OnDataReady() for %s", url.url.c_str());
        char *data = this->Read();
 
        if (!data)
-       {
-               this->Close();
                return false;
-       }
 
        if (this->status < HTTP_DATA)
        {
@@ -312,7 +326,8 @@ bool HTTPSocket::OnDataReady()
                                // HTTP reply (HTTP/1.1 200 msg)
                                char const* data = line.c_str();
                                data += 9;
-                               response = new HTTPClientResponse((Module*)Mod, req.GetSource() , url.url, atoi(data), data + 4);
+                               response->SetResponse(data);
+                               response->SetData(data + 4);
                                this->status = HTTP_HEADERS;
                                continue;
                        }
@@ -336,12 +351,26 @@ bool HTTPSocket::OnDataReady()
 
 void HTTPSocket::OnClose()
 {
-       if (data.empty())
-               return; // notification that request failed?
+       if (!closed)
+       {
+               closed = true;
+               Instance->Log(DEBUG,"HTTPSocket::OnClose response=%08lx", response);
+               std::string e;
+               if (data.empty())
+                       {
+                       Instance->Log(DEBUG,"Send error");
+                       HTTPClientError* err = new HTTPClientError((Module*)Mod, req.GetSource(), req.GetURL(), 0);
+                       err->Send();
+                       delete err;
+                       return;
+               }
 
-       response->data = data;
-       response->Send();
-       delete response;
+               Instance->Log(DEBUG,"Set data and send, %s", response->GetURL().c_str());
+               response->SetData(data);
+               response->Send();
+               delete response;
+       }
 }
 
 MODULE_INIT(ModuleHTTPClient)
+