Esempio n. 1
0
static int
decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
{
	ev_uint32_t number = 0;
	size_t len = evbuffer_get_length(evbuf);
	ev_uint8_t *data;
	size_t count = 0;
	int  shift = 0, done = 0;

	/*
	 * the encoding of a number is at most one byte more than its
	 * storage size.  however, it may also be much smaller.
	 */
	data = evbuffer_pullup(
		evbuf, len < sizeof(number) + 1 ? len : sizeof(number) + 1);
	if (!data)
		return (-1);

	while (count++ < len) {
		ev_uint8_t lower = *data++;
		if (shift >= 28) {
			/* Make sure it fits into 32 bits */
			if (shift > 28)
				return (-1);
			if ((lower & 0x7f) > 15)
				return (-1);
		}
		number |= (lower & (unsigned)0x7f) << shift;
		shift += 7;

		if (!(lower & 0x80)) {
			done = 1;
			break;
		}
	}

	if (!done)
		return (-1);

	if (dodrain)
		evbuffer_drain(evbuf, count);

	if (ptag != NULL)
		*ptag = number;

	return count > INT_MAX ? INT_MAX : (int)(count);
}
Esempio n. 2
0
File: article.c Progetto: ptt/pttbbs
static int
evbuffer_slice(struct evbuffer *buf, int offset, int size)
{
    int len = evbuffer_get_length(buf);
    if (offset + size > len)
	return -1;

    struct evbuffer *back = evbuffer_new();
    evbuffer_add_buffer(back, buf);

    if (evbuffer_add_reference(buf, evbuffer_pullup(back, len) + offset,
			       size, cleanup_evbuffer, back) == 0)
	return 0;

    evbuffer_free(back);
    return -1;
}
Esempio n. 3
0
static void
task_finish_func( void * vtask )
{
    struct tr_web_task * task = vtask;
    dbgmsg( "finished web task %p; got %ld", task, task->code );

    if( task->done_func != NULL )
        task->done_func( task->session,
                         task->did_connect,
                         task->did_timeout,
                         task->code,
                         evbuffer_pullup( task->response, -1 ),
                         evbuffer_get_length( task->response ),
                         task->done_func_user_data );

    task_free( task );
}
Esempio n. 4
0
static void dir_tree_file_read_on_last_chunk_cb (S3HttpClient *http, struct evbuffer *input_buf, gpointer ctx)
{
    gchar *buf = NULL;
    size_t buf_len;
    DirTreeFileOpData *op_data = (DirTreeFileOpData *) ctx;
    DirTreeFileRange *range;

    buf_len = evbuffer_get_length (input_buf);
    buf = (gchar *) evbuffer_pullup (input_buf, buf_len);
    
    /*
    range = g_queue_pop_head (op_data->q_ranges_requested);
    if (range) {
        op_data->c_size = range->size;
        op_data->c_off = range->off;
        op_data->c_req = range->c_req;
    }
    */

    op_data->total_read += buf_len;
    LOG_debug (DIR_TREE_LOG, "[%p %p] lTOTAL read: %zu (req: %zu), orig size: %zu, TOTAL: %"OFF_FMT", Qsize: %zu", 
        op_data->c_req, http,
        buf_len, op_data->c_size, op_data->en->size, op_data->total_read, g_queue_get_length (op_data->q_ranges_requested));
    
    if (op_data->file_read_cb)
        op_data->file_read_cb (op_data->c_req, TRUE, buf, buf_len);

    evbuffer_drain (input_buf, buf_len);
    
    // if there are more pending chunk requests 
    if (g_queue_get_length (op_data->q_ranges_requested) > 0) {
        range = g_queue_pop_head (op_data->q_ranges_requested);
        LOG_debug (DIR_TREE_LOG, "[%p] more data: %zd", range->c_req, range->size);
        op_data->c_size = range->size;
        op_data->c_off = range->off;
        op_data->c_req = range->c_req;
        g_free (range);

        op_data->op_in_progress = TRUE;
        // perform the next chunk request
        dir_tree_file_read_prepare_request (op_data, http, op_data->c_off, op_data->c_size);
    } else {
        LOG_debug (DIR_TREE_LOG, "Done downloading !!");
        op_data->op_in_progress = FALSE;
    }
}
Esempio n. 5
0
/* Read the data in the bufferevent and feed them into nghttp2 library
   function. Invocation of nghttp2_session_mem_recv() may make
   additional pending frames, so call session_send() at the end of the
   function. */
