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

Comparing ircd-hybrid/trunk/src/send.c (file contents):
Revision 3335 by michael, Thu Apr 17 18:55:31 2014 UTC vs.
Revision 4804 by michael, Tue Oct 28 15:27:43 2014 UTC

# Line 15 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
20   */
21  
# Line 35 | Line 35
35   #include "numeric.h"
36   #include "fdlist.h"
37   #include "s_bsd.h"
38 < #include "s_serv.h"
38 > #include "server.h"
39   #include "conf.h"
40   #include "log.h"
41   #include "memory.h"
42   #include "packet.h"
43  
44  
45 < static unsigned int current_serial = 0;
45 > static uint64_t current_serial;
46  
47  
48   /* send_format()
# Line 71 | Line 71 | send_format(struct dbuf_block *buffer, c
71     */
72    dbuf_put_args(buffer, pattern, args);
73  
74 <  if (buffer->size > sizeof(buffer->data) - 2)
75 <    buffer->size = sizeof(buffer->data) - 2;
74 >  if (buffer->size > IRCD_BUFSIZE - 2)
75 >    buffer->size = IRCD_BUFSIZE - 2;
76  
77    buffer->data[buffer->size++] = '\r';
78    buffer->data[buffer->size++] = '\n';
# Line 88 | Line 88 | send_message(struct Client *to, struct d
88   {
89    assert(!IsMe(to));
90    assert(to != &me);
91 +  assert(MyConnect(to));
92  
93 <  if (dbuf_length(&to->localClient->buf_sendq) + buf->size > get_sendq(&to->localClient->confs))
93 >  if (dbuf_length(&to->connection->buf_sendq) + buf->size > get_sendq(&to->connection->confs))
94    {
95      if (IsServer(to))
96        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
97                             "Max SendQ limit exceeded for %s: %lu > %u",
98                             get_client_name(to, HIDE_IP),
99 <                           (unsigned long)(dbuf_length(&to->localClient->buf_sendq) + buf->size),
100 <                           get_sendq(&to->localClient->confs));
99 >                           (unsigned long)(dbuf_length(&to->connection->buf_sendq) + buf->size),
100 >                           get_sendq(&to->connection->confs));
101      if (IsClient(to))
102        SetSendQExceeded(to);
103  
# Line 104 | Line 105 | send_message(struct Client *to, struct d
105      return;
106    }
107  
108 <  dbuf_add(&to->localClient->buf_sendq, buf);
108 >  dbuf_add(&to->connection->buf_sendq, buf);
109  
110    /*
111     * Update statistics. The following is slightly incorrect because
112     * it counts messages even if queued, but bytes only really sent.
113     * Queued bytes get updated in send_queued_write().
114     */
115 <  ++to->localClient->send.messages;
116 <  ++me.localClient->send.messages;
115 >  ++to->connection->send.messages;
116 >  ++me.connection->send.messages;
117  
118    send_queued_write(to);
119   }
# Line 130 | Line 131 | send_message(struct Client *to, struct d
131   static void
132   send_message_remote(struct Client *to, struct Client *from, struct dbuf_block *buf)
133   {
134 <  to = to->from;
134 <
135 <  if (!MyConnect(to))
136 <  {
137 <    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
138 <                         "Server send message to %s [%s] dropped from %s(Not local server)",
139 <                         to->name, to->from->name, from->name);
140 <    return;
141 <  }
134 >  assert(MyConnect(to));
135  
136    /* Optimize by checking if (from && to) before everything */
137    /* we set to->from up there.. */
# Line 182 | Line 175 | send_message_remote(struct Client *to, s
175   **      Called when a socket is ready for writing.
176   */
177   void
178 < sendq_unblocked(fde_t *fd, struct Client *client_p)
178 > sendq_unblocked(fde_t *fd, void *data)
179   {
180 <  assert(fd == &client_p->localClient->fd);
180 >  struct Client *client_p = data;
181 >  assert(fd == &client_p->connection->fd);
182  
183    DelFlag(client_p, FLAGS_BLOCKED);
184    send_queued_write(client_p);
# Line 209 | Line 203 | send_queued_write(struct Client *to)
203      return;  /* no use calling send() now */
204  
205    /* Next, lets try to write some data */
206 <  if (dbuf_length(&to->localClient->buf_sendq))
206 >  if (dbuf_length(&to->connection->buf_sendq))
207    {
208      do
209      {
210 <      struct dbuf_block *first = to->localClient->buf_sendq.blocks.head->data;
210 >      struct dbuf_block *first = to->connection->buf_sendq.blocks.head->data;
211  
212   #ifdef HAVE_LIBCRYPTO
213 <      if (to->localClient->fd.ssl)
213 >      if (to->connection->fd.ssl)
214        {
215 <        retlen = SSL_write(to->localClient->fd.ssl, first->data + to->localClient->buf_sendq.pos, first->size - to->localClient->buf_sendq.pos);
215 >        retlen = SSL_write(to->connection->fd.ssl, first->data + to->connection->buf_sendq.pos, first->size - to->connection->buf_sendq.pos);
216  
217          /* translate openssl error codes, sigh */
218          if (retlen < 0)
219          {
220 <          switch (SSL_get_error(to->localClient->fd.ssl, retlen))
220 >          switch (SSL_get_error(to->connection->fd.ssl, retlen))
221            {
222              case SSL_ERROR_WANT_READ:
223                return;  /* retry later, don't register for write events */
# Line 241 | Line 235 | send_queued_write(struct Client *to)
235        }
236        else
237   #endif
238 <        retlen = send(to->localClient->fd.fd, first->data + to->localClient->buf_sendq.pos, first->size - to->localClient->buf_sendq.pos, 0);
238 >        retlen = send(to->connection->fd.fd, first->data + to->connection->buf_sendq.pos, first->size - to->connection->buf_sendq.pos, 0);
239  
240        if (retlen <= 0)
241          break;
242  
243 <      dbuf_delete(&to->localClient->buf_sendq, retlen);
243 >      dbuf_delete(&to->connection->buf_sendq, retlen);
244  
245        /* We have some data written .. update counters */
246 <      to->localClient->send.bytes += retlen;
247 <      me.localClient->send.bytes += retlen;
248 <    } while (dbuf_length(&to->localClient->buf_sendq));
246 >      to->connection->send.bytes += retlen;
247 >      me.connection->send.bytes += retlen;
248 >    } while (dbuf_length(&to->connection->buf_sendq));
249  
250      if (retlen < 0 && ignoreErrno(errno))
251      {
252        AddFlag(to, FLAGS_BLOCKED);
253  
254        /* we have a non-fatal error, reschedule a write */
255 <      comm_setselect(&to->localClient->fd, COMM_SELECT_WRITE,
256 <                     (PF *)sendq_unblocked, to, 0);
255 >      comm_setselect(&to->connection->fd, COMM_SELECT_WRITE,
256 >                     sendq_unblocked, to, 0);
257      }
258      else if (retlen <= 0)
259      {
# Line 283 | Line 277 | send_queued_all(void)
277    /* Servers are processed first, mainly because this can generate
278     * a notice to opers, which is to be delivered by this function.
279     */
280 <  DLINK_FOREACH(ptr, serv_list.head)
280 >  DLINK_FOREACH(ptr, local_server_list.head)
281      send_queued_write(ptr->data);
282  
283    DLINK_FOREACH(ptr, unknown_list.head)
# Line 331 | Line 325 | void
325   sendto_one_numeric(struct Client *to, struct Client *from, enum irc_numerics numeric, ...)
326   {
327    struct dbuf_block *buffer = NULL;
328 <  const char *dest = NULL;
328 >  const char *dest = NULL, *numstr = NULL;
329    va_list args;
330  
331    if (IsDead(to->from))
# Line 344 | Line 338 | sendto_one_numeric(struct Client *to, st
338  
339    buffer = dbuf_alloc();
340  
341 <  dbuf_put_fmt(buffer, ":%s %03d %s ", ID_or_name(from, to), numeric, dest);
341 >  dbuf_put_fmt(buffer, ":%s %03d %s ", ID_or_name(from, to), numeric & ~SND_EXPLICIT, dest);
342  
343    va_start(args, numeric);
344 <  send_format(buffer, numeric_form(numeric), args);
344 >
345 >  if (numeric & SND_EXPLICIT)
346 >    numstr = va_arg(args, const char *);
347 >  else
348 >    numstr = numeric_form(numeric);
349 >
350 >  send_format(buffer, numstr, args);
351    va_end(args);
352  
353    send_message(to->from, buffer);
# Line 405 | Line 405 | sendto_channel_butone(struct Client *one
405  
406    local_buf = dbuf_alloc(), remote_buf = dbuf_alloc();
407  
408 <  if (IsServer(from))
409 <    dbuf_put_fmt(local_buf, ":%s ", from->name);
410 <  else
408 >  if (IsClient(from))
409      dbuf_put_fmt(local_buf, ":%s!%s@%s ", from->name, from->username, from->host);
410 +  else
411 +    dbuf_put_fmt(local_buf, ":%s ", from->name);
412  
413    dbuf_put_fmt(remote_buf, ":%s ", from->id);
414  
# Line 438 | Line 438 | sendto_channel_butone(struct Client *one
438  
439      if (MyConnect(target_p))
440        send_message(target_p, local_buf);
441 <    else if (target_p->from->localClient->serial != current_serial)
441 >    else if (target_p->from->connection->serial != current_serial)
442        send_message_remote(target_p->from, from, remote_buf);
443 <    target_p->from->localClient->serial = current_serial;
443 >    target_p->from->connection->serial = current_serial;
444    }
445  
446    dbuf_ref_free(local_buf);
# Line 481 | Line 481 | sendto_server(struct Client *one,
481    send_format(buffer, format, args);
482    va_end(args);
483  
484 <  DLINK_FOREACH(ptr, serv_list.head)
484 >  DLINK_FOREACH(ptr, local_server_list.head)
485    {
486      struct Client *client_p = ptr->data;
487  
# Line 492 | Line 492 | sendto_server(struct Client *one,
492      if (one && (client_p == one->from))
493        continue;
494      /* check we have required capabs */
495 <    if ((client_p->localClient->caps & caps) != caps)
495 >    if ((client_p->connection->caps & caps) != caps)
496        continue;
497      /* check we don't have any forbidden capabs */
498 <    if ((client_p->localClient->caps & nocaps))
498 >    if ((client_p->connection->caps & nocaps))
499        continue;
500  
501      send_message(client_p, buffer);
# Line 537 | Line 537 | sendto_common_channels_local(struct Clie
537    {
538      chptr = ((struct Membership *)cptr->data)->chptr;
539  
540 <    DLINK_FOREACH(uptr, chptr->members.head)
540 >    DLINK_FOREACH(uptr, chptr->locmembers.head)
541      {
542        ms = uptr->data;
543        target_p = ms->client_p;
544  
545 <      if (!MyConnect(target_p) || target_p == user || IsDefunct(target_p) ||
546 <          target_p->localClient->serial == current_serial)
545 >      if (target_p == user || IsDefunct(target_p) ||
546 >          target_p->connection->serial == current_serial)
547          continue;
548  
549        if (HasCap(target_p, cap) != cap)
550          continue;
551  
552 <      target_p->localClient->serial = current_serial;
552 >      target_p->connection->serial = current_serial;
553        send_message(target_p, buffer);
554      }
555    }
556  
557    if (touser && MyConnect(user) && !IsDead(user) &&
558 <      user->localClient->serial != current_serial)
558 >      user->connection->serial != current_serial)
559      if (HasCap(user, cap) == cap)
560        send_message(user, buffer);
561  
# Line 565 | Line 565 | sendto_common_channels_local(struct Clie
565   /* sendto_channel_local()
566   *
567   * inputs       - member status mask, e.g. CHFL_CHANOP | CHFL_VOICE
568 *              - whether to ignore +D clients (YES/NO)
568   *              - pointer to channel to send to
569   *              - var args pattern
570   * output       - NONE
# Line 573 | Line 572 | sendto_common_channels_local(struct Clie
572   *                locally connected to this server.
573   */
574   void
575 < sendto_channel_local(unsigned int type, int nodeaf, struct Channel *chptr,
575 > sendto_channel_local(unsigned int type, struct Channel *chptr,
576                       const char *pattern, ...)
577   {
578    va_list args;
# Line 586 | Line 585 | sendto_channel_local(unsigned int type,
585    send_format(buffer, pattern, args);
586    va_end(args);
587  
588 <  DLINK_FOREACH(ptr, chptr->members.head)
588 >  DLINK_FOREACH(ptr, chptr->locmembers.head)
589    {
590      struct Membership *ms = ptr->data;
591      struct Client *target_p = ms->client_p;
# Line 594 | Line 593 | sendto_channel_local(unsigned int type,
593      if (type && (ms->flags & type) == 0)
594        continue;
595  
596 <    if (!MyConnect(target_p) || IsDefunct(target_p) ||
598 <        (nodeaf && HasUMode(target_p, UMODE_DEAF)))
596 >    if (IsDefunct(target_p))
597        continue;
598  
599      send_message(target_p, buffer);
# Line 617 | Line 615 | sendto_channel_local(unsigned int type,
615   * WARNING - +D clients are omitted
616   */
617   void
618 < sendto_channel_local_butone(struct Client *one, unsigned int type, unsigned int cap,
618 > sendto_channel_local_butone(struct Client *one, unsigned int poscap, unsigned int negcap,
619                              struct Channel *chptr, const char *pattern, ...)
620   {
621    va_list args;
622    dlink_node *ptr = NULL;
623 <  struct dbuf_block *buffer;
626 <
627 <  buffer = dbuf_alloc();
623 >  struct dbuf_block *buffer = dbuf_alloc();
624  
625    va_start(args, pattern);
626    send_format(buffer, pattern, args);
627    va_end(args);
628  
629 <  DLINK_FOREACH(ptr, chptr->members.head)
629 >  DLINK_FOREACH(ptr, chptr->locmembers.head)
630    {
631      struct Membership *ms = ptr->data;
632      struct Client *target_p = ms->client_p;
633  
634 <    if (type && (ms->flags & type) == 0)
634 >    if (one && target_p == one->from)
635        continue;
636  
637 <    if (!MyConnect(target_p) || (one && target_p == one->from))
637 >    if (IsDefunct(target_p))
638        continue;
639  
640 <    if (IsDefunct(target_p) || HasUMode(target_p, UMODE_DEAF))
640 >    if (poscap && HasCap(target_p, poscap) != poscap)
641        continue;
642  
643 <    if (HasCap(target_p, cap) != cap)
643 >    if (negcap && HasCap(target_p, negcap))
644        continue;
645  
646      send_message(target_p, buffer);
# Line 717 | Line 713 | sendto_match_butone(struct Client *one,
713    }
714  
715    /* Now scan servers */
716 <  DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
716 >  DLINK_FOREACH_SAFE(ptr, ptr_next, local_server_list.head)
717    {
718      struct Client *client_p = ptr->data;
719  
# Line 767 | Line 763 | sendto_match_servs(struct Client *source
763                     const char *pattern, ...)
764   {
765    va_list args;
766 <  dlink_node *ptr = NULL;
767 <  struct dbuf_block *buff_suid;
772 <
773 <  buff_suid = dbuf_alloc();
766 >  dlink_node *ptr = NULL, *ptr_next = NULL;
767 >  struct dbuf_block *buffer = dbuf_alloc();
768  
769 +  dbuf_put_fmt(buffer, ":%s ", source_p->id);
770    va_start(args, pattern);
771 <  dbuf_put_fmt(buff_suid, ":%s ", source_p->id);
777 <  dbuf_put_args(buff_suid, pattern, args);
771 >  send_format(buffer, pattern, args);
772    va_end(args);
773  
774    ++current_serial;
775  
776 <  DLINK_FOREACH(ptr, global_serv_list.head)
776 >  DLINK_FOREACH_SAFE(ptr, ptr_next, global_server_list.head)
777    {
778      struct Client *target_p = ptr->data;
779  
# Line 787 | Line 781 | sendto_match_servs(struct Client *source
781      if (IsMe(target_p) || target_p->from == source_p->from)
782        continue;
783  
784 <    if (target_p->from->localClient->serial == current_serial)
784 >    if (target_p->from->connection->serial == current_serial)
785        continue;
786  
787 <    if (!match(mask, target_p->name))
788 <    {
795 <      /*
796 <       * if we set the serial here, then we'll never do a
797 <       * match() again, if !IsCapable()
798 <       */
799 <      target_p->from->localClient->serial = current_serial;
787 >    if (match(mask, target_p->name))
788 >      continue;
789  
790 <      if (!IsCapable(target_p->from, cap))
791 <        continue;
790 >    /*
791 >     * If we set the serial here, then we'll never do a
792 >     * match() again, if !IsCapable()
793 >     */
794 >    target_p->from->connection->serial = current_serial;
795  
796 <      send_message_remote(target_p->from, source_p, buff_suid);
797 <    }
796 >    if (!IsCapable(target_p->from, cap))
797 >      continue;
798 >
799 >    send_message_remote(target_p->from, source_p, buffer);
800    }
801  
802 <  dbuf_ref_free(buff_suid);
802 >  dbuf_ref_free(buffer);
803   }
804  
805   /* sendto_anywhere()
# Line 841 | Line 835 | sendto_anywhere(struct Client *to, struc
835    send_format(buffer, pattern, args);
836    va_end(args);
837  
838 <  if (MyClient(to))
838 >  if (MyConnect(to))
839      send_message(to, buffer);
840    else
841 <    send_message_remote(to, from, buffer);
841 >    send_message_remote(to->from, from, buffer);
842  
843    dbuf_ref_free(buffer);
844   }
# Line 911 | Line 905 | sendto_realops_flags(unsigned int flags,
905   *                (at most 5 warnings every 5 seconds)
906   */
907   void
908 < sendto_realops_flags_ratelimited(const char *pattern, ...)
908 > sendto_realops_flags_ratelimited(time_t *rate, const char *pattern, ...)
909   {
910    va_list args;
911    char buffer[IRCD_BUFSIZE] = "";
918  static time_t last = 0;
919  static int warnings = 0;
912  
913 <  if (CurrentTime - last < 5)
914 <  {
915 <    if (++warnings > 5)
924 <      return;
925 <  }
926 <  else
927 <  {
928 <    last = CurrentTime;
929 <    warnings = 0;
930 <  }
913 >  if ((CurrentTime - *rate) < 20)
914 >    return;
915 >  *rate = CurrentTime;
916  
917    va_start(args, pattern);
918    vsnprintf(buffer, sizeof(buffer), pattern, args);

Diff Legend

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