diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-08-15 13:11:22 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-08-15 13:11:22 +0000 |
commit | 2b4ce727a94196b76c3d2e6bf3f43c201207b82c (patch) | |
tree | dfbe08872ec71616ef3c34a56e461695b7581d9c /pjsip/src | |
parent | a3efa6db12c8d49a7021150e803e3183def178b0 (diff) |
Added initial PUBLISH client support, and also default account selection in pjsua/pjsua-lib
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@683 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src')
-rw-r--r-- | pjsip/src/pjsip-simple/publishc.c | 634 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_acc.c | 43 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_pres.c | 14 |
3 files changed, 682 insertions, 9 deletions
diff --git a/pjsip/src/pjsip-simple/publishc.c b/pjsip/src/pjsip-simple/publishc.c new file mode 100644 index 00000000..b61fa469 --- /dev/null +++ b/pjsip/src/pjsip-simple/publishc.c @@ -0,0 +1,634 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <pjsip-ua/sip_regc.h> +#include <pjsip/sip_endpoint.h> +#include <pjsip/sip_parser.h> +#include <pjsip/sip_module.h> +#include <pjsip/sip_transaction.h> +#include <pjsip/sip_event.h> +#include <pjsip/sip_util.h> +#include <pjsip/sip_auth_msg.h> +#include <pjsip/sip_errno.h> +#include <pj/assert.h> +#include <pj/guid.h> +#include <pj/os.h> +#include <pj/pool.h> +#include <pj/log.h> +#include <pj/rand.h> +#include <pj/string.h> + + +#define REFRESH_TIMER 1 +#define DELAY_BEFORE_REFRESH 5 +#define THIS_FILE "sip_regc.c" + +/** + * SIP client registration structure. + */ +struct pjsip_regc +{ + pj_pool_t *pool; + pjsip_endpoint *endpt; + pj_bool_t _delete_flag; + int pending_tsx; + + void *token; + pjsip_regc_cb *cb; + + pj_str_t str_srv_url; + pjsip_uri *srv_url; + pjsip_cid_hdr *cid_hdr; + pjsip_cseq_hdr *cseq_hdr; + pj_str_t from_uri; + pjsip_from_hdr *from_hdr; + pjsip_to_hdr *to_hdr; + char *contact_buf; + pjsip_generic_string_hdr *contact_hdr; + pjsip_expires_hdr *expires_hdr; + pjsip_contact_hdr *unreg_contact_hdr; + pjsip_expires_hdr *unreg_expires_hdr; + pj_uint32_t expires; + pjsip_route_hdr route_set; + + /* Authorization sessions. */ + pjsip_auth_clt_sess auth_sess; + + /* Auto refresh registration. */ + pj_bool_t auto_reg; + pj_time_val last_reg; + pj_time_val next_reg; + pj_timer_entry timer; +}; + + + +PJ_DEF(pj_status_t) pjsip_regc_create( pjsip_endpoint *endpt, void *token, + pjsip_regc_cb *cb, + pjsip_regc **p_regc) +{ + pj_pool_t *pool; + pjsip_regc *regc; + pj_status_t status; + + /* Verify arguments. */ + PJ_ASSERT_RETURN(endpt && cb && p_regc, PJ_EINVAL); + + pool = pjsip_endpt_create_pool(endpt, "regc%p", 1024, 1024); + PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); + + regc = pj_pool_zalloc(pool, sizeof(struct pjsip_regc)); + + regc->pool = pool; + regc->endpt = endpt; + regc->token = token; + regc->cb = cb; + regc->contact_buf = pj_pool_alloc(pool, PJSIP_REGC_CONTACT_BUF_SIZE); + regc->expires = PJSIP_REGC_EXPIRATION_NOT_SPECIFIED; + + status = pjsip_auth_clt_init(®c->auth_sess, endpt, regc->pool, 0); + if (status != PJ_SUCCESS) + return status; + + pj_list_init(®c->route_set); + + /* Done */ + *p_regc = regc; + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc) +{ + PJ_ASSERT_RETURN(regc, PJ_EINVAL); + + if (regc->pending_tsx) { + regc->_delete_flag = 1; + regc->cb = NULL; + } else { + pjsip_endpt_release_pool(regc->endpt, regc->pool); + } + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pjsip_regc_get_info( pjsip_regc *regc, + pjsip_regc_info *info ) +{ + PJ_ASSERT_RETURN(regc && info, PJ_EINVAL); + + info->server_uri = regc->str_srv_url; + info->client_uri = regc->from_uri; + info->is_busy = (regc->pending_tsx != 0); + info->auto_reg = regc->auto_reg; + info->interval = regc->expires; + + if (regc->pending_tsx) + info->next_reg = 0; + else if (regc->auto_reg == 0) + info->next_reg = 0; + else if (regc->expires < 0) + info->next_reg = regc->expires; + else { + pj_time_val now, next_reg; + + next_reg = regc->next_reg; + pj_gettimeofday(&now); + PJ_TIME_VAL_SUB(next_reg, now); + info->next_reg = next_reg.sec; + } + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_pool_t*) pjsip_regc_get_pool(pjsip_regc *regc) +{ + return regc->pool; +} + +static void set_expires( pjsip_regc *regc, pj_uint32_t expires) +{ + if (expires != regc->expires) { + regc->expires_hdr = pjsip_expires_hdr_create(regc->pool, expires); + } else { + regc->expires_hdr = NULL; + } +} + + +static pj_status_t set_contact( pjsip_regc *regc, + int contact_cnt, + const pj_str_t contact[] ) +{ + int i; + char *s; + const pj_str_t contact_STR = { "Contact", 7}; + + /* Concatenate contacts. */ + for (i=0, s=regc->contact_buf; i<contact_cnt; ++i) { + if ((s-regc->contact_buf) + contact[i].slen + 2 > PJSIP_REGC_CONTACT_BUF_SIZE) { + return PJSIP_EURITOOLONG; + } + pj_memcpy(s, contact[i].ptr, contact[i].slen); + s += contact[i].slen; + + if (i != contact_cnt - 1) { + *s++ = ','; + *s++ = ' '; + } + } + + /* Set "Contact" header. */ + regc->contact_hdr = pjsip_generic_string_hdr_create(regc->pool, + &contact_STR, + NULL); + regc->contact_hdr->hvalue.ptr = regc->contact_buf; + regc->contact_hdr->hvalue.slen = (s - regc->contact_buf); + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pjsip_regc_init( pjsip_regc *regc, + const pj_str_t *srv_url, + const pj_str_t *from_url, + const pj_str_t *to_url, + int contact_cnt, + const pj_str_t contact[], + pj_uint32_t expires) +{ + pj_str_t tmp; + pj_status_t status; + + PJ_ASSERT_RETURN(regc && srv_url && from_url && to_url && + contact_cnt && contact && expires, PJ_EINVAL); + + /* Copy server URL. */ + pj_strdup_with_null(regc->pool, ®c->str_srv_url, srv_url); + + /* Set server URL. */ + tmp = regc->str_srv_url; + regc->srv_url = pjsip_parse_uri( regc->pool, tmp.ptr, tmp.slen, 0); + if (regc->srv_url == NULL) { + return PJSIP_EINVALIDURI; + } + + /* Set "From" header. */ + pj_strdup_with_null(regc->pool, ®c->from_uri, from_url); + tmp = regc->from_uri; + regc->from_hdr = pjsip_from_hdr_create(regc->pool); + regc->from_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen, + PJSIP_PARSE_URI_AS_NAMEADDR); + if (!regc->from_hdr->uri) { + PJ_LOG(4,(THIS_FILE, "regc: invalid source URI %.*s", + from_url->slen, from_url->ptr)); + return PJSIP_EINVALIDURI; + } + + /* Set "To" header. */ + pj_strdup_with_null(regc->pool, &tmp, to_url); + regc->to_hdr = pjsip_to_hdr_create(regc->pool); + regc->to_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen, + PJSIP_PARSE_URI_AS_NAMEADDR); + if (!regc->to_hdr->uri) { + PJ_LOG(4,(THIS_FILE, "regc: invalid target URI %.*s", to_url->slen, to_url->ptr)); + return PJSIP_EINVALIDURI; + } + + + /* Set "Contact" header. */ + status = set_contact( regc, contact_cnt, contact); + if (status != PJ_SUCCESS) + return status; + + /* Set "Expires" header, if required. */ + set_expires( regc, expires); + + /* Set "Call-ID" header. */ + regc->cid_hdr = pjsip_cid_hdr_create(regc->pool); + pj_create_unique_string(regc->pool, ®c->cid_hdr->id); + + /* Set "CSeq" header. */ + regc->cseq_hdr = pjsip_cseq_hdr_create(regc->pool); + regc->cseq_hdr->cseq = pj_rand() % 0xFFFF; + pjsip_method_set( ®c->cseq_hdr->method, PJSIP_REGISTER_METHOD); + + /* Create "Contact" header used in unregistration. */ + regc->unreg_contact_hdr = pjsip_contact_hdr_create(regc->pool); + regc->unreg_contact_hdr->star = 1; + + /* Create "Expires" header used in unregistration. */ + regc->unreg_expires_hdr = pjsip_expires_hdr_create( regc->pool, 0); + + /* Done. */ + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc, + int count, + const pjsip_cred_info cred[] ) +{ + PJ_ASSERT_RETURN(regc && count && cred, PJ_EINVAL); + return pjsip_auth_clt_set_credentials(®c->auth_sess, count, cred); +} + +PJ_DEF(pj_status_t) pjsip_regc_set_route_set( pjsip_regc *regc, + const pjsip_route_hdr *route_set) +{ + const pjsip_route_hdr *chdr; + + PJ_ASSERT_RETURN(regc && route_set, PJ_EINVAL); + + pj_list_init(®c->route_set); + + chdr = route_set->next; + while (chdr != route_set) { + pj_list_push_back(®c->route_set, pjsip_hdr_clone(regc->pool, chdr)); + chdr = chdr->next; + } + + return PJ_SUCCESS; +} + +static pj_status_t create_request(pjsip_regc *regc, + pjsip_tx_data **p_tdata) +{ + pj_status_t status; + pjsip_tx_data *tdata; + + PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL); + + /* Create the request. */ + status = pjsip_endpt_create_request_from_hdr( regc->endpt, + &pjsip_register_method, + regc->srv_url, + regc->from_hdr, + regc->to_hdr, + NULL, + regc->cid_hdr, + regc->cseq_hdr->cseq, + NULL, + &tdata); + if (status != PJ_SUCCESS) + return status; + + /* Add cached authorization headers. */ + pjsip_auth_clt_init_req( ®c->auth_sess, tdata ); + + /* Add Route headers from route set, ideally after Via header */ + if (!pj_list_empty(®c->route_set)) { + pjsip_hdr *route_pos; + const pjsip_route_hdr *route; + + route_pos = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); + if (!route_pos) + route_pos = &tdata->msg->hdr; + + route = regc->route_set.next; + while (route != ®c->route_set) { + pjsip_hdr *new_hdr = pjsip_hdr_shallow_clone(tdata->pool, route); + pj_list_insert_after(route_pos, new_hdr); + route_pos = new_hdr; + route = route->next; + } + } + + /* Done. */ + *p_tdata = tdata; + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg, + pjsip_tx_data **p_tdata) +{ + pjsip_msg *msg; + pj_status_t status; + pjsip_tx_data *tdata; + + PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL); + + status = create_request(regc, &tdata); + if (status != PJ_SUCCESS) + return status; + + /* Add Contact header. */ + msg = tdata->msg; + pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->contact_hdr); + if (regc->expires_hdr) + pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->expires_hdr); + + if (regc->timer.id != 0) { + pjsip_endpt_cancel_timer(regc->endpt, ®c->timer); + regc->timer.id = 0; + } + + regc->auto_reg = autoreg; + + /* Done */ + *p_tdata = tdata; + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pjsip_regc_unregister(pjsip_regc *regc, + pjsip_tx_data **p_tdata) +{ + pjsip_tx_data *tdata; + pjsip_msg *msg; + pj_status_t status; + + PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL); + + if (regc->timer.id != 0) { + pjsip_endpt_cancel_timer(regc->endpt, ®c->timer); + regc->timer.id = 0; + } + + status = create_request(regc, &tdata); + if (status != PJ_SUCCESS) + return status; + + msg = tdata->msg; + pjsip_msg_add_hdr( msg, (pjsip_hdr*)regc->unreg_contact_hdr); + pjsip_msg_add_hdr( msg, (pjsip_hdr*)regc->unreg_expires_hdr); + + *p_tdata = tdata; + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pjsip_regc_update_contact( pjsip_regc *regc, + int contact_cnt, + const pj_str_t contact[] ) +{ + PJ_ASSERT_RETURN(regc, PJ_EINVAL); + return set_contact( regc, contact_cnt, contact ); +} + + +PJ_DEF(pj_status_t) pjsip_regc_update_expires( pjsip_regc *regc, + pj_uint32_t expires ) +{ + PJ_ASSERT_RETURN(regc, PJ_EINVAL); + set_expires( regc, expires ); + return PJ_SUCCESS; +} + + +static void call_callback(pjsip_regc *regc, pj_status_t status, int st_code, + const pj_str_t *reason, + pjsip_rx_data *rdata, pj_int32_t expiration, + int contact_cnt, pjsip_contact_hdr *contact[]) +{ + struct pjsip_regc_cbparam cbparam; + + + cbparam.regc = regc; + cbparam.token = regc->token; + cbparam.status = status; + cbparam.code = st_code; + cbparam.reason = *reason; + cbparam.rdata = rdata; + cbparam.contact_cnt = contact_cnt; + cbparam.expiration = expiration; + if (contact_cnt) { + pj_memcpy( cbparam.contact, contact, + contact_cnt*sizeof(pjsip_contact_hdr*)); + } + + (*regc->cb)(&cbparam); +} + +static void regc_refresh_timer_cb( pj_timer_heap_t *timer_heap, + struct pj_timer_entry *entry) +{ + pjsip_regc *regc = entry->user_data; + pjsip_tx_data *tdata; + pj_status_t status; + + PJ_UNUSED_ARG(timer_heap); + + entry->id = 0; + status = pjsip_regc_register(regc, 1, &tdata); + if (status == PJ_SUCCESS) { + status = pjsip_regc_send(regc, tdata); + } + + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + pj_str_t reason = pj_strerror(status, errmsg, sizeof(errmsg)); + call_callback(regc, status, 400, &reason, NULL, -1, 0, NULL); + } +} + +static void tsx_callback(void *token, pjsip_event *event) +{ + pj_status_t status; + pjsip_regc *regc = token; + pjsip_transaction *tsx = event->body.tsx_state.tsx; + + /* Decrement pending transaction counter. */ + pj_assert(regc->pending_tsx > 0); + --regc->pending_tsx; + + /* If registration data has been deleted by user then remove registration + * data from transaction's callback, and don't call callback. + */ + if (regc->_delete_flag) { + + /* Nothing to do */ + ; + + } else if (tsx->status_code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED || + tsx->status_code == PJSIP_SC_UNAUTHORIZED) + { + pjsip_rx_data *rdata = event->body.tsx_state.src.rdata; + pjsip_tx_data *tdata; + + status = pjsip_auth_clt_reinit_req( ®c->auth_sess, + rdata, + tsx->last_tx, + &tdata); + + if (status == PJ_SUCCESS) { + status = pjsip_regc_send(regc, tdata); + } + + if (status != PJ_SUCCESS) { + call_callback(regc, status, tsx->status_code, + &rdata->msg_info.msg->line.status.reason, + rdata, -1, 0, NULL); + } + + return; + + } else { + int contact_cnt = 0; + pjsip_contact_hdr *contact[PJSIP_REGC_MAX_CONTACT]; + pjsip_rx_data *rdata; + pj_int32_t expiration = 0xFFFF; + + if (tsx->status_code/100 == 2) { + int i; + pjsip_contact_hdr *hdr; + pjsip_msg *msg; + pjsip_expires_hdr *expires; + + rdata = event->body.tsx_state.src.rdata; + msg = rdata->msg_info.msg; + hdr = pjsip_msg_find_hdr( msg, PJSIP_H_CONTACT, NULL); + while (hdr) { + contact[contact_cnt++] = hdr; + hdr = hdr->next; + if (hdr == (void*)&msg->hdr) + break; + hdr = pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, hdr); + } + + expires = pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL); + + if (expires) + expiration = expires->ivalue; + + for (i=0; i<contact_cnt; ++i) { + hdr = contact[i]; + if (hdr->expires >= 0 && hdr->expires < expiration) + expiration = contact[i]->expires; + } + + if (regc->auto_reg && expiration != 0 && expiration != 0xFFFF) { + pj_time_val delay = { 0, 0}; + + delay.sec = expiration - DELAY_BEFORE_REFRESH; + if (regc->expires != PJSIP_REGC_EXPIRATION_NOT_SPECIFIED && + delay.sec > (pj_int32_t)regc->expires) + { + delay.sec = regc->expires; + } + if (delay.sec < DELAY_BEFORE_REFRESH) + delay.sec = DELAY_BEFORE_REFRESH; + regc->timer.cb = ®c_refresh_timer_cb; + regc->timer.id = REFRESH_TIMER; + regc->timer.user_data = regc; + pjsip_endpt_schedule_timer( regc->endpt, ®c->timer, &delay); + pj_gettimeofday(®c->last_reg); + regc->next_reg = regc->last_reg; + regc->next_reg.sec += delay.sec; + } + + } else { + rdata = (event->body.tsx_state.type==PJSIP_EVENT_RX_MSG) ? + event->body.tsx_state.src.rdata : NULL; + } + + + /* Call callback. */ + if (expiration == 0xFFFF) expiration = -1; + call_callback(regc, PJ_SUCCESS, tsx->status_code, + (rdata ? &rdata->msg_info.msg->line.status.reason + : pjsip_get_status_text(tsx->status_code)), + rdata, expiration, + contact_cnt, contact); + + } + + /* Delete the record if user destroy regc during the callback. */ + if (regc->_delete_flag && regc->pending_tsx==0) { + pjsip_regc_destroy(regc); + } +} + +PJ_DEF(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata) +{ + pj_status_t status; + pjsip_cseq_hdr *cseq_hdr; + pj_uint32_t cseq; + + /* Make sure we don't have pending transaction. */ + if (regc->pending_tsx) { + PJ_LOG(4,(THIS_FILE, "Unable to send request, regc has another " + "transaction pending")); + pjsip_tx_data_dec_ref( tdata ); + return PJSIP_EBUSY; + } + + /* Invalidate message buffer. */ + pjsip_tx_data_invalidate_msg(tdata); + + /* Increment CSeq */ + cseq = ++regc->cseq_hdr->cseq; + cseq_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL); + cseq_hdr->cseq = cseq; + + /* Increment pending transaction first, since transaction callback + * may be called even before send_request() returns! + */ + ++regc->pending_tsx; + status = pjsip_endpt_send_request(regc->endpt, tdata, -1, regc, &tsx_callback); + if (status!=PJ_SUCCESS) { + --regc->pending_tsx; + PJ_LOG(4,(THIS_FILE, "Error sending request, status=%d", status)); + } + + return status; +} + + diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index 05815ede..7860c33f 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -43,6 +43,25 @@ PJ_DEF(pj_bool_t) pjsua_acc_is_valid(pjsua_acc_id acc_id) /* + * Set default account + */ +PJ_DEF(pj_status_t) pjsua_acc_set_default(pjsua_acc_id acc_id) +{ + pjsua_var.default_acc = acc_id; + return PJ_SUCCESS; +} + + +/* + * Get default account. + */ +PJ_DEF(pjsua_acc_id) pjsua_acc_get_default(void) +{ + return pjsua_var.default_acc; +} + + +/* * Copy account configuration. */ static void copy_acc_config(pj_pool_t *pool, @@ -724,13 +743,25 @@ PJ_DEF(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url) sip_uri = pjsip_uri_get_uri(uri); + /* See if default acc match */ + if (pjsua_var.default_acc != PJSUA_INVALID_ID && + pj_stricmp(&pjsua_var.acc[pjsua_var.default_acc].srv_domain, &sip_uri->host)==0 && + pjsua_var.acc[pjsua_var.default_acc].srv_port == sip_uri->port) + { + acc_id = pjsua_var.default_acc; + } else { + acc_id = PJ_ARRAY_SIZE(pjsua_var.acc); + } + /* Find matching domain AND port */ - for (acc_id=0; acc_id<PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) { - if (!pjsua_var.acc[acc_id].valid) - continue; - if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0 && - pjsua_var.acc[acc_id].srv_port == sip_uri->port) - break; + if (acc_id == PJ_ARRAY_SIZE(pjsua_var.acc)) { + for (acc_id=0; acc_id<PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) { + if (!pjsua_var.acc[acc_id].valid) + continue; + if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0 && + pjsua_var.acc[acc_id].srv_port == sip_uri->port) + break; + } } /* If no match, try to match the domain part only */ diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c index cba0724c..ceb1b762 100644 --- a/pjsip/src/pjsua-lib/pjsua_pres.c +++ b/pjsip/src/pjsua-lib/pjsua_pres.c @@ -543,8 +543,10 @@ static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata) /* Create and send the first NOTIFY to active subscription: */ status = pjsip_pres_notify( sub, PJSIP_EVSUB_STATE_ACTIVE, NULL, NULL, &tdata); - if (status == PJ_SUCCESS) + if (status == PJ_SUCCESS) { + pjsua_process_msg_data(tdata, NULL); status = pjsip_pres_send_request( sub, tdata); + } if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create/send NOTIFY", @@ -611,8 +613,10 @@ static void refresh_server_subscription(int acc_id) pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status; pjsip_pres_set_status(uapres->sub, &pres_status); - if (pjsip_pres_current_notify(uapres->sub, &tdata)==PJ_SUCCESS) + if (pjsip_pres_current_notify(uapres->sub, &tdata)==PJ_SUCCESS) { + pjsua_process_msg_data(tdata, NULL); pjsip_pres_send_request(uapres->sub, tdata); + } } uapres = uapres->next; @@ -835,6 +839,8 @@ static void subscribe_buddy_presence(unsigned index) return; } + pjsua_process_msg_data(tdata, NULL); + status = pjsip_pres_send_request(buddy->sub, tdata); if (status != PJ_SUCCESS) { pjsip_pres_terminate(buddy->sub, PJ_FALSE); @@ -864,8 +870,10 @@ static void unsubscribe_buddy_presence(unsigned index) } status = pjsip_pres_initiate( buddy->sub, 0, &tdata); - if (status == PJ_SUCCESS) + if (status == PJ_SUCCESS) { + pjsua_process_msg_data(tdata, NULL); status = pjsip_pres_send_request( buddy->sub, tdata ); + } if (status != PJ_SUCCESS) { pjsip_pres_terminate(buddy->sub, PJ_FALSE); |