Ignore:
Timestamp:
Apr 20, 2010 2:36:38 PM (14 years ago)
Author:
nanang
Message:

Ticket #1057: Implemented pjsua_modify_acc().

File:
1 edited

Legend:

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

    r3139 r3144  
    9696} 
    9797 
     98/* 
     99 * Calculate CRC of proxy list. 
     100 */ 
     101static pj_uint32_t calc_proxy_crc(const pj_str_t proxy[], pj_size_t cnt) 
     102{ 
     103    pj_crc32_context ctx; 
     104    unsigned i; 
     105     
     106    pj_crc32_init(&ctx); 
     107    for (i=0; i<cnt; ++i) { 
     108        pj_crc32_update(&ctx, (pj_uint8_t*)proxy[i].ptr, proxy[i].slen); 
     109    } 
     110 
     111    return pj_crc32_final(&ctx); 
     112} 
    98113 
    99114/* 
     
    218233    } 
    219234 
    220      
    221235    /* Concatenate credentials from account config and global config */ 
    222236    acc->cred_cnt = 0; 
     
    299313    } 
    300314 
     315    /* Get CRC of account proxy setting */ 
     316    acc->local_route_crc = calc_proxy_crc(acc->cfg.proxy, acc->cfg.proxy_cnt); 
     317 
     318    /* Get CRC of global outbound proxy setting */ 
     319    acc->global_route_crc=calc_proxy_crc(pjsua_var.ua_cfg.outbound_proxy, 
     320                                         pjsua_var.ua_cfg.outbound_proxy_cnt); 
     321     
    301322    /* Check the route URI's and force loose route if required */ 
    302323    for (i=0; i<acc->cfg.proxy_cnt; ++i) { 
     
    503524                                      const pjsua_acc_config *cfg) 
    504525{ 
    505     PJ_TODO(pjsua_acc_modify); 
    506     PJ_UNUSED_ARG(acc_id); 
    507     PJ_UNUSED_ARG(cfg); 
    508     return PJ_EINVALIDOP; 
     526    pjsua_acc *acc; 
     527    pjsip_name_addr *id_name_addr = NULL; 
     528    pjsip_sip_uri *id_sip_uri = NULL; 
     529    pjsip_sip_uri *reg_sip_uri = NULL; 
     530    pj_uint32_t local_route_crc, global_route_crc; 
     531    pjsip_route_hdr global_route; 
     532    pjsip_route_hdr local_route; 
     533    pj_str_t acc_proxy[PJSUA_ACC_MAX_PROXIES]; 
     534    pj_bool_t update_reg = PJ_FALSE; 
     535    pj_status_t status = PJ_SUCCESS; 
     536 
     537    PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), 
     538                     PJ_EINVAL); 
     539 
     540    PJSUA_LOCK(); 
     541 
     542    acc = &pjsua_var.acc[acc_id]; 
     543    if (!acc->valid) { 
     544        status = PJ_EINVAL; 
     545        goto on_return; 
     546    } 
     547 
     548    /* == Validate first == */ 
     549 
     550    /* Account id */ 
     551    if (pj_strcmp(&acc->cfg.id, &cfg->id)) { 
     552        /* Need to parse id to get the elements: */ 
     553        id_name_addr = (pjsip_name_addr*) 
     554                        pjsip_parse_uri(acc->pool, cfg->id.ptr, cfg->id.slen, 
     555                                        PJSIP_PARSE_URI_AS_NAMEADDR); 
     556        if (id_name_addr == NULL) { 
     557            status = PJSIP_EINVALIDURI; 
     558            pjsua_perror(THIS_FILE, "Invalid local URI", status); 
     559            goto on_return; 
     560        } 
     561 
     562        /* URI MUST be a SIP or SIPS: */ 
     563        if (!PJSIP_URI_SCHEME_IS_SIP(id_name_addr) &&  
     564            !PJSIP_URI_SCHEME_IS_SIPS(id_name_addr))  
     565        { 
     566            status = PJSIP_EINVALIDSCHEME; 
     567            pjsua_perror(THIS_FILE, "Invalid local URI", status); 
     568            goto on_return; 
     569        } 
     570 
     571        /* Get the SIP URI object: */ 
     572        id_sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(id_name_addr); 
     573    } 
     574 
     575    /* Registrar URI */ 
     576    if (pj_strcmp(&acc->cfg.reg_uri, &cfg->reg_uri) && cfg->reg_uri.slen) { 
     577        pjsip_uri *reg_uri; 
     578 
     579        /* Need to parse reg_uri to get the elements: */ 
     580        reg_uri = pjsip_parse_uri(acc->pool, cfg->reg_uri.ptr,  
     581                                  cfg->reg_uri.slen, 0); 
     582        if (reg_uri == NULL) { 
     583            status = PJSIP_EINVALIDURI; 
     584            pjsua_perror(THIS_FILE, "Invalid registrar URI", status); 
     585            goto on_return; 
     586        } 
     587 
     588        /* Registrar URI MUST be a SIP or SIPS: */ 
     589        if (!PJSIP_URI_SCHEME_IS_SIP(reg_uri) &&  
     590            !PJSIP_URI_SCHEME_IS_SIPS(reg_uri))  
     591        { 
     592            status = PJSIP_EINVALIDSCHEME; 
     593            pjsua_perror(THIS_FILE, "Invalid registar URI", status); 
     594            goto on_return; 
     595        } 
     596 
     597        reg_sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(reg_uri); 
     598    } 
     599 
     600    /* Global outbound proxy */ 
     601    global_route_crc = calc_proxy_crc(pjsua_var.ua_cfg.outbound_proxy,  
     602                                      pjsua_var.ua_cfg.outbound_proxy_cnt); 
     603    if (global_route_crc != acc->global_route_crc) { 
     604        pjsip_route_hdr *r; 
     605        unsigned i; 
     606 
     607        /* Validate the global route and save it to temporary var */ 
     608        pj_list_init(&global_route); 
     609        for (i=0; i < pjsua_var.ua_cfg.outbound_proxy_cnt; ++i) { 
     610            pj_str_t hname = { "Route", 5}; 
     611            pj_str_t tmp; 
     612 
     613            pj_strdup_with_null(acc->pool, &tmp,  
     614                                &pjsua_var.ua_cfg.outbound_proxy[i]); 
     615            r = (pjsip_route_hdr*) 
     616                pjsip_parse_hdr(acc->pool, &hname, tmp.ptr, tmp.slen, NULL); 
     617            if (r == NULL) { 
     618                status = PJSIP_EINVALIDURI; 
     619                pjsua_perror(THIS_FILE, "Invalid outbound proxy URI", status); 
     620                goto on_return; 
     621            } 
     622            pj_list_push_back(&global_route, r); 
     623        } 
     624    } 
     625 
     626    /* Account proxy */ 
     627    local_route_crc = calc_proxy_crc(cfg->proxy, cfg->proxy_cnt); 
     628    if (local_route_crc != acc->local_route_crc) { 
     629        pjsip_route_hdr *r; 
     630        unsigned i; 
     631 
     632        /* Validate the local route and save it to temporary var */ 
     633        pj_list_init(&local_route); 
     634        for (i=0; i<cfg->proxy_cnt; ++i) { 
     635            pj_str_t hname = { "Route", 5}; 
     636 
     637            pj_strdup_with_null(acc->pool, &acc_proxy[i], &cfg->proxy[i]); 
     638            status = normalize_route_uri(acc->pool, &acc_proxy[i]); 
     639            if (status != PJ_SUCCESS) 
     640                goto on_return; 
     641            r = (pjsip_route_hdr*) 
     642                pjsip_parse_hdr(acc->pool, &hname, acc_proxy[i].ptr,  
     643                                acc_proxy[i].slen, NULL); 
     644            if (r == NULL) { 
     645                status = PJSIP_EINVALIDURI; 
     646                pjsua_perror(THIS_FILE, "Invalid URI in account route set", 
     647                             status); 
     648                goto on_return; 
     649            } 
     650 
     651            pj_list_push_back(&local_route, r); 
     652        } 
     653    } 
     654 
     655 
     656    /* == Apply the new config == */ 
     657 
     658    /* Account ID. */ 
     659    if (id_name_addr && id_sip_uri) { 
     660        pj_strdup_with_null(acc->pool, &acc->cfg.id, &cfg->id); 
     661        acc->display = id_name_addr->display; 
     662        acc->user_part = id_sip_uri->user; 
     663        acc->srv_domain = id_sip_uri->host; 
     664        acc->srv_port = 0; 
     665        update_reg = PJ_TRUE; 
     666    } 
     667 
     668    /* User data */ 
     669    acc->cfg.user_data = cfg->user_data; 
     670 
     671    /* Priority */ 
     672    if (acc->cfg.priority != cfg->priority) { 
     673        unsigned i; 
     674 
     675        acc->cfg.priority = cfg->priority; 
     676         
     677        /* Resort accounts priority */ 
     678        for (i=0; i<pjsua_var.acc_cnt; ++i) { 
     679            if (pjsua_var.acc_ids[i] == acc_id) 
     680                break; 
     681        } 
     682        pj_assert(i < pjsua_var.acc_cnt); 
     683        pj_array_erase(pjsua_var.acc_ids, sizeof(acc_id), 
     684                       pjsua_var.acc_cnt, i); 
     685        for (i=0; i<pjsua_var.acc_cnt; ++i) { 
     686            if (pjsua_var.acc[pjsua_var.acc_ids[i]].cfg.priority < 
     687                acc->cfg.priority) 
     688            { 
     689                break; 
     690            } 
     691        } 
     692        pj_array_insert(pjsua_var.acc_ids, sizeof(acc_id), 
     693                        pjsua_var.acc_cnt, i, &acc_id); 
     694    } 
     695 
     696    /* MWI */ 
     697    acc->cfg.mwi_enabled = cfg->mwi_enabled; 
     698 
     699    /* PIDF tuple ID */ 
     700    if (pj_strcmp(&acc->cfg.pidf_tuple_id, &cfg->pidf_tuple_id)) 
     701        pj_strdup_with_null(acc->pool, &acc->cfg.pidf_tuple_id, 
     702                            &cfg->pidf_tuple_id); 
     703 
     704    /* Publish */ 
     705    acc->cfg.publish_opt = cfg->publish_opt; 
     706    acc->cfg.unpublish_max_wait_time_msec = cfg->unpublish_max_wait_time_msec; 
     707    if (acc->cfg.publish_enabled != cfg->publish_enabled) { 
     708        acc->cfg.publish_enabled = cfg->publish_enabled; 
     709        if (!acc->cfg.publish_enabled) 
     710            pjsua_pres_unpublish(acc); 
     711        else 
     712            update_reg = PJ_TRUE; 
     713    } 
     714 
     715    /* Force contact URI */ 
     716    if (pj_strcmp(&acc->cfg.force_contact, &cfg->force_contact)) { 
     717        pj_strdup_with_null(acc->pool, &acc->cfg.force_contact, 
     718                            &cfg->force_contact); 
     719        update_reg = PJ_TRUE; 
     720    } 
     721 
     722    /* Contact param */ 
     723    if (pj_strcmp(&acc->cfg.contact_params, &cfg->contact_params)) { 
     724        pj_strdup_with_null(acc->pool, &acc->cfg.contact_params, 
     725                            &cfg->contact_params); 
     726        update_reg = PJ_TRUE; 
     727    } 
     728 
     729    /* Contact URI params */ 
     730    if (pj_strcmp(&acc->cfg.contact_uri_params, &cfg->contact_uri_params)) { 
     731        pj_strdup_with_null(acc->pool, &acc->cfg.contact_uri_params, 
     732                            &cfg->contact_uri_params); 
     733        update_reg = PJ_TRUE; 
     734    } 
     735 
     736    /* Reliable provisional response */ 
     737    acc->cfg.require_100rel = cfg->require_100rel; 
     738 
     739    /* Session timer */ 
     740    acc->cfg.require_timer = cfg->require_timer; 
     741    acc->cfg.timer_setting = cfg->timer_setting; 
     742 
     743    /* Transport and keep-alive */ 
     744    if (acc->cfg.transport_id != cfg->transport_id) { 
     745        acc->cfg.transport_id = cfg->transport_id; 
     746        update_reg = PJ_TRUE; 
     747    } 
     748    acc->cfg.ka_interval = cfg->ka_interval; 
     749    if (pj_strcmp(&acc->cfg.ka_data, &cfg->ka_data)) 
     750        pj_strdup(acc->pool, &acc->cfg.ka_data, &cfg->ka_data); 
     751#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
     752    acc->cfg.use_srtp = cfg->use_srtp; 
     753    acc->cfg.srtp_secure_signaling = cfg->srtp_secure_signaling; 
     754#endif 
     755 
     756    /* Global outbound proxy */ 
     757    if (global_route_crc != acc->global_route_crc) { 
     758        unsigned i, rcnt; 
     759 
     760        /* Remove the outbound proxies from the route set */ 
     761        rcnt = pj_list_size(&acc->route_set); 
     762        for (i=0; i < rcnt - acc->cfg.proxy_cnt; ++i) { 
     763            pjsip_route_hdr *r = acc->route_set.next; 
     764            pj_list_erase(r); 
     765        } 
     766 
     767        /* Insert the outbound proxies to the beginning of route set */ 
     768        pj_list_merge_first(&acc->route_set, &global_route); 
     769 
     770        /* Update global route CRC */ 
     771        acc->global_route_crc = global_route_crc; 
     772 
     773        update_reg = PJ_TRUE; 
     774    } 
     775 
     776    /* Account proxy */ 
     777    if (local_route_crc != acc->local_route_crc) { 
     778        unsigned i; 
     779 
     780        /* Remove the current account proxies from the route set */ 
     781        for (i=0; i < acc->cfg.proxy_cnt; ++i) { 
     782            pjsip_route_hdr *r = acc->route_set.prev; 
     783            pj_list_erase(r); 
     784        } 
     785 
     786        /* Insert new proxy setting to the route set */ 
     787        pj_list_merge_last(&acc->route_set, &local_route); 
     788 
     789        /* Update the proxy setting */ 
     790        acc->cfg.proxy_cnt = cfg->proxy_cnt; 
     791        for (i = 0; i < cfg->proxy_cnt; ++i) 
     792            acc->cfg.proxy[i] = acc_proxy[i]; 
     793 
     794        /* Update local route CRC */ 
     795        acc->local_route_crc = local_route_crc; 
     796 
     797        update_reg = PJ_TRUE; 
     798    } 
     799 
     800    /* Credential info */ 
     801    { 
     802        unsigned i; 
     803 
     804        /* Selective update credential info. */ 
     805        for (i = 0; i < cfg->cred_count; ++i) { 
     806            unsigned j; 
     807            pjsip_cred_info ci; 
     808 
     809            /* Find if this credential is already listed */ 
     810            for (j = i; j < acc->cfg.cred_count; ++i) { 
     811                if (pjsip_cred_info_cmp(&acc->cfg.cred_info[j],  
     812                                        &cfg->cred_info[i]) == 0) 
     813                { 
     814                    /* Found, but different index/position, swap */ 
     815                    if (j != i) { 
     816                        ci = acc->cfg.cred_info[i]; 
     817                        acc->cfg.cred_info[i] = acc->cfg.cred_info[j]; 
     818                        acc->cfg.cred_info[j] = ci; 
     819                    } 
     820                    break; 
     821                } 
     822            } 
     823 
     824            /* Not found, insert this */ 
     825            if (j == acc->cfg.cred_count) { 
     826                /* If account credential is full, discard the last one. */ 
     827                if (acc->cfg.cred_count == PJ_ARRAY_SIZE(acc->cfg.cred_info)) { 
     828                    pj_array_erase(acc->cfg.cred_info, sizeof(pjsip_cred_info), 
     829                                   acc->cfg.cred_count, acc->cfg.cred_count-1); 
     830                    acc->cfg.cred_count--; 
     831                } 
     832 
     833                /* Insert this */ 
     834                pjsip_cred_info_dup(acc->pool, &ci, &cfg->cred_info[i]); 
     835                pj_array_insert(acc->cfg.cred_info, sizeof(pjsip_cred_info), 
     836                                acc->cfg.cred_count, i, &ci); 
     837            } 
     838        } 
     839        acc->cfg.cred_count = cfg->cred_count; 
     840 
     841        /* Concatenate credentials from account config and global config */ 
     842        acc->cred_cnt = 0; 
     843        for (i=0; i<acc->cfg.cred_count; ++i) { 
     844            acc->cred[acc->cred_cnt++] = acc->cfg.cred_info[i]; 
     845        } 
     846        for (i=0; i<pjsua_var.ua_cfg.cred_count &&  
     847                  acc->cred_cnt < PJ_ARRAY_SIZE(acc->cred); ++i) 
     848        { 
     849            acc->cred[acc->cred_cnt++] = pjsua_var.ua_cfg.cred_info[i]; 
     850        } 
     851    } 
     852 
     853    /* Authentication preference */ 
     854    acc->cfg.auth_pref.initial_auth = cfg->auth_pref.initial_auth; 
     855    if (pj_strcmp(&acc->cfg.auth_pref.algorithm, &cfg->auth_pref.algorithm)) 
     856        pj_strdup_with_null(acc->pool, &acc->cfg.auth_pref.algorithm,  
     857                            &cfg->auth_pref.algorithm); 
     858 
     859    /* Registration */ 
     860    acc->cfg.reg_timeout = cfg->reg_timeout; 
     861    acc->cfg.unreg_timeout = cfg->unreg_timeout; 
     862    acc->cfg.allow_contact_rewrite = cfg->allow_contact_rewrite; 
     863    acc->cfg.reg_retry_interval = cfg->reg_retry_interval; 
     864    acc->cfg.drop_calls_on_reg_fail = cfg->drop_calls_on_reg_fail; 
     865 
     866    /* Normalize registration timeout */ 
     867    if (acc->cfg.reg_uri.slen && acc->cfg.reg_timeout == 0) 
     868        acc->cfg.reg_timeout = PJSUA_REG_INTERVAL; 
     869 
     870    /* Registrar URI */ 
     871    if (pj_strcmp(&acc->cfg.reg_uri, &cfg->reg_uri)) { 
     872        if (cfg->reg_uri.slen) { 
     873            pj_strdup_with_null(acc->pool, &acc->cfg.reg_uri, &cfg->reg_uri); 
     874            if (reg_sip_uri) 
     875                acc->srv_port = reg_sip_uri->port; 
     876        } else { 
     877            /* Unregister if registration was set */ 
     878            if (acc->cfg.reg_uri.slen) 
     879                pjsua_acc_set_registration(acc->index, PJ_FALSE); 
     880            pj_bzero(&acc->cfg.reg_uri, sizeof(acc->cfg.reg_uri)); 
     881        } 
     882        update_reg = PJ_TRUE; 
     883    } 
     884 
     885    /* Update registration */ 
     886    if (update_reg) { 
     887        /* If accounts has registration enabled, start registration */ 
     888        if (acc->cfg.reg_uri.slen) 
     889            pjsua_acc_set_registration(acc->index, PJ_TRUE); 
     890        else { 
     891            /* Otherwise subscribe to MWI, if it's enabled */ 
     892            if (acc->cfg.mwi_enabled) 
     893                pjsua_start_mwi(acc); 
     894        } 
     895    } 
     896 
     897on_return: 
     898    PJSUA_UNLOCK(); 
     899    return status; 
    509900} 
    510901 
Note: See TracChangeset for help on using the changeset viewer.