Exemplo n.º 1
0
/**
 * Create a new leg object for incoming request message.
 *
 * @param agent    agent object
 * @param callback function which is called for each 
 *                 incoming request belonging to this leg
 * @param magic    call leg context
 * @param msg      a request message
 *
 * @note The ownership of @a msg will pass back to NTA upon successful call
 * to the function nta_msg_leg(). In other words, if the call to @a
 * nta_msg_leg() is successful, the application may not do anything with @a
 * msg anymore.  Instead of that, NTA will create of a new incoming request
 * object for the @a msg and eventually return the request to application by
 * calling the @a callback function.
 *
 * @deprecated Use nta_leg_stateful() instead.
 */
nta_leg_t *nta_msg_leg(nta_agent_t *agent,
		       msg_t *msg,
		       nta_request_f *callback,
		       nta_leg_magic_t *magic,
		       ...)
{
  nta_leg_t *leg;
  sip_t *sip = sip_object(msg);

  SU_DEBUG_9(("\tnta_msg_leg(): called\n"));

  assert(msg && sip && sip->sip_request);

  if (!msg || !sip || !sip->sip_request || !callback)
    return NULL;

  leg = nta_leg_tcreate(agent, callback, magic,
			SIPTAG_CALL_ID(sip->sip_call_id),
			SIPTAG_FROM(sip->sip_to), /* local address */
			SIPTAG_TO(sip->sip_from), /* remote address */
			TAG_END());
  if (!leg) 
    /* xyzzy */;
  else if (nta_leg_server_route(leg, sip->sip_record_route, 
				sip->sip_contact) < 0)
    nta_leg_destroy(leg), leg = NULL;
  else if (nta_leg_stateful(leg, msg) < 0)
    nta_leg_destroy(leg), leg = NULL;

  SU_DEBUG_9(("\tnta_msg_leg(): returns %p\n", leg));

  return leg;
}
Exemplo n.º 2
0
/** @internal Create a handle for processing incoming request */
nua_handle_t *nua_stack_incoming_handle(nua_t *nua,
					nta_incoming_t *irq,
					sip_t const *sip,
					int create_dialog)
{
  nua_handle_t *nh;
  url_t const *url;
  sip_to_t to[1];
  sip_from_t from[1];

  assert(sip && sip->sip_from && sip->sip_to);

  if (sip->sip_contact)
    url = sip->sip_contact->m_url;
  else
    url = sip->sip_from->a_url;

  /* Strip away parameters */
  sip_from_init(from)->a_display = sip->sip_to->a_display;
  *from->a_url = *sip->sip_to->a_url;

  sip_to_init(to)->a_display = sip->sip_from->a_display;
  *to->a_url = *sip->sip_from->a_url;

  nh = nh_create(nua,
		 NUTAG_URL((url_string_t *)url), /* Remote target */
		 SIPTAG_TO(to), /* Local AoR */
		 SIPTAG_FROM(from), /* Remote AoR */
		 TAG_END());

  if (nh && nua_stack_init_handle(nua, nh, NULL) < 0)
    nh_destroy(nua, nh), nh = NULL;

  if (nh && create_dialog) {
    struct nua_dialog_state *ds = nh->nh_ds;

    nua_dialog_store_peer_info(nh, ds, sip);

    ds->ds_leg = nta_leg_tcreate(nua->nua_nta, nua_stack_process_request, nh,
				 SIPTAG_CALL_ID(sip->sip_call_id),
				 SIPTAG_FROM(sip->sip_to),
				 SIPTAG_TO(sip->sip_from),
				 NTATAG_REMOTE_CSEQ(sip->sip_cseq->cs_seq),
				 TAG_END());

    if (!ds->ds_leg || !nta_leg_tag(ds->ds_leg, nta_incoming_tag(irq, NULL)))
      nh_destroy(nua, nh), nh = NULL;
  }

  if (nh)
    nua_dialog_uas_route(nh, nh->nh_ds, sip, 1);

  return nh;
}
Exemplo n.º 3
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());
}
Exemplo n.º 4
0
static void invite_setup(void)
{
    dialog = su_home_new(sizeof *dialog);

    fail_unless(dialog != NULL);

    s2_nta_setup("NTA", NULL, TAG_END());

    fail_unless(s2sip->udp.contact != NULL);

    s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL,
                       NTATAG_UA(1),
                       TAG_END());

    leg = nta_leg_tcreate(s2->nta, NULL, NULL,
                          SIPTAG_FROM_STR("<sip:[email protected]>"),
                          SIPTAG_TO_STR("<sip:test2.3.1.example.org>"),
                          TAG_END());

    fail_unless(leg != NULL);
}
Exemplo n.º 5
0
int nua_stack_init(su_root_t *root, nua_t *nua)
{
  su_home_t *home;
  nua_handle_t *dnh;

  static int initialized_logs = 0;

  enter;

  if (!initialized_logs) {
    extern su_log_t tport_log[];
    extern su_log_t nta_log[];
    extern su_log_t nea_log[];
    extern su_log_t iptsec_log[];

    su_log_init(tport_log);
    su_log_init(nta_log);
    su_log_init(nea_log);
    su_log_init(iptsec_log);

    initialized_logs = 1;
  }

  nua->nua_root = root;

  home = nua->nua_home;
  nua->nua_handles_tail = &nua->nua_handles;
  sip_from_init(nua->nua_from);

  dnh = su_home_clone(nua->nua_home, sizeof (*dnh) + sizeof(*dnh->nh_prefs));
  if (!dnh)
    return -1;

  dnh->nh_prefs = (void *)(dnh + 1);
  dnh->nh_valid = nua_valid_handle_cookie;
  dnh->nh_nua = nua;
  nua_handle_ref(dnh); dnh->nh_ref_by_stack = 1;
  nua_handle_ref(dnh); dnh->nh_ref_by_user = 1;
  nh_append(nua, dnh);
  dnh->nh_identity = dnh;
  dnh->nh_ds->ds_local = nua->nua_from;
  dnh->nh_ds->ds_remote = nua->nua_from;

  if (nua_stack_set_defaults(dnh, dnh->nh_prefs) < 0)
    return -1;

  if (nua_stack_set_params(nua, dnh, nua_i_none, nua->nua_args) < 0)
    return -1;

  /* XXX - soa should know what it supports */
  nua->nua_invite_accept = sip_accept_make(home, SDP_MIME_TYPE);

  nua->nua_accept_multipart = sip_accept_format(home, "%s, %s",
						SDP_MIME_TYPE,
						"multipart/*");

  nua->nua_nta = nta_agent_create(root, NONE, NULL, NULL,
				  NTATAG_MERGE_482(1),
				  NTATAG_CLIENT_RPORT(1),
				  NTATAG_UA(1),
#if HAVE_SOFIA_SMIME
				  NTATAG_SMIME(nua->sm),
#endif
				  TPTAG_STUN_SERVER(1),
				  TAG_NEXT(nua->nua_args));

  dnh->nh_ds->ds_leg = nta_leg_tcreate(nua->nua_nta,
				       nua_stack_process_request, dnh,
				       NTATAG_NO_DIALOG(1),
				       TAG_END());

  if (nua->nua_nta == NULL ||
      dnh->nh_ds->ds_leg == NULL ||
      nta_agent_set_params(nua->nua_nta, NTATAG_UA(1), TAG_END()) < 0 ||
      nua_stack_init_transport(nua, nua->nua_args) < 0) {
    SU_DEBUG_1(("nua: initializing SIP stack failed\n"));
    return -1;
  }

  if (nua_stack_set_from(nua, 1, nua->nua_args) < 0)
    return -1;

  if (nua->nua_prefs->ngp_detect_network_updates)
    nua_stack_launch_network_change_detector(nua);

  return 0;
}
Exemplo n.º 6
0
/**Send a request message.
 *
 * @retval 0 if request is pending
 * @retval >=1 if error event has been sent
 * @retval < 0 if no error event has been sent
 */
static
int nua_client_request_sendmsg(nua_client_request_t *cr)
{
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_state_t *ds = nh->nh_ds;
  sip_method_t method = cr->cr_method;
  char const *name = cr->cr_method_name;
  url_string_t const *url = (url_string_t *)cr->cr_target;
  nta_leg_t *leg;
  msg_t *msg;
  sip_t *sip;
  int error;

  assert(cr->cr_orq == NULL);

  cr->cr_offer_sent = cr->cr_answer_recv = 0;
  cr->cr_offer_recv = cr->cr_answer_sent = 0;

  if (!ds->ds_leg && cr->cr_dialog) {
    ds->ds_leg = nta_leg_tcreate(nh->nh_nua->nua_nta,
				 nua_stack_process_request, nh,
				 SIPTAG_CALL_ID(cr->cr_sip->sip_call_id),
				 SIPTAG_FROM(cr->cr_sip->sip_from),
				 SIPTAG_TO(cr->cr_sip->sip_to),
				 SIPTAG_CSEQ(cr->cr_sip->sip_cseq),
				 TAG_END());
    if (!ds->ds_leg)
      return -1;
  }

  if (cr->cr_sip->sip_from && ds->ds_leg) {
    if (cr->cr_sip->sip_from->a_tag == NULL) {
      if (sip_from_tag(msg_home(cr->cr_msg), cr->cr_sip->sip_from,
		       nta_leg_tag(ds->ds_leg, NULL)) < 0) {
	return -1;
      }
    }
  }

  cr->cr_retry_count++;

  if (ds->ds_leg)
    leg = ds->ds_leg;
  else
    leg = nh->nh_nua->nua_dhandle->nh_ds->ds_leg; /* Default leg */

  msg = msg_copy(cr->cr_msg), sip = sip_object(msg);

  if (msg == NULL)
    return -1;

  if (nua_dialog_is_established(ds)) {
    while (sip->sip_route)
      sip_route_remove(msg, sip);
  }
  else if (!ds->ds_route) {
    sip_route_t *initial_route = NH_PGET(nh, initial_route);

    if (initial_route) {
      initial_route = sip_route_dup(msg_home(msg), initial_route);
      if (!initial_route) return -1;
      msg_header_prepend(msg, (msg_pub_t*)sip,
			 /* This should be
			    (msg_header_t **)&sip->sip_route
			  * but directly casting pointer &sip->sip_route gives
			  * spurious type-punning warning */
			 (msg_header_t **)((char *)sip + offsetof(sip_t, sip_route)),
			 (msg_header_t *)initial_route);
    }
  }


  /**
   * For in-dialog requests, the request URI is taken from the @Contact
   * header received from the remote party during dialog establishment,
   * and the NUTAG_URL() is ignored.
   *
   * Also, the @CallID and @CSeq headers and @From and @To tags are
   * generated based on the dialog information and added to the request.
   * If the dialog has a route, it is added to the request, too.
   */
  if (nta_msg_request_complete(msg, leg, method, name, url) < 0) {
    msg_destroy(msg);
    return -1;
  }

  /**@MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is
   * also added now, if it does not exist.
   */

  if (!ds->ds_remote)
    ds->ds_remote = sip_to_dup(nh->nh_home, sip->sip_to);
  if (!ds->ds_local)
    ds->ds_local = sip_from_dup(nh->nh_home, sip->sip_from);

  /**
   * Next, values previously set with nua_set_params() or nua_set_hparams()
   * are used: @Allow, @Supported, @Organization, @UserAgent and
   * @AllowEvents headers are added to the request if they are not already
   * set.
   */
  if (!sip->sip_allow)
    sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow));

  if (!sip->sip_supported && NH_PGET(nh, supported))
    sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported));

  if (method == sip_method_register && NH_PGET(nh, path_enable) &&
      !sip_has_feature(sip->sip_supported, "path") &&
      !sip_has_feature(sip->sip_require, "path"))
    sip_add_make(msg, sip, sip_supported_class, "path");

  if (!sip->sip_organization && NH_PGET(nh, organization))
    sip_add_make(msg, sip, sip_organization_class, NH_PGET(nh, organization));

  if (!sip->sip_user_agent && NH_PGET(nh, user_agent))
    sip_add_make(msg, sip, sip_user_agent_class, NH_PGET(nh, user_agent));

  /** Any node implementing one or more event packages SHOULD include an
   * appropriate @AllowEvents header indicating all supported events in
   * all methods which initiate dialogs and their responses (such as
   * INVITE) and OPTIONS responses.
   */
  if (!sip->sip_allow_events &&
      NH_PGET(nh, allow_events) &&
      (method == sip_method_notify || /* Always in NOTIFY */
       (!ds->ds_remote_tag &&	      /* And in initial requests */
	(method == sip_method_subscribe || method == sip_method_refer ||
	 method == sip_method_options ||
	 method == sip_method_invite))))
    sip_add_dup(msg, sip, (void *)NH_PGET(nh, allow_events));

  /**
   * Next, the stack generates a @Contact header for the request (unless
   * the application already gave a @Contact header or it does not want to
   * use @Contact and indicates that by including SIPTAG_CONTACT(NULL) or
   * SIPTAG_CONTACT(SIP_NONE) in the tagged parameters.) If the
   * application has registered the URI in @From header, the @Contact
   * header used with registration is used. Otherwise, the @Contact header
   * is generated from the local IP address and port number.
   */

  /**For the initial requests, @ServiceRoute set that was received from the
   * registrar is also added to the request message.
   */
  if (cr->cr_method != sip_method_register) {
    if (cr->cr_contactize && cr->cr_has_contact) {
      sip_contact_t *ltarget = sip_contact_dup(nh->nh_home, sip->sip_contact);
      if (ds->ds_ltarget)
	msg_header_free(nh->nh_home, (msg_header_t *)ds->ds_ltarget);
      ds->ds_ltarget = ltarget;
    }

    if (ds->ds_ltarget && !cr->cr_has_contact)
      sip_add_dup(msg, sip, (sip_header_t *)ds->ds_ltarget);

    if (nua_registration_add_contact_to_request(nh, msg, sip,
						cr->cr_contactize &&
						!cr->cr_has_contact &&
						!ds->ds_ltarget,
						!ds->ds_route) < 0) {
      msg_destroy(msg);
      return -1;
    }
  }

  cr->cr_wait_for_cred = 0;

  if (cr->cr_methods->crm_send)
    error = cr->cr_methods->crm_send(cr, msg, sip, NULL);
  else
    error = nua_base_client_request(cr, msg, sip, NULL);

  if (error == -1)
    msg_destroy(msg);

  return error;
}
Exemplo n.º 7
0
    int DrachtioController::processRequestOutsideDialog( nta_leg_t* defaultLeg, nta_incoming_t* irq, sip_t const *sip) {
        DR_LOG(log_debug) << "processRequestOutsideDialog" << endl ;
        int rc = validateSipMessage( sip ) ;
        if( 0 != rc ) {
            return rc ;
        }

        switch (sip->sip_request->rq_method ) {
            case sip_method_invite:
            {
                /* TODO:  should support optional config to only allow invites from defined addresses */

                /* system-wide minimum session-expires is 90 seconds */
                if( sip->sip_session_expires && sip->sip_session_expires->x_delta < 90 ) {
                      nta_incoming_treply( irq, SIP_422_SESSION_TIMER_TOO_SMALL, 
                        SIPTAG_MIN_SE_STR("90"),
                        TAG_END() ) ; 
                      return 0;
                } 

                string transactionId ;
                generateUuid( transactionId ) ;

                nta_incoming_treply( irq, SIP_100_TRYING, TAG_END() ) ;                
 
                 if( !m_pClientController->route_request_outside_dialog( irq, sip, transactionId ) )  {
                    DR_LOG(log_error) << "No providers available for invite" << endl ;
                    return 503 ;
                }

                nta_leg_t* leg = nta_leg_tcreate(m_nta, legCallback, this,
                                                   SIPTAG_CALL_ID(sip->sip_call_id),
                                                   SIPTAG_CSEQ(sip->sip_cseq),
                                                   SIPTAG_TO(sip->sip_from),
                                                   SIPTAG_FROM(sip->sip_to),
                                                   TAG_END());
                if( NULL == leg ) {
                    DR_LOG(log_error) << "Error creating a leg for  origination" << endl ;
                    //TODO: we got a client out there with a dead INVITE now...
                    return 500 ;
                }
                boost::shared_ptr<SipDialog> dlg = boost::make_shared<SipDialog>( leg, irq, sip ) ;
                dlg->setTransactionId( transactionId ) ;

                string contactStr ;
                generateOutgoingContact( sip->sip_contact, contactStr ) ;
                nta_leg_server_route( leg, sip->sip_record_route, sip->sip_contact ) ;

                m_pDialogController->addIncomingInviteTransaction( leg, irq, sip, transactionId, dlg ) ;


            }
            break ;

            case sip_method_ack:

                /* success case: call has been established */
                nta_incoming_destroy( irq ) ;
                return 0 ;               
            case sip_method_register:
            case sip_method_message:
            case sip_method_options:
            case sip_method_notify:
            {
                string transactionId ;
                generateUuid( transactionId ) ;

                if( !m_pClientController->route_request_outside_dialog( irq, sip, transactionId ) )  {
                    DR_LOG(log_error) << "No providers available for register" << endl ;
                    return 503 ;
                }

                m_pDialogController->addIncomingRequestTransaction( irq, transactionId ) ;
                return 0 ;
            }
            
            case sip_method_bye:
            case sip_method_cancel:
                DR_LOG(log_error) << "Received BYE or CANCEL for unknown dialog: " << sip->sip_call_id->i_id << endl ;
                return 481 ;
                
            default:
                DR_LOG(log_error) << "DrachtioController::processRequestOutsideDialog - unsupported method type: " << sip->sip_request->rq_method_name << ": " << sip->sip_call_id->i_id << endl ;
                return 501 ;
                break ;
                
        }
        
        return 0 ;
    }
Exemplo n.º 8
0
    void DrachtioController::run() {
        
        if( m_bDaemonize ) {
            daemonize() ;
        }

		/* now we can initialize logging */
		m_logger.reset( this->createLogger() );
		this->logConfig() ;

        DR_LOG(log_debug) << "Main thread id: " << boost::this_thread::get_id() << endl ;

       /* open stats connection */
        string adminAddress ;
        unsigned int adminPort = m_Config->getAdminPort( adminAddress ) ;
        if( 0 != adminPort ) {
            m_pClientController.reset( new ClientController( this, adminAddress, adminPort )) ;
        }

        string url ;
        m_Config->getSipUrl( url ) ;
        DR_LOG(log_notice) << "starting sip stack on " << url << endl ;
        
        int rv = su_init() ;
        if( rv < 0 ) {
            DR_LOG(log_error) << "Error calling su_init: " << rv << endl ;
            return ;
        }
        ::atexit(su_deinit);
        
        m_root = su_root_create( NULL ) ;
        if( NULL == m_root ) {
            DR_LOG(log_error) << "Error calling su_root_create: " << endl ;
            return  ;
        }
        m_home = su_home_create() ;
        if( NULL == m_home ) {
            DR_LOG(log_error) << "Error calling su_home_create" << endl ;
        }
        su_log_redirect(NULL, __sofiasip_logger_func, NULL);
        
        /* for now set logging to full debug */
        su_log_set_level(NULL, m_Config->getSofiaLogLevel() ) ;
        setenv("TPORT_LOG", "1", 1) ;
        
        /* this causes su_clone_start to start a new thread */
        su_root_threading( m_root, 0 ) ;
        rv = su_clone_start( m_root, m_clone, this, clone_init, clone_destroy ) ;
        if( rv < 0 ) {
           DR_LOG(log_error) << "Error calling su_clone_start" << endl ;
           return  ;
        }
        
        /* enable extended headers */
        if (sip_update_default_mclass(sip_extend_mclass(NULL)) < 0) {
            DR_LOG(log_error) << "Error calling sip_update_default_mclass" << endl ;
            return  ;
        }
 
         /* create our agent */
        char str[URL_MAXLEN] ;
        memset(str, 0, URL_MAXLEN) ;
        strncpy( str, url.c_str(), url.length() ) ;
        
		m_nta = nta_agent_create( m_root,
                                 URL_STRING_MAKE(str),               /* our contact address */
                                 NULL,         /* no callback function */
                                 NULL,                  /* therefore no context */
                                 TAG_NULL(),
                                 TAG_END() ) ;
        
        if( NULL == m_nta ) {
            DR_LOG(log_error) << "Error calling nta_agent_create" << endl ;
            return ;
        }
        
        m_defaultLeg = nta_leg_tcreate(m_nta, defaultLegCallback, this,
                                      NTATAG_NO_DIALOG(1),
                                      TAG_END());
        if( NULL == m_defaultLeg ) {
            DR_LOG(log_error) << "Error creating default leg" << endl ;
            return ;
        }
        
        
        /* save my contact url, via, etc */
        m_my_contact = nta_agent_contact( m_nta ) ;
        ostringstream s ;
        s << "SIP/2.0/UDP " <<  m_my_contact->m_url[0].url_host ;
        if( m_my_contact->m_url[0].url_port ) s << ":" <<  m_my_contact->m_url[0].url_port  ;
        m_my_via.assign( s.str().c_str(), s.str().length() ) ;
        DR_LOG(log_debug) << "My via header: " << m_my_via << endl ;

        m_pDialogController = boost::make_shared<SipDialogController>( this, &m_clone ) ;
              
        /* sofia event loop */
        DR_LOG(log_notice) << "Starting sofia event loop in main thread: " <<  boost::this_thread::get_id() << endl ;

        /* start a timer */
        m_timer = su_timer_create( su_root_task(m_root), 30000) ;
        su_timer_set_for_ever(m_timer, watchdogTimerHandler, this) ;
 
        su_root_run( m_root ) ;
        DR_LOG(log_notice) << "Sofia event loop ended" << endl ;
        
        su_root_destroy( m_root ) ;
        m_root = NULL ;
        su_home_unref( m_home ) ;
        su_deinit() ;

        m_Config.reset();
        this->deinitializeLogging() ;

        
    }