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

📄 soa_static.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
 * * @retval 1 if session was changed (or to be changed, if @a dryrun is nonzero) */ staticint soa_sdp_mode_set(sdp_session_t const *user,		     int const *s2u,		     sdp_session_t *session,		     sdp_session_t const *remote,		     char const *hold,		     int dryrun){  sdp_media_t *sm;  sdp_media_t const *rm, *rm_next, *um;  int retval = 0, i, j;  int hold_all;  int inactive_all;  int inactive = 0;  char const *hold_media = NULL;  sdp_mode_t send_mode, recv_mode;  SU_DEBUG_7(("soa_sdp_mode_set(%p, %p, \"%s\"): called\n",	      (void *)session, (void *)remote, hold ? hold : ""));  if (!session || !session->sdp_media)    return 0;  rm = remote ? remote->sdp_media : NULL, rm_next = NULL;  hold_all = str0cmp(hold, "*") == 0;  inactive_all = str0cmp(hold, "#") == 0;  i = 0;  for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next, i++) {    rm_next = rm ? rm->m_next : NULL;    inactive = 0;    if (sm->m_rejected)      continue;    assert(s2u);    for (j = 0, um = user->sdp_media; j != s2u[i]; um = um->m_next, j++)      assert(um);    if (um == NULL) {      if (dryrun)	return 1;      else	retval = 1;      sm->m_rejected = 1;      sm->m_mode = sdp_inactive;      sm->m_port = 0;      continue;    }    send_mode = um->m_mode & sdp_sendonly;    if (rm)      send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0;    recv_mode = um->m_mode & sdp_recvonly;    if (rm && rm->m_mode == sdp_inactive) {      send_mode = recv_mode = 0;    }    else if (inactive_all) {      send_mode = recv_mode = 0;    }    else if (hold_all) {      recv_mode = 0;    }    else if (hold && (hold_media = strcasestr(hold, sm->m_type_name))) {      recv_mode = 0;      hold_media += strlen(sm->m_type_name);      hold_media += strspn(hold_media, " \t");      if (hold_media[0] == '=') {	hold_media += strspn(hold, " \t");	if (strncasecmp(hold_media, "inactive", strlen("inactive")) == 0)	  recv_mode = send_mode = 0;      }    }    if (sm->m_mode != (unsigned)(recv_mode | send_mode)) {      if (dryrun)	return 1;      else	retval = 1;      sm->m_mode = recv_mode | send_mode;    }  }  return retval;}enum offer_answer_action {  generate_offer,  generate_answer,  process_answer};/** * Updates the modified copy of local SDP based * on application provided local SDP and remote SDP. */static int offer_answer_step(soa_session_t *ss,			     enum offer_answer_action action,			     char const *by){  soa_static_session_t *sss = (soa_static_session_t *)ss;  char c_address[64];  sdp_session_t *local = ss->ss_local->ssd_sdp;  sdp_session_t local0[1];  sdp_session_t *user = ss->ss_user->ssd_sdp;  unsigned user_version = ss->ss_user_version;  sdp_session_t *remote = ss->ss_remote->ssd_sdp;  unsigned remote_version = ss->ss_remote_version;  sdp_origin_t o[1] = {{ sizeof(o) }};  sdp_connection_t *c, c0[1] = {{ sizeof(c0) }};  sdp_time_t t[1] = {{ sizeof(t) }};  int *u2s = NULL, *s2u = NULL, *tbf;  char const *phrase = "Internal Media Error";  su_home_t tmphome[SU_HOME_AUTO_SIZE(8192)];  su_home_auto(tmphome, sizeof tmphome);  SU_DEBUG_7(("soa_static_offer_answer_action(%p, %s): called\n",	      (void *)ss, by));  if (user == NULL)    return soa_set_status(ss, 500, "No session set by user");  if (action == generate_offer)    remote = NULL;  else if (remote == NULL)    return soa_set_status(ss, 500, "No remote SDP");  /* Pre-negotiation Step: Expand truncated remote SDP */  if (local && remote) switch (action) {  case generate_answer:  case process_answer:    if (sdp_media_count(remote, sdp_media_any, "*", 0, 0) < 	sdp_media_count(local, sdp_media_any, "*", 0, 0)) {      SU_DEBUG_5(("%s: remote %s is truncated: expanding\n",		  by, action == generate_answer ? "offer" : "answer"));      remote = soa_sdp_expand_media(tmphome, remote, local);      if (remote == NULL)	return soa_set_status(ss, 500, "Cannot expand remote session");    }  default:    break;  }    /* Step A: Create local SDP session (based on user-supplied SDP) */  if (local == NULL) switch (action) {  case generate_offer:  case generate_answer:    SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,		"generating local description"));    local = local0;    *local = *user, local->sdp_media = NULL;    if (local->sdp_origin) {      o->o_username = local->sdp_origin->o_username;      /* o->o_address = local->sdp_origin->o_address; */    }    if (!o->o_address)      o->o_address = c0;     local->sdp_origin = o;    if (soa_init_sdp_origin(ss, o, c_address) < 0) {      phrase = "Cannot Get IP Address for Media";      goto internal_error;    }    break;  case process_answer:  default:    goto internal_error;  }  /* Step B: upgrade local SDP (add m= lines to it)  */  switch (action) {  case generate_offer:    /* Upgrade local SDP based on user SDP */    if (local != local0 && ss->ss_local_user_version == user_version)      break;    if (local != local0)      *local0 = *local, local = local0;    SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by, 		"upgrade with local description"));    if (soa_sdp_upgrade(ss, tmphome, local, user, NULL, &u2s, &s2u) < 0)      goto internal_error;    break;  case generate_answer:    /* Upgrade local SDP based on remote SDP */    if (ss->ss_local_user_version == user_version &&	ss->ss_local_remote_version == remote_version)      break;    if (1) {      if (local != local0)	*local0 = *local, local = local0;      SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,		  "upgrade with remote description"));      if (soa_sdp_upgrade(ss, tmphome, local, user, remote, &u2s, &s2u) < 0)	goto internal_error;    }    break;  case process_answer:  default:    break;  }  /* Step C: reject media */  switch (action) {  case generate_offer:    /* Local media is marked as rejected already in upgrade phase */    break;  case generate_answer:  case process_answer:    if (ss->ss_local_remote_version == remote_version)      break;    if (soa_sdp_reject_is_needed(local, remote)) {      if (local != local0) {	*local0 = *local, local = local0;#define DUP_LOCAL(local)					 \	do {							 \	  if (!local->sdp_media) break;				 \	  local->sdp_media =					 \	    sdp_media_dup_all(tmphome, local->sdp_media, local); \	  if (!local->sdp_media)				 \	    goto internal_error;				 \	} while (0)	DUP_LOCAL(local);      }      SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by, 		  "marking rejected media"));      soa_sdp_reject(tmphome, local, remote);    }    break;  default:    break;  }  /* Step D: Set media mode bits */  switch (action) {    int const *s2u_;  case generate_offer:  case generate_answer:  case process_answer:    s2u_ = s2u;    if (!s2u_) s2u_ = sss->sss_s2u;    if (soa_sdp_mode_set(user, s2u_, local, remote, ss->ss_hold, 1)) {      if (local != local0) {	*local0 = *local, local = local0;	DUP_LOCAL(local);      }      soa_sdp_mode_set(user, s2u_, local, remote, ss->ss_hold, 0);    }    break;  default:    break;  }  /* Step E: Upgrade codecs by answer. */  switch (action) {  case process_answer:    /* Upgrade local SDP based on remote SDP */    if (ss->ss_local_remote_version == remote_version)      break;    if (1 /* We don't have good test for codecs */) {      SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,		  "upgrade codecs with remote description"));      if (local != local0) {	*local0 = *local, local = local0; 	DUP_LOCAL(local);      }      soa_sdp_session_upgrade_rtpmaps(ss, local, remote);    }    break;  case generate_offer:  case generate_answer:  default:    break;  }  /* Step F: Update c= line */   switch (action) {  case generate_offer:  case generate_answer:    /* Upgrade local SDP based of user SDP */    if (ss->ss_local_user_version == user_version &&	local->sdp_connection)      break;    if (local->sdp_connection == NULL || 	(user->sdp_connection != NULL && 	 sdp_connection_cmp(local->sdp_connection, user->sdp_connection))) {      sdp_media_t *m;      /* Every m= line (even rejected one) must have a c= line        * or there must be a c= line at session level       */      if (user->sdp_connection)	c = user->sdp_connection;      else	c = local->sdp_origin->o_address;      for (m = local->sdp_media; m; m = m->m_next)	if (m->m_connections == NULL)	  break;      if (m) {	if (local != local0) {	  *local0 = *local, local = local0; 	  DUP_LOCAL(local);	}	local->sdp_connection = c;      }    }    break;  default:    break;  }  soa_description_free(ss, ss->ss_previous);  if (u2s) {    u2s = u2s_alloc(ss->ss_home, u2s);     s2u = u2s_alloc(ss->ss_home, s2u);    if (!u2s || !s2u)      goto internal_error;  }  if (ss->ss_local->ssd_sdp != local &&      sdp_session_cmp(ss->ss_local->ssd_sdp, local)) {    /* We have modified local session: update origin-line */    if (local->sdp_origin != o)      *o = *local->sdp_origin, local->sdp_origin = o;    o->o_version++;    /* Do sanity checks for the created SDP */    if (!local->sdp_subject)	/* s= is mandatory */      local->sdp_subject = "-";    if (!local->sdp_time)	/* t= is mandatory */      local->sdp_time = t;    if (action == generate_offer) {      /* Keep a copy of previous session state */      *ss->ss_previous = *ss->ss_local;      memset(ss->ss_local, 0, (sizeof *ss->ss_local));      ss->ss_previous_user_version = ss->ss_local_user_version;      ss->ss_previous_remote_version = ss->ss_local_remote_version;    }    SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,		"storing local description"));    /* Update the unparsed and pretty-printed descriptions  */    if (soa_description_set(ss, ss->ss_local, local, NULL, 0) < 0) {      if (action == generate_offer) {	/* Remove 2nd reference to local session state */	memset(ss->ss_previous, 0, (sizeof *ss->ss_previous));	ss->ss_previous_user_version = 0;	ss->ss_previous_remote_version = 0;      }            su_free(ss->ss_home, u2s), su_free(ss->ss_home, s2u);      goto internal_error;    }  }  if (u2s) {    tbf = sss->sss_u2s, sss->sss_u2s = u2s, su_free(ss->ss_home, tbf);    tbf = sss->sss_s2u, sss->sss_s2u = s2u, su_free(ss->ss_home, tbf);  }  /* Update version numbers */  switch (action) {  case generate_offer:    ss->ss_local_user_version = user_version;    break;  case generate_answer:    ss->ss_local_user_version = user_version;    ss->ss_local_remote_version = remote_version;    break;  case process_answer:    ss->ss_local_remote_version = remote_version;  default:    break;  }  su_home_deinit(tmphome);  return 0; internal_error:  su_home_deinit(tmphome);  return soa_set_status(ss, 500, phrase);}/** * Generates offer based on local SDP. */static int soa_static_generate_offer(soa_session_t *ss,				     soa_callback_f *completed){  if (!ss->ss_user->ssd_sdp)    return soa_set_status(ss, 500, "No session set by user");  if (offer_answer_step(ss, generate_offer, "soa_generate_offer") < 0)    return -1;  return soa_base_generate_offer(ss, NULL);}static int soa_static_generate_answer(soa_session_t *ss,				      soa_callback_f *completed){  /* NOTE:   * - local SDP might have changed   * - remote SDP might have been updated    */  if (offer_answer_step(ss, generate_answer, "soa_generate_answer") < 0)    return -1;  return soa_base_generate_answer(ss, NULL);}static int soa_static_process_answer(soa_session_t *ss,				     soa_callback_f *completed){  /* NOTE:   * - both local and remote information is available   * - local SDP might have changed   * - remote SDP might have been updated    */  if (offer_answer_step(ss, process_answer, "soa_process_answer") < 0)    return -1;  return soa_base_process_answer(ss, NULL);}/** Process rejected offer */static int soa_static_process_reject(soa_session_t *ss,				     soa_callback_f *completed){  struct soa_description d[1];  *d = *ss->ss_local;  *ss->ss_local = *ss->ss_previous;  ss->ss_local_user_version = ss->ss_previous_user_version;  ss->ss_local_remote_version = ss->ss_previous_remote_version;  memset(ss->ss_previous, 0, (sizeof *ss->ss_previous));  soa_description_free(ss, d);  return soa_base_process_reject(ss, NULL);}static int soa_static_activate(soa_session_t *ss, char const *option){  return soa_base_activate(ss, option);}static int soa_static_deactivate(soa_session_t *ss, char const *option){  return soa_base_deactivate(ss, option);}static void soa_static_terminate(soa_session_t *ss, char const *option){  soa_description_free(ss, ss->ss_user);  soa_base_terminate(ss, option);}

⌨️ 快捷键说明

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