ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/whowas.c
Revision: 9101
Committed: Wed Jan 1 09:58:45 2020 UTC (5 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 5965 byte(s)
Log Message:
- Bump copyright years everywhere

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2020 ircd-hybrid development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 /*! \file whowas.c
23 * \brief WHOWAS user cache.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "memory.h"
30 #include "whowas.h"
31 #include "client.h"
32 #include "hash.h"
33 #include "irc_string.h"
34 #include "ircd.h"
35 #include "conf.h"
36
37
38 static dlink_list whowas_list; /*! Chain of struct Whowas pointers */
39 static dlink_list whowas_hash[HASHSIZE];
40
41
42 /*! \brief Returns a slot of the whowas_hash by the hash value associated with it.
43 * \param hash_value Hash value.
44 */
45 const dlink_list *
46 whowas_get_hash(unsigned int hash_value)
47 {
48 if (hash_value >= HASHSIZE)
49 return NULL;
50
51 return &whowas_hash[hash_value];
52 }
53
54 /*! \brief Unlinks a Whowas struct from its associated lists.
55 * \param whowas Pointer to Whowas struct to be unlinked.
56 */
57 static struct Whowas *
58 whowas_unlink(struct Whowas *whowas)
59 {
60 if (whowas->online)
61 dlinkDelete(&whowas->cnode, &whowas->online->whowas_list);
62
63 dlinkDelete(&whowas->hnode, &whowas_hash[whowas->hash_value]);
64 dlinkDelete(&whowas->lnode, &whowas_list);
65
66 return whowas;
67 }
68
69 /*! \brief Unlinks a Whowas struct from its associated lists
70 * and frees memory.
71 * \param whowas Pointer to Whowas struct to be unlinked and freed.
72 */
73 static void
74 whowas_free(struct Whowas *whowas)
75 {
76 whowas_unlink(whowas);
77 xfree(whowas);
78 }
79
80 /*! \brief Returns a Whowas struct for further use. Either allocates
81 * a new one, or returns the oldest entry from the whowas_list
82 * if it ran over ConfigGeneral.whowas_history_length
83 */
84 static struct Whowas *
85 whowas_make(void)
86 {
87 struct Whowas *whowas;
88
89 if (dlink_list_length(&whowas_list) &&
90 dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
91 whowas = whowas_unlink(whowas_list.tail->data); /* Re-use oldest item */
92 else
93 whowas = xcalloc(sizeof(*whowas));
94
95 return whowas;
96 }
97
98 /*! \brief Trims the whowas_list if necessary until there are no
99 * more than ConfigGeneral.whowas_history_length Whowas
100 * struct items.
101 */
102 void
103 whowas_trim(void)
104 {
105 while (dlink_list_length(&whowas_list) &&
106 dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
107 whowas_free(whowas_list.tail->data);
108 }
109
110 /*! \brief Adds the currently defined name of the client to history.
111 * Usually called before changing to a new name (nick).
112 * Client must be a fully registered user.
113 * \param client_p Pointer to Client struct to add to whowas history
114 * \param online Either 1 if it's a nick change or 0 on client exit
115 */
116 void
117 whowas_add_history(struct Client *client_p, bool online)
118 {
119 struct Whowas *whowas = whowas_make();
120
121 assert(IsClient(client_p));
122
123 whowas->hash_value = strhash(client_p->name);
124 whowas->logoff = event_base->time.sec_real;
125 whowas->server_hidden = IsHidden(client_p->servptr) != 0;
126
127 strlcpy(whowas->account, client_p->account, sizeof(whowas->account));
128 strlcpy(whowas->name, client_p->name, sizeof(whowas->name));
129 strlcpy(whowas->username, client_p->username, sizeof(whowas->username));
130 strlcpy(whowas->hostname, client_p->host, sizeof(whowas->hostname));
131 strlcpy(whowas->realhost, client_p->realhost, sizeof(whowas->realhost));
132 strlcpy(whowas->sockhost, client_p->sockhost, sizeof(whowas->sockhost));
133 strlcpy(whowas->realname, client_p->info, sizeof(whowas->realname));
134 strlcpy(whowas->servername, client_p->servptr->name, sizeof(whowas->servername));
135
136 if (online == true)
137 {
138 whowas->online = client_p;
139 dlinkAdd(whowas, &whowas->cnode, &client_p->whowas_list);
140 }
141 else
142 whowas->online = NULL;
143
144 dlinkAdd(whowas, &whowas->hnode, &whowas_hash[whowas->hash_value]);
145 dlinkAdd(whowas, &whowas->lnode, &whowas_list);
146 }
147
148 /*! \brief This must be called when the client structure is about to
149 * be released. History mechanism keeps pointers to client
150 * structures and it must know when they cease to exist.
151 * \param client_p Pointer to Client struct
152 */
153 void
154 whowas_off_history(struct Client *client_p)
155 {
156 while (client_p->whowas_list.head)
157 {
158 struct Whowas *whowas = client_p->whowas_list.head->data;
159
160 whowas->online = NULL;
161 dlinkDelete(&whowas->cnode, &client_p->whowas_list);
162 }
163 }
164
165 /*! \brief Returns the current client that was using the given
166 * nickname within the timelimit. Returns NULL, if no
167 * one found.
168 * \param name Name of the nick
169 * \param timelimit Maximum age for a client since log-off
170 */
171 struct Client *
172 whowas_get_history(const char *name, uintmax_t timelimit)
173 {
174 dlink_node *node;
175
176 timelimit = event_base->time.sec_real - timelimit;
177
178 DLINK_FOREACH(node, whowas_hash[strhash(name)].head)
179 {
180 struct Whowas *whowas = node->data;
181
182 if (whowas->logoff < timelimit)
183 continue;
184 if (irccmp(name, whowas->name))
185 continue;
186 return whowas->online;
187 }
188
189 return NULL;
190 }
191
192 /*! \brief For debugging. Counts allocated structures stored in whowas_list
193 */
194 void
195 whowas_count_memory(unsigned int *const count, size_t *const bytes)
196 {
197 (*count) = dlink_list_length(&whowas_list);
198 (*bytes) = dlink_list_length(&whowas_list) * sizeof(struct Whowas);
199 }

Properties

Name Value
svn:eol-style native
svn:keywords Id