Changeset 129
- Timestamp:
- Feb 2, 2006 7:16:07 PM (19 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 9 added
- 7 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/pjmedia.dsp
r121 r129 97 97 # Begin Source File 98 98 99 SOURCE=..\src\pjmedia\errno.c 100 # End Source File 101 # Begin Source File 102 99 103 SOURCE=..\src\pjmedia\g711.c 100 104 # End Source File … … 130 134 # Begin Source File 131 135 136 SOURCE=..\src\pjmedia\sdp_cmp.c 137 # End Source File 138 # Begin Source File 139 140 SOURCE=..\src\pjmedia\sdp_neg.c 141 # End Source File 142 # Begin Source File 143 132 144 SOURCE=..\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 133 154 # End Source File 134 155 # Begin Source File … … 150 171 # Begin Source File 151 172 173 SOURCE=..\include\pjmedia\errno.h 174 # End Source File 175 # Begin Source File 176 152 177 SOURCE=..\include\pjmedia\jbuf.h 153 178 # End Source File … … 174 199 # Begin Source File 175 200 201 SOURCE=..\include\pjmedia\sdp_neg.h 202 # End Source File 203 # Begin Source File 204 176 205 SOURCE=..\include\pjmedia\session.h 177 206 # End Source File … … 183 212 184 213 SOURCE=..\include\pjmedia\stream.h 214 # End Source File 215 # Begin Source File 216 217 SOURCE=..\include\pjmedia\types.h 185 218 # End Source File 186 219 # End Group -
pjproject/trunk/pjmedia/build/pjmedia.dsw
r121 r129 78 78 Project_Dep_Name pjsdp 79 79 End Project Dependency 80 Begin Project Dependency 81 Project_Dep_Name pjlib_util 82 End Project Dependency 80 83 }}} 81 84 -
pjproject/trunk/pjmedia/build/pjmedia_test.dsp
r65 r129 43 43 # PROP Target_Dir "" 44 44 # 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 /c45 # 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 46 46 # ADD BASE RSC /l 0x409 /d "NDEBUG" 47 47 # ADD RSC /l 0x409 /d "NDEBUG" … … 67 67 # PROP Target_Dir "" 68 68 # 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 /c69 # 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 70 70 # ADD BASE RSC /l 0x409 /d "_DEBUG" 71 71 # ADD RSC /l 0x409 /d "_DEBUG" … … 100 100 # Begin Source File 101 101 102 SOURCE=..\src\test\sdp_neg_test.c 103 # End Source File 104 # Begin Source File 105 102 106 SOURCE=..\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 103 116 # End Source File 104 117 # Begin Source File 105 118 106 119 SOURCE=..\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 132 SOURCE=..\src\test\test.c 107 133 # End Source File 108 134 # End Group … … 110 136 111 137 # PROP Default_Filter "h;hpp;hxx;hm;inl" 138 # Begin Source File 139 140 SOURCE=..\src\test\test.h 141 # End Source File 112 142 # End Group 113 143 # Begin Group "Resource Files" -
pjproject/trunk/pjmedia/include/pjmedia.h
r121 r129 20 20 #define __PJMEDIA_H__ 21 21 22 #include <pjmedia/types.h> 23 #include <pjmedia/errno.h> 22 24 #include <pjmedia/codec.h> 23 25 #include <pjmedia/jbuf.h> … … 25 27 #include <pjmedia/rtcp.h> 26 28 #include <pjmedia/rtp.h> 27 #include <pjmedia/session.h>29 //#include <pjmedia/session.h> 28 30 #include <pjmedia/sound.h> 29 31 #include <pjmedia/sdp.h> 32 #include <pjmedia/sdp_neg.h> 30 33 31 34 #endif /* __PJMEDIA_H__ */ -
pjproject/trunk/pjmedia/include/pjmedia/sdp.h
r121 r129 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 #ifndef __PJ SDP_SDP_H__20 #define __PJ SDP_SDP_H__19 #ifndef __PJMEDIA_SDP_H__ 20 #define __PJMEDIA_SDP_H__ 21 21 22 22 /** … … 36 36 */ 37 37 38 #include <pj /types.h>38 #include <pjmedia/types.h> 39 39 40 40 PJ_BEGIN_DECL … … 44 44 #define PJSDP_MAX_MEDIA 16 45 45 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 */ 55 struct 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 */ 71 PJ_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 */ 83 PJ_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 */ 99 PJ_DECL(pjmedia_sdp_attr*) 100 pjmedia_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 */ 117 PJ_DECL(pjmedia_sdp_attr*) 118 pjmedia_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 */ 133 PJ_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 */ 148 PJ_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 */ 165 PJ_DECL(pj_status_t) pjmedia_sdp_attr_remove(unsigned *count, 166 pjmedia_sdp_attr *attr_array[], 167 pjmedia_sdp_attr *attr); 103 168 104 169 … … 106 171 * SDP \a rtpmap attribute. 107 172 */ 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; 173 struct 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 */ 192 PJ_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 */ 206 PJ_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 */ 219 PJ_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); 116 222 117 223 … … 119 225 * SDP \a fmtp attribute. 120 226 */ 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); 227 struct 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 */ 243 PJ_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 */ 190 251 191 252 /** 192 253 * SDP connection info. 193 254 */ 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; 255 struct 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 200 262 201 263 /** … … 207 269 * @return the new connection info. 208 270 */ 209 PJ_DECL(pjsdp_conn_info*) pjsdp_conn_info_clone (pj_pool_t *pool, 210 const pjsdp_conn_info *rhs); 271 PJ_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 */ 211 280 212 281 /** 213 282 * SDP media description. 214 283 */ 215 typedef struct pjsdp_media_desc 284 struct pjmedia_sdp_media 216 285 { 217 286 struct 218 287 { 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. */ 225 294 } desc; 226 295 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 232 302 233 303 /** … … 239 309 * @return a new media description. 240 310 */ 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. 311 PJ_DECL(pjmedia_sdp_media*) 312 pjmedia_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. 246 317 * 247 318 * @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 */ 326 PJ_DECL(pjmedia_sdp_attr*) 327 pjmedia_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 */ 342 PJ_DECL(pjmedia_sdp_attr*) 343 pjmedia_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 */ 354 PJ_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 */ 365 PJ_DECL(unsigned) 366 pjmedia_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 */ 373 PJ_DECL(pj_status_t) 374 pjmedia_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 */ 387 PJ_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 */ 265 397 266 398 … … 268 400 * This structure describes SDP session description. 269 401 */ 270 typedef struct pjsdp_session_desc 271 { 402 struct pjmedia_sdp_session 403 { 404 /** Origin (o= line) */ 272 405 struct 273 406 { 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. */ 280 413 } origin; 281 414 282 pj_str_t name; 283 pj sdp_conn_info *conn;415 pj_str_t name; /**< Subject line (s=) */ 416 pjmedia_sdp_conn *conn; /**< Connection line (c=) */ 284 417 418 /** Session time (t= line) */ 285 419 struct 286 420 { 287 pj_uint32_t start; 288 pj_uint32_t stop; 421 pj_uint32_t start; /**< Start time. */ 422 pj_uint32_t stop; /**< Stop time. */ 289 423 } time; 290 424 291 unsigned attr_count;292 pj sdp_attr *attr[PJSDP_MAX_ATTR];293 294 unsigned media_count;295 pj sdp_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 }; 298 432 299 433 … … 307 441 * @return SDP session description. 308 442 */ 309 PJ_DECL(pjsdp_session_desc*) pjsdp_parse( char *buf, pj_size_t len, 310 pj_pool_t *pool); 443 PJ_DECL(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool, 444 char *buf, pj_size_t len, 445 pjmedia_sdp_session **p_sdp ); 311 446 312 447 /** … … 319 454 * @return the length printed, or -1. 320 455 */ 321 PJ_DECL(int) pjsdp_print( const pjsdp_session_desc *desc, 322 char *buf, pj_size_t size); 323 456 PJ_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 */ 463 PJ_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 */ 474 PJ_DECL(pjmedia_sdp_session*) 475 pjmedia_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 */ 487 PJ_DECL(pj_status_t) pjmedia_sdp_session_cmp(const pjmedia_sdp_session *sd1, 488 const pjmedia_sdp_session *sd2, 489 unsigned option); 490 491 492 PJ_END_DECL 324 493 325 494 /** … … 327 496 */ 328 497 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 301 301 } 302 302 303 if ( jb->lst.count > jb->max_level)303 if ((int)jb->lst.count > jb->max_level) 304 304 jb->max_level++; 305 305 -
pjproject/trunk/pjmedia/src/pjmedia/sdp.c
r121 r129 18 18 */ 19 19 #include <pjmedia/sdp.h> 20 #include <pjmedia/errno.h> 20 21 #include <pjlib-util/scanner.h> 22 #include <pj/array.h> 21 23 #include <pj/except.h> 22 24 #include <pj/log.h> … … 25 27 #include <pj/pool.h> 26 28 #include <pj/assert.h> 29 #include <pj/ctype.h> 30 27 31 28 32 enum { … … 32 36 #define TOKEN "-.!%*_=`'~" 33 37 #define NTP_OFFSET ((pj_uint32_t)2208988800) 34 #define LOG_THIS "sdp" 38 #define THIS_FILE "sdp.c" 39 40 typedef struct parse_context 41 { 42 pj_status_t last_error; 43 } parse_context; 44 35 45 36 46 /* 37 47 * Prototypes for line parser. 38 48 */ 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 }; 49 static void parse_version(pj_scanner *scanner, parse_context *ctx); 50 static void parse_origin(pj_scanner *scanner, pjmedia_sdp_session *ses, 51 parse_context *ctx); 52 static void parse_time(pj_scanner *scanner, pjmedia_sdp_session *ses, 53 parse_context *ctx); 54 static void parse_generic_line(pj_scanner *scanner, pj_str_t *str, 55 parse_context *ctx); 56 static void parse_connection_info(pj_scanner *scanner, pjmedia_sdp_conn *conn, 57 parse_context *ctx); 58 static pjmedia_sdp_attr *parse_attr(pj_pool_t *pool, pj_scanner *scanner, 59 parse_context *ctx); 60 static void parse_media(pj_scanner *scanner, pjmedia_sdp_media *med, 61 parse_context *ctx); 62 122 63 123 64 /* … … 144 85 } 145 86 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 } 87 PJ_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 108 PJ_DEF(pjmedia_sdp_attr*) pjmedia_sdp_attr_clone(pj_pool_t *pool, 109 const pjmedia_sdp_attr *rhs) 110 { 111 pjmedia_sdp_attr *attr; 154 112 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 123 PJ_DEF(pjmedia_sdp_attr*) 124 pjmedia_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 162 PJ_DEF(pjmedia_sdp_attr*) 163 pjmedia_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 177 PJ_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 191 PJ_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 218 PJ_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 241 PJ_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 319 PJ_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 361 PJ_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 374 PJ_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; 161 408 *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; 166 414 *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) { 172 421 *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 438 static int print_connection_info( pjmedia_sdp_conn *c, char *buf, int len) 353 439 { 354 440 char *p = buf; … … 373 459 } 374 460 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)); 461 PJ_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)); 378 465 if (!c) return NULL; 379 466 … … 385 472 } 386 473 387 static int print_media_desc( pjsdp_media_desc *m, char *buf, int len) 474 static 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 498 static int print_media_desc( pjmedia_sdp_media *m, char *buf, int len) 388 499 { 389 500 char *p = buf; … … 440 551 } 441 552 442 PJ_DEF(pjsdp_media_desc*) pjsdp_media_desc_clone (pj_pool_t *pool, 443 const pjsdp_media_desc *rhs) 553 PJ_DEF(pjmedia_sdp_media*) pjmedia_sdp_media_clone( 554 pj_pool_t *pool, 555 const pjmedia_sdp_media *rhs) 444 556 { 445 557 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); 449 560 450 561 pj_strdup (pool, &m->desc.media, &rhs->desc.media); … … 457 568 458 569 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); 462 572 } else { 463 573 m->conn = NULL; … … 466 576 m->attr_count = rhs->attr_count; 467 577 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); 471 580 } 472 581 … … 474 583 } 475 584 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) 585 PJ_DEF(pjmedia_sdp_attr*) 586 pjmedia_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 595 PJ_DEF(pjmedia_sdp_attr*) 596 pjmedia_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 604 PJ_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 610 PJ_DEF(unsigned) 611 pjmedia_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 617 PJ_DEF(pj_status_t) 618 pjmedia_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 624 static int print_session(const pjmedia_sdp_session *ses, 625 char *buf, pj_ssize_t len) 507 626 { 508 627 char *p = buf; … … 605 724 */ 606 725 607 static void parse_version(pj_scanner *scanner) 608 { 726 static void parse_version(pj_scanner *scanner, parse_context *ctx) 727 { 728 ctx->last_error = PJMEDIA_SDP_EINVER; 729 609 730 pj_scan_advance_n(scanner, 3, SKIP_WS); 610 731 pj_scan_get_newline(scanner); 611 732 } 612 733 613 static void parse_origin(pj_scanner *scanner, pjsdp_session_desc *ses) 734 static void parse_origin(pj_scanner *scanner, pjmedia_sdp_session *ses, 735 parse_context *ctx) 614 736 { 615 737 pj_str_t str; 738 739 ctx->last_error = PJMEDIA_SDP_EINORIGIN; 616 740 617 741 /* o= */ … … 647 771 } 648 772 649 static void parse_time(pj_scanner *scanner, pjsdp_session_desc *ses) 773 static void parse_time(pj_scanner *scanner, pjmedia_sdp_session *ses, 774 parse_context *ctx) 650 775 { 651 776 pj_str_t str; 777 778 ctx->last_error = PJMEDIA_SDP_EINTIME; 652 779 653 780 /* t= */ … … 668 795 } 669 796 670 static void parse_generic_line(pj_scanner *scanner, pj_str_t *str) 671 { 797 static void parse_generic_line(pj_scanner *scanner, pj_str_t *str, 798 parse_context *ctx) 799 { 800 ctx->last_error = PJMEDIA_SDP_EINSDP; 801 672 802 /* x= */ 673 803 pj_scan_advance_n(scanner, 2, SKIP_WS); … … 680 810 } 681 811 682 static void parse_connection_info(pj_scanner *scanner, pjsdp_conn_info *conn) 683 { 812 static void parse_connection_info(pj_scanner *scanner, pjmedia_sdp_conn *conn, 813 parse_context *ctx) 814 { 815 ctx->last_error = PJMEDIA_SDP_EINCONN; 816 684 817 /* c= */ 685 818 pj_scan_advance_n(scanner, 2, SKIP_WS); … … 700 833 } 701 834 702 static void parse_media(pj_scanner *scanner, pjsdp_media_desc *med) 835 static void parse_media(pj_scanner *scanner, pjmedia_sdp_media *med, 836 parse_context *ctx) 703 837 { 704 838 pj_str_t str; 839 840 ctx->last_error = PJMEDIA_SDP_EINMEDIA; 705 841 706 842 /* m= */ … … 742 878 } 743 879 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 880 static void on_scanner_error(pj_scanner *scanner) 881 { 801 882 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 887 static 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)); 827 895 828 896 /* skip a= */ … … 830 898 831 899 /* 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 851 910 /* newline */ 852 911 pj_scan_get_newline(scanner); 853 912 854 913 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);862 914 } 863 915 … … 865 917 * Parse SDP message. 866 918 */ 867 PJ_DEF(pjsdp_session_desc*) pjsdp_parse( char *buf, pj_size_t len, 868 pj_pool_t *pool) 919 PJ_DEF(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool, 920 char *buf, pj_size_t len, 921 pjmedia_sdp_session **p_sdp) 869 922 { 870 923 pj_scanner scanner; 871 pj sdp_session_desc*session;872 pj sdp_media_desc*media = NULL;924 pjmedia_sdp_session *session; 925 pjmedia_sdp_media *media = NULL; 873 926 void *attr; 874 pj sdp_conn_info*conn;927 pjmedia_sdp_conn *conn; 875 928 pj_str_t dummy; 876 929 int cur_name = 254; 930 parse_context ctx; 877 931 PJ_USE_EXCEPTION; 878 932 933 ctx.last_error = PJ_SUCCESS; 934 879 935 init_sdp_parser(); 880 936 881 937 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); 883 940 884 941 PJ_TRY { … … 887 944 switch (cur_name) { 888 945 case 'a': 889 attr = parse_attr(pool, &scanner );946 attr = parse_attr(pool, &scanner, &ctx); 890 947 if (attr) { 891 948 if (media) { … … 897 954 break; 898 955 case 'o': 899 parse_origin(&scanner, session );956 parse_origin(&scanner, session, &ctx); 900 957 break; 901 958 case 's': 902 parse_generic_line(&scanner, &session->name );959 parse_generic_line(&scanner, &session->name, &ctx); 903 960 break; 904 961 case 'c': 905 962 conn = pj_pool_calloc(pool, 1, sizeof(*conn)); 906 parse_connection_info(&scanner, conn );963 parse_connection_info(&scanner, conn, &ctx); 907 964 if (media) { 908 965 media->conn = conn; … … 912 969 break; 913 970 case 't': 914 parse_time(&scanner, session );971 parse_time(&scanner, session, &ctx); 915 972 break; 916 973 case 'm': 917 974 media = pj_pool_calloc(pool, 1, sizeof(*media)); 918 parse_media(&scanner, media );975 parse_media(&scanner, media, &ctx); 919 976 session->media[ session->media_count++ ] = media; 920 977 break; 921 978 case 'v': 922 parse_version(&scanner );979 parse_version(&scanner, &ctx); 923 980 break; 924 981 default: 925 parse_generic_line(&scanner, &dummy );982 parse_generic_line(&scanner, &dummy, &ctx); 926 983 break; 927 984 } 928 985 } 986 987 ctx.last_error = PJ_SUCCESS; 988 929 989 } 930 990 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 939 1001 } 940 1002 PJ_END; 941 1003 942 1004 pj_scan_fini(&scanner); 943 return session; 1005 1006 *p_sdp = session; 1007 return ctx.last_error; 944 1008 } 945 1009 … … 947 1011 * Print SDP description. 948 1012 */ 949 PJ_DEF(int) pjsdp_print( const pjsdp_session_desc *desc, char *buf, pj_size_t size) 1013 PJ_DEF(int) pjmedia_sdp_print( const pjmedia_sdp_session *desc, 1014 char *buf, pj_size_t size) 950 1015 { 951 1016 return print_session(desc, buf, size); … … 953 1018 954 1019 1020 /* 1021 * Clone session 1022 */ 1023 PJ_DEF(pjmedia_sdp_session*) 1024 pjmedia_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. */ 1079 static 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. */ 1093 PJ_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 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 #include <pj/os.h> 20 #include <pj/pool.h> 21 #include <pjmedia/sound.h> 19 #include "test.h" 22 20 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" 27 22 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 33 pj_pool_factory *mem; 34 35 36 void app_perror(pj_status_t status, const char *msg) 29 37 { 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 45 int test_main(void) 46 { 47 int rc; 30 48 pj_caching_pool caching_pool; 31 49 … … 33 51 pj_caching_pool_init(&caching_pool, &pj_pool_factory_default_policy, 0); 34 52 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); 38 61 //jbuf_main(&caching_pool.factory); 39 62 63 PJ_LOG(3,(THIS_FILE," ")); 64 65 on_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 40 73 pj_caching_pool_destroy(&caching_pool); 41 return 0;74 return rc; 42 75 }
Note: See TracChangeset
for help on using the changeset viewer.