/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJMEDIA_SDP_H__
#define __PJMEDIA_SDP_H__

/**
 * @file sdp.h
 * @brief SDP header file.
 */
#include <pjmedia/types.h>
#include <pj/sock.h>

/**
 * @defgroup PJMEDIA_SDP SDP Parsing and Data Structure
 * @ingroup PJMEDIA_SESSION
 * @brief SDP data structure representation and parsing
 * @{
 *
 * The basic SDP session descriptor and elements are described in header
 * file <b><pjmedia/sdp.h></b>. This file contains declaration for
 * SDP session descriptor and SDP media descriptor, along with their
 * attributes. This file also declares functions to parse SDP message.
 */


PJ_BEGIN_DECL

/**
 * The PJMEDIA_MAX_SDP_FMT macro defines maximum format in a media line.
 */
#ifndef PJMEDIA_MAX_SDP_FMT
#   define PJMEDIA_MAX_SDP_FMT          32
#endif

/**
 * The PJMEDIA_MAX_SDP_BANDW macro defines maximum bandwidth information
 * lines in a media line.
 */
#ifndef PJMEDIA_MAX_SDP_BANDW
#   define PJMEDIA_MAX_SDP_BANDW        4
#endif

/**
 * The PJMEDIA_MAX_SDP_ATTR macro defines maximum SDP attributes in media and
 * session descriptor.
 */
#ifndef PJMEDIA_MAX_SDP_ATTR
#   define PJMEDIA_MAX_SDP_ATTR         (PJMEDIA_MAX_SDP_FMT*2 + 4)
#endif

/**
 * The PJMEDIA_MAX_SDP_MEDIA macro defines maximum SDP media lines in a
 * SDP session descriptor.
 */
#ifndef PJMEDIA_MAX_SDP_MEDIA
#   define PJMEDIA_MAX_SDP_MEDIA        16
#endif


/* **************************************************************************
 * SDP ATTRIBUTES
 ***************************************************************************
 */

/** 
 * Generic representation of attribute.
 */
struct pjmedia_sdp_attr
{
    pj_str_t            name;       /**< Attribute name.    */
    pj_str_t            value;      /**< Attribute value.   */
};

/**
 * @see pjmedia_sdp_attr
 */
typedef struct pjmedia_sdp_attr pjmedia_sdp_attr;


/**
 * Create SDP attribute.
 *
 * @param pool          Pool to create the attribute.
 * @param name          Attribute name.
 * @param value         Optional attribute value.
 *
 * @return              The new SDP attribute.
 */
PJ_DECL(pjmedia_sdp_attr*) pjmedia_sdp_attr_create(pj_pool_t *pool,
                                                   const char *name,
                                                   const pj_str_t *value);

/** 
 * Clone attribute 
 *
 * @param pool          Pool to be used.
 * @param attr          The attribute to clone.
 *
 * @return              New attribute as cloned from the attribute.
 */
PJ_DECL(pjmedia_sdp_attr*) pjmedia_sdp_attr_clone(pj_pool_t *pool, 
                                                  const pjmedia_sdp_attr*attr);

/** 
 * Find the first attribute with the specified type.
 *
 * @param count         Number of attributes in the array.
 * @param attr_array    Array of attributes.
 * @param name          Attribute name to find.
 * @param fmt           Optional string to indicate which payload format
 *                      to find for \a rtpmap and \a fmt attributes. For other
 *                      types of attributes, the value should be NULL.
 *
 * @return              The specified attribute, or NULL if it can't be found.
 *
 * @see pjmedia_sdp_attr_find2, pjmedia_sdp_media_find_attr, 
 *      pjmedia_sdp_media_find_attr2
 */
PJ_DECL(pjmedia_sdp_attr*) 
pjmedia_sdp_attr_find(unsigned count, 
                      pjmedia_sdp_attr *const attr_array[],
                      const pj_str_t *name, const pj_str_t *fmt);

/** 
 * Find the first attribute with the specified type.
 *
 * @param count         Number of attributes in the array.
 * @param attr_array    Array of attributes.
 * @param name          Attribute name to find.
 * @param fmt           Optional string to indicate which payload format
 *                      to find for \a rtpmap and \a fmt attributes. For other
 *                      types of attributes, the value should be NULL.
 *
 * @return              The specified attribute, or NULL if it can't be found.
 *
 * @see pjmedia_sdp_attr_find, pjmedia_sdp_media_find_attr,
 *      pjmedia_sdp_media_find_attr2
 */
PJ_DECL(pjmedia_sdp_attr*) 
pjmedia_sdp_attr_find2(unsigned count, 
                       pjmedia_sdp_attr *const attr_array[],
                       const char *name, const pj_str_t *fmt);

/**
 * Add a new attribute to array of attributes.
 *
 * @param count         Number of attributes in the array.
 * @param attr_array    Array of attributes.
 * @param attr          The attribute to add.
 *
 * @return              PJ_SUCCESS or the error code.
 *
 * @see pjmedia_sdp_media_add_attr
 */
PJ_DECL(pj_status_t) pjmedia_sdp_attr_add(unsigned *count,
                                          pjmedia_sdp_attr *attr_array[],
                                          pjmedia_sdp_attr *attr);

/**
 * Remove all attributes with the specified name in array of attributes.
 *
 * @param count         Number of attributes in the array.
 * @param attr_array    Array of attributes.
 * @param name          Attribute name to find.
 *
 * @return              Number of attributes removed.
 *
 * @see pjmedia_sdp_media_remove_all_attr
 */
PJ_DECL(unsigned) pjmedia_sdp_attr_remove_all(unsigned *count,
                                              pjmedia_sdp_attr *attr_array[],
                                              const char *name);


/**
 * Remove the specified attribute from the attribute array.
 *
 * @param count         Number of attributes in the array.
 * @param attr_array    Array of attributes.
 * @param attr          The attribute instance to remove.
 *
 * @return              PJ_SUCCESS when attribute has been removed, or 
 *                      PJ_ENOTFOUND when the attribute can not be found.
 *
 * @see pjmedia_sdp_media_remove_attr
 */
PJ_DECL(pj_status_t) pjmedia_sdp_attr_remove(unsigned *count,
                                             pjmedia_sdp_attr *attr_array[],
                                             pjmedia_sdp_attr *attr);


/**
 * This structure declares SDP \a rtpmap attribute.
 */
struct pjmedia_sdp_rtpmap
{
    pj_str_t            pt;         /**< Payload type.      */
    pj_str_t            enc_name;   /**< Encoding name.     */
    unsigned            clock_rate; /**< Clock rate.        */
    pj_str_t            param;      /**< Parameter.         */
};

/**
 * @see pjmedia_sdp_rtpmap
 */
typedef struct pjmedia_sdp_rtpmap pjmedia_sdp_rtpmap;


/**
 * Convert generic attribute to SDP \a rtpmap. This function allocates
 * a new attribute and call #pjmedia_sdp_attr_get_rtpmap().
 *
 * @param pool          Pool used to create the rtpmap attribute.
 * @param attr          Generic attribute to be converted to rtpmap, which
 *                      name must be "rtpmap".
 * @param p_rtpmap      Pointer to receive SDP rtpmap attribute.
 *
 * @return              PJ_SUCCESS if the attribute can be successfully
 *                      converted to \a rtpmap type.
 *
 * @see pjmedia_sdp_attr_get_rtpmap
 */
PJ_DECL(pj_status_t) pjmedia_sdp_attr_to_rtpmap(pj_pool_t *pool,
                                                const pjmedia_sdp_attr *attr,
                                                pjmedia_sdp_rtpmap **p_rtpmap);


/**
 * Get the rtpmap representation of the same SDP attribute.
 *
 * @param attr          Generic attribute to be converted to rtpmap, which
 *                      name must be "rtpmap". Attribute value must be
 *                      terminated with a NULL, CR, or LF character.
 * @param rtpmap        SDP \a rtpmap attribute to be initialized.
 *
 * @return              PJ_SUCCESS if the attribute can be successfully
 *                      converted to \a rtpmap attribute.
 *
 * @see pjmedia_sdp_attr_to_rtpmap
 */
