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

📄 nua_session.c

📁 Internet Phone, Chat, Conferencing
💻 C
📖 第 1 页 / 共 5 页
字号:
    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;}/** Respond to an INVITE request. * * XXX - use tags to indicate when to use reliable responses. * XXX - change prototype. */void 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;  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, 500, "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 == 183 &&	ds->ds_remote_ua->nr_supported &&	sip_has_feature(ds->ds_remote_ua->nr_supported, "100rel"))    || (status > 100 &&	ds->ds_remote_ua->nr_require &&	sip_has_feature(ds->ds_remote_ua->nr_require, "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)	status = soa_error_as_sip_response(nh->nh_soa, &phrase);      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)	status = 500, phrase = 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)      status = 500, phrase = 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,			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);}/** 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;}/** 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 */	status = 500, phrase = 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);  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 *//** Add timer featuretag and Session-Expires/Min-SE headers */static intuse_session_timer(nua_handle_t *nh, int uas, msg_t *msg, sip_t *sip){  struct nua_session_state *ss = nh->nh_ss;  sip_min_se_t min_se[1];  sip_session_expires_t session_expires[1];  static sip_param_t const x_params_uac[] = {"refresher=uac", NULL};  static sip_param_t const x_params_uas[] = {"refresher=uas", NULL};  /* Session-Expires timer */  if ((NH_PGET(nh, refresher) == 0 &&       NH_PGET(nh, session_timer) == 0) ||      /* Is timer feature supported? */      !sip_has_supported(NH_PGET(nh, supported), "timer"))    return 0;  sip_min_se_init(min_se)->min_delta = ss->ss_min_se;  sip_session_expires_init(session_expires)->x_delta = ss->ss_session_timer;  if (ss->ss_refresher == nua_remote_refresher)    session_expires->x_params = uas ? x_params_uac : x_params_uas;  else if (ss->ss_refresher == nua_local_refresher)    session_expires->x_params = uas ? x_params_uas : x_params_uac;  sip_add_tl(msg, sip,	     TAG_IF(ss->ss_session_timer,		    SIPTAG_SESSION_EXPIRES(session_expires)),	     TAG_IF(ss->ss_min_se != 0		    /* Min-SE: 0 is optional with initial INVITE */		    || ss->ss_state != nua_callstate_init,		    SIPTAG_MIN_SE(min_se)),	     TAG_IF(ss->ss_refresher == nua_remote_refresher,		    SIPTAG_REQUIRE_STR("timer")),

⌨️ 快捷键说明

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