static void mrcp_sofia_on_resource_discover(mrcp_sofia_agent_t   *sofia_agent,
									        nua_handle_t         *nh,
									        mrcp_sofia_session_t *sofia_session,
									        sip_t const          *sip,
									        tagi_t                tags[])
{
	char sdp_str[2048];
	const char *local_sdp_str = NULL;

	const char *ip = sofia_agent->config->ext_ip ? 
		sofia_agent->config->ext_ip : sofia_agent->config->local_ip;

	if(sdp_resource_discovery_string_generate(ip,sofia_agent->config->origin,sdp_str,sizeof(sdp_str)) > 0) {
		local_sdp_str = sdp_str;
		apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Resource Discovery SDP\n[%s]\n", 
				local_sdp_str);
	}

	nua_respond(nh, SIP_200_OK, 
				NUTAG_WITH_CURRENT(sofia_agent->nua),
				TAG_IF(sofia_agent->sip_contact_str,SIPTAG_CONTACT_STR(sofia_agent->sip_contact_str)),
				TAG_IF(local_sdp_str,SOATAG_USER_SDP_STR(local_sdp_str)),
				SOATAG_AUDIO_AUX("telephone-event"),
				TAG_END());
}
Example #2
0
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;
}
static void mrcp_sofia_task_initialize(apt_task_t *task)
{
	mrcp_sofia_agent_t *sofia_agent = apt_task_object_get(task);
	mrcp_sofia_client_config_t *sofia_config = sofia_agent->config;

	/* Initialize Sofia-SIP library and create event loop */
	su_init();
	sofia_agent->root = su_root_create(NULL);

	/* Create a user agent instance. The stack will call the 'event_callback()' 
	 * callback when events such as succesful registration to network, 
	 * an incoming call, etc, occur. 
	 */
	sofia_agent->nua = nua_create(
					sofia_agent->root,         /* Event loop */
					mrcp_sofia_event_callback, /* Callback for processing events */
					sofia_agent,               /* Additional data to pass to callback */
					NUTAG_URL(sofia_agent->sip_bind_str), /* Address to bind to */
					TAG_END());                /* Last tag should always finish the sequence */
	if(sofia_agent->nua) {
		nua_set_params(
					sofia_agent->nua,
					NUTAG_AUTOANSWER(0),
					NUTAG_APPL_METHOD("OPTIONS"),
					TAG_IF(sofia_config->sip_t1,NTATAG_SIP_T1(sofia_config->sip_t1)),
					TAG_IF(sofia_config->sip_t2,NTATAG_SIP_T2(sofia_config->sip_t2)),
					TAG_IF(sofia_config->sip_t4,NTATAG_SIP_T4(sofia_config->sip_t4)),
					TAG_IF(sofia_config->sip_t1x64,NTATAG_SIP_T1X64(sofia_config->sip_t1x64)),
					SIPTAG_USER_AGENT_STR(sofia_config->user_agent_name),
					TAG_END());
	}
}
Example #4
0
static
int nua_publish_client_request(nua_client_request_t *cr,
			       msg_t *msg, sip_t *sip,
			       tagi_t const *tags)
{
  nua_dialog_usage_t *du = cr->cr_usage;
  int un, done;
  sip_etag_t const *etag = NULL;

  un = cr->cr_terminating ||
    cr->cr_event != nua_r_publish ||
    (du && du->du_shutdown) ||
    (sip->sip_expires && sip->sip_expires->ex_delta == 0);
  nua_client_set_terminating(cr, un);
  done = un;

  if (du) {
    struct publish_usage *pu = nua_dialog_usage_private(du);

    if (nua_client_bind(cr, du) < 0)
      return -1;
    if (pu->pu_published)
      done = 1;
    etag = pu->pu_etag;
  }

  return nua_base_client_trequest(cr, msg, sip,
				  SIPTAG_IF_MATCH(etag),
				  TAG_IF(done, SIPTAG_PAYLOAD(NONE)),
				  TAG_IF(done, SIPTAG_CONTENT_TYPE(NONE)),
				  TAG_IF(un, SIPTAG_EXPIRES_STR("0")),
				  TAG_NEXT(tags));
}
static gboolean farsight_netsocket_stun_map (FarsightNetsocket *netsocket)
{
    FarsightNetsocketStun *self = FARSIGHT_NETSOCKET_STUN (netsocket);
    FarsightNetsocket *parent = FARSIGHT_NETSOCKET(self);
    gboolean res = TRUE;
    int stun_res = 0;

    g_return_val_if_fail(parent->sockfd != -1, FALSE);

    g_debug("%s", __func__);

    g_debug("server:%s domain:%s.", self->stun_server, self->stun_domain);

    self->stunh = stun_handle_init(self->root,
				   TAG_IF(self->stun_server, 
					  STUNTAG_SERVER(self->stun_server)),
				   TAG_IF(self->stun_domain, 
					  STUNTAG_DOMAIN(self->stun_domain)),
				   TAG_NULL()); 
    

    if (self->stunh) {
	stun_res = stun_obtain_shared_secret(self->stunh,
					     cb_stun_state, 
					     self,
					     TAG_NULL());
	
	if (stun_res < 0) {
	    if (self->strict_msgint) {
		res = FALSE;
		stun_handle_destroy(self->stunh), self->stunh = NULL;
		g_debug("STUN shared-secret request failed, unable to use STUN (strict msgint mode).");
	    }
	    else {
		if (stun_bind(self->stunh, cb_stun_state, self, 
			      STUNTAG_SOCKET(parent->sockfd), 
			      STUNTAG_REGISTER_EVENTS(1),
			      TAG_NULL()) < 0) {
		    res = FALSE;
		    stun_handle_destroy(self->stunh), self->stunh = NULL;
		    g_debug("Failed to start stun_bind().");
		}
	    }
	}
    }
    else {
	res = FALSE;
	g_debug("Failed to start connection to a STUN server.");
    }

    return res;
}
static apt_bool_t mrcp_sofia_session_offer(mrcp_session_t *session, mrcp_session_descriptor_t *descriptor)
{
	char sdp_str[2048];
	char *local_sdp_str = NULL;
	mrcp_sofia_session_t *sofia_session = session->obj;
	if(!sofia_session || !sofia_session->nh) {
		return FALSE;
	}

	if(session->signaling_agent) {
		mrcp_sofia_agent_t *sofia_agent = session->signaling_agent->obj;
		if(sofia_agent && sofia_agent->config->origin) {
			apt_string_set(&descriptor->origin,sofia_agent->config->origin);
		}
	}
	if(sdp_string_generate_by_mrcp_descriptor(sdp_str,sizeof(sdp_str),descriptor,TRUE) > 0) {
		local_sdp_str = sdp_str;
		apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Local SDP\n%s", local_sdp_str);
	}

	nua_invite(sofia_session->nh,
			   TAG_IF(local_sdp_str,SOATAG_USER_SDP_STR(local_sdp_str)),
			   TAG_END());

	return TRUE;
}
static apt_bool_t mrcp_sofia_on_session_answer(mrcp_session_t *session, mrcp_session_descriptor_t *descriptor)
{
	mrcp_sofia_session_t *sofia_session = session->obj;
	mrcp_sofia_agent_t *sofia_agent = session->signaling_agent->obj;
	const char *local_sdp_str = NULL;
	char sdp_str[2048];

	if(!sofia_agent || !sofia_session || !sofia_session->nh) {
		return FALSE;
	}

	if(sofia_agent->config->origin) {
		apt_string_set(&descriptor->origin,sofia_agent->config->origin);
	}

	if(sdp_string_generate_by_mrcp_descriptor(sdp_str,sizeof(sdp_str),descriptor,FALSE) > 0) {
		local_sdp_str = sdp_str;
		apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Local SDP\n%s", local_sdp_str);
	}

	nua_respond(sofia_session->nh, SIP_200_OK, 
				SIPTAG_CONTACT_STR(sofia_agent->sip_contact_str),
				TAG_IF(local_sdp_str,SOATAG_USER_SDP_STR(local_sdp_str)),
			    NUTAG_AUTOANSWER(0),
				TAG_END());
	
	return TRUE;
}
Example #8
0
/** Send request.
 *
 * @retval 0 success
 * @retval -1 if error occurred, but event has not been sent,
 *            and caller has to destroy request message @ msg
 * @retval -2 if error occurred, event has not been sent
 * @retval >=1 if error event has been sent
 */
