📄 parser.c
字号:
/* This file is part of FreeSDP Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org> FreeSDP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Benjamin Zores, (C) 2006 added support in parser for the a=control: lines. added support in parser for the a=range: lines.*//** * @file parser.c * * @short Parsing module implementation. * * This file implements the parsing routine <code>fsdp_parse</code> * and the <code>fsdp_get_xxxx</code> routines that allow to get the * session properties from a session description object build through * the application of <code>fsdp_parse</code> to a textual SDP session * description. **/#include "parserpriv.h"/** * \brief find the start of the next line * \param c pointer to current position in string * \return pointer to start of next line or NULL if illegal (i.e. * a '\r' is not followed by a '\n' */static const char *next_line(const char *c) { c += strcspn(c, "\n\r"); if (*c == 0) return c; if (*c == '\r') c++; if (*c == '\n') return c + 1; return NULL;}/** * Moves the <code>c<code> pointer up to the beginning of the next * line. * * @param c char pointer to pointer * @retval FSDPE_ILLEGAL_CHARACTER, when an illegal '\r' character * (not followed by a '\n') is found, returns */#define NEXT_LINE(c) do { if (!(c = next_line(c))) return FSDPE_ILLEGAL_CHARACTER; } while (0);fsdp_error_tfsdp_parse (const char *text_description, fsdp_description_t * dsc){ fsdp_error_t result; const char *p = text_description, *p2; unsigned int index, j; /* temps for sscanf */ const unsigned int TEMPCHARS = 6; char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN]; char longfsdp_buf[MAXLONGFIELDLEN]; const unsigned int TEMPINTS = 2; unsigned long int wuint[TEMPINTS]; if ((NULL == text_description) || (NULL == dsc)) return FSDPE_INVALID_PARAMETER; /***************************************************************************/ /* A) parse session-level description */ /***************************************************************************/ /* `v=' line (protocol version) */ /* according to the RFC, only `v=0' is valid */ if (sscanf (p, "v=%1lu", &wuint[0])) { if (wuint[0] != 0) return FSDPE_INVALID_VERSION; } else { return FSDPE_MISSING_VERSION; } NEXT_LINE (p); /* `o=' line (owner/creator and session identifier) */ /* o=<username> <session id> <version> <network type> <address type> <address> */ if (!strncmp (p, "o=", 2)) { p += 2; /* note that the following max lengths may vary in the future and are quite arbitary */ if (sscanf (p, "%" MSFLENS "[\x21-\xFF] %" MSFLENS "[0-9] %" MSFLENS "[0-9] %2s %3s %" MSFLENS "s", fsdp_buf[0], fsdp_buf[1], fsdp_buf[2], fsdp_buf[3], fsdp_buf[4], fsdp_buf[5]) != 6) return FSDPE_INVALID_OWNER; dsc->o_username = strdup (fsdp_buf[0]); dsc->o_session_id = strdup (fsdp_buf[1]); dsc->o_announcement_version = strdup (fsdp_buf[2]); if (!strncmp (fsdp_buf[3], "IN", 2)) { dsc->o_network_type = FSDP_NETWORK_TYPE_INET; if (!strncmp (fsdp_buf[4], "IP4", 3)) dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV4; else if (!strncmp (fsdp_buf[4], "IP6", 3)) dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV6; else return FSDPE_INVALID_OWNER; } else { return FSDPE_INVALID_OWNER; } /* TODO? check valid unicast address/FQDN */ dsc->o_address = strdup (fsdp_buf[5]); } else { return FSDPE_MISSING_OWNER; } NEXT_LINE (p); /* `s=' line (session name) -note that the name string cannot be empty */ /* s=<session name> */ if (!strncmp (p, "s=", 2)) { if (sscanf (p, "s=%" MLFLENS "[^\r\n]", longfsdp_buf) < 1) return FSDPE_EMPTY_NAME; dsc->s_name = strdup (longfsdp_buf); } else { return FSDPE_MISSING_NAME; } NEXT_LINE (p); /* `i=' line (session information) [optional] */ /* i=<session description> */ if (!strncmp (p, "i=", 2) && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf)) { dsc->i_information = strdup (longfsdp_buf); NEXT_LINE (p); } else { /* (optional) information absent */ } /* `u=' line (URI of description) [optional] */ /* u=<URI> */ if (!strncmp (p, "u=", 2) && sscanf (p, "u=%" MLFLENS "[^\r\n]", longfsdp_buf)) { /* TODO? check valid uri */ dsc->u_uri = strdup (longfsdp_buf); NEXT_LINE (p); } else { /* (optional) uri absent */ } /* `e=' lines (email address) [zero or more] */ /* e=<email address> */ p2 = p; j = 0; while (!strncmp (p2, "e=", 2)) { /* First, count how many emails are there */ j++; NEXT_LINE (p2); } dsc->emails_count = j; if (dsc->emails_count > 0) { /* Then, build the array of emails */ dsc->emails = calloc (j, sizeof (const char *)); for (j = 0; j < dsc->emails_count; j++) { sscanf (p, "e=%" MLFLENS "[^\r\n]", longfsdp_buf); /* TODO? check valid email-address. */ dsc->emails[j] = strdup (longfsdp_buf); NEXT_LINE (p); } } /* `p=' lines (phone number) [zero or more] */ /* p=<phone number> */ j = 0; /* assert ( p2 == p ); */ while (!strncmp (p2, "p=", 2)) { j++; NEXT_LINE (p2); } dsc->phones_count = j; if (dsc->phones_count > 0) { dsc->phones = calloc (j, sizeof (const char *)); for (j = 0; j < dsc->phones_count; j++) { sscanf (p, "p=%" MLFLENS "[^\r\n]", longfsdp_buf); /* TODO? check valid phone-number. */ dsc->phones[j] = strdup (longfsdp_buf); NEXT_LINE (p); } } /* `c=' line (connection information - not required if included in all media) [optional] */ /* c=<network type> <address type> <connection address> */ result = fsdp_parse_c (&p, &(dsc->c_network_type), &(dsc->c_address_type), &(dsc->c_address)); if (FSDPE_OK != result) return result; /* `b=' lines (bandwidth information) [optional] */ /* b=<modifier>:<bandwidth-value> */ result = fsdp_parse_b (&p, &(dsc->bw_modifiers), &(dsc->bw_modifiers_count)); if (FSDPE_OK != result) return result; /* A.1) Time descriptions: */ /* `t=' lines (time the session is active) [1 or more] */ /* t=<start time> <stop time> */ j = 0; p2 = p; while (!strncmp (p2, "t=", 2)) { j++; NEXT_LINE (p2); while (!strncmp (p2, "r=", 2)) NEXT_LINE (p2); } dsc->time_periods_count = j; if (dsc->time_periods_count == 0) return FSDPE_MISSING_TIME; dsc->time_periods = calloc (dsc->time_periods_count, sizeof (fsdp_time_period_t *)); index = 0; for (j = 0; j < dsc->time_periods_count; j++) { unsigned int h = 0; if (sscanf (p, "t=%10lu %10lu", &wuint[0], &wuint[1]) != 2) { /* not all periods have been successfully parsed */ dsc->time_periods_count = j; return FSDPE_INVALID_TIME; } dsc->time_periods[j] = calloc (1, sizeof (fsdp_time_period_t)); /* convert from NTP to time_t time */ if (wuint[0] != 0) wuint[0] -= NTP_EPOCH_OFFSET; if (wuint[1] != 0) wuint[1] -= NTP_EPOCH_OFFSET; dsc->time_periods[j]->start = wuint[0]; dsc->time_periods[j]->stop = wuint[1]; NEXT_LINE (p); /* `r' lines [zero or more repeat times for each t=] */ /*r=<repeat interval> <active duration> <list of offsets from start-time> */ p2 = p; while (!strncmp (p2, "r=", 2)) { h++; NEXT_LINE (p2); } dsc->time_periods[j]->repeats_count = h; if (h > 0) { unsigned int index2 = 0; dsc->time_periods[j]->repeats = calloc (h, sizeof (fsdp_repeat_t *)); for (h = 0; h < dsc->time_periods[j]->repeats_count; h++) { /* get_repeat_values(p,&(dsc->time_periods[index].repeats[index2])); fsdp_error_t get_repeat_values (const char *r, fsdp_repeat_t *repeat); */ if (sscanf (p, "r=%10s %10s %" MLFLENS "[^\r\n]", fsdp_buf[0], fsdp_buf[1], longfsdp_buf) == 3) { fsdp_repeat_t *repeat; dsc->time_periods[j]->repeats[h] = calloc (1, sizeof (fsdp_repeat_t)); repeat = dsc->time_periods[j]->repeats[h]; /* get interval, duration and list of offsets */ result = fsdp_repeat_time_to_uint (fsdp_buf[0], &(repeat->interval)); if (result == FSDPE_OK) { result = fsdp_repeat_time_to_uint (fsdp_buf[1], &(repeat->duration)); if (result == FSDPE_OK) { unsigned int k = 1; const char *i = longfsdp_buf; while (NULL != (i = strchr (i, ' '))) { k++; if (NULL != i) i++; } repeat->offsets_count = k; repeat->offsets = calloc (k, sizeof (time_t)); i = longfsdp_buf; for (k = 0; (k < repeat->offsets_count) && (result == FSDPE_OK); k++) { result = fsdp_repeat_time_to_uint (i, &(repeat-> offsets[k])); i = strchr (i, ' '); if (NULL != i) i++; } if (k < repeat->offsets_count) { /* there where invalid repeat offsets */ dsc->time_periods[j]->repeats_count = k; return FSDPE_INVALID_REPEAT; } } } if (result != FSDPE_OK) { /* not all repeats have been succesfully parsed */ dsc->time_periods[j]->repeats_count = h; return FSDPE_INVALID_REPEAT; } NEXT_LINE (p); } else { /* not all repeats have been succesfully parsed */ dsc->time_periods[j]->repeats_count = h; return FSDPE_INVALID_REPEAT; } index2++; } } } /* `z=' line (time zone adjustments) [zero or more] */ /* z=<adjustment time> <offset> <adjustment time> <offset> .... */ if (!strncmp (p, "z=", 2)) { if (sscanf (p, "z=%" MLFLENS "[^\r\n]", longfsdp_buf)) { /* TODO: guess how many pairs are there and process them */ dsc->timezone_adj = strdup (longfsdp_buf); NEXT_LINE (p); } else { return FSDPE_INVALID_TIMEZONE; } } /* `k=' line (encryption key) [optional] */ /* k=<method> k=<method>:<encryption key> */ result = fsdp_parse_k (&p, &(dsc->k_encryption_method), &(dsc->k_encryption_content)); if (result != FSDPE_OK) return result; /* A.2) Attributes */ /* `a=' lines (session attribute) [0 or more] */ /* a=<attribute> a=<attribute>:<value> */ while (!strncmp (p, "a=", 2)) { /* The "9" length specifier of the first string is subject to changes */ if (sscanf (p, "a=%9[^:\r\n]:%" MSFLENS "[^\r\n]", fsdp_buf[0], fsdp_buf[1]) == 2) { /* session-level value attributes */ if (!strncmp (fsdp_buf[0], "cat", 3)) dsc->a_category = strdup (fsdp_buf[1]); else if (!strncmp (fsdp_buf[0], "keywds", 6)) dsc->a_keywords = strdup (fsdp_buf[1]); else if (!strncmp (fsdp_buf[0], "tool", 4)) dsc->a_keywords = strdup (fsdp_buf[1]); else if (!strncmp (fsdp_buf[0], "rtpmap", 6)) fsdp_parse_rtpmap (&(dsc->a_rtpmaps), &(dsc->a_rtpmaps_count), fsdp_buf[1]); else if (!strncmp (fsdp_buf[0], "type", 4)) { if (!strncmp (fsdp_buf[1], "broadcast", 9)) dsc->a_type = FSDP_SESSION_TYPE_BROADCAST; else if (!strncmp (fsdp_buf[1], "meeting", 7)) dsc->a_type = FSDP_SESSION_TYPE_MEETING; else if (!strncmp (fsdp_buf[1], "moderated", 9)) dsc->a_type = FSDP_SESSION_TYPE_MODERATED; else if (!strncmp (fsdp_buf[1], "test", 4)) dsc->a_type = FSDP_SESSION_TYPE_TEST; else if (!strncmp (fsdp_buf[1], "H332", 4)) dsc->a_type = FSDP_SESSION_TYPE_H332; else return FSDPE_INVALID_SESSION_TYPE; } else if (!strncmp (fsdp_buf[0], "charset", 7)) dsc->a_charset = strdup (fsdp_buf[1]); else if (!strncmp (fsdp_buf[0], "sdplang", 7)) { if (NULL == dsc->a_sdplangs) { dsc->a_sdplangs_count = 0; dsc->a_sdplangs = calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); } if (dsc->a_sdplangs_count < SDPLANGS_MAX_COUNT) { dsc->a_sdplangs[dsc->a_sdplangs_count] = strdup (fsdp_buf[1]); dsc->a_sdplangs_count++; } } else if (!strncmp (fsdp_buf[0], "lang", 4)) { if (NULL == dsc->a_langs) { dsc->a_langs_count = 0; dsc->a_langs = calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); } if (dsc->a_langs_count < SDPLANGS_MAX_COUNT) { dsc->a_langs[dsc->a_langs_count] = strdup (fsdp_buf[1]); dsc->a_langs_count++; } } else if (!strncmp (fsdp_buf[0], "control", 7)) { if (NULL == dsc->a_controls) { dsc->a_controls_count = 0; dsc->a_controls = calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *)); } if (dsc->a_controls_count < SDPCONTROLS_MAX_COUNT) { dsc->a_controls[dsc->a_controls_count] = strdup (fsdp_buf[1]); dsc->a_controls_count++; } } else if (!strncmp (fsdp_buf[0], "range", 5)) { if (dsc->a_range) free (dsc->a_range); dsc->a_range = strdup (fsdp_buf[1]); } else { /* ignore unknown attributes, but provide access to them */ *longfsdp_buf = '\0'; strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN-1); strncat (longfsdp_buf, ":", MAXLONGFIELDLEN-strlen(longfsdp_buf)-1); strncat (longfsdp_buf, fsdp_buf[1], MAXLONGFIELDLEN-strlen(longfsdp_buf)-1); if (NULL == dsc->unidentified_attributes) { dsc->unidentified_attributes_count = 0; dsc->unidentified_attributes = calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, sizeof (char *));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -