diff options
-rw-r--r-- | include/connection.h | 3 | ||||
-rw-r--r-- | src/connection.cpp | 60 | ||||
-rw-r--r-- | src/inspircd.cpp | 2 |
3 files changed, 61 insertions, 4 deletions
diff --git a/include/connection.h b/include/connection.h index 9a72e6d6b..c996e0abd 100644 --- a/include/connection.h +++ b/include/connection.h @@ -27,7 +27,7 @@ class packet : public classbase { public: long key; - short int id; + int id; short int type; char data[MAXBUF]; @@ -51,6 +51,7 @@ class connection : public classbase bool haspassed; int port; int registered; + short int state; time_t lastping; time_t signon; time_t idle_lastmsg; diff --git a/src/connection.cpp b/src/connection.cpp index eb0af9833..1296e7d93 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -12,6 +12,9 @@ extern std::vector<ircd_module*> factory; extern int MODCOUNT; +#define STATE_CLEAR 1 +#define STATE_WAIT_FOR_ACK 2 + packet::packet() { srand(time(NULL)); @@ -26,6 +29,7 @@ connection::connection() { key = GenKey(); fd = 0; + state = STATE_CLEAR; } @@ -127,7 +131,59 @@ bool connection::SendPacket(char *message, char* host, int port, long ourkey) log(DEBUG,"sendto() failed for Connection::SendPacket() with a packet of size %d",sizeof(p)); return false; } - return true; + this->state = STATE_WAIT_FOR_ACK; + + + socklen_t host_address_size; + // host_address remains unchanged. we only want to receive from where we just sent the packet to. + + // retry the packet up to 5 times + for (int retries = 0; retries < 5; retries++) + { + host_address.sin_family=AF_INET; + host_address_size=sizeof(host_address); + + // wait for ack, or timeout. + // if reached a timeout, send again. + // the packet id in the ack must match that in the original packet + // this MUST operate in lock/step fashion!!! + int cycles = 0; + packet p2; + while ((recvfrom(fd,&p2,sizeof(p2),0,(sockaddr*)&host_address,&host_address_size)<0) && (cycles < 10)) + { + fd_set sfd; + timeval tval; + tval.tv_usec = 10; + tval.tv_sec = 0; + FD_ZERO(&sfd); + FD_SET(fd,&sfd); + int res = select(65535, &sfd, NULL, NULL, &tval); + cycles++; + } + if (cycles >= 10) + { + log(DEFAULT,"ERROR! connection::SendPacket() waited >100 nanosecs for an ACK. Will resend up to 5 times"); + } + else + { + if (p2.id != p.id) + { + log(DEFAULT,"ERROR! connection::SendPacket() received an ack for a packet it didnt send!"); + this->state = STATE_CLEAR; + return false; + } + else + { + log(DEFAULT,"Successfully received ACK"); + this->state = STATE_CLEAR; + return true; + break; + } + } + } + log(DEFAULT,"We never received an ack. Something fishy going on, host is dead."); + this->state = STATE_CLEAR; + return false; } @@ -180,7 +236,6 @@ bool connection::SendACK(char* host, int port, int reply_id) { return false; } - return true; } @@ -248,6 +303,7 @@ bool connection::RecvPacket(char *message, char* host, int &prt, long &theirkey) strcpy(message,p.data); strcpy(host,inet_ntoa(host_address.sin_addr)); prt = ntohs(host_address.sin_port); + this->state = STATE_CLEAR; return false; } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 0d09c22d4..8a8dbc761 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -6893,7 +6893,7 @@ int InspIRCd(void) { fd_set sfd; - struct timeval tval; + timeval tval; FD_ZERO(&sfd); user_hash::iterator count2 = clientlist.begin(); |