From 008a01428ae6d628d31abe35d361b51b3f4f154f Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Thu, 2 Nov 2000 17:31:27 +0000 Subject: [PATCH] Author: Kev Log message: 1) Use do_names() directly instead of calling through m_names(), which is ugly. 2) Add channel creation TS to JOIN protocol messages, which also requires us to seperate them; never transmute a JOIN into a CREATE, but create the channel with the proper TS, or with MAGIC_REMOTE_JOIN_TS. 3) Remove a compiler warning. Testing done: Checked for correct behavior; checked at the server<->server level to ensure channels are created with appropriate timestamps; also checked that CREATE gets bounced with MODE -o in appropriate circumstances. Testing needed: Beat on this heavily and make sure nothing weird happens ;) git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@306 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 16 +++++++++ include/s_user.h | 5 +++ ircd/channel.c | 91 +++++++++++++++++++++++++----------------------- ircd/m_join.c | 37 ++++++++------------ ircd/m_names.c | 3 -- ircd/m_whois.c | 2 +- 6 files changed, 84 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81f7ace..e3b2362 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2000-11-02 Kevin L. Mitchell + + * ircd/m_whois.c: remove compiler warning by adding a newline to + end of file + + * ircd/m_names.c: moved the flags up to s_user.h + + * ircd/m_join.c: call do_names instead of m_names; restructure + ms_join to never transmute a JOIN into a CREATE, but use the TS in + the JOIN (if present) to timestamp the channel + + * ircd/channel.c: send JOINs individually, instead of grouping + them, so that we can send the channel's creation time + + * include/s_user.h: declare do_names() + 2000-10-30 Isomer * ircd/m_oper.c: Fixed warning diff --git a/include/s_user.h b/include/s_user.h index 70da19b..e3e70c7 100644 --- a/include/s_user.h +++ b/include/s_user.h @@ -13,6 +13,7 @@ struct Client; struct User; struct Gline; +struct Channel; /* * Macros @@ -93,5 +94,9 @@ extern void add_target(struct Client *sptr, void *target); extern unsigned int umode_make_snomask(unsigned int oldmask, char *arg, int what); +#define NAMES_ALL 1 /* List all users in channel */ +#define NAMES_VIS 2 /* List only visible users in non-secret channels */ + +void do_names(struct Client* sptr, struct Channel* chptr, int filter); #endif /* INCLUDED_s_user_h */ diff --git a/ircd/channel.c b/ircd/channel.c index fcb4661..3a1ff75 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -3943,46 +3943,56 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags) assert(0 != jbuf); - if (chan) { - if (jbuf->jb_type == JOINBUF_TYPE_PART || - jbuf->jb_type == JOINBUF_TYPE_PARTALL) { - /* Send notification to channel */ - if (!(flags & CHFL_ZOMBIE)) - sendcmdto_channel_butserv(jbuf->jb_source, CMD_PART, chan, - (flags & CHFL_BANNED || !jbuf->jb_comment) ? - ":%H" : "%H :%s", chan, jbuf->jb_comment); - else if (MyUser(jbuf->jb_source)) - sendcmdto_one(jbuf->jb_source, CMD_PART, jbuf->jb_source, - (flags & CHFL_BANNED || !jbuf->jb_comment) ? - ":%H" : "%H :%s", chan, jbuf->jb_comment); - /* XXX: Shouldn't we send a PART here anyway? */ - /* to users on the channel? Why? From their POV, the user isn't on - * the channel anymore anyway. We don't send to servers until below, - * when we gang all the channel parts together. Note that this is - * exactly the same logic, albeit somewhat more concise, as was in - * the original m_part.c */ - - if (jbuf->jb_type == JOINBUF_TYPE_PARTALL || - IsLocalChannel(chan->chname)) /* got to remove user here */ - remove_user_from_channel(jbuf->jb_source, chan); - } else { - /* Add user to channel */ - add_user_to_channel(chan, jbuf->jb_source, flags); + if (!chan) { + if (jbuf->jb_type == JOINBUF_TYPE_JOIN) + sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect, "0"); - /* Send the notification to the channel */ - sendcmdto_channel_butserv(jbuf->jb_source, CMD_JOIN, chan, ":%H", chan); + return; + } - /* send an op, too, if needed */ - if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE && - !IsModelessChannel(chan->chname)) - sendcmdto_channel_butserv(jbuf->jb_source, CMD_MODE, chan, "%H +o %C", - chan, jbuf->jb_source); - } + if (jbuf->jb_type == JOINBUF_TYPE_PART || + jbuf->jb_type == JOINBUF_TYPE_PARTALL) { + /* Send notification to channel */ + if (!(flags & CHFL_ZOMBIE)) + sendcmdto_channel_butserv(jbuf->jb_source, CMD_PART, chan, + (flags & CHFL_BANNED || !jbuf->jb_comment) ? + ":%H" : "%H :%s", chan, jbuf->jb_comment); + else if (MyUser(jbuf->jb_source)) + sendcmdto_one(jbuf->jb_source, CMD_PART, jbuf->jb_source, + (flags & CHFL_BANNED || !jbuf->jb_comment) ? + ":%H" : "%H :%s", chan, jbuf->jb_comment); + /* XXX: Shouldn't we send a PART here anyway? */ + /* to users on the channel? Why? From their POV, the user isn't on + * the channel anymore anyway. We don't send to servers until below, + * when we gang all the channel parts together. Note that this is + * exactly the same logic, albeit somewhat more concise, as was in + * the original m_part.c */ + + if (jbuf->jb_type == JOINBUF_TYPE_PARTALL || + IsLocalChannel(chan->chname)) /* got to remove user here */ + remove_user_from_channel(jbuf->jb_source, chan); + } else { + /* Add user to channel */ + add_user_to_channel(chan, jbuf->jb_source, flags); - if (jbuf->jb_type == JOINBUF_TYPE_PARTALL || IsLocalChannel(chan->chname)) - return; /* don't send to remote */ + /* send notification to all servers */ + if (jbuf->jb_type != JOINBUF_TYPE_CREATE && !IsLocalChannel(chan->chname)) + sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect, + "%H %Tu", chan, chan->creationtime); + + /* Send the notification to the channel */ + sendcmdto_channel_butserv(jbuf->jb_source, CMD_JOIN, chan, ":%H", chan); + + /* send an op, too, if needed */ + if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE && + !IsModelessChannel(chan->chname)) + sendcmdto_channel_butserv(jbuf->jb_source, CMD_MODE, chan, "%H +o %C", + chan, jbuf->jb_source); } + if (jbuf->jb_type == JOINBUF_TYPE_PARTALL || IsLocalChannel(chan->chname)) + return; /* don't send to remote */ + /* figure out if channel name will cause buffer to be overflowed */ len = chan ? strlen(chan->chname) + 1 : 2; if (jbuf->jb_strlen + len > IRC_BUFSIZE) @@ -4007,7 +4017,8 @@ joinbuf_flush(struct JoinBuf *jbuf) int chanlist_i = 0; int i; - if (!jbuf->jb_count || jbuf->jb_type == JOINBUF_TYPE_PARTALL) + if (!jbuf->jb_count || jbuf->jb_type == JOINBUF_TYPE_PARTALL || + jbuf->jb_type == JOINBUF_TYPE_JOIN) return 0; /* no joins to process */ for (i = 0; i < jbuf->jb_count; i++) { /* build channel list */ @@ -4022,18 +4033,12 @@ joinbuf_flush(struct JoinBuf *jbuf) } jbuf->jb_count = 0; /* reset base counters */ - jbuf->jb_strlen = ((jbuf->jb_type == JOINBUF_TYPE_JOIN || - jbuf->jb_type == JOINBUF_TYPE_PART ? + jbuf->jb_strlen = ((jbuf->jb_type == JOINBUF_TYPE_PART ? STARTJOINLEN : STARTCREATELEN) + (jbuf->jb_comment ? strlen(jbuf->jb_comment) + 2 : 0)); /* and send the appropriate command */ switch (jbuf->jb_type) { - case JOINBUF_TYPE_JOIN: - sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect, - "%s", chanlist); - break; - case JOINBUF_TYPE_CREATE: sendcmdto_serv_butone(jbuf->jb_source, CMD_CREATE, jbuf->jb_connect, "%s %Tu", chanlist, jbuf->jb_create); diff --git a/ircd/m_join.c b/ircd/m_join.c index 86582b2..657bc4e 100644 --- a/ircd/m_join.c +++ b/ircd/m_join.c @@ -292,8 +292,7 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) chptr->topic_time); } - parv[1] = name; - m_names(cptr, sptr, 2, parv); /* XXX find a better way */ + do_names(sptr, chptr, NAMES_ALL); /* send /names list */ } joinbuf_flush(&join); /* must be first, if there's a JOIN 0 */ @@ -310,8 +309,8 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) struct Membership *member; struct Channel *chptr; struct JoinBuf join; - struct JoinBuf create; unsigned int flags = 0; + time_t creation = 0; char *p = 0; char *chanlist; char *name; @@ -324,8 +323,10 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) if (parc < 2 || *parv[1] == '\0') return need_more_params(sptr, "JOIN"); + if (parc > 2 && parv[2]) + creation = atoi(parv[2]); + joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0); - joinbuf_init(&create, sptr, cptr, JOINBUF_TYPE_CREATE, 0, TStime()); chanlist = last0(parv[1]); /* find last "JOIN 0" */ @@ -349,29 +350,19 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) chptr = FindChannel(name); } else flags = CHFL_DEOPPED | ((sptr->flags & FLAGS_TS8) ? CHFL_SERVOPOK : 0); - } else - flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP; + } else { + flags = CHFL_DEOPPED | ((sptr->flags & FLAGS_TS8) ? CHFL_SERVOPOK : 0); - if (chptr) - joinbuf_join(&join, chptr, flags); - /* Strange that a channel should get created by a JOIN, but as long - * as there are desynchs, we have to assume it's possible. Previous - * solutions involved sending a TS with the JOIN, but that seems - * unworkable to me; my solution is to transmute the JOIN into a - * CREATE, and let the next BURST try to fix the problem. Another - * solution would be to simply issue an upstream KICK, but that - * won't currently be accepted. Is this what DESTRUCT is for? - */ - else if (!(chptr = get_channel(sptr, name, CGT_CREATE))) - continue; /* couldn't get channel */ - else { - chptr->creationtime = TStime(); /* have to set the creation TS */ - joinbuf_join(&create, chptr, flags); + if ((chptr = get_channel(sptr, name, CGT_CREATE))) + chptr->creationtime = creation ? creation : MAGIC_REMOTE_JOIN_TS; + else + continue; /* couldn't get channel */ } + + joinbuf_join(&join, chptr, flags); } - joinbuf_flush(&join); /* must be first, if there's a JOIN 0 */ - joinbuf_flush(&create); + joinbuf_flush(&join); /* flush joins... */ return 0; } diff --git a/ircd/m_names.c b/ircd/m_names.c index 330b6f8..56cc590 100644 --- a/ircd/m_names.c +++ b/ircd/m_names.c @@ -102,9 +102,6 @@ #include #include -#define NAMES_ALL 1 /* List all users in channel */ -#define NAMES_VIS 2 /* List only visible users in non-secret channels */ - /* * Sends a suitably formatted 'names' reply to 'sptr' consisting of nicks within * 'chptr', depending on 'filter'. diff --git a/ircd/m_whois.c b/ircd/m_whois.c index c2b3fa1..eb041e1 100644 --- a/ircd/m_whois.c +++ b/ircd/m_whois.c @@ -466,4 +466,4 @@ int ms_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) send_reply(sptr, RPL_ENDOFWHOIS, parv[1]); return 0; -} \ No newline at end of file +} -- 2.20.1