Author: Carlo Wood <run@alinoe.com>
[ircu2.10.12-pk.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$
23  */
24
25 #include "config.h"
26
27 #include "client.h"
28 #include "hash.h"
29 #include "ircd.h"
30 #include "ircd_reply.h"
31 #include "ircd_string.h"
32 #include "msg.h"
33 #include "numeric.h"
34 #include "numnicks.h"
35 #include "send.h"
36 #include "channel.h"
37 #include "destruct_event.h"
38
39 #include <assert.h>
40 #include <stdlib.h>
41
42 /*
43  * ms_destruct - server message handler
44  *
45  * Added 1997 by Run, actually coded and used since 2002.
46  *
47  * parv[0] = sender prefix
48  * parv[1] = channel channelname
49  * parv[2] = channel time stamp
50  *
51  * This message is intended to destruct _empty_ channels.
52  *
53  * The reason it is needed is to somehow add the notion
54  * "I destructed information" to the networks state
55  * (also messages that are still propagating are part
56  *  of the global state).  Without it the network could
57  * easily be desynced as a result of destructing a channel
58  * on only a part of the network while keeping the modes
59  * and creation time on others.
60  * There are three possible ways a DESTRUCT message is
61  * handled by remote servers:
62  * 1) The channel is empty and has the same timestamp
63  *    as on the message.  Conclusion: The channel has
64  *    not been destructed and recreated in the meantime,
65  *    this means that the normal synchronization rules
66  *    account and we react as if we decided to destruct
67  *    the channel ourselfs: we destruct the channel and
68  *    send a DESTRUCT in all directions.
69  * 2) The channel is not empty.  In case we cannot remove
70  *    it and do not propagate the DESTRUCT message. Instead
71  *    a resynchronizing BURST message is sent upstream
72  *    in order to restore the channel on that side (which
73  *    will have a TS younger than the current channel if
74  *    it was recreated and will thus be fully synced, just
75  *    like in the case of a real net-junction).
76  * 3) The channel is empty, but the creation time of the
77  *    channel is older than the timestamp on the message.
78  *    This can happen when there is more than one minute
79  *    lag and remotely a channel was created slightly
80  *    after we created the channel, being abandoned again
81  *    and staying empty for a minute without that our
82  *    CREATE reached that remote server.  The remote server
83  *    then could have generated the DESTRUCT.  In the meantime
84  *    our user also left the channel.  We can ignore the
85  *    destruct because it comes from an 'area' that will
86  *    be overriden by our own CREATE: the state that generated
87  *    this DESTRUCT is 'history'.
88  */
89 int ms_destruct(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
90 {
91   time_t chanTS;                /* Creation time of the channel */
92   struct Channel* chptr;
93
94   assert(0 != cptr);
95   assert(0 != sptr);
96   assert(IsServer(cptr));
97
98   if (parc < 3 || EmptyString(parv[2]))
99     return need_more_params(sptr,"DESTRUCT");
100
101   chanTS = atoi(parv[2]);
102
103   /* Ignore DESTRUCT messages for non-existing channels. */
104   if (!(chptr = FindChannel(parv[1])))
105     return 0;
106
107   /* Ignore DESTRUCT when the channel is older than the
108      timestamp on the message. */
109   if (chanTS > chptr->creationtime)
110     return 0;
111
112   /* Don't pass on DESTRUCT messages for channels that
113      are not empty, but instead send a BURST msg upstream. */
114   if (chptr->users > 0) {
115     send_channel_modes(cptr, chptr);
116     return 0;
117   }
118
119   /* Pass on DESTRUCT message and ALSO bounce it back! */
120   sendcmdto_serv_butone(sptr, CMD_DESTRUCT, 0, "%s %Tu", parv[1], chanTS);
121
122   /* Remove the empty channel. */
123   remove_destruct_event(chptr);
124   destruct_channel(chptr);
125
126   return 0;
127 }