diff options
-rw-r--r-- | include/modules.h | 18 | ||||
-rw-r--r-- | src/inspircd.cpp | 36 | ||||
-rw-r--r-- | src/modules.cpp | 28 |
3 files changed, 69 insertions, 13 deletions
diff --git a/include/modules.h b/include/modules.h index a040757f6..34549b6c2 100644 --- a/include/modules.h +++ b/include/modules.h @@ -96,6 +96,8 @@ typedef std::deque<userrec*> chanuserlist; // ********************************************************************************************* +#define FD_MAGIC_NUMBER -42 + extern void createcommand(char* cmd, handlerfunc f, char flags, int minparams, char* source); extern void server_mode(char **parameters, int pcnt, userrec *user); @@ -667,6 +669,22 @@ class Server : public classbase */ virtual chanuserlist GetUsers(chanrec* chan); + /** Remove a user's connection to the irc server, but leave their client in existence in the + * user hash. When you call this function, the user's file descriptor will be replaced with the + * value of FD_MAGIC_NUMBER and their old file descriptor will be closed. This idle client will + * remain until it is restored with a valid file descriptor, or is removed from IRC by an operator + * After this call, the pointer to user will be invalid. + */ + virtual bool UserToPseudo(userrec* user,std::string message); + + /** This user takes one user, and switches their file descriptor with another user, so that one user + * "becomes" the other. The user in 'alive' is booted off the server with the given message. The user + * referred to by 'zombie' should have previously been locked with Server::ZombifyUser, otherwise + * stale sockets and file descriptor leaks can occur. After this call, the pointer to alive will be + * invalid, and the pointer to zombie will be equivalent in effect to the old pointer to alive. + */ + virtual bool PseudoToUser(userrec* alive,userrec* zombie,std::string message); + }; #define CONF_NOT_A_NUMBER 0x000010 diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 6ec5631a7..e5150a566 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -544,6 +544,8 @@ void ReadConfig(bool bail, userrec* user) void Write(int sock,char *text, ...) { + if (sock == FD_MAGIC_NUMBER) + return; if (!text) { log(DEFAULT,"*** BUG *** Write was given an invalid parameter"); @@ -568,6 +570,8 @@ void Write(int sock,char *text, ...) void WriteServ(int sock, char* text, ...) { + if (sock == FD_MAGIC_NUMBER) + return; if (!text) { log(DEFAULT,"*** BUG *** WriteServ was given an invalid parameter"); @@ -591,6 +595,8 @@ void WriteServ(int sock, char* text, ...) void WriteFrom(int sock, userrec *user,char* text, ...) { + if (sock == FD_MAGIC_NUMBER) + return; if ((!text) || (!user)) { log(DEFAULT,"*** BUG *** WriteFrom was given an invalid parameter"); @@ -619,6 +625,8 @@ void WriteTo(userrec *source, userrec *dest,char *data, ...) log(DEFAULT,"*** BUG *** WriteTo was given an invalid parameter"); return; } + if (dest->fd == FD_MAGIC_NUMBER) + return; char textbuffer[MAXBUF],tb[MAXBUF]; va_list argsPtr; va_start (argsPtr, data); @@ -656,7 +664,8 @@ void WriteChannel(chanrec* Ptr, userrec* user, char* text, ...) { if (has_channel(i->second,Ptr)) { - WriteTo(user,i->second,"%s",textbuffer); + if (i->second->fd != FD_MAGIC_NUMBER) + WriteTo(user,i->second,"%s",textbuffer); } } } @@ -681,7 +690,7 @@ void WriteChannelLocal(chanrec* Ptr, userrec* user, char* text, ...) { if (has_channel(i->second,Ptr)) { - if (i->second->fd != -1) + if ((i->second->fd != -1) && (i->second->fd != FD_MAGIC_NUMBER)) { if (!user) { @@ -713,7 +722,7 @@ void WriteChannelWithServ(char* ServerName, chanrec* Ptr, userrec* user, char* t { if (i->second) { - if (has_channel(i->second,Ptr)) + if ((has_channel(i->second,Ptr)) && (i->second->fd != FD_MAGIC_NUMBER)) { WriteServ(i->second->fd,"%s",textbuffer); } @@ -742,7 +751,7 @@ void ChanExceptSender(chanrec* Ptr, userrec* user, char* text, ...) { if (i->second) { - if (has_channel(i->second,Ptr) && (user != i->second)) + if ((has_channel(i->second,Ptr)) && (user != i->second) && (i->second->fd != FD_MAGIC_NUMBER)) { WriteTo(user,i->second,"%s",textbuffer); } @@ -798,7 +807,7 @@ void WriteCommon(userrec *u, char* text, ...) { if (i->second) { - if (common_channels(u,i->second) && (i->second != u)) + if ((common_channels(u,i->second) && (i->second != u)) && (i->second->fd != FD_MAGIC_NUMBER)) { WriteFrom(i->second->fd,u,"%s",textbuffer); } @@ -856,7 +865,7 @@ void WriteOpers(char* text, ...) for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++) { - if (i->second) + if ((i->second) && (i->second->fd != FD_MAGIC_NUMBER)) { if (strchr(i->second->modes,'o')) { @@ -1059,7 +1068,7 @@ void WriteMode(const char* modes, int flags, const char* text, ...) for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++) { - if (i->second) + if ((i->second) && (i->second->fd != FD_MAGIC_NUMBER)) { bool send_to_user = false; @@ -1114,7 +1123,7 @@ void WriteWallOps(userrec *source, bool local_only, char* text, ...) for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++) { - if (i->second) + if ((i->second) && (i->second->fd != FD_MAGIC_NUMBER)) { if (strchr(i->second->modes,'w')) { @@ -3765,10 +3774,11 @@ int InspIRCd(void) { for( int n = 0; n < fd_reap.size(); n++) { - //Blocking(fd_reap[n]); - close(fd_reap[n]); - shutdown (fd_reap[n],2); - //NonBlocking(fd_reap[n]); + if ((fd_reap[n] > -1)) + { + close(fd_reap[n]); + shutdown (fd_reap[n],2); + } } } fd_reap.clear(); @@ -3935,7 +3945,7 @@ int InspIRCd(void) #endif result = EAGAIN; - if ((count2a->second->fd != -1) && (FD_ISSET (count2a->second->fd, &sfd))) + if ((count2a->second->fd != FD_MAGIC_NUMBER) && (count2a->second->fd != -1) && (FD_ISSET (count2a->second->fd, &sfd))) { memset(data, 0, 10240); result = read(count2a->second->fd, data, 10240); diff --git a/src/modules.cpp b/src/modules.cpp index 324ab375c..2b4314dee 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -576,6 +576,34 @@ int Server::CountUsers(chanrec* c) } +bool Server::UserToPseudo(userrec* user,std::string message) +{ + unsigned int old_fd = user->fd; + user->fd = FD_MAGIC_NUMBER; + Write(old_fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,message.c_str()); + close(old_fd); + shutdown (old_fd,2); +} + +bool Server::PseudoToUser(userrec* alive,userrec* zombie,std::string message) +{ + zombie->fd = alive->fd; + alive->fd = FD_MAGIC_NUMBER; + Write(zombie->fd,"NICK %s",zombie->nick); + kill_link(alive,message.c_str()); + for (int i = 0; i != MAXCHANS; i++) + { + if (zombie->chans[i].channel != NULL) + { + if (zombie->chans[i].channel->name) + { + Write(zombie->fd,"JOIN %s",zombie->chans[i].channel->name); + } + } + } + +} + ConfigReader::ConfigReader() { this->cache = new std::stringstream(std::stringstream::in | std::stringstream::out); |