int nua_base_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip,
			    tagi_t const *tags)
{
  nua_handle_t *nh = cr->cr_owner;
  int proxy_is_set = NH_PISSET(nh, proxy);
  url_string_t * proxy = NH_PGET(nh, proxy);

  if (nh->nh_auth) {
    if (cr->cr_challenged ||
	NH_PGET(nh, auth_cache) == nua_auth_cache_dialog) {
      if (auc_authorize(&nh->nh_auth, msg, sip) < 0)
	return nua_client_return(cr, 900, "Cannot add credentials", msg);
    }
  }

  cr->cr_seq = sip->sip_cseq->cs_seq; /* Save last sequence number */

  assert(cr->cr_orq == NULL);

  cr->cr_orq = nta_outgoing_mcreate(nh->nh_nua->nua_nta,
				    nua_client_orq_response,
				    nua_client_request_ref(cr),
				    NULL,
				    msg,
				    TAG_IF(proxy_is_set,
					   NTATAG_DEFAULT_PROXY(proxy)),
				    TAG_NEXT(tags));

  if (cr->cr_orq == NULL) {
    nua_client_request_unref(cr);
    return -1;
  }

  return 0;
}
Example #9
0
/**
 * Create a new leg object
 *
 * @param agent    agent object
 * @param callback function which is called for each
 *                 incoming request belonging to this leg
 * @param magic    call leg context
 * @param i        optional @CallID
 *                 (if @c NULL, an ID generated by @b NTA is used)
 * @param from     optional @From (local address)
 * @param to       optional @To (remote address)
 * @param extra    optional extra header
 * @param headers  va_list of optional extra headers
 *
 * @deprecated Use nta_leg_tcreate() instead.
 */
