X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Finspsocket.cpp;h=4264700f54bd02cb6a7fe2c8942758cc2b7369ce;hb=8f9d0a68cd77b6a78eccfa7df9c1045d453ce581;hp=8177a31827b3d67b8aa2833a01a50984bd2a32c0;hpb=6b72ad31e5ed54dedb85db8a9ae77af3720b603b;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index 8177a3182..4264700f5 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -14,26 +14,19 @@ * --------------------------------------------------- */ -#include "inspircd_config.h" -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include #include #include +#include "inspircd_config.h" #include "socket.h" #include "inspircd.h" #include "configreader.h" #include "inspstring.h" #include "helperfuncs.h" #include "socketengine.h" +#include "message.h" extern InspIRCd* ServerInstance; @@ -49,14 +42,17 @@ 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; strlcpy(this->IP,ip,MAXBUF); this->ClosePending = false; - ServerInstance->SE->AddFd(this->fd,true,X_ESTAB_MODULE); - socket_ref[this->fd] = this; + if (this->fd > -1) + { + ServerInstance->SE->AddFd(this->fd,true,X_ESTAB_MODULE); + socket_ref[this->fd] = this; + } } InspSocket::InspSocket(const std::string &ahost, int aport, bool listening, unsigned long maxtime) : fd(-1) @@ -88,8 +84,11 @@ InspSocket::InspSocket(const std::string &ahost, int aport, bool listening, unsi else { this->state = I_LISTENING; - ServerInstance->SE->AddFd(this->fd,true,X_ESTAB_MODULE); - socket_ref[this->fd] = this; + if (this->fd > -1) + { + ServerInstance->SE->AddFd(this->fd,true,X_ESTAB_MODULE); + socket_ref[this->fd] = this; + } log(DEBUG,"New socket now in I_LISTENING state"); return; } @@ -121,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 @@ -159,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()"); @@ -171,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; @@ -195,9 +277,12 @@ bool InspSocket::DoConnect() } } this->state = I_CONNECTING; - ServerInstance->SE->AddFd(this->fd,false,X_ESTAB_MODULE); - socket_ref[this->fd] = this; - this->SetQueues(this->fd); + if (this->fd > -1) + { + ServerInstance->SE->AddFd(this->fd,false,X_ESTAB_MODULE); + socket_ref[this->fd] = this; + this->SetQueues(this->fd); + } log(DEBUG,"Returning true from InspSocket::DoConnect"); return true; } @@ -363,8 +448,11 @@ bool InspSocket::Poll() /* Our socket was in write-state, so delete it and re-add it * in read-state. */ - ServerInstance->SE->DelFd(this->fd); - ServerInstance->SE->AddFd(this->fd,true,X_ESTAB_MODULE); + if (this->fd > -1) + { + ServerInstance->SE->DelFd(this->fd); + ServerInstance->SE->AddFd(this->fd,true,X_ESTAB_MODULE); + } return this->OnConnected(); break; case I_LISTENING: @@ -375,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 @@ -412,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; }