ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/watch.c
Revision: 5347
Committed: Sun Jan 11 12:42:20 2015 UTC (10 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 6232 byte(s)
Log Message:
- Update copyright years

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 5347 * Copyright (c) 2005-2015 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     /*! \file watch.c
24     * \brief File including functions for WATCH support
25 michael 879 * \version $Id$
26 michael 876 */
27    
28     #include "stdinc.h"
29 michael 1011 #include "list.h"
30 michael 876 #include "client.h"
31     #include "hash.h"
32     #include "irc_string.h"
33     #include "ircd.h"
34     #include "numeric.h"
35 michael 1309 #include "conf.h"
36 michael 876 #include "send.h"
37 michael 1654 #include "mempool.h"
38 michael 876 #include "watch.h"
39    
40    
41     static dlink_list watchTable[HASHSIZE];
42 michael 3250 static mp_pool_t *watch_pool;
43 michael 876
44     /*! \brief Initializes the watch table
45     */
46     void
47     watch_init(void)
48     {
49 michael 1654 watch_pool = mp_pool_new(sizeof(struct Watch), MP_CHUNK_SIZE_WATCH);
50 michael 876 }
51    
52     /*
53     * Rough figure of the datastructures for watch:
54     *
55     * NOTIFY HASH client_p1
56     * | |- nick1
57     * nick1-|- client_p1 |- nick2
58     * | |- client_p2 client_p3
59     * | |- client_p3 client_p2 |- nick1
60     * | |- nick1
61     * nick2-|- client_p2 |- nick2
62     * |- client_p1
63     */
64    
65     /*! \brief Counts up memory used by watch list headers
66     */
67     void
68 michael 2297 watch_count_memory(unsigned int *const count, uint64_t *const bytes)
69 michael 876 {
70 michael 3250 for (unsigned int i = 0; i < HASHSIZE; ++i)
71     (*count) += dlink_list_length(&watchTable[i]);
72 michael 876
73 michael 2297 (*bytes) = *count * sizeof(struct Watch);
74 michael 876 }
75    
76     /*! \brief Notifies all clients that have client_p's nick name on
77     * their watch list.
78 michael 2855 * \param client_p Pointer to Client struct
79     * \param reply Numeric to send. Either RPL_LOGON or RPL_LOGOFF
80 michael 876 */
81     void
82 michael 4785 watch_check_hash(const struct Client *client_p, const enum irc_numerics reply)
83 michael 876 {
84 michael 4815 struct Watch *watch = NULL;
85 michael 4800 dlink_node *node = NULL;
86 michael 3250
87 michael 876 assert(IsClient(client_p));
88 michael 3250
89 michael 4815 if ((watch = watch_find_hash(client_p->name)) == NULL)
90 michael 2855 return; /* This nick isn't on watch */
91 michael 876
92 michael 1359 /* Update the time of last change to item */
93 michael 4815 watch->lasttime = CurrentTime;
94 michael 876
95 michael 1359 /* Send notifies out to everybody on the list in header */
96 michael 4815 DLINK_FOREACH(node, watch->watched_by.head)
97 michael 4800 sendto_one_numeric(node->data, &me, reply, client_p->name,
98 michael 3109 client_p->username, client_p->host,
99 michael 4815 watch->lasttime, client_p->info);
100 michael 876 }
101    
102     /*! \brief Looks up the watch table for a given nick
103 michael 2855 * \param name Nick name to look up
104 michael 876 */
105     struct Watch *
106     watch_find_hash(const char *name)
107     {
108 michael 4800 dlink_node *node = NULL;
109 michael 876
110 michael 4800 DLINK_FOREACH(node, watchTable[strhash(name)].head)
111 michael 876 {
112 michael 4815 struct Watch *watch = node->data;
113 michael 876
114 michael 4815 if (!irccmp(watch->nick, name))
115     return watch;
116 michael 876 }
117    
118     return NULL;
119     }
120    
121     /*! \brief Adds a watch entry to client_p's watch list
122 michael 2855 * \param nick Nick name to add
123 michael 876 * \param client_p Pointer to Client struct
124     */
125     void
126     watch_add_to_hash_table(const char *nick, struct Client *client_p)
127     {
128 michael 4815 struct Watch *watch = NULL;
129 michael 4800 dlink_node *node = NULL;
130 michael 876
131 michael 1359 /* If found NULL (no header for this nick), make one... */
132 michael 4815 if ((watch = watch_find_hash(nick)) == NULL)
133 michael 876 {
134 michael 4815 watch = mp_pool_get(watch_pool);
135 michael 3250
136 michael 4815 watch->lasttime = CurrentTime;
137     strlcpy(watch->nick, nick, sizeof(watch->nick));
138 michael 876
139 michael 4815 dlinkAdd(watch, &watch->node, &watchTable[strhash(watch->nick)]);
140 michael 876 }
141     else
142     {
143 michael 1359 /* Is this client already on the watch-list? */
144 michael 4815 node = dlinkFind(&watch->watched_by, client_p);
145 michael 876 }
146    
147 michael 4800 if (node == NULL)
148 michael 876 {
149 michael 4728 /* No it isn't, so add it in the bucket and client adding it */
150 michael 4815 dlinkAdd(client_p, make_dlink_node(), &watch->watched_by);
151     dlinkAdd(watch, make_dlink_node(), &client_p->connection->watches);
152 michael 876 }
153     }
154    
155     /*! \brief Removes a single entry from client_p's watch list
156 michael 2855 * \param nick Nick name to remove
157 michael 876 * \param client_p Pointer to Client struct
158     */
159     void
160     watch_del_from_hash_table(const char *nick, struct Client *client_p)
161     {
162 michael 4815 struct Watch *watch = NULL;
163 michael 4800 dlink_node *node = NULL;
164 michael 876
165 michael 4815 if ((watch = watch_find_hash(nick)) == NULL)
166 michael 2855 return; /* No header found for that nick. i.e. it's not being watched */
167 michael 876
168 michael 4815 if ((node = dlinkFind(&watch->watched_by, client_p)) == NULL)
169 michael 2855 return; /* This nick isn't being watched by client_p */
170 michael 876
171 michael 4815 dlinkDelete(node, &watch->watched_by);
172 michael 4800 free_dlink_node(node);
173 michael 876
174 michael 4815 if ((node = dlinkFindDelete(&client_p->connection->watches, watch)))
175 michael 4800 free_dlink_node(node);
176 michael 876
177 michael 1359 /* In case this header is now empty of notices, remove it */
178 michael 4815 if (watch->watched_by.head == NULL)
179 michael 876 {
180 michael 4815 assert(dlinkFind(&watchTable[strhash(watch->nick)], watch));
181     dlinkDelete(&watch->node, &watchTable[strhash(watch->nick)]);
182     mp_pool_release(watch);
183 michael 876 }
184     }
185    
186     /*! \brief Removes all entries from client_p's watch list
187     * and deletes headers that are no longer being watched.
188     * \param client_p Pointer to Client struct
189     */
190     void
191     watch_del_watch_list(struct Client *client_p)
192     {
193 michael 4800 dlink_node *node = NULL, *node_next = NULL;
194     dlink_node *temp = NULL;
195 michael 876
196 michael 4800 DLINK_FOREACH_SAFE(node, node_next, client_p->connection->watches.head)
197 michael 876 {
198 michael 4815 struct Watch *watch = node->data;
199 michael 876
200 michael 4815 assert(dlinkFind(&watch->watched_by, client_p));
201 michael 876
202 michael 4815 if ((temp = dlinkFindDelete(&watch->watched_by, client_p)))
203 michael 4800 free_dlink_node(temp);
204 michael 876
205 michael 1359 /* If this leaves a header without notifies, remove it. */
206 michael 4815 if (watch->watched_by.head == NULL)
207 michael 876 {
208 michael 4815 assert(dlinkFind(&watchTable[strhash(watch->nick)], watch));
209     dlinkDelete(&watch->node, &watchTable[strhash(watch->nick)]);
210 michael 876
211 michael 4815 mp_pool_release(watch);
212 michael 876 }
213    
214 michael 4800 dlinkDelete(node, &client_p->connection->watches);
215     free_dlink_node(node);
216 michael 876 }
217    
218 michael 4588 assert(client_p->connection->watches.head == NULL);
219     assert(client_p->connection->watches.tail == NULL);
220 michael 876 }

Properties

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