实例化pjsua应用程序。
应用程序必须在调用任何其他函数之前调用这个函数,以确保底层库被正确初始化。一旦这个函数成功返回,应用程序必须在退出之前调用pjsua_destroy()
PJ_DECL(pj_status_t) pjsua_create(void);
初始化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);
- pjsua_logging_config :这个结构描述了控制API和的设置 用户代理行为,可以在调用#pjsua_init()时指定。 在设置值之前,应用程序必须调用#pjsua_config_default() 使用默认值初始化该结构体。
- pjsua_logging_config:日志配置,可以在调用时(可选地)指定 pjsua_init()。应用程序必须调用pjsua_logging_config_default()用默认值初始化该结构。
- pjsua_media_config:这个结构描述了媒体配置,它将在调用pjsua_init()时指定。应用程序必须通过调用#pjsua_media_config_default()来初始化这个结构。
PJ_DECL(pj_status_t) pjsua_transport_create(pjsip_transport_type_e type,
const pjsua_transport_config *cfg,
pjsua_transport_id *p_id);
- pjsip_transport_type_e:传输类型
- pjsua_transport_config:传输配置
- pjsua_transport_id:传输ID
PJ_DECL(pj_status_t) pjsua_start(void);
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);
- pjsua_acc_config:账号配置,通过pjsua_acc_config_default获得
- is_default:如果非零,则此帐户将设置为默认帐户。如果未指定帐户,则在发送传出请求(例如拨打电话)时使用默认帐户;如果请求与任何帐户不匹配,则在接收传入请求时使用默认帐户。建议将默认帐户设置为本地/局域网帐户。
- p_acc_id:接收新账户的账号ID
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);
- acc_id:通过该账号呼叫
- dst_uri:放置在to头中的URI(通常与目标URI相同
- opt:可选的设置。这应该使用#pjsua_call_setting_default()进行初始化。
- user_data:user_data附加到调用的任意用户数据,可以稍后检索。
- msg_data:要添加到传出INVITE请求的可选标头等,如果不需要自定义标头,则为NULL。
- 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;
}