⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pjsua_im.c

📁 一个开源SIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
		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 + -