Created
December 18, 2018 18:08
-
-
Save azat/373867217af9de89917663c818b4b118 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <event2/bufferevent.h> | |
#include <event2/buffer.h> | |
#include <event2/event.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <assert.h> | |
struct ctx | |
{ | |
}; | |
static enum bufferevent_filter_result | |
proxy_in(struct evbuffer *src, struct evbuffer* dst, ev_ssize_t lim, | |
enum bufferevent_flush_mode state, void *_ctx) | |
{ | |
struct ctx *ctx = _ctx; | |
size_t slen = evbuffer_get_length(src); | |
size_t dlen = evbuffer_get_length(dst); | |
fprintf(stderr, "%10s: src=%p/%zu->dst=%p/%zu\n", __func__, src, slen, dst, dlen); | |
evbuffer_remove_buffer(src, dst, lim); | |
return BEV_OK; | |
} | |
static enum bufferevent_filter_result | |
proxy_out(struct evbuffer *src, struct evbuffer* dst, ev_ssize_t lim, | |
enum bufferevent_flush_mode state, void *_ctx) | |
{ | |
struct ctx *ctx = _ctx; | |
size_t slen = evbuffer_get_length(src); | |
size_t dlen = evbuffer_get_length(dst); | |
fprintf(stderr, "%10s: src=%p/%zu->dst=%p/%zu\n", __func__, src, slen, dst, dlen); | |
evbuffer_remove_buffer(src, dst, lim); | |
return BEV_OK; | |
} | |
static void readcb(struct bufferevent *bev, void *_ctx) | |
{ | |
struct ctx *ctx = _ctx; | |
struct evbuffer *in = bufferevent_get_input(bev); | |
struct evbuffer *out = bufferevent_get_output(bev); | |
size_t ilen = evbuffer_get_length(in); | |
size_t olen = evbuffer_get_length(out); | |
fprintf(stderr, "%10s: in=%p/%zu, out=%p/%zu\n", __func__, in, ilen, out, olen); | |
const char *data = evbuffer_pullup(in, ilen); | |
fprintf(stdout, "readcb: {'%.*s'}\n", (int)ilen, data); | |
} | |
static void writecb(struct bufferevent *bev, void *_ctx) | |
{ | |
struct ctx *ctx = _ctx; | |
struct evbuffer *in = bufferevent_get_input(bev); | |
struct evbuffer *out = bufferevent_get_output(bev); | |
size_t ilen = evbuffer_get_length(in); | |
size_t olen = evbuffer_get_length(out); | |
fprintf(stderr, "%10s: in=%p/%zu, out=%p/%zu\n", __func__, in, ilen, out, olen); | |
} | |
static void errorcb(struct bufferevent *bev, short what, void *_ctx) | |
{ | |
struct ctx *ctx = _ctx; | |
struct evbuffer *in = bufferevent_get_input(bev); | |
struct evbuffer *out = bufferevent_get_output(bev); | |
size_t ilen = evbuffer_get_length(in); | |
size_t olen = evbuffer_get_length(out); | |
fprintf(stderr, "%10s: in=%p/%zu, out=%p/%zu, what=%hx\n", __func__, in, ilen, out, olen, what); | |
} | |
int main(int argc, const char **argv) | |
{ | |
(void)argc; | |
(void)argv; | |
struct event_base *base; | |
struct bufferevent *bev[2]; | |
int pair[2]; | |
int err; | |
int be_flags; | |
struct ctx ctx_in, ctx_out; | |
be_flags |= BEV_OPT_CLOSE_ON_FREE; | |
setbuf(stdout, NULL); | |
setbuf(stderr, NULL); | |
err = evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair); | |
assert(!err && "socketpair"); | |
err = evutil_make_socket_nonblocking(pair[0]); | |
assert(!err && "nonblocking[0]"); | |
err = evutil_make_socket_nonblocking(pair[1]); | |
assert(!err && "nonblocking[1]"); | |
base = event_base_new(); | |
assert(base && "event_base_new"); | |
bev[0] = bufferevent_socket_new(base, pair[0], 0); | |
assert(bev[0] && "be_sock[0]"); | |
bev[1] = bufferevent_socket_new(base, pair[1], 0); | |
assert(bev[1] && "be_sock[1]"); | |
bev[0] = bufferevent_filter_new(bev[0], NULL, proxy_out, be_flags, NULL, &ctx_in); | |
assert(bev[0] && "be_filter[out/0]"); | |
bev[1] = bufferevent_filter_new(bev[1], proxy_in, NULL, be_flags, NULL, &ctx_out); | |
assert(bev[1] && "be_filter[in/1]"); | |
bufferevent_setcb(bev[0], readcb, writecb, errorcb, NULL); | |
bufferevent_setcb(bev[1], readcb, writecb, errorcb, NULL); | |
bufferevent_enable(bev[1], EV_READ); | |
bufferevent_write(bev[0], "foobar", 6); | |
err = event_base_loop(base, 0); | |
assert(!err && "loop"); | |
bufferevent_free(bev[0]); | |
bufferevent_free(bev[1]); | |
event_base_free(base); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment