📄 pjsua_im.c
字号:
pjsua_im_data *im_data2;
/* Must duplicate im_data */
im_data2 = pjsua_im_data_dup(tdata->pool, im_data);
/* Re-send request */
status = pjsip_endpt_send_request( pjsua_var.endpt, tdata, -1,
im_data2, &im_callback);
if (status == PJ_SUCCESS) {
/* Done */
return;
}
}
}
if (tsx->status_code/100 == 2) {
PJ_LOG(4,(THIS_FILE,
"Message \'%s\' delivered successfully",
im_data->body.ptr));
} else {
PJ_LOG(3,(THIS_FILE,
"Failed to deliver message \'%s\': %d/%.*s",
im_data->body.ptr,
tsx->status_code,
(int)tsx->status_text.slen,
tsx->status_text.ptr));
}
if (pjsua_var.ua_cfg.cb.on_pager_status)
pjsua_var.ua_cfg.cb.on_pager_status(im_data->call_id,
&im_data->to,
&im_data->body,
im_data->user_data,
tsx->status_code,
&tsx->status_text);
}
}
/* Outgoing typing indication callback.
* (used to reauthenticate request)
*/
static void typing_callback(void *token, pjsip_event *e)
{
pjsua_im_data *im_data = token;
if (e->type == PJSIP_EVENT_TSX_STATE) {
pjsip_transaction *tsx = e->body.tsx_state.tsx;
/* Ignore provisional response, if any */
if (tsx->status_code < 200)
return;
/* Handle authentication challenges */
if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG &&
(tsx->status_code == 401 || tsx->status_code == 407))
{
pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
pjsip_tx_data *tdata;
pjsip_auth_clt_sess auth;
pj_status_t status;
PJ_LOG(4,(THIS_FILE, "Resending IM with authentication"));
/* Create temporary authentication session */
pjsip_auth_clt_init(&auth,pjsua_var.endpt,rdata->tp_info.pool, 0);
pjsip_auth_clt_set_credentials(&auth,
pjsua_var.acc[im_data->acc_id].cred_cnt,
pjsua_var.acc[im_data->acc_id].cred);
status = pjsip_auth_clt_reinit_req(&auth, rdata, tsx->last_tx,
&tdata);
if (status == PJ_SUCCESS) {
pjsua_im_data *im_data2;
/* Must duplicate im_data */
im_data2 = pjsua_im_data_dup(tdata->pool, im_data);
/* Re-send request */
status = pjsip_endpt_send_request( pjsua_var.endpt, tdata, -1,
im_data2, &typing_callback);
if (status == PJ_SUCCESS) {
/* Done */
return;
}
}
}
}
}
/*
* Send instant messaging outside dialog, using the specified account for
* route set and authentication.
*/
PJ_DEF(pj_status_t) pjsua_im_send( pjsua_acc_id acc_id,
const pj_str_t *to,
const pj_str_t *mime_type,
const pj_str_t *content,
const pjsua_msg_data *msg_data,
void *user_data)
{
pjsip_tx_data *tdata;
const pj_str_t mime_text_plain = pj_str("text/plain");
const pj_str_t STR_CONTACT = { "Contact", 7 };
pjsip_media_type media_type;
pjsua_im_data *im_data;
pj_str_t contact;
pj_status_t status;
/* To and message body must be specified. */
PJ_ASSERT_RETURN(to && content, PJ_EINVAL);
/* Create request. */
status = pjsip_endpt_create_request(pjsua_var.endpt,
&pjsip_message_method, to,
&pjsua_var.acc[acc_id].cfg.id,
to, NULL, NULL, -1, NULL, &tdata);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to create request", status);
return status;
}
/* If account is locked to specific transport, then set transport to
* the request.
*/
if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {
pjsip_tpselector tp_sel;
pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
pjsip_tx_data_set_transport(tdata, &tp_sel);
}
/* Add accept header. */
pjsip_msg_add_hdr( tdata->msg,
(pjsip_hdr*)pjsua_im_create_accept(tdata->pool));
/* Add contact. */
status = pjsua_acc_create_uac_contact(tdata->pool, &contact, acc_id, to);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to generate Contact header", status);
pjsip_tx_data_dec_ref(tdata);
return status;
}
pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
pjsip_generic_string_hdr_create(tdata->pool,
&STR_CONTACT, &contact));
/* Create IM data to keep message details and give it back to
* application on the callback
*/
im_data = pj_pool_zalloc(tdata->pool, sizeof(*im_data));
im_data->acc_id = acc_id;
im_data->call_id = PJSUA_INVALID_ID;
pj_strdup_with_null(tdata->pool, &im_data->to, to);
pj_strdup_with_null(tdata->pool, &im_data->body, content);
im_data->user_data = user_data;
/* Set default media type if none is specified */
if (mime_type == NULL) {
mime_type = &mime_text_plain;
}
/* Parse MIME type */
pjsua_parse_media_type(tdata->pool, mime_type, &media_type);
/* Add message body */
tdata->msg->body = pjsip_msg_body_create( tdata->pool, &media_type.type,
&media_type.subtype,
&im_data->body);
if (tdata->msg->body == NULL) {
pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM);
pjsip_tx_data_dec_ref(tdata);
return PJ_ENOMEM;
}
/* Add additional headers etc. */
pjsua_process_msg_data(tdata, msg_data);
/* Add route set */
pjsua_set_msg_route_set(tdata, &pjsua_var.acc[acc_id].route_set);
/* Send request (statefully) */
status = pjsip_endpt_send_request( pjsua_var.endpt, tdata, -1,
im_data, &im_callback);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to send request", status);
return status;
}
return PJ_SUCCESS;
}
/*
* Send typing indication outside dialog.
*/
PJ_DEF(pj_status_t) pjsua_im_typing( pjsua_acc_id acc_id,
const pj_str_t *to,
pj_bool_t is_typing,
const pjsua_msg_data *msg_data)
{
const pj_str_t STR_CONTACT = { "Contact", 7 };
pjsua_im_data *im_data;
pjsip_tx_data *tdata;
pj_str_t contact;
pj_status_t status;
/* Create request. */
status = pjsip_endpt_create_request( pjsua_var.endpt, &pjsip_message_method,
to, &pjsua_var.acc[acc_id].cfg.id,
to, NULL, NULL, -1, NULL, &tdata);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to create request", status);
return status;
}
/* If account is locked to specific transport, then set transport to
* the request.
*/
if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {
pjsip_tpselector tp_sel;
pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
pjsip_tx_data_set_transport(tdata, &tp_sel);
}
/* Add accept header. */
pjsip_msg_add_hdr( tdata->msg,
(pjsip_hdr*)pjsua_im_create_accept(tdata->pool));
/* Add contact. */
status = pjsua_acc_create_uac_contact(tdata->pool, &contact, acc_id, to);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to generate Contact header", status);
pjsip_tx_data_dec_ref(tdata);
return status;
}
pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
pjsip_generic_string_hdr_create(tdata->pool,
&STR_CONTACT, &contact));
/* Create "application/im-iscomposing+xml" msg body. */
tdata->msg->body = pjsip_iscomposing_create_body( tdata->pool, is_typing,
NULL, NULL, -1);
/* Add additional headers etc. */
pjsua_process_msg_data(tdata, msg_data);
/* Add route set */
pjsua_set_msg_route_set(tdata, &pjsua_var.acc[acc_id].route_set);
/* Create data to reauthenticate */
im_data = pj_pool_zalloc(tdata->pool, sizeof(*im_data));
im_data->acc_id = acc_id;
/* Send request (statefully) */
status = pjsip_endpt_send_request( pjsua_var.endpt, tdata, -1,
im_data, &typing_callback);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to send request", status);
return status;
}
return PJ_SUCCESS;
}
/*
* Init pjsua IM module.
*/
pj_status_t pjsua_im_init(void)
{
const pj_str_t msg_tag = { "MESSAGE", 7 };
const pj_str_t STR_MIME_TEXT_PLAIN = { "text/plain", 10 };
const pj_str_t STR_MIME_APP_ISCOMPOSING =
{ "application/im-iscomposing+xml", 30 };
pj_status_t status;
/* Register module */
status = pjsip_endpt_register_module(pjsua_var.endpt, &mod_pjsua_im);
if (status != PJ_SUCCESS)
return status;
/* Register support for MESSAGE method. */
pjsip_endpt_add_capability( pjsua_var.endpt, &mod_pjsua_im, PJSIP_H_ALLOW,
NULL, 1, &msg_tag);
/* Register support for "application/im-iscomposing+xml" content */
pjsip_endpt_add_capability( pjsua_var.endpt, &mod_pjsua_im, PJSIP_H_ACCEPT,
NULL, 1, &STR_MIME_APP_ISCOMPOSING);
/* Register support for "text/plain" content */
pjsip_endpt_add_capability( pjsua_var.endpt, &mod_pjsua_im, PJSIP_H_ACCEPT,
NULL, 1, &STR_MIME_TEXT_PLAIN);
return PJ_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -