コード例 #1
0
ファイル: send.c プロジェクト: BackupTheBerlios/shadowircd
/*
 ** send_queued_write
 **      This is called when there is a chance that some output would
 **      be possible. This attempts to empty the send queue as far as
 **      possible, and then if any data is left, a write is rescheduled.
 */
void
send_queued_write(struct Client *to)
{
  int retlen;
#ifndef NDEBUG
  struct hook_io_data hdata;
#endif
  struct dbuf_block *first;
  
  /*
   ** Once socket is marked dead, we cannot start writing to it,
   ** even if the error is removed...
   */
  if (IsDead(to) || IsSendqBlocked(to))
    return;  /* no use calling send() now */

  /* Next, lets try to write some data */
  if (dbuf_length(&to->localClient->buf_sendq))
  {
#ifndef NDEBUG
    hdata.connection = to;
#endif
    do {
      first = to->localClient->buf_sendq.blocks.head->data;
#ifdef HAVE_LIBCRYPTO
      if(IsSSL(to))
      {
        retlen = safe_SSL_write(to, first->data, first->size);
        printf("safe_ssl_write: writing: %s\n", first->data);
        printf("safe_ssl_write: %d written\n", retlen);
        if (retlen <= 0)
         break;
      }
      else
#endif
      if ((retlen = send(to->localClient->fd, first->data,
                         first->size, 0)) <= 0)
        break;

#ifndef NDEBUG
      hdata.data = ((struct dbuf_block *)
                    to->localClient->buf_sendq.blocks.head->data)->data;
      hdata.len = retlen;
      hook_call_event("iosend", &hdata);
#endif
      dbuf_delete(&to->localClient->buf_sendq, retlen);

      /* We have some data written .. update counters */
      to->localClient->sendB += retlen;
      me.localClient->sendB += retlen;
      if (to->localClient->sendB > 1023)
      { 
        to->localClient->sendK += (to->localClient->sendB >> 10);
        to->localClient->sendB &= 0x03ff;        /* 2^10 = 1024, 3ff = 1023 */
      }
      else if (me.localClient->sendB > 1023)
      { 
        me.localClient->sendK += (me.localClient->sendB >> 10);
        me.localClient->sendB &= 0x03ff;
      }
コード例 #2
0
DLLFUNC CMD_FUNC(m_starttls)
{
	if (!MyConnect(sptr) || !IsUnknown(sptr))
		return 0;
#ifndef USE_SSL
	/* sendnotice(sptr, "This server does not support SSL"); */
	/* or numeric 691? */
	/* actually... it's probably best to just act like we don't know this command...? */
	sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "STARTTLS");
	return 0;
#else
	if (iConf.ssl_options & SSLFLAG_NOSTARTTLS)
	{
		sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "STARTTLS");
		return 0;
	}
	if (IsSecure(sptr))
	{
		sendto_one(sptr, err_str(ERR_STARTTLS), me.name, !BadPtr(sptr->name) ? sptr->name : "*", "STARTTLS failed. Already using TLS.");
		return 0;
	}
	dbuf_delete(&sptr->recvQ, 1000000); /* Clear up any remaining plaintext commands */
	sendto_one(sptr, rpl_str(RPL_STARTTLS), me.name, !BadPtr(sptr->name) ? sptr->name : "*");
	send_queued(sptr);

	SetSSLStartTLSHandshake(sptr);
	Debug((DEBUG_DEBUG, "Starting SSL handshake (due to STARTTLS) for %s", sptr->sockhost));
	if ((sptr->ssl = SSL_new(ctx_server)) == NULL)
		goto fail;
	sptr->flags |= FLAGS_SSL;
	SSL_set_fd(sptr->ssl, sptr->fd);
	SSL_set_nonblocking(sptr->ssl);
	if (!ircd_SSL_accept(sptr, sptr->fd)) {
		Debug((DEBUG_DEBUG, "Failed SSL accept handshake in instance 1: %s", sptr->sockhost));
		SSL_set_shutdown(sptr->ssl, SSL_RECEIVED_SHUTDOWN);
		SSL_smart_shutdown(sptr->ssl);
		SSL_free(sptr->ssl);
		goto fail;
	}

	/* HANDSHAKE IN PROGRESS */
	return 0;
fail:
	/* Failure */
	sendto_one(sptr, err_str(ERR_STARTTLS), me.name, !BadPtr(sptr->name) ? sptr->name : "*", "STARTTLS failed");
	sptr->ssl = NULL;
	sptr->flags &= ~FLAGS_SSL;
	SetUnknown(sptr);
	return 0;
#endif
}
コード例 #3
0
ファイル: dbuf.c プロジェクト: Niichan/snircd
/** Copy a single line from a data buffer.
 * If the output buffer cannot hold the whole line, or if there is no
 * EOL in the buffer, return 0.
 * @param[in,out] dyn Data buffer to copy from.
 * @param[out] buf Buffer to copy to.
 * @param[in] length Maximum number of bytes to copy.
 * @return Number of bytes copied to \a buf.
 */
unsigned int dbuf_getmsg(struct DBuf *dyn, char *buf, unsigned int length)
{
  struct DBufBuffer *db;
  char *start;
  char *end;
  unsigned int count;
  unsigned int copied = 0;

  assert(0 != dyn);
  assert(0 != buf);

  if (0 == dbuf_flush(dyn))
    return 0;

  assert(0 != dyn->head);

  db = dyn->head;
  start = db->start;

  assert(start < db->end);

  if (length > dyn->length)
    length = dyn->length;
  /*
   * might as well copy it while we're here
   */
  while (length > 0)
  {
    end = IRCD_MIN(db->end, (start + length));
    while (start < end && !IsEol(*start))
      *buf++ = *start++;

    count = start - db->start;
    if (start < end)
    {
      *buf = '\0';
      copied += count;
      dbuf_delete(dyn, copied);
      dbuf_flush(dyn);
      return copied;
    }
    if (0 == (db = db->next))
      break;
    copied += count;
    length -= count;
    start = db->start;
  }
  return 0;
}
コード例 #4
0
ファイル: dbuf.c プロジェクト: mysidia/irc2010bahamut
size_t dbuf_get(struct DBuf* dyn, char* buf, size_t length)
{
  size_t      moved = 0;
  size_t      chunk;
  const char* b;

  while (length > 0 && (b = dbuf_map(dyn, &chunk)) != 0) {
    if (chunk > length)
      chunk = length;

    memcpy(buf, b, chunk);
    dbuf_delete(dyn, chunk);

    buf    += chunk;
    length -= chunk;
    moved  += chunk;
  }
  return moved;
}
コード例 #5
0
ファイル: dbuf.c プロジェクト: Niichan/snircd
/** Copy data from a buffer and remove what was copied.
 * @param[in,out] dyn Buffer to copy from.
 * @param[out] buf Buffer to write to.
 * @param[in] length Maximum number of bytes to copy.
 * @return Number of bytes actually copied.
 */
unsigned int dbuf_get(struct DBuf *dyn, char *buf, unsigned int length)
{
  unsigned int moved = 0;
  unsigned int chunk;
  const char *b;

  assert(0 != dyn);
  assert(0 != buf);

  while (length > 0 && (b = dbuf_map(dyn, &chunk)) != 0)
  {
    if (chunk > length)
      chunk = length;

    memcpy(buf, b, chunk);
    dbuf_delete(dyn, chunk);

    buf += chunk;
    length -= chunk;
    moved += chunk;
  }
  return moved;
}
コード例 #6
0
ファイル: send.c プロジェクト: ahf/irc
/*
** send_queued
**	This function is called from the main select-loop (or whatever)
**	when there is a chance the some output would be possible. This
**	attempts to empty the send queue as far as possible...
*/
int	send_queued(aClient *to)
{
	char	*msg;
	int	len, rlen, more = 0;
	aClient *bysptr = NULL;

	/*
	** Once socket is marked dead, we cannot start writing to it,
	** even if the error is removed...
	*/
	if (IsDead(to))
	    {
		/*
		** Actually, we should *NEVER* get here--something is
		** not working correct if send_queued is called for a
		** dead socket... --msa
		*/
		return -1;
	    }
#ifdef	ZIP_LINKS
	/*
	** Here, we must make sure than nothing will be left in to->zip->outbuf
	** This buffer needs to be compressed and sent if all the sendQ is sent
	*/
	if ((to->flags & FLAGS_ZIP) && to->zip->outcount)
	    {
		if (DBufLength(&to->sendQ) > 0)
			more = 1;
		else
		    {
			msg = zip_buffer(to, NULL, &len, 1);
			
			if (len == -1)
			       return dead_link(to,
						"fatal error in zip_buffer()");

			if (dbuf_put(&to->sendQ, msg, len) < 0)
			    {
				to->exitc = EXITC_MBUF;
				return dead_link(to,
					 "Buffer allocation error for %s",
					get_client_name(to, FALSE));
			    }
		    }
	    }
#endif
	while (DBufLength(&to->sendQ) > 0 || more)
	    {
		msg = dbuf_map(&to->sendQ, &len);
					/* Returns always len > 0 */
		if ((rlen = deliver_it(to, msg, len)) < 0)
		{
			if ( (IsConnecting(to) || IsHandshake(to))
			     && to->serv && to->serv->byuid[0])
			{
				bysptr = find_uid(to->serv->byuid, NULL);
				if (bysptr && !MyConnect(bysptr))
				{
					sendto_one(bysptr, ":%s NOTICE %s :"
					"Write error (%s) to %s, closing link",
					ME, bysptr->name, strerror(-rlen),
					to->name);
				}
			}
			return dead_link(to,
				"Write error (%s) to %s, closing link",
				strerror(-rlen), get_client_name(to, FALSE));
		}
		(void)dbuf_delete(&to->sendQ, rlen);
		to->lastsq = DBufLength(&to->sendQ)/1024;
		if (rlen < len) /* ..or should I continue until rlen==0? */
			break;

#ifdef	ZIP_LINKS
		if (DBufLength(&to->sendQ) == 0 && more)
		    {
			/*
			** The sendQ is now empty, compress what's left
			** uncompressed and try to send it too
			*/
			more = 0;
			msg = zip_buffer(to, NULL, &len, 1);

			if (len == -1)
			       return dead_link(to,
						"fatal error in zip_buffer()");

			if (dbuf_put(&to->sendQ, msg, len) < 0)
			    {
				to->exitc = EXITC_MBUF;
				return dead_link(to,
					 "Buffer allocation error for %s",
					get_client_name(to, FALSE));
			    }
		    }
#endif
	    }

	return (IsDead(to)) ? -1 : 0;
}