/[svn]/ircd-hybrid-7.2/src/watch.c
ViewVC logotype

Contents of /ircd-hybrid-7.2/src/watch.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 879 - (show annotations)
Thu Oct 25 08:03:01 2007 UTC (12 years, 9 months ago) by michael
File MIME type: text/x-chdr
File size: 6663 byte(s)
svn propset svn:keywords
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 *
4 * Copyright (C) 1997 Jukka Santala (Donwulff)
5 * Copyright (C) 2005 by the 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
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 "tools.h"
30 #include "s_user.h"
31 #include "s_misc.h"
32 #include "client.h"
33 #include "common.h"
34 #include "hash.h"
35 #include "irc_string.h"
36 #include "sprintf_irc.h"
37 #include "ircd.h"
38 #include "list.h"
39 #include "listener.h"
40 #include "motd.h"
41 #include "numeric.h"
42 #include "s_conf.h"
43 #include "s_log.h"
44 #include "s_serv.h"
45 #include "s_stats.h"
46 #include "send.h"
47 #include "supported.h"
48 #include "whowas.h"
49 #include "memory.h"
50 #include "packet.h"
51 #include "s_misc.h"
52 #include "msg.h"
53 #include "watch.h"
54
55 #define WATCH_HEAP_SIZE 32
56
57 static dlink_list watchTable[HASHSIZE];
58
59 static BlockHeap *watch_heap = NULL;
60
61 /*! \brief Initializes the watch table
62 */
63 void
64 watch_init(void)
65 {
66 memset(watchTable, 0, sizeof(watchTable));
67
68 watch_heap = BlockHeapCreate("watch", sizeof(struct Watch), WATCH_HEAP_SIZE);
69 }
70
71 /*
72 * Rough figure of the datastructures for watch:
73 *
74 * NOTIFY HASH client_p1
75 * | |- nick1
76 * nick1-|- client_p1 |- nick2
77 * | |- client_p2 client_p3
78 * | |- client_p3 client_p2 |- nick1
79 * | |- nick1
80 * nick2-|- client_p2 |- nick2
81 * |- client_p1
82 */
83
84 /*! \brief Counts up memory used by watch list headers
85 */
86 void
87 watch_count_memory(unsigned int *const count, size_t *const memory)
88 {
89 unsigned int idx;
90
91 for (idx = 0; idx < HASHSIZE; ++idx)
92 *count += dlink_list_length(&watchTable[idx]);
93
94 *memory = *count * sizeof(struct Watch);
95 }
96
97 /*! \brief Notifies all clients that have client_p's nick name on
98 * their watch list.
99 * \param client_p pointer to Client struct
100 * \param reply numeric to send. Either RPL_LOGON or RPL_LOGOFF
101 */
102 void
103 watch_check_hash(struct Client *client_p, int reply)
104 {
105 struct Watch *anptr = NULL;
106 dlink_node *ptr = NULL;
107 assert(IsClient(client_p));
108 if ((anptr = watch_find_hash(client_p->name)) == NULL)
109 return; // This nick isn't on watch
110
111 // Update the time of last change to item
112 anptr->lasttime = CurrentTime;
113
114 // Send notifies out to everybody on the list in header
115 DLINK_FOREACH(ptr, anptr->watched_by.head)
116 {
117 struct Client *target_p = ptr->data;
118
119 sendto_one(target_p, form_str(reply),
120 me.name, target_p->name, client_p->name,
121 client_p->username, client_p->host,
122 anptr->lasttime, client_p->info);
123 }
124 }
125
126 /*! \brief Looks up the watch table for a given nick
127 * \param name nick name to look up
128 */
129 struct Watch *
130 watch_find_hash(const char *name)
131 {
132 dlink_node *ptr = NULL;
133
134 DLINK_FOREACH(ptr, watchTable[strhash(name)].head)
135 {
136 struct Watch *anptr = ptr->data;
137
138 if (!irccmp(anptr->nick, name))
139 return anptr;
140 }
141
142 return NULL;
143 }
144
145 /*! \brief Adds a watch entry to client_p's watch list
146 * \param nick nick name to add
147 * \param client_p Pointer to Client struct
148 */
149 void
150 watch_add_to_hash_table(const char *nick, struct Client *client_p)
151 {
152 struct Watch *anptr = NULL;
153 dlink_node *ptr = NULL;
154
155 // If found NULL (no header for this nick), make one...
156 if ((anptr = watch_find_hash(nick)) == NULL)
157 {
158 anptr = BlockHeapAlloc(watch_heap);
159 anptr->lasttime = CurrentTime;
160 strlcpy(anptr->nick, nick, sizeof(anptr->nick));
161
162 dlinkAdd(anptr, &anptr->node, &watchTable[strhash(nick)]);
163 }
164 else
165 {
166 // Is this client already on the watch-list?
167 ptr = dlinkFind(&anptr->watched_by, client_p);
168 }
169
170 if (ptr == NULL)
171 {
172 // No it isn't, so add it in the bucket and client addint it
173 dlinkAdd(client_p, make_dlink_node(), &anptr->watched_by);
174 dlinkAdd(anptr, make_dlink_node(), &client_p->localClient->watches);
175 }
176 }
177
178 /*! \brief Removes a single entry from client_p's watch list
179 * \param nick nick name to remove
180 * \param client_p Pointer to Client struct
181 */
182 void
183 watch_del_from_hash_table(const char *nick, struct Client *client_p)
184 {
185 struct Watch *anptr = NULL;
186 dlink_node *ptr = NULL;
187
188 if ((anptr = watch_find_hash(nick)) == NULL)
189 return; // No header found for that nick. i.e. it's not being watched
190
191 if ((ptr = dlinkFind(&anptr->watched_by, client_p)) == NULL)
192 return; // This nick isn't being watched by client_p
193
194 dlinkDelete(ptr, &anptr->watched_by);
195 free_dlink_node(ptr);
196
197 if ((ptr = dlinkFindDelete(&client_p->localClient->watches, anptr)))
198 free_dlink_node(ptr);
199
200 // In case this header is now empty of notices, remove it
201 if (anptr->watched_by.head == NULL)
202 {
203 assert(dlinkFind(&watchTable[strhash(nick)], anptr) != NULL);
204 dlinkDelete(&anptr->node, &watchTable[strhash(nick)]);
205 BlockHeapFree(watch_heap, anptr);
206 }
207 }
208
209 /*! \brief Removes all entries from client_p's watch list
210 * and deletes headers that are no longer being watched.
211 * \param client_p Pointer to Client struct
212 */
213 void
214 watch_del_watch_list(struct Client *client_p)
215 {
216 dlink_node *ptr = NULL, *ptr_next = NULL;
217 dlink_node *tmp = NULL;
218
219 DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->watches.head)
220 {
221 struct Watch *anptr = ptr->data;
222
223 assert(anptr);
224
225 assert(dlinkFind(&anptr->watched_by, client_p) != NULL);
226 if ((tmp = dlinkFindDelete(&anptr->watched_by, client_p)))
227 free_dlink_node(tmp);
228
229 // If this leaves a header without notifies, remove it.
230 if (anptr->watched_by.head == NULL)
231 {
232 assert(dlinkFind(&watchTable[strhash(anptr->nick)], anptr) != NULL);
233 dlinkDelete(&anptr->node, &watchTable[strhash(anptr->nick)]);
234
235 BlockHeapFree(watch_heap, anptr);
236 }
237
238 dlinkDelete(ptr, &client_p->localClient->watches);
239 free_dlink_node(ptr);
240 }
241
242 assert(client_p->localClient->watches.head == NULL);
243 assert(client_p->localClient->watches.tail == NULL);
244 }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28