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

📄 nua_session.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
    ss->ss_update_needed = ss->ss_100rel = 1;  if (nh->nh_soa) {    soa_init_offer_answer(nh->nh_soa);    if (sip->sip_payload)      offer_sent = 0;		/* XXX - kludge */    else if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0)      return -1;    else      offer_sent = 1;    if (offer_sent > 0 &&	session_include_description(nh->nh_soa, 1, msg, sip) < 0)      return nua_client_return(cr, 900, "Internal media error", msg);    if (NH_PGET(nh, media_features) &&	!nua_dialog_is_established(nh->nh_ds) &&	!sip->sip_accept_contact && !sip->sip_reject_contact) {      sip_accept_contact_t ac[1];      sip_accept_contact_init(ac);      ac->cp_params = (msg_param_t *)	soa_media_features(nh->nh_soa, 1, msg_home(msg));      if (ac->cp_params) {	msg_header_replace_param(msg_home(msg), ac->cp_common, "explicit");	sip_add_dup(msg, sip, (sip_header_t *)ac);      }    }  }  else {    offer_sent = session_get_description(sip, NULL, NULL);  }  retval = nua_base_client_trequest(cr, msg, sip,				    NTATAG_REL100(ss->ss_100rel),				    TAG_NEXT(tags));  if (retval == 0) {    if ((cr->cr_offer_sent = offer_sent))      ss->ss_oa_sent = Offer;    if (!cr->cr_restarting) /* Restart logic calls nua_invite_client_report */      signal_call_state_change(nh, ss, 0, "INVITE sent", 			       nua_callstate_calling);  }  return retval;}static int nua_invite_client_response(nua_client_request_t *cr,				      int status, char const *phrase,				      sip_t const *sip){  nua_dialog_usage_t *du = cr->cr_usage;  nua_session_usage_t *ss = nua_dialog_usage_private(du);  if (ss == NULL || sip == NULL) {    /* Xyzzy */  }  else if (status < 300) {    du->du_ready = 1;    if (session_timer_is_supported(ss->ss_timer))      session_timer_store(ss->ss_timer, sip);    session_timer_set(ss);  }    return nua_session_client_response(cr, status, phrase, sip);}static int nua_invite_client_preliminary(nua_client_request_t *cr,					 int status, char const *phrase,					 sip_t const *sip){  nua_handle_t *nh = cr->cr_owner;  nua_dialog_usage_t *du = cr->cr_usage;  nua_session_usage_t *ss = nua_dialog_usage_private(du);  assert(sip);  if (ss && sip && sip->sip_rseq) {    /* Handle 100rel responses */    sip_rseq_t *rseq = sip->sip_rseq;    /* Establish early dialog - we should fork here */    if (!nua_dialog_is_established(nh->nh_ds)) {      nta_outgoing_t *tagged;      nua_dialog_uac_route(nh, nh->nh_ds, sip, 1);      nua_dialog_store_peer_info(nh, nh->nh_ds, sip);            /* Tag the INVITE request */      tagged = nta_outgoing_tagged(cr->cr_orq,				   nua_client_orq_response, cr,				   sip->sip_to->a_tag, sip->sip_rseq);      if (tagged) {	nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = tagged;      }      else {	cr->cr_graceful = 1;	ss->ss_reason = "SIP;cause=500;text=\"Cannot Create Early Dialog\"";      }    }      if (!rseq) {      SU_DEBUG_5(("nua(%p): 100rel missing RSeq\n", (void *)nh));    }    else if (nta_outgoing_rseq(cr->cr_orq) > rseq->rs_response) {      SU_DEBUG_5(("nua(%p): 100rel bad RSeq %u (got %u)\n", (void *)nh, 		  (unsigned)rseq->rs_response,		  nta_outgoing_rseq(cr->cr_orq)));      return 1;    /* Do not send event */    }    else if (nta_outgoing_setrseq(cr->cr_orq, rseq->rs_response) < 0) {      SU_DEBUG_1(("nua(%p): cannot set RSeq %u\n", (void *)nh, 		  (unsigned)rseq->rs_response));      cr->cr_graceful = 1;      ss->ss_reason = "SIP;cause=400;text=\"Bad RSeq\"";    }  }  return nua_session_client_response(cr, status, phrase, sip);}/** Process response to a session request (INVITE, PRACK, UPDATE) */static int nua_session_client_response(nua_client_request_t *cr,				       int status, char const *phrase,				       sip_t const *sip){  nua_handle_t *nh = cr->cr_owner;  nua_dialog_usage_t *du = cr->cr_usage;  nua_session_usage_t *ss = nua_dialog_usage_private(du);  char const *sdp = NULL;  size_t len;  char const *received = NULL;#define LOG3(m) \  SU_DEBUG_3(("nua(%p): %s: %s %s in %u %s\n", \	      (void *)nh, cr->cr_method_name, (m), \	      received ? received : "SDP", status, phrase))#define LOG5(m) \  SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s\n", \	      (void *)nh, cr->cr_method_name, (m), received, status, phrase))  if (!ss || !sip || 300 <= status)    /* Xyzzy */;  else if (!session_get_description(sip, &sdp, &len))    /* No SDP */;  else if (cr->cr_answer_recv) {    /* Ignore spurious answers after completing O/A */    LOG3("ignoring duplicate");    sdp = NULL;  }  else if (cr->cr_offer_sent) {    /* case 1: answer to our offer */    cr->cr_answer_recv = status;    received = Answer;    if (nh->nh_soa == NULL)      LOG5("got SDP");    else if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) {      LOG3("error parsing SDP");      sdp = NULL;      cr->cr_graceful = 1;      ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\"";    }    else if (soa_process_answer(nh->nh_soa, NULL) < 0) {      LOG5("error processing SDP");      /* XXX */      sdp = NULL;    }    else if (soa_activate(nh->nh_soa, NULL) < 0)      /* XXX - what about errors? */      LOG3("error activating media after");    else      LOG5("processed SDP");  }  else if (cr->cr_method != sip_method_invite) {    /* If non-invite request did not have offer, ignore SDP in response */    LOG3("ignoring extra");    sdp = NULL;  }  else {    /* case 2: new offer */    cr->cr_offer_recv = 1, cr->cr_answer_sent = 0;    received = Offer;    if (nh->nh_soa && soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) {      LOG3("error parsing SDP");      sdp = NULL;      cr->cr_graceful = 1;      ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\"";    }    else       LOG5("got SDP");  }  if (ss && received)    ss->ss_oa_recv = received;  if (sdp && nh->nh_soa)    return nua_base_client_tresponse(cr, status, phrase, sip,				     NH_REMOTE_MEDIA_TAGS(1, nh->nh_soa),				     TAG_END());  else    return nua_base_client_response(cr, status, phrase, sip, NULL);}static int nua_invite_client_report(nua_client_request_t *cr,				    int status, char const *phrase,				    sip_t const *sip,				    nta_outgoing_t *orq,				    tagi_t const *tags){  nua_handle_t *nh = cr->cr_owner;  nua_dialog_state_t *ds = nh->nh_ds;  nua_dialog_usage_t *du = cr->cr_usage;  nua_session_usage_t *ss = nua_dialog_usage_private(du);  unsigned next_state;  int error;  nh_referral_respond(nh, status, phrase); /* XXX - restarting after 401/407 */  nua_stack_event(nh->nh_nua, nh, 		  nta_outgoing_getresponse(orq),		  cr->cr_event,		  status, phrase,		  tags);  if (cr->cr_waiting)    /* Do not report call state change if waiting for restart */    return 1;  if (ss == NULL) {    signal_call_state_change(nh, ss, status, phrase, nua_callstate_terminated);    return 1;  }  ss->ss_reporting = 1;  if (cr->cr_neutral) {    signal_call_state_change(nh, ss, status, phrase, ss->ss_state);    ss->ss_reporting = 0;    return 1;  }  if (orq != cr->cr_orq && cr->cr_orq) {	/* Being restarted */    next_state = nua_callstate_calling;  }  else if (status == 100) {    next_state = nua_callstate_calling;  }  else if (status < 300 && cr->cr_graceful) {    next_state = nua_callstate_terminating;    if (200 <= status) {      nua_invite_client_ack(cr, NULL);    }  }  else if (status < 200) {    next_state = nua_callstate_proceeding;    if (sip && sip->sip_rseq && 	!SIP_IS_ALLOWED(NH_PGET(nh, appl_method), sip_method_prack)) {      sip_rack_t rack[1];      sip_rack_init(rack);      rack->ra_response    = sip->sip_rseq->rs_response;      rack->ra_cseq        = sip->sip_cseq->cs_seq;      rack->ra_method      = sip->sip_cseq->cs_method;      rack->ra_method_name = sip->sip_cseq->cs_method_name;      error = nua_client_tcreate(nh, nua_r_prack, &nua_prack_client_methods, 				 SIPTAG_RACK(rack),				 TAG_END());      if (error < 0) {	cr->cr_graceful = 1;	next_state = nua_callstate_terminating;      }    }  }  else if (status < 300) {    next_state = nua_callstate_completing;  }  else if (cr->cr_terminated) {    next_state = nua_callstate_terminated;  }  else if (cr->cr_graceful && ss->ss_state >= nua_callstate_completing) {    next_state = nua_callstate_terminating;  }  else {    next_state = nua_callstate_init;  }  if (next_state == nua_callstate_calling) {    if (sip && sip->sip_status && sip->sip_status->st_status == 100) {      ss->ss_reporting = 0;      return 1;    }  }  if (next_state == nua_callstate_completing) {    if (NH_PGET(nh, auto_ack) ||	/* Auto-ACK response to re-INVITE unless auto_ack is set to 0 */	(ss->ss_state == nua_callstate_ready &&	 !NH_PISSET(nh, auto_ack))) {      nua_client_request_t *cru;      for (cru = ds->ds_cr; cru; cru = cru->cr_next) {	if (cr != cru && cru->cr_offer_sent && !cru->cr_answer_recv)	  break;      }      if (cru)	/* A final response to UPDATE or PRACK with answer on its way? */;      else if (nua_invite_client_ack(cr, NULL) > 0)	next_state = nua_callstate_ready;      else	next_state = nua_callstate_terminating;    }  }  if (next_state == nua_callstate_terminating) {    /* Send BYE or CANCEL */    /* XXX - Forking - send BYE to early dialog?? */    if (ss->ss_state > nua_callstate_proceeding || status >= 200)      error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL);    else      error = nua_client_create(nh, nua_r_cancel, 				&nua_cancel_client_methods, tags);    if (error) {      next_state = nua_callstate_terminated;      cr->cr_terminated = 1;    }    cr->cr_graceful = 0;  }  ss->ss_reporting = 0;  signal_call_state_change(nh, ss, status, phrase, next_state);  return 1;}/**@fn void nua_ack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Acknowledge a succesful response to INVITE request. * * Acknowledge a successful response (200..299) to INVITE request with the * SIP ACK request message. This function is needed only if NUTAG_AUTOACK() * parameter has been cleared. * * @param nh              Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return  *    nothing * * @par Related Tags: *    Header tags defined in <sofia-sip/sip_tag.h> * * @par Events: *    #nua_i_media_error \n *    #nua_i_state  (#nua_i_active, #nua_i_terminated)  * * @sa NUTAG_AUTOACK(), @ref nua_call_model, #nua_i_state */int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e,		  tagi_t const *tags){  nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds);  nua_session_usage_t *ss = nua_dialog_usage_private(du);  nua_client_request_t *cr = du ? du->du_cr : NULL;  int error;  if (!cr || cr->cr_orq == NULL || cr->cr_status < 200) {    UA_EVENT2(nua_i_error, 900, "No response to ACK");    return 1;  }  if (tags) {    nua_stack_set_params(nua, nh, nua_i_error, tags);    if (nh->nh_soa)      soa_set_params(nh->nh_soa, TAG_NEXT(tags));  }  error = nua_invite_client_ack(cr, tags);  if (error < 0) {    if (ss->ss_reason == NULL)      ss->ss_reason = "SIP;cause=500;text=\"Internal Error\"";

⌨️ 快捷键说明

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