parser.c

Go to the documentation of this file.
00001 /*
00002   This file is part of FreeSDP
00003   Copyright (C) 2001,2002,2003,2004 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   FreeSDP 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=%[^:\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=%"MSFLENS"[^\r\n]",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],"RTP/SAVP",8) )
00499        media->transport = FSDP_TP_RTP_SAVP;
00500      else if ( !strncmp(fsdp_buf[2],"RTP/AVPF",8) )
00501        media->transport = FSDP_TP_RTP_AVPF;
00502      else if ( !strncmp(fsdp_buf[2],"RTP/SAVPF",9) )
00503        media->transport = FSDP_TP_RTP_SAVPF;
00504      else if ( !strncmp(fsdp_buf[2],"udp",3) )
00505        media->transport = FSDP_TP_UDP;
00506      else if ( !strncmp(fsdp_buf[2],"TCP",3) )
00507        media->transport = FSDP_TP_TCP;
00508      else if ( !strncmp(fsdp_buf[2],"UDPTL",5) )
00509        media->transport = FSDP_TP_UDPTL;
00510      else if ( !strncmp(fsdp_buf[2],"vat",3) )
00511        media->transport = FSDP_TP_VAT;
00512      else if ( !strncmp(fsdp_buf[2],"rtp",3) )
00513        media->transport = FSDP_TP_OLD_RTP;
00514      else
00515        return FSDPE_UNKNOWN_MEDIA_TRANSPORT;
00516      {
00517        unsigned int k = 0;
00518        char *s = longfsdp_buf;
00519        while ( NULL != ( s = strchr(s,' ')) ) {
00520          k++;
00521          if ( NULL != s )
00522            s++;
00523        }
00524        k++; /* when there is no space left, count the last format */
00525        media->formats_count = k;
00526        media->formats = calloc(k,sizeof(char*));
00527        s = longfsdp_buf;
00528        for ( k = 0; k < media->formats_count; k++ ) {
00529          char *space = strchr(s,' ');
00530          if ( NULL != space )
00531            *space = '\0';
00532          media->formats[k] = strdup(s);
00533          s = space + 1;
00534        }
00535      }
00536      NEXT_LINE(p);
00537       }
00538       
00539       /* `i=' line (media title) [optional] */
00540       /* i=<media title> */
00541       if ( !strncmp(p,"i=",2)  && sscanf(p,"i=%"MLFLENS"[^\r\n]",longfsdp_buf) ) {
00542      media->i_title = strdup(longfsdp_buf);
00543      NEXT_LINE(p);
00544       } else {
00545      /* (optional) information absent */
00546       }
00547       
00548       /* `c=' line (connection information - overrides session-level
00549       line) [optional if provided at session-level] */
00550       /* c=<network type> <address type> <connection address> */    
00551       result = fsdp_parse_c(&p,&(media->c_network_type),
00552                    &(media->c_address_type),&(media->c_address));
00553       if ( result != FSDPE_OK )
00554      return result;
00555       
00556       /* `b=' lines (bandwidth information) [optional] */
00557       /* b=<modifier>:<bandwidth-value> */
00558       result = fsdp_parse_b(&p,&(media->bw_modifiers),
00559                    &(media->bw_modifiers_count));
00560       if ( FSDPE_OK != result )
00561      return result;
00562 
00563       /* `k=' line (encryption key) [optional] */
00564       /* k=<method> 
00565       k=<method>:<encryption key> */
00566       result = fsdp_parse_k(&p,&(media->k_encryption_method),
00567                    &(media->k_encryption_content)); 
00568       if ( result != FSDPE_OK )
00569      return result;
00570       
00571       /* B.1) Attributes */
00572       
00573       /* `a=' lines (zero or more media attribute lines) [optional] */
00574       /* a=<attribute>
00575       a=<attribute>:<value> */
00576       while ( !strncmp(p,"a=",2) ) {
00577      if ( sscanf(p,"a=%[^:\r\n]:%"MLFLENS"[^\r\n]",fsdp_buf[0],longfsdp_buf) 
00578           == 2 ) {  
00579        /* media-level value attributes */
00580        if ( !strncmp(fsdp_buf[0],"ptime",5) )
00581          media->a_ptime = strtoul(longfsdp_buf,NULL,10);
00582        else if ( !strncmp(fsdp_buf[0],"maxptime",8) )
00583          media->a_maxptime = strtoul(longfsdp_buf,NULL,10);
00584        else if ( !strncmp(fsdp_buf[0],"rtpmap",6) )
00585          fsdp_parse_rtpmap(&(media->a_rtpmaps),
00586                      &(media->a_rtpmaps_count),longfsdp_buf);
00587        else if ( !strncmp(fsdp_buf[0],"orient",6) ) {
00588          if ( !strncmp(longfsdp_buf,"portrait",8) ) 
00589            media->a_orient = FSDP_ORIENT_PORTRAIT;
00590          else if ( !strncmp(longfsdp_buf,"landscape",9) ) 
00591            media->a_orient = FSDP_ORIENT_LANDSCAPE;
00592          else if ( !strncmp(longfsdp_buf,"seascape",9) ) 
00593            media->a_orient = FSDP_ORIENT_SEASCAPE; 
00594        } else if ( !strncmp(fsdp_buf[0],"sdplang",7) ) {
00595          if ( NULL == dsc->a_sdplangs ) {
00596            media->a_sdplangs_count = 0;
00597            media->a_sdplangs = 
00598           calloc(SDPLANGS_MAX_COUNT,sizeof(char*));
00599          }
00600          if ( media->a_sdplangs_count < SDPLANGS_MAX_COUNT ) {
00601            media->a_sdplangs[dsc->a_sdplangs_count] = strdup(longfsdp_buf);
00602            media->a_sdplangs_count++;
00603          }
00604        } else if ( !strncmp(fsdp_buf[0],"lang",4) ) {
00605          if ( NULL == dsc->a_langs ) {
00606            media->a_langs_count = 0;
00607            media->a_langs = calloc(SDPLANGS_MAX_COUNT,sizeof(char*));
00608          }
00609          if ( media->a_langs_count < SDPLANGS_MAX_COUNT ) {
00610            media->a_langs[dsc->a_langs_count] = strdup(longfsdp_buf);
00611            media->a_langs_count++;
00612          }
00613        } else if ( !strncmp(fsdp_buf[0],"framerate",9) ) 
00614          media->a_framerate = strtof(longfsdp_buf,NULL);
00615        else if ( !strncmp(fsdp_buf[0],"fmtp",4) ) {
00616          if ( NULL == media->a_fmtps ) {
00617            media->a_fmtps_count = 0;
00618            media->a_fmtps = calloc(SDPLANGS_MAX_COUNT,sizeof(char*));
00619          }
00620          if ( media->a_fmtps_count < SDPLANGS_MAX_COUNT ) {
00621            media->a_fmtps[media->a_fmtps_count] = strdup(longfsdp_buf);
00622            media->a_fmtps_count++;
00623          }
00624        } else if ( !strncmp(fsdp_buf[0],"rtcp",4) ) {
00625          int opts = 0;
00626          /* rtcp attribute: a=rtcp:<port> <nettype> <addrtype> <address> */
00627          opts = sscanf(longfsdp_buf,"%lu %2s %3s %"MSFLENS"s",
00628                  &wuint[0],fsdp_buf[0],fsdp_buf[1],fsdp_buf[2]);
00629          if ( opts >= 1 ) {
00630            media->a_rtcp_port = wuint[0];
00631            if ( opts >= 2 ) {
00632           if ( !strncmp(fsdp_buf[0],"IN",2) ) {
00633             media->a_rtcp_network_type = FSDP_NETWORK_TYPE_INET;
00634           } /* else
00635             ; TODO: define error code? */
00636           if ( opts >= 3 ) {
00637             if ( !strncmp(fsdp_buf[1],"IP4",3) )
00638               media->a_rtcp_address_type = FSDP_ADDRESS_TYPE_IPV4;
00639             else if ( !strncmp(fsdp_buf[1],"IP6",3) )
00640               media->a_rtcp_address_type = FSDP_ADDRESS_TYPE_IPV6;
00641             else
00642               return FSDPE_INVALID_CONNECTION_NETTYPE; 
00643             /*add specific code?*/
00644             if ( opts >= 4)
00645               media->a_rtcp_address = strdup(fsdp_buf[2]);
00646           }
00647            }
00648          }
00649        } else {
00650          /* ignore unknown attributes, but provide access to them */     
00651          *fsdp_buf[1] = '\0';
00652          strncat(fsdp_buf[1],fsdp_buf[0],MAXLONGFIELDLEN);
00653          strncat(fsdp_buf[1],":",MAXLONGFIELDLEN);
00654          strncat(fsdp_buf[1],longfsdp_buf,MAXLONGFIELDLEN);
00655          if ( NULL == media->unidentified_attributes ) {
00656            media->unidentified_attributes_count = 0;
00657            media->unidentified_attributes = 
00658           calloc(UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,sizeof(char*));
00659          }
00660          if ( media->unidentified_attributes_count < 
00661            UNIDENTIFIED_ATTRIBUTES_MAX_COUNT ) {
00662            media->unidentified_attributes
00663           [media->unidentified_attributes_count] = strdup(fsdp_buf[1]);
00664            media->unidentified_attributes_count++;
00665          }
00666        }
00667        NEXT_LINE(p);
00668      } else if ( sscanf(p,"a=%"MSFLENS"[^\r\n]",fsdp_buf[0]) == 1 ) {  
00669        /* media-level property attributes */
00670        if ( !strncmp(fsdp_buf[0],"recvonly",8) )
00671          media->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
00672        else if ( !strncmp(fsdp_buf[0],"sendonly",8) )
00673          media->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
00674        else if ( !strncmp(fsdp_buf[0],"inactive",8) )
00675          media->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
00676        else if ( !strncmp(fsdp_buf[0],"sendrecv",8) )
00677          media->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
00678        else {
00679          /* ignore unknown attributes, but provide access to them */     
00680          *longfsdp_buf = '\0';
00681          strncat(longfsdp_buf,fsdp_buf[0],MAXLONGFIELDLEN);
00682          if ( NULL == media->unidentified_attributes ) {
00683            media->unidentified_attributes_count = 0;
00684            media->unidentified_attributes = 
00685           calloc(UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,sizeof(char*));
00686          }
00687          if ( media->unidentified_attributes_count < 
00688            UNIDENTIFIED_ATTRIBUTES_MAX_COUNT ) {
00689            media->unidentified_attributes
00690           [media->unidentified_attributes_count] = strdup(longfsdp_buf);
00691            media->unidentified_attributes_count++;
00692          }
00693        }
00694        NEXT_LINE(p);
00695      } else
00696        return FSDPE_INVALID_ATTRIBUTE;
00697       }
00698     } /* end of for */
00699   }
00700 
00701   /* Check c= has been given at session level or at media level for
00702      all media */
00703   if ( NULL == dsc->c_address.address ) {
00704     unsigned int c;
00705     for ( c = 0; c < dsc->media_announcements_count; c++)
00706       if ( NULL == dsc->media_announcements[c]->c_address.address )
00707      return FSDPE_MISSING_CONNECTION_INFO;
00708   }
00709 
00710   /* finish */
00711   if ( *p == '\0' )
00712     return FSDPE_OK;
00713   else
00714     return FSDPE_OVERFILLED;
00715 }
00716 
00717 static fsdp_error_t
00718 fsdp_parse_c(const char **p, fsdp_network_type_t *ntype, 
00719           fsdp_address_type_t *atype, fsdp_connection_address_t *address)
00720 {
00721   const unsigned int TEMPCHARS = 3;
00722   char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
00723 
00724   if ( !strncmp(*p,"c=",2) ) { 
00725     if ( sscanf(*p,"c=%2s %3s %"MSFLENS"s",fsdp_buf[0],fsdp_buf[1],fsdp_buf[2]) ) {
00726       if ( !strncmp(fsdp_buf[0],"IN",2) ) {
00727      *ntype = FSDP_NETWORK_TYPE_INET;
00728      if ( !strncmp(fsdp_buf[1],"IP4",3) )
00729        *atype = FSDP_ADDRESS_TYPE_IPV4;
00730      else if ( !strncmp(fsdp_buf[1],"IP6",3) )
00731        *atype = FSDP_ADDRESS_TYPE_IPV6;
00732      else
00733        return FSDPE_INVALID_CONNECTION_NETTYPE;
00734       } else {
00735      return FSDPE_INVALID_CONNECTION_ADDRTYPE;
00736       }
00737       {
00738      char *slash = strchr(fsdp_buf[2],'/');
00739      if ( NULL == slash ) {
00740        address->address = strdup(fsdp_buf[2]);
00741        address->address_ttl = 0;
00742        address->address_count = 0;
00743      } else {
00744        /* address is IP4 multicast */
00745        char *slash2;
00746        *slash = '\0';
00747        slash++;
00748        address->address = strdup(fsdp_buf[2]);
00749        slash2 = strchr(slash + 1,'/');
00750        if ( NULL == slash2 ) {
00751          address->address_ttl = strtol(slash,NULL,10);
00752          address->address_count = 0;
00753        } else {
00754          *slash2 = '\0';
00755          slash2++;
00756          address->address_ttl = strtol(slash,NULL,10);
00757          address->address_count = strtol(slash2,NULL,10);
00758        }
00759      }
00760       }
00761       NEXT_LINE(*p);
00762     } else {
00763       return FSDPE_INVALID_CONNECTION;
00764     }
00765   }
00766   return FSDPE_OK;
00767 }
00768     
00769 static fsdp_error_t
00770 fsdp_parse_b(const char **p, fsdp_bw_modifier_t **bw_modifiers, 
00771           unsigned int *bw_modifiers_count)
00772 {
00773   char fsdp_buf[MAXSHORTFIELDLEN];
00774   unsigned long int wuint;
00775   unsigned int i = 0;
00776   char *lp = (char*)*p;
00777 
00778   /* count b= lines */
00779   while ( !strncmp(lp,"b=",2) ) {
00780     NEXT_LINE(lp);
00781     i++;
00782   }
00783   *bw_modifiers = calloc(i,sizeof(fsdp_bw_modifier_t));
00784   *bw_modifiers_count = i;
00785 
00786   while ( i > 0 ) {
00787     unsigned int index = *bw_modifiers_count - i;
00788     if ( 2 == sscanf(*p,"b=%"MSFLENS"[^:\r\n]:%lu",fsdp_buf,&wuint) ) {
00789       if ( !strncmp(fsdp_buf,"CT",2) )
00790      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL;
00791       else if ( !strncmp(fsdp_buf,"AS",2) )
00792      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC;
00793       else if ( !strncmp(fsdp_buf,"RS",2) )
00794      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_SENDERS;
00795       else if ( !strncmp(fsdp_buf,"RR",2) )
00796      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_RECEIVERS;
00797       else {
00798      (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_UNKNOWN;
00799      (*bw_modifiers)[index].b_unknown_bw_modt = (char *)strdup(fsdp_buf);
00800       }
00801       (*bw_modifiers)[index].b_value = wuint;
00802       NEXT_LINE(*p);
00803     } else {
00804       *bw_modifiers_count -= i;
00805       return FSDPE_INVALID_BANDWIDTH;
00806     } 
00807     i--;
00808   }
00809   return FSDPE_OK;
00810 }
00811 
00812 static fsdp_error_t
00813 fsdp_parse_k(const char **p, fsdp_encryption_method_t *method, char **content)
00814 {
00815   char fsdp_buf[MAXSHORTFIELDLEN];
00816   char longfsdp_buf[MAXLONGFIELDLEN];
00817 
00818   if ( !strncmp(*p,"k=",2) ) {
00819     if ( sscanf(*p,"k=prompt") ) {
00820       *method = FSDP_ENCRYPTION_METHOD_PROMPT;
00821       *content = NULL;
00822       NEXT_LINE(*p);
00823     } else {
00824       if ( sscanf(*p,"k=%6[^:\r\n]:%"MLFLENS"s",fsdp_buf,longfsdp_buf) ) {
00825      if ( !strncmp(fsdp_buf,"clear",5) )
00826        *method = FSDP_ENCRYPTION_METHOD_CLEAR;
00827      else if ( !strncmp(fsdp_buf,"base64",6) )
00828        *method = FSDP_ENCRYPTION_METHOD_BASE64;   
00829      else if ( !strncmp(fsdp_buf,"uri",3) )
00830        *method = FSDP_ENCRYPTION_METHOD_URI; 
00831      else
00832        return FSDPE_INVALID_ENCRYPTION_METHOD;
00833      *content = strdup(longfsdp_buf);
00834      NEXT_LINE(*p);
00835       }
00836     }
00837   }
00838   return FSDPE_OK;
00839 }
00840 
00841 static fsdp_error_t
00842 fsdp_parse_rtpmap(fsdp_rtpmap_t ***rtpmap, unsigned int *counter, 
00843             const char *value)
00844 {
00845   fsdp_error_t result = FSDPE_OK;
00846   
00847   if ( 0 == *counter ) {
00848     *counter = 0;
00849     *rtpmap = calloc(MEDIA_RTPMAPS_MAX_COUNT,sizeof(fsdp_rtpmap_t*));
00850   }
00851   if ( *counter < MEDIA_RTPMAPS_MAX_COUNT ) {
00852     unsigned int c = *counter;
00853     fsdp_rtpmap_t **map = *rtpmap;
00854     char fsdp_buf[MAXSHORTFIELDLEN];
00855     char longfsdp_buf[MAXLONGFIELDLEN];
00856     map[c] = calloc(1,sizeof(fsdp_rtpmap_t));
00857 
00858     /* a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding
00859        parameters]> */
00860     if ( 2 == sscanf(value,"%s %s",fsdp_buf,longfsdp_buf) ) {
00861       char *slash1;
00862       map[c]->pt = strdup(fsdp_buf);
00863       /* parse <encoding name>/<clock rate>[/<encoding parameters>]*/
00864       slash1 = strchr(longfsdp_buf,'/');
00865       if ( NULL == slash1 ) {
00866      result = FSDPE_INVALID_ATTRIBUTE_RTPMAP;
00867       } else {
00868      char *slash2;
00869      *slash1 = '\0';
00870      slash1++;
00871      map[c]->encoding_name = strdup(longfsdp_buf);
00872      slash2 = strchr(slash1,'/');
00873      if ( NULL != slash2 ) {
00874        *slash2 = '\0';
00875        slash2++;
00876        map[c]->parameters = strdup(slash2);
00877      }    
00878      map[c]->clock_rate = strtol(slash1,NULL,10);
00879       }
00880       (*counter)++;
00881     }
00882   }
00883   return result;
00884 }
00885 
00886 static fsdp_error_t
00887 fsdp_repeat_time_to_uint(const char *time, unsigned long int *seconds)
00888 {
00889   const unsigned long SECONDS_PER_DAY = 86400;
00890   const unsigned long SECONDS_PER_HOUR = 3600;
00891   const unsigned long SECONDS_PER_MINUTE = 60;
00892   char c;
00893   unsigned long int wuint;
00894   
00895   if ( sscanf(time,"%lu%c",&wuint,&c) == 2 ) {
00896     /* time with unit specification character */
00897     switch(c) {
00898     case 'd':
00899       *seconds = wuint * SECONDS_PER_DAY;
00900       break;
00901     case 'h':
00902       *seconds = wuint * SECONDS_PER_HOUR;
00903       break;
00904     case 'm':
00905       *seconds = wuint * SECONDS_PER_MINUTE;
00906       break;
00907     case 's':
00908       *seconds = wuint;
00909       break;
00910     default:
00911       return FSDPE_INVALID_REPEAT;
00912       break;
00913     }
00914   } else if ( sscanf(time,"%lu",&wuint) == 1 ) {
00915     /* time without unit specification character */
00916     *seconds = wuint;
00917   } else {
00918     return FSDPE_INVALID_REPEAT;
00919   }    
00920   return FSDPE_OK;
00921 }
00922 
00923 const char *
00924 fsdp_get_wrong_string(const fsdp_description_t *dsc)
00925 {
00926   if ( NULL == dsc ) 
00927     return NULL;
00928   return NULL;
00929 }
00930 
00931 unsigned int
00932 fsdp_get_version(const fsdp_description_t *dsc)
00933 {
00934   if ( NULL == dsc)
00935     return 0;
00936   return dsc->version;
00937 }
00938 
00939 const char *
00940 fsdp_get_owner_username(const fsdp_description_t *dsc)
00941 {
00942   if ( NULL == dsc)
00943     return NULL;
00944   return dsc->o_username;
00945 }
00946 
00947 const char *
00948 fsdp_get_session_id(const fsdp_description_t *dsc)
00949 {
00950   if ( NULL == dsc)
00951     return NULL;
00952   return dsc->o_session_id;
00953 }
00954 
00955 const char *
00956 fsdp_get_announcement_version(const fsdp_description_t *dsc)
00957 {
00958   if ( NULL == dsc)
00959     return NULL;
00960   return dsc->o_announcement_version;
00961 }
00962 
00963 fsdp_network_type_t
00964 fsdp_get_owner_network_type(const fsdp_description_t *dsc)
00965 {
00966   if ( NULL == dsc)
00967     return FSDP_NETWORK_TYPE_UNDEFINED;
00968   return dsc->o_network_type;
00969 }
00970 
00971 fsdp_address_type_t
00972 fsdp_get_owner_address_type(const fsdp_description_t *dsc)
00973 {
00974   if ( NULL == dsc)
00975     return FSDP_ADDRESS_TYPE_UNDEFINED;
00976   return dsc->o_address_type;
00977 }
00978 
00979 const char *
00980 fsdp_get_owner_address(const fsdp_description_t *dsc)
00981 {
00982   if ( NULL == dsc)
00983     return NULL;
00984   return dsc->o_address;
00985 }
00986 
00987 const char *
00988 fsdp_get_name(const fsdp_description_t *dsc)
00989 {
00990   if ( NULL == dsc)
00991     return NULL;
00992   return dsc->s_name;
00993 }
00994 
00995 const char *
00996 fsdp_get_information(const fsdp_description_t *dsc)
00997 {
00998   if ( NULL == dsc)
00999     return NULL;
01000   return dsc->i_information;
01001 }
01002 
01003 const char *
01004 fsdp_get_uri(const fsdp_description_t *dsc)
01005 {
01006   if ( NULL == dsc)
01007     return NULL;
01008   return dsc->u_uri;
01009 }
01010 
01011 unsigned int
01012 fsdp_get_emails_count(const fsdp_description_t *dsc)
01013 {
01014   if ( NULL == dsc)
01015     return 0;
01016   return dsc->emails_count;
01017 }
01018 
01019 const char *
01020 fsdp_get_email(const fsdp_description_t *dsc, unsigned int index)
01021 {
01022   if ( (NULL == dsc) || (index >= dsc->emails_count) )
01023     return NULL;
01024   return dsc->emails[index];
01025 }
01026 
01027 unsigned int
01028 fsdp_get_phones_count(const fsdp_description_t *dsc)
01029 {
01030   if ( NULL == dsc)
01031     return 0;
01032   return dsc->phones_count;
01033 }
01034 
01035 const char *
01036 fsdp_get_phone(const fsdp_description_t *dsc, unsigned int index)
01037 {
01038   if ( (NULL == dsc ) || (index >= dsc->phones_count) )
01039     return NULL;
01040   return dsc->phones[index];
01041 }
01042 
01043 fsdp_network_type_t
01044 fsdp_get_global_conn_network_type(const fsdp_description_t *dsc)
01045 {
01046   if ( NULL == dsc)
01047     return FSDP_NETWORK_TYPE_UNDEFINED;
01048   return dsc->c_network_type;
01049 }
01050 
01051 fsdp_address_type_t
01052 fsdp_get_global_conn_address_type(const fsdp_description_t *dsc)
01053 {
01054   if ( NULL == dsc)
01055     return FSDP_ADDRESS_TYPE_UNDEFINED;
01056   return dsc->c_address_type;
01057 }
01058 
01059 const char *
01060 fsdp_get_global_conn_address(const fsdp_description_t *dsc)
01061 {
01062   if ( NULL == dsc)
01063     return NULL;
01064   return dsc->c_address.address;
01065 }
01066 
01067 unsigned int
01068 fsdp_get_global_conn_address_ttl(const fsdp_description_t *dsc)
01069 {
01070   if ( NULL == dsc)
01071     return 0;
01072   return dsc->c_address.address_ttl;
01073 }
01074 
01075 unsigned int
01076 fsdp_get_global_conn_addresses_count(const fsdp_description_t *dsc)
01077 {
01078   if ( NULL == dsc)
01079     return 0;
01080   return dsc->c_address.address_count;
01081 }
01082 
01083 unsigned int
01084 fsdp_get_bw_modifiers_count(const fsdp_description_t *dsc)
01085 {
01086   if ( (NULL == dsc) )
01087     return 0;
01088   return dsc->bw_modifiers_count;
01089 }
01090 
01091 fsdp_bw_modifier_type_t
01092 fsdp_get_bw_modifier_type(const fsdp_description_t *dsc, unsigned int index)
01093 {
01094   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) ) 
01095     return FSDP_BW_MOD_TYPE_UNDEFINED;
01096   return dsc->bw_modifiers[index].b_mod_type;
01097 }
01098 
01099 const char *
01100 fsdp_get_bw_modifier_type_unknown(const fsdp_description_t *dsc, 
01101                       unsigned int index)
01102 {
01103   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) ||
01104        (dsc->bw_modifiers[index].b_mod_type != FSDP_BW_MOD_TYPE_UNKNOWN) )
01105     return NULL;
01106   return dsc->bw_modifiers[index].b_unknown_bw_modt;
01107 }
01108 
01109 unsigned long int
01110 fsdp_get_bw_value(const fsdp_description_t *dsc, unsigned int index)
01111 {
01112   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) )
01113     return 0;
01114   return dsc->bw_modifiers[index].b_value;
01115 }
01116 
01117 unsigned long int
01118 fsdp_get_periods_count(const fsdp_description_t *dsc)
01119 {
01120   if ( NULL == dsc)
01121     return 0;
01122   return dsc->time_periods_count;
01123 }
01124 
01125 time_t
01126 fsdp_get_period_start(const fsdp_description_t *dsc, unsigned int index)
01127 {
01128   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01129     return 0;
01130   return dsc->time_periods[index]->start;
01131 }
01132 
01133 time_t
01134 fsdp_get_period_stop(const fsdp_description_t *dsc, unsigned int index)
01135 {
01136   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01137     return 0;
01138   return dsc->time_periods[index]->stop;
01139 }
01140 
01141 unsigned int
01142 fsdp_get_period_repeats_count(const fsdp_description_t *dsc, 
01143                      unsigned int index)
01144 {
01145   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01146        return 0;
01147   return dsc->time_periods[index]->repeats_count;
01148 }
01149 
01150 unsigned long int
01151 fsdp_get_period_repeat_interval(const fsdp_description_t *dsc, 
01152                      unsigned int index, unsigned int rindex)
01153 {
01154   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01155      return 0;
01156   return dsc->time_periods[index]->repeats[rindex]->interval;
01157 }
01158 
01159 unsigned long int
01160 fsdp_get_period_repeat_duration(const fsdp_description_t *dsc, 
01161                      unsigned int index, unsigned int rindex)
01162 {
01163   if ( (NULL == dsc) || (index >= dsc->time_periods_count) )
01164     return 0;
01165   return dsc->time_periods[index]->repeats[rindex]->duration;
01166 }
01167 
01168 unsigned long int
01169 fsdp_get_period_repeat_offsets_count(const fsdp_description_t *dsc, 
01170                          unsigned int index, unsigned int rindex)
01171 {
01172   if ( (NULL == dsc) || (index >= dsc->time_periods_count)  || 
01173        (rindex >= dsc->time_periods[index]->repeats_count) )
01174     return 0;
01175   return dsc->time_periods[index]->repeats[rindex]->offsets_count;
01176 }
01177 
01178 unsigned long int
01179 fsdp_get_period_repeat_offsets(const fsdp_description_t *dsc, 
01180                       unsigned int index, unsigned int rindex,
01181                       unsigned int oindex)
01182 {
01183   if ( (NULL == dsc) || (index >= dsc->time_periods_count)  || 
01184        (rindex >= dsc->time_periods[index]->repeats_count) || 
01185        (oindex >= dsc->time_periods[index]->repeats[rindex]->offsets_count) )
01186     return 0;
01187   return dsc->time_periods[index]->repeats[rindex]->offsets[oindex];
01188 }
01189 
01190 const char *
01191 fsdp_get_timezone_adj(const fsdp_description_t *dsc)
01192 {
01193   if ( NULL == dsc )
01194     return NULL;
01195   return dsc->timezone_adj;
01196 }
01197 
01198 unsigned int
01199 fsdp_get_unidentified_attributes_count(const fsdp_description_t *dsc)
01200 {
01201   if ( NULL == dsc )
01202     return 0;
01203   return dsc->unidentified_attributes_count;
01204 }
01205 
01206 const char *
01207 fsdp_get_unidentified_attribute(const fsdp_description_t *dsc, 
01208                     unsigned int index)
01209 {
01210   if ( NULL == dsc || (index >= dsc->unidentified_attributes_count) )
01211     return NULL;
01212   return dsc->unidentified_attributes[index];
01213 }
01214 
01215 fsdp_encryption_method_t
01216 fsdp_get_encryption_method(const fsdp_description_t *dsc)
01217 {
01218   if ( NULL == dsc )
01219     return FSDP_ENCRYPTION_METHOD_UNDEFINED;
01220   return dsc->k_encryption_method;
01221 }
01222 
01223 const char *
01224 fsdp_get_encryption_content(const fsdp_description_t *dsc)
01225 {
01226   if ( (NULL == dsc) || 
01227        (dsc->k_encryption_method == FSDP_ENCRYPTION_METHOD_UNDEFINED) )
01228     return NULL;
01229   return dsc->k_encryption_content;
01230 }
01231 
01232 unsigned int
01233 fsdp_get_rtpmap_count(const fsdp_description_t *dsc)
01234 {
01235   if ( NULL == dsc)
01236     return 0;
01237   return dsc->a_rtpmaps_count;
01238 }
01239 
01240 const char *
01241 fsdp_get_rtpmap_payload_type(const fsdp_description_t *dsc, unsigned int index)
01242 {
01243   if ( (NULL == dsc) || (index >= dsc->a_rtpmaps_count) )
01244     return NULL;
01245   return dsc->a_rtpmaps[index]->pt;
01246 }
01247 
01248 const char *
01249 fsdp_get_rtpmap_encoding_name(const fsdp_description_t *dsc, 
01250                      unsigned int index)
01251 {
01252   if ( (NULL == dsc) || (index >= dsc->a_rtpmaps_count) )
01253     return NULL;
01254   return dsc->a_rtpmaps[index]->encoding_name;
01255 }
01256 
01257 unsigned int
01258 fsdp_get_rtpmap_clock_rate(const fsdp_description_t *dsc, unsigned int index)
01259 {
01260   if ( (NULL == dsc) || (index >= dsc->a_rtpmaps_count) )
01261     return 0;
01262   return dsc->a_rtpmaps[index]->clock_rate;
01263 }
01264 
01265 const char *
01266 fsdp_get_rtpmap_encoding_parameters(const fsdp_description_t *dsc, 
01267                      unsigned int index)
01268 {
01269   if ( (NULL == dsc) || (index >= dsc->a_rtpmaps_count) )
01270     return NULL;
01271   return dsc->a_rtpmaps[index]->parameters;
01272 }
01273 
01274 const char *
01275 fsdp_get_str_att(const fsdp_description_t *dsc, fsdp_session_str_att_t att)
01276 {
01277   char *result;
01278   if ( NULL == dsc )
01279     return NULL;
01280   if ( att <= FSDP_LAST_SESSION_STR_ATT ) 
01281     result = dsc->a_str_attributes[att];
01282   else
01283     result = NULL;
01284   return result;
01285 }
01286 
01287 unsigned int
01288 fsdp_get_sdplang_count(const fsdp_description_t *dsc)
01289 {
01290   if ( NULL == dsc )
01291     return 0;
01292   return dsc->a_sdplangs_count;
01293 }
01294 
01295 const char *
01296 fsdp_get_sdplang(const fsdp_description_t *dsc, unsigned int index)
01297 {
01298   if ( (NULL == dsc) || (index >= dsc->a_sdplangs_count) )
01299     return NULL;
01300   return dsc->a_sdplangs[index];
01301 }
01302 
01303 unsigned int
01304 fsdp_get_lang_count(const fsdp_description_t *dsc)
01305 {
01306   if ( NULL == dsc )
01307     return 0;
01308   return dsc->a_langs_count;
01309 }
01310 
01311 const char *
01312 fsdp_get_lang(const fsdp_description_t *dsc, unsigned int index)
01313 {
01314   if ( (NULL == dsc) || (index >= dsc->a_langs_count) )
01315     return NULL;
01316   return dsc->a_langs[index];
01317 }
01318 
01319 fsdp_sendrecv_mode_t
01320 fsdp_get_sendrecv_mode(const fsdp_description_t *dsc)
01321 {
01322   if ( NULL == dsc )
01323     return FSDP_SENDRECV_UNDEFINED;
01324   return dsc->a_sendrecv_mode;
01325 }
01326 
01327 fsdp_session_type_t
01328 fsdp_get_session_type(const fsdp_description_t *dsc)
01329 {
01330   if ( NULL == dsc )
01331     return FSDP_SESSION_TYPE_UNDEFINED;
01332   return dsc->a_type;
01333 }
01334 
01335 unsigned int
01336 fsdp_get_media_count(const fsdp_description_t *dsc)
01337 {
01338   if ( NULL == dsc )
01339     return 0;
01340   return dsc->media_announcements_count;
01341 }
01342 
01343 const fsdp_media_description_t*
01344 fsdp_get_media(const fsdp_description_t *dsc, unsigned int index)
01345 {
01346   if ( (index >= dsc->media_announcements_count) )
01347     return NULL;
01348   return dsc->media_announcements[index];
01349 }
01350 
01351 fsdp_media_t
01352 fsdp_get_media_type(const fsdp_media_description_t *dsc)
01353 {
01354   if ( (NULL == dsc) )
01355     return FSDP_MEDIA_UNDEFINED;
01356   return dsc->media_type;
01357 }
01358 
01359 unsigned int
01360 fsdp_get_media_port(const fsdp_media_description_t *dsc)
01361 {
01362   if ( (NULL == dsc) )
01363     return 0;
01364   return dsc->port;
01365 }
01366 
01367 unsigned int
01368 fsdp_get_media_ports_count(const fsdp_media_description_t *dsc)
01369 {
01370   if ( (NULL == dsc) )
01371     return 0;
01372   return dsc->port_count;
01373 }
01374 
01375 fsdp_transport_protocol_t
01376 fsdp_get_media_transport_protocol(const fsdp_media_description_t *dsc)
01377 {
01378   if ( (NULL == dsc) )
01379     return FSDP_TP_UNDEFINED;
01380   return dsc->transport;
01381 }
01382 
01383 unsigned int
01384 fsdp_get_media_formats_count(const fsdp_media_description_t *dsc)
01385 {
01386   if ( (NULL == dsc) )
01387     return 0;
01388   return dsc->formats_count;
01389 }
01390 
01391 const char *
01392 fsdp_get_media_format(const fsdp_media_description_t *dsc, unsigned int index)
01393 {
01394   if ( (NULL == dsc) && (index < dsc->formats_count) )
01395     return NULL;
01396   return dsc->formats[index];
01397 }
01398 
01399 const char *
01400 fsdp_get_media_title(const fsdp_media_description_t *dsc)
01401 {
01402   if ( (NULL == dsc) )
01403     return NULL;
01404   return dsc->i_title;
01405 }
01406 
01407 fsdp_network_type_t 
01408 fsdp_get_media_network_type(const fsdp_media_description_t *dsc)
01409 {
01410   if ( (NULL == dsc) )
01411     return FSDP_NETWORK_TYPE_UNDEFINED;
01412   return dsc->c_network_type;
01413 }
01414 
01415 fsdp_address_type_t 
01416 fsdp_get_media_address_type(const fsdp_media_description_t *dsc)
01417 {
01418   if ( (NULL == dsc) )
01419     return FSDP_ADDRESS_TYPE_UNDEFINED;
01420   return dsc->c_address_type;
01421 }
01422 
01423 const char *
01424 fsdp_get_media_address(const fsdp_media_description_t *dsc)
01425 {
01426   if ( (NULL == dsc) )
01427     return NULL;
01428   return dsc->c_address.address;
01429 }
01430 
01431 unsigned int
01432 fsdp_get_media_address_ttl(const fsdp_media_description_t *mdsc)
01433 {
01434   if ( NULL == mdsc )
01435     return 0;
01436   return mdsc->c_address.address_ttl;
01437 }
01438 
01439 unsigned int
01440 fsdp_get_media_addresses_count(const fsdp_media_description_t *mdsc)
01441 {
01442   if ( NULL == mdsc)
01443     return 0;
01444   return mdsc->c_address.address_count;
01445 }
01446 
01447 fsdp_bw_modifier_type_t
01448 fsdp_get_media_bw_modifier_type(const fsdp_media_description_t *dsc, 
01449                     unsigned int index)
01450 {
01451   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) )
01452     return FSDP_BW_MOD_TYPE_UNDEFINED;
01453   return dsc->bw_modifiers[index].b_mod_type;
01454 }
01455 
01456 const char *
01457 fsdp_get_media_bw_modifier_type_unknown(const fsdp_media_description_t *dsc, 
01458                          unsigned int index)
01459 {
01460   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) ||
01461        (FSDP_BW_MOD_TYPE_UNKNOWN != dsc->bw_modifiers[index].b_mod_type) )
01462     return NULL;
01463   return dsc->bw_modifiers[index].b_unknown_bw_modt;
01464 }
01465 
01466 unsigned long int
01467 fsdp_get_media_bw_value(const fsdp_media_description_t *dsc, 
01468                unsigned int index)
01469 {
01470   if ( (NULL == dsc) || (index >= dsc->bw_modifiers_count) ) 
01471     return 0;
01472   return dsc->bw_modifiers[index].b_value;
01473 }
01474 
01475 fsdp_encryption_method_t
01476 fsdp_get_media_encryption_method(const fsdp_media_description_t *dsc)
01477 {
01478   if ( (NULL == dsc) )
01479     return FSDP_ENCRYPTION_METHOD_UNDEFINED;
01480   return dsc->k_encryption_method;
01481 }
01482 
01483 const char *
01484 fsdp_get_media_encryption_content(const fsdp_media_description_t *dsc)
01485 {
01486   if ( (NULL == dsc) )
01487     return NULL;
01488   return dsc->k_encryption_content;
01489 }
01490 
01491 unsigned int 
01492 fsdp_get_media_ptime(const fsdp_media_description_t *dsc)
01493 {
01494   if ( (NULL == dsc) )
01495     return 0;
01496   return dsc->a_ptime;
01497 }
01498 
01499 unsigned int
01500 fsdp_get_media_maxptime(const fsdp_media_description_t *dsc)
01501 {
01502   if ( (NULL == dsc) )
01503     return 0;
01504   return dsc->a_maxptime;
01505 }
01506 
01507 unsigned int
01508 fsdp_get_media_rtpmap_count(const fsdp_media_description_t *mdsc)
01509 {
01510   if ( NULL == mdsc)
01511     return 0;
01512   return mdsc->a_rtpmaps_count;
01513 }
01514 
01515 const char *
01516 fsdp_get_media_rtpmap_payload_type(const fsdp_media_description_t *mdsc,
01517                        unsigned int index)
01518 {
01519   if ( (NULL == mdsc) || (index >= mdsc->a_rtpmaps_count) )
01520     return NULL;
01521   return mdsc->a_rtpmaps[index]->pt;
01522 }
01523 
01524 const char *
01525 fsdp_get_media_rtpmap_encoding_name(const fsdp_media_description_t *mdsc,
01526                         unsigned int index)
01527 {
01528   if ( (NULL == mdsc) || (index >= mdsc->a_rtpmaps_count) )
01529     return NULL;
01530   return mdsc->a_rtpmaps[index]->encoding_name;
01531 }
01532 
01533 unsigned int
01534 fsdp_get_media_rtpmap_clock_rate(const fsdp_media_description_t *mdsc,
01535                      unsigned int index)
01536 {
01537   if ( (NULL == mdsc) || (index >= mdsc->a_rtpmaps_count) )
01538     return 0;
01539   return mdsc->a_rtpmaps[index]->clock_rate;
01540 }
01541 
01542 const char *
01543 fsdp_get_media_rtpmap_encoding_parameters(const fsdp_description_t *mdsc, 
01544                            unsigned int index)
01545 {
01546   if ( (NULL == mdsc) || (index >= mdsc->a_rtpmaps_count) )
01547     return NULL;
01548   return mdsc->a_rtpmaps[index]->parameters;
01549 }
01550 
01551 unsigned int
01552 fsdp_get_media_sdplang_count(const fsdp_media_description_t *mdsc)
01553 {
01554   if ( NULL == mdsc )
01555     return 0;
01556   return mdsc->a_sdplangs_count;
01557 }
01558 
01559 const char *
01560 fsdp_get_media_sdplang(const fsdp_media_description_t *mdsc, 
01561                  unsigned int index)
01562 {
01563   if ( (NULL == mdsc) || (index >= mdsc->a_sdplangs_count) )
01564     return NULL;
01565   return mdsc->a_sdplangs[index];
01566 }
01567 
01568 unsigned int
01569 fsdp_get_media_lang_count(const fsdp_media_description_t *mdsc)
01570 {
01571   if ( NULL == mdsc )
01572     return 0;
01573   return mdsc->a_langs_count;
01574 }
01575 
01576 const char *
01577 fsdp_get_media_lang(const fsdp_media_description_t *mdsc, 
01578                  unsigned int index)
01579 {
01580   if ( (NULL == mdsc) || (index >= mdsc->a_langs_count) )
01581     return NULL;
01582   return mdsc->a_langs[index];
01583 }
01584 
01585 unsigned int
01586 fsdp_get_media_fmtp_count(const fsdp_media_description_t *mdsc)
01587 {
01588   if ( NULL == mdsc )
01589     return 0;
01590   return mdsc->a_fmtps_count;
01591 }
01592 
01593 const char *
01594 fsdp_get_media_fmtp(const fsdp_media_description_t *mdsc, unsigned int index)
01595 {
01596   if ( (NULL == mdsc) || (index >= mdsc->a_fmtps_count) )
01597     return NULL;
01598   return mdsc->a_fmtps[index];
01599 }
01600 
01601 fsdp_orient_t
01602 fsdp_get_media_orient(const fsdp_media_description_t *dsc)
01603 {
01604   if ( (NULL == dsc) )
01605     return FSDP_ORIENT_UNDEFINED;
01606   return dsc->a_orient;
01607 }
01608 
01609 fsdp_sendrecv_mode_t
01610 fsdp_get_media_sendrecv(const fsdp_media_description_t *dsc)
01611 {
01612   if ( (NULL == dsc) )
01613     return FSDP_SENDRECV_UNDEFINED;
01614   return dsc->a_sendrecv_mode;
01615 }
01616 
01617 float
01618 fsdp_get_media_framerate(const fsdp_media_description_t *dsc)
01619 {
01620   if ( (NULL == dsc) )
01621     return 0;
01622   return dsc->a_framerate;
01623 }
01624 
01625 unsigned int
01626 fsdp_get_media_quality(const fsdp_media_description_t *dsc)
01627 {
01628   if ( (NULL == dsc) )
01629     return 0;
01630   return dsc->a_quality;
01631 }
01632 
01633 unsigned int
01634 fsdp_get_media_rtcp_port(const fsdp_media_description_t *dsc)
01635 {
01636   if ( (NULL == dsc) )
01637     return 0;
01638   return dsc->a_rtcp_port;
01639 }
01640 
01641 fsdp_network_type_t
01642 fsdp_get_media_rtcp_network_type(const fsdp_media_description_t *dsc)
01643 {
01644   if ( (NULL == dsc) )
01645     return FSDP_NETWORK_TYPE_UNDEFINED;
01646   return dsc->a_rtcp_network_type;
01647 }
01648 
01649 fsdp_address_type_t
01650 fsdp_get_media_rtcp_address_type(const fsdp_media_description_t *dsc)
01651 {
01652   if ( (NULL == dsc) )
01653     return FSDP_ADDRESS_TYPE_UNDEFINED;
01654   return dsc->a_rtcp_address_type;
01655 }
01656 
01657 const char*
01658 fsdp_get_media_rtcp_address(const fsdp_media_description_t *dsc)
01659 {
01660   if ( (NULL == dsc) )
01661     return NULL;
01662   return dsc->a_rtcp_address;
01663 }
01664 
01665 unsigned int
01666 fsdp_get_media_unidentified_attributes_count(const fsdp_media_description_t
01667                              *mdsc)
01668 {
01669   if ( NULL == mdsc )
01670     return 0;
01671   return mdsc->unidentified_attributes_count;
01672 }
01673 
01674 const char *
01675 fsdp_get_media_unidentified_attribute(const fsdp_media_description_t *mdsc,
01676                           unsigned int index)
01677 {
01678   if ( NULL == mdsc || (index < mdsc->unidentified_attributes_count) )
01679     return NULL;
01680   return mdsc->unidentified_attributes[index];
01681 }

Generated on Wed May 3 13:49:06 2006 for FreeSDP by  doxygen 1.4.6