📄 nua_notifier.c
字号:
expires = nu->nu_expires > now ? "noresource" : "timeout"; ss = sip_subscription_state_format(home, "%s;%s", nua_substate_name(nu->nu_substate), expires); msg_header_insert(msg, (void *)sip, (void *)ss); } else if (nu->nu_substate != nua_substate_terminated) { msg_header_replace_param(home, ss->ss_common, expires); }#if SU_HAVE_EXPERIMENTAL if (nu->nu_tag && !sip->sip_etag) msg_header_add_make(msg, (void *)sip, sip_etag_class, nu->nu_tag); if (nu->nu_no_body) { nu->nu_no_body = 0; msg_header_remove(msg, (void *)sip, (void *)sip->sip_payload); msg_header_remove(msg, (void *)sip, (void *)sip->sip_content_length); }#endif if (nu->nu_substate == nua_substate_terminated) cr->cr_terminating = 1; if (cr->cr_terminating) { nua_server_request_t *sr; for (sr = du->du_dialog->ds_sr; sr; sr = sr->sr_next) { if (sr->sr_usage == du) { /* If subscribe has not been responded, don't terminate usage by NOTIFY */ sr->sr_terminating = 1; cr->cr_terminating = 0; break; } } } if (du->du_event && !sip->sip_event) sip_add_dup(cr->cr_msg, sip, (sip_header_t *)du->du_event); return nua_base_client_request(cr, msg, sip, tags);}/** @NUA_EVENT nua_r_notify * * Response to an outgoing @b NOTIFY request. * * The @b NOTIFY may be sent explicitly by nua_notify() or implicitly by NUA * state machine. Implicit @b NOTIFY is sent when an established dialog is * refreshed by client or it is terminated (either by client or because of a * timeout). * * The current subscription state is included in NUTAG_SUBSTATE() tag. The * nua_substate_terminated indicates that the subscription is terminated, * the notifier usage has been removed and when there was no other usages of * the dialog the dialog state is also removed. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the subscription * @param hmagic application context associated with the handle * @param sip response to @b NOTIFY request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags NUTAG_SUBSTATE() indicating subscription state * SIPTAG_EVENT() indicating subscription event * * @sa nua_notify(), @RFC3265, #nua_i_subscribe, #nua_i_refer, NUTAG_SUBSTATE() * * @END_NUA_EVENT */static int nua_notify_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags){ nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; struct notifier_usage *nu = nua_dialog_usage_private(du); enum nua_substate substate = nua_substate_terminated; if (nu && !cr->cr_terminated) substate = nu->nu_substate; nua_stack_tevent(nh->nh_nua, nh, nta_outgoing_getresponse(orq), cr->cr_event, status, phrase, NUTAG_SUBSTATE(substate), SIPTAG_EVENT(du ? du->du_event : NULL), TAG_NEXT(tags)); if (du && du->du_cr == cr && !cr->cr_terminated) { if (nu->nu_requested) { /* Re-SUBSCRIBEd while NOTIFY was in progress, resend NOTIFY */ nua_client_resend_request(cr, 0); } else if (nu->nu_expires) { nua_dialog_usage_set_refresh_at(du, nu->nu_expires); } } return 0;}static void nua_notify_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now){ struct notifier_usage *nu = nua_dialog_usage_private(du); nua_client_request_t *cr = du->du_cr; nua_event_t e = nua_r_notify; if (cr) { int terminating = 0; if (nu->nu_expires && nu->nu_expires <= now) terminating = 1; else if (nu->nu_requested && nu->nu_requested <= now) terminating = 1; if (nua_client_resend_request(cr, terminating) >= 0) return; } else { if (nua_client_create(nh, e, &nua_notify_client_methods, NULL) >= 0) return; } nua_stack_tevent(nh->nh_nua, nh, NULL, e, NUA_ERROR_AT(__FILE__, __LINE__), NUTAG_SUBSTATE(nua_substate_terminated), TAG_END()); nua_dialog_usage_remove(nh, ds, du, NULL, NULL);}/** @interal Shut down NOTIFY usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */static int nua_notify_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du){ struct notifier_usage *nu = nua_dialog_usage_private(du); nua_client_request_t *cr = du->du_cr; nu->nu_substate = nua_substate_terminated; if (cr) { if (nua_client_resend_request(cr, 1) >= 0) return 0; } else { if (nua_client_tcreate(nh, nua_r_notify, &nua_notify_client_methods, SIPTAG_EVENT(du->du_event), NUTAG_SUBSTATE(nua_substate_terminated), TAG_END()) >= 0) return 0; } nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200;}/* ======================================================================== *//* REFER *//* RFC 3515 */static int nua_refer_server_init(nua_server_request_t *sr);static int nua_refer_server_preprocess(nua_server_request_t *sr);static int nua_refer_server_respond(nua_server_request_t*, tagi_t const *);static int nua_refer_server_report(nua_server_request_t*, tagi_t const *);nua_server_methods_t const nua_refer_server_methods = { SIP_METHOD_REFER, nua_i_refer, /* Event */ { 1, /* Create dialog */ 0, /* Initial request */ 1, /* Target refresh request */ 1, /* Add Contact */ }, nua_refer_server_init, nua_refer_server_preprocess, nua_base_server_params, nua_refer_server_respond, nua_refer_server_report, };static int nua_refer_server_init(nua_server_request_t *sr){ return 0;}static int nua_refer_server_preprocess(nua_server_request_t *sr){ nua_handle_t *nh = sr->sr_owner; sip_t const *sip = sr->sr_request.sip; struct notifier_usage *nu; sip_event_t *o; if (nh->nh_ds->ds_got_referrals || NH_PGET(nh, refer_with_id)) o = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq); else o = sip_event_make(nh->nh_home, "refer"); if (o) { sr->sr_usage = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o); msg_header_free(nh->nh_home, (msg_header_t *)o); } if (!sr->sr_usage) return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); nu = nua_dialog_usage_private(sr->sr_usage); nu->nu_requested = sip_now() + NH_PGET(nh, refer_expires); return 0;}staticint nua_refer_server_respond(nua_server_request_t *sr, tagi_t const *tags){ nua_handle_t *nh = sr->sr_owner; struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); sip_refer_sub_t const *rs = sip_refer_sub(sr->sr_response.sip); if (sr->sr_status < 200 || nu == NULL) { } else if (sr->sr_status < 300 && /* Application included Refer-Sub: false in response */ (rs == NULL || str0casecmp("false", rs->rs_value))) { sr->sr_usage->du_ready = 1; nu->nu_expires = sip_now() + NH_PGET(nh, refer_expires); if (sr->sr_application) /* Application responded to REFER */ nu->nu_substate = nua_substate_active; } else { /* Destroy the implicit subscription usage */ sr->sr_terminating = 1; } return nua_base_server_respond(sr, tags);}/** @NUA_EVENT nua_i_refer * * Incoming @b REFER request used to transfer calls. The tag list will * contain tag NUTAG_REFER_EVENT() with the @Event header constructed from * the REFER request. It will also contain the SIPTAG_REFERRED_BY() tag with * the @ReferredBy header containing the identity of the party sending the * REFER. The @ReferredBy structure contained in the tag is constructed from * the @From header if the @ReferredBy header was not present in the REFER * request. * * The application can let the nua to send NOTIFYs from the call it * initiates with nua_invite() if it includes in the nua_invite() arguments * both the NUTAG_NOTIFY_REFER() with the handle with which nua_i_refer was * received and the NUTAG_REFER_EVENT() from #nua_i_refer event tags. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the incoming request * @param hmagic application context associated with the handle * (NULL if outside of an already established session) * @param sip incoming REFER request * @param tags NUTAG_REFER_EVENT() \n * SIPTAG_REFERRED_BY() * * @sa nua_refer(), #nua_r_refer, @ReferTo, NUTAG_REFER_EVENT(), * SIPTAG_REFERRED_BY(), @ReferredBy, NUTAG_NOTIFY_REFER(), * NUTAG_REFER_WITH_ID(), @RFC3515. * * @END_NUA_EVENT */staticint nua_refer_server_report(nua_server_request_t *sr, tagi_t const *tags){ nua_handle_t *nh = sr->sr_owner; struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); sip_t const *sip = sr->sr_request.sip; sip_referred_by_t *by = sip->sip_referred_by, default_by[1]; sip_event_t const *o = sr->sr_usage->du_event; enum nua_substate substate = nua_substate_terminated; int initial = sr->sr_initial, retval; if (nu) { if (!sr->sr_terminating) substate = nu->nu_substate; } if (by == NULL) { by = sip_referred_by_init(default_by); by->b_display = sip->sip_from->a_display; *by->b_url = *sip->sip_from->a_url; } retval = nua_base_server_treport(sr, NUTAG_SUBSTATE(substate), NUTAG_REFER_EVENT(o), TAG_IF(by, SIPTAG_REFERRED_BY(by)), TAG_END()); if (retval >= 2 || nu == NULL) return retval; if (initial) nua_stack_post_signal(nh, nua_r_notify, SIPTAG_EVENT(o), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), SIPTAG_PAYLOAD_STR("SIP/2.0 100 Trying\r\n"), TAG_END()); return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -