/*# Send a request to the protocol thread */ int nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { su_msg_r sumsg = SU_MSG_R_INIT; size_t len, xtra, ee_len, l_len = 0, l_xtra = 0; ta_list ta; int retval = -1; if (nua == NULL) return -1; if (nua->nua_shutdown_started && event != nua_r_shutdown) return -1; ta_start(ta, tag, value); ee_len = offsetof(nua_ee_data_t, ee_data[0].e_tags); len = tl_len(ta_args(ta)); xtra = tl_xtra(ta_args(ta), len); if (su_msg_new(sumsg, ee_len + len + l_len + xtra + l_xtra) == 0) { nua_ee_data_t *ee = su_msg_data(sumsg); nua_event_data_t *e = ee->ee_data; tagi_t *t = e->e_tags; void *b = (char *)t + len + l_len; tagi_t *tend = (tagi_t *)b; char *bend = (char *)b + xtra + l_xtra; t = tl_dup(t, ta_args(ta), &b); assert(tend == t); (void)tend; assert(b == bend); (void)bend; e->e_always = event == nua_r_destroy || event == nua_r_shutdown; e->e_event = event; e->e_nh = nh ? nua_handle_ref(nh) : NULL; e->e_status = status; e->e_phrase = phrase; su_msg_deinitializer(sumsg, nua_event_deinit); retval = su_msg_send_to(sumsg, nua->nua_server, nua_stack_signal); if (retval == 0){ SU_DEBUG_7(("nua(%p): %s signal %s\n", (void *)nh, "sent", nua_event_name(event) + 4)); } else { SU_DEBUG_0(("nua(%p): %s signal %s\n", (void *)nh, "FAILED TO SEND", nua_event_name(event) + 4)); } } ta_end(ta); return retval; }
/** Allocate and duplicate a tag list using memory home. */ tagi_t *tl_adup(su_home_t *home, tagi_t const lst[]) { size_t len = tl_len(lst); size_t xtra = tl_xtra(lst, 0); void *b = su_alloc(home, len + xtra); tagi_t *d, *newlst = b; void *end = (char *)b + len + xtra; tagi_t *tend = (tagi_t*)((char *)b + len); b = (char *)b + len; d = tl_dup(newlst, lst, &b); assert(b == end); assert(tend == d); (void)end; (void)tend; return newlst; }
/** @internal Send an event to the application. */ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tagi_t const *tags) { su_msg_r sumsg = SU_MSG_R_INIT; size_t e_len, len, xtra, p_len; if (event == nua_r_ack || event == nua_i_none) return event; if (nh == nua->nua_dhandle) nh = NULL; if (nua_log->log_level >= 5) { char const *name = nua_event_name(event) + 4; char const *p = phrase ? phrase : ""; if (status == 0) SU_DEBUG_5(("nua(%p): event %s %s\n", (void *)nh, name, p)); else SU_DEBUG_5(("nua(%p): event %s %u %s\n", (void *)nh, name, status, p)); } if (event == nua_r_destroy) { if (msg) msg_destroy(msg); if (status >= 200) { nh_destroy(nua, nh); } return event; } if ((event > nua_r_authenticate && event <= nua_r_ack) || event < nua_i_error || (nh && !nh->nh_valid) || (nua->nua_shutdown && event != nua_r_shutdown && !nua->nua_prefs->ngp_shutdown_events)) { if (msg) msg_destroy(msg); return event; } if (tags) { e_len = offsetof(nua_ee_data_t, ee_data[0].e_tags); len = tl_len(tags); xtra = tl_xtra(tags, len); } else { e_len = sizeof(nua_ee_data_t), len = 0, xtra = 0; } p_len = phrase ? strlen(phrase) + 1 : 1; if (su_msg_new(sumsg, e_len + len + xtra + p_len) == 0) { nua_ee_data_t *ee = su_msg_data(sumsg); nua_event_data_t *e = ee->ee_data; void *p; if (tags) { tagi_t *t = e->e_tags, *t_end = (tagi_t *)((char *)t + len); void *b = t_end, *end = (char *)b + xtra; t = tl_dup(t, tags, &b); p = b; assert(t == t_end); assert(b == end); (void)end; } else p = e + 1; ee->ee_nua = nua_stack_ref(nua); e->e_event = event; e->e_nh = nh ? nua_handle_ref(nh) : NULL; e->e_status = status; e->e_phrase = strcpy(p, phrase ? phrase : ""); if (msg) e->e_msg = msg, su_home_threadsafe(msg_home(msg)); su_msg_deinitializer(sumsg, nua_event_deinit); su_msg_send_to(sumsg, nua->nua_client, nua_application_event); } return event; }