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, 4 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

# 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     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 michael 948 watch_count_memory(unsigned int *const count, uint64_t *const memory)
81 michael 876 {
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