ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/monitor.c
Revision: 9769
Committed: Wed Dec 2 18:46:55 2020 UTC (5 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 6841 byte(s)
Log Message:
- monitor.c:monitor_count_memory(): add +1 for '\0'

File Contents

# User Rev Content
1 michael 876 /*
2 michael 2855 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 michael 876 *
4 michael 2855 * Copyright (c) 1997 Jukka Santala (Donwulff)
5 michael 9101 * Copyright (c) 2005-2020 ircd-hybrid development team
6 michael 876 *
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 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20 michael 876 * USA
21     */
22    
23 michael 9750 /*! \file monitor.c
24     * \brief File including functions for MONITOR support
25 michael 879 * \version $Id$
26 michael 876 */
27    
28     #include "stdinc.h"
29 michael 1011 #include "list.h"
30 michael 8385 #include "memory.h"
31 michael 876 #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 michael 9750 #include "monitor.h"
38 michael 876
39    
40 michael 9762 static dlink_list monitor_hash[HASHSIZE];
41 michael 876
42    
43     /*
44 michael 9750 * Rough figure of the datastructures for monitor:
45 michael 876 *
46 michael 9750 * MONITOR HASH client1
47 michael 9250 * | |- nick1
48     * nick1-|- client1 |- nick2
49     * | |- client2 client3
50     * | |- client3 client2 |- nick1
51     * | |- nick1
52     * nick2-|- client2 |- nick2
53     * |- client1
54 michael 876 */
55    
56 michael 9750 /*! \brief Counts up memory used by monitor list headers
57 michael 876 */
58     void
59 michael 9750 monitor_count_memory(unsigned int *const count, size_t *const bytes)
60 michael 876 {
61 michael 3250 for (unsigned int i = 0; i < HASHSIZE; ++i)
62 michael 9767 {
63     dlink_node *node;
64 michael 9762 (*count) += dlink_list_length(&monitor_hash[i]);
65 michael 876
66 michael 9767 DLINK_FOREACH(node, monitor_hash[i].head)
67     {
68     const struct Monitor *const monitor = node->data;
69 michael 9769 (*bytes) += strlen(monitor->name) + 1; /* +1 for '\0' */
70 michael 9767 }
71     }
72    
73     (*bytes) += *count * sizeof(struct Monitor);
74 michael 876 }
75    
76 michael 9250 /*! \brief Notifies all clients that have client's name on
77 michael 9750 * their monitor list.
78 michael 9250 * \param client Pointer to Client struct
79 michael 876 */
80     void
81 michael 9750 monitor_signon(const struct Client *client)
82 michael 876 {
83 michael 9750 char buf[NICKLEN + USERLEN + HOSTLEN + 3]; /* +3 for !, @, \0 */
84     dlink_node *node;
85 michael 3250
86 michael 9250 assert(IsClient(client));
87 michael 3250
88 michael 9750 struct Monitor *monitor = monitor_find_hash(client->name);
89     if (monitor == NULL)
90     return; /* This name isn't on monitor */
91 michael 876
92 michael 9750 snprintf(buf, sizeof(buf), "%s!%s@%s", client->name,
93     client->username, client->host);
94 michael 876
95 michael 1359 /* Send notifies out to everybody on the list in header */
96 michael 9750 DLINK_FOREACH(node, monitor->monitored_by.head)
97     sendto_one_numeric(node->data, &me, RPL_MONONLINE, buf);
98 michael 876 }
99    
100 michael 9750 /*! \brief Notifies all clients that have client's name on
101     * their monitor list.
102     * \param client Pointer to Client struct
103     */
104     void
105     monitor_signoff(const struct Client *client)
106     {
107     dlink_node *node;
108    
109     assert(IsClient(client));
110    
111     struct Monitor *monitor = monitor_find_hash(client->name);
112     if (monitor == NULL)
113     return; /* This name isn't on monitor */
114    
115     /* Send notifies out to everybody on the list in header */
116     DLINK_FOREACH(node, monitor->monitored_by.head)
117     sendto_one_numeric(node->data, &me, RPL_MONOFFLINE, client->name);
118     }
119    
120     /*! \brief Looks up the monitor table for a given name
121 michael 2855 * \param name Nick name to look up
122 michael 876 */
123 michael 9750 struct Monitor *
124     monitor_find_hash(const char *name)
125 michael 876 {
126 michael 9750 dlink_node *node;
127 michael 876
128 michael 9762 DLINK_FOREACH(node, monitor_hash[strhash(name)].head)
129 michael 876 {
130 michael 9750 struct Monitor *monitor = node->data;
131 michael 876
132 michael 9750 if (irccmp(monitor->name, name) == 0)
133     return monitor;
134 michael 876 }
135    
136     return NULL;
137     }
138    
139 michael 9754 /*! \brief Adds a monitor entry to client's monitor list if it doesn't exist
140 michael 9250 * \param name Nick name to add
141     * \param client Pointer to Client struct
142 michael 9754 * \return false if the target is already being monitored, true otherwise
143 michael 876 */
144 michael 9750 bool
145     monitor_add_to_hash_table(const char *name, struct Client *client)
146 michael 876 {
147 michael 4800 dlink_node *node = NULL;
148 michael 876
149 michael 7084 /* If found NULL (no header for this name), make one... */
150 michael 9750 struct Monitor *monitor = monitor_find_hash(name);
151     if (monitor == NULL)
152 michael 876 {
153 michael 9750 monitor = xcalloc(sizeof(*monitor));
154 michael 9767 monitor->name = xstrdup(name);
155 michael 9750 monitor->hash_value = strhash(monitor->name);
156 michael 876
157 michael 9762 dlinkAdd(monitor, &monitor->node, &monitor_hash[monitor->hash_value]);
158 michael 876 }
159     else
160     {
161 michael 9750 /* Is this client already on the monitor-list? */
162     node = dlinkFind(&monitor->monitored_by, client);
163 michael 876 }
164    
165 michael 4800 if (node == NULL)
166 michael 876 {
167 michael 4728 /* No it isn't, so add it in the bucket and client adding it */
168 michael 9750 dlinkAdd(client, make_dlink_node(), &monitor->monitored_by);
169     dlinkAdd(monitor, make_dlink_node(), &client->connection->monitors);
170     return true;
171 michael 876 }
172 michael 9750
173     return false;
174 michael 876 }
175    
176 michael 9750 /*! \brief Removes a single entry from client's monitor list
177 michael 9250 * \param name Name to remove
178     * \param client Pointer to Client struct
179 michael 876 */
180     void
181 michael 9750 monitor_del_from_hash_table(const char *name, struct Client *client)
182 michael 876 {
183 michael 9750 struct Monitor *monitor = monitor_find_hash(name);
184     if (monitor == NULL)
185     return; /* No header found for that name. i.e. it's not being monitored */
186 michael 876
187 michael 9750 dlink_node *node = dlinkFind(&monitor->monitored_by, client);
188     if (node == NULL)
189     return; /* This name isn't being monitored by client */
190 michael 876
191 michael 9750 dlinkDelete(node, &monitor->monitored_by);
192 michael 4800 free_dlink_node(node);
193 michael 876
194 michael 9750 node = dlinkFindDelete(&client->connection->monitors, monitor);
195     if (node)
196 michael 4800 free_dlink_node(node);
197 michael 876
198 michael 1359 /* In case this header is now empty of notices, remove it */
199 michael 9750 if (monitor->monitored_by.head == NULL)
200 michael 876 {
201 michael 9762 assert(dlinkFind(&monitor_hash[monitor->hash_value], monitor));
202     dlinkDelete(&monitor->node, &monitor_hash[monitor->hash_value]);
203 michael 9767
204     xfree(monitor->name);
205 michael 9750 xfree(monitor);
206 michael 876 }
207     }
208    
209 michael 9750 /*! \brief Removes all entries from client's monitor list
210     * and deletes headers that are no longer being monitored.
211 michael 9250 * \param client Pointer to Client struct
212 michael 876 */
213     void
214 michael 9750 monitor_clear_list(struct Client *client)
215 michael 876 {
216 michael 9750 dlink_node *node, *node_next;
217 michael 876
218 michael 9750 DLINK_FOREACH_SAFE(node, node_next, client->connection->monitors.head)
219 michael 876 {
220 michael 9750 struct Monitor *monitor = node->data;
221 michael 876
222 michael 9750 assert(dlinkFind(&monitor->monitored_by, client));
223 michael 876
224 michael 9750 dlink_node *temp = dlinkFindDelete(&monitor->monitored_by, client);
225     if (temp)
226 michael 4800 free_dlink_node(temp);
227 michael 876
228 michael 1359 /* If this leaves a header without notifies, remove it. */
229 michael 9750 if (monitor->monitored_by.head == NULL)
230 michael 876 {
231 michael 9762 assert(dlinkFind(&monitor_hash[monitor->hash_value], monitor));
232     dlinkDelete(&monitor->node, &monitor_hash[monitor->hash_value]);
233 michael 876
234 michael 9767 xfree(monitor->name);
235 michael 9750 xfree(monitor);
236 michael 876 }
237    
238 michael 9750 dlinkDelete(node, &client->connection->monitors);
239 michael 4800 free_dlink_node(node);
240 michael 876 }
241    
242 michael 9750 assert(client->connection->monitors.head == NULL);
243     assert(client->connection->monitors.tail == NULL);
244 michael 876 }

Properties

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