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

📄 soa_static.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@CFILE soa_static.c * * @brief Static implementation of Sofia SDP Offer/Answer Engine * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Tue Aug 16 17:06:06 EEST 2005 * * @par Use-cases *  1. no existing session *    a) generating offer (upgrade with user-SDP) *    b) generating answer (upgrade with remote-SDP, rejects with user-SDP) *  2. session exists *    a) generating offer:  *       upgrades with user-SDP *    b) generating answer:  *       upgrades with remote-SDP, rejects with user-SDP *    c) processing answer:  *       rejects with user-SDP, no upgrades * * Upgrading session with user SDP: */#include "config.h"#include <stddef.h>#include <stdlib.h>#include <string.h>#include <assert.h>struct soa_static_complete;#define SU_MSG_ARG_T struct soa_static_completed#include <sofia-sip/su_wait.h>#include <sofia-sip/su_tag_class.h>#include <sofia-sip/su_tag_class.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/su_strlst.h>#include <sofia-sip/string0.h>#include <sofia-sip/bnf.h>#include "sofia-sip/soa.h"#include <sofia-sip/sdp.h>#include "sofia-sip/soa_session.h"#define NONE ((void *)-1)#define XXX assert(!"implemented")#if !HAVE_STRCASESTRchar *strcasestr(const char *haystack, const char *needle);#endiftypedef struct soa_static_session{  soa_session_t sss_session[1];  char *sss_audio_aux;  int sss_ordered_user;  /**< User SDP is ordered */  int sss_reuse_rejected; /**< Try to reuse rejected media line slots */  /** Mapping from user SDP m= lines to session SDP m= lines */  int  *sss_u2s;  /** Mapping from session SDP m= lines to user SDP m= lines */  int *sss_s2u;}soa_static_session_t;#define U2S_NOT_USED (-1)#define U2S_SENTINEL (-2)static int soa_static_init(char const *, soa_session_t *, soa_session_t *);static void soa_static_deinit(soa_session_t *);static int soa_static_set_params(soa_session_t *ss, tagi_t const *tags);static int soa_static_get_params(soa_session_t const *ss, tagi_t *tags);static tagi_t *soa_static_get_paramlist(soa_session_t const *ss,					tag_type_t tag, tag_value_t value, 					...);static int soa_static_set_capability_sdp(soa_session_t *ss, 				       sdp_session_t *sdp,				       char const *, isize_t);static int soa_static_set_remote_sdp(soa_session_t *ss, 				   int new_version,				   sdp_session_t *sdp,				   char const *, isize_t);static int soa_static_set_user_sdp(soa_session_t *ss, 				   sdp_session_t *sdp,				   char const *, isize_t);static int soa_static_generate_offer(soa_session_t *ss, soa_callback_f *);static int soa_static_generate_answer(soa_session_t *ss, soa_callback_f *);static int soa_static_process_answer(soa_session_t *ss, soa_callback_f *);static int soa_static_process_reject(soa_session_t *ss, soa_callback_f *);static int soa_static_activate(soa_session_t *ss, char const *option);static int soa_static_deactivate(soa_session_t *ss, char const *option);static void soa_static_terminate(soa_session_t *ss, char const *option);struct soa_session_actions const soa_default_actions =   {    (sizeof soa_default_actions),    sizeof (struct soa_static_session),    "static",    soa_static_init,    soa_static_deinit,    soa_static_set_params,    soa_static_get_params,    soa_static_get_paramlist,    soa_base_media_features,    soa_base_sip_require,    soa_base_sip_supported,    soa_base_remote_sip_features,    soa_static_set_capability_sdp,    soa_static_set_remote_sdp,    soa_static_set_user_sdp,    soa_static_generate_offer,    soa_static_generate_answer,    soa_static_process_answer,    soa_static_process_reject,    soa_static_activate,    soa_static_deactivate,    soa_static_terminate  };/* Initialize session */static int soa_static_init(char const *name,			   soa_session_t *ss,			   soa_session_t *parent){  return soa_base_init(name, ss, parent);}static void soa_static_deinit(soa_session_t *ss){  soa_base_deinit(ss);}static int soa_static_set_params(soa_session_t *ss, tagi_t const *tags){  soa_static_session_t *sss = (soa_static_session_t *)ss;  char const *audio_aux = sss->sss_audio_aux;  int ordered_user = sss->sss_ordered_user;  int reuse_rejected = sss->sss_reuse_rejected;  int n, m;  n = tl_gets(tags,	      SOATAG_AUDIO_AUX_REF(audio_aux),	      SOATAG_ORDERED_USER_REF(ordered_user),	      SOATAG_REUSE_REJECTED_REF(reuse_rejected),	      TAG_END());  if (n > 0 && str0casecmp(audio_aux, sss->sss_audio_aux)) {    char *s = su_strdup(ss->ss_home, audio_aux), *tbf = sss->sss_audio_aux;    if (s == NULL && audio_aux != NULL)      return -1;    sss->sss_audio_aux = s;    if (tbf)      su_free(ss->ss_home, tbf);  }  sss->sss_ordered_user = ordered_user != 0;  sss->sss_reuse_rejected = reuse_rejected != 0;  m = soa_base_set_params(ss, tags);  if (m < 0)    return m;  return n + m;}static int soa_static_get_params(soa_session_t const *ss, tagi_t *tags){  soa_static_session_t *sss = (soa_static_session_t *)ss;  int n, m;  n = tl_tgets(tags,	       SOATAG_AUDIO_AUX(sss->sss_audio_aux),	       SOATAG_ORDERED_USER(sss->sss_ordered_user),	       SOATAG_REUSE_REJECTED(sss->sss_reuse_rejected),	       TAG_END());  m = soa_base_get_params(ss, tags);  if (m < 0)    return m;  return n + m;}static tagi_t *soa_static_get_paramlist(soa_session_t const *ss,					tag_type_t tag, tag_value_t value, 					...){  soa_static_session_t *sss = (soa_static_session_t *)ss;  ta_list ta;  tagi_t *tl;  ta_start(ta, tag, value);  tl = soa_base_get_paramlist(ss,			      TAG_IF(sss->sss_audio_aux,				     SOATAG_AUDIO_AUX(sss->sss_audio_aux)),			      TAG_IF(sss->sss_ordered_user,				     SOATAG_ORDERED_USER(1)),			      TAG_IF(sss->sss_reuse_rejected,				     SOATAG_REUSE_REJECTED(1)),			      TAG_NEXT(ta_args(ta)));  ta_end(ta);  return tl;}static int soa_static_set_capability_sdp(soa_session_t *ss, 					 sdp_session_t *sdp,					 char const *sdp_str, 					 isize_t sdp_len){  return soa_base_set_capability_sdp(ss, sdp, sdp_str, sdp_len);}static int soa_static_set_remote_sdp(soa_session_t *ss, 				     int new_version,				     sdp_session_t *sdp,				     char const *sdp_str, 				     isize_t sdp_len){  return soa_base_set_remote_sdp(ss, new_version, sdp, sdp_str, sdp_len);}static int soa_static_set_user_sdp(soa_session_t *ss, 				   sdp_session_t *sdp,				   char const *sdp_str, 				   isize_t sdp_len){  return soa_base_set_user_sdp(ss, sdp, sdp_str, sdp_len);}/** Generate a rejected m= line */staticsdp_media_t *soa_sdp_make_rejected_media(su_home_t *home, 					 sdp_media_t const *m,					 sdp_session_t *sdp,					 int include_all_codecs){  sdp_media_t rejected[1] = {{ sizeof (rejected) }};  rejected->m_type = m->m_type;  rejected->m_type_name = m->m_type_name;  rejected->m_port = 0;  rejected->m_proto = m->m_proto;  rejected->m_proto_name = m->m_proto_name;  if (include_all_codecs) {    rejected->m_rtpmaps = m->m_rtpmaps;  }  rejected->m_rejected = 1;  return sdp_media_dup(home, rejected, sdp);}/** Expand a @a truncated SDP. */staticsdp_session_t *soa_sdp_expand_media(su_home_t *home,				    sdp_session_t const *truncated,				    sdp_session_t const *complete){  sdp_session_t *expanded;  sdp_media_t **m0;  sdp_media_t * const *m1;  expanded = sdp_session_dup(home, truncated);  if (expanded) {    for (m0 = &expanded->sdp_media, m1 = &complete->sdp_media;	 *m1;	 m1 = &(*m1)->m_next) {      if (!*m0) {	*m0 = soa_sdp_make_rejected_media(home, *m1, expanded, 0);	if (!*m0)	  return NULL;      }      m0 = &(*m0)->m_next;    }  }  return expanded;}/** Check if @a session should be upgraded with @a remote */ int soa_sdp_upgrade_is_needed(sdp_session_t const *session,			      sdp_session_t const *remote){  sdp_media_t const *rm, *lm;  if (!remote)    return 0;  if (!session)    return 1;  for (rm = remote->sdp_media, lm = session->sdp_media;        rm && lm ; rm = rm->m_next, lm = lm->m_next) {    if (rm->m_rejected)      continue;    if (lm->m_rejected)      break;  }  return rm != NULL;}/** Check if codec is in auxiliary list */staticint soa_sdp_is_auxiliary_codec(sdp_rtpmap_t const *rm, char const *auxiliary){  char const *codec;  size_t clen, alen;  char const *match;  if (!rm || !rm->rm_encoding || !auxiliary)    return 0;  codec = rm->rm_encoding;  clen = strlen(codec), alen = strlen(auxiliary);  if (clen > alen)    return 0;  for (match = auxiliary;       (match = strcasestr(match, codec));       match = match + 1) {    if (IS_ALPHANUM(match[clen]) || match[clen] == '-')      continue;    if (match != auxiliary &&	(IS_ALPHANUM(match[-1]) || match[-1] == '-'))      continue;    return 1;  }  return 0;}staticsdp_rtpmap_t *soa_sdp_media_matching_rtpmap(sdp_rtpmap_t const *from,					    sdp_rtpmap_t const *anylist,					    char const *auxiliary){  sdp_rtpmap_t const *rm;  for (rm = anylist; rm; rm = rm->rm_next) {    /* Ignore auxiliary codecs */    if (auxiliary && soa_sdp_is_auxiliary_codec(rm, auxiliary))      continue;    if (sdp_rtpmap_find_matching(from, rm))      return (sdp_rtpmap_t *)rm;  }  return NULL;}#define SDP_MEDIA_NONE ((sdp_media_t *)-1)/** Find first matching media in table @a mm. * * - if allow_rtp_mismatch == 0, search for a matching codec  * - if allow_rtp_mismatch == 1, prefer m=line with matching codec * - if allow_rtp_mismatch > 1, ignore codecs */staticint soa_sdp_matching_mindex(soa_session_t *ss, 			    sdp_media_t *mm[],			    sdp_media_t const *with,			    int *return_codec_mismatch){  int i, j = -1;  soa_static_session_t *sss = (soa_static_session_t *)ss;  int rtp = sdp_media_uses_rtp(with), dummy;  char const *auxiliary = NULL;  if (return_codec_mismatch == NULL)    return_codec_mismatch = &dummy;  if (with->m_type == sdp_media_audio) {    auxiliary = sss->sss_audio_aux;    /* Looking for a single codec */    if (with->m_rtpmaps && with->m_rtpmaps->rm_next == NULL)      auxiliary = NULL;  }  for (i = 0; mm[i]; i++) {    if (mm[i] == SDP_MEDIA_NONE)      continue;    if (!sdp_media_match_with(mm[i], with))      continue;        if (!rtp)      break;    if (soa_sdp_media_matching_rtpmap(with->m_rtpmaps, 				      mm[i]->m_rtpmaps,				      auxiliary))      break;    if (j == -1)      j = i;  }  if (mm[i])    return *return_codec_mismatch = 0, i;  else    return *return_codec_mismatch = 1, j;}/** Set payload types in @a l_m according to the values in @a r_m. *  * @retval number of common codecs */staticint soa_sdp_set_rtpmap_pt(sdp_media_t *l_m, 			  sdp_media_t const *r_m){  sdp_rtpmap_t *lrm, **next_lrm;  sdp_rtpmap_t const *rrm;  int local_codecs = 0, common_codecs = 0;  unsigned char dynamic_pt[128];  unsigned pt;  for (next_lrm = &l_m->m_rtpmaps; (lrm = *next_lrm); ) {    if (lrm->rm_any) {      /* Remove codecs known only by pt number */      *next_lrm = lrm->rm_next;      continue;    }    else {      next_lrm = &lrm->rm_next;    }    local_codecs++;    rrm = sdp_rtpmap_find_matching(r_m->m_rtpmaps, lrm);    /* XXX - do fmtp comparison */    if (rrm) {      /* Use same payload type as remote */      if (lrm->rm_pt != rrm->rm_pt) {	lrm->rm_predef = 0;	lrm->rm_pt = rrm->rm_pt;      }      common_codecs++;    }    else {      /* Determine payload type later */      lrm->rm_any = 1;    }  }    if (local_codecs == common_codecs)

⌨️ 快捷键说明

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