diff options
-rw-r--r-- | include/dns.h | 3 | ||||
-rw-r--r-- | include/socket.h | 11 | ||||
-rw-r--r-- | src/dns.cpp | 14 | ||||
-rw-r--r-- | src/inspircd.cpp | 3 | ||||
-rw-r--r-- | src/socket.cpp | 78 |
5 files changed, 75 insertions, 34 deletions
diff --git a/include/dns.h b/include/dns.h index 33b5f8c7a..91e655775 100644 --- a/include/dns.h +++ b/include/dns.h @@ -78,6 +78,9 @@ public: * and returns true if the lookup was successfully initiated. */ bool ForwardLookup(std::string host); + /** Used by modules to perform a dns lookup but have the socket engine poll a module, instead of the dns object directly. + */ + bool ForwardLookupWithFD(std::string host, int &fd); /** This method will return true when the lookup is completed. It uses poll internally * to determine the status of the socket. */ diff --git a/include/socket.h b/include/socket.h index 287726a0c..e8eec405c 100644 --- a/include/socket.h +++ b/include/socket.h @@ -26,12 +26,12 @@ /** * States which a socket may be in */ -enum InspSocketState { I_DISCONNECTED, I_CONNECTING, I_CONNECTED, I_LISTENING, I_ERROR }; +enum InspSocketState { I_DISCONNECTED, I_RESOLVING, I_CONNECTING, I_CONNECTED, I_LISTENING, I_ERROR }; /** * Error types which a socket may exhibit */ -enum InspSocketError { I_ERR_TIMEOUT, I_ERR_SOCKET, I_ERR_CONNECT, I_ERR_BIND }; +enum InspSocketError { I_ERR_TIMEOUT, I_ERR_SOCKET, I_ERR_CONNECT, I_ERR_BIND, I_ERR_RESOLVE }; /** * InspSocket is an extendable socket class which modules @@ -54,6 +54,11 @@ private: int fd; /** + * The resolver for this socket + */ + DNS dns; + + /** * The hostname connected to */ std::string host; @@ -308,6 +313,8 @@ public: * used for this socket. */ virtual ~InspSocket(); + + virtual DoResolve(); }; #endif diff --git a/src/dns.cpp b/src/dns.cpp index f6bba28da..67c309f41 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -735,6 +735,20 @@ bool DNS::ForwardLookup(std::string host) return true; } +bool DNS::ForwardLookupWithFD(std::string host, int &fd) +{ + ServerInstance->stats->statsDns++; + this->myfd = dns_getip4(host.c_str()); + fd = this->myfd; + if (this->myfd == -1) + { + + } + log(DEBUG,"DNS: ForwardLookupWithFD, fd=%d",this->myfd); + ServerInstance->SE->AddFd(this->myfd,true,X_ESTAB_MODULE); + return true; +} + bool DNS::HasResult(int fd) { return (fd == this->myfd); diff --git a/src/inspircd.cpp b/src/inspircd.cpp index a3297f921..6f61fbb31 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -21,11 +21,9 @@ using namespace std; #include "inspircd_config.h" #include "inspircd.h" #include "inspircd_io.h" -#include <unistd.h> #include <fcntl.h> #include <sys/errno.h> #include <sys/ioctl.h> -#include <sys/utsname.h> #include <time.h> #include <string> #ifdef GCC3 @@ -480,7 +478,6 @@ bool InspIRCd::LoadModule(const char* filename) { log(DEFAULT,"Unable to load %s: %s",modfile,factory[MODCOUNT+1]->LastError()); snprintf(MODERR,MAXBUF,"Loader/Linker error: %s",factory[MODCOUNT+1]->LastError()); - MODCOUNT--; return false; } if (factory[MODCOUNT+1]->factory) diff --git a/src/socket.cpp b/src/socket.cpp index 160f0f652..9c2f5a362 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -88,50 +88,67 @@ InspSocket::InspSocket(std::string host, int port, bool listening, unsigned long } } } else { - char* ip; this->host = host; - hostent* hoste = gethostbyname(host.c_str()); - if (!hoste) { - ip = (char*)host.c_str(); - } else { - struct in_addr* ia = (in_addr*)hoste->h_addr; - ip = inet_ntoa(*ia); + + if (this->dns.ForwardLookupWithFD(host,fd)) + { + timeout_end = time(NULL)+maxtime; + timeout = false; + this->state = I_RESOLVING; } + else + { + this->state = I_ERROR; + this->OnError(I_ERR_RESOLVE); + return; + } +} - this->IP = ip; +bool InspSocket::DoResolve() +{ + if (this->dns.HasResult()) + { + std::string res_ip = dns.GetResultIP(); + + if (res_ip != "") + { + this->IP = ip; + } + else + { + this->IP = this->host; + } - timeout_end = time(NULL)+maxtime; - timeout = false; - if ((this->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) + if ((this->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { this->state = I_ERROR; this->OnError(I_ERR_SOCKET); - return; + return false; } this->port = port; - inet_aton(ip,&addy); - addr.sin_family = AF_INET; - addr.sin_addr = addy; - addr.sin_port = htons(this->port); + inet_aton(ip,&addy); + addr.sin_family = AF_INET; + addr.sin_addr = addy; + addr.sin_port = htons(this->port); - int flags; - flags = fcntl(this->fd, F_GETFL, 0); - fcntl(this->fd, F_SETFL, flags | O_NONBLOCK); + int flags; + flags = fcntl(this->fd, F_GETFL, 0); + fcntl(this->fd, F_SETFL, flags | O_NONBLOCK); - if(connect(this->fd, (sockaddr*)&this->addr,sizeof(this->addr)) == -1) - { - if (errno != EINPROGRESS) - { + if(connect(this->fd, (sockaddr*)&this->addr,sizeof(this->addr)) == -1) + { + if (errno != EINPROGRESS) + { this->Close(); this->OnError(I_ERR_CONNECT); this->state = I_ERROR; - return; - } - } - this->state = I_CONNECTING; + return false; + } + } + this->state = I_CONNECTING; ServerInstance->SE->AddFd(this->fd,false,X_ESTAB_MODULE); socket_ref[this->fd] = this; - return; + return true; } } @@ -203,7 +220,7 @@ void InspSocket::FlushWriteBuffer() bool InspSocket::Timeout(time_t current) { - if ((this->state == I_CONNECTING) && (current > timeout_end)) + if (((this->state == I_RESOLVING) || (this->state == I_CONNECTING)) && (current > timeout_end)) { // for non-listening sockets, the timeout can occur // which causes termination of the connection after @@ -226,6 +243,9 @@ bool InspSocket::Poll() switch (this->state) { + case I_RESOLVING: + return this->DoResolve(); + break; case I_CONNECTING: this->SetState(I_CONNECTED); /* Our socket was in write-state, so delete it and re-add it |