static void echo_read_cb(struct bufferevent *bev, void *ctx) { char * line; char* retval; size_t len; /* This callback is invoked when there is data to read on bev. */ struct evbuffer *input = bufferevent_get_input(bev); struct evbuffer *output = bufferevent_get_output(bev); struct evbuffer_iovec v[2]; line = evbuffer_readln(input, &len, EVBUFFER_EOL_CRLF); retval = (char*)command_parser(line); //command_parser(line); evbuffer_reserve_space(output, strlen(retval), v, 2); evbuffer_add(output, retval, strlen(retval)); evbuffer_commit_space(output, v, 1); //evbuffer_add_buffer(output, input); //evbuffer_copyout(input, line, buffer_len); /* Copy all the data from the input buffer to the output buffer. */ printf("%s\n",line); free(line); }
static void test_evbuffer_reserve_many(void *ptr) { /* This is a glass-box test to handle expanding a buffer with more * chunks and reallocating chunks as needed */ struct evbuffer *buf = evbuffer_new(); struct evbuffer_iovec v[8]; int n; size_t sz; int add_data = ptr && !strcmp(ptr, "add"); int fill_first = ptr && !strcmp(ptr, "fill"); char *cp1, *cp2; /* When reserving the the first chunk, we just allocate it */ n = evbuffer_reserve_space(buf, 128, v, 2); evbuffer_validate(buf); tt_int_op(n, ==, 1); tt_assert(v[0].iov_len >= 128); sz = v[0].iov_len; cp1 = v[0].iov_base; if (add_data) { *(char*)v[0].iov_base = 'X'; v[0].iov_len = 1; n = evbuffer_commit_space(buf, v, 1); tt_int_op(n, ==, 0); } else if (fill_first) {
static void encrypt_mem(redsocks_client * client, char * data, size_t len, struct bufferevent * to, int decrypt) { ss_client *sclient = (void*)(client + 1); struct evbuffer_iovec vec; struct evbuffer * buf_out = bufferevent_get_output(to); size_t required; int rc; if (!len || !data) return; if (decrypt) required = ss_calc_buffer_size(&sclient->d_ctx, len); else required = ss_calc_buffer_size(&sclient->e_ctx, len); if (required && evbuffer_reserve_space(buf_out, required, &vec, 1) == 1) { if (decrypt) rc = ss_decrypt(&sclient->d_ctx, data, len, vec.iov_base, &vec.iov_len); else rc = ss_encrypt(&sclient->e_ctx, data, len, vec.iov_base, &vec.iov_len); if (!rc) vec.iov_len = 0; evbuffer_commit_space(buf_out, &vec, 1); } }
int encode_in(Gzb64* gzb64, const unsigned char* buf, const size_t length, const bool last) { int flush_type, zret; struct evbuffer_iovec v[2]; int n, i, written; size_t n_to_add = BUFF_SIZE; if(last) { flush_type = Z_FINISH; gzb64->encoded_last_chunk = true; } else { flush_type = Z_NO_FLUSH; } gzb64->gz_encode_strm.next_in = buf; gzb64->gz_encode_strm.avail_in = length; /* loop as long as more input available */ while( 0 != gzb64->gz_encode_strm.avail_in || Z_FINISH == flush_type ) { /* Reserve BUFF_SIZE bytes.*/ n = evbuffer_reserve_space(gzb64->encode_gzout_buffer, n_to_add, v, 2); if (n<=0) return -1; /* Unable to reserve the space for some reason. */ for (i=0; i<n && n_to_add > 0; ++i) { size_t len = v[i].iov_len; if (len > n_to_add) /* Don't write more than n_to_add bytes. */ len = n_to_add; gzb64->gz_encode_strm.avail_out = len; gzb64->gz_encode_strm.next_out = v[i].iov_base; zret = deflate (& gzb64->gz_encode_strm, flush_type); if(zret < 0) zerr(zret); written = len - gzb64->gz_encode_strm.avail_out; if(DEBUG) printf("Deflate Out:%d\n", written); /* If there was a problem during data generation, we can just stop here; no data will be committed to the buffer. */ /* Set iov_len to the number of bytes we actually wrote, so we don't commit too much. */ v[i].iov_len = written; } /* We commit the space here. Note that we give it 'i' (the number of vectors we actually used) rather than 'n' (the number of vectors we had available. */ if (evbuffer_commit_space(gzb64->encode_gzout_buffer, v, i) < 0) return -1; /* Error committing */ if( Z_FINISH == flush_type && 0 == written ) break; } return 0; }
static enum bufferevent_filter_result zlib_output_filter(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) { struct evbuffer_iovec v_in[1]; struct evbuffer_iovec v_out[1]; int nread, nwrite; int res, n; z_streamp p = ctx; do { /* let's do some compression */ n = evbuffer_peek(src, -1, NULL, v_in, 1); if (n) { p->avail_in = v_in[0].iov_len; p->next_in = v_in[0].iov_base; } else { p->avail_in = 0; p->next_in = 0; } evbuffer_reserve_space(dst, 4096, v_out, 1); p->next_out = v_out[0].iov_base; p->avail_out = v_out[0].iov_len; /* we need to flush zlib if we got a flush */ res = deflate(p, getstate(state)); /* let's figure out how much was decompressed */ nread = v_in[0].iov_len - p->avail_in; nwrite = v_out[0].iov_len - p->avail_out; evbuffer_drain(src, nread); v_out[0].iov_len = nwrite; evbuffer_commit_space(dst, v_out, 1); if (res==Z_BUF_ERROR) { /* We're out of space, or out of decodeable input. Only if nwrite == 0 assume the latter. */ if (nwrite == 0) return BEV_NEED_MORE; } else { assert(res == Z_OK || res == Z_STREAM_END); } } while (evbuffer_get_length(src) > 0); ++outfilter_calls; return (BEV_OK); }
int encode_out_ev(Gzb64* gzb64, struct evbuffer* output) { struct evbuffer_iovec v[2]; int n, i, written; size_t n_to_add = BUFF_SIZE; /* Reserve BUFF_SIZE bytes.*/ n = evbuffer_reserve_space(output, n_to_add, v, 2); if (n<=0) return -1; /* Unable to reserve the space for some reason. */ for (i=0; i<n && n_to_add > 0; ++i) { size_t len = v[i].iov_len; if (len > n_to_add) /* Don't write more than n_to_add bytes. */ len = n_to_add; if ( (written = encode_out(gzb64, v[i].iov_base, len)) < 0) { /* If there was a problem during data generation, we can just stop here; no data will be committed to the buffer. */ return -1; } /* Set iov_len to the number of bytes we actually wrote, so we don't commit too much. */ v[i].iov_len = written; } /* We commit the space here. Note that we give it 'i' (the number of vectors we actually used) rather than 'n' (the number of vectors we had available. */ if (evbuffer_commit_space(output, v, i) < 0) return -1; /* Error committing */ /* recurse if some bytes were retrieved */ if( written > 0 ) return encode_out_ev(gzb64, output); resetEncoder(gzb64); return 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); } }
static void test_evbuffer_reserve2(void *ptr) { /* Test the two-vector cases of reserve/commit. */ struct evbuffer *buf = evbuffer_new(); int n, i; struct evbuffer_iovec v[2]; size_t remaining; char *cp, *cp2; /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/ n = evbuffer_reserve_space(buf, 1024, v, 2); tt_int_op(n, ==, 1); tt_int_op(evbuffer_get_length(buf), ==, 0); tt_assert(v[0].iov_base != NULL); tt_int_op(v[0].iov_len, >=, 1024); memset(v[0].iov_base, 'X', 512); cp = v[0].iov_base; remaining = v[0].iov_len - 512; v[0].iov_len = 512; tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); tt_int_op(evbuffer_get_length(buf), ==, 512); /* Ask for another same-chunk request, in an existing chunk. Use 8 * bytes of it. */ n = evbuffer_reserve_space(buf, 32, v, 2); tt_int_op(n, ==, 1); tt_assert(cp + 512 == v[0].iov_base); tt_int_op(remaining, ==, v[0].iov_len); memset(v[0].iov_base, 'Y', 8); v[0].iov_len = 8; tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); tt_int_op(evbuffer_get_length(buf), ==, 520); remaining -= 8; /* Now ask for a request that will be split. Use only one byte of it, though. */ n = evbuffer_reserve_space(buf, remaining+64, v, 2); tt_int_op(n, ==, 2); tt_assert(cp + 520 == v[0].iov_base); tt_int_op(remaining, ==, v[0].iov_len); tt_assert(v[1].iov_base); tt_assert(v[1].iov_len >= 64); cp2 = v[1].iov_base; memset(v[0].iov_base, 'Z', 1); v[0].iov_len = 1; tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); tt_int_op(evbuffer_get_length(buf), ==, 521); remaining -= 1; /* Now ask for a request that will be split. Use some of the first * part and some of the second. */ n = evbuffer_reserve_space(buf, remaining+64, v, 2); tt_int_op(n, ==, 2); tt_assert(cp + 521 == v[0].iov_base); tt_int_op(remaining, ==, v[0].iov_len); tt_assert(v[1].iov_base == cp2); tt_assert(v[1].iov_len >= 64); memset(v[0].iov_base, 'W', 400); v[0].iov_len = 400; memset(v[1].iov_base, 'x', 60); v[1].iov_len = 60; tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2)); tt_int_op(evbuffer_get_length(buf), ==, 981); /* Now peek to make sure stuff got made how we like. */ memset(v,0,sizeof(v)); n = evbuffer_peek(buf, -1, NULL, v, 2); tt_int_op(n, ==, 2); tt_int_op(v[0].iov_len, ==, 921); tt_int_op(v[1].iov_len, ==, 60); cp = v[0].iov_base; for (i=0; i<512; ++i) tt_int_op(cp[i], ==, 'X'); for (i=512; i<520; ++i) tt_int_op(cp[i], ==, 'Y'); for (i=520; i<521; ++i) tt_int_op(cp[i], ==, 'Z'); for (i=521; i<921; ++i) tt_int_op(cp[i], ==, 'W'); cp = v[1].iov_base; for (i=0; i<60; ++i) tt_int_op(cp[i], ==, 'x'); end: evbuffer_free(buf); }
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); }
v[0].iov_len = 1; n = evbuffer_commit_space(buf, v, 1); tt_int_op(n, ==, 0); } else if (fill_first) { memset(v[0].iov_base, 'X', v[0].iov_len); n = evbuffer_commit_space(buf, v, 1); tt_int_op(n, ==, 0); n = evbuffer_reserve_space(buf, 128, v, 2); tt_int_op(n, ==, 1); sz = v[0].iov_len; tt_assert(v[0].iov_base != cp1); cp1 = v[0].iov_base; } /* Make another chunk get added. */ n = evbuffer_reserve_space(buf, sz+128, v, 2); evbuffer_validate(buf); tt_int_op(n, ==, 2); sz = v[0].iov_len + v[1].iov_len; tt_int_op(sz, >=, v[0].iov_len+128); if (add_data) { tt_assert(v[0].iov_base == cp1 + 1); } else { tt_assert(v[0].iov_base == cp1); } cp1 = v[0].iov_base; cp2 = v[1].iov_base; /* And a third chunk. */ n = evbuffer_reserve_space(buf, sz+128, v, 3); evbuffer_validate(buf);
static int decode(Gzb64* gzb64, bool last) { int b64in_size; struct evbuffer_iovec v[2]; int n, i; size_t n_to_add = BUFF_SIZE; if( last ) { b64in_size = evbuffer_get_length(gzb64->decode_input_buffer); /* dump everything in */ gzb64->decoded_last_chunk = true; } else { int contiguous = evbuffer_get_contiguous_space(gzb64->decode_input_buffer); b64in_size = contiguous - (contiguous % 4); /* must be mutliple of 4 */ } if(DEBUG) printf("Decode In:%zu\n", evbuffer_get_length(gzb64->decode_input_buffer)); unsigned char* b64in_buf = evbuffer_pullup(gzb64->decode_input_buffer, b64in_size); BIO *b64_src_temp = BIO_new_mem_buf(b64in_buf, b64in_size); gzb64->b64_decoder = BIO_push(gzb64->b64_decoder, b64_src_temp); int b64_output_len = BUFF_SIZE; while(b64_output_len == BUFF_SIZE) { /* Reserve BUFF_SIZE bytes.*/ n = evbuffer_reserve_space(gzb64->decode_output_buffer, n_to_add, v, 2); if (n<=0) return -1; /* Unable to reserve the space for some reason. */ for (i=0; i<n && n_to_add > 0; ++i) { size_t len = v[i].iov_len; if (len > n_to_add) /* Don't write more than n_to_add bytes. */ len = n_to_add; b64_output_len = BIO_read(gzb64->b64_decoder, v[i].iov_base, len); if ( b64_output_len < 0) { /* If there was a problem during data generation, we can just stop here; no data will be committed to the buffer. */ return -1; } /* Set iov_len to the number of bytes we actually wrote, so we don't commit too much. */ v[i].iov_len = b64_output_len; if(DEBUG) printf("Decode B64 Out:%d\n", b64_output_len); } /* We commit the space here. Note that we give it 'i' (the number of vectors we actually used) rather than 'n' (the number of vectors we had available. */ if (evbuffer_commit_space(gzb64->decode_output_buffer, v, i) < 0) return -1; /* Error committing */ } if(DEBUG) printf("Inflate In:%zu\n", evbuffer_get_length(gzb64->decode_output_buffer)); BIO_pop(gzb64->b64_decoder); BIO_free(b64_src_temp); BIO_reset(gzb64->b64_decoder); evbuffer_drain(gzb64->decode_input_buffer, b64in_size); return 0; }