From c149a6da7e31ff21242707b93b3dc1fe114fde4c Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Wed, 7 Oct 2015 10:55:10 +0200 Subject: [PATCH] Add API to handle custom SDP attributes. --- coreapi/bellesip_sal/sal_impl.c | 34 ++++++++++++++++ coreapi/bellesip_sal/sal_sdp.c | 32 ++++++++++++++++ coreapi/call_params.c | 64 ++++++++++++++++++++++++++----- coreapi/call_params.h | 34 ++++++++++++++++ coreapi/linphonecall.c | 16 +++++++- coreapi/linphonecore.h | 23 +++++++++-- coreapi/private.h | 4 ++ coreapi/sal.c | 2 + include/sal/sal.h | 12 ++++++ tester/call_tester.c | 35 +++++++++++++++++ tester/quality_reporting_tester.c | 2 +- 11 files changed, 244 insertions(+), 14 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index bf87b83d6..90295e38d 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -924,6 +924,40 @@ const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op){ return b->recv_custom_headers; } +SalCustomSdpAttribute * sal_custom_sdp_attribute_append(SalCustomSdpAttribute *csa, const char *name, const char *value) { + belle_sdp_session_description_t *desc = (belle_sdp_session_description_t *)csa; + belle_sdp_attribute_t *attr; + + if (desc == NULL) { + desc = (belle_sdp_session_description_t *)belle_sdp_session_description_new(); + belle_sip_object_ref(desc); + } + attr = BELLE_SDP_ATTRIBUTE(belle_sdp_raw_attribute_create(name, value)); + if (attr == NULL) { + belle_sip_error("Fail to create custom SDP attribute."); + return (SalCustomSdpAttribute*)desc; + } + belle_sdp_session_description_add_attribute(desc, attr); + return (SalCustomSdpAttribute *)desc; +} + +const char * sal_custom_sdp_attribute_find(const SalCustomSdpAttribute *csa, const char *name) { + if (csa) { + return belle_sdp_session_description_get_attribute_value((belle_sdp_session_description_t *)csa, name); + } + return NULL; +} + +void sal_custom_sdp_attribute_free(SalCustomSdpAttribute *csa) { + if (csa == NULL) return; + belle_sip_object_unref((belle_sdp_session_description_t *)csa); +} + +SalCustomSdpAttribute * sal_custom_sdp_attribute_clone(const SalCustomSdpAttribute *csa) { + if (csa == NULL) return NULL; + return (SalCustomSdpAttribute *)belle_sip_object_ref((belle_sdp_session_description_t *)csa); +} + void sal_set_uuid(Sal *sal, const char *uuid){ if (sal->uuid){ ms_free(sal->uuid); diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index ec84ccfe4..f5a55cb52 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -355,6 +355,16 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session belle_sip_object_unref((belle_sip_object_t*)media_attribute); } } + + if (stream->custom_sdp_attributes) { + belle_sdp_session_description_t *custom_desc = (belle_sdp_session_description_t *)stream->custom_sdp_attributes; + belle_sip_list_t *l = belle_sdp_session_description_get_attributes(custom_desc); + belle_sip_list_t *elem; + for (elem = l; elem != NULL; elem = elem->next) { + belle_sdp_media_description_add_attribute(media_desc, (belle_sdp_attribute_t *)elem->data); + } + } + /* * rfc5576 * 4.1. The "ssrc" Media Attribute @@ -415,6 +425,14 @@ belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescr if (desc->rtcp_xr.enabled == TRUE) { belle_sdp_session_description_add_attribute(session_desc, create_rtcp_xr_attribute(&desc->rtcp_xr)); } + if (desc->custom_sdp_attributes) { + belle_sdp_session_description_t *custom_desc = (belle_sdp_session_description_t *)desc->custom_sdp_attributes; + belle_sip_list_t *l = belle_sdp_session_description_get_attributes(custom_desc); + belle_sip_list_t *elem; + for (elem = l; elem != NULL; elem = elem->next) { + belle_sdp_session_description_add_attribute(session_desc, (belle_sdp_attribute_t *)elem->data); + } + } for ( i=0; inb_streams; i++ ) { stream_description_to_sdp(session_desc, desc, &desc->streams[i]); @@ -702,6 +720,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, belle_sdp_connection_t* cnx; belle_sdp_media_t* media; belle_sdp_attribute_t* attribute; + belle_sip_list_t *custom_attribute_it; const char* value; const char *mtype,*proto; @@ -816,6 +835,12 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, stream->rtcp_xr = md->rtcp_xr; // Use session parameters if no stream parameters are defined sdp_parse_media_rtcp_xr_parameters(media_desc, &stream->rtcp_xr); + /* Get the custom attributes */ + for (custom_attribute_it = belle_sdp_media_description_get_attributes(media_desc); custom_attribute_it != NULL; custom_attribute_it = custom_attribute_it->next) { + belle_sdp_attribute_t *attr = (belle_sdp_attribute_t *)custom_attribute_it->data; + stream->custom_sdp_attributes = sal_custom_sdp_attribute_append(stream->custom_sdp_attributes, belle_sdp_attribute_get_name(attr), belle_sdp_attribute_get_value(attr)); + } + md->nb_streams++; return stream; } @@ -826,6 +851,7 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S belle_sip_list_t* media_desc_it; belle_sdp_media_description_t* media_desc; belle_sdp_session_name_t *sname; + belle_sip_list_t *custom_attribute_it; const char* value; SalDtlsRole session_role=SalDtlsRoleInvalid; int i; @@ -887,6 +913,12 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S /* Get session RTCP-XR attributes if any */ sdp_parse_session_rtcp_xr_parameters(session_desc, &desc->rtcp_xr); + /* Get the custom attributes */ + for (custom_attribute_it = belle_sdp_session_description_get_attributes(session_desc); custom_attribute_it != NULL; custom_attribute_it = custom_attribute_it->next) { + belle_sdp_attribute_t *attr = (belle_sdp_attribute_t *)custom_attribute_it->data; + desc->custom_sdp_attributes = sal_custom_sdp_attribute_append(desc->custom_sdp_attributes, belle_sdp_attribute_get_name(attr), belle_sdp_attribute_get_value(attr)); + } + for ( media_desc_it=belle_sdp_session_description_get_media_descriptions ( session_desc ) ; media_desc_it!=NULL ; media_desc_it=media_desc_it->next ) { diff --git a/coreapi/call_params.c b/coreapi/call_params.c index 58a1bc17e..63dc25cbf 100644 --- a/coreapi/call_params.c +++ b/coreapi/call_params.c @@ -82,6 +82,26 @@ void linphone_call_params_set_custom_headers(LinphoneCallParams *params, const S } } +void linphone_call_params_set_custom_sdp_attributes(LinphoneCallParams *params, const SalCustomSdpAttribute *csa) { + if (params->custom_sdp_attributes) { + sal_custom_sdp_attribute_free(params->custom_sdp_attributes); + params->custom_sdp_attributes = NULL; + } + if (csa) { + params->custom_sdp_attributes = sal_custom_sdp_attribute_clone(csa); + } +} + +void linphone_call_params_set_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type, const SalCustomSdpAttribute *csa) { + if (params->custom_sdp_media_attributes[type]) { + sal_custom_sdp_attribute_free(params->custom_sdp_media_attributes[type]); + params->custom_sdp_media_attributes[type] = NULL; + } + if (csa) { + params->custom_sdp_media_attributes[type] = sal_custom_sdp_attribute_clone(csa); + } +} + /******************************************************************************* * Public functions * @@ -91,7 +111,16 @@ void linphone_call_params_add_custom_header(LinphoneCallParams *params, const ch params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value); } +void linphone_call_params_add_custom_sdp_attribute(LinphoneCallParams *params, const char *attribute_name, const char *attribute_value) { + params->custom_sdp_attributes = sal_custom_sdp_attribute_append(params->custom_sdp_attributes, attribute_name, attribute_value); +} + +void linphone_call_params_add_custom_sdp_media_attribute(LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name, const char *attribute_value) { + params->custom_sdp_media_attributes[type] = sal_custom_sdp_attribute_append(params->custom_sdp_media_attributes[type], attribute_name, attribute_value); +} + LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){ + unsigned int i; LinphoneCallParams *ncp=linphone_call_params_new(); memcpy(ncp,cp,sizeof(LinphoneCallParams)); if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file); @@ -100,6 +129,10 @@ LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){ * The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient. */ if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers); + if (cp->custom_sdp_attributes) ncp->custom_sdp_attributes = sal_custom_sdp_attribute_clone(cp->custom_sdp_attributes); + for (i = 0; i < (unsigned int)LinphoneStreamTypeUnknown; i++) { + if (cp->custom_sdp_media_attributes[i]) ncp->custom_sdp_media_attributes[i] = sal_custom_sdp_attribute_clone(cp->custom_sdp_media_attributes[i]); + } return ncp; } @@ -122,6 +155,11 @@ void linphone_call_params_enable_audio(LinphoneCallParams *cp, bool_t enabled){ cp->audio_dir=LinphoneMediaDirectionSendRecv; } +int linphone_call_params_enable_realtime_text(LinphoneCallParams *params, bool_t yesno) { + params->realtimetext_enabled=yesno; + return 0; +} + void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){ cp->has_video=enabled; if (enabled && cp->video_dir==LinphoneMediaDirectionInactive) @@ -132,6 +170,14 @@ const char *linphone_call_params_get_custom_header(const LinphoneCallParams *par return sal_custom_header_find(params->custom_headers,header_name); } +const char * linphone_call_params_get_custom_sdp_attribute(const LinphoneCallParams *params, const char *attribute_name) { + return sal_custom_sdp_attribute_find(params->custom_sdp_attributes, attribute_name); +} + +const char * linphone_call_params_get_custom_sdp_media_attribute(const LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name) { + return sal_custom_sdp_attribute_find(params->custom_sdp_media_attributes[type], attribute_name); +} + bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){ return cp->in_conference; } @@ -216,6 +262,10 @@ bool_t linphone_call_params_audio_enabled(const LinphoneCallParams *cp){ return cp->has_audio; } +bool_t linphone_call_params_realtime_text_enabled(const LinphoneCallParams *params) { + return params->realtimetext_enabled; +} + bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){ return cp->has_video; } @@ -278,8 +328,13 @@ bool_t linphone_call_params_video_multicast_enabled(const LinphoneCallParams *pa ******************************************************************************/ static void _linphone_call_params_destroy(LinphoneCallParams *cp){ + unsigned int i; if (cp->record_file) ms_free(cp->record_file); if (cp->custom_headers) sal_custom_header_free(cp->custom_headers); + if (cp->custom_sdp_attributes) sal_custom_sdp_attribute_free(cp->custom_sdp_attributes); + for (i = 0; i < (unsigned int)LinphoneStreamTypeUnknown; i++) { + if (cp->custom_sdp_media_attributes[i]) sal_custom_sdp_attribute_free(cp->custom_sdp_media_attributes[i]); + } if (cp->session_name) ms_free(cp->session_name); } @@ -305,12 +360,3 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallParams, belle_sip_object_t, NULL, // marshal FALSE ); - -int linphone_call_params_enable_realtime_text(LinphoneCallParams *params, bool_t yesno) { - params->realtimetext_enabled=yesno; - return 0; -} - -bool_t linphone_call_params_realtime_text_enabled(const LinphoneCallParams *params) { - return params->realtimetext_enabled; -} diff --git a/coreapi/call_params.h b/coreapi/call_params.h index 84b605bea..a9e81ee5e 100644 --- a/coreapi/call_params.h +++ b/coreapi/call_params.h @@ -388,6 +388,40 @@ LINPHONE_PUBLIC int linphone_call_params_enable_realtime_text(LinphoneCallParams **/ LINPHONE_PUBLIC bool_t linphone_call_params_realtime_text_enabled(const LinphoneCallParams *params); +/** + * Add a custom attribute related to all the streams in the SDP exchanged within SIP messages during a call. + * @param[in] params The #LinphoneCallParams to add a custom SDP attribute to. + * @param[in] attribute_name The name of the attribute to add. + * @param[in] attribute_value The content value of the attribute to add. + * @ingroup media_parameters +**/ +LINPHONE_PUBLIC void linphone_call_params_add_custom_sdp_attribute(LinphoneCallParams *params, const char *attribute_name, const char *attribute_value); + +/** + * Add a custom attribute related to a specific stream in the SDP exchanged within SIP messages during a call. + * @param[in] params The #LinphoneCallParams to add a custom SDP attribute to. + * @param[in] attribute_name The name of the attribute to add. + * @param[in] attribute_value The content value of the attribute to add. + * @ingroup media_parameters +**/ +LINPHONE_PUBLIC void linphone_call_params_add_custom_sdp_media_attribute(LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name, const char *attribute_value); + +/** + * Get a custom SDP attribute that is related to all the streams. + * @param[in] params The #LinphoneCallParams to get the custom SDP attribute from. + * @param[in] attribute_name The name of the attribute to get. + * @return The content value of the attribute or NULL if not found. +**/ +LINPHONE_PUBLIC const char * linphone_call_params_get_custom_sdp_attribute(const LinphoneCallParams *params, const char *attribute_name); + +/** + * Get a custom SDP attribute that is related to a specific stream. + * @param[in] params The #LinphoneCallParams to get the custom SDP attribute from. + * @param[in] attribute_name The name of the attribute to get. + * @return The content value of the attribute or NULL if not found. +**/ +LINPHONE_PUBLIC const char * linphone_call_params_get_custom_sdp_media_attribute(const LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name); + /******************************************************************************* * DEPRECATED * diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 348dcfeff..97385b29e 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -681,6 +681,9 @@ void linphone_call_make_local_media_description(LinphoneCall *call) { md->bandwidth=params->down_bw; else md->bandwidth=linphone_core_get_download_bandwidth(lc); + if (params->custom_sdp_attributes) + md->custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_attributes); + /*set audio capabilities */ if (params->has_audio) { strncpy(md->streams[call->main_audio_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_audio_stream_index),sizeof(md->streams[call->main_audio_stream_index].rtp_addr)); @@ -715,6 +718,8 @@ void linphone_call_make_local_media_description(LinphoneCall *call) { ms_message("Don't put audio stream on local offer for call [%p]",call); md->streams[call->main_audio_stream_index].dir = SalStreamInactive; } + if (params->custom_sdp_media_attributes[LinphoneStreamTypeAudio]) + md->streams[call->main_audio_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeAudio]); md->streams[call->main_video_stream_index].proto=md->streams[call->main_audio_stream_index].proto; md->streams[call->main_video_stream_index].dir=get_video_dir_from_call_params(params); @@ -745,7 +750,9 @@ void linphone_call_make_local_media_description(LinphoneCall *call) { ms_message("Don't put video stream on local offer for call [%p]",call); md->streams[call->main_video_stream_index].dir = SalStreamInactive; } - + if (params->custom_sdp_media_attributes[LinphoneStreamTypeVideo]) + md->streams[call->main_video_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeVideo]); + md->streams[call->main_text_stream_index].proto=md->streams[call->main_audio_stream_index].proto; md->streams[call->main_text_stream_index].dir=SalStreamSendRecv; md->streams[call->main_text_stream_index].type=SalText; @@ -776,6 +783,8 @@ void linphone_call_make_local_media_description(LinphoneCall *call) { ms_message("Don't put text stream on local offer for call [%p]",call); md->streams[call->main_text_stream_index].dir = SalStreamInactive; } + if (params->custom_sdp_media_attributes[LinphoneStreamTypeText]) + md->streams[call->main_text_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeText]); md->nb_streams = MAX(md->nb_streams,max_index+1); @@ -1804,6 +1813,11 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){ } } if (md->name[0]!='\0') linphone_call_params_set_session_name(cp,md->name); + + linphone_call_params_set_custom_sdp_attributes(call->remote_params, md->custom_sdp_attributes); + linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeAudio, md->streams[call->main_audio_stream_index].custom_sdp_attributes); + linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeVideo, md->streams[call->main_video_stream_index].custom_sdp_attributes); + linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeText, md->streams[call->main_text_stream_index].custom_sdp_attributes); } linphone_call_params_set_custom_headers(call->remote_params, sal_op_get_recv_custom_header(call->op)); return call->remote_params; diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index d5c7d5f74..2a4439c2c 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -111,6 +111,23 @@ enum _LinphoneTransportType{ **/ typedef enum _LinphoneTransportType LinphoneTransportType; +/** + * Enum describing the stream types. + * @ingroup initializing +**/ +enum _LinphoneStreamType { + LinphoneStreamTypeAudio, + LinphoneStreamTypeVideo, + LinphoneStreamTypeText, + LinphoneStreamTypeUnknown /* WARNING: Make sure this value remains the last one in the list */ +}; + +/** + * Enum describing the stream types. + * @ingroup initializing +**/ +typedef enum _LinphoneStreamType LinphoneStreamType; + /** * Object that represents a SIP address. * @@ -469,9 +486,9 @@ typedef struct _LinphoneVideoPolicy LinphoneVideoPolicy; * @{ **/ -#define LINPHONE_CALL_STATS_AUDIO 0 -#define LINPHONE_CALL_STATS_VIDEO 1 -#define LINPHONE_CALL_STATS_TEXT 2 +#define LINPHONE_CALL_STATS_AUDIO ((int)LinphoneStreamTypeAudio) +#define LINPHONE_CALL_STATS_VIDEO ((int)LinphoneStreamTypeVideo) +#define LINPHONE_CALL_STATS_TEXT ((int)LinphoneStreamTypeText) /** * Enum describing ICE states. diff --git a/coreapi/private.h b/coreapi/private.h index 1f1042fab..66cf24a64 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -128,6 +128,8 @@ struct _LinphoneCallParams{ char *record_file; char *session_name; SalCustomHeader *custom_headers; + SalCustomSdpAttribute *custom_sdp_attributes; + SalCustomSdpAttribute *custom_sdp_media_attributes[LinphoneStreamTypeUnknown]; LinphonePrivacyMask privacy; LinphoneMediaDirection audio_dir; LinphoneMediaDirection video_dir; @@ -346,6 +348,8 @@ SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params); SalStreamDir get_audio_dir_from_call_params(const LinphoneCallParams *params); SalStreamDir get_video_dir_from_call_params(const LinphoneCallParams *params); void linphone_call_params_set_custom_headers(LinphoneCallParams *params, const SalCustomHeader *ch); +void linphone_call_params_set_custom_sdp_attributes(LinphoneCallParams *params, const SalCustomSdpAttribute *csa); +void linphone_call_params_set_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type, const SalCustomSdpAttribute *csa); void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos); void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai); diff --git a/coreapi/sal.c b/coreapi/sal.c index a6f031dce..10fcc44d5 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -72,7 +72,9 @@ static void sal_media_description_destroy(SalMediaDescription *md){ ms_list_free_with_data(md->streams[i].already_assigned_payloads,(void (*)(void *))payload_type_destroy); md->streams[i].payloads=NULL; md->streams[i].already_assigned_payloads=NULL; + sal_custom_sdp_attribute_free(md->streams[i].custom_sdp_attributes); } + sal_custom_sdp_attribute_free(md->custom_sdp_attributes); ms_free(md); } diff --git a/include/sal/sal.h b/include/sal/sal.h index f17a01faf..b202224d9 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -59,6 +59,10 @@ struct SalCustomHeader; typedef struct SalCustomHeader SalCustomHeader; +struct SalCustomSdpAttribute; + +typedef struct SalCustomSdpAttribute SalCustomSdpAttribute; + struct addrinfo; typedef enum { @@ -234,6 +238,7 @@ typedef struct SalStreamDescription{ int max_rate; OrtpRtcpFbConfiguration rtcp_fb; OrtpRtcpXrConfiguration rtcp_xr; + SalCustomSdpAttribute *custom_sdp_attributes; SalIceCandidate ice_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES]; SalIceRemoteCandidate ice_remote_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES]; char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN]; @@ -263,6 +268,7 @@ typedef struct SalMediaDescription{ unsigned int session_id; SalStreamDir dir; SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS]; + SalCustomSdpAttribute *custom_sdp_attributes; OrtpRtcpXrConfiguration rtcp_xr; char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN]; char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN]; @@ -782,6 +788,12 @@ const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op); void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch); + +SalCustomSdpAttribute * sal_custom_sdp_attribute_append(SalCustomSdpAttribute *csa, const char *name, const char *value); +const char * sal_custom_sdp_attribute_find(const SalCustomSdpAttribute *csa, const char *name); +void sal_custom_sdp_attribute_free(SalCustomSdpAttribute *csa); +SalCustomSdpAttribute * sal_custom_sdp_attribute_clone(const SalCustomSdpAttribute *csa); + /** deprecated. use sal_set_log_level instead **/ void sal_enable_log(); /** deprecated. use sal_set_log_level instead **/ diff --git a/tester/call_tester.c b/tester/call_tester.c index f4cafb694..4d9099e8b 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1209,6 +1209,40 @@ static void call_with_custom_headers(void) { linphone_core_manager_destroy(pauline); } +static void call_with_custom_sdp_attributes(void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCall *call_marie, *call_pauline; + LinphoneCallParams *params; + const LinphoneCallParams *marie_remote_params; + const char *value; + + params = linphone_core_create_default_call_parameters(marie->lc); + linphone_call_params_add_custom_sdp_attribute(params, "weather", "bad"); + linphone_call_params_add_custom_sdp_attribute(params, "working", "yes"); + linphone_call_params_add_custom_sdp_media_attribute(params, LinphoneStreamTypeAudio, "sleeping", "almost"); + BC_ASSERT_TRUE(call_with_caller_params(pauline, marie, params)); + linphone_call_params_destroy(params); + + call_marie = linphone_core_get_current_call(marie->lc); + call_pauline = linphone_core_get_current_call(pauline->lc); + BC_ASSERT_PTR_NOT_NULL(call_marie); + BC_ASSERT_PTR_NOT_NULL(call_pauline); + + marie_remote_params = linphone_call_get_remote_params(call_marie); + value = linphone_call_params_get_custom_sdp_attribute(marie_remote_params, "weather"); + BC_ASSERT_PTR_NOT_NULL(value); + BC_ASSERT_STRING_EQUAL(value, "bad"); + value = linphone_call_params_get_custom_sdp_media_attribute(marie_remote_params, LinphoneStreamTypeAudio, "sleeping"); + BC_ASSERT_PTR_NOT_NULL(value); + BC_ASSERT_STRING_EQUAL(value, "almost"); + + end_call(pauline, marie); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + void call_paused_resumed_base(bool_t multicast) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -5271,6 +5305,7 @@ test_t call_tests[] = { { "Call from ICE to not ICE",ice_to_not_ice}, { "Call from not ICE to ICE",not_ice_to_ice}, { "Call with custom headers",call_with_custom_headers}, + { "Call with custom SDP attributes", call_with_custom_sdp_attributes }, { "Call established with rejected INFO",call_established_with_rejected_info}, { "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite}, { "Call established with rejected incoming RE-INVITE", call_established_with_rejected_incoming_reinvite }, diff --git a/tester/quality_reporting_tester.c b/tester/quality_reporting_tester.c index bdccb56b3..206a60fab 100644 --- a/tester/quality_reporting_tester.c +++ b/tester/quality_reporting_tester.c @@ -29,7 +29,7 @@ void on_report_send_mandatory(const LinphoneCall *call, SalStreamType stream_typ char * remote_metrics_start = __strstr(body, "RemoteMetrics:"); reporting_session_report_t * report = call->log->reporting.reports[stream_type]; MediaStream * ms; - if (stream_type == LINPHONE_CALL_STATS_AUDIO){ + if (stream_type == SalAudio){ ms = (MediaStream*)call->audiostream; }else{ ms = (MediaStream*)call->videostream;