PJ_DECL(pj_status_t) pjmedia_sdp_attr_get_rtpmap(const pjmedia_sdp_attr *attr,
                                                 pjmedia_sdp_rtpmap *rtpmap);


/**
 * Convert \a rtpmap attribute to generic attribute.
 *
 * @param pool          Pool to be used.
 * @param rtpmap        The \a rtpmap attribute.
 * @param p_attr        Pointer to receive the generic SDP attribute.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) 
pjmedia_sdp_rtpmap_to_attr( pj_pool_t *pool,
                            const pjmedia_sdp_rtpmap *rtpmap,
                            pjmedia_sdp_attr **p_attr);


/**
 * This structure describes SDP \a fmtp attribute.
 */
typedef struct pjmedia_sdp_fmtp
{
    pj_str_t            fmt;        /**< Format type.               */
    pj_str_t            fmt_param;  /**< Format specific parameter. */
} pjmedia_sdp_fmtp;


/**
 * Get the fmtp representation of the same SDP attribute.
 *
 * @param attr          Generic attribute to be converted to fmtp, which
 *                      name must be "fmtp".
 * @param fmtp          SDP fmtp attribute to be initialized.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_attr_get_fmtp(const pjmedia_sdp_attr *attr,
                                               pjmedia_sdp_fmtp *fmtp);


/**
 * This structure describes SDP \a rtcp attribute.
 */
typedef struct pjmedia_sdp_rtcp_attr
{
    unsigned    port;       /**< RTCP port number.          */
    pj_str_t    net_type;   /**< Optional network type.     */
    pj_str_t    addr_type;  /**< Optional address type.     */
    pj_str_t    addr;       /**< Optional address.          */
} pjmedia_sdp_rtcp_attr;


/**
 * Parse a generic SDP attribute to get SDP rtcp attribute values.
 *
 * @param attr          Generic attribute to be converted to rtcp, which
 *                      name must be "rtcp".
 * @param rtcp          SDP rtcp attribute to be initialized.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_attr_get_rtcp(const pjmedia_sdp_attr *attr,
                                               pjmedia_sdp_rtcp_attr *rtcp);


/**
 * Create a=rtcp attribute.
 *
 * @param pool          Pool to create the attribute.
 * @param a             Socket address.
 *
 * @return              SDP RTCP attribute.
 */
PJ_DECL(pjmedia_sdp_attr*) pjmedia_sdp_attr_create_rtcp(pj_pool_t *pool,
                                                        const pj_sockaddr *a);


/**
 * This structure describes SDP \a ssrc attribute.
 */
typedef struct pjmedia_sdp_ssrc_attr
{
    pj_uint32_t ssrc;       /**< RTP SSRC.      */
    pj_str_t    cname;      /**< RTCP CNAME.    */
} pjmedia_sdp_ssrc_attr;


/**
 * Parse a generic SDP attribute to get SDP ssrc attribute values.
 *
 * @param attr          Generic attribute to be converted to ssrc, which
 *                      name must be "ssrc".
 * @param rtcp          SDP ssrc attribute to be initialized.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_attr_get_ssrc(const pjmedia_sdp_attr *attr,
                                               pjmedia_sdp_ssrc_attr *rtcp);


/**
 * Create a=ssrc attribute.
 *
 * @param pool          Pool to create the attribute.
 * @param ssrc          SSRC identifier.
 * @param cname         CNAME.
 *
 * @return              SDP SSRC attribute.
 */
PJ_DECL(pjmedia_sdp_attr*) pjmedia_sdp_attr_create_ssrc(pj_pool_t *pool,
                                                        pj_uint32_t ssrc,
                                                        const pj_str_t *cname);


/**
 * Create a=label attribute.
 *
 * @param pool          Pool to create the attribute.
 * @param attr          Attribute to create.
 *
 * @return              SDP label attribute.
 */
PJ_DECL(pjmedia_sdp_attr*) pjmedia_sdp_attr_create_label(pj_pool_t *pool,
                                                const pj_str_t *label_str);


