From c95d1a0f5bbf0d68ba6ab45416d482165bb7c8dc Mon Sep 17 00:00:00 2001 From: Riza Sulistyo Date: Tue, 7 Jun 2016 10:07:57 +0000 Subject: Re #1929: Avoid memory pool growing when doing re-Registration. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5336 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsip/sip_auth.h | 1 + pjsip/include/pjsip/sip_config.h | 10 ++++++ pjsip/src/pjsip-ua/sip_reg.c | 8 +++++ pjsip/src/pjsip/sip_auth_client.c | 72 ++++++++++++++++++++++++++++++--------- 4 files changed, 74 insertions(+), 17 deletions(-) (limited to 'pjsip') diff --git a/pjsip/include/pjsip/sip_auth.h b/pjsip/include/pjsip/sip_auth.h index ce262ef9..ba03f600 100644 --- a/pjsip/include/pjsip/sip_auth.h +++ b/pjsip/include/pjsip/sip_auth.h @@ -166,6 +166,7 @@ typedef struct pjsip_cached_auth /** Standard list member */ PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth); + pj_pool_t *pool; /**< Pool for cached auth */ pj_str_t realm; /**< Realm. */ pj_bool_t is_proxy; /**< Server type (401/407) */ pjsip_auth_qop_type qop_value; /**< qop required by server. */ diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h index 210c6650..1c974812 100644 --- a/pjsip/include/pjsip/sip_config.h +++ b/pjsip/include/pjsip/sip_config.h @@ -1122,6 +1122,16 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void) # define PJSIP_REGISTER_CLIENT_ADD_XUID_PARAM 0 #endif +/** + * Maximum size of pool allowed for auth client session in pjsip_regc. + * After the size exceeds because of Digest authentication processing, + * the pool is reset. + * + * Default is 20 kB + */ +#ifndef PJSIP_AUTH_CACHED_POOL_MAX_SIZE +# define PJSIP_AUTH_CACHED_POOL_MAX_SIZE (20 * 1024) +#endif /***************************************************************************** * SIP Event framework and presence settings. diff --git a/pjsip/src/pjsip-ua/sip_reg.c b/pjsip/src/pjsip-ua/sip_reg.c index bdb0460b..52a55632 100644 --- a/pjsip/src/pjsip-ua/sip_reg.c +++ b/pjsip/src/pjsip-ua/sip_reg.c @@ -176,6 +176,7 @@ PJ_DEF(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc) regc->cb = NULL; pj_lock_release(regc->lock); } else { + pjsip_cached_auth *auth = NULL; pjsip_tpselector_dec_ref(®c->tp_sel); if (regc->last_transport) { pjsip_transport_dec_ref(regc->last_transport); @@ -189,6 +190,13 @@ PJ_DEF(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc) pj_lock_release(regc->lock); pj_lock_destroy(regc->lock); regc->lock = NULL; + + auth = regc->auth_sess.cached_auth.next; + while (auth != ®c->auth_sess.cached_auth) { + pjsip_endpt_release_pool(regc->endpt, auth->pool); + auth = auth->next; + } + pjsip_endpt_release_pool(regc->endpt, regc->pool); } diff --git a/pjsip/src/pjsip/sip_auth_client.c b/pjsip/src/pjsip/sip_auth_client.c index 3b2ee372..6a4c10a7 100644 --- a/pjsip/src/pjsip/sip_auth_client.c +++ b/pjsip/src/pjsip/sip_auth_client.c @@ -357,15 +357,14 @@ static pj_status_t respond_digest( pj_pool_t *pool, /* * Update authentication session with a challenge. */ -static void update_digest_session( pj_pool_t *ses_pool, - pjsip_cached_auth *cached_auth, +static void update_digest_session( pjsip_cached_auth *cached_auth, const pjsip_www_authenticate_hdr *hdr ) { if (hdr->challenge.digest.qop.slen == 0) { #if PJSIP_AUTH_AUTO_SEND_NEXT!=0 if (!cached_auth->last_chal || pj_stricmp2(&hdr->scheme, "digest")) { cached_auth->last_chal = (pjsip_www_authenticate_hdr*) - pjsip_hdr_clone(ses_pool, hdr); + pjsip_hdr_clone(cached_auth->pool, hdr); } else { /* Only update if the new challenge is "significantly different" * than the one in the cache, to reduce memory usage. @@ -382,7 +381,7 @@ static void update_digest_session( pj_pool_t *ses_pool, pj_strcmp(&d1->qop, &d2->qop)) { cached_auth->last_chal = (pjsip_www_authenticate_hdr*) - pjsip_hdr_clone(ses_pool, hdr); + pjsip_hdr_clone(cached_auth->pool, hdr); } } #endif @@ -393,10 +392,10 @@ static void update_digest_session( pj_pool_t *ses_pool, if (cached_auth->cnonce.slen == 0) { /* Save the whole challenge */ cached_auth->last_chal = (pjsip_www_authenticate_hdr*) - pjsip_hdr_clone(ses_pool, hdr); + pjsip_hdr_clone(cached_auth->pool, hdr); /* Create cnonce */ - pj_create_unique_string( ses_pool, &cached_auth->cnonce ); + pj_create_unique_string( cached_auth->pool, &cached_auth->cnonce ); /* Initialize nonce-count */ cached_auth->nc = 1; @@ -406,7 +405,7 @@ static void update_digest_session( pj_pool_t *ses_pool, pj_assert(cached_auth->realm.slen != 0); */ if (cached_auth->realm.slen == 0) { - pj_strdup(ses_pool, &cached_auth->realm, + pj_strdup(cached_auth->pool, &cached_auth->realm, &hdr->challenge.digest.realm); } @@ -419,13 +418,14 @@ static void update_digest_session( pj_pool_t *ses_pool, ++cached_auth->nc; } else { /* Server gives new nonce. */ - pj_strdup(ses_pool, &cached_auth->last_chal->challenge.digest.nonce, + pj_strdup(cached_auth->pool, + &cached_auth->last_chal->challenge.digest.nonce, &hdr->challenge.digest.nonce); /* Has the opaque changed? */ if (pj_strcmp(&cached_auth->last_chal->challenge.digest.opaque, &hdr->challenge.digest.opaque)) { - pj_strdup(ses_pool, + pj_strdup(cached_auth->pool, &cached_auth->last_chal->challenge.digest.opaque, &hdr->challenge.digest.opaque); } @@ -691,7 +691,7 @@ static pj_status_t auth_respond( pj_pool_t *req_pool, # if PJSIP_AUTH_QOP_SUPPORT { if (cached_auth) { - update_digest_session( sess_pool, cached_auth, hdr ); + update_digest_session( cached_auth, hdr ); cnonce = &cached_auth->cnonce; nc = cached_auth->nc; @@ -961,6 +961,33 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, } +static void recreate_cached_auth_pool( pjsip_endpoint *endpt, + pjsip_cached_auth *auth ) +{ + pj_pool_t *auth_pool = pjsip_endpt_create_pool(endpt, "regc_auth%p", 1024, + 1024); + + if (auth->realm.slen) { + pj_str_t realm; + pj_strdup(auth_pool, &realm, &auth->realm); + pj_strassign(&auth->realm, &realm); + } + + if (auth->cnonce.slen) { + pj_str_t cnonce; + pj_strdup(auth_pool, &cnonce, &auth->cnonce); + pj_strassign(&auth->cnonce, &cnonce); + } + + if (auth->last_chal) { + auth->last_chal = (pjsip_www_authenticate_hdr*) + pjsip_hdr_clone(auth_pool, auth->last_chal); + } + + pjsip_endpt_release_pool(endpt, auth->pool); + auth->pool = auth_pool; +} + /* Process authorization challenge */ static pj_status_t process_auth( pj_pool_t *req_pool, const pjsip_www_authenticate_hdr *hchal, @@ -1126,33 +1153,44 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess, if (hdr == &rdata->msg_info.msg->hdr) break; - hchal = (const pjsip_www_authenticate_hdr*) hdr; + hchal = (const pjsip_www_authenticate_hdr*)hdr; ++chal_cnt; /* Find authentication session for this realm, create a new one * if not present. */ - cached_auth = find_cached_auth(sess, &hchal->challenge.common.realm ); + cached_auth = find_cached_auth(sess, &hchal->challenge.common.realm); if (!cached_auth) { - cached_auth = PJ_POOL_ZALLOC_T( sess->pool, pjsip_cached_auth); - pj_strdup( sess->pool, &cached_auth->realm, &hchal->challenge.common.realm); + cached_auth = PJ_POOL_ZALLOC_T(sess->pool, pjsip_cached_auth); + cached_auth->pool = pjsip_endpt_create_pool(sess->endpt, + "regc_auth%p", + 1024, + 1024); + pj_strdup(cached_auth->pool, &cached_auth->realm, + &hchal->challenge.common.realm); cached_auth->is_proxy = (hchal->type == PJSIP_H_PROXY_AUTHENTICATE); # if (PJSIP_AUTH_HEADER_CACHING) { pj_list_init(&cached_auth->cached_hdr); } # endif - pj_list_insert_before( &sess->cached_auth, cached_auth ); + pj_list_insert_before(&sess->cached_auth, cached_auth); } /* Create authorization header for this challenge, and update * authorization session. */ - status = process_auth( tdata->pool, hchal, tdata->msg->line.req.uri, - tdata, sess, cached_auth, &hauth); + status = process_auth(tdata->pool, hchal, tdata->msg->line.req.uri, + tdata, sess, cached_auth, &hauth); if (status != PJ_SUCCESS) return status; + if (pj_pool_get_used_size(cached_auth->pool) > + PJSIP_AUTH_CACHED_POOL_MAX_SIZE) + { + recreate_cached_auth_pool(sess->endpt, cached_auth); + } + /* Add to the message. */ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); -- cgit v1.2.3