/**Check that we support all features which UAC requires. * * The list of supported features is compared with the list of features * required by the UAC. If some features are not listed as supported, return * 420. If @a irq is non-NULL, the 420 response message is sent to the * client along with list of unsupported features in the @Unsupported * header, too. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param supported list of protocol features supported * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @return 0 if successful. * 420 if any of the required features is not supported. */ int nta_check_required(nta_incoming_t *irq, sip_t const *sip, sip_supported_t const *supported, tag_type_t tag, tag_value_t value, ...) { int status = 0; if (sip->sip_require) { su_home_t home[SU_HOME_AUTO_SIZE(512)]; sip_unsupported_t *us; su_home_auto(home, sizeof home); us = sip_has_unsupported(home, supported, sip->sip_require); if (us) { status = 420; if (irq) { ta_list ta; ta_start(ta, tag, value); nta_incoming_treply(irq, SIP_420_BAD_EXTENSION, SIPTAG_UNSUPPORTED(us), SIPTAG_SUPPORTED(supported), ta_tags(ta)); ta_end(ta); } } su_home_deinit(home); } return status; }
int nth_site_get_params(nth_site_t const *site, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; server_t *server; int master; msg_mclass_t const *mclass; if (site == NULL) return (errno = EINVAL), -1; server = site->site_server; master = site == server->srv_sites; if (master && server->srv_mclass != http_default_mclass()) mclass = server->srv_mclass; else mclass = NULL; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), TAG_IF(master, NTHTAG_MCLASS(mclass)), TAG_IF(master, NTHTAG_MFLAGS(server->srv_mflags)), TAG_END()); ta_end(ta); return n; }
/**Forward a request. * * @deprecated * Use nta_outgoing_mcreate() instead. */ nta_outgoing_t *nta_outgoing_tclone(nta_agent_t *agent, nta_response_f *callback, nta_outgoing_magic_t *magic, url_string_t const *route_url, msg_t *parent, tag_type_t tag, tag_value_t value, ...) { ta_list ta; msg_t *msg; nta_outgoing_t *orq = NULL; if (parent == NULL) return NULL; if ((msg = nta_msg_create(agent, 0)) == NULL) return NULL; ta_start(ta, tag, value); msg_clone(msg, parent); if (parent && sip_copy_all(msg, sip_object(msg), sip_object(parent)) < 0) ; else if (sip_add_tl(msg, sip_object(msg), ta_tags(ta)) < 0) ; else orq = nta_outgoing_mcreate(agent, callback, magic, route_url, msg); ta_end(ta); if (!orq) msg_destroy(msg); return orq; }
int nth_engine_set_params(nth_engine_t * he, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; unsigned expires; int error_msg; msg_mclass_t const *mclass; int mflags; int streaming; url_string_t const *proxy; if (he == NULL) return (errno = EINVAL), -1; ta_start(ta, tag, value); expires = he->he_expires; error_msg = he->he_error_msg; mclass = he->he_mclass; mflags = he->he_mflags; streaming = he->he_streaming; proxy = (void *) he->he_default_proxy; n = tl_gets(ta_args(ta), NTHTAG_EXPIRES_REF(expires), NTHTAG_ERROR_MSG_REF(error_msg), NTHTAG_MCLASS_REF(mclass), NTHTAG_MFLAGS_REF(mflags), NTHTAG_STREAMING_REF(streaming), NTHTAG_PROXY_REF(proxy), TAG_END()); if (n > 0) { if (proxy->us_url != he->he_default_proxy) { url_t *copy = url_hdup(he->he_home, proxy->us_url); if (proxy && !copy) { n = -1; } else { su_free(he->he_home, (void *) he->he_default_proxy); he->he_default_proxy = copy; } } } if (n > 0) { he->he_expires = expires; he->he_error_msg = error_msg != 0; if (mclass) he->he_mclass = mclass; else he->he_mclass = http_default_mclass(); he->he_mflags = mflags; he->he_streaming = streaming != 0; } ta_end(ta); return n; }
int nth_engine_get_params(nth_engine_t const *he, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; msg_mclass_t const *mclass; if (he == NULL) return (errno = EINVAL), -1; if (he->he_mclass != http_default_mclass()) mclass = he->he_mclass; else mclass = NULL; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), NTHTAG_ERROR_MSG(he->he_error_msg), NTHTAG_MCLASS(mclass), NTHTAG_MFLAGS(he->he_mflags), NTHTAG_EXPIRES(he->he_expires), NTHTAG_STREAMING(he->he_streaming), NTHTAG_PROXY((url_string_t *) he->he_default_proxy), TAG_END()); ta_end(ta); return n; }
nth_engine_t *nth_engine_create(su_root_t *root, tag_type_t tag, tag_value_t value, ...) { nth_engine_t *he; ta_list ta; if ((he = su_home_new(sizeof(*he)))) { he->he_root = root; he->he_mflags = MSG_DO_CANONIC; he->he_mclass = http_default_mclass(); he->he_expires = 32000; ta_start(ta, tag, value); if (hc_htable_resize(he->he_home, he->he_clients, 0) < 0 || he_create_tports(he, ta_args(ta)) < 0 || he_timer_init(he) < 0 || nth_engine_set_params(he, ta_tags(ta)) < 0) { nth_engine_destroy(he), he = NULL; } ta_end(ta); } return he; }
nua_handle_t * subscribe_to_nua(char const *event, tag_type_t tag, tag_value_t value, ...) { ta_list ta; struct event *subscribe; struct message *response; nua_handle_t *nh; nua_set_params(nua, NUTAG_APPL_METHOD("SUBSCRIBE"), SIPTAG_ALLOW_EVENTS_STR(event), TAG_END()); fail_unless_event(nua_r_set_params, 200); ta_start(ta, tag, value); s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL, SIPTAG_EVENT_STR(event), ta_tags(ta)); ta_end(ta); subscribe = s2_wait_for_event(nua_i_subscribe, 100); nh = subscribe->nh; nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_SAVED(subscribe->event), TAG_END()); s2_free_event(subscribe); response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE); s2_sip_update_dialog(dialog, response); fail_unless(response->sip->sip_expires != NULL); s2_sip_free_message(response); return nh; }
static struct event * notify_to_nua(enum nua_substate expect_substate, tag_type_t tag, tag_value_t value, ...) { struct event *event; struct message *response; ta_list ta; int status; ta_start(ta, tag, value); fail_if(s2_sip_request_to(dialog, SIP_METHOD_NOTIFY, NULL, SIPTAG_CONTENT_TYPE_STR(event_mime_type), SIPTAG_PAYLOAD_STR(event_state), ta_tags(ta))); ta_end(ta); response = s2_sip_wait_for_response(0, SIP_METHOD_NOTIFY); fail_if(!response); status = response->sip->sip_status->st_status; fail_unless(status == 200); s2_sip_free_message(response); event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event); fail_unless(s2_check_substate(event, expect_substate)); return event; }
/*# 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; }
/** Check that we allow the request method. * * The request-method is compared with the list of supported methods in @a * allow. If match is found, 0 is is returned. Otherwise, if the * request-method is well-known, 405 is returned. If the request-method is * unknown, 501 is returned. If @a irq is non-NULL, the 405 or 501 response * message is sent to the client, too. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param allow list of allowed methods * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @return 0 if successful, 405 is request-method is not allowed, 501 if * request-method is unknown. */ int nta_check_method(nta_incoming_t *irq, sip_t const *sip, sip_allow_t const *allow, tag_type_t tag, tag_value_t value, ...) { /* Check extensions */ sip_method_t method = sip->sip_request->rq_method; char const *name = sip->sip_request->rq_method_name; if (sip_is_allowed(allow, method, name)) return 0; if (irq) { ta_list ta; ta_start(ta, tag, value); if (method != sip_method_unknown) /* Well-known method */ nta_incoming_treply(irq, SIP_405_METHOD_NOT_ALLOWED, SIPTAG_ALLOW(allow), ta_tags(ta)); else /* Completeley unknown method */ nta_incoming_treply(irq, SIP_501_NOT_IMPLEMENTED, SIPTAG_ALLOW(allow), ta_tags(ta)); ta_end(ta); } return method != sip_method_unknown ? 405 : 501; }
/** @internal Add authorization data */ static int nh_authorize(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { int retval = 0; tagi_t const *ti; ta_list ta; ta_start(ta, tag, value); for (ti = ta_args(ta); ti; ti = tl_next(ti)) { if (ti->t_tag == nutag_auth && ti->t_value) { char *data = (char *)ti->t_value; int rv = auc_credentials(&nh->nh_auth, nh->nh_home, data); if (rv > 0) { retval = 1; } else if (rv < 0) { retval = -1; break; } } } ta_end(ta); return retval; }
/** Find tags from given list. * * Copies values of argument tag list into the reference tags in the tag * list @a lst. * * @sa tl_gets() */ int tl_tgets(tagi_t lst[], tag_type_t tag, tag_value_t value, ...) { int n = 0; tagi_t *t; ta_list ta; ta_start(ta, tag, value); for (t = lst; t; t = (tagi_t *)t_next(t)) { tag_type_t tt = t->t_tag; if (!tt) continue; if (tt->tt_class == ref_tag_class) { assert(((tag_type_t)tt->tt_magic)->tt_class->tc_ref_set); n += tl_get(tt, (void *)t->t_value, ta_args(ta)); } #if !defined(NDEBUG) else if (tt->tt_class->tc_ref_set) { fprintf(stderr, "WARNING: tag %s::%s used in tl_tgets(lst)\n", tt->tt_ns, tt->tt_name); assert(tt->tt_class == ref_tag_class); } #endif } ta_end(ta); return n; }
/**Check @SessionExpires header. * * If the proposed session-expiration time is smaller than @MinSE or our * minimal session expiration time, respond with 422 containing shortest * acceptable session expiration time in @MinSE header. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param my_min_se minimal session expiration time in seconds * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @return 422 if session expiration time is too small, 0 when successful. */ int nta_check_session_expires(nta_incoming_t *irq, sip_t const *sip, sip_time_t my_min_se, tag_type_t tag, tag_value_t value, ...) { unsigned long min_se = my_min_se; if (sip->sip_min_se && min_se < sip->sip_min_se->min_delta) min_se = sip->sip_min_se->min_delta; if (sip->sip_session_expires->x_delta >= min_se) return 0; if (irq) { ta_list ta; sip_min_se_t min_se0[1]; ta_start(ta, tag, value); sip_min_se_init(min_se0)->min_delta = min_se; nta_incoming_treply(irq, SIP_422_SESSION_TIMER_TOO_SMALL, SIPTAG_MIN_SE(min_se0), ta_tags(ta)); ta_end(ta); } return 422; }
/** Check that we understand session content in the request. * * If there is no @ContentDisposition header or the @ContentDisposition * header indicated "session", the message body and content-type is compared * with the acceptable session content-types listed in @a session_accepts. * (typically, @c "application/sdp"). If no match is found, a 415 is * returned. If @a irq is non-NULL, the 415 response message is sent to the * client, too. * * If the @ContentDisposition header indicates something else but "session", * and it does not contain "handling=optional" parameter, a 415 response is * returned, too. * * Also, the @ContentEncoding header is checked. If it is not empty * (indicating no content-encoding), a 415 response is returned, too. * * @param irq incoming (server) transaction object (may be NULL). * @param sip contents of the SIP message * @param session_accepts list of acceptable content-types for "session" * content disposition * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @return 0 if successful, 415 if content-type is not acceptable. */ int nta_check_session_content(nta_incoming_t *irq, sip_t const *sip, sip_accept_t const *session_accepts, tag_type_t tag, tag_value_t value, ...) { sip_content_type_t const *c = sip->sip_content_type; sip_content_disposition_t const *cd = sip->sip_content_disposition; int acceptable_type = 0, acceptable_encoding = 0; if (sip->sip_payload == NULL) return 0; if (cd == NULL || su_casematch(cd->cd_type, "session")) { sip_accept_t const *ab = session_accepts; char const *c_type; if (c) c_type = c->c_type; else if (sip->sip_payload->pl_len > 3 && su_casenmatch(sip->sip_payload->pl_data, "v=0", 3)) /* Missing Content-Type, but it looks like SDP */ c_type = application_sdp; else /* No chance */ ab = NULL, c_type = NULL; for (; ab; ab = ab->ac_next) { if (su_casematch(c_type, ab->ac_type)) break; } if (ab) acceptable_type = 1; } else if (cd->cd_optional) acceptable_type = 1; /* Empty or missing Content-Encoding */ if (!sip->sip_content_encoding || !sip->sip_content_encoding->k_items || !sip->sip_content_encoding->k_items[0] || !sip->sip_content_encoding->k_items[0][0]) acceptable_encoding = 1; if (acceptable_type && acceptable_encoding) return 0; if (irq) { ta_list ta; ta_start(ta, tag, value); nta_incoming_treply(irq, SIP_415_UNSUPPORTED_MEDIA, SIPTAG_ACCEPT(session_accepts), ta_tags(ta)); ta_end(ta); } return 415; }
/** @internal * Post signal to stack itself */ void nua_stack_post_signal(nua_handle_t *nh, nua_event_t event, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); nua_signal((nh)->nh_nua, nh, NULL, event, 0, NULL, ta_tags(ta)); ta_end(ta); }
/** Filter tag list @a src with given tags. * * @sa tl_afilter(), tl_filtered_tlist(), TAG_FILTER(), TAG_ANY(), #ns_tag_class */ tagi_t *tl_tfilter(su_home_t *home, tagi_t const src[], tag_type_t tag, tag_value_t value, ...) { tagi_t *tl; ta_list ta; ta_start(ta, tag, value); tl = tl_afilter(home, ta_args(ta), src); ta_end(ta); return tl; }
/**Add tags to request message and send it, * * @retval 0 success * @retval -1 if error occurred, but event has not been sent * @retval -2 if error occurred, event has not been sent, * and @a msg has been destroyed * @retval >=1 if error event has been sent */ int nua_base_client_trequest(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = nua_base_client_request(cr, msg, sip, ta_args(ta)); ta_end(ta); return retval; }
int nua_stack_tevent(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, ...) { ta_list ta; int retval; ta_start(ta, tag, value); retval = nua_stack_event(nua, nh, msg, event, status, phrase, ta_args(ta)); ta_end(ta); return retval; }
/**Check that UAC accepts one of listed MIME content-types. * * The list of acceptable content-types are compared with the acceptable * content-types. If match is found, it is returned in @a return_acceptable. * If no match is found, a 406 is returned. If @a irq is non-NULL, the 406 * response message is sent to the client, too. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message * @param acceptable list of acceptable content types * @param return_acceptable optional return-value parameter for * matched content-type * @param tag, value, ... optional list of tagged arguments used * when responding to the transaction * * @return 406 if no content-type is acceptable by client, 0 if successful. */ int nta_check_accept(nta_incoming_t *irq, sip_t const *sip, sip_accept_t const *acceptable, sip_accept_t const **return_acceptable, tag_type_t tag, tag_value_t value, ...) { ta_list ta; sip_accept_t const *ac, *ab; sip_method_t method; if (!acceptable) return 0; if (sip->sip_request) method = sip->sip_request->rq_method; else /* if (sip->sip_cseq) */ method = sip->sip_cseq->cs_method; /* Missing Accept header implies support for SDP in INVITE and OPTIONS * (and PRACK and UPDATE?) */ if (!sip->sip_accept && (method == sip_method_invite || method == sip_method_options || method == sip_method_prack || method == sip_method_update)) { for (ab = acceptable; ab; ab = ab->ac_next) if (su_casematch(application_sdp, ab->ac_type)) { if (return_acceptable) *return_acceptable = ab; return 0; } } for (ac = sip->sip_accept; ac; ac = ac->ac_next) { if (sip_q_value(ac->ac_q) == 0 || !ac->ac_type) continue; for (ab = acceptable; ab; ab = ab->ac_next) if (su_casematch(ac->ac_type, ab->ac_type)) { if (return_acceptable) *return_acceptable = ab; return 0; } } if (irq) { ta_start(ta, tag, value); nta_incoming_treply(irq, SIP_406_NOT_ACCEPTABLE, SIPTAG_ACCEPT(acceptable), ta_tags(ta)); ta_end(ta); } return 406; }
/** Allocate and duplicate tagged arguments as a tag list using memory home. */ tagi_t *tl_tlist(su_home_t *home, tag_type_t tag, tag_value_t value, ...) { tagi_t *tl; ta_list ta; ta_start(ta, tag, value); tl = tl_adup(home, ta_args(ta)); ta_end(ta); return tl; }
int nua_client_tcreate(nua_handle_t *nh, int event, nua_client_methods_t const *methods, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = nua_client_create(nh, event, methods, ta_args(ta)); ta_end(ta); return retval; }
/**Create an authentication plugin module. * * The function auth_mod_create() creates a module used to authenticate the * requests. * * @param root pointer to a su_root_t object * @param tag,value,... tagged argument list * * @TAGS * AUTHTAG_METHOD(), AUTHTAG_REALM(), AUTHTAG_DB(), AUTHTAG_ALLOW(), * AUTHTAG_QOP(), AUTHTAG_ALGORITHM(), AUTHTAG_EXPIRES(), * AUTHTAG_BLACKLIST(), AUTHTAG_FORBIDDEN(), AUTHTAG_ANONYMOUS(), * AUTHTAG_REMOTE(). */ auth_mod_t *auth_mod_create(su_root_t *root, tag_type_t tag, tag_value_t value, ...) { auth_mod_t *am = NULL; ta_list ta; char const *method = NULL; ta_start(ta, tag, value); tl_gets(ta_args(ta), AUTHTAG_METHOD_REF(method), TAG_NULL()); if (method) { auth_scheme_t *bscheme = NULL; char const *base; size_t len; base = strrchr(method, '+'); if (base) len = base++ - method; else len = strlen(method); if (base == NULL) ; else if (su_casematch(base, "Basic")) bscheme = auth_scheme_basic; else if (su_casematch(base, "Digest")) bscheme = auth_scheme_digest; if (base == NULL || bscheme) { int i; for (i = 0; schemes[i] && i < N; i++) { if (su_casenmatch(schemes[i]->asch_method, method, len) && schemes[i]->asch_method[len] == 0) { am = auth_mod_alloc(schemes[i], ta_tags(ta)); if (schemes[i]->asch_init(am, bscheme, root, ta_tags(ta)) == -1) { auth_mod_destroy(am), am = NULL; } break; } } } } ta_end(ta); return am; }
/** Create a filtered tag list. * * @sa tl_afilter(), tl_tfilter(), TAG_FILTER(), TAG_ANY(), #ns_tag_class */ tagi_t *tl_filtered_tlist(su_home_t *home, tagi_t const filter[], tag_type_t tag, tag_value_t value, ...) { tagi_t *tl; ta_list ta; ta_start(ta, tag, value); tl = tl_afilter(home, filter, ta_args(ta)); ta_end(ta); return tl; }
/**Create a resolver. * * The function sres_resolver_create() is used to allocate and initialize * the resolver object using the Sofia asynchronous reactor #su_root_t. */ sres_resolver_t * sres_resolver_create(su_root_t *root, char const *conf_file_path, tag_type_t tag, tag_value_t value, ...) { sres_resolver_t *res; sres_sofia_t *srs; sres_cache_t *cache = NULL; ta_list ta; if (root == NULL) return su_seterrno(EFAULT), (void *)NULL; ta_start(ta, tag, value); tl_gets(ta_args(ta), SRESTAG_RESOLV_CONF_REF(conf_file_path), SRESTAG_CACHE_REF(cache), TAG_END()); ta_end(ta); res = sres_resolver_new_with_cache(conf_file_path, cache, NULL); srs = res ? su_zalloc(0, sizeof *srs) : NULL; if (res && srs) { su_timer_t *t; srs->srs_resolver = res; srs->srs_root = root; srs->srs_socket = INVALID_SOCKET; sres_resolver_set_async(res, sres_sofia_update, srs, 0); t = su_timer_create(su_root_task(root), SRES_RETRANSMIT_INTERVAL); srs->srs_timer = t; if (!srs->srs_timer) SU_DEBUG_3(("sres: cannot create timer\n")); #if nomore else if (su_timer_set_for_ever(t, sres_sofia_timer, srs) < 0) SU_DEBUG_3(("sres: cannot set timer\n")); #else else if (sres_resolver_set_timer_cb(res, sres_sofia_set_timer, srs) < 0) SU_DEBUG_3(("sres: cannot set timer cb\n")); #endif else return res; /* Success! */ sres_resolver_destroy(res), res = NULL; } return res; }
/** Activate (STUN) keepalive for transport */ int tport_keepalive(tport_t *tp, su_addrinfo_t const *ai, tag_type_t tag, tag_value_t value, ...) { if (tp && tp->tp_pri && tp->tp_pri->pri_vtable->vtp_keepalive) { int retval; ta_list ta; ta_start(ta, tag, value); retval = tp->tp_pri->pri_vtable->vtp_keepalive(tp, ai, ta_args(ta)); ta_end(ta); return retval; } return -1; }
int nua_client_treport(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tag_type_t tag, tag_value_t value, ...) { int retval; ta_list ta; ta_start(ta, tag, value); retval = nua_client_report(cr, status, phrase, sip, orq, ta_args(ta)); ta_end(ta); return retval; }
END_TEST static nua_handle_t *make_auth_natted_register( nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { struct message *m; ta_list ta; ta_start(ta, tag, value); nua_register(nh, ta_tags(ta)); ta_end(ta); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); s2_sip_respond_to(m, NULL, SIP_401_UNAUTHORIZED, SIPTAG_WWW_AUTHENTICATE_STR(s2_auth_digest_str), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); fail_unless_event(nua_r_register, 401); /* NAT detected event */ fail_unless_event(nua_i_outbound, 101); nua_authenticate(nh, NUTAG_AUTH(s2_auth_credentials), TAG_END()); m = s2_sip_wait_for_request(SIP_METHOD_REGISTER); fail_if(!m); fail_if(!m->sip->sip_authorization); /* should not unregister the previous contact * as it has not been successfully registered */ fail_if(!m->sip->sip_contact); fail_if(m->sip->sip_contact->m_next); s2_save_register(m); s2_sip_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), SIPTAG_VIA(natted_via(m, receive_natted)), TAG_END()); s2_sip_free_message(m); assert(s2->registration->contact != NULL); fail_unless_event(nua_r_register, 200); return nh; }
static struct message * invite_sent_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) { ta_list ta; ta_start(ta, tag, value); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), ta_tags(ta)); ta_end(ta); fail_unless(s2_check_callstate(nua_callstate_calling)); return s2_sip_wait_for_request(SIP_METHOD_INVITE); }
int nth_engine_get_stats(nth_engine_t const *he, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; if (he == NULL) return (errno = EINVAL), -1; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), TAG_END()); ta_end(ta); return n; }
/**@internal * Relay response event to the application. * * @todo * If handle has already been marked as destroyed by nua_handle_destroy(), * release the handle with nh_destroy(). * * @retval 0 if event was preliminary * @retval 1 if event was final * @retval 2 if event destroyed the handle, too. */ int nua_base_client_tresponse(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, tag_type_t tag, tag_value_t value, ...) { ta_list ta; int retval; if (cr->cr_event == nua_r_destroy) return nua_base_client_response(cr, status, phrase, sip, NULL); ta_start(ta, tag, value); retval = nua_base_client_response(cr, status, phrase, sip, ta_args(ta)); ta_end(ta); return retval; }