/* **************************************************************************
 * SDP CONNECTION INFO
 ****************************************************************************
 */

/**
 * This structure describes SDP connection info ("c=" line). 
 */
struct pjmedia_sdp_conn
{
    pj_str_t    net_type;       /**< Network type ("IN").               */
    pj_str_t    addr_type;      /**< Address type ("IP4", "IP6").       */
    pj_str_t    addr;           /**< The address.                       */
    pj_uint8_t  ttl;            /**< Multicast address TTL              */
    pj_uint8_t  no_addr;        /**< Multicast number of addresses      */
};


/**
 * @see pjmedia_sdp_conn
 */
typedef struct pjmedia_sdp_conn pjmedia_sdp_conn;


/** 
 * Clone connection info. 
 * 
 * @param pool      Pool to allocate memory for the new connection info.
 * @param rhs       The connection into to clone.
 *
 * @return          The new connection info.
 */
PJ_DECL(pjmedia_sdp_conn*) pjmedia_sdp_conn_clone(pj_pool_t *pool, 
                                                  const pjmedia_sdp_conn *rhs);


/** 
 * Compare connection info. 
 * 
 * @param conn1     The first connection info to compare.
 * @param conn2     The second connection info to compare.
 * @param option    Comparison option, which should be zero for now.
 *
 * @return          PJ_SUCCESS when both connection info are equal, otherwise
 *                  returns PJMEDIA_SDP_ECONNNOTEQUAL.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_conn_cmp(const pjmedia_sdp_conn *conn1, 
                                          const pjmedia_sdp_conn *conn2,
                                          unsigned option);


/* **************************************************************************
 * SDP BANDWIDTH INFO
 ****************************************************************************
 */

/**
 * This structure describes SDP bandwidth info ("b=" line). 
 */
typedef struct pjmedia_sdp_bandw
{
    pj_str_t    modifier;       /**< Bandwidth modifier.                */
    pj_uint32_t value;          /**< Bandwidth value.                   */
} pjmedia_sdp_bandw;


/** 
 * Clone bandwidth info. 
 * 
 * @param pool      Pool to allocate memory for the new bandwidth info.
 * @param rhs       The bandwidth into to clone.
 *
 * @return          The new bandwidth info.
 */
PJ_DECL(pjmedia_sdp_bandw*)
pjmedia_sdp_bandw_clone(pj_pool_t *pool, const pjmedia_sdp_bandw *rhs);



/* **************************************************************************
 * SDP MEDIA INFO/LINE
 ****************************************************************************
 */

/**
 * This structure describes SDP media descriptor. A SDP media descriptor
 * starts with "m=" line and contains the media attributes and optional
 * connection line.
 */
struct pjmedia_sdp_media
{
    /** Media descriptor line ("m=" line) */
    struct
    {
        pj_str_t    media;              /**< Media type ("audio", "video")  */
        pj_uint16_t port;               /**< Port number.                   */
        unsigned    port_count;         /**< Port count, used only when >2  */
        pj_str_t    transport;          /**< Transport ("RTP/AVP")          */
        unsigned    fmt_count;          /**< Number of formats.             */
        pj_str_t    fmt[PJMEDIA_MAX_SDP_FMT];       /**< Media formats.     */
    } desc;

    pjmedia_sdp_conn   *conn;           /**< Optional connection info.      */
    unsigned            bandw_count;    /**< Number of bandwidth info.      */
    pjmedia_sdp_bandw  *bandw[PJMEDIA_MAX_SDP_BANDW]; /**< Bandwidth info.  */
    unsigned            attr_count;     /**< Number of attributes.          */
    pjmedia_sdp_attr   *attr[PJMEDIA_MAX_SDP_ATTR];   /**< Attributes.      */

};


/**
 * @see pjmedia_sdp_media
 */
typedef struct pjmedia_sdp_media pjmedia_sdp_media;

/**
 * Print media description to a buffer.
 *
 * @param media     The media description.
 * @param buf       The buffer.
 * @param size      The buffer length.
 *
 * @return          The length printed, or -1 if the buffer is too
 *                  short.
 */
