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

📄 soa_static.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
    return common_codecs;  /* Select unique dynamic payload type for each payload */  memset(dynamic_pt, 0, sizeof dynamic_pt);  for (lrm = l_m->m_rtpmaps; lrm; lrm = lrm->rm_next) {    if (!lrm->rm_any)      dynamic_pt[lrm->rm_pt] = 1;  }  for (rrm = r_m->m_rtpmaps; rrm; rrm = rrm->rm_next) {    dynamic_pt[rrm->rm_pt] = 1;  }  for (next_lrm = &l_m->m_rtpmaps; (lrm = *next_lrm); ) {    if (!lrm->rm_any) {      next_lrm = &lrm->rm_next;      continue;    }        lrm->rm_any = 0;    pt = lrm->rm_pt;    if (dynamic_pt[pt]) {      for (pt = 96; pt < 128; pt++)        if (!dynamic_pt[pt])          break;            if (pt == 128) {        for (pt = 0; pt < 128; pt++)          if (!sdp_rtpmap_well_known[pt] && !dynamic_pt[pt])            break;      }      if (pt == 128)  {        for (pt = 0; pt < 128; pt++)          if (!dynamic_pt[pt])            break;      }      if (pt == 128) {        /* Too many payload types */        *next_lrm = lrm->rm_next;        continue;      }      lrm->rm_pt = pt;      lrm->rm_predef = 0;    }    dynamic_pt[pt] = 1;      next_lrm = &lrm->rm_next;  }  return common_codecs;}/** Sort rtpmaps in @a inout_list according to the values in @a rrm. * * @return Number of common codecs */staticint soa_sdp_sort_rtpmap(sdp_rtpmap_t **inout_list, 			sdp_rtpmap_t const *rrm,			char const *auxiliary){  sdp_rtpmap_t *sorted = NULL, **next = &sorted, **left;  sdp_rtpmap_t *aux = NULL, **next_aux = &aux;  int common_codecs = 0;  assert(inout_list);  if (!inout_list)    return 0;  /* If remote has only single codec, ignore list of auxiliary codecs */  if (rrm && !rrm->rm_next)    auxiliary = NULL;  /* Insertion sort from *inout_list to sorted */  for (; rrm && *inout_list; rrm = rrm->rm_next) {    for (left = inout_list; *left; left = &(*left)->rm_next) {      if (sdp_rtpmap_match(rrm, (*left)))	break;    }    if (!*left)      continue;    if (auxiliary && soa_sdp_is_auxiliary_codec(rrm, auxiliary)) {      *next_aux = *left, next_aux = &(*next_aux)->rm_next;    }    else {      common_codecs++;      *next = *left; next = &(*next)->rm_next;    }    *left = (*left)->rm_next;  }  /* Append common auxiliary codecs */  if (aux)    *next = aux, next = next_aux;  /* Append leftover codecs */  *next = *inout_list;  *inout_list = sorted;  return common_codecs;}/** Select rtpmaps in @a inout_list according to the values in @a rrm. * * @return Number of common codecs */staticint soa_sdp_select_rtpmap(sdp_rtpmap_t **inout_list, 			  sdp_rtpmap_t const *rrm,			  char const *auxiliary,			  int select_single){  sdp_rtpmap_t **left;  sdp_rtpmap_t *aux = NULL, **next_aux = &aux;  int common_codecs = 0;  assert(inout_list);  if (!inout_list)    return 0;  for (left = inout_list; *left; ) {    if (auxiliary && soa_sdp_is_auxiliary_codec(*left, auxiliary))      /* Insert into list of auxiliary codecs */      *next_aux = *left, *left = (*left)->rm_next, 	next_aux = &(*next_aux)->rm_next;    else if (!(select_single && common_codecs > 0)	     && sdp_rtpmap_find_matching(rrm, (*left)))      /* Select */      left = &(*left)->rm_next, common_codecs++;    else      /* Remove */      *left = (*left)->rm_next;  }  *left = aux, *next_aux = NULL;  return common_codecs;}/** Sort and select rtpmaps  */ staticint soa_sdp_media_upgrade_rtpmaps(soa_session_t *ss,				  sdp_media_t *sm,				  sdp_media_t const *rm){  soa_static_session_t *sss = (soa_static_session_t *)ss;  char const *auxiliary = NULL;  int common_codecs;  common_codecs = soa_sdp_set_rtpmap_pt(sm, rm);  if (rm->m_type == sdp_media_audio)    auxiliary = sss->sss_audio_aux;  if (ss->ss_rtp_sort == SOA_RTP_SORT_REMOTE ||       (ss->ss_rtp_sort == SOA_RTP_SORT_DEFAULT &&       rm->m_mode == sdp_recvonly)) {    soa_sdp_sort_rtpmap(&sm->m_rtpmaps, rm->m_rtpmaps, auxiliary);  }  if (common_codecs == 0)    ;  else if (ss->ss_rtp_select == SOA_RTP_SELECT_SINGLE) {    soa_sdp_select_rtpmap(&sm->m_rtpmaps, rm->m_rtpmaps, auxiliary, 1);  }  else if (ss->ss_rtp_select == SOA_RTP_SELECT_COMMON) {    soa_sdp_select_rtpmap(&sm->m_rtpmaps, rm->m_rtpmaps, auxiliary, 0);  }  return common_codecs;}/** Sort and select rtpmaps within session */ staticint soa_sdp_session_upgrade_rtpmaps(soa_session_t *ss,				    sdp_session_t *session,				    sdp_session_t const *remote){  sdp_media_t *sm;  sdp_media_t const *rm;  for (sm = session->sdp_media, rm = remote->sdp_media;        sm && rm;        sm = sm->m_next, rm = rm->m_next) {    if (!sm->m_rejected && sdp_media_uses_rtp(sm))      soa_sdp_media_upgrade_rtpmaps(ss, sm, rm);  }  return 0;}/** Upgrade m= lines within session */ staticint soa_sdp_upgrade(soa_session_t *ss,		    su_home_t *home,		    sdp_session_t *session,		    sdp_session_t const *user,		    sdp_session_t const *remote,		    int **return_u2s,		    int **return_s2u){  soa_static_session_t *sss = (soa_static_session_t *)ss;  int Ns, Nu, Nr, size, i, j;  sdp_media_t *m, **mm, *um;  sdp_media_t **s_media, **o_media, **u_media;  sdp_media_t const *rm, **r_media;  int *u2s = NULL, *s2u = NULL;  if (session == NULL || user == NULL)    return (errno = EFAULT), -1;  Ns = sdp_media_count(session, sdp_media_any, 0, 0, 0);  Nu = sdp_media_count(user, sdp_media_any, 0, 0, 0);  Nr = sdp_media_count(remote, sdp_media_any, 0, 0, 0);  if (remote == NULL)    size = Ns + Nu + 1;  else if (Ns < Nr)    size = Nr + 1;  else    size = Ns + 1;  s_media = su_zalloc(home, size * (sizeof *s_media));  o_media = su_zalloc(home, (Ns + 1) * (sizeof *o_media));  u_media = su_zalloc(home, (Nu + 1) * (sizeof *u_media));  r_media = su_zalloc(home, (Nr + 1) * (sizeof *r_media));  if (!s_media || !o_media || !u_media || !r_media)    return -1;  um = sdp_media_dup_all(home, user->sdp_media, session);   if (!um && user->sdp_media)    return -1;  u2s = su_alloc(home, (Nu + 1) * sizeof(*u2s));  s2u = su_alloc(home, size * sizeof(*s2u));  if (!u2s || !s2u)    return -1;  for (i = 0; i < Nu; i++)    u2s[i] = U2S_NOT_USED;  u2s[i] = U2S_SENTINEL;  for (i = 0; i <= size; i++)    s2u[i] = U2S_NOT_USED;  s2u[i] = U2S_SENTINEL;  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 = um; m && i < Nu; m = m->m_next)    u_media[i++] = m;  assert(i == Nu);  m = remote ? remote->sdp_media : NULL;  for (i = 0; m && i < Nr; m = m->m_next)      r_media[i++] = m;  assert(i == Nr);  if (sss->sss_ordered_user && sss->sss_u2s) {     /* User SDP is ordered */    for (j = 0; sss->sss_u2s[j] != U2S_SENTINEL; j++) {      i = sss->sss_u2s[j];      if (i == U2S_NOT_USED)	continue;      if (j >= Nu) /* lines removed from user SDP */	continue;      s_media[i] = u_media[j], u_media[j] = SDP_MEDIA_NONE;      u2s[j] = i, s2u[i] = j;    }  }  if (remote) {    /* Update session according to remote */    for (i = 0; i < Nr; i++) {      rm = r_media[i];      m = s_media[i];      if (!m) {	int codec_mismatch = 0;	if (!rm->m_rejected)	  j = soa_sdp_matching_mindex(ss, u_media, rm, &codec_mismatch);	else	  j = -1;	if (j == -1) {	  s_media[i] = soa_sdp_make_rejected_media(home, rm, session, 0);	  continue;	}	else if (codec_mismatch && !ss->ss_rtp_mismatch) {	  m = soa_sdp_make_rejected_media(home, u_media[j], session, 1);	  soa_sdp_set_rtpmap_pt(s_media[i] = m, rm);	  continue;	}	s_media[i] = m = u_media[j]; u_media[j] = SDP_MEDIA_NONE;	u2s[j] = i, s2u[i] = j;      }      if (sdp_media_uses_rtp(rm))	soa_sdp_media_upgrade_rtpmaps(ss, m, rm);    }  }  else {    if (sss->sss_ordered_user) {      /* Update session with unused media in u_media */      if (!sss->sss_reuse_rejected) {	/* Mark previously used slots */	for (i = 0; i < Ns; i++) {	  if (s_media[i])	    continue;	  s_media[i] = 	    soa_sdp_make_rejected_media(home, o_media[i], session, 0);	}      }      for (j = 0; j < Nu; j++) {	if (u_media[j] == SDP_MEDIA_NONE)	  continue;	for (i = 0; i < size - 1; i++) {	  if (s_media[i] == NULL) {	    s_media[i] = u_media[j], u_media[j] = SDP_MEDIA_NONE;	    u2s[j] = i, s2u[i] = j;	    break;	  }	}	assert(i != size - 1);      }    }    /* Match unused user media by media types with the existing session */    for (i = 0; i < Ns; i++) {      if (s_media[i])	continue;      j = soa_sdp_matching_mindex(ss, u_media, o_media[i], NULL);      if (j == -1) {	s_media[i] = soa_sdp_make_rejected_media(home, o_media[i], session, 0);	continue;      }      s_media[i] = u_media[j], u_media[j] = SDP_MEDIA_NONE;      u2s[j] = i, s2u[i] = j;    }    /* Here we just append new media at the end */    for (j = 0; j < Nu; j++) {      if (u_media[j] != SDP_MEDIA_NONE) {	s_media[i] = u_media[j], u_media[j] = SDP_MEDIA_NONE;	u2s[j] = i, s2u[i] = j;	i++;      }    }    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;  s2u[size = i] = U2S_SENTINEL;  *return_u2s = u2s;  *return_s2u = s2u;#ifndef NDEBUG			/* X check */  for (j = 0; j < Nu; j++) {    i = u2s[j];    assert(i == U2S_NOT_USED || s2u[i] == j);  }  for (i = 0; i < size; i++) {    j = s2u[i];    assert(j == U2S_NOT_USED || u2s[j] == i);  }#endif  return 0;}int *u2s_alloc(su_home_t *home, int const *u2s){  if (u2s) {    int i, *a;    for (i = 0; u2s[i] != U2S_SENTINEL; i++)      ;    a = su_alloc(home, (i + 1) * (sizeof *u2s));    if (a)      memcpy(a, u2s, (i + 1) * (sizeof *u2s));    return a;  }  return NULL;}/** Check if @a session contains media that are rejected by @a remote. */ staticint 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 {      /* Mode bits do not match */      if (((rm->m_mode & sdp_recvonly) == sdp_recvonly)	  != ((sm->m_mode & sdp_sendonly) == sdp_sendonly))	return 1;    }  }  if (sm)    return 1;  return 0;}/** If m= line is rejected by remote mark m= line rejected within session */ staticint 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;}/** Update mode within session. * * @sa soatag_hold

⌨️ 快捷键说明

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