]>
Commit | Line | Data |
---|---|---|
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 | } |