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 3241 by michael, Sun Mar 30 16:45:31 2014 UTC vs.
Revision 4209 by michael, Sat Jul 12 18:15:19 2014 UTC

# 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 #ifndef IOV_MAX
45 #define IOV_MAX 64
46 #endif
44  
45   static unsigned int current_serial = 0;
46  
# Line 188 | Line 185 | void
185   sendq_unblocked(fde_t *fd, struct Client *client_p)
186   {
187    assert(fd == &client_p->localClient->fd);
191  send_queued_write(client_p);
192 }
193
194 #ifdef HAVE_LIBCRYPTO
195 static int
196 send_SSL_writev(SSL *ssl, const struct iovec *vec, int iovcnt)
197 {
198  int total_written = 0;
199
200  for (int i = 0; i < iovcnt; ++i)
201  {
202    const struct iovec *iov = &vec[i];
203    int ret = 0;
204
205    /* Translate openssl error codes, sigh */
206    if ((ret = SSL_write(ssl, iov->iov_base, iov->iov_len)) <= 0)
207    {
208      switch (SSL_get_error(ssl, i))
209      {
210        case SSL_ERROR_WANT_READ:
211          return -1;
212        case SSL_ERROR_WANT_WRITE:
213          errno = EWOULDBLOCK;
214        case SSL_ERROR_SYSCALL:
215          break;
216        case SSL_ERROR_SSL:
217          if (errno == EAGAIN)
218            break;
219        default:
220          errno = 0;  /* Either an SSL-specific error or EOF */
221      }
222
223      return 0;
224    }
225
226    total_written += ret;
227  }
188  
189 <  return total_written;
189 >  DelFlag(client_p, FLAGS_BLOCKED);
190 >  send_queued_write(client_p);
191   }
231 #endif
192  
193   /*
194   ** send_queued_write
# Line 239 | Line 199 | send_SSL_writev(SSL *ssl, const struct i
199   void
200   send_queued_write(struct Client *to)
201   {
202 <  int retlen = 0, i = 0;
243 <  dlink_node *ptr = NULL;
244 <  struct iovec vec[IOV_MAX];
202 >  int retlen = 0;
203  
204    /*
205 <   * Once socket is marked dead, we cannot start writing to it,
206 <   * even if the error is removed...
205 >   ** Once socket is marked dead, we cannot start writing to it,
206 >   ** even if the error is removed...
207     */
208 <  if (IsDead(to))
209 <    return;  /* No use calling send() now */
252 <
253 <  if (HasFlag(to, FLAGS_CORK))
254 <    return;
255 <
256 <  /* Nothing to do? */
257 <  if (!dbuf_length(&to->localClient->buf_sendq))
258 <    return;
208 >  if (IsDead(to) || HasFlag(to, FLAGS_BLOCKED))
209 >    return;  /* no use calling send() now */
210  
211 <  /* Build iovec */
212 <  DLINK_FOREACH(ptr, to->localClient->buf_sendq.blocks.head)
211 >  /* Next, lets try to write some data */
212 >  if (dbuf_length(&to->localClient->buf_sendq))
213    {
214 <    struct dbuf_block *block = ptr->data;
215 <    struct iovec *iov;
216 <    int offset;
214 >    do
215 >    {
216 >      struct dbuf_block *first = to->localClient->buf_sendq.blocks.head->data;
217  
218 <    if (i >= sizeof(vec) / sizeof(struct iovec))
219 <      break;
220 <        
221 <    iov = &vec[i];
271 <    offset = !i ? to->localClient->buf_sendq.pos : 0;
218 > #ifdef HAVE_LIBCRYPTO
219 >      if (to->localClient->fd.ssl)
220 >      {
221 >        retlen = SSL_write(to->localClient->fd.ssl, first->data + to->localClient->buf_sendq.pos, first->size - to->localClient->buf_sendq.pos);
222  
223 <    iov->iov_base = block->data + offset;
224 <    iov->iov_len = block->size - offset;
223 >        /* translate openssl error codes, sigh */
224 >        if (retlen < 0)
225 >        {
226 >          switch (SSL_get_error(to->localClient->fd.ssl, retlen))
227 >          {
228 >            case SSL_ERROR_WANT_READ:
229 >              return;  /* retry later, don't register for write events */
230 >            case SSL_ERROR_WANT_WRITE:
231 >              errno = EWOULDBLOCK;
232 >            case SSL_ERROR_SYSCALL:
233 >              break;
234 >            case SSL_ERROR_SSL:
235 >              if (errno == EAGAIN)
236 >                break;
237 >            default:
238 >              retlen = errno = 0;  /* either an SSL-specific error or EOF */
239 >          }
240 >        }
241 >      }
242 >      else
243 > #endif
244 >        retlen = send(to->localClient->fd.fd, first->data + to->localClient->buf_sendq.pos, first->size - to->localClient->buf_sendq.pos, 0);
245  
246 <    ++i;
247 <  }
246 >      if (retlen <= 0)
247 >        break;
248  
249 <  /* Next, lets try to write some data */
280 < #ifdef HAVE_LIBCRYPTO
281 <  if (to->localClient->fd.ssl)
282 <  {
283 <    if ((retlen = send_SSL_writev(to->localClient->fd.ssl, vec, i)) == -1)
284 <      return;
285 <  }
286 <  else
287 < #endif
288 <    retlen = writev(to->localClient->fd.fd, vec, i);
249 >      dbuf_delete(&to->localClient->buf_sendq, retlen);
250  
251 <  if (retlen > 0)
252 <  {
253 <    dbuf_delete(&to->localClient->buf_sendq, retlen);
251 >      /* We have some data written .. update counters */
252 >      to->localClient->send.bytes += retlen;
253 >      me.localClient->send.bytes += retlen;
254 >    } while (dbuf_length(&to->localClient->buf_sendq));
255  
256 <    /* We have some data written .. update counters */
257 <    to->localClient->send.bytes += retlen;
258 <    me.localClient->send.bytes += retlen;
256 >    if (retlen < 0 && ignoreErrno(errno))
257 >    {
258 >      AddFlag(to, FLAGS_BLOCKED);
259  
260 <    if (dbuf_length(&to->localClient->buf_sendq))
260 >      /* we have a non-fatal error, reschedule a write */
261        comm_setselect(&to->localClient->fd, COMM_SELECT_WRITE,
262                       (PF *)sendq_unblocked, to, 0);
263 +    }
264 +    else if (retlen <= 0)
265 +    {
266 +      dead_link_on_write(to, errno);
267 +      return;
268 +    }
269    }
302  else if (retlen < 0 && ignoreErrno(errno))
303    /* we have a non-fatal error, reschedule a write */
304    comm_setselect(&to->localClient->fd, COMM_SELECT_WRITE,
305                   (PF *)sendq_unblocked, to, 0);
306  else if (retlen <= 0)
307    dead_link_on_write(to, errno);
270   }
271  
272   /* send_queued_all()
# Line 369 | Line 331 | void
331   sendto_one_numeric(struct Client *to, struct Client *from, enum irc_numerics numeric, ...)
332   {
333    struct dbuf_block *buffer = NULL;
334 <  const char *dest = NULL;
334 >  const char *dest = NULL, *numstr = NULL;
335    va_list args;
336  
337    if (IsDead(to->from))
338      return;
339  
340    dest = ID_or_name(to, to);
341 +
342    if (EmptyString(dest))
343      dest = "*";
344  
345    buffer = dbuf_alloc();
346  
347 <  dbuf_put_fmt(buffer, ":%s %03d %s ", ID_or_name(from, to), numeric, dest);
347 >  dbuf_put_fmt(buffer, ":%s %03d %s ", ID_or_name(from, to), numeric & ~SND_EXPLICIT, dest);
348  
349    va_start(args, numeric);
350 <  send_format(buffer, numeric_form(numeric), args);
350 >
351 >  if (numeric & SND_EXPLICIT)
352 >    numstr = va_arg(args, const char *);
353 >  else
354 >    numstr = numeric_form(numeric);
355 >  send_format(buffer, numstr, args);
356    va_end(args);
357  
358    send_message(to->from, buffer);
# Line 403 | Line 371 | sendto_one_notice(struct Client *to, str
371      return;
372  
373    dest = ID_or_name(to, to);
374 +
375    if (EmptyString(dest))
376      dest = "*";
377  
# Line 441 | Line 410 | sendto_channel_butone(struct Client *one
410  
411    local_buf = dbuf_alloc(), remote_buf = dbuf_alloc();
412  
413 <  if (IsServer(from))
445 <    dbuf_put_fmt(local_buf, ":%s ", from->name);
446 <  else
413 >  if (IsClient(from))
414      dbuf_put_fmt(local_buf, ":%s!%s@%s ", from->name, from->username, from->host);
415 +  else
416 +    dbuf_put_fmt(local_buf, ":%s ", from->name);
417  
418    dbuf_put_fmt(remote_buf, ":%s ", from->id);
419  
# Line 469 | Line 438 | sendto_channel_butone(struct Client *one
438          (one && target_p->from == one->from))
439        continue;
440  
441 <    if (type != 0 && (ms->flags & type) == 0)
441 >    if (type && (ms->flags & type) == 0)
442        continue;
443  
444      if (MyConnect(target_p))
# Line 525 | Line 494 | sendto_server(struct Client *one,
494      if (IsDead(client_p))
495        continue;
496      /* check against 'one' */
497 <    if (one != NULL && (client_p == one->from))
497 >    if (one && (client_p == one->from))
498        continue;
499      /* check we have required capabs */
500      if ((client_p->localClient->caps & caps) != caps)
501        continue;
502      /* check we don't have any forbidden capabs */
503 <    if ((client_p->localClient->caps & nocaps) != 0)
503 >    if ((client_p->localClient->caps & nocaps))
504        continue;
505  
506      send_message(client_p, buffer);
# Line 572 | Line 541 | sendto_common_channels_local(struct Clie
541    DLINK_FOREACH(cptr, user->channel.head)
542    {
543      chptr = ((struct Membership *)cptr->data)->chptr;
575    assert(chptr != NULL);
544  
545 <    DLINK_FOREACH(uptr, chptr->members.head)
545 >    DLINK_FOREACH(uptr, chptr->locmembers.head)
546      {
547        ms = uptr->data;
548        target_p = ms->client_p;
581      assert(target_p != NULL);
549  
550 <      if (!MyConnect(target_p) || target_p == user || IsDefunct(target_p) ||
550 >      if (target_p == user || IsDefunct(target_p) ||
551            target_p->localClient->serial == current_serial)
552          continue;
553  
# Line 624 | Line 591 | sendto_channel_local(unsigned int type,
591    send_format(buffer, pattern, args);
592    va_end(args);
593  
594 <  DLINK_FOREACH(ptr, chptr->members.head)
594 >  DLINK_FOREACH(ptr, chptr->locmembers.head)
595    {
596      struct Membership *ms = ptr->data;
597      struct Client *target_p = ms->client_p;
598  
599 <    if (type != 0 && (ms->flags & type) == 0)
599 >    if (type && (ms->flags & type) == 0)
600        continue;
601  
602 <    if (!MyConnect(target_p) || IsDefunct(target_p) ||
602 >    if (IsDefunct(target_p) ||
603          (nodeaf && HasUMode(target_p, UMODE_DEAF)))
604        continue;
605  
# Line 668 | Line 635 | sendto_channel_local_butone(struct Clien
635    send_format(buffer, pattern, args);
636    va_end(args);
637  
638 <  DLINK_FOREACH(ptr, chptr->members.head)
638 >  DLINK_FOREACH(ptr, chptr->locmembers.head)
639    {
640      struct Membership *ms = ptr->data;
641      struct Client *target_p = ms->client_p;
642  
643 <    if (type != 0 && (ms->flags & type) == 0)
643 >    if (type && (ms->flags & type) == 0)
644        continue;
645  
646 <    if (!MyConnect(target_p) || (one && target_p == one->from))
646 >    if (one && target_p == one->from)
647        continue;
648  
649      if (IsDefunct(target_p) || HasUMode(target_p, UMODE_DEAF))
# Line 805 | Line 772 | sendto_match_servs(struct Client *source
772                     const char *pattern, ...)
773   {
774    va_list args;
775 <  dlink_node *ptr = NULL;
776 <  struct dbuf_block *buff_suid;
775 >  dlink_node *ptr = NULL, *ptr_next = NULL;
776 >  struct dbuf_block *buffer;
777  
778 <  buff_suid = dbuf_alloc();
778 >  buffer = dbuf_alloc();
779  
780 +  dbuf_put_fmt(buffer, ":%s ", source_p->id);
781    va_start(args, pattern);
782 <  dbuf_put_fmt(buff_suid, ":%s ", source_p->id);
815 <  dbuf_put_args(buff_suid, pattern, args);
782 >  send_format(buffer, pattern, args);
783    va_end(args);
784  
785    ++current_serial;
786  
787 <  DLINK_FOREACH(ptr, global_serv_list.head)
787 >  DLINK_FOREACH_SAFE(ptr, ptr_next, global_server_list.head)
788    {
789      struct Client *target_p = ptr->data;
790  
# Line 839 | Line 806 | sendto_match_servs(struct Client *source
806        if (!IsCapable(target_p->from, cap))
807          continue;
808  
809 <      send_message_remote(target_p->from, source_p, buff_suid);
809 >      send_message_remote(target_p->from, source_p, buffer);
810      }
811    }
812  
813 <  dbuf_ref_free(buff_suid);
813 >  dbuf_ref_free(buffer);
814   }
815  
816   /* sendto_anywhere()
# Line 956 | Line 923 | sendto_realops_flags_ratelimited(const c
923    static time_t last = 0;
924    static int warnings = 0;
925  
959  /*
960   ** if we're running with TS_WARNINGS enabled and someone does
961   ** something silly like (remotely) connecting a nonTS server,
962   ** we'll get a ton of warnings, so we make sure we don't send
963   ** more than 5 every 5 seconds.  -orabidoo
964   */
965
926    if (CurrentTime - last < 5)
927    {
928      if (++warnings > 5)

Diff Legend

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