Exemplo n.º 1
0
/**Create a client request.
 *
 * @retval 0 if request is pending
 * @retval > 0 if error event has been sent
 * @retval < 0 upon an error
 */
int nua_client_create(nua_handle_t *nh,
		      int event,
		      nua_client_methods_t const *methods,
		      tagi_t const * const tags)
{
  su_home_t *home = nh->nh_home;
  nua_client_request_t *cr;
  sip_method_t method;
  char const *name;

  method = methods->crm_method, name = methods->crm_method_name;
  if (!name) {
    tagi_t const *t = tl_find_last(tags, nutag_method);
    if (t)
      name = (char const *)t->t_value;
  }

  cr = su_zalloc(home, sizeof *cr + methods->crm_extra);
  if (!cr) {
    return nua_stack_event(nh->nh_nua, nh,
			   NULL,
			   (enum nua_event_e)event,
			   NUA_ERROR_AT(__FILE__, __LINE__),
			   NULL);
  }

  cr->cr_methods = methods;
  cr->cr_event = event;
  cr->cr_method = method;
  cr->cr_method_name = name;
  cr->cr_contactize = methods->crm_flags.target_refresh;
  cr->cr_dialog = methods->crm_flags.create_dialog;
  cr->cr_auto = 1;

  if (su_msg_is_non_null(nh->nh_nua->nua_signal)) {
    nua_event_data_t *e = su_msg_data(nh->nh_nua->nua_signal)->ee_data;

    if (tags == e->e_tags && event == e->e_event) {
      cr->cr_auto = 0;

      if (tags) {
	nua_move_signal(cr->cr_signal, nh->nh_nua->nua_signal);
	if (cr->cr_signal) {
	  /* Steal reference from signal */
	  cr->cr_owner = e->e_nh, e->e_nh = NULL;
	  cr->cr_tags = tags;
	}
      }
    }
  }

  if (cr->cr_owner == NULL)
    cr->cr_owner = nua_handle_ref(nh);

  if (tags && cr->cr_tags == NULL)
    cr->cr_tags = tl_tlist(nh->nh_home, TAG_NEXT(tags));

#if HAVE_MEMLEAK_LOG
  SU_DEBUG_0(("%p %s() for %s\n", cr, __func__, cr->cr_methods->crm_method_name));
#endif

  if (nua_client_request_queue(cr))
    return 0;

  return nua_client_init_request(cr);
}
Exemplo n.º 2
0
static int nua_notify_client_init(nua_client_request_t *cr,
				  msg_t *msg, sip_t *sip,
				  tagi_t const *tags)
{
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_usage_t *du;
  struct notifier_usage *nu;
  sip_event_t const *o = sip->sip_event;
  sip_subscription_state_t *ss = sip->sip_subscription_state;
  sip_time_t now = sip_now();

  if (o == NULL && nh->nh_ds->ds_has_notifys == 1)
    o = NONE;

  du = nua_dialog_usage_get(nh->nh_ds, nua_notify_usage, o);

  if (!du) {
    tagi_t const *newsub = tl_find_last(tags, nutag_newsub);

    if (!newsub || !newsub->t_value)
      return 0; /* Rejected eventually by nua_notify_client_request() */

    /* Create new notifier */
    du = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o);
    if (du == NULL)
      return -1;

    nu = nua_dialog_usage_private(du);
    nu->nu_expires = now;
  }
  else
    nu = nua_dialog_usage_private(du);


  if (nu->nu_substate == nua_substate_terminated) {
    /*Xyzzy*/;
  }
  else if (ss != NULL) {
    /* SIPTAG_SUBSCRIPTION_STATE() overrides NUTAG_SUBSTATE() */
    nu->nu_substate = nua_substate_make(ss->ss_substate);

    if (ss->ss_expires) {
      unsigned long expires = strtoul(ss->ss_expires, NULL, 10);
      if (now + expires < now)
	expires = SIP_TIME_MAX - now - 1;

      /* We can change the lifetime of unsolicited subscription at will */
      if (nu->nu_requested == 0)
	nu->nu_expires = nu->nu_requested = now + expires;
      /* Notifier can only shorten the subscribed time */
      else if (nu->nu_requested >= now + expires)
	nu->nu_expires = nu->nu_requested = now + expires;
    }
    else {
      if (nu->nu_requested >= nu->nu_expires)
	nu->nu_expires = nu->nu_requested;
    }

  }
  else {
    enum nua_substate substate = nu->nu_substate;

    if (nu->nu_requested >= nu->nu_expires)
      nu->nu_expires = nu->nu_requested;

    if (nu->nu_expires > now) {
      tagi_t const *t = tl_find_last(tags, nutag_substate);
      if (t)
        substate = (enum nua_substate)t->t_value;
    }
    else
      substate = nua_substate_terminated;

    switch (substate) {
    case nua_substate_embryonic:
      /*FALLTHROUGH*/
    case nua_substate_pending:
      nu->nu_substate = nua_substate_pending;
      break;
    case nua_substate_active:
    default:
      nu->nu_substate = nua_substate_active;
      break;
    case nua_substate_terminated:
      nu->nu_substate = nua_substate_terminated;
      break;
    }
  }

  cr->cr_usage = du;

  return nua_notify_client_init_etag(cr, msg, sip, tags);
}