📄 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 + -