diff --git a/proxy.c b/proxy.c index fe35537..3c7f238 100644 --- a/proxy.c +++ b/proxy.c @@ -129,7 +129,7 @@ pxy_conn_meta_ctx_new() ctx->uuid = malloc(sizeof(uuid_t)); -// @todo Set this switch during compile time +// @todo Set this switch at compile time #ifdef OPENBSD uuid_create(ctx->uuid, NULL); char *uuid_str; diff --git a/pxyconn.c b/pxyconn.c index d15134f..da9e960 100644 --- a/pxyconn.c +++ b/pxyconn.c @@ -285,7 +285,7 @@ pxy_conn_ctx_free_child(pxy_conn_ctx_t *ctx) (void*)ctx); } #endif /* DEBUG_PROXY */ - pxy_thrmgr_detach_e2(ctx->thrmgr, ctx->thridx, ctx->mctx); + pxy_thrmgr_detach_child(ctx->thrmgr, ctx->thridx, ctx->mctx); if (ctx->srchost_str) { free(ctx->srchost_str); @@ -354,7 +354,7 @@ pxy_conn_ctx_free_child(pxy_conn_ctx_t *ctx) log_err_printf("Warning: Content log close failed\n"); } } - ctx->child_info->freed = 1; +// ctx->child_info->freed = 1; free(ctx); } @@ -1236,6 +1236,7 @@ bufferevent_free_and_close_fd(struct bufferevent *bev, pxy_conn_ctx_t *ctx) } #endif /* DEBUG_PROXY */ +// bufferevent_setcb(bev, NULL, NULL, NULL, NULL); bufferevent_free(bev); /* does not free SSL unless the option BEV_OPT_CLOSE_ON_FREE was set */ if (ssl) { @@ -1266,6 +1267,7 @@ bufferevent_free_and_close_fd_nonssl(struct bufferevent *bev, pxy_conn_ctx_t *ct } #endif /* DEBUG_PROXY */ +// bufferevent_setcb(bev, NULL, NULL, NULL, NULL); bufferevent_free(bev); /* does not free SSL unless the option BEV_OPT_CLOSE_ON_FREE was set */ if (evutil_closesocket(fd) == -1) { @@ -1805,16 +1807,13 @@ pxy_conn_is_ready_to_free(pxy_conn_ctx_t *ctx) } // Start of decisions - if (src_closed && !src_inbuf_empty && !e2src_closed && src->bev && e2src->bev) { + if (!src_inbuf_empty && !e2src_closed) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free: src_closed && !src_inbuf_empty && !e2src_closed fd=%d\n", ctx->fd); - struct evbuffer *src_inbuf = bufferevent_get_input(src->bev); - struct evbuffer *e2src_outbuf = bufferevent_get_output(e2src->bev); -// evbuffer_add_buffer(e2src_outbuf, src_inbuf); pxy_bev_readcb(src->bev, ctx); goto not_ready; } - if (e2src_closed && !e2src_inbuf_empty && !src_closed) { + if (!e2src_inbuf_empty && !src_closed) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free: e2src_closed && !e2src_inbuf_empty && !src_closed fd=%d\n", ctx->fd); struct evbuffer *e2src_inbuf = bufferevent_get_input(e2src->bev); struct evbuffer *src_outbuf = bufferevent_get_output(src->bev); @@ -1891,12 +1890,17 @@ pxy_conn_is_ready_to_free_child(pxy_conn_ctx_t *ctx) int dst_closed = ctx->dst.closed; - pxy_conn_desc_t *dst = &ctx->dst; - struct evbuffer *dst_inbuf = bufferevent_get_input(dst->bev); - int dst_inbuf_empty = evbuffer_get_length(dst_inbuf) == 0; + int dst_inbuf_empty = 1; + int dst_outbuf_empty = 1; - struct evbuffer *dst_outbuf = bufferevent_get_output(dst->bev); - int dst_outbuf_empty = evbuffer_get_length(dst_outbuf) == 0; + pxy_conn_desc_t *dst = &ctx->dst; + if (dst->bev) { + struct evbuffer *dst_inbuf = bufferevent_get_input(dst->bev); + dst_inbuf_empty = evbuffer_get_length(dst_inbuf) == 0; + + struct evbuffer *dst_outbuf = bufferevent_get_output(dst->bev); + dst_outbuf_empty = evbuffer_get_length(dst_outbuf) == 0; + } if (!e2_closed) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: e2_closed NOT CLOSED fd=%d\n", ctx->fd); @@ -1925,16 +1929,13 @@ pxy_conn_is_ready_to_free_child(pxy_conn_ctx_t *ctx) pxy_conn_ctx_t *parent_ctx = parent_ctx = ctx->mctx->parent_ctx; // Start of decisions - if ((e2_closed || !parent_ctx) && !e2_inbuf_empty && !dst_closed) { + if (!e2_inbuf_empty && !dst_closed) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: (e2_closed || !parent_ctx) && !e2_inbuf_empty && !dst_closed fd=%d\n", ctx->fd); - struct evbuffer *e2dst_inbuf = bufferevent_get_input(e2dst->bev); - struct evbuffer *dst_outbuf = bufferevent_get_output(dst->bev); -// evbuffer_add_buffer(dst_outbuf, e2dst_inbuf); pxy_bev_readcb_child(e2dst->bev, ctx); goto not_ready; } - if ((dst_closed || !parent_ctx) && !dst_inbuf_empty && !e2_closed) { + if (!dst_inbuf_empty && !e2_closed) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: (dst_closed || !parent_ctx) && !dst_inbuf_empty && !e2_closed fd=%d\n", ctx->fd); struct evbuffer *dst_inbuf = bufferevent_get_input(dst->bev); struct evbuffer *e2dst_outbuf = bufferevent_get_output(e2dst->bev); @@ -1947,11 +1948,16 @@ pxy_conn_is_ready_to_free_child(pxy_conn_ctx_t *ctx) goto not_ready; } - if ((e2_closed && dst_closed) || (e2_closed && dst_outbuf_empty) || (dst_closed && e2_outbuf_empty) || !parent_ctx) { + if ((e2_closed && dst_closed) || (e2_closed && dst_outbuf_empty) || (dst_closed && e2_outbuf_empty)) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: other conditions fd=%d\n", ctx->fd); goto ready; } + if (!parent_ctx) { + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: parent NULL fd=%d\n", ctx->fd); + goto ready; + } + not_ready: log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: EXIT NOT READY, fd=%d\n", ctx->fd); return 0; @@ -1971,14 +1977,18 @@ ready: } } - if (!dst_inbuf_empty) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: dst_inbuf DRAIN fd=%d\n", ctx->fd); - evbuffer_drain(dst_inbuf, evbuffer_get_length(dst_inbuf)); - } - - if (!dst_outbuf_empty) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: dst_outbuf DRAIN fd=%d\n", ctx->fd); - evbuffer_drain(dst_outbuf, evbuffer_get_length(dst_outbuf)); + if (dst->bev) { + if (!dst_inbuf_empty) { + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: dst_inbuf DRAIN fd=%d\n", ctx->fd); + struct evbuffer *dst_inbuf = bufferevent_get_input(dst->bev); + evbuffer_drain(dst_inbuf, evbuffer_get_length(dst_inbuf)); + } + + if (!dst_outbuf_empty) { + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: dst_outbuf DRAIN fd=%d\n", ctx->fd); + struct evbuffer *dst_outbuf = bufferevent_get_output(dst->bev); + evbuffer_drain(dst_outbuf, evbuffer_get_length(dst_outbuf)); + } } log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pxy_conn_is_ready_to_free_child: EXIT READY, fd=%d\n", ctx->fd); @@ -1986,9 +1996,10 @@ ready: } static int -pxy_conn_free(pxy_conn_ctx_t *); +pxy_conn_free(pxy_conn_ctx_t *, int); -void remove_child_ctx(pxy_conn_ctx_t *child_ctx, pxy_conn_ctx_t **head) { +static void +remove_child_ctx(pxy_conn_ctx_t *child_ctx, pxy_conn_ctx_t **head) { if (child_ctx->fd == (*head)->fd) { *head = (*head)->next_child_ctx; return; @@ -2007,8 +2018,33 @@ void remove_child_ctx(pxy_conn_ctx_t *child_ctx, pxy_conn_ctx_t **head) { return; } +static void +remove_child_info(pxy_conn_child_info_t *node, pxy_conn_child_info_t **head) +{ + assert(node != NULL); + assert(*head != NULL); + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> remove_child_info: DELETING, child_idx=%d --------------------------------------------------------------------------------------<<<\n", node->child_idx); + + if (node->child_idx == (*head)->child_idx) { + *head = (*head)->next; + return; + } + + pxy_conn_child_info_t *current = (*head)->next; + pxy_conn_child_info_t *previous = *head; + while (current != NULL && previous != NULL) { + if (node->child_idx == current->child_idx) { + previous->next = current->next; + return; + } + previous = current; + current = current->next; + } + return; +} + static int -pxy_conn_free_child(pxy_conn_ctx_t *ctx, int free) +pxy_conn_free_child(pxy_conn_ctx_t *ctx, int force) { assert(ctx != NULL); assert(ctx->mctx != NULL); @@ -2016,12 +2052,12 @@ pxy_conn_free_child(pxy_conn_ctx_t *ctx, int free) log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: ENTER\n"); evutil_socket_t fd = ctx->fd; - // @attention Get the parent ctx pointer now, because we may need to free it after freeing ctx - pxy_conn_ctx_t *parent_ctx = ctx->mctx->parent_ctx; + // @attention Get the mctx pointer now, because we cannot get it after freeing ctx + proxy_conn_meta_ctx_t *mctx = ctx->mctx; - evutil_socket_t pfd = parent_ctx ? parent_ctx->fd : -1; + evutil_socket_t pfd = mctx->parent_ctx ? mctx->parent_ctx->fd : -1; - if (pxy_conn_is_ready_to_free_child(ctx) || free) { + if (force || pxy_conn_is_ready_to_free_child(ctx)) { pxy_conn_desc_t *dst = &ctx->dst; if (dst->bev) { log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free_child: evutil_closesocket dst->bev, fd=%d\n", bufferevent_getfd(dst->bev)); @@ -2038,43 +2074,52 @@ pxy_conn_free_child(pxy_conn_ctx_t *ctx, int free) int rv = 1; log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: remove_node\n"); - remove_child_ctx(ctx, &ctx->mctx->child_list); + remove_child_ctx(ctx, &mctx->child_list); + remove_child_info(ctx->child_info, &mctx->child_info_list); + free(ctx->child_info); - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: CHECKING\n"); - pxy_conn_ctx_t *current_child_ctx = ctx->mctx->child_list; - while (current_child_ctx) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free_child: NOT NULL CHILD, fd=%d\n", current_child_ctx->fd); - current_child_ctx = current_child_ctx->next_child_ctx; + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: FREEING CTX, fd=%d, parent fd=%d\n", fd, pfd); + pxy_conn_ctx_free_child(ctx); + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free_child: FREED CTX, fd=%d, parent fd=%d\n", fd, pfd); + +// // @attention Free the parent ctx asap, we need its fds +// if (mctx->parent_ctx) { +// log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free_child: TRY freeing parent, fd=%d, parent fd=%d\n", fd, pfd); +// if (pxy_conn_free(mctx->parent_ctx, 0)) { +// log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: FREE parent SUCCESS, fd=%d, parent fd=%d\n", fd, pfd); +// } +// } + + if (!mctx->parent_ctx) { + // @attention Free the child ctxs asap, we need their fds + pxy_conn_ctx_t *child_ctx = mctx->child_list; +// while (child_ctx) { +// pxy_conn_ctx_t *next = child_ctx->next_child_ctx; +// // @attention Force freeing child +// if (pxy_conn_free_child(child_ctx, 1)) { +// log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: FREE child SUCCESS, pfd=%d, fd2=%d, cfd=%d\n", pfd, mctx->child_fd, fd); +// } +// child_ctx = next; +// } + if (child_ctx) { + if (pxy_conn_free_child(child_ctx, 1)) { + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: FREE child SUCCESS, pfd=%d, fd2=%d, cfd=%d\n", pfd, mctx->child_fd, fd); + } + } } - if (!ctx->mctx->parent_ctx && !ctx->mctx->child_list) { - if (ctx->mctx->child_evcl) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free_child: FREEING evcl2, pfd=%d, fd2=%d, cfd=%d\n", pfd, ctx->mctx->child_fd, fd); - // @todo Should we use evconnlistener_get_fd() instead of ctx->mctx->fd2? - //evutil_closesocket(evconnlistener_get_fd(ctx->mctx->evcl2)); - evconnlistener_free(ctx->mctx->child_evcl); - evutil_closesocket(ctx->mctx->child_fd); + if (!mctx->parent_ctx && !mctx->child_list) { + if (mctx->child_evcl) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free_child: FREEING evcl2, pfd=%d, fd2=%d, cfd=%d\n", pfd, mctx->child_fd, fd); + // @attention evconnlistener was created with LEV_OPT_CLOSE_ON_FREE, so do not close its socket again, otherwise causes "Bad file descriptor" errors + evconnlistener_free(mctx->child_evcl); + mctx->child_evcl = NULL; } log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free_child: RELEASING META CTX, fd=%d, parent fd=%d\n", fd, pfd); rv = 2; } else { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free_child: CANNOT FREE evcl2, pfd=%d, fd2=%d, cfd=%d\n", pfd, ctx->mctx->child_fd, fd); - } - - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: FREEING CTX, fd=%d, parent fd=%d\n", fd, pfd); - - pxy_conn_ctx_free_child(ctx); - - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free_child: FREED CTX, fd=%d, parent fd=%d\n", fd, pfd); - - // @attention Free the parent ctx asap, we need its fds - if (parent_ctx) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free_child: RETRY freeing parent, fd=%d, parent fd=%d\n", fd, pfd); - rv = pxy_conn_free(parent_ctx); - if (rv) { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free_child: FREE parent SUCCESS, fd=%d, parent fd=%d\n", fd, pfd); - } + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free_child: CANNOT FREE META CTX, pfd=%d, fd2=%d, cfd=%d\n", pfd, mctx->child_fd, fd); } return rv; } else { @@ -2084,7 +2129,7 @@ pxy_conn_free_child(pxy_conn_ctx_t *ctx, int free) } static int -pxy_conn_free(pxy_conn_ctx_t *ctx) +pxy_conn_free(pxy_conn_ctx_t *ctx, int force) { assert(ctx != NULL); assert(ctx->mctx != NULL); @@ -2092,30 +2137,22 @@ pxy_conn_free(pxy_conn_ctx_t *ctx) proxy_conn_meta_ctx_t *mctx = ctx->mctx; evutil_socket_t fd = ctx->fd; - evutil_socket_t cfd = ctx->mctx->child_list ? ctx->mctx->child_list->fd : -1; + evutil_socket_t cfd = mctx->child_list ? mctx->child_list->fd : -1; - if (pxy_conn_is_ready_to_free(ctx)) { - - // @todo Should we try to free child ctxs, or should they be cleaned up by the expired conns list? - // @attention Do not check if the parent is init yet, because we may be cleaning up due to timeout, i.e. timeouts should disregard init flag - pxy_conn_ctx_t *child_ctx = ctx->mctx->child_list; - while (child_ctx) { - pxy_conn_ctx_t *next = child_ctx->next_child_ctx; - if (pxy_conn_free_child(child_ctx, 0)) { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free: FREE child SUCCESS, fd=%d, child fd=%d\n", fd, cfd); - } - child_ctx = next; - } + if (force || pxy_conn_is_ready_to_free(ctx)) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free: TRY FREE ctx->src\n"); pxy_conn_desc_t *src = &ctx->src; - if (src->bev) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free: bufferevent_free_and_close_fd src->bev, fd=%d\n", bufferevent_getfd(src->bev)); - bufferevent_free_and_close_fd(src->bev, ctx); - src->bev = NULL; - } else { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free: evutil_closesocket on NULL src->bev, fd=%d\n", fd); - evutil_closesocket(fd); + if (!src->closed) { + if (src->bev) { + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free: bufferevent_free_and_close_fd src->bev, fd=%d\n", bufferevent_getfd(src->bev)); + bufferevent_free_and_close_fd(src->bev, ctx); + src->bev = NULL; + } else { + // @todo src fd may be open, although src.bev is NULL, where do we close the src fd? + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free: evutil_closesocket on NULL src->bev, fd=%d\n", fd); + evutil_closesocket(fd); + } } pxy_conn_desc_t *dst = &ctx->dst; @@ -2133,36 +2170,44 @@ pxy_conn_free(pxy_conn_ctx_t *ctx) } int rv = 1; - ctx->mctx->parent_ctx = NULL; - if (!ctx->mctx->child_list) { - if (ctx->mctx->child_evcl) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free: FREEING evcl2, pfd=%d, fd2=%d, cfd=%d\n", fd, ctx->mctx->child_fd, cfd); - evconnlistener_free(ctx->mctx->child_evcl); - evutil_closesocket(ctx->mctx->child_fd); - } - - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free: RELEASING META CTX, fd=%d, child fd=%d\n", fd, cfd); - rv = 2; - } else { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free: CANNOT FREE evcl2, pfd=%d, fd2=%d, cfd=%d\n", fd, ctx->mctx->child_fd, cfd); - } + mctx->parent_ctx = NULL; log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free: FREEING ctx, fd=%d, child fd=%d\n", fd, cfd); pxy_conn_ctx_free(ctx); log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free: FREED CTX, fd=%d, child fd=%d\n", fd, cfd); + // @todo Should we try to free child ctxs, or should they be cleaned up by the expired conns list? + // @attention Do not check if the parent is init yet, because we may be cleaning up due to timeout, i.e. timeouts should disregard init flag // @attention Free the child ctxs asap, we need their fds - child_ctx = mctx->child_list; + pxy_conn_ctx_t *child_ctx = mctx->child_list; +// while (child_ctx) { +// pxy_conn_ctx_t *next = child_ctx->next_child_ctx; +// // @attention Force freeing child +// if (pxy_conn_free_child(child_ctx, 1)) { +// log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free: FREE child SUCCESS, fd=%d, child fd=%d\n", fd, cfd); +// } +// child_ctx = next; +// } if (child_ctx) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free: RETRY freeing children, fd=%d, child fd=%d\n", fd, cfd); - while (child_ctx) { - pxy_conn_ctx_t *next = child_ctx->next_child_ctx; - if (rv = pxy_conn_free_child(child_ctx, 0)) { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free: FREE child SUCCESS, fd=%d, child fd=%d\n", fd, cfd); - } - child_ctx = next; + // @attention Force freeing child + if (pxy_conn_free_child(child_ctx, 1)) { + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free: FREE child SUCCESS, fd=%d, child fd=%d\n", fd, cfd); } } + + if (!mctx->child_list) { + // @attention Parent may be closing before there was any child at all, so try to close the child listener here too + if (mctx->child_evcl) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_conn_free: FREEING evcl2, pfd=%d, fd2=%d, cfd=%d\n", fd, mctx->child_fd, cfd); + // child_evcl was created with LEV_OPT_CLOSE_ON_FREE, so no need to close mctx->child_fd + evconnlistener_free(mctx->child_evcl); + mctx->child_evcl = NULL; + } + + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_conn_free: RELEASING META CTX, fd=%d, child fd=%d\n", fd, cfd); + rv = 2; + } + return rv; } else { log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_conn_free: CANNOT FREE CTX, fd=%d, child fd=%d\n", fd, cfd); @@ -2193,29 +2238,8 @@ pxy_child_conn_free(pxy_conn_ctx_t *ctx) log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_child_conn_free: remove_node\n"); remove_child_ctx(ctx, &ctx->mctx->child_list); - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_child_conn_free: CHECKING\n"); - pxy_conn_ctx_t *current_child_ctx = ctx->mctx->child_list; - while (current_child_ctx) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_child_conn_free: NOT NULL CHILD, fd=%d\n", current_child_ctx->fd); - current_child_ctx = current_child_ctx->next_child_ctx; - } - - if (!ctx->mctx->parent_ctx && !ctx->mctx->child_list) { - if (ctx->mctx->child_evcl) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_child_conn_free: FREEING evcl2, pfd=%d, fd2=%d, cfd=%d\n", pfd, ctx->mctx->child_fd, fd); - evconnlistener_free(ctx->mctx->child_evcl); - evutil_closesocket(ctx->mctx->child_fd); - } - - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_child_conn_free: RELEASING META CTX, fd=%d, parent fd=%d\n", fd, pfd); - } else { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_child_conn_free: CANNOT FREE evcl2, pfd=%d, fd2=%d, cfd=%d\n", pfd, ctx->mctx->child_fd, fd); - } - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_child_conn_free: FREEING CTX, fd=%d, parent fd=%d\n", fd, pfd); - pxy_conn_ctx_free_child(ctx); - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_child_conn_free: FREED CTX, fd=%d, parent fd=%d\n", fd, pfd); } @@ -2227,13 +2251,15 @@ pxy_parent_conn_free(pxy_conn_ctx_t *ctx) log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_parent_conn_free: TRY FREE ctx->src\n"); pxy_conn_desc_t *src = &ctx->src; - if (src->bev) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_parent_conn_free: bufferevent_free_and_close_fd src->bev, fd=%d\n", bufferevent_getfd(src->bev)); - bufferevent_free_and_close_fd(src->bev, ctx); - src->bev = NULL; - } else { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_parent_conn_free: evutil_closesocket on NULL src->bev, fd=%d\n", fd); - evutil_closesocket(fd); + if (!src->closed) { + if (src->bev) { + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_parent_conn_free: bufferevent_free_and_close_fd src->bev, fd=%d\n", bufferevent_getfd(src->bev)); + bufferevent_free_and_close_fd(src->bev, ctx); + src->bev = NULL; + } else { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_parent_conn_free: evutil_closesocket on NULL src->bev, fd=%d\n", fd); + evutil_closesocket(fd); + } } pxy_conn_desc_t *dst = &ctx->dst; @@ -2251,17 +2277,6 @@ pxy_parent_conn_free(pxy_conn_ctx_t *ctx) } ctx->mctx->parent_ctx = NULL; - if (!ctx->mctx->child_list) { - if (ctx->mctx->child_evcl) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_parent_conn_free: FREEING evcl2, pfd=%d, fd2=%d, cfd=%d\n", fd, ctx->mctx->child_fd, cfd); - evconnlistener_free(ctx->mctx->child_evcl); - evutil_closesocket(ctx->mctx->child_fd); - } - - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_parent_conn_free: RELEASING META CTX, fd=%d, child fd=%d\n", fd, cfd); - } else { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_parent_conn_free: CANNOT FREE evcl2, pfd=%d, fd2=%d, cfd=%d\n", fd, ctx->mctx->child_fd, cfd); - } log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">############################# pxy_parent_conn_free: FREEING ctx, fd=%d, child fd=%d\n", fd, cfd); pxy_conn_ctx_free(ctx); @@ -2278,12 +2293,20 @@ pxy_all_conn_free(proxy_conn_meta_ctx_t *mctx) current = next; } + if (mctx->child_evcl) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">############################# pxy_all_conn_free: FREEING evcl2, pfd=%d, fd2=%d\n", mctx->fd, mctx->child_fd); + // child_evcl was created with LEV_OPT_CLOSE_ON_FREE, so no need to close mctx->child_fd + evconnlistener_free(mctx->child_evcl); + mctx->child_evcl = NULL; + } + if (mctx->parent_ctx) { pxy_parent_conn_free(mctx->parent_ctx); } // @todo Can we free mctx here too? - //pxy_conn_meta_ctx_free(mctx); + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">############################# pxy_all_conn_free: EXIT FREE META CTX\n"); + pxy_conn_meta_ctx_free(mctx); } char *bev_names[] = { @@ -2346,14 +2369,14 @@ pxy_bev_readcb(struct bufferevent *bev, void *arg) } } + struct evbuffer *inbuf = bufferevent_get_input(bev); + + if (ctx->e2src.closed) { + evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); + goto leave; + } + if (ctx->e2src.bev) { - struct evbuffer *inbuf = bufferevent_get_input(bev); - - if (ctx->e2src.closed) { - evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); - goto leave; - } - char *custom_key = "\r\nSSLproxy-Addr: "; size_t custom_field_len = strlen(custom_key) + strlen(ctx->mctx->child_addr) + 1; @@ -2435,14 +2458,14 @@ pxy_bev_readcb(struct bufferevent *bev, void *arg) } } else if (bev == ctx->e2src.bev) { + struct evbuffer *inbuf = bufferevent_get_input(bev); + + if (ctx->src.closed) { + evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); + goto leave; + } + if (ctx->src.bev) { - struct evbuffer *inbuf = bufferevent_get_input(bev); - - if (ctx->src.closed) { - evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); - goto leave; - } - size_t packet_size = evbuffer_get_length(inbuf); char *packet = malloc(packet_size); if (!packet) { @@ -2511,17 +2534,16 @@ pxy_bev_readcb_child(struct bufferevent *bev, void *arg) getpeername(ctx->fd, &peeraddr, &peeraddrlen); if (bev == ctx->e2dst.bev) { + struct evbuffer *inbuf = bufferevent_get_input(ctx->e2dst.bev); + + if (ctx->dst.closed) { + evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); + goto leave; + } + if (ctx->dst.bev) { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>.................................................................................... pxy_bev_readcb_child: PEER [%s]:%d <<<<< fd=%d, parent fd=%d\n", inet_ntoa(peeraddr.sin_addr), (int) ntohs(peeraddr.sin_port), ctx->fd, pfd); - struct evbuffer *inbuf = bufferevent_get_input(ctx->e2dst.bev); - - if (ctx->dst.closed) { - evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); - goto leave; - } - char *custom_key = "SSLproxy-Addr: "; struct evbuffer_ptr ebp = evbuffer_search(inbuf, custom_key, strlen(custom_key), NULL); if (ebp.pos != -1) { @@ -2605,14 +2627,14 @@ pxy_bev_readcb_child(struct bufferevent *bev, void *arg) } } else if (bev == ctx->dst.bev) { + struct evbuffer *inbuf = bufferevent_get_input(bev); + + if (ctx->e2dst.closed) { + evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); + goto leave; + } + if (ctx->e2dst.bev) { - struct evbuffer *inbuf = bufferevent_get_input(bev); - - if (ctx->e2dst.closed) { - evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); - goto leave; - } - size_t packet_size = evbuffer_get_length(inbuf); char *packet = malloc(packet_size); if (!packet) { @@ -2784,7 +2806,7 @@ pxy_connected_enable(struct bufferevent *bev, pxy_conn_ctx_t *ctx, char *event_n ctx->mctx->dst_fd = bufferevent_getfd(ctx->dst.bev); } - // @attention Free the dst of the parent ctx asap, we don't need it, but we need its fds asap + // @attention Free the dst of the parent ctx asap, we don't need it, but we need its fd pxy_conn_desc_t *dst = &ctx->dst; if (dst->bev) { log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>=================================== pxy_connected_enable: evutil_closesocket dst->bev, fd=%d\n", bufferevent_getfd(dst->bev)); @@ -2804,23 +2826,25 @@ pxy_connected_enable(struct bufferevent *bev, pxy_conn_ctx_t *ctx, char *event_n evutil_socket_t fd2; if ((fd2 = privsep_client_opensock_e2(ctx->mctx->lctx->clisock, ctx->mctx->lctx->spec)) == -1) { log_err_printf("Error opening socket: %s (%i)\n", strerror(errno), errno); + pxy_all_conn_free(ctx->mctx); return 0; } ctx->mctx->child_fd = fd2; log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_connected_enable: Opened fd2, fd=%d, fd2=%d\n", ctx->mctx->fd, ctx->mctx->child_fd); - struct evconnlistener *evcl2 = evconnlistener_new(ctx->mctx->thr->evbase, proxy_listener_acceptcb_child, ctx->mctx, LEV_OPT_CLOSE_ON_FREE, 1024, ctx->mctx->child_fd); - if (!evcl2) { - log_err_printf("Error creating evconnlistener e2: %s, fd=%d, fd2=%d <<<<<<\n", strerror(errno), ctx->mctx->fd, ctx->mctx->child_fd); + struct evconnlistener *child_evcl = evconnlistener_new(ctx->mctx->thr->evbase, proxy_listener_acceptcb_child, ctx->mctx, LEV_OPT_CLOSE_ON_FREE, 1024, ctx->mctx->child_fd); + if (!child_evcl) { + log_err_printf("Error creating child evconnlistener: %s, fd=%d, fd2=%d <<<<<<\n", strerror(errno), ctx->mctx->fd, ctx->mctx->child_fd); // @attention Cannot call proxy_listener_ctx_free() on evcl2, evcl2 does not have any ctx with next listener // @todo Create a new struct for evcl2 and related functions //proxy_listener_ctx_free(lctxe2); evutil_closesocket(ctx->mctx->child_fd); + pxy_all_conn_free(ctx->mctx); return 0; } - ctx->mctx->child_evcl = evcl2; + ctx->mctx->child_evcl = child_evcl; - evconnlistener_set_error_cb(evcl2, proxy_listener_errorcb); + evconnlistener_set_error_cb(child_evcl, proxy_listener_errorcb); log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>=================================== pxy_connected_enable: FINISHED SETTING UP E2 SUCCESS, parent fd=%d, NEW fd2=%d\n", ctx->mctx->fd, ctx->mctx->child_fd); struct sockaddr_in e2listener_addr; @@ -2832,8 +2856,8 @@ pxy_connected_enable(struct bufferevent *bev, pxy_conn_ctx_t *ctx, char *event_n if (getsockname(ctx->mctx->child_fd, &e2listener_addr, &e2listener_len) < 0) { perror("getsockname"); log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_connected_enable: %s, getsockname ERROR= %s, fd=%d ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, fd2=%d\n", event_name, strerror(errno), ctx->fd, ctx->mctx->child_fd); - // @todo If getsockname() fails, terminate the connection instead? - // Leaving the packet in the buffer will eventually time out and drop the connection + // @todo If getsockname() fails, should we really terminate the connection? + pxy_all_conn_free(ctx->mctx); return 0; } @@ -2857,6 +2881,8 @@ pxy_connected_enable_child(struct bufferevent *bev, pxy_conn_ctx_t *ctx, char *e log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_connected_enable_child: ENTER bev = %s\n", event_name); if (bev == ctx->dst.bev) { + ctx->connected = 1; + // @attention Create and enable e2dst.bev before, but connect here, because we check if e2src.bev is NULL elsewhere log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_connected_enable_child: enable callbacks for e2dst.bev\n"); bufferevent_enable(ctx->e2dst.bev, EV_READ|EV_WRITE); @@ -2893,7 +2919,24 @@ pxy_bev_writecb(struct bufferevent *bev, void *arg) log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>+++++++++++++++++++++++++++++++++++ pxy_bev_writecb: %s, %d\n", event_name, ctx->fd); if ((bev==ctx->src.bev) || (bev==ctx->e2src.bev)) { + pxy_conn_desc_t *this = (bev==ctx->src.bev) ? &ctx->src : &ctx->e2src; pxy_conn_desc_t *other = (bev==ctx->src.bev) ? &ctx->e2src : &ctx->src; + void (*bufferevent_free_and_close_fd_func)(struct bufferevent *, pxy_conn_ctx_t *) = (bev==ctx->e2src.bev) ? &bufferevent_free_and_close_fd_nonssl : &bufferevent_free_and_close_fd; + + if (other->closed) { + struct evbuffer *outbuf = bufferevent_get_output(bev); + if (evbuffer_get_length(outbuf) == 0) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>+++++++++++++++++++++++++++++++++++ pxy_bev_writecb: other->closed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + /* finished writing and other end is closed; + * close this end too and clean up memory */ + this->closed = 1; + bufferevent_free_and_close_fd_func(bev, ctx); + this->bev = NULL; + rv = pxy_conn_free(ctx, 1); + } + goto leave; + } + if (other->bev && !(bufferevent_get_enabled(other->bev) & EV_READ)) { /* data source temporarily disabled; * re-enable and reset watermark to 0. */ @@ -2903,15 +2946,17 @@ pxy_bev_writecb(struct bufferevent *bev, void *arg) } } - if (ctx->src.closed || ctx->e2src.closed) { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>+++++++++++++++++++++++++++++++++++ pxy_bev_writecb: TRY CLOSING PARENT fd=%d\n", ctx->fd); - rv = pxy_conn_free(ctx); - } +// if (ctx->src.closed || ctx->e2src.closed) { +// log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>+++++++++++++++++++++++++++++++++++ pxy_bev_writecb: TRY CLOSING PARENT fd=%d\n", ctx->fd); +// rv = pxy_conn_free(ctx, 0); +// } +leave: log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>+++++++++++++++++++++++++++++++++++ pxy_bev_writecb: EXIT\n"); if (rv == 2) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>+++++++++++++++++++++++++++++++++++ pxy_bev_writecb: EXIT FREE META CTX\n"); + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>+++++++++++++++++++++++++++++++++++ pxy_bev_writecb: EXIT FREEING META CTX\n"); pxy_conn_meta_ctx_free(mctx); + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>+++++++++++++++++++++++++++++++++++ pxy_bev_writecb: EXIT FREED META CTX\n"); } } @@ -2942,18 +2987,24 @@ pxy_bev_writecb_child(struct bufferevent *bev, void *arg) evutil_socket_t fd = ctx->fd; - int src_eof = 1; - int e2src_eof = 1; - if (parent_ctx) { - src_eof = parent_ctx->src.closed; - e2src_eof = parent_ctx->e2src.closed; - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>??????????????????????????? pxy_bev_writecb_child: %s, %d-%d-%d-%d, fd=%d\n", event_name, - src_eof, e2src_eof, ctx->e2dst.closed, ctx->dst.closed, fd); - } else { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>??????????????????????????? pxy_bev_writecb_child: ctx->parent_ctx NULL %s, %d\n", event_name, fd); + pxy_conn_desc_t *this = (bev==ctx->e2dst.bev) ? &ctx->e2dst : &ctx->dst; + pxy_conn_desc_t *other = (bev==ctx->e2dst.bev) ? &ctx->dst : &ctx->e2dst; + void (*bufferevent_free_and_close_fd_func)(struct bufferevent *, pxy_conn_ctx_t *) = (bev==ctx->e2dst.bev) ? &bufferevent_free_and_close_fd_nonssl : &bufferevent_free_and_close_fd; + + if (other->closed) { + struct evbuffer *outbuf = bufferevent_get_output(bev); + if (evbuffer_get_length(outbuf) == 0) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>??????????????????????????? pxy_bev_writecb_child: other->closed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + /* finished writing and other end is closed; + * close this end too and clean up memory */ + this->closed = 1; + bufferevent_free_and_close_fd_func(bev, ctx); + this->bev = NULL; + rv = pxy_conn_free_child(ctx, 1); + } + goto leave; } - pxy_conn_desc_t *other = (bev==ctx->e2dst.bev) ? &ctx->dst : &ctx->e2dst; if (other->bev && !(bufferevent_get_enabled(other->bev) & EV_READ)) { /* data source temporarily disabled; * re-enable and reset watermark to 0. */ @@ -2962,15 +3013,17 @@ pxy_bev_writecb_child(struct bufferevent *bev, void *arg) bufferevent_enable(other->bev, EV_READ); } - if (ctx->e2dst.closed || ctx->dst.closed || !parent_ctx) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>??????????????????????????? pxy_bev_writecb_child: TRY CLOSING CHILD fd=%d\n", fd); - rv = pxy_conn_free_child(ctx, 0); - } +// if (ctx->e2dst.closed || ctx->dst.closed || !parent_ctx) { +// log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>??????????????????????????? pxy_bev_writecb_child: TRY CLOSING CHILD fd=%d\n", fd); +// rv = pxy_conn_free_child(ctx, 0); +// } +leave: log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>??????????????????????????? pxy_bev_writecb_child: EXIT\n"); if (rv == 2) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>??????????????????????????? pxy_bev_writecb_child: EXIT FREE META CTX\n"); + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>??????????????????????????? pxy_bev_writecb_child: EXIT FREEING META CTX\n"); pxy_conn_meta_ctx_free(mctx); + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>??????????????????????????? pxy_bev_writecb_child: EXIT FREED META CTX\n"); } } @@ -2993,6 +3046,12 @@ pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg) // @attention Get the mctx pointer now, because we may need to free it after freeing ctx proxy_conn_meta_ctx_t *mctx = ctx->mctx; + pxy_conn_desc_t *this = (bev==ctx->src.bev) ? &ctx->src : &ctx->e2src; + pxy_conn_desc_t *other = (bev==ctx->src.bev) ? &ctx->e2src : &ctx->src; + + void (*this_free_and_close_fd_func)(struct bufferevent *, pxy_conn_ctx_t *) = (this->bev==ctx->src.bev) ? &bufferevent_free_and_close_fd : &bufferevent_free_and_close_fd_nonssl; + void (*other_free_and_close_fd_func)(struct bufferevent *, pxy_conn_ctx_t *) = (other->bev==ctx->e2src.bev) ? &bufferevent_free_and_close_fd_nonssl : &bufferevent_free_and_close_fd; + int rv = 0; ctx->mctx->access_time = time(NULL); @@ -3141,35 +3200,71 @@ pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg) } // @todo Close and free the connections upon errors - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb: ERROR pxy_conn_free, %s fd=%d\n", event_name, ctx->fd); + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb: ERROR pxy_all_conn_free, %s fd=%d\n", event_name, ctx->fd); pxy_all_conn_free(mctx); - rv = 2; - goto leave; + return; } if (events & BEV_EVENT_EOF) { if (bev == ctx->dst.bev) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb: dst EOF: %d\n", ctx->fd); + bufferevent_free_and_close_fd(ctx->dst.bev, ctx); + ctx->dst.bev = NULL; ctx->dst.closed = 1; ctx->mctx->dst_eof = 1; - } else if (bev == ctx->e2src.bev) { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb: e2src EOF: %d\n", ctx->fd); - ctx->e2src.closed = 1; - ctx->mctx->e2src_eof = 1; - } else if (bev == ctx->src.bev) { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb: src EOF: %d\n", ctx->fd); - ctx->src.closed = 1; - ctx->mctx->src_eof = 1; + goto leave; +// } else if (bev == ctx->e2src.bev) { +// log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb: e2src EOF: %d\n", ctx->fd); +// ctx->e2src.closed = 1; +// ctx->mctx->e2src_eof = 1; +// } else if (bev == ctx->src.bev) { +// log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb: src EOF: %d\n", ctx->fd); +// ctx->src.closed = 1; +// ctx->mctx->src_eof = 1; + } else { + if (bev == ctx->e2src.bev) { + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb: e2src EOF: %d\n", ctx->fd); + } else if (bev == ctx->src.bev) { + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb: src EOF: %d\n", ctx->fd); + } + if (!ctx->connected) { + log_dbg_printf("EOF on inbound connection while " + "connecting to original destination\n"); + evutil_closesocket(ctx->fd); + other->closed = 1; + } else if (!other->closed) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb: !other->closed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + struct evbuffer *inbuf, *outbuf; + inbuf = bufferevent_get_input(bev); + outbuf = bufferevent_get_output(other->bev); + if (evbuffer_get_length(inbuf) > 0) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb: evbuffer_get_length(inbuf) > 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); +// evbuffer_add_buffer(outbuf, inbuf); + pxy_bev_readcb(bev, ctx); + } else { + /* if the other end is still open and doesn't + * have data to send, close it, otherwise its + * writecb will close it after writing what's + * left in the output buffer. */ + if (evbuffer_get_length(outbuf) == 0) { +// bufferevent_free_and_close_fd( + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb: evbuffer_get_length(inbuf) == 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + other_free_and_close_fd_func(other->bev, ctx); + other->bev = NULL; + other->closed = 1; + (bev==ctx->src.bev) ? (ctx->mctx->e2src_eof = 1) : (ctx->mctx->src_eof = 1); + } + } + } + goto leave2; } - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb: EOF %s, %d-%d-%d-%d, fd=%d\n", event_name, - ctx->src.closed, ctx->e2src.closed, ctx->e2dst.closed, ctx->dst.closed, ctx->fd); } - if (ctx->src.closed || ctx->e2src.closed) { - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>=================================== pxy_bev_eventcb(): 1+ EOF TRY FREEING fd=%d\n", ctx->fd); - rv = pxy_conn_free(ctx); - goto leave; - } +// if (ctx->src.closed || ctx->e2src.closed) { +// log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>=================================== pxy_bev_eventcb(): 1+ EOF TRY FREEING fd=%d\n", ctx->fd); +// rv = pxy_conn_free(ctx, 0); +// goto leave; +// } leave: log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>=================================== pxy_bev_eventcb EXIT fd=%d\n", fd); @@ -3178,6 +3273,29 @@ leave: log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>>=================================== pxy_bev_eventcb: EXIT FREE META CTX\n"); pxy_conn_meta_ctx_free(mctx); } + return; + +leave2: + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb: leave2 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + /* we only get a single disconnect event here for both connections */ + if (OPTS_DEBUG(ctx->opts)) { + log_dbg_printf("%s disconnected to [%s]:%s\n", + this->ssl ? "SSL" : "TCP", + ctx->dsthost_str, ctx->dstport_str); + log_dbg_printf("%s disconnected from [%s]:%s\n", + this->ssl ? "SSL" : "TCP", + ctx->srchost_str, ctx->srcport_str); + } + + this->closed = 1; + (bev==ctx->src.bev) ? (ctx->mctx->src_eof = 1) : (ctx->mctx->e2src_eof = 1); + this_free_and_close_fd_func(bev, ctx); + this->bev = NULL; + if (other->closed) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb: leave2 other->closed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + rv = pxy_conn_free(ctx, 1); + } + goto leave; } static void @@ -3195,6 +3313,12 @@ pxy_bev_eventcb_child(struct bufferevent *bev, short events, void *arg) // @attention Get the mctx pointer now, because we may need to free it after freeing ctx proxy_conn_meta_ctx_t *mctx = ctx->mctx; + pxy_conn_desc_t *this = (bev==ctx->e2dst.bev) ? &ctx->e2dst : &ctx->dst; + pxy_conn_desc_t *other = (bev==ctx->e2dst.bev) ? &ctx->dst : &ctx->e2dst; + + void (*this_free_and_close_fd_func)(struct bufferevent *, pxy_conn_ctx_t *) = (this->bev==ctx->e2dst.bev) ? &bufferevent_free_and_close_fd_nonssl : &bufferevent_free_and_close_fd; + void (*other_free_and_close_fd_func)(struct bufferevent *, pxy_conn_ctx_t *) = (other->bev==ctx->dst.bev) ? &bufferevent_free_and_close_fd : &bufferevent_free_and_close_fd_nonssl; + int rv = 0; ctx->mctx->access_time = time(NULL); @@ -3212,43 +3336,55 @@ pxy_bev_eventcb_child(struct bufferevent *bev, short events, void *arg) int fd = ctx->fd; if (events & BEV_EVENT_EOF) { - int e2dst_eof = ctx->e2dst.closed; - int dst_eof = ctx->dst.closed; - - // @attention Get the parent ctx pointer now, because we need it after freeing ctx - pxy_conn_ctx_t *parent_ctx = ctx->mctx->parent_ctx; - if (bev == ctx->e2dst.bev) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>--------------------- pxy_bev_eventcb_child: e2dst EOF: %d\n", fd); - ctx->e2dst.closed = 1; - ctx->mctx->e2dst_eof = 1; - ctx->child_info->e2dst_eof = 1; - - rv = pxy_conn_free_child(ctx, 0); +// ctx->e2dst.closed = 1; +// ctx->mctx->e2dst_eof = 1; +// ctx->child_info->e2dst_eof = 1; +// +// rv = pxy_conn_free_child(ctx, 0); } else if (bev == ctx->dst.bev) { log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>>--------------------- pxy_bev_eventcb_child: dst EOF: %d\n", fd); - ctx->dst.closed = 1; - ctx->mctx->dst2_eof = 1; - ctx->child_info->dst2_eof = 1; - - rv = pxy_conn_free_child(ctx, 0); +// ctx->dst.closed = 1; +// ctx->mctx->dst2_eof = 1; +// ctx->child_info->dst2_eof = 1; +// +// rv = pxy_conn_free_child(ctx, 0); } // @todo Handle the following case -// if (!ctx->connected) { -// log_dbg_printf("EOF on inbound connection while " -// "connecting to original destination\n"); -// evutil_closesocket(ctx->fd); -// other->closed = 1; -// } else - - if (!parent_ctx) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>--------------------- pxy_bev_eventcb_child: EOF %s, NO PARENT, %d-%d, fd=%d\n", event_name, - e2dst_eof, dst_eof, fd); + if (!ctx->connected) { + log_dbg_printf("EOF on inbound connection while " + "connecting to original destination\n"); + evutil_closesocket(ctx->fd); + other->closed = 1; + } else if (!other->closed) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb_child: !other->closed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + struct evbuffer *inbuf, *outbuf; + inbuf = bufferevent_get_input(bev); + outbuf = bufferevent_get_output(other->bev); + if (evbuffer_get_length(inbuf) > 0) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb_child: evbuffer_get_length(inbuf) > 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + pxy_bev_readcb_child(bev, ctx); + } else { + /* if the other end is still open and doesn't + * have data to send, close it, otherwise its + * writecb will close it after writing what's + * left in the output buffer. */ + if (evbuffer_get_length(outbuf) == 0) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>=================================== pxy_bev_eventcb_child: evbuffer_get_length(inbuf) == 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + other_free_and_close_fd_func(other->bev, ctx); + other->bev = NULL; + other->closed = 1; + (bev==ctx->e2dst.bev) ? (ctx->mctx->e2dst_eof = 1) : (ctx->mctx->dst2_eof = 1); + (bev==ctx->e2dst.bev) ? (ctx->child_info->e2dst_eof = 1) : (ctx->child_info->dst2_eof = 1); + } + } } + goto leave2; } if (events & BEV_EVENT_ERROR) { @@ -3333,7 +3469,7 @@ pxy_bev_eventcb_child(struct bufferevent *bev, short events, void *arg) } log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>--------------------- pxy_bev_eventcb_child: ERROR pxy_conn_free_child, %s fd=%d\n", event_name, ctx->fd); - rv = pxy_conn_free_child(ctx, 0); + rv = pxy_conn_free_child(ctx, 1); goto leave; } @@ -3344,6 +3480,30 @@ leave: log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>--------------------- pxy_bev_eventcb_child: EXIT FREE META CTX\n"); pxy_conn_meta_ctx_free(mctx); } + return; + +leave2: + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>--------------------- pxy_bev_eventcb_child: leave2 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + /* we only get a single disconnect event here for both connections */ + if (OPTS_DEBUG(ctx->opts)) { + log_dbg_printf("%s disconnected to [%s]:%s\n", + this->ssl ? "SSL" : "TCP", + ctx->dsthost_str, ctx->dstport_str); + log_dbg_printf("%s disconnected from [%s]:%s\n", + this->ssl ? "SSL" : "TCP", + ctx->srchost_str, ctx->srcport_str); + } + + this->closed = 1; + (bev==ctx->e2dst.bev) ? (ctx->mctx->e2dst_eof = 1) : (ctx->mctx->dst2_eof = 1); + (bev==ctx->e2dst.bev) ? (ctx->child_info->e2dst_eof = 1) : (ctx->child_info->dst2_eof = 1); + this_free_and_close_fd_func(bev, ctx); + this->bev = NULL; + if (other->closed) { + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>>--------------------- pxy_bev_eventcb_child: leave2 other->closed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CONN TERM\n"); + rv = pxy_conn_free_child(ctx, 1); + } + goto leave; } /* @@ -3390,8 +3550,12 @@ pxy_conn_connect(pxy_conn_ctx_t *ctx) pxy_conn_ctx_free(ctx); return; } - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_conn_connect: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< bufferevent_enable(ctx->dst.bev)\n"); - bufferevent_enable(ctx->dst.bev, EV_READ|EV_WRITE); + + // @attention Do not enable read or write cbs for dst: (1) We do nothing in those cbs for dst and (2) sometimes write cb fires before event cb, + // especially if this listener cb is not finished yet, then event cb never fires, so the conn stalls. Not enabling those cbs seems solve the problem. + // @todo Why does not enabling those cbs solve the problem? + //log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_conn_connect: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< bufferevent_enable(ctx->dst.bev)\n"); + //bufferevent_enable(ctx->dst.bev, EV_READ|EV_WRITE); if (OPTS_DEBUG(ctx->opts)) { char *host, *port; diff --git a/pxythrmgr.c b/pxythrmgr.c index 7899e48..3a3a190 100644 --- a/pxythrmgr.c +++ b/pxythrmgr.c @@ -47,7 +47,7 @@ #define THR_TIMER_TIMEOUT 10 #define THR_TIMER_PRINT_INFO_TIMEOUT 1*THR_TIMER_TIMEOUT -#define CONN_EXPIRE_TIME 30 +#define CONN_EXPIRE_TIME 120 /* * Dummy recurring timer event to prevent the event loops from exiting when @@ -72,7 +72,6 @@ pxy_thrmgr_timer_cb(UNUSED evutil_socket_t fd, UNUSED short what, log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! pxy_thrmgr_timer_cb: DELETE thr=%d, fd=%d, fd2=%d, time=%lld <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< TIMED OUT\n", expired->thridx, expired->fd, expired->child_fd, (long int) now - expired->access_time); pxy_all_conn_free(expired); - pxy_conn_meta_ctx_free(expired); expired = next; } @@ -169,7 +168,7 @@ pxy_thrmgr_run(pxy_thrmgr_ctx_t *ctx) } ctx->thr[idx]->load = 0; ctx->thr[idx]->running = 0; - ctx->thr[idx]->mctx = NULL; + ctx->thr[idx]->mctx_list = NULL; ctx->thr[idx]->thridx = idx; ctx->thr[idx]->timeout_count = 0; } @@ -250,7 +249,7 @@ pxy_thrmgr_free(pxy_thrmgr_ctx_t *ctx) free(ctx); } -void +static void pxy_thrmgr_remove_mctx(proxy_conn_meta_ctx_t *node, proxy_conn_meta_ctx_t **head) { assert(node != NULL); @@ -315,10 +314,11 @@ pxy_thrmgr_attach(pxy_thrmgr_ctx_t *ctx, struct event_base **evbase, mctx->thridx = thridx; mctx->thr = ctx->thr[thridx]; - mctx->next = ctx->thr[thridx]->mctx; - ctx->thr[thridx]->mctx = mctx; + mctx->next = ctx->thr[thridx]->mctx_list; + ctx->thr[thridx]->mctx_list = mctx; - pxy_thrmgr_print_thr_info(ctx->thr[thridx]); + // @todo Is it ok to call conn thread functions from another thread? We are running on the thrmgr thread now. No it is not anymore. + //pxy_thrmgr_print_thr_info(ctx->thr[thridx]); log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> EXIT pxy_thrmgr_attach()\n"); pthread_mutex_unlock(&ctx->mutex); @@ -350,48 +350,56 @@ pxy_thrmgr_detach(pxy_thrmgr_ctx_t *ctx, int thridx, proxy_conn_meta_ctx_t *mctx pthread_mutex_lock(&ctx->mutex); log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_thrmgr_detach(): BEFORE pxy_thrmgr_remove_node\n"); - pxy_thrmgr_print_thr_info(ctx->thr[thridx]); +// pxy_thrmgr_print_thr_info(ctx->thr[thridx]); + pxy_thrmgr_print_thr_info(mctx->thr); - ctx->thr[thridx]->load--; +// ctx->thr[thridx]->load--; + mctx->thr->load--; if (!mctx->child_list) { - pxy_thrmgr_remove_mctx(mctx, &ctx->thr[thridx]->mctx); +// pxy_thrmgr_remove_mctx(mctx, &ctx->thr[thridx]->mctx); + pxy_thrmgr_remove_mctx(mctx, &mctx->thr->mctx_list); } else { log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>> pxy_thrmgr_detach(): parent ctx has an active child, will not remove from the list, fd=%d, fd2=%d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", mctx->fd, mctx->child_fd); } log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>> pxy_thrmgr_detach(): AFTER pxy_thrmgr_remove_node\n"); - pxy_thrmgr_print_thr_info(ctx->thr[thridx]); +// pxy_thrmgr_print_thr_info(ctx->thr[thridx]); + pxy_thrmgr_print_thr_info(mctx->thr); pthread_mutex_unlock(&ctx->mutex); } void -pxy_thrmgr_detach_e2(pxy_thrmgr_ctx_t *ctx, int thridx, proxy_conn_meta_ctx_t *mctx) +pxy_thrmgr_detach_child(pxy_thrmgr_ctx_t *ctx, int thridx, proxy_conn_meta_ctx_t *mctx) { - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_thrmgr_detach_e2()\n"); + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_thrmgr_detach_child()\n"); pthread_mutex_lock(&ctx->mutex); - log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_thrmgr_detach_e2(): BEFORE pxy_thrmgr_remove_node\n"); - pxy_thrmgr_print_thr_info(ctx->thr[thridx]); + log_dbg_level_printf(LOG_DBG_MODE_FINEST, ">>>>> pxy_thrmgr_detach_child(): BEFORE pxy_thrmgr_remove_node\n"); +// pxy_thrmgr_print_thr_info(ctx->thr[thridx]); + pxy_thrmgr_print_thr_info(mctx->thr); - ctx->thr[thridx]->load--; +// ctx->thr[thridx]->load--; + mctx->thr->load--; if (!mctx->parent_ctx && !mctx->child_list) { - pxy_thrmgr_remove_mctx(mctx, &ctx->thr[thridx]->mctx); +// pxy_thrmgr_remove_mctx(mctx, &ctx->thr[thridx]->mctx); + pxy_thrmgr_remove_mctx(mctx, &mctx->thr->mctx_list); } else { if (mctx->parent_ctx) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>> pxy_thrmgr_detach_e2(): child ctx has an active parent, will not remove from the list, fd=%d, fd2=%d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>> pxy_thrmgr_detach_child(): child ctx has an active parent, will not remove from the list, fd=%d, fd2=%d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", mctx->fd, mctx->child_fd); } else if (mctx->child_list) { - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>> pxy_thrmgr_detach_e2(): conn has 1+ active child, will not remove from the list, fd=%d, fd2=%d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>>>> pxy_thrmgr_detach_child(): conn has 1+ active child, will not remove from the list, fd=%d, fd2=%d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", mctx->fd, mctx->child_fd); } } - log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>> pxy_thrmgr_detach_e2(): AFTER pxy_thrmgr_remove_node\n"); - pxy_thrmgr_print_thr_info(ctx->thr[thridx]); + log_dbg_level_printf(LOG_DBG_MODE_FINER, ">>>>> pxy_thrmgr_detach_child(): AFTER pxy_thrmgr_remove_node\n"); +// pxy_thrmgr_print_thr_info(ctx->thr[thridx]); + pxy_thrmgr_print_thr_info(mctx->thr); pthread_mutex_unlock(&ctx->mutex); } @@ -400,8 +408,10 @@ void pxy_thrmgr_print_child_info(pxy_conn_child_info_t *info, int thridx, int count) { assert(info != NULL); - log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>> .......... pxy_thrmgr_print_child_info(): thr=%d, cont=%d, e2dst=%d, dst2=%d, c=%d-%d, ci=%d, f=%d\n", - thridx, count, info->e2dst_fd, info->dst2_fd, info->e2dst_eof, info->dst2_eof, info->child_idx, info->freed); +// log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>> .......... pxy_thrmgr_print_child_info(): thr=%d, cont=%d, e2dst=%d, dst2=%d, c=%d-%d, ci=%d, f=%d\n", +// thridx, count, info->e2dst_fd, info->dst2_fd, info->e2dst_eof, info->dst2_eof, info->child_idx, info->freed); + log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>> .......... pxy_thrmgr_print_child_info(): thr=%d, cont=%d, e2dst=%d, dst2=%d, c=%d-%d, ci=%d\n", + thridx, count, info->e2dst_fd, info->dst2_fd, info->e2dst_eof, info->dst2_eof, info->child_idx); if (info->next) { pxy_thrmgr_print_child_info(info->next, thridx, count); } @@ -414,10 +424,10 @@ pxy_thrmgr_print_thr_info(pxy_thr_ctx_t *ctx) log_dbg_level_printf(LOG_DBG_MODE_FINE, ">>> pxy_thrmgr_print_thr_info(): thr=%d, load=%lu\n", ctx->thridx, ctx->load); - if (ctx->mctx) { + if (ctx->mctx_list) { time_t now = time(NULL); - proxy_conn_meta_ctx_t *mctx = ctx->mctx; + proxy_conn_meta_ctx_t *mctx = ctx->mctx_list; int count = 0; while (mctx) { char *host, *port; @@ -453,7 +463,7 @@ pxy_thrmgr_get_thr_expired_conns(pxy_thr_ctx_t *ctx, proxy_conn_meta_ctx_t **exp time_t now = time(NULL); - proxy_conn_meta_ctx_t *mctx = ctx->mctx; + proxy_conn_meta_ctx_t *mctx = ctx->mctx_list; while (mctx) { unsigned long elapsed_time = now - mctx->access_time; if (elapsed_time > CONN_EXPIRE_TIME) { diff --git a/pxythrmgr.h b/pxythrmgr.h index 3026d29..2ede96f 100644 --- a/pxythrmgr.h +++ b/pxythrmgr.h @@ -48,7 +48,7 @@ typedef struct pxy_thr_ctx { struct evdns_base *dnsbase; int running; int timeout_count; - proxy_conn_meta_ctx_t *mctx; + proxy_conn_meta_ctx_t *mctx_list; } pxy_thr_ctx_t; typedef struct pxy_thrmgr_ctx { @@ -66,7 +66,7 @@ int pxy_thrmgr_attach(pxy_thrmgr_ctx_t *, struct event_base **, struct evdns_base **, proxy_conn_meta_ctx_t *) WUNRES; void pxy_thrmgr_attach_child(pxy_thrmgr_ctx_t *ctx, int thridx); void pxy_thrmgr_detach(pxy_thrmgr_ctx_t *, int, proxy_conn_meta_ctx_t *); -void pxy_thrmgr_detach_e2(pxy_thrmgr_ctx_t *, int, proxy_conn_meta_ctx_t *); +void pxy_thrmgr_detach_child(pxy_thrmgr_ctx_t *, int, proxy_conn_meta_ctx_t *); void pxy_thrmgr_print_thr_info(pxy_thr_ctx_t *ctx); void pxy_thrmgr_get_thr_expired_conns(pxy_thr_ctx_t *ctx, proxy_conn_meta_ctx_t **expired_conns);