Giter Site home page Giter Site logo

paullouisageneau / libdatachannel Goto Github PK

View Code? Open in Web Editor NEW
1.5K 41.0 322.0 53.64 MB

C/C++ WebRTC network library featuring Data Channels, Media Transport, and WebSockets

Home Page: https://libdatachannel.org/

License: Mozilla Public License 2.0

Makefile 0.72% C++ 87.46% C 2.30% CMake 5.53% Python 0.68% CSS 1.10% HTML 2.20%
webrtc webrtc-datachannel datachannel rtcdatachannel p2p peer-to-peer websocket peerconnection cpp sctp

libdatachannel's Introduction

Hello, I'm Paul-Louis 👋

  • 👨 I'm a Software Engineer and Computer Science PhD from France.
  • 🔭 I like working on network protocols and applications, particularly distributed ones.
  • 💻 I have a wide range of interests in new technologies, from video game graphics to robotics and 3D printing.
  • ⭐ I'm a WebRTC expert and the author of libdatachannel, a C/C++ WebRTC standalone library.
  • ♥️ I'm looking for sponsors to continue maintaining open-source projects.
  • 📫 Please find my contact information and résumé on paul-louis.ageneau.org
  • 🎩 Check out my blog where I tinker with stuff on chapelierfou.org
  • 👍 Follow me on GitHub or Mastodon
  • 😄 Pronouns: he/him

Some of my open source projects:

I'm a contributor to node-datachannel, Node.js bindings for libdatachannel.

I've also been contributing to WebTorrent, and libtorrent, in which I added WebTorrent support. This first native WebTorrent implementation opens exciting possibilities for Peer-to-Peer file exchanges between Web browsers and native clients!

Otherwise, I like working on robots and tinkering with Minitels! Check out my blog 🤖

libdatachannel's People

Contributors

asgeir avatar cheungxiongwei avatar davideichmann avatar dependabot[bot] avatar dw9 avatar ecotarobles avatar gasperov avatar hanseuljun avatar hhgyu avatar ilsalvopss avatar industriousonesoft avatar jonasvautherin avatar kanglin avatar kuzux avatar leonavel avatar melpon avatar murat-dogan avatar nicochatzi avatar nyran avatar ognkrmms avatar paullouisageneau avatar se2dev avatar sean-der avatar sebihoefle avatar snowinszu avatar stevedanomodolor avatar therockstarsteam avatar tytan652 avatar web2098 avatar zitaliao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libdatachannel's Issues

Multiple stun server & stun server credentials

I was using webrtc datachannel before seeing this library for one of my project.
Now I want to integrate this library instead of giant webrtc datachannel.

I have some questions for now;

  • In webrtc I can use multiple stun server. As I see in this project we have to use only one. What is the difference?
  • I could not find any place for stun credentials if needed. (username, password for stun server)

Example with remote peers

Hi,

I wonder is there an example with remote peers? Peers that are running on different machines.

Thank you,
Rabah

Building on mac os issue

Hi,

I thought I'd start a separate issue for building on mac os. It obviously seems to be a problem with building the juice dependency, but I'm unsure of how to resolve it. I've just noticed that this actually seems to be written by you as well! cmake seems to run without errors, but when I run the generated makefile, I get:

Scanning dependencies of target juice-static
[  3%] Building C object deps/libjuice/CMakeFiles/juice-static.dir/src/addr.c.o
[  3%] Building C object deps/libjuice/CMakeFiles/juice-static.dir/src/agent.c.o
[  6%] Building C object deps/libjuice/CMakeFiles/juice-static.dir/src/crc32.c.o
[  9%] Building C object deps/libjuice/CMakeFiles/juice-static.dir/src/hmac.c.o
/Users/will.munn/code/experiments/libdatachannel/deps/libjuice/src/hmac.c:22:10: fatal error: 'nettle/hmac.h' file not found
#include <nettle/hmac.h>
         ^~~~~~~~~~~~~~~
1 error generated.
make[2]: *** [deps/libjuice/CMakeFiles/juice-static.dir/src/hmac.c.o] Error 1
make[1]: *** [deps/libjuice/CMakeFiles/juice-static.dir/all] Error 2
make: *** [all] Error 2

Building with CMake on Windows: does not find NETTLE

Hi,

Trying to build this on Windows.

Am using OpenSSL. therefore: DUSE_GNUTLS=0

With command:

cmake -DUSE_JUICE=1 -DUSE_GNUTLS=0 ..

I get below Warning. Help please.

The package name passed tofind_package_handle_standard_args(NETTLE) does not match the name of the calling package (Nettle). This can lead to problems in calling code that expectsfind_packageresult variables (e.g.,_FOUND) to follow a certain pattern. Call Stack (most recent call first): deps/libjuice/cmake/Modules/FindNettle.cmake:6 (find_package_handle_standard_args) deps/libjuice/CMakeLists.txt:63 (find_package) This warning is for project developers. Use -Wno-dev to suppress it.

Building on windows fails

I am using Visual Studio Developer shell to run the commands listed to build, but the build fails with the following error -

agent.c : 202 - error C2440: 'function': cannot convert from 'thread_return_t (__cdecl *)(void *)' to 'LPTHREAD_START_ROUTINE'

Connection Stats

I want to get some information about connection like in WebRTC Stats.
I need at least these values;

  • roundTripTime (like ping time)
  • bytesSent
  • bytesReceived

We can have bytesSent and bytesReceived values easily but I could not find a good way for calculating roundTripTime.

  • Do you have any idea, how to calculate roundTripTime?
  • Should we add stats function to libdatachannel?

Thread management

It may not be a bug but a feature but I would like to make sure which one it is.
From my observations, I see the following behavior:
when I "rtcSetRemoteDescription" or "rtcAddRemoteCandidate" from thread T1 I sometimes (very rare) get the callbacks that are set by "rtcSetLocalDescriptionCallback" and "rtcSetLocalCandidateCallback" called on the same thread T1.

Due to being unable to reproduce it constantly I am not sure if it happens when calling rtcSetRemoteDescription or rtcAddRemoteCandidate but I would like to make sure it's an expected behavior or not.

Usually, when you register for callbacks and then call functions of the library you do not expect the callbacks to be called during your call to the library and using your thread. They usually arrive from some external thread created by the library.

