X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Finspsocket.cpp;h=4264700f54bd02cb6a7fe2c8942758cc2b7369ce;hb=8f9d0a68cd77b6a78eccfa7df9c1045d453ce581;hp=74931cee34b2fd80a9e3ed92b046ea006bceca86;hpb=14004479dc1d471c4388f0ab7f86f869ba7f098a;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index 74931cee3..4264700f5 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -26,6 +26,7 @@ #include "inspstring.h" #include "helperfuncs.h" #include "socketengine.h" +#include "message.h" extern InspIRCd* ServerInstance; @@ -41,7 +42,7 @@ InspSocket::InspSocket() this->ClosePending = false; } -InspSocket::InspSocket(int newfd, char* ip) +InspSocket::InspSocket(int newfd, const char* ip) { this->fd = newfd; this->state = I_CONNECTED; @@ -119,6 +120,23 @@ InspSocket::InspSocket(const std::string &ahost, int aport, bool listening, unsi } } +void InspSocket::WantWrite() +{ + /** XXX: + * The socket engine may only have each FD in the list ONCE. + * This means we cant watch for write AND read at the same + * time. We have to remove the READ fd, to insert the WRITE + * fd. Once we receive our WRITE event (which WILL ARRIVE, + * pretty much gauranteed) we switch back to watching for + * READ events again. + * + * This behaviour may be fixed in a later version. + */ + this->WaitingForWriteEvent = true; + ServerInstance->SE->DelFd(this->fd); + ServerInstance->SE->AddFd(this->fd,false,X_ESTAB_MODULE); +} + void InspSocket::SetQueues(int nfd) { // attempt to increase socket sendq and recvq as high as its possible @@ -157,6 +175,69 @@ bool InspSocket::DoResolve() return true; } +/* Most irc servers require you to specify the ip you want to bind to. + * If you dont specify an IP, they rather dumbly bind to the first IP + * of the box (e.g. INADDR_ANY). In InspIRCd, we scan thought the IP + * addresses we've bound server ports to, and we try and bind our outbound + * connections to the first usable non-loopback and non-any IP we find. + * This is easier to configure when you have a lot of links and a lot + * of servers to configure. + */ +bool InspSocket::BindAddr() +{ + insp_inaddr n; + ConfigReader Conf; + + log(DEBUG,"In InspSocket::BindAddr()"); + for (int j =0; j < Conf.Enumerate("bind"); j++) + { + std::string Type = Conf.ReadValue("bind","type",j); + std::string IP = Conf.ReadValue("bind","address",j); + if (Type == "servers") + { + if ((IP != "*") && (IP != "127.0.0.1") && (IP != "")) + { + insp_sockaddr s; + char resolved_addr[MAXBUF]; + + if (!inet_aton(IP.c_str(),&n)) + { + /* If they gave a hostname, bind to the IP it resolves to */ + log(DEBUG,"Resolving host %s",IP.c_str()); + if (CleanAndResolve(resolved_addr, IP.c_str(), true)) + { + log(DEBUG,"Resolved host %s to %s",IP.c_str(),resolved_addr); + IP = resolved_addr; + } + } + + if (inet_aton(IP.c_str(),&n)) + { + log(DEBUG,"Found an IP to bind to: %s",IP.c_str()); + s.sin_addr = n; + s.sin_family = AF_INET; + if (bind(this->fd,(struct sockaddr*)&s,sizeof(s)) < 0) + { + log(DEBUG,"Cant bind()"); + this->state = I_ERROR; + this->OnError(I_ERR_BIND); + this->fd = -1; + return false; + } + log(DEBUG,"bind() reports outbound fd bound to ip %s",IP.c_str()); + return true; + } + else + { + log(DEBUG,"Address '%s' was not an IP address",IP.c_str()); + } + } + } + } + log(DEBUG,"Found no suitable IPs to bind, binding INADDR_ANY"); + return true; +} + bool InspSocket::DoConnect() { log(DEBUG,"In DoConnect()"); @@ -169,6 +250,9 @@ bool InspSocket::DoConnect() return false; } + if (!this->BindAddr()) + return false; + log(DEBUG,"Part 2 DoConnect() %s",this->IP); inet_aton(this->IP,&addy); addr.sin_family = AF_INET; @@ -379,7 +463,20 @@ bool InspSocket::Poll() return true; break; case I_CONNECTED: - n = this->OnDataReady(); + + if (this->WaitingForWriteEvent) + { + /* Switch back to read events */ + ServerInstance->SE->DelFd(this->fd); + ServerInstance->SE->AddFd(this->fd,true,X_ESTAB_MODULE); + /* Trigger the write event */ + n = this->OnWriteReady(); + } + else + { + /* Process the read event */ + n = this->OnDataReady(); + } /* Flush any pending, but not till after theyre done with the event * so there are less write calls involved. * Both FlushWriteBuffer AND the return result of OnDataReady must @@ -416,6 +513,7 @@ void InspSocket::OnError(InspSocketError e) { return; } int InspSocket::OnDisconnect() { return 0; } int InspSocket::OnIncomingConnection(int newfd, char* ip) { return 0; } bool InspSocket::OnDataReady() { return true; } +bool InspSocket::OnWriteReady() { return true; } void InspSocket::OnTimeout() { return; } void InspSocket::OnClose() { return; }