Esempio n. 1
0
int nua_subscribe_server_preprocess(nua_server_request_t *sr)
{
  nua_handle_t *nh = sr->sr_owner;
  nua_dialog_state_t *ds = nh->nh_ds;
  nua_dialog_usage_t *du;
  struct notifier_usage *nu;
  sip_t const *sip = sr->sr_request.sip;
  sip_event_t *o = sip->sip_event;
  char const *event = o ? o->o_type : NULL;
  /* Maximum expiration time */
  unsigned long expires = sip->sip_expires ? sip->sip_expires->ex_delta : 3600;
  sip_time_t now = sip_now();
  sip_allow_events_t *appl_event = NH_PGET(nh, appl_event);

  assert(nh && nh->nh_nua->nua_dhandle != nh);

  du = nua_dialog_usage_get(ds, nua_notify_usage, o);

  if (du == NULL) {
    /* Create a new subscription */
    du = nua_dialog_usage_add(nh, ds, nua_notify_usage, o);
    if (du == NULL)
      return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);
  }
  else if (!msg_header_find_param((void *)appl_event, event)) {
    unsigned max_expires;

    /* Refresh existing subscription */
    if (su_strmatch(event, "refer"))
      max_expires = NH_PGET(nh, refer_expires);
    else
      max_expires = NH_PGET(nh, sub_expires);

    if (expires >= max_expires)
      expires = max_expires;

    SR_STATUS1(sr, SIP_200_OK);
  }

  nu = nua_dialog_usage_private(du);

  if (now + expires >= now)
    nu->nu_requested = now + expires;
  else
    nu->nu_requested = SIP_TIME_MAX - 1;

#if SU_HAVE_EXPERIMENTAL
  nu->nu_etags =
    sip_suppress_body_if_match(sip) ||
    sip_suppress_notify_if_match(sip) ||
    sip_has_feature(sr->sr_request.sip->sip_supported, "etags");
#endif

  sr->sr_usage = du;

  return sr->sr_status <= 100 ? 0 : sr->sr_status;
}
Esempio n. 2
0
int nua_publish_server_init(nua_server_request_t *sr)
{
  sip_allow_events_t *allow_events = NH_PGET(sr->sr_owner, allow_events);
  sip_event_t *o = sr->sr_request.sip->sip_event;
  char const *event = o ? o->o_type : NULL;

  if (!allow_events)
    return SR_STATUS1(sr, SIP_501_NOT_IMPLEMENTED);
  else if (!event || !msg_header_find_param(allow_events->k_common, event))
    return SR_STATUS1(sr, SIP_489_BAD_EVENT);

  return 0;
}
Esempio n. 3
0
/** Repeat shutdown of all usages.
 *
 * @note Caller must have a reference to nh
 */
int nua_dialog_repeat_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds)
{
  nua_dialog_usage_t *du;
  nua_server_request_t *sr, *sr_next;

  for (sr = ds->ds_sr; sr; sr = sr_next) {
    sr_next = sr->sr_next;

    if (nua_server_request_is_pending(sr)) {
      SR_STATUS1(sr, SIP_410_GONE); /* 410 terminates dialog */
      nua_server_respond(sr, NULL);
      nua_server_report(sr);
    }
  }

  for (du = ds->ds_usage; du ;) {
    nua_dialog_usage_t *du_next = du->du_next;

    nua_dialog_usage_shutdown(owner, ds, du);

    if (du_next == NULL)
      break;

    for (du = ds->ds_usage; du; du = du->du_next) {
      if (du == du_next)
	break;
      else if (!du->du_shutdown)
	break;
    }
  }

  return ds->ds_usage != NULL;
}
Esempio n. 4
0
static int nua_refer_server_preprocess(nua_server_request_t *sr)
{
  nua_handle_t *nh = sr->sr_owner;
  sip_t const *sip = sr->sr_request.sip;
  struct notifier_usage *nu;
  sip_event_t *o;

  if (nh->nh_ds->ds_got_referrals || NH_PGET(nh, refer_with_id))
    o = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq);
  else
    o = sip_event_make(nh->nh_home, "refer");

  if (o) {
    sr->sr_usage = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o);
    msg_header_free(nh->nh_home, (msg_header_t *)o);
  }

  if (!sr->sr_usage)
    return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);

  nu = nua_dialog_usage_private(sr->sr_usage);
  nu->nu_requested = sip_now() + NH_PGET(nh, refer_expires);

  return 0;
}
Esempio n. 5
0
int nua_subscribe_server_init(nua_server_request_t *sr)
{
  nua_handle_t *nh = sr->sr_owner;
  nua_dialog_state_t *ds = nh->nh_ds;
  sip_allow_events_t const *allow_events = NH_PGET(nh, allow_events);
  sip_t const *sip = sr->sr_request.sip;
  sip_event_t *o = sip->sip_event;
  char const *event = o ? o->o_type : NULL;

  if (sr->sr_initial || !nua_dialog_usage_get(ds, nua_notify_usage, o)) {
    if (su_strmatch(event, "refer"))
      /* refer event subscription should be initiated with REFER */
      return SR_STATUS1(sr, SIP_403_FORBIDDEN);

    /* XXX - event is case-sensitive, should use msg_header_find_item() */
    if (!event || !msg_header_find_param(allow_events->k_common, event))
      return SR_STATUS1(sr, SIP_489_BAD_EVENT);
  }

  return 0;
}
Esempio n. 6
0
int nua_notify_server_preprocess(nua_server_request_t *sr)
{
  nua_dialog_state_t *ds = sr->sr_owner->nh_ds;
  nua_dialog_usage_t *du;
  struct event_usage *eu;
  sip_t const *sip = sr->sr_request.sip;
  sip_event_t *o = sip->sip_event;
  enum nua_substate substate = nua_substate_terminated;
  sip_subscription_state_t *subs = sip->sip_subscription_state;
  char const *what = "", *reason = NULL;
  int solicited = 1;

  du = nua_dialog_usage_get(ds, nua_subscribe_usage, o);

  if (du == NULL) {
    if (!sip_is_allowed(NH_PGET(sr->sr_owner, appl_method), SIP_METHOD_NOTIFY))
      return SR_STATUS(sr, 481, "Subscription Does Not Exist");

    solicited = 0;    /* Let application to handle unsolicited NOTIFY */
    du = nua_dialog_usage_add(sr->sr_owner, ds, nua_subscribe_usage, o);
    if (!du)
      return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);
  }

  sr->sr_usage = du;
  eu = nua_dialog_usage_private(du); assert(eu);
  eu->eu_notified++;
  if (!o || !o->o_id)
    eu->eu_no_id = 1;

  if (subs == NULL) {
    /* Compatibility */
    unsigned long delta = eu->eu_delta;
    if (sip->sip_expires)
      delta = sip->sip_expires->ex_delta;

    if (delta == 0)
      substate = nua_substate_terminated, what = "terminated";
    else
      substate = nua_substate_active, what = "active";
  }
  else if (su_casematch(subs->ss_substate, what = "terminated")) {
    substate = nua_substate_terminated;
    reason = subs->ss_reason;

    if (su_casematch(reason, "deactivated") ||
	su_casematch(reason, "probation"))
      substate = nua_substate_embryonic;
  }
  else if (su_casematch(subs->ss_substate, what = "pending")) {
    substate = nua_substate_pending;
  }
  else /* if (su_casematch(subs->ss_substate, what = "active")) */ {
    /* Any extended state is considered as active */
    what = subs->ss_substate;
    substate = nua_substate_active;
  }

  eu->eu_substate = substate;
  if (!solicited)
    eu->eu_unsolicited = 1;

  SU_DEBUG_5(("nua(%p): %s: %s (%s)\n",
	      (void *)sr->sr_owner, "nua_notify_server_preprocess",
	      what, reason ? reason : ""));

  if (solicited)
    return SR_STATUS1(sr, SIP_200_OK);

  return 0;
}