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

📄 nua_stack.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
  size_t len, xtra, ee_len, l_len = 0, l_xtra = 0;  ta_list ta;  int retval = -1;  if (nua == NULL)    return -1;  if (nua->nua_shutdown_started && event != nua_r_shutdown)    return -1;  ta_start(ta, tag, value);  ee_len = offsetof(nua_ee_data_t, ee_data[0].e_tags);  len = tl_len(ta_args(ta));  xtra = tl_xtra(ta_args(ta), len);  if (su_msg_new(sumsg, ee_len + len + l_len + xtra + l_xtra) == 0) {    nua_ee_data_t *ee = su_msg_data(sumsg);    nua_event_data_t *e = ee->ee_data;    tagi_t *t = e->e_tags;    void *b = (char *)t + len + l_len;    tagi_t *tend = (tagi_t *)b;    char *bend = (char *)b + xtra + l_xtra;    t = tl_dup(t, ta_args(ta), &b);    assert(tend == t); (void)tend; assert(b == bend); (void)bend;    e->e_always = event == nua_r_destroy || event == nua_r_shutdown;    e->e_event = event;    e->e_nh = nh ? nua_handle_ref(nh) : NULL;    e->e_status = status;    e->e_phrase = phrase;    su_msg_deinitializer(sumsg, nua_event_deinit);          retval = su_msg_send_to(sumsg, nua->nua_server, nua_stack_signal);    if (retval == 0){      SU_DEBUG_7(("nua(%p): %s signal %s\n", (void *)nh,		  "sent", nua_event_name(event) + 4));    }    else {      SU_DEBUG_0(("nua(%p): %s signal %s\n", (void *)nh,		  "FAILED TO SEND", nua_event_name(event) + 4));    }  }  ta_end(ta);  return retval;}/* ---------------------------------------------------------------------- * Receiving events from client */staticvoid nua_stack_signal(nua_t *nua, su_msg_r msg, nua_ee_data_t *ee){  nua_event_data_t *e = ee->ee_data;  nua_handle_t *nh = e->e_nh;  tagi_t *tags = e->e_tags;  nua_event_t event;  int error = 0;  if (nh) {    if (!nh->nh_prev)      nh_append(nua, nh);    if (!nh->nh_ref_by_stack) {      /* Mark handle as used by stack */      nh->nh_ref_by_stack = 1;      nua_handle_ref(nh);    }  }  if (nua_log->log_level >= 5) {    char const *name = nua_event_name(e->e_event);    if (e->e_status == 0)      SU_DEBUG_5(("nua(%p): %s signal %s\n", (void *)nh, "recv", name + 4));    else      SU_DEBUG_5(("nua(%p): recv signal %s %u %s\n",		  (void *)nh, name + 4,		  e->e_status, e->e_phrase ? e->e_phrase : ""));  }  su_msg_save(nua->nua_signal, msg);  event = e->e_event;  if (nua->nua_shutdown && !e->e_always) {    /* Shutting down */    nua_stack_event(nua, nh, NULL, event,		    901, "Stack is going down",		    NULL);  }  else switch (event) {  case nua_r_get_params:    nua_stack_get_params(nua, nh ? nh : nua->nua_dhandle, event, tags);    break;  case nua_r_set_params:    nua_stack_set_params(nua, nh ? nh : nua->nua_dhandle, event, tags);    break;  case nua_r_shutdown:    nua_stack_shutdown(nua);    break;  case nua_r_register:  case nua_r_unregister:    nua_stack_register(nua, nh, event, tags);    break;  case nua_r_invite:    error = nua_stack_invite(nua, nh, event, tags);    break;  case nua_r_cancel:    error = nua_stack_cancel(nua, nh, event, tags);    break;  case nua_r_bye:    error = nua_stack_bye(nua, nh, event, tags);    break;  case nua_r_options:    error = nua_stack_options(nua, nh, event, tags);    break;  case nua_r_refer:    error = nua_stack_refer(nua, nh, event, tags);    break;  case nua_r_publish:  case nua_r_unpublish:    error = nua_stack_publish(nua, nh, event, tags);    break;  case nua_r_info:    error = nua_stack_info(nua, nh, event, tags);    break;  case nua_r_prack:    error = nua_stack_prack(nua, nh, event, tags);    break;  case nua_r_update:    error = nua_stack_update(nua, nh, event, tags);    break;  case nua_r_message:    error = nua_stack_message(nua, nh, event, tags);    break;  case nua_r_subscribe:  case nua_r_unsubscribe:    error = nua_stack_subscribe(nua, nh, event, tags);    break;  case nua_r_notify:    error = nua_stack_notify(nua, nh, event, tags);    break;  case nua_r_notifier:    nua_stack_notifier(nua, nh, event, tags);    break;  case nua_r_terminate:    nua_stack_terminate(nua, nh, event, tags);    break;  case nua_r_method:    error = nua_stack_method(nua, nh, event, tags);    break;  case nua_r_authenticate:    nua_stack_authenticate(nua, nh, event, tags);    break;  case nua_r_authorize:    nua_stack_authorize(nua, nh, event, tags);    break;  case nua_r_ack:    error = nua_stack_ack(nua, nh, event, tags);    break;  case nua_r_respond:    nua_stack_respond(nua, nh, e->e_status, e->e_phrase, tags);    break;  case nua_r_destroy:     nua_stack_destroy_handle(nua, nh, tags);    su_msg_destroy(nua->nua_signal);    return;  default:    break;  }  if (error < 0) {    nua_stack_event(nh->nh_nua, nh, NULL, event,		    NUA_ERROR_AT(__FILE__, __LINE__), NULL);  }  su_msg_destroy(nua->nua_signal);}/* ====================================================================== *//* Signal and event handling *//** Get event data. * * @sa #nua_event_e, nua_event_save(), nua_saved_event_request(), nua_destroy_event(). */nua_event_data_t const *nua_event_data(nua_saved_event_t const saved[1]){  return saved && saved[0] ? su_msg_data(saved)->ee_data : NULL;}/** Destroy saved event. * * @sa #nua_event_e, nua_event_save(), nua_event_data(), nua_saved_event_request(). */void nua_destroy_event(nua_saved_event_t saved[1]){  if (saved) su_msg_destroy(saved);}/** @internal Move signal. */void nua_move_signal(nua_saved_signal_t a[1], nua_saved_signal_t b[1]){  su_msg_save(a, b);}void nua_destroy_signal(nua_saved_signal_t saved[1]){  if (saved) su_msg_destroy(saved);}nua_signal_data_t const *nua_signal_data(nua_saved_signal_t const saved[1]){  return nua_event_data(saved);}/* ====================================================================== */static int nh_call_pending(nua_handle_t *nh, sip_time_t time);/**@internal * Timer routine. * * Go through all active handles and execute pending tasks */void nua_stack_timer(nua_t *nua, su_timer_t *t, su_timer_arg_t *a){  nua_handle_t *nh, *nh_next;  sip_time_t now = sip_now();  su_root_t *root = su_timer_root(t);  su_timer_set(t, nua_stack_timer, a);  if (nua->nua_shutdown) {    nua_stack_shutdown(nua);    return;  }  for (nh = nua->nua_handles; nh; nh = nh_next) {    nh_next = nh->nh_next;    nh_call_pending(nh, now);    su_root_yield(root);	/* Handle received packets */  }}staticint nh_call_pending(nua_handle_t *nh, sip_time_t now){  nua_dialog_state_t *ds = nh->nh_ds;  nua_dialog_usage_t *du;  sip_time_t next = now + NUA_STACK_TIMER_INTERVAL / 1000;  for (du = ds->ds_usage; du; du = du->du_next) {    if (now == 0)      break;    if (du->du_refresh && du->du_refresh < next)      break;  }  if (du == NULL)    return 0;  nua_handle_ref(nh);  while (du) {    nua_dialog_usage_t *du_next = du->du_next;    nua_dialog_usage_refresh(nh, ds, du, now);    if (du_next == NULL)      break;    for (du = nh->nh_ds->ds_usage; du; du = du->du_next)      if (du == du_next)	break;    for (; du; du = du->du_next) {      if (now == 0)	break;      if (du->du_refresh && du->du_refresh < next)	break;    }  }  nua_handle_unref(nh);  return 1;}/* ====================================================================== *//**Shutdown a @nua stack. * * When the @nua stack is shutdown, ongoing calls are released, * registrations unregistered, publications un-PUBLISHed and subscriptions * terminated. If the stack cannot terminate everything within 30 seconds, * it sends the #nua_r_shutdown event with status 500. * * @param nua         Pointer to @nua stack object * * @return *     nothing * * @par Related tags: *     none * * @par Events: *     #nua_r_shutdown * * @sa #nua_r_shutdown, nua_destroy(), nua_create(), nua_bye(), * nua_unregister(), nua_unpublish(), nua_unsubscribe(), nua_notify(), * nua_handle_destroy(), nua_handle_unref() *//** @NUA_EVENT nua_r_shutdown * * Answer to nua_shutdown(). * * Status codes * - 100 shutdown started * - 101 shutdown in progress (sent when shutdown has been progressed) * - 200 shutdown was successful * - 500 shutdown timeout after 30 sec * * @param status shutdown status code * @param nh     NULL * @param hmagic NULL * @param sip    NULL * @param tags   empty * * @sa nua_shutdown(), nua_destroy() * * @END_NUA_EVENT *//** @internal Shut down stack. */void nua_stack_shutdown(nua_t *nua){  nua_handle_t *nh, *nh_next;  int busy = 0;  sip_time_t now = sip_now();  int status;  char const *phrase;  enter;  if (!nua->nua_shutdown)    nua->nua_shutdown = now;  for (nh = nua->nua_handles; nh; nh = nh_next) {    nua_dialog_state_t *ds = nh->nh_ds;    nh_next = nh->nh_next;    busy += nua_dialog_repeat_shutdown(nh, ds);    if (nh->nh_soa) {      soa_destroy(nh->nh_soa), nh->nh_soa = NULL;    }    if (nua_client_request_pending(ds->ds_cr))      busy++;    if (nh_notifier_shutdown(nh, NULL, NEATAG_REASON("noresource"), TAG_END()))      busy++;  }  if (!busy)    SET_STATUS(200, "Shutdown successful");  else if (now == nua->nua_shutdown)    SET_STATUS(100, "Shutdown started");  else if (now - nua->nua_shutdown < 30)    SET_STATUS(101, "Shutdown in progress");  else    SET_STATUS(500, "Shutdown timeout");  if (status >= 200) {    for (nh = nua->nua_handles; nh; nh = nh_next) {      nh_next = nh->nh_next;      while (nh->nh_ds && nh->nh_ds->ds_usage) {	nua_dialog_usage_remove(nh, nh->nh_ds, nh->nh_ds->ds_usage, NULL, NULL);      }    }    su_timer_destroy(nua->nua_timer), nua->nua_timer = NULL;    nta_agent_destroy(nua->nua_nta), nua->nua_nta = NULL;  }  nua_stack_event(nua, NULL, NULL, nua_r_shutdown, status, phrase, NULL);}/* ---------------------------------------------------------------------- *//** @internal Create a handle */nua_handle_t *nh_create(nua_t *nua, tag_type_t tag, tag_value_t value, ...){  ta_list ta;  nua_handle_t *nh;  enter;  ta_start(ta, tag, value);  nh = nh_create_handle(nua, NULL, ta_args(ta));  ta_end(ta);  if (nh) {    nh->nh_ref_by_stack = 1;    nh_append(nua, nh);  }  return nh;}/** @internal Append a handle to the list of handles */void nh_append(nua_t *nua, nua_handle_t *nh){  nh->nh_next = NULL;  nh->nh_prev = nua->nua_handles_tail;  *nua->nua_handles_tail = nh;  nua->nua_handles_tail = &nh->nh_next;}nua_handle_t *nh_validate(nua_t *nua, nua_handle_t *maybe){  nua_handle_t *nh;  if (maybe)    for (nh = nua->nua_handles; nh; nh = nh->nh_next)      if (nh == maybe)	return nh;  return NULL;}void nua_stack_destroy_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags){  if (nh->nh_notifier)    nua_stack_terminate(nua, nh, 0, NULL);  nua_dialog_shutdown(nh, nh->nh_ds);  if (nh->nh_ref_by_user) {    nh->nh_ref_by_user = 0;    nua_handle_unref(nh);  }  nh_destroy(nua, nh);}#define nh_is_inserted(nh) ((nh)->nh_prev != NULL)/** @internal Remove a handle from list of handles */staticvoid nh_remove(nua_t *nua, nua_handle_t *nh){  assert(nh_is_inserted(nh)); assert(*nh->nh_prev == nh);  if (nh->nh_next)    nh->nh_next->nh_prev = nh->nh_prev;  else    nua->nua_handles_tail = nh->nh_prev;  *nh->nh_prev = nh->nh_next;  nh->nh_prev = NULL;  nh->nh_next = NULL;}

⌨️ 快捷键说明

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