Changeset 3366


Ignore:
Timestamp:
Nov 16, 2010 3:07:46 AM (10 years ago)
Author:
bennylp
Message:

Implemented SIP outbound (closed #1020)

Location:
pjproject/trunk/pjsip
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r3339 r3366  
    23342334 
    23352335    /** 
     2336     * Control the use of SIP outbound feature. SIP outbound is described in 
     2337     * RFC 5626 to enable proxies or registrar to send inbound requests back 
     2338     * to UA using the same connection initiated by the UA for its 
     2339     * registration. This feature is highly useful in NAT-ed deployemtns, 
     2340     * hence it is enabled by default. 
     2341     * 
     2342     * Note: currently SIP outbound can only be used with TCP and TLS 
     2343     * transports. If UDP is used for the registration, the SIP outbound 
     2344     * feature will be silently ignored for the account. 
     2345     * 
     2346     * Default: PJ_TRUE 
     2347     */ 
     2348    unsigned         use_rfc5626; 
     2349 
     2350    /** 
     2351     * Specify SIP outbound (RFC 5626) instance ID to be used by this 
     2352     * application. If empty, an instance ID will be generated based on 
     2353     * the hostname of this agent. If application specifies this parameter, the 
     2354     * value will look like "<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>" 
     2355     * without the doublequote. 
     2356     * 
     2357     * Default: empty 
     2358     */ 
     2359    pj_str_t         rfc5626_instance_id; 
     2360 
     2361    /** 
     2362     * Specify SIP outbound (RFC 5626) registration ID. The default value 
     2363     * is empty, which would cause the library to automatically generate 
     2364     * a suitable value. 
     2365     * 
     2366     * Default: empty 
     2367     */ 
     2368    pj_str_t         rfc5626_reg_id; 
     2369 
     2370    /** 
    23362371     * Set the interval for periodic keep-alive transmission for this account. 
    23372372     * If this value is zero, keep-alive will be disabled for this account. 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r3349 r3366  
    115115}; 
    116116 
    117  
    118117/** 
    119118 * Account 
     
    129128    pj_str_t         user_part;     /**< User part of local URI.        */ 
    130129    pj_str_t         contact;       /**< Our Contact header.            */ 
     130    pj_str_t         reg_contact;   /**< Contact header for REGISTER. 
     131                                         It may be different than acc 
     132                                         contact if outbound is used    */ 
    131133 
    132134    pj_str_t         srv_domain;    /**< Host part of reg server.       */ 
     
    152154    pj_uint32_t      global_route_crc; /** CRC of global route setting. */ 
    153155    pj_uint32_t      local_route_crc;  /** CRC of account route setting.*/ 
     156 
     157    unsigned         rfc5626_status;/**< SIP outbound status: 
     158                                           0: not used 
     159                                           1: requested 
     160                                           2: acknowledged by servers   */ 
     161    pj_str_t         rfc5626_instprm;/**< SIP outbound instance param.  */ 
     162    pj_str_t         rfc5626_regprm;/**< SIP outbound reg param.        */ 
    154163 
    155164    unsigned         cred_cnt;      /**< Number of credentials.         */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c

    r3326 r3366  
    2424#define THIS_FILE               "pjsua_acc.c" 
    2525 
     26enum 
     27{ 
     28    OUTBOUND_NONE, 
     29    OUTBOUND_WANTED, 
     30    OUTBOUND_ACTIVE 
     31}; 
     32 
    2633 
    2734static void schedule_reregistration(pjsua_acc *acc); 
     
    8087    pj_strdup_with_null(pool, &dst->force_contact, &src->force_contact); 
    8188    pj_strdup_with_null(pool, &dst->pidf_tuple_id, &src->pidf_tuple_id); 
     89    pj_strdup_with_null(pool, &dst->rfc5626_instance_id, &src->rfc5626_instance_id); 
     90    pj_strdup_with_null(pool, &dst->rfc5626_reg_id, &src->rfc5626_reg_id); 
    8291 
    8392    dst->proxy_cnt = src->proxy_cnt; 
     
    269278    if (status != PJ_SUCCESS) 
    270279        return status; 
     280 
     281    /* If SIP outbound is enabled, generate instance and reg ID if they are 
     282     * not specified 
     283     */ 
     284    if (acc_cfg->use_rfc5626) { 
     285        if (acc_cfg->rfc5626_instance_id.slen==0) { 
     286            const pj_str_t *hostname; 
     287            pj_uint32_t hval, pos; 
     288            char instprm[] = ";+sip.instance=\"<urn:uuid:00000000-0000-0000-0000-0000CCDDEEFF>\""; 
     289 
     290            hostname = pj_gethostname(); 
     291            pos = pj_ansi_strlen(instprm) - 10; 
     292            hval = pj_hash_calc(0, hostname->ptr, hostname->slen); 
     293            pj_val_to_hex_digit( ((char*)&hval)[0], instprm+pos+0); 
     294            pj_val_to_hex_digit( ((char*)&hval)[1], instprm+pos+2); 
     295            pj_val_to_hex_digit( ((char*)&hval)[2], instprm+pos+4); 
     296            pj_val_to_hex_digit( ((char*)&hval)[3], instprm+pos+6); 
     297 
     298            pj_strdup2(acc->pool, &acc->rfc5626_instprm, instprm); 
     299        } else { 
     300            const char *prmname = ";+sip.instance=\""; 
     301            unsigned len; 
     302 
     303            len = pj_ansi_strlen(prmname) + acc_cfg->rfc5626_instance_id.slen + 1; 
     304            acc->rfc5626_instprm.ptr = (char*)pj_pool_alloc(acc->pool, len+1); 
     305            pj_ansi_snprintf(acc->rfc5626_instprm.ptr, len+1, 
     306                             "%s%.*s\"", 
     307                             prmname, 
     308                             (int)acc_cfg->rfc5626_instance_id.slen, 
     309                             acc_cfg->rfc5626_instance_id.ptr); 
     310            acc->rfc5626_instprm.slen = len; 
     311        } 
     312 
     313        if (acc_cfg->rfc5626_reg_id.slen==0) { 
     314            acc->rfc5626_regprm = pj_str(";reg-id=1"); 
     315        } else { 
     316            const char *prmname = ";reg-id="; 
     317            unsigned len; 
     318 
     319            len = pj_ansi_strlen(prmname) + acc_cfg->rfc5626_reg_id.slen; 
     320            acc->rfc5626_regprm.ptr = (char*)pj_pool_alloc(acc->pool, len+1); 
     321            pj_ansi_snprintf(acc->rfc5626_regprm.ptr, len+1, 
     322                             "%s%.*s\"", 
     323                             prmname, 
     324                             (int)acc_cfg->rfc5626_reg_id.slen, 
     325                             acc_cfg->rfc5626_reg_id.ptr); 
     326            acc->rfc5626_regprm.slen = len; 
     327        } 
     328    } 
    271329 
    272330    /* Mark account as valid */ 
     
    900958    } 
    901959 
     960    /* SIP outbound setting */ 
     961    if (acc->cfg.use_rfc5626 != cfg->use_rfc5626 || 
     962        pj_strcmp(&acc->cfg.rfc5626_instance_id, &cfg->rfc5626_instance_id) || 
     963        pj_strcmp(&acc->cfg.rfc5626_reg_id, &cfg->rfc5626_reg_id)) 
     964    { 
     965        update_reg = PJ_TRUE; 
     966    } 
     967 
    902968    /* Update registration */ 
    903969    if (update_reg) { 
     
    9541020    pjsua_pres_update_acc(acc_id, PJ_TRUE); 
    9551021    return PJ_SUCCESS; 
     1022} 
     1023 
     1024/* Create reg_contact, mainly for SIP outbound */ 
     1025static void update_regc_contact(pjsua_acc *acc) 
     1026{ 
     1027    pjsua_acc_config *acc_cfg = &acc->cfg; 
     1028    pj_bool_t need_outbound = PJ_FALSE; 
     1029    const pj_str_t tcp_param = pj_str(";transport=tcp"); 
     1030    const pj_str_t tls_param = pj_str(";transport=tls"); 
     1031 
     1032    if (!acc_cfg->use_rfc5626) 
     1033        goto done; 
     1034 
     1035    if (pj_stristr(&acc->contact, &tcp_param)==NULL && 
     1036        pj_stristr(&acc->contact, &tls_param)==NULL) 
     1037    { 
     1038        /* Currently we can only do SIP outbound for TCP 
     1039         * and TLS. 
     1040         */ 
     1041        goto done; 
     1042    } 
     1043 
     1044    /* looks like we can use outbound */ 
     1045    need_outbound = PJ_TRUE; 
     1046 
     1047done: 
     1048    if (!need_outbound) { 
     1049        /* Outbound is not needed/wanted for the account. acc->reg_contact 
     1050         * is set to the same as acc->contact. 
     1051         */ 
     1052        acc->reg_contact = acc->contact; 
     1053        acc->rfc5626_status = OUTBOUND_NONE; 
     1054    } else { 
     1055        /* Need to use outbound, append the contact with +sip.instance and 
     1056         * reg-id parameters. 
     1057         */ 
     1058        unsigned len; 
     1059        pj_str_t reg_contact; 
     1060 
     1061        acc->rfc5626_status = OUTBOUND_WANTED; 
     1062        len = acc->contact.slen + acc->rfc5626_instprm.slen + 
     1063              acc->rfc5626_regprm.slen; 
     1064        reg_contact.ptr = (char*) pj_pool_alloc(acc->pool, reg_contact.slen); 
     1065 
     1066        pj_strcpy(&reg_contact, &acc->contact); 
     1067        pj_strcat(&reg_contact, &acc->rfc5626_regprm); 
     1068        pj_strcat(&reg_contact, &acc->rfc5626_instprm); 
     1069 
     1070        acc->reg_contact = reg_contact; 
     1071 
     1072        PJ_LOG(4,(THIS_FILE, 
     1073                  "Contact for acc %d updated for SIP outbound: %.*s", 
     1074                  acc->index, 
     1075                  (int)acc->reg_contact.slen, 
     1076                  acc->reg_contact.ptr)); 
     1077    } 
    9561078} 
    9571079 
     
    9991121    if (acc->cfg.allow_contact_rewrite == PJ_FALSE) 
    10001122        return PJ_FALSE; 
     1123 
     1124    /* If SIP outbound is active, no need to update */ 
     1125    if (acc->rfc5626_status == OUTBOUND_ACTIVE) { 
     1126        PJ_LOG(4,(THIS_FILE, "Acc %d has SIP outbound active, no need to " 
     1127                             "update registration Contact", acc->index)); 
     1128        return PJ_FALSE; 
     1129    } 
    10011130 
    10021131#if 0 
     
    11431272     */ 
    11441273    { 
     1274        const char *ob = ";ob"; 
    11451275        char *tmp; 
    11461276        const char *beginquote, *endquote; 
     
    11571287        tmp = (char*) pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); 
    11581288        len = pj_ansi_snprintf(tmp, PJSIP_MAX_URL_SIZE, 
    1159                                "<sip:%.*s%s%s%.*s%s:%d;transport=%s%.*s>%.*s", 
     1289                               "<sip:%.*s%s%s%.*s%s:%d;transport=%s%.*s%s>%.*s", 
    11601290                               (int)acc->user_part.slen, 
    11611291                               acc->user_part.ptr, 
     
    11691299                               (int)acc->cfg.contact_uri_params.slen, 
    11701300                               acc->cfg.contact_uri_params.ptr, 
     1301                               ob, 
    11711302                               (int)acc->cfg.contact_params.slen, 
    11721303                               acc->cfg.contact_params.ptr); 
     
    11781309        pj_strdup2_with_null(acc->pool, &acc->contact, tmp); 
    11791310 
     1311        update_regc_contact(acc); 
     1312 
    11801313        /* Always update, by http://trac.pjsip.org/repos/ticket/864. */ 
    11811314        pj_strdup_with_null(tp->pool, &tp->local_name.host, via_addr); 
     
    11851318 
    11861319    if (acc->cfg.contact_rewrite_method == 2 && acc->regc != NULL) { 
    1187         pjsip_regc_update_contact(acc->regc, 1, &acc->contact); 
     1320        pjsip_regc_update_contact(acc->regc, 1, &acc->reg_contact); 
    11881321    } 
    11891322 
     
    14191552 
    14201553 
     1554/* Update the status of SIP outbound registration request */ 
     1555static void update_rfc5626_status(pjsua_acc *acc, pjsip_rx_data *rdata) 
     1556{ 
     1557    pjsip_require_hdr *hreq; 
     1558    const pj_str_t STR_OUTBOUND = {"outbound", 8}; 
     1559    unsigned i; 
     1560 
     1561    if (acc->rfc5626_status == OUTBOUND_NONE) { 
     1562        goto on_return; 
     1563    } 
     1564 
     1565    hreq = rdata->msg_info.require; 
     1566    if (!hreq) { 
     1567        acc->rfc5626_status = OUTBOUND_NONE; 
     1568        goto on_return; 
     1569    } 
     1570 
     1571    for (i=0; i<hreq->count; ++i) { 
     1572        if (pj_stricmp(&hreq->values[i], &STR_OUTBOUND)==0) { 
     1573            acc->rfc5626_status = OUTBOUND_ACTIVE; 
     1574            goto on_return; 
     1575        } 
     1576    } 
     1577 
     1578    /* Server does not support outbound */ 
     1579    acc->rfc5626_status = OUTBOUND_NONE; 
     1580 
     1581on_return: 
     1582    PJ_LOG(4,(THIS_FILE, "SIP outbound status for acc %d is %s", 
     1583                         acc->index, (acc->rfc5626_status==OUTBOUND_ACTIVE? 
     1584                                         "active": "not active"))); 
     1585} 
     1586 
    14211587/* 
    14221588 * This callback is called by pjsip_regc when outgoing register 
     
    14741640                      pjsua_var.acc[acc->index].cfg.id.ptr)); 
    14751641        } else { 
     1642            /* Check and update SIP outbound status first, since the result 
     1643             * will determine if we should update re-registration 
     1644             */ 
     1645            update_rfc5626_status(acc, param->rdata); 
     1646 
    14761647            /* Check NAT bound address */ 
    14771648            if (acc_check_nat_addr(acc, param)) { 
    1478                 /* Update address, don't notify application yet */ 
    14791649                PJSUA_UNLOCK(); 
    14801650                return; 
     
    15961766 
    15971767        pj_strdup_with_null(acc->pool, &acc->contact, &tmp_contact); 
     1768        update_regc_contact(acc); 
    15981769    } 
    15991770 
     
    16021773                              &acc->cfg.id,  
    16031774                              &acc->cfg.id, 
    1604                               1, &acc->contact,  
     1775                              1, &acc->reg_contact, 
    16051776                              acc->cfg.reg_timeout); 
    16061777    if (status != PJ_SUCCESS) { 
     
    16831854                                            &pjsua_var.ua_cfg.user_agent); 
    16841855        pj_list_push_back(&hdr_list, (pjsip_hdr*)h); 
     1856 
     1857        pjsip_regc_add_headers(acc->regc, &hdr_list); 
     1858    } 
     1859 
     1860    /* If SIP outbound is used, add "Supported: outbound, path header" */ 
     1861    if (acc->rfc5626_status == OUTBOUND_WANTED) { 
     1862        pjsip_hdr hdr_list; 
     1863        pjsip_supported_hdr *hsup; 
     1864 
     1865        pj_list_init(&hdr_list); 
     1866        hsup = pjsip_supported_hdr_create(pool); 
     1867        pj_list_push_back(&hdr_list, hsup); 
     1868 
     1869        hsup->count = 2; 
     1870        hsup->values[0] = pj_str("outbound"); 
     1871        hsup->values[1] = pj_str("path"); 
    16851872 
    16861873        pjsip_regc_add_headers(acc->regc, &hdr_list); 
     
    21472334    const char *beginquote, *endquote; 
    21482335    char transport_param[32]; 
     2336    const char *ob = ";ob"; 
    21492337 
    21502338     
     
    22322420    contact->ptr = (char*)pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); 
    22332421    contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE, 
    2234                                      "%.*s%s<%s:%.*s%s%s%.*s%s:%d%s%.*s>%.*s", 
     2422                                     "%.*s%s<%s:%.*s%s%s%.*s%s:%d%s%.*s%s>%.*s", 
    22352423                                     (int)acc->display.slen, 
    22362424                                     acc->display.ptr, 
     
    22482436                                     (int)acc->cfg.contact_uri_params.slen, 
    22492437                                     acc->cfg.contact_uri_params.ptr, 
     2438                                     ob, 
    22502439                                     (int)acc->cfg.contact_params.slen, 
    22512440                                     acc->cfg.contact_params.ptr); 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r3330 r3366  
    184184    cfg->reg_retry_interval = PJSUA_REG_RETRY_INTERVAL; 
    185185    cfg->contact_rewrite_method = PJSUA_CONTACT_REWRITE_METHOD; 
     186    cfg->use_rfc5626 = PJ_TRUE; 
    186187    cfg->reg_use_proxy = PJSUA_REG_USE_OUTBOUND_PROXY | 
    187188                         PJSUA_REG_USE_ACC_PROXY; 
Note: See TracChangeset for help on using the changeset viewer.