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

📄 soa_static.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 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/soa.h"#include <sofia-sip/sdp.h>#include "sofia-sip/soa_session.h"#define NONE ((void *)-1)#define XXX assert(!"implemented")#define str0cmp(a, b) strcmp(a ? a : "", b ? b : "")#if !HAVE_STRCASESTRchar *strcasestr(const char *haystack, const char *needle);#endiftypedef struct soa_static_session{  soa_session_t sss_session[1];}soa_static_session_t;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 *, int);static int soa_static_set_remote_sdp(soa_session_t *ss, 				   int new_version,				   sdp_session_t *sdp,				   char const *, int);static int soa_static_set_user_sdp(soa_session_t *ss, 				   sdp_session_t *sdp,				   char const *, int);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){  return soa_base_set_params(ss, tags);}static int soa_static_get_params(soa_session_t const *ss, tagi_t *tags){    return soa_base_get_params(ss, tags);}static tagi_t *soa_static_get_paramlist(soa_session_t const *ss,					tag_type_t tag, tag_value_t value, 					...){  ta_list ta;  tagi_t *tl;  ta_start(ta, tag, value);  tl = soa_base_get_paramlist(ss, 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, 					 int 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, 				     int 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, 				   int sdp_len){  return soa_base_set_user_sdp(ss, sdp, sdp_str, sdp_len);}/** Generate a rejected m= line */sdp_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. */sdp_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;}/** Find first matching media in table. */sdp_media_t *soa_sdp_matching(soa_session_t *ss, 			      sdp_media_t *mm[],			      sdp_media_t const *with,			      int *return_common_codecs){  int i, j = -1;  sdp_media_t *m;  sdp_rtpmap_t const *rm;  for (i = 0; mm[i]; i++) {    if (!sdp_media_match_with(mm[i], with))      continue;        if (!sdp_media_uses_rtp(with))      break;    if (!return_common_codecs)      break;    /* Check also rtpmaps  */    for (rm = mm[i]->m_rtpmaps; rm; rm = rm->rm_next) {      if (sdp_rtpmap_find_matching(with->m_rtpmaps, rm))	break;    }    if (rm)      break;    if (j == -1)      j = i;  }  if (return_common_codecs)    *return_common_codecs = mm[i] != NULL;  if (mm[i] == NULL && j != -1)    i = j;			/* return m= line without common codecs */  m = mm[i];  for (; mm[i]; i++)    mm[i] = mm[i + 1];  return m;}/** Set payload types in @a l_m according to the values in @a r_m. *  * @retval number of common codecs */int 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)    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 l_m according to the values in @a r_m. * * @return Number of common codecs */int soa_sdp_sort_rtpmap(sdp_rtpmap_t **inout_list, 			sdp_rtpmap_t const *rrm){  sdp_rtpmap_t *sorted = NULL, **next = &sorted, **left;  int common_codecs = 0;  assert(inout_list);  if (!inout_list)    return 0;  /* 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;    common_codecs++;    *next = *left; next = &(*next)->rm_next;    *left = (*left)->rm_next;  }  /* Append leftover codecs */  *next = *inout_list;  *inout_list = sorted;  return common_codecs;}/** Select rtpmaps in @a l_m according to the values in @a r_m. * * @return Number of common codecs */int soa_sdp_select_rtpmap(sdp_rtpmap_t **inout_list, 			  sdp_rtpmap_t const *rrm){  sdp_rtpmap_t **left;  int common_codecs = 0;  assert(inout_list);  if (!inout_list)    return 0;  for (left = inout_list; *left; ) {    if (sdp_rtpmap_find_matching(rrm, (*left)))      /* Select */      left = &(*left)->rm_next, common_codecs++;    else      /* Remove */      *left = (*left)->rm_next;  }  return common_codecs;}/** Sort and select rtpmaps within session */ int soa_sdp_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)      continue;    if (sdp_media_uses_rtp(sm)) {      int common_codecs = soa_sdp_set_rtpmap_pt(sm, rm);      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);      }      if (common_codecs == 0)	;      else if (ss->ss_rtp_select == SOA_RTP_SELECT_SINGLE) {	if (sm->m_rtpmaps)	  sm->m_rtpmaps->rm_next = NULL;      }      else if (ss->ss_rtp_select == SOA_RTP_SELECT_COMMON) {	soa_sdp_select_rtpmap(&sm->m_rtpmaps, rm->m_rtpmaps);      }    }  }  return 0;}/** Upgrade m= lines within session */ int soa_sdp_upgrade(soa_session_t *ss,		    su_home_t *home,		    sdp_session_t *session,		    sdp_session_t const *caps,		    sdp_session_t const *upgrader){  int Ns, Nc, Nu, size, i, j;  sdp_media_t *m, **mm, *cm;  sdp_media_t **s_media, **o_media, **c_media;  sdp_media_t const **u_media;  Ns = sdp_media_count(session, sdp_media_any, 0, 0, 0);  Nc = sdp_media_count(caps, sdp_media_any, 0, 0, 0);  Nu = sdp_media_count(upgrader, sdp_media_any, 0, 0, 0);  if (caps == upgrader)    size = Ns + Nc + 1;  else if (Ns < Nu)    size = Nu + 1;  else    size = Ns + 1;  s_media = su_zalloc(home, size * (sizeof *s_media));  o_media = su_zalloc(home, (Ns + 1) * (sizeof *o_media));  c_media = su_zalloc(home, (Nc + 1) * (sizeof *c_media));  u_media = su_zalloc(home, (Nu + 1) * (sizeof *u_media));

⌨️ 快捷键说明

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