]>
Commit | Line | Data |
---|---|---|
84563ebd | 1 | /* Keeps track of current "dangling" auths. |
2 | * | |
3 | * Every entry here corresponds to a user who has an open session in the | |
4 | * session table, but we cannot be sure that the user has actually gone. | |
5 | * This means either (a) their server has split off or (b) we restarted and | |
6 | * found a dangling entry in the session table. | |
7 | * | |
8 | * Entries leave when either (a) the user comes back (the entry is dropped), | |
9 | * or (b) the server the user was on relinks without them, in which case we | |
10 | * close off their session. | |
11 | */ | |
12 | ||
13 | #include "authtracker.h" | |
2aaa684c | 14 | #include "../chanserv.h" |
84563ebd | 15 | #include "../../core/nsmalloc.h" |
16 | #include "../../server/server.h" | |
17 | #include "../../irc/irc_config.h" | |
18 | ||
19 | #include <time.h> | |
20 | ||
21 | #define DANGLING_HASHSIZE 500 | |
22 | #define dangling_hash(x) ((x)%DANGLING_HASHSIZE) | |
23 | ||
84563ebd | 24 | struct dangling_entry { |
25 | unsigned int numeric; | |
26 | unsigned long userid; | |
27 | time_t authts; | |
28 | time_t losttime; | |
29 | int reason; /* AT_NETSPLIT or AT_RESTART */ | |
30 | struct dangling_entry *next; | |
31 | }; | |
32 | ||
33 | struct dangling_server { | |
34 | struct dangling_entry *de[DANGLING_HASHSIZE]; | |
35 | }; | |
36 | ||
37 | struct dangling_server *ds[MAXSERVERS]; | |
84563ebd | 38 | |
39 | static struct dangling_entry *get_de() { | |
9c610068 | 40 | return nsmalloc(POOL_AUTHTRACKER, sizeof(struct dangling_entry)); |
84563ebd | 41 | } |
42 | ||
43 | static void free_de(struct dangling_entry *dep) { | |
9c610068 | 44 | nsfree(POOL_AUTHTRACKER, dep); |
84563ebd | 45 | } |
46 | ||
47 | void at_lostnick(unsigned int numeric, unsigned long userid, time_t accountts, time_t losttime, int reason) { | |
48 | unsigned int server=homeserver(numeric); | |
49 | unsigned int i; | |
50 | struct dangling_entry *dep; | |
51 | unsigned int thehash=dangling_hash(numeric); | |
52 | ||
53 | /* If their server doesn't have an entry, make one. */ | |
54 | if (!ds[server]) { | |
55 | ds[server]=nsmalloc(POOL_AUTHTRACKER, sizeof(struct dangling_server)); | |
56 | for (i=0;i<DANGLING_HASHSIZE;i++) | |
57 | ds[server]->de[i]=NULL; | |
58 | } | |
59 | ||
60 | /* Now make an entry */ | |
61 | dep=get_de(); | |
62 | dep->numeric=numeric; | |
63 | dep->userid=userid; | |
64 | dep->authts=accountts; | |
65 | dep->losttime=losttime; | |
66 | dep->reason=reason; | |
67 | dep->next=ds[server]->de[thehash]; | |
68 | ds[server]->de[thehash]=dep; | |
69 | } | |
70 | ||
71 | /* Removes a returning user from the "dangling" tables. Return 1 if we found it, 0 otherwise. */ | |
72 | int at_foundnick(unsigned int numeric, unsigned long userid, time_t accountts) { | |
73 | unsigned int server=homeserver(numeric); | |
74 | struct dangling_entry *dep, **deh; | |
75 | unsigned int thehash=dangling_hash(numeric); | |
76 | ||
77 | /* If we've not got an entry for their server we certainly won't for them. */ | |
78 | if (!ds[server]) | |
79 | return 0; | |
80 | ||
81 | for (deh=&(ds[server]->de[thehash]); *deh; deh=&((*deh)->next)) { | |
82 | dep=*deh; | |
83 | if ((dep->numeric == numeric) && (dep->userid==userid) && (dep->authts==accountts)) { | |
84 | /* Got it */ | |
85 | *deh=dep->next; | |
86 | free_de(dep); | |
87 | return 1; | |
88 | } | |
89 | } | |
90 | ||
91 | /* Dropped through - didn't find it */ | |
92 | return 0; | |
93 | } | |
94 | ||
95 | /* When a server is back (fully linked), any remaining dangling users on that server are definately gone. */ | |
96 | void at_serverback(unsigned int server) { | |
97 | int i; | |
98 | struct dangling_entry *dep, *ndep; | |
99 | ||
100 | if (!ds[server]) | |
101 | return; | |
102 | ||
103 | for (i=0;i<DANGLING_HASHSIZE;i++) { | |
104 | for (dep=ds[server]->de[i];dep;dep=ndep) { | |
105 | ndep=dep->next; | |
106 | ||
107 | at_logquit(dep->userid, dep->authts, time(NULL), (dep->reason==AT_NETSPLIT)? "(netsplit)" : "(restart)"); | |
108 | free_de(dep); | |
109 | } | |
110 | } | |
111 | ||
112 | nsfree(POOL_AUTHTRACKER, ds[server]); | |
113 | ds[server]=NULL; | |
114 | } | |
115 | ||
116 | void at_flushghosts() { | |
117 | int i; | |
118 | ||
119 | for (i=0;i<MAXSERVERS;i++) { | |
120 | if (serverlist[i].linkstate == LS_LINKED) | |
121 | at_serverback(i); | |
122 | } | |
123 | } | |
2aaa684c | 124 | |
125 | int at_dumpdb(void *source, int argc, char **argv) { | |
126 | nick *np=source; | |
127 | struct dangling_entry *dep; | |
128 | unsigned int i,j,k; | |
129 | ||
130 | for(i=0;i<MAXSERVERS;i++) { | |
131 | if (ds[i]) { | |
132 | k=0; | |
133 | for(j=0;j<DANGLING_HASHSIZE;j++) { | |
134 | for (dep=ds[i]->de[j];dep;dep=dep->next) { | |
135 | k++; | |
136 | } | |
137 | } | |
138 | chanservsendmessage(np, "Server %d (%s) has %d entries.",i,longtonumeric(i,2),k); | |
139 | } | |
140 | } | |
141 | ||
142 | chanservstdmessage(np,QM_ENDOFLIST); | |
143 | ||
144 | return CMD_OK; | |
9c610068 | 145 | } |