Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
libnice
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
libnice
Commits
a13ac437
Commit
a13ac437
authored
May 13, 2021
by
Ole André Vadla Ravnås
Committed by
Olivier Crête
Nov 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
agent: Add support for bytestream TCP
parent
7bd11cf0
Changes
15
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
610 additions
and
173 deletions
+610
-173
agent/agent-priv.h
agent/agent-priv.h
+1
-1
agent/agent.c
agent/agent.c
+380
-154
agent/agent.h
agent/agent.h
+2
-0
agent/component.c
agent/component.c
+19
-3
agent/component.h
agent/component.h
+13
-0
tests/meson.build
tests/meson.build
+2
-1
tests/test-bytestream-tcp.c
tests/test-bytestream-tcp.c
+130
-0
tests/test-io-stream-cancelling.c
tests/test-io-stream-cancelling.c
+1
-1
tests/test-io-stream-closing-read.c
tests/test-io-stream-closing-read.c
+2
-1
tests/test-io-stream-closing-write.c
tests/test-io-stream-closing-write.c
+2
-1
tests/test-io-stream-common.c
tests/test-io-stream-common.c
+45
-7
tests/test-io-stream-common.h
tests/test-io-stream-common.h
+8
-1
tests/test-io-stream-pollable.c
tests/test-io-stream-pollable.c
+1
-1
tests/test-io-stream-thread.c
tests/test-io-stream-thread.c
+1
-1
tests/test-send-recv.c
tests/test-send-recv.c
+3
-1
No files found.
agent/agent-priv.h
View file @
a13ac437
...
...
@@ -178,10 +178,10 @@ struct _NiceAgent
#endif
gchar
*
software_attribute
;
/* SOFTWARE attribute */
gboolean
reliable
;
/* property: reliable */
gboolean
bytestream_tcp
;
/* property: bytestream-tcp */
gboolean
keepalive_conncheck
;
/* property: keepalive_conncheck */
GQueue
pending_signals
;
guint16
rfc4571_expecting_length
;
gboolean
use_ice_udp
;
gboolean
use_ice_tcp
;
gboolean
use_ice_trickle
;
...
...
agent/agent.c
View file @
a13ac437
This diff is collapsed.
Click to expand it.
agent/agent.h
View file @
a13ac437
...
...
@@ -409,6 +409,7 @@ typedef enum
* @NICE_AGENT_OPTION_SUPPORT_RENOMINATION: Enable renomination triggered by NOMINATION STUN attribute
* proposed here: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00
* @NICE_AGENT_OPTION_CONSENT_FRESHNESS: Enable RFC 7675 consent freshness support. (Since: 0.1.19)
* @NICE_AGENT_OPTION_BYTESTREAM_TCP: Use bytestream mode for reliable TCP connections. (Since: 0.1.20)
*
* These are options that can be passed to nice_agent_new_full(). They set
* various properties on the agent. Not including them sets the property to
...
...
@@ -424,6 +425,7 @@ typedef enum {
NICE_AGENT_OPTION_ICE_TRICKLE
=
1
<<
3
,
NICE_AGENT_OPTION_SUPPORT_RENOMINATION
=
1
<<
4
,
NICE_AGENT_OPTION_CONSENT_FRESHNESS
=
1
<<
5
,
NICE_AGENT_OPTION_BYTESTREAM_TCP
=
1
<<
6
,
}
NiceAgentOption
;
/**
...
...
agent/component.c
View file @
a13ac437
...
...
@@ -388,6 +388,7 @@ nice_component_close (NiceAgent *agent, NiceStream *stream, NiceComponent *cmp)
}
g_free
(
cmp
->
recv_buffer
);
g_free
(
cmp
->
rfc4571_buffer
);
}
/*
...
...
@@ -1129,6 +1130,9 @@ nice_component_init (NiceComponent *component)
component
->
recv_buffer
=
g_malloc
(
MAX_BUFFER_SIZE
);
component
->
recv_buffer_size
=
MAX_BUFFER_SIZE
;
component
->
rfc4571_buffer_size
=
sizeof
(
guint16
)
+
G_MAXUINT16
;
component
->
rfc4571_buffer
=
g_malloc
(
component
->
rfc4571_buffer_size
);
}
static
void
...
...
@@ -1304,6 +1308,9 @@ static gboolean
component_source_prepare
(
GSource
*
source
,
gint
*
timeout_
)
{
ComponentSource
*
component_source
=
(
ComponentSource
*
)
source
;
/* We can’t be sure if the ComponentSource itself needs to be dispatched until
* poll() is called on all the child sources. */
gboolean
skip_poll
=
FALSE
;
NiceAgent
*
agent
;
NiceComponent
*
component
;
GSList
*
parentl
,
*
childl
;
...
...
@@ -1320,6 +1327,11 @@ component_source_prepare (GSource *source, gint *timeout_)
&
component
))
goto
done
;
if
(
component
->
rfc4571_wakeup_needed
)
{
component
->
rfc4571_wakeup_needed
=
FALSE
;
skip_poll
=
TRUE
;
goto
done
;
}
if
(
component
->
socket_sources_age
==
component_source
->
component_socket_sources_age
)
...
...
@@ -1393,9 +1405,7 @@ component_source_prepare (GSource *source, gint *timeout_)
agent_unlock_and_emit
(
agent
);
g_object_unref
(
agent
);
/* We can’t be sure if the ComponentSource itself needs to be dispatched until
* poll() is called on all the child sources. */
return
FALSE
;
return
skip_poll
;
}
static
gboolean
...
...
@@ -1659,3 +1669,9 @@ nice_component_get_sockets (NiceComponent *component)
return
array
;
}
guint
nice_component_compute_rfc4571_headroom
(
NiceComponent
*
component
)
{
return
component
->
rfc4571_buffer_offset
-
component
->
rfc4571_frame_offset
;
}
agent/component.h
View file @
a13ac437
...
...
@@ -241,6 +241,16 @@ struct _NiceComponent {
*/
guint8
*
recv_buffer
;
guint
recv_buffer_size
;
/* ICE-TCP frame state */
guint8
*
rfc4571_buffer
;
guint
rfc4571_buffer_offset
;
guint
rfc4571_buffer_size
;
guint
rfc4571_frame_offset
;
guint
rfc4571_frame_size
;
guint
rfc4571_consumed_size
;
NiceAddress
rfc4571_remote_addr
;
gboolean
rfc4571_wakeup_needed
;
};
typedef
struct
{
...
...
@@ -331,6 +341,9 @@ nice_component_verify_remote_candidate (NiceComponent *component,
GPtrArray
*
nice_component_get_sockets
(
NiceComponent
*
component
);
guint
nice_component_compute_rfc4571_headroom
(
NiceComponent
*
component
);
G_END_DECLS
#endif
/* _NICE_COMPONENT_H */
...
...
tests/meson.build
View file @
a13ac437
...
...
@@ -23,6 +23,7 @@ nice_tests = [
'test-trickle',
'test-tcp',
'test-icetcp',
'test-bytestream-tcp',
'test-credentials',
'test-turn',
'test-drop-invalid',
...
...
@@ -40,7 +41,7 @@ if cc.has_header('arpa/inet.h')
endif
foreach tname : nice_tests
if tname.startswith('test-io-stream') or tname.startswith('test-send-recv')
if tname.startswith('test-io-stream') or tname.startswith('test-send-recv')
or tname == 'test-bytestream-tcp'
extra_src = ['test-io-stream-common.c']
else
extra_src = []
...
...
tests/test-bytestream-tcp.c
0 → 100644
View file @
a13ac437
/*
* This file is part of the Nice GLib ICE library.
*
* (C) 2013 Collabora Ltd.
* Contact: Philip Withnall
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Nice GLib ICE library.
*
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
* Corporation. All Rights Reserved.
*
* Contributors:
* Philip Withnall, Collabora Ltd.
*
* Alternatively, the contents of this file may be used under the terms of the
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
* case the provisions of LGPL are applicable instead of those above. If you
* wish to allow use of your version of this file only under the terms of the
* LGPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replace
* them with the notice and other provisions required by the LGPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the LGPL.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "agent.h"
#include "test-io-stream-common.h"
#include <stdlib.h>
#include <string.h>
#ifndef G_OS_WIN32
#include <unistd.h>
#endif
typedef
struct
{
gsize
recv_count
;
gsize
*
other_recv_count
;
gsize
send_count
;
gsize
*
other_send_count
;
}
ThreadData
;
static
const
gchar
test_sequence
[]
=
{
'1'
,
'2'
,
'3'
,
'4'
};
static
void
read_thread_cb
(
GInputStream
*
input_stream
,
TestIOStreamThreadData
*
data
)
{
ThreadData
*
user_data
=
data
->
user_data
;
guint8
buf
[
2
];
GError
*
error
=
NULL
;
g_input_stream_read_all
(
input_stream
,
buf
,
sizeof
(
buf
),
NULL
,
NULL
,
&
error
);
g_assert_no_error
(
error
);
user_data
->
recv_count
++
;
g_assert_cmpmem
(
buf
,
sizeof
(
buf
),
test_sequence
,
sizeof
(
buf
));
g_input_stream_read_all
(
input_stream
,
buf
,
sizeof
(
buf
),
NULL
,
NULL
,
&
error
);
g_assert_no_error
(
error
);
user_data
->
recv_count
++
;
g_assert_cmpmem
(
buf
,
sizeof
(
buf
),
test_sequence
+
2
,
sizeof
(
buf
));
check_for_termination
(
data
,
&
user_data
->
recv_count
,
user_data
->
other_recv_count
,
&
user_data
->
send_count
,
2
);
}
static
void
write_thread_cb
(
GOutputStream
*
output_stream
,
TestIOStreamThreadData
*
data
)
{
ThreadData
*
user_data
=
data
->
user_data
;
GError
*
error
=
NULL
;
g_output_stream_write_all
(
output_stream
,
test_sequence
,
sizeof
(
test_sequence
),
NULL
,
NULL
,
&
error
);
g_assert_no_error
(
error
);
user_data
->
send_count
+=
2
;
}
int
main
(
void
)
{
ThreadData
*
l_data
,
*
r_data
;
const
TestIOStreamCallbacks
callbacks
=
{
read_thread_cb
,
write_thread_cb
,
NULL
,
NULL
,
};
#ifdef G_OS_WIN32
WSADATA
w
;
WSAStartup
(
0x0202
,
&
w
);
#endif
l_data
=
g_malloc0
(
sizeof
(
ThreadData
));
r_data
=
g_malloc0
(
sizeof
(
ThreadData
));
l_data
->
recv_count
=
0
;
l_data
->
other_recv_count
=
&
r_data
->
recv_count
;
l_data
->
send_count
=
0
;
l_data
->
other_send_count
=
&
r_data
->
send_count
;
r_data
->
recv_count
=
0
;
r_data
->
other_recv_count
=
&
l_data
->
recv_count
;
r_data
->
send_count
=
0
;
r_data
->
other_send_count
=
&
l_data
->
send_count
;
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
l_data
,
NULL
,
r_data
,
NULL
,
TEST_IO_STREAM_OPTION_TCP_ONLY
|
TEST_IO_STREAM_OPTION_BYTESTREAM_TCP
);
g_free
(
r_data
);
g_free
(
l_data
);
#ifdef G_OS_WIN32
WSACleanup
();
#endif
return
0
;
}
tests/test-io-stream-cancelling.c
View file @
a13ac437
...
...
@@ -128,7 +128,7 @@ int main (void)
r_cancellation_thread
=
spawn_thread
(
"libnice R cancel"
,
cancellation_thread_cb
,
&
r_data
);
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
&
l_data
,
NULL
,
&
r_data
,
NULL
);
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
&
l_data
,
NULL
,
&
r_data
,
NULL
,
0
);
g_thread_join
(
l_cancellation_thread
);
g_thread_join
(
r_cancellation_thread
);
...
...
tests/test-io-stream-closing-read.c
View file @
a13ac437
...
...
@@ -128,7 +128,8 @@ int main (void)
WSAStartup
(
0x0202
,
&
w
);
#endif
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
(
gpointer
)
TRUE
,
NULL
,
NULL
,
NULL
);
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
(
gpointer
)
TRUE
,
NULL
,
NULL
,
NULL
,
0
);
#ifdef G_OS_WIN32
WSACleanup
();
...
...
tests/test-io-stream-closing-write.c
View file @
a13ac437
...
...
@@ -128,7 +128,8 @@ int main (void)
WSAStartup
(
0x0202
,
&
w
);
#endif
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
(
gpointer
)
TRUE
,
NULL
,
NULL
,
NULL
);
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
(
gpointer
)
TRUE
,
NULL
,
NULL
,
NULL
,
0
);
#ifdef G_OS_WIN32
WSACleanup
();
...
...
tests/test-io-stream-common.c
View file @
a13ac437
...
...
@@ -243,7 +243,8 @@ new_selected_pair_cb (NiceAgent *agent, guint stream_id, guint component_id,
static
NiceAgent
*
create_agent
(
gboolean
controlling_mode
,
TestIOStreamThreadData
*
data
,
GMainContext
**
main_context
,
GMainLoop
**
main_loop
)
GMainContext
**
main_context
,
GMainLoop
**
main_loop
,
TestIOStreamOption
flags
)
{
NiceAgent
*
agent
;
NiceAddress
base_addr
;
...
...
@@ -253,17 +254,29 @@ create_agent (gboolean controlling_mode, TestIOStreamThreadData *data,
*
main_context
=
g_main_context_new
();
*
main_loop
=
g_main_loop_new
(
*
main_context
,
FALSE
);
/* Use Google compatibility to ignore credentials. */
if
(
data
->
reliable
)
agent
=
nice_agent_new_reliable
(
*
main_context
,
NICE_COMPATIBILITY_
GOOGLE
);
agent
=
nice_agent_new_reliable
(
*
main_context
,
NICE_COMPATIBILITY_
RFC5245
);
else
agent
=
nice_agent_new
(
*
main_context
,
NICE_COMPATIBILITY_
GOOGLE
);
agent
=
nice_agent_new
(
*
main_context
,
NICE_COMPATIBILITY_
RFC5245
);
g_object_set
(
G_OBJECT
(
agent
),
"controlling-mode"
,
controlling_mode
,
"upnp"
,
FALSE
,
NULL
);
if
(
flags
&
TEST_IO_STREAM_OPTION_TCP_ONLY
)
{
g_object_set
(
G_OBJECT
(
agent
),
"ice-udp"
,
FALSE
,
"ice-tcp"
,
TRUE
,
NULL
);
}
if
(
flags
&
TEST_IO_STREAM_OPTION_BYTESTREAM_TCP
)
{
g_object_set
(
G_OBJECT
(
agent
),
"bytestream-tcp"
,
TRUE
,
NULL
);
}
/* Specify which local interface to use. */
g_assert_true
(
nice_address_set_from_string
(
&
base_addr
,
"127.0.0.1"
));
nice_agent_add_local_address
(
agent
,
&
base_addr
);
...
...
@@ -310,6 +323,28 @@ add_stream (NiceAgent *agent)
GUINT_TO_POINTER
(
stream_id
));
}
static
void
swap_credentials
(
NiceAgent
*
agent
)
{
guint
stream_id
;
gchar
*
ufrag
,
*
password
;
NiceAgent
*
other_agent
;
guint
other_stream_id
;
stream_id
=
GPOINTER_TO_UINT
(
g_object_get_data
(
G_OBJECT
(
agent
),
"stream-id"
));
nice_agent_get_local_credentials
(
agent
,
stream_id
,
&
ufrag
,
&
password
);
other_agent
=
g_object_get_data
(
G_OBJECT
(
agent
),
"other-agent"
);
other_stream_id
=
GPOINTER_TO_UINT
(
g_object_get_data
(
G_OBJECT
(
other_agent
),
"stream-id"
));
nice_agent_set_remote_credentials
(
other_agent
,
other_stream_id
,
ufrag
,
password
);
g_free
(
ufrag
);
g_free
(
password
);
}
static
void
run_agent
(
TestIOStreamThreadData
*
data
,
NiceAgent
*
agent
)
{
...
...
@@ -346,7 +381,8 @@ void
run_io_stream_test
(
guint
deadlock_timeout
,
gboolean
reliable
,
const
TestIOStreamCallbacks
*
callbacks
,
gpointer
l_user_data
,
GDestroyNotify
l_user_data_free
,
gpointer
r_user_data
,
GDestroyNotify
r_user_data_free
)
gpointer
r_user_data
,
GDestroyNotify
r_user_data_free
,
TestIOStreamOption
flags
)
{
GMainLoop
*
error_loop
;
GThread
*
l_main_thread
,
*
r_main_thread
;
...
...
@@ -396,9 +432,9 @@ run_io_stream_test (guint deadlock_timeout, gboolean reliable,
/* Create the L and R agents. */
l_data
.
agent
=
create_agent
(
TRUE
,
&
l_data
,
&
l_data
.
main_context
,
&
l_data
.
main_loop
);
&
l_data
.
main_context
,
&
l_data
.
main_loop
,
flags
);
r_data
.
agent
=
create_agent
(
FALSE
,
&
r_data
,
&
r_data
.
main_context
,
&
r_data
.
main_loop
);
&
r_data
.
main_context
,
&
r_data
.
main_loop
,
flags
);
g_object_set_data
(
G_OBJECT
(
l_data
.
agent
),
"other-agent"
,
r_data
.
agent
);
g_object_set_data
(
G_OBJECT
(
r_data
.
agent
),
"other-agent"
,
l_data
.
agent
);
...
...
@@ -411,6 +447,8 @@ run_io_stream_test (guint deadlock_timeout, gboolean reliable,
add_stream
(
l_data
.
agent
);
add_stream
(
r_data
.
agent
);
swap_credentials
(
l_data
.
agent
);
swap_credentials
(
r_data
.
agent
);
run_agent
(
&
l_data
,
l_data
.
agent
);
run_agent
(
&
r_data
,
r_data
.
agent
);
...
...
tests/test-io-stream-common.h
View file @
a13ac437
...
...
@@ -105,12 +105,19 @@ struct _TestIOStreamThreadData {
guint
*
start_count
;
};
typedef
enum
{
TEST_IO_STREAM_OPTION_TCP_ONLY
=
1
<<
0
,
TEST_IO_STREAM_OPTION_BYTESTREAM_TCP
=
1
<<
1
,
}
TestIOStreamOption
;
GThread
*
spawn_thread
(
const
gchar
*
thread_name
,
GThreadFunc
thread_func
,
gpointer
user_data
);
void
run_io_stream_test
(
guint
deadlock_timeout
,
gboolean
reliable
,
const
TestIOStreamCallbacks
*
callbacks
,
gpointer
l_user_data
,
GDestroyNotify
l_user_data_free
,
gpointer
r_user_data
,
GDestroyNotify
r_user_data_free
);
gpointer
r_user_data
,
GDestroyNotify
r_user_data_free
,
TestIOStreamOption
flags
);
void
check_for_termination
(
TestIOStreamThreadData
*
data
,
gsize
*
recv_count
,
gsize
*
other_recv_count
,
volatile
gsize
*
send_count
,
gsize
expected_recv_count
);
...
...
tests/test-io-stream-pollable.c
View file @
a13ac437
...
...
@@ -178,7 +178,7 @@ int main (void)
r_data
->
other_send_count
=
&
l_data
->
send_count
;
r_data
->
recv_offset
=
0
;
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
l_data
,
NULL
,
r_data
,
NULL
);
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
l_data
,
NULL
,
r_data
,
NULL
,
0
);
g_free
(
r_data
);
g_free
(
l_data
);
...
...
tests/test-io-stream-thread.c
View file @
a13ac437
...
...
@@ -143,7 +143,7 @@ int main (void)
r_data
->
send_count
=
0
;
r_data
->
other_send_count
=
&
l_data
->
send_count
;
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
l_data
,
NULL
,
r_data
,
NULL
);
run_io_stream_test
(
30
,
TRUE
,
&
callbacks
,
l_data
,
NULL
,
r_data
,
NULL
,
0
);
/* Verify that correct number of local candidates were reported. */
g_assert_cmpuint
(
l_data
->
cand_count
,
==
,
1
);
...
...
tests/test-send-recv.c
View file @
a13ac437
...
...
@@ -1146,7 +1146,9 @@ test (gboolean reliable, StreamApi stream_api, gsize n_bytes, guint n_messages,
&
l_data
.
received_bytes
,
&
l_data
.
received_messages
);
run_io_stream_test
(
deadlock_timeout
,
reliable
,
&
callbacks
[
stream_api
],
&
l_data
,
NULL
,
&
r_data
,
NULL
);
&
l_data
,
NULL
,
&
r_data
,
NULL
,
/* Ensure TCP has the same behavior as Pseudo-TCP in reliable mode: */
reliable
?
TEST_IO_STREAM_OPTION_BYTESTREAM_TCP
:
0
);
test_data_clear
(
&
r_data
);
test_data_clear
(
&
l_data
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment