Ignore:
Timestamp:
May 26, 2006 12:17:46 PM (18 years ago)
Author:
bennylp
Message:

First stage in pjsua library re-arrangements towards creating an easy to use high level API

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r452 r476  
    1818 */ 
    1919#include <pjsua-lib/pjsua.h> 
     20#include "pjsua_imp.h" 
    2021 
    2122/* 
     
    4445 * Init default application parameters. 
    4546 */ 
    46 void pjsua_default(void) 
     47PJ_DEF(void) pjsua_default_config(pjsua_config *cfg) 
    4748{ 
    4849    unsigned i; 
    4950 
    50  
    51     /* Normally need another thread for console application, because main  
    52      * thread will be blocked in fgets(). 
    53      */ 
    54     pjsua.thread_cnt = 1; 
    55  
    56  
    57     /* Default transport settings: */ 
    58     pjsua.sip_port = 5060; 
    59  
    60  
    61     /* Default we start RTP at port 4000 */ 
    62     pjsua.start_rtp_port = 4000; 
    63  
    64  
    65     /* Default logging settings: */ 
    66     pjsua.log_level = 5; 
    67     pjsua.app_log_level = 4; 
    68     pjsua.log_decor = PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME |  
    69                       PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE; 
    70  
    71  
    72     /* Default call settings. */ 
    73     pjsua.uas_refresh = -1; 
    74     pjsua.uas_duration = -1; 
    75  
    76     /* Default: do not use STUN: */ 
    77     pjsua.stun_port1 = pjsua.stun_port2 = 0; 
    78  
    79     /* Default for media: */ 
     51    pj_memset(cfg, 0, sizeof(pjsua_config)); 
     52 
     53    cfg->thread_cnt = 1; 
     54    cfg->udp_port = 5060; 
     55    cfg->start_rtp_port = 4000; 
     56    cfg->max_calls = 4; 
     57    cfg->conf_ports = 0; 
     58 
    8059#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    8160    pjsua.clock_rate = 44100; 
    8261#endif 
    83     pjsua.complexity = -1; 
    84     pjsua.quality = 4; 
     62 
     63    cfg->complexity = 10; 
     64    cfg->quality = 10; 
     65     
     66    cfg->auto_answer = 100; 
     67    cfg->uas_duration = 3600; 
     68 
     69    /* Default logging settings: */ 
     70    cfg->log_level = 5; 
     71    cfg->app_log_level = 4; 
     72    cfg->log_decor =  PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME |  
     73                      PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE; 
     74 
     75 
     76    /* Also init logging settings in pjsua.config, because log 
     77     * may be written before pjsua_init() is called. 
     78     */ 
     79    pjsua.config.log_level = 5; 
     80    pjsua.config.app_log_level = 4; 
    8581 
    8682 
    8783    /* Init accounts: */ 
    88     pjsua.acc_cnt = 1; 
    8984    for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) { 
    90         pjsua.acc[i].index = i; 
    91         pjsua.acc[i].local_uri = pj_str(PJSUA_LOCAL_URI); 
    92         pjsua.acc[i].reg_timeout = 55; 
    93         pjsua.acc[i].online_status = PJ_TRUE; 
    94         pj_list_init(&pjsua.acc[i].route_set); 
    95         pj_list_init(&pjsua.acc[i].pres_srv_list); 
    96     } 
    97  
    98     /* Init call array: */ 
    99     for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i) { 
    100         pjsua.calls[i].index = i; 
    101         pjsua.calls[i].refresh_tm._timer_id = -1; 
    102         pjsua.calls[i].hangup_tm._timer_id = -1; 
    103         pjsua.calls[i].conf_slot = 0; 
    104     } 
    105  
    106     /* Default max nb of calls. */ 
    107     pjsua.max_calls = 4; 
    108  
    109     /* Init server presence subscription list: */ 
    110      
    111  
    112 } 
    113  
     85        cfg->acc_config[i].reg_timeout = 55; 
     86    } 
     87} 
     88 
     89 
     90#define strncpy_with_null(dst,src,len)  \ 
     91do { \ 
     92    strncpy(dst, src, len); \ 
     93    dst[len-1] = '\0'; \ 
     94} while (0) 
     95 
     96 
     97 
     98PJ_DEF(pj_status_t) pjsua_test_config( const pjsua_config *cfg, 
     99                                       char *errmsg, 
     100                                       int len) 
     101{ 
     102    unsigned i; 
     103 
     104    /* If UDP port is zero, then sip_host and sip_port must be specified */ 
     105    if (cfg->udp_port == 0) { 
     106        if (cfg->sip_host.slen==0 || cfg->sip_port==0) { 
     107            strncpy_with_null(errmsg,  
     108                              "sip_host and sip_port must be specified", 
     109                              len); 
     110            return -1; 
     111        } 
     112    } 
     113 
     114    if (cfg->max_calls < 1) { 
     115        strncpy_with_null(errmsg,  
     116                          "max_calls needs to be at least 1", 
     117                          len); 
     118        return -1; 
     119    } 
     120 
     121    /* STUN */ 
     122    if (cfg->stun_srv1.slen || cfg->stun_port1 || cfg->stun_port2 ||  
     123        cfg->stun_srv2.slen)  
     124    { 
     125        if (cfg->stun_port1 == 0) { 
     126            strncpy_with_null(errmsg, "stun_port1 required", len); 
     127            return -1; 
     128        } 
     129        if (cfg->stun_srv1.slen == 0) { 
     130            strncpy_with_null(errmsg, "stun_srv1 required", len); 
     131            return -1; 
     132        } 
     133        if (cfg->stun_port2 == 0) { 
     134            strncpy_with_null(errmsg, "stun_port2 required", len); 
     135            return -1; 
     136        } 
     137        if (cfg->stun_srv2.slen == 0) { 
     138            strncpy_with_null(errmsg, "stun_srv2 required", len); 
     139            return -1; 
     140        } 
     141    } 
     142 
     143    /* Verify accounts */ 
     144    for (i=0; i<cfg->acc_cnt; ++i) { 
     145        const pjsua_acc_config *acc_cfg = &cfg->acc_config[i]; 
     146        unsigned j; 
     147 
     148        if (acc_cfg->id.slen == 0) { 
     149            strncpy_with_null(errmsg, "missing account ID", len); 
     150            return -1; 
     151        } 
     152 
     153        if (acc_cfg->id.slen == 0) { 
     154            strncpy_with_null(errmsg, "missing registrar URI", len); 
     155            return -1; 
     156        } 
     157 
     158        if (acc_cfg->reg_timeout == 0) { 
     159            strncpy_with_null(errmsg, "missing registration timeout", len); 
     160            return -1; 
     161        } 
     162 
     163 
     164        for (j=0; j<acc_cfg->cred_count; ++j) { 
     165 
     166            if (acc_cfg->cred_info[j].scheme.slen == 0) { 
     167                strncpy_with_null(errmsg, "missing auth scheme in account",  
     168                                  len); 
     169                return -1; 
     170            } 
     171 
     172            if (acc_cfg->cred_info[j].realm.slen == 0) { 
     173                strncpy_with_null(errmsg, "missing realm in account", len); 
     174                return -1; 
     175            } 
     176 
     177            if (acc_cfg->cred_info[j].username.slen == 0) { 
     178                strncpy_with_null(errmsg, "missing username in account", len); 
     179                return -1; 
     180            } 
     181 
     182        } 
     183    } 
     184 
     185    return PJ_SUCCESS; 
     186} 
    114187 
    115188 
     
    153226 
    154227 
     228static int PJ_THREAD_FUNC pjsua_poll(void *arg) 
     229{ 
     230    pj_status_t last_err = 0; 
     231 
     232    PJ_UNUSED_ARG(arg); 
     233 
     234    do { 
     235        pj_time_val timeout = { 0, 10 }; 
     236        pj_status_t status; 
     237         
     238        status = pjsip_endpt_handle_events (pjsua.endpt, &timeout); 
     239        if (status != PJ_SUCCESS && status != last_err) { 
     240            last_err = status; 
     241            pjsua_perror(THIS_FILE, "handle_events() returned error", status); 
     242        } 
     243    } while (!pjsua.quit_flag); 
     244 
     245    return 0; 
     246} 
     247 
     248 
     249 
     250#define pjsua_has_stun()    (pjsua.config.stun_port1 && \ 
     251                             pjsua.config.stun_port2) 
     252 
     253 
     254/* 
     255 * Create and initialize SIP socket (and possibly resolve public 
     256 * address via STUN, depending on config). 
     257 */ 
     258static pj_status_t create_sip_udp_sock(int port, 
     259                                       pj_sock_t *p_sock, 
     260                                       pj_sockaddr_in *p_pub_addr) 
     261{ 
     262    pj_sock_t sock; 
     263    pj_status_t status; 
     264 
     265    status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock); 
     266    if (status != PJ_SUCCESS) { 
     267        pjsua_perror(THIS_FILE, "socket() error", status); 
     268        return status; 
     269    } 
     270 
     271    status = pj_sock_bind_in(sock, 0, (pj_uint16_t)port); 
     272    if (status != PJ_SUCCESS) { 
     273        pjsua_perror(THIS_FILE, "bind() error", status); 
     274        pj_sock_close(sock); 
     275        return status; 
     276    } 
     277 
     278    if (pjsua_has_stun()) { 
     279        status = pj_stun_get_mapped_addr(&pjsua.cp.factory, 1, &sock, 
     280                                         &pjsua.config.stun_srv1,  
     281                                         pjsua.config.stun_port1, 
     282                                         &pjsua.config.stun_srv2,  
     283                                         pjsua.config.stun_port2, 
     284                                         p_pub_addr); 
     285        if (status != PJ_SUCCESS) { 
     286            pjsua_perror(THIS_FILE, "STUN resolve error", status); 
     287            pj_sock_close(sock); 
     288            return status; 
     289        } 
     290 
     291    } else { 
     292 
     293        const pj_str_t *hostname = pj_gethostname(); 
     294        struct pj_hostent he; 
     295 
     296        status = pj_gethostbyname(hostname, &he); 
     297        if (status != PJ_SUCCESS) { 
     298            pjsua_perror(THIS_FILE, "Unable to resolve local host", status); 
     299            pj_sock_close(sock); 
     300            return status; 
     301        } 
     302 
     303        pj_memset(p_pub_addr, 0, sizeof(pj_sockaddr_in)); 
     304        p_pub_addr->sin_family = PJ_AF_INET; 
     305        p_pub_addr->sin_port = pj_htons((pj_uint16_t)port); 
     306        p_pub_addr->sin_addr = *(pj_in_addr*)he.h_addr; 
     307    } 
     308 
     309    *p_sock = sock; 
     310    return PJ_SUCCESS; 
     311} 
     312 
     313 
    155314/*  
    156  * Initialize sockets and optionally get the public address via STUN.  
    157  */ 
    158 static pj_status_t init_sockets(pj_bool_t sip, 
    159                                 pjmedia_sock_info *skinfo) 
     315 * Create RTP and RTCP socket pair, and possibly resolve their public 
     316 * address via STUN. 
     317 */ 
     318static pj_status_t create_rtp_rtcp_sock(pjmedia_sock_info *skinfo) 
    160319{ 
    161320    enum {  
    162321        RTP_RETRY = 100 
    163322    }; 
    164     enum { 
    165         SIP_SOCK, 
    166         RTP_SOCK, 
    167         RTCP_SOCK, 
    168     }; 
    169323    int i; 
    170324    static pj_uint16_t rtp_port; 
    171     pj_sock_t sock[3]; 
    172     pj_sockaddr_in mapped_addr[3]; 
     325    pj_sockaddr_in mapped_addr[2]; 
    173326    pj_status_t status = PJ_SUCCESS; 
     327    pj_sock_t sock[2]; 
    174328 
    175329    if (rtp_port == 0) 
    176         rtp_port = (pj_uint16_t)pjsua.start_rtp_port; 
    177  
    178     for (i=0; i<3; ++i) 
     330        rtp_port = (pj_uint16_t)pjsua.config.start_rtp_port; 
     331 
     332    for (i=0; i<2; ++i) 
    179333        sock[i] = PJ_INVALID_SOCKET; 
    180  
    181     /* Create and bind SIP UDP socket. */ 
    182     status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[SIP_SOCK]); 
    183     if (status != PJ_SUCCESS) { 
    184         pjsua_perror(THIS_FILE, "socket() error", status); 
    185         goto on_error; 
    186     } 
    187  
    188     if (sip) { 
    189         status = pj_sock_bind_in(sock[SIP_SOCK], 0, pjsua.sip_port); 
    190         if (status != PJ_SUCCESS) { 
    191             pjsua_perror(THIS_FILE, "bind() error", status); 
    192             goto on_error; 
    193         } 
    194     } else { 
    195         status = pj_sock_bind_in(sock[SIP_SOCK], 0, 0); 
    196         if (status != PJ_SUCCESS) { 
    197             pjsua_perror(THIS_FILE, "bind() error", status); 
    198             goto on_error; 
    199         } 
    200     } 
    201334 
    202335 
     
    205338 
    206339        /* Create and bind RTP socket. */ 
    207         status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[RTP_SOCK]); 
     340        status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[0]); 
    208341        if (status != PJ_SUCCESS) { 
    209342            pjsua_perror(THIS_FILE, "socket() error", status); 
    210             goto on_error; 
    211         } 
    212  
    213         status = pj_sock_bind_in(sock[RTP_SOCK], 0, rtp_port); 
     343            return status; 
     344        } 
     345 
     346        status = pj_sock_bind_in(sock[0], 0, rtp_port); 
    214347        if (status != PJ_SUCCESS) { 
    215             pj_sock_close(sock[RTP_SOCK]);  
    216             sock[RTP_SOCK] = PJ_INVALID_SOCKET; 
     348            pj_sock_close(sock[0]);  
     349            sock[0] = PJ_INVALID_SOCKET; 
    217350            continue; 
    218351        } 
    219352 
    220353        /* Create and bind RTCP socket. */ 
    221         status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[RTCP_SOCK]); 
     354        status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[1]); 
    222355        if (status != PJ_SUCCESS) { 
    223356            pjsua_perror(THIS_FILE, "socket() error", status); 
    224             goto on_error; 
    225         } 
    226  
    227         status = pj_sock_bind_in(sock[RTCP_SOCK], 0, (pj_uint16_t)(rtp_port+1)); 
     357            pj_sock_close(sock[0]); 
     358            return status; 
     359        } 
     360 
     361        status = pj_sock_bind_in(sock[1], 0, (pj_uint16_t)(rtp_port+1)); 
    228362        if (status != PJ_SUCCESS) { 
    229             pj_sock_close(sock[RTP_SOCK]);  
    230             sock[RTP_SOCK] = PJ_INVALID_SOCKET; 
    231  
    232             pj_sock_close(sock[RTCP_SOCK]);  
    233             sock[RTCP_SOCK] = PJ_INVALID_SOCKET; 
     363            pj_sock_close(sock[0]);  
     364            sock[0] = PJ_INVALID_SOCKET; 
     365 
     366            pj_sock_close(sock[1]);  
     367            sock[1] = PJ_INVALID_SOCKET; 
    234368            continue; 
    235369        } 
     
    239373         * and make sure that the mapped RTCP port is adjacent with the RTP. 
    240374         */ 
    241         if (pjsua.stun_port1 == 0) { 
     375        if (pjsua_has_stun()) { 
     376            status=pj_stun_get_mapped_addr(&pjsua.cp.factory, 2, sock, 
     377                                           &pjsua.config.stun_srv1,  
     378                                           pjsua.config.stun_port1, 
     379                                           &pjsua.config.stun_srv2,  
     380                                           pjsua.config.stun_port2, 
     381                                           mapped_addr); 
     382            if (status != PJ_SUCCESS) { 
     383                pjsua_perror(THIS_FILE, "STUN resolve error", status); 
     384                goto on_error; 
     385            } 
     386 
     387            if (pj_ntohs(mapped_addr[1].sin_port) ==  
     388                pj_ntohs(mapped_addr[0].sin_port)+1) 
     389            { 
     390                /* Success! */ 
     391                break; 
     392            } 
     393 
     394            pj_sock_close(sock[0]);  
     395            sock[0] = PJ_INVALID_SOCKET; 
     396 
     397            pj_sock_close(sock[1]);  
     398            sock[1] = PJ_INVALID_SOCKET; 
     399 
     400        } else { 
    242401            const pj_str_t *hostname; 
    243402            pj_sockaddr_in addr; 
     
    255414            } 
    256415 
    257             for (i=0; i<3; ++i) 
     416            for (i=0; i<2; ++i) 
    258417                pj_memcpy(&mapped_addr[i], &addr, sizeof(addr)); 
    259418 
    260             if (sip) { 
    261                 mapped_addr[SIP_SOCK].sin_port =  
    262                     pj_htons((pj_uint16_t)pjsua.sip_port); 
    263             } 
    264             mapped_addr[RTP_SOCK].sin_port=pj_htons((pj_uint16_t)rtp_port); 
    265             mapped_addr[RTCP_SOCK].sin_port=pj_htons((pj_uint16_t)(rtp_port+1)); 
     419            mapped_addr[0].sin_port=pj_htons((pj_uint16_t)rtp_port); 
     420            mapped_addr[1].sin_port=pj_htons((pj_uint16_t)(rtp_port+1)); 
    266421            break; 
    267  
    268         } else { 
    269             status=pj_stun_get_mapped_addr(&pjsua.cp.factory, 3, sock, 
    270                                            &pjsua.stun_srv1, pjsua.stun_port1, 
    271                                            &pjsua.stun_srv2, pjsua.stun_port2, 
    272                                            mapped_addr); 
    273             if (status != PJ_SUCCESS) { 
    274                 pjsua_perror(THIS_FILE, "STUN error", status); 
    275                 goto on_error; 
    276             } 
    277  
    278             if (pj_ntohs(mapped_addr[2].sin_port) ==  
    279                 pj_ntohs(mapped_addr[1].sin_port)+1) 
    280             { 
    281                 break; 
    282             } 
    283  
    284             pj_sock_close(sock[RTP_SOCK]);  
    285             sock[RTP_SOCK] = PJ_INVALID_SOCKET; 
    286  
    287             pj_sock_close(sock[RTCP_SOCK]);  
    288             sock[RTCP_SOCK] = PJ_INVALID_SOCKET; 
    289         } 
    290     } 
    291  
    292     if (sock[RTP_SOCK] == PJ_INVALID_SOCKET) { 
     422        } 
     423    } 
     424 
     425    if (sock[0] == PJ_INVALID_SOCKET) { 
    293426        PJ_LOG(1,(THIS_FILE,  
    294427                  "Unable to find appropriate RTP/RTCP ports combination")); 
     
    296429    } 
    297430 
    298     if (sip) { 
    299         pjsua.sip_sock = sock[SIP_SOCK]; 
    300         pj_memcpy(&pjsua.sip_sock_name,  
    301                   &mapped_addr[SIP_SOCK],  
    302                   sizeof(pj_sockaddr_in)); 
    303     } else { 
    304         pj_sock_close(sock[0]); 
    305     } 
    306  
    307     skinfo->rtp_sock = sock[RTP_SOCK]; 
     431 
     432    skinfo->rtp_sock = sock[0]; 
    308433    pj_memcpy(&skinfo->rtp_addr_name,  
    309               &mapped_addr[RTP_SOCK], sizeof(pj_sockaddr_in)); 
    310  
    311     skinfo->rtcp_sock = sock[RTCP_SOCK]; 
     434              &mapped_addr[0], sizeof(pj_sockaddr_in)); 
     435 
     436    skinfo->rtcp_sock = sock[1]; 
    312437    pj_memcpy(&skinfo->rtcp_addr_name,  
    313               &mapped_addr[RTCP_SOCK], sizeof(pj_sockaddr_in)); 
    314  
    315     if (sip) { 
    316         PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d", 
    317                   pj_inet_ntoa(pjsua.sip_sock_name.sin_addr),  
    318                   pj_ntohs(pjsua.sip_sock_name.sin_port))); 
    319     } 
     438              &mapped_addr[1], sizeof(pj_sockaddr_in)); 
     439 
    320440    PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s:%d", 
    321441              pj_inet_ntoa(skinfo->rtp_addr_name.sin_addr),  
     
    329449 
    330450on_error: 
    331     for (i=0; i<3; ++i) { 
    332         if (sip && i==0) 
    333             continue; 
     451    for (i=0; i<2; ++i) { 
    334452        if (sock[i] != PJ_INVALID_SOCKET) 
    335453            pj_sock_close(sock[i]); 
     
    340458 
    341459 
    342 /*  
    343  * Initialize stack.  
    344  */ 
    345 static pj_status_t init_stack(void) 
     460/** 
     461 * Create pjsua application. 
     462 * This initializes pjlib/pjlib-util, and creates memory pool factory to 
     463 * be used by application. 
     464 */ 
     465PJ_DEF(pj_status_t) pjsua_create(void) 
    346466{ 
    347467    pj_status_t status; 
    348468 
     469    /* Init PJLIB: */ 
     470 
     471    status = pj_init(); 
     472    if (status != PJ_SUCCESS) { 
     473        pjsua_perror(THIS_FILE, "pj_init() error", status); 
     474        return status; 
     475    } 
     476 
     477    /* Init PJLIB-UTIL: */ 
     478 
     479    status = pjlib_util_init(); 
     480    if (status != PJ_SUCCESS) { 
     481        pjsua_perror(THIS_FILE, "pjlib_util_init() error", status); 
     482        return status; 
     483    } 
     484 
     485    /* Init memory pool: */ 
     486 
     487    /* Init caching pool. */ 
     488    pj_caching_pool_init(&pjsua.cp, &pj_pool_factory_default_policy, 0); 
     489 
     490    /* Create memory pool for application. */ 
     491    pjsua.pool = pj_pool_create(&pjsua.cp.factory, "pjsua", 4000, 4000, NULL); 
     492 
     493    /* Must create endpoint to initialize SIP parser. */ 
    349494    /* Create global endpoint: */ 
    350495 
    351     { 
    352         const pj_str_t *hostname; 
    353         const char *endpt_name; 
    354  
    355         /* Endpoint MUST be assigned a globally unique name. 
    356          * The name will be used as the hostname in Warning header. 
    357          */ 
    358  
    359         /* For this implementation, we'll use hostname for simplicity */ 
    360         hostname = pj_gethostname(); 
    361         endpt_name = hostname->ptr; 
    362  
    363         /* Create the endpoint: */ 
    364  
    365         status = pjsip_endpt_create(&pjsua.cp.factory, endpt_name,  
    366                                     &pjsua.endpt); 
     496    status = pjsip_endpt_create(&pjsua.cp.factory,  
     497                                pj_gethostname()->ptr,  
     498                                &pjsua.endpt); 
     499    if (status != PJ_SUCCESS) { 
     500        pjsua_perror(THIS_FILE, "Unable to create SIP endpoint", status); 
     501        return status; 
     502    } 
     503 
     504    /* Must create media endpoint too */ 
     505    status = pjmedia_endpt_create(&pjsua.cp.factory,  
     506                                  pjsip_endpt_get_ioqueue(pjsua.endpt), 0, 
     507                                  &pjsua.med_endpt); 
     508    if (status != PJ_SUCCESS) { 
     509        pjsua_perror(THIS_FILE,  
     510                     "Media stack initialization has returned error",  
     511                     status); 
     512        return status; 
     513    } 
     514 
     515 
     516    return PJ_SUCCESS; 
     517} 
     518 
     519 
     520 
     521/* 
     522 * Init media. 
     523 */ 
     524static pj_status_t init_media(void) 
     525{ 
     526    int i; 
     527    unsigned options; 
     528    unsigned clock_rate; 
     529    unsigned samples_per_frame; 
     530    pj_str_t codec_id; 
     531    pj_status_t status; 
     532 
     533    /* Register all codecs */ 
     534#if PJMEDIA_HAS_SPEEX_CODEC 
     535    /* Register speex. */ 
     536    status = pjmedia_codec_speex_init(pjsua.med_endpt,  
     537                                      PJMEDIA_SPEEX_NO_UWB, 
     538                                      pjsua.config.quality,  
     539                                      pjsua.config.complexity ); 
     540    if (status != PJ_SUCCESS) { 
     541        pjsua_perror(THIS_FILE, "Error initializing Speex codec", 
     542                     status); 
     543        return status; 
     544    } 
     545 
     546    /* Set "speex/16000/1" to have highest priority */ 
     547    codec_id = pj_str("speex/16000/1"); 
     548    pjmedia_codec_mgr_set_codec_priority(  
     549        pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 
     550        &codec_id,  
     551        PJMEDIA_CODEC_PRIO_HIGHEST); 
     552 
     553#endif /* PJMEDIA_HAS_SPEEX_CODEC */ 
     554 
     555#if PJMEDIA_HAS_GSM_CODEC 
     556    /* Register GSM */ 
     557    status = pjmedia_codec_gsm_init(pjsua.med_endpt); 
     558    if (status != PJ_SUCCESS) { 
     559        pjsua_perror(THIS_FILE, "Error initializing GSM codec", 
     560                     status); 
     561        return status; 
     562    } 
     563#endif /* PJMEDIA_HAS_GSM_CODEC */ 
     564 
     565#if PJMEDIA_HAS_G711_CODEC 
     566    /* Register PCMA and PCMU */ 
     567    status = pjmedia_codec_g711_init(pjsua.med_endpt); 
     568    if (status != PJ_SUCCESS) { 
     569        pjsua_perror(THIS_FILE, "Error initializing G711 codec", 
     570                     status); 
     571        return status; 
     572    } 
     573#endif  /* PJMEDIA_HAS_G711_CODEC */ 
     574 
     575#if PJMEDIA_HAS_L16_CODEC 
     576    /* Register L16 family codecs, but disable all */ 
     577    status = pjmedia_codec_l16_init(pjsua.med_endpt, 0); 
     578    if (status != PJ_SUCCESS) { 
     579        pjsua_perror(THIS_FILE, "Error initializing L16 codecs", 
     580                     status); 
     581        return status; 
     582    } 
     583 
     584    /* Disable ALL L16 codecs */ 
     585    codec_id = pj_str("L16"); 
     586    pjmedia_codec_mgr_set_codec_priority(  
     587        pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 
     588        &codec_id,  
     589        PJMEDIA_CODEC_PRIO_DISABLED); 
     590 
     591#endif  /* PJMEDIA_HAS_L16_CODEC */ 
     592 
     593 
     594    /* Enable those codecs that user put with "--add-codec", and move 
     595     * the priority to top 
     596     */ 
     597    for (i=0; i<(int)pjsua.config.codec_cnt; ++i) { 
     598        pjmedia_codec_mgr_set_codec_priority(  
     599            pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 
     600            &pjsua.config.codec_arg[i],  
     601            PJMEDIA_CODEC_PRIO_HIGHEST); 
     602    } 
     603 
     604 
     605    /* Init options for conference bridge. */ 
     606    options = 0; 
     607 
     608    /* Calculate maximum number of ports, if it's not specified */ 
     609    if (pjsua.config.conf_ports == 0) { 
     610        pjsua.config.conf_ports = 3 * pjsua.config.max_calls; 
     611    } 
     612 
     613    /* Init conference bridge. */ 
     614    clock_rate = pjsua.config.clock_rate ? pjsua.config.clock_rate : 16000; 
     615    samples_per_frame = clock_rate * 10 / 1000; 
     616    status = pjmedia_conf_create(pjsua.pool,  
     617                                 pjsua.config.conf_ports,  
     618                                 clock_rate,  
     619                                 1, /* mono */ 
     620                                 samples_per_frame,  
     621                                 16,  
     622                                 options, 
     623                                 &pjsua.mconf); 
     624    if (status != PJ_SUCCESS) { 
     625        pjsua_perror(THIS_FILE,  
     626                     "Media stack initialization has returned error",  
     627                     status); 
     628        return status; 
     629    } 
     630 
     631    /* Create WAV file player if required: */ 
     632 
     633    if (pjsua.config.wav_file.slen) { 
     634        pj_str_t port_name; 
     635 
     636        /* Create the file player port. */ 
     637        status = pjmedia_wav_player_port_create(  pjsua.pool,  
     638                                                  pjsua.config.wav_file.ptr, 
     639                                                  0, 0, -1, NULL,  
     640                                                  &pjsua.file_port); 
    367641        if (status != PJ_SUCCESS) { 
    368             pjsua_perror(THIS_FILE, "Unable to create SIP endpoint", status); 
     642            pjsua_perror(THIS_FILE,  
     643                         "Error playing media file",  
     644                         status); 
    369645            return status; 
    370646        } 
    371     } 
    372  
     647 
     648        /* Add port to conference bridge: */ 
     649        port_name = pjsua.config.wav_file; 
     650        status = pjmedia_conf_add_port(pjsua.mconf, pjsua.pool,  
     651                                       pjsua.file_port,  
     652                                       &port_name, 
     653                                       &pjsua.wav_slot); 
     654        if (status != PJ_SUCCESS) { 
     655            pjsua_perror(THIS_FILE,  
     656                         "Unable to add file player to conference bridge",  
     657                         status); 
     658            return status; 
     659        } 
     660    } 
     661 
     662 
     663    return PJ_SUCCESS; 
     664} 
     665 
     666 
     667/* 
     668 * Copy configuration. 
     669 */ 
     670static void copy_config(pj_pool_t *pool, pjsua_config *dst,  
     671                        const pjsua_config *src) 
     672{ 
     673    unsigned i; 
     674 
     675    /* Plain memcpy */ 
     676    pj_memcpy(dst, src, sizeof(pjsua_config)); 
     677 
     678    /* Duplicate strings */ 
     679    pj_strdup_with_null(pool, &dst->sip_host, &src->sip_host); 
     680    pj_strdup_with_null(pool, &dst->stun_srv1, &src->stun_srv1); 
     681    pj_strdup_with_null(pool, &dst->stun_srv2, &src->stun_srv2); 
     682    pj_strdup_with_null(pool, &dst->wav_file, &src->wav_file); 
     683     
     684    for (i=0; i<src->codec_cnt; ++i) { 
     685        pj_strdup_with_null(pool, &dst->codec_arg[i], &src->codec_arg[i]); 
     686    } 
     687 
     688    pj_strdup_with_null(pool, &dst->outbound_proxy, &src->outbound_proxy); 
     689    pj_strdup_with_null(pool, &dst->uri_to_call, &src->uri_to_call); 
     690 
     691    for (i=0; i<src->acc_cnt; ++i) { 
     692        pjsua_acc_config *dst_acc = &dst->acc_config[i]; 
     693        const pjsua_acc_config *src_acc = &src->acc_config[i]; 
     694        unsigned j; 
     695 
     696        pj_strdup_with_null(pool, &dst_acc->id, &src_acc->id); 
     697        pj_strdup_with_null(pool, &dst_acc->reg_uri, &src_acc->reg_uri); 
     698        pj_strdup_with_null(pool, &dst_acc->contact, &src_acc->contact); 
     699        pj_strdup_with_null(pool, &dst_acc->proxy, &src_acc->proxy); 
     700 
     701        for (j=0; j<src_acc->cred_count; ++j) { 
     702            pj_strdup_with_null(pool, &dst_acc->cred_info[j].realm,  
     703                                &src_acc->cred_info[j].realm); 
     704            pj_strdup_with_null(pool, &dst_acc->cred_info[j].scheme,  
     705                                &src_acc->cred_info[j].scheme); 
     706            pj_strdup_with_null(pool, &dst_acc->cred_info[j].username,  
     707                                &src_acc->cred_info[j].username); 
     708            pj_strdup_with_null(pool, &dst_acc->cred_info[j].data,  
     709                                &src_acc->cred_info[j].data); 
     710        } 
     711    } 
     712 
     713    pj_strdup_with_null(pool, &dst->log_filename, &src->log_filename); 
     714 
     715    for (i=0; i<src->buddy_cnt; ++i) { 
     716        pj_strdup_with_null(pool, &dst->buddy_uri[i], &src->buddy_uri[i]); 
     717    } 
     718} 
     719 
     720 
     721/* 
     722 * Initialize pjsua application. 
     723 * This will initialize all libraries, create endpoint instance, and register 
     724 * pjsip modules. 
     725 */ 
     726PJ_DECL(pj_status_t) pjsua_init(const pjsua_config *cfg, 
     727                                const pjsua_callback *cb) 
     728{ 
     729    char errmsg[80]; 
     730    unsigned i; 
     731    pj_status_t status; 
     732 
     733 
     734    /* Init accounts: */ 
     735    for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) { 
     736        pjsua.acc[i].index = i; 
     737        pjsua.acc[i].online_status = PJ_TRUE; 
     738        pj_list_init(&pjsua.acc[i].route_set); 
     739        pj_list_init(&pjsua.acc[i].pres_srv_list); 
     740    } 
     741 
     742    /* Init call array: */ 
     743    for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i) { 
     744        pjsua.calls[i].index = i; 
     745        pjsua.calls[i].refresh_tm._timer_id = -1; 
     746        pjsua.calls[i].hangup_tm._timer_id = -1; 
     747        pjsua.calls[i].conf_slot = 0; 
     748    } 
     749 
     750    /* Copy configuration */ 
     751    copy_config(pjsua.pool, &pjsua.config, cfg); 
     752 
     753    /* Copy callback */ 
     754    pj_memcpy(&pjsua.cb, cb, sizeof(pjsua_callback)); 
     755 
     756    /* Test configuration */ 
     757    if (pjsua_test_config(&pjsua.config, errmsg, sizeof(errmsg))) { 
     758        PJ_LOG(1,(THIS_FILE, "Error in configuration: %s", errmsg)); 
     759        return -1; 
     760    } 
     761 
     762 
     763    /* Init PJLIB logging: */ 
     764 
     765    pj_log_set_level(pjsua.config.log_level); 
     766    pj_log_set_decor(pjsua.config.log_decor); 
     767 
     768 
     769    /* Create SIP UDP socket */ 
     770    if (pjsua.config.udp_port) { 
     771 
     772        status = create_sip_udp_sock( pjsua.config.udp_port, 
     773                                      &pjsua.sip_sock, 
     774                                      &pjsua.sip_sock_name); 
     775        if (status != PJ_SUCCESS) 
     776            return status; 
     777     
     778        pj_strdup2_with_null(pjsua.pool, &pjsua.config.sip_host, 
     779                             pj_inet_ntoa(pjsua.sip_sock_name.sin_addr)); 
     780        pjsua.config.sip_port = pj_ntohs(pjsua.sip_sock_name.sin_port); 
     781 
     782    } else { 
     783 
     784        /* Check that SIP host and port is configured */ 
     785        if (cfg->sip_host.slen == 0 || cfg->sip_port == 0) { 
     786            PJ_LOG(1,(THIS_FILE,  
     787                      "Error: sip_host and sip_port must be specified")); 
     788            return PJ_EINVAL; 
     789        } 
     790 
     791        pjsua.sip_sock = PJ_INVALID_SOCKET; 
     792    } 
     793 
     794 
     795    /* Init media endpoint */ 
     796    status = init_media(); 
     797    if (status != PJ_SUCCESS) 
     798        return status; 
     799 
     800 
     801    /* Init RTP sockets, only when UDP transport is enabled */ 
     802    for (i=0; pjsua.config.start_rtp_port && i<pjsua.config.max_calls; ++i) { 
     803        status = create_rtp_rtcp_sock(&pjsua.calls[i].skinfo); 
     804        if (status != PJ_SUCCESS) { 
     805            unsigned j; 
     806            for (j=0; j<i; ++j) { 
     807                pjmedia_transport_udp_close(pjsua.calls[j].med_tp); 
     808            } 
     809            return status; 
     810        } 
     811        status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL, 
     812                                              &pjsua.calls[i].skinfo, 
     813                                              &pjsua.calls[i].med_tp); 
     814    } 
     815 
     816    /* Init PJSIP : */ 
    373817 
    374818    /* Initialize transaction layer: */ 
     
    428872    } 
    429873 
    430     /* Done */ 
    431  
    432     return PJ_SUCCESS; 
    433  
    434  
    435 on_error: 
    436     pjsip_endpt_destroy(pjsua.endpt); 
    437     pjsua.endpt = NULL; 
    438     return status; 
    439 } 
    440  
    441  
    442 static int PJ_THREAD_FUNC pjsua_poll(void *arg) 
    443 { 
    444     pj_status_t last_err = 0; 
    445  
    446     PJ_UNUSED_ARG(arg); 
    447  
    448     do { 
    449         pj_time_val timeout = { 0, 10 }; 
    450         pj_status_t status; 
    451          
    452         status = pjsip_endpt_handle_events (pjsua.endpt, &timeout); 
    453         if (status != PJ_SUCCESS && status != last_err) { 
    454             last_err = status; 
    455             pjsua_perror(THIS_FILE, "handle_events() returned error", status); 
    456         } 
    457     } while (!pjsua.quit_flag); 
    458  
    459     return 0; 
    460 } 
    461  
    462 /* 
    463  * Initialize pjsua application. 
    464  * This will initialize all libraries, create endpoint instance, and register 
    465  * pjsip modules. 
    466  */ 
    467 pj_status_t pjsua_init(void) 
    468 { 
    469     pj_status_t status; 
    470  
    471     /* Init PJLIB logging: */ 
    472  
    473     pj_log_set_level(pjsua.log_level); 
    474     pj_log_set_decor(pjsua.log_decor); 
    475  
    476  
    477     /* Init PJLIB: */ 
    478  
    479     status = pj_init(); 
    480     if (status != PJ_SUCCESS) { 
    481         pjsua_perror(THIS_FILE, "pj_init() error", status); 
    482         return status; 
    483     } 
    484  
    485     /* Init PJLIB-UTIL: */ 
    486  
    487     status = pjlib_util_init(); 
    488     if (status != PJ_SUCCESS) { 
    489         pjsua_perror(THIS_FILE, "pjlib_util_init() error", status); 
    490         return status; 
    491     } 
    492  
    493     /* Init memory pool: */ 
    494  
    495     /* Init caching pool. */ 
    496     pj_caching_pool_init(&pjsua.cp, &pj_pool_factory_default_policy, 0); 
    497  
    498     /* Create memory pool for application. */ 
    499     pjsua.pool = pj_pool_create(&pjsua.cp.factory, "pjsua", 4000, 4000, NULL); 
    500  
    501  
    502     /* Init PJSIP : */ 
    503  
    504     status = init_stack(); 
    505     if (status != PJ_SUCCESS) { 
    506         pj_caching_pool_destroy(&pjsua.cp); 
    507         pjsua_perror(THIS_FILE, "Stack initialization has returned error",  
    508                      status); 
    509         return status; 
    510     } 
    511  
    512  
    513874    /* Init core SIMPLE module : */ 
    514875 
     
    531892    pjsua_im_init(); 
    532893 
    533  
    534     /* Init media endpoint: */ 
    535  
    536     status = pjmedia_endpt_create(&pjsua.cp.factory,  
    537                                   pjsip_endpt_get_ioqueue(pjsua.endpt), 0, 
    538                                   &pjsua.med_endpt); 
    539     if (status != PJ_SUCCESS) { 
    540         pj_caching_pool_destroy(&pjsua.cp); 
    541         pjsua_perror(THIS_FILE,  
    542                      "Media stack initialization has returned error",  
    543                      status); 
    544         return status; 
    545     } 
    546894 
    547895    /* Done. */ 
    548896    return PJ_SUCCESS; 
     897 
     898on_error: 
     899    pj_caching_pool_destroy(&pjsua.cp); 
     900    return status; 
    549901} 
    550902 
     
    557909    pjsip_uri *uri; 
    558910    pjsip_sip_uri *sip_uri; 
    559     int acc_index; 
     911    unsigned acc_index; 
    560912 
    561913    uri = rdata->msg_info.to->uri; 
    562914 
    563     /* Just return account #0 if To URI is not SIP: */ 
     915    /* Just return last account if To URI is not SIP: */ 
    564916    if (!PJSIP_URI_SCHEME_IS_SIP(uri) &&  
    565917        !PJSIP_URI_SCHEME_IS_SIPS(uri))  
    566918    { 
    567         return 0; 
     919        return pjsua.config.acc_cnt; 
    568920    } 
    569921 
     
    572924 
    573925    /* Find account which has matching username and domain. */ 
    574     for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) { 
     926    for (acc_index=0; acc_index < pjsua.config.acc_cnt; ++acc_index) { 
    575927 
    576928        pjsua_acc *acc = &pjsua.acc[acc_index]; 
     
    585937 
    586938    /* No matching, try match domain part only. */ 
    587     for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) { 
     939    for (acc_index=0; acc_index < pjsua.config.acc_cnt; ++acc_index) { 
    588940 
    589941        pjsua_acc *acc = &pjsua.acc[acc_index]; 
     
    595947    } 
    596948 
    597     /* Still no match, just return account #0 */ 
    598     return 0; 
     949    /* Still no match, just return last account */ 
     950    return pjsua.config.acc_cnt; 
    599951} 
    600952 
     
    611963} 
    612964 
    613  
    614 /* 
    615  * Init media. 
    616  */ 
    617 static pj_status_t init_media(void) 
    618 { 
    619     int i; 
    620     unsigned options; 
    621     unsigned clock_rate; 
    622     unsigned samples_per_frame; 
    623     pj_str_t codec_id; 
    624     pj_status_t status; 
    625  
    626     /* Register all codecs */ 
    627 #if PJMEDIA_HAS_SPEEX_CODEC 
    628     /* Register speex. */ 
    629     status = pjmedia_codec_speex_init(pjsua.med_endpt,  
    630                                       PJMEDIA_SPEEX_NO_UWB, 
    631                                       pjsua.quality, pjsua.complexity ); 
    632     if (status != PJ_SUCCESS) { 
    633         pjsua_perror(THIS_FILE, "Error initializing Speex codec", 
    634                      status); 
    635         return status; 
    636     } 
    637  
    638     /* Set "speex/16000/1" to have highest priority */ 
    639     codec_id = pj_str("speex/16000/1"); 
    640     pjmedia_codec_mgr_set_codec_priority(  
    641         pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 
    642         &codec_id,  
    643         PJMEDIA_CODEC_PRIO_HIGHEST); 
    644  
    645 #endif /* PJMEDIA_HAS_SPEEX_CODEC */ 
    646  
    647 #if PJMEDIA_HAS_GSM_CODEC 
    648     /* Register GSM */ 
    649     status = pjmedia_codec_gsm_init(pjsua.med_endpt); 
    650     if (status != PJ_SUCCESS) { 
    651         pjsua_perror(THIS_FILE, "Error initializing GSM codec", 
    652                      status); 
    653         return status; 
    654     } 
    655 #endif /* PJMEDIA_HAS_GSM_CODEC */ 
    656  
    657 #if PJMEDIA_HAS_G711_CODEC 
    658     /* Register PCMA and PCMU */ 
    659     status = pjmedia_codec_g711_init(pjsua.med_endpt); 
    660     if (status != PJ_SUCCESS) { 
    661         pjsua_perror(THIS_FILE, "Error initializing G711 codec", 
    662                      status); 
    663         return status; 
    664     } 
    665 #endif  /* PJMEDIA_HAS_G711_CODEC */ 
    666  
    667 #if PJMEDIA_HAS_L16_CODEC 
    668     /* Register L16 family codecs, but disable all */ 
    669     status = pjmedia_codec_l16_init(pjsua.med_endpt, 0); 
    670     if (status != PJ_SUCCESS) { 
    671         pjsua_perror(THIS_FILE, "Error initializing L16 codecs", 
    672                      status); 
    673         return status; 
    674     } 
    675  
    676     /* Disable ALL L16 codecs */ 
    677     codec_id = pj_str("L16"); 
    678     pjmedia_codec_mgr_set_codec_priority(  
    679         pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 
    680         &codec_id,  
    681         PJMEDIA_CODEC_PRIO_DISABLED); 
    682  
    683 #endif  /* PJMEDIA_HAS_L16_CODEC */ 
    684  
    685  
    686     /* Enable those codecs that user put with "--add-codec", and move 
    687      * the priority to top 
    688      */ 
    689     for (i=0; i<pjsua.codec_cnt; ++i) { 
    690         pjmedia_codec_mgr_set_codec_priority(  
    691             pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 
    692             &pjsua.codec_arg[i],  
    693             PJMEDIA_CODEC_PRIO_HIGHEST); 
    694     } 
    695  
    696  
    697     /* Init options for conference bridge. */ 
    698     options = 0; 
    699     if (pjsua.no_mic) 
    700         options |= PJMEDIA_CONF_NO_MIC; 
    701  
    702     /* Init conference bridge. */ 
    703     clock_rate = pjsua.clock_rate ? pjsua.clock_rate : 16000; 
    704     samples_per_frame = clock_rate * 10 / 1000; 
    705     status = pjmedia_conf_create(pjsua.pool,  
    706                                  pjsua.max_calls+PJSUA_CONF_MORE_PORTS,  
    707                                  clock_rate,  
    708                                  1, /* mono */ 
    709                                  samples_per_frame,  
    710                                  16,  
    711                                  options, 
    712                                  &pjsua.mconf); 
    713     if (status != PJ_SUCCESS) { 
    714         pjsua_perror(THIS_FILE,  
    715                      "Media stack initialization has returned error",  
    716                      status); 
    717         return status; 
    718     } 
    719  
    720     /* Add NULL port to the bridge. */ 
    721     status = pjmedia_null_port_create( pjsua.pool, clock_rate,  
    722                                        1, /* mono */ 
    723                                        samples_per_frame, 16, 
    724                                        &pjsua.null_port); 
    725     pjmedia_conf_add_port( pjsua.mconf, pjsua.pool, pjsua.null_port,  
    726                            &pjsua.null_port->info.name, NULL ); 
    727  
    728     /* Create WAV file player if required: */ 
    729  
    730     if (pjsua.wav_file) { 
    731         pj_str_t port_name; 
    732  
    733         /* Create the file player port. */ 
    734         status = pjmedia_wav_player_port_create(  pjsua.pool, pjsua.wav_file, 
    735                                                   0, 0, -1, NULL,  
    736                                                   &pjsua.file_port); 
    737         if (status != PJ_SUCCESS) { 
    738             pjsua_perror(THIS_FILE,  
    739                          "Error playing media file",  
    740                          status); 
    741             return status; 
    742         } 
    743  
    744         /* Add port to conference bridge: */ 
    745         status = pjmedia_conf_add_port(pjsua.mconf, pjsua.pool,  
    746                                        pjsua.file_port,  
    747                                        pj_cstr(&port_name, pjsua.wav_file), 
    748                                        &pjsua.wav_slot); 
    749         if (status != PJ_SUCCESS) { 
    750             pjsua_perror(THIS_FILE,  
    751                          "Unable to add file player to conference bridge",  
    752                          status); 
    753             return status; 
    754         } 
    755     } 
    756  
    757  
    758     return PJ_SUCCESS; 
    759 } 
    760965 
    761966 
     
    764969 * This will start the registration process, if registration is configured. 
    765970 */ 
    766 pj_status_t pjsua_start(void) 
     971PJ_DEF(pj_status_t) pjsua_start(void) 
    767972{ 
    768973    int i;  /* Must be signed */ 
    769     pjsip_transport *udp_transport; 
    770974    pj_status_t status = PJ_SUCCESS; 
    771975 
    772     /* 
    773      * Init media subsystem (codecs, conference bridge, et all). 
    774      */ 
    775     status = init_media(); 
    776     if (status != PJ_SUCCESS) 
    777         return status; 
    778  
    779     /* Init sockets (STUN etc): */ 
    780     for (i=0; i<(int)pjsua.max_calls; ++i) { 
    781         status = init_sockets(i==0, &pjsua.calls[i].skinfo); 
    782         if (status == PJ_SUCCESS) 
    783             status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL, 
    784                                                   &pjsua.calls[i].skinfo, 
    785                                                   &pjsua.calls[i].med_tp); 
    786         if (status != PJ_SUCCESS) { 
    787             pjsua_perror(THIS_FILE, "init_sockets() has returned error",  
    788                          status); 
    789             --i; 
    790             if (i >= 0) 
    791                 pj_sock_close(pjsua.sip_sock); 
    792             while (i >= 0) { 
    793                 pjmedia_transport_udp_close(pjsua.calls[i].med_tp); 
    794             } 
    795             return status; 
    796         } 
    797     } 
    798976 
    799977    /* Add UDP transport: */ 
    800  
    801     { 
     978    if (pjsua.sip_sock > 0) { 
     979 
    802980        /* Init the published name for the transport. 
    803981         * Depending whether STUN is used, this may be the STUN mapped 
     
    806984        pjsip_host_port addr_name; 
    807985 
    808         addr_name.host.ptr = pj_inet_ntoa(pjsua.sip_sock_name.sin_addr); 
    809         addr_name.host.slen = pj_ansi_strlen(addr_name.host.ptr); 
    810         addr_name.port = pj_ntohs(pjsua.sip_sock_name.sin_port); 
     986        addr_name.host = pjsua.config.sip_host; 
     987        addr_name.port = pjsua.config.sip_port; 
    811988 
    812989        /* Create UDP transport from previously created UDP socket: */ 
     
    814991        status = pjsip_udp_transport_attach( pjsua.endpt, pjsua.sip_sock, 
    815992                                             &addr_name, 1,  
    816                                              &udp_transport); 
     993                                             NULL); 
    817994        if (status != PJ_SUCCESS) { 
    818995            pjsua_perror(THIS_FILE, "Unable to start UDP transport",  
     
    822999    } 
    8231000 
    824     /* Initialize Contact URI, if one is not specified: */ 
    825     for (i=0; i<pjsua.acc_cnt; ++i) { 
    826  
     1001    /* The last account is default account to be used when nothing match  
     1002     * any configured accounts. 
     1003     */ 
     1004    { 
     1005        char buf[80]; 
     1006        pj_str_t tmp; 
     1007        pjsua_acc_config *acc_cfg =  
     1008            &pjsua.config.acc_config[pjsua.config.acc_cnt]; 
     1009 
     1010        tmp.ptr = buf; 
     1011        tmp.slen = pj_ansi_sprintf(tmp.ptr, "<sip:%s:%d>",  
     1012                                   pjsua.config.sip_host.ptr, 
     1013                                   pjsua.config.sip_port); 
     1014 
     1015        pj_strdup_with_null( pjsua.pool, &acc_cfg->id, &tmp); 
     1016        acc_cfg->contact = acc_cfg->id; 
     1017    } 
     1018     
     1019 
     1020    /* Initialize accounts: */ 
     1021    for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 
     1022 
     1023        pjsua_acc_config *acc_cfg = &pjsua.config.acc_config[i]; 
     1024        pjsua_acc *acc = &pjsua.acc[i]; 
    8271025        pjsip_uri *uri; 
    8281026        pjsip_sip_uri *sip_uri; 
     
    8301028        /* Need to parse local_uri to get the elements: */ 
    8311029 
    832         uri = pjsip_parse_uri(pjsua.pool, pjsua.acc[i].local_uri.ptr, 
    833                               pjsua.acc[i].local_uri.slen, 0); 
     1030        uri = pjsip_parse_uri(pjsua.pool, acc_cfg->id.ptr, 
     1031                              acc_cfg->id.slen, 0); 
    8341032        if (uri == NULL) { 
    8351033            pjsua_perror(THIS_FILE, "Invalid local URI",  
     
    8531051        sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri); 
    8541052 
    855         pjsua.acc[i].user_part = sip_uri->user; 
    856         pjsua.acc[i].host_part = sip_uri->host; 
    857  
    858         if (pjsua.acc[i].contact_uri.slen == 0 &&  
    859             pjsua.acc[i].local_uri.slen)  
    860         { 
     1053        acc->user_part = sip_uri->user; 
     1054        acc->host_part = sip_uri->host; 
     1055 
     1056        /* Build Contact header */ 
     1057 
     1058        if (acc_cfg->contact.slen == 0)  { 
    8611059            char contact[128]; 
     1060            const char *addr; 
     1061            int port; 
    8621062            int len; 
     1063 
     1064            addr = pjsua.config.sip_host.ptr; 
     1065            port = pjsua.config.sip_port; 
    8631066 
    8641067            /* The local Contact is the username@ip-addr, where 
     
    8741077                /* With the user part. */ 
    8751078                len = pj_ansi_snprintf(contact, sizeof(contact), 
    876                                   "<sip:%.*s@%.*s:%d>", 
     1079                                  "<sip:%.*s@%s:%d>", 
    8771080                                  (int)sip_uri->user.slen, 
    8781081                                  sip_uri->user.ptr, 
    879                                   (int)udp_transport->local_name.host.slen, 
    880                                   udp_transport->local_name.host.ptr, 
    881                                   udp_transport->local_name.port); 
     1082                                  addr, port); 
    8821083            } else { 
    8831084 
     
    8851086 
    8861087                len = pj_ansi_snprintf(contact, sizeof(contact), 
    887                                   "<sip:%.*s:%d>", 
    888                                   (int)udp_transport->local_name.host.slen, 
    889                                   udp_transport->local_name.host.ptr, 
    890                                   udp_transport->local_name.port); 
     1088                                  "<sip:%s:%d>", 
     1089                                  addr, port); 
    8911090            } 
    8921091 
     
    8981097            /* Duplicate Contact uri. */ 
    8991098 
    900             pj_strdup2(pjsua.pool, &pjsua.acc[i].contact_uri, contact); 
    901  
    902         } 
    903     } 
    904  
    905     /* If outbound_proxy is specified, put it in the route_set: */ 
    906  
    907     if (pjsua.outbound_proxy.slen) { 
    908  
    909         pjsip_route_hdr *route; 
    910         const pj_str_t hname = { "Route", 5 }; 
    911         int parsed_len; 
    912  
    913         route = pjsip_parse_hdr( pjsua.pool, &hname,  
    914                                  pjsua.outbound_proxy.ptr,  
    915                                  pjsua.outbound_proxy.slen, 
    916                                    &parsed_len); 
    917         if (route == NULL) { 
    918             pjsua_perror(THIS_FILE, "Invalid outbound proxy URL",  
    919                          PJSIP_EINVALIDURI); 
    920             return PJSIP_EINVALIDURI; 
    921         } 
    922  
    923         for (i=0; i<pjsua.acc_cnt; ++i) { 
    924             pj_list_push_front(&pjsua.acc[i].route_set, route); 
    925         } 
    926     } 
     1099            pj_strdup2(pjsua.pool, &acc_cfg->contact, contact); 
     1100 
     1101        } 
     1102 
     1103 
     1104        /* Build route-set for this account */ 
     1105        if (pjsua.config.outbound_proxy.slen) { 
     1106            pj_str_t hname = { "Route", 5}; 
     1107            pjsip_route_hdr *r; 
     1108            pj_str_t tmp; 
     1109 
     1110            pj_strdup_with_null(pjsua.pool, &tmp, &pjsua.config.outbound_proxy); 
     1111            r = pjsip_parse_hdr(pjsua.pool, &hname, tmp.ptr, tmp.slen, NULL); 
     1112            pj_list_push_back(&acc->route_set, r); 
     1113        } 
     1114 
     1115        if (acc_cfg->proxy.slen) { 
     1116            pj_str_t hname = { "Route", 5}; 
     1117            pjsip_route_hdr *r; 
     1118            pj_str_t tmp; 
     1119 
     1120            pj_strdup_with_null(pjsua.pool, &tmp, &acc_cfg->proxy); 
     1121            r = pjsip_parse_hdr(pjsua.pool, &hname, tmp.ptr, tmp.slen, NULL); 
     1122            pj_list_push_back(&acc->route_set, r); 
     1123        } 
     1124    } 
     1125 
     1126 
    9271127 
    9281128 
    9291129    /* Create worker thread(s), if required: */ 
    9301130 
    931     for (i=0; i<pjsua.thread_cnt; ++i) { 
     1131    for (i=0; i<(int)pjsua.config.thread_cnt; ++i) { 
    9321132        status = pj_thread_create( pjsua.pool, "pjsua", &pjsua_poll, 
    9331133                                   NULL, 0, 0, &pjsua.threads[i]); 
     
    9451145 
    9461146    /* Create client registration session: */ 
    947     for (i=0; i<pjsua.acc_cnt; ++i) { 
     1147    for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 
    9481148        status = pjsua_regc_init(i); 
    9491149        if (status != PJ_SUCCESS) 
     
    9561156    } 
    9571157 
     1158 
     1159    /* Init buddies */ 
     1160    for (i=0; i<(int)pjsua.config.buddy_cnt; ++i) { 
     1161        pjsua.buddies[i].uri = pjsua.config.buddy_uri[i]; 
     1162    } 
     1163    pjsua.buddy_cnt = pjsua.config.buddy_cnt; 
    9581164 
    9591165    /* Find account for outgoing preence subscription */ 
     
    9871193 * Destroy pjsua. 
    9881194 */ 
    989 pj_status_t pjsua_destroy(void) 
     1195PJ_DEF(pj_status_t) pjsua_destroy(void) 
    9901196{ 
    9911197    int i;  /* Must be signed */ 
     
    10011207 
    10021208    /* Unregister, if required: */ 
    1003     for (i=0; i<pjsua.acc_cnt; ++i) { 
     1209    for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 
    10041210        if (pjsua.acc[i].regc) { 
    10051211            pjsua_regc_update(i, 0); 
     
    10081214 
    10091215    /* Wait worker threads to quit: */ 
    1010     for (i=0; i<pjsua.thread_cnt; ++i) { 
     1216    for (i=0; i<(int)pjsua.config.thread_cnt; ++i) { 
    10111217         
    10121218        if (pjsua.threads[i]) { 
     
    10301236        pjmedia_port_destroy(pjsua.file_port); 
    10311237 
    1032     /* Destroy null port. */ 
    1033     if (pjsua.null_port) 
    1034         pjmedia_port_destroy(pjsua.null_port); 
    1035  
    10361238 
    10371239    /* Shutdown all codecs: */ 
     
    10541256 
    10551257    /* Close transports */ 
    1056     for (i=0; i<pjsua.call_cnt; ++i) { 
     1258    for (i=0; pjsua.config.start_rtp_port && i<(int)pjsua.config.max_calls; ++i) { 
    10571259        pjmedia_transport_udp_close(pjsua.calls[i].med_tp); 
    10581260    } 
Note: See TracChangeset for help on using the changeset viewer.