static int session_recv(http2_session_data *session_data)
{
  int rv;
  struct evbuffer *input = bufferevent_get_input(session_data->bev);
  size_t datalen = evbuffer_get_length(input);
  unsigned char *data = evbuffer_pullup(input, -1);
  rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
  if(rv < 0) {
    warnx("Fatal error: %s", nghttp2_strerror(rv));
    return -1;
  }
  evbuffer_drain(input, rv);
  if(session_send(session_data) != 0) {
    return -1;
  }
  return 0;
}
Esempio n. 6
0
static void
extract_parts_from_multipart (const struct evkeyvalq  * headers,
                              struct evbuffer         * body,
                              tr_ptrArray             * setme_parts)
{
  const char * content_type = evhttp_find_header (headers, "Content-Type");
  const char * in = (const char*) evbuffer_pullup (body, -1);
  size_t inlen = evbuffer_get_length (body);

  const char * boundary_key = "boundary=";
  const char * boundary_key_begin = content_type ? strstr (content_type, boundary_key) : NULL;
  const char * boundary_val = boundary_key_begin ? boundary_key_begin + strlen (boundary_key) : "arglebargle";
  char * boundary = tr_strdup_printf ("--%s", boundary_val);
  const size_t boundary_len = strlen (boundary);

  const char * delim = tr_memmem (in, inlen, boundary, boundary_len);
  while (delim)
    {
      size_t part_len;
      const char * part = delim + boundary_len;

      inlen -= (part - in);
      in = part;

      delim = tr_memmem (in, inlen, boundary, boundary_len);
      part_len = delim ? (size_t)(delim - part) : inlen;

      if (part_len)
        {
          const char * rnrn = tr_memmem (part, part_len, "\r\n\r\n", 4);
          if (rnrn)
            {
              struct tr_mimepart * p = tr_new (struct tr_mimepart, 1);
              p->headers_len = (size_t) (rnrn - part);
              p->headers = tr_strndup (part, p->headers_len);
              p->body_len = (size_t) ((part + part_len) - (rnrn + 4));
              p->body = tr_strndup (rnrn+4, p->body_len);
              tr_ptrArrayAppend (setme_parts, p);
            }
        }
    }

  tr_free (boundary);
}
Esempio n. 7
0
static void pipe_bev_readable(struct bufferevent *bev, void *ctx)
{
	struct pipe_data *data = ctx;
	int avail;
	struct evbuffer *buf;
	struct evbuffer_iovec vec_out;
	err_t ret;
	int wait_for_more = 0;
	u8_t apiflags;

	avail = tcp_sndbuf(data->pcb);
	if (!avail) {
		bufferevent_disable(bev, EV_READ);
		return;
	}

	buf = bufferevent_get_input(data->bev);
	if (avail < evbuffer_get_length(buf))
		wait_for_more = 1;
	else if (avail > evbuffer_get_length(buf))
		avail = evbuffer_get_length(buf);

	if (!avail)
		return;

	evbuffer_pullup(buf, avail);
	evbuffer_peek(buf, avail, NULL, &vec_out, 1);

	apiflags = TCP_WRITE_FLAG_COPY;
	if (wait_for_more)
		apiflags |= TCP_WRITE_FLAG_MORE;
	ret = tcp_write(data->pcb, vec_out.iov_base, avail, apiflags);
	if (ret < 0) {
		bufferevent_disable(bev, EV_READ);
		if (ret != ERR_MEM) {
			pipe_tcp_free(data);
			pipe_bev_flush(data);
		}
	} else {
		evbuffer_drain(buf, avail);
		if (wait_for_more)
			bufferevent_disable(bev, EV_READ);
	}
}
Esempio n. 8
0
std::string HTTPRequest::ReadBody()
{
    struct evbuffer* buf = evhttp_request_get_input_buffer(req);
    if (!buf)
        return "";
    size_t size = evbuffer_get_length(buf);
    /** Trivial implementation: if this is ever a performance bottleneck,
     * internal copying can be avoided in multi-segment buffers by using
     * evbuffer_peek and an awkward loop. Though in that case, it'd be even
     * better to not copy into an intermediate string but use a stream
     * abstraction to consume the evbuffer on the fly in the parsing algorithm.
     */
    const char* data = (const char*)evbuffer_pullup(buf, size);
    if (!data) // returns NULL in case of empty buffer
        return "";
    std::string rv(data, size);
    evbuffer_drain(buf, size);
    return rv;
}
Esempio n. 9
0
static enum bufferevent_filter_result
bufferevent_input_filter(struct evbuffer *src, struct evbuffer *dst,
    ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx)
{
	const unsigned char *buffer;
	int i;

	buffer = evbuffer_pullup(src, evbuffer_get_length(src));
	for (i = 0; i < evbuffer_get_length(src); i += 2) {
		assert(buffer[i] == 'x');
		evbuffer_add(dst, buffer + i + 1, 1);

		if (i + 2 > evbuffer_get_length(src))
			break;
	}

	evbuffer_drain(src, i);
	return (BEV_OK);
}
Esempio n. 10
0
static void
socks_relay_cb(struct bufferevent *bev, void *ptr)
{
	obfsproxyssh_client_session_t *session = ptr;
	obfsproxyssh_t *state = session->client->state;
	struct evbuffer *buf;
	unsigned char *p;
	size_t len;
	ssize_t rval;

	assert(session->socks_ev == bev);

	/*
	 * Note: This is not very efficient, but since libssh2 doesn't have
	 * scatter/gather I/O and libssh2 is most efficient when sending 1 SSH
	 * packet worth of data (32 KiB) at a time, I can't think of a better
	 * way to do this.
	 */

	buf = bufferevent_get_input(bev);
	len = evbuffer_get_length(buf);
	len = (len > OBFSPROXYSSH_CLIENT_WRITE_SZ) ?
		OBFSPROXYSSH_CLIENT_WRITE_SZ : len;
	p = evbuffer_pullup(buf, len);
	if (NULL == p) {
		log_f(state, "RELAY: Error: %s Failed to pullup (OOM?)",
				bdata(session->socks_addr));
		ssh_relay_event_cb(session->ssh_ev, BEV_EVENT_ERROR, session);
		return;
	}

	rval = libssh2_channel_write(session->ssh_channel, (char *) p, len);
	if (LIBSSH2_ERROR_EAGAIN == rval || 0 == rval)
		return;
	else if (rval < 0) {
		log_f(state, "RELAY: Error: %s Channel write failed (%d)",
				bdata(session->ssh_addr), rval);
		ssh_relay_event_cb(session->ssh_ev, BEV_EVENT_ERROR, session);
		return;
	} else
		evbuffer_drain(buf, rval);
}
Esempio n. 11
0
/* Read the data in the bufferevent and feed them into nghttp2 library
   function. Invocation of nghttp2_session_mem_recv() may make
   additional pending frames, so call session_send() at the end of the
   function. */
