Added vampires Lazy Link patches, and uh, where'd the template go?
[ircu2.10.12-pk.git] / patches / diffs / lazy.diff
1 Index: include/channel.h
2 ===================================================================
3 RCS file: /home/coder-com/cvs/ircu2.10/include/channel.h,v
4 retrieving revision 1.31
5 diff -u -r1.31 channel.h
6 --- include/channel.h   2002/03/27 22:30:24     1.31
7 +++ include/channel.h   2002/04/02 07:11:52
8 @@ -95,6 +95,8 @@
9  #define MODE_BURSTADDED        0x80000 /* channel was created by a BURST */
10  #define MODE_UPASS     0x100000
11  #define MODE_APASS     0x200000
12 +#define MODE_EMPTY     0x400000 /* LazeLeaf: no more locals, remove channel asap */
13 +
14  /*
15   * mode flags which take another parameter (With PARAmeterS)
16   */
17 @@ -222,15 +224,20 @@
18    time_t             creationtime;
19    time_t             topic_time;
20    unsigned int       users;
21 +  unsigned int       locals;
22    struct Membership* members;
23    struct SLink*      invites;
24    struct SLink*      banlist;
25    struct Mode        mode;
26    char               topic[TOPICLEN + 1];
27    char               topic_nick[NICKLEN + 1];
28 -  char               chname[1];
29 +  unsigned long      ll_bits;          /* LazyLeaf */
30 +  char               chname[1];                /* This *must* be last */
31  };
32  
33 +#define LeafKnowsChannel(c,x)  (cli_serv(c)->ll_mask & (x)->ll_bits)
34 +#define LL_ALL                 (~0UL)
35 +
36  struct ListingArgs {
37    time_t max_time;
38    time_t min_time;
39 @@ -350,6 +357,7 @@
40  extern int is_zombie(struct Client *cptr, struct Channel *chptr);
41  extern int has_voice(struct Client *cptr, struct Channel *chptr);
42  extern void send_channel_modes(struct Client *cptr, struct Channel *chptr);
43 +extern void ll_send_channel(struct Client *cptr, struct Channel *chptr);
44  extern char *pretty_mask(char *mask);
45  extern void del_invite(struct Client *cptr, struct Channel *chptr);
46  extern void list_next_channels(struct Client *cptr, int nr);
47 Index: include/client.h
48 ===================================================================
49 RCS file: /home/coder-com/cvs/ircu2.10/include/client.h,v
50 retrieving revision 1.25
51 diff -u -r1.25 client.h
52 --- include/client.h    2002/03/19 10:54:28     1.25
53 +++ include/client.h    2002/04/02 07:11:53
54 @@ -369,6 +369,7 @@
55  #define FLAGS_DOID      0x00040000      /* I-lines say must use ident return */
56  #define FLAGS_NONL      0x00080000      /* No \n in buffer */
57  #define FLAGS_TS8       0x00100000      /* Why do you want to know? */
58 +#define FLAGS_LAZY     0x00200000      /* LazyLeaf */
59  #define FLAGS_MAP       0x00800000      /* Show server on the map */
60  #define FLAGS_JUNCTION  0x01000000      /* Junction causing the net.burst */
61  #define FLAGS_DEAF      0x02000000      /* Makes user deaf */
62 @@ -413,6 +414,7 @@
63  #define IsAccount(x)            (cli_flags(x) & FLAGS_ACCOUNT)
64  #define IsHiddenHost(x)                (cli_flags(x) & FLAGS_HIDDENHOST)
65  #define HasHiddenHost(x)       (IsAccount(x) && IsHiddenHost(x))
66 +#define IsLazy(x)              (cli_flags(x) & FLAGS_LAZY)
67  
68  #define IsPrivileged(x)         (IsAnOper(x) || IsServer(x))
69  
70 @@ -435,6 +437,7 @@
71  #define SetService(x)           (cli_flags(x) |= FLAGS_SERVICE)
72  #define SetAccount(x)           (cli_flags(x) |= FLAGS_ACCOUNT)
73  #define SetHiddenHost(x)       (cli_flags(x) |= FLAGS_HIDDENHOST)
74 +#define SetLazy(x)             (cli_flags(x) |= FLAGS_LAZY)
75  
76  #define ClearAccess(x)          (cli_flags(x) &= ~FLAGS_CHKACCESS)
77  #define ClearBurst(x)           (cli_flags(x) &= ~FLAGS_BURST)
78 @@ -450,6 +453,7 @@
79  #define ClearWallops(x)         (cli_flags(x) &= ~FLAGS_WALLOP)
80  #define ClearServNotice(x)      (cli_flags(x) &= ~FLAGS_SERVNOTICE)
81  #define ClearHiddenHost(x)     (cli_flags(x) &= ~FLAGS_HIDDENHOST)
82 +#define ClearLazy(x)           (cli_flags(x) &= ~FLAGS_LAZY)
83  
84  /* free flags */
85  #define FREEFLAG_SOCKET        0x0001  /* socket needs to be freed */
86 Index: include/handlers.h
87 ===================================================================
88 RCS file: /home/coder-com/cvs/ircu2.10/include/handlers.h,v
89 retrieving revision 1.16
90 diff -u -r1.16 handlers.h
91 --- include/handlers.h  2002/03/19 22:03:36     1.16
92 +++ include/handlers.h  2002/04/02 07:11:53
93 @@ -183,6 +183,7 @@
94  extern int ms_gline(struct Client*, struct Client*, int, char*[]);
95  extern int ms_info(struct Client*, struct Client*, int, char*[]);
96  extern int ms_invite(struct Client*, struct Client*, int, char*[]);
97 +extern int ms_forget(struct Client*, struct Client*, int, char*[]);
98  extern int ms_join(struct Client*, struct Client*, int, char*[]);
99  extern int ms_jupe(struct Client*, struct Client*, int, char*[]);
100  extern int ms_kick(struct Client*, struct Client*, int, char*[]);
101 Index: include/ircd_features.h
102 ===================================================================
103 RCS file: /home/coder-com/cvs/ircu2.10/include/ircd_features.h,v
104 retrieving revision 1.14
105 diff -u -r1.14 ircd_features.h
106 --- include/ircd_features.h     2002/03/20 06:33:24     1.14
107 +++ include/ircd_features.h     2002/04/02 07:11:53
108 @@ -37,6 +37,7 @@
109    FEAT_KILL_IPMISMATCH,
110    FEAT_IDLE_FROM_MSG,
111    FEAT_HUB,
112 +  FEAT_LAZY_LEAF,
113    FEAT_WALLOPS_OPER_ONLY,
114    FEAT_NODNS,
115    FEAT_RANDOM_SEED,
116 Index: include/msg.h
117 ===================================================================
118 RCS file: /home/coder-com/cvs/ircu2.10/include/msg.h,v
119 retrieving revision 1.12
120 diff -u -r1.12 msg.h
121 --- include/msg.h       2002/02/14 00:20:40     1.12
122 +++ include/msg.h       2002/04/02 07:11:53
123 @@ -330,6 +330,10 @@
124  #define TOK_ACCOUNT            "AC"
125  #define CMD_ACCOUNT            MSG_ACCOUNT, TOK_ACCOUNT
126  
127 +#define MSG_FORGET             "FORGET"        /* FORGET */
128 +#define TOK_FORGET             "FO"
129 +#define CMD_FORGET             MSG_FORGET, TOK_FORGET
130 +
131  #define MSG_POST                "POST"          /* POST */
132  #define TOK_POST                "POST"
133  
134 Index: include/s_serv.h
135 ===================================================================
136 RCS file: /home/coder-com/cvs/ircu2.10/include/s_serv.h,v
137 retrieving revision 1.6
138 diff -u -r1.6 s_serv.h
139 --- include/s_serv.h    2001/06/08 23:12:16     1.6
140 +++ include/s_serv.h    2002/04/02 07:11:53
141 @@ -12,9 +12,11 @@
142  
143  struct ConfItem;
144  struct Client;
145 +struct Channel;
146  
147  extern unsigned int max_connection_count;
148  extern unsigned int max_client_count;
149 +extern unsigned long GlobalLeafBits;
150  
151  /*
152   * Prototypes
153 @@ -24,5 +26,8 @@
154  extern int a_kills_b_too(struct Client *a, struct Client *b);
155  extern int server_estab(struct Client *cptr, struct ConfItem *aconf);
156  
157 +extern int ll_add(struct Client *cptr);
158 +extern void ll_remove(struct Client *cptr);
159 +extern void ll_check_channel(struct Client *cptr, struct Channel *chptr);
160  
161  #endif /* INCLUDED_s_serv_h */
162 Index: include/send.h
163 ===================================================================
164 RCS file: /home/coder-com/cvs/ircu2.10/include/send.h,v
165 retrieving revision 1.17
166 diff -u -r1.17 send.h
167 --- include/send.h      2002/02/14 00:20:41     1.17
168 +++ include/send.h      2002/04/02 07:11:53
169 @@ -47,6 +47,12 @@
170                                   const char *tok, struct Client *one,
171                                   const char *pattern, ...);
172  
173 +/* Same as above, but only when the server's ll_mask matches */
174 +extern void sendcmdto_mask_butone(struct Client *from, const char *cmd,
175 +                                 const char *tok, unsigned long ll_mask,
176 +                                 struct Client *one,
177 +                                 const char *pattern, ...);
178 +
179  /* Send command to all channels user is on */
180  extern void sendcmdto_common_channels_butone(struct Client *from,
181                                              const char *cmd,
182 Index: include/struct.h
183 ===================================================================
184 RCS file: /home/coder-com/cvs/ircu2.10/include/struct.h,v
185 retrieving revision 1.3
186 diff -u -r1.3 struct.h
187 --- include/struct.h    2002/02/14 00:20:41     1.3
188 +++ include/struct.h    2002/04/02 07:11:53
189 @@ -52,6 +52,7 @@
190    unsigned short  nn_last;      /* Last numeric nick for p9 servers only */
191    unsigned int    nn_mask;      /* [Remote] FD_SETSIZE - 1 */
192    char          nn_capacity[4]; /* numeric representation of server capacity */
193 +  unsigned long   ll_mask;     /* LazyLeaf mask */
194  
195    char *last_error_msg;         /* Allocated memory with last message receive with an ERROR */
196    char by[NICKLEN + 1];
197 Index: ircd/channel.c
198 ===================================================================
199 RCS file: /home/coder-com/cvs/ircu2.10/ircd/channel.c,v
200 retrieving revision 1.79
201 diff -u -r1.79 channel.c
202 --- ircd/channel.c      2002/04/02 00:26:46     1.79
203 +++ ircd/channel.c      2002/04/02 07:11:54
204 @@ -46,6 +46,7 @@
205  #include "s_conf.h"
206  #include "s_debug.h"
207  #include "s_misc.h"
208 +#include "s_serv.h"
209  #include "s_user.h"
210  #include "send.h"
211  #include "struct.h"
212 @@ -533,6 +534,8 @@
213        remove_destruct_event(chptr);
214      ++chptr->users;
215      ++((cli_user(who))->joined);
216 +    if (MyUser(who))
217 +      ++chptr->locals;
218    }
219  }
220  
221 @@ -562,6 +565,8 @@
222      (cli_user(member->user))->channel = member->next_channel;
223  
224    --(cli_user(member->user))->joined;
225 +  if (MyUser(member->user))
226 +    --chptr->locals;
227  
228    member->next_member = membershipFreeList;
229    membershipFreeList = member;
230 @@ -587,6 +592,12 @@
231    struct Membership* member;
232    assert(0 != chptr);
233  
234 +  if (chptr->mode.mode & MODE_EMPTY) {
235 +    while (remove_member_from_channel(chptr->members))
236 +      ;
237 +    return;
238 +  }
239 +
240    if ((member = find_member_link(chptr, cptr))) {
241      if (remove_member_from_channel(member)) {
242        if (channel_all_zombies(chptr)) {
243 @@ -1417,6 +1428,7 @@
244      for (; acptr != &me; acptr = (cli_serv(acptr))->up)
245        if (acptr == (cli_user(who))->server)   /* Case d) (server 5) */
246        {
247 +        ll_check_channel(who, chptr);
248          remove_user_from_channel(who, chptr);
249          return;
250        }
251 @@ -1769,8 +1781,8 @@
252  
253      if (mbuf->mb_dest & MODEBUF_DEST_OPMODE) {
254        /* If OPMODE was set, we're propagating the mode as an OPMODE message */
255 -      sendcmdto_serv_butone(mbuf->mb_source, CMD_OPMODE, mbuf->mb_connect,
256 -                           "%H %s%s%s%s%s%s", mbuf->mb_channel,
257 +      sendcmdto_mask_butone(mbuf->mb_source, CMD_OPMODE, mbuf->mb_channel->ll_bits,
258 +                           mbuf->mb_connect, "%H %s%s%s%s%s%s", mbuf->mb_channel,
259                             rembuf_i ? "-" : "", rembuf, addbuf_i ? "+" : "",
260                             addbuf, remstr, addstr);
261      } else if (mbuf->mb_dest & MODEBUF_DEST_BOUNCE) {
262 @@ -1789,14 +1801,16 @@
263         * we send the actual channel TS unless this is a HACK3 or a HACK4
264         */
265        if (IsServer(mbuf->mb_source))
266 -       sendcmdto_serv_butone(mbuf->mb_source, CMD_MODE, mbuf->mb_connect,
267 +       sendcmdto_mask_butone(mbuf->mb_source, CMD_MODE,
268 +                             mbuf->mb_channel->ll_bits, mbuf->mb_connect,
269                               "%H %s%s%s%s%s%s %Tu", mbuf->mb_channel,
270                               rembuf_i ? "-" : "", rembuf, addbuf_i ? "+" : "",
271                               addbuf, remstr, addstr,
272                               (mbuf->mb_dest & MODEBUF_DEST_HACK4) ? 0 :
273                               mbuf->mb_channel->creationtime);
274        else
275 -       sendcmdto_serv_butone(mbuf->mb_source, CMD_MODE, mbuf->mb_connect,
276 +       sendcmdto_mask_butone(mbuf->mb_source, CMD_MODE, 
277 +                             mbuf->mb_channel->ll_bits, mbuf->mb_connect,
278                               "%H %s%s%s%s%s%s", mbuf->mb_channel,
279                               rembuf_i ? "-" : "", rembuf, addbuf_i ? "+" : "",
280                               addbuf, remstr, addstr);
281 @@ -3143,7 +3157,7 @@
282  
283      /* send notification to all servers */
284      if (jbuf->jb_type != JOINBUF_TYPE_CREATE && !IsLocalChannel(chan->chname))
285 -      sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect,
286 +      sendcmdto_mask_butone(jbuf->jb_source, CMD_JOIN, chan->ll_bits, jbuf->jb_connect,
287                             "%H %Tu", chan, chan->creationtime);
288  
289      /* Send the notification to the channel */
290 @@ -3191,9 +3205,37 @@
291      build_string(chanlist, &chanlist_i,
292                  jbuf->jb_channels[i] ? jbuf->jb_channels[i]->chname : "0", 0,
293                  i == 0 ? '\0' : ',');
294 -    if (JOINBUF_TYPE_PART == jbuf->jb_type)
295 +
296 +    /*
297 +     * For lazy leafs, joins/parts have to be sent separately for 
298 +     * each channel. 
299 +     */
300 +    switch (jbuf->jb_type) {
301 +    case JOINBUF_TYPE_CREATE:
302 +      sendcmdto_mask_butone(jbuf->jb_source, CMD_CREATE,
303 +                           jbuf->jb_channels[i] ? jbuf->jb_channels[i]->ll_bits : LL_ALL,
304 +                           jbuf->jb_connect, "%s %Tu",
305 +                           jbuf->jb_channels[i] ? jbuf->jb_channels[i]->chname : "0",
306 +                           jbuf->jb_create);
307 +      break;
308 +
309 +    case JOINBUF_TYPE_PART:
310 +      sendcmdto_mask_butone(jbuf->jb_source, CMD_PART,
311 +                           jbuf->jb_channels[i]->ll_bits,
312 +                           jbuf->jb_connect,
313 +                           jbuf->jb_comment ? "%s :%s" : "%s",
314 +                           jbuf->jb_channels[i]->chname,
315 +                           jbuf->jb_comment);
316 +      break;
317 +    }
318 +
319 +    if (JOINBUF_TYPE_PART == jbuf->jb_type) {
320 +      /* Check now, as remove_user* may free the channel */
321 +      ll_check_channel(jbuf->jb_source, jbuf->jb_channels[i]);
322 +       
323        /* Remove user from channel */
324        remove_user_from_channel(jbuf->jb_source, jbuf->jb_channels[i]);
325 +    }
326  
327      jbuf->jb_channels[i] = 0; /* mark slot empty */
328    }
329 @@ -3203,6 +3245,7 @@
330                       STARTJOINLEN : STARTCREATELEN) +
331                      (jbuf->jb_comment ? strlen(jbuf->jb_comment) + 2 : 0));
332  
333 +#if 0
334    /* and send the appropriate command */
335    switch (jbuf->jb_type) {
336    case JOINBUF_TYPE_CREATE:
337 @@ -3216,6 +3259,7 @@
338                           jbuf->jb_comment);
339      break;
340    }
341 +#endif
342  
343    return 0;
344  }
345 Index: ircd/ircd_features.c
346 ===================================================================
347 RCS file: /home/coder-com/cvs/ircu2.10/ircd/ircd_features.c,v
348 retrieving revision 1.18
349 diff -u -r1.18 ircd_features.c
350 --- ircd/ircd_features.c        2002/03/20 06:33:25     1.18
351 +++ ircd/ircd_features.c        2002/04/02 07:11:55
352 @@ -244,6 +244,7 @@
353    F_B(KILL_IPMISMATCH, FEAT_OPER, 0, 0),
354    F_B(IDLE_FROM_MSG, 0, 1, 0),
355    F_B(HUB, 0, 0, 0),
356 +  F_B(LAZY_LEAF, 0, 0, 0),
357    F_B(WALLOPS_OPER_ONLY, 0, 0, 0),
358    F_B(NODNS, 0, 0, 0),
359    F_N(RANDOM_SEED, FEAT_NODISP, random_seed_set, 0, 0, 0, 0, 0, 0),
360 Index: ircd/m_burst.c
361 ===================================================================
362 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_burst.c,v
363 retrieving revision 1.16
364 diff -u -r1.16 m_burst.c
365 --- ircd/m_burst.c      2002/03/27 22:30:24     1.16
366 +++ ircd/m_burst.c      2002/04/02 07:11:55
367 @@ -89,6 +89,7 @@
368  #include "ircd_policy.h"
369  #include "ircd_reply.h"
370  #include "ircd_string.h"
371 +#include "ircd_features.h"
372  #include "list.h"
373  #include "match.h"
374  #include "msg.h"
375 @@ -463,6 +464,11 @@
376        lp->flags &= (CHFL_BAN | CHFL_BAN_IPMASK); /* reset the flag */
377        lp_p = &(*lp_p)->next;
378      }
379 +  }
380 +
381 +  if (IsLazy(cptr) && !LeafKnowsChannel(cptr, chptr)) {
382 +    chptr->ll_bits |= cli_serv(cptr)->ll_mask;
383 +    send_channel_modes(cptr, chptr);
384    }
385  
386    return mbuf ? modebuf_flush(mbuf) : 0;
387 Index: ircd/m_clearmode.c
388 ===================================================================
389 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_clearmode.c,v
390 retrieving revision 1.20
391 diff -u -r1.20 m_clearmode.c
392 --- ircd/m_clearmode.c  2002/02/14 00:20:42     1.20
393 +++ ircd/m_clearmode.c  2002/04/02 07:11:55
394 @@ -234,8 +234,8 @@
395  
396    /* Then send it */
397    if (!IsLocalChannel(chptr->chname))
398 -    sendcmdto_serv_butone(sptr, CMD_CLEARMODE, cptr, "%H %s", chptr,
399 -                         control_buf);
400 +    sendcmdto_mask_butone(sptr, CMD_CLEARMODE, chptr->ll_bits, cptr,
401 +                         "%H %s", chptr, control_buf);
402  
403    return 0;
404  }
405 Index: ircd/m_create.c
406 ===================================================================
407 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_create.c,v
408 retrieving revision 1.12
409 diff -u -r1.12 m_create.c
410 --- ircd/m_create.c     2002/02/14 00:20:42     1.12
411 +++ ircd/m_create.c     2002/04/02 07:11:55
412 @@ -154,6 +154,7 @@
413        continue;
414  
415      if ((chptr = FindChannel(name))) {
416 +      int hack2 = IsLazy(cptr) ? 0 : MODEBUF_DEST_HACK2;
417        name = chptr->chname;
418  
419        /* Check if we need to bounce a mode */
420 @@ -162,7 +163,7 @@
421            chptr->creationtime != MAGIC_REMOTE_JOIN_TS)) {
422         modebuf_init(&mbuf, sptr, cptr, chptr,
423                      (MODEBUF_DEST_SERVER |  /* Send mode to server */
424 -                     MODEBUF_DEST_HACK2  |  /* Send a HACK(2) message */
425 +                     hack2               |  /* Send a HACK(2) message */
426                       MODEBUF_DEST_BOUNCE)); /* And bounce the mode */
427  
428         modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr);
429 @@ -180,6 +181,11 @@
430      joinbuf_join(badop ? &join : &create, chptr,
431                  (badop || IsModelessChannel(name)) ?
432                  CHFL_DEOPPED : CHFL_CHANOP);
433 +
434 +    if (IsLazy(cptr) && !LeafKnowsChannel(cptr, chptr)) {
435 +      chptr->ll_bits |= cli_serv(cptr)->ll_mask;
436 +      send_channel_modes(cptr, chptr);
437 +    }
438    }
439  
440    joinbuf_flush(&join); /* flush out the joins and creates */
441 Index: ircd/m_join.c
442 ===================================================================
443 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_join.c,v
444 retrieving revision 1.19
445 diff -u -r1.19 m_join.c
446 --- ircd/m_join.c       2002/03/13 09:19:21     1.19
447 +++ ircd/m_join.c       2002/04/02 07:11:55
448 @@ -373,6 +373,11 @@
449         chptr->creationtime = creation;
450      } 
451  
452 +    if (IsLazy(cptr) && !LeafKnowsChannel(cptr, chptr)) {
453 +      chptr->ll_bits |= cli_serv(cptr)->ll_mask;
454 +      send_channel_modes(cptr, chptr);
455 +    }
456 +
457      joinbuf_join(&join, chptr, flags);
458    }
459  
460 Index: ircd/m_kick.c
461 ===================================================================
462 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_kick.c,v
463 retrieving revision 1.8
464 diff -u -r1.8 m_kick.c
465 --- ircd/m_kick.c       2002/03/13 09:19:21     1.8
466 +++ ircd/m_kick.c       2002/04/02 07:11:55
467 @@ -150,7 +150,7 @@
468    comment = EmptyString(parv[parc - 1]) ? parv[0] : parv[parc - 1];
469  
470    if (!IsLocalChannel(name))
471 -    sendcmdto_serv_butone(sptr, CMD_KICK, cptr, "%H %C :%s", chptr, who,
472 +    sendcmdto_mask_butone(sptr, CMD_KICK, chptr->ll_bits, cptr, "%H %C :%s", chptr, who,
473                           comment);
474  
475    sendcmdto_channel_butserv_butone(sptr, CMD_KICK, chptr, NULL, "%H %C :%s", chptr, who,
476 @@ -228,7 +228,7 @@
477      }
478    } else {
479      /* Propagate kick... */
480 -    sendcmdto_serv_butone(sptr, CMD_KICK, cptr, "%H %C :%s", chptr, who,
481 +    sendcmdto_mask_butone(sptr, CMD_KICK, chptr->ll_bits, cptr, "%H %C :%s", chptr, who,
482                           comment);
483  
484      if (member) { /* and tell the channel about it */
485 Index: ircd/m_server.c
486 ===================================================================
487 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_server.c,v
488 retrieving revision 1.26
489 diff -u -r1.26 m_server.c
490 --- ircd/m_server.c     2002/03/19 22:03:36     1.26
491 +++ ircd/m_server.c     2002/04/02 07:11:56
492 @@ -181,6 +181,9 @@
493        case 's':
494         SetService(cptr);
495         break;
496 +      case 'l':
497 +        SetLazy(cptr);
498 +       break;
499        }
500    }
501  
502 Index: ircd/m_topic.c
503 ===================================================================
504 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_topic.c,v
505 retrieving revision 1.10
506 diff -u -r1.10 m_topic.c
507 --- ircd/m_topic.c      2002/02/14 00:20:43     1.10
508 +++ ircd/m_topic.c      2002/04/02 07:11:56
509 @@ -115,8 +115,8 @@
510     chptr->topic_time = CurrentTime;
511     /* Fixed in 2.10.11: Don't propergate local topics */
512     if (!IsLocalChannel(chptr->chname))
513 -     sendcmdto_serv_butone(sptr, CMD_TOPIC, cptr, "%H :%s", chptr,
514 -                          chptr->topic);
515 +     sendcmdto_mask_butone(sptr, CMD_TOPIC, chptr->ll_bits, cptr, "%H %Tu :%s", chptr,
516 +                          chptr->topic_time, chptr->topic);
517     if (newtopic)
518        sendcmdto_channel_butserv_butone(sptr, CMD_TOPIC, chptr, NULL,
519                                        "%H :%s", chptr, chptr->topic);
520 Index: ircd/parse.c
521 ===================================================================
522 RCS file: /home/coder-com/cvs/ircu2.10/ircd/parse.c,v
523 retrieving revision 1.34
524 diff -u -r1.34 parse.c
525 --- ircd/parse.c        2002/03/19 22:03:36     1.34
526 +++ ircd/parse.c        2002/04/02 07:11:57
527 @@ -577,6 +577,13 @@
528      /* UNREG, CLIENT, SERVER, OPER, SERVICE */
529      { m_ignore, m_ignore, ms_account, m_ignore, m_ignore }
530    },
531 +  {
532 +    MSG_FORGET,
533 +    TOK_FORGET,
534 +    0, MAXPARA, MFLG_SLOW, 0,
535 +    /* UNREG, CLIENT, SERVER, OPER, SERVICE */
536 +    { m_ignore, m_ignore, ms_forget, m_ignore, m_ignore }
537 +  },
538    /* This command is an alias for QUIT during the unregistered part of
539     * of the server.  This is because someone jumping via a broken web
540     * proxy will send a 'POST' as their first command - which we will
541 Index: ircd/s_bsd.c
542 ===================================================================
543 RCS file: /home/coder-com/cvs/ircu2.10/ircd/s_bsd.c,v
544 retrieving revision 1.47
545 diff -u -r1.47 s_bsd.c
546 --- ircd/s_bsd.c        2002/04/02 00:26:46     1.47
547 +++ ircd/s_bsd.c        2002/04/02 07:11:58
548 @@ -465,7 +465,8 @@
549    sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s :%s",
550                  cli_name(&me), cli_serv(&me)->timestamp, newts,
551                 MAJOR_PROTOCOL, NumServCap(&me),
552 -               feature_bool(FEAT_HUB) ? "h" : "", cli_info(&me));
553 +               feature_bool(FEAT_HUB) ? "h" :
554 +               feature_bool(FEAT_LAZY_LEAF) ? "l" : "", cli_info(&me));
555  
556    return (IsDead(cptr)) ? 0 : 1;
557  }
558 Index: ircd/s_misc.c
559 ===================================================================
560 RCS file: /home/coder-com/cvs/ircu2.10/ircd/s_misc.c,v
561 retrieving revision 1.31
562 diff -u -r1.31 s_misc.c
563 --- ircd/s_misc.c       2002/04/02 00:26:47     1.31
564 +++ ircd/s_misc.c       2002/04/02 07:11:59
565 @@ -48,6 +48,7 @@
566  #include "s_conf.h"
567  #include "s_debug.h"
568  #include "s_user.h"
569 +#include "s_serv.h"
570  #include "send.h"
571  #include "struct.h"
572  #include "support.h"
573 @@ -477,6 +478,8 @@
574      sendto_opmask_butone(0, SNO_NETWORK, "Net break: %C %C (%s)",
575                          cli_serv(victim)->up, victim, comment);
576  
577 +    if (IsLazy(victim))
578 +      ll_remove(victim);
579  #if defined(HEAD_IN_SAND_MAP) || defined(HEAD_IN_SAND_LINKS)    
580      map_update(victim);
581  #endif
582 Index: ircd/s_serv.c
583 ===================================================================
584 RCS file: /home/coder-com/cvs/ircu2.10/ircd/s_serv.c,v
585 retrieving revision 1.28
586 diff -u -r1.28 s_serv.c
587 --- ircd/s_serv.c       2002/02/14 00:20:44     1.28
588 +++ ircd/s_serv.c       2002/04/02 07:11:59
589 @@ -36,6 +36,7 @@
590  #include "ircd_string.h"
591  #include "ircd_snprintf.h"
592  #include "ircd_xopen.h"
593 +#include "ircd_log.h"
594  #include "jupe.h"
595  #include "list.h"
596  #include "match.h"
597 @@ -61,6 +62,7 @@
598  
599  unsigned int max_connection_count = 0;
600  unsigned int max_client_count = 0;
601 +unsigned long GlobalLeafBits = 0;
602  
603  int exit_new_server(struct Client *cptr, struct Client *sptr, const char *host,
604                      time_t timestamp, const char *pattern, ...)
605 @@ -113,7 +115,8 @@
606      sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s :%s",
607                   cli_name(&me), cli_serv(&me)->timestamp,
608                   cli_serv(cptr)->timestamp, MAJOR_PROTOCOL, NumServCap(&me),
609 -                 feature_bool(FEAT_HUB) ? "h" : "",
610 +                 feature_bool(FEAT_HUB) ? "h" :
611 +                 feature_bool(FEAT_LAZY_LEAF) ? "l" : "",
612                   *(cli_info(&me)) ? cli_info(&me) : "IRCers United");
613      /*
614       * Don't charge this IP# for connecting
615 @@ -135,6 +138,9 @@
616  
617    SetBurst(cptr);
618  
619 +  if (IsLazy(cptr) && !ll_add(cptr))
620 +    ClearLazy(cptr);
621 +
622  /*    nextping = CurrentTime; */
623  
624    /*
625 @@ -241,6 +247,7 @@
626     * Last, send the BURST.
627     * (Or for 2.9 servers: pass all channels plus statuses)
628     */
629 +  if (!IsLazy(cptr))
630    {
631      struct Channel *chptr;
632      for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
633 @@ -252,3 +259,42 @@
634    return 0;
635  }
636  
637 +int ll_add(struct Client *cptr)
638 +{
639 +  int i = 1;
640 +
641 +  assert(IsLazy(cptr));
642 +
643 +  while ((GlobalLeafBits & i) && i < 0x80000000)
644 +    i <<= 1;
645 +  if (GlobalLeafBits & i) {
646 +    sendto_opmask_butone(NULL, SNO_OLDSNO, "No more bits for LazyLeaf %s.", cli_name(cptr));
647 +    return 0;
648 +  }
649 +  GlobalLeafBits |= i;
650 +  cli_serv(cptr)->ll_mask = i;
651 +  log_write(LS_DEBUG, L_DEBUG, 0, "Added LazyLeaf %s with mask 0x%lx. GlobalLeafBits=0x%lx", cli_name(cptr), i, GlobalLeafBits);
652 +  return 1;
653 +}
654 +
655 +void ll_remove(struct Client *cptr)
656 +{
657 +  struct Channel *chptr;
658 +
659 +  assert(IsLazy(cptr));
660 +
661 +  for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
662 +    chptr->ll_bits &= ~cli_serv(cptr)->ll_mask;
663 +
664 +  GlobalLeafBits &= ~cli_serv(cptr)->ll_mask;
665 +  log_write(LS_DEBUG, L_DEBUG, 0, "Removed LazyLeaf %s with mask 0x%lx. GlobalLeafBits=0x%lx", cli_name(cptr), cli_serv(cptr)->ll_mask, GlobalLeafBits);
666 +}
667 +
668 +void ll_check_channel(struct Client *cptr, struct Channel *chptr)
669 +{
670 +  if (feature_bool(FEAT_LAZY_LEAF) && MyUser(cptr) && chptr->locals <= 1) {
671 +    log_write(LS_DEBUG, L_DEBUG, 0, "LazyLeaf: Channel %s has no more locals", chptr->chname);
672 +    sendcmdto_serv_butone(&me, CMD_FORGET, NULL, "%s", chptr->chname);
673 +    chptr->mode.mode |= MODE_EMPTY;
674 +  }
675 +}
676 Index: ircd/send.c
677 ===================================================================
678 RCS file: /home/coder-com/cvs/ircu2.10/ircd/send.c,v
679 retrieving revision 1.46
680 diff -u -r1.46 send.c
681 --- ircd/send.c 2002/02/14 00:20:45     1.46
682 +++ ircd/send.c 2002/04/02 07:11:59
683 @@ -328,6 +328,35 @@
684    msgq_clean(mb);
685  }
686  
687 +void sendcmdto_mask_butone(struct Client *from, const char *cmd,
688 +                          const char *tok, unsigned long ll_mask,
689 +                          struct Client *one,
690 +                          const char *pattern, ...)
691 +{
692 +  struct VarData vd;
693 +  struct MsgBuf *mb;
694 +  struct DLink *lp;
695 +
696 +  vd.vd_format = pattern; /* set up the struct VarData for %v */
697 +  va_start(vd.vd_args, pattern);
698 +
699 +  /* use token */
700 +  mb = msgq_make(&me, "%C %s %v", from, tok, &vd);
701 +  va_end(vd.vd_args);
702 +
703 +  /* send it to our downlinks */
704 +  for (lp = cli_serv(&me)->down; lp; lp = lp->next) {
705 +    if (one && lp->value.cptr == cli_from(one))
706 +      continue;
707 +    if (IsLazy(lp->value.cptr) && !(cli_serv(lp->value.cptr)->ll_mask & ll_mask))
708 +      continue;
709 +    send_buffer(lp->value.cptr, mb, 0);
710 +  }
711 +
712 +  msgq_clean(mb);
713 +}
714 +
715 +
716  /*
717   * Send a (prefix) command originating from <from> to all channels
718   * <from> is locally on.  <from> must be a user. <tok> is ignored in
719 --- /dev/null   Tue Mar 19 18:25:27 2002
720 +++ ircd/m_forget.c     Tue Apr  2 18:49:42 2002
721 @@ -0,0 +1,123 @@
722 +/*
723 + * IRC - Internet Relay Chat, ircd/m_forget.c
724 + * Copyright (C) 2002 Alex Badea <vampire@p16.pub.ro>
725 + *
726 + * See file AUTHORS in IRC package for additional names of
727 + * the programmers.
728 + *
729 + * This program is free software; you can redistribute it and/or modify
730 + * it under the terms of the GNU General Public License as published by
731 + * the Free Software Foundation; either version 1, or (at your option)
732 + * any later version.
733 + *
734 + * This program is distributed in the hope that it will be useful,
735 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
736 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
737 + * GNU General Public License for more details.
738 + *
739 + * You should have received a copy of the GNU General Public License
740 + * along with this program; if not, write to the Free Software
741 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
742 + *
743 + * $Id: lazy.diff,v 1.1 2002-04-02 07:17:11 isomer Exp $
744 + */
745 +
746 +/*
747 + * m_functions execute protocol messages on this server:
748 + *
749 + *    cptr    is always NON-NULL, pointing to a *LOCAL* client
750 + *            structure (with an open socket connected!). This
751 + *            identifies the physical socket where the message
752 + *            originated (or which caused the m_function to be
753 + *            executed--some m_functions may call others...).
754 + *
755 + *    sptr    is the source of the message, defined by the
756 + *            prefix part of the message if present. If not
757 + *            or prefix not found, then sptr==cptr.
758 + *
759 + *            (!IsServer(cptr)) => (cptr == sptr), because
760 + *            prefixes are taken *only* from servers...
761 + *
762 + *            (IsServer(cptr))
763 + *                    (sptr == cptr) => the message didn't
764 + *                    have the prefix.
765 + *
766 + *                    (sptr != cptr && IsServer(sptr) means
767 + *                    the prefix specified servername. (?)
768 + *
769 + *                    (sptr != cptr && !IsServer(sptr) means
770 + *                    that message originated from a remote
771 + *                    user (not local).
772 + *
773 + *            combining
774 + *
775 + *            (!IsServer(sptr)) means that, sptr can safely
776 + *            taken as defining the target structure of the
777 + *            message in this server.
778 + *
779 + *    *Always* true (if 'parse' and others are working correct):
780 + *
781 + *    1)      sptr->from == cptr  (note: cptr->from == cptr)
782 + *
783 + *    2)      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
784 + *            *cannot* be a local connection, unless it's
785 + *            actually cptr!). [MyConnect(x) should probably
786 + *            be defined as (x == x->from) --msa ]
787 + *
788 + *    parc    number of variable parameter strings (if zero,
789 + *            parv is allowed to be NULL)
790 + *
791 + *    parv    a NULL terminated list of parameter pointers,
792 + *
793 + *                    parv[0], sender (prefix string), if not present
794 + *                            this points to an empty string.
795 + *                    parv[1]...parv[parc-1]
796 + *                            pointers to additional parameters
797 + *                    parv[parc] == NULL, *always*
798 + *
799 + *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
800 + *                    non-NULL pointers.
801 + */
802 +#include "config.h"
803 +
804 +#include "client.h"
805 +#include "hash.h"
806 +#include "ircd.h"
807 +#include "ircd_reply.h"
808 +#include "ircd_string.h"
809 +#include "msg.h"
810 +#include "numeric.h"
811 +#include "numnicks.h"
812 +#include "send.h"
813 +#include "channel.h"
814 +#include "ircd_log.h"
815 +
816 +#include <assert.h>
817 +#include <stdlib.h>
818 +
819 +/*
820 + * ms_forget - server message handler
821 + */
822 +int ms_forget(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
823 +{
824 +  struct Channel *chptr;
825 +
826 +  assert(0 != cptr);
827 +  assert(0 != sptr);
828 +  assert(IsServer(cptr));
829 +
830 +  if (parc < 2)
831 +    return need_more_params(sptr, "FORGET");
832 +
833 +  if (!IsLazy(cptr))
834 +    return 0;
835 +
836 +  /* Don't pass on forget messages for channels that exist */
837 +  if (!(chptr = FindChannel(parv[1])))
838 +    return 0;
839 +
840 +  chptr->ll_bits &= ~cli_serv(cptr)->ll_mask;
841 +  log_write(LS_DEBUG, L_DEBUG, 0, "LazyLeaf %s forgot about %s", cli_name(cptr), chptr->chname);
842 +
843 +  return 0;
844 +}