/** @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) { SU_DEBUG_5(("%s(%p, %p, %p): using existing cr=%p\n", "nua_notify_usage_shutdown", (void *)nh, (void *)ds, (void *)du, (void *)cr)); if (nua_client_resend_request(cr, 1) >= 0) return 0; } else { SU_DEBUG_5(("%s(%p, %p, %p): new NOTIFY cr for %s\n", "nua_notify_usage_shutdown", (void *)nh, (void *)ds, (void *)du, du->du_event ? du->du_event->o_type : "<implicit>")); 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; }
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), (enum nua_event_e)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); }
/** Refresh subscription */ static void nua_subscribe_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now) { nua_client_request_t *cr = du->du_cr; struct event_usage *eu = nua_dialog_usage_private(du); assert(eu); if (eu->eu_final_wait) { /* Did not receive NOTIFY for fetch */ sip_event_t const *o = du->du_event; char const *id = o ? o->o_id : NULL; SU_DEBUG_3(("nua(%p): event %s%s%s fetch timeouts\n", (void *)nh, o ? o->o_type : "(empty)", id ? "; id=" : "", id ? id : "")); nua_stack_tevent(nh->nh_nua, nh, NULL, nua_i_notify, 408, "Fetch Timeouts without NOTIFY", NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_EVENT(du->du_event), TAG_END()); nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return; } if (cr) { if (nua_client_resend_request(cr, 0) >= 0) return; } else if (eu->eu_refer) { /* * XXX - If we have received a NOTIFY, we should try to terminate * subscription */ } if (!eu->eu_unsolicited) nua_stack_tevent(nh->nh_nua, nh, NULL, nua_i_notify, NUA_ERROR_AT(__FILE__, __LINE__), NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_EVENT(du->du_event), TAG_END()); nua_dialog_usage_remove(nh, ds, du, NULL, NULL); }
/** @interal Shut down PUBLISH usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ static int nua_publish_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { nua_client_request_t *cr = du->du_cr; if (cr) { if (nua_client_resend_request(cr, 1) >= 0) return 0; } /* XXX - report to user */ nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200; }
/** Terminate subscription. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ static int nua_subscribe_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { struct event_usage *eu = nua_dialog_usage_private(du); nua_client_request_t *cr = du->du_cr; assert(eu); (void)eu; if (cr) { if (nua_client_resend_request(cr, 1) >= 0) return 0; } nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200; }
static void nua_publish_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now) { nua_client_request_t *cr = du->du_cr; if (cr) { if (nua_client_resend_request(cr, 0) >= 0) return; } nua_stack_event(nh->nh_nua, nh, NULL, nua_r_publish, NUA_ERROR_AT(__FILE__, __LINE__), NULL); nua_dialog_usage_remove(nh, ds, du, NULL, NULL); }
static void nua_notify_usage_refresh(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; nua_event_t e = nua_r_notify; if (cr) { int terminating = 0; sip_time_t now = sip_now(); SU_DEBUG_7(("%s(%p, %p, %p): using existing cr=%p\n", "nua_notify_usage_refresh", (void *)nh, (void *)ds, (void *)du, (void *)cr)); 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 { SU_DEBUG_7(("%s(%p, %p, %p): new NOTIFY cr for %s\n", "nua_notify_usage_refresh", (void *)nh, (void *)ds, (void *)du, du->du_event ? du->du_event->o_type : "<implicit>")); 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); }