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

📄 nua_session.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 5 页
字号:
       !NH_PISSET(nh, auto_answer))) {    respond_to_invite(nua, nh, SIP_200_OK, AUTOANSWER);    return 0;  }  ss->ss_srequest->sr_respond = respond_to_invite;  if (NH_PGET(nh, auto_alert)) {    if (ss->ss_100rel &&	(sip_has_feature(nh->nh_ds->ds_remote_ua->nr_supported, "100rel") ||	 sip_has_feature(nh->nh_ds->ds_remote_ua->nr_require, "100rel"))) {      respond_to_invite(nua, nh, SIP_183_SESSION_PROGRESS, AUTOANSWER);    }    else {      respond_to_invite(nua, nh, SIP_180_RINGING, AUTOANSWER);    }  }  else {    nta_incoming_treply(irq, SIP_100_TRYING, TAG_END());    nua_stack_event(nh->nh_nua, nh, sr->sr_msg,	     nua_i_invite, SIP_100_TRYING,	     NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa),	     TAG_END());    sr->sr_msg = NULL;    signal_call_state_change(nh, SIP_100_TRYING,			     nua_callstate_received,			     sr->sr_offer_recv ? "offer" : 0, 0);  }  return 0;}/** @internal Respond to an INVITE request. * * XXX - use tags to indicate when to use reliable responses. * XXX - change prototype. */staticvoid respond_to_invite(nua_t *nua, nua_handle_t *nh,		       int status, char const *phrase,		       tagi_t const *tags){  su_home_t home[1] = { SU_HOME_INIT(home) };  msg_t *msg;  sip_t *sip;  int reliable;  int original_status = status;  sip_warning_t *warning = NULL;  nua_dialog_state_t *ds = nh->nh_ds;  nua_session_state_t *ss = nh->nh_ss;  nua_server_request_t *sr = ss->ss_srequest;  int autoanswer = 0, offer = 0, answer = 0;    enter;  if (ss->ss_srequest->sr_irq == NULL ||      nta_incoming_status(ss->ss_srequest->sr_irq) >= 200) {    nua_stack_event(nh->nh_nua, nh, NULL,	     nua_i_error, 900, "No INVITE request to response", TAG_END());    return;  }  if (tags == AUTOANSWER)    autoanswer = 1, tags = NULL;  assert(ss->ss_usage);  if (nh->nh_soa)    soa_set_params(nh->nh_soa, TAG_NEXT(tags));  reliable =    (status >= 200)    || (status > 100 &&	ds->ds_remote_ua->nr_require &&	sip_has_feature(ds->ds_remote_ua->nr_require, "100rel"))    || (status > 100 && !NH_PGET(nh, only183_100rel) && 	(NH_PGET(nh, early_media) ||	 (ds->ds_remote_ua->nr_require &&	  sip_has_feature(ds->ds_remote_ua->nr_require, "precondition"))) && 	ds->ds_remote_ua->nr_supported &&	sip_has_feature(ds->ds_remote_ua->nr_supported, "100rel"))    || (status == 183 &&	ds->ds_remote_ua->nr_supported &&	sip_has_feature(ds->ds_remote_ua->nr_supported, "100rel"))    || (status == 183 &&	ds->ds_remote_ua->nr_require &&	sip_has_feature(ds->ds_remote_ua->nr_require, "precondition"))    || (status > 100 &&	ds->ds_remote_ua->nr_require &&	sip_has_feature(ds->ds_remote_ua->nr_require, "precondition") &&	sr->sr_offer_recv && !sr->sr_answer_sent);  msg = nh_make_response(nua, nh, ss->ss_srequest->sr_irq,			 status, phrase,			 TAG_IF(status < 300, NUTAG_ADD_CONTACT(1)),			 SIPTAG_SUPPORTED(NH_PGET(nh, supported)),			 TAG_NEXT(tags));  sip = sip_object(msg);  assert(sip);			/* XXX */  if (!nh->nh_soa)    /* Xyzzy */;  else if (status >= 300) {    soa_clear_remote_sdp(nh->nh_soa);  }  else if (status >= 200 || ss->ss_100rel) {    if ((sr->sr_offer_recv && sr->sr_answer_sent) ||	(sr->sr_offer_sent && !sr->sr_answer_recv))      /* Nothing to do */;    else if (sr->sr_offer_recv && !sr->sr_answer_sent) {      if (soa_generate_answer(nh->nh_soa, NULL) < 0) {	int wcode;	char const *text;	char const *host = "invalid.";	status = soa_error_as_sip_response(nh->nh_soa, &phrase);	wcode = soa_get_warning(nh->nh_soa, &text);	if (wcode) {	  if (sip->sip_contact)	    host = sip->sip_contact->m_url->url_host;	  warning = sip_warning_format(home, "%u %s \"%s\"",				       wcode, host, text);	}      }      else {	answer = 1;	soa_activate(nh->nh_soa, NULL);	/* signal that O/A answer sent (answer to invite) */      }    }    else if (!sr->sr_offer_recv && !sr->sr_offer_sent) {      if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0)	status = soa_error_as_sip_response(nh->nh_soa, &phrase);      else	offer = 1;    }    if (offer || answer) {      if (session_include_description(nh->nh_soa, msg, sip) < 0)	SET_STATUS1(SIP_500_INTERNAL_SERVER_ERROR);    }  }  if (ss->ss_refresher && 200 <= status && status < 300)    use_session_timer(nh, 1, msg, sip);#if HAVE_SOFIA_SMIME  if (nua->sm->sm_enable && sdp) {    int sm_status;    sm_status = sm_encode_message(nua->sm, msg, sip, SM_ID_NULL);    switch (sm_status) {    case SM_SUCCESS:      break;    case SM_ERROR:      status = 500, phrase = "S/MIME processing error";      break;    case SM_CERT_NOTFOUND:    case SM_CERTFILE_NOTFOUND:      status = 500, phrase = "S/MIME certificate error";      break;    }  }#endif  if (reliable && status < 200) {    nta_reliable_t *rel;    rel = nta_reliable_mreply(ss->ss_srequest->sr_irq,			      process_prack, nh, msg);    if (!rel)      SET_STATUS1(SIP_500_INTERNAL_SERVER_ERROR);  }  if (reliable && status < 200)    /* we are done */;  else if (status != original_status) {    /* Error responding */    assert(status >= 200);    ss->ss_srequest->sr_respond = NULL;    nta_incoming_treply(ss->ss_srequest->sr_irq,			status, phrase,			SIPTAG_WARNING(warning),			TAG_END());    msg_destroy(msg), msg = NULL;  }  else {    if (status >= 200)      ss->ss_srequest->sr_respond = NULL;    nta_incoming_mreply(ss->ss_srequest->sr_irq, msg);  }  if (autoanswer) {    nua_stack_event(nh->nh_nua, nh, sr->sr_msg,	     nua_i_invite, status, phrase,	     NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa),	     TAG_END());    sr->sr_msg = NULL;  }  else if (status != original_status)    nua_stack_event(nua, nh, NULL, nua_i_error, status, phrase, TAG_END());  if (status >= 300)    offer = 0, answer = 0;  if (offer)    sr->sr_offer_sent = 1;  else if (answer)    sr->sr_answer_sent = 1 + reliable;  /* Update session state */  assert(ss->ss_state != nua_callstate_calling);  assert(ss->ss_state != nua_callstate_proceeding);  signal_call_state_change(nh, status, phrase,			   status >= 300			   ? nua_callstate_init			   : status >= 200			   ? nua_callstate_completed			   : nua_callstate_early,			   autoanswer && sr->sr_offer_recv ? "offer" : 0,			   offer ? "offer" : answer ? "answer" : 0);  if (status == 180)    ss->ss_alerting = 1;  else if (status >= 200)    ss->ss_alerting = 0;  if (status >= 200) {    ss->ss_usage->du_ready = 1;  }  if (status >= 300) {    if (nh->nh_soa)      soa_init_offer_answer(nh->nh_soa);    nta_incoming_destroy(ss->ss_srequest->sr_irq);    ss->ss_srequest->sr_irq = NULL;    ss->ss_srequest->sr_respond = NULL;  }  su_home_deinit(home);  if (ss->ss_state == nua_callstate_init)    nsession_destroy(nh);}/** @internal Process ACK or CANCEL or timeout (no ACK) for incoming INVITE */staticint process_ack_or_cancel(nua_handle_t *nh,			  nta_incoming_t *irq,			  sip_t const *sip){  int retval;  nua_server_request_t *sr = nh->nh_ss->ss_srequest;  enter;  if (sip && sip->sip_request->rq_method == sip_method_ack)    retval = process_ack(nh, irq, sip);  else if (sip && sip->sip_request->rq_method == sip_method_cancel)    retval = process_cancel(nh, irq, sip);  else    retval = process_timeout(nh, irq);  assert(sr->sr_irq == irq);  nta_incoming_destroy(sr->sr_irq);  memset(sr, 0, sizeof *sr);  return retval;}/** @internal Process PRACK or (timeout from 100rel) */staticint process_prack(nua_handle_t *nh,		  nta_reliable_t *rel,		  nta_incoming_t *irq,		  sip_t const *sip){  struct nua_session_state *ss = nh->nh_ss;  nua_server_request_t *sr = ss->ss_srequest;  int status = 200; char const *phrase = sip_200_OK;  char const *recv = NULL, *sent = NULL;  nta_reliable_destroy(rel);  if (!sr->sr_irq) /* XXX  */    return 481;  if (sip)    /* received PRACK */;  else if (sr->sr_respond == NULL) { /* Final response interrupted 100rel */    /* Ignore */    return 200;  }  else if (sip == NULL) {    SET_STATUS(504, "Reliable Response Timeout");    respond_to_invite(nh->nh_nua, nh, status, phrase, NULL);    nua_stack_event(nh->nh_nua, nh, NULL,		    nua_i_error, status, phrase, TAG_END());    return status;  }  if (nh->nh_soa) {    msg_t *msg = nta_incoming_getrequest(irq);    char const *sdp;    size_t len;    if (session_get_description(msg, sip, &sdp, &len)) {      su_home_t home[1] = { SU_HOME_INIT(home) };      sip_content_disposition_t *cd = NULL;      sip_content_type_t *ct = NULL;      sip_payload_t *pl = NULL;      if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) {	SU_DEBUG_5(("nua(%p): error parsing SDP in INVITE\n", nh));	msg_destroy(msg);	status = 400, phrase = "Bad Session Description";      }      /* Respond to PRACK */      if (status >= 300)	;      else if (sr->sr_offer_sent) {	recv = "answer";	sr->sr_answer_recv = 1;	if (soa_process_answer(nh->nh_soa, NULL) < 0)	  status = soa_error_as_sip_response(nh->nh_soa, &phrase);      }      else {	recv = "offer";	if (soa_generate_answer(nh->nh_soa, NULL) < 0) {	  status = soa_error_as_sip_response(nh->nh_soa, &phrase);	}	else {	  session_make_description(home, nh->nh_soa, &cd, &ct, &pl);	  sent = "answer";	}      }      if (nta_incoming_treply(irq, status, phrase,			      SIPTAG_CONTENT_DISPOSITION(cd),			      SIPTAG_CONTENT_TYPE(ct),			      SIPTAG_PAYLOAD(pl),			      TAG_END()) < 0)	/* Respond with 500 if nta_incoming_treply() failed */	SET_STATUS1(SIP_500_INTERNAL_SERVER_ERROR);      su_home_deinit(home);    }    msg_destroy(msg);  }  nua_stack_event(nh->nh_nua, nh, nta_incoming_getrequest(irq),		  nua_i_prack, status, phrase, TAG_END());  if (status < 300 && (recv || sent)) {    soa_activate(nh->nh_soa, NULL);    signal_call_state_change(nh, status, phrase,			     nua_callstate_early, recv, sent);  }  if (status < 300 &&      NH_PGET(nh, auto_alert) && !ss->ss_alerting && !ss->ss_precondition)    respond_to_invite(nh->nh_nua, nh, SIP_180_RINGING, NULL);  return status;}int process_ack(nua_handle_t *nh,		nta_incoming_t *irq,		sip_t const *sip){  struct nua_session_state *ss = nh->nh_ss;  nua_server_request_t *sr = ss->ss_srequest;  msg_t *msg = nta_incoming_getrequest_ackcancel(irq);  char const *recv = NULL;  if (nh->nh_soa && sr->sr_offer_sent && !sr->sr_answer_recv) {    char const *sdp;    size_t len;    if (!session_get_description(msg, sip, &sdp, &len) ||	!(recv = "answer") ||	soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0 ||	soa_process_answer(nh->nh_soa, NULL) < 0 ||	soa_activate(nh->nh_soa, NULL)) {      int status; char const *phrase, *reason;      status = soa_error_as_sip_response(nh->nh_soa, &phrase);      reason = soa_error_as_sip_reason(nh->nh_soa);      nua_stack_event(nh->nh_nua, nh, msg,	       nua_i_ack, status, phrase, TAG_END());      nua_stack_event(nh->nh_nua, nh, NULL,	       nua_i_media_error, status, phrase, TAG_END());      signal_call_state_change(nh, 488, "Offer-Answer Error",			       nua_callstate_terminating, recv, 0);      nua_stack_post_signal(nh, nua_r_bye,			    SIPTAG_REASON_STR(reason),			    TAG_END());      return 0;    }  }  soa_clear_remote_sdp(nh->nh_soa);  nua_stack_event(nh->nh_nua, nh, msg, nua_i_ack, SIP_200_OK, TAG_END());  signal_call_state_change(nh, 200, "OK", nua_callstate_ready, recv, 0);  set_session_timer(nh);  return 0;}/* CANCEL  */staticint process_cancel(nua_handle_t *nh,		   nta_incoming_t *irq,		   sip_t const *sip){  struct nua_session_state *ss = nh->nh_ss;  msg_t *msg = nta_incoming_getrequest_ackcancel(irq);  nua_stack_event(nh->nh_nua, nh, msg, nua_i_cancel, SIP_200_OK, TAG_END());  signal_call_state_change(nh, 0, "Received CANCEL", nua_callstate_init, 0, 0);  if (nh->nh_soa && ss->ss_state < nua_callstate_ready) {    soa_terminate(nh->nh_soa, NULL);    nsession_destroy(nh);  }  return 0;}/* Timeout (no ACK or PRACK received) */staticint process_timeout(nua_handle_t *nh,		    nta_incoming_t *irq){  struct nua_session_state *ss = nh->nh_ss;  nua_stack_event(nh->nh_nua, nh, 0, nua_i_error,	   408, "Response timeout",	   TAG_END());  soa_terminate(nh->nh_soa, NULL);  if (ss->ss_state == nua_callstate_ready) {    /* send BYE if 200 OK (or 183 to re-INVITE) timeouts  */    signal_call_state_change(nh, 0, "Timeout",			     nua_callstate_terminating, 0, 0);    nua_stack_post_signal(nh, nua_r_bye,		 SIPTAG_REASON_STR("SIP;cause=408;text=\"ACK Timeout\""),		 TAG_END());  }  else {    nta_incoming_treply(irq, SIP_504_GATEWAY_TIME_OUT,			SIPTAG_REASON_STR("SIP;cause=504;"					  "text=\"PRACK Timeout\""),			TAG_END());    signal_call_state_change(nh, 0, "Timeout",			     nua_callstate_init, 0, 0);  }  return 0;}/* ---------------------------------------------------------------------- *//* Session timer */

⌨️ 快捷键说明

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