reference-count http session objects
This commit is contained in:
@@ -76,10 +76,12 @@ typedef struct http_cstream {
|
||||
|
||||
struct isc_nm_http_session {
|
||||
unsigned int magic;
|
||||
isc_refcount_t references;
|
||||
isc_mem_t *mctx;
|
||||
|
||||
bool sending;
|
||||
bool closed;
|
||||
bool reading;
|
||||
bool closed;
|
||||
|
||||
nghttp2_session *ngsession;
|
||||
bool client;
|
||||
@@ -127,6 +129,9 @@ server_send_error_response(const isc_http_error_responses_t error,
|
||||
static isc_result_t
|
||||
client_send(isc_nmhandle_t *handle, const isc_region_t *region);
|
||||
|
||||
static void
|
||||
finish_http_session(isc_nm_http_session_t *session);
|
||||
|
||||
static bool
|
||||
inactive(isc_nmsocket_t *sock) {
|
||||
return (!isc__nmsocket_active(sock) || atomic_load(&sock->closing) ||
|
||||
@@ -134,6 +139,66 @@ inactive(isc_nmsocket_t *sock) {
|
||||
(sock->server != NULL && !isc__nmsocket_active(sock->server)));
|
||||
}
|
||||
|
||||
static void
|
||||
new_session(isc_mem_t *mctx, isc_tlsctx_t *tctx,
|
||||
isc_nm_http_session_t **sessionp) {
|
||||
isc_nm_http_session_t *session = NULL;
|
||||
|
||||
REQUIRE(sessionp != NULL && *sessionp == NULL);
|
||||
REQUIRE(mctx != NULL);
|
||||
|
||||
session = isc_mem_get(mctx, sizeof(isc_nm_http_session_t));
|
||||
*session = (isc_nm_http_session_t){ .magic = HTTP2_SESSION_MAGIC,
|
||||
.free_tlsctx = (tctx != NULL),
|
||||
.tlsctx = tctx };
|
||||
isc_refcount_init(&session->references, 1);
|
||||
isc_mem_attach(mctx, &session->mctx);
|
||||
ISC_LIST_INIT(session->cstreams);
|
||||
|
||||
*sessionp = session;
|
||||
}
|
||||
|
||||
static void
|
||||
session_attach(isc_nm_http_session_t *source, isc_nm_http_session_t **targetp) {
|
||||
REQUIRE(VALID_HTTP2_SESSION(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
isc_refcount_increment(&source->references);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
static void
|
||||
session_detach(isc_nm_http_session_t **sessionp) {
|
||||
isc_nm_http_session_t *session = NULL;
|
||||
|
||||
REQUIRE(sessionp != NULL);
|
||||
|
||||
session = *sessionp;
|
||||
*sessionp = NULL;
|
||||
|
||||
REQUIRE(VALID_HTTP2_SESSION(session));
|
||||
|
||||
if (isc_refcount_decrement(&session->references) > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
finish_http_session(session);
|
||||
|
||||
INSIST(ISC_LIST_EMPTY(session->sstreams));
|
||||
INSIST(ISC_LIST_EMPTY(session->cstreams));
|
||||
|
||||
/* We need an acquire memory barrier here */
|
||||
(void)isc_refcount_current(&session->references);
|
||||
|
||||
session->magic = 0;
|
||||
if (session->free_tlsctx) {
|
||||
isc_tlsctx_free(&session->tlsctx);
|
||||
}
|
||||
isc_mem_putanddetach(&session->mctx, session,
|
||||
sizeof(isc_nm_http_session_t));
|
||||
}
|
||||
|
||||
static http_cstream_t *
|
||||
find_http_cstream(int32_t stream_id, isc_nm_http_session_t *session) {
|
||||
http_cstream_t *cstream = NULL;
|
||||
@@ -236,19 +301,6 @@ put_http_cstream(isc_mem_t *mctx, http_cstream_t *stream) {
|
||||
isc_mem_put(mctx, stream, sizeof(http_cstream_t));
|
||||
}
|
||||
|
||||
static void
|
||||
delete_http_session(isc_nm_http_session_t *session) {
|
||||
REQUIRE(ISC_LIST_EMPTY(session->sstreams));
|
||||
REQUIRE(ISC_LIST_EMPTY(session->cstreams));
|
||||
|
||||
session->magic = 0;
|
||||
if (session->free_tlsctx) {
|
||||
isc_tlsctx_free(&session->tlsctx);
|
||||
}
|
||||
isc_mem_putanddetach(&session->mctx, session,
|
||||
sizeof(isc_nm_http_session_t));
|
||||
}
|
||||
|
||||
static void
|
||||
finish_http_session(isc_nm_http_session_t *session) {
|
||||
if (session->handle != NULL) {
|
||||
@@ -347,9 +399,8 @@ on_stream_close_callback(nghttp2_session *ngsession, int32_t stream_id,
|
||||
|
||||
/*
|
||||
* NOTE: calling isc_nm_cancelread() or isc__nmsocket_prep_destroy()
|
||||
* on a socket will lead to an indirect call to the
|
||||
* delete_http_session() which will, in turn, perform required
|
||||
* stream session cleanup.
|
||||
* on a socket will lead to an indirect call to detach the session,
|
||||
* which will, in turn, perform required stream cleanup.
|
||||
*/
|
||||
if (session->client) {
|
||||
http_cstream_t *cstream = find_http_cstream(stream_id, session);
|
||||
@@ -797,7 +848,6 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
isc_nmsocket_t *transp_sock = NULL;
|
||||
http_cstream_t *cstream = NULL;
|
||||
isc_mem_t *mctx = NULL;
|
||||
bool freectx;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(http_sock));
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
@@ -806,7 +856,6 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
|
||||
REQUIRE(VALID_NMSOCK(transp_sock));
|
||||
|
||||
transp_sock->h2.session = NULL;
|
||||
mctx = transp_sock->mgr->mctx;
|
||||
|
||||
INSIST(http_sock->h2.connect.uri != NULL);
|
||||
@@ -815,16 +864,8 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
freectx = (http_sock->tls.ctx != NULL);
|
||||
|
||||
session = isc_mem_get(mctx, sizeof(isc_nm_http_session_t));
|
||||
*session = (isc_nm_http_session_t){ .magic = HTTP2_SESSION_MAGIC,
|
||||
.free_tlsctx = freectx,
|
||||
.tlsctx = http_sock->tls.ctx,
|
||||
.handle = NULL,
|
||||
.client = true };
|
||||
isc_mem_attach(mctx, &session->mctx);
|
||||
ISC_LIST_INIT(session->cstreams);
|
||||
new_session(mctx, http_sock->tls.ctx, &session);
|
||||
session->client = true;
|
||||
|
||||
transp_sock->h2.connect.post = http_sock->h2.connect.post;
|
||||
transp_sock->h2.connect.uri = http_sock->h2.connect.uri;
|
||||
@@ -832,8 +873,8 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
http_sock->tls.ctx = NULL;
|
||||
isc_nmhandle_attach(handle, &session->handle);
|
||||
isc__nmsocket_attach(handle->sock, &http_sock->h2.connect.transport);
|
||||
transp_sock->h2.session = session;
|
||||
http_sock->h2.session = session;
|
||||
session_attach(session, &transp_sock->h2.session);
|
||||
session_attach(session, &http_sock->h2.session);
|
||||
|
||||
if (session->tlsctx != NULL) {
|
||||
const unsigned char *alpn = NULL;
|
||||
@@ -854,7 +895,7 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
|
||||
initialize_nghttp2_client_session(session);
|
||||
if (!send_client_connection_header(session)) {
|
||||
transp_sock->h2.session = NULL;
|
||||
session_detach(&transp_sock->h2.session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -867,6 +908,7 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
http_call_connect_cb(http_sock, result);
|
||||
http_do_bio(session);
|
||||
isc__nmsocket_detach(&http_sock);
|
||||
session_detach(&session);
|
||||
return;
|
||||
|
||||
error:
|
||||
@@ -879,6 +921,10 @@ error:
|
||||
isc_mem_free(mctx, http_sock->h2.connect.uri);
|
||||
}
|
||||
|
||||
if (session != NULL) {
|
||||
session_detach(&session);
|
||||
}
|
||||
|
||||
isc__nmsocket_detach(&http_sock);
|
||||
}
|
||||
|
||||
@@ -1736,15 +1782,10 @@ httplisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
session = isc_mem_get(httplistensock->mgr->mctx,
|
||||
sizeof(isc_nm_http_session_t));
|
||||
*session = (isc_nm_http_session_t){ .magic = HTTP2_SESSION_MAGIC,
|
||||
.free_tlsctx = false,
|
||||
.client = false };
|
||||
new_session(httplistensock->mgr->mctx, NULL, &session);
|
||||
initialize_nghttp2_server_session(session);
|
||||
handle->sock->h2.session = session;
|
||||
|
||||
isc_mem_attach(httplistensock->mgr->mctx, &session->mctx);
|
||||
isc_nmhandle_attach(handle, &session->handle);
|
||||
isc__nmsocket_attach(httplistensock, &session->serversocket);
|
||||
session->serversocket = httplistensock;
|
||||
@@ -1901,16 +1942,6 @@ clear_handlers(isc_nmsocket_t *sock) {
|
||||
RWUNLOCK(&sock->h2.lock, isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_session(isc_nmsocket_t *sock) {
|
||||
if (sock->h2.session != NULL) {
|
||||
isc_nm_http_session_t *session = sock->h2.session;
|
||||
finish_http_session(session);
|
||||
delete_http_session(session);
|
||||
sock->h2.session = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_async_httpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
isc__netievent_httpstop_t *ievent = (isc__netievent_httpstop_t *)ev0;
|
||||
@@ -2256,7 +2287,9 @@ isc__nm_http_cleanup_data(isc_nmsocket_t *sock) {
|
||||
sock->h2.buf = NULL;
|
||||
}
|
||||
|
||||
clear_session(sock);
|
||||
if (sock->h2.session != NULL) {
|
||||
session_detach(&sock->h2.session);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -157,8 +157,6 @@ isc__nm_dump_active(isc_nm_t *nm);
|
||||
#define isc__nmsocket_prep_destroy(sock) isc___nmsocket_prep_destroy(sock)
|
||||
#endif
|
||||
|
||||
typedef struct isc_nm_http_session isc_nm_http_session_t;
|
||||
|
||||
/*
|
||||
* Single network event loop worker.
|
||||
*/
|
||||
@@ -196,6 +194,7 @@ typedef struct isc__networker {
|
||||
atomic_load(&(t)->references) > 0)
|
||||
|
||||
typedef void (*isc__nm_closecb)(isc_nmhandle_t *);
|
||||
typedef struct isc_nm_http_session isc_nm_http_session_t;
|
||||
|
||||
struct isc_nmhandle {
|
||||
int magic;
|
||||
|
||||
Reference in New Issue
Block a user