PJSUA Error on sip registration with c
Asked Answered
S

1

5

so i am writing a soft phone client with PJSUA using C. So first i tried out an example given from pjsip-homepage. Now i faced an error on registration to my asterisk-server, but i couldn't figure out why this happens. I can make successfully calls, but i can't receive any since it's not registered. I tried an python example for registration and this works fine.

Of course i have configured my asterisk on sip.con and extensions.conf that he is able to register this client, which shows by registering with python sample program.

So i appreciate your time for finding my mistake.

so here my c code:

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

and here my output of my program:

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:[email protected]
19:11:53.845    pjsua_acc.c  .Account sip:[email protected] 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:[email protected]>;tag=z51e618QFYLeBsmdY9nVhzIvmajoODP-
To: <sip:[email protected]>
Call-ID: VViAieGUFSZ6qg9pOOuU2xaarZkBACiy
CSeq: 2433 REGISTER
Contact: <sip:[email protected]: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:[email protected]>;tag=z51e618QFYLeBsmdY9nVhzIvmajoODP-
To: <sip:[email protected]>;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]
Shikari answered 24/11, 2015 at 10:48 Comment(0)
J
9

From PJSIP's FAQ

I cannot login/REGISTER to my server. It complains about authentication error.

Most likely this is caused by wrong credential in the configuration. The remedy depends on what error was reported by PJSIP.

For ​PJSIP_ENOCREDENTIAL error:

This error is caused by the realm specified in the credential doesn't match the realm challenged by the server in the 401/407 response. If you use PJSIP version 0.7-trunk or PJSIP version 0.7.1 or later, you can put wildcard ("*") as the realm to make PJSIP respond to any realms challenged by the server. If you use older PJSIP, you have to match the realm in the credential with the realm in the challenge. The realm normally would be equal to the domain name, but it doesn't have to. Asterisk, for example, always set the realm to "asterisk".

Updated

Set realm and scheme as the following

    cfg.cred_info[0].realm = pj_str((char *)"*");
    cfg.cred_info[0].scheme = pj_str((char *)"digest");
Joanejoanie answered 24/11, 2015 at 11:6 Comment(1)
thank you, i interchanged realm with sheme. Working now!Shikari

© 2022 - 2024 — McMap. All rights reserved.