Re #1929: Avoid memory pool growing when doing re-Registration.

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@5336 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Riza Sulistyo 2016-06-07 10:07:57 +00:00
parent 24200380fa
commit e05bd3c197
4 changed files with 74 additions and 17 deletions

View File

@ -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. */

View File

@ -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.

View File

@ -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(&regc->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 != &regc->auth_sess.cached_auth) {
pjsip_endpt_release_pool(regc->endpt, auth->pool);
auth = auth->next;
}
pjsip_endpt_release_pool(regc->endpt, regc->pool);
}

View File

@ -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);