PJ_DECL(int) pjmedia_sdp_media_print(const pjmedia_sdp_media *media, char *buf, pj_size_t size);

/** 
 * Clone SDP media description. 
 *
 * @param pool      Pool to allocate memory for the new media description.
 * @param rhs       The media descriptin to clone.
 *
 * @return          New media description.
 */
PJ_DECL(pjmedia_sdp_media*) 
pjmedia_sdp_media_clone( pj_pool_t *pool, 
                         const pjmedia_sdp_media *rhs);

/**
 * Print attribute to a buffer.
 *
 * @param attr      The attribute.
 * @param buf       The buffer.
 * @param size      The buffer length.
 *
 * @return          The length printed, or -1 if the buffer is too
 *                  short.
 */
PJ_DECL(int) pjmedia_sdp_attr_print(const pjmedia_sdp_attr *attr, char *buf, pj_size_t size);

/**
 * Find the first occurence of the specified attribute name in the media 
 * descriptor. Optionally the format may be specified.
 *
 * @param m             The SDP media description.
 * @param name          Attribute name to find.
 * @param fmt           Optional payload type to match in the
 *                      attribute list, when the attribute is \a rtpmap
 *                      or \a fmtp. For other types of SDP attributes, this
 *                      value should be NULL.
 *
 * @return              The first instance of the specified attribute or NULL.
 */
PJ_DECL(pjmedia_sdp_attr*) 
pjmedia_sdp_media_find_attr(const pjmedia_sdp_media *m,
                            const pj_str_t *name, const pj_str_t *fmt);


/**
 * Find the first occurence of the specified attribute name in the SDP media 
 * descriptor. Optionally the format may be specified.
 *
 * @param m             The SDP media description.
 * @param name          Attribute name to find.
 * @param fmt           Optional payload type to match in the
 *                      attribute list, when the attribute is \a rtpmap
 *                      or \a fmtp. For other types of SDP attributes, this
 *                      value should be NULL.
 *
 * @return              The first instance of the specified attribute or NULL.
 */
PJ_DECL(pjmedia_sdp_attr*) 
pjmedia_sdp_media_find_attr2(const pjmedia_sdp_media *m,
                             const char *name, const pj_str_t *fmt);

/**
 * Add new attribute to the media descriptor.
 *
 * @param m             The SDP media description.
 * @param attr          Attribute to add.
 *
 * @return              PJ_SUCCESS or the appropriate error code.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_media_add_attr(pjmedia_sdp_media *m,
                                                pjmedia_sdp_attr *attr);

/**
 * Remove all attributes with the specified name from the SDP media
 * descriptor.
 *
 * @param m             The SDP media description.
 * @param name          Attribute name to remove.
 *
 * @return              The number of attributes removed.
 */
PJ_DECL(unsigned) 
pjmedia_sdp_media_remove_all_attr(pjmedia_sdp_media *m,
                                  const char *name);


/**
 * Remove the occurence of the specified attribute from the SDP media
 * descriptor.
 *
 * @param m             The SDP media descriptor.
 * @param attr          The attribute to find and remove.
 *
 * @return              PJ_SUCCESS if the attribute can be found and has
 *                      been removed from the array.
 */
PJ_DECL(pj_status_t)
pjmedia_sdp_media_remove_attr(pjmedia_sdp_media *m,
                              pjmedia_sdp_attr *attr);


/**
 * Compare two SDP media for equality.
 *
 * @param sd1       The first SDP media to compare.
 * @param sd2       The second SDP media to compare.
 * @param option    Comparison option, which should be zero for now.
 *
 * @return          PJ_SUCCESS when both SDP medias are equal, or the
 *                  appropriate status code describing which part of
 *                  the descriptors that are not equal.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_media_cmp(const pjmedia_sdp_media *sd1,
                                           const pjmedia_sdp_media *sd2,
                                           unsigned option);


/**
 * Compare two media transports for compatibility.
 *
 * @param t1        The first media transport to compare.
 * @param t2        The second media transport to compare.
 *
 * @return          PJ_SUCCESS when both media transports are compatible,
 *                  otherwise returns PJMEDIA_SDP_ETPORTNOTEQUAL.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_transport_cmp(const pj_str_t *t1,
                                               const pj_str_t *t2);


/**
 * Get media transport protocol info, i.e: base transport and profiles,
 * from the provided SDP media transport name string.
 *
 * @param tp        The SDP media transport name.
 *
 * @return          Media transport info, combination of transport protocol
 *                  and profile bit flag defined in pjmedia_tp_proto.
 */
PJ_DECL(pj_uint32_t) pjmedia_sdp_transport_get_proto(const pj_str_t *tp);


/**
 * Deactivate SDP media.
 *
 * @param pool      Memory pool to allocate memory from.
 * @param m         The SDP media to deactivate.
 *
 * @return          PJ_SUCCESS when SDP media successfully deactivated,
 *                  otherwise appropriate status code returned.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_media_deactivate(pj_pool_t *pool,
                                                  pjmedia_sdp_media *m);


/**
 * Clone SDP media description and deactivate the new SDP media.
 *
 * @param pool      Memory pool to allocate memory for the clone.
 * @param rhs       The SDP media to clone.
 *
 * @return          New media descrption with deactivated indication.
 */
PJ_DECL(pjmedia_sdp_media*) pjmedia_sdp_media_clone_deactivate(
                                                pj_pool_t *pool,
                                                const pjmedia_sdp_media *rhs);


/* **************************************************************************
 * SDP SESSION DESCRIPTION
 ****************************************************************************
 */


/**
 * This structure describes SDP session description. A SDP session descriptor
 * contains complete information about a session, and normally is exchanged
 * with remote media peer using signaling protocol such as SIP.
 */
struct pjmedia_sdp_session
{
    /** Session origin (o= line) */
    struct
    {
        pj_str_t    user;           /**< User                           */
        pj_uint_t   id;             /**< Session ID                     */
        pj_uint_t   version;        /**< Session version                */
        pj_str_t    net_type;       /**< Network type ("IN")            */
        pj_str_t    addr_type;      /**< Address type ("IP4", "IP6")    */
        pj_str_t    addr;           /**< The address.                   */
    } origin;

    pj_str_t           name;        /**< Subject line (s=)              */
    pjmedia_sdp_conn  *conn;        /**< Connection line (c=)           */
    unsigned           bandw_count; /**< Number of bandwidth info (b=)  */
    pjmedia_sdp_bandw *bandw[PJMEDIA_MAX_SDP_BANDW];
                                    /**< Bandwidth info array (b=)      */
    
    /** Session time (t= line)  */
    struct
    {
        pj_uint_t start;            /**< Start time.                    */
        pj_uint_t stop;             /**< Stop time.                     */
    } time;

    unsigned           attr_count;              /**< Number of attributes.  */
    pjmedia_sdp_attr  *attr[PJMEDIA_MAX_SDP_ATTR]; /**< Attributes array.   */

    unsigned           media_count;             /**< Number of media.       */
    pjmedia_sdp_media *media[PJMEDIA_MAX_SDP_MEDIA];    /**< Media array.   */

};

/**
 * @see pjmedia_sdp_session
 */
typedef struct pjmedia_sdp_session pjmedia_sdp_session;



/**
 * Parse SDP message.
 *
 * Note that the input message buffer MUST be NULL terminated and have
 * length at least len+1 (len MUST NOT include the NULL terminator).
 *
 * @param pool      The pool to allocate SDP session description.
 * @param buf       The message buffer, MUST be NULL terminated.
 * @param len       The length of the message, excluding NULL terminator.
 * @param p_sdp     Pointer to receive the SDP session descriptor.
 *
 * @return          PJ_SUCCESS if message was successfully parsed into
 *                  SDP session descriptor.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool,
                                        char *buf, pj_size_t len, 
                                        pjmedia_sdp_session **p_sdp );

/**
 * Print SDP description to a buffer.
 *
 * @param sdp       The SDP session description.
 * @param buf       The buffer.
 * @param size      The buffer length.
 *
 * @return          the length printed, or -1 if the buffer is too
 *                  short.
 */
PJ_DECL(int) pjmedia_sdp_print( const pjmedia_sdp_session *sdp, 
                                char *buf, pj_size_t size);


/**
 * Perform semantic validation for the specified SDP session descriptor.
 * This function perform validation beyond just syntactic verification,
 * such as to verify the value of network type and address type, check
 * the connection line, and verify that \a rtpmap attribute is present
 * when dynamic payload type is used.
 *
 * @param sdp       The SDP session descriptor to validate.
 *
 * @return          PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_validate(const pjmedia_sdp_session *sdp);


/**
 * Perform semantic validation for the specified SDP session descriptor.
 * This function perform validation beyond just syntactic verification,
 * such as to verify the value of network type and address type, check
 * the connection line, and verify that \a rtpmap attribute is present
 * when dynamic payload type is used.
 *
 * @param sdp       The SDP session descriptor to validate.
 * @param strict    Flag whether the check should be strict, i.e: allow
 *                  media without connection line when port is zero.
 *
 * @return          PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_validate2(const pjmedia_sdp_session *sdp,
                                           pj_bool_t strict);


/**
 * Clone SDP session descriptor.
 *
 * @param pool      The pool used to clone the session.
 * @param sdp       The SDP session to clone.
 *
 * @return          New SDP session.
 */
PJ_DECL(pjmedia_sdp_session*) 
pjmedia_sdp_session_clone( pj_pool_t *pool,
                           const pjmedia_sdp_session *sdp);


/**
 * Compare two SDP session for equality, by comparing:
 * - the fields origin, subject, connection, time
 * - the attributes direction, fmtp, and rtpmap
 * - the media descriptions (see #pjmedia_sdp_media_cmp())
 *
 * The function will also call the callback
 * \a pjmedia_sdp_session_cmp_cb() if registered.
 *
 * @param sd1       The first SDP session to compare.
 * @param sd2       The second SDP session to compare.
 * @param option    Must be zero for now.
 *
 * @return          PJ_SUCCESS when both SDPs are equal, or otherwise
 *                  the status code indicates which part of the session
 *                  descriptors are not equal.
 *                  If \a pjmedia_sdp_session_cmp_cb() is registered,
 *                  will return the status output parameter of the callback.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_session_cmp(const pjmedia_sdp_session *sd1,
                                             const pjmedia_sdp_session *sd2,
                                             unsigned option);


/**
 * The declaration of customized SDP session comparison callback. See
 * #pjmedia_sdp_session_register_cmp_cb() for more info.
 *
 * @param sd1       The first SDP session to compare.
 * @param sd2       The second SDP session to compare.
 * @param option    Must be zero for now.
 * @param status    Status code to be returned for the SDP comparison result
 *                  (PJ_SUCCESS meaning both SDPs are equal).
 *                  On input, it contains the return status of
 *                  #pjmedia_sdp_session_cmp().
 */
typedef void (*pjmedia_sdp_session_cmp_cb)(const pjmedia_sdp_session *sd1,
                                           const pjmedia_sdp_session *sd2,
                                           unsigned option,
                                           pj_status_t *status);


/**
 * Register customized SDP session comparison callback. The callback will
 * be called by #pjmedia_sdp_session_cmp().
 * To unregister, just call this function with parameter cb set to NULL.
 *
 * @param cb            The customized SDP session comparison callback or
 *                      NULL to unregister the callback.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t)
pjmedia_sdp_session_register_cmp_cb(pjmedia_sdp_session_cmp_cb cb);


/**
 * Add new attribute to the session descriptor.
 *
 * @param s             The SDP session description.
 * @param attr          Attribute to add.
 *
 * @return              PJ_SUCCESS or the appropriate error code.
 */
PJ_DECL(pj_status_t) pjmedia_sdp_session_add_attr(pjmedia_sdp_session *s,
                                                  pjmedia_sdp_attr *attr);


PJ_END_DECL

/**
 * @}
 */

#endif  /* __PJMEDIA_SDP_H__ */