static int session_recv(http2_session_data *session_data) {
  ssize_t readlen;
  struct evbuffer *input = bufferevent_get_input(session_data->bev);
  size_t datalen = evbuffer_get_length(input);
  unsigned char *data = evbuffer_pullup(input, -1);

  readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
  if (readlen < 0) {
    warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
    return -1;
  }
  if (evbuffer_drain(input, (size_t)readlen) != 0) {
    warnx("Fatal error: evbuffer_drain failed");
    return -1;
  }
  if (session_send(session_data) != 0) {
    return -1;
  }
  return 0;
}
Esempio n. 12
0
static void upnpc_soap_response(struct evhttp_request * req, void * pvoid)
{
	size_t len;
	unsigned char * data;
	struct evbuffer * input_buffer;
	upnpc_device_t * d = (upnpc_device_t *)pvoid;
	int code;

	if(req == NULL) {
		debug_printf("%s(%p, %p) NULL argument !\n", __func__, req, pvoid);
		return;
	}
	code = evhttp_request_get_response_code(req);
	input_buffer = evhttp_request_get_input_buffer(req);
	len = evbuffer_get_length(input_buffer);
	data = evbuffer_pullup(input_buffer, len);
	debug_printf("%s %d (%d bytes)\n", __func__, code, (int)len);
	debug_printf("%.*s\n", (int)len, (char *)data);
	if(data == NULL)
		return;

	ClearNameValueList(&d->soap_response_data);
	ParseNameValue((char *)data, (int)len, 
	               &d->soap_response_data);
	d->state &= ~UPNPC_DEVICE_SOAP_REQ;
	if(d->state & UPNPC_DEVICE_READY) {
		d->parent->soap_cb(code, d->parent, d, d->parent->cb_data);
	} else if(d->state & UPNPC_DEVICE_GETSTATUS) {
		const char * connection_status;
		d->state &= ~UPNPC_DEVICE_GETSTATUS;
		connection_status = GetValueFromNameValueList(&d->soap_response_data, "NewConnectionStatus");
		d->state |= UPNPC_DEVICE_READY;
		if((code == 200) && connection_status && (0 == strcmp("Connected", connection_status))) {
			d->parent->ready_cb(code, d->parent, d, d->parent->cb_data);
			d->state |= UPNPC_DEVICE_CONNECTED;
			event_del(d->parent->ev_ssdp_recv);
		} else {
			d->parent->ready_cb(UPNPC_ERR_NOT_CONNECTED, d->parent, d, d->parent->cb_data);
		}
	}
}
/* Post Request Function */
void http_requset_post_cb(struct evhttp_request *req, void *arg)
{
    struct http_request_post *http_req_post = (struct http_request_post *)arg;
    switch(req->response_code)
    {
        case HTTP_OK:
        {
            struct evbuffer* buf = evhttp_request_get_input_buffer(req);
            size_t len = evbuffer_get_length(buf);
            printf("print the head info:\n");
            print_request_head_info(req->output_headers);
            
            printf("len:%zu  body size:%zu\n", len, req->body_size);
            char *tmp = malloc(len+1);
            memcpy(tmp, evbuffer_pullup(buf, -1), len);
            tmp[len] = '\0';
            printf("print the body:\n");
            printf("HTML BODY:%s\n", tmp);
            free(tmp);
            
            event_base_loopexit(http_req_post->base, 0);
            break;
        }
        case HTTP_MOVEPERM:
            printf("%s", "the uri moved permanently\n");
            break;
        case HTTP_MOVETEMP:
        {
            const char *new_location = evhttp_find_header(req->input_headers, "Location");
            struct evhttp_uri *new_uri = evhttp_uri_parse(new_location);
            evhttp_uri_free(http_req_post->uri);
            http_req_post->uri = new_uri;
            start_url_request((struct http_request_get *)http_req_post, REQUEST_POST_FLAG);
            return;
        }
            
        default:
            event_base_loopexit(http_req_post->base, 0);
            return;
    }
}
Esempio n. 14
0
bool __check_zero_handshake(struct evbuffer* in,
                            struct nbd_client* client)
{
    uint32_t* peek;
    peek = (uint32_t*) evbuffer_pullup(in, 4);

