mirror of
https://gitlab.gnome.org/GNOME/calls.git
synced 2024-11-16 05:15:36 +00:00
e75e04fb4e
A property of type SipMediaEncryption is added to both the origin and the call which allows to state if we want the media session to be encrypted with SRTP. Logic is added to interact with the CallsSdpCryptoContext if encryption is desired.
294 lines
9.6 KiB
C
294 lines
9.6 KiB
C
/*
|
|
* Copyright (C) 2022 Purism SPC
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0+
|
|
*
|
|
* Author: Evangelos Ribeiro Tzaras <evangelos.tzaras@puri.sm>
|
|
*/
|
|
|
|
#include "calls-sip-call.h"
|
|
#include "calls-sip-media-manager.h"
|
|
#include "calls-srtp-utils.h"
|
|
#include "gst-rfc3551.h"
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <gst/gst.h>
|
|
|
|
static gboolean
|
|
find_string_in_sdp_message (const char *sdp,
|
|
const char *string)
|
|
{
|
|
char **split_string = NULL;
|
|
gboolean found = FALSE;
|
|
|
|
split_string = g_strsplit (sdp, "\r\n", -1);
|
|
|
|
for (guint i = 0; split_string[i] != NULL; i++) {
|
|
if (g_strcmp0 (split_string[i], string) == 0) {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_strfreev (split_string);
|
|
return found;
|
|
}
|
|
|
|
|
|
static void
|
|
test_sip_media_manager_caps (void)
|
|
{
|
|
CallsSipMediaManager *manager = calls_sip_media_manager_default ();
|
|
char *sdp_message = NULL;
|
|
GList *codecs = NULL;
|
|
GList *crypto_attributes;
|
|
calls_srtp_crypto_attribute *attr;
|
|
|
|
attr = calls_srtp_crypto_attribute_new (1);
|
|
attr->tag = 1;
|
|
attr->crypto_suite = CALLS_SRTP_SUITE_AES_128_SHA1_80;
|
|
calls_srtp_crypto_attribute_init_keys (attr);
|
|
|
|
crypto_attributes = g_list_append (NULL, attr);
|
|
/* Check single codecs */
|
|
codecs = g_list_append (NULL, media_codec_by_name ("PCMA"));
|
|
|
|
g_debug ("Testing generated SDP messages");
|
|
|
|
/* PCMA RTP */
|
|
sdp_message =
|
|
calls_sip_media_manager_get_capabilities (manager, NULL, 40002, 40003, NULL, codecs);
|
|
|
|
g_assert_true (sdp_message);
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"m=audio 40002 RTP/AVP 8"));
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"a=rtpmap:8 PCMA/8000"));
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"a=rtcp:40003"));
|
|
|
|
g_free (sdp_message);
|
|
|
|
g_debug ("PCMA RTP test OK");
|
|
|
|
/* PCMA SRTP */
|
|
sdp_message =
|
|
calls_sip_media_manager_get_capabilities (manager, NULL, 42002, 42003, crypto_attributes, codecs);
|
|
g_assert_true (sdp_message);
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"m=audio 42002 RTP/SAVP 8"));
|
|
|
|
g_clear_pointer (&codecs, g_list_free);
|
|
g_free (sdp_message);
|
|
|
|
g_debug ("PCMA SRTP test OK");
|
|
|
|
/* G722 RTP */
|
|
codecs = g_list_append (NULL, media_codec_by_name ("G722"));
|
|
|
|
sdp_message =
|
|
calls_sip_media_manager_get_capabilities (manager, NULL, 42042, 55543, NULL, codecs);
|
|
|
|
g_assert_true (sdp_message);
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"m=audio 42042 RTP/AVP 9"));
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"a=rtpmap:9 G722/8000"));
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"a=rtcp:55543"));
|
|
|
|
g_clear_pointer (&codecs, g_list_free);
|
|
g_free (sdp_message);
|
|
|
|
g_debug ("G722 RTP test OK");
|
|
|
|
/* G722 PCMU PCMA RTP (in this order) */
|
|
codecs = g_list_append (NULL, media_codec_by_name ("G722"));
|
|
codecs = g_list_append (codecs, media_codec_by_name ("PCMU"));
|
|
codecs = g_list_append (codecs, media_codec_by_name ("PCMA"));
|
|
|
|
sdp_message =
|
|
calls_sip_media_manager_get_capabilities (manager, NULL, 33340, 33341, NULL, codecs);
|
|
|
|
g_assert_true (sdp_message);
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"m=audio 33340 RTP/AVP 9 0 8"));
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"a=rtpmap:9 G722/8000"));
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"a=rtpmap:0 PCMU/8000"));
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"a=rtpmap:8 PCMA/8000"));
|
|
|
|
g_clear_pointer (&codecs, g_list_free);
|
|
g_free (sdp_message);
|
|
|
|
g_debug ("multiple codecs RTP test OK");
|
|
|
|
/* GSM PCMA G722 PCMU SRTP (in this order) */
|
|
codecs = g_list_append (NULL, media_codec_by_name ("GSM"));
|
|
codecs = g_list_append (codecs, media_codec_by_name ("PCMA"));
|
|
codecs = g_list_append (codecs, media_codec_by_name ("G722"));
|
|
codecs = g_list_append (codecs, media_codec_by_name ("PCMU"));
|
|
|
|
sdp_message =
|
|
calls_sip_media_manager_get_capabilities (manager, NULL, 18098, 18099, crypto_attributes, codecs);
|
|
|
|
g_assert_true (sdp_message);
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"m=audio 18098 RTP/SAVP 3 8 9 0"));
|
|
|
|
g_clear_pointer (&codecs, g_list_free);
|
|
g_free (sdp_message);
|
|
|
|
g_debug ("multiple codecs SRTP test OK");
|
|
|
|
/* no codecs */
|
|
g_test_expect_message ("CallsSipMediaManager", G_LOG_LEVEL_WARNING,
|
|
"No supported codecs found. Can't build meaningful SDP message");
|
|
sdp_message =
|
|
calls_sip_media_manager_get_capabilities (manager, NULL, 25048, 25049, NULL, NULL);
|
|
|
|
g_test_assert_expected_messages ();
|
|
g_assert_true (sdp_message);
|
|
g_assert_true (find_string_in_sdp_message (sdp_message,
|
|
"m=audio 0 RTP/AVP"));
|
|
|
|
g_free (sdp_message);
|
|
|
|
g_debug ("no codecs test OK");
|
|
|
|
g_list_free (crypto_attributes);
|
|
calls_srtp_crypto_attribute_free (attr);
|
|
}
|
|
|
|
|
|
static void
|
|
test_media_pipeline_states (void)
|
|
{
|
|
CallsSipMediaPipeline *pipeline = calls_sip_media_pipeline_new (NULL);
|
|
MediaCodecInfo *codec = media_codec_by_name ("PCMA");
|
|
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_NEED_CODEC);
|
|
|
|
calls_sip_media_pipeline_set_codec (pipeline, codec);
|
|
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_READY);
|
|
|
|
calls_sip_media_pipeline_start (pipeline);
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_PLAY_PENDING);
|
|
|
|
calls_sip_media_pipeline_pause (pipeline, TRUE);
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_PAUSE_PENDING);
|
|
|
|
calls_sip_media_pipeline_pause (pipeline, FALSE);
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_PLAY_PENDING);
|
|
|
|
calls_sip_media_pipeline_stop (pipeline);
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_STOP_PENDING);
|
|
|
|
g_assert_finalize_object (pipeline);
|
|
}
|
|
|
|
|
|
static void
|
|
test_media_pipeline_setup_codecs (void)
|
|
{
|
|
const char * const codec_names[] = {"PCMA", "PCMU", "GSM", "G722"};
|
|
|
|
for (uint i = 0; i < G_N_ELEMENTS (codec_names); i++) {
|
|
g_autoptr (CallsSipMediaPipeline) pipeline = calls_sip_media_pipeline_new (NULL);
|
|
MediaCodecInfo *codec = media_codec_by_name ("PCMA");
|
|
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_NEED_CODEC);
|
|
|
|
calls_sip_media_pipeline_set_codec (pipeline, codec);
|
|
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_READY);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
test_media_pipeline_start_no_codec (void)
|
|
{
|
|
g_autoptr (CallsSipMediaPipeline) pipeline = calls_sip_media_pipeline_new (NULL);
|
|
|
|
g_assert_cmpint (calls_sip_media_pipeline_get_state (pipeline), ==,
|
|
CALLS_MEDIA_PIPELINE_STATE_NEED_CODEC);
|
|
|
|
g_test_expect_message ("CallsSipMediaPipeline", G_LOG_LEVEL_WARNING,
|
|
"Cannot start pipeline because it's not ready");
|
|
|
|
calls_sip_media_pipeline_start (pipeline);
|
|
g_test_assert_expected_messages ();
|
|
|
|
g_test_expect_message ("CallsSipMediaPipeline", G_LOG_LEVEL_WARNING,
|
|
"Cannot pause or unpause pipeline because it's not currently active");
|
|
|
|
calls_sip_media_pipeline_pause (pipeline, TRUE);
|
|
g_test_assert_expected_messages ();
|
|
}
|
|
|
|
|
|
static void
|
|
test_media_pipeline_finalized_in_call (void)
|
|
{
|
|
CallsSipMediaManager *manager = calls_sip_media_manager_default ();
|
|
CallsSipMediaPipeline *pipeline = calls_sip_media_pipeline_new (NULL);
|
|
CallsSipCall *call = calls_sip_call_new ("sip:alice@example.org",
|
|
TRUE,
|
|
"127.0.0.1",
|
|
pipeline,
|
|
SIP_MEDIA_ENCRYPTION_NONE,
|
|
NULL);
|
|
|
|
g_object_unref (call);
|
|
g_assert_finalize_object (pipeline);
|
|
|
|
pipeline = calls_sip_media_manager_get_pipeline (manager);
|
|
call = calls_sip_call_new ("sip:bob@example.org",
|
|
TRUE,
|
|
"127.0.0.1",
|
|
pipeline,
|
|
SIP_MEDIA_ENCRYPTION_NONE,
|
|
NULL);
|
|
g_object_unref (call);
|
|
g_assert_finalize_object (pipeline);
|
|
}
|
|
|
|
|
|
int
|
|
main (int argc,
|
|
char *argv[])
|
|
{
|
|
CallsSipMediaManager *manager = calls_sip_media_manager_default ();
|
|
int ret;
|
|
|
|
gtk_test_init (&argc, &argv, NULL);
|
|
|
|
gst_init (NULL, NULL);
|
|
|
|
g_test_add_func ("/Calls/media/media_manager/capabilities", test_sip_media_manager_caps);
|
|
g_test_add_func ("/Calls/media/pipeline/states", test_media_pipeline_states);
|
|
g_test_add_func ("/Calls/media/pipeline/setup_codecs", test_media_pipeline_setup_codecs);
|
|
g_test_add_func ("/Calls/media/pipeline/start_no_codec", test_media_pipeline_start_no_codec);
|
|
g_test_add_func ("/Calls/media/pipeline/finalized_in_call", test_media_pipeline_finalized_in_call);
|
|
|
|
ret = g_test_run ();
|
|
|
|
g_assert_finalize_object (manager);
|
|
|
|
gst_deinit ();
|
|
|
|
return ret;
|
|
}
|