Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

users.h File Reference

#include "inspircd_config.h"
#include "channels.h"
#include "inspstring.h"
#include "connection.h"
#include <string>
#include "hashcomp.h"

Include dependency graph for users.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  Invited
 Holds a channel name to which a user has been invited. More...
class  ConnectClass
 Holds information relevent to <connect allow> and <connect deny> tags in the config file. More...
class  userrec
 Holds all information about a user This class stores all information about a user connected to the irc server. More...
class  WhoWasUser
 A lightweight userrec used by WHOWAS. More...

Defines

#define STATUS_OP   4
#define STATUS_HOP   2
#define STATUS_VOICE   1
#define STATUS_NORMAL   0
#define CC_ALLOW   0
#define CC_DENY   1

Typedefs

typedef std::vector< InvitedInvitedList
 Holds a complete list of all channels to which a user has been invited and has not yet joined.
typedef std::vector< ConnectClassClassVector
 Holds a complete list of all allow and deny tags from the configuration file (connection classes).

Functions

template<typename T>
string ConvToStr (const T &in)
void AddOper (userrec *user)
void DeleteOper (userrec *user)
void kill_link (userrec *user, const char *r)
void kill_link_silent (userrec *user, const char *r)
void AddWhoWas (userrec *u)
void AddClient (int socket, char *host, int port, bool iscached, char *ip)
void FullConnectUser (userrec *user)
void ConnectUser (userrec *user)
userrecReHashNick (char *Old, char *New)
void force_nickchange (userrec *user, const char *newnick)


Define Documentation

#define CC_ALLOW   0
 

Definition at line 36 of file users.h.

Referenced by AddClient().

#define CC_DENY   1
 

Definition at line 37 of file users.h.

#define STATUS_HOP   2
 

Definition at line 32 of file users.h.

Referenced by kick_channel().

#define STATUS_NORMAL   0
 

Definition at line 34 of file users.h.

#define STATUS_OP   4
 

Definition at line 31 of file users.h.

#define STATUS_VOICE   1
 

Definition at line 33 of file users.h.


Typedef Documentation

typedef std::vector<ConnectClass> ClassVector
 

Holds a complete list of all allow and deny tags from the configuration file (connection classes).

Definition at line 107 of file users.h.

typedef std::vector<Invited> InvitedList
 

Holds a complete list of all channels to which a user has been invited and has not yet joined.

Definition at line 101 of file users.h.


Function Documentation

void AddClient int  socket,
char *  host,
int  port,
bool  iscached,
char *  ip
 

Definition at line 524 of file users.cpp.

References SocketEngine::AddFd(), CC_ALLOW, ucrec::channel, ServerConfig::Classes, clientlist, ConvToStr(), DEBUG, ServerConfig::dns_timeout, FindServerNamePtr(), kill_link(), local_users, log(), matches_exception(), matches_zline(), InspIRCd::SE, ServerConfig::ServerName, ServerConfig::SoftLimit, TIME, ucrec::uc_modes, and X_ESTAB_CLIENT.