    if (peek)
    {
        if (*peek != 0)
        {
            client->state = NBD_DISCONNECTED;
            return false;
        }

        evbuffer_drain(in, 4);
        client->state = NBD_ZERO_RECEIVED;
        return false;
    }

    return true;
}
Esempio n. 15
0
void
tr_tracker_http_announce( tr_session                 * session,
                          const tr_announce_request  * request,
                          tr_announce_response_func    response_func,
                          void                       * response_func_user_data )
{
    struct announce_data * d;
    struct evbuffer * buf = announce_url_new( session, request );
    const char * url = (const char *) evbuffer_pullup( buf, -1 );

    d = tr_new0( struct announce_data, 1 );
    d->response_func = response_func;
    d->response_func_user_data = response_func_user_data;
    memcpy( d->response.info_hash, request->info_hash, SHA_DIGEST_LENGTH );
    tr_strlcpy( d->log_name, request->log_name, sizeof( d->log_name ) );

    dbgmsg( request->log_name, "Sending announce to libcurl: \"%s\"", url );
    tr_webRun( session, url, NULL, NULL, on_announce_done, d );

    evbuffer_free( buf );
}
Esempio n. 16
0
static void s3http_connection_on_responce_cb (struct evhttp_request *req, void *ctx)
{
    RequestData *data = (RequestData *) ctx;
    struct evbuffer *inbuf;
    const char *buf = NULL;
    size_t buf_len;

    LOG_debug (CON_LOG, "Got HTTP response from server !");

    if (!req) {
        LOG_err (CON_LOG, "Request failed !");
        if (data->error_cb)
            data->error_cb (data->con, data->ctx);
        goto done;
    }

    // XXX: handle redirect
    // 200 and 204 (No Content) are ok
    if (evhttp_request_get_response_code (req) != 200 && evhttp_request_get_response_code (req) != 204
        && evhttp_request_get_response_code (req) != 307) {
        LOG_err (CON_LOG, "Server returned HTTP error: %d !", evhttp_request_get_response_code (req));
        LOG_debug (CON_LOG, "Error str: %s", req->response_code_line);
        if (data->error_cb)
            data->error_cb (data->con, data->ctx);
        goto done;
    }

    inbuf = evhttp_request_get_input_buffer (req);
    buf_len = evbuffer_get_length (inbuf);
    buf = (const char *) evbuffer_pullup (inbuf, buf_len);
    
    if (data->responce_cb)
        data->responce_cb (data->con, data->ctx, buf, buf_len, evhttp_request_get_input_headers (req));
    else
        LOG_debug (CON_LOG, ">>> NO callback function !");

done:
    g_free (data);
}
Esempio n. 17
0
static int
testJSONSnippet( const char * benc_str,
                 const char * expected )
{
    tr_benc top;
    char * serialized;
    struct evbuffer * buf;

    tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL );
    buf = tr_bencToBuf( &top, TR_FMT_JSON );
    serialized = (char*) evbuffer_pullup( buf, -1 );
    stripWhitespace( serialized );
#if 0
    fprintf( stderr, "benc: %s\n", benc_str );
    fprintf( stderr, "json: %s\n", serialized );
    fprintf( stderr, "want: %s\n", expected );
#endif
    check_streq (expected, serialized);
    tr_bencFree( &top );
    evbuffer_free( buf );
    return 0;
}
Esempio n. 18
0
static bool
getfile (char ** setme, const char * root, tr_variant * path, struct evbuffer * buf)
{
  bool success = false;

  if (tr_variantIsList (path))
    {
      int i;
      const int n = tr_variantListSize (path);

      evbuffer_drain (buf, evbuffer_get_length (buf));
      evbuffer_add (buf, root, strlen (root));
      for (i=0; i<n; i++)
        {
          size_t len;
          const char * str;

          if (tr_variantGetStr (tr_variantListChild (path, i), &str, &len))
            {
              evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
              evbuffer_add (buf, str, len);
            }
        }

      *setme = tr_utf8clean ((char*)evbuffer_pullup (buf, -1), evbuffer_get_length (buf));
      /* fprintf (stderr, "[%s]\n", *setme); */
      success = true;
    }

  if ((*setme != NULL) && path_is_suspicious (*setme))
    {
      tr_free (*setme);
      *setme = NULL;
      success = false;
    }

  return success;
}
Esempio n. 19
0
/* readcb for bufferevent. Here we get the data from the input buffer
   of bufferevent and feed them to nghttp2 library. This may invoke
   nghttp2 callbacks. It may also queues the frame in nghttp2 session
   context. To send them, we call session_send() in the end. */
