ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/watch.c
Revision: 1309
Committed: Sun Mar 25 11:24:18 2012 UTC (14 years, 6 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/watch.c
File size: 6527 byte(s)
Log Message:
- renaming files:

  ircd_parser.y -> conf_parser.y
  ircd_lexer.l  -> conf_lexer.l
  s_conf.c      -> conf.c
  s_conf.h      -> conf.h
  s_log.c       -> log.c
  s_log.h       -> log.h

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

Properties

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