ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/watch.c
Revision: 1028
Committed: Sun Nov 8 13:03:38 2009 UTC (14 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 6549 byte(s)
Log Message:
- move ircd-hybrid-7.2 to trunk

File Contents

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

Properties

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