mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 12:16:00 +00:00
Merge "SDP: Rework SDP offer/answer model and update capabilities merges."
This commit is contained in:
@@ -253,16 +253,6 @@ void ast_sdp_s_free(struct ast_sdp_s_line *s_line);
|
|||||||
*/
|
*/
|
||||||
void ast_sdp_t_free(struct ast_sdp_t_line *t_line);
|
void ast_sdp_t_free(struct ast_sdp_t_line *t_line);
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Free an SDP
|
|
||||||
* Frees the sdp and all resources it contains
|
|
||||||
*
|
|
||||||
* \param sdp The sdp to free
|
|
||||||
*
|
|
||||||
* \since 15
|
|
||||||
*/
|
|
||||||
void ast_sdp_free(struct ast_sdp *sdp);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Allocate an SDP Attribute
|
* \brief Allocate an SDP Attribute
|
||||||
*
|
*
|
||||||
@@ -544,7 +534,7 @@ int ast_sdp_m_add_format(struct ast_sdp_m_line *m_line, const struct ast_sdp_opt
|
|||||||
int rtp_code, int asterisk_format, const struct ast_format *format, int code);
|
int rtp_code, int asterisk_format, const struct ast_format *format, int code);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Create an SDP
|
* \brief Create an SDP ao2 object
|
||||||
*
|
*
|
||||||
* \param o_line Origin
|
* \param o_line Origin
|
||||||
* \param c_line Connection
|
* \param c_line Connection
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#define _ASTERISK_SDP_OPTIONS_H
|
#define _ASTERISK_SDP_OPTIONS_H
|
||||||
|
|
||||||
#include "asterisk/udptl.h"
|
#include "asterisk/udptl.h"
|
||||||
|
#include "asterisk/format_cap.h"
|
||||||
|
|
||||||
struct ast_sdp_options;
|
struct ast_sdp_options;
|
||||||
|
|
||||||
@@ -79,6 +80,149 @@ enum ast_sdp_options_encryption {
|
|||||||
AST_SDP_ENCRYPTION_DTLS,
|
AST_SDP_ENCRYPTION_DTLS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Callback when processing an offer SDP for our answer SDP.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This callback is called after merging our last negotiated topology
|
||||||
|
* with the remote's offer topology and before we have sent our answer
|
||||||
|
* SDP. At this point you can alter new_topology streams. You can
|
||||||
|
* decline, remove formats, or rename streams. Changing anything else
|
||||||
|
* on the streams is likely to not end well.
|
||||||
|
*
|
||||||
|
* * To decline a stream simply set the stream state to
|
||||||
|
* AST_STREAM_STATE_REMOVED. You could implement a maximum number
|
||||||
|
* of active streams of a given type policy.
|
||||||
|
*
|
||||||
|
* * To remove formats use the format API to remove any formats from a
|
||||||
|
* stream. The streams have the current joint negotiated formats.
|
||||||
|
* Most likely you would want to remove all but the first format.
|
||||||
|
*
|
||||||
|
* * To rename a stream you need to clone the stream and give it a
|
||||||
|
* new name and then set it in new_topology using
|
||||||
|
* ast_stream_topology_set_stream().
|
||||||
|
*
|
||||||
|
* \note Removing all formats is an error. You should decline the
|
||||||
|
* stream instead.
|
||||||
|
*
|
||||||
|
* \param context User supplied context data pointer for the SDP
|
||||||
|
* state.
|
||||||
|
* \param old_topology Active negotiated topology. NULL if this is
|
||||||
|
* the first SDP negotiation. The old topology is available so you
|
||||||
|
* can tell if any streams are new or changing type.
|
||||||
|
* \param new_topology New negotiated topology that we intend to
|
||||||
|
* generate the answer SDP.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
typedef void (*ast_sdp_answerer_modify_cb)(void *context,
|
||||||
|
const struct ast_stream_topology *old_topology,
|
||||||
|
struct ast_stream_topology *new_topology);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Callback when generating a topology for our SDP offer.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This callback is called after merging any topology updates from the
|
||||||
|
* system by ast_sdp_state_update_local_topology() and before we have
|
||||||
|
* sent our offer SDP. At this point you can alter new_topology
|
||||||
|
* streams. You can decline, add/remove/update formats, or rename
|
||||||
|
* streams. Changing anything else on the streams is likely to not
|
||||||
|
* end well.
|
||||||
|
*
|
||||||
|
* * To decline a stream simply set the stream state to
|
||||||
|
* AST_STREAM_STATE_REMOVED. You could implement a maximum number
|
||||||
|
* of active streams of a given type policy.
|
||||||
|
*
|
||||||
|
* * To update formats use the format API to change formats of the
|
||||||
|
* streams. The streams have the current proposed formats. You
|
||||||
|
* could do whatever you want for formats but you should stay within
|
||||||
|
* the configured formats for the stream type's endpoint. However,
|
||||||
|
* you should use ast_sdp_state_update_local_topology() instead of
|
||||||
|
* this backdoor method.
|
||||||
|
*
|
||||||
|
* * To rename a stream you need to clone the stream and give it a
|
||||||
|
* new name and then set it in new_topology using
|
||||||
|
* ast_stream_topology_set_stream().
|
||||||
|
*
|
||||||
|
* \note Removing all formats is an error. You should decline the
|
||||||
|
* stream instead.
|
||||||
|
*
|
||||||
|
* \note Declined new streams that are in slots higher than present in
|
||||||
|
* old_topology are removed so the SDP can be smaller. The remote has
|
||||||
|
* never seen those slots so we shouldn't bother keeping them.
|
||||||
|
*
|
||||||
|
* \param context User supplied context data pointer for the SDP
|
||||||
|
* state.
|
||||||
|
* \param old_topology Active negotiated topology. NULL if this is
|
||||||
|
* the first SDP negotiation. The old topology is available so you
|
||||||
|
* can tell if any streams are new or changing type.
|
||||||
|
* \param new_topology Merged topology that we intend to generate the
|
||||||
|
* offer SDP.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
typedef void (*ast_sdp_offerer_modify_cb)(void *context,
|
||||||
|
const struct ast_stream_topology *old_topology,
|
||||||
|
struct ast_stream_topology *new_topology);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Callback when generating an offer SDP to configure extra stream data.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This callback is called after any ast_sdp_offerer_modify_cb
|
||||||
|
* callback and before we have sent our offer SDP. The callback can
|
||||||
|
* call several SDP API calls to configure the proposed capabilities
|
||||||
|
* of streams before we create the SDP offer. For example, the
|
||||||
|
* callback could configure a stream specific connection address, T.38
|
||||||
|
* parameters, RTP instance, or UDPTL instance parameters.
|
||||||
|
*
|
||||||
|
* \param context User supplied context data pointer for the SDP
|
||||||
|
* state.
|
||||||
|
* \param topology Topology ready to configure extra stream options.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
typedef void (*ast_sdp_offerer_config_cb)(void *context, const struct ast_stream_topology *topology);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Callback before applying a topology.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This callback is called before the topology is applied so the
|
||||||
|
* using module can do what is necessary before the topology becomes
|
||||||
|
* active.
|
||||||
|
*
|
||||||
|
* \param context User supplied context data pointer for the SDP
|
||||||
|
* state.
|
||||||
|
* \param topology Topology ready to be applied.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
typedef void (*ast_sdp_preapply_cb)(void *context, const struct ast_stream_topology *topology);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Callback after applying a topology.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This callback is called after the topology is applied so the
|
||||||
|
* using module can do what is necessary after the topology becomes
|
||||||
|
* active.
|
||||||
|
*
|
||||||
|
* \param context User supplied context data pointer for the SDP
|
||||||
|
* state.
|
||||||
|
* \param topology Topology already applied.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
typedef void (*ast_sdp_postapply_cb)(void *context, const struct ast_stream_topology *topology);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \since 15.0.0
|
* \since 15.0.0
|
||||||
* \brief Allocate a new SDP options structure.
|
* \brief Allocate a new SDP options structure.
|
||||||
@@ -204,6 +348,24 @@ void ast_sdp_options_set_rtp_engine(struct ast_sdp_options *options,
|
|||||||
*/
|
*/
|
||||||
const char *ast_sdp_options_get_rtp_engine(const struct ast_sdp_options *options);
|
const char *ast_sdp_options_get_rtp_engine(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
|
void ast_sdp_options_set_state_context(struct ast_sdp_options *options, void *state_context);
|
||||||
|
void *ast_sdp_options_get_state_context(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
|
void ast_sdp_options_set_answerer_modify_cb(struct ast_sdp_options *options, ast_sdp_answerer_modify_cb answerer_modify_cb);
|
||||||
|
ast_sdp_answerer_modify_cb ast_sdp_options_get_answerer_modify_cb(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
|
void ast_sdp_options_set_offerer_modify_cb(struct ast_sdp_options *options, ast_sdp_offerer_modify_cb offerer_modify_cb);
|
||||||
|
ast_sdp_offerer_modify_cb ast_sdp_options_get_offerer_modify_cb(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
|
void ast_sdp_options_set_offerer_config_cb(struct ast_sdp_options *options, ast_sdp_offerer_config_cb offerer_config_cb);
|
||||||
|
ast_sdp_offerer_config_cb ast_sdp_options_get_offerer_config_cb(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
|
void ast_sdp_options_set_preapply_cb(struct ast_sdp_options *options, ast_sdp_preapply_cb preapply_cb);
|
||||||
|
ast_sdp_preapply_cb ast_sdp_options_get_preapply_cb(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
|
void ast_sdp_options_set_postapply_cb(struct ast_sdp_options *options, ast_sdp_postapply_cb postapply_cb);
|
||||||
|
ast_sdp_postapply_cb ast_sdp_options_get_postapply_cb(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \since 15.0.0
|
* \since 15.0.0
|
||||||
* \brief Set SDP Options rtp_symmetric
|
* \brief Set SDP Options rtp_symmetric
|
||||||
@@ -503,6 +665,26 @@ void ast_sdp_options_set_udptl_far_max_datagram(struct ast_sdp_options *options,
|
|||||||
*/
|
*/
|
||||||
unsigned int ast_sdp_options_get_udptl_far_max_datagram(const struct ast_sdp_options *options);
|
unsigned int ast_sdp_options_get_udptl_far_max_datagram(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \since 15.0.0
|
||||||
|
* \brief Set SDP Options max_streams
|
||||||
|
*
|
||||||
|
* \param options SDP Options
|
||||||
|
* \param max_streams
|
||||||
|
*/
|
||||||
|
void ast_sdp_options_set_max_streams(struct ast_sdp_options *options,
|
||||||
|
unsigned int max_streams);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \since 15.0.0
|
||||||
|
* \brief Get SDP Options max_streams
|
||||||
|
*
|
||||||
|
* \param options SDP Options
|
||||||
|
*
|
||||||
|
* \returns max_streams
|
||||||
|
*/
|
||||||
|
unsigned int ast_sdp_options_get_max_streams(const struct ast_sdp_options *options);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \since 15.0.0
|
* \since 15.0.0
|
||||||
* \brief Enable setting SSRC level attributes on SDPs
|
* \brief Enable setting SSRC level attributes on SDPs
|
||||||
@@ -547,4 +729,46 @@ void ast_sdp_options_set_sched_type(struct ast_sdp_options *options,
|
|||||||
struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options,
|
struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options,
|
||||||
enum ast_media_type type);
|
enum ast_media_type type);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set all allowed stream types to create new streams.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \param options SDP Options
|
||||||
|
* \param cap Format capabilities to set all allowed stream types at once.
|
||||||
|
* Could be NULL to disable creating any new streams.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
void ast_sdp_options_set_format_caps(struct ast_sdp_options *options,
|
||||||
|
struct ast_format_cap *cap);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the SDP options format cap used to create new streams of the type.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \param options SDP Options
|
||||||
|
* \param type Media type the format cap represents.
|
||||||
|
* \param cap Format capabilities to use for the specified media type.
|
||||||
|
* Could be NULL to disable creating new streams of type.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
void ast_sdp_options_set_format_cap_type(struct ast_sdp_options *options,
|
||||||
|
enum ast_media_type type, struct ast_format_cap *cap);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the SDP options format cap used to create new streams of the type.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \param options SDP Options
|
||||||
|
* \param type Media type the format cap represents.
|
||||||
|
*
|
||||||
|
* \retval NULL if stream not allowed to be created.
|
||||||
|
* \retval cap to use in negotiating the new stream.
|
||||||
|
*
|
||||||
|
* \note The returned cap does not have its own ao2 ref.
|
||||||
|
*/
|
||||||
|
struct ast_format_cap *ast_sdp_options_get_format_cap_type(const struct ast_sdp_options *options,
|
||||||
|
enum ast_media_type type);
|
||||||
|
|
||||||
#endif /* _ASTERISK_SDP_OPTIONS_H */
|
#endif /* _ASTERISK_SDP_OPTIONS_H */
|
||||||
|
@@ -30,12 +30,22 @@ struct ast_control_t38_parameters;
|
|||||||
/*!
|
/*!
|
||||||
* \brief Allocate a new SDP state
|
* \brief Allocate a new SDP state
|
||||||
*
|
*
|
||||||
|
* \details
|
||||||
* SDP state keeps tabs on everything SDP-related for a media session.
|
* SDP state keeps tabs on everything SDP-related for a media session.
|
||||||
* Most SDP operations will require the state to be provided.
|
* Most SDP operations will require the state to be provided.
|
||||||
* Ownership of the SDP options is taken on by the SDP state.
|
* Ownership of the SDP options is taken on by the SDP state.
|
||||||
* A good strategy is to call this during session creation.
|
* A good strategy is to call this during session creation.
|
||||||
|
*
|
||||||
|
* \param topology Initial stream topology to offer.
|
||||||
|
* NULL if we are going to be the answerer. We can always
|
||||||
|
* update the local topology later if it turns out we need
|
||||||
|
* to be the offerer.
|
||||||
|
* \param options SDP options for the duration of the session.
|
||||||
|
*
|
||||||
|
* \retval SDP state struct
|
||||||
|
* \retval NULL on failure
|
||||||
*/
|
*/
|
||||||
struct ast_sdp_state *ast_sdp_state_alloc(struct ast_stream_topology *streams,
|
struct ast_sdp_state *ast_sdp_state_alloc(struct ast_stream_topology *topology,
|
||||||
struct ast_sdp_options *options);
|
struct ast_sdp_options *options);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -86,6 +96,8 @@ int ast_sdp_state_get_stream_connection_address(const struct ast_sdp_state *sdp_
|
|||||||
*
|
*
|
||||||
* If this is called prior to receiving a remote SDP, then this will just mirror
|
* If this is called prior to receiving a remote SDP, then this will just mirror
|
||||||
* the local configured endpoint capabilities.
|
* the local configured endpoint capabilities.
|
||||||
|
*
|
||||||
|
* \note Cannot return NULL. It is a BUG if it does.
|
||||||
*/
|
*/
|
||||||
const struct ast_stream_topology *ast_sdp_state_get_joint_topology(
|
const struct ast_stream_topology *ast_sdp_state_get_joint_topology(
|
||||||
const struct ast_sdp_state *sdp_state);
|
const struct ast_sdp_state *sdp_state);
|
||||||
@@ -93,6 +105,7 @@ const struct ast_stream_topology *ast_sdp_state_get_joint_topology(
|
|||||||
/*!
|
/*!
|
||||||
* \brief Get the local topology
|
* \brief Get the local topology
|
||||||
*
|
*
|
||||||
|
* \note Cannot return NULL. It is a BUG if it does.
|
||||||
*/
|
*/
|
||||||
const struct ast_stream_topology *ast_sdp_state_get_local_topology(
|
const struct ast_stream_topology *ast_sdp_state_get_local_topology(
|
||||||
const struct ast_sdp_state *sdp_state);
|
const struct ast_sdp_state *sdp_state);
|
||||||
@@ -114,9 +127,10 @@ const struct ast_sdp_options *ast_sdp_state_get_options(
|
|||||||
* \retval NULL Failure
|
* \retval NULL Failure
|
||||||
*
|
*
|
||||||
* \note
|
* \note
|
||||||
* This function will allocate a new SDP with RTP instances if it has not already
|
* This function will return the last local SDP created if one were
|
||||||
* been allocated.
|
* previously requested for the current negotiation. Otherwise it
|
||||||
*
|
* creates our SDP offer/answer depending on what role we are playing
|
||||||
|
* in the current negotiation.
|
||||||
*/
|
*/
|
||||||
const struct ast_sdp *ast_sdp_state_get_local_sdp(struct ast_sdp_state *sdp_state);
|
const struct ast_sdp *ast_sdp_state_get_local_sdp(struct ast_sdp_state *sdp_state);
|
||||||
|
|
||||||
@@ -152,6 +166,7 @@ const void *ast_sdp_state_get_local_sdp_impl(struct ast_sdp_state *sdp_state);
|
|||||||
*
|
*
|
||||||
* \retval 0 Success
|
* \retval 0 Success
|
||||||
* \retval non-0 Failure
|
* \retval non-0 Failure
|
||||||
|
* Use ast_sdp_state_is_offer_rejected() to see if the SDP offer was rejected.
|
||||||
*
|
*
|
||||||
* \since 15
|
* \since 15
|
||||||
*/
|
*/
|
||||||
@@ -165,39 +180,72 @@ int ast_sdp_state_set_remote_sdp(struct ast_sdp_state *sdp_state, const struct a
|
|||||||
*
|
*
|
||||||
* \retval 0 Success
|
* \retval 0 Success
|
||||||
* \retval non-0 Failure
|
* \retval non-0 Failure
|
||||||
|
* Use ast_sdp_state_is_offer_rejected() to see if the SDP offer was rejected.
|
||||||
*
|
*
|
||||||
* \since 15
|
* \since 15
|
||||||
*/
|
*/
|
||||||
int ast_sdp_state_set_remote_sdp_from_impl(struct ast_sdp_state *sdp_state, const void *remote);
|
int ast_sdp_state_set_remote_sdp_from_impl(struct ast_sdp_state *sdp_state, const void *remote);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Reset the SDP state and stream capabilities as if the SDP state had just been allocated.
|
* \brief Was the set remote offer rejected.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \param sdp_state
|
||||||
|
*
|
||||||
|
* \retval 0 if not rejected.
|
||||||
|
* \retval non-zero if rejected.
|
||||||
|
*/
|
||||||
|
int ast_sdp_state_is_offer_rejected(struct ast_sdp_state *sdp_state);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Are we the SDP offerer.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \param sdp_state
|
||||||
|
*
|
||||||
|
* \retval 0 if we are not the offerer.
|
||||||
|
* \retval non-zero we are the offerer.
|
||||||
|
*/
|
||||||
|
int ast_sdp_state_is_offerer(struct ast_sdp_state *sdp_state);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Are we the SDP answerer.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \param sdp_state
|
||||||
|
*
|
||||||
|
* \retval 0 if we are not the answerer.
|
||||||
|
* \retval non-zero we are the answerer.
|
||||||
|
*/
|
||||||
|
int ast_sdp_state_is_answerer(struct ast_sdp_state *sdp_state);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Restart the SDP offer/answer negotiations.
|
||||||
*
|
*
|
||||||
* \param sdp_state
|
* \param sdp_state
|
||||||
* \param remote The implementation's representation of an SDP.
|
|
||||||
*
|
*
|
||||||
* \retval 0 Success
|
* \retval 0 Success
|
||||||
*
|
* \retval non-0 Failure
|
||||||
* \note
|
|
||||||
* This is most useful for when a channel driver is sending a session refresh message
|
|
||||||
* and needs to re-advertise its initial capabilities instead of the previously-negotiated
|
|
||||||
* joint capabilities.
|
|
||||||
*
|
|
||||||
* \since 15
|
|
||||||
*/
|
*/
|
||||||
int ast_sdp_state_reset(struct ast_sdp_state *sdp_state);
|
int ast_sdp_state_restart_negotiations(struct ast_sdp_state *sdp_state);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Update the local stream topology on the SDP state.
|
* \brief Update the local stream topology on the SDP state.
|
||||||
*
|
*
|
||||||
|
* \details
|
||||||
|
* Basically we are saving off any topology updates until we create the
|
||||||
|
* next SDP offer. Repeated updates merge with the previous updated
|
||||||
|
* topology.
|
||||||
|
*
|
||||||
* \param sdp_state
|
* \param sdp_state
|
||||||
* \param streams The new stream topology.
|
* \param topology The new stream topology.
|
||||||
*
|
*
|
||||||
* \retval 0 Success
|
* \retval 0 Success
|
||||||
|
* \retval non-0 Failure
|
||||||
*
|
*
|
||||||
* \since 15
|
* \since 15
|
||||||
*/
|
*/
|
||||||
int ast_sdp_state_update_local_topology(struct ast_sdp_state *sdp_state, struct ast_stream_topology *streams);
|
int ast_sdp_state_update_local_topology(struct ast_sdp_state *sdp_state, struct ast_stream_topology *topology);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Set the local address (IP address) to use for connection addresses
|
* \brief Set the local address (IP address) to use for connection addresses
|
||||||
@@ -231,7 +279,26 @@ int ast_sdp_state_set_connection_address(struct ast_sdp_state *sdp_state, int st
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \since 15.0.0
|
* \since 15.0.0
|
||||||
* \brief Set a stream to be held or unheld
|
* \brief Set the global locally held state.
|
||||||
|
*
|
||||||
|
* \param sdp_state
|
||||||
|
* \param locally_held
|
||||||
|
*/
|
||||||
|
void ast_sdp_state_set_global_locally_held(struct ast_sdp_state *sdp_state, unsigned int locally_held);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \since 15.0.0
|
||||||
|
* \brief Get the global locally held state.
|
||||||
|
*
|
||||||
|
* \param sdp_state
|
||||||
|
*
|
||||||
|
* \returns locally_held
|
||||||
|
*/
|
||||||
|
unsigned int ast_sdp_state_get_global_locally_held(const struct ast_sdp_state *sdp_state);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \since 15.0.0
|
||||||
|
* \brief Set a stream to be held or unheld locally
|
||||||
*
|
*
|
||||||
* \param sdp_state
|
* \param sdp_state
|
||||||
* \param stream_index The stream to set the held value for
|
* \param stream_index The stream to set the held value for
|
||||||
@@ -240,6 +307,30 @@ int ast_sdp_state_set_connection_address(struct ast_sdp_state *sdp_state, int st
|
|||||||
void ast_sdp_state_set_locally_held(struct ast_sdp_state *sdp_state,
|
void ast_sdp_state_set_locally_held(struct ast_sdp_state *sdp_state,
|
||||||
int stream_index, unsigned int locally_held);
|
int stream_index, unsigned int locally_held);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \since 15.0.0
|
||||||
|
* \brief Get whether a stream is locally held or not
|
||||||
|
*
|
||||||
|
* \param sdp_state
|
||||||
|
* \param stream_index The stream to get the held state for
|
||||||
|
*
|
||||||
|
* \returns locally_held
|
||||||
|
*/
|
||||||
|
unsigned int ast_sdp_state_get_locally_held(const struct ast_sdp_state *sdp_state,
|
||||||
|
int stream_index);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \since 15.0.0
|
||||||
|
* \brief Get whether a stream is remotely held or not
|
||||||
|
*
|
||||||
|
* \param sdp_state
|
||||||
|
* \param stream_index The stream to get the held state for
|
||||||
|
*
|
||||||
|
* \returns remotely_held
|
||||||
|
*/
|
||||||
|
unsigned int ast_sdp_state_get_remotely_held(const struct ast_sdp_state *sdp_state,
|
||||||
|
int stream_index);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \since 15.0.0
|
* \since 15.0.0
|
||||||
* \brief Set the UDPTL session parameters
|
* \brief Set the UDPTL session parameters
|
||||||
@@ -251,16 +342,4 @@ void ast_sdp_state_set_locally_held(struct ast_sdp_state *sdp_state,
|
|||||||
void ast_sdp_state_set_t38_parameters(struct ast_sdp_state *sdp_state,
|
void ast_sdp_state_set_t38_parameters(struct ast_sdp_state *sdp_state,
|
||||||
int stream_index, struct ast_control_t38_parameters *params);
|
int stream_index, struct ast_control_t38_parameters *params);
|
||||||
|
|
||||||
/*!
|
|
||||||
* \since 15.0.0
|
|
||||||
* \brief Get whether a stream is held or not
|
|
||||||
*
|
|
||||||
* \param sdp_state
|
|
||||||
* \param stream_index The stream to get the held state for
|
|
||||||
*
|
|
||||||
* \returns locally_held
|
|
||||||
*/
|
|
||||||
unsigned int ast_sdp_state_get_locally_held(const struct ast_sdp_state *sdp_state,
|
|
||||||
int stream_index);
|
|
||||||
|
|
||||||
#endif /* _ASTERISK_SDP_STATE_H */
|
#endif /* _ASTERISK_SDP_STATE_H */
|
||||||
|
@@ -227,6 +227,17 @@ void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state
|
|||||||
*/
|
*/
|
||||||
const char *ast_stream_state2str(enum ast_stream_state state);
|
const char *ast_stream_state2str(enum ast_stream_state state);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Convert a string to a stream state
|
||||||
|
*
|
||||||
|
* \param str The string to convert
|
||||||
|
*
|
||||||
|
* \return The stream state
|
||||||
|
*
|
||||||
|
* \since 15.0.0
|
||||||
|
*/
|
||||||
|
enum ast_stream_state ast_stream_str2state(const char *str);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Get the opaque stream data
|
* \brief Get the opaque stream data
|
||||||
*
|
*
|
||||||
|
99
main/sdp.c
99
main/sdp.c
@@ -109,11 +109,9 @@ void ast_sdp_t_free(struct ast_sdp_t_line *t_line)
|
|||||||
ast_free(t_line);
|
ast_free(t_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_sdp_free(struct ast_sdp *sdp)
|
static void ast_sdp_dtor(void *vdoomed)
|
||||||
{
|
{
|
||||||
if (!sdp) {
|
struct ast_sdp *sdp = vdoomed;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ast_sdp_o_free(sdp->o_line);
|
ast_sdp_o_free(sdp->o_line);
|
||||||
ast_sdp_s_free(sdp->s_line);
|
ast_sdp_s_free(sdp->s_line);
|
||||||
@@ -121,7 +119,6 @@ void ast_sdp_free(struct ast_sdp *sdp)
|
|||||||
ast_sdp_t_free(sdp->t_line);
|
ast_sdp_t_free(sdp->t_line);
|
||||||
ast_sdp_a_lines_free(sdp->a_lines);
|
ast_sdp_a_lines_free(sdp->a_lines);
|
||||||
ast_sdp_m_lines_free(sdp->m_lines);
|
ast_sdp_m_lines_free(sdp->m_lines);
|
||||||
ast_free(sdp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COPY_STR_AND_ADVANCE(p, dest, source) \
|
#define COPY_STR_AND_ADVANCE(p, dest, source) \
|
||||||
@@ -314,28 +311,28 @@ struct ast_sdp *ast_sdp_alloc(struct ast_sdp_o_line *o_line,
|
|||||||
{
|
{
|
||||||
struct ast_sdp *new_sdp;
|
struct ast_sdp *new_sdp;
|
||||||
|
|
||||||
new_sdp = ast_calloc(1, sizeof *new_sdp);
|
new_sdp = ao2_alloc_options(sizeof(*new_sdp), ast_sdp_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
|
||||||
if (!new_sdp) {
|
if (!new_sdp) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_sdp->a_lines = ast_calloc(1, sizeof(*new_sdp->a_lines));
|
new_sdp->a_lines = ast_calloc(1, sizeof(*new_sdp->a_lines));
|
||||||
if (!new_sdp->a_lines) {
|
if (!new_sdp->a_lines) {
|
||||||
ast_sdp_free(new_sdp);
|
ao2_ref(new_sdp, -1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (AST_VECTOR_INIT(new_sdp->a_lines, 20)) {
|
if (AST_VECTOR_INIT(new_sdp->a_lines, 20)) {
|
||||||
ast_sdp_free(new_sdp);
|
ao2_ref(new_sdp, -1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_sdp->m_lines = ast_calloc(1, sizeof(*new_sdp->m_lines));
|
new_sdp->m_lines = ast_calloc(1, sizeof(*new_sdp->m_lines));
|
||||||
if (!new_sdp->m_lines) {
|
if (!new_sdp->m_lines) {
|
||||||
ast_sdp_free(new_sdp);
|
ao2_ref(new_sdp, -1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (AST_VECTOR_INIT(new_sdp->m_lines, 20)) {
|
if (AST_VECTOR_INIT(new_sdp->m_lines, 20)) {
|
||||||
ast_sdp_free(new_sdp);
|
ao2_ref(new_sdp, -1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,6 +738,62 @@ static void process_fmtp_lines(const struct ast_sdp_m_line *m_line, int payload,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Determine the RTP stream direction in the given a lines.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \param a_lines Attribute lines to search.
|
||||||
|
*
|
||||||
|
* \retval Stream direction on success.
|
||||||
|
* \retval AST_STREAM_STATE_REMOVED on failure.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
static enum ast_stream_state get_a_line_direction(const struct ast_sdp_a_lines *a_lines)
|
||||||
|
{
|
||||||
|
if (a_lines) {
|
||||||
|
enum ast_stream_state direction;
|
||||||
|
int idx;
|
||||||
|
const struct ast_sdp_a_line *a_line;
|
||||||
|
|
||||||
|
for (idx = 0; idx < AST_VECTOR_SIZE(a_lines); ++idx) {
|
||||||
|
a_line = AST_VECTOR_GET(a_lines, idx);
|
||||||
|
direction = ast_stream_str2state(a_line->name);
|
||||||
|
if (direction != AST_STREAM_STATE_REMOVED) {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AST_STREAM_STATE_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Determine the RTP stream direction.
|
||||||
|
* \since 15.0.0
|
||||||
|
*
|
||||||
|
* \param a_lines The SDP media global attributes
|
||||||
|
* \param m_line The SDP media section to convert
|
||||||
|
*
|
||||||
|
* \return Stream direction
|
||||||
|
*/
|
||||||
|
static enum ast_stream_state get_stream_direction(const struct ast_sdp_a_lines *a_lines, const struct ast_sdp_m_line *m_line)
|
||||||
|
{
|
||||||
|
enum ast_stream_state direction;
|
||||||
|
|
||||||
|
direction = get_a_line_direction(m_line->a_lines);
|
||||||
|
if (direction != AST_STREAM_STATE_REMOVED) {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
direction = get_a_line_direction(a_lines);
|
||||||
|
if (direction != AST_STREAM_STATE_REMOVED) {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
return AST_STREAM_STATE_SENDRECV;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Needed so we don't have an external function referenced as data.
|
* Needed so we don't have an external function referenced as data.
|
||||||
* The dynamic linker doesn't handle that very well.
|
* The dynamic linker doesn't handle that very well.
|
||||||
@@ -758,13 +811,14 @@ static void rtp_codecs_free(struct ast_rtp_codecs *codecs)
|
|||||||
* Given an m-line from an SDP, convert it into an ast_stream structure.
|
* Given an m-line from an SDP, convert it into an ast_stream structure.
|
||||||
* This takes formats, as well as clock-rate and fmtp attributes into account.
|
* This takes formats, as well as clock-rate and fmtp attributes into account.
|
||||||
*
|
*
|
||||||
|
* \param a_lines The SDP media global attributes
|
||||||
* \param m_line The SDP media section to convert
|
* \param m_line The SDP media section to convert
|
||||||
* \param g726_non_standard Non-zero if G.726 is non-standard
|
* \param g726_non_standard Non-zero if G.726 is non-standard
|
||||||
*
|
*
|
||||||
* \retval NULL An error occurred
|
* \retval NULL An error occurred
|
||||||
* \retval non-NULL The converted stream
|
* \retval non-NULL The converted stream
|
||||||
*/
|
*/
|
||||||
static struct ast_stream *get_stream_from_m(const struct ast_sdp_m_line *m_line, int g726_non_standard)
|
static struct ast_stream *get_stream_from_m(const struct ast_sdp_a_lines *a_lines, const struct ast_sdp_m_line *m_line, int g726_non_standard)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int non_ast_fmts;
|
int non_ast_fmts;
|
||||||
@@ -793,6 +847,14 @@ static struct ast_stream *get_stream_from_m(const struct ast_sdp_m_line *m_line,
|
|||||||
ao2_ref(caps, -1);
|
ao2_ref(caps, -1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ast_stream_set_data(stream, AST_STREAM_DATA_RTP_CODECS, codecs,
|
||||||
|
(ast_stream_data_free_fn) rtp_codecs_free);
|
||||||
|
|
||||||
|
if (!m_line->port) {
|
||||||
|
/* Stream is declined. There may not be any attributes. */
|
||||||
|
ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
options = g726_non_standard ? AST_RTP_OPT_G726_NONSTANDARD : 0;
|
options = g726_non_standard ? AST_RTP_OPT_G726_NONSTANDARD : 0;
|
||||||
for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {
|
for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {
|
||||||
@@ -819,10 +881,16 @@ static struct ast_stream *get_stream_from_m(const struct ast_sdp_m_line *m_line,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ast_rtp_codecs_payload_formats(codecs, caps, &non_ast_fmts);
|
ast_rtp_codecs_payload_formats(codecs, caps, &non_ast_fmts);
|
||||||
ast_stream_set_data(stream, AST_STREAM_DATA_RTP_CODECS, codecs,
|
|
||||||
(ast_stream_data_free_fn) rtp_codecs_free);
|
ast_stream_set_state(stream, get_stream_direction(a_lines, m_line));
|
||||||
break;
|
break;
|
||||||
case AST_MEDIA_TYPE_IMAGE:
|
case AST_MEDIA_TYPE_IMAGE:
|
||||||
|
if (!m_line->port) {
|
||||||
|
/* Stream is declined. There may not be any attributes. */
|
||||||
|
ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {
|
for (i = 0; i < ast_sdp_m_get_payload_count(m_line); ++i) {
|
||||||
struct ast_sdp_payload *payload;
|
struct ast_sdp_payload *payload;
|
||||||
|
|
||||||
@@ -830,12 +898,15 @@ static struct ast_stream *get_stream_from_m(const struct ast_sdp_m_line *m_line,
|
|||||||
payload = ast_sdp_m_get_payload(m_line, i);
|
payload = ast_sdp_m_get_payload(m_line, i);
|
||||||
if (!strcasecmp(payload->fmt, "t38")) {
|
if (!strcasecmp(payload->fmt, "t38")) {
|
||||||
ast_format_cap_append(caps, ast_format_t38, 0);
|
ast_format_cap_append(caps, ast_format_t38, 0);
|
||||||
|
ast_stream_set_state(stream, AST_STREAM_STATE_SENDRECV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AST_MEDIA_TYPE_UNKNOWN:
|
case AST_MEDIA_TYPE_UNKNOWN:
|
||||||
case AST_MEDIA_TYPE_TEXT:
|
case AST_MEDIA_TYPE_TEXT:
|
||||||
case AST_MEDIA_TYPE_END:
|
case AST_MEDIA_TYPE_END:
|
||||||
|
/* Consider these unsupported streams as declined */
|
||||||
|
ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -858,7 +929,7 @@ struct ast_stream_topology *ast_get_topology_from_sdp(const struct ast_sdp *sdp,
|
|||||||
for (i = 0; i < ast_sdp_get_m_count(sdp); ++i) {
|
for (i = 0; i < ast_sdp_get_m_count(sdp); ++i) {
|
||||||
struct ast_stream *stream;
|
struct ast_stream *stream;
|
||||||
|
|
||||||
stream = get_stream_from_m(ast_sdp_get_m(sdp, i), g726_non_standard);
|
stream = get_stream_from_m(sdp->a_lines, ast_sdp_get_m(sdp, i), g726_non_standard);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
/*
|
/*
|
||||||
* The topology cannot match the SDP because
|
* The topology cannot match the SDP because
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#define DEFAULT_ICE AST_SDP_ICE_DISABLED
|
#define DEFAULT_ICE AST_SDP_ICE_DISABLED
|
||||||
#define DEFAULT_IMPL AST_SDP_IMPL_STRING
|
#define DEFAULT_IMPL AST_SDP_IMPL_STRING
|
||||||
#define DEFAULT_ENCRYPTION AST_SDP_ENCRYPTION_DISABLED
|
#define DEFAULT_ENCRYPTION AST_SDP_ENCRYPTION_DISABLED
|
||||||
|
#define DEFAULT_MAX_STREAMS 16 /* Set to match our PJPROJECT PJMEDIA_MAX_SDP_MEDIA. */
|
||||||
|
|
||||||
#define DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(field, assert_on_null) \
|
#define DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(field, assert_on_null) \
|
||||||
void ast_sdp_options_set_##field(struct ast_sdp_options *options, const char *value) \
|
void ast_sdp_options_set_##field(struct ast_sdp_options *options, const char *value) \
|
||||||
@@ -60,6 +61,12 @@ DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(sdpowner, 0);
|
|||||||
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(sdpsession, 0);
|
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(sdpsession, 0);
|
||||||
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(rtp_engine, 0);
|
DEFINE_STRINGFIELD_GETTERS_SETTERS_FOR(rtp_engine, 0);
|
||||||
|
|
||||||
|
DEFINE_GETTERS_SETTERS_FOR(void *, state_context);
|
||||||
|
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_answerer_modify_cb, answerer_modify_cb);
|
||||||
|
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_offerer_modify_cb, offerer_modify_cb);
|
||||||
|
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_offerer_config_cb, offerer_config_cb);
|
||||||
|
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_preapply_cb, preapply_cb);
|
||||||
|
DEFINE_GETTERS_SETTERS_FOR(ast_sdp_postapply_cb, postapply_cb);
|
||||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, rtp_symmetric);
|
DEFINE_GETTERS_SETTERS_FOR(unsigned int, rtp_symmetric);
|
||||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, udptl_symmetric);
|
DEFINE_GETTERS_SETTERS_FOR(unsigned int, udptl_symmetric);
|
||||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_t38_ec_modes, udptl_error_correction);
|
DEFINE_GETTERS_SETTERS_FOR(enum ast_t38_ec_modes, udptl_error_correction);
|
||||||
@@ -71,6 +78,7 @@ DEFINE_GETTERS_SETTERS_FOR(unsigned int, tos_audio);
|
|||||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, cos_audio);
|
DEFINE_GETTERS_SETTERS_FOR(unsigned int, cos_audio);
|
||||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, tos_video);
|
DEFINE_GETTERS_SETTERS_FOR(unsigned int, tos_video);
|
||||||
DEFINE_GETTERS_SETTERS_FOR(unsigned int, cos_video);
|
DEFINE_GETTERS_SETTERS_FOR(unsigned int, cos_video);
|
||||||
|
DEFINE_GETTERS_SETTERS_FOR(unsigned int, max_streams);
|
||||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_dtmf, dtmf);
|
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_dtmf, dtmf);
|
||||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_ice, ice);
|
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_ice, ice);
|
||||||
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_impl, impl);
|
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_impl, impl);
|
||||||
@@ -110,12 +118,87 @@ void ast_sdp_options_set_sched_type(struct ast_sdp_options *options, enum ast_me
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ast_format_cap *ast_sdp_options_get_format_cap_type(const struct ast_sdp_options *options,
|
||||||
|
enum ast_media_type type)
|
||||||
|
{
|
||||||
|
struct ast_format_cap *cap = NULL;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case AST_MEDIA_TYPE_AUDIO:
|
||||||
|
case AST_MEDIA_TYPE_VIDEO:
|
||||||
|
case AST_MEDIA_TYPE_IMAGE:
|
||||||
|
case AST_MEDIA_TYPE_TEXT:
|
||||||
|
cap = options->caps[type];
|
||||||
|
break;
|
||||||
|
case AST_MEDIA_TYPE_UNKNOWN:
|
||||||
|
case AST_MEDIA_TYPE_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_sdp_options_set_format_cap_type(struct ast_sdp_options *options,
|
||||||
|
enum ast_media_type type, struct ast_format_cap *cap)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case AST_MEDIA_TYPE_AUDIO:
|
||||||
|
case AST_MEDIA_TYPE_VIDEO:
|
||||||
|
case AST_MEDIA_TYPE_IMAGE:
|
||||||
|
case AST_MEDIA_TYPE_TEXT:
|
||||||
|
ao2_cleanup(options->caps[type]);
|
||||||
|
options->caps[type] = NULL;
|
||||||
|
if (cap && !ast_format_cap_empty(cap)) {
|
||||||
|
ao2_ref(cap, +1);
|
||||||
|
options->caps[type] = cap;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AST_MEDIA_TYPE_UNKNOWN:
|
||||||
|
case AST_MEDIA_TYPE_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_sdp_options_set_format_caps(struct ast_sdp_options *options,
|
||||||
|
struct ast_format_cap *cap)
|
||||||
|
{
|
||||||
|
enum ast_media_type type;
|
||||||
|
|
||||||
|
for (type = AST_MEDIA_TYPE_UNKNOWN; type < AST_MEDIA_TYPE_END; ++type) {
|
||||||
|
ao2_cleanup(options->caps[type]);
|
||||||
|
options->caps[type] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cap || ast_format_cap_empty(cap)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (type = AST_MEDIA_TYPE_UNKNOWN + 1; type < AST_MEDIA_TYPE_END; ++type) {
|
||||||
|
struct ast_format_cap *type_cap;
|
||||||
|
|
||||||
|
type_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
|
||||||
|
if (!type_cap) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_format_cap_set_framing(type_cap, ast_format_cap_get_framing(cap));
|
||||||
|
if (ast_format_cap_append_from_cap(type_cap, cap, type)
|
||||||
|
|| ast_format_cap_empty(type_cap)) {
|
||||||
|
ao2_ref(type_cap, -1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This takes the allocation reference */
|
||||||
|
options->caps[type] = type_cap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void set_defaults(struct ast_sdp_options *options)
|
static void set_defaults(struct ast_sdp_options *options)
|
||||||
{
|
{
|
||||||
options->dtmf = DEFAULT_DTMF;
|
options->dtmf = DEFAULT_DTMF;
|
||||||
options->ice = DEFAULT_ICE;
|
options->ice = DEFAULT_ICE;
|
||||||
options->impl = DEFAULT_IMPL;
|
options->impl = DEFAULT_IMPL;
|
||||||
options->encryption = DEFAULT_ENCRYPTION;
|
options->encryption = DEFAULT_ENCRYPTION;
|
||||||
|
options->max_streams = DEFAULT_MAX_STREAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ast_sdp_options *ast_sdp_options_alloc(void)
|
struct ast_sdp_options *ast_sdp_options_alloc(void)
|
||||||
@@ -138,6 +221,15 @@ struct ast_sdp_options *ast_sdp_options_alloc(void)
|
|||||||
|
|
||||||
void ast_sdp_options_free(struct ast_sdp_options *options)
|
void ast_sdp_options_free(struct ast_sdp_options *options)
|
||||||
{
|
{
|
||||||
|
enum ast_media_type type;
|
||||||
|
|
||||||
|
if (!options) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (type = AST_MEDIA_TYPE_UNKNOWN; type < AST_MEDIA_TYPE_END; ++type) {
|
||||||
|
ao2_cleanup(options->caps[type]);
|
||||||
|
}
|
||||||
ast_string_field_free_memory(options);
|
ast_string_field_free_memory(options);
|
||||||
ast_free(options);
|
ast_free(options);
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
struct ast_sdp_options {
|
struct ast_sdp_options {
|
||||||
AST_DECLARE_STRING_FIELDS(
|
AST_DECLARE_STRING_FIELDS(
|
||||||
/*! Media address to use in SDP */
|
/*! Media address to advertise in SDP session c= line */
|
||||||
AST_STRING_FIELD(media_address);
|
AST_STRING_FIELD(media_address);
|
||||||
/*! Optional address of the interface media should use. */
|
/*! Optional address of the interface media should use. */
|
||||||
AST_STRING_FIELD(interface_address);
|
AST_STRING_FIELD(interface_address);
|
||||||
@@ -37,12 +37,25 @@ struct ast_sdp_options {
|
|||||||
);
|
);
|
||||||
/*! Scheduler context for the media stream types (Mainly for RTP) */
|
/*! Scheduler context for the media stream types (Mainly for RTP) */
|
||||||
struct ast_sched_context *sched[AST_MEDIA_TYPE_END];
|
struct ast_sched_context *sched[AST_MEDIA_TYPE_END];
|
||||||
|
/*! Capabilities to create new streams of the indexed media type. */
|
||||||
|
struct ast_format_cap *caps[AST_MEDIA_TYPE_END];
|
||||||
|
/*! User supplied context data pointer for the SDP state. */
|
||||||
|
void *state_context;
|
||||||
|
/*! Modify negotiated topology before create answer SDP callback. */
|
||||||
|
ast_sdp_answerer_modify_cb answerer_modify_cb;
|
||||||
|
/*! Modify proposed topology before create offer SDP callback. */
|
||||||
|
ast_sdp_offerer_modify_cb offerer_modify_cb;
|
||||||
|
/*! Configure proposed topology extra stream options before create offer SDP callback. */
|
||||||
|
ast_sdp_offerer_config_cb offerer_config_cb;
|
||||||
|
/*! Negotiated topology is about to be applied callback. */
|
||||||
|
ast_sdp_preapply_cb preapply_cb;
|
||||||
|
/*! Negotiated topology was just applied callback. */
|
||||||
|
ast_sdp_postapply_cb postapply_cb;
|
||||||
struct {
|
struct {
|
||||||
unsigned int rtp_symmetric:1;
|
unsigned int rtp_symmetric:1;
|
||||||
unsigned int udptl_symmetric:1;
|
unsigned int udptl_symmetric:1;
|
||||||
unsigned int rtp_ipv6:1;
|
unsigned int rtp_ipv6:1;
|
||||||
unsigned int g726_non_standard:1;
|
unsigned int g726_non_standard:1;
|
||||||
unsigned int locally_held:1;
|
|
||||||
unsigned int rtcp_mux:1;
|
unsigned int rtcp_mux:1;
|
||||||
unsigned int ssrc:1;
|
unsigned int ssrc:1;
|
||||||
};
|
};
|
||||||
@@ -52,6 +65,8 @@ struct ast_sdp_options {
|
|||||||
unsigned int tos_video;
|
unsigned int tos_video;
|
||||||
unsigned int cos_video;
|
unsigned int cos_video;
|
||||||
unsigned int udptl_far_max_datagram;
|
unsigned int udptl_far_max_datagram;
|
||||||
|
/*! Maximum number of streams to allow. */
|
||||||
|
unsigned int max_streams;
|
||||||
};
|
};
|
||||||
enum ast_sdp_options_dtmf dtmf;
|
enum ast_sdp_options_dtmf dtmf;
|
||||||
enum ast_sdp_options_ice ice;
|
enum ast_sdp_options_ice ice;
|
||||||
|
2195
main/sdp_state.c
2195
main/sdp_state.c
File diff suppressed because it is too large
Load Diff
@@ -214,6 +214,23 @@ const char *ast_stream_state2str(enum ast_stream_state state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ast_stream_state ast_stream_str2state(const char *str)
|
||||||
|
{
|
||||||
|
if (!strcmp("sendrecv", str)) {
|
||||||
|
return AST_STREAM_STATE_SENDRECV;
|
||||||
|
}
|
||||||
|
if (!strcmp("sendonly", str)) {
|
||||||
|
return AST_STREAM_STATE_SENDONLY;
|
||||||
|
}
|
||||||
|
if (!strcmp("recvonly", str)) {
|
||||||
|
return AST_STREAM_STATE_RECVONLY;
|
||||||
|
}
|
||||||
|
if (!strcmp("inactive", str)) {
|
||||||
|
return AST_STREAM_STATE_INACTIVE;
|
||||||
|
}
|
||||||
|
return AST_STREAM_STATE_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
void *ast_stream_get_data(struct ast_stream *stream, enum ast_stream_data_slot slot)
|
void *ast_stream_get_data(struct ast_stream *stream, enum ast_stream_data_slot slot)
|
||||||
{
|
{
|
||||||
ast_assert(stream != NULL);
|
ast_assert(stream != NULL);
|
||||||
|
@@ -484,7 +484,7 @@ AST_TEST_DEFINE(pjmedia_to_sdp_test)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
ast_sdp_free(sdp);
|
ao2_cleanup(sdp);
|
||||||
ast_sdp_translator_free(translator);
|
ast_sdp_translator_free(translator);
|
||||||
pj_pool_release(pool);
|
pj_pool_release(pool);
|
||||||
return res;
|
return res;
|
||||||
@@ -560,7 +560,7 @@ AST_TEST_DEFINE(sdp_to_pjmedia_test)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
ast_sdp_free(sdp);
|
ao2_cleanup(sdp);
|
||||||
ast_sdp_translator_free(translator);
|
ast_sdp_translator_free(translator);
|
||||||
pj_pool_release(pool);
|
pj_pool_release(pool);
|
||||||
return res;
|
return res;
|
||||||
|
1202
tests/test_sdp.c
1202
tests/test_sdp.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user