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

📄 sdp_decode.c

📁 嵌入式系统中c程序实现了rtsp协议的基本内容
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 * 
 * The Original Code is MPEG4IP.
 * 
 * The Initial Developer of the Original Code is Cisco Systems Inc.
 * Portions created by Cisco Systems Inc. are
 * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
 * 
 * Contributor(s): 
 *              Bill May        wmay@cisco.com
 */
/*
 * sdp_decode.c
 *
 * decode SDP format from file into session description structures
 * defined in sdp.h
 *
 * October, 2000
 * Bill May (wmay@cisco.com)
 * Cisco Systems, Inc.
 */
/*#include "stddefs.h"
#if ((defined ST_7109 || defined ST_7100 )&& defined ST_OSLINUX)
#include "compat.h"
#endif*/
#include "sdp.h"
#include "sdp_decode_private.h"
#include "rtsp_private.h"
#define ADV_SPACE(a) {while (isspace(*(a)) && (*(a) != '\0'))(a)++;}

static const char *SPACES=" \t";

#define FREE_CHECK(a,b,c,d) if (a->b != NULL) { Rtsp_Free(a->b,c,d); a->b = NULL;}

/*****************************************************************************
 * Memory free routines - frees memory associated with various structures
 *****************************************************************************/
#if 1
static char *strsep (char **sptr, const char *delim)
{
	char *start, *ret;
	start = ret = *sptr;
	if ((ret == NULL) || ret == '\0') {
	   return (NULL);
	}

	while (*ret != '\0' &&
		   strchr(delim, *ret) == NULL) {
		ret++;
	}
	if (*ret == '\0') {
		*sptr = NULL;
	} else {
	    *ret = '\0';
	    ret++;
	    *sptr = ret;
	}
	return (start);
}
#endif

static void free_bandwidth_desc (bandwidth_t *bptr)
{
  bandwidth_t *q;
  while (bptr != NULL) {
    q = bptr;
    bptr = q->next;
    FREE_CHECK(q, user_band,__LINE__,__FILE__);
    Rtsp_Free(q,__LINE__,__FILE__);
  }
}

static void free_category_list (category_list_t **cptr)
{
  category_list_t *p;
  if (*cptr == NULL) return;
  
  while (*cptr != NULL) {
    p = *cptr;
    *cptr = p->next;
    Rtsp_Free(p,__LINE__,__FILE__);
  }
}

static void free_connect_desc (connect_desc_t *cptr)
{
  FREE_CHECK(cptr, conn_type,__LINE__,__FILE__);
  FREE_CHECK(cptr, conn_addr,__LINE__,__FILE__);
}

/*
 * free_media_desc()
 * Frees all memory associated with a media descriptor(mptr)
 */
static void free_media_desc (media_desc_t *mptr)
{
  free_bandwidth_desc(mptr->media_bandwidth);
  mptr->media_bandwidth = NULL;
  free_connect_desc(&mptr->media_connect);
  sdp_free_format_list(&mptr->fmt);
  sdp_free_string_list(&mptr->unparsed_a_lines);
  FREE_CHECK(mptr, media,__LINE__,__FILE__);
  FREE_CHECK(mptr, media_desc,__LINE__,__FILE__);
  FREE_CHECK(mptr, proto,__LINE__,__FILE__);
  FREE_CHECK(mptr, sdplang,__LINE__,__FILE__);
  FREE_CHECK(mptr, lang,__LINE__,__FILE__);
  FREE_CHECK(mptr, orient_user_type,__LINE__,__FILE__);
  FREE_CHECK(mptr, control_string,__LINE__,__FILE__);
  FREE_CHECK(mptr, key.key,__LINE__,__FILE__);
  mptr->parent = NULL;
  Rtsp_Free(mptr,__LINE__,__FILE__);
}

