enum ast_sip_dtmf_mode dtmf;
/*! Initial incoming INVITE Request-URI. NULL otherwise. */
pjsip_uri *request_uri;
+ /* Media statistics for negotiated RTP streams */
+ AST_VECTOR(, struct ast_rtp_instance_stats *) media_stats;
};
typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
struct ast_sip_session_media *ast_sip_session_media_state_add(struct ast_sip_session *session,
struct ast_sip_session_media_state *media_state, enum ast_media_type type, int position);
+/*!
+ * \brief Save a media stats.
+ *
+ * \param media_state The media state to save
+ */
+void ast_sip_session_media_stats_save(struct ast_sip_session *sip_session, struct ast_sip_session_media_state *media_state);
+
/*!
* \brief Reset a media state to a clean state
* \since 15.0.0
#include "asterisk/pickup.h"
#include "asterisk/test.h"
#include "asterisk/stream.h"
+#include "asterisk/vector.h"
#define SDP_HANDLER_BUCKETS 11
ao2_callback_data(sdp_handlers, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, remove_handler, (void *)stream_type, handler);
}
+static int media_stats_local_ssrc_cmp(
+ const struct ast_rtp_instance_stats *vec_elem, const struct ast_rtp_instance_stats *srch)
+{
+ if (vec_elem->local_ssrc == srch->local_ssrc) {
+ return 1;
+ }
+
+ return 0;
+}
+
static struct ast_sip_session_media_state *internal_sip_session_media_state_alloc(
size_t sessions, size_t read_callbacks)
{
DEFAULT_NUM_SESSION_MEDIA, DEFAULT_NUM_SESSION_MEDIA);
}
+void ast_sip_session_media_stats_save(struct ast_sip_session *sip_session, struct ast_sip_session_media_state *media_state)
+{
+ int i;
+ int ret;
+
+ if (!media_state || !sip_session) {
+ return;
+ }
+
+ for (i = 0; i < AST_VECTOR_SIZE(&media_state->sessions); i++) {
+ struct ast_rtp_instance_stats *stats_tmp = NULL;
+ struct ast_sip_session_media *media = AST_VECTOR_GET(&media_state->sessions, i);
+ if (!media || !media->rtp) {
+ continue;
+ }
+
+ stats_tmp = ast_calloc(1, sizeof(struct ast_rtp_instance_stats));
+ if (!stats_tmp) {
+ return;
+ }
+
+ ret = ast_rtp_instance_get_stats(media->rtp, stats_tmp, AST_RTP_INSTANCE_STAT_ALL);
+ if (ret) {
+ ast_free(stats_tmp);
+ continue;
+ }
+
+ /* remove all the duplicated stats if exist */
+ AST_VECTOR_REMOVE_CMP_UNORDERED(&sip_session->media_stats, stats_tmp, media_stats_local_ssrc_cmp, ast_free);
+
+ AST_VECTOR_APPEND(&sip_session->media_stats, stats_tmp);
+ }
+}
+
void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
{
int index;
}
/* Active and pending flip flop as needed */
+ ast_sip_session_media_stats_save(session, session->active_media_state);
SWAP(session->active_media_state, session->pending_media_state);
ast_sip_session_media_state_reset(session->pending_media_state);
ast_sip_session_remove_supplements(session);
AST_LIST_HEAD_DESTROY(&session->supplements);
+ /* remove all saved media stats */
+ AST_VECTOR_RESET(&session->media_stats, ast_free);
+ AST_VECTOR_FREE(&session->media_stats);
+
ast_taskprocessor_unreference(session->serializer);
ao2_cleanup(session->datastores);
ast_sip_session_media_state_free(session->active_media_state);
if (!session->pending_media_state) {
return NULL;
}
+ if (AST_VECTOR_INIT(&session->media_stats, 1) < 0) {
+ return NULL;
+ }
if (endpoint->dtmf == AST_SIP_DTMF_INBAND || endpoint->dtmf == AST_SIP_DTMF_AUTO) {
dsp_features |= DSP_FEATURE_DIGIT_DETECT;
* places when the session is to be terminated we terminate any existing
* media sessions here.
*/
+ ast_sip_session_media_stats_save(session, session->active_media_state);
SWAP(session->active_media_state, session->pending_media_state);
ast_sip_session_media_state_reset(session->pending_media_state);