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

📄 sdp_decode.c

📁 嵌入式系统中c程序实现了rtsp协议的基本内容
💻 C
📖 第 1 页 / 共 4 页
字号:
    if (mptr == NULL) {
      if (sptr->control_string != NULL) {
/*	Rtsp_Printf( "2nd control statement in media\n");
*/
	return (-1);
      }
      sptr->control_string = strdup(lptr);
    } else {
      if (mptr->control_string != NULL) {
/*	Rtsp_Printf( "2nd control statement in session\n");
*/
	return (-1);
      }
      mptr->control_string = strdup(lptr);
    }
    break;
  case 8:
    if (sptr->etag != NULL) {
/*      Rtsp_Printf( "2nd etag statement\n");
*/
      return (-1);
    }
    sptr->etag = strdup(lptr);
    break;
  }
  return (0);
}
	

/*
 * This structure provides the information needed by the parsing
 * engine in sdp_decode_parse_a.  This function processes lines of
 * the format a=<identifier>[:<options>].
 * name - <identifier>
 * len - sizeof(identifier) (saves on CPU time)
 * have_colon - if a colon is necessary
 * remove_spaces_after_colon - if colon is necessary, and we want
 *   to remove spaces before <option>.  Do not use this if other character
 *   sets may come into play.
 * parse_routine - routine to call if keyword matched.  Return 0 if successful-
 *   -1 will save the whole "a=..." string.
 * arg - value to pass to parse_routine
 */
static struct {
  char *name;
  uint32_t len;
  int have_colon;
  int remove_spaces_after_colon;
  int (*parse_routine)(int arg, char *lptr,
		       session_desc_t *sptr, media_desc_t *mptr);
  int arg;
} a_types[] =
{
  { "rtpmap", sizeof("rtpmap"), TRUE, TRUE, sdp_decode_parse_a_rtpmap, 0 },
  { "cat", sizeof("cat"), TRUE, TRUE, sdp_decode_parse_a_cat, 0 },
  { "fmtp", sizeof("fmtp"), TRUE, TRUE, sdp_decode_parse_a_fmtp, 0 },
  { "keywds", sizeof("keywds"), TRUE, FALSE, sdp_decode_parse_a_str, 0},
  { "tool", sizeof("tool"), TRUE, TRUE, sdp_decode_parse_a_str, 1},
  { "charset", sizeof("charset"), TRUE, TRUE, sdp_decode_parse_a_str, 2},
  { "sdplang", sizeof("sdplang"), TRUE, TRUE, sdp_decode_parse_a_str, 3},
  { "lang", sizeof("lang"), TRUE, TRUE, sdp_decode_parse_a_str, 4},
  { "type", sizeof("type"), TRUE, TRUE, sdp_decode_parse_a_str, 5},
  { "orient", sizeof("orient"), TRUE, TRUE, sdp_decode_parse_a_str, 6},
  { "control", sizeof("control"), TRUE, TRUE, sdp_decode_parse_a_str, 7},
  { "etag", sizeof("etag"), TRUE, TRUE, sdp_decode_parse_a_str, 8},
  { "recvonly", sizeof("recvonly"), FALSE, FALSE, sdp_decode_parse_a_bool, 0},
  { "sendrecv", sizeof("sendrecv"), FALSE, FALSE, sdp_decode_parse_a_bool, 1},
  { "sendonly", sizeof("sendonly"), FALSE, FALSE, sdp_decode_parse_a_bool, 2},
  { "ptime", sizeof("ptime"), TRUE, TRUE, sdp_decode_parse_a_int, 0 },
  { "quality", sizeof("quality"), TRUE, TRUE, sdp_decode_parse_a_int, 1},
  { "framerate", sizeof("framerate"), TRUE, TRUE, sdp_decode_parse_a_frame, 0},
  { "range", sizeof("range"), TRUE, TRUE, sdp_decode_parse_a_range, 0 },
  { NULL, 0, FALSE, FALSE, NULL },
};

/*
 * sdp_decode_parse_a()
 * decodes a= lines, or stores the complete string in media or session
 * unparsed_a_lines list.
 */
static int sdp_decode_parse_a (char *lptr,
			       char *line,
			       session_desc_t *sptr,
			       media_desc_t *mptr)
{
  int ix;
  int errret;
  int parsed;
  char *after;
  
  ix = 0;
  errret = 0;
  parsed = FALSE;
  /*
   * go through above array, looking for a complete match
   */
  while (a_types[ix].name != NULL) {
    if (strncmp(lptr,
		    a_types[ix].name,
		    a_types[ix].len - 1) == 0) {
      after = lptr + a_types[ix].len - 1;
      if (!(isspace(*after) ||
	    *after == ':' ||
	    *after == '\0')) {
	/* partial match - not good enough*/
	continue;
      }
			   
      parsed = TRUE;

      /*
       * Have a match.  If specified, look for colon, and remove space
       * after colon
       */
      if (a_types[ix].have_colon) {
	ADV_SPACE(after);
	if (*after != ':') {
	  errret = ESDP_ATTRIBUTES_NO_COLON;
	  break;
	}
	after++;
	if (a_types[ix].remove_spaces_after_colon) {
	  ADV_SPACE(after);
	}
      }
      /*
       * Call the correct parsing routine
       */
      errret = (a_types[ix].parse_routine)(a_types[ix].arg, after, sptr, mptr);
      break;
    }
    ix++;
  }
  /*
   * Worse comes to worst, store the whole line
   */
  if (parsed == FALSE || errret != 0) {
    if (sdp_add_string_to_list(mptr == NULL ?
			   &sptr->unparsed_a_lines :
			   &mptr->unparsed_a_lines,
			   line) == FALSE) {
      return (ST_ERROR_NO_MEMORY);
    }
  }
  return (0);
}

/*
 * sdp_decode_parse_bandwidth()
 * parses b=<modifier>:<value>
 * Inputs: lptr - pointer to line, bptr - pointer to store in
 * Outputs: TRUE - valid, FALSE, invalid
 */
static int sdp_decode_parse_bandwidth (char *lptr,
				       bandwidth_t **bptr)
{
  char *cptr, *endptr;
  bandwidth_t *new, *p;
  bandwidth_modifier_t modifier;
  uint32_t temp;
  cptr = strchr(lptr, ':');
  if (cptr == NULL) {
    Rtsp_Printf( "No colon in bandwidth\n");
    return (ESDP_BANDWIDTH);
  }
  *cptr++ = '\0';
  
  if (strncmp(lptr, "as", strlen("as")) == 0) {
    modifier = BANDWIDTH_MODIFIER_AS;
  } else if (strncmp(lptr, "ct", strlen("ct")) == 0) {
    modifier = BANDWIDTH_MODIFIER_CT;
  } else {
    modifier = BANDWIDTH_MODIFIER_USER;
    endptr = cptr - 2;
    while (isspace(*endptr) && endptr >lptr) *endptr-- = '\0';
  }

  if (*cptr == '\0') {
    Rtsp_Printf( "No bandwidth in bandwidth\n");
    return (ESDP_BANDWIDTH);
  }
  temp = (uint32_t)strtoul(cptr, &endptr, 10);
  if (*endptr != '\0') {
    if(*endptr=='.')
    {
        temp++;
    }
    else
    {
        Rtsp_Printf( "Error in decoding bandwidth value %s\n", cptr);
        return (ESDP_BANDWIDTH);
    }
  }
  
  new = Rtsp_Malloc(sizeof(bandwidth_t),__LINE__,__FILE__);
  if (new == NULL) {
    return (ST_ERROR_NO_MEMORY);
  }
  new->modifier = modifier;
  if (modifier == BANDWIDTH_MODIFIER_USER) {
    new->user_band = strdup(lptr);
    if (new->user_band == NULL) {
      Rtsp_Free(new,__LINE__,__FILE__);
      return (ST_ERROR_NO_MEMORY);
    }
  } else {
	new->user_band = NULL;
  }
  new->bandwidth = temp;
  new->next = NULL;
  if (*bptr == NULL) {
    *bptr = new;
  } else {
    p = *bptr;
    while (p->next != NULL) p = p->next;
    p->next = new;
  }
  return (0);
}

/*
 * sdp_decode_parse_connect()
 * parse c=<network type> <address type> <connect address>
 * Inputs: lptr, connect pointer
 * Outputs - error code or 0 if parsed correctly
 */
