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

📄 sdp_decode.c

📁 完整的RTP RTSP代码库
💻 C
📖 第 1 页 / 共 4 页
字号:
    break;  case 7: // control    if (mptr == NULL) {      if (sptr->control_string != NULL) {	sdp_debug(LOG_ERR, "2nd control statement in media");	return (-1);      }      sptr->control_string = strdup(lptr);    } else {      if (mptr->control_string != NULL) {	sdp_debug(LOG_ERR, "2nd control statement in session");	return (-1);      }      mptr->control_string = strdup(lptr);    }    break;  case 8:    if (sptr->etag != NULL) {      sdp_debug(LOG_ERR, "2nd etag statement");      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 },  { "rtcp", sizeof("rtcp"), TRUE, TRUE, sdp_decode_parse_a_rtcp, 0 },  { NULL, 0, FALSE, FALSE, NULL, 0 },};/* * 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 (strncasecmp(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 (ENOMEM);    }  }  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) {    sdp_debug(LOG_ERR, "No colon in bandwidth");    return (ESDP_BANDWIDTH);  }  *cptr++ = '\0';    if (strncasecmp(lptr, "as", strlen("as")) == 0) {    modifier = BANDWIDTH_MODIFIER_AS;  } else if (strncasecmp(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') {    sdp_debug(LOG_ERR, "No bandwidth in bandwidth");    return (ESDP_BANDWIDTH);  }  temp = strtoul(cptr, &endptr, 10);  if (*endptr != '\0') {    sdp_debug(LOG_ERR, "Error in decoding bandwidth value %s", cptr);    return (ESDP_BANDWIDTH);  }    new = malloc(sizeof(bandwidth_t));  if (new == NULL) {    return (ENOMEM);  }  new->modifier = modifier;  if (modifier == BANDWIDTH_MODIFIER_USER) {    new->user_band = strdup(lptr);    if (new->user_band == NULL) {      free(new);      return (ENOMEM);    }  } 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;  if (cptr->used != FALSE) return ESDP_CONNECT;  cptr->ttl = 0;  cptr->num_addr = 0;  // <network type> should be IN  sep = strsep(&lptr, SPACES);  if (sep == NULL ||      lptr == NULL ||      strcasecmp(sep, "IN") != 0) {    sdp_debug(LOG_ERR, "IN statement missing from c");    return (ESDP_CONNECT);  }  // <address type> - should be IPV4  ADV_SPACE(lptr);  sep = strsep(&lptr, SPACES);  if (sep == NULL || lptr == NULL) {    sdp_debug(LOG_ERR, "No connection type in c=");    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 = strsep(&lptr, " \t/");  if (!isdigit(*sep)) {    free_connect_desc(cptr);    sdp_debug(LOG_ERR, "No multicast TTL in c=");    return (ESDP_CONNECT);  }  if (sscanf(sep, "%u", &cptr->ttl) != 1) return -1;  // 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)) {      sdp_debug(LOG_ERR, "c=: garbage after multicast ttl %s", lptr);      free_connect_desc(cptr);      return (ESDP_CONNECT);    }    if (sscanf(lptr, "%u", &cptr->num_addr) != 1) return -1;  }  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 (strncasecmp(lptr, "clear", strlen("clear")) == 0) {    kptr->key_type = KEY_TYPE_CLEAR;    lptr += strlen("clear");  } else if (strncasecmp(lptr, "base64", strlen("base64")) == 0) {    kptr->key_type = KEY_TYPE_BASE64;    lptr += strlen("base64");  } else if (strncasecmp(lptr, "uri", strlen("uri")) == 0) {    kptr->key_type = KEY_TYPE_URI;    lptr += strlen("uri");  } else {    sdp_debug(LOG_ERR, "key statement keyword error %s", 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);  if (kptr->key == NULL)    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_in, port_no;  string_list_t *q;  *err = 0;  // m=<media> <port> <transport> <fmt list>  mdesc = strsep(&lptr, SPACES);  if (mdesc == NULL || lptr == NULL) {    sdp_debug(LOG_CRIT, "No media type");    *err = ESDP_MEDIA;    return (NULL);  }  // <port>  ADV_SPACE(lptr);  read_in = 0;  if (!isdigit(*lptr)) {    sdp_debug(LOG_ERR, "Illegal port number in media %s", lptr);    *err = ESDP_MEDIA;    return (NULL);  }  while (isdigit(*lptr)) {    read_in *= 10;    read_in += *lptr - '0';    lptr++;  }  ADV_SPACE(lptr);  // number of ports (optional)  if (*lptr == '/') {    lptr++;    ADV_SPACE(lptr);    if (!isdigit(*lptr)) {      sdp_debug(LOG_ERR, "Illegal port number in media %s", lptr);      *err = ESDP_MEDIA;      return (NULL);    }    sep = strsep(&lptr, SPACES);    if (lptr == NULL) {      sdp_debug(LOG_ERR, "Missing keywords in media");      *err = ESDP_MEDIA;      return (NULL);    }    if (sscanf(sep, "%u", &port_no) != 1) {      *err = ESDP_MEDIA;      return NULL;    }    ADV_SPACE(lptr);  } else {    port_no = 0;  }  // <transport> (protocol)  proto = strsep(&lptr, SPACES);  if (proto == NULL || lptr == NULL) {    sdp_debug(LOG_ERR, "No transport in media");    *err = ESDP_MEDIA;    return (NULL);  }  ADV_SPACE(lptr);  if (!isalnum(*lptr)) {    *err = ESDP_MEDIA;    return (NULL);  }    // malloc memory and set.  new = malloc(sizeof(media_desc_t));  if (new == NULL) {    *err = ENOMEM;    return (NULL);  }  memset(new, 0, sizeof(media_desc_t));  new->media = strdup(mdesc);  new->port = (uint16_t)read_in;  new->proto = strdup(proto);  new->num_ports = (unsigned short)port_no;  // parse format list - these are not necessarilly lists of numbers  // so we store as strings.  q = NULL;  do {    sep = strsep(&lptr, SPACES);    if (sep != NULL) {      if (sdp_add_format_to_list(new, sep) == NULL) {	sdp_free_media_desc(new);	*err = ENOMEM;	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;  if (sptr->create_addr_type != NULL) return ESDP_ORIGIN;  // Username - leave null if "-"  username = strsep(&lptr, SPACES);  if (username == NULL || lptr == NULL) {    sdp_debug(LOG_ERR, "o=: no username");    return (ESDP_ORIGIN);  }  ADV_SPACE(lptr);  if (strcmp(username, "-") != 0) {    sptr->orig_username = strdup(username);  }      if (strtou64(&lptr, &sptr->session_id) == FALSE) {    sdp_debug(LOG_ERR, "Non-numeric session id");    return (ESDP_ORIGIN);  }  if (strtou64(&lptr, &sptr->session_version) == FALSE) {    sdp_debug(LOG_ERR, "Non-numeric session version");    return (ESDP_ORIGIN);  }    ADV_SPACE(lptr);  sep = strsep(&lptr, SPACES);  if ((sep == NULL) ||      (lptr == NULL) ||      (strcasecmp(sep, "IN") != 0)) {    sdp_debug(LOG_ERR, "o=: no IN statement");    return (ESDP_ORIGIN);  }  ADV_SPACE(lptr);  sep = strsep(&lptr, SPACES);  if (sep == NULL || lptr == NULL) {    sdp_debug(LOG_ERR, "o=: No creation address type");    return (ESDP_ORIGIN);  }  sptr->create_addr_type = strdup(sep);  ADV_SPACE(lptr);  sep = strsep(&lptr, SPACES);  if (sep == NULL) {    sdp_debug(LOG_ERR, "o=: No creation address");    return (ESDP_ORIGIN);  }  sptr->create_addr = 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){

⌨️ 快捷键说明

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