Beispiel #1
0
void 
have(struct Piece *piece, struct Torrent *t)
{
     uint32_t have_prefix = htonl(5);
     uint8_t have_id = 4;
     uint32_t index = htonl(piece->index);
     struct PeerNode *head = t->peer_list;

     while (head != NULL) {
          bufferevent_write(head->cargo->bufev, (const void *)&have_prefix, sizeof(have_prefix));
          bufferevent_write(head->cargo->bufev, (const void *)&have_id, sizeof(have_id));
          bufferevent_write(head->cargo->bufev, (const void *)&index, sizeof(index));
          head = head->next;
     }

     t->have_bitfield[piece->index] = 1;

     uint64_t i = pieces_remaining(t->have_bitfield, t->num_pieces);

     /* if 0 pieces remain, the torrent is complete */
     if (i == 0) {
          complete(t);
     }

#ifdef DEBUG
     if (i < 5) {
          print_pieces_remaining(t->have_bitfield, t->num_pieces);
     }
#endif
}
Beispiel #2
0
static void
rrdtool_write_command(struct rrdtool_drv *drv, char *command)
{
	bufferevent_write(drv->evb, command, strlen(command));
	if (command[strlen(command) - 1] != '\n')
		bufferevent_write(drv->evb, "\n", 1);
}
/* Add bytes to a buffer and filter '\n' according to separator. */
void
cmd_paste_buffer_filter(struct window_pane *wp,
    const char *data, size_t size, const char *sep, int bracket)
{
	const char	*end = data + size;
	const char	*lf;
	size_t		 seplen;

	if (bracket)
		bufferevent_write(wp->event, "\033[200~", 6);

	seplen = strlen(sep);
	while ((lf = memchr(data, '\n', end - data)) != NULL) {
		if (lf != data)
			bufferevent_write(wp->event, data, lf - data);
		bufferevent_write(wp->event, sep, seplen);
		data = lf + 1;
	}

	if (end != data)
		bufferevent_write(wp->event, data, end - data);

	if (bracket)
		bufferevent_write(wp->event, "\033[201~", 6);
}
Beispiel #4
0
void
tty_putc(struct tty *tty, u_char ch)
{
	const char	*acs;
	u_int		 sx;

	if (tty->cell.attr & GRID_ATTR_CHARSET) {
		acs = tty_acs_get(tty, ch);
		if (acs != NULL)
			bufferevent_write(tty->event, acs, strlen(acs));
		else
			bufferevent_write(tty->event, &ch, 1);
	} else
		bufferevent_write(tty->event, &ch, 1);

	if (ch >= 0x20 && ch != 0x7f) {
		sx = tty->sx;
		if (tty->term->flags & TERM_EARLYWRAP)
			sx--;

		if (tty->cx >= sx) {
			tty->cx = 1;
			if (tty->cy != tty->rlower)
				tty->cy++;
		} else
			tty->cx++;
	}

	if (tty->log_fd != -1)
		write(tty->log_fd, &ch, 1);
}
Beispiel #5
0
//channel_id number
//packet lstring
static int lpacket_sender(lua_State *L)
{
    int channel_id = luaL_checkint(L, 1);
    struct bufferevent *bev = AllChannels[channel_id]._bev;
    if (!bev) {
        logging("lpacket_sender error : channel has closed");
        lua_pushboolean(L, 0);
        return 1;
    }
    size_t sz;
    const char *packet = luaL_checklstring(L, 2, &sz);

    if (sz > MAX_PACKET_SZ) {
        logging("packet tooooo big, throw it");
        lua_pushboolean(L, 0);
        return 1;
    }
    packet_header_t packet_len = (packet_header_t)sz;
    if ((bufferevent_write(bev, &packet_len, PACKET_HEADER_SZ) != -1)
            && bufferevent_write(bev, packet, packet_len) != -1) {
        lua_pushboolean(L, 1);
        return 1;
    }
    logging("write packet error");
    lua_pushboolean(L, 0);
    return 1;
}
Beispiel #6
0
static void send_bptree_result(tcp_client *c, int rv, int32_t vsize, void *v)
{
	int size = sizeof(int32_t) + vsize;
	bufferevent_write(c->buffer_ev, &size,sizeof(int));
	bufferevent_write(c->buffer_ev, &rv,sizeof(int));
	bufferevent_write(c->buffer_ev, &vsize,sizeof(int32_t));
	bufferevent_write(c->buffer_ev,v,vsize);
}
Beispiel #7
0
void 
unchoke(struct Peer *p)
{
     uint32_t unchoke_prefix = htonl(1);
     uint8_t unchoke_id = 1;

     bufferevent_write(p->bufev, (const void *)&unchoke_prefix, sizeof(unchoke_prefix));
     bufferevent_write(p->bufev, (const void *)&unchoke_id, sizeof(unchoke_id));
     p->tstate.choked = 0;
}
Beispiel #8
0
void 
not_interested(struct Peer *p)
{
     uint32_t not_interested_prefix = htonl(1);
     uint8_t not_interested_id = 3;

     bufferevent_write(p->bufev, (const void *)&not_interested_prefix, sizeof(not_interested_prefix));
     bufferevent_write(p->bufev, (const void *)&not_interested_id, sizeof(not_interested_id));
     p->tstate.interested = 0;
}
Beispiel #9
0
void 
interested(struct Peer *p)
{
     uint32_t interested_prefix = htonl(1);
     uint8_t interested_id = 2;
     
     bufferevent_write(p->bufev, (const void *)&interested_prefix, sizeof(interested_prefix));
     bufferevent_write(p->bufev, (const void *)&interested_id, sizeof(interested_id));
     p->tstate.interested = 1;
}
Beispiel #10
0
static void
write_socks_request(struct conninfo *info)
{
	if (info->socks == SOCKS_4) {
		struct sockaddr_in *sin = (struct sockaddr_in*)&info->addr;

		if (info->addr.ss_family != AF_INET) {
			finish_connection(info, 0,
				"SOCKS 4 can't handle ipv6!");
		}

		/* connection request */
		bufferevent_write(info->bev, "\x04\x01", 2);
		bufferevent_write(info->bev, &sin->sin_port,
				  sizeof(sin->sin_port));
		bufferevent_write(info->bev, &sin->sin_addr.s_addr,
				  sizeof(sin->sin_addr.s_addr));
		bufferevent_write(info->bev, "xx", 3);
	} else {
		ev_uint16_t port = htons(info->port);

		assert(info->host != NULL);
		bufferevent_write(info->bev, "\x04\x01", 2);
		bufferevent_write(info->bev, &port, sizeof(port));
		bufferevent_write(info->bev, "\x00\x00\x00\xff", 4);
		bufferevent_write(info->bev, "xx", 3);
		bufferevent_write(info->bev, info->host, strlen(info->host)+1);
	}

	bufferevent_enable(info->bev, EV_READ);
}
Beispiel #11
0
int togo_wt_send_cb(TOGO_THREAD_ITEM * socket_item)
{
	int ret;
	char int_str[12];

	/* If sstatus equal to 3, send the big data! */
	if (socket_item->sstatus == 3) {

		BDATA_CALLBACK callback;
		if (socket_item->bsbuf == NULL || socket_item->bssize == 0) {
			return 0;
		}

		togo_itoa((uint32_t) socket_item->bssize, int_str, 10);

		/**
		 * Retrun:TOGO_S10TOGO_E/r/nAAAAAAAAAA
		 */
		ret = bufferevent_write(socket_item->bev, TOGO_SBUF_START,
				togo_strlen(TOGO_SBUF_START));
		ret = bufferevent_write(socket_item->bev, int_str,
				togo_strlen(int_str));
		ret += bufferevent_write(socket_item->bev, TOGO_SBUF_END,
				togo_strlen(TOGO_SBUF_END));
		ret += bufferevent_write(socket_item->bev, socket_item->bsbuf,
				socket_item->bssize);

		if (ret < 0) {
			togo_log(INFO, "Send data error");
		}

		callback = socket_item->bscb;
		if (callback != NULL) {
			callback(socket_item);
		}
		socket_item->sstatus = 0;

	} else {

		if (socket_item->sfd < 1 || socket_item->sbuf == NULL
				|| socket_item->ssize == 0) {
			return 0;
		}

		ret = bufferevent_write(socket_item->bev, socket_item->sbuf,
				socket_item->ssize);
		if (ret < 0) {
			togo_log(INFO, "Send data error");
		}
		socket_item->ssize = 0;
	}

	return ret;
}
Beispiel #12
0
// server has produced data, relay it to the websocket client
static void server_read ( struct bufferevent* be, void* arg ) {
  struct bufferevent* client = (struct bufferevent*) arg;
  char buf[1024 * 10];
  int n = bufferevent_read ( be, buf, sizeof buf );
  if ( n > 0 ) {
    bufferevent_write ( client, frame, 1 );      // start of frame
    bufferevent_write ( client, buf, n );
    bufferevent_write ( client, frame + 1, 1 );  // end of frame
    bufferevent_enable ( client, EV_WRITE );
  }
}
Beispiel #13
0
void send_server_message(struct bufferevent *bev, const char *msg, uint16_t len)
{
    struct packet_server_message data;

    data.hdr.proto = PROTO_EDONKEY;
    data.hdr.length = sizeof(data) - sizeof(data.hdr) + len;
    data.opcode = OP_SERVERMESSAGE;
    data.msg_len = len;

    bufferevent_write(bev, &data, sizeof(data));
    bufferevent_write(bev, msg, len);
}
Beispiel #14
0
void send_found_sources(struct bufferevent *bev, const unsigned char *hash, struct file_source *sources, size_t count)
{
    struct packet_found_sources data;
    size_t srcs_len = count * sizeof(*sources);

    data.hdr.proto = PROTO_EDONKEY;
    memcpy(data.hash, hash, sizeof(data.hash));
    data.hdr.length = sizeof(data) - sizeof(data.hdr) + srcs_len;
    data.opcode = OP_FOUNDSOURCES;
    data.count = count;
    bufferevent_write(bev, &data, sizeof(data));
    if (count)
        bufferevent_write(bev, sources, srcs_len);
}
Beispiel #15
0
static ssize_t
levent_ctl_send(struct lldpd_one_client *client, int type, void *data, size_t len)
{
	struct bufferevent *bev = client->bev;
	struct hmsg_header hdr = { .len = len, .type = type };
	bufferevent_disable(bev, EV_WRITE);
	if (bufferevent_write(bev, &hdr, sizeof(struct hmsg_header)) == -1 ||
	    (len > 0 && bufferevent_write(bev, data, len) == -1)) {
		log_warnx("event", "unable to create answer to client");
		levent_ctl_free_client(client);
		return -1;
	}
	bufferevent_enable(bev, EV_WRITE);
	return len;
}
void thread_bufferread_cb_enc(struct bufferevent *bev, void *ptr)
{
    P_TRANS_ITEM p_trans = (P_TRANS_ITEM)ptr; 

    ENC_FRAME from_f;
    ENC_FRAME to_f;

    struct evbuffer *input = bufferevent_get_input(bev);
    struct evbuffer *output = bufferevent_get_output(bev);

    if (bev == p_trans->bev_u && p_trans->bev_d) 
    {
        st_d_print("加密转发数据包USR->REMOTE");    // 解密

        from_f.len = bufferevent_read(p_trans->bev_u, from_f.dat, FRAME_SIZE); 
        if (from_f.len > 0)
        {
            decrypt(&p_trans->ctx_dec, &from_f, &to_f);
            bufferevent_write(p_trans->bev_d, to_f.dat, from_f.len);
        }        
        else
        {
            st_d_error("读取数据出错!");
        }

    }
    else if (bev == p_trans->bev_d && p_trans->bev_u) 
    {
        st_d_print("加密转发数据包REMOTE->USR");    // 加密

        from_f.len = bufferevent_read(p_trans->bev_d, from_f.dat, FRAME_SIZE);
        if (from_f.len > 0)
        {
            encrypt(&p_trans->ctx_enc, &from_f, &to_f);
            bufferevent_write(p_trans->bev_u, to_f.dat, to_f.len);
        }        
        else
        {
            st_d_error("读取数据出错!");
        }
    }
    else
    {
        SYS_ABORT("WRRRRRR!");
    }

    return;
}
Beispiel #17
0
int
fcgi_add_param(struct server_fcgi_param *p, const char *key,
    const char *val, struct client *clt)
{
	struct fcgi_record_header	*h;
	int				 len = 0;
	int				 key_len = strlen(key);
	int				 val_len = strlen(val);
	uint8_t				*param;

	len += key_len + val_len;
	len += key_len > 127 ? 4 : 1;
	len += val_len > 127 ? 4 : 1;

	DPRINTF("%s: %s[%d] => %s[%d], total_len: %d", __func__, key, key_len,
	    val, val_len, p->total_len);

	if (len > FCGI_CONTENT_SIZE)
		return (-1);

	if (p->total_len + len > FCGI_CONTENT_SIZE) {
		bufferevent_write(clt->clt_srvbev, p->buf,
		    sizeof(struct fcgi_record_header) + p->total_len);
		p->total_len = 0;
	}

	h = (struct fcgi_record_header *)p->buf;
	param = p->buf + sizeof(*h) + p->total_len;

	if (key_len > 127) {
		*param++ = ((key_len >> 24) & 0xff) | 0x80;
		*param++ = ((key_len >> 16) & 0xff);
		*param++ = ((key_len >> 8) & 0xff);
		*param++ = (key_len & 0xff);
	} else
Beispiel #18
0
void client_invalid_version(Client *cl)
{
  static const uint8_t message[] = {SOCKS5_VER, AUTH_METHOD_INVALID};

  bufferevent_write(cl->client.bufev, message, sizeof (message));
  client_disconnect(cl);
}
Beispiel #19
0
static void httpr_client_read_content(struct bufferevent *buffev, redsocks_client *client)
{
	httpr_client *httpr = (void*)(client + 1);

	static int post_buffer_len = 64 * 1024;
	char *post_buffer = calloc(post_buffer_len, 1);
	if (!post_buffer) {
		redsocks_log_error(client, LOG_ERR, "run out of memory");
		redsocks_drop_client(client);
		return;
	}
	int error;
	while (true) {
		error = evbuffer_remove(buffev->input, post_buffer, post_buffer_len);
		if (error < 0) {
			free(post_buffer);
			redsocks_log_error(client, LOG_ERR, "evbuffer_remove");
			redsocks_drop_client(client);
			return;
		}
		if (error == 0)
			break;
		httpr_buffer_append(&httpr->client_buffer, post_buffer, error);
		if (client->relay && client->state >= httpr_request_sent) {
			if (bufferevent_write(client->relay, post_buffer, error) != 0) {
				free(post_buffer);
				redsocks_log_error(client, LOG_ERR, "bufferevent_write");
				redsocks_drop_client(client);
				return;
			}
		}

	}
	free(post_buffer);
}
Beispiel #20
0
/* Add bytes to a buffer but change every '\n' to '\r'. */
void
cmd_paste_buffer_lf2cr(struct window_pane *wp, const char *data, size_t size)
{
	const char	*end = data + size;
	const char	*lf;

	while ((lf = memchr(data, '\n', end - data)) != NULL) {
		if (lf != data)
			bufferevent_write(wp->event, data, lf - data);
		bufferevent_write(wp->event, "\r", 1);
		data = lf + 1;
	}

	if (end != data)
		bufferevent_write(wp->event, data, end - data);
}
Beispiel #21
0
int  bufferevent_send(struct bufferevent *bev, const void *data, uint32_t len)
{
    uint32_t max_write = 0;
    int sent_total = 0;
    uint32_t sent = 0;
    uint32_t left = len;

    while(left > 0) {
        max_write = bufferevent_get_max_to_write(bev);
        sent = left;
        if(sent > max_write) sent = max_write;

        if(sent > 0){
            /* LoggerDebug("@@-- sent %d/%d bytes, send:%d max:%d.", */
            /*             sent_total, length, sent, max_write); */
            if(0 == bufferevent_write(bev, data + sent_total, sent)){
                /* send OK */
                sent_total += sent;
                left -= sent;
                /* printf("@@!! sent %d/%d bytes, send:%d max:%d.\n", */
                /*             sent_total, len, sent, max_write); */
            } else {
                log_info("bufferevent_write  failed: %s", strerror(errno));
                return -1;
            }
        } else {
            log_dbg("wait...");
        }
    }

    /* bufferevent_flush(bev, EV_WRITE, BEV_FLUSH); */

    return sent_total;
}
Beispiel #22
0
Client::Client(struct event_base* base, evutil_socket_t fd, struct sockaddr *socket, int socket_len)
{
	m_buffer = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
	if (!m_buffer) 
	{
		fprintf(stderr, "Error constructing bufferevent!");
		event_base_loopbreak(base);
		throw;
	}
	
	bufferevent_setcb(m_buffer, conn_readcb, conn_writecb, conn_eventcb, this);
	bufferevent_enable(m_buffer, EV_READ|EV_WRITE);
//	bufferevent_setwatermark(m_buffer, EV_READ, 128, 0);
	
	struct timeval time1, time2;
//	time1.tv_sec = 10;
//	time2.tv_sec = 11;
//	bufferevent_set_timeouts(m_buffer, &time1, &time2);
	
	if(socket->sa_family == AF_INET)
	{
		struct sockaddr_in *socket4 = (struct sockaddr_in*)socket;
		m_ip = string(inet_ntoa(socket4->sin_addr));
		m_port = ntohs(socket4->sin_port);
	}
	
	bufferevent_write(m_buffer, "hello", strlen("hello"));//tmp
	
}
Beispiel #23
0
static err_t pipe_tcp_recv(void *ctx, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
	struct pipe_data *data = ctx;
	struct pbuf *curr;
	int len;

	if (!data->bev) {
		pipe_tcp_free(data);
		free(data);
		return ERR_ABRT;
	}

	if (err < 0 || !p) {
		pipe_tcp_kill(data);
		pipe_bev_flush(data);
		return ERR_ABRT;
	}

	if (evbuffer_get_length(bufferevent_get_output(data->bev)) >= 262144)
		return ERR_WOULDBLOCK;

	len = p->tot_len;
	for (curr = p; curr; curr = curr->next)
		bufferevent_write(data->bev, curr->payload, curr->len);
	pbuf_free(p);
	tcp_recved(pcb, len);

	return 0;
}
Beispiel #24
0
struct StreamRequest *new_stream_request(const char *method, const char *source_address, int source_port, const char *path,
        void (*header_cb)(struct bufferevent *bev, struct evkeyvalq *headers, void *arg),
        void (*read_cb)(struct bufferevent *bev, void *arg),
        void (*error_cb)(struct bufferevent *bev, void *arg),
        void *arg) {
    struct StreamRequest *sr;
    int fd;
    struct evbuffer *http_request;
    
    fd = stream_request_connect(source_address, source_port);
    if (fd == -1) {
        return NULL;
    }
    
    sr = malloc(sizeof(struct StreamRequest));
    sr->fd = fd;
    sr->state = read_firstline;
    sr->header_cb = header_cb;
    sr->read_cb = read_cb;
    sr->error_cb = error_cb;
    sr->arg = arg;
    sr->bev = bufferevent_new(sr->fd, stream_request_readcb, stream_request_writecb, stream_request_errorcb, sr);
    http_request = evbuffer_new();
    evbuffer_add_printf(http_request, "%s %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", method, path, source_address);
    bufferevent_write(sr->bev, (char *)EVBUFFER_DATA(http_request), EVBUFFER_LENGTH(http_request));
    evbuffer_free(http_request);
    
    return sr;
}
Beispiel #25
0
 void Connection::write( const char* data, unsigned int length, bool close )
 {
     TRACE("%s", data );
     bufferevent_write( m_handle, data, length );
 
     m_close = close;
 }
Beispiel #26
0
void
client_read(struct bufferevent *bufev, void *arg)
{
	struct session	*s = arg;
	size_t		 buf_avail, read;
	int		 n;

	do {
		buf_avail = sizeof s->cbuf - s->cbuf_valid;
		read = bufferevent_read(bufev, s->cbuf + s->cbuf_valid,
		    buf_avail);
		s->cbuf_valid += read;

		while ((n = get_line(s->cbuf, &s->cbuf_valid)) > 0) {
			logmsg(LOG_DEBUG, "#%d client: %s", s->id, linebuf);
			if (!client_parse(s)) {
				end_session(s);
				return;
			}
			bufferevent_write(s->server_bufev, linebuf, linelen);
		}

		if (n == -1) {
			logmsg(LOG_ERR, "#%d client command too long or not"
			    " clean", s->id);
			end_session(s);
			return;
		}
	} while (read == buf_avail);
}
Beispiel #27
0
/** Read from one buffer and write the results to the other */
void
pipe_cb(struct bufferevent *from_bev, void *data)
{
  struct conn *c = data;
  char buff[BUFFER_LEN];
  size_t len;
  struct bufferevent *to_bev = NULL;

  if (c->local_bev == from_bev) {
#if SSL_DEBUG_LEVEL > 1
    errputs(stdout, "got data from mush.");
#endif
    to_bev = c->remote_bev;
  } else {
#if SSL_DEBUG_LEVEL > 1
    errputs(stdout, "got data from SSL");
#endif
    to_bev = c->local_bev;
  }

  len = bufferevent_read(from_bev, buff, sizeof buff);

#if SSL_DEBUG_LEVEL > 1
  errprintf(stdout, "ssl_slave: read %zu bytes.\n", len);
#endif

  if (to_bev && len > 0) {
    if (bufferevent_write(to_bev, buff, len) < 0)
      errputs(stderr, "write failed!");
  }
}
Beispiel #28
0
/* Translate mouse and output. */
void
input_mouse(struct window_pane *wp, struct mouse_event *m)
{
	char	buf[10];
	size_t	len;

	if (wp->screen->mode & ALL_MOUSE_MODES) {
		if (wp->screen->mode & MODE_MOUSE_UTF8) {
			len = xsnprintf(buf, sizeof buf, "\033[M");
			len += utf8_split2(m->b + 32, &buf[len]);
			len += utf8_split2(m->x + 33, &buf[len]);
			len += utf8_split2(m->y + 33, &buf[len]);
		} else {
			if (m->b > 223 || m->x >= 222 || m->y > 222)
				return;
			len = xsnprintf(buf, sizeof buf, "\033[M");
			buf[len++] = m->b + 32;
			buf[len++] = m->x + 33;
			buf[len++] = m->y + 33;
		}
		bufferevent_write(wp->event, buf, len);
	} else if ((m->b & MOUSE_BUTTON) != MOUSE_2) {
		if (options_get_number(&wp->window->options, "mode-mouse") &&
		    window_pane_set_mode(wp, &window_copy_mode) == 0) {
			window_copy_init_from_pane(wp);
			if (wp->mode->mouse != NULL)
				wp->mode->mouse(wp, NULL, m);
		}
	}
}
Beispiel #29
0
int
cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args		*args = self->args;
	struct client		*c = ctx->cmdclient;
	struct paste_buffer	*pb;
	const char		*path;
	char			*cause;
	int			 buffer;
	mode_t			 mask;
	FILE			*f;

	if (!args_has(args, 'b')) {
		if ((pb = paste_get_top(&global_buffers)) == NULL) {
			ctx->error(ctx, "no buffers");
			return (-1);
		}
	} else {
		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
		if (cause != NULL) {
			ctx->error(ctx, "buffer %s", cause);
			xfree(cause);
			return (-1);
		}

		pb = paste_get_index(&global_buffers, buffer);
		if (pb == NULL) {
			ctx->error(ctx, "no buffer %d", buffer);
			return (-1);
		}
	}

	path = args->argv[0];
	if (strcmp(path, "-") == 0) {
		if (c == NULL) {
			ctx->error(ctx, "%s: can't write to stdout", path);
			return (-1);
		}
		bufferevent_write(c->stdout_event, pb->data, pb->size);
	} else {
		mask = umask(S_IRWXG | S_IRWXO);
		if (args_has(self->args, 'a'))
			f = fopen(path, "ab");
		else
			f = fopen(path, "wb");
		umask(mask);
		if (f == NULL) {
			ctx->error(ctx, "%s: %s", path, strerror(errno));
			return (-1);
		}
		if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
			ctx->error(ctx, "%s: fwrite error", path);
			fclose(f);
			return (-1);
		}
		fclose(f);
	}

	return (0);
}
Beispiel #30
0
static size_t copy_evbuffer(struct bufferevent * dst, const struct bufferevent * src)
{
	int n, i;
	size_t written = 0;
	struct evbuffer_iovec *v;
	struct evbuffer_iovec quick_v[5];/* a vector with 5 elements is usually enough */

	size_t maxlen = dst->wm_write.high - EVBUFFER_LENGTH(dst->output);
	maxlen = EVBUFFER_LENGTH(src->input)> maxlen?maxlen: EVBUFFER_LENGTH(src->input);

	n = evbuffer_peek(src->input, maxlen, NULL, NULL, 0);
	if (n>sizeof(quick_v)/sizeof(struct evbuffer_iovec))
		v = malloc(sizeof(struct evbuffer_iovec)*n);
	else
		v = quick_v;
	n = evbuffer_peek(src->input, maxlen, NULL, v, n);
	for (i=0; i<n; ++i) {
        size_t len = v[i].iov_len;
        if (written + len > maxlen)
            len = maxlen - written;
		if (bufferevent_write(dst, v[i].iov_base, len))
            break;
        /* We keep track of the bytes written separately; if we don't,
 *            we may write more than we need if the last chunk puts
 *                       us over the limit. */
        written += len;
    }
	if (n>sizeof(quick_v)/sizeof(struct evbuffer_iovec))
		free(v);
	return written;
}