static int sdp_decode_parse_connect (char *lptr, connect_desc_t *cptr)
{
  char *sep, *beg;

  cptr->ttl = 0;
  cptr->num_addr = 0;

  /* <network type> should be IN*/
  sep = (char*)strsep(&lptr, SPACES);
  if (sep == NULL ||
      lptr == NULL ||
      strcmp(sep, "IN") != 0) {
    Rtsp_Printf( "IN statement missing from c\n");
    return (ESDP_CONNECT);
  }

  /* <address type> - should be IPV4*/
  ADV_SPACE(lptr);
  sep =(char*)strsep(&lptr, SPACES);
  if (sep == NULL || lptr == NULL) {
    Rtsp_Printf( "No connection type in c=\n");
    return (ESDP_CONNECT);
  }
  cptr->conn_type = strdup(sep);

  /* Address - first look if we have a / - that indicates multicast, and a
  ttl.*/
  ADV_SPACE(lptr);
  sep = strchr(lptr, '/');
  if (sep == NULL) {
    /* unicast address*/
    cptr->conn_addr = strdup(lptr);
    cptr->used = TRUE;
    return (0);
  }

  /* Okay - multicast address.  Take address up to / (get rid of trailing
   spaces)*/
  beg = lptr;
  lptr = sep + 1;
  sep--;
  while (isspace(*sep) && sep > beg) sep--;
  sep++;
  *sep = '\0';
  cptr->conn_addr = strdup(beg);

  /* Now grab the ttl*/
  ADV_SPACE(lptr);
  sep = (char*)strsep(&lptr, " \t/");
  if (!isdigit(*sep)) {
    free_connect_desc(cptr);
/*    Rtsp_Printf( "No multicast TTL in c=\n");
*/
    return (ESDP_CONNECT);
  }
  sscanf(sep, "%u", &cptr->ttl);
  /* And see if we have a number of ports*/
  if (lptr != NULL) {
    /* we have a number of ports, as well*/
    ADV_SPACE(lptr);
    if (!isdigit(*lptr)) {
/*      Rtsp_Printf( "c=: garbage after multicast ttl %s\n", lptr);
*/
      free_connect_desc(cptr);
      return (ESDP_CONNECT);
    }
    sscanf(lptr, "%u", &cptr->num_addr);
  }
  cptr->used = TRUE;
  return (0);
}


/*
 * sdp_decode_parse_key()
 */
static int sdp_decode_parse_key (char *lptr, key_desc_t *kptr)
{
  if (strncmp(lptr, "prompt", strlen("prompt")) == 0) {
    /* handle prompt command*/
    kptr->key_type = KEY_TYPE_PROMPT;
    return (0);
  }
  if (strncmp(lptr, "clear", strlen("clear")) == 0) {
    kptr->key_type = KEY_TYPE_CLEAR;
    lptr += strlen("clear");
  } else if (strncmp(lptr, "base64", strlen("base64")) == 0) {
    kptr->key_type = KEY_TYPE_BASE64;
    lptr += strlen("base64");
  } else if (strncmp(lptr, "uri", strlen("uri")) == 0) {
    kptr->key_type = KEY_TYPE_URI;
    lptr += strlen("uri");
  } else {
    Rtsp_Printf( "key statement keyword error %s\n", lptr);
    return (ESDP_KEY);
  }
  ADV_SPACE(lptr);
  if (*lptr != ':') {
    return (ESDP_KEY);
  }
  lptr++;
  /* Because most of the types can have spaces, we take everything after
   the colon here.  To eliminate the whitespace, use ADV_SPACE(lptr);*/
  kptr->key = strdup(lptr);
  return (0);
}


/*
 * sdp_decode_parse_media()
 * decodes m= lines.
 * m=<media> <port>[/<numport>] <proto> <fmt list>
 * Inputs:
 *   lptr - pointer to line
 *   sptr - pointer to session description to modify
 * Outputs:
 *   pointer to new media description
 */
