ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/channel.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/channel.c (file contents):
Revision 6867 by michael, Mon Nov 30 19:29:46 2015 UTC vs.
Revision 7612 by michael, Tue Jun 21 12:57:05 2016 UTC

# Line 1 | Line 1
1   /*
2   *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (c) 1997-2015 ircd-hybrid development team
4 > *  Copyright (c) 1997-2016 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 31 | Line 31
31   #include "client.h"
32   #include "hash.h"
33   #include "conf.h"
34 + #include "conf_resv.h"
35   #include "hostmask.h"
36   #include "irc_string.h"
37   #include "ircd.h"
# Line 41 | Line 42
42   #include "memory.h"
43   #include "mempool.h"
44   #include "misc.h"
44 #include "resv.h"
45  
46  
47   dlink_list channel_list;
48   mp_pool_t *ban_pool;    /*! \todo ban_pool shouldn't be a global var */
49  
50 < static mp_pool_t *member_pool, *channel_pool;
50 > static mp_pool_t *member_pool, *channel_pool, *invite_pool;
51  
52  
53   /*! \brief Initializes the channel blockheap, adds known channel CAPAB
# Line 58 | Line 58 | channel_init(void)
58    add_capability("EX", CAPAB_EX);
59    add_capability("IE", CAPAB_IE);
60  
61 +  invite_pool = mp_pool_new(sizeof(struct Invite), MP_CHUNK_SIZE_INVITE);
62    channel_pool = mp_pool_new(sizeof(struct Channel), MP_CHUNK_SIZE_CHANNEL);
63    ban_pool = mp_pool_new(sizeof(struct Ban), MP_CHUNK_SIZE_BAN);
64    member_pool = mp_pool_new(sizeof(struct Membership), MP_CHUNK_SIZE_MEMBER);
# Line 74 | Line 75 | void
75   add_user_to_channel(struct Channel *chptr, struct Client *client_p,
76                      unsigned int flags, int flood_ctrl)
77   {
77  struct Membership *member = NULL;
78
78    assert(IsClient(client_p));
79  
80    if (GlobalSetOptions.joinfloodtime > 0)
# Line 109 | Line 108 | add_user_to_channel(struct Channel *chpt
108      chptr->last_join_time = CurrentTime;
109    }
110  
111 <  member = mp_pool_get(member_pool);
111 >  struct Membership *member = mp_pool_get(member_pool);
112    member->client_p = client_p;
113    member->chptr = chptr;
114    member->flags = flags;
# Line 224 | Line 223 | channel_send_mask_list(struct Client *cl
223    int tlen, mlen, cur_len;
224    char *pp = pbuf;
225  
226 <  if (!list->length)
226 >  if (!dlink_list_length(list))
227      return;
228  
229    mlen = snprintf(mbuf, sizeof(mbuf), ":%s BMASK %ju %s %c :", me.id,
# Line 322 | Line 321 | remove_ban(struct Ban *ban, dlink_list *
321   static void
322   channel_free_mask_list(dlink_list *list)
323   {
324 <  dlink_node *node = NULL, *node_next = NULL;
325 <
326 <  DLINK_FOREACH_SAFE(node, node_next, list->head)
327 <    remove_ban(node->data, list);
324 >  while (list->head)
325 >  {
326 >    struct Ban *ban = list->head->data;
327 >    remove_ban(ban, list);
328 >  }
329   }
330  
331   /*! \brief Get Channel block for name (and allocate a new channel
# Line 346 | Line 346 | channel_make(const char *name)
346    chptr->creationtime = CurrentTime;
347    chptr->last_join_time = CurrentTime;
348  
349 <  strlcpy(chptr->name, name, sizeof(chptr->name));
350 <  dlinkAdd(chptr, &chptr->node, &channel_list);
349 >  chptr->name_len = strlcpy(chptr->name, name, sizeof(chptr->name));
350 >  if (chptr->name_len >= sizeof(chptr->name))
351 >    chptr->name_len = sizeof(chptr->name) - 1;
352  
353 +  dlinkAdd(chptr, &chptr->node, &channel_list);
354    hash_add_channel(chptr);
355  
356    return chptr;
# Line 469 | Line 471 | channel_member_names(struct Client *clie
471      sendto_one_numeric(client_p, &me, RPL_ENDOFNAMES, chptr->name);
472   }
473  
474 + static struct Invite *
475 + find_invite(struct Channel *chptr, struct Client *client_p)
476 + {
477 +  dlink_node *node, *node_next;
478 +  dlink_list *list;
479 +
480 +  if (dlink_list_length(&client_p->connection->invited) < dlink_list_length(&chptr->invites))
481 +    list = &client_p->connection->invited;
482 +  else
483 +    list = &chptr->invites;
484 +
485 +  DLINK_FOREACH_SAFE(node, node_next, list->head)
486 +  {
487 +    struct Invite *invite = node->data;
488 +
489 +    if (invite->chptr == chptr && invite->client_p == client_p)
490 +      return invite;
491 +  }
492 +
493 +  return NULL;
494 + }
495 +
496   /*! \brief Adds client to invite list
497   * \param chptr    Pointer to channel block
498   * \param client_p Pointer to client to add invite to
# Line 476 | Line 500 | channel_member_names(struct Client *clie
500   void
501   add_invite(struct Channel *chptr, struct Client *client_p)
502   {
503 <  assert(IsClient(client_p));
503 >  struct Invite *invite;
504  
505 <  del_invite(chptr, client_p);
505 >  if ((invite = find_invite(chptr, client_p)))
506 >    del_invite(invite);
507  
508 <  /*
509 <   * Delete last link in chain if the list is max length
510 <   */
511 <  if (dlink_list_length(&client_p->connection->invited) >=
512 <      ConfigChannel.max_channels)
513 <    del_invite(client_p->connection->invited.tail->data, client_p);
508 >  invite = mp_pool_get(invite_pool);
509 >  invite->client_p = client_p;
510 >  invite->chptr = chptr;
511 >  invite->when = CurrentTime;
512 >
513 >  /* Delete last link in chain if the list is max length */
514 >  while (dlink_list_length(&client_p->connection->invited) &&
515 >         dlink_list_length(&client_p->connection->invited) >= ConfigChannel.max_channels)
516 >    del_invite(client_p->connection->invited.tail->data);
517  
518    /* Add client to channel invite list */
519 <  dlinkAdd(client_p, make_dlink_node(), &chptr->invites);
519 >  dlinkAdd(invite, &invite->chan_node, &chptr->invites);
520  
521    /* Add channel to the end of the client invite list */
522 <  dlinkAdd(chptr, make_dlink_node(), &client_p->connection->invited);
522 >  dlinkAdd(invite, &invite->user_node, &client_p->connection->invited);
523   }
524  
525   /*! \brief Delete Invite block from channel invite list
526   *         and client invite list
527 < * \param chptr    Pointer to Channel struct
500 < * \param client_p Pointer to client to remove invites from
527 > * \param invite Pointer to Invite struct
528   */
529   void
530 < del_invite(struct Channel *chptr, struct Client *client_p)
530 > del_invite(struct Invite *invite)
531   {
532 <  dlink_node *node = NULL;
533 <
507 <  if ((node = dlinkFindDelete(&client_p->connection->invited, chptr)))
508 <    free_dlink_node(node);
532 >  dlinkDelete(&invite->user_node, &invite->client_p->connection->invited);
533 >  dlinkDelete(&invite->chan_node, &invite->chptr->invites);
534  
535 <  if ((node = dlinkFindDelete(&chptr->invites, client_p)))
536 <    free_dlink_node(node);
535 >  /* Release memory pointed to by 'invite' */
536 >  mp_pool_release(invite);
537   }
538  
539   /*! \brief Removes all invites of a specific channel
# Line 517 | Line 542 | del_invite(struct Channel *chptr, struct
542   void
543   clear_invites_channel(struct Channel *chptr)
544   {
545 <  dlink_node *node = NULL, *node_next = NULL;
546 <
522 <  DLINK_FOREACH_SAFE(node, node_next, chptr->invites.head)
523 <    del_invite(chptr, node->data);
545 >  while (chptr->invites.head)
546 >    del_invite(chptr->invites.head->data);
547   }
548  
549   /*! \brief Removes all invites of a specific client
# Line 529 | Line 552 | clear_invites_channel(struct Channel *ch
552   void
553   clear_invites_client(struct Client *client_p)
554   {
555 <  dlink_node *node = NULL, *node_next = NULL;
556 <
534 <  DLINK_FOREACH_SAFE(node, node_next, client_p->connection->invited.head)
535 <    del_invite(node->data, client_p);
555 >  while (client_p->connection->invited.head)
556 >    del_invite(client_p->connection->invited.head->data);
557   }
558  
559   /* get_member_status()
# Line 549 | Line 570 | clear_invites_client(struct Client *clie
570   const char *
571   get_member_status(const struct Membership *member, const int combine)
572   {
573 <  static char buffer[4];  /* 4 for @%+\0 */
573 >  static char buffer[CMEMBER_STATUS_FLAGS_LEN + 1];  /* +1 for \0 */
574    char *p = buffer;
575  
576    if (member->flags & CHFL_CHANOP)
# Line 579 | Line 600 | get_member_status(const struct Membershi
600   * \return 1 if ban found for given n!u\@h mask, 0 otherwise
601   */
602   static int
603 < find_bmask(const struct Client *client_p, const dlink_list *const list)
603 > find_bmask(const struct Client *client_p, const dlink_list *list)
604   {
605    const dlink_node *node = NULL;
606  
# Line 636 | Line 657 | is_banned(const struct Channel *chptr, c
657   * \return ERR_BANNEDFROMCHAN, ERR_INVITEONLYCHAN, ERR_CHANNELISFULL
658   *         or 0 if allowed to join.
659   */
660 < int
661 < can_join(struct Client *client_p, const struct Channel *chptr, const char *key)
660 > static int
661 > can_join(struct Client *client_p, struct Channel *chptr, const char *key)
662   {
663    if ((chptr->mode.mode & MODE_SSLONLY) && !HasUMode(client_p, UMODE_SSL))
664      return ERR_SSLONLYCHAN;
# Line 649 | Line 670 | can_join(struct Client *client_p, const
670      return ERR_OPERONLYCHAN;
671  
672    if (chptr->mode.mode & MODE_INVITEONLY)
673 <    if (!dlinkFind(&client_p->connection->invited, chptr))
673 >    if (!find_invite(chptr, client_p))
674        if (!find_bmask(client_p, &chptr->invexlist))
675          return ERR_INVITEONLYCHAN;
676  
# Line 740 | Line 761 | int
761   can_send(struct Channel *chptr, struct Client *client_p,
762           struct Membership *member, const char *message, int notice)
763   {
764 <  const struct MaskItem *conf = NULL;
764 >  const struct ResvItem *resv = NULL;
765  
766    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE))
767      return CAN_SEND_OPV;
768  
769 <  if (MyClient(client_p) && !HasFlag(client_p, FLAGS_EXEMPTRESV))
769 >  if (MyConnect(client_p) && !HasFlag(client_p, FLAGS_EXEMPTRESV))
770      if (!(HasUMode(client_p, UMODE_OPER) && HasOFlag(client_p, OPER_FLAG_JOIN_RESV)))
771 <      if ((conf = match_find_resv(chptr->name)) && !resv_find_exempt(client_p, conf))
771 >      if ((resv = resv_find(chptr->name, match)) && !resv_exempt_find(client_p, resv))
772          return ERR_CANNOTSENDTOCHAN;
773  
774    if ((chptr->mode.mode & MODE_NOCTRL) && msg_has_ctrls(message))
# Line 774 | Line 795 | can_send(struct Channel *chptr, struct C
795      return ERR_CANNOTSENDTOCHAN;
796  
797    /* Cache can send if banned */
798 <  if (MyClient(client_p))
798 >  if (MyConnect(client_p))
799    {
800      if (member)
801      {
# Line 871 | Line 892 | check_spambot_warning(struct Client *cli
892   */
893   void
894   channel_set_topic(struct Channel *chptr, const char *topic,
895 <                  const char *topic_info, time_t topicts, int local)
895 >                  const char *topic_info, uintmax_t topicts, int local)
896   {
897    if (local)
898      strlcpy(chptr->topic, topic, IRCD_MIN(sizeof(chptr->topic), ConfigServerInfo.max_topic_length + 1));
# Line 894 | Line 915 | channel_set_topic(struct Channel *chptr,
915   void
916   channel_do_join_0(struct Client *client_p)
917   {
897  dlink_node *node = NULL, *node_next = NULL;
898
918    if (client_p->channel.head)
919      if (MyConnect(client_p) && !HasUMode(client_p, UMODE_OPER))
920        check_spambot_warning(client_p, NULL);
921  
922 <  DLINK_FOREACH_SAFE(node, node_next, client_p->channel.head)
922 >  while (client_p->channel.head)
923    {
924 <    struct Channel *chptr = ((struct Membership *)node->data)->chptr;
924 >    struct Membership *member = client_p->channel.head->data;
925  
926      sendto_server(client_p, 0, 0, ":%s PART %s",
927 <                  client_p->id, chptr->name);
928 <    sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s!%s@%s PART %s",
927 >                  client_p->id, member->chptr->name);
928 >    sendto_channel_local(NULL, member->chptr, 0, 0, 0, ":%s!%s@%s PART %s",
929                           client_p->name, client_p->username,
930 <                         client_p->host, chptr->name);
930 >                         client_p->host, member->chptr->name);
931  
932 <    remove_user_from_channel(node->data);
932 >    remove_user_from_channel(member);
933    }
934   }
935  
# Line 949 | Line 968 | void
968   channel_do_join(struct Client *client_p, char *channel, char *key_list)
969   {
970    char *p = NULL;
952  char *chan = NULL;
971    char *chan_list = NULL;
972    struct Channel *chptr = NULL;
973 <  struct MaskItem *conf = NULL;
973 >  const struct ResvItem *resv = NULL;
974    const struct ClassItem *const class = get_class_ptr(&client_p->connection->confs);
957  int i = 0;
975    unsigned int flags = 0;
976  
977    assert(IsClient(client_p));
978  
979    chan_list = channel_find_last0(client_p, channel);
980  
981 <  for (chan = strtok_r(chan_list, ",", &p); chan;
982 <       chan = strtok_r(NULL,      ",", &p))
981 >  for (const char *chan = strtok_r(chan_list, ",", &p); chan;
982 >                   chan = strtok_r(NULL,      ",", &p))
983    {
984      const char *key = NULL;
985  
# Line 982 | Line 999 | channel_do_join(struct Client *client_p,
999  
1000      if (!HasFlag(client_p, FLAGS_EXEMPTRESV) &&
1001          !(HasUMode(client_p, UMODE_OPER) && HasOFlag(client_p, OPER_FLAG_JOIN_RESV)) &&
1002 <        ((conf = match_find_resv(chan)) && !resv_find_exempt(client_p, conf)))
1002 >        ((resv = resv_find(chan, match)) && !resv_exempt_find(client_p, resv)))
1003      {
1004 <      ++conf->count;
988 <      sendto_one_numeric(client_p, &me, ERR_CHANBANREASON, chan, conf->reason);
1004 >      sendto_one_numeric(client_p, &me, ERR_CHANBANREASON, chan, resv->reason);
1005        sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
1006                             "Forbidding reserved channel %s from user %s",
1007                             chan, get_client_name(client_p, HIDE_IP));
# Line 1004 | Line 1020 | channel_do_join(struct Client *client_p,
1020        if (IsMember(client_p, chptr))
1021          continue;
1022  
1023 <      /*
1024 <       * can_join checks for +i key, bans.
1025 <       */
1010 <      if ((i = can_join(client_p, chptr, key)))
1023 >      /* can_join() checks for +i, +l, key, bans, etc. */
1024 >      int ret = can_join(client_p, chptr, key);
1025 >      if (ret)
1026        {
1027 <        sendto_one_numeric(client_p, &me, i, chptr->name);
1027 >        sendto_one_numeric(client_p, &me, ret, chptr->name);
1028          continue;
1029        }
1030  
# Line 1084 | Line 1099 | channel_do_join(struct Client *client_p,
1099                               client_p->host, client_p->away);
1100      }
1101  
1102 <    del_invite(chptr, client_p);
1102 >    struct Invite *invite = find_invite(chptr, client_p);
1103 >    if (invite)
1104 >      del_invite(invite);
1105  
1106      if (chptr->topic[0])
1107      {
# Line 1100 | Line 1117 | channel_do_join(struct Client *client_p,
1117   }
1118  
1119   /*! \brief Removes a client from a specific channel
1120 < * \param client_p Pointer to source client to remove
1120 > * \param client_p Pointer to client to remove
1121   * \param name     Name of channel to remove from
1122   * \param reason   Part reason to show
1123   */
# Line 1130 | Line 1147 | channel_part_one_client(struct Client *c
1147     * only allow /part reasons in -m chans
1148     */
1149    if (*reason && (!MyConnect(client_p) ||
1150 <      ((can_send(chptr, client_p, member, reason, 0) < 0 &&
1151 <       (client_p->connection->firsttime + ConfigGeneral.anti_spam_exit_message_time)
1152 <        < CurrentTime))))
1150 >      ((client_p->connection->firsttime +
1151 >        ConfigGeneral.anti_spam_exit_message_time) < CurrentTime &&
1152 >       can_send(chptr, client_p, member, reason, 0) < 0)))
1153    {
1154      sendto_server(client_p, 0, 0, ":%s PART %s :%s",
1155                    client_p->id, chptr->name, reason);

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)