]> jfr.im git - irc/quakenet/snircd.git/blob - ircd/m_destruct.c
merge 07 in
[irc/quakenet/snircd.git] / ircd / m_destruct.c
1 /*
2 * IRC - Internet Relay Chat, ircd/m_destruct.c
3 * Copyright (C) 1997 Carlo Wood.
4 *
5 * See file AUTHORS in IRC package for additional names of
6 * the programmers.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 1, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * $Id: m_destruct.c,v 1.9 2005/03/20 16:06:18 entrope Exp $
23 */
24
25 #include "config.h"
26
27 #include "client.h"
28 #include "hash.h"
29 #include "ircd.h"
30 #include "ircd_log.h"
31 #include "ircd_reply.h"
32 #include "ircd_string.h"
33 #include "msg.h"
34 #include "numeric.h"
35 #include "numnicks.h"
36 #include "send.h"
37 #include "channel.h"
38 #include "destruct_event.h"
39
40 /* #include <assert.h> -- Now using assert in ircd_log.h */
41 #include <stdlib.h>
42
43 /*
44 * ms_destruct - server message handler
45 *
46 * Added 1997 by Run, actually coded and used since 2002.
47 *
48 * parv[0] = sender prefix
49 * parv[1] = channel channelname
50 * parv[2] = channel time stamp
51 *
52 * This message is intended to destruct _empty_ channels.
53 *
54 * The reason it is needed is to somehow add the notion
55 * "I destructed information" to the networks state
56 * (also messages that are still propagating are part
57 * of the global state). Without it the network could
58 * easily be desynced as a result of destructing a channel
59 * on only a part of the network while keeping the modes
60 * and creation time on others.
61 * There are three possible ways a DESTRUCT message is
62 * handled by remote servers:
63 * 1) The channel is empty and has the same timestamp
64 * as on the message. Conclusion: The channel has
65 * not been destructed and recreated in the meantime,
66 * this means that the normal synchronization rules
67 * account and we react as if we decided to destruct
68 * the channel ourselves: we destruct the channel and
69 * send a DESTRUCT in all directions.
70 * 2) The channel is not empty. In case we cannot remove
71 * it and do not propagate the DESTRUCT message. Instead
72 * a resynchronizing BURST message is sent upstream
73 * in order to restore the channel on that side (which
74 * will have a TS younger than the current channel if
75 * it was recreated and will thus be fully synced, just
76 * like in the case of a real net-junction).
77 * 3) The channel is empty, but the creation time of the
78 * channel is older than the timestamp on the message.
79 * This can happen when there is more than one minute
80 * lag and remotely a channel was created slightly
81 * after we created the channel, being abandoned again
82 * and staying empty for a minute without that our
83 * CREATE reached that remote server. The remote server
84 * then could have generated the DESTRUCT. In the meantime
85 * our user also left the channel. We can ignore the
86 * destruct because it comes from an 'area' that will
87 * be overridden by our own CREATE: the state that generated
88 * this DESTRUCT is 'history'.
89 */
90 int ms_destruct(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
91 {
92 time_t chanTS; /* Creation time of the channel */
93 struct Channel* chptr;
94
95 assert(0 != cptr);
96 assert(0 != sptr);
97 assert(IsServer(cptr));
98
99 if (parc < 3 || EmptyString(parv[2]))
100 return need_more_params(sptr,"DESTRUCT");
101
102 chanTS = atoi(parv[2]);
103
104 /* Ignore DESTRUCT messages for non-existing channels. */
105 if (!(chptr = FindChannel(parv[1])))
106 return 0;
107
108 /* Ignore DESTRUCT when the channel is older than the
109 timestamp on the message. */
110 if (chanTS > chptr->creationtime)
111 return 0;
112
113 /* Don't pass on DESTRUCT messages for channels that
114 are not empty, but instead send a BURST msg upstream. */
115 if (chptr->users > 0) {
116 send_channel_modes(cptr, chptr);
117 return 0;
118 }
119
120 /* Pass on DESTRUCT message and ALSO bounce it back! */
121 sendcmdto_serv_butone(&me, CMD_DESTRUCT, 0, "%s %Tu", parv[1], chanTS);
122
123 /* Remove the empty channel. */
124 remove_destruct_event(chptr);
125 destruct_channel(chptr);
126
127 return 0;
128 }