static media_desc_t *sdp_decode_parse_media (char *lptr,
					     session_desc_t *sptr,
					     int *err)
{
  char *mdesc, *proto, *sep;
  media_desc_t *new, *mp;
  uint32_t read, port_no;
  string_list_t *q;

  *err = 0;
  /* m=<media> <port> <transport> <fmt list>*/
  mdesc =(char*) strsep(&lptr, SPACES);
  if (mdesc == NULL || lptr == NULL) {
    Rtsp_Printf( "No media type\n");
    *err = ESDP_MEDIA;
    return (NULL);
  }

  /* <port>*/
  ADV_SPACE(lptr);
  read = 0;
  if (!isdigit(*lptr)) {
    Rtsp_Printf( "Illegal port number in media %s\n", lptr);
    *err = ESDP_MEDIA;
    return (NULL);
  }
  while (isdigit(*lptr)) {
    read *= 10;
    read += *lptr - '0';
    lptr++;
  }
  ADV_SPACE(lptr);

  /* number of ports (optional)*/
  if (*lptr == '/') {
    lptr++;
    ADV_SPACE(lptr);
    if (!isdigit(*lptr)) {
      Rtsp_Printf( "Illegal port number in media %s\n", lptr);
      *err = ESDP_MEDIA;
      return (NULL);
    }
    sep = (char*)strsep(&lptr, SPACES);
    if (lptr == NULL) {
      Rtsp_Printf( "Missing keywords in media\n");
      *err = ESDP_MEDIA;
      return (NULL);
    }
    sscanf(sep, "%u", &port_no);
    ADV_SPACE(lptr);
  } else {
    port_no = 0;
  }

  /* <transport> (protocol)*/
  proto = (char*)strsep(&lptr, SPACES);
  if (proto == NULL || lptr == NULL) {
    Rtsp_Printf( "No transport in media\n");
    *err = ESDP_MEDIA;
    return (NULL);
  }
  ADV_SPACE(lptr);
  if (!isalnum(*lptr)) {
    *err = ESDP_MEDIA;
    return (NULL);
  }  

  /* malloc memory and set.*/
  new = Rtsp_Malloc(sizeof(media_desc_t),__LINE__,__FILE__);
  if (new == NULL) {
    *err = ST_ERROR_NO_MEMORY;
    return (NULL);
  }
  memset(new, 0, sizeof(media_desc_t));
  new->media =(char*) strdup(mdesc);
  new->port = (uint16_t)read;
  new->proto = strdup(proto);
  new->num_ports = (unsigned short)port_no;
  #if 0 //wxf add it
  new->control_string=Rtsp_Malloc(10,__LINE__,__FILE__);
#endif 
  /* parse format list - these are not necessarilly lists of numbers
   so we store as strings.*/
  q = NULL;
  do {
    sep =(char*)strsep(&lptr, SPACES);
    if (sep != NULL) {
      if (sdp_add_format_to_list(new, sep) == NULL) {
	free_media_desc(new);
	*err = ST_ERROR_NO_MEMORY;
	return (NULL);
      }
      if (lptr != NULL) {
	ADV_SPACE(lptr);
      }
    }
  } while (sep != NULL);

  new->parent = sptr;
  /* Add to list of media*/
  if (sptr->media == NULL) {
    sptr->media = new;
  } else {
    mp = sptr->media;
    while (mp->next != NULL) mp = mp->next;
    mp->next = new;
  }
  
  return (new);
}

/*
 * sdp_decode_parse_origin()
 * parses o= line
 * o=<username> <session id> <version> <network type> <addr type> <addr>
 *
 * Inputs:
 *   lptr - pointer to line to parse
 *   sptr - session desc
 * Output - TRUE, valid, FALSE, invalid
 */
static int sdp_decode_parse_origin (char *lptr, session_desc_t *sptr)
{
  char *username, *sep;

  /* Username - leave null if "-"*/
  username =(char*)strsep(&lptr, SPACES);
  if (username == NULL || lptr == NULL) {
    Rtsp_Printf( "o=: no username\n");
    return (ESDP_ORIGIN);
  }
  ADV_SPACE(lptr);
  if (strcmp(username, "-") != 0) {
    sptr->orig_username = strdup(username);
  }
    
  if (strtou64(&lptr, &sptr->session_id) == FALSE) {
    Rtsp_Printf( "Non-numeric session id\n");
    return (ESDP_ORIGIN);
  }

  if (strtou64(&lptr, &sptr->session_version) == FALSE) {
    Rtsp_Printf( "Non-numeric session version\n");
    return (ESDP_ORIGIN);
  }
  
  ADV_SPACE(lptr);
  sep = (char*)strsep(&lptr, SPACES);
  if ((sep == NULL) ||
      (lptr == NULL) ||
      (strcmp(sep, "IN") != 0)) {
    Rtsp_Printf( "o=: no IN statement\n");
    return (ESDP_ORIGIN);
  }

  ADV_SPACE(lptr);
  sep = (char*)strsep(&lptr, SPACES);
  if (sep == NULL || lptr == NULL) {
    Rtsp_Printf( "o=: No creation address type\n");
    return (ESDP_ORIGIN);
  }
  sptr->create_addr_type = strdup(sep);

  ADV_SPACE(lptr);
  sep =(char*) strsep(&lptr, SPACES);
  if (sep == NULL) {
    Rtsp_Printf( "o=: No creation address\n");
    return (ESDP_ORIGIN);
  }
  sptr->create_addr =(char*) strdup(sep);
  
  return (0);
}

/*
 * sdp_decode_parse_time()
 * decode t= statements
 *
 * Inputs:
 *   sptr - pointer to session_desc_t to write into.
 *   lptr - pointer to line.  Should point at first number (spaces removed)
 *
 * Outputs:
 *   pointer to session_time_desc_t to use as current one.
 *   NULL if string invalid
 */
static session_time_desc_t *sdp_decode_parse_time (char *lptr,
						   session_desc_t *sptr,
						   int *err)
{
  session_time_desc_t *tptr;
  uint32_t start, end;

  *err = 0;
  if (!isdigit(*lptr)) {

⌨️ 快捷键说明

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