/* * Modify local SDP and wait for remote answer. */ PJ_DEF(pj_status_t) pjmedia_sdp_neg_modify_local_offer( pj_pool_t *pool, pjmedia_sdp_neg *neg, const pjmedia_sdp_session *local) { pjmedia_sdp_session *new_offer; pjmedia_sdp_session *old_offer; char media_used[PJMEDIA_MAX_SDP_MEDIA]; unsigned oi; /* old offer media index */ pj_status_t status; /* Check arguments are valid. */ PJ_ASSERT_RETURN(pool && neg && local, PJ_EINVAL); /* Can only do this in STATE_DONE. */ PJ_ASSERT_RETURN(neg->state == PJMEDIA_SDP_NEG_STATE_DONE, PJMEDIA_SDPNEG_EINSTATE); /* Validate the new offer */ status = pjmedia_sdp_validate(local); if (status != PJ_SUCCESS) return status; /* Change state to STATE_LOCAL_OFFER */ neg->state = PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER; /* Init vars */ pj_bzero(media_used, sizeof(media_used)); old_offer = neg->active_local_sdp; new_offer = pjmedia_sdp_session_clone(pool, local); /* RFC 3264 Section 8: When issuing an offer that modifies the session, * the "o=" line of the new SDP MUST be identical to that in the * previous SDP, except that the version in the origin field MUST * increment by one from the previous SDP. */ pj_strdup(pool, &new_offer->origin.user, &old_offer->origin.user); new_offer->origin.id = old_offer->origin.id; new_offer->origin.version = old_offer->origin.version + 1; pj_strdup(pool, &new_offer->origin.net_type, &old_offer->origin.net_type); pj_strdup(pool, &new_offer->origin.addr_type,&old_offer->origin.addr_type); pj_strdup(pool, &new_offer->origin.addr, &old_offer->origin.addr); /* Generating the new offer, in the case media lines doesn't match the * active SDP (e.g. current/active SDP's have m=audio and m=video lines, * and the new offer only has m=audio line), the negotiator will fix * the new offer by reordering and adding the missing media line with * port number set to zero. */ for (oi = 0; oi < old_offer->media_count; ++oi) { pjmedia_sdp_media *om; pjmedia_sdp_media *nm; unsigned ni; /* new offer media index */ pj_bool_t found = PJ_FALSE; om = old_offer->media[oi]; for (ni = oi; ni < new_offer->media_count; ++ni) { nm = new_offer->media[ni]; if (pj_strcmp(&nm->desc.media, &om->desc.media) == 0) { if (ni != oi) { /* The same media found but the position unmatched to the * old offer, so let's put this media in the right place, * and keep the order of the rest. */ pj_array_insert(new_offer->media, /* array */ sizeof(new_offer->media[0]), /* elmt size*/ ni, /* count */ oi, /* pos */ &nm); /* new elmt */ } found = PJ_TRUE; break; } } if (!found) { pjmedia_sdp_media *m; m = pjmedia_sdp_media_clone(pool, om); m->desc.port = 0; pj_array_insert(new_offer->media, sizeof(new_offer->media[0]), new_offer->media_count++, oi, &m); } } /* New_offer fixed */ neg->initial_sdp = new_offer; neg->neg_local_sdp = pjmedia_sdp_session_clone(pool, new_offer); return PJ_SUCCESS; }
/* * Initialize a new account (after configuration is set). */ static pj_status_t initialize_acc(unsigned acc_id) { pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg; pjsua_acc *acc = &pjsua_var.acc[acc_id]; pjsip_name_addr *name_addr; pjsip_sip_uri *sip_uri, *sip_reg_uri; pj_status_t status; unsigned i; /* Need to parse local_uri to get the elements: */ name_addr = (pjsip_name_addr*) pjsip_parse_uri(acc->pool, acc_cfg->id.ptr, acc_cfg->id.slen, PJSIP_PARSE_URI_AS_NAMEADDR); if (name_addr == NULL) { pjsua_perror(THIS_FILE, "Invalid local URI", PJSIP_EINVALIDURI); return PJSIP_EINVALIDURI; } /* Local URI MUST be a SIP or SIPS: */ if (!PJSIP_URI_SCHEME_IS_SIP(name_addr) && !PJSIP_URI_SCHEME_IS_SIPS(name_addr)) { pjsua_perror(THIS_FILE, "Invalid local URI", PJSIP_EINVALIDSCHEME); return PJSIP_EINVALIDSCHEME; } /* Get the SIP URI object: */ sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(name_addr); /* Parse registrar URI, if any */ if (acc_cfg->reg_uri.slen) { pjsip_uri *reg_uri; reg_uri = pjsip_parse_uri(acc->pool, acc_cfg->reg_uri.ptr, acc_cfg->reg_uri.slen, 0); if (reg_uri == NULL) { pjsua_perror(THIS_FILE, "Invalid registrar URI", PJSIP_EINVALIDURI); return PJSIP_EINVALIDURI; } /* Registrar URI MUST be a SIP or SIPS: */ if (!PJSIP_URI_SCHEME_IS_SIP(reg_uri) && !PJSIP_URI_SCHEME_IS_SIPS(reg_uri)) { pjsua_perror(THIS_FILE, "Invalid registar URI", PJSIP_EINVALIDSCHEME); return PJSIP_EINVALIDSCHEME; } sip_reg_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(reg_uri); } else { sip_reg_uri = NULL; } /* Save the user and domain part. These will be used when finding an * account for incoming requests. */ acc->display = name_addr->display; acc->user_part = sip_uri->user; acc->srv_domain = sip_uri->host; acc->srv_port = 0; if (sip_reg_uri) { acc->srv_port = sip_reg_uri->port; } /* Create Contact header if not present. */ //if (acc_cfg->contact.slen == 0) { // acc_cfg->contact = acc_cfg->id; //} /* Build account route-set from outbound proxies and route set from * account configuration. */ pj_list_init(&acc->route_set); for (i=0; i<pjsua_var.ua_cfg.outbound_proxy_cnt; ++i) { pj_str_t hname = { "Route", 5}; pjsip_route_hdr *r; pj_str_t tmp; pj_strdup_with_null(acc->pool, &tmp, &pjsua_var.ua_cfg.outbound_proxy[i]); r = (pjsip_route_hdr*) pjsip_parse_hdr(acc->pool, &hname, tmp.ptr, tmp.slen, NULL); if (r == NULL) { pjsua_perror(THIS_FILE, "Invalid outbound proxy URI", PJSIP_EINVALIDURI); return PJSIP_EINVALIDURI; } pj_list_push_back(&acc->route_set, r); } for (i=0; i<acc_cfg->proxy_cnt; ++i) { pj_str_t hname = { "Route", 5}; pjsip_route_hdr *r; pj_str_t tmp; pj_strdup_with_null(acc->pool, &tmp, &acc_cfg->proxy[i]); r = (pjsip_route_hdr*) pjsip_parse_hdr(acc->pool, &hname, tmp.ptr, tmp.slen, NULL); if (r == NULL) { pjsua_perror(THIS_FILE, "Invalid URI in account route set", PJ_EINVAL); return PJ_EINVAL; } pj_list_push_back(&acc->route_set, r); } /* Concatenate credentials from account config and global config */ acc->cred_cnt = 0; for (i=0; i<acc_cfg->cred_count; ++i) { acc->cred[acc->cred_cnt++] = acc_cfg->cred_info[i]; } for (i=0; i<pjsua_var.ua_cfg.cred_count && acc->cred_cnt < PJ_ARRAY_SIZE(acc->cred); ++i) { acc->cred[acc->cred_cnt++] = pjsua_var.ua_cfg.cred_info[i]; } status = pjsua_pres_init_acc(acc_id); if (status != PJ_SUCCESS) return status; /* Mark account as valid */ pjsua_var.acc[acc_id].valid = PJ_TRUE; /* Insert account ID into account ID array, sorted by priority */ for (i=0; i<pjsua_var.acc_cnt; ++i) { if ( pjsua_var.acc[pjsua_var.acc_ids[i]].cfg.priority < pjsua_var.acc[acc_id].cfg.priority) { break; } } pj_array_insert(pjsua_var.acc_ids, sizeof(pjsua_var.acc_ids[0]), pjsua_var.acc_cnt, i, &acc_id); return PJ_SUCCESS; }