From 003ffd64e31edf3dc3e087e51a6ce33228563386 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Sun, 13 Jul 2008 12:24:55 +0000 Subject: Ticket #518: some fixes for growing memory usage in PJSUA-LIB, by using temporary pools for temporary variables and by having separate pool for each account and buddy git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2130 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsua-lib/pjsua_internal.h | 2 ++ pjsip/src/pjsua-lib/pjsua_acc.c | 59 +++++++++++++++++++++++--------- pjsip/src/pjsua-lib/pjsua_call.c | 32 +++++++++-------- pjsip/src/pjsua-lib/pjsua_core.c | 17 +++++++-- pjsip/src/pjsua-lib/pjsua_pres.c | 39 ++++++++++++++++++--- 5 files changed, 112 insertions(+), 37 deletions(-) (limited to 'pjsip') diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h index 8d5a7b9d..3660540f 100644 --- a/pjsip/include/pjsua-lib/pjsua_internal.h +++ b/pjsip/include/pjsua-lib/pjsua_internal.h @@ -98,6 +98,7 @@ typedef struct pjsua_srv_pres */ typedef struct pjsua_acc { + pj_pool_t *pool; /**< Pool for this account. */ pjsua_acc_config cfg; /**< Account configuration. */ pj_bool_t valid; /**< Is this account valid? */ @@ -155,6 +156,7 @@ typedef struct pjsua_transport_data */ typedef struct pjsua_buddy { + pj_pool_t *pool; /**< Pool for this buddy. */ unsigned index; /**< Buddy index. */ pj_str_t uri; /**< Buddy URI. */ pj_str_t contact; /**< Contact learned from subscrp. */ diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index ac6d6171..008c439e 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -108,7 +108,7 @@ static pj_status_t initialize_acc(unsigned acc_id) /* Need to parse local_uri to get the elements: */ name_addr = (pjsip_name_addr*) - pjsip_parse_uri(pjsua_var.pool, acc_cfg->id.ptr, + pjsip_parse_uri(acc->pool, acc_cfg->id.ptr, acc_cfg->id.slen, PJSIP_PARSE_URI_AS_NAMEADDR); if (name_addr == NULL) { @@ -136,7 +136,7 @@ static pj_status_t initialize_acc(unsigned acc_id) if (acc_cfg->reg_uri.slen) { pjsip_uri *reg_uri; - reg_uri = pjsip_parse_uri(pjsua_var.pool, acc_cfg->reg_uri.ptr, + reg_uri = pjsip_parse_uri(acc->pool, acc_cfg->reg_uri.ptr, acc_cfg->reg_uri.slen, 0); if (reg_uri == NULL) { pjsua_perror(THIS_FILE, "Invalid registrar URI", @@ -187,10 +187,10 @@ static pj_status_t initialize_acc(unsigned acc_id) pjsip_route_hdr *r; pj_str_t tmp; - pj_strdup_with_null(pjsua_var.pool, &tmp, + pj_strdup_with_null(acc->pool, &tmp, &pjsua_var.ua_cfg.outbound_proxy[i]); r = (pjsip_route_hdr*) - pjsip_parse_hdr(pjsua_var.pool, &hname, tmp.ptr, tmp.slen, NULL); + pjsip_parse_hdr(acc->pool, &hname, tmp.ptr, tmp.slen, NULL); if (r == NULL) { pjsua_perror(THIS_FILE, "Invalid outbound proxy URI", PJSIP_EINVALIDURI); @@ -204,9 +204,9 @@ static pj_status_t initialize_acc(unsigned acc_id) pjsip_route_hdr *r; pj_str_t tmp; - pj_strdup_with_null(pjsua_var.pool, &tmp, &acc_cfg->proxy[i]); + pj_strdup_with_null(acc->pool, &tmp, &acc_cfg->proxy[i]); r = (pjsip_route_hdr*) - pjsip_parse_hdr(pjsua_var.pool, &hname, tmp.ptr, tmp.slen, NULL); + pjsip_parse_hdr(acc->pool, &hname, tmp.ptr, tmp.slen, NULL); if (r == NULL) { pjsua_perror(THIS_FILE, "Invalid URI in account route set", PJ_EINVAL); @@ -256,6 +256,7 @@ PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg, pj_bool_t is_default, pjsua_acc_id *p_acc_id) { + pjsua_acc *acc; unsigned id; pj_status_t status; @@ -277,8 +278,16 @@ PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg, PJ_ASSERT_ON_FAIL( id < PJ_ARRAY_SIZE(pjsua_var.acc), {PJSUA_UNLOCK(); return PJ_EBUG;}); + acc = &pjsua_var.acc[id]; + + /* Create pool for this account. */ + if (acc->pool) + pj_pool_reset(acc->pool); + else + acc->pool = pjsua_pool_create("acc%p", 512, 256); + /* Copy config */ - pjsua_acc_config_dup(pjsua_var.pool, &pjsua_var.acc[id].cfg, cfg); + pjsua_acc_config_dup(acc->pool, &pjsua_var.acc[id].cfg, cfg); /* Normalize registration timeout */ if (pjsua_var.acc[id].cfg.reg_uri.slen && @@ -290,6 +299,8 @@ PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg, status = initialize_acc(id); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Error adding account", status); + pj_pool_release(acc->pool); + acc->pool = NULL; PJSUA_UNLOCK(); return status; } @@ -399,6 +410,12 @@ PJ_DEF(pj_status_t) pjsua_acc_del(pjsua_acc_id acc_id) /* Delete server presence subscription */ pjsua_pres_delete_acc(acc_id); + /* Release account pool */ + if (pjsua_var.acc[acc_id].pool) { + pj_pool_release(pjsua_var.acc[acc_id].pool); + pjsua_var.acc[acc_id].pool = NULL; + } + /* Invalidate */ pjsua_var.acc[acc_id].valid = PJ_FALSE; @@ -471,8 +488,11 @@ PJ_DEF(pj_status_t) pjsua_acc_set_online_status2( pjsua_acc_id acc_id, PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_var.acc[acc_id].valid, PJ_EINVALIDOP); + PJSUA_LOCK(); pjsua_var.acc[acc_id].online_status = is_online; - pjrpid_element_dup(pjsua_var.pool, &pjsua_var.acc[acc_id].rpid, pr); + pjrpid_element_dup(pjsua_var.acc[acc_id].pool, &pjsua_var.acc[acc_id].rpid, pr); + PJSUA_UNLOCK(); + pjsua_pres_update_acc(acc_id, PJ_TRUE); return PJ_SUCCESS; } @@ -594,7 +614,7 @@ static pj_bool_t acc_check_nat_addr(pjsua_acc *acc, pj_pool_release(pool); return PJ_FALSE; } - pj_strdup2(pjsua_var.pool, &acc->contact, tmp); + pj_strdup2(acc->pool, &acc->contact, tmp); } /* For UDP transport, if STUN is enabled then update the transport's @@ -702,8 +722,8 @@ void update_service_route(pjsua_acc *acc, pjsip_rx_data *rdata) /* Then append the Service-Route URIs */ for (i=0; iname_addr.uri = (pjsip_uri*)pjsip_uri_clone(pjsua_var.pool, uri[i]); + hr = pjsip_route_hdr_create(acc->pool); + hr->name_addr.uri = (pjsip_uri*)pjsip_uri_clone(acc->pool, uri[i]); pj_list_push_back(&acc->route_set, hr); } @@ -982,7 +1002,7 @@ static pj_status_t pjsua_regc_init(int acc_id) return status; } - pj_strdup_with_null(pjsua_var.pool, &acc->contact, &tmp_contact); + pj_strdup_with_null(acc->pool, &acc->contact, &tmp_contact); } status = pjsip_regc_init( acc->regc, @@ -1267,16 +1287,18 @@ PJ_DEF(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url) pj_str_t tmp; pjsip_uri *uri; pjsip_sip_uri *sip_uri; + pj_pool_t *tmp_pool; unsigned i; PJSUA_LOCK(); - PJ_TODO(dont_use_pjsua_pool); + tmp_pool = pjsua_pool_create("tmpacc10", 256, 256); - pj_strdup_with_null(pjsua_var.pool, &tmp, url); + pj_strdup_with_null(tmp_pool, &tmp, url); - uri = pjsip_parse_uri(pjsua_var.pool, tmp.ptr, tmp.slen, 0); + uri = pjsip_parse_uri(tmp_pool, tmp.ptr, tmp.slen, 0); if (!uri) { + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return pjsua_var.default_acc; } @@ -1294,11 +1316,13 @@ PJ_DEF(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url) if (i != PJ_ARRAY_SIZE(pjsua_var.acc)) { /* Found rather matching account */ + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); - return 0; + return i; } /* Not found, use default account */ + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return pjsua_var.default_acc; } @@ -1311,6 +1335,7 @@ PJ_DEF(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url) if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0 && pjsua_var.acc[acc_id].srv_port == sip_uri->port) { + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return acc_id; } @@ -1321,6 +1346,7 @@ PJ_DEF(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url) unsigned acc_id = pjsua_var.acc_ids[i]; if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0) { + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return acc_id; } @@ -1328,6 +1354,7 @@ PJ_DEF(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url) /* Still no match, just use default account */ + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return pjsua_var.default_acc; } diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index f493c9d8..f3424a6e 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -330,6 +330,7 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, const pjsua_msg_data *msg_data, pjsua_call_id *p_call_id) { + pj_pool_t *tmp_pool; pjsip_dialog *dlg = NULL; pjmedia_sdp_session *offer; pjsip_inv_session *inv = NULL; @@ -382,30 +383,25 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, call = &pjsua_var.calls[call_id]; + /* Create temporary pool */ + tmp_pool = pjsua_pool_create("tmpcall10", 512, 256); + /* Verify that destination URI is valid before calling * pjsua_acc_create_uac_contact, or otherwise there * a misleading "Invalid Contact URI" error will be printed * when pjsua_acc_create_uac_contact() fails. */ if (1) { - pj_pool_t *pool; pjsip_uri *uri; pj_str_t dup; - pool = pjsua_pool_create("tmp-uri", 4000, 4000); - if (!pool) { - pjsua_perror(THIS_FILE, "Unable to create pool", PJ_ENOMEM); - PJSUA_UNLOCK(); - return PJ_ENOMEM; - } - - pj_strdup_with_null(pool, &dup, dest_uri); - uri = pjsip_parse_uri(pool, dup.ptr, dup.slen, 0); - pj_pool_release(pool); + pj_strdup_with_null(tmp_pool, &dup, dest_uri); + uri = pjsip_parse_uri(tmp_pool, dup.ptr, dup.slen, 0); if (uri == NULL) { pjsua_perror(THIS_FILE, "Unable to make call", PJSIP_EINVALIDREQURI); + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return PJSIP_EINVALIDREQURI; } @@ -426,11 +422,12 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, if (acc->contact.slen) { contact = acc->contact; } else { - status = pjsua_acc_create_uac_contact(pjsua_var.pool, &contact, + status = pjsua_acc_create_uac_contact(tmp_pool, &contact, acc_id, dest_uri); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to generate Contact header", status); + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return status; } @@ -442,6 +439,7 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, dest_uri, dest_uri, &dlg); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Dialog creation failed", status); + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return status; } @@ -549,6 +547,7 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, if (p_call_id) *p_call_id = call_id; + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return PJ_SUCCESS; @@ -566,6 +565,7 @@ on_error: pjsua_media_channel_deinit(call_id); } + pj_pool_release(tmp_pool); PJSUA_UNLOCK(); return status; } @@ -2617,17 +2617,21 @@ static pj_status_t create_inactive_sdp(pjsua_call *call, pjmedia_sdp_session **p_answer) { pj_status_t status; + pj_pool_t *pool; pjmedia_sdp_conn *conn; pjmedia_sdp_attr *attr; pjmedia_transport_info tp_info; pjmedia_sdp_session *sdp; + /* Use call's pool */ + pool = call->inv->pool; + /* Get media socket info */ pjmedia_transport_info_init(&tp_info); pjmedia_transport_get_info(call->med_tp, &tp_info); /* Create new offer */ - status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pjsua_var.pool, 1, + status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pool, 1, &tp_info.sock_info, &sdp); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create local SDP", status); @@ -2649,7 +2653,7 @@ static pj_status_t create_inactive_sdp(pjsua_call *call, pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); /* Add inactive attribute */ - attr = pjmedia_sdp_attr_create(pjsua_var.pool, "inactive", NULL); + attr = pjmedia_sdp_attr_create(pool, "inactive", NULL); pjmedia_sdp_media_add_attr(sdp->media[0], attr); *p_answer = sdp; diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 0bee539d..bc26f62e 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -580,7 +580,7 @@ PJ_DEF(pj_status_t) pjsua_create(void) pj_caching_pool_init(&pjsua_var.cp, NULL, 0); /* Create memory pool for application. */ - pjsua_var.pool = pjsua_pool_create("pjsua", 4000, 4000); + pjsua_var.pool = pjsua_pool_create("pjsua", 1000, 1000); PJ_ASSERT_RETURN(pjsua_var.pool, PJ_ENOMEM); @@ -1069,7 +1069,15 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) /* Terminate all presence subscriptions. */ pjsua_pres_shutdown(); - /* Unregister, if required: */ + /* Destroy pool in the buddy object */ + for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) { + if (pjsua_var.buddy[i].pool) { + pj_pool_release(pjsua_var.buddy[i].pool); + pjsua_var.buddy[i].pool = NULL; + } + } + + /* Destroy accounts */ for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { if (!pjsua_var.acc[i].valid) continue; @@ -1077,6 +1085,11 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) if (pjsua_var.acc[i].regc) { pjsua_acc_set_registration(i, PJ_FALSE); } + + if (pjsua_var.acc[i].pool) { + pj_pool_release(pjsua_var.acc[i].pool); + pjsua_var.acc[i].pool = NULL; + } } /* Wait for some time to allow unregistration to complete: */ diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c index c7a3ffc4..e1d71113 100644 --- a/pjsip/src/pjsua-lib/pjsua_pres.c +++ b/pjsip/src/pjsua-lib/pjsua_pres.c @@ -173,7 +173,9 @@ PJ_DEF(pj_status_t) pjsua_buddy_get_info( pjsua_buddy_id buddy_id, */ static void reset_buddy(pjsua_buddy_id id) { + pj_pool_t *pool = pjsua_var.buddy[id].pool; pj_bzero(&pjsua_var.buddy[id], sizeof(pjsua_var.buddy[id])); + pjsua_var.buddy[id].pool = pool; pjsua_var.buddy[id].index = id; } @@ -185,6 +187,7 @@ PJ_DEF(pj_status_t) pjsua_buddy_add( const pjsua_buddy_config *cfg, pjsua_buddy_id *p_buddy_id) { pjsip_name_addr *url; + pjsua_buddy *buddy; pjsip_sip_uri *sip_uri; int index; pj_str_t tmp; @@ -209,21 +212,37 @@ PJ_DEF(pj_status_t) pjsua_buddy_add( const pjsua_buddy_config *cfg, return PJ_ETOOMANY; } + buddy = &pjsua_var.buddy[index]; + + /* Create pool for this buddy */ + if (buddy->pool) { + pj_pool_reset(buddy->pool); + } else { + char name[PJ_MAX_OBJ_NAME]; + pj_ansi_snprintf(name, sizeof(name), "buddy%03d", index); + buddy->pool = pjsua_pool_create(name, 512, 256); + } /* Get name and display name for buddy */ - pj_strdup_with_null(pjsua_var.pool, &tmp, &cfg->uri); - url = (pjsip_name_addr*)pjsip_parse_uri(pjsua_var.pool, tmp.ptr, tmp.slen, + pj_strdup_with_null(buddy->pool, &tmp, &cfg->uri); + url = (pjsip_name_addr*)pjsip_parse_uri(buddy->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR); if (url == NULL) { pjsua_perror(THIS_FILE, "Unable to add buddy", PJSIP_EINVALIDURI); + pj_pool_release(buddy->pool); + buddy->pool = NULL; PJSUA_UNLOCK(); return PJSIP_EINVALIDURI; } /* Only support SIP schemes */ - if (!PJSIP_URI_SCHEME_IS_SIP(url) && !PJSIP_URI_SCHEME_IS_SIPS(url)) + if (!PJSIP_URI_SCHEME_IS_SIP(url) && !PJSIP_URI_SCHEME_IS_SIPS(url)) { + pj_pool_release(buddy->pool); + buddy->pool = NULL; + PJSUA_UNLOCK(); return PJSIP_EINVALIDSCHEME; + } /* Reset buddy, to make sure everything is cleared with default * values @@ -1049,7 +1068,7 @@ static void pjsua_evsub_on_tsx_state(pjsip_evsub *sub, } buddy->contact.ptr = (char*) - pj_pool_alloc(pjsua_var.pool, PJSIP_MAX_URL_SIZE); + pj_pool_alloc(buddy->pool, PJSIP_MAX_URL_SIZE); buddy->contact.slen = pjsip_uri_print( PJSIP_URI_IN_CONTACT_HDR, contact_hdr->uri, buddy->contact.ptr, @@ -1116,6 +1135,7 @@ static pjsip_evsub_user pres_callback = /* It does what it says.. */ static void subscribe_buddy_presence(unsigned index) { + pj_pool_t *tmp_pool = NULL; pjsua_buddy *buddy; int acc_id; pjsua_acc *acc; @@ -1137,11 +1157,14 @@ static void subscribe_buddy_presence(unsigned index) if (acc->contact.slen) { contact = acc->contact; } else { - status = pjsua_acc_create_uac_contact(pjsua_var.pool, &contact, + tmp_pool = pjsua_pool_create("tmpbuddy", 512, 256); + + status = pjsua_acc_create_uac_contact(tmp_pool, &contact, acc_id, &buddy->uri); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to generate Contact header", status); + pj_pool_release(tmp_pool); return; } } @@ -1155,6 +1178,7 @@ static void subscribe_buddy_presence(unsigned index) if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create dialog", status); + if (tmp_pool) pj_pool_release(tmp_pool); return; } @@ -1165,6 +1189,7 @@ static void subscribe_buddy_presence(unsigned index) pjsua_perror(THIS_FILE, "Unable to create presence client", status); pjsip_dlg_terminate(buddy->dlg); + if (tmp_pool) pj_pool_release(tmp_pool); return; } @@ -1202,6 +1227,7 @@ static void subscribe_buddy_presence(unsigned index) buddy->sub = NULL; pjsua_perror(THIS_FILE, "Unable to create initial SUBSCRIBE", status); + if (tmp_pool) pj_pool_release(tmp_pool); return; } @@ -1215,8 +1241,11 @@ static void subscribe_buddy_presence(unsigned index) buddy->sub = NULL; pjsua_perror(THIS_FILE, "Unable to send initial SUBSCRIBE", status); + if (tmp_pool) pj_pool_release(tmp_pool); return; } + + if (tmp_pool) pj_pool_release(tmp_pool); } -- cgit v1.2.3