ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/branches/ircd-hybrid-newconf/src/watch.c
Revision: 1027
Committed: Sun Nov 8 13:01:13 2009 UTC (14 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 6312 byte(s)
Log Message:
- Move old 7.3 sources to branches/ircd-hybrid-newconf

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

Properties

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