|
|
|
|
@@ -61,7 +61,17 @@ static inline struct tfe_conn_private * __peer_conn(struct tfe_stream_private *
|
|
|
|
|
|
|
|
|
|
static inline enum tfe_conn_dir __bev_dir(struct tfe_stream_private * _stream, struct bufferevent * bev)
|
|
|
|
|
{
|
|
|
|
|
return ((bev == _stream->conn_downstream->bev) ? CONN_DIR_DOWNSTREAM : CONN_DIR_UPSTREAM);
|
|
|
|
|
if (_stream->conn_downstream && bev == _stream->conn_downstream->bev)
|
|
|
|
|
{
|
|
|
|
|
return CONN_DIR_DOWNSTREAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(_stream->conn_upstream && bev == _stream->conn_upstream->bev)
|
|
|
|
|
{
|
|
|
|
|
return CONN_DIR_UPSTREAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool __is_ssl(struct tfe_stream_private * _stream)
|
|
|
|
|
@@ -194,6 +204,15 @@ static void __conn_private_destory(struct tfe_conn_private * conn)
|
|
|
|
|
free(conn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __conn_private_destory_with_ssl(struct event_base * ev_base,
|
|
|
|
|
struct tfe_conn_private * conn, struct ssl_stream * ssl_stream)
|
|
|
|
|
{
|
|
|
|
|
if (ssl_stream == NULL) return __conn_private_destory(conn);
|
|
|
|
|
evutil_socket_t __to_closed_fd = __conn_private_release_fd(conn);
|
|
|
|
|
ssl_stream_free_and_close_fd(ssl_stream, ev_base, __to_closed_fd);
|
|
|
|
|
return __conn_private_destory(conn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __stream_bev_passthrough_readcb(struct bufferevent * bev, void * arg)
|
|
|
|
|
{
|
|
|
|
|
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
|
|
|
|
@@ -313,15 +332,22 @@ static void __stream_bev_readcb(struct bufferevent * bev, void * arg)
|
|
|
|
|
enum tfe_conn_dir dir = __bev_dir(_stream, bev);
|
|
|
|
|
struct tfe_conn_private * peer_conn = __peer_conn(_stream, dir);
|
|
|
|
|
|
|
|
|
|
/* Peer connection is terminated, drain all data.
|
|
|
|
|
* This connection will be destoryed in __event_cb */
|
|
|
|
|
struct evbuffer * inbuf = bufferevent_get_input(bev);
|
|
|
|
|
if (peer_conn == NULL)
|
|
|
|
|
{
|
|
|
|
|
evbuffer_drain(inbuf, evbuffer_get_length(inbuf));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct evbuffer * outbuf = bufferevent_get_output(peer_conn->bev);
|
|
|
|
|
enum tfe_stream_action action_tmp = ACTION_FORWARD_DATA;
|
|
|
|
|
enum tfe_stream_action action_final = ACTION_FORWARD_DATA;
|
|
|
|
|
|
|
|
|
|
struct evbuffer * inbuf = bufferevent_get_input(bev);
|
|
|
|
|
struct evbuffer * outbuf = bufferevent_get_output(peer_conn->bev);
|
|
|
|
|
|
|
|
|
|
size_t drain_size = 0;
|
|
|
|
|
size_t contigous_len = evbuffer_get_length(inbuf);
|
|
|
|
|
const unsigned char * contiguous_data = (const unsigned char *) evbuffer_pullup(inbuf, contigous_len);
|
|
|
|
|
unsigned char * contiguous_data = evbuffer_pullup(inbuf, contigous_len);
|
|
|
|
|
|
|
|
|
|
_stream->defer_bytes = 0;
|
|
|
|
|
_stream->drop_bytes = 0;
|
|
|
|
|
@@ -395,19 +421,13 @@ static void __stream_bev_readcb(struct bufferevent * bev, void * arg)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (evbuffer_get_length(inbuf) != 0)
|
|
|
|
|
{
|
|
|
|
|
bufferevent_trigger(bev, EV_READ, BEV_OPT_DEFER_CALLBACKS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
if (evbuffer_get_length(outbuf) >= TFE_CONFIG_OUTPUT_LIMIT_DEFAULT)
|
|
|
|
|
{
|
|
|
|
|
bufferevent_setwatermark(peer_conn->bev, EV_WRITE,
|
|
|
|
|
TFE_CONFIG_OUTPUT_LIMIT_DEFAULT / 2, TFE_CONFIG_OUTPUT_LIMIT_DEFAULT);
|
|
|
|
|
bufferevent_setwatermark(peer_conn->bev, EV_WRITE, TFE_CONFIG_OUTPUT_LIMIT_DEFAULT / 2, TFE_CONFIG_OUTPUT_LIMIT_DEFAULT);
|
|
|
|
|
bufferevent_disable(bev, EV_READ);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -418,18 +438,42 @@ static void __stream_bev_readcb(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 = __bev_dir(_stream, bev);
|
|
|
|
|
struct tfe_conn_private * peer_conn = __peer_conn(_stream, dir);
|
|
|
|
|
struct event_base * ev_base = bufferevent_get_base(bev);
|
|
|
|
|
|
|
|
|
|
// struct evbuffer * outbuf = bufferevent_get_output(bev);
|
|
|
|
|
struct tfe_conn_private ** ref_this_conn{};
|
|
|
|
|
struct tfe_conn_private ** ref_peer_conn{};
|
|
|
|
|
struct ssl_stream ** ref_this_ssl_stream{};
|
|
|
|
|
|
|
|
|
|
if (peer_conn->bev && !(bufferevent_get_enabled(peer_conn->bev) & EV_READ))
|
|
|
|
|
if (__bev_dir(_stream, bev) == CONN_DIR_UPSTREAM)
|
|
|
|
|
{
|
|
|
|
|
/* data source temporarily disabled;
|
|
|
|
|
* re-enable and reset watermark to 0. */
|
|
|
|
|
bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
|
|
|
|
|
bufferevent_enable(peer_conn->bev, EV_READ);
|
|
|
|
|
ref_this_conn = &_stream->conn_upstream;
|
|
|
|
|
ref_peer_conn = &_stream->conn_downstream;
|
|
|
|
|
ref_this_ssl_stream = &_stream->ssl_downstream;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (__bev_dir(_stream, bev) == CONN_DIR_DOWNSTREAM)
|
|
|
|
|
{
|
|
|
|
|
ref_this_conn = &_stream->conn_downstream;
|
|
|
|
|
ref_peer_conn = &_stream->conn_upstream;
|
|
|
|
|
ref_this_ssl_stream = &_stream->ssl_downstream;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_with_ssl(ev_base, *ref_this_conn, *ref_this_ssl_stream);
|
|
|
|
|
*ref_this_conn = NULL;
|
|
|
|
|
*ref_this_ssl_stream = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*ref_peer_conn == NULL && *ref_this_conn == NULL)
|
|
|
|
|
{
|
|
|
|
|
tfe_stream_destory(_stream);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -439,50 +483,90 @@ static void __stream_bev_writecb(struct bufferevent * bev, 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 = __bev_dir(_stream, bev);
|
|
|
|
|
struct tfe_conn_private * this_conn = __this_conn(_stream, dir);
|
|
|
|
|
struct tfe_conn_private * peer_conn = __peer_conn(_stream, dir);
|
|
|
|
|
struct event_base * ev_base = bufferevent_get_base(bev);
|
|
|
|
|
|
|
|
|
|
const struct tfe_plugin * plugins = _stream->thread_ref->modules;
|
|
|
|
|
struct plugin_ctx * plug_ctx = NULL;
|
|
|
|
|
int plug_num = _stream->thread_ref->nr_modules, i = 0;
|
|
|
|
|
enum tfe_stream_close_reason reason = REASON_PASSIVE_CLOSED;
|
|
|
|
|
struct tfe_conn_private ** ref_this_conn{};
|
|
|
|
|
struct tfe_conn_private ** ref_peer_conn{};
|
|
|
|
|
struct ssl_stream ** ref_this_ssl_stream{};
|
|
|
|
|
struct ssl_stream ** ref_peer_ssl_stream{};
|
|
|
|
|
|
|
|
|
|
if (events & BEV_EVENT_ERROR)
|
|
|
|
|
if (__bev_dir(_stream, bev) == CONN_DIR_UPSTREAM)
|
|
|
|
|
{
|
|
|
|
|
this_conn->closed = 1;
|
|
|
|
|
reason = REASON_ERROR;
|
|
|
|
|
if (__is_ssl(_stream))
|
|
|
|
|
{
|
|
|
|
|
ssl_stream_log_error(bev, dir, __STREAM_LOGGER(_stream));
|
|
|
|
|
}
|
|
|
|
|
goto call_plugin_close;
|
|
|
|
|
ref_this_conn = &_stream->conn_upstream;
|
|
|
|
|
ref_peer_conn = &_stream->conn_downstream;
|
|
|
|
|
ref_this_ssl_stream = &_stream->ssl_upstream;
|
|
|
|
|
ref_peer_ssl_stream = &_stream->ssl_downstream;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (events & BEV_EVENT_EOF)
|
|
|
|
|
if (__bev_dir(_stream, bev) == CONN_DIR_DOWNSTREAM)
|
|
|
|
|
{
|
|
|
|
|
ref_this_conn = &_stream->conn_downstream;
|
|
|
|
|
ref_peer_conn = &_stream->conn_upstream;
|
|
|
|
|
ref_this_ssl_stream = &_stream->ssl_downstream;
|
|
|
|
|
ref_peer_ssl_stream = &_stream->ssl_upstream;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (events & BEV_EVENT_ERROR || events & BEV_EVENT_EOF)
|
|
|
|
|
{
|
|
|
|
|
if (evbuffer_get_length(bufferevent_get_input(bev)))
|
|
|
|
|
{
|
|
|
|
|
//generate a 0 size read callback to notify plugins.
|
|
|
|
|
__stream_bev_readcb(bev, arg);
|
|
|
|
|
this_conn->closed = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (peer_conn->closed == 1 && this_conn->closed == 1)
|
|
|
|
|
{
|
|
|
|
|
reason = REASON_PASSIVE_CLOSED;
|
|
|
|
|
goto call_plugin_close;
|
|
|
|
|
goto __close_connection;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
call_plugin_close:
|
|
|
|
|
for (i = 0; i < plug_num; i++)
|
|
|
|
|
__close_connection:
|
|
|
|
|
if (*ref_peer_conn != NULL)
|
|
|
|
|
{
|
|
|
|
|
_stream->calling_idx = i;
|
|
|
|
|
plug_ctx = _stream->plugin_ctxs + i;
|
|
|
|
|
plugins[i].on_close(&(_stream->head), _stream->thread_ref->thread_id, reason, &(plug_ctx->pme));
|
|
|
|
|
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_with_ssl(ev_base, *ref_peer_conn, *ref_peer_ssl_stream);
|
|
|
|
|
*ref_peer_conn = NULL;
|
|
|
|
|
*ref_peer_ssl_stream = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*ref_this_conn != NULL)
|
|
|
|
|
{
|
|
|
|
|
__conn_private_destory_with_ssl(ev_base, *ref_this_conn, *ref_this_ssl_stream);
|
|
|
|
|
*ref_this_conn = NULL;
|
|
|
|
|
*ref_this_ssl_stream = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*ref_this_conn == NULL && *ref_peer_conn == NULL)
|
|
|
|
|
{
|
|
|
|
|
goto __call_plugin_close;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
__call_plugin_close:
|
|
|
|
|
unsigned int plugin_id_iter = 0;
|
|
|
|
|
unsigned int plugin_id = 0;
|
|
|
|
|
|
|
|
|
|
for (const struct tfe_plugin * p_info_iter = tfe_plugin_iterate(&plugin_id_iter);
|
|
|
|
|
p_info_iter != NULL; p_info_iter = tfe_plugin_iterate(&plugin_id_iter))
|
|
|
|
|
{
|
|
|
|
|
_stream->calling_idx = plugin_id;
|
|
|
|
|
struct plugin_ctx * plug_ctx = &_stream->plugin_ctxs[plugin_id];
|
|
|
|
|
|
|
|
|
|
//TODO: do not use pme to determinate we call on_open or not ever.
|
|
|
|
|
if (p_info_iter->on_close && plug_ctx->pme != NULL)
|
|
|
|
|
{
|
|
|
|
|
p_info_iter->on_close(&_stream->head, _stream->thread_ref->thread_id,
|
|
|
|
|
REASON_PASSIVE_CLOSED, &(plug_ctx->pme));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
plugin_id++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tfe_stream_destory(_stream);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static tfe_conn_private * __conn_private_create_by_fd(struct tfe_stream_private * stream, evutil_socket_t fd)
|
|
|
|
|
@@ -583,17 +667,30 @@ struct tfe_stream * tfe_stream_create(struct tfe_proxy * pxy, struct tfe_thread_
|
|
|
|
|
struct tfe_stream_private * _stream = ALLOC(struct tfe_stream_private, 1);
|
|
|
|
|
_stream->thread_ref = thread_ctx;
|
|
|
|
|
_stream->proxy_ref = pxy;
|
|
|
|
|
_stream->stream_logger = pxy->logger;
|
|
|
|
|
|
|
|
|
|
unsigned int total_plugin_count = tfe_plugin_total_counts();
|
|
|
|
|
_stream->plugin_ctxs = ALLOC(struct plugin_ctx, total_plugin_count);
|
|
|
|
|
return (struct tfe_stream *) &_stream->head;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __stream_access_log_write(struct tfe_stream_private * stream)
|
|
|
|
|
{
|
|
|
|
|
MESA_handle_runtime_log(stream->stream_logger, RLOG_LV_INFO, "access", "%s", stream->str_stream_addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tfe_stream_destory(struct tfe_stream_private * stream)
|
|
|
|
|
{
|
|
|
|
|
struct tfe_thread_ctx * thread = stream->thread_ref;
|
|
|
|
|
struct event_base * ev_base = thread->evbase;
|
|
|
|
|
|
|
|
|
|
__stream_access_log_write(stream);
|
|
|
|
|
|
|
|
|
|
if (stream->str_stream_addr)
|
|
|
|
|
{
|
|
|
|
|
free(stream->str_stream_addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (__is_ssl(stream) && stream->ssl_upstream)
|
|
|
|
|
{
|
|
|
|
|
evutil_socket_t __to_closed_fd = __conn_private_release_fd(stream->conn_upstream);
|
|
|
|
|
@@ -673,8 +770,8 @@ static struct tfe_stream_addr * __stream_addr_create_by_fds(struct tfe_stream *
|
|
|
|
|
sizeof(struct tfe_stream_addr) + sizeof(struct tfe_stream_addr_tuple4_v4));
|
|
|
|
|
|
|
|
|
|
struct tfe_stream_addr_ipv4 * st_addr_v4 = __stream_addr->ipv4;
|
|
|
|
|
struct sockaddr_in * sk_v4_src_ptr = (struct sockaddr_in *)sk_src_ptr;
|
|
|
|
|
struct sockaddr_in * sk_v4_dst_ptr = (struct sockaddr_in *)sk_dst_ptr;
|
|
|
|
|
struct sockaddr_in * sk_v4_src_ptr = (struct sockaddr_in *) sk_src_ptr;
|
|
|
|
|
struct sockaddr_in * sk_v4_dst_ptr = (struct sockaddr_in *) sk_dst_ptr;
|
|
|
|
|
|
|
|
|
|
__stream_addr->addrtype = TFE_ADDR_STREAM_TUPLE4_V4;
|
|
|
|
|
__stream_addr->addrlen = sizeof(struct tfe_stream_addr_tuple4_v4);
|
|
|
|
|
@@ -691,7 +788,8 @@ static struct tfe_stream_addr * __stream_addr_create_by_fds(struct tfe_stream *
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
TFE_STREAM_LOG_ERROR(stream, "Invalid sockaddr family for fd %d: sa_family is %d.",
|
|
|
|
|
fd_downstream, sk_src_ptr->sa_family); goto __errout;
|
|
|
|
|
fd_downstream, sk_src_ptr->sa_family);
|
|
|
|
|
goto __errout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return __stream_addr;
|
|
|
|
|
@@ -713,7 +811,9 @@ void tfe_stream_init_by_fds(struct tfe_stream * stream, evutil_socket_t fd_downs
|
|
|
|
|
evutil_make_socket_nonblocking(fd_upstream);
|
|
|
|
|
|
|
|
|
|
_stream->head.addr = __stream_addr_create_by_fds(stream, fd_downstream);
|
|
|
|
|
if(unlikely(_stream->head.addr == NULL))
|
|
|
|
|
_stream->str_stream_addr = tfe_stream_addr_to_str(_stream->head.addr);
|
|
|
|
|
|
|
|
|
|
if (unlikely(_stream->head.addr == NULL))
|
|
|
|
|
{
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
@@ -762,3 +862,17 @@ int tfe_stream_option_set(struct tfe_stream * stream, enum tfe_stream_option opt
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tfe_stream_write_log(const struct tfe_stream * stream, int level, const char * fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list arg_ptr;
|
|
|
|
|
va_start(arg_ptr, fmt);
|
|
|
|
|
struct tfe_stream_private * _stream = container_of(stream, struct tfe_stream_private, head);
|
|
|
|
|
|
|
|
|
|
/* Format input content */
|
|
|
|
|
char __tmp_buffer[TFE_STRING_MAX];
|
|
|
|
|
vsnprintf(__tmp_buffer, sizeof(__tmp_buffer), fmt, arg_ptr);
|
|
|
|
|
|
|
|
|
|
/* Log content with stream tag */
|
|
|
|
|
MESA_handle_runtime_log(_stream->stream_logger, level, "S-DETAIL", "%s %s", _stream->str_stream_addr, __tmp_buffer);
|
|
|
|
|
}
|
|
|
|
|
|