📄 sip_xfer.c
字号:
refer_to_uri = &xfer->refer_to_uri;
} else {
pj_strdup(xfer->dlg->pool, &xfer->refer_to_uri, refer_to_uri);
}
/* Create and add Refer-To header. */
hdr = pjsip_generic_string_hdr_create(tdata->pool, &refer_to,
refer_to_uri);
if (!hdr) {
pjsip_tx_data_dec_ref(tdata);
status = PJ_ENOMEM;
goto on_return;
}
pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr);
/* Done. */
*p_tdata = tdata;
status = PJ_SUCCESS;
on_return:
pjsip_dlg_dec_lock(xfer->dlg);
return status;
}
/*
* Accept the incoming REFER request by sending 2xx response.
*
*/
PJ_DEF(pj_status_t) pjsip_xfer_accept( pjsip_evsub *sub,
pjsip_rx_data *rdata,
int st_code,
const pjsip_hdr *hdr_list )
{
/*
* Don't need to add custom headers, so just call basic
* evsub response.
*/
return pjsip_evsub_accept( sub, rdata, st_code, hdr_list );
}
/*
* For notifier, create NOTIFY request to subscriber, and set the state
* of the subscription.
*/
PJ_DEF(pj_status_t) pjsip_xfer_notify( pjsip_evsub *sub,
pjsip_evsub_state state,
int xfer_st_code,
const pj_str_t *xfer_st_text,
pjsip_tx_data **p_tdata)
{
pjsip_tx_data *tdata;
pjsip_xfer *xfer;
const pj_str_t reason = { "noresource", 10 };
char *body;
int bodylen;
pjsip_msg_body *msg_body;
pj_status_t status;
/* Check arguments. */
PJ_ASSERT_RETURN(sub, PJ_EINVAL);
/* Get the xfer object. */
xfer = pjsip_evsub_get_mod_data(sub, mod_xfer.id);
PJ_ASSERT_RETURN(xfer != NULL, PJSIP_ENOREFERSESSION);
/* Lock object. */
pjsip_dlg_inc_lock(xfer->dlg);
/* Create the NOTIFY request.
* Note that reason is only used when state is TERMINATED, and
* the defined termination reason for REFER is "noresource".
*/
status = pjsip_evsub_notify( sub, state, NULL, &reason, &tdata);
if (status != PJ_SUCCESS)
goto on_return;
/* Check status text */
if (xfer_st_text==NULL || xfer_st_text->slen==0)
xfer_st_text = pjsip_get_status_text(xfer_st_code);
/* Save st_code and st_text, for current_notify() */
xfer->last_st_code = xfer_st_code;
pj_strdup(xfer->dlg->pool, &xfer->last_st_text, xfer_st_text);
/* Create sipfrag content. */
body = pj_pool_alloc(tdata->pool, 128);
bodylen = pj_ansi_snprintf(body, 128, "SIP/2.0 %u %.*s",
xfer_st_code,
(int)xfer_st_text->slen,
xfer_st_text->ptr);
PJ_ASSERT_ON_FAIL(bodylen > 0 && bodylen < 128,
{status=PJ_EBUG; pjsip_tx_data_dec_ref(tdata);
goto on_return; });
/* Create SIP message body. */
msg_body = pj_pool_zalloc(tdata->pool, sizeof(pjsip_msg_body));
msg_body->content_type.type = STR_MESSAGE;
msg_body->content_type.subtype = STR_SIPFRAG;
msg_body->content_type.param = STR_SIPFRAG_VERSION;
msg_body->data = body;
msg_body->len = bodylen;
msg_body->print_body = &pjsip_print_text_body;
msg_body->clone_data = &pjsip_clone_text_data;
/* Attach sipfrag body. */
tdata->msg->body = msg_body;
/* Done. */
*p_tdata = tdata;
on_return:
pjsip_dlg_dec_lock(xfer->dlg);
return status;
}
/*
* Send current state and the last sipfrag body.
*/
PJ_DEF(pj_status_t) pjsip_xfer_current_notify( pjsip_evsub *sub,
pjsip_tx_data **p_tdata )
{
pjsip_xfer *xfer;
pj_status_t status;
/* Check arguments. */
PJ_ASSERT_RETURN(sub, PJ_EINVAL);
/* Get the xfer object. */
xfer = pjsip_evsub_get_mod_data(sub, mod_xfer.id);
PJ_ASSERT_RETURN(xfer != NULL, PJSIP_ENOREFERSESSION);
pjsip_dlg_inc_lock(xfer->dlg);
status = pjsip_xfer_notify(sub, pjsip_evsub_get_state(sub),
xfer->last_st_code, &xfer->last_st_text,
p_tdata);
pjsip_dlg_dec_lock(xfer->dlg);
return status;
}
/*
* Send request message.
*/
PJ_DEF(pj_status_t) pjsip_xfer_send_request( pjsip_evsub *sub,
pjsip_tx_data *tdata)
{
return pjsip_evsub_send_request(sub, tdata);
}
/*
* This callback is called by event subscription when subscription
* state has changed.
*/
static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
{
pjsip_xfer *xfer;
xfer = pjsip_evsub_get_mod_data(sub, mod_xfer.id);
PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
if (xfer->user_cb.on_evsub_state)
(*xfer->user_cb.on_evsub_state)(sub, event);
}
/*
* Called when transaction state has changed.
*/
static void xfer_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
pjsip_event *event)
{
pjsip_xfer *xfer;
xfer = pjsip_evsub_get_mod_data(sub, mod_xfer.id);
PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
if (xfer->user_cb.on_tsx_state)
(*xfer->user_cb.on_tsx_state)(sub, tsx, event);
}
/*
* Called when REFER is received to refresh subscription.
*/
static void xfer_on_evsub_rx_refresh( pjsip_evsub *sub,
pjsip_rx_data *rdata,
int *p_st_code,
pj_str_t **p_st_text,
pjsip_hdr *res_hdr,
pjsip_msg_body **p_body)
{
pjsip_xfer *xfer;
xfer = pjsip_evsub_get_mod_data(sub, mod_xfer.id);
PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
if (xfer->user_cb.on_rx_refresh) {
(*xfer->user_cb.on_rx_refresh)(sub, rdata, p_st_code, p_st_text,
res_hdr, p_body);
} else {
/* Implementors MUST send NOTIFY if it implements on_rx_refresh
* (implementor == "us" from evsub point of view.
*/
pjsip_tx_data *tdata;
pj_status_t status;
if (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED) {
status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_TERMINATED,
xfer->last_st_code,
&xfer->last_st_text,
&tdata);
} else {
status = pjsip_xfer_current_notify(sub, &tdata);
}
if (status == PJ_SUCCESS)
pjsip_xfer_send_request(sub, tdata);
}
}
/*
* Called when NOTIFY is received.
*/
static void xfer_on_evsub_rx_notify( pjsip_evsub *sub,
pjsip_rx_data *rdata,
int *p_st_code,
pj_str_t **p_st_text,
pjsip_hdr *res_hdr,
pjsip_msg_body **p_body)
{
pjsip_xfer *xfer;
xfer = pjsip_evsub_get_mod_data(sub, mod_xfer.id);
PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
if (xfer->user_cb.on_rx_notify)
(*xfer->user_cb.on_rx_notify)(sub, rdata, p_st_code, p_st_text,
res_hdr, p_body);
}
/*
* Called when it's time to send SUBSCRIBE.
*/
static void xfer_on_evsub_client_refresh(pjsip_evsub *sub)
{
pjsip_xfer *xfer;
xfer = pjsip_evsub_get_mod_data(sub, mod_xfer.id);
PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
if (xfer->user_cb.on_client_refresh) {
(*xfer->user_cb.on_client_refresh)(sub);
} else {
pj_status_t status;
pjsip_tx_data *tdata;
status = pjsip_xfer_initiate(sub, NULL, &tdata);
if (status == PJ_SUCCESS)
pjsip_xfer_send_request(sub, tdata);
}
}
/*
* Called when no refresh is received after the interval.
*/
static void xfer_on_evsub_server_timeout(pjsip_evsub *sub)
{
pjsip_xfer *xfer;
xfer = pjsip_evsub_get_mod_data(sub, mod_xfer.id);
PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
if (xfer->user_cb.on_server_timeout) {
(*xfer->user_cb.on_server_timeout)(sub);
} else {
pj_status_t status;
pjsip_tx_data *tdata;
status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,
xfer->last_st_code,
&xfer->last_st_text, &tdata);
if (status == PJ_SUCCESS)
pjsip_xfer_send_request(sub, tdata);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -