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

📄 nua_stack.c

📁 Internet Phone, Chat, Conferencing
💻 C
📖 第 1 页 / 共 5 页
字号:
  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);  }}/* ======================================================================== *//** 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;}/** 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;}/** 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;}/** 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;}/** Create request message. * * @param nua * @param nh * @param method * @param name * @param tag @a 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;  url_string_t const *url = NULL;  long seq = -1;  int copy = 1;  /* 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;	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));  }  if (msg) {    ta_list ta;    int use_dialog = 0, add_contact = 0;    sip = sip_object(msg);    ta_start(ta, tag, value);    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) {      /* 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)	msg_destroy(msg), msg = NULL;    }    else {      // tl_gets(ta_args(ta), TAG_END());      if ((sip_add_tl(msg, sip,		      TAG_IF(method != sip_method_register,			     SIPTAG_ROUTE(nua->nua_service_route)),		      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))	msg_destroy(msg), msg = NULL;      if (use_dialog && msg) {	sip_route_t *route = sip->sip_route;	if (method == sip_method_invite ||	    method == sip_method_subscribe ||	    method == sip_method_notify)	  route = NULL;	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_ROUTE(route),				     SIPTAG_CSEQ(sip->sip_cseq),				     TAG_END());	if (!sip->sip_from->a_tag) {	  nta_leg_tag(ds->ds_leg, NULL);	  sip_from_tag(msg_home(msg),		       sip->sip_from,		       nta_leg_get_tag(ds->ds_leg));	}	/* XXX - check error */      }    }    if (add_contact && msg && !sip->sip_contact) {      /* We are missing contact */      /* If application did not specify an empty contact, use ours */      if (!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)) {	if (sip->sip_request->rq_url->url_type == url_sips &&	    nua->nua_sips_contact)	  sip_add_dup(msg, sip, (sip_header_t *)nua->nua_sips_contact);	else	  sip_add_dup(msg, sip, (sip_header_t *)nua->nua_contact);      }    }    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)	  msg_destroy(msg), msg = NULL;      }    }    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);    if (!ds->ds_remote)      ds->ds_remote = sip_to_dup(nh->nh_home, sip->sip_to);    if (!ds->ds_local)      ds->ds_local = sip_from_dup(nh->nh_home, sip->sip_from);    if (copy) {      cr->cr_msg = msg;      msg = msg_copy(msg);    }  }  return msg;}/** Create response message. * * @param nua * @param nh * @param irq * @param status * @param phrase * @param tag, @a value, ... list of tag-value pairs */msg_t *nh_make_response(nua_t *nua, nua_handle_t *nh,			nta_incoming_t *irq,			int status, char const *phrase,			tag_type_t tag, tag_value_t value, ...){  ta_list ta;  msg_t *msg = nta_msg_create(nua->nua_nta, 0);  sip_t *sip = sip_object(msg);  sip_header_t *m;  int add_contact = 0;  if (nta_incoming_url(irq)->url_type == url_sips && nua->nua_sips_contact)    m = (sip_header_t*)nua->nua_sips_contact;  else    m = (sip_header_t*)nua->nua_contact;  ta_start(ta, tag, value);  tl_gets(ta_args(ta),	  NUTAG_ADD_CONTACT_REF(add_contact),	  TAG_END());  if (!msg)    return NULL;  else if (nta_msg_response_complete(msg, irq, status, phrase) < 0)    msg_destroy(msg);  else if (sip_add_tl(msg, sip, ta_tags(ta)) < 0)    msg_destroy(msg);  else if (sip_complete_message(msg) < 0)    msg_destroy(msg);  else if (add_contact && !sip->sip_contact && sip_add_dup(msg, sip, m) < 0)    msg_destroy(msg);  else if (!sip->sip_supported && NH_PGET(nh, supported) &&	   sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported)) < 0)    msg_destroy(msg);  else if (!sip->sip_user_agent && NH_PGET(nh, user_agent) &&	   sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, user_agent)) < 0)    msg_destroy(msg);

⌨️ 快捷键说明

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