mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 01:45:33 +00:00
rtsp-stream: Don't require address pool in the transport specific case
If "transport.client-settings" parameter is set to true, the client is allowed to specify destination, ports and ttl. There is no need for pre-configured address pool. Change-Id: I6ae578fb5164d78e8ec1e2ee82dc4eaacd0912d1 https://bugzilla.gnome.org/show_bug.cgi?id=793441
This commit is contained in:
parent
308480e762
commit
048e24a7c6
2 changed files with 168 additions and 54 deletions
|
@ -1326,11 +1326,11 @@ error:
|
||||||
static gboolean
|
static gboolean
|
||||||
alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
|
alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
|
||||||
GSocket * socket_out[2], GstRTSPAddress ** server_addr_out,
|
GSocket * socket_out[2], GstRTSPAddress ** server_addr_out,
|
||||||
gboolean multicast, GstRTSPTransport * ct)
|
gboolean multicast, GstRTSPTransport * ct, gboolean use_transport_settings)
|
||||||
{
|
{
|
||||||
GstRTSPStreamPrivate *priv = stream->priv;
|
GstRTSPStreamPrivate *priv = stream->priv;
|
||||||
GSocket *rtp_socket = NULL;
|
GSocket *rtp_socket = NULL;
|
||||||
GSocket *rtcp_socket;
|
GSocket *rtcp_socket = NULL;
|
||||||
gint tmp_rtp, tmp_rtcp;
|
gint tmp_rtp, tmp_rtcp;
|
||||||
guint count;
|
guint count;
|
||||||
GList *rejected_addresses = NULL;
|
GList *rejected_addresses = NULL;
|
||||||
|
@ -1339,6 +1339,7 @@ alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
|
||||||
GSocketAddress *rtp_sockaddr = NULL;
|
GSocketAddress *rtp_sockaddr = NULL;
|
||||||
GSocketAddress *rtcp_sockaddr = NULL;
|
GSocketAddress *rtcp_sockaddr = NULL;
|
||||||
GstRTSPAddressPool *pool;
|
GstRTSPAddressPool *pool;
|
||||||
|
gboolean transport_settings_defined = FALSE;
|
||||||
|
|
||||||
pool = priv->pool;
|
pool = priv->pool;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -1346,6 +1347,30 @@ alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
|
||||||
/* Start with random port */
|
/* Start with random port */
|
||||||
tmp_rtp = 0;
|
tmp_rtp = 0;
|
||||||
|
|
||||||
|
if (use_transport_settings) {
|
||||||
|
if (!multicast)
|
||||||
|
goto no_mcast;
|
||||||
|
|
||||||
|
if (ct == NULL)
|
||||||
|
goto no_transport;
|
||||||
|
|
||||||
|
/* multicast and transport specific case */
|
||||||
|
if (ct->destination != NULL) {
|
||||||
|
tmp_rtp = ct->port.min;
|
||||||
|
tmp_rtcp = ct->port.max;
|
||||||
|
inetaddr = g_inet_address_new_from_string (ct->destination);
|
||||||
|
if (inetaddr == NULL)
|
||||||
|
goto destination_error;
|
||||||
|
if (!g_inet_address_get_is_multicast (inetaddr))
|
||||||
|
goto destination_no_mcast;
|
||||||
|
g_object_unref (inetaddr);
|
||||||
|
inetaddr = g_inet_address_new_any (family);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (stream, "use transport settings");
|
||||||
|
transport_settings_defined = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rtcp_socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM,
|
rtcp_socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM,
|
||||||
G_SOCKET_PROTOCOL_UDP, NULL);
|
G_SOCKET_PROTOCOL_UDP, NULL);
|
||||||
if (!rtcp_socket)
|
if (!rtcp_socket)
|
||||||
|
@ -1364,55 +1389,60 @@ again:
|
||||||
g_socket_set_multicast_loopback (rtp_socket, FALSE);
|
g_socket_set_multicast_loopback (rtp_socket, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pool && gst_rtsp_address_pool_has_unicast_addresses (pool)) || multicast) {
|
if (!transport_settings_defined) {
|
||||||
GstRTSPAddressFlags flags;
|
if ((pool && gst_rtsp_address_pool_has_unicast_addresses (pool))
|
||||||
|
|| multicast) {
|
||||||
|
GstRTSPAddressFlags flags;
|
||||||
|
|
||||||
if (addr)
|
if (addr)
|
||||||
rejected_addresses = g_list_prepend (rejected_addresses, addr);
|
rejected_addresses = g_list_prepend (rejected_addresses, addr);
|
||||||
|
|
||||||
if (!pool)
|
if (!pool)
|
||||||
goto no_pool;
|
goto no_pool;
|
||||||
|
|
||||||
flags = GST_RTSP_ADDRESS_FLAG_EVEN_PORT;
|
flags = GST_RTSP_ADDRESS_FLAG_EVEN_PORT;
|
||||||
if (multicast)
|
if (multicast)
|
||||||
flags |= GST_RTSP_ADDRESS_FLAG_MULTICAST;
|
flags |= GST_RTSP_ADDRESS_FLAG_MULTICAST;
|
||||||
else
|
else
|
||||||
flags |= GST_RTSP_ADDRESS_FLAG_UNICAST;
|
flags |= GST_RTSP_ADDRESS_FLAG_UNICAST;
|
||||||
|
|
||||||
if (family == G_SOCKET_FAMILY_IPV6)
|
if (family == G_SOCKET_FAMILY_IPV6)
|
||||||
flags |= GST_RTSP_ADDRESS_FLAG_IPV6;
|
flags |= GST_RTSP_ADDRESS_FLAG_IPV6;
|
||||||
else
|
else
|
||||||
flags |= GST_RTSP_ADDRESS_FLAG_IPV4;
|
flags |= GST_RTSP_ADDRESS_FLAG_IPV4;
|
||||||
|
|
||||||
addr = gst_rtsp_address_pool_acquire_address (pool, flags, 2);
|
addr = gst_rtsp_address_pool_acquire_address (pool, flags, 2);
|
||||||
|
|
||||||
if (addr == NULL)
|
if (addr == NULL)
|
||||||
goto no_address;
|
goto no_address;
|
||||||
|
|
||||||
tmp_rtp = addr->port;
|
tmp_rtp = addr->port;
|
||||||
|
|
||||||
g_clear_object (&inetaddr);
|
g_clear_object (&inetaddr);
|
||||||
/* FIXME: Does it really work with the IP_MULTICAST_ALL socket option and
|
/* FIXME: Does it really work with the IP_MULTICAST_ALL socket option and
|
||||||
* socket control message set in udpsrc? */
|
* socket control message set in udpsrc? */
|
||||||
if (multicast)
|
if (multicast)
|
||||||
inetaddr = g_inet_address_new_any (family);
|
inetaddr = g_inet_address_new_any (family);
|
||||||
else
|
else
|
||||||
inetaddr = g_inet_address_new_from_string (addr->address);
|
inetaddr = g_inet_address_new_from_string (addr->address);
|
||||||
} else {
|
} else {
|
||||||
if (tmp_rtp != 0) {
|
if (tmp_rtp != 0) {
|
||||||
tmp_rtp += 2;
|
tmp_rtp += 2;
|
||||||
if (++count > 20)
|
if (++count > 20)
|
||||||
goto no_ports;
|
goto no_ports;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inetaddr == NULL)
|
||||||
|
inetaddr = g_inet_address_new_any (family);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inetaddr == NULL)
|
|
||||||
inetaddr = g_inet_address_new_any (family);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rtp_sockaddr = g_inet_socket_address_new (inetaddr, tmp_rtp);
|
rtp_sockaddr = g_inet_socket_address_new (inetaddr, tmp_rtp);
|
||||||
if (!g_socket_bind (rtp_socket, rtp_sockaddr, FALSE, NULL)) {
|
if (!g_socket_bind (rtp_socket, rtp_sockaddr, FALSE, NULL)) {
|
||||||
GST_DEBUG_OBJECT (stream, "rtp bind() failed, will try again");
|
GST_DEBUG_OBJECT (stream, "rtp bind() failed, will try again");
|
||||||
g_object_unref (rtp_sockaddr);
|
g_object_unref (rtp_sockaddr);
|
||||||
|
if (transport_settings_defined)
|
||||||
|
goto transport_settings_error;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
g_object_unref (rtp_sockaddr);
|
g_object_unref (rtp_sockaddr);
|
||||||
|
@ -1423,17 +1453,22 @@ again:
|
||||||
goto socket_error;
|
goto socket_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_rtp =
|
if (!transport_settings_defined) {
|
||||||
g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (rtp_sockaddr));
|
tmp_rtp =
|
||||||
g_object_unref (rtp_sockaddr);
|
g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (rtp_sockaddr));
|
||||||
|
|
||||||
/* check if port is even */
|
/* check if port is even. RFC 3550 encorages the use of an even/odd port
|
||||||
if ((tmp_rtp & 1) != 0) {
|
* pair, however it's not a strict requirement so this check is not done
|
||||||
/* port not even, close and allocate another */
|
* for the client selected ports. */
|
||||||
tmp_rtp++;
|
if ((tmp_rtp & 1) != 0) {
|
||||||
g_clear_object (&rtp_socket);
|
/* port not even, close and allocate another */
|
||||||
goto again;
|
tmp_rtp++;
|
||||||
|
g_object_unref (rtp_sockaddr);
|
||||||
|
g_clear_object (&rtp_socket);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
g_object_unref (rtp_sockaddr);
|
||||||
|
|
||||||
/* set port */
|
/* set port */
|
||||||
tmp_rtcp = tmp_rtp + 1;
|
tmp_rtcp = tmp_rtp + 1;
|
||||||
|
@ -1443,15 +1478,21 @@ again:
|
||||||
GST_DEBUG_OBJECT (stream, "rctp bind() failed, will try again");
|
GST_DEBUG_OBJECT (stream, "rctp bind() failed, will try again");
|
||||||
g_object_unref (rtcp_sockaddr);
|
g_object_unref (rtcp_sockaddr);
|
||||||
g_clear_object (&rtp_socket);
|
g_clear_object (&rtp_socket);
|
||||||
|
if (transport_settings_defined)
|
||||||
|
goto transport_settings_error;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
g_object_unref (rtcp_sockaddr);
|
g_object_unref (rtcp_sockaddr);
|
||||||
|
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
addr = g_slice_new0 (GstRTSPAddress);
|
addr = g_slice_new0 (GstRTSPAddress);
|
||||||
addr->address = g_inet_address_to_string (inetaddr);
|
|
||||||
addr->port = tmp_rtp;
|
addr->port = tmp_rtp;
|
||||||
addr->n_ports = 2;
|
addr->n_ports = 2;
|
||||||
|
if (transport_settings_defined)
|
||||||
|
addr->address = g_strdup (ct->destination);
|
||||||
|
else
|
||||||
|
addr->address = g_inet_address_to_string (inetaddr);
|
||||||
|
addr->ttl = ct->ttl;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_object (&inetaddr);
|
g_clear_object (&inetaddr);
|
||||||
|
@ -1468,6 +1509,28 @@ again:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
no_mcast:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (stream, "failed to allocate UDP ports: wrong transport");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
no_transport:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (stream, "failed to allocate UDP ports: no transport");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
destination_error:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (stream,
|
||||||
|
"failed to allocate UDP ports: destination error");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
destination_no_mcast:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (stream,
|
||||||
|
"failed to allocate UDP ports: destination not multicast address");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
no_udp_protocol:
|
no_udp_protocol:
|
||||||
{
|
{
|
||||||
GST_WARNING_OBJECT (stream, "failed to allocate UDP ports: protocol error");
|
GST_WARNING_OBJECT (stream, "failed to allocate UDP ports: protocol error");
|
||||||
|
@ -1489,6 +1552,12 @@ no_ports:
|
||||||
GST_WARNING_OBJECT (stream, "failed to allocate UDP ports: no ports");
|
GST_WARNING_OBJECT (stream, "failed to allocate UDP ports: no ports");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
transport_settings_error:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (stream,
|
||||||
|
"failed to allocate UDP ports with requested transport settings");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
socket_error:
|
socket_error:
|
||||||
{
|
{
|
||||||
GST_WARNING_OBJECT (stream, "failed to allocate UDP ports: socket error");
|
GST_WARNING_OBJECT (stream, "failed to allocate UDP ports: socket error");
|
||||||
|
@ -1563,12 +1632,13 @@ gst_rtsp_stream_allocate_udp_sockets (GstRTSPStream * stream,
|
||||||
/* UDP unicast */
|
/* UDP unicast */
|
||||||
GST_DEBUG_OBJECT (stream, "GST_RTSP_LOWER_TRANS_UDP, ipv4");
|
GST_DEBUG_OBJECT (stream, "GST_RTSP_LOWER_TRANS_UDP, ipv4");
|
||||||
ret = alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV4,
|
ret = alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV4,
|
||||||
priv->socket_v4, &priv->server_addr_v4, FALSE, ct);
|
priv->socket_v4, &priv->server_addr_v4, FALSE, ct, FALSE);
|
||||||
} else {
|
} else {
|
||||||
/* multicast */
|
/* multicast */
|
||||||
GST_DEBUG_OBJECT (stream, "GST_RTSP_LOWER_TRANS_MCAST_UDP, ipv4");
|
GST_DEBUG_OBJECT (stream, "GST_RTSP_LOWER_TRANS_MCAST_UDP, ipv4");
|
||||||
ret = alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV4,
|
ret = alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV4,
|
||||||
priv->mcast_socket_v4, &priv->mcast_addr_v4, TRUE, ct);
|
priv->mcast_socket_v4, &priv->mcast_addr_v4, TRUE, ct,
|
||||||
|
use_transport_settings);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* IPv6 */
|
/* IPv6 */
|
||||||
|
@ -1576,13 +1646,14 @@ gst_rtsp_stream_allocate_udp_sockets (GstRTSPStream * stream,
|
||||||
/* unicast */
|
/* unicast */
|
||||||
GST_DEBUG_OBJECT (stream, "GST_RTSP_LOWER_TRANS_UDP, ipv6");
|
GST_DEBUG_OBJECT (stream, "GST_RTSP_LOWER_TRANS_UDP, ipv6");
|
||||||
ret = alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV6,
|
ret = alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV6,
|
||||||
priv->socket_v6, &priv->server_addr_v6, FALSE, ct);
|
priv->socket_v6, &priv->server_addr_v6, FALSE, ct, FALSE);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* multicast */
|
/* multicast */
|
||||||
GST_DEBUG_OBJECT (stream, "GST_RTSP_LOWER_TRANS_MCAST_UDP, ipv6");
|
GST_DEBUG_OBJECT (stream, "GST_RTSP_LOWER_TRANS_MCAST_UDP, ipv6");
|
||||||
ret = alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV6,
|
ret = alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV6,
|
||||||
priv->mcast_socket_v6, &priv->mcast_addr_v6, TRUE, ct);
|
priv->mcast_socket_v6, &priv->mcast_addr_v6, TRUE, ct,
|
||||||
|
use_transport_settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_mutex_unlock (&priv->lock);
|
g_mutex_unlock (&priv->lock);
|
||||||
|
|
|
@ -726,7 +726,8 @@ GST_START_TEST (test_client_multicast_ignore_transport_specific)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
GST_START_TEST (test_client_multicast_transport_specific)
|
static void
|
||||||
|
multicast_transport_specific (void)
|
||||||
{
|
{
|
||||||
GstRTSPClient *client;
|
GstRTSPClient *client;
|
||||||
GstRTSPMessage request = { 0, };
|
GstRTSPMessage request = { 0, };
|
||||||
|
@ -760,7 +761,6 @@ GST_START_TEST (test_client_multicast_transport_specific)
|
||||||
fail_unless (gst_rtsp_client_handle_message (client,
|
fail_unless (gst_rtsp_client_handle_message (client,
|
||||||
&request) == GST_RTSP_OK);
|
&request) == GST_RTSP_OK);
|
||||||
gst_rtsp_message_unset (&request);
|
gst_rtsp_message_unset (&request);
|
||||||
expected_transport = NULL;
|
|
||||||
|
|
||||||
gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
|
gst_rtsp_client_set_send_func (client, test_setup_response_200_multicast,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
@ -769,14 +769,44 @@ GST_START_TEST (test_client_multicast_transport_specific)
|
||||||
fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
|
fail_unless (gst_rtsp_session_pool_get_n_sessions (session_pool) == 1);
|
||||||
g_object_unref (session_pool);
|
g_object_unref (session_pool);
|
||||||
|
|
||||||
send_teardown (client);
|
/* send PLAY request */
|
||||||
|
fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
|
||||||
|
"rtsp://localhost/test") == GST_RTSP_OK);
|
||||||
|
str = g_strdup_printf ("%d", cseq);
|
||||||
|
gst_rtsp_message_take_header (&request, GST_RTSP_HDR_CSEQ, str);
|
||||||
|
gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SESSION, session_id);
|
||||||
|
gst_rtsp_client_set_send_func (client, test_response_200, NULL, NULL);
|
||||||
|
fail_unless (gst_rtsp_client_handle_message (client,
|
||||||
|
&request) == GST_RTSP_OK);
|
||||||
|
gst_rtsp_message_unset (&request);
|
||||||
|
|
||||||
|
send_teardown (client);
|
||||||
teardown_client (client);
|
teardown_client (client);
|
||||||
g_object_unref (ctx.auth);
|
g_object_unref (ctx.auth);
|
||||||
gst_rtsp_token_unref (ctx.token);
|
gst_rtsp_token_unref (ctx.token);
|
||||||
gst_rtsp_context_pop_current (&ctx);
|
gst_rtsp_context_pop_current (&ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CASE: multicast address requested by the client exists in the address pool */
|
||||||
|
GST_START_TEST (test_client_multicast_transport_specific)
|
||||||
|
{
|
||||||
|
expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
|
||||||
|
"ttl=1;port=5000-5001;mode=\"PLAY\"";
|
||||||
|
multicast_transport_specific ();
|
||||||
|
expected_transport = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* CASE: multicast address requested by the client does not exist in the address pool */
|
||||||
|
GST_START_TEST (test_client_multicast_transport_specific_no_address_in_pool)
|
||||||
|
{
|
||||||
|
expected_transport = "RTP/AVP;multicast;destination=234.252.0.3;"
|
||||||
|
"ttl=1;port=6000-6001;mode=\"PLAY\"";
|
||||||
|
multicast_transport_specific ();
|
||||||
|
expected_transport = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1061,7 +1091,8 @@ mcast_transport_specific_two_clients (gboolean shared)
|
||||||
g_object_unref (thread_pool);
|
g_object_unref (thread_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test if two multicast clients can choose different transport settings */
|
/* test if two multicast clients can choose different transport settings
|
||||||
|
* CASE: media is shared */
|
||||||
GST_START_TEST
|
GST_START_TEST
|
||||||
(test_client_multicast_transport_specific_two_clients_shared_media) {
|
(test_client_multicast_transport_specific_two_clients_shared_media) {
|
||||||
mcast_transport_specific_two_clients (TRUE);
|
mcast_transport_specific_two_clients (TRUE);
|
||||||
|
@ -1069,6 +1100,15 @@ GST_START_TEST
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* test if two multicast clients can choose different transport settings
|
||||||
|
* CASE: media is not shared */
|
||||||
|
GST_START_TEST (test_client_multicast_transport_specific_two_clients)
|
||||||
|
{
|
||||||
|
mcast_transport_specific_two_clients (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
rtspclient_suite (void)
|
rtspclient_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -1091,6 +1131,9 @@ rtspclient_suite (void)
|
||||||
tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags);
|
tcase_add_test (tc, test_client_sdp_with_no_bitrate_tags);
|
||||||
tcase_add_test (tc,
|
tcase_add_test (tc,
|
||||||
test_client_multicast_transport_specific_two_clients_shared_media);
|
test_client_multicast_transport_specific_two_clients_shared_media);
|
||||||
|
tcase_add_test (tc, test_client_multicast_transport_specific_two_clients);
|
||||||
|
tcase_add_test (tc,
|
||||||
|
test_client_multicast_transport_specific_no_address_in_pool);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue