ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/watch.c
Revision: 879
Committed: Thu Oct 25 08:03:01 2007 UTC (17 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/watch.c
File size: 6663 byte(s)
Log Message:
svn propset svn:keywords

File Contents

# User Rev Content
1 michael 876 /*
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 michael 879 * \version $Id$
26 michael 876 */
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