void evbuffer_commit_read(struct evbuffer *evbuf, ev_ssize_t nBytes) { struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf); struct evbuffer_iovec iov[2]; int n_vec; EVBUFFER_LOCK(evbuf); EVUTIL_ASSERT(buf->read_in_progress && !buf->write_in_progress); EVUTIL_ASSERT(nBytes >= 0); /* XXXX Can this be false? */ evbuffer_unfreeze(evbuf, 0); iov[0].iov_base = buf->buffers[0].buf; if ((size_t)nBytes <= buf->buffers[0].len) { iov[0].iov_len = nBytes; n_vec = 1; } else { iov[0].iov_len = buf->buffers[0].len; iov[1].iov_base = buf->buffers[1].buf; iov[1].iov_len = nBytes - iov[0].iov_len; n_vec = 2; } if (evbuffer_commit_space(evbuf, iov, n_vec) < 0) EVUTIL_ASSERT(0); /* XXXX fail nicer. */ pin_release(buf, EVBUFFER_MEM_PINNED_R); buf->read_in_progress = 0; _evbuffer_decref_and_unlock(evbuf); }
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 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 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 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; }