PJSUA使用c进行sip注册时出错

MrN*_*ice 4 c python asterisk registration pjsip

所以我正在用PJSUA用C编写一个软电话客户端.所以首先我尝试了一个pjsip-homepage给出的例子.现在我在注册到我的星号服务器时遇到错误,但我无法弄清楚为什么会发生这种情况.我可以成功拨打电话,但由于没有注册,我无法接收任何电话.我尝试了一个python示例进行注册,这很好用.

当然我已经在sip.con和extensions.conf上配置了我的星号,他能够注册这个客户端,通过注册python示例程序来显示.

所以我很感激你找错我的时间.

所以我的c代码:

#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0 
#include <pjsua-lib/pjsua.h>
#include <pjlib.h> 
#include <pjlib-util.h> 
#include <pjnath.h> 
#include <pjsip.h> 
#include <pjsip_ua.h> 
#include <pjsip_simple.h> 
#include <pjmedia.h> 
#include <pjmedia-codec.h> 
#define THIS_FILE "App"
#define SIP_USER "demo-user2"
#define SIP_DOMAIN "192.168.2.59"
#define SIP_PASSWD "123456"

static void on_incoming_call( pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata );
static void on_call_state( pjsua_call_id call_id, pjsip_event *e );
static void on_call_media_state( pjsua_call_id call_id );
static void error_exit( const char *title, pj_status_t status );

int main( int argc, char *argv[] ) {
    pjsua_acc_id acc_id;
    pj_status_t status;

    /* Create pjsua */  
    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 ( argc > 1 ) {
        status = pjsua_verify_url( argv[1] );
        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 );
        }
    }

    /* Start pjsua */
    status = pjsua_start();
    if ( status != PJ_SUCCESS ) {
        error_exit( "Error starting pjsua", status );
    }

    /* Register to SIP server */
    {
        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( "*" );
        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 ( argc > 1 ) {
        pj_str_t uri = pj_str( argv[1] );
        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. */
    while ( 1 ) {
        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;
}

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 );
}

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 ) );
}

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 ) {
        pjsua_conf_connect( ci.conf_slot, 0 );
        pjsua_conf_connect( 0, ci.conf_slot );
    }
}

static void error_exit( const char *title, pj_status_t status ) {
    pjsua_perror( THIS_FILE, title, status );
    pjsua_destroy();
    exit( 1 );
}
Run Code Online (Sandbox Code Playgroud)

在这里我的程序输出:

19:11:53.627 os_core_unix.c !pjlib 2.4.5-svn for POSIX initialized
19:11:53.631 sip_endpoint.c  .Creating endpoint instance...
19:11:53.632          pjlib  .select() I/O Queue created (0x1ca0f30)
19:11:53.632 sip_endpoint.c  .Module "mod-msg-print" registered
19:11:53.633 sip_transport.  .Transport manager created.
19:11:53.633   pjsua_core.c  .PJSUA state changed: NULL --> CREATED
19:11:53.633 sip_endpoint.c  .Module "mod-pjsua-log" registered
19:11:53.633 sip_endpoint.c  .Module "mod-tsx-layer" registered
19:11:53.633 sip_endpoint.c  .Module "mod-stateful-util" registered
19:11:53.633 sip_endpoint.c  .Module "mod-ua" registered
19:11:53.633 sip_endpoint.c  .Module "mod-100rel" registered
19:11:53.634 sip_endpoint.c  .Module "mod-pjsua" registered
19:11:53.634 sip_endpoint.c  .Module "mod-invite" registered
19:11:53.803     alsa_dev.c  ..ALSA driver found 11 devices
19:11:53.804     alsa_dev.c  ..ALSA initialized
19:11:53.805          pjlib  ..select() I/O Queue created (0x1ccb8ac)
19:11:53.837 sip_endpoint.c  .Module "mod-evsub" registered
19:11:53.838 sip_endpoint.c  .Module "mod-presence" registered
19:11:53.838 sip_endpoint.c  .Module "mod-mwi" registered
19:11:53.839 sip_endpoint.c  .Module "mod-refer" registered
19:11:53.839 sip_endpoint.c  .Module "mod-pjsua-pres" registered
19:11:53.839 sip_endpoint.c  .Module "mod-pjsua-im" registered
19:11:53.840 sip_endpoint.c  .Module "mod-pjsua-options" registered
19:11:53.840   pjsua_core.c  .1 SIP worker threads created
19:11:53.841   pjsua_core.c  .pjsua version 2.4.5-svn for Linux-4.1.7/armv7l/glibc-2.13 initialized
19:11:53.841   pjsua_core.c  .PJSUA state changed: CREATED --> INIT
19:11:53.842   pjsua_core.c  SIP UDP socket reachable at 192.168.2.83:5060
19:11:53.843   udp0x1cde4c8  SIP UDP transport started, published address is 192.168.2.83:5060
19:11:53.843   pjsua_core.c  PJSUA state changed: INIT --> STARTING
19:11:53.843 sip_endpoint.c  .Module "mod-unsolicited-mwi" registered
19:11:53.844   pjsua_core.c  .PJSUA state changed: STARTING --> RUNNING
19:11:53.844    pjsua_acc.c  Adding account: id=sip:demo-user2@192.168.2.59
19:11:53.845    pjsua_acc.c  .Account sip:demo-user2@192.168.2.59 added with id 0
19:11:53.845    pjsua_acc.c  .Acc 0: setting registration..
19:11:53.846   pjsua_core.c  ...TX 499 bytes Request msg REGISTER/cseq=2433 (tdta0x1ce2858) to UDP 192.168.2.59:5060:
REGISTER sip:192.168.2.59 SIP/2.0
Via: SIP/2.0/UDP 192.168.2.83:5060;rport;branch=z9hG4bKPjkPDfnXzyPfl.tr1YUGuqWnb0xXPaMNGc
Max-Forwards: 70
From: <sip:demo-user2@192.168.2.59>;tag=z51e618QFYLeBsmdY9nVhzIvmajoODP-
To: <sip:demo-user2@192.168.2.59>
Call-ID: VViAieGUFSZ6qg9pOOuU2xaarZkBACiy
CSeq: 2433 REGISTER
Contact: <sip:demo-user2@192.168.2.83:5060;ob>
Expires: 300
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Content-Length:  0


--end msg--
19:11:53.847    pjsua_acc.c  ..Acc 0: Registration sent
Press 'h' to hangup all calls, 'q' to quit
19:11:53.851   pjsua_core.c  .RX 578 bytes Response msg 401/REGISTER/cseq=2433 (rdata0x1cdfafc) from UDP 192.168.2.59:5060:
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.2.83:5060;branch=z9hG4bKPjkPDfnXzyPfl.tr1YUGuqWnb0xXPaMNGc;received=192.168.2.83;rport=5060
From: <sip:demo-user2@192.168.2.59>;tag=z51e618QFYLeBsmdY9nVhzIvmajoODP-
To: <sip:demo-user2@192.168.2.59>;tag=as19db99ad
Call-ID: VViAieGUFSZ6qg9pOOuU2xaarZkBACiy
CSeq: 2433 REGISTER
Server: Asterisk PBX 13.6.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="5b64ff92"
Content-Length: 0


--end msg--
19:11:53.851 sip_auth_clien  ...Unable to set auth for tdta0x1ce2858: can not find credential for asterisk/Digest
19:11:53.851    pjsua_acc.c  ....SIP registration error: No suitable credential (PJSIP_ENOCREDENTIAL) [status=171101]
Run Code Online (Sandbox Code Playgroud)

tes*_*sla 6

来自PJSIP的常见问题解答

我无法登录/注册到我的服务器.它抱怨身份验证错误.

这很可能是由配置中的错误凭据引起的.补救措施取决于PJSIP报告的错误.

对于PJSIP_ENOCREDENTIAL错误:

此错误是由凭据中指定的域与401/407响应中服务器质询的域不匹配引起的.如果您使用PJSIP版本0.7-trunk或PJSIP版本0.7.1或更高版本,您可以将通配符("*")作为领域,以使PJSIP响应服务器挑战的任何领域.如果您使用较旧的PJSIP,则必须将凭证中的领域与挑战中的领域相匹配.领域通常等于域名,但它不必.例如,Asterisk总是将领域设置为"星号".

更新

设置realmscheme为以下

    cfg.cred_info[0].realm = pj_str((char *)"*");
    cfg.cred_info[0].scheme = pj_str((char *)"digest");
Run Code Online (Sandbox Code Playgroud)