00525 {
00526         string tempnick;
00527         char tn2[MAXBUF];
00528         user_hash::iterator iter;
00529 
00530         tempnick = ConvToStr(socket) + "-unknown";
00531         sprintf(tn2,"%lu-unknown",(unsigned long)socket);
00532 
00533         iter = clientlist.find(tempnick);
00534 
00535         // fix by brain.
00536         // as these nicknames are 'RFC impossible', we can be sure nobody is going to be
00537         // using one as a registered connection. As theyre per fd, we can also safely assume
00538         // that we wont have collisions. Therefore, if the nick exists in the list, its only
00539         // used by a dead socket, erase the iterator so that the new client may reclaim it.
00540         // this was probably the cause of 'server ignores me when i hammer it with reconnects'
00541         // issue in earlier alphas/betas
00542         if (iter != clientlist.end())
00543         {
00544                 userrec* goner = iter->second;
00545                 delete goner;
00546                 clientlist.erase(iter);
00547         }
00548 
00549         /*
00550          * It is OK to access the value here this way since we know
00551          * it exists, we just created it above.
00552          *
00553          * At NO other time should you access a value in a map or a
00554          * hash_map this way.
00555          */
00556         clientlist[tempnick] = new userrec();
00557 
00558         log(DEBUG,"AddClient: %lu %s %d %s",(unsigned long)socket,host,port,ip);
00559 
00560         clientlist[tempnick]->fd = socket;
00561         strlcpy(clientlist[tempnick]->nick, tn2,NICKMAX);
00562         strlcpy(clientlist[tempnick]->host, host,160);
00563         strlcpy(clientlist[tempnick]->dhost, host,160);
00564         clientlist[tempnick]->server = (char*)FindServerNamePtr(Config->ServerName);
00565         strlcpy(clientlist[tempnick]->ident, "unknown",IDENTMAX);
00566         clientlist[tempnick]->registered = 0;
00567         clientlist[tempnick]->signon = TIME + Config->dns_timeout;
00568         clientlist[tempnick]->lastping = 1;
00569         clientlist[tempnick]->port = port;
00570         strlcpy(clientlist[tempnick]->ip,ip,16);
00571 
00572         // set the registration timeout for this user
00573         unsigned long class_regtimeout = 90;
00574         int class_flood = 0;
00575         long class_threshold = 5;
00576         long class_sqmax = 262144;      // 256kb
00577         long class_rqmax = 4096;        // 4k
00578 
00579         for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
00580         {
00581                 if (match(clientlist[tempnick]->host,i->host) && (i->type == CC_ALLOW))
00582                 {
00583                         class_regtimeout = (unsigned long)i->registration_timeout;
00584                         class_flood = i->flood;
00585                         clientlist[tempnick]->pingmax = i->pingtime;
00586                         class_threshold = i->threshold;
00587                         class_sqmax = i->sendqmax;
00588                         class_rqmax = i->recvqmax;
00589                         break;
00590                 }
00591         }
00592 
00593         clientlist[tempnick]->nping = TIME+clientlist[tempnick]->pingmax + Config->dns_timeout;
00594         clientlist[tempnick]->timeout = TIME+class_regtimeout;
00595         clientlist[tempnick]->flood = class_flood;
00596         clientlist[tempnick]->threshold = class_threshold;
00597         clientlist[tempnick]->sendqmax = class_sqmax;
00598         clientlist[tempnick]->recvqmax = class_rqmax;
00599 
00600         ucrec a;
00601         a.channel = NULL;
00602         a.uc_modes = 0;
00603         for (int i = 0; i < MAXCHANS; i++)
00604                 clientlist[tempnick]->chans.push_back(a);
00605 
00606         if (clientlist.size() > Config->SoftLimit)
00607         {
00608                 kill_link(clientlist[tempnick],"No more connections allowed");
00609                 return;
00610         }
00611 
00612         if (clientlist.size() >= MAXCLIENTS)
00613         {
00614                 kill_link(clientlist[tempnick],"No more connections allowed");
00615                 return;
00616         }
00617 
00618         // this is done as a safety check to keep the file descriptors within range of fd_ref_table.
00619         // its a pretty big but for the moment valid assumption:
00620         // file descriptors are handed out starting at 0, and are recycled as theyre freed.
00621         // therefore if there is ever an fd over 65535, 65536 clients must be connected to the
00622         // irc server at once (or the irc server otherwise initiating this many connections, files etc)
00623         // which for the time being is a physical impossibility (even the largest networks dont have more
00624         // than about 10,000 users on ONE server!)
00625         if ((unsigned)socket > 65534)
00626         {
00627                 kill_link(clientlist[tempnick],"Server is full");
00628                 return;
00629         }
00630         char* e = matches_exception(ip);
00631         if (!e)
00632         {
00633                 char* r = matches_zline(ip);
00634                 if (r)
00635                 {
00636                         char reason[MAXBUF];
00637                         snprintf(reason,MAXBUF,"Z-Lined: %s",r);
00638                         kill_link(clientlist[tempnick],reason);
00639                         return;
00640                 }
00641         }
00642         fd_ref_table[socket] = clientlist[tempnick];
00643         local_users.push_back(clientlist[tempnick]);
00644         ServerInstance->SE->AddFd(socket,true,X_ESTAB_CLIENT);
00645 }

