static int nua_refer_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du, *du0 = cr->cr_usage; struct event_usage *eu; sip_event_t *event; int error; cr->cr_usage = NULL; event = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq); if (!event) return -1; if (du0 == NULL || du0->du_event == NULL || du0->du_event->o_id == NULL || strcmp(du0->du_event->o_id, event->o_id)) { du = nua_dialog_usage_add(nh, nh->nh_ds, nua_subscribe_usage, event); if (!du) return -1; } else { du = du0, du0 = NULL; } if (du0) nua_dialog_usage_remove(nh, nh->nh_ds, du0, NULL, NULL); eu = nua_dialog_usage_private(cr->cr_usage = du); eu ->eu_refer = 1; error = nua_base_client_request(cr, msg, sip, tags); if (!error) { /* Give application an Event header for matching NOTIFYs with REFER */ nua_stack_tevent(nh->nh_nua, nh, NULL, (enum nua_event_e)cr->cr_event, SIP_100_TRYING, NUTAG_REFER_EVENT(event), SIPTAG_EVENT(event), TAG_END()); su_free(nh->nh_home, event); } return error; }
static int 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; }