Is it something that is supposed to happen or not ?

ICE Internals

Hi @paullouisageneau ,

I am using webrtc since 2 years but I don't know internals so much.
I am trying to learn with this project.

Have some basic questions;

  • Is communication with STUN/TURN for gathering candidates encrypted?
  • Basically libnice will select a candidate pair and all communication will be over this pair.
    For example;
Candidate 1: a=candidate:9 1 TCP 1010828031 192.168.1.25 60451 typ host tcptype passive
Candidate 2: a=candidate:9 1 TCP 1010828031 192.168.1.25 43948 typ host tcptype passive

If this pair is selected, then communication will be over this ports (TCP).
Is this right?
Is this communication is encrypted?

  • If above is true then what is sctptransport for?
    I mean all communication is over libnice (TCP) what is the purpose of sctp layer?

Thanks,

Race condition on libjuice agent destruction

Using libjuice and libdatachannel, i'm facing an invalid access to the underlying ice agent when disconnecting and deleting the peerconnection.

I'm destroying the peerconnection to make room for a new one when refreshing the browser (other peer), but doing that, sometimes (due to threads in action?), agent_run triggers the agent_do_destroy before the ~IceTransport destructor. This destructor is then calling agent_destroy on an already freed agent.

If the icetransport destructor is called before the end of agent_run, everything is fine. Am i missing something to properly trigger these in order everytime ?

Use after free

Hi.
I am running a libdatachannel under valgrind and it detects a use-after-free error.
Valgrind output:

