ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/watch.c
Revision: 8385
Committed: Fri Mar 16 20:09:55 2018 UTC (7 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 6011 byte(s)
Log Message:
- Rip out mempool

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997 Jukka Santala (Donwulff)
5 * Copyright (c) 2005-2018 ircd-hybrid development team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20 * USA
21 */
22
23 /*! \file watch.c
24 * \brief File including functions for WATCH support
25 * \version $Id$
26 */
27
28 #include "stdinc.h"
29 #include "list.h"
30 #include "memory.h"
31 #include "client.h"
32 #include "hash.h"
33 #include "irc_string.h"
34 #include "ircd.h"
35 #include "numeric.h"
36 #include "send.h"
37 #include "watch.h"
38
39
40 static dlink_list watchTable[HASHSIZE];
41
42
43 /*
44 * Rough figure of the datastructures for watch:
45 *
46 * NOTIFY HASH client_p1
47 * | |- nick1
48 * nick1-|- client_p1 |- nick2
49 * | |- client_p2 client_p3
50 * | |- client_p3 client_p2 |- nick1
51 * | |- nick1
52 * nick2-|- client_p2 |- nick2
53 * |- client_p1
54 */
55
56 /*! \brief Counts up memory used by watch list headers
57 */
58 void
59 watch_count_memory(unsigned int *const count, size_t *const bytes)
60 {
61 for (unsigned int i = 0; i < HASHSIZE; ++i)
62 (*count) += dlink_list_length(&watchTable[i]);
63
64 (*bytes) = *count * sizeof(struct Watch);
65 }
66
67 /*! \brief Notifies all clients that have client_p's name on
68 * their watch list.
69 * \param client_p Pointer to Client struct
70 * \param reply Numeric to send. Either RPL_LOGON or RPL_LOGOFF
71 */
72 void
73 watch_check_hash(const struct Client *client_p, const enum irc_numerics reply)
74 {
75 struct Watch *watch = NULL;
76 dlink_node *node = NULL;
77
78 assert(IsClient(client_p));
79
80 if ((watch = watch_find_hash(client_p->name)) == NULL)
81 return; /* This name isn't on watch */
82
83 /* Update the time of last change to item */
84 watch->lasttime = CurrentTime;
85
86 /* Send notifies out to everybody on the list in header */
87 DLINK_FOREACH(node, watch->watched_by.head)
88 sendto_one_numeric(node->data, &me, reply, client_p->name,
89 client_p->username, client_p->host,
90 watch->lasttime, client_p->info);
91 }
92
93 /*! \brief Looks up the watch table for a given name
94 * \param name Nick name to look up
95 */
96 struct Watch *
97 watch_find_hash(const char *name)
98 {
99 dlink_node *node = NULL;
100
101 DLINK_FOREACH(node, watchTable[strhash(name)].head)
102 {
103 struct Watch *watch = node->data;
104
105 if (!irccmp(watch->name, name))
106 return watch;
107 }
108
109 return NULL;
110 }
111
112 /*! \brief Adds a watch entry to client_p's watch list
113 * \param name Nick name to add
114 * \param client_p Pointer to Client struct
115 */
116 void
117 watch_add_to_hash_table(const char *name, struct Client *client_p)
118 {
119 struct Watch *watch = NULL;
120 dlink_node *node = NULL;
121
122 /* If found NULL (no header for this name), make one... */
123 if ((watch = watch_find_hash(name)) == NULL)
124 {
125 watch = xcalloc(sizeof(*watch));
126
127 watch->lasttime = CurrentTime;
128 strlcpy(watch->name, name, sizeof(watch->name));
129
130 dlinkAdd(watch, &watch->node, &watchTable[strhash(watch->name)]);
131 }
132 else
133 {
134 /* Is this client already on the watch-list? */
135 node = dlinkFind(&watch->watched_by, client_p);
136 }
137
138 if (node == NULL)
139 {
140 /* No it isn't, so add it in the bucket and client adding it */
141 dlinkAdd(client_p, make_dlink_node(), &watch->watched_by);
142 dlinkAdd(watch, make_dlink_node(), &client_p->connection->watches);
143 }
144 }
145
146 /*! \brief Removes a single entry from client_p's watch list
147 * \param name Name to remove
148 * \param client_p Pointer to Client struct
149 */
150 void
151 watch_del_from_hash_table(const char *name, struct Client *client_p)
152 {
153 struct Watch *watch = NULL;
154 dlink_node *node = NULL;
155
156 if ((watch = watch_find_hash(name)) == NULL)
157 return; /* No header found for that name. i.e. it's not being watched */
158
159 if ((node = dlinkFind(&watch->watched_by, client_p)) == NULL)
160 return; /* This name isn't being watched by client_p */
161
162 dlinkDelete(node, &watch->watched_by);
163 free_dlink_node(node);
164
165 if ((node = dlinkFindDelete(&client_p->connection->watches, watch)))
166 free_dlink_node(node);
167
168 /* In case this header is now empty of notices, remove it */
169 if (watch->watched_by.head == NULL)
170 {
171 assert(dlinkFind(&watchTable[strhash(watch->name)], watch));
172 dlinkDelete(&watch->node, &watchTable[strhash(watch->name)]);
173 xfree(watch);
174 }
175 }
176
177 /*! \brief Removes all entries from client_p's watch list
178 * and deletes headers that are no longer being watched.
179 * \param client_p Pointer to Client struct
180 */
181 void
182 watch_del_watch_list(struct Client *client_p)
183 {
184 dlink_node *node = NULL, *node_next = NULL;
185 dlink_node *temp = NULL;
186
187 DLINK_FOREACH_SAFE(node, node_next, client_p->connection->watches.head)
188 {
189 struct Watch *watch = node->data;
190
191 assert(dlinkFind(&watch->watched_by, client_p));
192
193 if ((temp = dlinkFindDelete(&watch->watched_by, client_p)))
194 free_dlink_node(temp);
195
196 /* If this leaves a header without notifies, remove it. */
197 if (watch->watched_by.head == NULL)
198 {
199 assert(dlinkFind(&watchTable[strhash(watch->name)], watch));
200 dlinkDelete(&watch->node, &watchTable[strhash(watch->name)]);
201
202 xfree(watch);
203 }
204
205 dlinkDelete(node, &client_p->connection->watches);
206 free_dlink_node(node);
207 }
208
209 assert(client_p->connection->watches.head == NULL);
210 assert(client_p->connection->watches.tail == NULL);
211 }

Properties

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