X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fm_destruct.c;h=f5b7dd60cfc118cbda14667fcfbf4ea1909403e2;hb=refs%2Fheads%2Fupstream;hp=8fca75a636796864826a757e5e6de2467b8edd68;hpb=fc21303989a07d6091ef684150db29c49f682614;p=ircu2.10.12-pk.git diff --git a/ircd/m_destruct.c b/ircd/m_destruct.c index 8fca75a..f5b7dd6 100644 --- a/ircd/m_destruct.c +++ b/ircd/m_destruct.c @@ -1,6 +1,6 @@ /* * IRC - Internet Relay Chat, ircd/m_destruct.c - * Copyright (C) 1997 Carlo Wood. + * Copyright (C) 1997, 2005 Carlo Wood. * * See file AUTHORS in IRC package for additional names of * the programmers. @@ -65,7 +65,7 @@ * not been destructed and recreated in the meantime, * this means that the normal synchronization rules * account and we react as if we decided to destruct - * the channel ourselfs: we destruct the channel and + * the channel ourselves: we destruct the channel and * send a DESTRUCT in all directions. * 2) The channel is not empty. In case we cannot remove * it and do not propagate the DESTRUCT message. Instead @@ -84,7 +84,7 @@ * then could have generated the DESTRUCT. In the meantime * our user also left the channel. We can ignore the * destruct because it comes from an 'area' that will - * be overriden by our own CREATE: the state that generated + * be overridden by our own CREATE: the state that generated * this DESTRUCT is 'history'. */ int ms_destruct(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) @@ -113,7 +113,76 @@ int ms_destruct(struct Client* cptr, struct Client* sptr, int parc, char* parv[] /* Don't pass on DESTRUCT messages for channels that are not empty, but instead send a BURST msg upstream. */ if (chptr->users > 0) { +#if 0 /* Once all servers are 2.10.12, this can be used too. + Until then we have to use CREATE and MODE to + get the message accross, because older server do + not accept a BURST outside the net.burst. */ send_channel_modes(cptr, chptr); +#else + /* This happens when a JOIN and DESTRUCT crossed, ie: + + server1 ----------------- server2 + DESTRUCT--> <-- JOIN,MODE + + Where the JOIN and MODE are the result of joining + the zannel before it expired on server2, or in the + case of simulateous expiration, a DESTRUCT crossing + with another DESTRUCT (that will be ignored) and + a CREATE of a user joining right after that: + + server1 ----------------- server2 + DESTRUCT--> <-- DESTRUCT <-- CREATE + + in both cases, when the DESTRUCT arrives on + server2 we need to send synchronizing messages + upstream (to server1). Since sending two CREATEs + or JOINs for the same user after another is a + protocol violation, we first have to send PARTs + (we can't send a DESTRUCT because 2.10.11 ignores + DESTRUCT messages (just passes them on) and has + a bug that causes two JOIN's for the same user to + result in that user being on the channel twice). */ + + struct Membership *member; + struct ModeBuf mbuf; + struct Ban *link; + + /* Next, send all PARTs upstream. */ + for (member = chptr->members; member; member = member->next_member) + sendcmdto_one(member->user, CMD_PART, cptr, "%H", chptr); + + /* Next, send JOINs for all members. */ + for (member = chptr->members; member; member = member->next_member) + sendcmdto_one(member->user, CMD_JOIN, cptr, "%H", chptr); + + /* Build MODE strings. We use MODEBUF_DEST_BOUNCE with MODE_DEL to assure + that the resulting MODEs are only sent upstream. */ + modebuf_init(&mbuf, sptr, cptr, chptr, MODEBUF_DEST_SERVER | MODEBUF_DEST_BOUNCE); + + /* Op/voice the users as appropriate. We use MODE_DEL because we fake a bounce. */ + for (member = chptr->members; member; member = member->next_member) + { + if (IsChanOp(member)) + modebuf_mode_client(&mbuf, MODE_DEL | MODE_CHANOP, member->user, OpLevel(member)); + if (HasVoice(member)) + modebuf_mode_client(&mbuf, MODE_DEL | MODE_VOICE, member->user, MAXOPLEVEL + 1); + } + + /* Send other MODEs. */ + modebuf_mode(&mbuf, MODE_DEL | chptr->mode.mode); + if (*chptr->mode.key) + modebuf_mode_string(&mbuf, MODE_DEL | MODE_KEY, chptr->mode.key, 0); + if (chptr->mode.limit) + modebuf_mode_uint(&mbuf, MODE_DEL | MODE_LIMIT, chptr->mode.limit); + if (*chptr->mode.upass) + modebuf_mode_string(&mbuf, MODE_DEL | MODE_UPASS, chptr->mode.upass, 0); + if (*chptr->mode.apass) + modebuf_mode_string(&mbuf, MODE_DEL | MODE_APASS, chptr->mode.apass, 0); + for (link = chptr->banlist; link; link = link->next) + modebuf_mode_string(&mbuf, MODE_DEL | MODE_BAN, link->banstr, 0); + modebuf_flush(&mbuf); +#endif + return 0; } @@ -121,7 +190,8 @@ int ms_destruct(struct Client* cptr, struct Client* sptr, int parc, char* parv[] sendcmdto_serv_butone(&me, CMD_DESTRUCT, 0, "%s %Tu", parv[1], chanTS); /* Remove the empty channel. */ - remove_destruct_event(chptr); + if (chptr->destruct_event) + remove_destruct_event(chptr); destruct_channel(chptr); return 0;