==19020== Thread 21:
==19020== Invalid read of size 4
==19020== at 0x8C38AA: sctp_free_assoc (sctp_pcb.c:5663)
==19020== by 0x88939C: sctp_handle_abort (sctp_input.c:910)
==19020== by 0x8861F3: sctp_process_control (sctp_input.c:5256)
==19020== by 0x8839A5: sctp_common_input_processing (sctp_input.c:5913)
==19020== by 0x87F139: usrsctp_conninput (user_socket.c:3353)
==19020== by 0x594445: rtc::SctpTransport::incoming(std::shared_ptrrtc::Message) (sctptransport.cpp:295)
==19020== by 0x56678B: void std::__invoke_impl<void, void (rtc::Transport::&)(std::shared_ptrrtc::Message), rtc::Transport&, std::shared_ptrrtc::Message >(std::__invoke_memfun_deref, void (rtc::Transport::&)(std::shared_ptrrtc::Message), rtc::Transport&, std::shared_ptrrtc::Message&&) (invoke.h:73)
==19020== by 0x566AF4: operator() (std_function.h:706)
==19020== by 0x566AF4: rtc::synchronized_callback<std::shared_ptrrtc::Message >::operator()(std::shared_ptrrtc::Message) const (include.hpp:97)
==19020== by 0x565CEF: rtc::Transport::recv(std::shared_ptrrtc::Message) (transport.hpp:63)
==19020== by 0x5635CE: rtc::DtlsTransport::runRecvLoop() (dtlstransport.cpp:450)
==19020== by 0x55216DE: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==19020== by 0x5DAA6DA: start_thread (pthread_create.c:463)
==19020== Address 0x1159c374 is 484 bytes inside a block of size 584 free'd
==19020== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19020== by 0x8788C8: sodealloc (user_socket.c:241)
==19020== by 0x878848: sofree (user_socket.c:302)
==19020== by 0x87C8F9: usrsctp_close (user_socket.c:2020)
==19020== by 0x591B6E: rtc::SctpTransport::shutdown() (sctptransport.cpp:244)
==19020== by 0x5912DC: rtc::SctpTransport::stop() (sctptransport.cpp:202)
==19020== by 0x57A205: operator() (peerconnection.cpp:451)
==19020== by 0x57A205: __invoke_impl<void, (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:449:17)> (invoke.h:60)
==19020== by 0x57A205: __invoke<(lambda at src/thirdparty/libdatachannel/peerconnection.cpp:449:17)> (invoke.h:95)
==19020== by 0x57A205: _M_invoke<0> (thread:234)
==19020== by 0x57A205: operator() (thread:243)
==19020== by 0x57A205: std::thread::_State_impl<std::thread::_Invoker<std::tuplertc::PeerConnection::closeTransports()::$_5 > >::_M_run() (thread:186)
==19020== by 0x55216DE: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==19020== by 0x5DAA6DA: start_thread (pthread_create.c:463)
==19020== by 0x60E388E: clone (clone.S:95)
==19020== Block was alloc'd at
==19020== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19020== by 0x879463: soalloc (user_socket.c:206)
==19020== by 0x87B34C: socreate (user_socket.c:1251)
==19020== by 0x87B5FC: usrsctp_socket (user_socket.c:1346)
==19020== by 0x58F603: rtc::SctpTransport::SctpTransport(std::shared_ptrrtc::Transport, unsigned short, std::function<void (std::shared_ptrrtc::Message)>, std::function<void (unsigned short, unsigned long)>, std::function<void (rtc::Transport::State)>) (sctptransport.cpp:95)
==19020== by 0x5753E1: construct<rtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (new_allocator.h:136)
==19020== by 0x5753E1: construct<rtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (alloc_traits.h:475)
==19020== by 0x5753E1: _Sp_counted_ptr_inplace<std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr_base.h:526)
==19020== by 0x5753E1: __shared_count<rtc::SctpTransport, std::allocatorrtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr_base.h:637)
==19020== by 0x5753E1: __shared_ptr<std::allocatorrtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr_base.h:1294)
==19020== by 0x5753E1: shared_ptr<std::allocatorrtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr.h:344)
==19020== by 0x5753E1: allocate_shared<rtc::SctpTransport, std::allocatorrtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr.h:690)
==19020== by 0x5753E1: make_shared<rtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr.h:706)
==19020== by 0x5753E1: rtc::PeerConnection::initSctpTransport() (peerconnection.cpp:387)
==19020== by 0x5795CA: operator() (peerconnection.cpp:331)
==19020== by 0x5795CA: std::_Function_handler<void (rtc::Transport::State), rtc::PeerConnection::initDtlsTransport()::$_3>::_M_invoke(std::_Any_data const&, rtc::Transport::State&&) (std_function.h:316)
==19020== by 0x5633C6: operator() (std_function.h:706)
==19020== by 0x5633C6: operator() (include.hpp:97)
==19020== by 0x5633C6: changeState (transport.hpp:66)
==19020== by 0x5633C6: rtc::DtlsTransport::runRecvLoop() (dtlstransport.cpp:441)
==19020== by 0x55216DE: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==19020== by 0x5DAA6DA: start_thread (pthread_create.c:463)
==19020== by 0x60E388E: clone (clone.S:95)
==19020==
==19020== Invalid write of size 4
==19020== at 0x8C38E4: sctp_free_assoc (sctp_pcb.c:5663)
==19020== by 0x88939C: sctp_handle_abort (sctp_input.c:910)
==19020== by 0x8861F3: sctp_process_control (sctp_input.c:5256)
==19020== by 0x8839A5: sctp_common_input_processing (sctp_input.c:5913)
==19020== by 0x87F139: usrsctp_conninput (user_socket.c:3353)
==19020== by 0x594445: rtc::SctpTransport::incoming(std::shared_ptrrtc::Message) (sctptransport.cpp:295)
==19020== by 0x56678B: void std::__invoke_impl<void, void (rtc::Transport::&)(std::shared_ptrrtc::Message), rtc::Transport&, std::shared_ptrrtc::Message >(std::__invoke_memfun_deref, void (rtc::Transport::&)(std::shared_ptrrtc::Message), rtc::Transport&, std::shared_ptrrtc::Message&&) (invoke.h:73)
==19020== by 0x566AF4: operator() (std_function.h:706)
==19020== by 0x566AF4: rtc::synchronized_callback<std::shared_ptrrtc::Message >::operator()(std::shared_ptrrtc::Message) const (include.hpp:97)
==19020== by 0x565CEF: rtc::Transport::recv(std::shared_ptrrtc::Message) (transport.hpp:63)
==19020== by 0x5635CE: rtc::DtlsTransport::runRecvLoop() (dtlstransport.cpp:450)
==19020== by 0x55216DE: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==19020== by 0x5DAA6DA: start_thread (pthread_create.c:463)
==19020== Address 0x1159c374 is 484 bytes inside a block of size 584 free'd
==19020== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19020== by 0x8788C8: sodealloc (user_socket.c:241)
==19020== by 0x878848: sofree (user_socket.c:302)
==19020== by 0x87C8F9: usrsctp_close (user_socket.c:2020)
==19020== by 0x591B6E: rtc::SctpTransport::shutdown() (sctptransport.cpp:244)
==19020== by 0x5912DC: rtc::SctpTransport::stop() (sctptransport.cpp:202)
==19020== by 0x57A205: operator() (peerconnection.cpp:451)
==19020== by 0x57A205: __invoke_impl<void, (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:449:17)> (invoke.h:60)
==19020== by 0x57A205: __invoke<(lambda at src/thirdparty/libdatachannel/peerconnection.cpp:449:17)> (invoke.h:95)
==19020== by 0x57A205: _M_invoke<0> (thread:234)
==19020== by 0x57A205: operator() (thread:243)
==19020== by 0x57A205: std::thread::_State_impl<std::thread::_Invoker<std::tuplertc::PeerConnection::closeTransports()::$_5 > >::_M_run() (thread:186)
==19020== by 0x55216DE: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==19020== by 0x5DAA6DA: start_thread (pthread_create.c:463)
==19020== by 0x60E388E: clone (clone.S:95)
==19020== Block was alloc'd at
==19020== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19020== by 0x879463: soalloc (user_socket.c:206)
==19020== by 0x87B34C: socreate (user_socket.c:1251)
==19020== by 0x87B5FC: usrsctp_socket (user_socket.c:1346)
==19020== by 0x58F603: rtc::SctpTransport::SctpTransport(std::shared_ptrrtc::Transport, unsigned short, std::function<void (std::shared_ptrrtc::Message)>, std::function<void (unsigned short, unsigned long)>, std::function<void (rtc::Transport::State)>) (sctptransport.cpp:95)
==19020== by 0x5753E1: construct<rtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (new_allocator.h:136)
==19020== by 0x5753E1: construct<rtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (alloc_traits.h:475)
==19020== by 0x5753E1: _Sp_counted_ptr_inplace<std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr_base.h:526)
==19020== by 0x5753E1: __shared_count<rtc::SctpTransport, std::allocatorrtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr_base.h:637)
==19020== by 0x5753E1: __shared_ptr<std::allocatorrtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr_base.h:1294)
==19020== by 0x5753E1: shared_ptr<std::allocatorrtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr.h:344)
==19020== by 0x5753E1: allocate_shared<rtc::SctpTransport, std::allocatorrtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr.h:690)
==19020== by 0x5753E1: make_shared<rtc::SctpTransport, std::shared_ptrrtc::DtlsTransport &, unsigned short &, (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at include/thirdparty/rtc/include.hpp:73:9), (lambda at src/thirdparty/libdatachannel/peerconnection.cpp:390:7)> (shared_ptr.h:706)
==19020== by 0x5753E1: rtc::PeerConnection::initSctpTransport() (peerconnection.cpp:387)
==19020== by 0x5795CA: operator() (peerconnection.cpp:331)
==19020== by 0x5795CA: std::_Function_handler<void (rtc::Transport::State), rtc::PeerConnection::initDtlsTransport()::$_3>::_M_invoke(std::_Any_data const&, rtc::Transport::State&&) (std_function.h:316)
==19020== by 0x5633C6: operator() (std_function.h:706)
==19020== by 0x5633C6: operator() (include.hpp:97)
==19020== by 0x5633C6: changeState (transport.hpp:66)
==19020== by 0x5633C6: rtc::DtlsTransport::runRecvLoop() (dtlstransport.cpp:441)
==19020== by 0x55216DE: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==19020== by 0x5DAA6DA: start_thread (pthread_create.c:463)
==19020== by 0x60E388E: clone (clone.S:95)
==19020==

in sctptransport::stop() there is:
shutdown();
onRecv(nullptr);
Shouldn't it be in reverse order ?

usrctp/libjuice/libdatachannel are from current master.

Connection Speed