static void readcb(struct bufferevent *bev, void *ptr) {
  http2_session_data *session_data = (http2_session_data *)ptr;
  ssize_t readlen;
  struct evbuffer *input = bufferevent_get_input(bev);
  size_t datalen = evbuffer_get_length(input);
  unsigned char *data = evbuffer_pullup(input, -1);

  readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
  if (readlen < 0) {
    warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
    delete_http2_session_data(session_data);
    return;
  }
  if (evbuffer_drain(input, (size_t)readlen) != 0) {
    warnx("Fatal error: evbuffer_drain failed");
    delete_http2_session_data(session_data);
    return;
  }
  if (session_send(session_data) != 0) {
    delete_http2_session_data(session_data);
    return;
  }
}
Esempio n. 20
0
static void userInput2Buff(struct evhttp_request *req, void *args)
{
	UserInput *ui = (UserInput *)args;
	struct event_base *base = ui->base;
	char *buff = ui->buff;
	struct evbuffer *body = evhttp_request_get_input_buffer(req);
	size_t len = evbuffer_get_length(body);
	unsigned char *requestLine;
	struct evbuffer *buf = evbuffer_new();

	switch(req->type) {
		case EVHTTP_REQ_POST:
			requestLine = evbuffer_pullup(body, -1);
			requestLine[len] = '\0';
			memcpy(buff, requestLine, len);
			evhttp_send_reply(req, HTTP_OK, "OK", buf);
			break;
		default:
			evhttp_send_error(req, HTTP_BADREQUEST, "Available POST only");
			break;
	}
	evbuffer_free(buf);
	event_base_loopbreak(base);
}
Esempio n. 21
0
/* 2 $A \leftarrow B$: Diffie Hellman $Y_B$, PadB */
static int readYb(tr_handshake * handshake, struct evbuffer * inbuf) {
    int isEncrypted;
    const uint8_t * secret;
    uint8_t yb[KEY_LEN];
    struct evbuffer * outbuf;
    size_t needlen = HANDSHAKE_NAME_LEN;

    (...)
    isEncrypted = memcmp(evbuffer_pullup(inbuf, HANDSHAKE_NAME_LEN),
                    HANDSHAKE_NAME, HANDSHAKE_NAME_LEN);
    (...)
    tr_peerIoSetEncryption(handshake->io, isEncrypted ? PEER_ENCRYPTION_RC4
                                                      : PEER_ENCRYPTION_NONE);

    if (!isEncrypted) {
        setState(handshake, AWAITING_HANDSHAKE); // Handshake não encriptado acaba aqui.
        return READ_NOW;
    }

    (...)
    /* compute the secret $S$*/
    evbuffer_remove(inbuf, yb, KEY_LEN);
    secret = tr_cryptoComputeSecret(handshake->crypto, yb);
    memcpy(handshake->mySecret, secret, KEY_LEN);
Esempio n. 22
0
int encode_in_ev(Gzb64* gzb64, struct evbuffer* input)
{
	int contiguous;
	unsigned char* input_block;

	while(evbuffer_get_length(input) > 0) 
	{
		contiguous = evbuffer_get_contiguous_space(input);	
		input_block = evbuffer_pullup(input, contiguous);

		if( contiguous < evbuffer_get_length(input) ) 
		{
			encode_in(gzb64, &input_block[0], contiguous, false);
			evbuffer_drain(input, contiguous);			
		} else 
		{
			/* last (only) block */
			encode_in(gzb64, &input_block[0], contiguous, true);
			evbuffer_drain(input, contiguous);
		}
	}
	
	return 0;
}
Esempio n. 23
0
static void http_request_done(struct evhttp_request *req, void *ctx)
{
    HTTPReply *reply = static_cast<HTTPReply*>(ctx);

    if (req == nullptr) {
        /* If req is nullptr, it means an error occurred while connecting: the
         * error code will have been passed to http_error_cb.
         */
        reply->status = 0;
        return;
    }

    reply->status = evhttp_request_get_response_code(req);

    struct evbuffer *buf = evhttp_request_get_input_buffer(req);
    if (buf)
    {
        size_t size = evbuffer_get_length(buf);
        const char *data = (const char*)evbuffer_pullup(buf, size);
        if (data)
            reply->body = std::string(data, size);
        evbuffer_drain(buf, size);
    }
}
Esempio n. 24
0
static void http_request_done(struct evhttp_request *req, void *ctx)
{
    HTTPReply *reply = static_cast<HTTPReply*>(ctx);

    if (req == nullptr) {
        /* If req is nullptr, it means an error occurred while connecting, but
         * I'm not sure how to find out which one. We also don't really care.
         */
        reply->status = 0;
        return;
    }

    reply->status = evhttp_request_get_response_code(req);

    struct evbuffer *buf = evhttp_request_get_input_buffer(req);
    if (buf)
    {
        size_t size = evbuffer_get_length(buf);
        const char *data = (const char*)evbuffer_pullup(buf, size);
        if (data)
            reply->body = std::string(data, size);
        evbuffer_drain(buf, size);
    }
}
Esempio n. 25
0
File: conn.c Progetto: 0xffea/shim
static void
conn_readcb(struct bufferevent *bev, void *arg)
{
	struct conninfo *info = arg;
	struct evbuffer *inbuf = bufferevent_get_input(bev);
	unsigned char *data;
	unsigned char code;

	/* socks4 and socks4a both have an 8 byte response */
	if (evbuffer_get_length(inbuf) < 8) {
		log_debug("conn: waiting for full socks response");
		return;
	}

	data = evbuffer_pullup(inbuf, 8);
	code = data[1];
	evbuffer_drain(inbuf, 8);

	if (code != 0x5a) {
		finish_connection(info, 0, socks4_error_to_string(code));
	} else {
		finish_connection(info, 1, NULL);
	}
}
Esempio n. 26
0
static void
on_announce_done( tr_session   * session,
                  bool           did_connect,
                  bool           did_timeout,
                  long           response_code,
                  const void   * msg,
                  size_t         msglen,
                  void         * vdata )
{
    tr_announce_response * response;
    struct announce_data * data = vdata;

    response = &data->response;
    response->did_connect = did_connect;
    response->did_timeout = did_timeout;
    dbgmsg( data->log_name, "Got announce response" );

    if( response_code != HTTP_OK )
    {
        const char * fmt = _( "Tracker gave HTTP response code %1$ld (%2$s)" );
        const char * response_str = tr_webGetResponseStr( response_code );
        response->errmsg = tr_strdup_printf( fmt, response_code, response_str );
    }
    else
    {
        tr_benc benc;
        const int benc_loaded = !tr_bencLoad( msg, msglen, &benc, NULL );

        if( getenv( "TR_CURL_VERBOSE" ) != NULL )
        {
            struct evbuffer * buf = tr_bencToBuf( &benc, TR_FMT_JSON );
            fprintf( stderr, "Announce response:\n< %s\n", evbuffer_pullup( buf, -1 ) );
            tr_free( buf );
        }

        if( benc_loaded && tr_bencIsDict( &benc ) )
        {
            int64_t i;
            size_t rawlen;
            tr_benc * tmp;
            const char * str;
            const uint8_t * raw;

            if( tr_bencDictFindStr( &benc, "failure reason", &str ) )
                response->errmsg = tr_strdup( str );

            if( tr_bencDictFindStr( &benc, "warning message", &str ) )
                response->warning = tr_strdup( str );

            if( tr_bencDictFindInt( &benc, "interval", &i ) )
                response->interval = i;

            if( tr_bencDictFindInt( &benc, "min interval", &i ) )
                response->min_interval = i;

            if( tr_bencDictFindStr( &benc, "tracker id", &str ) )
                response->tracker_id_str = tr_strdup( str );

            if( tr_bencDictFindInt( &benc, "complete", &i ) )
                response->seeders = i;

            if( tr_bencDictFindInt( &benc, "incomplete", &i ) )
                response->leechers = i;

            if( tr_bencDictFindInt( &benc, "downloaded", &i ) )
                response->downloads = i;

            if( tr_bencDictFindRaw( &benc, "peers6", &raw, &rawlen ) ) {
                dbgmsg( data->log_name, "got a peers6 length of %zu", rawlen );
                response->pex6 = tr_peerMgrCompact6ToPex( raw, rawlen,
                                              NULL, 0, &response->pex6_count );
            }

            if( tr_bencDictFindRaw( &benc, "peers", &raw, &rawlen ) ) {
                dbgmsg( data->log_name, "got a compact peers length of %zu", rawlen );
                response->pex = tr_peerMgrCompactToPex( raw, rawlen,
                                               NULL, 0, &response->pex_count );
            } else if( tr_bencDictFindList( &benc, "peers", &tmp ) ) {
                response->pex = listToPex( tmp, &response->pex_count );
                dbgmsg( data->log_name, "got a peers list with %zu entries",
                        response->pex_count );
            }
        }

        if( benc_loaded )
            tr_bencFree( &benc );
    }

    tr_runInEventThread( session, on_announce_done_eventthread, data );
}
Esempio n. 27
0
/* Thread: httpd */
void
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf)
{
  unsigned char outbuf[128 * 1024];
  z_stream strm;
  struct evbuffer *gzbuf;
  struct evkeyvalq *headers;
  const char *param;
  int flush;
  int zret;
  int ret;

  if (!req)
    return;

  if (!evbuf || (evbuffer_get_length(evbuf) == 0))
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping body-less reply\n");

      goto no_gzip;
    }

  headers = evhttp_request_get_input_headers(req);

  param = evhttp_find_header(headers, "Accept-Encoding");
  if (!param)
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping; no Accept-Encoding header\n");

      goto no_gzip;
    }
  else if (!strstr(param, "gzip") && !strstr(param, "*"))
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping; gzip not in Accept-Encoding (%s)\n", param);

      goto no_gzip;
    }

  gzbuf = evbuffer_new();
  if (!gzbuf)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n");

      goto no_gzip;
    }

  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;

  /* Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default) */
  zret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
  if (zret != Z_OK)
    {
      DPRINTF(E_DBG, L_HTTPD, "zlib setup failed: %s\n", zError(zret));

      goto out_fail_init;
    }

  strm.next_in = evbuffer_pullup(evbuf, -1);
  strm.avail_in = evbuffer_get_length(evbuf);

  flush = Z_NO_FLUSH;

  /* 2 iterations: Z_NO_FLUSH until input is consumed, then Z_FINISH */
  for (;;)
    {
      do
	{
	  strm.next_out = outbuf;
	  strm.avail_out = sizeof(outbuf);

	  zret = deflate(&strm, flush);
	  if (zret == Z_STREAM_ERROR)
	    {
	      DPRINTF(E_LOG, L_HTTPD, "Could not deflate data: %s\n", strm.msg);

	      goto out_fail_gz;
	    }

	  ret = evbuffer_add(gzbuf, outbuf, sizeof(outbuf) - strm.avail_out);
	  if (ret < 0)
	    {
	      DPRINTF(E_LOG, L_HTTPD, "Out of memory adding gzipped data to evbuffer\n");

	      goto out_fail_gz;
	    }
	}
      while (strm.avail_out == 0);

      if (flush == Z_FINISH)
	break;

      flush = Z_FINISH;
    }

  if (zret != Z_STREAM_END)
    {
      DPRINTF(E_LOG, L_HTTPD, "Compressed data not finalized!\n");

      goto out_fail_gz;
    }

  deflateEnd(&strm);

  headers = evhttp_request_get_output_headers(req);

  evhttp_add_header(headers, "Content-Encoding", "gzip");
  evhttp_send_reply(req, code, reason, gzbuf);

  evbuffer_free(gzbuf);

  /* Drain original buffer, as would be after evhttp_send_reply() */
  evbuffer_drain(evbuf, evbuffer_get_length(evbuf));

  return;

 out_fail_gz:
  deflateEnd(&strm);
 out_fail_init:
  evbuffer_free(gzbuf);
 no_gzip:
  evhttp_send_reply(req, code, reason, evbuf);
}
Esempio n. 28
0
static void
add_response (struct evhttp_request * req,
              struct tr_rpc_server  * server,
              struct evbuffer       * out,
              struct evbuffer       * content)
{
  const char * key = "Accept-Encoding";
  const char * encoding = evhttp_find_header (req->input_headers, key);
  const int do_compress = encoding && strstr (encoding, "gzip");

