ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/m_tburst.c
Revision: 336
Committed: Mon Dec 26 18:31:08 2005 UTC (18 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 7233 byte(s)
Log Message:
- This should finally fix the TBURST issue as reported by
  ThaPrince. Untested as always

File Contents

# User Rev Content
1 michael 325 /* modules/m_tburst.c
2     * Copyright (C) 2002, 2003, 2004, 2005 Hybrid Development Team
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are
6     * met:
7     *
8     * 1.Redistributions of source code must retain the above copyright notice,
9     * this list of conditions and the following disclaimer.
10     * 2.Redistributions in binary form must reproduce the above copyright
11     * notice, this list of conditions and the following disclaimer in the
12     * documentation and/or other materials provided with the distribution.
13     * 3.The name of the author may not be used to endorse or promote products
14     * derived from this software without specific prior written permission.
15     *
16     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19     * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24     * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25     * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26     * POSSIBILITY OF SUCH DAMAGE.
27     *
28 michael 335 * $Id$
29 michael 325 */
30    
31     #include "stdinc.h"
32     #include "handlers.h"
33     #include "client.h"
34     #include "common.h"
35     #include "ircd.h"
36     #include "send.h"
37     #include "msg.h"
38     #include "modules.h"
39     #include "hash.h"
40     #include "s_serv.h"
41     #include "s_conf.h"
42    
43     static void ms_tb(struct Client *, struct Client *, int, char *[]);
44     static void ms_tburst(struct Client *, struct Client *, int, char *[]);
45 michael 335 static void set_topic(struct Client *, struct Channel *, time_t,
46     const char *, const char *);
47 michael 325
48     struct Message tburst_msgtab = {
49     "TBURST", 0, 0, 6, 0, MFLG_SLOW, 0,
50 michael 335 { m_ignore, m_ignore, ms_tburst, m_ignore, m_ignore, m_ignore }
51 michael 325 };
52    
53     struct Message tb_msgtab = {
54     "TB", 0, 0, 0, 0, MFLG_SLOW, 0,
55 michael 335 { m_ignore, m_ignore, ms_tb, m_ignore, m_ignore, m_ignore }
56 michael 325 };
57    
58     #ifndef STATIC_MODULES
59    
60     void
61     _modinit(void)
62     {
63     mod_add_cmd(&tb_msgtab);
64     add_capability("TB", CAP_TB, 1);
65    
66     mod_add_cmd(&tburst_msgtab);
67     add_capability("TBURST", CAP_TBURST, 1);
68     }
69    
70     void
71     _moddeinit(void)
72     {
73     mod_del_cmd(&tb_msgtab);
74     delete_capability("TB");
75    
76     mod_del_cmd(&tburst_msgtab);
77     delete_capability("TBURST");
78     }
79    
80     const char *_version = "$Revision: 122 $";
81    
82     #endif /* !STATIC_MODULES */
83    
84     /* ms_tburst()
85     *
86     * parv[0] = sender prefix
87     * parv[1] = channel timestamp
88     * parv[2] = channel
89     * parv[3] = topic timestamp
90     * parv[4] = topic setter
91     * parv[5] = topic
92     */
93     static void
94     ms_tburst(struct Client *client_p, struct Client *source_p,
95     int parc, char *parv[])
96     {
97     struct Channel *chptr = NULL;
98 michael 336 int accept_remote = 0;
99     time_t remote_channel_ts = atol(parv[1]);
100     time_t remote_topic_ts = atol(parv[3]);
101 michael 325
102 michael 336 /*
103     * Do NOT test parv[5] for an empty string and return if true!
104     * parv[5] CAN be an empty string, i.e. if the other side wants
105     * to unset our topic. Don't forget: an empty topic is also a
106     * valid topic.
107     */
108    
109    
110 michael 325 if ((chptr = hash_find_channel(parv[2])) == NULL)
111     return;
112    
113 michael 336 /*
114     * The logic for accepting and rejecting channel topics was
115     * always a bit hairy, so now we got exactly 2 cases where
116     * we would accept a bursted topic
117     *
118     * Case 1:
119     * The TS of the remote channel is older than ours
120     * Case 2:
121     * The TS of the remote channel is equal to ours AND
122     * the TS of the remote topic is newer than ours
123 michael 325 */
124 michael 336 if (remote_channel_ts < chptr->channelts)
125     accept_remote = 1;
126     else if (remote_channel_ts == chptr->channelts)
127     if (remote_topic_ts > chptr->topic_time)
128     accept_remote = 1;
129    
130     if (accept_remote)
131     {
132     int topic_differs = strcmp(chptr->topic ? chptr->topic : "", parv[5]);
133    
134     set_channel_topic(chptr, parv[5], parv[4], remote_topic_ts);
135    
136     if (topic_differs)
137     sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s TOPIC %s :%s",
138     ConfigServerHide.hide_servers ? me.name : source_p->name,
139     chptr->chname, chptr->topic == NULL ? "" : chptr->topic);
140     }
141    
142     /*
143     * Always propagate what we have received, not only if we accept the topic.
144     * This will keep other servers in sync.
145     */
146     sendto_server(source_p, NULL, chptr, CAP_TBURST, NOCAPS, NOFLAGS,
147     ":%s TBURST %s %s %s %s :%s",
148     source_p->name, parv[1], parv[2], parv[3], parv[4], parv[5]);
149     sendto_server(source_p, NULL, chptr, CAP_TB, CAP_TBURST, NOFLAGS,
150     ":%s TB %s %s %s :%s",
151     source_p->name, parv[1], parv[2], parv[3], parv[4]);
152 michael 325 }
153    
154     /* ms_tb()
155     *
156     * parv[0] = sender prefix
157     * parv[1] = channel name
158     * parv[2] = topic timestamp
159     * parv[3] = topic setter OR topic itself if parc == 4
160     * parv[4] = topic itself if parc == 5
161     */
162     #define tb_channel parv[1]
163     #define tb_topicts_str parv[2]
164    
165     static void
166     ms_tb(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
167     {
168     struct Channel *chptr;
169     time_t tb_topicts = atol(tb_topicts_str);
170     char *tb_whoset = NULL;
171     char *tb_topic = NULL;
172    
173     if ((chptr = hash_find_channel(tb_channel)) == NULL)
174     return;
175    
176     if (parc == 5)
177     {
178     tb_whoset = parv[3];
179     tb_topic = parv[4];
180     }
181     else
182     {
183     tb_whoset = source_p->name;
184     tb_topic = parv[3];
185     }
186    
187     set_topic(source_p, chptr, tb_topicts, tb_whoset, tb_topic);
188     }
189    
190     /*
191     * set_topic
192     *
193     * inputs - source_p pointer
194     * - channel pointer
195     * - topicts to set
196     * - who to set as who doing the topic
197     * - topic
198     * output - none
199     * Side effects - simply propagates topic as needed
200     * little helper function, could be removed
201     */
202     static void
203 michael 335 set_topic(struct Client *source_p, struct Channel *chptr, time_t topicts,
204     const char *topicwho, const char *topic)
205 michael 325 {
206 michael 335 int new_topic = strcmp(chptr->topic ? chptr->topic : "", topic);
207    
208 michael 325 set_channel_topic(chptr, topic, topicwho, topicts);
209    
210 michael 335 /* Only send TOPIC to channel if it's different */
211     if (new_topic)
212 michael 325 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s TOPIC %s :%s",
213     ConfigServerHide.hide_servers ? me.name : source_p->name,
214     chptr->chname, chptr->topic == NULL ? "" : chptr->topic);
215    
216     sendto_server(source_p, NULL, chptr, CAP_TBURST, NOCAPS, NOFLAGS,
217     ":%s TBURST %lu %s %lu %s :%s",
218     me.name, (unsigned long)chptr->channelts, chptr->chname,
219     (unsigned long)chptr->topic_time,
220     chptr->topic_info == NULL ? "" : chptr->topic_info,
221     chptr->topic == NULL ? "" : chptr->topic);
222     sendto_server(source_p, NULL, chptr, CAP_TB, CAP_TBURST, NOFLAGS,
223     ":%s TB %s %lu %s :%s",
224     me.name, chptr->chname,
225     (unsigned long)chptr->topic_time,
226     chptr->topic_info == NULL ? "" : chptr->topic_info,
227     chptr->topic == NULL ? "" : chptr->topic);
228     }

Properties

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