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

📄 parser.c

📁 SDP文件解析代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  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 + -