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

📄 nua_stack.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
    busy += nh_call_pending(nh, 0);    if (nh->nh_soa) {      soa_destroy(nh->nh_soa), nh->nh_soa = NULL;    }    if (nh->nh_cr->cr_orq || nh->nh_ss->ss_crequest->cr_orq)      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);      }    }    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, TAG_END());}/* ---------------------------------------------------------------------- *//** @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 an 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){  nh_call_pending(nh, 0);	/* Call pending operations with 0 */  if (nh->nh_notifier)    nua_stack_terminate(nua, nh, 0, NULL);#if 0  if (nh->nh_ref_by_user) {    nh->nh_ref_by_user = 0;    nua_handle_unref(nh);  }#endif  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;}void nh_destroy(nua_t *nua, nua_handle_t *nh){  assert(nh); assert(nh != nua->nua_dhandle);  nh_enter;  if (nh->nh_notifier)    nea_server_destroy(nh->nh_notifier), nh->nh_notifier = NULL;  nua_creq_deinit(nh->nh_cr, NULL);  if (nh->nh_ss)    nua_creq_deinit(nh->nh_ss->ss_crequest, NULL);  if (nh->nh_ds->ds_leg) {    nta_leg_destroy(nh->nh_ds->ds_leg), nh->nh_ds->ds_leg = NULL;  }  if (nh->nh_ss->ss_srequest->sr_irq) {    nta_incoming_destroy(nh->nh_ss->ss_srequest->sr_irq);    nh->nh_ss->ss_srequest->sr_irq = NULL;  }  if (nh->nh_soa)    soa_destroy(nh->nh_soa), nh->nh_soa = NULL;  if (nh_is_inserted(nh))    nh_remove(nua, nh);  nua_handle_unref(nh);		/* Remove stack reference */}void nua_creq_deinit(struct nua_client_request *cr, nta_outgoing_t *orq){  if (orq == NULL || orq == cr->cr_orq) {    cr->cr_retry_count = 0;    cr->cr_offer_sent = cr->cr_answer_recv = 0;    if (cr->cr_msg)      msg_destroy(cr->cr_msg);    cr->cr_msg = NULL;    if (cr->cr_orq)      nta_outgoing_destroy(cr->cr_orq);    cr->cr_orq = NULL;  }  else {    nta_outgoing_destroy(orq);  }}/* ======================================================================== *//**@internal * Initialize handle Allow and authentication info. * * @retval -1 upon an error * @retval 0 when successful */int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh,			  enum nh_kind kind,			  char const *default_allow,			  tag_type_t tag, tag_value_t value, ...){  ta_list ta;  int retval = 0;  if (nh == NULL)    return -1;  if (kind && !nh_is_special(nh) && !nh->nh_has_invite) {    switch (kind) {    case nh_has_invite:    nh->nh_has_invite = 1;    break;    case nh_has_subscribe: nh->nh_has_subscribe = 1; break;    case nh_has_notify:    nh->nh_has_notify = 1;    break;    case nh_has_register:  nh->nh_has_register = 1;  break;    case nh_has_streaming: nh->nh_has_streaming = 1; break;    case nh_has_nothing:    default:      break;    }  }  assert(nh != nua->nua_dhandle);  ta_start(ta, tag, value);  if (nua_stack_set_params(nua, nh, nua_i_error, ta_args(ta)) < 0)    retval = -1;  if (!retval && !nh->nh_soa && nua->nua_dhandle->nh_soa) {    nh->nh_soa = soa_clone(nua->nua_dhandle->nh_soa, nua->nua_root, nh);    if (nh->nh_soa && nh->nh_tags)      if (soa_set_params(nh->nh_soa, TAG_NEXT(nh->nh_tags)))	retval = -1;  }  if (!retval && nh->nh_soa)    if (soa_set_params(nh->nh_soa, ta_tags(ta)) < 0)      retval = -1;  ta_end(ta);  if (retval || nh->nh_init) /* Already initialized? */    return retval;#if HAVE_UICC_H  if (nh->nh_has_register && nua->nua_uicc)    auc_with_uicc(&nh->nh_auth, nh->nh_home, nua->nua_uicc);#endif  if (nh->nh_tags)    nh_authorize(nh, TAG_NEXT(nh->nh_tags));  nh->nh_ss->ss_min_se = NH_PGET(nh, min_se);  nh->nh_ss->ss_session_timer = NH_PGET(nh, session_timer);  nh->nh_ss->ss_refresher = NH_PGET(nh, refresher);  nh->nh_init = 1;  return 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,					enum nh_kind kind,					int create_dialog){  nua_handle_t *nh;  url_t const *url;  char const *default_allow = NULL; /* XXX - should be argument? */  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;  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),		 SIPTAG_TO(to), /* Local address */		 SIPTAG_FROM(from), /* Remote address */		 TAG_END());  if (nua_stack_init_handle(nh->nh_nua, nh, kind, default_allow,			    TAG_END()) < 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;}/** @internal Add authorization data */int nh_authorize(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...){  int retval = 0;  tagi_t const *ti;  ta_list ta;  ta_start(ta, tag, value);  for (ti = ta_args(ta); ti; ti = tl_next(ti)) {    if (ti->t_tag == nutag_auth && ti->t_value) {      char *data = (char *)ti->t_value;      int rv = auc_credentials(&nh->nh_auth, nh->nh_home, data);      if (rv > 0) {	retval = 1;      }      else if (rv < 0) {	retval = -1;	break;      }    }  }  ta_end(ta);  return retval;}/**@internal * Collect challenges from response. * * @return Number of updated challenges, 0 if no updates found. * @retval -1 upon error. */staticint nh_challenge(nua_handle_t *nh, sip_t const *sip){  int server = 0, proxy = 0;  if (sip->sip_www_authenticate)    server = auc_challenge(&nh->nh_auth, nh->nh_home,			   sip->sip_www_authenticate,			   sip_authorization_class);  if (sip->sip_proxy_authenticate)    proxy = auc_challenge(&nh->nh_auth, nh->nh_home,			  sip->sip_proxy_authenticate,			  sip_proxy_authorization_class);  if (server < 0 || proxy < 0)    return -1;  return server + proxy;}/**@internal * Create a request message. * * @param nua * @param nh * @param cr * @param restart * @param method * @param name * @param tag, value, ... list of tag-value pairs */msg_t *nua_creq_msg(nua_t *nua,		    nua_handle_t *nh,		    struct nua_client_request *cr,		    int restart,		    sip_method_t method, char const *name,		    tag_type_t tag, tag_value_t value, ...){  struct nua_dialog_state *ds = nh->nh_ds;  msg_t *msg;  sip_t *sip;  ta_list ta;  url_string_t const *url = NULL;  long seq = -1;  int copy = 1, use_dialog = 0, add_contact = 0, add_service_route;  /* If restarting, use existing message */  if (restart) {    msg = cr->cr_msg; sip = sip_object(msg);    /* Trying to restart different method? */    if (sip && method && sip->sip_request->rq_method != method) {      SU_DEBUG_3(("nua(%p): trying to %s "		  "but there is already %s waiting to restart\n",		  nh, name, sip->sip_request->rq_method_name));      restart = 0, msg = NULL; sip = NULL;    }    /* Remove CSeq */    if (sip && sip->sip_cseq)      sip_header_remove(msg, sip, (sip_header_t *)sip->sip_cseq);    if (sip && sip->sip_request)      method = sip->sip_request->rq_method,	name = sip->sip_request->rq_method_name;  }  if (!restart) {    if (cr->cr_msg) {      /* If method is ACK or CANCEL, use existing CSeq */      if (method == sip_method_ack || method == sip_method_cancel) {	sip_t *nh_sip = sip_object(cr->cr_msg);	if (nh_sip && nh_sip->sip_cseq)	  seq = nh_sip->sip_cseq->cs_seq;	/* ACK/CANCEL cannot be restarted so we do not copy message */	copy = 0;      }      else	msg_destroy(cr->cr_msg), cr->cr_msg = NULL;    }    msg = nta_msg_create(nua->nua_nta, 0);    tl_gets(nh->nh_tags, NUTAG_URL_REF(url), TAG_END());    sip_add_tl(msg, sip_object(msg), TAG_NEXT(nh->nh_tags));  }  ta_start(ta, tag, value);  sip = sip_object(msg);  if (!sip)    goto error;  {    tl_gets(ta_args(ta),	    NUTAG_URL_REF(url),	    NUTAG_USE_DIALOG_REF(use_dialog),	    /* NUTAG_COPY_REF(copy), */	    NUTAG_ADD_CONTACT_REF(add_contact),	    TAG_END());    if (method == sip_method_register && url == NULL) {      tl_gets(ta_args(ta), NUTAG_REGISTRAR_REF(url), TAG_END());      if (url == NULL)	tl_gets(nh->nh_tags, NUTAG_REGISTRAR_REF(url), TAG_END());      if (url == NULL)	url = (url_string_t *)nua->nua_registrar;    }    if (seq != -1) {      sip_cseq_t *cseq =	sip_cseq_create(msg_home(msg), seq, method, name);      sip_header_insert(msg, sip, (sip_header_t *)cseq);    }    if (ds->ds_leg) {      add_service_route = 0;      /* If leg has established route, use it, not original URL */      if (ds->ds_route)	url = NULL;      if (sip_add_tl(msg, sip, ta_tags(ta)) < 0 ||	  nta_msg_request_complete(msg, ds->ds_leg, method, name, url) < 0)	goto error;    }    else {      if (sip_add_tl(msg, sip, ta_tags(ta)) < 0	  || (ds->ds_remote_tag &&	      sip_to_tag(nh->nh_home, sip->sip_to, ds->ds_remote_tag) < 0)	  || nta_msg_request_complete(msg, nua->nua_dhandle->nh_ds->ds_leg,				      method, name, url) < 0	  || (sip->sip_from == NULL &&	      sip_add_dup(msg, sip, (sip_header_t *)nua->nua_from) < 0))	goto error;      if (use_dialog) {	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_from),				     SIPTAG_TO(sip->sip_to),				     SIPTAG_CSEQ(sip->sip_cseq),				     TAG_END());	if (!ds->ds_leg)	  goto error;	if (!sip->sip_from->a_tag &&	    sip_from_tag(msg_home(msg), sip->sip_from,			 nta_leg_tag(ds->ds_leg, NULL)) < 0)	  goto error;      }      add_service_route = !restart;    }    /*     * If application did not specify an empty contact,     * use contact generated by stack.     */    if (!add_contact ||	sip->sip_contact ||	tl_find(nh->nh_tags, siptag_contact) ||	tl_find(nh->nh_tags, siptag_contact_str) ||	tl_find(ta_args(ta), siptag_contact) ||	tl_find(ta_args(ta), siptag_contact_str))      add_contact = 0;    if (add_contact || add_service_route) {      if (nua_registration_add_contact(nh, msg, sip, 				       add_contact, add_service_route) < 0)	goto error;    }    if (!sip->sip_user_agent && NH_PGET(nh, user_agent))      sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, user_agent));    if (method != sip_method_ack) {      if (!sip->sip_allow && !ds->ds_remote_tag)	sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow));      if (!sip->sip_supported && NH_PGET(nh, supported))	sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported));      if (method == sip_method_register && NH_PGET(nh, path_enable) &&	  !sip_has_feature(sip->sip_supported, "path") &&	  !sip_has_feature(sip->sip_require, "path"))	sip_add_make(msg, sip, sip_supported_class, "path");      if (!sip->sip_organization && NH_PGET(nh, organization))	sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, organization));      if (nh->nh_auth) {	nh_authorize(nh, ta_tags(ta));	if (method != sip_method_invite &&	    method != sip_method_update &&	    /* auc_authorize() removes existing authentication headers */	    auc_authorize(&nh->nh_auth, msg, sip) < 0)	  goto error;      }    }    else /* ACK */ {      while (sip->sip_allow)	sip_header_remove(msg, sip, (sip_header_t*)sip->sip_allow);      while (sip->sip_priority)	sip_header_remove(msg, sip, (sip_header_t*)sip->sip_priority);      while (sip->sip_proxy_require)	sip_header_remove(msg, sip, (sip_header_t*)sip->sip_proxy_require);      while (sip->sip_require)	sip_header_remove(msg, sip, (sip_header_t*)sip->sip_require);      while (sip->sip_subject)	sip_header_remove(msg, sip, (sip_header_t*)sip->sip_subject);      while (sip->sip_supported)	sip_header_remove(msg, sip, (sip_header_t*)sip->sip_supported);    }    ta_end(ta);

⌨️ 快捷键说明

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