Exemplo n.º 1
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.º 2
0
/** Remove dialog information. */
int nua_dialog_zap(nua_owner_t *own,
		   nua_dialog_state_t *ds)
{
  /* zap peer info */
  nua_dialog_store_peer_info(own, ds, NULL);
  /* Local Contact */
  msg_header_free(own, (msg_header_t *)ds->ds_ltarget), ds->ds_ltarget = NULL;
  /* Leg */
  nta_leg_destroy(ds->ds_leg), ds->ds_leg = NULL;
  /* Remote tag */
  su_free(own, (void *)ds->ds_remote_tag), ds->ds_remote_tag = NULL;
  /* Ready to set route/remote target */
  ds->ds_route = 0;

  return 0;
}
Exemplo n.º 3
0
/** Process response to the client request.
 *
 * The response can be generated by the stack (@a sip is NULL) or
 * returned by the remote server.
 *
 * @retval 0 if response event was preliminary
 * @retval 1 if response event was final
 * @retval 2 if response event destroyed the handle, too.
 */
int nua_client_response(nua_client_request_t *cr,
			int status,
			char const *phrase,
			sip_t const *sip)
{
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_usage_t *du = cr->cr_usage;
  int retval = 0;

  if (cr->cr_restarting)
    return 0;

  nua_client_request_ref(cr);

  cr->cr_status = status;
  cr->cr_phrase = phrase;

  if (status < 200) {
    /* Xyzzy */
  }
  else if (sip && nua_client_check_restart(cr, status, phrase, sip)) {
    nua_client_request_unref(cr);
    return 0;
  }
  else if (status < 300) {
    if (cr->cr_terminating) {
      cr->cr_terminated = 1;
    }
    else {
      if (sip) {
	if (cr->cr_contactize)
	  nua_dialog_uac_route(nh, nh->nh_ds, sip, 1, cr->cr_initial);
	nua_dialog_store_peer_info(nh, nh->nh_ds, sip);
      }

      if (du && du->du_cr == cr)
	du->du_ready = 1;
    }
  }
  else {
    sip_method_t method = cr->cr_method;
    int terminated, graceful = 1;

    if (status < 700)
      terminated = sip_response_terminates_dialog(status, method, &graceful);
    else
      /* XXX - terminate usage by all internal error responses */
      terminated = 0, graceful = 1;

    if (terminated < 0)
      cr->cr_terminated = terminated;
    else if (cr->cr_terminating || terminated)
      cr->cr_terminated = 1;
    else if (graceful)
      cr->cr_graceful = 1;
  }

  if (status < 200) {
    if (cr->cr_methods->crm_preliminary)
      cr->cr_methods->crm_preliminary(cr, status, phrase, sip);
    else
      nua_base_client_response(cr, status, phrase, sip, NULL);
    cr->cr_phrase = NULL;
  }
  else {
    if (cr->cr_methods->crm_recv)
      retval = cr->cr_methods->crm_recv(cr, status, phrase, sip);
    else
      retval = nua_base_client_response(cr, status, phrase, sip, NULL);
  }

  nua_client_request_unref(cr);

  return retval;
}