ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/whowas.c
Revision: 7924
Committed: Sat Dec 31 13:57:08 2016 UTC (8 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 6044 byte(s)
Log Message:
- Update copyright years

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2017 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 "mempool.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 mp_pool_t *whowas_pool;
39
40 static dlink_list whowas_list; /*! Chain of struct Whowas pointers */
41 static dlink_list whowas_hash[HASHSIZE];
42
43
44 /*! \brief Initializes the whowas memory pool.
45 */
46 void
47 whowas_init(void)
48 {
49 whowas_pool = mp_pool_new(sizeof(struct Whowas), MP_CHUNK_SIZE_WHOWAS);
50 }
51
52 /*! \brief Returns a slot of the whowas_hash by the hash value associated with it.
53 * \param hashv Hash value.
54 */
55 const dlink_list *
56 whowas_get_hash(unsigned int hashv)
57 {
58 if (hashv >= HASHSIZE)
59 return NULL;
60
61 return &whowas_hash[hashv];
62 }
63
64 /*! \brief Unlinks a Whowas struct from its associated lists.
65 * \param whowas Pointer to Whowas struct to be unlinked.
66 */
67 static struct Whowas *
68 whowas_unlink(struct Whowas *whowas)
69 {
70 if (whowas->online)
71 dlinkDelete(&whowas->cnode, &whowas->online->whowas_list);
72
73 dlinkDelete(&whowas->hnode, &whowas_hash[whowas->hashv]);
74 dlinkDelete(&whowas->lnode, &whowas_list);
75
76 return whowas;
77 }
78
79 /*! \brief Unlinks a Whowas struct from its associated lists
80 * and returns memory back to the pooling allocator.
81 * \param whowas Pointer to Whowas struct to be unlinked and freed.
82 */
83 static void
84 whowas_free(struct Whowas *whowas)
85 {
86 whowas_unlink(whowas);
87 mp_pool_release(whowas);
88 }
89
90 /*! \brief Returns a Whowas struct for further use. Either allocates
91 * a new one, or returns the oldest entry from the whowas_list
92 * if it ran over ConfigGeneral.whowas_history_length
93 */
94 static struct Whowas *
95 whowas_make(void)
96 {
97 struct Whowas *whowas;
98
99 if (dlink_list_length(&whowas_list) &&
100 dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
101 whowas = whowas_unlink(whowas_list.tail->data); /* Re-use oldest item */
102 else
103 whowas = mp_pool_get(whowas_pool);
104
105 return whowas;
106 }
107
108 /*! \brief Trims the whowas_list if necessary until there are no
109 * more than ConfigGeneral.whowas_history_length Whowas
110 * struct items.
111 */
112 void
113 whowas_trim(void)
114 {
115 while (dlink_list_length(&whowas_list) &&
116 dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
117 whowas_free(whowas_list.tail->data);
118 }
119
120 /*! \brief Adds the currently defined name of the client to history.
121 * Usually called before changing to a new name (nick).
122 * Client must be a fully registered user.
123 * \param client_p Pointer to Client struct to add to whowas history
124 * \param online Either 1 if it's a nick change or 0 on client exit
125 */
126 void
127 whowas_add_history(struct Client *client_p, const int online)
128 {
129 struct Whowas *whowas = whowas_make();
130
131 assert(IsClient(client_p));
132
133 whowas->hashv = strhash(client_p->name);
134 whowas->shide = IsHidden(client_p->servptr) != 0;
135 whowas->logoff = CurrentTime;
136
137 strlcpy(whowas->account, client_p->account, sizeof(whowas->account));
138 strlcpy(whowas->name, client_p->name, sizeof(whowas->name));
139 strlcpy(whowas->username, client_p->username, sizeof(whowas->username));
140 strlcpy(whowas->hostname, client_p->host, sizeof(whowas->hostname));
141 strlcpy(whowas->sockhost, client_p->sockhost, sizeof(whowas->sockhost));
142 strlcpy(whowas->realname, client_p->info, sizeof(whowas->realname));
143 strlcpy(whowas->servername, client_p->servptr->name, sizeof(whowas->servername));
144
145 if (online)
146 {
147 whowas->online = client_p;
148 dlinkAdd(whowas, &whowas->cnode, &client_p->whowas_list);
149 }
150 else
151 whowas->online = NULL;
152
153 dlinkAdd(whowas, &whowas->hnode, &whowas_hash[whowas->hashv]);
154 dlinkAdd(whowas, &whowas->lnode, &whowas_list);
155 }
156
157 /*! \brief This must be called when the client structure is about to
158 * be released. History mechanism keeps pointers to client
159 * structures and it must know when they cease to exist.
160 * \param client_p Pointer to Client struct
161 */
162 void
163 whowas_off_history(struct Client *client_p)
164 {
165 while (client_p->whowas_list.head)
166 {
167 struct Whowas *whowas = client_p->whowas_list.head->data;
168
169 whowas->online = NULL;
170 dlinkDelete(&whowas->cnode, &client_p->whowas_list);
171 }
172 }
173
174 /*! \brief Returns the current client that was using the given
175 * nickname within the timelimit. Returns NULL, if no
176 * one found.
177 * \param name Name of the nick
178 * \param timelimit Maximum age for a client since log-off
179 */
180 struct Client *
181 whowas_get_history(const char *name, uintmax_t timelimit)
182 {
183 dlink_node *node;
184
185 timelimit = CurrentTime - timelimit;
186
187 DLINK_FOREACH(node, whowas_hash[strhash(name)].head)
188 {
189 struct Whowas *whowas = node->data;
190
191 if (whowas->logoff < timelimit)
192 continue;
193 if (irccmp(name, whowas->name))
194 continue;
195 return whowas->online;
196 }
197
198 return NULL;
199 }
200
201 /*! \brief For debugging. Counts allocated structures stored in whowas_list
202 */
203 void
204 whowas_count_memory(unsigned int *const count, size_t *const bytes)
205 {
206 (*count) = dlink_list_length(&whowas_list);
207 (*bytes) = dlink_list_length(&whowas_list) * sizeof(struct Whowas);
208 }

Properties

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