增加TCP Passthrough功能实现,调通明文转发流程。
This commit is contained in:
@@ -27,17 +27,16 @@
|
||||
#include <platform.h>
|
||||
#include <ssl_stream.h>
|
||||
#include <tcp_stream.h>
|
||||
#include <cert.h>
|
||||
#include <proxy.h>
|
||||
|
||||
#ifndef TFE_CONFIG_OUTPUT_LIMIT_DEFAULT
|
||||
#define TFE_CONFIG_OUTPUT_LIMIT_DEFAULT (1024 * 1024)
|
||||
#define TFE_CONFIG_OUTPUT_LIMIT_DEFAULT (1024 * 1024)
|
||||
#endif
|
||||
|
||||
/* forward declaration of libevent callbacks */
|
||||
static void tfe_stream_readcb(struct bufferevent *, void *);
|
||||
static void tfe_stream_writecb(struct bufferevent *, void *);
|
||||
static void tfe_stream_eventcb(struct bufferevent *, short, void *);
|
||||
static void __stream_bev_readcb(struct bufferevent *, void *);
|
||||
static void __stream_bev_writecb(struct bufferevent *, void *);
|
||||
static void __stream_bev_eventcb(struct bufferevent *, short, void *);
|
||||
|
||||
static inline struct tfe_stream_private * __TO_STREAM_PRIVATE(const struct tfe_stream * stream)
|
||||
{
|
||||
@@ -46,17 +45,17 @@ static inline struct tfe_stream_private * __TO_STREAM_PRIVATE(const struct tfe_s
|
||||
|
||||
static inline struct tfe_conn_private * __THIS_CONN(struct tfe_stream_private * _stream, enum tfe_conn_dir dir)
|
||||
{
|
||||
return ((dir == CONN_DIR_UPSTREAM) ? (_stream->conn_upstream) : (_stream->conn_downstream));
|
||||
return ((dir == CONN_DIR_DOWNSTREAM) ? (_stream->conn_downstream) : (_stream->conn_upstream));
|
||||
}
|
||||
|
||||
static inline struct tfe_conn_private * __PEER_CONN(struct tfe_stream_private * _stream, enum tfe_conn_dir dir)
|
||||
{
|
||||
return ((dir == CONN_DIR_UPSTREAM) ? (_stream->conn_downstream) : (_stream->conn_upstream));
|
||||
return ((dir == CONN_DIR_DOWNSTREAM) ? (_stream->conn_upstream) : (_stream->conn_downstream));
|
||||
}
|
||||
|
||||
static inline enum tfe_conn_dir __DIR(struct tfe_stream_private * _stream, struct bufferevent * bev)
|
||||
static inline enum tfe_conn_dir __BEV_DIR(struct tfe_stream_private * _stream, struct bufferevent * bev)
|
||||
{
|
||||
return ((bev == _stream->conn_downstream->bev) ? CONN_DIR_UPSTREAM : CONN_DIR_DOWNSTREAM);
|
||||
return ((bev == _stream->conn_downstream->bev) ? CONN_DIR_DOWNSTREAM : CONN_DIR_UPSTREAM);
|
||||
}
|
||||
|
||||
static inline bool __IS_SSL(struct tfe_stream_private * _stream)
|
||||
@@ -88,8 +87,6 @@ int tfe_stream_preempt(const struct tfe_stream * stream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct tfe_stream_write_ctx * tfe_stream_write_frag_start(const struct tfe_stream * stream, enum tfe_conn_dir dir)
|
||||
{
|
||||
struct tfe_stream_private * _stream = __TO_STREAM_PRIVATE(stream);
|
||||
@@ -131,15 +128,152 @@ int tfe_stream_write(const struct tfe_stream * stream, enum tfe_conn_dir dir, co
|
||||
return ret;
|
||||
}
|
||||
|
||||
static tfe_conn_private * __conn_private_create(struct tfe_stream_private * stream, struct bufferevent * bev)
|
||||
{
|
||||
struct tfe_conn_private * __conn_private = ALLOC(struct tfe_conn_private, 1);
|
||||
__conn_private->bev = bev;
|
||||
__conn_private->fd = bufferevent_getfd(bev);
|
||||
|
||||
bufferevent_setcb(__conn_private->bev, __stream_bev_readcb, __stream_bev_writecb, __stream_bev_eventcb, stream);
|
||||
bufferevent_enable(__conn_private->bev, EV_READ | EV_WRITE);
|
||||
|
||||
return __conn_private;
|
||||
}
|
||||
|
||||
evutil_socket_t __conn_private_release_fd(struct tfe_conn_private * conn)
|
||||
{
|
||||
evutil_socket_t __to_release_fd = conn->fd;
|
||||
conn->fd = 0;
|
||||
return __to_release_fd;
|
||||
}
|
||||
|
||||
static void __conn_private_destory(struct tfe_conn_private * conn)
|
||||
{
|
||||
bufferevent_disable(conn->bev, EV_READ | EV_WRITE);
|
||||
bufferevent_free(conn->bev);
|
||||
|
||||
if (conn->fd > 0) evutil_closesocket(conn->fd);
|
||||
free(conn);
|
||||
}
|
||||
|
||||
static void __stream_bev_passthrough_readcb(struct bufferevent * bev, void * arg)
|
||||
{
|
||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||
struct tfe_conn_private * this_conn = __THIS_CONN(_stream, __BEV_DIR(_stream, bev));
|
||||
struct tfe_conn_private * peer_conn = __PEER_CONN(_stream, __BEV_DIR(_stream, bev));
|
||||
|
||||
struct evbuffer * __input_buffer = bufferevent_get_input(bev);
|
||||
if (peer_conn == NULL)
|
||||
{
|
||||
evbuffer_drain(__input_buffer, evbuffer_get_length(__input_buffer));
|
||||
return;
|
||||
}
|
||||
|
||||
struct evbuffer * __output_buffer = bufferevent_get_output(peer_conn->bev);
|
||||
evbuffer_add_buffer(__output_buffer, __input_buffer);
|
||||
}
|
||||
|
||||
static void __stream_bev_passthrough_writecb(struct bufferevent * bev, void * arg)
|
||||
{
|
||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||
struct tfe_conn_private ** ref_this_conn{};
|
||||
struct tfe_conn_private ** ref_peer_conn{};
|
||||
|
||||
if (__BEV_DIR(_stream, bev) == CONN_DIR_UPSTREAM)
|
||||
{
|
||||
ref_this_conn = &_stream->conn_upstream;
|
||||
ref_peer_conn = &_stream->conn_downstream;
|
||||
}
|
||||
|
||||
if (__BEV_DIR(_stream, bev) == CONN_DIR_DOWNSTREAM)
|
||||
{
|
||||
ref_this_conn = &_stream->conn_downstream;
|
||||
ref_peer_conn = &_stream->conn_upstream;
|
||||
}
|
||||
|
||||
struct evbuffer * __output_buffer = bufferevent_get_output(bev);
|
||||
assert(__output_buffer != NULL);
|
||||
|
||||
if (*ref_peer_conn == NULL && evbuffer_get_length(__output_buffer) == 0)
|
||||
{
|
||||
__conn_private_destory(*ref_this_conn);
|
||||
*ref_this_conn = NULL;
|
||||
}
|
||||
|
||||
if (*ref_peer_conn == NULL && *ref_this_conn == NULL)
|
||||
{
|
||||
tfe_stream_destory(_stream);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void __stream_bev_passthrough_eventcb(struct bufferevent * bev, short events, void * arg)
|
||||
{
|
||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||
struct tfe_conn_private ** ref_this_conn{};
|
||||
struct tfe_conn_private ** ref_peer_conn{};
|
||||
|
||||
if (__BEV_DIR(_stream, bev) == CONN_DIR_UPSTREAM)
|
||||
{
|
||||
ref_this_conn = &_stream->conn_upstream;
|
||||
ref_peer_conn = &_stream->conn_downstream;
|
||||
}
|
||||
|
||||
if (__BEV_DIR(_stream, bev) == CONN_DIR_DOWNSTREAM)
|
||||
{
|
||||
ref_this_conn = &_stream->conn_downstream;
|
||||
ref_peer_conn = &_stream->conn_upstream;
|
||||
}
|
||||
|
||||
if (events & BEV_EVENT_ERROR || events & BEV_EVENT_EOF)
|
||||
{
|
||||
if (evbuffer_get_length(bufferevent_get_input(bev)))
|
||||
{
|
||||
__stream_bev_passthrough_readcb(bev, arg);
|
||||
}
|
||||
|
||||
goto __close_connection;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
__close_connection:
|
||||
if (*ref_peer_conn != NULL)
|
||||
{
|
||||
struct bufferevent * __peer_bev = (*ref_peer_conn)->bev;
|
||||
struct evbuffer * __peer_output_buffer = bufferevent_get_output(__peer_bev);
|
||||
|
||||
if (evbuffer_get_length(__peer_output_buffer) == 0)
|
||||
{
|
||||
__conn_private_destory(*ref_peer_conn);
|
||||
*ref_peer_conn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (*ref_this_conn != NULL)
|
||||
{
|
||||
__conn_private_destory(*ref_this_conn);
|
||||
*ref_this_conn = NULL;
|
||||
}
|
||||
|
||||
if (*ref_this_conn == NULL && *ref_peer_conn == NULL)
|
||||
{
|
||||
tfe_stream_destory(_stream);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for read events on the up- and downstream connection bufferevents.
|
||||
* Called when there is data ready in the input evbuffer.
|
||||
*/
|
||||
|
||||
static void tfe_stream_readcb(struct bufferevent * bev, void * arg)
|
||||
static void __stream_bev_readcb(struct bufferevent * bev, void * arg)
|
||||
{
|
||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||
enum tfe_conn_dir dir = __DIR(_stream, bev);
|
||||
enum tfe_conn_dir dir = __BEV_DIR(_stream, bev);
|
||||
struct tfe_conn_private * this_conn = __THIS_CONN(_stream, dir);
|
||||
struct tfe_conn_private * peer_conn = __PEER_CONN(_stream, dir);
|
||||
|
||||
@@ -235,10 +369,10 @@ static void tfe_stream_readcb(struct bufferevent * bev, void * arg)
|
||||
* Called when either all data from the output evbuffer has been written,
|
||||
* or if the outbuf is only half full again after having been full.
|
||||
*/
|
||||
static void tfe_stream_writecb(struct bufferevent * bev, void * arg)
|
||||
static void __stream_bev_writecb(struct bufferevent * bev, void * arg)
|
||||
{
|
||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||
enum tfe_conn_dir dir = __DIR(_stream, bev);
|
||||
enum tfe_conn_dir dir = __BEV_DIR(_stream, bev);
|
||||
struct tfe_conn_private * this_conn = __THIS_CONN(_stream, dir);
|
||||
struct tfe_conn_private * peer_conn = __PEER_CONN(_stream, dir);
|
||||
|
||||
@@ -257,10 +391,10 @@ static void tfe_stream_writecb(struct bufferevent * bev, void * arg)
|
||||
* Callback for meta events on the up- and downstream connection bufferevents.
|
||||
* Called when EOF has been reached, a connection has been made, and on errors.
|
||||
*/
|
||||
static void tfe_stream_eventcb(struct bufferevent * bev, short events, void * arg)
|
||||
static void __stream_bev_eventcb(struct bufferevent * bev, short events, void * arg)
|
||||
{
|
||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||
enum tfe_conn_dir dir = __DIR(_stream, bev);
|
||||
enum tfe_conn_dir dir = __BEV_DIR(_stream, bev);
|
||||
struct tfe_conn_private * this_conn = __THIS_CONN(_stream, dir);
|
||||
struct tfe_conn_private * peer_conn = __PEER_CONN(_stream, dir);
|
||||
|
||||
@@ -279,9 +413,10 @@ static void tfe_stream_eventcb(struct bufferevent * bev, short events, void * ar
|
||||
if (events & BEV_EVENT_EOF)
|
||||
{
|
||||
//generate a 0 size read callback to notify plugins.
|
||||
tfe_stream_readcb(bev, arg);
|
||||
__stream_bev_readcb(bev, arg);
|
||||
this_conn->closed = 1;
|
||||
}
|
||||
|
||||
if (peer_conn->closed == 1 && this_conn->closed == 1)
|
||||
{
|
||||
reason = REASON_PASSIVE_CLOSED;
|
||||
@@ -315,7 +450,17 @@ static tfe_conn_private * __conn_private_create(struct tfe_stream_private * stre
|
||||
goto __errout;
|
||||
}
|
||||
|
||||
bufferevent_setcb(__conn_private->bev, tfe_stream_readcb, tfe_stream_writecb, tfe_stream_eventcb, stream);
|
||||
if (stream->passthough)
|
||||
{
|
||||
bufferevent_setcb(__conn_private->bev, __stream_bev_passthrough_readcb,
|
||||
__stream_bev_passthrough_writecb, __stream_bev_passthrough_eventcb, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferevent_setcb(__conn_private->bev, __stream_bev_readcb,
|
||||
__stream_bev_writecb, __stream_bev_eventcb, stream);
|
||||
}
|
||||
|
||||
bufferevent_enable(__conn_private->bev, EV_READ | EV_WRITE);
|
||||
return __conn_private;
|
||||
|
||||
@@ -324,28 +469,7 @@ __errout:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static tfe_conn_private * __conn_private_create(struct tfe_stream_private * stream, struct bufferevent * bev)
|
||||
{
|
||||
struct tfe_conn_private * __conn_private = ALLOC(struct tfe_conn_private, 1);
|
||||
__conn_private->bev = bev;
|
||||
__conn_private->fd = bufferevent_getfd(bev);
|
||||
|
||||
bufferevent_setcb(__conn_private->bev, tfe_stream_readcb, tfe_stream_writecb, tfe_stream_eventcb, stream);
|
||||
bufferevent_enable(__conn_private->bev, EV_READ | EV_WRITE);
|
||||
return __conn_private;
|
||||
}
|
||||
|
||||
evutil_socket_t __conn_private_release_fd(struct tfe_conn_private * conn)
|
||||
{
|
||||
evutil_socket_t __to_release_fd = conn->fd;
|
||||
conn->fd = 0;
|
||||
return __to_release_fd;
|
||||
}
|
||||
|
||||
static void __conn_private_destory(struct tfe_conn_private * conn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void ssl_downstream_create_on_success(future_result_t * result, void * user)
|
||||
{
|
||||
@@ -458,13 +582,18 @@ void tfe_stream_destory(struct tfe_stream_private * stream)
|
||||
thread->load--;
|
||||
}
|
||||
|
||||
void tfe_stream_init_by_fds(struct tfe_stream * stream, enum tfe_session_proto session_type,
|
||||
evutil_socket_t fd_downstream, evutil_socket_t fd_upstream)
|
||||
void tfe_stream_init_by_fds(struct tfe_stream * stream, evutil_socket_t fd_downstream, evutil_socket_t fd_upstream)
|
||||
{
|
||||
struct tfe_stream_private * _stream = container_of(stream, struct tfe_stream_private, head);
|
||||
struct event_base * ev_base = _stream->thread_ref->evbase;
|
||||
|
||||
if (session_type == SESSION_PROTO_PLAIN)
|
||||
_stream->defer_fd_downstream = fd_downstream;
|
||||
_stream->defer_fd_upstream = fd_upstream;
|
||||
|
||||
evutil_make_socket_nonblocking(fd_downstream);
|
||||
evutil_make_socket_nonblocking(fd_upstream);
|
||||
|
||||
if (_stream->session_type == SESSION_PROTO_PLAIN)
|
||||
{
|
||||
_stream->conn_downstream = __conn_private_create(_stream, fd_downstream);
|
||||
_stream->conn_upstream = __conn_private_create(_stream, fd_upstream);
|
||||
@@ -473,7 +602,7 @@ void tfe_stream_init_by_fds(struct tfe_stream * stream, enum tfe_session_proto s
|
||||
assert(_stream->conn_upstream != NULL);
|
||||
}
|
||||
|
||||
if (session_type == SESSION_PROTO_SSL)
|
||||
if (_stream->session_type == SESSION_PROTO_SSL)
|
||||
{
|
||||
_stream->ssl_mgr = _stream->proxy_ref->ssl_mgr_handler;
|
||||
|
||||
@@ -483,10 +612,26 @@ void tfe_stream_init_by_fds(struct tfe_stream * stream, enum tfe_session_proto s
|
||||
/* Defer setup conn_downstream & conn_upstream in async callbacks. */
|
||||
ssl_async_upstream_create(_stream->future_upstream_create,
|
||||
_stream->ssl_mgr, fd_upstream, fd_downstream, ev_base);
|
||||
|
||||
_stream->defer_fd_downstream = fd_downstream;
|
||||
_stream->defer_fd_upstream = fd_upstream;
|
||||
}
|
||||
|
||||
_stream->session_type = session_type;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int tfe_stream_option_set(struct tfe_stream * stream, enum tfe_stream_option opt, const void * arg, size_t sz_arg)
|
||||
{
|
||||
struct tfe_stream_private * _stream = container_of(stream, struct tfe_stream_private, head);
|
||||
|
||||
if (opt == TFE_STREAM_OPT_SESSION_TYPE)
|
||||
{
|
||||
assert(sz_arg == sizeof(enum tfe_session_proto));
|
||||
_stream->session_type = *(enum tfe_session_proto *)arg;
|
||||
}
|
||||
else if (opt == TFE_STREAM_OPT_PASSTHROUGH)
|
||||
{
|
||||
assert(sz_arg == sizeof(bool));
|
||||
_stream->passthough = *(bool *)arg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user