static void free_time_desc (session_time_desc_t *time)
{
  time_repeat_desc_t *rptr;
  
  if (time->next != NULL) {
    free_time_desc(time->next);
    time->next = NULL;
  }
  while (time->repeat != NULL) {
    rptr = time->repeat;
    time->repeat = rptr->next;
    Rtsp_Free(rptr,__LINE__,__FILE__);
  }

  Rtsp_Free(time,__LINE__,__FILE__);
}

/*
 * sdp_free_session_desc()
 * Inputs - sptr - pointer to session_description list to free
 */
void sdp_free_session_desc (session_desc_t *sptr)
{
  session_desc_t *p;
  media_desc_t *mptr, *q;

  p = sptr;
  while (p != NULL) {
    sptr = p;
    p = p->next;
    
    sptr->next = NULL;
    mptr = sptr->media;
    sptr->media = NULL;

    while (mptr != NULL) {
      q = mptr;
      mptr = q->next;
      free_media_desc(q);
    }

    FREE_CHECK(sptr, etag,__LINE__,__FILE__);
    FREE_CHECK(sptr, orig_username,__LINE__,__FILE__);
    FREE_CHECK(sptr, control_string,__LINE__,__FILE__);
    FREE_CHECK(sptr, create_addr_type,__LINE__,__FILE__);
    FREE_CHECK(sptr, create_addr,__LINE__,__FILE__);
    FREE_CHECK(sptr, session_name,__LINE__,__FILE__);
    FREE_CHECK(sptr, session_desc,__LINE__,__FILE__);
    FREE_CHECK(sptr, uri,__LINE__,__FILE__);
    FREE_CHECK(sptr, key.key,__LINE__,__FILE__);
    FREE_CHECK(sptr, keywds,__LINE__,__FILE__);
    FREE_CHECK(sptr, lang,__LINE__,__FILE__);
    FREE_CHECK(sptr, tool,__LINE__,__FILE__);
    FREE_CHECK(sptr, charset,__LINE__,__FILE__);
    FREE_CHECK(sptr, sdplang,__LINE__,__FILE__);
    FREE_CHECK(sptr, conf_type_user,__LINE__,__FILE__);

    if (sptr->time_desc != NULL) {
      free_time_desc(sptr->time_desc);
      sptr->time_desc = NULL;
    }

    free_bandwidth_desc(sptr->session_bandwidth);
    sptr->session_bandwidth = NULL;
    free_category_list(&sptr->category_list);
    free_connect_desc(&sptr->session_connect);
    sdp_free_string_list(&sptr->admin_phone);
    sdp_free_string_list(&sptr->admin_email);
    sdp_free_string_list(&sptr->unparsed_a_lines);
    
    while (sptr->time_adj_desc != NULL) {
      time_adj_desc_t *aptr;
      aptr = sptr->time_adj_desc;
      sptr->time_adj_desc = aptr->next;
      Rtsp_Free(aptr,__LINE__,__FILE__);
    }
  
    Rtsp_Free(sptr,__LINE__,__FILE__);
  }
}

/*****************************************************************************
 * Utility routines - string manipulation, etc
 *****************************************************************************/
/*
 * get_next_line will get the next line to process, and stick it in
 * lptr.
 *
 * Inputs:
 *    lptr - buffer to store into
 *    decode - pointer to where to get next line
 *    buflen - max length of buffer
 *
 * Outputs:
 *    TRUE - have a new line.
 *    FALSE - all done.
 */
static int get_next_line (char **polptr,
			  sdp_decode_info_t *decode,
			  uint32_t *buflen)
{
  char *fret;
  int len;
  uint32_t buflen_left;
  const char *cptr;

  if (decode->isMem) {
    cptr = decode->memptr;

    if (*cptr == '\0') return FALSE;

    while (*cptr != '\0' && *cptr != '\n' && *cptr != '\r') cptr++;

    len = cptr - decode->memptr;
    if (*buflen <= len + 1) {
      if (len > 65535) {
	Rtsp_Printf( "Max line length of 65535 exceeded %u\n", 
		  len);
	return (FALSE);
      }
      *polptr = realloc(*polptr, len + 1);
      *buflen = len + 1;
    }
    memcpy(*polptr, decode->memptr, len);
    (*polptr)[len] = '\0';
    decode->memptr += len;
    while (*decode->memptr == '\n' || *decode->memptr == '\r')
      decode->memptr++;
  } else {
    char *ptr;
    /* File reads...*/
    if (decode->ifile == NULL)
      return FALSE;
    if (*buflen == 0) {
      *polptr = (char *)Rtsp_Malloc(1024,__LINE__,__FILE__);
      *buflen = 1024;
    }

    /* Read file until we hit the end, or a non-blank line read*/
    ptr = *polptr;
    buflen_left = *buflen;
    len = 0;

    while (1) {
      fret = fgets(ptr, buflen_left, decode->ifile);
      if (fret == NULL) {
	if (len > 0) {
/*	  Rtsp_Printf( "Unterminated last line\n");
*/
	  (*polptr)[len] = '\0'; /* make sure*/
	  return (TRUE);
	}
	return (FALSE);
      }

      len = strlen(ptr);
      if (ptr[len - 1] == '\n' || ptr[len - 1] == '\r') {
	/* we have an end of line*/
	len--;
	while (len >= 0 &&
	       (ptr[len] == '\n' || ptr[len] == '\r')) {
	  ptr[len] = '\0';
	  len--;
	}
	return (TRUE);
      }
      
      /* too long...*/
      buflen_left -= len;
      if (*buflen + 1024 > 65535) {
	Rtsp_Printf( "Max line length of 65535 exceeded %u\n", 
		  *buflen);
	return (FALSE);
      }
      *buflen += 1024;
      buflen_left += 1024;
      *polptr = realloc(*polptr, *buflen);
      ptr = *polptr + *buflen - buflen_left;
    }
  }

  return TRUE;
}

/*
 * strtou64()
 * Converts string to uint32_t number up to next space, with error checking.
 * Inputs:
 *    lptr - pointer to pointer to string.  *lptr will be modified
 *    num - return value
 * Outputs - TRUE - sucess, FALSE, failure
 */
static int strtou64 (char **lptr, uint32_t *num)
{
  char *sep;
  
  *num = 0;
  ADV_SPACE((*lptr));
  sep = (char*)strsep(lptr, SPACES);
  if (sep == NULL || *lptr == NULL) {
    return (FALSE);
  }
  *num = 0;
  while (*sep != '\0') {
    if (isdigit(*sep)) {
      *num *= 10;
      *num += *sep - '0';
      sep++;
    } else {
      return (FALSE);
    }
  }
  return (TRUE);
}

/*
 * str_to_time_offset()
 * converts typed-time field (number or [#d][#h][#m][#s])
 *
 * Inputs -
 *   str - \0 terminated string to translate
 *   retval - pointer to return value
 * Returns -
 *   TRUE - valid string processed;
 *   FALSE - invalid string
 */
static int str_to_time_offset (const char *str, uint32_t *retval)
{
  uint32_t value;
  uint32_t accum;
  char temp;
  
  value = 0;
  accum = 0;

  if (!isdigit(*str)) return (FALSE);
  
  while (*str != '\0') {
    if (isdigit(*str)) {
      accum *= 10;
      accum += (*str - '0');
    } else {
      temp = tolower(*str);
      if (temp == 'd') {
	value += accum * SEC_PER_DAY;
	accum = 0;
      } else if (temp == 'h') {
	value += accum * SEC_PER_HOUR;
	accum = 0;
      } else if (temp == 'm') {
	value += accum * SEC_PER_MINUTE;
	accum = 0;
      } else if (temp == 's') {
	value += accum;
	accum = 0;
      } else {
	Rtsp_Printf( "Illegal character %c in time offset\n", temp);
	return (FALSE);
      }
    }
    str++;
  }
  value += accum;
  *retval = value;
  return (TRUE);
}

