📄 nua_stack.c
字号:
else if (!sip->sip_organization && NH_PGET(nh, organization) && sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, organization)) < 0) msg_destroy(msg); else if (!sip->sip_allow && NH_PGET(nh, allow) && sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow)) < 0) msg_destroy(msg); else return msg; return NULL;}/* ======================================================================== *//* Generic processing */int nua_stack_process_unknown(nua_t *nua, nua_handle_t *nh, nta_incoming_t *irq, sip_t const *sip){ return 501;}intnua_stack_method(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags){ return UA_EVENT1(e, SIP_501_NOT_IMPLEMENTED);}/**Relay response message to the application. * * If handle has already been marked as destroyed by nua_handle_destroy(), * release the handle with nh_destroy(). */int nua_stack_process_response(nua_handle_t *nh, struct nua_client_request *cr, nta_outgoing_t *orq, sip_t const *sip, tag_type_t tag, tag_value_t value, ...){ msg_t *msg = nta_outgoing_getresponse(orq); int status = sip->sip_status->st_status; char const *phrase = sip->sip_status->st_phrase; ta_list ta; int final; if (status >= 200 && status < 300) nh_challenge(nh, sip); /* Collect nextnonce */ if (nta_outgoing_method(orq) == sip_method_invite) final = status >= 300; else final = status >= 200; if (final) { nua_creq_deinit(cr, orq); if (cr->cr_usage && nh->nh_cr == cr) { if ((status >= 300 && !cr->cr_usage->du_ready) || cr->cr_usage->du_terminating) nua_dialog_usage_remove(nh, nh->nh_ds, cr->cr_usage); } cr->cr_usage = NULL; } ta_start(ta, tag, value); nua_stack_event(nh->nh_nua, nh, msg, cr->cr_event, status, phrase, ta_tags(ta)); if (final) cr->cr_event = nua_i_error; ta_end(ta); return 0;}static inlineint can_redirect(sip_contact_t const *m, sip_method_t method){ if (m && m->m_url->url_host) { enum url_type_e type = m->m_url->url_type; return type == url_sip || type == url_sips || (type == url_tel && (method == sip_method_invite || method == sip_method_message)) || (type == url_im && method == sip_method_message) || (type == url_pres && method == sip_method_subscribe); } return 0;}int nua_creq_restart_with(nua_handle_t *nh, struct nua_client_request *cr, nta_outgoing_t *orq, int status, char const *phrase, nua_creq_restart_f *f, TAG_LIST){ ta_list ta; msg_t *msg = nta_outgoing_getresponse(orq); nua_stack_event(nh->nh_nua, nh, msg, cr->cr_event, status, phrase, TAG_END()); nta_outgoing_destroy(orq); if (f) { ta_start(ta, tag, value); f(nh, ta_args(ta)); ta_end(ta); } return 1;}/** Check response, return true if we can restart the request. * */int nua_creq_check_restart(nua_handle_t *nh, struct nua_client_request *cr, nta_outgoing_t *orq, sip_t const *sip, nua_creq_restart_f *f){ int status = sip->sip_status->st_status; sip_method_t method = nta_outgoing_method(orq); int removed = 0; nua_dialog_usage_t *du = cr->cr_usage; assert(f); if (orq == cr->cr_orq) removed = 1, cr->cr_orq = NULL; cr->cr_restart = NULL; if (cr->cr_msg == NULL || status < 200) ; else if (++cr->cr_retry_count > NH_PGET(nh, retry_count)) ; else if (status == 302) { if (can_redirect(sip->sip_contact, method)) { return nua_creq_restart_with(nh, cr, orq, 100, "Redirected", f, NUTAG_URL(sip->sip_contact->m_url), TAG_END()); } } else if (status == 423) { sip_t *req = sip_object(cr->cr_msg); unsigned my_expires = 0; if (req->sip_expires) my_expires = req->sip_expires->ex_delta; if (sip->sip_min_expires && sip->sip_min_expires->me_delta > my_expires) { sip_expires_t ex[1]; sip_expires_init(ex); ex->ex_delta = sip->sip_min_expires->me_delta; return nua_creq_restart_with(nh, cr, orq, 100, "Re-Negotiating Subscription Expiration", f, SIPTAG_EXPIRES(ex), TAG_END()); } } else if (method != sip_method_ack && method != sip_method_cancel && ((status == 401 && sip->sip_www_authenticate) || (status == 407 && sip->sip_proxy_authenticate)) && nh_challenge(nh, sip) > 0) { sip_t *rsip; int done; rsip = sip_object(cr->cr_msg); /* XXX - check for instant restart */ done = auc_authorization(&nh->nh_auth, cr->cr_msg, (msg_pub_t*)rsip, rsip->sip_request->rq_method_name, rsip->sip_request->rq_url, rsip->sip_payload); if (done > 0) { return nua_creq_restart_with(nh, cr, orq, 100, "Request Authorized by Cache", f, TAG_END()); } else if (done == 0) { msg_t *msg = nta_outgoing_getresponse(orq); nua_stack_event(nh->nh_nua, nh, msg, cr->cr_event, status, sip->sip_status->st_phrase, TAG_END()); nta_outgoing_destroy(orq); if (du) { du->du_pending = NULL; du->du_refresh = 0; } /* Wait for nua_authenticate() */ cr->cr_restart = f; return 1; } else { SU_DEBUG_5(("nua(%p): auc_authorization failed\n", nh)); } }#if HAVE_SOFIA_SMIME else if (status == 493) /* try detached signature */ ;#endif else if (status == 422 && method == sip_method_invite) { if (sip->sip_min_se && nh->nh_ss->ss_min_se < sip->sip_min_se->min_delta) nh->nh_ss->ss_min_se = sip->sip_min_se->min_delta; if (nh->nh_ss->ss_min_se > nh->nh_ss->ss_session_timer) nh->nh_ss->ss_session_timer = nh->nh_ss->ss_min_se; return nua_creq_restart_with(nh, cr, orq, 100, "Re-Negotiating Session Timer", f, TAG_END()); } /* This was final response that cannot be restarted. */ if (removed) cr->cr_orq = orq; if (du) { du->du_pending = NULL; du->du_refresh = 0; } cr->cr_retry_count = 0; if (cr->cr_msg) msg_destroy(cr->cr_msg), cr->cr_msg = NULL; return 0;}/** Restart a request */int nua_creq_restart(nua_handle_t *nh, struct nua_client_request *cr, nta_response_f *cb, tagi_t *tags){ msg_t *msg; cr->cr_restart = NULL; if (!cr->cr_msg) return 0; msg = nua_creq_msg(nh->nh_nua, nh, cr, 1, SIP_METHOD_UNKNOWN, TAG_NEXT(tags)); cr->cr_orq = nta_outgoing_mcreate(nh->nh_nua->nua_nta, cb, nh, NULL, msg, SIPTAG_END(), TAG_NEXT(tags)); if (!cr->cr_orq) { msg_destroy(msg); return 0; } return 1;}/* ======================================================================== *//* Authentication */voidnua_stack_authenticate(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags){ int status = nh_authorize(nh, TAG_NEXT(tags)); if (status > 0) { nua_creq_restart_f *restart = NULL; nua_stack_event(nua, nh, NULL, e, SIP_200_OK, TAG_END()); if (nh->nh_cr->cr_restart) { restart = nh->nh_cr->cr_restart; nh->nh_cr->cr_restart = NULL; } else if (nh->nh_ss->ss_crequest->cr_restart) { restart = nh->nh_ss->ss_crequest->cr_restart; nh->nh_ss->ss_crequest->cr_restart = NULL; } if (restart) restart(nh, (tagi_t *)tags); /* Restart operation */ } else if (status < 0) { nua_stack_event(nua, nh, NULL, e, 500, "Cannot add credentials", TAG_END()); } else { nua_stack_event(nua, nh, NULL, e, 404, "No matching challenge", TAG_END()); }}/* ======================================================================== *//* * Process incoming requests */int nua_stack_process_request(nua_handle_t *nh, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip){ nua_t *nua = nh->nh_nua; sip_method_t method = sip->sip_request->rq_method; sip_user_agent_t const *user_agent = NH_PGET(nh, user_agent); sip_supported_t const *supported = NH_PGET(nh, supported); sip_allow_t const *allow = NH_PGET(nh, allow); enter; nta_incoming_tag(irq, NULL); if (nta_check_method(irq, sip, allow, SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT(user_agent), TAG_END())) return 405; switch (sip->sip_request->rq_url->url_type) { case url_sip: case url_sips: case url_im: case url_pres: case url_tel: break; default: nta_incoming_treply(irq, SIP_416_UNSUPPORTED_URI, SIPTAG_ALLOW(allow), SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT(user_agent), TAG_END()); } if (nta_check_required(irq, sip, supported, SIPTAG_ALLOW(allow), SIPTAG_USER_AGENT(user_agent), TAG_END())) return 420; if (nh == nua->nua_dhandle) { if (!sip->sip_to->a_tag) ; else if (method == sip_method_message && NH_PGET(nh, win_messenger_enable)) ; else { nta_incoming_treply(irq, 481, "Initial transaction with a To tag", TAG_END()); return 481; } nh = NULL; } if (sip->sip_timestamp) nta_incoming_treply(irq, SIP_100_TRYING, TAG_END()); switch (method) { case sip_method_invite: return nua_stack_process_invite(nua, nh, irq, sip); case sip_method_info: if (nh) return nua_stack_process_info(nua, nh, irq, sip); /*FALLTHROUGH*/ case sip_method_update: if (nh) return nua_stack_process_update(nua, nh, irq, sip); /*FALLTHROUGH*/ case sip_method_bye: if (nh) return nua_stack_process_bye(nua, nh, irq, sip); nta_incoming_treply(irq, 481, "Call Does Not Exist", SIPTAG_ALLOW(allow), SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT(user_agent), TAG_END()); return 481; case sip_method_message: return nua_stack_process_message(nua, nh, irq, sip); case sip_method_notify: return nua_stack_process_notify(nua, nh, irq, sip); case sip_method_subscribe: return nua_stack_process_subsribe(nua, nh, irq, sip); case sip_method_options: return nua_stack_process_options(nua, nh, irq, sip); case sip_method_refer: return nua_stack_process_refer(nua, nh, irq, sip); case sip_method_publish: return nua_stack_process_publish(nua, nh, irq, sip); case sip_method_ack: case sip_method_cancel: SU_DEBUG_1(("nua(%p): strange %s from <" URL_PRINT_FORMAT ">\n", nh, sip->sip_request->rq_method_name, URL_PRINT_ARGS(sip->sip_from->a_url))); /* Send nua_i_error ? */ return 481; default: return nua_stack_process_unknown(nua, nh, irq, sip); }}voidnua_stack_respond(nua_t *nua, nua_handle_t *nh, int status, char const *phrase, tagi_t const *tags){ struct nua_session_state *ss = nh->nh_ss; nua_server_request_t *sr = ss->ss_srequest; if (sr->sr_respond) { sr->sr_respond(nua, nh, status, phrase, tags); }#if 0 else if (nta_incoming_status(nh->nh_irq) < 200) { int add_contact = 0; sip_contact_t *m; if (nta_incoming_url(nh->nh_irq)->url_type == url_sips && nua->nua_sips_contact) m = nua->nua_sips_contact; else m = nua->nua_contact; SU_DEBUG_1(("nua: anonymous response %u %s\n", status, phrase)); tl_gets(tags, NUTAG_ADD_CONTACT_REF(add_contact), TAG_END()); nta_incoming_treply(nh->nh_irq, status, phrase, TAG_IF(add_contact, SIPTAG_CONTACT(m)), TAG_NEXT(tags)); if (status >= 200) nta_incoming_destroy(nh->nh_irq), nh->nh_irq = NULL; }#endif else if (ss->ss_srequest->sr_irq) { nua_stack_event(nua, nh, NULL, nua_i_error, 500, "Already Sent Final Response", TAG_END()); } else { nua_stack_event(nua, nh, NULL, nua_i_error, 500, "Responding to a Non-Existing Request", TAG_END()); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -