⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nua_dialog.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 2 页
字号:
  }  return NULL;}/** @internal Remove dialog usage. */void nua_dialog_usage_remove(nua_owner_t *own, 			     nua_dialog_state_t *ds,			     nua_dialog_usage_t *du,			     nua_client_request_t *cr,			     nua_server_request_t *sr){  nua_dialog_usage_t **at;  assert(own); assert(ds); assert(du);  for (at = &ds->ds_usage; *at; at = &(*at)->du_next)    if (du == *at)      break;  assert(*at);  nua_dialog_usage_remove_at(own, ds, at, cr, sr);}/** @internal Remove dialog usage.  * * Zap dialog state (leg, tag and route) if no usages remain. */static void nua_dialog_usage_remove_at(nua_owner_t *own, 				nua_dialog_state_t *ds,				nua_dialog_usage_t **at,				nua_client_request_t *cr0,				nua_server_request_t *sr0){  if (*at) {    nua_dialog_usage_t *du = *at;    sip_event_t const *o = NULL;    nua_client_request_t *cr, *cr_next;    nua_server_request_t *sr, *sr_next;    *at = du->du_next;    o = du->du_event;    SU_DEBUG_5(("nua(%p): removing %s usage%s%s\n",		(void *)own, nua_dialog_usage_name(du), 		o ? " with event " : "", o ? o->o_type :""));    du->du_class->usage_remove(own, ds, du, cr0, sr0);    /* Destroy saved client request */    if (cr0 != du->du_cr && nua_client_is_bound(du->du_cr)) {      nua_client_bind(cr = du->du_cr, NULL);      if (nua_client_is_queued(cr))	nua_client_request_complete(cr);      else if (nua_client_is_reporting(cr))	;      else	nua_client_request_destroy(cr);    }    /* Clean references from queued client requests */    for (cr = ds->ds_cr; cr; cr = cr_next) {      cr_next = cr->cr_next;      if (cr->cr_usage == du)	cr->cr_usage = NULL;    }    for (sr = ds->ds_sr; sr; sr = sr_next) {      sr_next = sr->sr_next;      if (sr->sr_usage == du) {	if (sr != sr0)	  nua_server_request_destroy(sr);	sr->sr_usage = NULL;      }    }    su_home_unref(own);    su_free(own, du);  }  /* Zap dialog if there are no more usages */  if (ds->ds_terminating)    ;  else if (ds->ds_usage == NULL) {    nua_dialog_remove(own, ds, NULL);    ds->ds_has_events = 0;    return;  }  else {    nua_dialog_log_usage(own, ds);  }}staticvoid nua_dialog_log_usage(nua_owner_t *own, nua_dialog_state_t *ds){  nua_dialog_usage_t *du;  if (SU_LOG->log_level >= 3) {    char buffer[160];    size_t l = 0, N = sizeof buffer;    ssize_t n;        buffer[0] = '\0';    for (du = ds->ds_usage; du; du = du->du_next) {      msg_header_t const *h = (void *)du->du_event;      if (!h)	continue;      n = sip_event_e(buffer + l, N - l, h, 0);      if (n == -1)	break;      l += (size_t)n;      if (du->du_next && l + 2 < sizeof(buffer)) {	strcpy(buffer + l, ", ");	l += 2;      }    }        SU_DEBUG_3(("nua(%p): handle with %s%s%s\n", (void *)own,		ds->ds_has_session ? "session and " : "", 		ds->ds_has_events ? "events " : "",		buffer));  }}/** Deinitialize dialog and its usage. @internal */void nua_dialog_deinit(nua_owner_t *own,		       nua_dialog_state_t *ds){  ds->ds_terminating = 1;  while (ds->ds_usage) {    nua_dialog_usage_remove_at(own, ds, &ds->ds_usage, NULL, NULL);  }  nua_dialog_remove(own, ds, NULL);  ds->ds_has_events = 0;  ds->ds_terminating = 0;}void nua_dialog_update_params(nua_dialog_state_t *ds,			      nua_handle_preferences_t const *changed,			      nua_handle_preferences_t const *params,			      nua_handle_preferences_t const *defaults){  nua_dialog_usage_t *usage;  for (usage = ds->ds_usage; usage; usage = usage->du_next) {    usage->du_class->usage_update_params(usage, changed, params, defaults);  }}void nua_base_usage_update_params(nua_dialog_usage_t const *du,				  nua_handle_preferences_t const *changed,				  nua_handle_preferences_t const *params,				  nua_handle_preferences_t const *defaults){  (void)du, (void)changed, (void)params, (void)defaults;}/**@internal * Set refresh value suitably.  * * The refresh time is set either around half of the @a delta interval or, * if @a delta is less than 5 minutes but longer than 90 seconds, 30..60 * seconds before end of interval. * * If @a delta is 0, the dialog usage is never refreshed. */void nua_dialog_usage_set_refresh(nua_dialog_usage_t *du, unsigned delta){  if (delta == 0)    nua_dialog_usage_reset_refresh(du);  else if (delta > 90 && delta < 5 * 60)    /* refresh 30..60 seconds before deadline */    nua_dialog_usage_set_refresh_range(du, delta - 60, delta - 30);  else {    /* By default, refresh around half time before deadline */    unsigned min = (delta + 2) / 4;    unsigned max = (delta + 2) / 4 + (delta + 1) / 2;    if (min == 0)      min = 1;    nua_dialog_usage_set_refresh_range(du, min, max);  }}/**@internal Set refresh in range min..max seconds in the future. */void nua_dialog_usage_set_refresh_range(nua_dialog_usage_t *du, 					unsigned min, unsigned max){  sip_time_t now = sip_now(), target;  unsigned delta;  if (max < min)    max = min;  if (min != max)    delta = su_randint(min, max);  else    delta = min;  if (now + delta >= now)    target = now + delta;  else    target = SIP_TIME_MAX;  SU_DEBUG_7(("nua(): refresh %s after %lu seconds (in [%u..%u])\n",	      nua_dialog_usage_name(du), target - now, min, max));  du->du_refquested = now;  nua_dialog_usage_set_refresh_at(du, target);}/** Set absolute refresh time */void nua_dialog_usage_set_refresh_at(nua_dialog_usage_t *du,				     sip_time_t target){  SU_DEBUG_7(("nua(): refresh %s after %lu seconds\n",	      nua_dialog_usage_name(du), target - sip_now()));  du->du_refresh = target;} /**@internal Do not refresh. */void nua_dialog_usage_reset_refresh(nua_dialog_usage_t *du){  if (du) {    du->du_refquested = sip_now();    du->du_refresh = 0;  }}/** @internal Refresh usage. */void nua_dialog_usage_refresh(nua_owner_t *owner,			      nua_dialog_state_t *ds,			      nua_dialog_usage_t *du, 			      sip_time_t now){  assert(du && du->du_class->usage_refresh);  du->du_class->usage_refresh(owner, ds, du, now);}/** Terminate all dialog usages gracefully. */int nua_dialog_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds){  nua_dialog_usage_t *du;  ds->ds_terminating = 1;  do {    for (du = ds->ds_usage; du; du = du->du_next) {      if (!du->du_shutdown) {	nua_dialog_usage_shutdown(owner, ds, du);	break;      }    }  } while (du);  return 1;}/** Shutdown (gracefully terminate) usage. * * @retval >0  shutdown done * @retval 0   shutdown in progress * @retval <0  try again later */int nua_dialog_usage_shutdown(nua_owner_t *owner,			      nua_dialog_state_t *ds,			      nua_dialog_usage_t *du){  if (du) {    nua_dialog_usage_reset_refresh(du);    du->du_shutdown = 1;    assert(du->du_class->usage_shutdown);    return du->du_class->usage_shutdown(owner, ds, du);  }  else    return 200;}/** 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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -