Changeset 129


Ignore:
Timestamp:
Feb 2, 2006 7:16:07 PM (19 years ago)
Author:
bennylp
Message:

Added SDP negotiator and changed SDP structs (tested)

Location:
pjproject/trunk/pjmedia
Files:
9 added
7 edited
1 copied

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/build/pjmedia.dsp

    r121 r129  
    9797# Begin Source File 
    9898 
     99SOURCE=..\src\pjmedia\errno.c 
     100# End Source File 
     101# Begin Source File 
     102 
    99103SOURCE=..\src\pjmedia\g711.c 
    100104# End Source File 
     
    130134# Begin Source File 
    131135 
     136SOURCE=..\src\pjmedia\sdp_cmp.c 
     137# End Source File 
     138# Begin Source File 
     139 
     140SOURCE=..\src\pjmedia\sdp_neg.c 
     141# End Source File 
     142# Begin Source File 
     143 
    132144SOURCE=..\src\pjmedia\session.c 
     145 
     146!IF  "$(CFG)" == "pjmedia - Win32 Release" 
     147 
     148!ELSEIF  "$(CFG)" == "pjmedia - Win32 Debug" 
     149 
     150# PROP Exclude_From_Build 1 
     151 
     152!ENDIF  
     153 
    133154# End Source File 
    134155# Begin Source File 
     
    150171# Begin Source File 
    151172 
     173SOURCE=..\include\pjmedia\errno.h 
     174# End Source File 
     175# Begin Source File 
     176 
    152177SOURCE=..\include\pjmedia\jbuf.h 
    153178# End Source File 
     
    174199# Begin Source File 
    175200 
     201SOURCE=..\include\pjmedia\sdp_neg.h 
     202# End Source File 
     203# Begin Source File 
     204 
    176205SOURCE=..\include\pjmedia\session.h 
    177206# End Source File 
     
    183212 
    184213SOURCE=..\include\pjmedia\stream.h 
     214# End Source File 
     215# Begin Source File 
     216 
     217SOURCE=..\include\pjmedia\types.h 
    185218# End Source File 
    186219# End Group 
  • pjproject/trunk/pjmedia/build/pjmedia.dsw

    r121 r129  
    7878    Project_Dep_Name pjsdp 
    7979    End Project Dependency 
     80    Begin Project Dependency 
     81    Project_Dep_Name pjlib_util 
     82    End Project Dependency 
    8083}}} 
    8184 
  • pjproject/trunk/pjmedia/build/pjmedia_test.dsp

    r65 r129  
    4343# PROP Target_Dir "" 
    4444# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 
    45 # ADD CPP /nologo /MD /W3 /GX /O2 /I "../../pjlib/src" /I "../src" /I "../../pjsdp/src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 
     45# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../pjlib/include" /I "../include" /D "NDEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 
    4646# ADD BASE RSC /l 0x409 /d "NDEBUG" 
    4747# ADD RSC /l 0x409 /d "NDEBUG" 
     
    6767# PROP Target_Dir "" 
    6868# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 
    69 # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../pjlib/src" /I "../src" /I "../../pjsdp/src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c 
     69# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../pjlib/include" /I "../include" /D "_DEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c 
    7070# ADD BASE RSC /l 0x409 /d "_DEBUG" 
    7171# ADD RSC /l 0x409 /d "_DEBUG" 
     
    100100# Begin Source File 
    101101 
     102SOURCE=..\src\test\sdp_neg_test.c 
     103# End Source File 
     104# Begin Source File 
     105 
    102106SOURCE=..\src\test\sdptest.c 
     107 
     108!IF  "$(CFG)" == "pjmedia_test - Win32 Release" 
     109 
     110!ELSEIF  "$(CFG)" == "pjmedia_test - Win32 Debug" 
     111 
     112# PROP Exclude_From_Build 1 
     113 
     114!ENDIF  
     115 
    103116# End Source File 
    104117# Begin Source File 
    105118 
    106119SOURCE=..\src\test\session_test.c 
     120 
     121!IF  "$(CFG)" == "pjmedia_test - Win32 Release" 
     122 
     123!ELSEIF  "$(CFG)" == "pjmedia_test - Win32 Debug" 
     124 
     125# PROP Exclude_From_Build 1 
     126 
     127!ENDIF  
     128 
     129# End Source File 
     130# Begin Source File 
     131 
     132SOURCE=..\src\test\test.c 
    107133# End Source File 
    108134# End Group 
     
    110136 
    111137# PROP Default_Filter "h;hpp;hxx;hm;inl" 
     138# Begin Source File 
     139 
     140SOURCE=..\src\test\test.h 
     141# End Source File 
    112142# End Group 
    113143# Begin Group "Resource Files" 
  • pjproject/trunk/pjmedia/include/pjmedia.h

    r121 r129  
    2020#define __PJMEDIA_H__ 
    2121 
     22#include <pjmedia/types.h> 
     23#include <pjmedia/errno.h> 
    2224#include <pjmedia/codec.h> 
    2325#include <pjmedia/jbuf.h> 
     
    2527#include <pjmedia/rtcp.h> 
    2628#include <pjmedia/rtp.h> 
    27 #include <pjmedia/session.h> 
     29//#include <pjmedia/session.h> 
    2830#include <pjmedia/sound.h> 
    2931#include <pjmedia/sdp.h> 
     32#include <pjmedia/sdp_neg.h> 
    3033 
    3134#endif  /* __PJMEDIA_H__ */ 
  • pjproject/trunk/pjmedia/include/pjmedia/sdp.h

    r121 r129  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
    19 #ifndef __PJSDP_SDP_H__ 
    20 #define __PJSDP_SDP_H__ 
     19#ifndef __PJMEDIA_SDP_H__ 
     20#define __PJMEDIA_SDP_H__ 
    2121 
    2222/** 
     
    3636 */ 
    3737 
    38 #include <pj/types.h> 
     38#include <pjmedia/types.h> 
    3939 
    4040PJ_BEGIN_DECL 
     
    4444#define PJSDP_MAX_MEDIA 16 
    4545 
    46 /** 
    47  * This enumeration describes the attribute type. 
    48  */ 
    49 typedef enum pjsdp_attr_type_e 
    50 { 
    51     PJSDP_ATTR_RTPMAP, 
    52     PJSDP_ATTR_CAT, 
    53     PJSDP_ATTR_KEYWORDS, 
    54     PJSDP_ATTR_TOOL, 
    55     PJSDP_ATTR_PTIME, 
    56     PJSDP_ATTR_RECV_ONLY, 
    57     PJSDP_ATTR_SEND_ONLY, 
    58     PJSDP_ATTR_SEND_RECV, 
    59     PJSDP_ATTR_ORIENT, 
    60     PJSDP_ATTR_TYPE, 
    61     PJSDP_ATTR_CHARSET, 
    62     PJSDP_ATTR_SDP_LANG, 
    63     PJSDP_ATTR_LANG, 
    64     PJSDP_ATTR_FRAME_RATE, 
    65     PJSDP_ATTR_QUALITY, 
    66     PJSDP_ATTR_FMTP, 
    67     PJSDP_ATTR_INACTIVE, 
    68     PJSDP_ATTR_GENERIC, 
    69     PJSDP_END_OF_ATTR, 
    70 } pjsdp_attr_type_e; 
    71  
    72  
    73 /** 
    74  * This structure keeps the common attributes that all 'descendants'  
    75  * will have. 
    76  */ 
    77 typedef struct pjsdp_attr 
    78 { 
    79     pjsdp_attr_type_e   type;   /**< Attribute type. */ 
    80 } pjsdp_attr; 
    81  
    82  
    83 /** 
    84  * This is the structure to represent generic attribute which has a  
    85  * string value. 
    86  */ 
    87 typedef struct pjsdp_attr_string 
    88 { 
    89     pjsdp_attr_type_e   type; 
    90     pj_str_t            value; 
    91 } pjsdp_attr_string; 
    92  
    93  
    94 /** 
    95  * This is the structure to represent generic SDP attribute which has 
    96  * a numeric value. 
    97  */ 
    98 typedef struct pjsdp_attr_num 
    99 { 
    100     pjsdp_attr_type_e   type; 
    101     pj_uint32_t         value; 
    102 } pjsdp_attr_num; 
     46 
     47/**************************************************************************** 
     48 * SDP ATTRIBUTES 
     49 **************************************************************************** 
     50 */ 
     51 
     52/**  
     53 * SDP generic attribute. 
     54 */ 
     55struct pjmedia_sdp_attr 
     56{ 
     57    pj_str_t            name;       /**< Attribute name.    */ 
     58    pj_str_t            value;      /**< Attribute value.   */ 
     59}; 
     60 
     61 
     62/** 
     63 * Create SDP attribute. 
     64 * 
     65 * @param pool          Pool to create the attribute. 
     66 * @param name          Attribute name. 
     67 * @param value         Optional attribute value. 
     68 * 
     69 * @return              The new SDP attribute. 
     70 */ 
     71PJ_DECL(pjmedia_sdp_attr*) pjmedia_sdp_attr_create(pj_pool_t *pool, 
     72                                                   const char *name, 
     73                                                   const pj_str_t *value); 
     74 
     75/**  
     76 * Clone attribute  
     77 * 
     78 * @param pool          Pool to be used. 
     79 * @param attr          The attribute to clone. 
     80 * 
     81 * @return              New attribute as cloned from the attribute. 
     82 */ 
     83PJ_DECL(pjmedia_sdp_attr*) pjmedia_sdp_attr_clone(pj_pool_t *pool,  
     84                                                  const pjmedia_sdp_attr*attr); 
     85 
     86/**  
     87 * Find the first attribute with the specified type. 
     88 * 
     89 * @param count         Number of attributes in the array. 
     90 * @param attr_array    Array of attributes. 
     91 * @param name          Attribute name to find. 
     92 * @param fmt           Optional string to indicate which payload format 
     93 *                      to find for rtpmap and fmt attributes. 
     94 * 
     95 * @return              The specified attribute, or NULL if it can't be found. 
     96 * 
     97 * @see pjmedia_sdp_attr_find2, pjmedia_sdp_media_find_attr 
     98 */ 
     99PJ_DECL(pjmedia_sdp_attr*)  
     100pjmedia_sdp_attr_find(unsigned count,  
     101                      const pjmedia_sdp_attr *const attr_array[], 
     102                      const pj_str_t *name, const pj_str_t *fmt); 
     103 
     104/**  
     105 * Find the first attribute with the specified type. 
     106 * 
     107 * @param count         Number of attributes in the array. 
     108 * @param attr_array    Array of attributes. 
     109 * @param name          Attribute name to find. 
     110 * @param fmt           Optional string to indicate which payload format 
     111 *                      to find for rtpmap and fmt attributes. 
     112 * 
     113 * @return              The specified attribute, or NULL if it can't be found. 
     114 * 
     115 * @see pjmedia_sdp_attr_find, pjmedia_sdp_media_find_attr2 
     116 */ 
     117PJ_DECL(pjmedia_sdp_attr*)  
     118pjmedia_sdp_attr_find2(unsigned count,  
     119                       const pjmedia_sdp_attr *const attr_array[], 
     120                       const char *name, const pj_str_t *fmt); 
     121 
     122/** 
     123 * Add a new attribute to array of attributes. 
     124 * 
     125 * @param count         Number of attributes in the array. 
     126 * @param attr_array    Array of attributes. 
     127 * @param attr          The attribute to add. 
     128 * 
     129 * @return              PJ_SUCCESS or the error code. 
     130 * 
     131 * @see pjmedia_sdp_media_add_attr 
     132 */ 
     133PJ_DECL(pj_status_t) pjmedia_sdp_attr_add(unsigned *count, 
     134                                          pjmedia_sdp_attr *attr_array[], 
     135                                          pjmedia_sdp_attr *attr); 
     136 
     137/** 
     138 * Remove all attributes with the specified name when they present. 
     139 * 
     140 * @param count         Number of attributes in the array. 
     141 * @param attr_array    Array of attributes. 
     142 * @param name          Attribute name to find. 
     143 * 
     144 * @return              Number of attributes removed. 
     145 * 
     146 * @see pjmedia_sdp_media_remove_all_attr 
     147 */ 
     148PJ_DECL(unsigned) pjmedia_sdp_attr_remove_all(unsigned *count, 
     149                                              pjmedia_sdp_attr *attr_array[], 
     150                                              const char *name); 
     151 
     152 
     153/** 
     154 * Remove the specified attribute from the attribute array. 
     155 * 
     156 * @param count         Number of attributes in the array. 
     157 * @param attr_array    Array of attributes. 
     158 * @param name          Attribute name to find. 
     159 * 
     160 * @return              PJ_SUCCESS when attribute has been removed, or  
     161 *                      PJ_ENOTFOUND when the attribute can not be found. 
     162 * 
     163 * @see pjmedia_sdp_media_remove_attr 
     164 */ 
     165PJ_DECL(pj_status_t) pjmedia_sdp_attr_remove(unsigned *count, 
     166                                             pjmedia_sdp_attr *attr_array[], 
     167                                             pjmedia_sdp_attr *attr); 
    103168 
    104169 
     
    106171 * SDP \a rtpmap attribute. 
    107172 */ 
    108 typedef struct pjsdp_rtpmap_attr 
    109 { 
    110     pjsdp_attr_type_e   type; 
    111     unsigned            payload_type; 
    112     pj_str_t            encoding_name; 
    113     unsigned            clock_rate; 
    114     pj_str_t            parameter; 
    115 } pjsdp_rtpmap_attr; 
     173struct pjmedia_sdp_rtpmap 
     174{ 
     175    pj_str_t            pt;         /**< Payload type.      */ 
     176    pj_str_t            enc_name;   /**< Encoding name.     */ 
     177    unsigned            clock_rate; /**< Clock rate.        */ 
     178    pj_str_t            param;      /**< Parameter.         */ 
     179}; 
     180 
     181 
     182/** 
     183 * Convert generic attribute to SDP rtpmap. 
     184 * 
     185 * @param pool          Pool used to create the rtpmap attribute. 
     186 * @param attr          Generic attribute to be converted to rtpmap, which 
     187 *                      name must be "rtpmap". 
     188 * @param p_rtpmap      Pointer to receive SDP rtpmap attribute. 
     189 * 
     190 * @return              PJ_SUCCESS on success. 
     191 */ 
     192PJ_DECL(pj_status_t) pjmedia_sdp_attr_to_rtpmap(pj_pool_t *pool, 
     193                                                const pjmedia_sdp_attr *attr, 
     194                                                pjmedia_sdp_rtpmap **p_rtpmap); 
     195 
     196 
     197/** 
     198 * Get the rtpmap representation of the same SDP attribute. 
     199 * 
     200 * @param attr          Generic attribute to be converted to rtpmap, which 
     201 *                      name must be "rtpmap". 
     202 * @param rtpmap        SDP rtpmap attribute to be initialized. 
     203 * 
     204 * @return              PJ_SUCCESS on success. 
     205 */ 
     206PJ_DECL(pj_status_t) pjmedia_sdp_attr_get_rtpmap(const pjmedia_sdp_attr *attr, 
     207                                                 pjmedia_sdp_rtpmap *rtpmap); 
     208 
     209 
     210/** 
     211 * Convert rtpmap attribute to generic attribute. 
     212 * 
     213 * @param pool          Pool to be used. 
     214 * @param rtpmap        The rtpmap attribute. 
     215 * @param p_attr        Pointer to receive the generic SDP attribute. 
     216 * 
     217 * @return              PJ_SUCCESS on success. 
     218 */ 
     219PJ_DECL(pj_status_t) pjmedia_sdp_rtpmap_to_attr(pj_pool_t *pool, 
     220                                                const pjmedia_sdp_rtpmap *rtpmap, 
     221                                                pjmedia_sdp_attr **p_attr); 
    116222 
    117223 
     
    119225 * SDP \a fmtp attribute. 
    120226 */ 
    121 typedef struct pjsdp_fmtp_attr 
    122 { 
    123     pjsdp_attr_type_e   type; 
    124     pj_str_t            format; 
    125     pj_str_t            param; 
    126 } pjsdp_fmtp_attr; 
    127  
    128  
    129 /**  
    130  * SDP generic attribute. 
    131  */ 
    132 typedef struct pjsdp_generic_attr 
    133 { 
    134     pjsdp_attr_type_e   type; 
    135     pj_str_t            name; 
    136     pj_str_t            value; 
    137 } pjsdp_generic_attr; 
    138  
    139  
    140 /** SDP \a cat attribute. */ 
    141 typedef struct pjsdp_attr_string pjsdp_cat_attr; 
    142  
    143 /** SDP \a keywds attribute. */ 
    144 typedef struct pjsdp_attr_string pjsdp_keywds_attr; 
    145  
    146 /** SDP \a tool attribute. */ 
    147 typedef struct pjsdp_attr_string pjsdp_tool_attr; 
    148  
    149 /** SDP \a ptime attribute. */ 
    150 typedef struct pjsdp_attr_num pjsdp_ptime_attr; 
    151  
    152 /** SDP \a recvonly attribute. */ 
    153 typedef struct pjsdp_attr pjsdp_recv_only_attr; 
    154  
    155 /** SDP \a sendonly attribute. */ 
    156 typedef struct pjsdp_attr pjsdp_send_only_attr; 
    157  
    158 /** SDP \a sendrecv attribute. */ 
    159 typedef struct pjsdp_attr pjsdp_send_recv_attr; 
    160  
    161 /** SDP \a orient attribute. */ 
    162 typedef struct pjsdp_attr_string pjsdp_orient_attr; 
    163  
    164 /** SDP \a type attribute. */ 
    165 typedef struct pjsdp_attr_string pjsdp_type_attr; 
    166  
    167 /** SDP \a charset attribute. */ 
    168 typedef struct pjsdp_attr_string pjsdp_charset_attr; 
    169  
    170 /** SDP \a sdplang attribute. */ 
    171 typedef struct pjsdp_attr_string pjsdp_sdp_lang_attr; 
    172  
    173 /** SDP \a lang attribute. */ 
    174 typedef struct pjsdp_attr_string pjsdp_lang_attr; 
    175  
    176 /** SDP \a framerate attribute. */ 
    177 typedef struct pjsdp_attr_string pjsdp_frame_rate_attr; 
    178  
    179 /** SDP \a quality attribute. */ 
    180 typedef struct pjsdp_attr_num pjsdp_quality_attr; 
    181  
    182 /** SDP \a inactive attribute. */ 
    183 typedef struct pjsdp_attr pjsdp_inactive_attr; 
    184  
    185 /** Clone attribute */ 
    186 PJ_DECL(pjsdp_attr*) pjsdp_attr_clone (pj_pool_t *pool, const pjsdp_attr *rhs); 
    187  
    188 /** Find attribute */ 
    189 PJ_DECL(const pjsdp_attr*) pjsdp_attr_find (int count, const pjsdp_attr *attr_array[], int type); 
     227struct pjmedia_sdp_fmtp 
     228{ 
     229    pj_str_t            fmt;        /**< Format type.               */ 
     230    pj_str_t            fmt_param;  /**< Format specific parameter. */ 
     231}; 
     232 
     233 
     234/** 
     235 * Get the fmtp representation of the same SDP attribute. 
     236 * 
     237 * @param attr          Generic attribute to be converted to fmtp, which 
     238 *                      name must be "fmtp". 
     239 * @param fmtp          SDP fmtp attribute to be initialized. 
     240 * 
     241 * @return              PJ_SUCCESS on success. 
     242 */ 
     243PJ_DECL(pj_status_t) pjmedia_sdp_attr_get_fmtp(const pjmedia_sdp_attr *attr, 
     244                                               pjmedia_sdp_fmtp *fmtp); 
     245 
     246 
     247/**************************************************************************** 
     248 * SDP CONNECTION INFO 
     249 **************************************************************************** 
     250 */ 
    190251 
    191252/** 
    192253 * SDP connection info. 
    193254 */ 
    194 typedef struct pjsdp_conn_info 
    195 { 
    196     pj_str_t    net_type; 
    197     pj_str_t    addr_type; 
    198     pj_str_t    addr; 
    199 } pjsdp_conn_info; 
     255struct pjmedia_sdp_conn 
     256{ 
     257    pj_str_t    net_type;       /**< Network type ("IN").               */ 
     258    pj_str_t    addr_type;      /**< Address type ("IP4", "IP6").       */ 
     259    pj_str_t    addr;           /**< The address.                       */ 
     260}; 
     261 
    200262 
    201263/**  
     
    207269 * @return the new connection info. 
    208270 */ 
    209 PJ_DECL(pjsdp_conn_info*) pjsdp_conn_info_clone (pj_pool_t *pool,  
    210                                                  const pjsdp_conn_info *rhs); 
     271PJ_DECL(pjmedia_sdp_conn*) pjmedia_sdp_conn_clone(pj_pool_t *pool,  
     272                                                  const pjmedia_sdp_conn *rhs); 
     273 
     274 
     275 
     276/**************************************************************************** 
     277 * SDP MEDIA INFO/LINE 
     278 **************************************************************************** 
     279 */ 
    211280 
    212281/** 
    213282 * SDP media description. 
    214283 */ 
    215 typedef struct pjsdp_media_desc 
     284struct pjmedia_sdp_media 
    216285{ 
    217286    struct 
    218287    { 
    219         pj_str_t    media; 
    220         pj_uint16_t port; 
    221         unsigned    port_count; 
    222         pj_str_t    transport; 
    223         unsigned    fmt_count; 
    224         pj_str_t    fmt[PJSDP_MAX_FMT]; 
     288        pj_str_t    media;              /**< Media type ("audio", "video")  */ 
     289        pj_uint16_t port;               /**< Port number.                   */ 
     290        unsigned    port_count;         /**< Port count, used only when >2  */ 
     291        pj_str_t    transport;          /**< Transport ("RTP/AVP")          */ 
     292        unsigned    fmt_count;          /**< Number of formats.             */ 
     293        pj_str_t    fmt[PJSDP_MAX_FMT]; /**< Media formats.                 */ 
    225294    } desc; 
    226295 
    227     pjsdp_conn_info *conn; 
    228     unsigned        attr_count; 
    229     pjsdp_attr     *attr[PJSDP_MAX_ATTR]; 
    230  
    231 } pjsdp_media_desc; 
     296    pjmedia_sdp_conn *conn;             /**< Optional connection info.      */ 
     297    unsigned         attr_count;        /**< Number of attributes.          */ 
     298    pjmedia_sdp_attr*attr[PJSDP_MAX_ATTR];  /**< Attributes.                */ 
     299 
     300}; 
     301 
    232302 
    233303/**  
     
    239309 * @return a new media description. 
    240310 */ 
    241 PJ_DECL(pjsdp_media_desc*) pjsdp_media_desc_clone (pj_pool_t *pool,  
    242                                                    const pjsdp_media_desc *rhs); 
    243  
    244 /**  
    245  * Check if the media description has the specified attribute. 
     311PJ_DECL(pjmedia_sdp_media*)  
     312pjmedia_sdp_media_clone( pj_pool_t *pool,  
     313                         const pjmedia_sdp_media *rhs); 
     314 
     315/** 
     316 * Find the first occurence of the specified attribute name. 
    246317 * 
    247318 * @param m             The SDP media description. 
    248  * @param attr_type     The attribute type. 
    249  * 
    250  * @return nonzero if true. 
    251  */ 
    252 PJ_DECL(pj_bool_t) pjsdp_media_desc_has_attr (const pjsdp_media_desc *m,  
    253                                               pjsdp_attr_type_e attr_type); 
    254  
    255 /**  
    256  * Find rtpmap attribute for the specified payload type.  
    257  * 
    258  * @param m         The SDP media description. 
    259  * @param pt        RTP payload type. 
    260  * 
    261  * @return the SDP rtpmap attribute for the payload type, or NULL if not found. 
    262  */ 
    263 PJ_DECL(const pjsdp_rtpmap_attr*)  
    264 pjsdp_media_desc_find_rtpmap (const pjsdp_media_desc *m, unsigned pt); 
     319 * @param name          Attribute name to find. 
     320 * @param fmt           Optional payload format type to find in the 
     321 *                      attribute list. The payload format type will be 
     322 *                      compared for attributes such as rtpmap and fmtp. 
     323 * 
     324 * @return              The first instance of the specified attribute or NULL. 
     325 */ 
     326PJ_DECL(pjmedia_sdp_attr*)  
     327pjmedia_sdp_media_find_attr(const pjmedia_sdp_media *m, 
     328                            const pj_str_t *name, const pj_str_t *fmt); 
     329 
     330 
     331/** 
     332 * Find the first occurence of the specified attribute name. 
     333 * 
     334 * @param m             The SDP media description. 
     335 * @param name          Attribute name to find. 
     336 * @param fmt           Optional payload format type to find in the 
     337 *                      attribute list. The payload format type will be 
     338 *                      compared for attributes such as rtpmap and fmtp. 
     339 * 
     340 * @return              The first instance of the specified attribute or NULL. 
     341 */ 
     342PJ_DECL(pjmedia_sdp_attr*)  
     343pjmedia_sdp_media_find_attr2(const pjmedia_sdp_media *m, 
     344                             const char *name, const pj_str_t *fmt); 
     345 
     346/** 
     347 * Add new attribute to the media descriptor. 
     348 * 
     349 * @param m             The SDP media description. 
     350 * @param name          Attribute to add. 
     351 * 
     352 * @return              PJ_SUCCESS or the appropriate error code. 
     353 */ 
     354PJ_DECL(pj_status_t) pjmedia_sdp_media_add_attr(pjmedia_sdp_media *m, 
     355                                                pjmedia_sdp_attr *attr); 
     356 
     357/** 
     358 * Remove all attributes with the specified name. 
     359 * 
     360 * @param m             The SDP media description. 
     361 * @param name          Attribute name to remove. 
     362 * 
     363 * @return              The number of attributes removed. 
     364 */ 
     365PJ_DECL(unsigned)  
     366pjmedia_sdp_media_remove_all_attr(pjmedia_sdp_media *m, 
     367                                  const char *name); 
     368 
     369 
     370/** 
     371 * Remove the occurence of the specified attribute. 
     372 */ 
     373PJ_DECL(pj_status_t) 
     374pjmedia_sdp_media_remove_attr(pjmedia_sdp_media *m, 
     375                              pjmedia_sdp_attr *attr); 
     376 
     377 
     378/** 
     379 * Compare two SDP media for equality. 
     380 * 
     381 * @param sd1       The first SDP media to compare. 
     382 * @param sd2       The second SDP media to compare. 
     383 * @param option    Comparison option. 
     384 * 
     385 * @return          PJ_SUCCESS when both SDP medias are equal. 
     386 */ 
     387PJ_DECL(pj_status_t) pjmedia_sdp_media_cmp(const pjmedia_sdp_media *sd1, 
     388                                           const pjmedia_sdp_media *sd2, 
     389                                           unsigned option); 
     390 
     391 
     392 
     393/**************************************************************************** 
     394 * SDP SESSION DESCRIPTION 
     395 **************************************************************************** 
     396 */ 
    265397 
    266398 
     
    268400 * This structure describes SDP session description. 
    269401 */ 
    270 typedef struct pjsdp_session_desc 
    271 { 
     402struct pjmedia_sdp_session 
     403{ 
     404    /** Origin (o= line) */ 
    272405    struct 
    273406    { 
    274         pj_str_t    user; 
    275         pj_uint32_t id; 
    276         pj_uint32_t version; 
    277         pj_str_t    net_type; 
    278         pj_str_t    addr_type; 
    279         pj_str_t    addr; 
     407        pj_str_t    user;           /**< User                           */ 
     408        pj_uint32_t id;             /**< Session ID                     */ 
     409        pj_uint32_t version;        /**< Session version                */ 
     410        pj_str_t    net_type;       /**< Network type ("IN")            */ 
     411        pj_str_t    addr_type;      /**< Address type ("IP4", "IP6")    */ 
     412        pj_str_t    addr;           /**< The address.                   */ 
    280413    } origin; 
    281414 
    282     pj_str_t         name; 
    283     pjsdp_conn_info *conn; 
     415    pj_str_t         name;          /**< Subject line (s=)              */ 
     416    pjmedia_sdp_conn *conn;         /**< Connection line (c=)           */ 
    284417     
     418    /** Session time (t= line)  */ 
    285419    struct 
    286420    { 
    287         pj_uint32_t start; 
    288         pj_uint32_t stop; 
     421        pj_uint32_t start;          /**< Start time.                    */ 
     422        pj_uint32_t stop;           /**< Stop time.                     */ 
    289423    } time; 
    290424 
    291     unsigned        attr_count; 
    292     pjsdp_attr     *attr[PJSDP_MAX_ATTR]; 
    293  
    294     unsigned          media_count; 
    295     pjsdp_media_desc *media[PJSDP_MAX_MEDIA]; 
    296  
    297 } pjsdp_session_desc; 
     425    unsigned           attr_count;              /**< Number of attributes.  */ 
     426    pjmedia_sdp_attr  *attr[PJSDP_MAX_ATTR];    /**< Attributes array.      */ 
     427 
     428    unsigned           media_count;             /**< Number of media.       */ 
     429    pjmedia_sdp_media *media[PJSDP_MAX_MEDIA];  /**< Media array.           */ 
     430 
     431}; 
    298432 
    299433 
     
    307441 * @return SDP session description. 
    308442 */ 
    309 PJ_DECL(pjsdp_session_desc*) pjsdp_parse( char *buf, pj_size_t len,  
    310                                           pj_pool_t *pool); 
     443PJ_DECL(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool, 
     444                                        char *buf, pj_size_t len,  
     445                                        pjmedia_sdp_session **p_sdp ); 
    311446 
    312447/** 
     
    319454 * @return the length printed, or -1. 
    320455 */ 
    321 PJ_DECL(int) pjsdp_print( const pjsdp_session_desc *desc,  
    322                           char *buf, pj_size_t size); 
    323  
     456PJ_DECL(int) pjmedia_sdp_print( const pjmedia_sdp_session *desc,  
     457                                char *buf, pj_size_t size); 
     458 
     459 
     460/** 
     461 * Validate SDP descriptor. 
     462 */ 
     463PJ_DECL(pj_status_t) pjmedia_sdp_validate(const pjmedia_sdp_session *sdp); 
     464 
     465 
     466/** 
     467 * Clone SDP session. 
     468 * 
     469 * @param pool      The pool used to clone the session. 
     470 * @param sess      The SDP session to clone. 
     471 * 
     472 * @return          New SDP session. 
     473 */ 
     474PJ_DECL(pjmedia_sdp_session*)  
     475pjmedia_sdp_session_clone( pj_pool_t *pool, 
     476                           const pjmedia_sdp_session *sess); 
     477 
     478 
     479/** 
     480 * Compare two SDP session for equality. 
     481 * 
     482 * @param sd1       The first SDP session to compare. 
     483 * @param sd2       The second SDP session to compare. 
     484 * 
     485 * @return          PJ_SUCCESS when both SDPs are equal. 
     486 */ 
     487PJ_DECL(pj_status_t) pjmedia_sdp_session_cmp(const pjmedia_sdp_session *sd1, 
     488                                             const pjmedia_sdp_session *sd2, 
     489                                             unsigned option); 
     490 
     491 
     492PJ_END_DECL 
    324493 
    325494/** 
     
    327496 */ 
    328497 
    329 PJ_END_DECL 
    330  
    331 #endif  /* __PJSDP_SDP_H__ */ 
    332  
     498#endif  /* __PJMEDIA_SDP_H__ */ 
     499 
  • pjproject/trunk/pjmedia/src/pjmedia/jbuf.c

    r121 r129  
    301301    } 
    302302 
    303     if (jb->lst.count > jb->max_level) 
     303    if ((int)jb->lst.count > jb->max_level) 
    304304        jb->max_level++; 
    305305 
  • pjproject/trunk/pjmedia/src/pjmedia/sdp.c

    r121 r129  
    1818 */ 
    1919#include <pjmedia/sdp.h> 
     20#include <pjmedia/errno.h> 
    2021#include <pjlib-util/scanner.h> 
     22#include <pj/array.h> 
    2123#include <pj/except.h> 
    2224#include <pj/log.h> 
     
    2527#include <pj/pool.h> 
    2628#include <pj/assert.h> 
     29#include <pj/ctype.h> 
     30 
    2731 
    2832enum { 
     
    3236#define TOKEN           "-.!%*_=`'~" 
    3337#define NTP_OFFSET      ((pj_uint32_t)2208988800) 
    34 #define LOG_THIS        "sdp" 
     38#define THIS_FILE       "sdp.c" 
     39 
     40typedef struct parse_context 
     41{  
     42    pj_status_t last_error; 
     43} parse_context; 
     44 
    3545 
    3646/* 
    3747 * Prototypes for line parser. 
    3848 */ 
    39 static void parse_version(pj_scanner *scanner); 
    40 static void parse_origin(pj_scanner *scanner, pjsdp_session_desc *ses); 
    41 static void parse_time(pj_scanner *scanner, pjsdp_session_desc *ses); 
    42 static void parse_generic_line(pj_scanner *scanner, pj_str_t *str); 
    43 static void parse_connection_info(pj_scanner *scanner, pjsdp_conn_info *conn); 
    44 static pjsdp_attr *parse_attr(pj_pool_t *pool, pj_scanner *scanner); 
    45 static void parse_media(pj_scanner *scanner, pjsdp_media_desc *med); 
    46  
    47 /* 
    48  * Prototypes for attribute parsers. 
    49  */ 
    50 static pjsdp_rtpmap_attr *  parse_rtpmap_attr( pj_pool_t *pool, pj_scanner *scanner ); 
    51 static pjsdp_attr_string *  parse_generic_string_attr( pj_pool_t *pool, pj_scanner *scanner ); 
    52 static pjsdp_attr_num *     parse_generic_num_attr( pj_pool_t *pool, pj_scanner *scanner ); 
    53 static pjsdp_attr *         parse_name_only_attr( pj_pool_t *pool, pj_scanner *scanner ); 
    54 static pjsdp_fmtp_attr *    parse_fmtp_attr( pj_pool_t *pool, pj_scanner *scanner ); 
    55  
    56  
    57 /*  
    58  * Prototypes for functions to print attribute. 
    59  * All of them returns integer for the length printed, or -1 on error. 
    60  */ 
    61 static int print_rtpmap_attr(const pjsdp_rtpmap_attr *attr,  
    62                              char *buf, int length); 
    63 static int print_generic_string_attr(const pjsdp_attr_string *attr,  
    64                                      char *buf, int length); 
    65 static int print_generic_num_attr(const pjsdp_attr_num *attr,  
    66                                   char *buf, int length); 
    67 static int print_name_only_attr(const pjsdp_attr *attr,  
    68                                 char *buf, int length); 
    69 static int print_fmtp_attr(const pjsdp_fmtp_attr *attr,  
    70                            char *buf, int length); 
    71  
    72 /* 
    73  * Prototypes for cloning attributes. 
    74  */ 
    75 static pjsdp_attr* clone_rtpmap_attr (pj_pool_t *pool, const pjsdp_attr *rhs); 
    76 static pjsdp_attr* clone_generic_string_attr (pj_pool_t *pool, const pjsdp_attr *rhs); 
    77 static pjsdp_attr* clone_generic_num_attr (pj_pool_t *pool, const pjsdp_attr *rhs); 
    78 static pjsdp_attr* clone_name_only_attr (pj_pool_t *pool, const pjsdp_attr *rhs); 
    79 static pjsdp_attr* clone_fmtp_attr (pj_pool_t *pool, const pjsdp_attr *rhs); 
    80  
    81  
    82 /* 
    83  * Prototypes 
    84  */ 
    85 static void init_sdp_parser(void); 
    86  
    87  
    88 typedef void *  (*FPARSE)(pj_pool_t *pool, pj_scanner *scanner); 
    89 typedef int (*FPRINT)(const void *attr, char *buf, int length); 
    90 typedef pjsdp_attr*  (*FCLONE)(pj_pool_t *pool, const pjsdp_attr *rhs); 
    91  
    92 /* 
    93  * Array of functions to print attribute. 
    94  */ 
    95 static struct attr_map_rec 
    96 { 
    97     pj_str_t name; 
    98     FPARSE   parse_attr; 
    99     FPRINT   print_attr; 
    100     FCLONE   clone; 
    101 } attr_map[] =  
    102 { 
    103     {{"rtpmap", 6},    (FPARSE)&parse_rtpmap_attr,         (FPRINT)&print_rtpmap_attr,          (FCLONE)&clone_rtpmap_attr}, 
    104     {{"cat", 3},       (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    105     {{"keywds", 6},    (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    106     {{"tool", 4},      (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    107     {{"ptime", 5},     (FPARSE)&parse_generic_num_attr,    (FPRINT)&print_generic_num_attr,     (FCLONE)&clone_generic_num_attr}, 
    108     {{"recvonly", 8},  (FPARSE)&parse_name_only_attr,      (FPRINT)&print_name_only_attr,       (FCLONE)&clone_name_only_attr}, 
    109     {{"sendonly", 8},  (FPARSE)&parse_name_only_attr,      (FPRINT)&print_name_only_attr,       (FCLONE)&clone_name_only_attr}, 
    110     {{"sendrecv", 8},  (FPARSE)&parse_name_only_attr,      (FPRINT)&print_name_only_attr,       (FCLONE)&clone_name_only_attr}, 
    111     {{"orient", 6},    (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    112     {{"type", 4},      (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    113     {{"charset", 7},   (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    114     {{"sdplang", 7},   (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    115     {{"lang", 4},      (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    116     {{"framerate", 9}, (FPARSE)&parse_generic_string_attr, (FPRINT)&print_generic_string_attr,  (FCLONE)&clone_generic_string_attr}, 
    117     {{"quality", 7},   (FPARSE)&parse_generic_num_attr,    (FPRINT)&print_generic_num_attr,     (FCLONE)&clone_generic_num_attr}, 
    118     {{"fmtp", 4},      (FPARSE)&parse_fmtp_attr,           (FPRINT)&print_fmtp_attr,            (FCLONE)&clone_fmtp_attr}, 
    119     {{"inactive", 8},  (FPARSE)&parse_name_only_attr,      (FPRINT)&print_name_only_attr,       (FCLONE)&clone_name_only_attr}, 
    120     {{"", 0},          NULL, (FPRINT)&print_generic_string_attr,        (FCLONE)&clone_generic_string_attr} 
    121 }; 
     49static void parse_version(pj_scanner *scanner, parse_context *ctx); 
     50static void parse_origin(pj_scanner *scanner, pjmedia_sdp_session *ses, 
     51                         parse_context *ctx); 
     52static void parse_time(pj_scanner *scanner, pjmedia_sdp_session *ses, 
     53                       parse_context *ctx); 
     54static void parse_generic_line(pj_scanner *scanner, pj_str_t *str, 
     55                               parse_context *ctx); 
     56static void parse_connection_info(pj_scanner *scanner, pjmedia_sdp_conn *conn, 
     57                                  parse_context *ctx); 
     58static pjmedia_sdp_attr *parse_attr(pj_pool_t *pool, pj_scanner *scanner, 
     59                                    parse_context *ctx); 
     60static void parse_media(pj_scanner *scanner, pjmedia_sdp_media *med, 
     61                        parse_context *ctx); 
     62 
    12263 
    12364/* 
     
    14485} 
    14586 
    146 static int print_rtpmap_attr(const pjsdp_rtpmap_attr *rtpmap,  
    147                              char *buf, int len) 
    148 { 
    149     char *p = buf; 
    150  
    151     if (len < 16+rtpmap->encoding_name.slen+rtpmap->parameter.slen) { 
    152         return -1; 
    153     } 
     87PJ_DEF(pjmedia_sdp_attr*) pjmedia_sdp_attr_create( pj_pool_t *pool, 
     88                                                   const char *name, 
     89                                                   const pj_str_t *value) 
     90{ 
     91    pjmedia_sdp_attr *attr; 
     92 
     93    PJ_ASSERT_RETURN(pool && name, NULL); 
     94 
     95    attr = pj_pool_alloc(pool, sizeof(pjmedia_sdp_attr)); 
     96    pj_strdup2(pool, &attr->name, name); 
     97 
     98    if (value) 
     99        pj_strdup(pool, &attr->value, value); 
     100    else { 
     101        attr->value.ptr = NULL; 
     102        attr->value.slen = 0; 
     103    } 
     104 
     105    return attr; 
     106} 
     107 
     108PJ_DEF(pjmedia_sdp_attr*) pjmedia_sdp_attr_clone(pj_pool_t *pool,  
     109                                                 const pjmedia_sdp_attr *rhs) 
     110{ 
     111    pjmedia_sdp_attr *attr; 
    154112     
    155     /* colon and payload type. */ 
    156     *p++ = ':'; 
    157     len = pj_utoa(rtpmap->payload_type, p); 
    158     p += len; 
    159  
    160     /* space, encoding name */ 
     113    PJ_ASSERT_RETURN(pool && rhs, NULL); 
     114 
     115    attr = pj_pool_alloc(pool, sizeof(pjmedia_sdp_attr)); 
     116 
     117    pj_strdup(pool, &attr->name, &rhs->name); 
     118    pj_strdup(pool, &attr->value, &rhs->value); 
     119 
     120    return attr; 
     121} 
     122 
     123PJ_DEF(pjmedia_sdp_attr*)  
     124pjmedia_sdp_attr_find (unsigned count,  
     125                       const pjmedia_sdp_attr *const attr_array[], 
     126                       const pj_str_t *name, 
     127                       const pj_str_t *c_fmt) 
     128{ 
     129    char fmtbuf[16]; 
     130    pj_str_t fmt = { NULL, 0}; 
     131    unsigned i; 
     132 
     133    if (c_fmt) { 
     134        /* To search the format, we prepend the string with a colon and 
     135         * append space 
     136         */ 
     137        PJ_ASSERT_RETURN(c_fmt->slen<sizeof(fmtbuf)-2, NULL); 
     138        fmt.ptr = fmtbuf; 
     139        fmt.slen = c_fmt->slen + 2; 
     140        fmtbuf[0] = ':'; 
     141        pj_memcpy(fmt.ptr+1, c_fmt->ptr, c_fmt->slen); 
     142        fmtbuf[c_fmt->slen+1] = ' '; 
     143 
     144    }  
     145 
     146    for (i=0; i<count; ++i) { 
     147        if (pj_strcmp(&attr_array[i]->name, name) == 0) { 
     148            const pjmedia_sdp_attr *a = attr_array[i]; 
     149            if (c_fmt) { 
     150                if (a->value.slen > fmt.slen && 
     151                    pj_strncmp(&a->value, &fmt, fmt.slen)==0) 
     152                { 
     153                    return (pjmedia_sdp_attr*)a; 
     154                } 
     155            } else  
     156                return (pjmedia_sdp_attr*)a; 
     157        } 
     158    } 
     159    return NULL; 
     160} 
     161 
     162PJ_DEF(pjmedia_sdp_attr*)  
     163pjmedia_sdp_attr_find2(unsigned count,  
     164                       const pjmedia_sdp_attr *const attr_array[], 
     165                       const char *c_name, 
     166                       const pj_str_t *c_fmt) 
     167{ 
     168    pj_str_t name; 
     169 
     170    name.ptr = (char*)c_name; 
     171    name.slen = pj_native_strlen(c_name); 
     172 
     173    return pjmedia_sdp_attr_find(count, attr_array, &name, c_fmt); 
     174} 
     175 
     176 
     177PJ_DEF(pj_status_t) pjmedia_sdp_attr_add(unsigned *count, 
     178                                         pjmedia_sdp_attr *attr_array[], 
     179                                         pjmedia_sdp_attr *attr) 
     180{ 
     181    PJ_ASSERT_RETURN(count && attr_array && attr, PJ_EINVAL); 
     182    PJ_ASSERT_RETURN(*count < PJSDP_MAX_ATTR, PJ_ETOOMANY); 
     183 
     184    attr_array[*count] = attr; 
     185    (*count)++; 
     186 
     187    return PJ_SUCCESS; 
     188} 
     189 
     190 
     191PJ_DEF(unsigned) pjmedia_sdp_attr_remove_all(unsigned *count, 
     192                                             pjmedia_sdp_attr *attr_array[], 
     193                                             const char *name) 
     194{ 
     195    unsigned i, removed = 0; 
     196    pj_str_t attr_name; 
     197 
     198    PJ_ASSERT_RETURN(count && attr_array && name, PJ_EINVAL); 
     199 
     200    attr_name.ptr = (char*)name; 
     201    attr_name.slen = pj_native_strlen(name); 
     202 
     203    for (i=0; i<*count; ) { 
     204        if (pj_strcmp(&attr_array[i]->name, &attr_name)==0) { 
     205            pj_array_erase(attr_array, sizeof(pjmedia_sdp_attr*), 
     206                           *count, i); 
     207            --(*count); 
     208            ++removed; 
     209        } else { 
     210            ++i; 
     211        }    
     212    } 
     213 
     214    return removed; 
     215} 
     216 
     217 
     218PJ_DEF(pj_status_t) pjmedia_sdp_attr_remove( unsigned *count, 
     219                                             pjmedia_sdp_attr *attr_array[], 
     220                                             pjmedia_sdp_attr *attr ) 
     221{ 
     222    unsigned i, removed=0; 
     223 
     224    PJ_ASSERT_RETURN(count && attr_array && attr, PJ_EINVAL); 
     225 
     226    for (i=0; i<*count; ) { 
     227        if (attr_array[i] == attr) { 
     228            pj_array_erase(attr_array, sizeof(pjmedia_sdp_attr*), 
     229                           *count, i); 
     230            --(*count); 
     231            ++removed; 
     232        } else { 
     233            ++i; 
     234        } 
     235    } 
     236 
     237    return removed ? PJ_SUCCESS : PJ_ENOTFOUND; 
     238} 
     239 
     240 
     241PJ_DEF(pj_status_t) pjmedia_sdp_attr_get_rtpmap( const pjmedia_sdp_attr *attr, 
     242                                                 pjmedia_sdp_rtpmap *rtpmap) 
     243{ 
     244    const char *p = attr->value.ptr; 
     245    const char *end = attr->value.ptr + attr->value.slen; 
     246    pj_str_t token; 
     247 
     248    PJ_ASSERT_RETURN(pj_strcmp2(&attr->name, "rtpmap")==0, PJ_EINVALIDOP); 
     249 
     250    /* rtpmap sample: 
     251     *  a=rtpmap:98 L16/16000/2. 
     252     */ 
     253 
     254    /* Eat the first ':' */ 
     255    if (*p != ':') return PJMEDIA_SDP_EINRTPMAP; 
     256 
     257    /* Get ':' */ 
     258    ++p; 
     259 
     260    /* Get payload type. */ 
     261    token.ptr = (char*)p; 
     262    while (pj_isdigit(*p) && p!=end) 
     263        ++p; 
     264    token.slen = p - token.ptr; 
     265    if (token.slen == 0) 
     266        return PJMEDIA_SDP_EINRTPMAP; 
     267 
     268    rtpmap->pt = token; 
     269 
     270    /* Expecting space after payload type. */ 
     271    if (*p != ' ') return PJMEDIA_SDP_EINRTPMAP; 
     272 
     273    /* Get space. */ 
     274    ++p; 
     275 
     276    /* Get encoding name. */ 
     277    token.ptr = (char*)p; 
     278    while (*p != '/' && p != end) 
     279        ++p; 
     280    token.slen = p - token.ptr; 
     281    if (token.slen == 0) 
     282        return PJMEDIA_SDP_EINRTPMAP; 
     283    rtpmap->enc_name = token; 
     284 
     285    /* Expecting '/' after encoding name. */ 
     286    if (*p != '/') return PJMEDIA_SDP_EINRTPMAP; 
     287 
     288    /* Get '/' */ 
     289    ++p; 
     290 
     291    /* Get the clock rate. */ 
     292    token.ptr = (char*)p; 
     293    while (pj_isdigit(*p) && p != end) 
     294        ++p; 
     295    token.slen = p - token.ptr; 
     296    if (token.slen == 0) 
     297        return PJMEDIA_SDP_EINRTPMAP; 
     298 
     299    rtpmap->clock_rate = pj_strtoul(&token); 
     300 
     301    /* Expecting either '/' or EOF */ 
     302    if (*p != '/' && p != end) 
     303        return PJMEDIA_SDP_EINRTPMAP; 
     304 
     305    if (*p == '/') { 
     306        ++p; 
     307        token.ptr = (char*)p; 
     308        token.slen = end-p; 
     309        rtpmap->param = token; 
     310    } else { 
     311        rtpmap->param.ptr = NULL; 
     312        rtpmap->param.slen = 0; 
     313    } 
     314 
     315    return PJ_SUCCESS; 
     316 
     317} 
     318 
     319PJ_DEF(pj_status_t) pjmedia_sdp_attr_get_fmtp( const pjmedia_sdp_attr *attr, 
     320                                               pjmedia_sdp_fmtp *fmtp) 
     321{ 
     322    const char *p = attr->value.ptr; 
     323    const char *end = attr->value.ptr + attr->value.slen; 
     324    pj_str_t token; 
     325 
     326    PJ_ASSERT_RETURN(pj_strcmp2(&attr->name, "fmtp")==0, PJ_EINVALIDOP); 
     327 
     328    /* fmtp BNF: 
     329     *  a=fmtp:<format> <format specific parameter> 
     330     */ 
     331 
     332    /* Eat the first ':' */ 
     333    if (*p != ':') return PJMEDIA_SDP_EINFMTP; 
     334 
     335    /* Get ':' */ 
     336    ++p; 
     337 
     338    /* Get format. */ 
     339    token.ptr = (char*)p; 
     340    while (pj_isdigit(*p) && p!=end) 
     341        ++p; 
     342    token.slen = p - token.ptr; 
     343    if (token.slen == 0) 
     344        return PJMEDIA_SDP_EINFMTP; 
     345 
     346    fmtp->fmt = token; 
     347 
     348    /* Expecting space after format. */ 
     349    if (*p != ' ') return PJMEDIA_SDP_EINFMTP; 
     350 
     351    /* Get space. */ 
     352    ++p; 
     353 
     354    /* Set the remaining string as fmtp format parameter. */ 
     355    fmtp->fmt_param.ptr = (char*)p; 
     356    fmtp->fmt_param.slen = end - p; 
     357 
     358    return PJ_SUCCESS; 
     359} 
     360 
     361PJ_DEF(pj_status_t) pjmedia_sdp_attr_to_rtpmap(pj_pool_t *pool, 
     362                                               const pjmedia_sdp_attr *attr, 
     363                                               pjmedia_sdp_rtpmap **p_rtpmap) 
     364{ 
     365    PJ_ASSERT_RETURN(pool && attr && p_rtpmap, PJ_EINVAL); 
     366 
     367    *p_rtpmap = pj_pool_alloc(pool, sizeof(pjmedia_sdp_rtpmap)); 
     368    PJ_ASSERT_RETURN(*p_rtpmap, PJ_ENOMEM); 
     369 
     370    return pjmedia_sdp_attr_get_rtpmap(attr, *p_rtpmap); 
     371} 
     372 
     373 
     374PJ_DEF(pj_status_t) pjmedia_sdp_rtpmap_to_attr(pj_pool_t *pool, 
     375                                               const pjmedia_sdp_rtpmap *rtpmap, 
     376                                               pjmedia_sdp_attr **p_attr) 
     377{ 
     378    pjmedia_sdp_attr *attr; 
     379    char tempbuf[64], *p, *endbuf; 
     380    int i; 
     381 
     382    /* Check arguments. */ 
     383    PJ_ASSERT_RETURN(pool && rtpmap && p_attr, PJ_EINVAL); 
     384 
     385    /* Check that mandatory attributes are specified. */ 
     386    PJ_ASSERT_RETURN(rtpmap->enc_name.slen && rtpmap->clock_rate, 
     387                     PJMEDIA_SDP_EINRTPMAP); 
     388 
     389    /* Check size. */ 
     390    i = rtpmap->enc_name.slen + rtpmap->param.slen + 32; 
     391    if (i >= sizeof(tempbuf)-1) { 
     392        pj_assert(!"rtpmap attribute is too long"); 
     393        return PJMEDIA_SDP_ERTPMAPTOOLONG; 
     394    } 
     395 
     396    attr = pj_pool_alloc(pool, sizeof(pjmedia_sdp_attr)); 
     397    PJ_ASSERT_RETURN(attr != NULL, PJ_ENOMEM); 
     398 
     399    attr->name.ptr = "rtpmap"; 
     400    attr->name.slen = 6; 
     401 
     402    p = tempbuf; 
     403    endbuf = tempbuf+sizeof(tempbuf); 
     404 
     405    /* Add payload type. */ 
     406    pj_memcpy(p, rtpmap->pt.ptr, rtpmap->pt.slen); 
     407    p += rtpmap->pt.slen; 
    161408    *p++ = ' '; 
    162     pj_memcpy(p, rtpmap->encoding_name.ptr, rtpmap->encoding_name.slen); 
    163     p += rtpmap->encoding_name.slen; 
    164  
    165     /* slash, clock-rate. */ 
     409 
     410    /* Add encoding name. */ 
     411    for (i=0; i<rtpmap->enc_name.slen; ++i) 
     412        p[i] = rtpmap->enc_name.ptr[i]; 
     413    p += rtpmap->enc_name.slen; 
    166414    *p++ = '/'; 
    167     len = pj_utoa(rtpmap->clock_rate, p); 
    168     p += len; 
    169  
    170     /* optionally add encoding parameter. */ 
    171     if (rtpmap->parameter.slen) { 
     415 
     416    /* Add clock rate. */ 
     417    p += pj_utoa(rtpmap->clock_rate, p); 
     418 
     419    /* Add parameter if necessary. */ 
     420    if (rtpmap->param.slen > 0) { 
    172421        *p++ = '/'; 
    173         pj_memcpy(p, rtpmap->parameter.ptr, rtpmap->parameter.slen); 
    174         p += rtpmap->parameter.slen; 
    175     } 
    176  
    177     return p-buf; 
    178 } 
    179  
    180 static int print_generic_string_attr(const pjsdp_attr_string *attr,  
    181                                      char *buf, int len) 
    182 { 
    183     char *p = buf; 
    184  
    185     if (len < attr->value.slen + 4) { 
    186         return -1; 
    187     } 
    188  
    189     /* colon and attribute value. */ 
    190     *p++ = ':'; 
    191     pj_memcpy(p, attr->value.ptr, attr->value.slen); 
    192     p += attr->value.slen; 
    193  
    194     return p-buf; 
    195 } 
    196  
    197 static int print_generic_num_attr(const pjsdp_attr_num *attr, char *buf, int len) 
    198 { 
    199     char *p = buf; 
    200  
    201     if (len < 10) { 
    202         return -1; 
    203     } 
    204     *p++ = ':'; 
    205     return pj_utoa(attr->value, p); 
    206 } 
    207  
    208 static int print_name_only_attr(const pjsdp_attr *attr, char *buf, int len) 
    209 { 
    210     PJ_UNUSED_ARG(attr); 
    211     PJ_UNUSED_ARG(buf); 
    212     PJ_UNUSED_ARG(len); 
    213     return 0; 
    214 } 
    215  
    216 static int print_fmtp_attr(const pjsdp_fmtp_attr *fmtp, char *buf, int len) 
    217 { 
    218     char *p = buf; 
    219  
    220     if (len < 4+fmtp->format.slen+fmtp->param.slen) { 
    221         return -1; 
    222     } 
    223  
    224     /* colon and format. */ 
    225     *p++ = ':'; 
    226     pj_memcpy(p, fmtp->format.ptr, fmtp->format.slen); 
    227     p += fmtp->format.slen; 
    228  
    229     /* space and parameter. */ 
    230     *p++ = ' '; 
    231     pj_memcpy(p, fmtp->param.ptr, fmtp->param.slen); 
    232     p += fmtp->param.slen; 
    233  
    234     return p-buf; 
    235 } 
    236  
    237  
    238 static int print_attr(const pjsdp_attr *attr, char *buf, int len) 
    239 { 
    240     char *p = buf; 
    241     struct attr_map_rec *desc = &attr_map[attr->type]; 
    242  
    243     if (len < 16) { 
    244         return -1; 
    245     } 
    246  
    247     *p++ = 'a'; 
    248     *p++ = '='; 
    249     pj_memcpy(p, desc->name.ptr, desc->name.slen); 
    250     p += desc->name.slen; 
    251      
    252     len = (*desc->print_attr)(attr, p, (buf+len)-p); 
    253     if (len < 0) { 
    254         return -1; 
    255     } 
    256     p += len; 
    257     *p++ = '\r'; 
    258     *p++ = '\n'; 
    259     return p-buf; 
    260 } 
    261  
    262 static pjsdp_attr* clone_rtpmap_attr (pj_pool_t *pool, const pjsdp_attr *p) 
    263 { 
    264     const pjsdp_rtpmap_attr *rhs = (const pjsdp_rtpmap_attr*)p; 
    265     pjsdp_rtpmap_attr *attr = pj_pool_alloc (pool, sizeof(pjsdp_rtpmap_attr)); 
    266     if (!attr) 
    267         return NULL; 
    268  
    269     attr->type = rhs->type; 
    270     attr->payload_type = rhs->payload_type; 
    271     if (!pj_strdup (pool, &attr->encoding_name, &rhs->encoding_name)) return NULL; 
    272     attr->clock_rate = rhs->clock_rate; 
    273     if (!pj_strdup (pool, &attr->parameter, &rhs->parameter)) return NULL; 
    274  
    275     return (pjsdp_attr*)attr; 
    276 } 
    277  
    278 static pjsdp_attr* clone_generic_string_attr (pj_pool_t *pool, const pjsdp_attr *p) 
    279 { 
    280     const pjsdp_attr_string* rhs = (const pjsdp_attr_string*) p; 
    281     pjsdp_attr_string *attr = pj_pool_alloc (pool, sizeof(pjsdp_attr_string)); 
    282     if (!attr) 
    283         return NULL; 
    284  
    285     attr->type = rhs->type; 
    286     if (!pj_strdup (pool, &attr->value, &rhs->value)) return NULL; 
    287  
    288     return (pjsdp_attr*)attr; 
    289 } 
    290  
    291 static pjsdp_attr* clone_generic_num_attr (pj_pool_t *pool, const pjsdp_attr *p) 
    292 { 
    293     const pjsdp_attr_num* rhs = (const pjsdp_attr_num*) p; 
    294     pjsdp_attr_num *attr = pj_pool_alloc (pool, sizeof(pjsdp_attr_num)); 
    295     if (!attr) 
    296         return NULL; 
    297  
    298     attr->type = rhs->type; 
    299     attr->value = rhs->value; 
    300  
    301     return (pjsdp_attr*)attr; 
    302 } 
    303  
    304 static pjsdp_attr* clone_name_only_attr (pj_pool_t *pool, const pjsdp_attr *rhs) 
    305 { 
    306     pjsdp_attr *attr = pj_pool_alloc (pool, sizeof(pjsdp_attr)); 
    307     if (!attr) 
    308         return NULL; 
    309  
    310     attr->type = rhs->type; 
    311     return attr; 
    312 } 
    313  
    314 static pjsdp_attr* clone_fmtp_attr (pj_pool_t *pool, const pjsdp_attr *p) 
    315 { 
    316     const pjsdp_fmtp_attr* rhs = (const pjsdp_fmtp_attr*) p; 
    317     pjsdp_fmtp_attr *attr = pj_pool_alloc (pool, sizeof(pjsdp_fmtp_attr)); 
    318     if (!attr) 
    319         return NULL; 
    320  
    321     attr->type = rhs->type; 
    322     if (!pj_strdup (pool, &attr->format, &rhs->format)) return NULL; 
    323     if (!pj_strdup (pool, &attr->param, &rhs->param)) return NULL; 
    324  
    325     return (pjsdp_attr*)attr; 
    326 } 
    327  
    328 PJ_DEF(pjsdp_attr*) pjsdp_attr_clone (pj_pool_t *pool, const pjsdp_attr *rhs) 
    329 { 
    330     struct attr_map_rec *desc; 
    331  
    332     if (rhs->type >= PJSDP_END_OF_ATTR) { 
    333         pj_assert(0); 
    334         return NULL; 
    335     } 
    336  
    337     desc = &attr_map[rhs->type]; 
    338     return (*desc->clone) (pool, rhs); 
    339 } 
    340  
    341 PJ_DEF(const pjsdp_attr*) pjsdp_attr_find (int count, const pjsdp_attr *attr_array[], int type) 
    342 { 
    343     int i; 
    344  
    345     for (i=0; i<count; ++i) { 
    346         if (attr_array[i]->type == type) 
    347             return attr_array[i]; 
    348     } 
    349     return NULL; 
    350 } 
    351  
    352 static int print_connection_info( pjsdp_conn_info *c, char *buf, int len) 
     422        for (i=0; i<rtpmap->param.slen; ++i) 
     423            p[i] = rtpmap->param.ptr[i]; 
     424        p += rtpmap->param.slen; 
     425    } 
     426 
     427    *p = '\0'; 
     428 
     429    attr->value.slen = p-tempbuf; 
     430    attr->value.ptr = pj_pool_alloc(pool, attr->value.slen); 
     431    pj_memcpy(attr->value.ptr, tempbuf, attr->value.slen); 
     432 
     433    *p_attr = attr; 
     434    return PJ_SUCCESS; 
     435} 
     436 
     437 
     438static int print_connection_info( pjmedia_sdp_conn *c, char *buf, int len) 
    353439{ 
    354440    char *p = buf; 
     
    373459} 
    374460 
    375 PJ_DEF(pjsdp_conn_info*) pjsdp_conn_info_clone (pj_pool_t *pool, const pjsdp_conn_info *rhs) 
    376 { 
    377     pjsdp_conn_info *c = pj_pool_alloc (pool, sizeof(pjsdp_conn_info)); 
     461PJ_DEF(pjmedia_sdp_conn*) pjmedia_sdp_conn_clone (pj_pool_t *pool,  
     462                                                  const pjmedia_sdp_conn *rhs) 
     463{ 
     464    pjmedia_sdp_conn *c = pj_pool_alloc (pool, sizeof(pjmedia_sdp_conn)); 
    378465    if (!c) return NULL; 
    379466 
     
    385472} 
    386473 
    387 static int print_media_desc( pjsdp_media_desc *m, char *buf, int len) 
     474static pj_ssize_t print_attr(const pjmedia_sdp_attr *attr,  
     475                             char *buf, pj_size_t len) 
     476{ 
     477    char *p = buf; 
     478 
     479    if ((int)len < attr->name.slen + attr->value.slen + 10) 
     480        return -1; 
     481 
     482    *p++ = 'a'; 
     483    *p++ = '='; 
     484    pj_memcpy(p, attr->name.ptr, attr->name.slen); 
     485    p += attr->name.slen; 
     486     
     487 
     488    if (attr->value.slen) { 
     489        pj_memcpy(p, attr->value.ptr, attr->value.slen); 
     490        p += attr->value.slen; 
     491    } 
     492 
     493    *p++ = '\r'; 
     494    *p++ = '\n'; 
     495    return p-buf; 
     496} 
     497 
     498static int print_media_desc( pjmedia_sdp_media *m, char *buf, int len) 
    388499{ 
    389500    char *p = buf; 
     
    440551} 
    441552 
    442 PJ_DEF(pjsdp_media_desc*) pjsdp_media_desc_clone (pj_pool_t *pool,  
    443                                                   const pjsdp_media_desc *rhs) 
     553PJ_DEF(pjmedia_sdp_media*) pjmedia_sdp_media_clone( 
     554                                                 pj_pool_t *pool,  
     555                                                 const pjmedia_sdp_media *rhs) 
    444556{ 
    445557    unsigned int i; 
    446     pjsdp_media_desc *m = pj_pool_alloc (pool, sizeof(pjsdp_media_desc)); 
    447     if (!m) 
    448         return NULL; 
     558    pjmedia_sdp_media *m = pj_pool_alloc (pool, sizeof(pjmedia_sdp_media)); 
     559    PJ_ASSERT_RETURN(m != NULL, NULL); 
    449560 
    450561    pj_strdup (pool, &m->desc.media, &rhs->desc.media); 
     
    457568 
    458569    if (rhs->conn) { 
    459         m->conn = pjsdp_conn_info_clone (pool, rhs->conn); 
    460         if (!m->conn) 
    461             return NULL; 
     570        m->conn = pjmedia_sdp_conn_clone (pool, rhs->conn); 
     571        PJ_ASSERT_RETURN(m->conn != NULL, NULL); 
    462572    } else { 
    463573        m->conn = NULL; 
     
    466576    m->attr_count = rhs->attr_count; 
    467577    for (i=0; i < rhs->attr_count; ++i) { 
    468         m->attr[i] = pjsdp_attr_clone (pool, rhs->attr[i]); 
    469         if (!m->attr[i]) 
    470             return NULL; 
     578        m->attr[i] = pjmedia_sdp_attr_clone (pool, rhs->attr[i]); 
     579        PJ_ASSERT_RETURN(m->attr[i] != NULL, NULL); 
    471580    } 
    472581 
     
    474583} 
    475584 
    476 /** Check if the media description has the specified attribute. */ 
    477 PJ_DEF(pj_bool_t) pjsdp_media_desc_has_attr (const pjsdp_media_desc *m,  
    478                                              pjsdp_attr_type_e attr_type) 
    479 { 
    480     unsigned i; 
    481     for (i=0; i<m->attr_count; ++i) { 
    482         pjsdp_attr *attr = m->attr[i]; 
    483         if (attr->type == attr_type) 
    484             return 1; 
    485     } 
    486     return 0; 
    487 } 
    488  
    489 /** Find rtpmap attribute for the specified payload type. */ 
    490 PJ_DEF(const pjsdp_rtpmap_attr*)  
    491 pjsdp_media_desc_find_rtpmap (const pjsdp_media_desc *m, unsigned pt) 
    492 { 
    493     unsigned i; 
    494     for (i=0; i<m->attr_count; ++i) { 
    495         pjsdp_attr *attr = m->attr[i]; 
    496         if (attr->type == PJSDP_ATTR_RTPMAP) { 
    497             const pjsdp_rtpmap_attr* rtpmap = (const pjsdp_rtpmap_attr*)attr; 
    498             if (rtpmap->payload_type == pt) 
    499                 return rtpmap; 
    500         } 
    501     } 
    502     return NULL; 
    503 } 
    504  
    505  
    506 static int print_session(const pjsdp_session_desc *ses, char *buf, pj_ssize_t len) 
     585PJ_DEF(pjmedia_sdp_attr*)  
     586pjmedia_sdp_media_find_attr(const pjmedia_sdp_media *m, 
     587                            const pj_str_t *name, const pj_str_t *fmt) 
     588{ 
     589    PJ_ASSERT_RETURN(m && name, NULL); 
     590    return pjmedia_sdp_attr_find(m->attr_count, m->attr, name, fmt); 
     591} 
     592 
     593 
     594 
     595PJ_DEF(pjmedia_sdp_attr*)  
     596pjmedia_sdp_media_find_attr2(const pjmedia_sdp_media *m, 
     597                             const char *name, const pj_str_t *fmt) 
     598{ 
     599    PJ_ASSERT_RETURN(m && name, NULL); 
     600    return pjmedia_sdp_attr_find2(m->attr_count, m->attr, name, fmt); 
     601} 
     602 
     603 
     604PJ_DEF(pj_status_t) pjmedia_sdp_media_add_attr( pjmedia_sdp_media *m, 
     605                                                pjmedia_sdp_attr *attr) 
     606{ 
     607    return pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr); 
     608} 
     609 
     610PJ_DEF(unsigned)  
     611pjmedia_sdp_media_remove_all_attr(pjmedia_sdp_media *m, 
     612                                  const char *name) 
     613{ 
     614    return pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, name); 
     615} 
     616 
     617PJ_DEF(pj_status_t) 
     618pjmedia_sdp_media_remove_attr(pjmedia_sdp_media *m, 
     619                              pjmedia_sdp_attr *attr) 
     620{ 
     621    return pjmedia_sdp_attr_remove(&m->attr_count, m->attr, attr); 
     622} 
     623 
     624static int print_session(const pjmedia_sdp_session *ses,  
     625                         char *buf, pj_ssize_t len) 
    507626{ 
    508627    char *p = buf; 
     
    605724 */ 
    606725 
    607 static void parse_version(pj_scanner *scanner) 
    608 { 
     726static void parse_version(pj_scanner *scanner, parse_context *ctx) 
     727{ 
     728    ctx->last_error = PJMEDIA_SDP_EINVER; 
     729 
    609730    pj_scan_advance_n(scanner, 3, SKIP_WS); 
    610731    pj_scan_get_newline(scanner); 
    611732} 
    612733 
    613 static void parse_origin(pj_scanner *scanner, pjsdp_session_desc *ses) 
     734static void parse_origin(pj_scanner *scanner, pjmedia_sdp_session *ses, 
     735                         parse_context *ctx) 
    614736{ 
    615737    pj_str_t str; 
     738 
     739    ctx->last_error = PJMEDIA_SDP_EINORIGIN; 
    616740 
    617741    /* o= */ 
     
    647771} 
    648772 
    649 static void parse_time(pj_scanner *scanner, pjsdp_session_desc *ses) 
     773static void parse_time(pj_scanner *scanner, pjmedia_sdp_session *ses, 
     774                       parse_context *ctx) 
    650775{ 
    651776    pj_str_t str; 
     777 
     778    ctx->last_error = PJMEDIA_SDP_EINTIME; 
    652779 
    653780    /* t= */ 
     
    668795} 
    669796 
    670 static void parse_generic_line(pj_scanner *scanner, pj_str_t *str) 
    671 { 
     797static void parse_generic_line(pj_scanner *scanner, pj_str_t *str, 
     798                               parse_context *ctx) 
     799{ 
     800    ctx->last_error = PJMEDIA_SDP_EINSDP; 
     801 
    672802    /* x= */ 
    673803    pj_scan_advance_n(scanner, 2, SKIP_WS); 
     
    680810} 
    681811 
    682 static void parse_connection_info(pj_scanner *scanner, pjsdp_conn_info *conn) 
    683 { 
     812static void parse_connection_info(pj_scanner *scanner, pjmedia_sdp_conn *conn, 
     813                                  parse_context *ctx) 
     814{ 
     815    ctx->last_error = PJMEDIA_SDP_EINCONN; 
     816 
    684817    /* c= */ 
    685818    pj_scan_advance_n(scanner, 2, SKIP_WS); 
     
    700833} 
    701834 
    702 static void parse_media(pj_scanner *scanner, pjsdp_media_desc *med) 
     835static void parse_media(pj_scanner *scanner, pjmedia_sdp_media *med, 
     836                        parse_context *ctx) 
    703837{ 
    704838    pj_str_t str; 
     839 
     840    ctx->last_error = PJMEDIA_SDP_EINMEDIA; 
    705841 
    706842    /* m= */ 
     
    742878} 
    743879 
    744 static pjsdp_rtpmap_attr * parse_rtpmap_attr( pj_pool_t *pool, pj_scanner *scanner ) 
    745 { 
    746     pjsdp_rtpmap_attr *rtpmap; 
    747     pj_str_t str; 
    748  
    749     rtpmap = pj_pool_calloc(pool, 1, sizeof(*rtpmap)); 
    750     if (pj_scan_get_char(scanner) != ':') { 
    751         PJ_THROW(SYNTAX_ERROR); 
    752     } 
    753     pj_scan_get_until_ch(scanner, ' ', &str); 
    754     rtpmap->payload_type = pj_strtoul(&str); 
    755     pj_scan_get_char(scanner); 
    756  
    757     pj_scan_get_until_ch(scanner, '/', &rtpmap->encoding_name); 
    758     pj_scan_get_char(scanner); 
    759     pj_scan_get(scanner, &cs_token, &str); 
    760     rtpmap->clock_rate = pj_strtoul(&str); 
    761  
    762     if (*scanner->curptr == '/') { 
    763         pj_scan_get_char(scanner); 
    764         pj_scan_get_until_ch(scanner, '\r', &rtpmap->parameter); 
    765     } 
    766  
    767     return rtpmap; 
    768 } 
    769  
    770 static pjsdp_attr_string * parse_generic_string_attr( pj_pool_t *pool, pj_scanner *scanner ) 
    771 { 
    772     pjsdp_attr_string *attr; 
    773     attr = pj_pool_calloc(pool, 1, sizeof(*attr)); 
    774  
    775     if (pj_scan_get_char(scanner) != ':') { 
    776         PJ_THROW(SYNTAX_ERROR); 
    777     } 
    778     pj_scan_get_until_ch(scanner, '\r', &attr->value); 
    779     return attr; 
    780 } 
    781  
    782 static pjsdp_attr_num * parse_generic_num_attr( pj_pool_t *pool, pj_scanner *scanner ) 
    783 { 
    784     pjsdp_attr_num *attr; 
    785     pj_str_t str; 
    786  
    787     attr = pj_pool_calloc(pool, 1, sizeof(*attr)); 
    788  
    789     if (pj_scan_get_char(scanner) != ':') { 
    790         PJ_THROW(SYNTAX_ERROR); 
    791     } 
    792     pj_scan_get_until_ch(scanner, '\r', &str); 
    793     attr->value = pj_strtoul(&str); 
    794     return attr; 
    795 } 
    796  
    797 static pjsdp_attr * parse_name_only_attr( pj_pool_t *pool, pj_scanner *scanner ) 
    798 { 
    799     pjsdp_attr *attr; 
    800  
     880static void on_scanner_error(pj_scanner *scanner) 
     881{ 
    801882    PJ_UNUSED_ARG(scanner); 
    802     attr = pj_pool_calloc(pool, 1, sizeof(*attr)); 
    803     return attr; 
    804 } 
    805  
    806 static pjsdp_fmtp_attr * parse_fmtp_attr( pj_pool_t *pool, pj_scanner *scanner ) 
    807 { 
    808     pjsdp_fmtp_attr *fmtp; 
    809  
    810     fmtp = pj_pool_calloc(pool, 1, sizeof(*fmtp)); 
    811  
    812     if (pj_scan_get_char(scanner) != ':') { 
    813         PJ_THROW(SYNTAX_ERROR); 
    814     } 
    815     pj_scan_get_until_ch(scanner, ' ', &fmtp->format); 
    816     pj_scan_get_char(scanner); 
    817     pj_scan_get_until_ch(scanner, '\r', &fmtp->param); 
    818     return fmtp; 
    819 } 
    820  
    821 static pjsdp_attr *parse_attr( pj_pool_t *pool, pj_scanner *scanner) 
    822 { 
    823     void * (*parse_func)(pj_pool_t *pool, pj_scanner *scanner) = NULL; 
    824     pj_str_t attrname; 
    825     unsigned i; 
    826     pjsdp_attr *attr; 
     883 
     884    PJ_THROW(SYNTAX_ERROR); 
     885} 
     886 
     887static pjmedia_sdp_attr *parse_attr( pj_pool_t *pool, pj_scanner *scanner, 
     888                                    parse_context *ctx) 
     889{ 
     890    pjmedia_sdp_attr *attr; 
     891 
     892    ctx->last_error = PJMEDIA_SDP_EINATTR; 
     893 
     894    attr = pj_pool_alloc(pool, sizeof(pjmedia_sdp_attr)); 
    827895 
    828896    /* skip a= */ 
     
    830898     
    831899    /* get attr name. */ 
    832     pj_scan_get(scanner, &cs_token, &attrname); 
    833  
    834     /* find entry to handle attrname */ 
    835     for (i=0; i<PJ_ARRAY_SIZE(attr_map); ++i) { 
    836         struct attr_map_rec *p = &attr_map[i]; 
    837         if (pj_strcmp(&attrname, &p->name) == 0) { 
    838             parse_func = p->parse_attr; 
    839             break; 
    840         } 
    841     } 
    842  
    843     /* fallback to generic string parser. */ 
    844     if (parse_func == NULL) { 
    845         parse_func = &parse_generic_string_attr; 
    846     } 
    847  
    848     attr = (*parse_func)(pool, scanner); 
    849     attr->type = i; 
    850          
     900    pj_scan_get(scanner, &cs_token, &attr->name); 
     901 
     902    if (*scanner->curptr != '\r' && *scanner->curptr != '\n') { 
     903        /* get value */ 
     904        pj_scan_get_until_ch(scanner, '\r', &attr->value); 
     905    } else { 
     906        attr->value.ptr = NULL; 
     907        attr->value.slen = 0; 
     908    } 
     909 
    851910    /* newline */ 
    852911    pj_scan_get_newline(scanner); 
    853912 
    854913    return attr; 
    855 } 
    856  
    857 static void on_scanner_error(pj_scanner *scanner) 
    858 { 
    859     PJ_UNUSED_ARG(scanner); 
    860  
    861     PJ_THROW(SYNTAX_ERROR); 
    862914} 
    863915 
     
    865917 * Parse SDP message. 
    866918 */ 
    867 PJ_DEF(pjsdp_session_desc*) pjsdp_parse( char *buf, pj_size_t len,  
    868                                          pj_pool_t *pool) 
     919PJ_DEF(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool, 
     920                                       char *buf, pj_size_t len,  
     921                                       pjmedia_sdp_session **p_sdp) 
    869922{ 
    870923    pj_scanner scanner; 
    871     pjsdp_session_desc *session; 
    872     pjsdp_media_desc *media = NULL; 
     924    pjmedia_sdp_session *session; 
     925    pjmedia_sdp_media *media = NULL; 
    873926    void *attr; 
    874     pjsdp_conn_info *conn; 
     927    pjmedia_sdp_conn *conn; 
    875928    pj_str_t dummy; 
    876929    int cur_name = 254; 
     930    parse_context ctx; 
    877931    PJ_USE_EXCEPTION; 
    878932 
     933    ctx.last_error = PJ_SUCCESS; 
     934 
    879935    init_sdp_parser(); 
    880936 
    881937    pj_scan_init(&scanner, buf, len, 0, &on_scanner_error); 
    882     session = pj_pool_calloc(pool, 1, sizeof(*session)); 
     938    session = pj_pool_calloc(pool, 1, sizeof(pjmedia_sdp_session)); 
     939    PJ_ASSERT_RETURN(session != NULL, PJ_ENOMEM); 
    883940 
    884941    PJ_TRY { 
     
    887944                switch (cur_name) { 
    888945                case 'a': 
    889                     attr = parse_attr(pool, &scanner); 
     946                    attr = parse_attr(pool, &scanner, &ctx); 
    890947                    if (attr) { 
    891948                        if (media) { 
     
    897954                    break; 
    898955                case 'o': 
    899                     parse_origin(&scanner, session); 
     956                    parse_origin(&scanner, session, &ctx); 
    900957                    break; 
    901958                case 's': 
    902                     parse_generic_line(&scanner, &session->name); 
     959                    parse_generic_line(&scanner, &session->name, &ctx); 
    903960                    break; 
    904961                case 'c': 
    905962                    conn = pj_pool_calloc(pool, 1, sizeof(*conn)); 
    906                     parse_connection_info(&scanner, conn); 
     963                    parse_connection_info(&scanner, conn, &ctx); 
    907964                    if (media) { 
    908965                        media->conn = conn; 
     
    912969                    break; 
    913970                case 't': 
    914                     parse_time(&scanner, session); 
     971                    parse_time(&scanner, session, &ctx); 
    915972                    break; 
    916973                case 'm': 
    917974                    media = pj_pool_calloc(pool, 1, sizeof(*media)); 
    918                     parse_media(&scanner, media); 
     975                    parse_media(&scanner, media, &ctx); 
    919976                    session->media[ session->media_count++ ] = media; 
    920977                    break; 
    921978                case 'v': 
    922                     parse_version(&scanner); 
     979                    parse_version(&scanner, &ctx); 
    923980                    break; 
    924981                default: 
    925                     parse_generic_line(&scanner, &dummy); 
     982                    parse_generic_line(&scanner, &dummy, &ctx); 
    926983                    break; 
    927984                } 
    928985        } 
     986 
     987        ctx.last_error = PJ_SUCCESS; 
     988 
    929989    } 
    930990    PJ_CATCH(SYNTAX_ERROR) { 
    931         PJ_LOG(2, (LOG_THIS, "Syntax error in SDP parser '%c' line %d col %d", 
    932                 cur_name, scanner.line, pj_scan_get_col(&scanner))); 
    933         if (!pj_scan_is_eof(&scanner)) { 
    934             if (*scanner.curptr != '\r') { 
    935                 pj_scan_get_until_ch(&scanner, '\r', &dummy); 
    936             } 
    937             pj_scan_get_newline(&scanner); 
    938         } 
     991         
     992        char errmsg[PJMEDIA_ERR_MSG_SIZE]; 
     993        pjmedia_strerror(ctx.last_error, errmsg, sizeof(errmsg)); 
     994 
     995        PJ_LOG(4, (THIS_FILE, "Error parsing SDP in line %d col %d: %s", 
     996                   scanner.line, pj_scan_get_col(&scanner), 
     997                   errmsg)); 
     998 
     999        session = NULL; 
     1000 
    9391001    } 
    9401002    PJ_END; 
    9411003 
    9421004    pj_scan_fini(&scanner); 
    943     return session; 
     1005 
     1006    *p_sdp = session; 
     1007    return ctx.last_error; 
    9441008} 
    9451009 
     
    9471011 * Print SDP description. 
    9481012 */ 
    949 PJ_DEF(int) pjsdp_print( const pjsdp_session_desc *desc, char *buf, pj_size_t size) 
     1013PJ_DEF(int) pjmedia_sdp_print( const pjmedia_sdp_session *desc,  
     1014                               char *buf, pj_size_t size) 
    9501015{ 
    9511016    return print_session(desc, buf, size); 
     
    9531018 
    9541019 
     1020/* 
     1021 * Clone session 
     1022 */ 
     1023PJ_DEF(pjmedia_sdp_session*)  
     1024pjmedia_sdp_session_clone( pj_pool_t *pool, 
     1025                           const pjmedia_sdp_session *rhs) 
     1026{ 
     1027    pjmedia_sdp_session *sess; 
     1028    unsigned i; 
     1029 
     1030    PJ_ASSERT_RETURN(pool && rhs, NULL); 
     1031 
     1032    sess = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_session)); 
     1033    PJ_ASSERT_RETURN(sess != NULL, NULL); 
     1034 
     1035    /* Clone origin line. */ 
     1036    pj_strdup(pool, &sess->origin.user, &rhs->origin.user); 
     1037    sess->origin.id = rhs->origin.id; 
     1038    sess->origin.version = rhs->origin.version; 
     1039    pj_strdup(pool, &sess->origin.net_type, &rhs->origin.net_type); 
     1040    pj_strdup(pool, &sess->origin.addr_type, &rhs->origin.addr_type); 
     1041    pj_strdup(pool, &sess->origin.addr, &rhs->origin.addr); 
     1042 
     1043    /* Clone subject line. */ 
     1044    pj_strdup(pool, &sess->name, &rhs->name); 
     1045 
     1046    /* Clone connection line */ 
     1047    if (rhs->conn) { 
     1048        sess->conn = pjmedia_sdp_conn_clone(pool, rhs->conn); 
     1049        PJ_ASSERT_RETURN(sess->conn != NULL, NULL); 
     1050    } 
     1051 
     1052    /* Clone time line. */ 
     1053    sess->time.start = rhs->time.start; 
     1054    sess->time.stop = rhs->time.stop; 
     1055 
     1056    /* Duplicate session attributes. */ 
     1057    sess->attr_count = rhs->attr_count; 
     1058    for (i=0; i<rhs->attr_count; ++i) { 
     1059        sess->attr[i] = pjmedia_sdp_attr_clone(pool, rhs->attr[i]); 
     1060    } 
     1061 
     1062    /* Duplicate media descriptors. */ 
     1063    sess->media_count = rhs->media_count; 
     1064    for (i=0; i<rhs->media_count; ++i) { 
     1065        sess->media[i] = pjmedia_sdp_media_clone(pool, rhs->media[i]); 
     1066    } 
     1067 
     1068    return sess; 
     1069} 
     1070 
     1071 
     1072#define CHECK(exp,ret)  do {                    \ 
     1073                            pj_assert(exp);     \ 
     1074                            if (!(exp))         \ 
     1075                                return ret;     \ 
     1076                        } while (0) 
     1077 
     1078/* Validate SDP connetion info. */ 
     1079static pj_status_t validate_sdp_conn(const pjmedia_sdp_conn *c) 
     1080{ 
     1081    CHECK( c, PJ_EINVAL); 
     1082    CHECK( pj_strcmp2(&c->net_type, "IN")==0, PJMEDIA_SDP_EINCONN); 
     1083    CHECK( pj_strcmp2(&c->addr_type, "IP4")==0 || 
     1084           pj_strcmp2(&c->addr_type, "IP6")==0,  
     1085           PJMEDIA_SDP_EINCONN); 
     1086    CHECK( c->addr.slen != 0, PJMEDIA_SDP_EINCONN); 
     1087 
     1088    return PJ_SUCCESS; 
     1089} 
     1090 
     1091 
     1092/* Validate SDP session descriptor. */ 
     1093PJ_DEF(pj_status_t) pjmedia_sdp_validate(const pjmedia_sdp_session *sdp) 
     1094{ 
     1095    unsigned i; 
     1096 
     1097    CHECK( sdp != NULL, PJ_EINVAL); 
     1098 
     1099    /* Validate origin line. */ 
     1100    CHECK( sdp->origin.user.slen != 0, PJMEDIA_SDP_EINORIGIN); 
     1101    CHECK( pj_strcmp2(&sdp->origin.net_type, "IN")==0,  
     1102           PJMEDIA_SDP_EINORIGIN); 
     1103    CHECK( pj_strcmp2(&sdp->origin.addr_type, "IP4")==0 || 
     1104           pj_strcmp2(&sdp->origin.addr_type, "IP6")==0,  
     1105           PJMEDIA_SDP_EINORIGIN); 
     1106    CHECK( sdp->origin.addr.slen != 0, PJMEDIA_SDP_EINORIGIN); 
     1107 
     1108    /* Validate subject line. */ 
     1109    CHECK( sdp->name.slen != 0, PJMEDIA_SDP_EINNAME); 
     1110 
     1111    /* Ignore start and stop time. */ 
     1112 
     1113    /* If session level connection info is present, validate it. */ 
     1114    if (sdp->conn) { 
     1115        pj_status_t status = validate_sdp_conn(sdp->conn); 
     1116        if (status != PJ_SUCCESS) 
     1117            return status; 
     1118    } 
     1119 
     1120    /* Validate each media. */ 
     1121    for (i=0; i<sdp->media_count; ++i) { 
     1122        const pjmedia_sdp_media *m = sdp->media[i]; 
     1123        unsigned j; 
     1124 
     1125        /* Validate the m= line. */ 
     1126        CHECK( m->desc.media.slen != 0, PJMEDIA_SDP_EINMEDIA); 
     1127        CHECK( m->desc.transport.slen != 0, PJMEDIA_SDP_EINMEDIA); 
     1128        CHECK( m->desc.fmt_count != 0, PJMEDIA_SDP_ENOFMT); 
     1129 
     1130        /* If media level connection info is present, validate it. */ 
     1131        if (m->conn) { 
     1132            pj_status_t status = validate_sdp_conn(m->conn); 
     1133            if (status != PJ_SUCCESS) 
     1134                return status; 
     1135        } 
     1136 
     1137        /* If media doesn't have connection info, then connection info 
     1138         * must be present in the session. 
     1139         */ 
     1140        if (m->conn == NULL) { 
     1141            if (sdp->conn == NULL) 
     1142                return PJMEDIA_SDP_EMISSINGCONN; 
     1143        } 
     1144 
     1145        /* Verify payload type. */ 
     1146        for (j=0; j<m->desc.fmt_count; ++j) { 
     1147            unsigned pt = pj_strtoul(&m->desc.fmt[j]); 
     1148 
     1149            /* Payload type is between 0 and 127. */ 
     1150            CHECK( pt <= 127, PJMEDIA_SDP_EINPT); 
     1151 
     1152            /* If port is not zero, then for each dynamic payload type, an 
     1153             * rtpmap attribute must be specified. 
     1154             */ 
     1155            if (m->desc.port != 0 && pt >= 96) { 
     1156                const pjmedia_sdp_attr *a; 
     1157 
     1158                a = pjmedia_sdp_media_find_attr2(m, "rtpmap", &m->desc.fmt[j]); 
     1159                CHECK( a != NULL, PJMEDIA_SDP_EMISSINGRTPMAP); 
     1160            } 
     1161        } 
     1162    } 
     1163 
     1164    /* Looks good. */ 
     1165    return PJ_SUCCESS; 
     1166} 
     1167 
     1168 
  • pjproject/trunk/pjmedia/src/test/test.c

    r112 r129  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
    19 #include <pj/os.h> 
    20 #include <pj/pool.h> 
    21 #include <pjmedia/sound.h> 
     19#include "test.h" 
    2220 
    23 pj_status_t session_test (pj_pool_factory *pf); 
    24 pj_status_t rtp_test (pj_pool_factory *pf); 
    25 pj_status_t sdp_test(pj_pool_factory *pf); 
    26 int jbuf_main(pj_pool_factory *pf); 
     21#define THIS_FILE   "test.c" 
    2722 
    28 int main() 
     23#define DO_TEST(test)   do { \ 
     24                            PJ_LOG(3, (THIS_FILE, "Running %s...", #test));  \ 
     25                            rc = test; \ 
     26                            PJ_LOG(3, (THIS_FILE,  \ 
     27                                       "%s(%d)",  \ 
     28                                       (rc ? "..ERROR" : "..success"), rc)); \ 
     29                            if (rc!=0) goto on_return; \ 
     30                        } while (0) 
     31 
     32 
     33pj_pool_factory *mem; 
     34 
     35 
     36void app_perror(pj_status_t status, const char *msg) 
    2937{ 
     38    char errbuf[PJMEDIA_ERR_MSG_SIZE]; 
     39     
     40    pjmedia_strerror(status, errbuf, sizeof(errbuf)); 
     41 
     42    PJ_LOG(3,(THIS_FILE, "%s: %s", msg, errbuf)); 
     43} 
     44 
     45int test_main(void) 
     46{ 
     47    int rc; 
    3048    pj_caching_pool caching_pool; 
    3149 
     
    3351    pj_caching_pool_init(&caching_pool, &pj_pool_factory_default_policy, 0); 
    3452 
    35     sdp_test (&caching_pool.factory); 
    36     rtp_test(&caching_pool.factory); 
    37     session_test (&caching_pool.factory); 
     53    pj_log_set_decor(PJ_LOG_HAS_NEWLINE); 
     54 
     55    mem = &caching_pool.factory; 
     56 
     57    DO_TEST(sdp_neg_test()); 
     58    //sdp_test (&caching_pool.factory); 
     59    //rtp_test(&caching_pool.factory); 
     60    //session_test (&caching_pool.factory); 
    3861    //jbuf_main(&caching_pool.factory); 
    3962 
     63    PJ_LOG(3,(THIS_FILE," ")); 
     64 
     65on_return: 
     66 
     67    if (rc != 0) { 
     68        PJ_LOG(3,(THIS_FILE,"Test completed with error(s)!")); 
     69    } else { 
     70        PJ_LOG(3,(THIS_FILE,"Looks like everything is okay!")); 
     71    } 
     72 
    4073    pj_caching_pool_destroy(&caching_pool); 
    41     return 0; 
     74    return rc; 
    4275} 
Note: See TracChangeset for help on using the changeset viewer.