/**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;
}
/** 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;
}
Exemple #4
0
/** 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;
}
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;
}
/**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;
  
}
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;
}
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;
}
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;
}
Exemple #10
0
/*# 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;
}
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;
}
/**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;
}
Exemple #13
0
/** @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;
}
/** 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;
}
Exemple #15
0
/** @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);
}
Exemple #16
0
/** 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;
}
Exemple #17
0
/** 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;
}
Exemple #18
0
/**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;
}
Exemple #19
0
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;
}
Exemple #21
0
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;
}
static struct event *
subscription_by_nua(nua_handle_t *nh,
                    enum nua_substate current,
                    tag_type_t tag, tag_value_t value, ...)
{
    struct message *subscribe;
    struct event *notify, *event;
    ta_list ta;
    enum nua_substate substate = nua_substate_active;
    char const *substate_str = subscription_state;
    char const *expires = "600";

    subscribe = s2_sip_wait_for_request(SIP_METHOD_SUBSCRIBE);
    if (event_type)
        fail_if(!subscribe->sip->sip_event ||
                strcmp(event_type, subscribe->sip->sip_event->o_type));

    if (subscribe->sip->sip_expires && subscribe->sip->sip_expires->ex_delta == 0) {
        substate = nua_substate_terminated;
        substate_str = "terminated;reason=timeout";
        expires = "0";
    }

    ta_start(ta, tag, value);

    if (send_notify_before_response) {
        s2_sip_save_uas_dialog(dialog, subscribe->sip);
        notify = notify_to_nua(substate,
                               SIPTAG_EVENT(subscribe->sip->sip_event),
                               SIPTAG_SUBSCRIPTION_STATE_STR(substate_str),
                               ta_tags(ta));
        event = respond_to_subscribe(subscribe, nua_r_subscribe, substate,
                                     SIP_200_OK,
                                     SIPTAG_EXPIRES_STR(expires),
                                     TAG_END());
        s2_free_event(event);
    }
    else {
        event = respond_to_subscribe(subscribe, nua_r_subscribe, current,
                                     SIP_202_ACCEPTED,
                                     SIPTAG_EXPIRES_STR(expires),
                                     TAG_END());
        s2_free_event(event);
        notify = notify_to_nua(substate,
                               SIPTAG_EVENT(subscribe->sip->sip_event),
                               SIPTAG_SUBSCRIPTION_STATE_STR(substate_str),
                               ta_tags(ta));
    }

    s2_sip_free_message(subscribe);

    return notify;
}
/**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;
}
Exemple #24
0
/** 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;
}
Exemple #25
0
/**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;
}
Exemple #27
0
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);
}
Exemple #30
0
/**@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;
}