📄 pjsua_acc.c
字号:
/* * Update registration or perform unregistration. */PJ_DEF(pj_status_t) pjsua_acc_set_registration( pjsua_acc_id acc_id, pj_bool_t renew){ pj_status_t status = 0; pjsip_tx_data *tdata = 0; PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_var.acc[acc_id].valid, PJ_EINVALIDOP); PJSUA_LOCK(); if (renew) { if (pjsua_var.acc[acc_id].regc == NULL) { status = pjsua_regc_init(acc_id); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create registration", status); goto on_return; } } if (!pjsua_var.acc[acc_id].regc) { status = PJ_EINVALIDOP; goto on_return; } status = pjsip_regc_register(pjsua_var.acc[acc_id].regc, 1, &tdata); } else { if (pjsua_var.acc[acc_id].regc == NULL) { PJ_LOG(3,(THIS_FILE, "Currently not registered")); status = PJ_EINVALIDOP; goto on_return; } status = pjsip_regc_unregister(pjsua_var.acc[acc_id].regc, &tdata); } if (status == PJ_SUCCESS) { //pjsua_process_msg_data(tdata, NULL); status = pjsip_regc_send( pjsua_var.acc[acc_id].regc, tdata ); } if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create/send REGISTER", status); } else { PJ_LOG(3,(THIS_FILE, "%s sent", (renew? "Registration" : "Unregistration"))); }on_return: PJSUA_UNLOCK(); return status;}/* * Get account information. */PJ_DEF(pj_status_t) pjsua_acc_get_info( pjsua_acc_id acc_id, pjsua_acc_info *info){ pjsua_acc *acc = &pjsua_var.acc[acc_id]; pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg; PJ_ASSERT_RETURN(info != NULL, PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL); pj_bzero(info, sizeof(pjsua_acc_info)); PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_var.acc[acc_id].valid, PJ_EINVALIDOP); PJSUA_LOCK(); if (pjsua_var.acc[acc_id].valid == PJ_FALSE) { PJSUA_UNLOCK(); return PJ_EINVALIDOP; } info->id = acc_id; info->is_default = (pjsua_var.default_acc == acc_id); info->acc_uri = acc_cfg->id; info->has_registration = (acc->cfg.reg_uri.slen > 0); info->online_status = acc->online_status; if (acc->reg_last_err) { info->status = acc->reg_last_err; pj_strerror(acc->reg_last_err, info->buf_, sizeof(info->buf_)); info->status_text = pj_str(info->buf_); } else if (acc->reg_last_code) { if (info->has_registration) { info->status = acc->reg_last_code; info->status_text = *pjsip_get_status_text(acc->reg_last_code); } else { info->status = 0; info->status_text = pj_str("not registered"); } } else if (acc->cfg.reg_uri.slen) { info->status = 100; info->status_text = pj_str("In Progress"); } else { info->status = 0; info->status_text = pj_str("does not register"); } if (acc->regc) { pjsip_regc_info regc_info; pjsip_regc_get_info(acc->regc, ®c_info); info->expires = regc_info.next_reg; } else { info->expires = -1; } PJSUA_UNLOCK(); return PJ_SUCCESS;}/* * Enum accounts all account ids. */PJ_DEF(pj_status_t) pjsua_enum_accs(pjsua_acc_id ids[], unsigned *count ){ unsigned i, c; PJ_ASSERT_RETURN(ids && *count, PJ_EINVAL); PJSUA_LOCK(); for (i=0, c=0; c<*count && i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { if (!pjsua_var.acc[i].valid) continue; ids[c] = i; ++c; } *count = c; PJSUA_UNLOCK(); return PJ_SUCCESS;}/* * Enum accounts info. */PJ_DEF(pj_status_t) pjsua_acc_enum_info( pjsua_acc_info info[], unsigned *count ){ unsigned i, c; PJ_ASSERT_RETURN(info && *count, PJ_EINVAL); PJSUA_LOCK(); for (i=0, c=0; c<*count && i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { if (!pjsua_var.acc[i].valid) continue; pjsua_acc_get_info(i, &info[c]); ++c; } *count = c; PJSUA_UNLOCK(); return PJ_SUCCESS;}/* * This is an internal function to find the most appropriate account to * used to reach to the specified URL. */PJ_DEF(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url){ pj_str_t tmp; pjsip_uri *uri; pjsip_sip_uri *sip_uri; unsigned i; PJSUA_LOCK(); PJ_TODO(dont_use_pjsua_pool); pj_strdup_with_null(pjsua_var.pool, &tmp, url); uri = pjsip_parse_uri(pjsua_var.pool, tmp.ptr, tmp.slen, 0); if (!uri) { PJSUA_UNLOCK(); return pjsua_var.default_acc; } if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) { /* Return the first account with proxy */ for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { if (!pjsua_var.acc[i].valid) continue; if (!pj_list_empty(&pjsua_var.acc[i].route_set)) break; } if (i != PJ_ARRAY_SIZE(pjsua_var.acc)) { /* Found rather matching account */ PJSUA_UNLOCK(); return 0; } /* Not found, use default account */ PJSUA_UNLOCK(); return pjsua_var.default_acc; } sip_uri = pjsip_uri_get_uri(uri); /* Find matching domain AND port */ for (i=0; i<pjsua_var.acc_cnt; ++i) { unsigned acc_id = pjsua_var.acc_ids[i]; if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0 && pjsua_var.acc[acc_id].srv_port == sip_uri->port) { PJSUA_UNLOCK(); return acc_id; } } /* If no match, try to match the domain part only */ for (i=0; i<pjsua_var.acc_cnt; ++i) { unsigned acc_id = pjsua_var.acc_ids[i]; if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0) { PJSUA_UNLOCK(); return acc_id; } } /* Still no match, just use default account */ PJSUA_UNLOCK(); return pjsua_var.default_acc;}/* * This is an internal function to find the most appropriate account to be * used to handle incoming calls. */PJ_DEF(pjsua_acc_id) pjsua_acc_find_for_incoming(pjsip_rx_data *rdata){ pjsip_uri *uri; pjsip_sip_uri *sip_uri; unsigned i; uri = rdata->msg_info.to->uri; /* Just return default account if To URI is not SIP: */ if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) { return pjsua_var.default_acc; } PJSUA_LOCK(); sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri); /* Find account which has matching username and domain. */ for (i=0; i < pjsua_var.acc_cnt; ++i) { unsigned acc_id = pjsua_var.acc_ids[i]; pjsua_acc *acc = &pjsua_var.acc[acc_id]; if (acc->valid && pj_stricmp(&acc->user_part, &sip_uri->user)==0 && pj_stricmp(&acc->srv_domain, &sip_uri->host)==0) { /* Match ! */ PJSUA_UNLOCK(); return acc_id; } } /* No matching account, try match domain part only. */ for (i=0; i < pjsua_var.acc_cnt; ++i) { unsigned acc_id = pjsua_var.acc_ids[i]; pjsua_acc *acc = &pjsua_var.acc[acc_id]; if (acc->valid && pj_stricmp(&acc->srv_domain, &sip_uri->host)==0) { /* Match ! */ PJSUA_UNLOCK(); return acc_id; } } /* No matching account, try match user part (and transport type) only. */ for (i=0; i < pjsua_var.acc_cnt; ++i) { unsigned acc_id = pjsua_var.acc_ids[i]; pjsua_acc *acc = &pjsua_var.acc[acc_id]; if (acc->valid && pj_stricmp(&acc->user_part, &sip_uri->user)==0) { if (acc->cfg.transport_id != PJSUA_INVALID_ID) { pjsip_transport_type_e type; type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); if (type == PJSIP_TRANSPORT_UNSPECIFIED) type = PJSIP_TRANSPORT_UDP; if (pjsua_var.tpdata[acc->cfg.transport_id].type != type) continue; } /* Match ! */ PJSUA_UNLOCK(); return acc_id; } } /* Still no match, use default account */ PJSUA_UNLOCK(); return pjsua_var.default_acc;}/* * Create arbitrary requests for this account. */PJ_DEF(pj_status_t) pjsua_acc_create_request(pjsua_acc_id acc_id, const pjsip_method *method, const pj_str_t *target, pjsip_tx_data **p_tdata){ pjsip_tx_data *tdata; pjsua_acc *acc; pjsip_route_hdr *r; pj_status_t status; PJ_ASSERT_RETURN(method && target && p_tdata, PJ_EINVAL); PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL); acc = &pjsua_var.acc[acc_id]; status = pjsip_endpt_create_request(pjsua_var.endpt, method, target, &acc->cfg.id, target, NULL, NULL, -1, NULL, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create request", status); return status; } /* Copy routeset */ r = acc->route_set.next; while (r != &acc->route_set) { pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_clone(tdata->pool, r)); r = r->next; } /* Done */ *p_tdata = tdata; return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool, pj_str_t *contact, pjsua_acc_id acc_id, const pj_str_t *suri){ pjsua_acc *acc; pjsip_sip_uri *sip_uri; pj_status_t status; pjsip_transport_type_e tp_type = PJSIP_TRANSPORT_UNSPECIFIED; pj_str_t local_addr; pjsip_tpselector tp_sel; unsigned flag; int secure; int local_port; PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL); acc = &pjsua_var.acc[acc_id]; /* If force_contact is configured, then use use it */ if (acc->cfg.force_contact.slen) { *contact = acc->cfg.force_contact; return PJ_SUCCESS; } /* If route-set is configured for the account, then URI is the * first entry of the route-set. */ if (!pj_list_empty(&acc->route_set)) { sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(acc->route_set.next->name_addr.uri); } else { pj_str_t tmp; pjsip_uri *uri; pj_strdup_with_null(pool, &tmp, suri); uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0); if (uri == NULL) return PJSIP_EINVALIDURI; /* For non-SIP scheme, route set should be configured */ if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) return PJSIP_EINVALIDREQURI; sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri); } /* Get transport type of the URI */ if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) tp_type = PJSIP_TRANSPORT_TLS; else if (sip_uri->transport_param.slen == 0) { tp_type = PJSIP_TRANSPORT_UDP; } else tp_type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); if (tp_type == PJSIP_TRANSPORT_UNSPECIFIED) return PJSIP_EUNSUPTRANSPORT; flag = pjsip_transport_get_flag_from_type(tp_type); secure = (flag & PJSIP_TRANSPORT_SECURE) != 0; /* Init transport selector. */ pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel); /* Get local address suitable to send request from */ status = pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(pjsua_var.endpt), pool, tp_type, &tp_sel, &local_addr, &local_port); if (status != PJ_SUCCESS) return status; /* Create the contact header */ contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE, "%.*s%s<%s:%.*s%s%.*s:%d;transport=%s>", (int)acc->display.slen, acc->display.ptr, (acc->display.slen?" " : ""), (secure ? "sips" : "sip"), (int)acc->user_part.slen, acc->user_part.ptr, (acc->user_part.slen?"@":""), (int)local_addr.slen, local_addr.ptr, local_port, pjsip_transport_get_type_name(tp_type)); return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsua_acc_create_uas_contact( pj_pool_t *pool, pj_str_t *contact, pjsua_acc_id acc_id, pjsip_rx_data *rdata ){ /* * Section 12.1.1, paragraph about using SIPS URI in Contact. * If the request that initiated the dialog contained a SIPS URI * in the Request-URI or in the top Record-Route header field value, * if there was any, or the Contact header field if there was no * Record-Route header field, the Contact header field in the response * MUST be a SIPS URI. */ pjsua_acc *acc; pjsip_sip_uri *sip_uri; pj_status_t status; pjsip_transport_type_e tp_type = PJSIP_TRANSPORT_UNSPECIFIED; pj_str_t local_addr; pjsip_tpselector tp_sel; unsigned flag; int secure; int local_port; PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL); acc = &pjsua_var.acc[acc_id]; /* If force_contact is configured, then use use it */ if (acc->cfg.force_contact.slen) { *contact = acc->cfg.force_contact; return PJ_SUCCESS; } /* If Record-Route is present, then URI is the top Record-Route. */ if (rdata->msg_info.record_route) { sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(rdata->msg_info.record_route->name_addr.uri); } else { pjsip_contact_hdr *h_contact; pjsip_uri *uri = NULL; /* Otherwise URI is Contact URI */ h_contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL); if (h_contact) uri = pjsip_uri_get_uri(h_contact->uri); /* Or if Contact URI is not present, take the remote URI from * the From URI. */ if (uri == NULL) uri = pjsip_uri_get_uri(rdata->msg_info.from->uri); /* Can only do sip/sips scheme at present. */ if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) return PJSIP_EINVALIDREQURI; sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri); } /* Get transport type of the URI */ if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) tp_type = PJSIP_TRANSPORT_TLS; else if (sip_uri->transport_param.slen == 0) { tp_type = PJSIP_TRANSPORT_UDP; } else tp_type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); if (tp_type == PJSIP_TRANSPORT_UNSPECIFIED) return PJSIP_EUNSUPTRANSPORT; flag = pjsip_transport_get_flag_from_type(tp_type); secure = (flag & PJSIP_TRANSPORT_SECURE) != 0; /* Init transport selector. */ pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel); /* Get local address suitable to send request from */ status = pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(pjsua_var.endpt), pool, tp_type, &tp_sel, &local_addr, &local_port); if (status != PJ_SUCCESS) return status; /* Create the contact header */ contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE, "%.*s%s<%s:%.*s%s%.*s:%d;transport=%s>", (int)acc->display.slen, acc->display.ptr, (acc->display.slen?" " : ""), (secure ? "sips" : "sip"), (int)acc->user_part.slen, acc->user_part.ptr, (acc->user_part.slen?"@":""), (int)local_addr.slen, local_addr.ptr, local_port, pjsip_transport_get_type_name(tp_type)); return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsua_acc_set_transport( pjsua_acc_id acc_id, pjsua_transport_id tp_id){ pjsua_acc *acc; PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL); acc = &pjsua_var.acc[acc_id]; PJ_ASSERT_RETURN(tp_id >= 0 && tp_id < PJ_ARRAY_SIZE(pjsua_var.tpdata), PJ_EINVAL); acc->cfg.transport_id = tp_id; return PJ_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -