static void mrcp_sofia_on_resource_discover( int status, mrcp_sofia_agent_t *sofia_agent, nua_handle_t *nh, mrcp_sofia_session_t *sofia_session, sip_t const *sip, tagi_t tags[]) { mrcp_session_t *session = sofia_session->session; if(session) { const char *remote_sdp_str = NULL; mrcp_session_descriptor_t *descriptor = NULL; tl_gets(tags, SOATAG_REMOTE_SDP_STR_REF(remote_sdp_str), TAG_END()); if(remote_sdp_str) { sdp_parser_t *parser = NULL; sdp_session_t *sdp = NULL; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Resource Discovery SDP %s\n%s", session->name, remote_sdp_str); parser = sdp_parse(sofia_session->home,remote_sdp_str,(int)strlen(remote_sdp_str),0); sdp = sdp_session(parser); descriptor = mrcp_descriptor_generate_by_sdp_session(sdp,NULL,session->pool); sdp_parser_free(parser); } mrcp_session_discover_response(session,descriptor); } }
static void mrcp_sofia_on_state_change( int status, mrcp_sofia_agent_t *sofia_agent, nua_handle_t *nh, mrcp_sofia_session_t *sofia_session, sip_t const *sip, tagi_t tags[]) { int ss_state = nua_callstate_init; tl_gets(tags, NUTAG_CALLSTATE_REF(ss_state), TAG_END()); apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"SIP Call State %s [%s]", sofia_session ? sofia_session->session->name : "", nua_callstate_name(ss_state)); switch(ss_state) { case nua_callstate_ready: mrcp_sofia_on_session_ready(status,sofia_agent,nh,sofia_session,sip,tags); break; case nua_callstate_terminated: mrcp_sofia_on_session_terminate(status,sofia_agent,nh,sofia_session,sip,tags); break; } }
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; }
static int soa_static_set_params(soa_session_t *ss, tagi_t const *tags) { soa_static_session_t *sss = (soa_static_session_t *)ss; char const *audio_aux = sss->sss_audio_aux; int ordered_user = sss->sss_ordered_user; int reuse_rejected = sss->sss_reuse_rejected; int n, m; n = tl_gets(tags, SOATAG_AUDIO_AUX_REF(audio_aux), SOATAG_ORDERED_USER_REF(ordered_user), SOATAG_REUSE_REJECTED_REF(reuse_rejected), TAG_END()); if (n > 0 && !su_casematch(audio_aux, sss->sss_audio_aux)) { char *s = su_strdup(ss->ss_home, audio_aux), *tbf = sss->sss_audio_aux; if (s == NULL && audio_aux != NULL) return -1; sss->sss_audio_aux = s; if (tbf) su_free(ss->ss_home, tbf); } sss->sss_ordered_user = ordered_user != 0; sss->sss_reuse_rejected = reuse_rejected != 0; m = soa_base_set_params(ss, tags); if (m < 0) return m; return n + m; }
static void mrcp_sofia_on_session_ready( int status, mrcp_sofia_agent_t *sofia_agent, nua_handle_t *nh, mrcp_sofia_session_t *sofia_session, sip_t const *sip, tagi_t tags[]) { const char *local_sdp_str = NULL, *remote_sdp_str = NULL; mrcp_session_descriptor_t *descriptor = NULL; tl_gets(tags, SOATAG_LOCAL_SDP_STR_REF(local_sdp_str), SOATAG_REMOTE_SDP_STR_REF(remote_sdp_str), TAG_END()); if(remote_sdp_str) { sdp_parser_t *parser = NULL; sdp_session_t *sdp = NULL; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remote SDP\n%s", remote_sdp_str); parser = sdp_parse(sofia_session->home,remote_sdp_str,(int)strlen(remote_sdp_str),0); sdp = sdp_session(parser); descriptor = mrcp_descriptor_generate_by_sdp_session(sdp,sofia_session->session->pool); sdp_parser_free(parser); } mrcp_session_answer(sofia_session->session,descriptor); }
static void mrcp_sofia_on_state_change( int status, mrcp_sofia_agent_t *sofia_agent, nua_handle_t *nh, mrcp_sofia_session_t *sofia_session, sip_t const *sip, tagi_t tags[]) { int nua_state = nua_callstate_init; tl_gets(tags, NUTAG_CALLSTATE_REF(nua_state), TAG_END()); if(!sofia_session || !sofia_session->session) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"SIP Call State [%s]", nua_callstate_name(nua_state)); return; } apt_obj_log(APT_LOG_MARK,APT_PRIO_NOTICE,sofia_session->session->log_obj,"SIP Call State %s [%s]", sofia_session->session->name, nua_callstate_name(nua_state)); switch(nua_state) { case nua_callstate_ready: mrcp_sofia_on_session_ready(status,sofia_agent,nh,sofia_session,sip,tags); break; case nua_callstate_terminated: mrcp_sofia_on_session_terminate(status,sofia_agent,nh,sofia_session,sip,tags); break; } sofia_session->nua_state = nua_state; }
/**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 event view for notifier */ static nea_event_t *nh_notifier_event(nua_handle_t *nh, su_home_t *home, sip_event_t const *event, tagi_t const *tags) { nea_event_t *ev = nea_event_get(nh->nh_notifier, event->o_type); sip_accept_t const *accept = NULL; char const *accept_s = NULL; sip_content_type_t const *ct = NULL; char const *ct_s = NULL; if (ev == NULL) { char *o_type, *o_subtype; char *temp = NULL; o_type = su_strdup(home, event->o_type); if (o_type == NULL) return NULL; o_subtype = strchr(o_type, '.'); if (o_subtype) *o_subtype++ = '\0'; tl_gets(tags, SIPTAG_ACCEPT_REF(accept), SIPTAG_ACCEPT_STR_REF(accept_s), SIPTAG_CONTENT_TYPE_REF(ct), SIPTAG_CONTENT_TYPE_STR_REF(ct_s), TAG_END()); /* * XXX - We really should build accept header when we add new content * types */ if (accept_s == NULL && accept) accept_s = temp = sip_header_as_string(home, (sip_header_t *)accept); if (accept_s == NULL && ct) accept_s = ct->c_type; if (accept_s == NULL && ct_s) accept_s = ct_s; ev = nea_event_create(nh->nh_notifier, authorize_watcher, nh, o_type, o_subtype, ct ? ct->c_type : ct_s, accept_s); su_free(home, temp); su_free(home, o_type); } return ev; }
/**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; }
static void mrcp_sofia_on_call_receive(mrcp_sofia_agent_t *sofia_agent, nua_handle_t *nh, mrcp_sofia_session_t *sofia_session, sip_t const *sip, tagi_t tags[]) { apt_bool_t status = FALSE; const char *remote_sdp_str = NULL; mrcp_session_descriptor_t *descriptor; if(!sofia_session) { sofia_session = mrcp_sofia_session_create(sofia_agent,nh); if(!sofia_session) { nua_respond(nh, SIP_488_NOT_ACCEPTABLE, TAG_END()); return; } } descriptor = mrcp_session_descriptor_create(sofia_session->session->pool); tl_gets(tags, SOATAG_REMOTE_SDP_STR_REF(remote_sdp_str), TAG_END()); if(remote_sdp_str) { sdp_parser_t *parser = NULL; sdp_session_t *sdp = NULL; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remote SDP "APT_NAMESID_FMT"\n%s", sofia_session->session->name, MRCP_SESSION_SID(sofia_session->session), remote_sdp_str); parser = sdp_parse(sofia_session->home,remote_sdp_str,(int)strlen(remote_sdp_str),0); sdp = sdp_session(parser); status = mrcp_descriptor_generate_by_sdp_session(descriptor,sdp,NULL,sofia_session->session->pool); sdp_parser_free(parser); } if(status == FALSE) { nua_respond(nh, SIP_400_BAD_REQUEST, TAG_END()); return; } mrcp_session_offer(sofia_session->session,descriptor); }
static void mrcp_sofia_on_call_receive(mrcp_sofia_agent_t *sofia_agent, nua_handle_t *nh, mrcp_sofia_session_t *sofia_session, sip_t const *sip, tagi_t tags[]) { int offer_recv = 0, answer_recv = 0, offer_sent = 0, answer_sent = 0; const char *local_sdp_str = NULL, *remote_sdp_str = NULL; mrcp_session_descriptor_t *descriptor = NULL; tl_gets(tags, NUTAG_OFFER_RECV_REF(offer_recv), NUTAG_ANSWER_RECV_REF(answer_recv), NUTAG_OFFER_SENT_REF(offer_sent), NUTAG_ANSWER_SENT_REF(answer_sent), SOATAG_LOCAL_SDP_STR_REF(local_sdp_str), SOATAG_REMOTE_SDP_STR_REF(remote_sdp_str), TAG_END()); if(!sofia_session) { sofia_session = mrcp_sofia_session_create(sofia_agent,nh); if(!sofia_session) { nua_respond(nh, SIP_488_NOT_ACCEPTABLE, TAG_END()); return; } } if(remote_sdp_str) { sdp_parser_t *parser = NULL; sdp_session_t *sdp = NULL; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remote SDP\n%s", remote_sdp_str); parser = sdp_parse(sofia_session->home,remote_sdp_str,(int)strlen(remote_sdp_str),0); sdp = sdp_session(parser); descriptor = mrcp_descriptor_generate_by_sdp_session(sdp,NULL,sofia_session->session->pool); sdp_parser_free(parser); } if(!descriptor) { nua_respond(nh, SIP_400_BAD_REQUEST, TAG_END()); return; } mrcp_session_offer(sofia_session->session,descriptor); }
int nth_site_set_params(nth_site_t *site, tag_type_t tag, tag_value_t value, ...) { int n; ta_list ta; server_t *server; int master; msg_mclass_t const *mclass; int mflags; auth_mod_t *am; if (site == NULL) return (errno = EINVAL), -1; server = site->site_server; master = site == server->srv_sites; am = site->site_auth; mclass = server->srv_mclass; mflags = server->srv_mflags; ta_start(ta, tag, value); n = tl_gets(ta_args(ta), TAG_IF(master, NTHTAG_MCLASS_REF(mclass)), TAG_IF(master, NTHTAG_MFLAGS_REF(mflags)), NTHTAG_AUTH_MODULE_REF(am), TAG_END()); if (n > 0) { if (mclass) server->srv_mclass = mclass; else server->srv_mclass = http_default_mclass(); server->srv_mflags = mflags; auth_mod_ref(am), auth_mod_unref(site->site_auth), site->site_auth = am; } ta_end(ta); return n; }
static int tport_http_connect_init_primary(tport_primary_t *pri, tp_name_t tpn[1], su_addrinfo_t *ai, tagi_t const *tags, char const **return_culprit) { tport_http_connect_t *thc = (tport_http_connect_t *)pri; char const *http_connect = NULL; url_t *http_proxy; int error; char const *host, *port; su_addrinfo_t hints[1]; tl_gets(tags, TPTAG_HTTP_CONNECT_REF(http_connect), TAG_END()); if (!http_connect) return *return_culprit = "missing proxy url", -1; http_proxy = url_hdup(pri->pri_home, URL_STRING_MAKE(http_connect)->us_url); if (!http_proxy || !http_proxy->url_host) return *return_culprit = "invalid proxy url", -1; host = http_proxy->url_host; port = http_proxy->url_port; if (!port || !port[0]) port = "8080"; memcpy(hints, ai, sizeof hints); hints->ai_flags = 0; hints->ai_addr = NULL; hints->ai_addrlen = 0; hints->ai_next = NULL; hints->ai_canonname = NULL; error = su_getaddrinfo(host, port, hints, &thc->thc_proxy); if (error) return *return_culprit = "su_getaddrinfo", -1; return tport_tcp_init_client(pri, tpn, ai, tags, return_culprit); }
void nua_stack_authorize(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { nea_sub_t *sub = NULL; int state = nea_extended; tl_gets(tags, NEATAG_SUB_REF(sub), NUTAG_SUBSTATE_REF(state), TAG_END()); if (sub && state > 0) { nea_sub_auth(sub, (nea_state_t)state, TAG_NEXT(tags)); nua_stack_event(nua, nh, NULL, e, SIP_200_OK, NULL); } else { nua_stack_event(nua, nh, NULL, e, NUA_ERROR_AT(__FILE__, __LINE__), NULL); } }
static void mrcp_sofia_on_session_ready( int status, mrcp_sofia_agent_t *sofia_agent, nua_handle_t *nh, mrcp_sofia_session_t *sofia_session, sip_t const *sip, tagi_t tags[]) { mrcp_session_t *session = sofia_session->session; if(session) { const char *local_sdp_str = NULL, *remote_sdp_str = NULL; mrcp_session_descriptor_t *descriptor = NULL; tl_gets(tags, SOATAG_LOCAL_SDP_STR_REF(local_sdp_str), SOATAG_REMOTE_SDP_STR_REF(remote_sdp_str), TAG_END()); if(remote_sdp_str) { sdp_parser_t *parser = NULL; sdp_session_t *sdp = NULL; const char *force_destination_ip = NULL; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remote SDP "APT_NAMESID_FMT"\n%s", session->name, MRCP_SESSION_SID(session), remote_sdp_str); parser = sdp_parse(sofia_session->home,remote_sdp_str,(int)strlen(remote_sdp_str),0); sdp = sdp_session(parser); if(sofia_session->sip_settings->force_destination == TRUE) { force_destination_ip = sofia_session->sip_settings->server_ip; } descriptor = mrcp_descriptor_generate_by_sdp_session(sdp,force_destination_ip,session->pool); sdp_parser_free(parser); } mrcp_session_answer(session,descriptor); } }
/** @internal Terminate notifier. */ void nua_stack_terminate(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { sip_event_t const *event = NULL; sip_content_type_t const *ct = NULL; sip_payload_t const *pl = NULL; char const *event_s = NULL, *ct_s = NULL, *pl_s = NULL; nea_event_t *nev = NULL; if (nh->nh_notifier == NULL) { UA_EVENT2(e, 900, "No event server to terminate"); return; } tl_gets(tags, SIPTAG_EVENT_REF(event), SIPTAG_EVENT_STR_REF(event_s), SIPTAG_CONTENT_TYPE_REF(ct), SIPTAG_CONTENT_TYPE_STR_REF(ct_s), SIPTAG_PAYLOAD_REF(pl), SIPTAG_PAYLOAD_STR_REF(pl_s), TAG_END()); nev = nea_event_get(nh->nh_notifier, event ? event->o_type : event_s); if (nev && (pl || pl_s) && (ct || ct_s)) { nea_server_update(nh->nh_notifier, nev, TAG_NEXT(tags)); } nh_notifier_shutdown(nh, NULL, NEATAG_REASON("noresource"), TAG_NEXT(tags)); nua_stack_event(nua, nh, NULL, e, SIP_200_OK, NULL); }
void nua_stack_notifier(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { su_home_t home[1] = { SU_HOME_INIT(home) }; sip_event_t const *event = NULL; sip_content_type_t const *ct = NULL; sip_payload_t const *pl = NULL; url_string_t const *url = NULL; char const *event_s = NULL, *ct_s = NULL, *pl_s = NULL; nea_event_t *ev; int status = 900; char const *phrase = nua_internal_error; nua_stack_init_handle(nua, nh, tags); tl_gets(tags, NUTAG_URL_REF(url), SIPTAG_EVENT_REF(event), SIPTAG_EVENT_STR_REF(event_s), SIPTAG_CONTENT_TYPE_STR_REF(ct_s), SIPTAG_PAYLOAD_REF(pl), SIPTAG_PAYLOAD_STR_REF(pl_s), TAG_END()); if (!event && !event_s) status = 400, phrase = "Missing Event"; else if (!ct && !ct_s) status = 400, phrase = "Missing Content-Type"; else if (!nh->nh_notifier && !(nh->nh_notifier = nea_server_create(nua->nua_nta, nua->nua_root, url->us_url, NH_PGET(nh, max_subscriptions), NULL, nh, TAG_NEXT(tags)))) status = 900, phrase = nua_internal_error; else if (!event && !(event = sip_event_make(home, event_s))) status = 900, phrase = "Could not create an event header"; else if (!(ev = nh_notifier_event(nh, home, event, tags))) status = 900, phrase = "Could not create an event view"; else if (nea_server_update(nh->nh_notifier, ev, TAG_NEXT(tags)) < 0) status = 900, phrase = "No content for event"; else if (nea_server_notify(nh->nh_notifier, ev) < 0) status = 900, phrase = "Error when notifying watchers"; else nua_stack_tevent(nua, nh, NULL, e, status = SIP_200_OK, SIPTAG_EVENT(event), SIPTAG_CONTENT_TYPE(ct), TAG_END()); if (status != 200) nua_stack_event(nua, nh, NULL, e, status, phrase, NULL); su_home_deinit(home); }
server_t *server_create(url_t const *url, tag_type_t tag, tag_value_t value, ...) { server_t *srv; msg_mclass_t const *mclass = NULL; tp_name_t tpn[1] = {{ NULL }}; su_root_t *root = NULL; http_server_t const *server = NULL; int persistent = 0; char const *server_str = SERVER_VERSION; ta_list ta; ta_start(ta, tag, value); tl_gets(ta_args(ta), NTHTAG_ROOT_REF(root), NTHTAG_MCLASS_REF(mclass), TPTAG_REUSE_REF(persistent), HTTPTAG_SERVER_REF(server), HTTPTAG_SERVER_STR_REF(server_str), TAG_END()); if (!root || !url || (url->url_type != url_http && url->url_type != url_https) || !(srv = su_home_new(sizeof(*srv)))) { ta_end(ta); return NULL; } tpn->tpn_proto = url_tport_default((enum url_type_e)url->url_type); tpn->tpn_canon = url->url_host; tpn->tpn_host = url->url_host; tpn->tpn_port = url_port(url); srv->srv_tports = tport_tcreate(srv, nth_server_class, root, TPTAG_IDLE(600000), TPTAG_TIMEOUT(300000), ta_tags(ta)); srv->srv_persistent = persistent; srv->srv_max_bodylen = 1 << 30; /* 1 GB */ if (tport_tbind(srv->srv_tports, tpn, http_tports, TAG_END()) >= 0 || tport_tbind(srv->srv_tports, tpn, http_no_tls_tports, TAG_END()) >= 0) { srv->srv_root = root; srv->srv_mclass = mclass ? mclass : http_default_mclass(); srv->srv_mflags = MSG_DO_CANONIC; if (server) srv->srv_server = http_server_dup(srv->srv_home, server); else srv->srv_server = http_server_make(srv->srv_home, server_str); tport_get_params(srv->srv_tports, TPTAG_QUEUESIZE_REF(srv->srv_queuesize), TAG_END()); } else { SU_DEBUG_1(("nth_server_create: cannot bind transports " URL_FORMAT_STRING "\n", URL_PRINT_ARGS(url))); server_destroy(srv), srv = NULL; } ta_end(ta); return srv; }
int tport_udp_init_primary(tport_primary_t *pri, tp_name_t tpn[1], su_addrinfo_t *ai, tagi_t const *tags, char const **return_culprit) { unsigned rmem = 0, wmem = 0; int events = SU_WAIT_IN; int s; #if HAVE_IP_ADD_MEMBERSHIP su_sockaddr_t *su = (su_sockaddr_t *)ai->ai_addr; #endif int const one = 1; (void)one; s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s == INVALID_SOCKET) return *return_culprit = "socket", -1; pri->pri_primary->tp_socket = s; if (tport_bind_socket(s, ai, return_culprit) < 0) return -1; tport_set_tos(s, ai, pri->pri_params->tpp_tos); #if HAVE_IP_ADD_MEMBERSHIP if (ai->ai_family == AF_INET && IN_MULTICAST(ntohl(su->su_sin.sin_addr.s_addr))) { /* Try to join to the multicast group */ /* Bind to the SIP address like <sip:88.77.66.55:5060;maddr=224.0.1.75;transport=udp> */ struct ip_mreq imr[1]; struct in_addr iface; memset(imr, 0, sizeof imr); imr->imr_multiaddr = su->su_sin.sin_addr; if (host_is_ip4_address(tpn->tpn_canon) && su_inet_pton(AF_INET, tpn->tpn_canon, &iface) > 0) { imr->imr_interface = iface; } if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, imr, (sizeof imr)) < 0) { SU_DEBUG_3(("setsockopt(%s): %s\n", "IP_ADD_MEMBERSHIP", su_strerror(su_errno()))); } #if HAVE_IP_MULTICAST_LOOP else if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof one) < 0) { SU_DEBUG_3(("setsockopt(%s): %s\n", "IP_MULTICAST_LOOP", su_strerror(su_errno()))); } #endif } #endif #if HAVE_IP_MTU_DISCOVER { /* Turn off DF flag on Linux */ int dont = IP_PMTUDISC_DONT; if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &dont, sizeof(dont)) < 0) { SU_DEBUG_3(("setsockopt(%s): %s\n", "IP_MTU_DISCOVER", su_strerror(su_errno()))); } } #endif #if HAVE_IP_RECVERR if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { if (setsockopt(s, IPPROTO_IP, IP_RECVERR, &one, sizeof(one)) < 0) { if (ai->ai_family == AF_INET) SU_DEBUG_3(("setsockopt(%s): %s\n", "IPVRECVERR", su_strerror(su_errno()))); } events |= SU_WAIT_ERR; } #endif #if HAVE_IPV6_RECVERR if (ai->ai_family == AF_INET6) { if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVERR, &one, sizeof(one)) < 0) SU_DEBUG_3(("setsockopt(IPV6_RECVERR): %s\n", su_strerror(su_errno()))); events |= SU_WAIT_ERR; } #endif tl_gets(tags, TPTAG_UDP_RMEM_REF(rmem), TPTAG_UDP_WMEM_REF(wmem), TAG_END()); if (rmem != 0 && #if HAVE_SO_RCVBUFFORCE setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void *)&rmem, sizeof rmem) < 0 && #endif setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void *)&rmem, sizeof rmem) < 0) { SU_DEBUG_3(("setsockopt(SO_RCVBUF): %s\n", su_strerror(su_errno()))); } if (wmem != 0 && #if HAVE_SO_SNDBUFFORCE setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void *)&wmem, sizeof wmem) < 0 && #endif setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void *)&wmem, sizeof wmem) < 0) { SU_DEBUG_3(("setsockopt(SO_SNDBUF): %s\n", su_strerror(su_errno()))); } pri->pri_primary->tp_events = events; tport_init_compressor(pri->pri_primary, tpn->tpn_comp, tags); tport_check_trunc(pri->pri_primary, ai); #if HAVE_SOFIA_STUN tport_stun_server_add_socket(pri->pri_primary); #endif return 0; }
/**Initialize an authentication module instance. * * The function auth_mod_init_default() initializes an authentication module * object used to authenticate the requests. * * @param am * @param base * @param root * @param tag,value,... tagged argument list * * @TAGS * AUTHTAG_REALM(), AUTHTAG_OPAQUE(), AUTHTAG_DB(), AUTHTAG_QOP(), * AUTHTAG_ALGORITHM(), AUTHTAG_EXPIRES(), AUTHTAG_NEXT_EXPIRES(), * AUTHTAG_BLACKLIST(), AUTHTAG_FORBIDDEN(), AUTHTAG_ANONYMOUS(), * AUTHTAG_FAKE(), AUTHTAG_ALLOW(), AUTHTAG_REMOTE(), and * AUTHTAG_MASTER_KEY(). * * @return 0 if successful * @return -1 upon an error */ int auth_init_default(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...) { int retval = 0; ta_list ta; char const *realm = NULL, *opaque = NULL, *db = NULL, *allows = NULL; char const *qop = NULL, *algorithm = NULL; unsigned expires = 60 * 60, next_expires = 5 * 60; unsigned max_ncount = 0; unsigned blacklist = 5; int forbidden = 0; int anonymous = 0; int fake = 0; url_string_t const *remote = NULL; char const *master_key = "fish"; char *s; ta_start(ta, tag, value); /* Authentication stuff */ tl_gets(ta_args(ta), AUTHTAG_REALM_REF(realm), AUTHTAG_OPAQUE_REF(opaque), AUTHTAG_DB_REF(db), AUTHTAG_QOP_REF(qop), AUTHTAG_ALGORITHM_REF(algorithm), AUTHTAG_EXPIRES_REF(expires), AUTHTAG_NEXT_EXPIRES_REF(next_expires), AUTHTAG_MAX_NCOUNT_REF(max_ncount), AUTHTAG_BLACKLIST_REF(blacklist), AUTHTAG_FORBIDDEN_REF(forbidden), AUTHTAG_ANONYMOUS_REF(anonymous), AUTHTAG_FAKE_REF(fake), AUTHTAG_ALLOW_REF(allows), AUTHTAG_REMOTE_REF(remote), AUTHTAG_MASTER_KEY_REF(master_key), TAG_NULL()); if (!realm) realm = "*"; if (!allows) allows = "ACK, BYE, CANCEL"; am->am_realm = su_strdup(am->am_home, realm); am->am_opaque = su_strdup(am->am_home, opaque); am->am_db = su_strdup(am->am_home, db); s = su_strdup(am->am_home, allows); if (s) msg_commalist_d(am->am_home, &s, &am->am_allow, NULL); am->am_expires = expires; am->am_next_exp = next_expires; am->am_max_ncount = max_ncount; am->am_blacklist = blacklist; am->am_forbidden = forbidden; am->am_anonymous = anonymous; am->am_fake = fake; am->am_remote = url_hdup(am->am_home, (url_t *)remote); am->am_algorithm = algorithm ? su_strdup(am->am_home, algorithm) : "MD5"; am->am_nextnonce = !algorithm || su_casematch(algorithm, "MD5"); if (next_expires == 0) am->am_nextnonce = 0; am->am_qop = su_strdup(am->am_home, qop); if (master_key) { su_md5_t md5[1]; su_md5_init(md5); su_md5_strupdate(md5, master_key); su_md5_strupdate(md5, "70P 53KR37"); su_md5_digest(md5, am->am_master_key); } auth_md5_hmac_key(am); /* Make sure that we have something that can be used to identify credentials */ if (am->am_opaque && strcmp(am->am_opaque, "*") == 0) { #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 255 #endif char hostname[HOST_NAME_MAX + 1]; su_md5_t md5[1]; uint8_t hmac[6]; gethostname(hostname, sizeof hostname); auth_md5_hmac_init(am, md5); su_md5_strupdate(md5, hostname); su_md5_update(md5, ":", 1); if (am->am_remote) url_update(md5, am->am_remote); auth_md5_hmac_digest(am, md5, hmac, sizeof hmac); base64_e(hostname, sizeof hostname, hmac, sizeof hmac); am->am_opaque = su_strdup(am->am_home, hostname); if (!am->am_opaque) { retval = -1; SU_DEBUG_1(("%s: cannot create unique identifier\n", __func__)); } } if (retval < 0) ; else if (db) { retval = auth_readdb(am); if (retval == -1) { int err = errno; SU_DEBUG_1(("auth-module: %s: %s\n", am->am_db, strerror(err))); errno = err; } } else { retval = auth_htable_resize(am->am_home, am->am_users, 0); } ta_end(ta); return retval; }
/** Initialize logging. */ int tport_open_log(tport_master_t *mr, tagi_t *tags) { int n; int log_msg = mr->mr_log != 0; char const *dump = NULL; char const *capt = NULL;; if(mr->mr_capt_name) capt = mr->mr_capt_name; n = tl_gets(tags, TPTAG_LOG_REF(log_msg), TPTAG_DUMP_REF(dump), TPTAG_CAPT_REF(capt), TAG_END()); if (getenv("MSG_STREAM_LOG") != NULL || getenv("TPORT_LOG") != NULL) log_msg = 1; mr->mr_log = log_msg ? MSG_DO_EXTRACT_COPY : 0; if (getenv("TPORT_CAPT")) capt = getenv("TPORT_CAPT"); if (getenv("MSG_DUMP")) dump = getenv("MSG_DUMP"); if (getenv("TPORT_DUMP")) dump = getenv("TPORT_DUMP"); if(capt) { char *captname, *p, *host_s; char port[10]; su_addrinfo_t *ai = NULL, hints[1] = {{ 0 }}; unsigned len =0; if (mr->mr_capt_name && mr->mr_capt_sock && strcmp(capt, mr->mr_capt_name) == 0) return n; captname = su_strdup(mr->mr_home, capt); if (captname == NULL) return n; if(strncmp(captname, "udp:",4) != 0) { su_log("tport_open_log: capturing. Only udp protocol supported [%s]\n", captname); return n; } /* separate proto and host */ p = captname+4; if( (*(p)) == '\0') { su_log("malformed ip address\n"); return n; } host_s = p; if( (p = strrchr(p+1, ':')) == 0 ) { su_log("no host or port specified\n"); return n; } /*the address contains a port number*/ *p = '\0'; p++; if (atoi(p) <1024 || atoi(p)>65536) { su_log("invalid port number; must be in [1024,65536]\n"); return n; } strncpy(port, p, sizeof(port)); *p = '\0'; /* check if we have [] */ if (host_s[0] == '[') { len = strlen(host_s + 1) - 1; if(host_s[len+1] != ']') { su_log("bracket not closed\n"); return n; } memmove(host_s, host_s + 1, len); host_s[len] = '\0'; } /* and again */ captname = su_strdup(mr->mr_home, capt); if (captname == NULL) return n; su_free(mr->mr_home, mr->mr_capt_name); mr->mr_capt_name = captname; if (mr->mr_capt_sock) su_close(mr->mr_capt_sock), mr->mr_capt_sock = 0; /* HINTS && getaddrinfo */ hints->ai_flags = AI_NUMERICSERV; hints->ai_family = AF_UNSPEC; hints->ai_socktype = SOCK_DGRAM; hints->ai_protocol = IPPROTO_UDP; if (su_getaddrinfo(host_s, port, hints, &ai)) { su_perror("capture: su_getaddrinfo()"); return n; } mr->mr_capt_sock = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (mr->mr_capt_sock == INVALID_SOCKET) { su_perror("capture: invalid socket"); return n; } su_setblocking(mr->mr_capt_sock, 0); /* Don't block */ if (connect(mr->mr_capt_sock, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == -1) { if (errno != EINPROGRESS) { su_perror("capture: socket connect"); return n; } } su_freeaddrinfo(ai); } else if(mr->mr_capt_sock) { /* close capture server*/ su_close(mr->mr_capt_sock); mr->mr_capt_sock = 0; } if (dump) { time_t now; char *dumpname; if (mr->mr_dump && strcmp(dump, mr->mr_dump) == 0) return n; dumpname = su_strdup(mr->mr_home, dump); if (dumpname == NULL) return n; su_free(mr->mr_home, mr->mr_dump); mr->mr_dump = dumpname; if (mr->mr_dump_file && mr->mr_dump_file != stdout) fclose(mr->mr_dump_file), mr->mr_dump_file = NULL; if (strcmp(dumpname, "-")) mr->mr_dump_file = fopen(dumpname, "ab"); /* XXX */ else mr->mr_dump_file = stdout; if (mr->mr_dump_file) { time(&now); fprintf(mr->mr_dump_file, "dump started at %s\n\n", ctime(&now)); } } return n; }
static int tport_ws_init_primary_secure(tport_primary_t *pri, tp_name_t tpn[1], su_addrinfo_t *ai, tagi_t const *tags, char const **return_culprit) { tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri; const char *cert = "/ssl.pem"; const char *key = "/ssl.pem"; char *homedir; char *tbf = NULL; su_home_t autohome[SU_HOME_AUTO_SIZE(1024)]; char const *path = NULL; int ret = -1; su_home_auto(autohome, sizeof autohome); tl_gets(tags, TPTAG_CERTIFICATE_REF(path), TAG_END()); if (!path) { homedir = getenv("HOME"); if (!homedir) homedir = ""; path = tbf = su_sprintf(autohome, "%s/.sip/auth", homedir); } if (path) { key = su_sprintf(autohome, "%s/%s", path, "wss.key"); if (access(key, R_OK) != 0) key = NULL; cert = su_sprintf(autohome, "%s/%s", path, "wss.crt"); if (access(cert, R_OK) != 0) cert = NULL; if ( !key ) key = su_sprintf(autohome, "%s/%s", path, "wss.pem"); if ( !cert ) cert = su_sprintf(autohome, "%s/%s", path, "wss.pem"); if (access(key, R_OK) != 0) key = NULL; if (access(cert, R_OK) != 0) cert = NULL; } init_ssl(); // OpenSSL_add_all_algorithms(); /* load & register cryptos */ // SSL_load_error_strings(); /* load all error messages */ wspri->ssl_method = SSLv23_server_method(); /* create server instance */ wspri->ssl_ctx = SSL_CTX_new((SSL_METHOD *)wspri->ssl_method); /* create context */ SSL_CTX_sess_set_remove_cb(wspri->ssl_ctx, NULL); wspri->ws_secure = 1; if ( !wspri->ssl_ctx ) goto done; /* set the local certificate from CertFile */ SSL_CTX_use_certificate_file(wspri->ssl_ctx, cert, SSL_FILETYPE_PEM); /* set the private key from KeyFile */ SSL_CTX_use_PrivateKey_file(wspri->ssl_ctx, key, SSL_FILETYPE_PEM); /* verify private key */ if ( !SSL_CTX_check_private_key(wspri->ssl_ctx) ) { goto done; } SSL_CTX_set_cipher_list(wspri->ssl_ctx, "HIGH:!DSS:!aNULL@STRENGTH"); ret = tport_ws_init_primary(pri, tpn, ai, tags, return_culprit); done: su_home_zap(autohome); return ret; }
int test_events(struct context *ctx) { BEGIN(); struct endpoint *a = &ctx->a, *b = &ctx->b; struct call *a_call = a->call, *b_call = b->call; struct event *e, *en, *es; sip_t const *sip; tagi_t const *t, *n_tags, *r_tags; url_t b_url[1]; enum nua_substate substate; nea_sub_t *sub = NULL; char const open[] = "<?xml version='1.0' encoding='UTF-8'?>\n" "<presence xmlns='urn:ietf:params:xml:ns:cpim-pidf' \n" " entity='pres:[email protected]'>\n" " <tuple id='ksac9udshce'>\n" " <status><basic>open</basic></status>\n" " <contact priority='1.0'>sip:[email protected]</contact>\n" " </tuple>\n" "</presence>\n"; char const closed[] = "<?xml version='1.0' encoding='UTF-8'?>\n" "<presence xmlns='urn:ietf:params:xml:ns:cpim-pidf' \n" " entity='pres:[email protected]'>\n" " <tuple id='ksac9udshce'>\n" " <status><basic>closed</basic></status>\n" " </tuple>\n" "</presence>\n"; /* SUBSCRIBE test A B |------SUBSCRIBE---->| |<--------405--------| | | */ if (print_headings) printf("TEST NUA-12.1: SUBSCRIBE without notifier\n"); nua_set_params(b->nua, SIPTAG_ALLOW_EVENTS(NULL), TAG_END()); run_b_until(ctx, nua_r_set_params, until_final_response); TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url), SIPTAG_EVENT_STR("presence"), TAG_END()); run_ab_until(ctx, -1, save_until_final_response, -1, NULL /* XXX save_until_received */); /* Client events: nua_subscribe(), nua_r_subscribe */ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_subscribe); TEST(e->data->e_status, 489); TEST_1(!e->next); #if 0 /* XXX */ /* Server events: nua_i_subscribe */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_subscribe); TEST(e->data->e_status, 405); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence"); TEST_1(!e->next); #endif free_events_in_list(ctx, a->events); free_events_in_list(ctx, b->events); nua_handle_destroy(b_call->nh), b_call->nh = NULL; if (print_headings) printf("TEST NUA-12.1: PASSED\n"); /* ---------------------------------------------------------------------- */ /* SUBSCRIBE test using notifier and establishing subscription A B | | |------SUBSCRIBE---->| |<--------202--------| |<------NOTIFY-------| |-------200 OK------>| | | */ if (print_headings) printf("TEST NUA-12.2: using notifier and establishing subscription\n"); TEST_1(b_call->nh = nua_handle(b->nua, b_call, TAG_END())); *b_url = *b->contact->m_url; NOTIFIER(b, b_call, b_call->nh, NUTAG_URL(b_url), SIPTAG_EVENT_STR("presence"), SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"), SIPTAG_PAYLOAD_STR(closed), NEATAG_THROTTLE(1), TAG_END()); run_b_until(ctx, nua_r_notifier, until_final_response); SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url), SIPTAG_EVENT_STR("presence"), SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"), TAG_END()); run_ab_until(ctx, -1, save_until_notified_and_responded, -1, save_until_received); /* Client events: nua_subscribe(), nua_i_notify/nua_r_subscribe */ TEST_1(en = event_by_type(a->events->head, nua_i_notify)); TEST_1(es = event_by_type(a->events->head, nua_r_subscribe)); TEST_1(e = es); TEST_E(e->data->e_event, nua_r_subscribe); r_tags = e->data->e_tags; TEST_1(tl_find(r_tags, nutag_substate)); if (es->next == en) { TEST_1(200 <= e->data->e_status && e->data->e_status < 300); TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_embryonic); } else { TEST_1(200 <= e->data->e_status && e->data->e_status < 300); TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_active); } TEST_1(e = en); TEST_E(e->data->e_event, nua_i_notify); TEST_1(sip = sip_object(e->data->e_msg)); n_tags = e->data->e_tags; TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence"); TEST_1(sip->sip_content_type); TEST_S(sip->sip_content_type->c_type, "application/pidf+xml"); TEST_1(sip->sip_subscription_state); TEST_S(sip->sip_subscription_state->ss_substate, "active"); TEST_1(sip->sip_subscription_state->ss_expires); TEST_1(tl_find(n_tags, nutag_substate)); TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active); TEST_1(!en->next || !es->next); free_events_in_list(ctx, a->events); /* XXX --- Do not check server side events */ free_events_in_list(ctx, b->events); if (print_headings) printf("TEST NUA-12.2: PASSED\n"); /* ---------------------------------------------------------------------- */ /* NOTIFY with updated content A B | | |<------NOTIFY-------| |-------200 OK------>| | | */ if (print_headings) printf("TEST NUA-12.3: update notifier\n"); /* Update presence data */ NOTIFIER(b, b_call, b_call->nh, SIPTAG_EVENT_STR("presence"), SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"), SIPTAG_PAYLOAD_STR(open), TAG_END()); run_ab_until(ctx, -1, save_until_notified, -1, save_until_received); /* subscriber events: nua_i_notify */ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_notify); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence"); TEST_1(sip->sip_content_type); TEST_S(sip->sip_content_type->c_type, "application/pidf+xml"); TEST_1(sip->sip_subscription_state); TEST_S(sip->sip_subscription_state->ss_substate, "active"); TEST_1(sip->sip_subscription_state->ss_expires); n_tags = e->data->e_tags; TEST_1(tl_find(n_tags, nutag_substate)); TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active); TEST_1(!e->next); free_events_in_list(ctx, a->events); /* XXX --- Do not check server side events */ free_events_in_list(ctx, b->events); if (print_headings) printf("TEST NUA-12.3: PASSED\n"); /* ---------------------------------------------------------------------- */ /* un-SUBSCRIBE A B | | |------SUBSCRIBE---->| |<--------202--------| |<------NOTIFY-------| |-------200 OK------>| | | */ if (print_headings) printf("TEST NUA-12.5: un-SUBSCRIBE\n"); memset(&a->flags, 0, sizeof a->flags); UNSUBSCRIBE(a, a_call, a_call->nh, TAG_END()); run_ab_until(ctx, -1, save_until_notified_and_responded, -1, save_until_subscription); /* Client events: nua_unsubscribe(), nua_i_notify/nua_r_unsubscribe */ TEST_1(e = a->events->head); if (e->data->e_event == nua_i_notify) { TEST_E(e->data->e_event, nua_i_notify); TEST_1(sip = sip_object(e->data->e_msg)); n_tags = e->data->e_tags; TEST_1(sip->sip_event); TEST_1(sip->sip_subscription_state); TEST_S(sip->sip_subscription_state->ss_substate, "terminated"); TEST_1(!sip->sip_subscription_state->ss_expires); TEST_1(tl_find(n_tags, nutag_substate)); TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_unsubscribe); TEST_1(tl_find(e->data->e_tags, nutag_substate)); TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_terminated); } else { TEST_E(e->data->e_event, nua_r_unsubscribe); TEST_1(tl_find(e->data->e_tags, nutag_substate)); /* NOTIFY is no more dropped after successful response to unsubscribe */ TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_active); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify); TEST_1(sip = sip_object(e->data->e_msg)); n_tags = e->data->e_tags; TEST_1(sip->sip_event); TEST_1(sip->sip_subscription_state); TEST_S(sip->sip_subscription_state->ss_substate, "terminated"); TEST_1(!sip->sip_subscription_state->ss_expires); TEST_1(tl_find(n_tags, nutag_substate)); TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated); } TEST_1(!e->next); free_events_in_list(ctx, a->events); /* Server events: nua_i_subscription with terminated status */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_subscription); TEST(tl_gets(e->data->e_tags, NEATAG_SUB_REF(sub), NUTAG_SUBSTATE_REF(substate), TAG_END()), 2); TEST_1(sub); TEST(substate, nua_substate_terminated); TEST_1(!e->next); free_events_in_list(ctx, b->events); if (print_headings) printf("TEST NUA-12.5: PASSED\n"); /* ---------------------------------------------------------------------- */ /* Fetch event, SUBSCRIBE with expires: 0 A B | | |------SUBSCRIBE---->| |<--------202--------| |<------NOTIFY-------| |-------200 OK------>| | | */ if (print_headings) printf("TEST NUA-12.5.1: event fetch\n"); SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url), SIPTAG_EVENT_STR("presence"), SIPTAG_ACCEPT_STR("application/pidf+xml"), SIPTAG_EXPIRES_STR("0"), TAG_END()); run_ab_until(ctx, -1, save_until_notified_and_responded, -1, save_until_subscription); /* Client events: nua_subscribe(), nua_i_notify/nua_r_subscribe */ TEST_1(en = event_by_type(a->events->head, nua_i_notify)); TEST_1(es = event_by_type(a->events->head, nua_r_subscribe)); e = es; TEST_E(e->data->e_event, nua_r_subscribe); TEST_1(t = tl_find(e->data->e_tags, nutag_substate)); TEST_1(t->t_value == nua_substate_pending || t->t_value == nua_substate_terminated || t->t_value == nua_substate_embryonic); e = en; TEST_E(e->data->e_event, nua_i_notify); TEST_1(sip = sip_object(e->data->e_msg)); n_tags = e->data->e_tags; TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence"); TEST_1(sip->sip_content_type); TEST_S(sip->sip_content_type->c_type, "application/pidf+xml"); TEST_1(sip->sip_payload && sip->sip_payload->pl_data); TEST_1(sip->sip_subscription_state); TEST_S(sip->sip_subscription_state->ss_substate, "terminated"); TEST_1(tl_find(n_tags, nutag_substate)); TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated); TEST_1(!en->next || !es->next); free_events_in_list(ctx, a->events); /* Server events: nua_i_subscription */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_subscription); TEST(tl_gets(e->data->e_tags, NEATAG_SUB_REF(sub), TAG_END()), 1); TEST_1(sub); TEST_1(!e->next); free_events_in_list(ctx, b->events); if (print_headings) printf("TEST NUA-12.4.1: PASSED\n"); /* ---------------------------------------------------------------------- */ /* 2nd SUBSCRIBE with event id A B | | |------SUBSCRIBE---->| |<--------202--------| |<------NOTIFY-------| |-------200 OK------>| | | */ /* XXX - we should do this before unsubscribing first one */ if (print_headings) printf("TEST NUA-12.4.2: establishing 2nd subscription\n"); NOTIFIER(b, b_call, b_call->nh, SIPTAG_EVENT_STR("presence"), SIPTAG_CONTENT_TYPE_STR("application/xpidf+xml"), SIPTAG_PAYLOAD_STR(open), NEATAG_THROTTLE(1), NUTAG_SUBSTATE(nua_substate_pending), TAG_END()); run_b_until(ctx, nua_r_notifier, until_final_response); NOTIFIER(b, b_call, b_call->nh, SIPTAG_EVENT_STR("presence"), SIPTAG_CONTENT_TYPE_STR("application/xpidf+xml"), SIPTAG_PAYLOAD_STR(closed), NEATAG_THROTTLE(1), NEATAG_FAKE(1), NUTAG_SUBSTATE(nua_substate_pending), TAG_END()); run_b_until(ctx, nua_r_notifier, until_final_response); SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url), SIPTAG_EVENT_STR("presence;id=1"), SIPTAG_ACCEPT_STR("application/xpidf+xml"), TAG_END()); run_ab_until(ctx, -1, save_until_notified_and_responded, -1, save_until_subscription); /* Client events: nua_subscribe(), nua_i_notify/nua_r_subscribe */ TEST_1(en = event_by_type(a->events->head, nua_i_notify)); TEST_1(es = event_by_type(a->events->head, nua_r_subscribe)); e = es; TEST_E(e->data->e_event, nua_r_subscribe); TEST_1(t = tl_find(e->data->e_tags, nutag_substate)); TEST_1(t->t_value == nua_substate_pending || t->t_value == nua_substate_embryonic); e = en; TEST_E(e->data->e_event, nua_i_notify); TEST_1(sip = sip_object(e->data->e_msg)); n_tags = e->data->e_tags; TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence"); TEST_S(sip->sip_event->o_id, "1"); TEST_1(sip->sip_content_type); TEST_S(sip->sip_content_type->c_type, "application/xpidf+xml"); TEST_1(sip->sip_payload && sip->sip_payload->pl_data); /* Check that we really got "fake" content */ TEST_1(memmem(sip->sip_payload->pl_data, sip->sip_payload->pl_len, "<basic>closed</basic>", strlen("<basic>closed</basic>"))); TEST_1(sip->sip_subscription_state); TEST_S(sip->sip_subscription_state->ss_substate, "pending"); TEST_1(sip->sip_subscription_state->ss_expires); TEST_1(tl_find(n_tags, nutag_substate)); TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_pending); TEST_1(!en->next || !es->next); free_events_in_list(ctx, a->events); /* Server events: nua_i_subscription */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_subscription); TEST(tl_gets(e->data->e_tags, NEATAG_SUB_REF(sub), TAG_END()), 1); TEST_1(sub); TEST_1(!e->next); free_events_in_list(ctx, b->events); /* Authorize user A */ AUTHORIZE(b, b_call, b_call->nh, NUTAG_SUBSTATE(nua_substate_active), NEATAG_SUB(sub), NEATAG_FAKE(0), TAG_END()); run_ab_until(ctx, -1, save_until_notified, -1, save_until_final_response); /* subscriber events: nua_i_notify with NUTAG_SUBSTATE(nua_substate_active) */ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_notify); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence"); TEST_1(sip->sip_content_type); TEST_S(sip->sip_content_type->c_type, "application/xpidf+xml"); TEST_1(sip->sip_payload && sip->sip_payload->pl_data); /* Check that we really got real content */ TEST_1(memmem(sip->sip_payload->pl_data, sip->sip_payload->pl_len, "<basic>open</basic>", strlen("<basic>open</basic>"))); TEST_1(sip->sip_subscription_state); TEST_S(sip->sip_subscription_state->ss_substate, "active"); TEST_1(sip->sip_subscription_state->ss_expires); n_tags = e->data->e_tags; TEST_1(tl_find(n_tags, nutag_substate)); TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active); TEST_1(!e->next); free_events_in_list(ctx, a->events); /* Server events: nua_r_authorize */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_authorize); TEST_1(!e->next); free_events_in_list(ctx, b->events); if (print_headings) printf("TEST NUA-12.4: PASSED\n"); /* ---------------------------------------------------------------------- */ /* NOTIFY terminating subscription A B | | |<------NOTIFY-------| |-------200 OK------>| | | */ if (print_headings) printf("TEST NUA-12.6: terminate notifier\n"); TERMINATE(b, b_call, b_call->nh, TAG_END()); run_ab_until(ctx, -1, save_until_notified, -1, until_final_response); /* Client events: nua_i_notify */ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_notify); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence"); TEST_S(sip->sip_event->o_id, "1"); TEST_1(sip->sip_subscription_state); TEST_S(sip->sip_subscription_state->ss_substate, "terminated"); TEST_1(!sip->sip_subscription_state->ss_expires); n_tags = e->data->e_tags; TEST_1(tl_find(n_tags, nutag_substate)); TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated); TEST_1(!e->next); free_events_in_list(ctx, a->events); if (print_headings) printf("TEST NUA-12.6: PASSED\n"); /* ---------------------------------------------------------------------- */ nua_handle_destroy(a_call->nh), a_call->nh = NULL; nua_handle_destroy(b_call->nh), b_call->nh = NULL; END(); /* test_events */ }