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

📄 nua_stack.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
void nh_destroy(nua_t *nua, nua_handle_t *nh){  assert(nh); assert(nh != nua->nua_dhandle);  if (nh->nh_notifier)    nea_server_destroy(nh->nh_notifier), nh->nh_notifier = NULL;  while (nh->nh_ds->ds_cr)    nua_client_request_destroy(nh->nh_ds->ds_cr);  while (nh->nh_ds->ds_sr)    nua_server_request_destroy(nh->nh_ds->ds_sr);  nua_dialog_deinit(nh, nh->nh_ds);  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 */}/* ======================================================================== *//**@internal * Save handle parameters and initial authentication info. * * @retval -1 upon an error * @retval 0 when successful */int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags){  int retval = 0;  if (nh == NULL)    return -1;  assert(nh != nua->nua_dhandle);  if (nua_stack_set_params(nua, nh, nua_i_error, tags) < 0)    retval = -1;  if (retval || nh->nh_init) /* Already initialized? */    return retval;  if (nh->nh_tags)    nh_authorize(nh, TAG_NEXT(nh->nh_tags));  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,					int create_dialog){  nua_handle_t *nh;  url_t const *url;  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;  /* Strip away parameters */  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), /* Remote target */		 SIPTAG_TO(to), /* Local AoR */		 SIPTAG_FROM(from), /* Remote AoR */		 TAG_END());  if (nh && nua_stack_init_handle(nua, nh, NULL) < 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;}/** Set flags and special event on handle. * * @retval 0 when successful * @retval -1 upon an error */int nua_stack_set_handle_special(nua_handle_t *nh,				 enum nh_kind kind,				 nua_event_t special){  if (nh == NULL)    return -1;  if (special && nh->nh_special && nh->nh_special != special)    return -1;  if (!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_nothing:    default:      break;    }    if (special)      nh->nh_special = special;  }  return 0;}sip_replaces_t *nua_stack_handle_make_replaces(nua_handle_t *nh, 					       su_home_t *home,					       int early_only){  if (nh && nh->nh_ds && nh->nh_ds->ds_leg)    return nta_leg_make_replaces(nh->nh_ds->ds_leg, home, early_only);  else    return NULL;}nua_handle_t *nua_stack_handle_by_replaces(nua_t *nua,					   sip_replaces_t const *r){  if (nua) {    nta_leg_t *leg = nta_leg_by_replaces(nua->nua_nta, r);    if (leg)      return nta_leg_magic(leg, nua_stack_process_request);  }  return NULL;}nua_handle_t *nua_stack_handle_by_call_id(nua_t *nua, const char *call_id){  if (nua) {    nta_leg_t *leg = nta_leg_by_call_id(nua->nua_nta, call_id);    if (leg)      return nta_leg_magic(leg, nua_stack_process_request);  }  return NULL;}/** @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;}su_inlineint can_redirect(sip_contact_t const *m, sip_method_t method){  if (m && m->m_url->url_host) {    enum url_type_e type = m->m_url->url_type;    return      type == url_sip ||      type == url_sips ||      (type == url_tel &&       (method == sip_method_invite || method == sip_method_message)) ||      (type == url_im && method == sip_method_message) ||      (type == url_pres && method == sip_method_subscribe);  }  return 0;}/* ======================================================================== *//* Authentication *//** @NUA_EVENT nua_r_authenticate * * Response to nua_authenticate(). Under normal operation, this event is * never sent but rather the unauthenticated operation is completed.  * However, if there is no operation to authentication or if there is an * authentication error the #nua_r_authenticate event is sent to the * application with the status code as follows: * - <i>202 No operation to restart</i>:\n *   The authenticator associated with the handle was updated, but there was *   no operation to retry with the new credentials. * - <i>900 Cannot add credentials</i>:\n *   There was internal problem updating authenticator. * - <i>904 No matching challenge</i>:\n *   There was no challenge matching with the credentials provided by *   nua_authenticate(), e.g., their realm did not match with the one  *   received with the challenge. *  * @param status status code from authentication  * @param phrase a short textual description of @a status code * @param nh     operation handle authenticated * @param hmagic application context associated with the handle * @param sip    NULL * @param tags   empty *  * @sa nua_terminate(), nua_handle_destroy() * * @END_NUA_EVENT */voidnua_stack_authenticate(nua_t *nua, nua_handle_t *nh, nua_event_t e,		       tagi_t const *tags){  nua_client_request_t *cr = nh->nh_ds->ds_cr;  int status = nh_authorize(nh, TAG_NEXT(tags));  if (status > 0) {    if (cr && cr->cr_wait_for_cred) {      cr->cr_waiting = cr->cr_wait_for_cred = 0;      nua_client_restart_request(cr, cr->cr_terminating, tags);    }    else {      nua_stack_event(nua, nh, NULL, e, 		      202, "No operation to restart",		      NULL);    }  }  else if (cr && cr->cr_wait_for_cred) {    cr->cr_waiting = cr->cr_wait_for_cred = 0;        if (status < 0)      nua_client_response(cr, 900, "Operation cannot add credentials", NULL);    else      nua_client_response(cr, 904, "Operation has no matching challenge ", NULL);  }  else if (status < 0) {    nua_stack_event(nua, nh, NULL, e, 900, "Cannot add credentials", NULL);  }  else {    nua_stack_event(nua, nh, NULL, e, 904, "No matching challenge", NULL);  }}/* ======================================================================== *//* * Process incoming requests */nua_server_methods_t const *nua_server_methods[] = {  /* These must be in same order as in sip_method_t */  &nua_extension_server_methods,  &nua_invite_server_methods,	/**< INVITE */  NULL,				/**< ACK */  NULL,				/**< CANCEL */  &nua_bye_server_methods,	/**< BYE */  &nua_options_server_methods,	/**< OPTIONS */  &nua_register_server_methods,	/**< REGISTER */  &nua_info_server_methods,	/**< INFO */  &nua_prack_server_methods,	/**< PRACK */  &nua_update_server_methods,	/**< UPDATE */  &nua_message_server_methods,	/**< MESSAGE */  &nua_subscribe_server_methods,/**< SUBSCRIBE */  &nua_notify_server_methods,	/**< NOTIFY */  &nua_refer_server_methods,	/**< REFER */  &nua_publish_server_methods,	/**< PUBLISH */  NULL};int nua_stack_process_request(nua_handle_t *nh,			      nta_leg_t *leg,			      nta_incoming_t *irq,			      sip_t const *sip){  nua_t *nua = nh->nh_nua;  sip_method_t method = sip->sip_request->rq_method;  char const *name = sip->sip_request->rq_method_name;  nua_server_methods_t const *sm;  nua_server_request_t *sr, sr0[1];  int status, initial = 1;  int create_dialog;  char const *user_agent = NH_PGET(nh, user_agent);  sip_supported_t const *supported = NH_PGET(nh, supported);  sip_allow_t const *allow = NH_PGET(nh, allow);  enter;  nta_incoming_tag(irq, NULL);  if (method == sip_method_cancel)    return 481;  /* Hook to outbound */  if (method == sip_method_options) {    status = nua_registration_process_request(nua->nua_registrations,					      irq, sip);    if (status)      return status;  }  if (nta_check_method(irq, sip, allow,		       SIPTAG_SUPPORTED(supported),		       SIPTAG_USER_AGENT_STR(user_agent),		       TAG_END()))    return 405;  switch (sip->sip_request->rq_url->url_type) {  case url_sip:  case url_sips:  case url_im:  case url_pres:  case url_tel:    break;  default:    nta_incoming_treply(irq, status = SIP_416_UNSUPPORTED_URI,			SIPTAG_ALLOW(allow),			SIPTAG_SUPPORTED(supported),			SIPTAG_USER_AGENT_STR(user_agent),			TAG_END());    return status;  }  if (nta_check_required(irq, sip, supported,			 SIPTAG_ALLOW(allow),			 SIPTAG_USER_AGENT_STR(user_agent),			 TAG_END()))    return 420;  if (method > sip_method_unknown && method <= sip_method_publish)    sm = nua_server_methods[method];  else    sm = nua_server_methods[0];  initial = nh == nua->nua_dhandle;  if (sm == NULL) {    SU_DEBUG_1(("nua(%p): strange %s from <" URL_PRINT_FORMAT ">\n",		(void *)nh, sip->sip_request->rq_method_name,		URL_PRINT_ARGS(sip->sip_from->a_url)));  }  else if (initial && sm->sm_flags.in_dialog) {    /* These must be in-dialog */    sm = NULL;  }  else if (initial && sip->sip_to->a_tag) {    /* RFC 3261 section 12.2.2:              If the UAS wishes to reject the request because it does not wish to       recreate the dialog, it MUST respond to the request with a 481       (Call/Transaction Does Not Exist) status code and pass that to the       server transaction.    */    if (method == sip_method_info)      /* accept out-of-dialog info */; else    if (method != sip_method_message || !NH_PGET(nh, win_messenger_enable))      sm = NULL;  }  if (!sm) {    nta_incoming_treply(irq,			status = 481, "Call Does Not Exist",			SIPTAG_ALLOW(allow),			SIPTAG_SUPPORTED(supported),			SIPTAG_USER_AGENT_STR(user_agent),			TAG_END());    return 481;  }  create_dialog = sm->sm_flags.create_dialog;  if (method == sip_method_message && NH_PGET(nh, win_messenger_enable))    create_dialog = 1;  sr = memset(sr0, 0, (sizeof sr0));  sr->sr_methods = sm;  sr->sr_method = method = sip->sip_request->rq_method;  sr->sr_add_contact = sm->sm_flags.add_contact;  sr->sr_target_refresh = sm->sm_flags.target_refresh;  sr->sr_owner = nh;  sr->sr_initial = initial;  sr->sr_irq = irq;  SR_STATUS1(sr, SIP_100_TRYING);  sr->sr_request.msg = nta_incoming_getrequest(irq);  sr->sr_request.sip = sip;  assert(sr->sr_request.msg);  sr->sr_response.msg = nta_incoming_create_response(irq, 0, NULL);  sr->sr_response.sip = sip_object(sr->sr_response.msg);  if (sr->sr_response.msg == NULL) {    SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);  }  else if (sm->sm_init && sm->sm_init(sr)) {    if (sr->sr_status < 200)    /* Init may have set response status */      SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);  }  /* Create handle if request does not fail */  else if (initial && sr->sr_status < 300) {    if ((nh = nua_stack_incoming_handle(nua, irq, sip, create_dialog)))      sr->sr_owner = nh;    else      SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);  }  if (sr->sr_status < 300 && sm->sm_preprocess && sm->sm_preprocess(sr)) {    if (sr->sr_status < 200)    /* Set response status if preprocess did not */      SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);  }  if (sr->sr_status < 300) {    if (sr->sr_target_refresh)      nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); /* Set route and tags */    nua_dialog_store_peer_info(nh, nh->nh_ds, sip);  }  if (sr->sr_status == 100 && method != sip_method_unknown &&      !sip_is_allowed(NH_PGET(sr->sr_owner, appl_method), method, name)) {    if (method == sip_method_refer || method == sip_method_subscribe)      SR_STATUS1(sr, SIP_202_ACCEPTED);    else      SR_STATUS1(sr, SIP_200_OK);  }  /* INVITE server request is not finalized after 2XX response */  if (sr->sr_status < (method == sip_method_invite ? 300 : 200)) {    sr = su_alloc(nh->nh_home, (sizeof *sr));    if (sr) {

⌨️ 快捷键说明

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