void AddOper userrec user  ) 
 

Definition at line 330 of file users.cpp.

References all_opers, DEBUG, and log().

00331 {
00332         log(DEBUG,"Oper added to optimization list");
00333         all_opers.push_back(user);
00334 }

void AddWhoWas userrec u  ) 
 

Definition at line 471 of file users.cpp.

References DEBUG, userrec::dhost, WhoWasUser::dhost, userrec::fullname, WhoWasUser::fullname, connection::host, WhoWasUser::host, userrec::ident, WhoWasUser::ident, log(), WhoWasUser::nick, userrec::nick, userrec::server, WhoWasUser::server, connection::signon, WhoWasUser::signon, TIME, whowas, WHOWAS_MAX, and WHOWAS_STALE.

Referenced by kill_link().

00472 {
00473         whowas_hash::iterator iter = whowas.find(u->nick);
00474         WhoWasUser *a = new WhoWasUser();
00475         strlcpy(a->nick,u->nick,NICKMAX);
00476         strlcpy(a->ident,u->ident,IDENTMAX);
00477         strlcpy(a->dhost,u->dhost,160);
00478         strlcpy(a->host,u->host,160);
00479         strlcpy(a->fullname,u->fullname,MAXGECOS);
00480         strlcpy(a->server,u->server,256);
00481         a->signon = u->signon;
00482 
00483         /* MAX_WHOWAS:   max number of /WHOWAS items
00484          * WHOWAS_STALE: number of hours before a WHOWAS item is marked as stale and
00485          *               can be replaced by a newer one
00486          */
00487 
00488         if (iter == whowas.end())
00489         {
00490                 if (whowas.size() >= (unsigned)WHOWAS_MAX)
00491                 {
00492                         for (whowas_hash::iterator i = whowas.begin(); i != whowas.end(); i++)
00493                         {
00494                                 // 3600 seconds in an hour ;)
00495                                 if ((i->second->signon)<(TIME-(WHOWAS_STALE*3600)))
00496                                 {
00497                                         // delete the old one
00498                                         if (i->second) delete i->second;
00499                                         // replace with new one
00500                                         i->second = a;
00501                                         log(DEBUG,"added WHOWAS entry, purged an old record");
00502                                         return;
00503                                 }
00504                         }
00505                         // no space left and user doesnt exist. Don't leave ram in use!
00506                         log(DEBUG,"Not able to update whowas (list at WHOWAS_MAX entries and trying to add new?), freeing excess ram");
00507                         delete a;
00508                 }
00509                 else
00510                 {
00511                         log(DEBUG,"added fresh WHOWAS entry");
00512                         whowas[a->nick] = a;
00513                 }
00514         }
00515         else
00516         {
00517                 log(DEBUG,"updated WHOWAS entry");
00518                 if (iter->second) delete iter->second;
00519                 iter->second = a;
00520         }
00521 }

void ConnectUser userrec user  ) 
 

Definition at line 731 of file users.cpp.

References userrec::dns_done, FullConnectUser(), and connection::registered.

00732 {
00733         // dns is already done, things are fast. no need to wait for dns to complete just pass them straight on
00734         if ((user->dns_done) && (user->registered >= 3) && (AllModulesReportReady(user)))
00735         {
00736                 FullConnectUser(user);
00737         }
00738 }

template<typename T>
string ConvToStr const T &  in  )  [inline]
 

Definition at line 56 of file users.cpp.

Referenced by AddClient().

00057 {
00058         stringstream tmp;
00059         if (!(tmp << in)) return string();
00060         return tmp.str();
00061 }

void DeleteOper userrec user  ) 
 

Definition at line 336 of file users.cpp.

References all_opers, DEBUG, and log().

00337 {
00338         for (std::vector<userrec*>::iterator a = all_opers.begin(); a < all_opers.end(); a++)
00339         {
00340                 if (*a == user)
00341                 {
00342                         log(DEBUG,"Oper removed from optimization list");
00343                         all_opers.erase(a);
00344                         return;
00345                 }
00346         }
00347 }