nta_leg_t *nta_leg_vcreate(nta_agent_t *agent,
			   nta_request_f *callback,
			   nta_leg_magic_t *magic,
			   sip_call_id_t const *i,
			   sip_from_t const *from,
			   sip_to_t const *to,
			   void const *extra, va_list headers)
{
  sip_route_t const *route = NULL;
  sip_cseq_t const *cseq = NULL;

  for (; extra ; extra = va_arg(headers, void *)) {
    sip_header_t const *h = (sip_header_t const *)extra;

    if (h == SIP_NONE)
      continue;
    else if (sip_call_id_p(h)) {
      if (i == NULL) i = h->sh_call_id;
    }
    else if (sip_from_p(h)) {
      if (from == NULL) from = h->sh_from;
    }
    else if (sip_to_p(h)) {
      if (to == NULL) to = h->sh_to;
    }
    else if (sip_route_p(h)) {
      route = h->sh_route;
    }
    else if (sip_cseq_p(h)) {
      cseq = h->sh_cseq;
    }
    else {
      SU_DEBUG_3(("nta_leg_create: extra header %s\n", 
		  sip_header_name(h, 0)));
    }
  }

  return nta_leg_tcreate(agent, callback, magic,
			 NTATAG_NO_DIALOG(i == SIP_NONE->sh_call_id),
			 TAG_IF(i != SIP_NONE->sh_call_id, SIPTAG_CALL_ID(i)),
			 TAG_IF(from != SIP_NONE->sh_from, SIPTAG_FROM(from)),
			 TAG_IF(to != SIP_NONE->sh_to, SIPTAG_TO(to)),
			 SIPTAG_ROUTE(route),
			 SIPTAG_CSEQ(cseq),
			 TAG_END());
}
Example #10
0
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 void mrcp_sofia_task_initialize(apt_task_t *task)
{
	mrcp_sofia_agent_t *sofia_agent = apt_task_object_get(task);
	mrcp_sofia_server_config_t *sofia_config = sofia_agent->config;

	/* Initialize Sofia-SIP library and create event loop */
	su_init();
	sofia_agent->root = su_root_create(NULL);

	/* Create a user agent instance. The stack will call the 'event_callback()' 
	 * callback when events such as succesful registration to network, 
	 * an incoming call, etc, occur. 
	 */
	sofia_agent->nua = nua_create(
		sofia_agent->root,         /* Event loop */
		mrcp_sofia_event_callback, /* Callback for processing events */
		sofia_agent,               /* Additional data to pass to callback */
		NUTAG_URL(sofia_agent->sip_bind_str), /* Address to bind to */
		NUTAG_AUTOANSWER(0),
		NUTAG_APPL_METHOD("OPTIONS"),
		TAG_IF(sofia_config->sip_t1,NTATAG_SIP_T1(sofia_config->sip_t1)),
		TAG_IF(sofia_config->sip_t2,NTATAG_SIP_T2(sofia_config->sip_t2)),
		TAG_IF(sofia_config->sip_t4,NTATAG_SIP_T4(sofia_config->sip_t4)),
		TAG_IF(sofia_config->sip_t1x64,NTATAG_SIP_T1X64(sofia_config->sip_t1x64)),
		SIPTAG_USER_AGENT_STR(sofia_config->user_agent_name),
		TAG_IF(sofia_config->tport_log == TRUE,TPTAG_LOG(1)), /* Print out SIP messages to the console */
		TAG_IF(sofia_config->tport_dump_file,TPTAG_DUMP(sofia_config->tport_dump_file)), /* Dump SIP messages to the file */
		TAG_END());                /* Last tag should always finish the sequence */
	if(!sofia_agent->nua) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create NUA [%s] %s",
					apt_task_name_get(task),
					sofia_agent->sip_bind_str);
	}
}
static apt_bool_t mrcp_sofia_on_session_answer(mrcp_session_t *session, mrcp_session_descriptor_t *descriptor)
{
	mrcp_sofia_session_t *sofia_session = session->obj;
	mrcp_sofia_agent_t *sofia_agent = session->signaling_agent->obj;
	const char *local_sdp_str = NULL;
	char sdp_str[2048];

	if(!sofia_agent || !sofia_session || !sofia_session->nh) {
		return FALSE;
	}

	if(descriptor->status != MRCP_SESSION_STATUS_OK) {
		int status = sip_status_get(descriptor->status);
		nua_respond(sofia_session->nh, status, sip_status_phrase(status),
					TAG_IF(sofia_agent->sip_contact_str,SIPTAG_CONTACT_STR(sofia_agent->sip_contact_str)),
					TAG_END());
		return TRUE;
	}

	if(sofia_agent->config->origin) {
		apt_string_set(&descriptor->origin,sofia_agent->config->origin);
	}

	if(sdp_string_generate_by_mrcp_descriptor(sdp_str,sizeof(sdp_str),descriptor,FALSE) > 0) {
		local_sdp_str = sdp_str;
		apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Local SDP "APT_NAMESID_FMT"\n%s", 
			session->name,
			MRCP_SESSION_SID(session), 
			local_sdp_str);
	}

	nua_respond(sofia_session->nh, SIP_200_OK, 
				TAG_IF(sofia_agent->sip_contact_str,SIPTAG_CONTACT_STR(sofia_agent->sip_contact_str)),
				TAG_IF(local_sdp_str,SOATAG_USER_SDP_STR(local_sdp_str)),
				SOATAG_AUDIO_AUX("telephone-event"),
				NUTAG_AUTOANSWER(0),
				TAG_END());
	
	return TRUE;
}
Example #13
0
static tagi_t *soa_static_get_paramlist(soa_session_t const *ss,
					tag_type_t tag, tag_value_t value,
					...)
{
  soa_static_session_t *sss = (soa_static_session_t *)ss;

  ta_list ta;
  tagi_t *tl;

  ta_start(ta, tag, value);

  tl = soa_base_get_paramlist(ss,
			      TAG_IF(sss->sss_audio_aux,
				     SOATAG_AUDIO_AUX(sss->sss_audio_aux)),
			      TAG_IF(sss->sss_ordered_user,
				     SOATAG_ORDERED_USER(1)),
			      TAG_IF(sss->sss_reuse_rejected,
				     SOATAG_REUSE_REJECTED(1)),
			      TAG_NEXT(ta_args(ta)));

  ta_end(ta);

  return tl;
}
Example #14
0
/** @internal Send a keepalive OPTIONS that probes the registration */
static int keepalive_options_with_registration_probe(outbound_t *ob)
{
  msg_t *req;
  sip_t *sip;
  void *request_uri;

  if (ob->ob_keepalive.orq)
    return 0;

  req = msg_copy(ob->ob_keepalive.msg);
  if (!req)
    return -1;

  sip = sip_object(req); assert(sip);
  request_uri = sip->sip_to->a_url;

  if (nta_msg_request_complete(req, nta_default_leg(ob->ob_nta),
       			SIP_METHOD_OPTIONS, request_uri) < 0)
    return msg_destroy(req), -1;

  if (ob->ob_keepalive.auc[0])
    auc_authorization(ob->ob_keepalive.auc, req, (void *)sip,
		      "OPTIONS", request_uri, sip->sip_payload);

  ob->ob_keepalive.orq =
    nta_outgoing_mcreate(ob->ob_nta,
			 response_to_keepalive_options,
			 ob,
			 NULL,
			 req,
			 TAG_IF(ob->ob_proxy_override,
				NTATAG_DEFAULT_PROXY(ob->ob_proxy)),
			 SIPTAG_SUBJECT_STR("REGISTRATION PROBE"),
			 /* NONE is used to remove
			    Max-Forwards: 0 found in ordinary keepalives */
			 SIPTAG_MAX_FORWARDS(SIP_NONE),
			 TAG_END());

  if (!ob->ob_keepalive.orq)
    return msg_destroy(req), -1;

  ob->ob_keepalive.validating = 1;
  ob->ob_keepalive.validated = 0;

  return 0;
}
static apt_bool_t mrcp_sofia_session_create(mrcp_session_t *session, mrcp_sig_settings_t *settings)
{
	mrcp_sofia_agent_t *sofia_agent = mrcp_sofia_agent_get(session);
	mrcp_sofia_session_t *sofia_session;
	session->request_vtable = &session_request_vtable;

	if(!sofia_agent->nua) {
		return FALSE;
	}

	sofia_session = apr_palloc(session->pool,sizeof(mrcp_sofia_session_t));
	sofia_session->mutex = NULL;
	sofia_session->home = su_home_new(sizeof(*sofia_session->home));
	sofia_session->session = session;
	sofia_session->sip_settings = settings;
	sofia_session->terminate_requested = FALSE;
	sofia_session->descriptor = NULL;
	session->obj = sofia_session;

	if(settings->user_name && settings->user_name != '\0') {
		sofia_session->sip_to_str = apr_psprintf(session->pool,"sip:%s@%s:%hu",
										settings->user_name,
										settings->server_ip,
										settings->server_port);
	}
	else {
		sofia_session->sip_to_str = apr_psprintf(session->pool,"sip:%s:%hu",
										settings->server_ip,
										settings->server_port);
	}

	sofia_session->nh = nua_handle(
				sofia_agent->nua,
				sofia_session,
				SIPTAG_TO_STR(sofia_session->sip_to_str),
				SIPTAG_FROM_STR(sofia_agent->sip_from_str),
				SIPTAG_CONTACT_STR(sofia_agent->sip_contact_str),
				TAG_IF(settings->feature_tags,SIPTAG_ACCEPT_CONTACT_STR(settings->feature_tags)),
				TAG_END());
	sofia_session->nua_state = nua_callstate_init;

	apr_thread_mutex_create(&sofia_session->mutex,APR_THREAD_MUTEX_DEFAULT,session->pool);
	return TRUE;
}
Example #16
0
static
int nua_refer_server_report(nua_server_request_t *sr, tagi_t const *tags)
{
  nua_handle_t *nh = sr->sr_owner;
  struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage);
  sip_t const *sip = sr->sr_request.sip;
  sip_referred_by_t *by = sip->sip_referred_by, default_by[1];
  sip_event_t const *o = sr->sr_usage->du_event;
  enum nua_substate substate = nua_substate_terminated;
  int initial = sr->sr_initial, retval;

  if (nu) {
    if (!sr->sr_terminating)
      substate = nu->nu_substate;
  }

  if (by == NULL) {
     by = sip_referred_by_init(default_by);

    by->b_display = sip->sip_from->a_display;
    *by->b_url = *sip->sip_from->a_url;
  }

  retval = nua_base_server_treport(sr,
				   NUTAG_SUBSTATE(substate),
				   NUTAG_REFER_EVENT(o),
				   TAG_IF(by, SIPTAG_REFERRED_BY(by)),
				   TAG_END());

  if (retval >= 2 || nu == NULL)
    return retval;

  if (initial)
    nua_stack_post_signal(nh,
			  nua_r_notify,
			  SIPTAG_EVENT(o),
			  SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
			  SIPTAG_PAYLOAD_STR("SIP/2.0 100 Trying\r\n"),
			  TAG_END());

  return retval;
}
static apt_bool_t mrcp_sofia_session_offer(mrcp_session_t *session, mrcp_session_descriptor_t *descriptor)
{
	char sdp_str[2048];
	const char *local_sdp_str = NULL;
	apt_bool_t res = FALSE;
	mrcp_sofia_session_t *sofia_session = session->obj;
	if(!sofia_session) {
		return FALSE;
	}

	if(session->signaling_agent) {
		mrcp_sofia_agent_t *sofia_agent = mrcp_sofia_agent_get(session);
		if(sofia_agent) {
			if(sofia_agent->config->origin) {
				apt_string_set(&descriptor->origin,sofia_agent->config->origin);
			}
		}
	}
	if(sdp_string_generate_by_mrcp_descriptor(sdp_str,sizeof(sdp_str),descriptor,TRUE) > 0) {
		local_sdp_str = sdp_str;
		sofia_session->descriptor = descriptor;
		apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->log_obj,"Local SDP "APT_NAMESID_FMT"\n%s", 
			session->name,
			MRCP_SESSION_SID(session), 
			local_sdp_str);
	}

	apr_thread_mutex_lock(sofia_session->mutex);

	if(sofia_session->nh) {
		res = TRUE;
		nua_invite(sofia_session->nh,
				TAG_IF(local_sdp_str,SOATAG_USER_SDP_STR(local_sdp_str)),
				TAG_END());
	}

	apr_thread_mutex_unlock(sofia_session->mutex);
	return res;
}
Example #18
0
static int keepalive_options(outbound_t *ob)
{
  msg_t *req;
  sip_t *sip;

  if (ob->ob_keepalive.orq)
    return 0;

  if (ob->ob_prefs.validate && ob->ob_registered && !ob->ob_validated)
    return keepalive_options_with_registration_probe(ob);

  req = msg_copy(ob->ob_keepalive.msg);
  if (!req)
    return -1;
  sip = sip_object(req); assert(sip); assert(sip->sip_request);

  if (nta_msg_request_complete(req, nta_default_leg(ob->ob_nta),
			       SIP_METHOD_UNKNOWN, NULL) < 0)
    return msg_destroy(req), -1;

  if (ob->ob_keepalive.auc[0])
    auc_authorization(ob->ob_keepalive.auc, req, (void *)sip,
		      "OPTIONS", sip->sip_request->rq_url, sip->sip_payload);

  ob->ob_keepalive.orq =
    nta_outgoing_mcreate(ob->ob_nta,
			 response_to_keepalive_options,
			 ob,
			 NULL,
			 req,
			 TAG_IF(ob->ob_proxy_override,
				NTATAG_DEFAULT_PROXY(ob->ob_proxy)),
			 TAG_END());

  if (!ob->ob_keepalive.orq)
    return msg_destroy(req), -1;

  return 0;
}
Example #19
0
int nth_request_treply(nth_request_t *req,
		       int status, char const *phrase,
		       tag_type_t tag, tag_value_t value, ...)
{
  msg_t *response, *next = NULL;
  http_t *http;
  int retval = -1;
  int req_close, close;
  ta_list ta;
  http_header_t const *as_info = NULL;

  if (req == NULL || status < 100 || status >= 600) {
    return -1;
  }

  response = req->req_response;
  http = http_object(response);

  if (status >= 200 && req->req_as)
    as_info = (http_header_t const *)req->req_as->as_info;

  ta_start(ta, tag, value);

  http_add_tl(response, http,
	      HTTPTAG_SERVER(req->req_server->srv_server),
	      HTTPTAG_HEADER(as_info),
	      ta_tags(ta));

  if (http->http_payload && !http->http_content_length) {
    http_content_length_t *l;
    http_payload_t *pl;
    size_t len = 0;

    for (pl = http->http_payload; pl; pl = pl->pl_next)
      len += pl->pl_len;

    if (len > UINT32_MAX)
      goto fail;

    l = http_content_length_create(msg_home(response), (uint32_t)len);

    msg_header_insert(response, (msg_pub_t *)http, (msg_header_t *)l);
  }

  if (req->req_method == http_method_head && http->http_payload) {
    http_payload_t *pl;

    for (pl = http->http_payload; pl; pl = pl->pl_next)
      msg_header_remove(response, (msg_pub_t *)http, (msg_header_t *)pl);
  }

  http_complete_response(response, status, phrase,
			 http_object(req->req_request));

  if (!http->http_date) {
    http_date_t date[1];
    http_date_init(date)->d_time = msg_now();
    msg_header_add_dup(response, (msg_pub_t *)http, (msg_header_t*)date);
  }

  if (status < 200) {
    close = 0;
    next = server_msg_create(req->req_server, 0, NULL, 0, NULL, NULL);
  }
  else {
    req_close = req->req_close;

    close = (http->http_connection &&
	     msg_params_find(http->http_connection->k_items, "close"));

    if (req_close && !close && status >= 200) {
      close = 1;
      http_add_tl(response, http, HTTPTAG_CONNECTION_STR("close"), TAG_END());
    }
  }

  msg_serialize(response, (msg_pub_t *)http);

  retval = tport_tqsend(req->req_tport, response, next,
			TAG_IF(close, TPTAG_CLOSE_AFTER(1)),
			ta_tags(ta));

 fail:
  ta_end(ta);

  if (retval == 0)
    req->req_status = status;

  return retval;
}
Example #20
0
/** @internal Create a message template for keepalive. */
static int create_keepalive_message(outbound_t *ob, sip_t const *regsip)
{
  msg_t *msg = nta_msg_create(ob->ob_nta, MSG_FLG_COMPACT), *previous;
  sip_t *osip = sip_object(msg);
  sip_contact_t *m = ob->ob_rcontact;

  unsigned d = ob->ob_keepalive.interval;

  if (msg == NULL)
    return -1;

  assert(regsip); assert(regsip->sip_request);

  if (m && m->m_params) {
    sip_accept_contact_t *ac;
    size_t i;
    int features = 0;

    ac = sip_accept_contact_make(msg_home(msg), "*;require;explicit");

    for (i = 0; m->m_params[i]; i++) {
      char const *s = m->m_params[i];
      if (!sip_is_callerpref(s))
	continue;
      features++;
      s = su_strdup(msg_home(msg), s);
      msg_header_add_param(msg_home(msg), ac->cp_common, s);
    }

    if (features)
      msg_header_insert(msg, NULL, (void *)ac);
    else
      msg_header_free(msg_home(msg), (void *)ac);
  }

  if (0 >
      /* Duplicate essential headers from REGISTER request: */
      sip_add_tl(msg, osip,
		 SIPTAG_TO(regsip->sip_to),
		 SIPTAG_FROM(regsip->sip_from),
		 /* XXX - we should only use loose routing here */
		 /* XXX - if we used strict routing,
		    the route header/request_uri must be restored
		 */
		 SIPTAG_ROUTE(regsip->sip_route),
		 /* Add Max-Forwards 0 */
		 TAG_IF(d, SIPTAG_MAX_FORWARDS_STR("0")),
		 TAG_IF(d, SIPTAG_SUBJECT_STR("KEEPALIVE")),
		 SIPTAG_CALL_ID_STR(ob->ob_cookie),
		 SIPTAG_ACCEPT_STR(outbound_content_type),
		 TAG_END()) ||
      /* Create request-line, Call-ID, CSeq */
      nta_msg_request_complete(msg,
       			nta_default_leg(ob->ob_nta),
       			SIP_METHOD_OPTIONS,
       			(void *)regsip->sip_to->a_url) < 0 ||
      msg_serialize(msg, (void *)osip) < 0 ||
      msg_prepare(msg) < 0)
    return msg_destroy(msg), -1;

  previous = ob->ob_keepalive.msg;
  ob->ob_keepalive.msg = msg;
  msg_destroy(previous);

  return 0;
}
Example #21
0
/**
 * Creates a new operation object and stores it the list of
 * active operations for 'cli'.
 */
