Changeset 1990


Ignore:
Timestamp:
Jun 6, 2008 2:51:48 PM (11 years ago)
Author:
bennylp
Message:

More ticket #485: added TURN support in PJSUA-LIB API

Location:
pjproject/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r1976 r1990  
    171171    puts  (""); 
    172172    puts  ("Media Options:"); 
    173     puts  ("  --use-ice           Enable ICE (default:no)"); 
    174173    puts  ("  --add-codec=name    Manually add codec (default is to enable all)"); 
    175174    puts  ("  --dis-codec=name    Disable codec (can be specified multiple times)"); 
     
    189188    puts  ("  --rec-file=file     Open file recorder (extension can be .wav or .mp3"); 
    190189    puts  ("  --auto-rec          Automatically record conversation"); 
    191     puts  ("  --rtp-port=N        Base port to try for RTP (default=4000)"); 
    192190    puts  ("  --quality=N         Specify media quality (0-10, default=6)"); 
    193191    puts  ("  --ptime=MSEC        Override codec ptime to MSEC (default=specific)"); 
     
    195193    puts  ("  --ec-tail=MSEC      Set echo canceller tail length (default=256)"); 
    196194    puts  ("  --ilbc-mode=MODE    Set iLBC codec mode (20 or 30, default is 20)"); 
     195    puts  ("  --capture-dev=id    Audio capture device ID (default=-1)"); 
     196    puts  ("  --playback-dev=id   Audio playback device ID (default=-1)"); 
     197 
     198    puts  (""); 
     199    puts  ("Media Transport Options:"); 
     200    puts  ("  --use-ice           Enable ICE (default:no)"); 
     201    puts  ("  --ice-no-host       Disable ICE host candidates"); 
     202    puts  ("  --rtp-port=N        Base port to try for RTP (default=4000)"); 
    197203    puts  ("  --rx-drop-pct=PCT   Drop PCT percent of RX RTP (for pkt lost sim, default: 0)"); 
    198204    puts  ("  --tx-drop-pct=PCT   Drop PCT percent of TX RTP (for pkt lost sim, default: 0)"); 
    199     puts  ("  --capture-dev=id    Audio capture device ID (default=-1)"); 
    200     puts  ("  --playback-dev=id   Audio playback device ID (default=-1)"); 
    201  
     205    puts  ("  --use-turn          Enable TURN relay with ICE (default:no)"); 
     206    puts  ("  --turn-srv          Domain or host name of TURN server (\"NAME:PORT\" format)"); 
     207    puts  ("  --turn-tcp          Use TCP connection to TURN server (default no)"); 
     208    puts  ("  --turn-user         TURN username"); 
     209    puts  ("  --turn-passwd       TURN password"); 
    202210 
    203211    puts  (""); 
     
    393401           OPT_AUTO_CONF, OPT_CLOCK_RATE, OPT_SND_CLOCK_RATE, OPT_STEREO, 
    394402           OPT_USE_ICE, OPT_USE_SRTP, OPT_SRTP_SECURE, 
     403           OPT_USE_TURN,OPT_ICE_NO_HOST, OPT_TURN_SRV, OPT_TURN_TCP, 
     404           OPT_TURN_USER, OPT_TURN_PASSWD, 
    395405           OPT_PLAY_FILE, OPT_PLAY_TONE, OPT_RTP_PORT, OPT_ADD_CODEC,  
    396406           OPT_ILBC_MODE, OPT_REC_FILE, OPT_AUTO_REC, 
     
    452462        { "rec-file",   1, 0, OPT_REC_FILE}, 
    453463        { "rtp-port",   1, 0, OPT_RTP_PORT}, 
     464 
    454465        { "use-ice",    0, 0, OPT_USE_ICE}, 
     466        { "use-turn",   0, 0, OPT_USE_TURN}, 
     467        { "ice-no-host",0, 0, OPT_ICE_NO_HOST}, 
     468        { "turn-srv",   1, 0, OPT_TURN_SRV}, 
     469        { "turn-tcp",   0, 0, OPT_TURN_TCP}, 
     470        { "turn-user",  1, 0, OPT_TURN_USER}, 
     471        { "turn-passwd",1, 0, OPT_TURN_PASSWD}, 
     472 
    455473#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    456474        { "use-srtp",   1, 0, OPT_USE_SRTP}, 
     
    826844            break; 
    827845 
     846        case OPT_USE_TURN: 
     847            cfg->media_cfg.enable_turn = PJ_TRUE; 
     848            break; 
     849 
     850        case OPT_ICE_NO_HOST: 
     851            cfg->media_cfg.ice_no_host_cands = PJ_TRUE; 
     852            break; 
     853 
     854        case OPT_TURN_SRV: 
     855            cfg->media_cfg.turn_server = pj_str(pj_optarg); 
     856            break; 
     857 
     858        case OPT_TURN_TCP: 
     859            cfg->media_cfg.turn_conn_type = PJ_TURN_TP_TCP; 
     860            break; 
     861 
     862        case OPT_TURN_USER: 
     863            cfg->media_cfg.turn_auth_cred.type = PJ_STUN_AUTH_CRED_STATIC; 
     864            cfg->media_cfg.turn_auth_cred.data.static_cred.realm = pj_str("*"); 
     865            cfg->media_cfg.turn_auth_cred.data.static_cred.username = pj_str(pj_optarg); 
     866            break; 
     867 
     868        case OPT_TURN_PASSWD: 
     869            cfg->media_cfg.turn_auth_cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN; 
     870            cfg->media_cfg.turn_auth_cred.data.static_cred.data = pj_str(pj_optarg); 
     871            break; 
     872 
    828873#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    829874        case OPT_USE_SRTP: 
     
    13601405#endif 
    13611406 
    1362     /* Media */ 
     1407    /* Media Transport*/ 
    13631408    if (config->media_cfg.enable_ice) 
    13641409        pj_strcat2(&cfg, "--use-ice\n"); 
     1410 
     1411    if (config->media_cfg.enable_turn) 
     1412        pj_strcat2(&cfg, "--use-turn\n"); 
     1413 
     1414    if (config->media_cfg.ice_no_host_cands) 
     1415        pj_strcat2(&cfg, "--ice-no-host\n"); 
     1416 
     1417    if (config->media_cfg.turn_server.slen) { 
     1418        pj_ansi_sprintf(line, "--turn-srv %.*s\n", 
     1419                        (int)config->media_cfg.turn_server.slen, 
     1420                        config->media_cfg.turn_server.ptr); 
     1421        pj_strcat2(&cfg, line); 
     1422    } 
     1423 
     1424    if (config->media_cfg.turn_conn_type == PJ_TURN_TP_TCP) 
     1425        pj_strcat2(&cfg, "--turn-tcp\n"); 
     1426 
     1427    if (config->media_cfg.turn_auth_cred.data.static_cred.username.slen) { 
     1428        pj_ansi_sprintf(line, "--turn-user %.*s\n", 
     1429                        (int)config->media_cfg.turn_auth_cred.data.static_cred.username.slen, 
     1430                        config->media_cfg.turn_auth_cred.data.static_cred.username.ptr); 
     1431        pj_strcat2(&cfg, line); 
     1432    } 
     1433 
     1434    if (config->media_cfg.turn_auth_cred.data.static_cred.data.slen) { 
     1435        pj_ansi_sprintf(line, "--turn-passwd %.*s\n", 
     1436                        (int)config->media_cfg.turn_auth_cred.data.static_cred.data.slen, 
     1437                        config->media_cfg.turn_auth_cred.data.static_cred.data.ptr); 
     1438        pj_strcat2(&cfg, line); 
     1439    } 
     1440 
     1441    /* Media */ 
    13651442    if (config->null_audio) 
    13661443        pj_strcat2(&cfg, "--null-audio\n"); 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r1951 r1990  
    10291029    /** 
    10301030     * Specify domain name to be resolved with DNS SRV resolution to get the 
    1031      * address of the STUN servers. Alternatively application may specify 
    1032      * \a stun_host and \a stun_relay_host instead. 
     1031     * address of the STUN server. Alternatively application may specify 
     1032     * \a stun_host instead. 
    10331033     * 
    10341034     * If DNS SRV resolution failed for this domain, then DNS A resolution 
     
    10421042     */ 
    10431043    pj_str_t        stun_host; 
    1044  
    1045     /** 
    1046      * Specify STUN relay server to be used. 
    1047      */ 
    1048     pj_str_t        stun_relay_host; 
    10491044 
    10501045    /** 
     
    38873882 
    38883883    /** 
    3889      * Enable ICE media relay. 
    3890      */ 
    3891     pj_bool_t           enable_relay; 
     3884     * Disable ICE host candidates. 
     3885     */ 
     3886    pj_bool_t           ice_no_host_cands; 
     3887 
     3888    /** 
     3889     * Enable TURN relay candidate in ICE. 
     3890     */ 
     3891    pj_bool_t           enable_turn; 
     3892 
     3893    /** 
     3894     * Specify TURN domain name or host name, in in "DOMAIN:PORT" or  
     3895     * "HOST:PORT" format. 
     3896     */ 
     3897    pj_str_t            turn_server; 
     3898 
     3899    /** 
     3900     * Specify the connection type to be used to the TURN server. Valid 
     3901     * values are PJ_TURN_TP_UDP or PJ_TURN_TP_TCP. 
     3902     * 
     3903     * Default: PJ_TURN_TP_UDP 
     3904     */ 
     3905    pj_turn_tp_type     turn_conn_type; 
     3906 
     3907    /** 
     3908     * Specify the credential to authenticate with the TURN server. 
     3909     */ 
     3910    pj_stun_auth_cred   turn_auth_cred; 
    38923911}; 
    38933912 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r1889 r1990  
    5353                                         call was triggered by xfer.        */ 
    5454    pjmedia_transport   *med_tp;    /**< Current media transport.           */ 
     55    pj_status_t          med_tp_st; /**< Media transport status.            */ 
    5556    pjmedia_transport   *med_orig;  /**< Original media transport           */ 
    5657    pj_timer_entry       refresh_tm;/**< Timer to send re-INVITE.           */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r1898 r1990  
    114114    pj_strdup_with_null(pool, &dst->stun_domain, &src->stun_domain); 
    115115    pj_strdup_with_null(pool, &dst->stun_host, &src->stun_host); 
    116     pj_strdup_with_null(pool, &dst->stun_relay_host, &src->stun_relay_host); 
    117116} 
    118117 
     
    173172    cfg->ec_tail_len = PJSUA_DEFAULT_EC_TAIL_LEN; 
    174173    cfg->jb_init = cfg->jb_min_pre = cfg->jb_max_pre = cfg->jb_max = -1; 
     174 
     175    cfg->turn_conn_type = PJ_TURN_TP_UDP; 
    175176} 
    176177 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r1970 r1990  
    3737 
    3838 
     39static void pjsua_media_config_dup(pj_pool_t *pool, 
     40                                   pjsua_media_config *dst, 
     41                                   const pjsua_media_config *src) 
     42{ 
     43    pj_memcpy(dst, src, sizeof(*src)); 
     44    pj_strdup(pool, &dst->turn_server, &src->turn_server); 
     45    pj_stun_auth_cred_dup(pool, &dst->turn_auth_cred, &src->turn_auth_cred); 
     46} 
     47 
    3948/** 
    4049 * Init media subsystems. 
     
    5059 
    5160    /* Copy configuration */ 
    52     pj_memcpy(&pjsua_var.media_cfg, cfg, sizeof(*cfg)); 
     61    pjsua_media_config_dup(pjsua_var.pool, &pjsua_var.media_cfg, cfg); 
    5362 
    5463    /* Normalize configuration */ 
     
    582591 
    583592/* This callback is called when ICE negotiation completes */ 
    584 static void on_ice_complete(pjmedia_transport *tp, pj_status_t result) 
    585 { 
    586     unsigned id, c; 
     593static void on_ice_complete(pjmedia_transport *tp,  
     594                            pj_ice_strans_op op, 
     595                            pj_status_t result) 
     596{ 
     597    unsigned id; 
    587598    pj_bool_t found = PJ_FALSE; 
    588599 
    589     /* We're only interested with failure case */ 
    590     if (result == PJ_SUCCESS) 
     600    /* Find call which has this media transport */ 
     601 
     602    PJSUA_LOCK(); 
     603 
     604    for (id=0; id<pjsua_var.ua_cfg.max_calls; ++id) { 
     605        if (pjsua_var.calls[id].med_tp == tp || 
     606            pjsua_var.calls[id].med_orig == tp)  
     607        { 
     608            found = PJ_TRUE; 
     609            break; 
     610        } 
     611    } 
     612 
     613    PJSUA_UNLOCK(); 
     614 
     615    if (!found) 
    591616        return; 
    592617 
    593     /* Find call which has this media transport */ 
    594  
    595     PJSUA_LOCK(); 
    596  
    597     for (id=0, c=0; id<PJSUA_MAX_CALLS && c<pjsua_var.call_cnt; ++id) { 
    598         pjsua_call *call = &pjsua_var.calls[id]; 
    599         if (call->inv) { 
    600             ++c; 
    601  
    602             if (call->med_tp == tp) { 
    603                 call->media_st = PJSUA_CALL_MEDIA_ERROR; 
    604                 call->media_dir = PJMEDIA_DIR_NONE; 
    605                 found = PJ_TRUE; 
    606                 break; 
     618    switch (op) { 
     619    case PJ_ICE_STRANS_OP_INIT: 
     620        pjsua_var.calls[id].med_tp_st = result; 
     621        break; 
     622    case PJ_ICE_STRANS_OP_NEGOTIATION: 
     623        if (result != PJ_SUCCESS) { 
     624            pjsua_var.calls[id].media_st = PJSUA_CALL_MEDIA_ERROR; 
     625            pjsua_var.calls[id].media_dir = PJMEDIA_DIR_NONE; 
     626 
     627            if (pjsua_var.ua_cfg.cb.on_call_media_state) { 
     628                pjsua_var.ua_cfg.cb.on_call_media_state(id); 
    607629            } 
    608630        } 
    609     } 
    610  
    611     PJSUA_UNLOCK(); 
    612  
    613     if (found && pjsua_var.ua_cfg.cb.on_call_media_state) { 
    614         pjsua_var.ua_cfg.cb.on_call_media_state(id); 
    615     } 
    616 } 
    617  
     631        break; 
     632    } 
     633} 
     634 
     635 
     636/* Parse "HOST:PORT" format */ 
     637static pj_status_t parse_host_port(const pj_str_t *host_port, 
     638                                   pj_str_t *host, pj_uint16_t *port) 
     639{ 
     640    pj_str_t str_port; 
     641 
     642    str_port.ptr = pj_strchr(host_port, ':'); 
     643    if (str_port.ptr != NULL) { 
     644        int iport; 
     645 
     646        host->ptr = host_port->ptr; 
     647        host->slen = (str_port.ptr - host->ptr); 
     648        str_port.ptr++; 
     649        str_port.slen = host_port->slen - host->slen - 1; 
     650        iport = (int)pj_strtoul(&str_port); 
     651        if (iport < 1 || iport > 65535) 
     652            return PJ_EINVAL; 
     653        *port = (pj_uint16_t)iport; 
     654    } else { 
     655        *host = *host_port; 
     656        *port = 0; 
     657    } 
     658 
     659    return PJ_SUCCESS; 
     660} 
    618661 
    619662/* Create ICE media transports (when ice is enabled) */ 
    620 static pj_status_t create_ice_media_transports(pjsua_transport_config *cfg) 
    621 { 
     663static pj_status_t create_ice_media_transports(void) 
     664{ 
     665    char stunip[PJ_INET6_ADDRSTRLEN]; 
     666    pj_ice_strans_cfg ice_cfg; 
    622667    unsigned i; 
    623     pj_sockaddr_in addr; 
    624668    pj_status_t status; 
    625669 
     
    631675    } 
    632676 
    633     pj_sockaddr_in_init(&addr, 0, (pj_uint16_t)cfg->port); 
     677    /* Create ICE stream transport configuration */ 
     678    pj_ice_strans_cfg_default(&ice_cfg); 
     679    pj_stun_config_init(&ice_cfg.stun_cfg, &pjsua_var.cp.factory, 0, 
     680                        pjsip_endpt_get_ioqueue(pjsua_var.endpt), 
     681                        pjsip_endpt_get_timer_heap(pjsua_var.endpt)); 
     682     
     683    ice_cfg.af = pj_AF_INET(); 
     684    ice_cfg.resolver = pjsua_var.resolver; 
     685     
     686    /* Configure STUN settings */ 
     687    if (pj_sockaddr_has_addr(&pjsua_var.stun_srv)) { 
     688        pj_sockaddr_print(&pjsua_var.stun_srv, stunip, sizeof(stunip), 0); 
     689        ice_cfg.stun.server = pj_str(stunip); 
     690        ice_cfg.stun.port = pj_sockaddr_get_port(&pjsua_var.stun_srv); 
     691    } 
     692    ice_cfg.stun.no_host_cands = pjsua_var.media_cfg.ice_no_host_cands; 
     693 
     694    /* Configure TURN settings */ 
     695    if (pjsua_var.media_cfg.enable_turn) { 
     696        status = parse_host_port(&pjsua_var.media_cfg.turn_server, 
     697                                 &ice_cfg.turn.server, 
     698                                 &ice_cfg.turn.port); 
     699        if (status != PJ_SUCCESS || ice_cfg.turn.server.slen == 0) { 
     700            PJ_LOG(1,(THIS_FILE, "Invalid TURN server setting")); 
     701            return PJ_EINVAL; 
     702        } 
     703        if (ice_cfg.turn.port == 0) 
     704            ice_cfg.turn.port = 3479; 
     705        ice_cfg.turn.conn_type = pjsua_var.media_cfg.turn_conn_type; 
     706        pj_memcpy(&ice_cfg.turn.auth_cred,  
     707                  &pjsua_var.media_cfg.turn_auth_cred, 
     708                  sizeof(ice_cfg.turn.auth_cred)); 
     709    } 
    634710 
    635711    /* Create each media transport */ 
    636712    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 
    637         pj_ice_strans_comp comp; 
    638713        pjmedia_ice_cb ice_cb; 
    639         int next_port; 
    640714        char name[32]; 
    641 #if PJMEDIA_ADVERTISE_RTCP 
    642         enum { COMP_CNT=2 }; 
    643 #else 
    644         enum { COMP_CNT=1 }; 
    645 #endif 
     715        unsigned comp_cnt; 
    646716 
    647717        pj_bzero(&ice_cb, sizeof(pjmedia_ice_cb)); 
    648718        ice_cb.on_ice_complete = &on_ice_complete; 
    649  
    650719        pj_ansi_snprintf(name, sizeof(name), "icetp%02d", i); 
    651                           
    652         status = pjmedia_ice_create(pjsua_var.med_endpt, name, COMP_CNT, 
    653                                     &pjsua_var.stun_cfg, &ice_cb, 
     720        pjsua_var.calls[i].med_tp_st = PJ_EPENDING; 
     721 
     722        comp_cnt = 1; 
     723        if (PJMEDIA_ADVERTISE_RTCP) 
     724            ++comp_cnt; 
     725 
     726        status = pjmedia_ice_create(pjsua_var.med_endpt, name, comp_cnt, 
     727                                    &ice_cfg, &ice_cb, 
    654728                                    &pjsua_var.calls[i].med_tp); 
    655729        if (status != PJ_SUCCESS) { 
     
    659733        } 
    660734 
     735        /* Wait until transport is initialized, or time out */ 
     736        PJSUA_UNLOCK(); 
     737        while (pjsua_var.calls[i].med_tp_st == PJ_EPENDING) { 
     738            pjsua_handle_events(100); 
     739        } 
     740        PJSUA_LOCK(); 
     741        if (pjsua_var.calls[i].med_tp_st != PJ_SUCCESS) { 
     742            pjsua_perror(THIS_FILE, "Error initializing ICE media transport", 
     743                         pjsua_var.calls[i].med_tp_st); 
     744            status = pjsua_var.calls[i].med_tp_st; 
     745            goto on_error; 
     746        } 
     747 
    661748        pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp, 
    662749                                        PJMEDIA_DIR_ENCODING, 
     
    666753                                        PJMEDIA_DIR_DECODING, 
    667754                                        pjsua_var.media_cfg.rx_drop_pct); 
    668  
    669         status = pjmedia_ice_start_init(pjsua_var.calls[i].med_tp, 0, &addr, 
    670                                         &pjsua_var.stun_srv.ipv4, NULL); 
    671         if (status != PJ_SUCCESS) { 
    672             pjsua_perror(THIS_FILE, "Error starting ICE transport", 
    673                          status); 
    674             goto on_error; 
    675         } 
    676  
    677         pjmedia_ice_get_comp(pjsua_var.calls[i].med_tp, 1, &comp); 
    678         next_port = pj_ntohs(comp.local_addr.ipv4.sin_port); 
    679         next_port += 2; 
    680         addr.sin_port = pj_htons((pj_uint16_t)next_port); 
    681     } 
    682  
    683     /* Wait until all ICE transports are ready */ 
    684     for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 
    685  
    686         /* Wait until interface status is PJ_SUCCESS */ 
    687         for (;;) { 
    688             status = pjmedia_ice_get_init_status(pjsua_var.calls[i].med_tp); 
    689             if (status == PJ_EPENDING) 
    690                 pjsua_handle_events(100); 
    691             else 
    692                 break; 
    693         } 
    694  
    695         if (status != PJ_SUCCESS) { 
    696             pjsua_perror(THIS_FILE,  
    697                          "Error adding STUN address to ICE media transport", 
    698                          status); 
    699             goto on_error; 
    700         } 
    701  
    702755    } 
    703756 
     
    745798 
    746799    if (pjsua_var.media_cfg.enable_ice) { 
    747         status = create_ice_media_transports(&cfg); 
     800        status = create_ice_media_transports(); 
    748801    } else { 
    749802        status = create_udp_media_transports(&cfg); 
     
    897950    pjsua_call *call = &pjsua_var.calls[call_id]; 
    898951 
    899     pjmedia_transport_media_stop(call->med_tp); 
     952    //see ticket #525 
     953    //pjmedia_transport_media_stop(call->med_tp); 
    900954 
    901955    if (call->conf_slot != PJSUA_INVALID_ID) { 
Note: See TracChangeset for help on using the changeset viewer.