void force_nickchange userrec user,
const char *  newnick
 

Definition at line 769 of file users.cpp.

References FOREACH_RESULT, kill_link(), matches_qline(), InspIRCd::Parser, connection::registered, InspIRCd::stats, and serverstats::statsCollisions.

Referenced by Server::ChangeUserNick().

00770 {
00771         char nick[MAXBUF];
00772         int MOD_RESULT = 0;
00773 
00774         strcpy(nick,"");
00775 
00776         FOREACH_RESULT(OnUserPreNick(user,newnick));
00777         if (MOD_RESULT) {
00778                 ServerInstance->stats->statsCollisions++;
00779                 kill_link(user,"Nickname collision");
00780                 return;
00781         }
00782         if (matches_qline(newnick))
00783         {
00784                 ServerInstance->stats->statsCollisions++;
00785                 kill_link(user,"Nickname collision");
00786                 return;
00787         }
00788 
00789         if (user)
00790         {
00791                 if (newnick)
00792                 {
00793                         strncpy(nick,newnick,MAXBUF);
00794                 }
00795                 if (user->registered == 7)
00796                 {
00797                         char* pars[1];
00798                         pars[0] = nick;
00799                         std::string cmd = "NICK";
00800                         ServerInstance->Parser->CallHandler(cmd,pars,1,user);
00801                 }
00802         }
00803 }

void FullConnectUser userrec user  ) 
 

Definition at line 647 of file users.cpp.

References DEBUG, connection::fd, FOREACH_MOD, connection::haspassed, connection::host, userrec::ident, connection::idle_lastmsg, connection::ip, kill_link(), kill_link_silent(), log(), matches_exception(), matches_gline(), matches_kline(), ServerConfig::Network, userrec::nick, connection::port, connection::registered, ServerConfig::ServerName, InspIRCd::stats, serverstats::statsConnects, TIME, WriteOpers(), and WriteServ().

Referenced by ConnectUser().

00648 {
00649         ServerInstance->stats->statsConnects++;
00650         user->idle_lastmsg = TIME;
00651         log(DEBUG,"ConnectUser: %s",user->nick);
00652 
00653         if ((strcmp(Passwd(user),"")) && (!user->haspassed))
00654         {
00655                 kill_link(user,"Invalid password");
00656                 return;
00657         }
00658         if (IsDenied(user))
00659         {
00660                 kill_link(user,"Unauthorised connection");
00661                 return;
00662         }
00663 
00664         char match_against[MAXBUF];
00665         snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host);
00666         char* e = matches_exception(match_against);
00667         if (!e)
00668         {
00669                 char* r = matches_gline(match_against);
00670                 if (r)
00671                 {
00672                         char reason[MAXBUF];
00673                         snprintf(reason,MAXBUF,"G-Lined: %s",r);
00674                         kill_link_silent(user,reason);
00675                         return;
00676                 }
00677                 r = matches_kline(user->host);
00678                 if (r)
00679                 {
00680                         char reason[MAXBUF];
00681                         snprintf(reason,MAXBUF,"K-Lined: %s",r);
00682                         kill_link_silent(user,reason);
00683                         return;
00684                 }
00685         }
00686 
00687 
00688         WriteServ(user->fd,"NOTICE Auth :Welcome to \002%s\002!",Config->Network);
00689         WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Config->Network,user->nick,user->ident,user->host);
00690         WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,Config->ServerName,VERSION);
00691         WriteServ(user->fd,"003 %s :This server was created %s %s",user->nick,__TIME__,__DATE__);
00692         WriteServ(user->fd,"004 %s %s %s iowghraAsORVSxNCWqBzvdHtGI lvhopsmntikrRcaqOALQbSeKVfHGCuzN",user->nick,Config->ServerName,VERSION);
00693         // the neatest way to construct the initial 005 numeric, considering the number of configure constants to go in it...
00694         std::stringstream v;
00695         v << "WALLCHOPS MODES=13 CHANTYPES=# PREFIX=(ohv)@%+ MAP SAFELIST MAXCHANNELS=" << MAXCHANS;
00696         v << " MAXBANS=60 NICKLEN=" << NICKMAX;
00697         v << " TOPICLEN=" << MAXTOPIC << " KICKLEN=" << MAXKICK << " MAXTARGETS=20 AWAYLEN=" << MAXAWAY << " CHANMODES=ohvb,k,l,psmnti NETWORK=";
00698         v << Config->Network;
00699         std::string data005 = v.str();
00700         FOREACH_MOD On005Numeric(data005);
00701         // anfl @ #ratbox, efnet reminded me that according to the RFC this cant contain more than 13 tokens per line...
00702         // so i'd better split it :)
00703         std::stringstream out(data005);
00704         std::string token = "";
00705         std::string line5 = "";
00706         int token_counter = 0;
00707         while (!out.eof())
00708         {
00709                 out >> token;
00710                 line5 = line5 + token + " ";
00711                 token_counter++;
00712                 if ((token_counter >= 13) || (out.eof() == true))
00713                 {
00714                         WriteServ(user->fd,"005 %s %s:are supported by this server",user->nick,line5.c_str());
00715                         line5 = "";
00716                         token_counter = 0;
00717                 }
00718         }
00719         ShowMOTD(user);
00720 
00721         // fix 3 by brain, move registered = 7 below these so that spurious modes and host changes dont go out
00722         // onto the network and produce 'fake direction'
00723         FOREACH_MOD OnUserConnect(user);
00724         FOREACH_MOD OnGlobalConnect(user);
00725         user->registered = 7;
00726         WriteOpers("*** Client connecting on port %lu: %s!%s@%s [%s]",(unsigned long)user->port,user->nick,user->ident,user->host,user->ip);
00727 }

void kill_link userrec user,
const char *  r
 

Definition at line 349 of file users.cpp.

References AddWhoWas(), clientlist, userrec::CloseSocket(), DEBUG, SocketEngine::DelFd(), connection::fd, userrec::FlushWriteBuf(), FOREACH_MOD, ServerConfig::GetIOHook(), connection::host, userrec::ident, local_users, log(), userrec::nick, Module::OnRawSocketClose(), connection::port, connection::registered, InspIRCd::SE, Write(), WriteCommonExcept(), and WriteOpers().

Referenced by AddClient(), force_nickchange(), FullConnectUser(), Server::PseudoToUser(), and Server::QuitUser().

00350 {
00351         user_hash::iterator iter = clientlist.find(user->nick);
00352 
00353         char reason[MAXBUF];
00354 
00355         strncpy(reason,r,MAXBUF);
00356 
00357         if (strlen(reason)>MAXQUIT)
00358         {
00359                 reason[MAXQUIT-1] = '\0';
00360         }
00361 
00362         log(DEBUG,"kill_link: %s '%s'",user->nick,reason);
00363         Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason);
00364         log(DEBUG,"closing fd %lu",(unsigned long)user->fd);
00365 
00366         if (user->registered == 7) {
00367                 FOREACH_MOD OnUserQuit(user,reason);
00368                 WriteCommonExcept(user,"QUIT :%s",reason);
00369         }
00370 
00371         user->FlushWriteBuf();
00372 
00373         FOREACH_MOD OnUserDisconnect(user);
00374 
00375         if (user->fd > -1)
00376         {
00377                 if (Config->GetIOHook(user->port))
00378                 {
00379                         Config->GetIOHook(user->port)->OnRawSocketClose(user->fd);
00380                 }
00381                 ServerInstance->SE->DelFd(user->fd);
00382                 user->CloseSocket();
00383         }
00384 
00385         // this must come before the WriteOpers so that it doesnt try to fill their buffer with anything
00386         // if they were an oper with +s.
00387         if (user->registered == 7) {
00388                 purge_empty_chans(user);
00389                 // fix by brain: only show local quits because we only show local connects (it just makes SENSE)
00390                 if (user->fd > -1)
00391                         WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason);
00392                 AddWhoWas(user);
00393         }
00394 
00395         if (iter != clientlist.end())
00396         {
00397                 log(DEBUG,"deleting user hash value %lu",(unsigned long)user);
00398                 if (user->fd > -1)
00399                 {
00400                         fd_ref_table[user->fd] = NULL;
00401                         if (find(local_users.begin(),local_users.end(),user) != local_users.end())
00402                         {
00403                                 local_users.erase(find(local_users.begin(),local_users.end(),user));
00404                                 log(DEBUG,"Delete local user");
00405                         }
00406                 }
00407                 clientlist.erase(iter);
00408         }
00409         delete user;
00410 }

void kill_link_silent userrec user,
const char *  r
 

Definition at line 412 of file users.cpp.

References clientlist, userrec::CloseSocket(), DEBUG, SocketEngine::DelFd(), connection::fd, userrec::FlushWriteBuf(), FOREACH_MOD, ServerConfig::GetIOHook(), connection::host, userrec::ident, local_users, log(), userrec::nick, Module::OnRawSocketClose(), connection::port, connection::registered, InspIRCd::SE, Write(), and WriteCommonExcept().

Referenced by FullConnectUser().

00413 {
00414         user_hash::iterator iter = clientlist.find(user->nick);
00415 
00416         char reason[MAXBUF];
00417 
00418         strncpy(reason,r,MAXBUF);
00419 
00420         if (strlen(reason)>MAXQUIT)
00421         {
00422                 reason[MAXQUIT-1] = '\0';
00423         }
00424 
00425         log(DEBUG,"kill_link: %s '%s'",user->nick,reason);
00426         Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason);
00427         log(DEBUG,"closing fd %lu",(unsigned long)user->fd);
00428 
00429         user->FlushWriteBuf();
00430 
00431         if (user->registered == 7) {
00432                 FOREACH_MOD OnUserQuit(user,reason);
00433                 WriteCommonExcept(user,"QUIT :%s",reason);
00434         }
00435 
00436         FOREACH_MOD OnUserDisconnect(user);
00437 
00438         if (user->fd > -1)
00439         {
00440                 if (Config->GetIOHook(user->port))
00441                 {
00442                         Config->GetIOHook(user->port)->OnRawSocketClose(user->fd);
00443                 }
00444                 ServerInstance->SE->DelFd(user->fd);
00445                 user->CloseSocket();
00446         }
00447 
00448         if (user->registered == 7) {
00449                 purge_empty_chans(user);
00450         }
00451 
00452         if (iter != clientlist.end())
00453         {
00454                 log(DEBUG,"deleting user hash value %lu",(unsigned long)user);
00455                 if (user->fd > -1)
00456                 {
00457                         fd_ref_table[user->fd] = NULL;
00458                         if (find(local_users.begin(),local_users.end(),user) != local_users.end())
00459                         {
00460                                 log(DEBUG,"Delete local user");
00461                                 local_users.erase(find(local_users.begin(),local_users.end(),user));
00462                         }
00463                 }
00464                 clientlist.erase(iter);
00465         }
00466         delete user;
00467 }

userrec* ReHashNick char *  Old,
char *  New
 

Definition at line 743 of file users.cpp.

References clientlist, DEBUG, and log().

00744 {
00745         //user_hash::iterator newnick;
00746         user_hash::iterator oldnick = clientlist.find(Old);
00747 
00748         log(DEBUG,"ReHashNick: %s %s",Old,New);
00749 
00750         if (!strcasecmp(Old,New))
00751         {
00752                 log(DEBUG,"old nick is new nick, skipping");
00753                 return oldnick->second;
00754         }
00755 
00756         if (oldnick == clientlist.end()) return NULL; /* doesnt exist */
00757 
00758         log(DEBUG,"ReHashNick: Found hashed nick %s",Old);
00759 
00760         userrec* olduser = oldnick->second;
00761         clientlist[New] = olduser;
00762         clientlist.erase(oldnick);
00763 
00764         log(DEBUG,"ReHashNick: Nick rehashed as %s",New);
00765 
00766         return clientlist[New];
00767 }


Generated on Mon Dec 19 18:05:21 2005 for InspIRCd by  doxygen 1.4.4-20050815