ssc_oper_t *ssc_oper_create(ssc_t *ssc,
                            sip_method_t method,
                            char const *name,
                            char const *address,
                            tag_type_t tag, tag_value_t value, ...)
{
    ssc_oper_t *op, *old;

    ta_list ta;

    enter;

    for (old = ssc->ssc_operations; old; old = old->op_next)
        if (!old->op_persistent)
            break;

    if (address) {
        int have_url = 1;
        sip_to_t *to;

        to = sip_to_make(ssc->ssc_home, address);

        if (to == NULL) {
            printf("%s: %s: invalid address: %s\n", ssc->ssc_name, name, address);
            return NULL;
        }

        /* Try to make sense out of the URL */
        if (url_sanitize(to->a_url) < 0) {
            printf("%s: %s: invalid address\n", ssc->ssc_name, name);
            return NULL;
        }

        if (!(op = su_zalloc(ssc->ssc_home, sizeof(*op)))) {
            printf("%s: %s: cannot create handle\n", ssc->ssc_name, name);
            return NULL;
        }

        op->op_next = ssc->ssc_operations;
        op->op_prev_state = -1;
        op->op_ssc = ssc;
        ssc->ssc_operations = op;

        if (method == sip_method_register)
            have_url = 0;

        ta_start(ta, tag, value);

        op->op_handle = nua_handle(ssc->ssc_nua, op,
                                   TAG_IF(have_url, NUTAG_URL(to->a_url)),
                                   SIPTAG_TO(to),
                                   ta_tags(ta));

        ta_end(ta);

        op->op_ident = sip_header_as_string(ssc->ssc_home, (sip_header_t *)to);

        ssc_oper_assign(op, method, name);

        if (!op->op_persistent) {
            ssc_oper_t *old_next;
            for (; old; old = old_next) {      /* Clean old handles */
                old_next = old->op_next;
                if (!old->op_persistent && !old->op_callstate)
                    ssc_oper_destroy(ssc, old);
            }
        }

        su_free(ssc->ssc_home, to);
    }
    else if (method || name)
        ssc_oper_assign(op = old, method, name);
    else
        return old;

    if (!op) {
        if (address)
            printf("%s: %s: invalid destination\n", ssc->ssc_name, name);
        else
            printf("%s: %s: no destination\n", ssc->ssc_name, name);
        return NULL;
    }

    return op;
}
/* Callback from nea_server asking nua to authorize subscription */
static
void authorize_watcher(nea_server_t *nes,
		       nua_handle_t *nh,
		       nea_event_t *ev,
		       nea_subnode_t *sn,
		       sip_t const *sip)
{
  nua_t *nua = nh->nh_nua;
  msg_t *msg = NULL;
  nta_incoming_t *irq = NULL;
  int substate = sn->sn_state;
  int status; char const *phrase;

  SET_STATUS1(SIP_200_OK);

  /* OK. In nhp (nua_handle_preferences_t) structure we have the
     current default action (or state) for incoming
     subscriptions.
     Action can now be modified by the application with NUTAG_SUBSTATE().
  */
  irq = nea_sub_get_request(sn->sn_subscriber);
  msg = nta_incoming_getrequest(irq);

  if (sn->sn_state == nea_embryonic) {
    char const *what;

    substate = NH_PGET(nh, substate);

    if (substate == nua_substate_embryonic)
      substate = nua_substate_pending;

    if (substate == nua_substate_terminated) {
      what = "rejected"; SET_STATUS1(SIP_403_FORBIDDEN);
    }
    else if (substate == nua_substate_pending) {
      what = "pending"; SET_STATUS1(SIP_202_ACCEPTED);
    }
    else {
      what = "active";
    }

    SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n", (void *)nh, what));
    nea_sub_auth(sn->sn_subscriber, (nea_state_t)substate,
		 TAG_IF(substate == nua_substate_pending,
			NEATAG_FAKE(1)),
		 TAG_IF(substate == nua_substate_terminated,
			NEATAG_REASON("rejected")),
		 TAG_END());
  }
  else if (sn->sn_state == nea_terminated || sn->sn_expires == 0) {
    substate = nua_substate_terminated;
    nea_server_flush(nes, NULL);
    SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n",
		(void *)nh, "watcher is removed"));
  }

  nua_stack_tevent(nua, nh, msg, nua_i_subscription, status, phrase,
		   NUTAG_SUBSTATE(substate),
		   NEATAG_SUB(sn->sn_subscriber),
		   TAG_END());
}
Example #23
0
/** Respond without creating a request structure */
static void server_reply(server_t *srv, tport_t *tport,
			 msg_t *request, msg_t *response,
			 int status, char const *phrase)
{
  http_t *http;
  http_payload_t *pl;
  int close;
  http_status_t st[1];
  char const *req_version = NULL;

  if (status < 200 || status >= 600)
    status = 500, phrase = http_500_internal_server;

  http = http_object(request);

  if (http && http->http_request)
    req_version = http->http_request->rq_version;

  close = status >= 200 &&
    (!srv->srv_persistent
     || status == 400
     || (http && http->http_request &&
	 http->http_request->rq_version != http_version_1_1)
     || (http && http->http_connection &&
	 msg_params_find(http->http_connection->k_items, "close")));

  msg_destroy(request);

  http = http_object(response);

  pl = http_payload_format(msg_home(response),
			   "<html>\n"
			   "<head><title>%u %s</title></head>\n"
			   "<body><h2>%u %s</h2></body>\n"
			   "</html>\n", status, phrase, status, phrase);

  msg_header_insert(response, (msg_pub_t *)http, (msg_header_t *)pl);

  if (req_version != http_version_0_9) {
    http_status_init(st);
    st->st_version = http_version_1_1;
    st->st_status = status;
    st->st_phrase = phrase;

    http_add_tl(response, http,
		HTTPTAG_STATUS(st),
		HTTPTAG_SERVER(srv->srv_server),
		HTTPTAG_CONTENT_TYPE_STR("text/html"),
		HTTPTAG_SEPARATOR_STR("\r\n"),
		TAG_IF(close, HTTPTAG_CONNECTION_STR("close")),
		TAG_END());

    msg_serialize(response, (msg_pub_t *)http);
  } else {
    /* Just send the response */
    *msg_chain_head(response) = (msg_header_t *)pl;
    close = 1;
  }

  if (tport_tqsend(tport, response, NULL,
		   TPTAG_CLOSE_AFTER(close),
		   TAG_END()) == -1) {
    SU_DEBUG_3(("server_reply(): cannot queue response\n"));
    tport_shutdown(tport, 2);
  }

  msg_destroy(response);
}
int test_extension(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;
  sip_t const *sip;


/* Test for EXTENSION

   A			B
   |------EXTENSION---->|
   |<--------501--------| (method not recognized)
   |			|
   |------EXTENSION---->|
   |<-------200---------| (method allowed, responded)
   |			|
*/

  if (print_headings)
    printf("TEST NUA-13.1: EXTENSION\n");


  TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));

  /* Test first without NUTAG_METHOD() */
  METHOD(a, a_call, a_call->nh,
	 TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
	 TAG_END());

  run_ab_until(ctx, -1, save_until_final_response, -1, NULL);

  /* Client events:
     nua_method(), nua_r_method
  */
  TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_method);
  TEST(e->data->e_status, 900);	/* Internal error */
  TEST_1(!e->data->e_msg);
  TEST_1(!e->next);

  free_events_in_list(ctx, a->events);
  nua_handle_destroy(a_call->nh), a_call->nh = NULL;

  TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));

  METHOD(a, a_call, a_call->nh,
	 TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
	 NUTAG_METHOD("EXTENSION"),
	 TAG_END());

  run_ab_until(ctx, -1, save_until_final_response, -1, NULL);

  /* Client events:
     nua_method(), nua_r_method
  */
  TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_method);
  TEST(e->data->e_status, 501);
  TEST_1(!e->next);

  free_events_in_list(ctx, a->events);
  nua_handle_destroy(a_call->nh), a_call->nh = NULL;

  free_events_in_list(ctx, b->events);
  nua_handle_destroy(b_call->nh), b_call->nh = NULL;

  nua_set_params(b->nua, NUTAG_ALLOW("EXTENSION"), 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()));

  METHOD(a, a_call, a_call->nh,
	 TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
	 NUTAG_METHOD("EXTENSION"),
	 TAG_END());

  run_ab_until(ctx, -1, save_until_final_response, -1, respond_to_extension);

  /* Client events:
     nua_method(), nua_r_method
  */
  TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_method);
  TEST(e->data->e_status, 200);
  TEST_1(sip = sip_object(e->data->e_msg));
  TEST_1(!e->next);

  /*
   Server events:
   nua_i_method
  */
  TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_method);
  TEST(e->data->e_status, 100);
  TEST_1(!e->next);

  free_events_in_list(ctx, a->events);
  nua_handle_destroy(a_call->nh), a_call->nh = NULL;

  free_events_in_list(ctx, b->events);
  nua_handle_destroy(b_call->nh), b_call->nh = NULL;

  nua_set_params(b->nua,
		 SIPTAG_ALLOW(b->allow),
		 NUTAG_APPL_METHOD(NULL),
		 NUTAG_APPL_METHOD(b->appl_method),
		 TAG_END());
  run_b_until(ctx, nua_r_set_params, until_final_response);

  if (print_headings)
    printf("TEST NUA-13.1: PASSED\n");
  END();
}