/*
 * time_adj_order_in_list()
 * order linked list by adj_time values.  We don't allow 2 items in the
 * list - "new" value might be free'd at end
 * Inputs:
 *   start - pointer to start of list
 *   new - pointer to new value
 * Returns:
 *   pointer to head of list - new value might be free'd.
 */
static time_adj_desc_t *time_adj_order_in_list (time_adj_desc_t *start,
						time_adj_desc_t *new)
{
  time_adj_desc_t *p, *q;
  if (start == NULL)
    return (new);

  p = start;
  q = NULL;
  while (p != NULL) {
    if (new->adj_time == p->adj_time) {
      Rtsp_Printf( "Duplicate time %ld in adj description\n", p->adj_time);
      Rtsp_Free(new,__LINE__,__FILE__);
      return (start);
    }
    if (new->adj_time < p->adj_time) {
      new->next = p;
      if (q == NULL) {
	return (new);
      } else {
	q->next = new;
	return (start);
      }
    }
    q = p;
    p = p->next;
  }
  q->next = new;
  return (start);
}


/*****************************************************************************
 * Line parsing routines
 *****************************************************************************/
/*
 * sdp_decode_parse_a_bool()
 * parses a boolean field.
 */
static int sdp_decode_parse_a_bool (int arg,
				    char *lptr,
				    session_desc_t *sptr,
				    media_desc_t *mptr)
{
  switch (arg) {
  case 0:
    if (mptr != NULL) mptr->recvonly = TRUE;
    else sptr->recvonly = TRUE;
    break;
  case 1:
    if (mptr != NULL) mptr->sendrecv = TRUE;
    else sptr->sendrecv = TRUE;
    break;
  case 2:
    if (mptr != NULL) mptr->sendonly = TRUE;
    else sptr->sendonly = TRUE;
    break;

  }
  return (0);
}

/*
 * sdp_decode_parse_a_rtpmap()
 * parses a=rtpmap:<fmt> <name>/<clockrate>[/<enc_param>]
 */
static int sdp_decode_parse_a_fmtp (int arg,
				    char *lptr,
				    session_desc_t *sptr,
				    media_desc_t *mptr)
{
  format_list_t *fptr;
  int len;
  
  if (mptr == NULL)
    return (-1);

  /*
   * See our format matches a value in the media's format list.
   */
  fptr = sdp_find_format_in_line(mptr->fmt,lptr) ;

  if (fptr == NULL) {
    Rtsp_Printf( "Can't find fmtp format %s in media format list\n", lptr);
    return (-1);
  }

  len = strlen(fptr->fmt);
  lptr += len;
  lptr++;
  ADV_SPACE(lptr);
  fptr->fmt_param = strdup(lptr);
  if (fptr->fmt_param == NULL) {
    return (-1);
  }
  return (0);
}

/*
 * sdp_decode_parse_a_rtpmap()
 * parses a=rtpmap:<fmt> <name>/<clockrate>[/<enc_param>]
 */
static int sdp_decode_parse_a_rtpmap (int arg,
				      char *lptr,
				      session_desc_t *sptr,
				      media_desc_t *mptr)
{
  char *enc, *slash, *temp;
  format_list_t *fptr;
  int len;
  uint32_t a, b;
  
  if (mptr == NULL)
    return (-1);

  /*
   * See our format matches a value in the media's format list.
   */
  fptr = sdp_find_format_in_line(mptr->fmt,lptr) ;

  if (fptr == NULL) {
    Rtsp_Printf( "Can't find rtpmap format %s in media list\n", lptr);
    return (-1);
  }

  len = strlen(fptr->fmt);
  /*
   * Matches entry left in fptr.  Decode rest of line
   */
  enc = lptr + len;
  ADV_SPACE(enc);
  slash = strchr(enc, '/');  
  if (slash != NULL) {
    *slash++ = '\0';
    temp = enc;
    while ((!(isspace(*temp))) && *temp != '\0') temp++;
    *temp = '\0';
  
    /* enc points to encode name*/
    ADV_SPACE(slash);

⌨️ 快捷键说明

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