Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Examples

parser.c

Go to the documentation of this file.
00001 /*
00002   This file is part of FreeSDP
00003   Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
00004   
00005   FreeSDP is free software; you can redistribute it and/or modify it
00006   under the terms of the GNU General Public License as published by
00007   the Free Software Foundation; either version 2 of the License, or
00008   (at your option) any later version.
00009 
00010   This program is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013   GNU General Public License for more details.
00014 
00015   You should have received a copy of the GNU General Public License
00016   along with this program; if not, write to the Free Software
00017   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 */
00019 
00032 #include "parserpriv.h"
00033 
00042 #define NEXT_LINE(c)                                                \
00043 ({                                                                  \
00044  while ((*(c) != '\0') && (*(c) != '\r') && (*(c) != '\n')) {       \
00045     (c)++;                                                          \
00046  }                                                                  \
00047  if (*(c) == '\n') {                                                \
00048     (c)++;                                                          \
00049  } else if (*(c) == '\r') {                                         \
00050     (c)++;                                                          \
00051     if (*(c) == '\n') {                                             \
00052        (c)++;                                                       \
00053     } else {                                                        \
00054        return FSDPE_ILLEGAL_CHARACTER;                              \
00055    }                                                                \
00056  }                                                                  \
00057 })
00058 
00059 fsdp_error_t
00060 fsdp_parse(const char *text_description, fsdp_description_t *dsc)
00061 {
00062   fsdp_error_t result;
00063   const char *p = text_description, *p2;
00064   unsigned int index, j;
00065   /* temps for sscanf */
00066   const unsigned int TEMPCHARS = 6;
00067   char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
00068   char longfsdp_buf[MAXLONGFIELDLEN];
00069   const unsigned int TEMPINTS = 2;
00070   unsigned long int wuint[TEMPINTS];
00071 
00072   if ( (NULL == text_description) || (NULL == dsc) )
00073     return FSDPE_INVALID_PARAMETER;
00074 
00075   /***************************************************************************/
00076   /* A) parse session-level description                                      */
00077   /***************************************************************************/
00078   
00079   /* `v=' line (protocol version) */
00080   /* according to the RFC, only `v=0' is valid */
00081   if ( sscanf(p,"v=%1lu",&wuint[0]) ){
00082     if ( wuint[0] != 0 )
00083       return FSDPE_INVALID_VERSION;
00084   } else {
00085     return FSDPE_MISSING_VERSION;
00086   }
00087   NEXT_LINE(p);
00088 
00089   /* `o=' line (owner/creator and session identifier) */
00090   /* o=<username> <session id> <version> <network type> <address type>
00091      <address> */
00092   if ( !strncmp(p,"o=",2) ) {
00093     p += 2;
00094     /* note that the following max lengths may vary in the future and
00095        are quite arbitary */
00096     if ( sscanf(p,"%"MSFLENS"[\x21-\xFF] %"MSFLENS"[0-9] %"MSFLENS"[0-9] %2s %3s %"MSFLENS"s",
00097           fsdp_buf[0],fsdp_buf[1],fsdp_buf[2],fsdp_buf[3],fsdp_buf[4],fsdp_buf[5]) != 6)
00098       return FSDPE_INVALID_OWNER;
00099     dsc->o_username = strdup(fsdp_buf[0]);
00100     dsc->o_session_id = strdup(fsdp_buf[1]);
00101     dsc->o_announcement_version = strdup(fsdp_buf[2]);
00102     if ( !strncmp(fsdp_buf[3],"IN",2) ) {
00103       dsc->o_network_type = FSDP_NETWORK_TYPE_INET;
00104       if ( !strncmp(fsdp_buf[4],"IP4",3) )
00105      dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV4;
00106       else if ( !strncmp(fsdp_buf[4],"IP6",3) )
00107      dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV6;
00108       else
00109      return FSDPE_INVALID_OWNER;  
00110     } else {
00111       return FSDPE_INVALID_OWNER;
00112     }
00113     /* TODO? check valid unicast address/FQDN */
00114     dsc->o_address = strdup(fsdp_buf[5]);
00115   } else {
00116     return FSDPE_MISSING_OWNER;
00117   }
00118   NEXT_LINE(p);
00119   
00120   /* `s=' line (session name) -note that the name string cannot be empty */
00121   /* s=<session name> */
00122   if ( !strncmp(p,"s=",2) ) {
00123     if ( sscanf(p,"s=%"MLFLENS"[^\r\n]",longfsdp_buf) < 1 )
00124       return FSDPE_EMPTY_NAME;
00125     dsc->s_name = strdup(longfsdp_buf);
00126   } else {
00127     return FSDPE_MISSING_NAME;
00128   }
00129   NEXT_LINE(p);
00130   
00131   /* `i=' line (session information) [optional] */
00132   /* i=<session description> */
00133   if ( !strncmp(p,"i=",2) && sscanf(p,"i=%"MLFLENS"[^\r\n]",longfsdp_buf) ) {
00134     dsc->i_information = strdup(longfsdp_buf);
00135     NEXT_LINE(p);
00136   } else {
00137     /* (optional) information absent */
00138   }
00139   
00140   /* `u=' line (URI of description)  [optional] */
00141   /* u=<URI> */
00142   if ( !strncmp(p,"u=",2) && sscanf(p,"u=%"MLFLENS"[^\r\n]",longfsdp_buf) ) {
00143     /* TODO? check valid uri */
00144     dsc->u_uri = strdup(longfsdp_buf);
00145     NEXT_LINE(p);
00146   } else {
00147     /* (optional) uri absent */
00148   }
00149        
00150   /* `e=' lines (email address) [zero or more] */
00151   /* e=<email address> */
00152   p2 = p;
00153   j = 0;
00154   while ( !strncmp(p2,"e=",2) ) {
00155     /* First, count how many emails are there */
00156     j++;
00157     NEXT_LINE(p2);
00158   }
00159   dsc->emails_count = j;
00160   if ( dsc->emails_count > 0 ) {
00161     /* Then, build the array of emails */
00162     dsc->emails = calloc(j,sizeof(const char *));
00163     for ( j = 0; j < dsc->emails_count; j++) {
00164       sscanf(p,"e=%"MLFLENS"[^\r\n]",longfsdp_buf);
00165       /* TODO? check valid email-address. */
00166       dsc->emails[j] = strdup(longfsdp_buf);
00167       NEXT_LINE(p);
00168     }
00169   }
00170 
00171   /* `p=' lines (phone number) [zero or more] */
00172   /*  p=<phone number> */
00173   j = 0;
00174   /* assert ( p2 == p ); */
00175   while ( !strncmp(p2,"p=",2) ) {
00176     j++;
00177     NEXT_LINE(p2);
00178   }
00179   dsc->phones_count = j;
00180   if ( dsc->phones_count > 0 ) {
00181     dsc->phones = calloc(j,sizeof(const char *));
00182     for ( j = 0; j < dsc->phones_count; j++ ) {
00183       sscanf(p,"p=%"MLFLENS"[^\r\n]",longfsdp_buf);
00184       /* TODO? check valid phone-number. */
00185       dsc->phones[j] = strdup(longfsdp_buf);
00186       NEXT_LINE(p);
00187     }
00188   }
00189   
00190   /* `c=' line (connection information - not required if included in all media) [optional] */
00191   /* c=<network type> <address type> <connection address> */
00192   result = fsdp_parse_c(&p,&(dsc->c_network_type),&(dsc->c_address_type),
00193                &(dsc->c_address));
00194   if ( FSDPE_OK != result )
00195     return result;
00196   
00197   /* `b=' lines (bandwidth information) [optional] */
00198   /* b=<modifier>:<bandwidth-value> */
00199   result = fsdp_parse_b(&p,&(dsc->bw_modifiers),&(dsc->bw_modifiers_count));
00200   if ( FSDPE_OK != result ) 
00201     return result;
00202     
00203   /* A.1) Time descriptions: */
00204   
00205   /* `t=' lines (time the session is active) [1 or more] */
00206   /* t=<start time>  <stop time> */
00207   j = 0;
00208   p2 = p;
00209   while ( !strncmp(p2,"t=",2) ) {
00210     j++;
00211     NEXT_LINE(p2);
00212     while ( !strncmp(p2,"r=",2) )
00213       NEXT_LINE(p2);
00214   }
00215   dsc->time_periods_count = j;
00216   if ( dsc->time_periods_count == 0 )
00217     return FSDPE_MISSING_TIME;
00218   dsc->time_periods = calloc(dsc->time_periods_count,
00219                     sizeof(fsdp_time_period_t*));
00220   index = 0;
00221   for ( j = 0; j < dsc->time_periods_count; j++ ) { 
00222     unsigned int h = 0;
00223     if ( sscanf(p,"t=%10lu %10lu",&wuint[0],&wuint[1]) != 2 ) {
00224       /* not all periods have been successfully parsed */
00225       dsc->time_periods_count = j;
00226       return FSDPE_INVALID_TIME;
00227     }
00228     dsc->time_periods[j] = calloc(1,sizeof(fsdp_time_period_t));
00229 
00230     /* convert from NTP to time_t time */
00231     if (wuint[0] != 0)
00232       wuint[0] -= NTP_EPOCH_OFFSET;
00233     if (wuint[1] != 0)
00234       wuint[1] -= NTP_EPOCH_OFFSET;
00235     dsc->time_periods[j]->start = wuint[0];
00236     dsc->time_periods[j]->stop = wuint[1];
00237     NEXT_LINE(p);
00238     
00239     /* `r' lines [zero or more repeat times for each t=] */
00240     /*r=<repeat interval> <active duration> <list of offsets from
00241       start-time>*/
00242     p2 = p;
00243     while ( !strncmp(p2,"r=",2) ) {
00244       h++;
00245       NEXT_LINE(p2);
00246     }
00247     dsc->time_periods[j]->repeats_count = h;
00248     if ( h > 0 ) { 
00249       unsigned int index2 = 0;
00250       dsc->time_periods[j]->repeats = calloc(h,sizeof(fsdp_repeat_t*));
00251       for ( h = 0; h < dsc->time_periods[j]->repeats_count; h++ ) {
00252      /*
00253        get_repeat_values(p,&(dsc->time_periods[index].repeats[index2]));
00254        fsdp_error_t get_repeat_values (const char *r, fsdp_repeat_t
00255        *repeat);
00256        */
00257      if ( sscanf(p,"r=%10s %10s %"MLFLENS"[^\r\n]",
00258               fsdp_buf[0],fsdp_buf[1],longfsdp_buf) == 3 ) {
00259        fsdp_repeat_t *repeat;
00260        dsc->time_periods[j]->repeats[h] = calloc(1,sizeof(fsdp_repeat_t));
00261        repeat = dsc->time_periods[j]->repeats[h];
00262        /* get interval, duration and list of offsets */
00263        result = fsdp_repeat_time_to_uint(fsdp_buf[0],&(repeat->interval));
00264        if ( result == FSDPE_OK ) {
00265          result = fsdp_repeat_time_to_uint(fsdp_buf[1],&(repeat->duration));
00266          if ( result == FSDPE_OK ) {
00267            unsigned int k = 1;
00268            const char *i = longfsdp_buf;
00269            while ( NULL != (i = strchr(i,' ')) ) {
00270           k++;
00271           if ( NULL != i )
00272             i++;
00273            }
00274            repeat->offsets_count = k;
00275            repeat->offsets = calloc(k,sizeof(time_t));
00276            i = longfsdp_buf;
00277            for ( k = 0; 
00278               (k < repeat->offsets_count) && (result == FSDPE_OK);
00279               k++ ) {
00280           result = fsdp_repeat_time_to_uint(i,&(repeat->offsets[k])); 
00281           i = strchr(i,' ');
00282           if ( NULL != i)
00283             i++;
00284            }
00285            if ( k < repeat->offsets_count ) {
00286           /* there where invalid repeat offsets */
00287           dsc->time_periods[j]->repeats_count = k;
00288           return FSDPE_INVALID_REPEAT;
00289            }         
00290          }
00291        }
00292        if ( result != FSDPE_OK ) {
00293          /* not all repeats have been succesfully parsed */
00294          dsc->time_periods[j]->repeats_count = h;
00295          return FSDPE_INVALID_REPEAT;
00296        }      
00297        NEXT_LINE(p);
00298      } else {
00299        /* not all repeats have been succesfully parsed */
00300        dsc->time_periods[j]->repeats_count = h;
00301        return FSDPE_INVALID_REPEAT;
00302      }
00303      index2++;
00304       }
00305     }
00306   }
00307   
00308   /* `z=' line (time zone adjustments) [zero or more] */
00309   /* z=<adjustment time> <offset> <adjustment time> <offset> .... */
00310   if ( !strncmp(p,"z=",2) ) {
00311     if ( sscanf(p,"z=%"MLFLENS"[^\r\n]",longfsdp_buf) ) {
00312       /* TODO: guess how many pairs are there and process them */
00313       dsc->timezone_adj = strdup(longfsdp_buf);
00314       NEXT_LINE(p);
00315     } else {
00316       return FSDPE_INVALID_TIMEZONE;
00317     }
00318   }
00319 
00320   /* `k=' line (encryption key) [optional] */
00321   /* k=<method> 
00322      k=<method>:<encryption key> */
00323   result = fsdp_parse_k(&p,&(dsc->k_encryption_method),
00324                &(dsc->k_encryption_content));
00325   if ( result != FSDPE_OK )
00326     return result;
00327   
00328   /* A.2) Attributes */
00329   /* `a=' lines (session attribute) [0 or more] */
00330   /* a=<attribute>
00331      a=<attribute>:<value> */
00332   while ( !strncmp(p,"a=",2) ) {
00333     /* The "9" lenght specifier of the first string is subject to
00334        changes */
00335     if ( sscanf(p,"a=%9[^:\r\n]:%"MSFLENS"[^\r\n]",fsdp_buf[0],fsdp_buf[1]) == 2 ) {  
00336       /* session-level value attributes */
00337       if ( !strncmp(fsdp_buf[0],"cat",3) )
00338      dsc->a_str_attributes[FSDP_SESSION_STR_ATT_CATEGORY] = 
00339        strdup(fsdp_buf[1]);
00340       else if ( !strncmp(fsdp_buf[0],"keywds",6) )
00341      dsc->a_str_attributes[FSDP_SESSION_STR_ATT_KEYWORDS] =
00342        strdup(fsdp_buf[1]);
00343       else if ( !strncmp(fsdp_buf[0],"tool",4) )
00344      dsc->a_str_attributes[FSDP_SESSION_STR_ATT_TOOL] =
00345        strdup(fsdp_buf[1]);
00346       else if ( !strncmp(fsdp_buf[0],"rtpmap",6) )
00347      fsdp_parse_rtpmap(&(dsc->a_rtpmaps),
00348                 &(dsc->a_rtpmaps_count),fsdp_buf[1]);
00349       else if ( !strncmp(fsdp_buf[0],"type",4) ) {
00350      if ( !strncmp(fsdp_buf[1],"broadcast",9) )
00351        dsc->a_type = FSDP_SESSION_TYPE_BROADCAST;
00352      else if ( !strncmp(fsdp_buf[1],"meeting",7) )
00353        dsc->a_type = FSDP_SESSION_TYPE_MEETING;
00354      else if ( !strncmp(fsdp_buf[1],"moderated",9) )
00355        dsc->a_type = FSDP_SESSION_TYPE_MODERATED;
00356      else if ( !strncmp(fsdp_buf[1],"test",4) )
00357        dsc->a_type = FSDP_SESSION_TYPE_TEST;
00358      else if ( !strncmp(fsdp_buf[1],"H332",4) )
00359        dsc->a_type = FSDP_SESSION_TYPE_H332;
00360      else
00361        return FSDPE_INVALID_SESSION_TYPE;
00362       } else if ( !strncmp(fsdp_buf[0],"charset",7) )
00363      dsc->a_str_attributes[FSDP_SESSION_STR_ATT_CHARSET] =
00364        strdup(fsdp_buf[1]);
00365       else if ( !strncmp(fsdp_buf[0],"sdplang",7) ) {
00366      if ( NULL == dsc->a_sdplangs ) {
00367        dsc->a_sdplangs_count = 0;
00368        dsc->a_sdplangs = calloc(SDPLANGS_MAX_COUNT,sizeof(char*));
00369      }
00370      if ( dsc->a_sdplangs_count < SDPLANGS_MAX_COUNT ) {
00371        dsc->a_sdplangs[dsc->a_sdplangs_count] = strdup(fsdp_buf[1]);
00372        dsc->a_sdplangs_count++;
00373      }
00374       } else if ( !strncmp(fsdp_buf[0],"lang",4) ) {
00375      if ( NULL == dsc->a_langs ) {
00376        dsc->a_langs_count = 0;
00377        dsc->a_langs = calloc(SDPLANGS_MAX_COUNT,sizeof(char*));
00378      }
00379      if ( dsc->a_langs_count < SDPLANGS_MAX_COUNT ) {
00380        dsc->a_langs[dsc->a_langs_count] = strdup(fsdp_buf[1]);
00381        dsc->a_langs_count++;
00382      }
00383       }  else {
00384      /* ignore unknown attributes, but provide access to them */     
00385      *longfsdp_buf = '\0';
00386      strncat(longfsdp_buf,fsdp_buf[0],MAXLONGFIELDLEN);
00387      strncat(longfsdp_buf,":",MAXLONGFIELDLEN);
00388      strncat(longfsdp_buf,fsdp_buf[1],MAXLONGFIELDLEN);
00389      if ( NULL == dsc->unidentified_attributes ) {
00390        dsc->unidentified_attributes_count = 0;
00391        dsc->unidentified_attributes = 
00392          calloc(UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,sizeof(char*));
00393      }
00394      if ( dsc->unidentified_attributes_count < 
00395           UNIDENTIFIED_ATTRIBUTES_MAX_COUNT ) {
00396        dsc->unidentified_attributes
00397          [dsc->unidentified_attributes_count] = strdup(longfsdp_buf);
00398        dsc->unidentified_attributes_count++;
00399      }
00400       }
00401       NEXT_LINE(p);  
00402     } else if ( sscanf(p,"a=%20s",fsdp_buf[0]) == 1 ) {  
00403       /* session-level property attributes */
00404       if ( !strncmp(fsdp_buf[0],"recvonly",8) )
00405      dsc->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
00406       else if ( !strncmp(fsdp_buf[0],"sendonly",8) )
00407      dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
00408       else if ( !strncmp(fsdp_buf[0],"inactive",8) )
00409      dsc->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
00410       else if ( !strncmp(fsdp_buf[0],"sendrecv",8) )
00411      dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
00412       else {
00413      /* ignore unknown attributes, but provide access to them */     
00414      *longfsdp_buf = '\0';
00415      strncat(longfsdp_buf,fsdp_buf[0],MAXLONGFIELDLEN);
00416      if ( NULL == dsc->unidentified_attributes ) {
00417        dsc->unidentified_attributes_count = 0;
00418        dsc->unidentified_attributes = 
00419          calloc(UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,sizeof(char*));
00420      }
00421      if ( dsc->unidentified_attributes_count < 
00422           UNIDENTIFIED_ATTRIBUTES_MAX_COUNT ) {
00423        dsc->unidentified_attributes
00424          [dsc->unidentified_attributes_count] = strdup(longfsdp_buf);
00425        dsc->unidentified_attributes_count++;
00426      }
00427       }
00428       NEXT_LINE(p);
00429     } else
00430       return FSDPE_INVALID_ATTRIBUTE;
00431   }
00432   
00433   /***************************************************************************/
00434   /* B) parse media-level descriptions                                       */
00435   /***************************************************************************/
00436   p2 = p;
00437   j = 0;
00438   while ( (*p2 != '\0') && !strncmp(p2,"m=",2) ) {
00439     char c;
00440     j++;
00441     NEXT_LINE(p2);
00442     while ( sscanf(p2,"%c=",&c) == 1 ) {
00443       if ( c == 'i' || c == 'c' || c == 'b' || c == 'k' || c == 'a' ) {
00444      NEXT_LINE(p2);
00445       } else if ( c == 'm' ) {
00446      break;
00447       } else {
00448      return FSDPE_INVALID_LINE;
00449       }
00450     }
00451   }
00452   dsc->media_announcements_count = j;
00453   if ( dsc->media_announcements_count == 0 ) {
00454     ;
00455     /*return FSDPE_MISSING_MEDIA;*/
00456   } else {  /* dsc->media_announcements_count > 0 */
00457     dsc->media_announcements = calloc(j,sizeof(fsdp_media_announcement_t*));
00458     for ( j = 0; j < dsc->media_announcements_count; j++ ) {
00459       fsdp_media_announcement_t *media = NULL;
00460       /* `m=' line (media name, transport address and format list) */
00461       /* m=<media>  <port>  <transport> <fmt list> */
00462       /* The max. string lengths are subject to change */
00463       if ( sscanf(p,"m=%11s %8s %7s %"MLFLENS"[^\r\n]",
00464             fsdp_buf[0],fsdp_buf[1],fsdp_buf[2],longfsdp_buf) != 4 ) {
00465      return FSDPE_INVALID_MEDIA;
00466       } else {
00467      dsc->media_announcements[j] = 
00468        calloc(1,sizeof(fsdp_media_announcement_t));
00469      media = dsc->media_announcements[j];
00470      if ( !strncmp(fsdp_buf[0],"audio",5) )
00471        media->media_type = FSDP_MEDIA_AUDIO;
00472      else if ( !strncmp(fsdp_buf[0],"video",5) )
00473        media->media_type = FSDP_MEDIA_VIDEO;
00474      else if ( !strncmp(fsdp_buf[0],"text",4) )
00475        media->media_type = FSDP_MEDIA_TEXT;
00476      else if ( !strncmp(fsdp_buf[0],"application",11) )
00477        media->media_type = FSDP_MEDIA_APPLICATION;
00478      else if ( !strncmp(fsdp_buf[0],"data",4) )
00479        media->media_type = FSDP_MEDIA_DATA;
00480      else if ( !strncmp(fsdp_buf[0],"control",7) )
00481        media->media_type = FSDP_MEDIA_CONTROL;
00482      else
00483        return FSDPE_UNKNOWN_MEDIA_TYPE;
00484      { /* try to get port specification as port/number */
00485        char *slash;
00486        if ( (slash = strchr(fsdp_buf[1],'/')) ) {
00487          *slash = '\0';
00488          slash++;
00489          media->port = strtol(fsdp_buf[1],NULL,10);
00490          media->port_count = strtol(slash,NULL,10);
00491        } else {
00492          media->port = strtol(fsdp_buf[1],NULL,10);
00493          media->port_count = 0;
00494        }
00495      }
00496      if ( !strncmp(fsdp_buf[2],"RTP/AVP",7) )
00497        media->transport = FSDP_TP_RTP_AVP;
00498      else if ( !strncmp(fsdp_buf[2],"udp",3) )
00499        media->transport = FSDP_TP_UDP;
00500      else if ( !strncmp(fsdp_buf[2],"TCP",3) )
00501        media->transport = FSDP_TP_TCP;
00502      else if ( !strncmp(fsdp_buf[2],"UDPTL",5) )
00503        media->transport = FSDP_TP_UDPTL;
00504      else if ( !strncmp(fsdp_buf[2],"vat",3) )
00505        media->transport = FSDP_TP_VAT;
00506      else if ( !strncmp(fsdp_buf[2],"rtp",3) )
00507        media->transport = FSDP_TP_OLD_RTP;
00508      else
00509        return FSDPE_UNKNOWN_MEDIA_TRANSPORT;
00510      {
00511        unsigned int k = 0;
00512        char *s = longfsdp_buf;
00513        while ( NULL != ( s = strchr(s,' ')) ) {
00514          k++;
00515          if ( NULL != s )
00516            s++;
00517        }
00518        k++; /* when there is no space left, count the last format */
00519        media->formats_count = k;
00520        media->formats = calloc(k,sizeof(char*));
00521        s = longfsdp_buf;
00522        for ( k = 0; k < media->formats_count; k++ ) {
00523          char *space = strchr(s,' ');
00524          if ( NULL != space )
00525            *space = '\0';
00526          media->formats[k] = strdup(s);
00527          s = space + 1;
00528        }
00529      }
00530      NEXT_LINE(p);
00531       }
00532       
00533       /* `i=' line (media title) [optional] */
00534       /* i=<media title> */
00535       if ( !strncmp(p,"i=",2)  && sscanf(p,"i=%"MLFLENS"[^\r\n]",longfsdp_buf) ) {
00536      media->i_title = strdup(longfsdp_buf);
00537      NEXT_LINE(p);
00538       } else {
00539      /* (optional) information absent */
00540       }
00541       
00542       /* `c=' line (connection information - overrides session-level
00543       line) [optional if provided at session-level] */
00544       /* c=<network type> <address type> <connection address> */    
00545       result = fsdp_parse_c(&p,&(media->c_network_type),
00546                    &(media->c_address_type),&(media->c_address));
00547       if ( result != FSDPE_OK )
00548      return result;
00549       
00550       /* `b=' lines (bandwidth information) [optional] */
00551       /* b=<modifier>:<bandwidth-value> */
00552       result = fsdp_parse_b(&p,&(media->bw_modifiers),
00553                    &(media->bw_modifiers_count));
00554       if ( FSDPE_OK != result )
00555      return result;
00556 
00557       /* `k=' line (encryption key) [optional] */
00558       /* k=<method> 
00559       k=<method>:<encryption key> */
00560       result = fsdp_parse_k(&p,&(media->k_encryption_method),
00561                    &(media->k_encryption_content)); 
00562       if ( result != FSDPE_OK )
00563      return result;
00564       
00565       /* B.1) Attributes */
00566       
00567       /* `a=' lines (zero or more media attribute lines) [optional] */
00568       /* a=<attribute>
00569       a=<attribute>:<value> */
00570       while ( !strncmp(p,"a=",2) ) {
00571      if ( sscanf(p,"a=%9[^:\r\n]:%"MLFLENS"[^\r\n]",fsdp_buf[0],longfsdp_buf) 
00572           == 2 ) {  
00573        /* media-level value attributes */
00574        if ( !strncmp(fsdp_buf[0],"ptime",5) )
00575          media->a_ptime = strtoul(longfsdp_buf,NULL,10);
00576        else if ( !strncmp(fsdp_buf[0],"maxptime",8) )
00577          media->a_maxptime = strtoul(longfsdp_buf,NULL,10);
00578        else if ( !strncmp(fsdp_buf[0],"rtpmap",6) )
00579          fsdp_parse_rtpmap(&(media->a_rtpmaps),
00580                      &(media->a_rtpmaps_count),longfsdp_buf);
00581        else if ( !strncmp(fsdp_buf[0],"orient",6) ) {
00582          if ( !strncmp(longfsdp_buf,"portrait",8) ) 
00583            media->a_orient = FSDP_ORIENT_PORTRAIT;
00584          else if ( !strncmp(longfsdp_buf,"landscape",9) ) 
00585            media->a_orient = FSDP_ORIENT_LANDSCAPE;
00586          else if ( !strncmp(longfsdp_buf,"seascape",9) ) 
00587            media->a_orient = FSDP_ORIENT_SEASCAPE; 
00588        } else if ( !strncmp(fsdp_buf[0],"sdplang",7) ) {
00589          if ( NULL == dsc->a_sdplangs ) {
00590            media->a_sdplangs_count = 0;
00591            media->a_sdplangs = 
00592           calloc(SDPLANGS_MAX_COUNT,sizeof(char*));
00593          }
00594          if ( media->a_sdplangs_count < SDPLANGS_MAX_COUNT ) {
00595            media->a_sdplangs[dsc->a_sdplangs_count] = strdup(longfsdp_buf);
00596            media->a_sdplangs_count++;
00597          }
00598        } else if ( !strncmp(fsdp_buf[0],"lang",4) ) {
00599          if ( NULL == dsc->a_langs ) {
00600            media->a_langs_count = 0;
00601            media->a_langs = calloc(SDPLANGS_MAX_COUNT,sizeof(char*));
00602          }
00603          if ( media->a_langs_count < SDPLANGS_MAX_COUNT ) {
00604            media->a_langs[dsc->a_langs_count] = strdup(longfsdp_buf);
00605            media->a_langs_count++;
00606          }
00607        } else if ( !strncmp(fsdp_buf[0],"framerate",9) ) 
00608          media->a_framerate = strtof(longfsdp_buf,NULL);
00609        else if ( !strncmp(fsdp_buf[0],"fmtp",4) ) {
00610          if ( NULL == media->a_fmtps ) {
00611            media->a_fmtps_count = 0;
00612            media->a_fmtps = calloc(SDPLANGS_MAX_COUNT,sizeof(char*));
00613          }
00614          if ( media->a_fmtps_count < SDPLANGS_MAX_COUNT ) {
00615            media->a_fmtps[media->a_fmtps_count] = strdup(longfsdp_buf);
00616            media->a_fmtps_count++;
00617          }
00618        } else if ( !strncmp(fsdp_buf[0],"rtcp",4) ) {
00619          int opts = 0;
00620          /* rtcp attribute: a=rtcp:<port> <nettype> <addrtype> <address> */
00621          opts = sscanf(longfsdp_buf,"%lu %2s %3s %"MSFLENS"s",
00622                  &wuint[0],fsdp_buf[0],fsdp_buf[1],fsdp_buf[2]);
00623          if ( opts >= 1 ) {
00624            media->a_rtcp_port = wuint[0];
00625            if ( opts >= 2 ) {
00626           if ( !strncmp(fsdp_buf[0],"IN",2) ) {
00627             media->a_rtcp_network_type = FSDP_NETWORK_TYPE_INET;
00628           } /* else
00629             ; TODO: define error code? */
00630           if ( opts >= 3 ) {
00631             if ( !strncmp(fsdp_buf[1],"IP4",3) )
00632               media->a_rtcp_address_type = FSDP_ADDRESS_TYPE_IPV4;
00633             else if ( !strncmp(fsdp_buf[1],"IP6",3) )
00634               media->a_rtcp_address_type = FSDP_ADDRESS_TYPE_IPV6;
00635             else
00636               return FSDPE_INVALID_CONNECTION_NETTYPE; 
00637             /*add specific code?*/
00638             if ( opts >= 4)
00639               media->a_rtcp_address = strdup(fsdp_buf[2]);
00640           }
00641            }
00642          }
00643        } else {
00644          /* ignore unknown attributes, but provide access to them */     
00645          *fsdp_buf[1] = '\0';
00646          strncat(fsdp_buf[1],fsdp_buf[0],MAXLONGFIELDLEN);
00647          strncat(fsdp_buf[1],":",MAXLONGFIELDLEN);
00648          strncat(fsdp_buf[1],longfsdp_buf,MAXLONGFIELDLEN);
00649          if ( NULL == media->unidentified_attributes ) {
00650            media->unidentified_attributes_count = 0;
00651            media->unidentified_attributes = 
00652           calloc(UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,sizeof(char*));
00653          }
00654          if ( media->unidentified_attributes_count < 
00655            UNIDENTIFIED_ATTRIBUTES_MAX_COUNT ) {
00656            media->unidentified_attributes
00657           [media->unidentified_attributes_count] = strdup(fsdp_buf[1]);
00658            media->unidentified_attributes_count++;
00659          }
00660        }
00661        NEXT_LINE(p);
00662      } else if ( sscanf(p,"a=%8s",fsdp_buf[0]) == 1 ) {  
00663        /* media-level property attributes */
00664        if ( !strncmp(fsdp_buf[0],"recvonly",8) )
00665          media->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
00666        else if ( !strncmp(fsdp_buf[0],"sendonly",8) )
00667          media->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
00668        else if ( !strncmp(fsdp_buf[0],"inactive",8) )
00669          media->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
00670        else if ( !strncmp(fsdp_buf[0],"sendrecv",8) )
00671          media->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
00672        else {
00673          /* ignore unknown attributes, but provide access to them */     
00674          *longfsdp_buf = '\0';
00675          strncat(longfsdp_buf,fsdp_buf[0],MAXLONGFIELDLEN);
00676          if ( NULL == media->unidentified_attributes ) {
00677            media->unidentified_attributes_count = 0;
00678            media->unidentified_attributes = 
00679           calloc(UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,sizeof(char*));
00680          }
00681          if ( media->unidentified_attributes_count < 
00682            UNIDENTIFIED_ATTRIBUTES_MAX_COUNT ) {
00683            media->unidentified_attributes
00684           [media->unidentified_attributes_count] = strdup(longfsdp_buf);
00685            media->unidentified_attributes_count++;
00686          }
00687        }
00688        NEXT_LINE(p);
00689      } else
00690        return FSDPE_INVALID_ATTRIBUTE;
00691       }
00692     } /* end of for */
00693   }
00694 
00695   /* Check c= has been given at session level or at media level for
00696      all media */
00697   if ( NULL == dsc->c_address.address ) {
00698     unsigned int c;
00699     for ( c = 0; c < dsc->media_announcements_count; c++)
00700       if ( NULL == dsc->media_announcements[c]->c_address.address )
00701      return FSDPE_MISSING_CONNECTION_INFO;
00702   }
00703 
00704   /* finish */
00705   if ( *p == '\0' )
00706     return FSDPE_OK;
00707   else
00708     return FSDPE_OVERFILLED;
00709 }
00710 
00711 static fsdp_error_t
00712 fsdp_parse_c(const char **p, fsdp_network_type_t *ntype, 
00713           fsdp_address_type_t *atype, fsdp_connection_address_t *address)
00714 {
00715   const unsigned int TEMPCHARS = 3;
00716   char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
00717 
00718   if ( !strncmp(*p,"c=",2) ) { 
00719     if ( sscanf(*p,"c=%2s %3s %"MSFLENS"s",fsdp_buf[0],fsdp_buf[1],fsdp_buf[2]) ) {
00720       if ( !strncmp(fsdp_buf[0],"IN",2) ) {
00721      *ntype = FSDP_NETWORK_TYPE_INET;
00722      if ( !strncmp(fsdp_buf[1],"IP4",3) )
00723        *atype = FSDP_ADDRESS_TYPE_IPV4;
00724      else if ( !strncmp(fsdp_buf[1],"IP6",3) )
00725        *atype = FSDP_ADDRESS_TYPE_IPV6;
00726      else
00727        return FSDPE_INVALID_CONNECTION_NETTYPE;
00728       } else {
00729      return FSDPE_INVALID_CONNECTION_ADDRTYPE;
00730       }
00731       {
00732      char *slash = strchr(fsdp_buf[2],'/');
00733      if ( NULL == slash ) {
00734        address->address = strdup(fsdp_buf[2]);
00735        address->address_ttl = 0;
00736        address->address_count = 0;
00737      } else {
00738        /* address is IP4 multicast */
00739        char *slash2;
00740        *slash = '\0';
00741        slash++;
00742        address->address = strdup(fsdp_buf[2]);
00743        slash2 = strchr(slash + 1,'/');
00744        if ( NULL == slash2 ) {
00745          address->address_ttl = strtol(slash,NULL,10);
00746          address->address_count = 0;
00747        } else {
00748          *slash2 = '\0';
00749          slash2++;
00750          address->address_ttl = strtol(slash,NULL,10);
00751          address->address_count = strtol(slash2,NULL,10);
00752        }
00753      }
00754       }
00755       NEXT_LINE(*p);
00756     } else {
00757       return FSDPE_INVALID_CONNECTION;
00758     }
00759   }
00760   return FSDPE_OK;
00761 }
00762     
00763 static fsdp_error_t
00764 fsdp_parse_b(const char **p, fsdp_bw_modifier_t **bw_modifiers, 
00765           unsigned int *bw_modifiers_count)
00766 {
00767   char fsdp_buf[MAXSHORTFIELDLEN];
00768   unsigned long int wuint;
00769   unsigned int i = 0;
00770   char *lp = (char*)*p;
00771 
00772   /* count b= lines */
00773   while ( !strncmp(lp,"b=",2) ) {
00774     NEXT_LINE(lp);
00775     i++;
00776   }
00777   *bw_modifiers = calloc(i,sizeof(fsdp_bw_modifier_t));
00778   *bw_modifiers_count = i;
00779 
00780   while ( i > 0 ) {
00781     unsigned int index = *bw_modifiers_count - i;
00782     if ( 2 == sscanf(*p,"b=%20[^:\r\n]:%lu",fsdp_buf,&wuint) ) {
00783       if ( !strncmp(fsdp_buf,"CT",2) )
00784      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL;
00785       else if ( !strncmp(fsdp_buf,"AS",2) )
00786      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC;
00787       else if ( !strncmp(fsdp_buf,"RS",2) )
00788      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_SENDERS;
00789       else if ( !strncmp(fsdp_buf,"RR",2) )
00790      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_RECEIVERS;
00791       else {
00792      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_UNKNOWN;
00793      (*bw_modifiers)[index].b_unknown_bw_modt = (char *)strdup(fsdp_buf);
00794       }
00795       (*bw_modifiers)[index].b_value = wuint;
00796       NEXT_LINE(*p);
00797     } else {
00798       *bw_modifiers_count -= i;
00799       return FSDPE_INVALID_BANDWIDTH;
00800     } 
00801     i--;
00802   }
00803   return FSDPE_OK;
00804 }
00805 
00806 static fsdp_error_t
00807 fsdp_parse_k(const char **p, fsdp_encryption_method_t *method, char **content)
00808 {
00809   char fsdp_buf[MAXSHORTFIELDLEN];
00810   char longfsdp_buf[MAXLONGFIELDLEN];
00811 
00812   if ( !strncmp(*p,"k=",2) ) {
00813     if ( sscanf(*p,"k=prompt") ) {
00814       *method = FSDP_ENCRYPTION_METHOD_PROMPT;
00815       *content = NULL;
00816       NEXT_LINE(*p);
00817     } else {
00818       if ( sscanf(*p,"k=%6[^:\r\n]:%"MLFLENS"s",fsdp_buf,longfsdp_buf) ) {
00819      if ( !strncmp(fsdp_buf,"clear",5) )
00820        *method = FSDP_ENCRYPTION_METHOD_CLEAR;
00821      else if ( !strncmp(fsdp_buf,"base64",6) )
00822        *method = FSDP_ENCRYPTION_METHOD_BASE64;   
00823      else if ( !strncmp(fsdp_buf,"uri",3) )
00824        *method = FSDP_ENCRYPTION_METHOD_URI; 
00825      else
00826        return FSDPE_INVALID_ENCRYPTION_METHOD;
00827      *content = strdup(longfsdp_buf);
00828      NEXT_LINE(*p);
00829       }
00830     }
00831   }
00832   return FSDPE_OK;
00833 }
00834 
00835 static fsdp_error_t
00836 fsdp_parse_rtpmap(fsdp_rtpmap_t ***rtpmap, unsigned int *counter, 
00837             const char *value)
00838 {
00839   fsdp_error_t result = FSDPE_OK;
00840   
00841   if ( 0 == *counter ) {
00842     *counter = 0;
00843     *rtpmap = calloc(MEDIA_RTPMAPS_MAX_COUNT,sizeof(fsdp_rtpmap_t*));
00844   }
00845   if ( *counter < MEDIA_RTPMAPS_MAX_COUNT ) {
00846     unsigned int c = *counter;
00847     fsdp_rtpmap_t **map = *rtpmap;
00848     char fsdp_buf[MAXSHORTFIELDLEN];
00849     char longfsdp_buf[MAXLONGFIELDLEN];
00850     map[c] = calloc(1,sizeof(fsdp_rtpmap_t));
00851 
00852     /* a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding
00853        parameters]> */
00854     if ( 2 == sscanf(value,"%s %s",fsdp_buf,longfsdp_buf) ) {
00855       char *slash1;
00856       map[c]->pt = strdup(fsdp_buf);
00857       /* parse <encoding name>/<clock rate>[/<encoding parameters>]*/
00858       slash1 = strchr(longfsdp_buf,'/');
00859       if ( NULL == slash1 ) {
00860      result = FSDPE_INVALID_ATTRIBUTE_RTPMAP;
00861       } else {
00862      char *slash2;
00863      *slash1 = '\0';
00864      slash1++;
00865      map[c]->encoding_name = strdup(longfsdp_buf);
00866      slash2 = strchr(slash1,'/');
00867      if ( NULL != slash2 ) {
00868        *slash2 = '\0';
00869        slash2++;
00870        map[c]->parameters = strdup(slash2);
00871      }    
00872      map[c]->clock_rate = strtol(slash1,NULL,10);
00873       }
00874       (*counter)++;
00875     }
00876   }
00877   return result;
00878 }
00879 
00880 static fsdp_error_t
00881 fsdp_repeat_time_to_uint(const char *time, unsigned long int *seconds)
00882 {
00883   const unsigned long SECONDS_PER_DAY = 86400;
00884   const unsigned long SECONDS_PER_HOUR = 3600;
00885   const unsigned long SECONDS_PER_MINUTE = 60;
00886   char c;
00887   unsigned long int wuint;
00888   
00889   if ( sscanf(time,"%lu%c",&wuint,&c) == 2 ) {
00890     /* time with unit specification character */
00891     switch(c) {
00892     case 'd':
00893       *seconds = wuint * SECONDS_PER_DAY;
00894       break;
00895     case 'h':
00896       *seconds = wuint * SECONDS_PER_HOUR;
00897       break;
00898     case 'm':
00899       *seconds = wuint * SECONDS_PER_MINUTE;
00900       break;
00901     case 's':
00902       *seconds = wuint;
00903       break;
00904     default:
00905       return FSDPE_INVALID_REPEAT;
00906       break;
00907     }
00908   } else if ( sscanf(time,"%lu",&wuint) == 1 ) {
00909     /* time without unit specification character */
00910     *seconds = wuint;
00911   } else {
00912     return FSDPE_INVALID_REPEAT;
00913   }    
00914   return FSDPE_OK;
00915 }
00916 
00917 unsigned int
00918 fsdp_get_version(const fsdp_description_t *dsc)
00919 {
00920   if ( NULL == dsc)
00921     return 0;
00922   return dsc->version;
00923 }
00924 
00925 const char *
00926 fsdp_get_owner_username(const fsdp_description_t *dsc)
00927 {
00928   if ( NULL == dsc)
00929     return NULL;
00930   return dsc->o_username;
00931 }
00932 
00933 const char *
00934 fsdp_get_session_id(const fsdp_description_t *dsc)
00935 {
00936   if ( NULL == dsc)
00937     return NULL;
00938   return dsc->o_session_id;
00939 }
00940 
00941 const char *
00942 fsdp_get_announcement_version(const fsdp_description_t *dsc)
00943 {
00944   if ( NULL == dsc)
00945     return NULL;
00946   return dsc->o_announcement_version;
00947 }
00948 
00949 fsdp_network_type_t
00950 fsdp_get_owner_network_type(const fsdp_description_t *dsc)
00951 {
00952   if ( NULL == dsc)
00953     return FSDP_NETWORK_TYPE_UNDEFINED;
00954   return dsc->o_network_type;
00955 }
00956 
00957 fsdp_address_type_t
00958 fsdp_get_owner_address_type(const fsdp_description_t *dsc)
00959 {
00960   if ( NULL == dsc)
00961     return FSDP_ADDRESS_TYPE_UNDEFINED;
00962   return dsc->o_address_type;
00963 }
00964 
00965 const char *
00966 fsdp_get_owner_address(const fsdp_description_t *dsc)
00967 {
00968   if ( NULL == dsc)
00969     return NULL;
00970   return dsc->o_address;
00971 }
00972 
00973 const char *
00974 fsdp_get_name(const fsdp_description_t *dsc)
00975 {
00976   if ( NULL == dsc)
00977     return NULL;
00978   return dsc->s_name;
00979 }
00980 
00981 const char *
00982 fsdp_get_information(const fsdp_description_t *dsc)
00983 {
00984   if ( NULL == dsc)
00985     return NULL;
00986   return dsc->i_information;
00987 }
00988 
00989 const char *
00990 fsdp_get_uri(const fsdp_description_t *dsc)
00991 {
00992   if ( NULL == dsc)
00993     return NULL;
00994   return dsc->u_uri;
00995 }
00996 
00997 unsigned int
00998 fsdp_get_emails_count(const fsdp_description_t *dsc)
00999 {
01000   if ( NULL == dsc)
01001     return 0;
01002   return dsc->emails_count;
01003 }
01004 
01005 const char *
01006 fsdp_get_email(const fsdp_description_t *dsc, unsigned int index)
01007 {
01008   if ( (NULL == dsc) || (index >= dsc->emails_count) )
01009     return NULL;
01010   return dsc->emails[index];
01011 }
01012 
01013 unsigned int
01014 fsdp_get_phones_count(const fsdp_description_t *dsc)
01015 {
01016   if ( NULL == dsc)
01017     return 0;
01018   return dsc->phones_count;
01019 }
01020 
01021 const char *
01022 fsdp_get_phone(const fsdp_description_t *dsc, unsigned int index)
01023 {
01024   if ( (NULL == dsc ) || (index >= dsc->phones_count) )
01025     return NULL;
01026   return dsc->phones[index];
01027 }
01028 
01029 fsdp_network_type_t
01030 fsdp_get_global_conn_network_type(const fsdp_description_t *dsc)
01031 {
01032   if ( NULL == dsc)
01033     return FSDP_NETWORK_TYPE_UNDEFINED;
01034   return dsc->c_network_type;
01035 }
01036 
01037 fsdp_address_type_t
01038 fsdp_get_global_conn_address_type(const fsdp_description_t *dsc)
01039 {
01040   if ( NULL == dsc)
01041     return FSDP_ADDRESS_TYPE_UNDEFINED;
01042   return dsc->c_address_type;
01043 }
01044 
01045 const char *
01046 fsdp_get_global_conn_address(const fsdp_description_t *dsc)
01047 {
01048   if ( NULL == dsc)
01049     return NULL;
01050   return dsc->c_address.address;
01051 }
01052 
01053 unsigned int
01054 fsdp_get_global_conn_address_ttl(const fsdp_description_t *dsc)
01055 {
01056   if ( NULL == dsc)
01057     return 0;
01058   return dsc->c_address.address_ttl;
01059 }
01060 
01061 unsigned int
01062 fsdp_get_global_conn_address_count(const fsdp_description_t *dsc)
01063 {
01064   if ( NULL == dsc)
01065     return 0;
01066   return dsc->c_address.address_count;
01067 }
01068 
01069 unsigned int
01070 fsdp_get_bw_modifier_count(const fsdp_description_t *dsc)
01071 {
01072   if ( (NULL == dsc) )
01073     return 0;
01074   return dsc->bw_modifiers_count;
01075 }
01076 
01077 fsdp_bw_modifier_type_t
01078 fsdp_get_bw_modifier_type(const fsdp_description_t *dsc, unsigned int index)
01079 {
01080   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) ) 
01081     return FSDP_BW_MOD_TYPE_UNDEFINED;
01082   return dsc->bw_modifiers[index].b_mod_type;
01083 }
01084 
01085 const char *
01086 fsdp_get_bw_modifier_type_unknown(const fsdp_description_t *dsc, 
01087                       unsigned int index)
01088 {
01089   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) ||
01090        (dsc->bw_modifiers[index].b_mod_type != FSDP_BW_MOD_TYPE_UNKNOWN) )
01091     return NULL;
01092   return dsc->bw_modifiers[index].b_unknown_bw_modt;
01093 }
01094 
01095 unsigned long int
01096 fsdp_get_bw_value(const fsdp_description_t *dsc, unsigned int index)
01097 {
01098   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) )
01099     return 0;
01100   return dsc->bw_modifiers[index].b_value;
01101 }
01102 
01103 time_t
01104 fsdp_get_period_start(const fsdp_description_t *dsc, unsigned int index)
01105 {
01106   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01107     return 0;
01108   return dsc->time_periods[index]->start;
01109 }
01110 
01111 time_t
01112 fsdp_get_period_stop(const fsdp_description_t *dsc, unsigned int index)
01113 {
01114   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01115     return 0;
01116   return dsc->time_periods[index]->stop;
01117 }
01118 
01119 unsigned int
01120 fsdp_get_period_repeats_count(const fsdp_description_t *dsc, 
01121                      unsigned int index)
01122 {
01123   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01124        return 0;
01125   return dsc->time_periods[index]->repeats_count;
01126 }
01127 
01128 unsigned long int
01129 fsdp_get_period_repeat_interval(const fsdp_description_t *dsc, 
01130                      unsigned int index, unsigned int rindex)
01131 {
01132   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01133      return 0;
01134   return dsc->time_periods[index]->repeats[rindex]->interval;
01135 }
01136 
01137 unsigned long int
01138 fsdp_get_period_repeat_duration(const fsdp_description_t *dsc, 
01139                      unsigned int index, unsigned int rindex)
01140 {
01141   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01142     return 0;
01143   return dsc->time_periods[index]->repeats[rindex]->duration;
01144 }
01145 
01146 const unsigned long int *
01147 fsdp_get_period_repeat_offsets(const fsdp_description_t *dsc, 
01148                      unsigned int index, unsigned int rindex)
01149 {
01150   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01151     return NULL;
01152   return dsc->time_periods[index]->repeats[rindex]->offsets;
01153 }
01154 
01155 const char *
01156 fsdp_get_timezone_adj(const fsdp_description_t *dsc)
01157 {
01158   if ( NULL == dsc )
01159     return NULL;
01160   return dsc->timezone_adj;
01161 }
01162 
01163 unsigned int
01164 fsdp_get_unidentified_attribute_count(const fsdp_description_t *dsc)
01165 {
01166   if ( NULL == dsc )
01167     return 0;
01168   return dsc->unidentified_attributes_count;
01169 }
01170 
01171 const char *
01172 fsdp_get_unidentified_attribute(const fsdp_description_t *dsc, 
01173                     unsigned int index)
01174 {
01175   if ( NULL == dsc || (index < dsc->unidentified_attributes_count) )
01176     return NULL;
01177   return dsc->unidentified_attributes[index];
01178 }
01179 
01180 fsdp_encryption_method_t
01181 fsdp_get_encryption_method(const fsdp_description_t *dsc)
01182 {
01183   if ( NULL == dsc )
01184     return FSDP_ENCRYPTION_METHOD_UNDEFINED;
01185   return dsc->k_encryption_method;
01186 }
01187 
01188 const char *
01189 fsdp_get_encryption_content(const fsdp_description_t *dsc)
01190 {
01191   if ( (NULL == dsc) || 
01192        (dsc->k_encryption_method == FSDP_ENCRYPTION_METHOD_UNDEFINED) )
01193     return NULL;
01194   return dsc->k_encryption_content;
01195 }
01196 
01197 unsigned int
01198 fsdp_get_rtpmap_count(const fsdp_description_t *dsc)
01199 {
01200   if ( NULL == dsc)
01201     return 0;
01202   return dsc->a_rtpmaps_count;
01203 }
01204 
01205 const char *
01206 fsdp_get_rtpmap_payload_type(const fsdp_description_t *dsc, unsigned int index)
01207 {
01208   if ( (NULL == dsc) || (index >= dsc->a_rtpmaps_count) )
01209     return NULL;
01210   return dsc->a_rtpmaps[index]->pt;
01211 }
01212 
01213 const char *
01214 fsdp_get_rtpmap_encoding_name(const fsdp_description_t *dsc, 
01215                      unsigned int index)
01216 {
01217   if ( (NULL == dsc) || (index >= dsc->a_rtpmaps_count) )
01218     return NULL;
01219   return dsc->a_rtpmaps[index]->encoding_name;
01220 }
01221 
01222 unsigned int
01223 fsdp_get_rtpmap_clock_rate(const fsdp_description_t *dsc, unsigned int index)
01224 {
01225   if ( (NULL == dsc) || (index >= dsc->a_rtpmaps_count) )
01226     return 0;
01227   return dsc->a_rtpmaps[index]->clock_rate;
01228 }
01229 
01230 const char *
01231 fsdp_get_rtpmap_encoding_parameters(const fsdp_description_t *dsc, 
01232                      unsigned int index)
01233 {
01234   if ( (NULL == dsc) || (index >= dsc->a_rtpmaps_count) )
01235     return NULL;
01236   return dsc->a_rtpmaps[index]->parameters;
01237 }
01238 
01239 const char *
01240 fsdp_get_str_att(const fsdp_description_t *dsc, fsdp_session_str_att_t att)
01241 {
01242   char *result;
01243   if ( NULL == dsc )
01244     return NULL;
01245   if ( att <= FSDP_LAST_SESSION_STR_ATT ) 
01246     result = dsc->a_str_attributes[att];
01247   else
01248     result = NULL;
01249   return result;
01250 }
01251 
01252 unsigned int
01253 fsdp_get_sdplang_count(const fsdp_description_t *dsc)
01254 {
01255   if ( NULL == dsc )
01256     return 0;
01257   return dsc->a_sdplangs_count;
01258 }
01259 
01260 const char *
01261 fsdp_get_sdplang(const fsdp_description_t *dsc, unsigned int index)
01262 {
01263   if ( (NULL == dsc) || (index >= dsc->a_sdplangs_count) )
01264     return NULL;
01265   return dsc->a_sdplangs[index];
01266 }
01267 
01268 unsigned int
01269 fsdp_get_lang_count(const fsdp_description_t *dsc)
01270 {
01271   if ( NULL == dsc )
01272     return 0;
01273   return dsc->a_langs_count;
01274 }
01275 
01276 const char *
01277 fsdp_get_lang(const fsdp_description_t *dsc, unsigned int index)
01278 {
01279   if ( (NULL == dsc) || (index >= dsc->a_langs_count) )
01280     return NULL;
01281   return dsc->a_langs[index];
01282 }
01283 
01284 fsdp_sendrecv_mode_t
01285 fsdp_get_sendrecv_mode(const fsdp_description_t *dsc)
01286 {
01287   if ( NULL == dsc )
01288     return FSDP_SENDRECV_UNDEFINED;
01289   return dsc->a_sendrecv_mode;
01290 }
01291 
01292 fsdp_session_type_t
01293 fsdp_get_session_type(const fsdp_description_t *dsc)
01294 {
01295   if ( NULL == dsc )
01296     return FSDP_SESSION_TYPE_UNDEFINED;
01297   return dsc->a_type;
01298 }
01299 
01300 unsigned int
01301 fsdp_get_media_count(const fsdp_description_t *dsc)
01302 {
01303   if ( NULL == dsc )
01304     return 0;
01305   return dsc->media_announcements_count;
01306 }
01307 
01308 const fsdp_media_description_t*
01309 fsdp_get_media(const fsdp_description_t *dsc, unsigned int index)
01310 {
01311   if ( (index >= dsc->media_announcements_count) )
01312     return NULL;
01313   return dsc->media_announcements[index];
01314 }
01315 
01316 fsdp_media_t
01317 fsdp_get_media_type(const fsdp_media_description_t *dsc)
01318 {
01319   if ( (NULL == dsc) )
01320     return FSDP_MEDIA_UNDEFINED;
01321   return dsc->media_type;
01322 }
01323 
01324 unsigned int
01325 fsdp_get_media_port(const fsdp_media_description_t *dsc)
01326 {
01327   if ( (NULL == dsc) )
01328     return 0;
01329   return dsc->port;
01330 }
01331 
01332 unsigned int
01333 fsdp_get_media_port_count(const fsdp_media_description_t *dsc)
01334 {
01335   if ( (NULL == dsc) )
01336     return 0;
01337   return dsc->port_count;
01338 }
01339 
01340 fsdp_transport_protocol_t
01341 fsdp_get_media_transport_protocol(const fsdp_media_description_t *dsc)
01342 {
01343   if ( (NULL == dsc) )
01344     return FSDP_TP_UNDEFINED;
01345   return dsc->transport;
01346 }
01347 
01348 unsigned int
01349 fsdp_get_media_formats_count(const fsdp_media_description_t *dsc)
01350 {
01351   if ( (NULL == dsc) )
01352     return 0;
01353   return dsc->formats_count;
01354 }
01355 
01356 const char *
01357 fsdp_get_media_format(const fsdp_media_description_t *dsc, unsigned int index)
01358 {
01359   if ( (NULL == dsc) && (index < dsc->formats_count) )
01360     return NULL;
01361   return dsc->formats[index];
01362 }
01363 
01364 const char *
01365 fsdp_get_media_title(const fsdp_media_description_t *dsc)
01366 {
01367   if ( (NULL == dsc) )
01368     return NULL;
01369   return dsc->i_title;
01370 }
01371 
01372 fsdp_network_type_t 
01373 fsdp_get_media_network_type(const fsdp_media_description_t *dsc)
01374 {
01375   if ( (NULL == dsc) )
01376     return FSDP_NETWORK_TYPE_UNDEFINED;
01377   return dsc->c_network_type;
01378 }
01379 
01380 fsdp_address_type_t 
01381 fsdp_get_media_address_type(const fsdp_media_description_t *dsc)
01382 {
01383   if ( (NULL == dsc) )
01384     return FSDP_ADDRESS_TYPE_UNDEFINED;
01385   return dsc->c_address_type;
01386 }
01387 
01388 const char *
01389 fsdp_get_media_address(const fsdp_media_description_t *dsc)
01390 {
01391   if ( (NULL == dsc) )
01392     return NULL;
01393   return dsc->c_address.address;
01394 }
01395 
01396 unsigned int
01397 fsdp_get_media_address_ttl(const fsdp_media_description_t *mdsc)
01398 {
01399   if ( NULL == mdsc )
01400     return 0;
01401   return mdsc->c_address.address_ttl;
01402 }
01403 
01404 unsigned int
01405 fsdp_get_media_address_count(const fsdp_media_description_t *mdsc)
01406 {
01407   if ( NULL == mdsc)
01408     return 0;
01409   return mdsc->c_address.address_count;
01410 }
01411 
01412 fsdp_bw_modifier_type_t
01413 fsdp_get_media_bw_modifier_type(const fsdp_media_description_t *dsc, 
01414                     unsigned int index)
01415 {
01416   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) )
01417     return FSDP_BW_MOD_TYPE_UNDEFINED;
01418   return dsc->bw_modifiers[index].b_mod_type;
01419 }
01420 
01421 const char *
01422 fsdp_get_media_bw_modifier_type_unknown(const fsdp_media_description_t *dsc, 
01423                          unsigned int index)
01424 {
01425   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) ||
01426        (FSDP_BW_MOD_TYPE_UNKNOWN != dsc->bw_modifiers[index].b_mod_type) )
01427     return NULL;
01428   return dsc->bw_modifiers[index].b_unknown_bw_modt;
01429 }
01430 
01431 unsigned long int
01432 fsdp_get_media_bw_value(const fsdp_media_description_t *dsc, 
01433                unsigned int index)
01434 {
01435   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) ) 
01436     return 0;
01437   return dsc->bw_modifiers[index].b_value;
01438 }
01439 
01440 fsdp_encryption_method_t
01441 fsdp_get_media_encryption_method(const fsdp_media_description_t *dsc)
01442 {
01443   if ( (NULL == dsc) )
01444     return FSDP_ENCRYPTION_METHOD_UNDEFINED;
01445   return dsc->k_encryption_method;
01446 }
01447 
01448 const char *
01449 fsdp_get_media_encryption_content(const fsdp_media_description_t *dsc)
01450 {
01451   if ( (NULL == dsc) )
01452     return NULL;
01453   return dsc->k_encryption_content;
01454 }
01455 
01456 unsigned int 
01457 fsdp_get_media_ptime(const fsdp_media_description_t *dsc)
01458 {
01459   if ( (NULL == dsc) )
01460     return 0;
01461   return dsc->a_ptime;
01462 }
01463 
01464 unsigned int
01465 fsdp_get_media_maxptime(const fsdp_media_description_t *dsc)
01466 {
01467   if ( (NULL == dsc) )
01468     return 0;
01469   return dsc->a_maxptime;
01470 }
01471 
01472 unsigned int
01473 fsdp_get_media_rtpmap_count(const fsdp_media_description_t *mdsc)
01474 {
01475   if ( NULL == mdsc)
01476     return 0;
01477   return mdsc->a_rtpmaps_count;
01478 }
01479 
01480 const char *
01481 fsdp_get_media_rtpmap_payload_type(const fsdp_media_description_t *mdsc,
01482                        unsigned int index)
01483 {
01484   if ( (NULL == mdsc) || (index >= mdsc->a_rtpmaps_count) )
01485     return NULL;
01486   return mdsc->a_rtpmaps[index]->pt;
01487 }
01488 
01489 const char *
01490 fsdp_get_media_rtpmap_encoding_name(const fsdp_media_description_t *mdsc,
01491                         unsigned int index)
01492 {
01493   if ( (NULL == mdsc) || (index >= mdsc->a_rtpmaps_count) )
01494     return NULL;
01495   return mdsc->a_rtpmaps[index]->encoding_name;
01496 }
01497 
01498 unsigned int
01499 fsdp_get_media_rtpmap_clock_rate(const fsdp_media_description_t *mdsc,
01500                      unsigned int index)
01501 {
01502   if ( (NULL == mdsc) || (index >= mdsc->a_rtpmaps_count) )
01503     return 0;
01504   return mdsc->a_rtpmaps[index]->clock_rate;
01505 }
01506 
01507 const char *
01508 fsdp_get_media_rtpmap_encoding_parameters(const fsdp_description_t *mdsc, 
01509                            unsigned int index)
01510 {
01511   if ( (NULL == mdsc) || (index >= mdsc->a_rtpmaps_count) )
01512     return NULL;
01513   return mdsc->a_rtpmaps[index]->parameters;
01514 }
01515 
01516 unsigned int
01517 fsdp_get_media_sdplang_count(const fsdp_media_description_t *mdsc)
01518 {
01519   if ( NULL == mdsc )
01520     return 0;
01521   return mdsc->a_sdplangs_count;
01522 }
01523 
01524 const char *
01525 fsdp_get_media_sdplang(const fsdp_media_description_t *mdsc, 
01526                  unsigned int index)
01527 {
01528   if ( (NULL == mdsc) || (index >= mdsc->a_sdplangs_count) )
01529     return NULL;
01530   return mdsc->a_sdplangs[index];
01531 }
01532 
01533 unsigned int
01534 fsdp_get_media_lang_count(const fsdp_media_description_t *mdsc)
01535 {
01536   if ( NULL == mdsc )
01537     return 0;
01538   return mdsc->a_langs_count;
01539 }
01540 
01541 const char *
01542 fsdp_get_media_lang(const fsdp_media_description_t *mdsc, 
01543                  unsigned int index)
01544 {
01545   if ( (NULL == mdsc) || (index >= mdsc->a_langs_count) )
01546     return NULL;
01547   return mdsc->a_langs[index];
01548 }
01549 
01550 unsigned int
01551 fsdp_get_media_fmtp_count(const fsdp_media_description_t *mdsc)
01552 {
01553   if ( NULL == mdsc )
01554     return 0;
01555   return mdsc->a_fmtps_count;
01556 }
01557 
01558 const char *
01559 fsdp_get_media_fmtp(const fsdp_media_description_t *mdsc, unsigned int index)
01560 {
01561   if ( (NULL == mdsc) || (index >= mdsc->a_fmtps_count) )
01562     return NULL;
01563   return mdsc->a_fmtps[index];
01564 }
01565 
01566 fsdp_orient_t
01567 fsdp_get_media_orient(const fsdp_media_description_t *dsc)
01568 {
01569   if ( (NULL == dsc) )
01570     return FSDP_ORIENT_UNDEFINED;
01571   return dsc->a_orient;
01572 }
01573 
01574 fsdp_sendrecv_mode_t
01575 fsdp_get_media_sendrecv(const fsdp_media_description_t *dsc)
01576 {
01577   if ( (NULL == dsc) )
01578     return FSDP_SENDRECV_UNDEFINED;
01579   return dsc->a_sendrecv_mode;
01580 }
01581 
01582 float
01583 fsdp_get_media_framerate(const fsdp_media_description_t *dsc)
01584 {
01585   if ( (NULL == dsc) )
01586     return 0;
01587   return dsc->a_framerate;
01588 }
01589 
01590 unsigned int
01591 fsdp_get_media_quality(const fsdp_media_description_t *dsc)
01592 {
01593   if ( (NULL == dsc) )
01594     return 0;
01595   return dsc->a_quality;
01596 }
01597 
01598 unsigned int
01599 fsdp_get_media_rtcp_port(const fsdp_media_description_t *dsc)
01600 {
01601   if ( (NULL == dsc) )
01602     return 0;
01603   return dsc->a_rtcp_port;
01604 }
01605 
01606 fsdp_network_type_t
01607 fsdp_get_media_rtcp_network_type(const fsdp_media_description_t *dsc)
01608 {
01609   if ( (NULL == dsc) )
01610     return FSDP_NETWORK_TYPE_UNDEFINED;
01611   return dsc->a_rtcp_network_type;
01612 }
01613 
01614 fsdp_address_type_t
01615 fsdp_get_media_rtcp_address_type(const fsdp_media_description_t *dsc)
01616 {
01617   if ( (NULL == dsc) )
01618     return FSDP_ADDRESS_TYPE_UNDEFINED;
01619   return dsc->a_rtcp_address_type;
01620 }
01621 
01622 const char*
01623 fsdp_get_media_rtcp_address(const fsdp_media_description_t *dsc)
01624 {
01625   if ( (NULL == dsc) )
01626     return NULL;
01627   return dsc->a_rtcp_address;
01628 }
01629 
01630 unsigned int
01631 fsdp_get_media_unidentified_attribute_count(const fsdp_media_description_t
01632                              *mdsc)
01633 {
01634   if ( NULL == mdsc )
01635     return 0;
01636   return mdsc->unidentified_attributes_count;
01637 }
01638 
01639 const char *
01640 fsdp_get_media_unidentified_attribute(const fsdp_media_description_t *mdsc,
01641                           unsigned int index)
01642 {
01643   if ( NULL == mdsc || (index < mdsc->unidentified_attributes_count) )
01644     return NULL;
01645   return mdsc->unidentified_attributes[index];
01646 }

Generated on Sun Jan 18 21:12:44 2004 for FreeSDP by doxygen 1.3.4