当前位置: 首页 > 工具软件 > PJSIP > 使用案例 >

pjsip-01

姬国安
2023-12-01
  1. 实例化pjsua应用程序。
    应用程序必须在调用任何其他函数之前调用这个函数,以确保底层库被正确初始化。一旦这个函数成功返回,应用程序必须在退出之前调用pjsua_destroy()

    PJ_DECL(pj_status_t) pjsua_create(void);
    
  2. 初始化pjsua应用程序
    使用指定的设置初始化pjsua。所有的设置都是可选的,当没有指定配置时将使用默认值。

    PJ_DECL(pj_status_t) pjsua_init(const pjsua_config *ua_cfg,
    				const pjsua_logging_config *log_cfg,
    				const pjsua_media_config *media_cfg);
    
  1. pjsua_logging_config :这个结构描述了控制API和的设置 用户代理行为,可以在调用#pjsua_init()时指定。 在设置值之前,应用程序必须调用#pjsua_config_default() 使用默认值初始化该结构体。
  2. pjsua_logging_config:日志配置,可以在调用时(可选地)指定 pjsua_init()。应用程序必须调用pjsua_logging_config_default()用默认值初始化该结构。
  3. pjsua_media_config:这个结构描述了媒体配置,它将在调用pjsua_init()时指定。应用程序必须通过调用#pjsua_media_config_default()来初始化这个结构。
  1. 根据指定的设置创建并启动新的SIP传输。
PJ_DECL(pj_status_t) pjsua_transport_create(pjsip_transport_type_e type,
					    const pjsua_transport_config *cfg,
					    pjsua_transport_id *p_id);

  1. pjsip_transport_type_e:传输类型
  2. pjsua_transport_config:传输配置
  3. pjsua_transport_id:传输ID
  1. 初始化完成,现在启动pjsua
PJ_DECL(pj_status_t) pjsua_start(void);
  1. 通过创建SIP帐号注册到SIP服务器。
PJ_DECL(pj_status_t) pjsua_acc_add(const pjsua_acc_config *acc_cfg,
				   pj_bool_t is_default,
				   pjsua_acc_id *p_acc_id);
  1. pjsua_acc_config:账号配置,通过pjsua_acc_config_default获得
  2. is_default:如果非零,则此帐户将设置为默认帐户。如果未指定帐户,则在发送传出请求(例如拨打电话)时使用默认帐户;如果请求与任何帐户不匹配,则在接收传入请求时使用默认帐户。建议将默认帐户设置为本地/局域网帐户。
  3. p_acc_id:接收新账户的账号ID
  1. 呼叫指定的sip账号
PJ_DECL(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id,
					  const pj_str_t *dst_uri,
					  const pjsua_call_setting *opt,
					  void *user_data,
					  const pjsua_msg_data *msg_data,
					  pjsua_call_id *p_call_id);
  1. acc_id:通过该账号呼叫
  2. dst_uri:放置在to头中的URI(通常与目标URI相同
  3. opt:可选的设置。这应该使用#pjsua_call_setting_default()进行初始化。
  4. user_data:user_data附加到调用的任意用户数据,可以稍后检索。
  5. msg_data:要添加到传出INVITE请求的可选标头等,如果不需要自定义标头,则为NULL。
  6. p_call_id:接收呼叫标识的指针。

完整示例:

#include <pjsip/pjsua-lib/pjsua.h>

#define THIS_FILE "===LEO===="

#define SIP_DOMAIN "192.168.2.113" // sip.linphone.org"
#define SIP_USER "root"		   //"leo_id1"
#define SIP_PASSWD "12345"

/* Callback called by the library upon receiving incoming call */
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
			     pjsip_rx_data *rdata)
{
	pjsua_call_info ci;

	PJ_UNUSED_ARG(acc_id);
	PJ_UNUSED_ARG(rdata);

	pjsua_call_get_info(call_id, &ci);

	PJ_LOG(3, (THIS_FILE, "Incoming call from %.*s!!",
		   (int)ci.remote_info.slen,
		   ci.remote_info.ptr));

	/* Automatically answer incoming calls with 200/OK */
	pjsua_call_answer(call_id, 200, NULL, NULL);
}

/* Callback called by the library when call's state has changed */
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
	pjsua_call_info ci;

	PJ_UNUSED_ARG(e);

	pjsua_call_get_info(call_id, &ci);
	PJ_LOG(3, (THIS_FILE, "Call %d state=%.*s", call_id,
		   (int)ci.state_text.slen,
		   ci.state_text.ptr));
}

/* Callback called by the library when call's media state has changed */
static void on_call_media_state(pjsua_call_id call_id)
{
	pjsua_call_info ci;

	pjsua_call_get_info(call_id, &ci);

	if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE)
	{
		// When media is active, connect call to sound device.
		pjsua_conf_connect(ci.conf_slot, 0);
		pjsua_conf_connect(0, ci.conf_slot);
	}
}

/* Display error and exit application */
static void error_exit(const char *title, pj_status_t status)
{
	pjsua_perror(THIS_FILE, title, status);
	pjsua_destroy();
	exit(1);
}

/*
 * main()
 *
 * argv[1] may contain URL to call.
 */
int pjsip_test(char *url)
{
	pjsua_acc_id acc_id;
	pj_status_t status;

	/* Create pjsua first! */
	status = pjsua_create();
	if (status != PJ_SUCCESS)
		error_exit("Error in pjsua_create()", status);

	/* If argument is specified, it's got to be a valid SIP URL */

	if (url != NULL)
	{
		status = pjsua_verify_url(url);
		if (status != PJ_SUCCESS)
			error_exit("Invalid URL in argv", status);
	}
	/* Init pjsua */
	{
		pjsua_config cfg;
		pjsua_logging_config log_cfg;

		pjsua_config_default(&cfg);
		cfg.cb.on_incoming_call = &on_incoming_call;
		cfg.cb.on_call_media_state = &on_call_media_state;
		cfg.cb.on_call_state = &on_call_state;

		pjsua_logging_config_default(&log_cfg);
		log_cfg.console_level = 4;

		status = pjsua_init(&cfg, &log_cfg, NULL);
		if (status != PJ_SUCCESS)
			error_exit("Error in pjsua_init()", status);
	}

	/* Add UDP transport. */
	{
		pjsua_transport_config cfg;

		pjsua_transport_config_default(&cfg);
		cfg.port = 5060;
		status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
		if (status != PJ_SUCCESS)
			error_exit("Error creating transport", status);
	}

	/* Initialization is done, now start pjsua */
	status = pjsua_start();
	if (status != PJ_SUCCESS)
		error_exit("Error starting pjsua", status);

	/* Register to SIP server by creating SIP account. */
	{
		pjsua_acc_config cfg;

		pjsua_acc_config_default(&cfg);
		cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
		cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
		cfg.cred_count = 1;
		cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
		cfg.cred_info[0].scheme = pj_str("digest");
		cfg.cred_info[0].username = pj_str(SIP_USER);
		cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
		cfg.cred_info[0].data = pj_str(SIP_PASSWD);

		status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
		if (status != PJ_SUCCESS)
			error_exit("Error adding account", status);
	}

	/* If URL is specified, make call to the URL. */
	if (url != NULL)
	{
		pj_str_t uri = pj_str(url);
		status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL);
		if (status != PJ_SUCCESS)
			error_exit("Error making call", status);
	}

	/* Wait until user press "q" to quit. */
	for (;;)
	{
		char option[10];

		puts("Press 'h' to hangup all calls, 'q' to quit");
		if (fgets(option, sizeof(option), stdin) == NULL)
		{
			puts("EOF while reading stdin, will quit now..");
			break;
		}

		if (option[0] == 'q')
			break;

		if (option[0] == 'h')
			pjsua_call_hangup_all();
	}

	/* Destroy pjsua */
	pjsua_destroy();

	return 0;
}

 类似资料: