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

📄 nua_session.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 5 页
字号:
	  session_include_description(nh->nh_soa, msg, sip) < 0) {	reason = soa_error_as_sip_reason(nh->nh_soa);	status = 900, phrase = "Internal media error";	reason = "SIP;cause=500;text=\"Internal media error\"";      }      else {	cr->cr_answer_sent = 1;	soa_activate(nh->nh_soa, NULL);	/* signal that O/A round is complete */	sent = "answer";      }    }    if (!reason &&	/* ss->ss_offer_sent && !ss->ss_answer_recv */	!soa_is_complete(nh->nh_soa)) {      /* No SDP answer in 2XX response -> terminate call */      status = 988, phrase = "Incomplete offer/answer";      reason = "SIP;cause=488;text=\"Incomplete offer/answer\"";    }  }  if (sip)    ack = nta_outgoing_mcreate(nua->nua_nta, NULL, NULL, NULL, msg,			       SIPTAG_END(), TAG_NEXT(tags));  if (!ack) {    if (!reason) {      status = 900, phrase = "Cannot send ACK";      reason = "SIP;cause=500;text=\"Internal Error\"";    }    msg_destroy(msg);  }  nua_creq_deinit(cr, NULL);	/* Destroy INVITE transaction */  nta_outgoing_destroy(ack);	/* TR engine keeps this around for T2 */  if (status < 300) {    signal_call_state_change(nh, status, phrase, nua_callstate_ready,			     received, sent);  }  else {    signal_call_state_change(nh, status, phrase, nua_callstate_terminating,			     0, 0);    nua_stack_post_signal(nh, nua_r_bye,			  SIPTAG_REASON_STR(reason),			  TAG_END());  }  return 0;}static intprocess_100rel(nua_handle_t *nh,	       nta_outgoing_t *orq,	       sip_t const *sip){  struct nua_session_state *ss = nh->nh_ss;  struct nua_client_request *cr_invite = ss->ss_crequest;  struct nua_client_request *cr_prack = nh->nh_cr;  /* Reliable provisional response */  sip_content_disposition_t *cd = NULL;  sip_content_type_t *ct = NULL;  sip_payload_t *pl = NULL;  nta_outgoing_t *prack;  char const *recv = NULL, *sent = NULL;  int status = 408;  int offer_sent_in_prack = 0, answer_sent_in_prack = 0;  su_home_t home[1] = { SU_HOME_INIT(home) };  if (cr_prack->cr_orq) {    SU_DEBUG_3(("nua(%p): cannot send PRACK because %s is pending\n", nh,		nta_outgoing_method_name(cr_prack->cr_orq)));    return 0;			/* We have to wait! */  }  if (sip && sip->sip_status)    status = sip->sip_status->st_status;  if (!nua_dialog_is_established(nh->nh_ds)) {    /* Tag the INVITE request */    nua_dialog_uac_route(nh, nh->nh_ds, sip, 1);    nua_dialog_store_peer_info(nh, nh->nh_ds, sip);    cr_invite->cr_orq =      nta_outgoing_tagged(orq, process_response_to_invite, nh,			  sip->sip_to->a_tag, sip->sip_rseq);    nta_outgoing_destroy(orq);    orq = cr_invite->cr_orq;  }  if (session_process_response(nh, cr_invite, orq, sip, &recv) < 0) {    /* XXX */  }  else if (cr_invite->cr_offer_recv && !cr_invite->cr_answer_sent) {    if (soa_generate_answer(nh->nh_soa, NULL) < 0 ||	session_make_description(home, nh->nh_soa, &cd, &ct, &pl) < 0)      /* XXX */;    else {      answer_sent_in_prack = 1, sent = "answer";      soa_activate(nh->nh_soa, NULL);    }  }  else if (ss->ss_precondition && status == 183) { /* XXX */    if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0 ||	session_make_description(home, nh->nh_soa, &cd, &ct, &pl) < 0)      /* XXX */;    else      offer_sent_in_prack = 1, sent = "offer";  }  prack = nta_outgoing_prack(nh->nh_ds->ds_leg, orq,			     process_response_to_prack, nh, NULL,			     sip,			     SIPTAG_CONTENT_DISPOSITION(cd),			     SIPTAG_CONTENT_TYPE(ct),			     SIPTAG_PAYLOAD(pl),			     TAG_END());  if (prack) {    cr_prack->cr_event = nua_r_prack;    cr_prack->cr_orq = prack;    if (answer_sent_in_prack)      cr_invite->cr_answer_sent = 1;    else if (offer_sent_in_prack)      cr_prack->cr_offer_sent = 1;    signal_call_state_change(nh,			     sip->sip_status->st_status,			     sip->sip_status->st_phrase,			     nua_callstate_proceeding, recv, sent);  }  else {    /* XXX - call state? */    nua_stack_event(nh->nh_nua, nh, NULL, nua_i_error,		    900, "Cannot PRACK",		    TAG_END());  }  su_home_deinit(home);  return 0;}static intprocess_response_to_prack(nua_handle_t *nh,			  nta_outgoing_t *orq,			  sip_t const *sip){  struct nua_client_request *cr = nh->nh_cr;  int status;  char const *phrase = "OK", *reason = NULL, *recv = NULL;  if (sip)    status = sip->sip_status->st_status, phrase = sip->sip_status->st_phrase;  else    status = 408, phrase = sip_408_Request_timeout;  SU_DEBUG_5(("nua: process_response_to_prack: %u %s\n", status, phrase));#if 0  if (nua_creq_check_restart(nh, cr, orq, sip, restart_prack))    return 0;#endif  if (status < 200)    return 0;  if (status < 300) {    if (session_process_response(nh, cr, orq, sip, &recv) < 0) {      status = 900, phrase = "Malformed Session in Response";      reason = "SIP;status=400;phrase=\"Malformed Session in Response\"";    }  }  else    nua_stack_process_response(nh, cr, orq, sip, TAG_END());  if (recv)    signal_call_state_change(nh, status, phrase,			     nua_callstate_proceeding, recv, NULL);  if (status < 300 && nh->nh_ss->ss_update_needed)    nua_stack_update(nh->nh_nua, nh, nua_r_update, NULL);  return 0;}staticchar const reason_timeout[] = "SIP;cause=408;text=\"Session timeout\"";void cancel_invite(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now){  static tagi_t const timeout_tags[] = {    { siptag_reason_str, (tag_value_t)reason_timeout },    { NULL }  };  signal_call_state_change(nh, 487, "Call Canceled",			   nua_callstate_init, NULL, NULL);  nua_stack_cancel(nh->nh_nua, nh, nua_r_destroy, timeout_tags);}voidrefresh_invite(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now){  tagi_t tags[2] =     {{ SIPTAG_SUBJECT_STR("Session refresh") }, { TAG_END() }};  if (now > 0 && NH_PGET(nh, update_refresh))    nua_stack_update(nh->nh_nua, nh, nua_r_update, tags);  else if (now > 0)    nua_stack_invite(nh->nh_nua, nh, nua_r_invite, tags);  else    session_timeout(nh, du, SIP_TIME_MAX);}static voidsession_timeout(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now){  if (now > 1) {    signal_call_state_change(nh, 408, "Session Timeout",			     nua_callstate_terminating, NULL, NULL);    nua_stack_post_signal(nh, nua_r_bye,			  SIPTAG_REASON_STR(reason_timeout),			  TAG_END());  }}/** Restart invite (e.g., after 302 or 407) */voidrestart_invite(nua_handle_t *nh, tagi_t *tags){  ua_invite2(nh->nh_nua, nh, nua_r_invite, 1, tags);}static int process_response_to_cancel(nua_handle_t *nh,				      nta_outgoing_t *orq,				      sip_t const *sip);/* CANCEL */intnua_stack_cancel(nua_t *nua, nua_handle_t *nh, nua_event_t e,		 tagi_t const *tags){  nua_session_state_t *ss = nh->nh_ss;  nua_client_request_t *cri = ss->ss_crequest;  nua_client_request_t *crc = nh->nh_cr;  if (nh && cri->cr_orq && cri->cr_usage &&      cri->cr_usage->du_pending == cancel_invite) {    nua_dialog_usage_t *du = cri->cr_usage;    nta_outgoing_t *orq;    du->du_pending = NULL;    /* nh_referral_respond(nh, SIP_487_REQUEST_TERMINATED); */    if (e)      orq = nta_outgoing_tcancel(cri->cr_orq, process_response_to_cancel, nh,				 TAG_NEXT(tags));    else      orq = nta_outgoing_tcancel(cri->cr_orq, NULL, NULL, TAG_NEXT(tags));    if (orq == NULL)      return nua_stack_event(nua, nh, NULL, e, 400, "Internal error",			     TAG_END());    if (e && crc->cr_orq == NULL)      crc->cr_orq = orq, crc->cr_event = e;    return 0;  }  return UA_EVENT2(e, 481, "No transaction to CANCEL");}static int process_response_to_cancel(nua_handle_t *nh,				      nta_outgoing_t *orq,				      sip_t const *sip){  return nua_stack_process_response(nh, nh->nh_cr, orq, sip, TAG_END());}/* ---------------------------------------------------------------------- *//* UAS side of INVITE */static void respond_to_invite(nua_t *nua, nua_handle_t *nh,			      int status, char const *phrase,			      tagi_t const *tags);static int  process_invite1(nua_t *, nua_handle_t**, nta_incoming_t *, msg_t *, sip_t *),  process_invite2(nua_t *, nua_handle_t *, nta_incoming_t *, sip_t *),  process_prack(nua_handle_t *, nta_reliable_t *, nta_incoming_t *,		sip_t const *),  process_ack_or_cancel(nua_handle_t *, nta_incoming_t *, sip_t const *),  process_ack(nua_handle_t *, nta_incoming_t *, sip_t const *),  process_cancel(nua_handle_t *, nta_incoming_t *, sip_t const *),  process_timeout(nua_handle_t *, nta_incoming_t *);/** @internal Process incoming INVITE. */int nua_stack_process_invite(nua_t *nua,			     nua_handle_t *nh0,			     nta_incoming_t *irq,			     sip_t const *sip){  nua_handle_t *nh = nh0;  msg_t *msg = nta_incoming_getrequest(irq);  int status;  status = process_invite1(nua, &nh, irq, msg, (sip_t *)sip);  if (status) {    msg_destroy(msg);    if (nh != nh0)      nh_destroy(nua, nh);    return status;  }  return process_invite2(nua, nh, irq, (sip_t *)sip);}/** @internal Preprocess incoming invite - sure we have a valid request. */staticint process_invite1(nua_t *nua,		    nua_handle_t **return_nh,		    nta_incoming_t *irq,		    msg_t *msg,		    sip_t *sip){  nua_handle_t *nh = *return_nh;  nua_handle_t *dnh = nua->nua_dhandle, *nh0 = nh ? nh : dnh;  nua_server_request_t *sr;  int have_sdp;  char const *sdp;  size_t len;  sip_user_agent_t const *user_agent = NH_PGET(nh0, user_agent);#if HAVE_SOFIA_SMIME  int sm_status;  sm_status = sm_decode_message(nua->sm, msg, sip);  switch(sm_status) {  case SM_SMIME_DISABLED:  case SM_ERROR:    nta_incoming_treply(irq, 493, "Undecipherable", TAG_END());    return 493;  case SM_SUCCESS:    break;  default:    break;  }#endif  if (nh0->nh_soa) {    /* Make sure caller uses application/sdp without compression */    if (nta_check_session_content(irq, sip,				  nua->nua_invite_accept,				  SIPTAG_USER_AGENT(user_agent),				  SIPTAG_ACCEPT_ENCODING_STR(""),				  TAG_END()))      return 415;    /* Make sure caller accepts application/sdp */    if (nta_check_accept(irq, sip,			 nua->nua_invite_accept,			 NULL,			 SIPTAG_USER_AGENT(user_agent),			 SIPTAG_ACCEPT_ENCODING_STR(""),			 TAG_END()))      return 406;  }  if (sip->sip_session_expires) {    unsigned min_se = nh ? nh->nh_ss->ss_min_se : DNH_PGET(dnh, min_se);    if (nta_check_session_expires(irq, sip,				  min_se,				  SIPTAG_USER_AGENT(user_agent),				  TAG_END()))      return 500; /* respond with 500 Internal Server Error  */  }  if (!nh) {    if (!DNH_PGET(dnh, invite_enable))      return 403;    if (!(nh = nua_stack_incoming_handle(nua, irq, sip, nh_has_invite, 1)))      return 500;  }  have_sdp = session_get_description(msg, sip, &sdp, &len);  if (nh->nh_ss->ss_srequest->sr_irq      /* XXX || (have_sdp && nh->nh_sr->sr_offer_recv) XXX */) {    /* Overlapping invites - RFC 3261 14.2 */    sip_retry_after_t af[1];    /* Random delay of 0..10 seconds */    sip_retry_after_init(af)->af_delta = (unsigned)random() % 11U;    af->af_comment = "Overlapping INVITE Request";    nta_incoming_treply(irq, 500, af->af_comment,			SIPTAG_RETRY_AFTER(af),			TAG_END());    return 500;  }  if (nh->nh_ss->ss_crequest->cr_orq ||      (have_sdp && nh->nh_cr->cr_orq && nh->nh_cr->cr_offer_sent)) {    /* Glare - RFC 3261 14.2 and RFC 3311 section 5.2 */    nta_incoming_treply(irq, SIP_491_REQUEST_PENDING, TAG_END());    return 491;  }  *return_nh = nh;  sr = nh->nh_ss->ss_srequest; memset(sr, 0, sizeof *sr);  if (nh->nh_soa) {    soa_init_offer_answer(nh->nh_soa);    if (have_sdp) {      if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) {	SU_DEBUG_5(("nua(%p): error parsing SDP in INVITE\n", nh));	nta_incoming_treply(irq, 400, "Bad Session Description", TAG_END());	return 400;      }      sr->sr_offer_recv = 1;    }  }  /** Add a dialog usage */  if (!nh->nh_ss->ss_usage)    nh->nh_ss->ss_usage =      nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL);  if (!nh->nh_ss->ss_usage) {    nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());    return 500;  }  sr->sr_msg = msg;  sr->sr_irq = irq;  return 0;}/** @internal Process incoming invite - initiate media, etc. */staticint process_invite2(nua_t *nua,		    nua_handle_t *nh,		    nta_incoming_t *irq,		    sip_t *sip){  nua_session_state_t *ss = nh->nh_ss;  nua_server_request_t *sr = ss->ss_srequest;  ss->ss_100rel = NH_PGET(nh, early_media);  ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition");  if (ss->ss_precondition)    ss->ss_100rel = 1;  /* Session Timer negotiation */  init_session_timer(nh, sip);  nua_dialog_uas_route(nh, nh->nh_ds, sip, 1);	/* Set route and tags */  nta_incoming_bind(irq, process_ack_or_cancel, nh);  assert(ss->ss_state >= nua_callstate_ready ||	 ss->ss_state == nua_callstate_init);  /* Magical value indicating autoanswer within respond_to_invite() */#define AUTOANSWER ((void*)-1)  if (NH_PGET(nh, auto_answer) ||      /* Auto-answert to re-INVITE unless auto_answer is set to 0 */      (ss->ss_state == nua_callstate_ready &&

⌨️ 快捷键说明

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