ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/watch.c
Revision: 1592
Committed: Sat Oct 27 21:02:32 2012 UTC (12 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 6511 byte(s)
Log Message:
- Second time's the charm? Moving svnroot/ircd-hybrid-8 to
  svnroot/ircd-hybrid/trunk

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

Properties

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