  if (!do_compress)
    {
      evbuffer_add_buffer (out, content);
    }
  else
    {
      int state;
      struct evbuffer_iovec iovec[1];
      void * content_ptr = evbuffer_pullup (content, -1);
      const size_t content_len = evbuffer_get_length (content);

      if (!server->isStreamInitialized)
        {
          int compressionLevel;

          server->isStreamInitialized = true;
          server->stream.zalloc = (alloc_func) Z_NULL;
          server->stream.zfree = (free_func) Z_NULL;
          server->stream.opaque = (voidpf) Z_NULL;

          /* zlib's manual says: "Add 16 to windowBits to write a simple gzip header
           * and trailer around the compressed data instead of a zlib wrapper." */
#ifdef TR_LIGHTWEIGHT
          compressionLevel = Z_DEFAULT_COMPRESSION;
#else
          compressionLevel = Z_BEST_COMPRESSION;
#endif
          deflateInit2 (&server->stream, compressionLevel, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
        }

      server->stream.next_in = content_ptr;
      server->stream.avail_in = content_len;

      /* allocate space for the raw data and call deflate () just once --
       * we won't use the deflated data if it's longer than the raw data,
       * so it's okay to let deflate () run out of output buffer space */
      evbuffer_reserve_space (out, content_len, iovec, 1);
      server->stream.next_out = iovec[0].iov_base;
      server->stream.avail_out = iovec[0].iov_len;
      state = deflate (&server->stream, Z_FINISH);

      if (state == Z_STREAM_END)
        {
          iovec[0].iov_len -= server->stream.avail_out;

#if 0
          fprintf (stderr, "compressed response is %.2f of original (raw==%zu bytes; compressed==%zu)\n",
                   (double)evbuffer_get_length (out)/content_len,
                   content_len, evbuffer_get_length (out));
#endif
          evhttp_add_header (req->output_headers,
                             "Content-Encoding", "gzip");
        }
      else
        {
          memcpy (iovec[0].iov_base, content_ptr, content_len);
          iovec[0].iov_len = content_len;
        }

      evbuffer_commit_space (out, iovec, 1);
      deflateReset (&server->stream);
    }
}
Esempio n. 29
0
static void
test_evbuffer(void *ptr)
{
	static char buffer[512], *tmp;
	struct evbuffer *evb = evbuffer_new();
	struct evbuffer *evb_two = evbuffer_new();
	size_t sz_tmp;
	int i;

	evbuffer_validate(evb);
	evbuffer_add_printf(evb, "%s/%d", "hello", 1);
	evbuffer_validate(evb);

	tt_assert(evbuffer_get_length(evb) == 7);
	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));

	evbuffer_add_buffer(evb, evb_two);
	evbuffer_validate(evb);

	evbuffer_drain(evb, strlen("hello/"));
	evbuffer_validate(evb);
	tt_assert(evbuffer_get_length(evb) == 1);
	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));

	evbuffer_add_printf(evb_two, "%s", "/hello");
	evbuffer_validate(evb);
	evbuffer_add_buffer(evb, evb_two);
	evbuffer_validate(evb);

	tt_assert(evbuffer_get_length(evb_two) == 0);
	tt_assert(evbuffer_get_length(evb) == 7);
	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0);

	memset(buffer, 0, sizeof(buffer));
	evbuffer_add(evb, buffer, sizeof(buffer));
	evbuffer_validate(evb);
	tt_assert(evbuffer_get_length(evb) == 7 + 512);

	tmp = (char *)evbuffer_pullup(evb, 7 + 512);
	tt_assert(tmp);
	tt_assert(!strncmp(tmp, "1/hello", 7));
	tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
	evbuffer_validate(evb);

	evbuffer_prepend(evb, "something", 9);
	evbuffer_validate(evb);
	evbuffer_prepend(evb, "else", 4);
	evbuffer_validate(evb);

	tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
	tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
	evbuffer_validate(evb);

	evbuffer_drain(evb, -1);
	evbuffer_validate(evb);
	evbuffer_drain(evb_two, -1);
	evbuffer_validate(evb);

	for (i = 0; i < 3; ++i) {
		evbuffer_add(evb_two, buffer, sizeof(buffer));
		evbuffer_validate(evb_two);
		evbuffer_add_buffer(evb, evb_two);
		evbuffer_validate(evb);
		evbuffer_validate(evb_two);
	}

	tt_assert(evbuffer_get_length(evb_two) == 0);
	tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));

	/* test remove buffer */
	sz_tmp = (size_t)(sizeof(buffer)*2.5);
	evbuffer_remove_buffer(evb, evb_two, sz_tmp);
	tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
	tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
	evbuffer_validate(evb);

	if (memcmp(evbuffer_pullup(
			   evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
	    memcmp(evbuffer_pullup(
			   evb_two, -1), buffer, sizeof(buffer) != 0))
		tt_abort_msg("Pullup did not preserve content");

	evbuffer_validate(evb);


	/* testing one-vector reserve and commit */
	{
		struct evbuffer_iovec v[1];
		char *buf;
		int i, j, r;

		for (i = 0; i < 3; ++i) {
			r = evbuffer_reserve_space(evb, 10000, v, 1);
			tt_int_op(r, ==, 1);
			tt_assert(v[0].iov_len >= 10000);
			tt_assert(v[0].iov_base != NULL);

			evbuffer_validate(evb);
			buf = v[0].iov_base;
			for (j = 0; j < 10000; ++j) {
				buf[j] = j;
			}
			evbuffer_validate(evb);

			tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
			evbuffer_validate(evb);

			tt_assert(evbuffer_get_length(evb) >= 10000);

			evbuffer_drain(evb, j * 5000);
			evbuffer_validate(evb);
		}
	}

 end:
	evbuffer_free(evb);
	evbuffer_free(evb_two);
}
Esempio n. 30
0
void conn_read_cb(struct bufferevent *bev, void *arg)
{
    conn *c = (conn *)arg;
    user_callback *cb = (user_callback *)(c->data);

    struct evbuffer* input = bufferevent_get_input(bev);
    size_t total_len = evbuffer_get_length(input);

    while (1)
    {
        if (total_len < MSG_HEAD_SIZE) {
            goto conti;
        }
        else {
            unsigned char *buffer = evbuffer_pullup(input, MSG_HEAD_SIZE);
            if (NULL == buffer)
            {
                merror("evbuffer_pullup MSG_HEAD_SIZE failed!");
                goto err;
            }

            unsigned short *cur = (unsigned short *)buffer;
            unsigned int len = ntohs(*(unsigned int *)cur);
            cur += 2;

            if (MSG_MAX_SIZE < len)
            {
                merror("len:%d > MSG_MAX_SIZE!", len);
                goto err;
            }

            if (total_len < MSG_HEAD_SIZE + len)
                goto conti;

            size_t msg_len = MSG_HEAD_SIZE + len;
            buffer = evbuffer_pullup(input, msg_len);
            if (NULL == buffer)
            {
                merror("evbuffer_pullup msg_len failed!");
                goto err;
            }

            /* TODO frequency limit */

            /* callback */
            if (cb->rpc)
                (*(cb->rpc))(c, buffer, msg_len);

            if (evbuffer_drain(input, msg_len) < 0)
            {
                merror("evbuffer_drain failed!");
                goto err;
            }

            total_len -= msg_len;
        }
    }
    return;

err:
    mdebug("close sockect!");
    if (cb->disconnect) {
        (*(cb->disconnect))(c);
    }
    conn_decref(c);
    return;

conti:
    bufferevent_enable(bev, EV_READ);
    return;
}