Skip to content

Instantly share code, notes, and snippets.

@azat
Created December 18, 2018 18:08
Show Gist options
  • Save azat/373867217af9de89917663c818b4b118 to your computer and use it in GitHub Desktop.
Save azat/373867217af9de89917663c818b4b118 to your computer and use it in GitHub Desktop.
#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