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

📄 soa_static.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 2 页
字号:
  cm = sdp_media_dup_all(home, caps->sdp_media, session);   if (!s_media || !c_media || !u_media || !cm)    return -1;  for (i = 0, m = session->sdp_media; m && i < Ns; m = m->m_next)    o_media[i++] = m;  assert(i == Ns);  for (i = 0, m = cm; m && i < Nc; m = m->m_next)    c_media[i++] = m;  assert(i == Nc);  for (i = 0, m = upgrader->sdp_media; m && i < Nu; m = m->m_next)    u_media[i++] = m;  assert(i == Nu);  if (caps != upgrader) {    /* Update session according to remote */    for (i = 0; i < Nu; i++) {      int common_codecs = 0;      m = soa_sdp_matching(ss, c_media, u_media[i], &common_codecs);      if (!m || u_media[i]->m_rejected) {	m = soa_sdp_make_rejected_media(home, u_media[i], session, 0);      }      else if (sdp_media_uses_rtp(m)) {	/* Process rtpmaps */	if (!common_codecs && !ss->ss_rtp_mismatch)	  m = soa_sdp_make_rejected_media(home, m, session, 1);	soa_sdp_set_rtpmap_pt(m, u_media[i]);	if (ss->ss_rtp_sort == SOA_RTP_SORT_REMOTE || 	    (ss->ss_rtp_sort == SOA_RTP_SORT_DEFAULT &&	     u_media[i]->m_mode == sdp_recvonly)) {	  soa_sdp_sort_rtpmap(&m->m_rtpmaps, u_media[i]->m_rtpmaps);	}	if (common_codecs &&	    (ss->ss_rtp_select == SOA_RTP_SELECT_SINGLE ||	     ss->ss_rtp_select == SOA_RTP_SELECT_COMMON)) {	  soa_sdp_select_rtpmap(&m->m_rtpmaps, u_media[i]->m_rtpmaps);	  if (ss->ss_rtp_select == SOA_RTP_SELECT_SINGLE) {	    if (m->m_rtpmaps)	      m->m_rtpmaps->rm_next = NULL;	  }	}      }      s_media[i] = m;    }  }  else {    /* Update session according to local */    for (i = 0; i < Ns; i++) {      m = soa_sdp_matching(ss, c_media, o_media[i], NULL);      if (!m)	m = soa_sdp_make_rejected_media(home, o_media[i], session, 0);      s_media[i] = m;    }    /* Here we just append new media at the end */    for (j = 0; c_media[j]; j++)      s_media[i++] = c_media[j];    assert(i <= size);  }  mm = &session->sdp_media;  for (i = 0; s_media[i]; i++) {    m = s_media[i]; *mm = m; mm = &m->m_next;  }  *mm = NULL;  return 0;}/** Check if @a session contains media that are rejected by @a remote. */ int soa_sdp_reject_is_needed(sdp_session_t const *session,			     sdp_session_t const *remote){  sdp_media_t const *sm, *rm;  if (!remote)    return 1;  if (!session)    return 0;  for (sm = session->sdp_media, rm = remote->sdp_media;        sm && rm; sm = sm->m_next, rm = rm->m_next) {    if (rm->m_rejected) {      if (!sm->m_rejected)	return 1;    }    else {      sdp_mode_t send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0;      if (send_mode != (sm->m_mode & sdp_sendonly))	return 1;    }  }  if (sm)    return 1;  return 0;}/** If m= line is rejected by, remote mark m= line rejected within session */ int soa_sdp_reject(su_home_t *home,		   sdp_session_t *session,		   sdp_session_t const *remote){  sdp_media_t *sm;  sdp_media_t const *rm;  if (!session || !session->sdp_media || !remote)    return 0;  rm = remote->sdp_media;  for (sm = session->sdp_media; sm; sm = sm->m_next) {    if (!rm || rm->m_rejected) {      sm->m_rejected = 1;      sm->m_mode = 0;      sm->m_port = 0;      sm->m_number_of_ports = 1;      if (sm->m_format)	sm->m_format->l_next = NULL;      if (sm->m_rtpmaps)	sm->m_rtpmaps->rm_next = NULL;      sm->m_information = NULL;      if (sm->m_connections)	sm->m_connections->c_next = NULL;      sm->m_bandwidths = NULL;      sm->m_key = NULL;      sm->m_attributes = NULL;      sm->m_user = NULL;    }    if (rm)      rm = rm->m_next;  }  return 0;}/** Check if @a session mode should be changed. */ int soa_sdp_mode_set_is_needed(sdp_session_t const *session,			       sdp_session_t const *remote,			       char const *hold){  sdp_media_t const *sm, *rm, *rm_next;  int hold_all;  sdp_mode_t send_mode, recv_mode;  SU_DEBUG_7(("soa_sdp_mode_set_is_needed(%p, %p, \"%s\"): called\n",	      session, remote, hold ? hold : ""));  if (!session )    return 0;  hold_all = str0cmp(hold, "*") == 0;  rm = remote ? remote->sdp_media : NULL, rm_next = NULL;  for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next) {    rm_next = rm ? rm->m_next : NULL;    if (sm->m_rejected)      continue;    if (rm) {      send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0;      if (send_mode != (sm->m_mode & sdp_sendonly))	return 1;    }    recv_mode = sm->m_mode & sdp_recvonly;    if (recv_mode && hold &&	(hold_all || strcasestr(hold, sm->m_type_name)))      return 1;  }  return 0;}/** Update mode within session */ int soa_sdp_mode_set(sdp_session_t *session,		     sdp_session_t const *remote,		     char const *hold){  sdp_media_t *sm;  sdp_media_t const *rm, *rm_next;  int hold_all;  sdp_mode_t send_mode, recv_mode;  SU_DEBUG_7(("soa_sdp_mode_set(%p, %p, \"%s\"): called\n",	      session, remote, hold ? hold : ""));  if (!session || !session->sdp_media)    return 0;  rm = remote ? remote->sdp_media : NULL, rm_next = NULL;  hold_all = str0cmp(hold, "*") == 0;  for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next) {    rm_next = rm ? rm->m_next : NULL;    if (sm->m_rejected)      continue;    send_mode = sdp_sendonly;    if (rm)      send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0;    recv_mode = sm->m_mode & sdp_recvonly;    if (recv_mode && hold && (hold_all || strcasestr(hold, sm->m_type_name)))      recv_mode = 0;    sm->m_mode = recv_mode | send_mode;  }  return 0;}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){  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) }};  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", ss, by));  if (user == NULL)    return soa_set_status(ss, 500, "No session set by user");  if (action == generate_offer)    remote = NULL;  /* 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);    }  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): generating local description\n", ss, by));    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", ss, by, 		"upgrade with local description"));    soa_sdp_upgrade(ss, tmphome, local, user, user);    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 (ss->ss_local_user_version != user_version ||	soa_sdp_upgrade_is_needed(local, remote)) {      if (local != local0)	*local0 = *local, local = local0;      SU_DEBUG_7(("soa_static(%p, %s): %s\n", ss, by,		  "upgrade with remote description"));      soa_sdp_upgrade(ss, tmphome, local, user, remote);    }    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): marking rejected media\n", ss, by));      soa_sdp_reject(tmphome, local, remote);    }    break;  default:    break;  }  /* Step D: Set media mode bits */  switch (action) {  case generate_offer:  case generate_answer:  case process_answer:    if (soa_sdp_mode_set_is_needed(local, remote, ss->ss_hold)) {      if (local != local0) {	*local0 = *local, local = local0;	DUP_LOCAL(local);      }      soa_sdp_mode_set(local, remote, ss->ss_hold);    }    break;  default:    break;  }  /* Step E: Upgrade codecs */  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", ss, by,		  "upgrade codecs with remote description"));      if (local != local0) {	*local0 = *local, local = local0; 	DUP_LOCAL(local);      }      soa_sdp_upgrade_rtpmaps(ss, local, remote);    }    break;  case generate_offer:  case generate_answer:  default:    break;  }  soa_description_free(ss, ss->ss_previous);  if (local == local0) {    /* We have modfied 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;    /* Every m= line (even rejected one) must have a c= line      * or there must be a c= line at session level     */    c = local->sdp_origin->o_address;    if (local->sdp_connection == NULL) {      sdp_media_t *m;      for (m = local->sdp_media; m; m = m->m_next)	if (m->m_connections == NULL)	  break;      if (m)	local->sdp_connection = c;    }    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): storing local description\n", ss, by));    /* Update the unparsed and pretty-printed descriptions  */    if (soa_description_set(ss, ss->ss_local, local, NULL, 0) < 0) {      goto internal_error;    }  }  /* 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 + -