I am testing connection speed with these circumstances;

  • Both peer on same network
  • Using iPerf3 to test speed
  • Running iPerf3 for 60 sec
  • Average speed ise ~10Mbit

Actually it is lower than what I expected. If I make iPerf test with direct IPs I get ~75MBit.

PLOG logs multiple calls after peerconnection reset

Scenario:
I'm creating a peerconnection via shared_ptr
I reset my shared_ptr upon parent object destruction
All destructors are called correctly along the way
I then create another peerconnection
I get 2x logs from this peerconnection
And it keeps going after each destruction/construction of a peerconnection

Example after 2 destructions:

2020-03-04 16:30:07.754 INFO  [43988] [rtc::DtlsTransport::runRecvLoop@485] DTLS disconnected
2020-03-04 16:30:07.754 INFO  [43988] [rtc::DtlsTransport::runRecvLoop@485] DTLS disconnected
2020-03-04 16:30:07.754 INFO  [43988] [rtc::DtlsTransport::runRecvLoop@485] DTLS disconnected

Writing the P2P example in C

I am trying to write the p2p example in c but I am having problem on what the parametres type an mid means in this functions

rtcSetRemoteDescription(other->pc, sdp, type);
rtcAddRemoteCandidate(other->pc, cand, mid);
Also do you have a list of more c api like to help me convet the following code
std::optional<std::chrono::milliseconds> rtt = pc->rtt();
if (pc->getSelectedCandidatePair(&local, &remote)) {
    cout << "Local: " << local.address << ":" << local.port << " " << local.type << " " << local.transportType << endl;
    cout << "Remote: " << remote.address << ":" << remote.port << " " << remote.type << " " << remote.transportType << endl;
    cout << "Bytes Sent:" << pc->bytesSent() << " / Bytes Received:" << pc->bytesReceived() << " / Round-Trip Time:";
    if (rtt.has_value())
        cout << rtt.value().count();
    else
        cout << "null";
    cout << " ms";
} else
    cout << "Could not get Candidate Pair Info" << endl;

benchmark on Windows

This is result of benchmark on windows

Description 1: v=0
o=- 2649482864 0 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE data
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=mid:data
a=sctp-port:5000
a=max-message-size:262144
a=ice-options:trickle
a=ice-ufrag:Sb7x
a=ice-pwd:J7k0Pslc2jT2aJIDtGqijR
a=setup:actpass
a=tls-id:1
a=fingerprint:sha-256 AB:56:43:64:E8:F5:49:34:35:93:A2:73:BF:5D:34:2D:75:A5:52:5D:BA:6F:51:CF:EE:15:FB:78:D0:C2:9A:A2

Description 2: v=0
o=- 2642587225 0 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE data
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=mid:data
a=sctp-port:5000
a=max-message-size:262144
a=ice-options:trickle
a=ice-ufrag:1x2Z
a=ice-pwd:fkQnpmrsqsbh/s/ZtWIhoo
a=setup:active
a=tls-id:1
a=fingerprint:sha-256 AB:56:43:64:E8:F5:49:34:35:93:A2:73:BF:5D:34:2D:75:A5:52:5D:BA:6F:51:CF:EE:15:FB:78:D0:C2:9A:A2

Gathering state 2: in_progress
Candidate 2: a=candidate:1 1 UDP 2015363327 10.0.0.12 18703 typ host
Candidate 2: a=candidate:2 1 UDP 2015363583 fe80::b415:a528:ee00:3900 50283 typ host
Gathering state 2: complete
Gathering state 1: in_progress
State 1: State 2: connecting
connecting
Candidate 1: a=candidate:1 1 UDP 2015363327 10.0.0.12 15625 typ host
Candidate 1: a=candidate:2 1 UDP 2015363583 fe80::b415:a528:ee00:3900 14642 typ host
Gathering state 1: complete
State 2: connected
State 1: connected
DataChannel open, sending data...
Received: 14286 KB
Received: 21954 KB
Received: 57605 KB
Received: 89062 KB
Received: 128317 KB
Received: 147388 KB
Received: 186053 KB
Received: 240054 KB
Received: 283176 KB
Received: 304475 KB
Test duration: 30000 ms
Connect duration: 231 ms
Goodput: 10.01 MB/s (80.08 Mbit/s)
State 1: closed
State 2: closed

On linux it is typically 500MBit/s.

Could you please check on your side?

thread synchronization with onMessage

please excuse my ignorance if I misunderstand something. My understanding is that mMessageCallback is called on an internal network thread, and the callback is set from the client thread. Yet, there is no sychronization of this shared variable.

Perhaps more importantly, the call to set the onMessage callback really must synchronize to ensure that mMessageCallback is not clobbered while being executed and additionally, that once onMessage returns, the previous callback will not be called. i.e. I think you need a mutex around the whole call and the assignment.

Obviously that would mean clients would have to be careful to not update the callback from within the callback itself, as that would be a dead-lock (should be documented).

Add an option to disable TLS verification

Would you consider adding a flag or an argument that allows the user to disable TLS verification in the WebSocket API? Currently, it is disabled under OpenSSL on Windows and when the certificate directory cannot be found.

It is difficult to use ws:// anywhere else than locally, with Heroku and others forcing wss://. Being able to skip certificate verification would be useful for development purposes :)

// SSL_CTX_set_default_verify_paths() does nothing on Windows

Websocket c API?

I just went through the c api and notices that the WebSocket API is not longer there

OpenSSL handshake and firefox

I am getting a random hang on the DTLS handshake talking to firefox, SSL_is_init_finished says no for ever, making the connection hang indefinitely.

This is on localhost, i am getting a hang maybe 1 out of 10 times. Chrome is fine though. I don't know enough about SSL handshake to say if this is a firefox issue or not.

Is this something others reproduce? Where should i investigate on this?

Connection Stats

I want to get some information about connection like in WebRTC Stats.
I need at least these values;

roundTripTime (like ping time)
bytesSent
bytesReceived
We can have bytesSent and bytesReceived values easily but I could not find a good way for calculating roundTripTime.

Do you have any idea, how to calculate roundTripTime?
Should we add stats function to libdatachannel?

Crash on closed write (usrstcp)

This is not libdatachannel issue but more like usrsctp weird behavior issue but it would be nice if libdatachannel could protect from it.

usrsctp: Send callback is invoked on already closed socket:
sctplab/usrsctp#405

I believe this issue leads to this crashlog I am able to inconsistently reproduce with libdatachannel on Android device:
libc.so - (__fortify_fatal(char const*, ...)+34)
libc.so - (HandleUsingDestroyedMutex(pthread_mutex_t*, char const*)+20)
libc.so - (pthread_mutex_lock+136)
libdatachannel.so - (std::__ndk1::mutex::lock()+4)
libdatachannel.so - (rtc::SctpTransport::handleWrite(std::byte*, unsigned int, unsigned char, unsigned char)+356)
libdatachannel.so - (rtc::SctpTransport::WriteCallback(void*, void*, unsigned int, unsigned char, unsigned char)+24)

It's pretty rare as probably happens if you call close exactly as the packet arrives but can we add some kind of protection against it if my theory is correct ?

DTLS Handshake seems to fail when connecting Android/Linux

Hello.

I am using libdatachannel when two peers are running on different OSes.
Peer1 Linux 64 bit (ubuntu 18.04)
Peer2 Android 10

The problems seems only to happen when android is "answering" and Linux is "offering".
Two peers are in fact in local network but do get a working stun server on the internet when creating connection.
I see that they in fact can successfully talk to each other but for whatever reason DTLS handshake seems to fail.

when android is "offering" and Linux is "answering" everything works fine.
when android is "answering" and Linux is "offering" I never got to connection success. It seems the DTLS handshake doesn't receive anything although there is data received as I can see from the logs.
STUN does seem to succeed too.
On Android I use the same openssl(compiled by me) as on Linux.
Linux <-> Linux communication always works.
Android <-> Android communication does not seem to work at all.

I have prepared log files of the sessions (mostly coming from libjuice) + annotation of what I do but as they are a bit long I don't think posting here is appropriate.
Logs are available at https://gofile.io/d/v3lXb9

Zip contains two directories with two files in each directory.
dir "android_is_answerer_does_not_work" contains android.txt and linux.txt when DTLS seems to get stuck.
dir "android_is_offerer_does_work" contains android.txt and linux.txt when it does work.

I am using libdatachannel from https://github.com/paullouisageneau/libdatachannel/tree/usrsctp-fix-notifications

Did anyone get anything like it ? The behavior seems to change due to offer/answer so I believe it libdatachannel related.

Valgrind error on app exit

Hello,

I launched my app with valgrind: valgrind -v ./[app_name] and I got next error when app exits (when I send ctrl + c interrupt signal):

...
==87275==
==87275== HEAP SUMMARY:
==87275==     in use at exit: 106,107 bytes in 158 blocks
==87275==   total heap usage: 7,748 allocs, 7,590 frees, 1,277,517 bytes allocated
==87275==
==87275== Searching for pointers to 158 not-freed blocks
==87275== Checked 17,104,880 bytes
==87275==
==87275== LEAK SUMMARY:
==87275==    definitely lost: 0 bytes in 0 blocks
==87275==    indirectly lost: 0 bytes in 0 blocks
==87275==      possibly lost: 704 bytes in 2 blocks
==87275==    still reachable: 105,403 bytes in 156 blocks
==87275==         suppressed: 0 bytes in 0 blocks
==87275== Rerun with --leak-check=full to see details of leaked memory
==87275==
==87275== Use --track-origins=yes to see where uninitialised values come from
==87275== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==87275==
==87275== 1 errors in context 1 of 1:
==87275== Conditional jump or move depends on uninitialised value(s)
==87275==    at 0x7B3824: rtc::PeerConnection::changeGatheringState(rtc::PeerConnection::GatheringState) (peerconnection.cpp:558)
==87275==    by 0x7B0FC8: rtc::PeerConnection::initIceTransport(rtc::Description::Role)::{lambda(rtc::IceTransport::GatheringState)#2}::operator()(rtc::IceTransport::GatheringState) const (peerconnection.cpp:239)
==87275==    by 0x7B7074: std::_Function_handler<void (rtc::IceTransport::GatheringState), rtc::PeerConnection::initIceTransport(rtc::Description::Role)::{lambda(rtc::IceTransport::GatheringState)#2}>::_M_invoke(std::_Any_data const&, rtc::IceTransport::GatheringState&&) (std_function.h:297)
==87275==    by 0x7E5AAD: std::function<void (rtc::IceTransport::GatheringState)>::operator()(rtc::IceTransport::GatheringState) const (std_function.h:687)
==87275==    by 0x7E4827: rtc::IceTransport::changeGatheringState(rtc::IceTransport::GatheringState) (icetransport.cpp:183)
==87275==    by 0x7E42A5: rtc::IceTransport::gatherLocalCandidates() (icetransport.cpp:139)
==87275==    by 0x7B00FF: rtc::PeerConnection::setRemoteDescription(rtc::Description) (peerconnection.cpp:97)
==87275==    by 0x74E1F6: ClientConnection::connect(WebRtcNegotiationClientParams&, WebRtcNegotiationServerParams&, rtc::Configuration&) (client-connection.cpp:60)
==87275==    by 0x772F93: NetworkManager::connectClient(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, WebRtcNegotiationClientParams&) (network-manager.cpp:33)
==87275==    by 0x7753CE: SignalingServer::start()::{lambda(served::response&, served::request const&)#1}::operator()(served::response&, served::request const&) const (signaling-server.cpp:40)
==87275==    by 0x775DA3: std::_Function_handler<void (served::response&, served::request const&), SignalingServer::start()::{lambda(served::response&, served::request const&)#1}>::_M_invoke(std::_Any_data const&, served::response&, served::request const&) (std_function.h:297)
==87275==    by 0x7EE45A: std::function<void (served::response&, served::request const&)>::operator()(served::response&, served::request const&) const (std_function.h:687)
==87275==
==87275== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
...

It points to this line in libdatachannel sources:
image

My peerConnection state was connecting and gathering state was complete. I think error happens after peerConnection->close() method executed.

Is this something that I should worry about or I can ignore this error?

Version

Commit 6302d99

SCTP RTT

There is something i don't understand with SCTP RTTs. I must be missing something obvious but i don't get it.

In order to test the new rtt getter from peerconnection, i am creating a thread and sending messages to an unordered and reliable channel (on localhost) in a loop.

  • When creating the datachannel, the RTT reported is 1ms (which is OK)
  • If i send big messages (which will be chunked by SCTP), the RTT stays at 1ms
  • If i send 1 byte messages every millisecond i get something like 5ms RTTs, which is still relatively fine.
  • But then if i send 1 byte messages every seconds, the RTT starts increasing (because it is smoothed) and eventually capping at 200ish ms.

I know this is probably related to usrsctp more than to libdatachannel, but am im missing something here? Is this because of the 1 out of 2 messages SACKs rule of SCTP, is this a thread issue because of the sleep ? I'm lost :D

Use libdatachannel from another project

I am trying to integrate libdatachannel to a project.
My own project is also using cmake.

I added this;
add_subdirectory(third-party/libdatachannel)

While compiling I got;
[build] libdatachannel.so.0.2.1: undefined reference to `pthread_atfork'

We need to add Thread as an requirement to libdatachannel.

EWOULDBLOCK != EAGAIN

if (ret >= 0) {
	PLOG_VERBOSE << "SCTP sent size=" << message->size();
	return true;
} else if (errno == EWOULDBLOCK && errno == EAGAIN) {
	PLOG_VERBOSE << "SCTP sending not possible";
	return false;
} else {
	PLOG_ERROR << "SCTP sending failed, errno=" << errno;
	throw std::runtime_error("Sending failed, errno=" + std::to_string(errno));
}	

should not it be this instead ?

if (errno == EWOULDBLOCK || errno == EAGAIN)

WebTransport

There's a new WebRTC adjacent protocol in the works: https://tools.ietf.org/id/draft-vvv-webtransport-http3-02.html

WebTransport is a protocol framework that enables clients constrained by the Web security model to communicate with a remote server using a secure multiplexed transport. This document describes Http3Transport, a WebTransport protocol that is based on HTTP/3 [HTTP3] and provides support for unidirectional streams, bidirectional streams and datagrams, all multiplexed within the same HTTP/3 connection.

@paullouisageneau is this something within the remit of libdatachannel?

Datachannel Reliability

If one side of communication ended or terminated, the other side still sends messages without any error, state is still connected.
About 5 min later state changes to disconnected.

You can make a test like that;

  • Start tests/p2p apps.
  • Make a connection
  • Send some message
  • Terminate one side
  • Continue to send messages from other side
  • It will send without any error
  • Wait until state=disconnected message

SCTP Invalid notification length

Hello.

I am getting a weird behavior when sending data bidirectionally on a connection.
I use libjuice and openssl compiling with clang on 64 bit linux.
Let's assume I create and connect 2 rtcdatachannels c1 and c2 to each other.

If c1 is only sending messages to c2 - everything works fine and c2 receives the sent messages from c1 as expected.

If c1 and c2 send messages to each other, it works for (randomly) about 20-30 messages and then when for ex. c1 sends 50k bytes message, c2 will receive a message with less than 50k bytes.
I as well see the following when logger is set to debug:
WARN [5730] [rtc::SctpTransport::processNotification@576] Invalid notification length
each time it happens.
The connection can continue and I will again receive a number of messages that are OK but then (randomly after 10-15 messages) it will happen again. The message gets truncated or something. Although I checked the first bytes of the truncated message and they do not correspond to the first bytes of the sent message.

I tried using only single datachannel and using it to both send/recv AND tried opening two datachannels (single RTC connection with two data channels) so one is used to send and one is used to receive. Still the problem remains.

I can provide logs but when I set log level to DEBUG this is the only useful line if I set it to VERBOSE I get about 20-30mb log file before the problem happens.

Can someone point me where should I dig ? I tried updating usrsctp & libjuice to latest versions from master and it doesn't seem to help. Did anyone had this kind of a problem ?

Update:
It seems the truncation only happens for big messages.
Message size 100k -> truncated message that I receive is 33644 bytes
Message size 70k -> truncated message that I receive is 3644 bytes
Message size 60k -> no truncation, everything works fine (at least for about 10 minutes sending/receiving full speed)
So the problem is somewhere at 66356 which is very close to 2^16... Is there any unsigned short that can overflow ?

Javascript to native example

Hi,

First, I wanted to say thanks for your help on getting the library compiling on mac os. We had a hack day in our team yesterday where we built a peer to peer connection between a native c++ and a browser based javascript program.

To communicate the connection information, we built a simple little webserver. I was wondering if you'd be interested in us cleaning up and including this as part of this library?

Relay Server over TCP

Hi @paullouisageneau ,

I am making some tests.
As I see libdatachannel can not create Turn+TCP candidates.
But can create STUN+TCP candidates. (Direct connection over TCP port)

I am using a TURN server.
All candidates over TURN are UDP. (Yes i am enabling ice-tcp)

Even I disable ice-udp I can not gather TCP candidates.

Is that normal?

Long Execution Time

mPeerConnPtr = std::make_shared<rtc::PeerConnection>(config);  // LibNice

It takes ~4 seconds to execute this line of code on Windows 10. (Xeon Processor)
Is it normal?

error: ‘IP_DONTFRAG’ undeclared (first use in this function)

Hi,

Below is the output when using mingw32 (MSYS2). What could be the problem?

[ 0%] Building C object deps/libjuice/CMakeFiles/juice-static.dir/src/udp.c.o
/c/Users/Pol/Desktop/Git/libdatachannel/deps/libjuice/src/udp.c: In function ‘udp_create_socket’:
/c/Users/Pol/Desktop/Git/libdatachannel/deps/libjuice/src/udp.c:95:31: error: ‘IP_DONTFRAG’ undeclared (first use in this function); did you mean ‘IPV6_DONTFRAG’?
95 | setsockopt(sock, IPPROTO_IP, IP_DONTFRAG, (char *)&enabled, sizeof(enabled));
| ^~~~~~~~~~~
| IPV6_DONTFRAG
/c/Users/Pol/Desktop/Git/libdatachannel/deps/libjuice/src/udp.c:95:31: note: each undeclared identifier is reported only once for each function it appears in
make[2]: *** [deps/libjuice/CMakeFiles/juice-static.dir/build.make:200: deps/libjuice/CMakeFiles/juice-static.dir/src/udp.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:1101: deps/libjuice/CMakeFiles/juice-static.dir/all] Error 2
make: *** [Makefile:150: all] Error 2

`

When browser is offerer data-channel is forever in 'connecting' state

Hello, I have a problem when webrtc offer is sent from browser. In this case data-channel is never opened and ice connection state is forever 'connecting'. I enabled verbose logging for libdatachannel. I see that after pasting remote offer and adding remote candidates it keeps output same messages:

2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:366: Leaving select
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:386: Received a datagram, size=100
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:272: Reading STUN message, class=0, method=1
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:307: Reading attribute 6, length=9
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:353: Reading username
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:359: Got username: wuza:2gZ2
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:307: Reading attribute C057, length=4
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:427: Ignoring unknown STUN attribute type C057
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:307: Reading attribute 802A, length=8
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:408: Found ICE controlling attribute
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:307: Reading attribute 25, length=0
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:403: Found use candidate flag
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:307: Reading attribute 24, length=4
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:393: Reading priority
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:399: Got priority: 1845501695
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:307: Reading attribute 8, length=20
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:363: Reading message integrity
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:307: Reading attribute 8028, length=4
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:372: Reading fingerprint
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:388: STUN fingerprint check succeeded
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:287: Finished reading STUN attributes
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:401: Received a STUN message
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:508: STUN message integrity check succeeded
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:651: STUN message is from the remote peer
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:965: A remote candidate exists for the remote address
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:1083: STUN entry 2 matching incoming address
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:689: Received STUN binding request
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:750: Got a nominated pair (controlled)
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:846: Sending STUN binding response
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:55: Writing STUN message, class=100, method=1
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:75: Writing XOR mapped address
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:205: Writing IPv4 address
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:178: Writing STUN attribute type 20, length=8
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:178: Writing STUN attribute type 8, length=20
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: stun.c:178: Writing STUN attribute type 8028, length=4
2020-05-14 15:35:18.446 VERB  [79] [rtc::IceTransport::LogCallback@262] juice: agent.c:349: Setting select timeout to 7709 ms
... and so on, repeated many times

Tested with Chrome/Firefox on MacOS and Windows. Also, when browser is answerer side and libdatachannel is offerer, data-channel is opened and I can send/receive messages.

How to reproduce

I have created two test web apps which allow to reproduce this bug (one work and other don't).

Outputs

Also I gathered verbose output of libdatachannel 'answerer' example app and other info: https://drive.google.com/file/d/1Jz4jvsdvgON81jlilN2u5kGM_1j5MCVi/view?usp=sharing

Outputs of working example (when browser is answerer): https://drive.google.com/file/d/1TE7EK0FFkXFPzQKG5McCrqiZYdZnW4Fo/view?usp=sharing

Version

I am using latest version of libdatachannel.

Memory leaks & Connections Left Behind

I have problems with ICE connection. Here is how I am testing;

  • Create a connection
  • Send some data
  • Close/Delete connection
  • Repeat the procedure

As I see we can not destroy ICE connection properly.

  • Memory used by app increases
  • Peer connection & stun connections left open. Using https://www.nirsoft.net/utils/live_tcp_udp_watch.html to watch connections.
  • File handles increases by 150 for every new connection
  • After 3-4 connection ICE begins to fail to make connection.
  • After deleting peer connection still I can see SCTP threads alive.

I tried some new procedures but could not achieve.
Please look at here https://github.com/libnice/libnice/blob/master/tests/test-turn.c

Help running example

Hi,

I'm quite new to web rtc (and c++ in general). I'm trying to prove that web rtc can be used to communicate very simple text data between a native desktop application and a web browser. I'm on mac OS, but I've managed to build this library inside an ubuntu docker container, however, I'm struggling to run the example working. Here's what I've been doing:

I'm running:

$ ./offerer
v=0
o=- 2760690859 0 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=ice-ufrag:UzVT
a=ice-pwd:eAtO73loK51GMlDrJjFd6I
a=ice-options:trickle
a=mid:0
a=setup:actpass
a=dtls-id:1
a=fingerprint:sha-256 2A:3B:30:DF:05:98:F7:82:FC:0D:59:74:18:D5:B5:1A:32:5D:0B:D6:5A:6C:51:F9:8E:15:E2:4D:CC:CA:B4:69
a=sctp-port:5000
a=max-message-size:262144
Local Description (Paste this to other peer):
^a=max-message-size:2621443B:30:DF:05:98:F7:82:FC:0D:59:74:18:D5:B5:1A:32:5D:0B:D6:5A:6C:51:F9:8E:15:E2:4D:CC:CA:B4:69

[ Gathering State: in_progress ]
Local Candidate (Paste this to other peer):
a=candidate:1 1 UDP 2122317823 172.17.0.2 48437 typ host



*************************************************************************
* 0: Exit / 1: Enter Description / 2: Enter Candidate / 3: Send Message *

I'm then running the following in another terminal on the same docker container:

$ ./datachannel

*************************************************************************
* 0: Exit / 1: Enter Description / 2: Enter Candidate / 3: Send Message *

I select option 1 and paste the fingerprint output from the first command (a=fingerprint:sha-256 2A:3B:30:DF:05:98:F7:82:FC:0D:59:74:18:D5:B5:1A:32:5D:0B:D6:5A:6C:51:F9:8E:15:E2:4D:CC:CA:B4:69)

which outputs:

[Command]: [ State: connecting ]
[ Gathering State: complete ]

I then select option 2 and enter the candatate from the first command (a=candidate:1 1 UDP 2122317823 172.17.0.2 48437 typ host)

In the terminal running the the first command I then see something like this:

2020-02-23 19:56:25.216 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:25.216 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:25.720 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:25.720 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:26.721 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:26.721 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:28.727 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:28.727 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:31.731 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:31.731 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:32.234 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:32.234 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:32.727 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:32.727 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:33.237 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:33.237 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:35.243 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:35.243 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed
2020-02-23 19:56:39.256 WARN  [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:539: STUN local ufrag check failed, expected="pRRI", actual="0"
2020-02-23 19:56:39.256 ERROR [21] [rtc::IceTransport::LogCallback@251] juice: agent.c:355: STUN message verification failed

From what I've read and understand, STUN is a protocol that webrtc uses to obtain an IP address and port to connect the 2 clients. Do these messages indicate that they cannot communicate with the stun server? Should I configure the address of this server somewhere? I wonder if docker networking is getting in the way here, but I had issues building this project on mac os.

Is this even the right project for what I am trying to achieve?

Any help would be amazing. Thanks :)

clang analyzer issue in rtc.cpp

Sorry for just dumping this here, I haven't had time to look into this myself yet. Feel free to close if you think this is a false positive:

/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:332:3: error: Inner pointer of container used after re/deallocation [clang-analyzer-cplusplus.InnerPointer,-warnings-as-errors]
                std::copy(addr->data(), addr->data() + size, buffer);
                ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:327:2: note: Taking false branch
        if (!peerConnection)
        ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:330:11: note: Assuming the condition is true
        if (auto addr = peerConnection->localAddress()) {
                 ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:330:2: note: Taking true branch
        if (auto addr = peerConnection->localAddress()) {
        ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:332:13: note: Pointer to inner buffer of 'std::__1::__optional_destruct_base<class std::__1::basic_string<char>, false>::value_type' obtained here
                std::copy(addr->data(), addr->data() + size, buffer);
                          ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:332:27: note: Calling 'optional::operator->'
                std::copy(addr->data(), addr->data() + size, buffer);
                                        ^
/usr/lib/llvm-10/bin/../include/c++/v1/optional:894:16: note: Inner buffer of 'std::__1::__optional_destruct_base<class std::__1::basic_string<char>, false>::value_type' reallocated by call to 'addressof'
        return _VSTD::addressof(this->__get());
               ^
/usr/lib/llvm-10/bin/../include/c++/v1/__config:782:15: note: expanded from macro '_VSTD'
#define _VSTD std::_LIBCPP_ABI_NAMESPACE
              ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:332:27: note: Returning; inner buffer was reallocated
                std::copy(addr->data(), addr->data() + size, buffer);
                                        ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:332:3: note: Inner pointer of container used after re/deallocation
                std::copy(addr->data(), addr->data() + size, buffer);
                ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:346:3: error: Inner pointer of container used after re/deallocation [clang-analyzer-cplusplus.InnerPointer,-warnings-as-errors]
                std::copy(addr->data(), addr->data() + size, buffer);
                ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:341:2: note: Taking false branch
        if (!peerConnection)
        ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:344:11: note: Assuming the condition is true
        if (auto addr = peerConnection->remoteAddress()) {
                 ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:344:2: note: Taking true branch
        if (auto addr = peerConnection->remoteAddress()) {
        ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:346:13: note: Pointer to inner buffer of 'std::__1::__optional_destruct_base<class std::__1::basic_string<char>, false>::value_type' obtained here
                std::copy(addr->data(), addr->data() + size, buffer);
                          ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:346:27: note: Calling 'optional::operator->'
                std::copy(addr->data(), addr->data() + size, buffer);
                                        ^
/usr/lib/llvm-10/bin/../include/c++/v1/optional:894:16: note: Inner buffer of 'std::__1::__optional_destruct_base<class std::__1::basic_string<char>, false>::value_type' reallocated by call to 'addressof'
        return _VSTD::addressof(this->__get());
               ^
/usr/lib/llvm-10/bin/../include/c++/v1/__config:782:15: note: expanded from macro '_VSTD'
#define _VSTD std::_LIBCPP_ABI_NAMESPACE
              ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:346:27: note: Returning; inner buffer was reallocated
                std::copy(addr->data(), addr->data() + size, buffer);
                                        ^
/home/arvid/dev/libtorrent/deps/libdatachannel/src/rtc.cpp:346:3: note: Inner pointer of container used after re/deallocation
                std::copy(addr->data(), addr->data() + size, buffer);
                ^

turns & transport option

In configuration.cpp we have code below;

	string scheme = opt[2].value_or("stun");
	if (scheme == "stun" || scheme == "STUN")
		type = Type::Stun;
	else if (scheme == "turn" || scheme == "TURN")
		type = Type::Turn;
	else if (scheme == "turns" || scheme == "TURNS")
		type = Type::Turn;
	else
		throw std::invalid_argument("Unknown ICE server protocol: " + scheme);

	relayType = RelayType::TurnUdp;
	if (auto &query = opt[15]) {
		if (query->find("transport=udp") != string::npos)
			relayType = RelayType::TurnUdp;
		if (query->find("transport=tcp") != string::npos)
			relayType = RelayType::TurnTcp;
		if (query->find("transport=tls") != string::npos)
			relayType = RelayType::TurnTls;
	}

According to libnice docs

NICE_RELAY_TYPE_TURN_UDP	A TURN relay using UDP
NICE_RELAY_TYPE_TURN_TCP	A TURN relay using TCP
NICE_RELAY_TYPE_TURN_TLS	A TURN relay using TLS over TCP

As I understand turns always uses TCP. So if scheme is turns than relayType should be TurnTls.

DataChannel has no transport

Is there a reason why this error is appearing, all the independence were installed.

2020-05-17 11:40:00.727 ERROR [65349] [rtcSendMessage@362] DataChannel has no transport

2020-05-17 11:40:00.727 DEBUG [65642] [rtc::IceTransport::stop@457] Stopping ICE thread

Header Only Library

I think we need to transition this library to be header only. As much as I like the idea of shared or static distributables, it is just not practical for C++ projects like it is for C. This all stems from the ABI stability problems that C++ has over C.

The C ABI is very stable and can support blind swapping of libraries between compilers. However in C++ a shared or static library produced by one compiler is not necessarily compatible with another.

Herb Sutter outlined the problem and a potential solution in this paper.

But the C++ standard moves slowly as that paper was written in 2014 and we are no closer to solving the problem.

I plan of making a header only transition sometime in the near future. Is that a change you would be willing to accept as a PR?

Nodejs wrapper

Do you know if there is a Nodejs (native) wrapper available for libdatachannel, or if somebody is working on it already?

Missing dependency, client example code

Is the plog library already installed during libdatachannel installation or do we have to install it. I am asking because i got this error.

/usr/local/include/rtc/log.hpp:22:10: fatal error: plog/Log.h: No such file or directory

   22 | #include "plog/Log.h"
      |          ^~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/datachannel-client.dir/build.make:63: CMakeFiles/datachannel-client.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/datachannel-client.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.