/* $NetBSD: le-proxy.c,v 1.1.1.3 2021/04/07 02:43:15 christos Exp $ */
/*
This example code shows how to write an (optionally encrypting) SSL proxy
with Libevent's bufferevent layer.
XXX It's a little ugly and should probably be cleaned up.
*/
// Get rid of OSX 10.7 and greater deprecation warnings.
#if defined(__APPLE__) && defined(__clang__)
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
if (evbuffer_get_length(dst) >= MAX_OUTPUT) {
/* We're giving the other side data faster than it can
* pass it on. Stop reading here until we have drained the
* other side to MAX_OUTPUT/2 bytes. */
bufferevent_setcb(partner, readcb, drained_writecb,
eventcb, bev);
bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2,
MAX_OUTPUT);
bufferevent_disable(bev, EV_READ);
}
}
/* We were choking the other side until we drained our outbuf a bit.
* Now it seems drained. */
bufferevent_setcb(bev, readcb, NULL, eventcb, partner);
bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
if (partner)
bufferevent_enable(partner, EV_READ);
}
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
if (what & BEV_EVENT_ERROR) {
unsigned long err;
while ((err = (bufferevent_get_openssl_error(bev)))) {
const char *msg = (const char*)
ERR_reason_error_string(err);
const char *lib = (const char*)
ERR_lib_error_string(err);
const char *func = (const char*)
ERR_func_error_string(err);
fprintf(stderr,
"%s in %s %s\n", msg, lib, func);
}
if (errno)
perror("connection error");
}
if (partner) {
/* Flush all pending data */
readcb(bev, ctx);
if (evbuffer_get_length(
bufferevent_get_output(partner))) {
/* We still have to flush data from the other
* side, but when that's done, close the other
* side. */
bufferevent_setcb(partner,
NULL, close_on_finished_writecb,
eventcb, NULL);
bufferevent_disable(partner, EV_READ);
} else {
/* We have nothing left to say to the other
* side; close it. */
bufferevent_free(partner);
}
}
bufferevent_free(bev);
}
}
static void
accept_cb(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr *a, int slen, void *p)
{
struct bufferevent *b_out, *b_in;
/* Create two linked bufferevent objects: one to connect, one for the
* new connection */
b_in = bufferevent_socket_new(base, fd,
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);