📄 sdp_decode.c
字号:
/* * 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 "sdp.h"#include "sdp_decode_private.h"static const char *SPACES=" \t";#define FREE_CHECK(a,b) if (a->b != NULL) { free((void*)a->b); a->b = NULL;}/***************************************************************************** * Memory free routines - frees memory associated with various structures *****************************************************************************/static void free_bandwidth_desc (bandwidth_t *bptr){ bandwidth_t *q; while (bptr != NULL) { q = bptr; bptr = q->next; FREE_CHECK(q, user_band); free(q); }}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; free(p); }}static void free_connect_desc (connect_desc_t *cptr){ FREE_CHECK(cptr, conn_type); FREE_CHECK(cptr, conn_addr);}/* * sdp_free_media_desc() * Frees all memory associated with a media descriptor(mptr) */void sdp_free_media_desc (media_desc_t *mptr){ free_bandwidth_desc(mptr->media_bandwidth); mptr->media_bandwidth = NULL; free_connect_desc(&mptr->media_connect); free_connect_desc(&mptr->rtcp_connect); sdp_free_format_list(&mptr->fmt_list); sdp_free_string_list(&mptr->unparsed_a_lines); FREE_CHECK(mptr, media); FREE_CHECK(mptr, media_desc); FREE_CHECK(mptr, proto); FREE_CHECK(mptr, sdplang); FREE_CHECK(mptr, lang); FREE_CHECK(mptr, orient_user_type); FREE_CHECK(mptr, control_string); FREE_CHECK(mptr, key.key); mptr->parent = NULL; free(mptr);}static void free_time_desc (session_time_desc_t *ptime){ time_repeat_desc_t *rptr; if (ptime->next != NULL) { free_time_desc(ptime->next); ptime->next = NULL; } while (ptime->repeat != NULL) { rptr = ptime->repeat; ptime->repeat = rptr->next; free (rptr); } free(ptime);}/* * 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; sdp_free_media_desc(q); } FREE_CHECK(sptr, etag); FREE_CHECK(sptr, orig_username); FREE_CHECK(sptr, control_string); FREE_CHECK(sptr, create_addr_type); FREE_CHECK(sptr, create_addr); FREE_CHECK(sptr, session_name); FREE_CHECK(sptr, session_desc); FREE_CHECK(sptr, uri); FREE_CHECK(sptr, key.key); FREE_CHECK(sptr, keywds); FREE_CHECK(sptr, lang); FREE_CHECK(sptr, tool); FREE_CHECK(sptr, charset); FREE_CHECK(sptr, sdplang); FREE_CHECK(sptr, conf_type_user); 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; free(aptr); } free(sptr); }}/***************************************************************************** * 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; uint32_t 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 (*polptr == NULL || *buflen <= len + 1) { if (len > 65535) { sdp_debug(LOG_CRIT, "Max line length of 65535 exceeded %u", len); return (FALSE); } *polptr = realloc(*polptr, len + 1); if (*polptr == NULL) return FALSE; *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 *)malloc(1024); if (*polptr == NULL) return FALSE; *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) { sdp_debug(LOG_WARNING, "Unterminated last line"); (*polptr)[len] = '\0'; // make sure return (TRUE); } return (FALSE); } len = strlen(ptr); if (len == 0) return FALSE; 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) { sdp_debug(LOG_CRIT, "Max line length of 65535 exceeded %u", *buflen); return (FALSE); } *buflen += 1024; buflen_left += 1024; *polptr = realloc(*polptr, *buflen); if (*polptr == NULL) return FALSE; ptr = *polptr + *buflen - buflen_left; } } return TRUE;}/* * strtou64() * Converts string to uint64_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, uint64_t *num){ char *sep; *num = 0; ADV_SPACE((*lptr)); sep = 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 { sdp_debug(LOG_ERR, "Illegal character %c in time offset", 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) { sdp_debug(LOG_NOTICE, "Duplicate time %ld in adj description", p->adj_time); free(new); 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_list, lptr) ; if (fptr == NULL) { sdp_debug(LOG_ALERT, "Can't find fmtp format %s in media format list", lptr); return (-1); } if (fptr->fmt_param != NULL) { sdp_debug(LOG_ALERT, "Duplicate fmpt line %s", 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_list, lptr); if (fptr == NULL) { sdp_debug(LOG_ALERT, "Can't find rtpmap format %s in media list", lptr); return (-1); } if (fptr->rtpmap_name != NULL) { sdp_debug(LOG_ALERT, "rtpmap already loaded in fmt %s", fptr->fmt); 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); temp = strsep(&slash, " \t/"); if (temp == NULL) { sdp_debug(LOG_ERR, "Can't find seperator after encode name in rtpmap"); return (-1); } if (sscanf(temp, "%u", &a) == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -