📄 sip_reg.c
字号:
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;
}
}
/* Add additional request headers */
if (!pj_list_empty(®c->hdr_list)) {
const pjsip_hdr *hdr;
hdr = regc->hdr_list.next;
while (hdr != ®c->hdr_list) {
pjsip_hdr *new_hdr = pjsip_hdr_shallow_clone(tdata->pool, hdr);
pjsip_msg_add_hdr(tdata->msg, new_hdr);
hdr = hdr->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_shallow_clone(tdata->pool,
regc->contact_hdr));
if (regc->expires_hdr)
pjsip_msg_add_hdr(msg, pjsip_hdr_shallow_clone(tdata->pool,
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_shallow_clone(tdata->pool,
regc->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_unregister_all(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;
if (!regc->cb)
return;
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);
/* Temporarily increase busy flag to prevent regc from being deleted
* in pjsip_regc_send()
*/
regc->busy++;
entry->id = 0;
status = pjsip_regc_register(regc, 1, &tdata);
if (status == PJ_SUCCESS) {
status = pjsip_regc_send(regc, tdata);
}
if (status != PJ_SUCCESS && regc->cb) {
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);
}
regc->busy--;
/* Delete the record if user destroy regc during the callback. */
if (regc->_delete_flag && regc->busy==0) {
pjsip_regc_destroy(regc);
}
}
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->has_tsx);
regc->has_tsx = PJ_FALSE;
/* Handle 401/407 challenge (even when _delete_flag is set) */
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) {
/* Only call callback if application is still interested
* in it.
*/
if (regc->_delete_flag == 0) {
/* Increment busy flag temporarily to prevent regc from
* being destroyed.
*/
++regc->busy;
call_callback(regc, status, tsx->status_code,
&rdata->msg_info.msg->line.status.reason,
rdata, -1, 0, NULL);
/* Decrement busy flag */
--regc->busy;
}
}
} else if (regc->_delete_flag) {
/* User has called pjsip_regc_destroy(), so don't call callback.
* This regc will be destroyed later in this function.
*/
/* Nothing to do */
;
} 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;
}
/* Increment busy flag temporarily to prevent regc from
* being destroyed.
*/
++regc->busy;
/* 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);
/* Decrement busy flag */
--regc->busy;
}
/* Delete the record if user destroy regc during the callback. */
if (regc->_delete_flag && regc->busy==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->has_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->has_tsx = PJ_TRUE;
++regc->busy;
status = pjsip_endpt_send_request(regc->endpt, tdata, REGC_TSX_TIMEOUT,
regc, &tsx_callback);
if (status!=PJ_SUCCESS) {
PJ_LOG(4,(THIS_FILE, "Error sending request, status=%d", status));
}
--regc->busy;
/* Delete the record if user destroy regc during the callback. */
if (regc->_delete_flag && regc->busy==0) {
pjsip_regc_destroy(regc);
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -