opened
paullouisageneau
username_0
This PR suggests an implementation of the WebTorrent protocol inside libtorrent. With this add-on, libtorrent can be used to run hybrid peers seamlessly.

WebTorrent peers use the same application protocol as classic peers but with WebRTC Data Channels as underlying transport instead of uTP or TCP, allowing to run peers in web browsers. Due to the necessary connection signaling, WebTorrent peers require a specific WebSocket tracker to connect. 

WebTorrent specification is lacking but you can find useful information and the reference Javascript implementation here: https://github.com/webtorrent/webtorrent

The implementation requires two external dependencies added as submodules:
- [libdatachannel](https://github.com/username_0/libdatachannel), my lightweight WebRTC Data Channels implementation
- [nlohmann/json](https://github.com/nlohmann/json), a header-only JSON library for the tracker protocol

To test, you need a torrent file with at least one WebSocket tracker, for instance `wss://tracker.openwebtorrent.com`.
You can find such a torrent file here: https://ageneau.org/upload/sintel.torrent
You can also run a web browser peer on this page: https://webtorrent.io/
WebTorrent support
issue
created
arvidn
username_1
to give this a shot at building on CI, you need to update the requirements from C++14 to C++17.
```
git grep cxxstd
git grep CMAKE_CXX_STANDARD
```
comment
created
arvidn
username_1
the switch to C++17 seems to cause some warnings of use of deprecated std facilities. I will factor out just the upgrade to C++17 into a separate PR and fix all those in there. But I don't intend to land it before the 2.0 cut.
comment
created
paullouisageneau
username_0
Currently, libdatachannel depends on gnutls for cryptography. I plan to add an option to use openssl as backend instead, so it can integrate cleanly here.
comment
created
paullouisageneau
username_0
I cleaned up the stuff related to the C++17 bump and rebased on the `cxx-17` branch.
comment
created
arvidn
username_1
cool. I expect to push a bunch more, rebase and squash that PR before it lands. just so you know.
comment
created
arvidn
username_1
https://travis-ci.org/username_1/libtorrent/jobs/628064314#L546 that's a check to make sure headers are self-contained. i.e. include all of their dependencies.
comment
created
paullouisageneau
username_0
Indeed, I changed the type to `time_duration` instead, and the timer to `basic_waitable_timer<steady_clock>` instead of `deadline_timer` which relies on the old-fashioned `boost::posix_time`.
comment
created
MasterOfTheTiger
username_2
Sorry to be that guy, but how far along is this PR? Is it in the early stages, or is it closer to being merged?
comment
created
paullouisageneau
username_0
@username_2 From my point of view it's nearly ready, only some details might need fixing. For the actual timeline, it's mainly @username_1 's decision, he wanted to merge it after transitioning libtorrent to C++17. Also, I'd be grateful if some people had the opportunity to test this implementation!

I just pushed some changes to merge the latin1 functions with the existing Unicode conversion functions, and to remove the dependency on libnice and glib (libdatachannel now relies on my own ICE lib, [libjuice.](https://github.com/username_0/libjuice)).
comment
created
leoherzog
username_3
At a high level, has @username_1 given any hint of how he feels about this addition to `libtorrent`, pro or against?
comment
created
arvidn
username_1
yes, I'm fine with adding these features. These are my thoughts:

1. I would like to cut 2.0 before landing this in master. Partly because 2.0 only requires C++14, and this patch will bump that to 17. But also partly because 2.0 already has a lot of new functionality, enough for a major release. I also think this is a big patch that should soak in master for a while before being declared stable.

2. I would like to have a build configuration option to exclude webtorrent support

3. I would like somewhat thorough tests. unit tests for as much as possible and maybe even simulations/end-to-end tests. But I think the latter is difficult unless libdatachannel sits on top of boost.asio. Obviously the existing tests need to build and pass still, so there are some challenges just to make sure all the CI work as well.

4. I would prefer to use boost.beast for websocket support, but I guess that's all built into libdatachannel, so this is mostly a preference (just like I would like to replace all existing HTTP support in libtorrent with boost.beast, it's just a lot of work).

5. I would prefer to use a lighter weight json library. This is kind of a detail as well, I don't expect it to be a lot of work to switch it out. boost.json (which I don't believe is part of boost yet) may be a good option. I'm not sure it can *generate* json though, but it's a parser.
comment
created
paullouisageneau
username_0
Good point, boost.json would make sense, I'll look into it.
comment
created
vijayanandnandam
username_4
@username_0 i can help you in testing this in production.
comment
created
Allardje
username_5
Yuuushhhhh it's happening! I've been waiting so long for this. Goodluck boys and a lot of love for your work.
comment
created
paullouisageneau
username_0
I replaced nlhomann/json by boost.JSON as suggested by @username_1. I'll now add unit test coverage for new parts of the code.
comment
created
pengpeng
username_6
@username_0 could you tell me the boost and gcc version please.
I try to use
boost 1.72.0
gcc 7.5.0
ubuntu 16.04 
and I can not build it
comment
created
pengpeng
username_6
I use https://github.com/webtorrent/bittorrent-tracker be the tracker
The torrent has only one tracker ws://myip:myport

I set up two client_test on one server, one is the seeder, the other is the downloader
I disabled lsd and dht

I crashed on add_peer.list:1018
iterator iter = std::lower_bound(m_peers.begin(), m_peers.end()
              , peer_id, peer_address_compare());

seems m_peers is 0x0

it's very confused me, please give me some advice, thanks
comment
created
pengpeng
username_6
I found the above problem

I added "need_peer_list();"
before "torrent_state st = get_peer_list_state();"
at torrent.cpp:5707

and it works

but I met another the problem, the two clients are on the same machine, but the speed is not very stable, it will close the connection after a few seconds

I checked the log
seeder's log looks good, but the downloader's log had

[Mar 22 15:40:54] bbb_sunflower_1080p_30fps_normal.mp4 hash for piece 704 failed
[Mar 22 15:40:55] bbb_sunflower_1080p_30fps_normal.mp4 peer [ 172.21.0.13:50632 client: libtorrent 2.0.0 ] peer error [bittorrent] [libtorrent]: packet too large
[Mar 22 15:40:55] bbb_sunflower_1080p_30fps_normal.mp4 peer [ 172.21.0.13:49788 client: libtorrent 2.0.0 ] peer error [bittorrent] [libtorrent]: packet too large

please give me some advice, thanks
comment
created
paullouisageneau
username_0
@username_6 thanks for the test and investigation! I'll look into that packet too large issue.
comment
created
pengpeng
username_6
Thanks username_0, it's my pleasure

I use a workaround method to changed datachannel.cpp:67
from RECV_QUEUE_LIMT 1024* 1024
TO
 RECV_QUEUE_LIMT 20 *1024* 1024

It seems to work now
comment
created
paullouisageneau
username_0
I fixed issues related to SCTP handling and I have a hard time reproducing the behavior now, so I think it is solved.
It's also good to check interoperability with existing webtorrent clients, on my side I tested with https://github.com/webtorrent/webtorrent-desktop
comment
created
paullouisageneau
username_0
I fixed issues related to SCTP handling and I have a hard time reproducing the behavior now, so I think it might be solved.
It's also good to check interoperability with existing webtorrent clients, on my side I tested with https://github.com/webtorrent/webtorrent-desktop
comment
created
kropple
username_7
id love to help.
comment
created
pengpeng
username_6
i test with two libtorrent client on two aws server
I will test webtorrent-desktop yesterday and do some other test

so far, I have two problems:
1.   I still have the "packet too large" problem, almost every time
I add some log, see "libdatachannel: WARN rtc::SctpTransport::processNotification@510: Invalid notification length" before "packet too large"

2.  When I kill one client, the other will crashed(not every time), here is the core dump
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ff7a62f8801 in __GI_abort () at abort.c:79
#2  0x00005610d9a9d335 in __gnu_cxx::__verbose_terminate_handler() ()
#3  0x00005610d9a05356 in __cxxabiv1::__terminate(void (*)()) ()
#4  0x00005610d9a05bd9 in __cxa_call_terminate ()
#5  0x00005610d9a04d98 in __gxx_personality_v0 ()
#6  0x00005610d9aa9313 in _Unwind_RaiseException_Phase2 ()
#7  0x00005610d9aa9e4e in _Unwind_Resume ()
#8  0x00005610d996b013 in rtc::PeerConnection::close() ()
#9  0x00005610d996b051 in rtc::PeerConnection::~PeerConnection() ()
#10 0x00005610d9727d9a in libtorrent::aux::rtc_stream_impl::~rtc_stream_impl() ()
#11 0x00005610d972a578 in std::_Function_handler<void (), libtorrent::aux::rtc_stream_impl::init()::{lambda()#1}>::_M_invoke(std::_Any_data const&) ()
#12 0x00005610d9945c62 in rtc::Channel::triggerAvailable(unsigned long) ()
#13 0x00005610d995cacb in rtc::DataChannel::incoming(std::shared_ptr<rtc::Message const>) ()
#14 0x00005610d996d4b4 in rtc::PeerConnection::forwardMessage(std::shared_ptr<rtc::Message const>) ()
#15 0x00005610d996f5b3 in std::_Function_handler<void (std::shared_ptr<rtc::Message const>), std::_Bind<void (rtc::PeerConnection::*(rtc::PeerConnection*, std::_Placeholder<1>))(std::shared_ptr<rtc::Message const>)> >::_M_invoke(std::_Any_data const&, std::shared_ptr<rtc::Message const>&&) ()
#16 0x00005610d9978484 in rtc::SctpTransport::processNotification(sctp_notification const*, unsigned long) ()
#17 0x00005610d997a0f2 in rtc::SctpTransport::handleRecv(socket*, sctp_sockstore, std::byte const*, unsigned long, sctp_rcvinfo, int) ()
#18 0x00005610d997a66c in rtc::SctpTransport::RecvCallback(socket*, sctp_sockstore, void*, unsigned long, sctp_rcvinfo, int, void*) ()
#19 0x00005610d99d638e in sctp_invoke_recv_callback ()
#20 0x00005610d99d65c5 in sctp_add_to_readq ()
#21 0x00005610d99d7556 in sctp_notify_stream_reset.part ()
#22 0x00005610d99994bc in sctp_handle_stream_reset ()
#23 0x00005610d999a37f in sctp_process_control ()
#24 0x00005610d999dbbc in sctp_common_input_processing ()
#25 0x00005610d9991e4b in usrsctp_conninput ()
#26 0x00005610d99744d5 in rtc::SctpTransport::incoming(std::shared_ptr<rtc::Message const>) ()
#27 0x00005610d997bc83 in std::_Function_handler<void (std::shared_ptr<rtc::Message const>), std::_Bind<void (rtc::Transport::*(rtc::Transport*, std::_Placeholder<1>))(std::shared_ptr<rtc::Message const>)> >::_M_invoke(std::_Any_data const&, std::shared_ptr<rtc::Message const>&&) ()
#28 0x00005610d9984462 in rtc::DtlsTransport::runRecvLoop() ()
#29 0x00005610d9a5081f in execute_native_thread_routine ()
#30 0x00007ff7a6a4e6db in start_thread (arg=0x7ff795ffb700) at pthread_create.c:463
#31 0x00007ff7a63d988f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

sorry for my poor English

thanks
comment
created
paullouisageneau
username_0
Thanks for the log line, I think I've found a potential issue with SCTP fragmentation handling. I've no idea why I can't reliably reproduce it. I'm on the crash issue you found now, deletion is actually not handled properly in the `rtc_stream` wrapper.
comment
created
pengpeng
username_6
Here is my test case:
https://bytetrade.s3.amazonaws.com/web3.torrent
https://bytetrade.s3.amazonaws.com/bbb_sunflower_1080p_30fps_normal.mp4

![image](https://user-images.githubusercontent.com/921131/77912420-1aaeab80-72c5-11ea-8536-7b7bfff8a3ff.png)

I already started a tracker at 18.139.132.115:8000 (use bittorrent-tracker)
I also started a seeder use libtorrent

Could it help you to reproduce the problem?
comment
created
paullouisageneau
username_0
@username_6 Thank you very much for the test environment, it's very handy. 
I think I fixed both issues. I can still observe sometimes webtorrent-desktop pausing when downloading, but this doesn't seem to be triggered by an error on the other side. Could you confirm on your side ?
comment
created
pengpeng
username_6
@username_0 thank you. I will test as soon as possible
comment
created
pengpeng
username_6
@username_0 sorry for my late reply, I was sick last week

I updated to the newest libdatachanel and libjuice and the "the large packet" problem was still here

And I found a lot of "juice: agent.c:882: STUN message send failed, errno=101"
The first picture is before the first announce, the announce was succeed after 5-6 times failed
The second picture is before the webtorrent to connect, the connect was failed

![image](https://user-images.githubusercontent.com/921131/78508237-c2d9de00-77b7-11ea-82d7-c59a6f4a9c1b.png)


![image](https://user-images.githubusercontent.com/921131/78508309-6d520100-77b8-11ea-96f8-b3f2540581ce.png)
comment
created
paullouisageneau
username_0
The `STUN message send failed, errno=101` is network unreachable, it probably comes from a configured IPv6 address with no configured IPv6 routes. It's no big deal, I could actually make it more explicit and change it to a warning.

I'm very puzzle by this "large packet issue"... Do you please have the log for the entire session? Also, for confirmation, you test with two local peers running on Linux, right?
comment
created
arvidn
username_1
I would expect that the underlying issue causing "large packet" error is some kind of corruption on the bittorrent peer connection. Where range of bytes may be lost or duplicated (for example). I would expect the bittorrent messages to get out-of-sync and interpret "random" data as the message length.
comment
created
paullouisageneau
username_0
That was my thinking too, then I thought the corruption was caused by SCTP partial notifications, which could be interleaved with partial data by default. It was a perfect culprit, however it doesn't seem to solve the actual problem.
comment
created
pengpeng
username_6
1. I tested on two AWS server, the system is ubuntu 18.04 LTS

2. Here is the log of the client_test ( compiled by https://github.com/username_0/libtorrent), the only change is add in client_test.cpp

settings.set_bool(settings_pack::enable_lsd, false);
settings.set_bool(settings_pack::enable_dht, false);
settings.set_bool(settings_pack::enable_upnp, false);
settings.set_bool(settings_pack::enable_natpmp, false);

this is the leecher log: https://bytetrade.s3.amazonaws.com/client_test.log.leecher.txt
this is the seeder log: https://bytetrade.s3.amazonaws.com/client_test.log.seeder.txt

3. This is the log of my code integrated the libdatachannel:
this is the leecher log: https://bytetrade.s3.amazonaws.com/username_6.log.leecher.txt
this is the seeder log:  https://bytetrade.s3.amazonaws.com/username_6.log.seeder.txt
I modify some code in bt_peer_conncectiont, but I think bt_peer_conneciton itself works well. 

4.  The important use of webrtc is to be able to play streaming media. Now it takes 15s from client startup to send the first announce to the tracker. It is difficult for users to accept that there is no content in 15s after loading. I think this will limit the use of this function. 
in username_6.log.seeder.txt: start time is 12:13:02.287153, announce send time is 12:13:18.804120
in username_6.log.leecher.txt: start time is 12:13:33.289923, announce send time is 12:13:49.860594

5. @username_0  you can add more logs in libdatachannel and libjuice,  and I can catch the log for you. if it helps
comment
created
paullouisageneau
username_0
Good point, the delay you observe is linked to the network unreachable errors you mentionned earlier. I'm pretty sure the cause is unconfigured IPv6 routing that makes the ICE agent (juice) wait for the timeout of the corresponding candidate before marking candidate gathering as finished (WebTorrent does not use candidate trickling). To prevent that, I guess it could be safe to consider a candidate as failed as soon as send fails on it, this should reduce the time before announce to 1 or 2 seconds in your setup. I'll do the corresponding changes.
comment
created
paullouisageneau
username_0
@username_6 The time before announce should now be greatly reduced in your case (ICE candidates for which the agent fails to send a datagram are now immediately marked as failed).
comment
created
pengpeng
username_6
@username_0 sorry， I had just read the message.  I will test as soon as possible. many thanks for your great work
comment
created
kak2zz
username_8
@username_0 thank you for this! But client_test cant  seed to websocket tracker (https://github.com/webtorrent/bittorrent-tracker)

Command for launch:
`libtorrent/build/examples/client_test "magnet:?xt=urn:btih:dcbdce78786333f93935601a2bdd64c0a493cf9f&xt=urn:btmh:1220177b03d442b1a90829b24513bb2eda8cfa21c8ac2ac2aa5d2e4352a345c17be8&dn=video.mp4&tr=ws%3a%2f%2f127.0.0.1%3a8000" -f log`

Log from client:
```
[May 12 16:42:02] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6882] sending announce (started)
[May 12 16:42:02] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6882] sending announce (started)
```

But on websocket tracker side no attempts from client. Maybe this is a problem on the tracker side. There may be other implementations of websocket trackers?
comment
created
paullouisageneau
username_0
@username_8 It looks like a client problem, else you'd see a connection on the tracker side. How have you built the client? 
I just tried your command with the same local tracker (sadly this is the only webtorrent tracker implementation I know of) and I get:
```
[May 12 18:00:19] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6881] sending announce (started)
[May 12 18:00:19] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6881] sending announce (started)
[...]
[May 12 18:00:29] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6881] received peers: 0
[May 12 18:00:29] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6881] received peers: 0
```
I used the cmake config `cmake -B build -Dvariant=debug -Dlogging=1 -Dwebtorrent=1 -Ddht=0 -Dextensions=0 -Dbuild_examples=1`
comment
created
kak2zz
username_8
My steps to build:
```
git clone --recurse-submodules https://github.com/username_0/libtorrent

mkdir libtorrent/build

cd libtorrent/build/

cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 -Dvariant=debug -Dlogging=1 -Dwebtorrent=1 -Ddht=0 -Dextensions=0 -Dbuild_examples=1 -G Ninja ..

ninja -j8

./examples/make_torrent video.mp4 -t "ws://localhost:8000" > torrent.torrent

./examples/client_test torrent.torrent -f log

```

maybe its problem in my environment (OS/cmake version/boost version), because before (about 1 month ago) everything worked well (not to mention announce timeout ~15s, as discussed above).. I will try to restore previous environment and rebuild
comment
created
paullouisageneau
username_0
OK, so the exact same setup works properly for me with linux and boost 1.72. Could you please check that the submodules are updated and that the tests of libdatachannel work for you?
comment
created
kak2zz
username_8
@username_0  im rebuild libtorrent and now client_test connects successfully to webtorrent tracker:
```
[May 18 07:48:08] video.mp4 (ws://34.91.79.64:8000)[127.0.0.1:6881] sending announce (started)
[May 18 07:48:08] video.mp4 (ws://34.91.79.64:8000)[127.0.0.1:6881] sending announce (started)
[May 18 07:48:18] video.mp4 (ws://34.91.79.64:8000)[127.0.0.1:6881] received peers: 0
[May 18 07:48:18] video.mp4 (ws://34.91.79.64:8000)[127.0.0.1:6881] received peers: 0
[May 18 07:50:18] video.mp4 (ws://34.91.79.64:8000)[127.0.0.1:6881] sending announce (none)
[May 18 07:50:28] video.mp4 (ws://34.91.79.64:8000)[127.0.0.1:6881] received peers: 0
[May 18 07:52:28] video.mp4 (ws://34.91.79.64:8000)[127.0.0.1:6881] sending announce (none)
```
But received peers always 0:
`[May 18 07:50:28] video.mp4 (ws://34.91.79.64:8000)[127.0.0.1:6881] received peers: 0`


For test i have:
webtorrent tracker on host 34.91.79.64 (port 8000)
libtorrent client_test running on host 34.91.79.64 for seeding file:
```
:~$ libtorrent/build/examples/dump_torrent torrent.torrent
trackers:

 0: ws://34.91.79.64:8000
number of pieces: 486
piece length: 65536
info hash: dcbdce78786333f93935601a2bdd64c0a493cf9f, 177b03d442b1a90829b24513bb2eda8cfa21c8ac2ac2aa5d2e4352a345c17be8
comment:
created by: libtorrent
magnet link: magnet:?xt=urn:btih:dcbdce78786333f93935601a2bdd64c0a493cf9f&xt=urn:btmh:1220177b03d442b1a90829b24513bb2eda8cfa21c8ac2ac2aa5d2e4352a345c17be8&dn=video.mp4&tr=ws%3a%2f%2f34.91.79.64%3a8000
name: video.mp4
number of files: 1
files:
        0    31838355 ---- [     0,   485 ]       0 c01307eb3ff150a7c20fd64c4d27b0780c959c3ac9a19e372e61ad4e3cbc1525 video.mp4

```
html page http://34.91.79.64/ for webtorrent client who download magnet: 
`magnet:?xt=urn:btih:dcbdce78786333f93935601a2bdd64c0a493cf9f&xt=urn:btmh:1220177b03d442b1a90829b24513bb2eda8cfa21c8ac2ac2aa5d2e4352a345c17be8&dn=video.mp4&tr=ws%3a%2f%2f34.91.79.64%3a8000`



Log file contain only this information about peer
```
[May 18 08:31:11] video.mp4 peer [ 188.255.14.176:55438 client: WW 0.0.0.8 ] disconnecting (RTC) [bittorrent] [libtorrent]: timed out: no interest (reason: 0)
[May 18 08:31:11] video.mp4 peer [ 188.255.14.176:58690 client: WW 0.0.0.8 ] disconnecting (RTC) [bittorrent] [libtorrent]: timed out: no interest (reason: 0)
```
comment
created
paullouisageneau
username_0
That, on the contrary, is really weird. So it connects, but nothing else? I think you should enable peer alerts in client_test to see in the look what's missing.
comment
created
arvidn
username_1
I think that peer disconnect error is caused by [this](https://github.com/username_1/libtorrent/blob/RC_1_2/include/libtorrent/error_code.hpp#L169) error. Which is triggered [here](https://github.com/username_1/libtorrent/blob/86f04b2c094e509c2b9c9ab0a12f1a67147649fe/src/peer_connection.cpp#L4954) if neither peers has been *interested* in the other for a long enough time. For instance both are *upload only* and have all the pieces they want already.
comment
created
paullouisageneau
username_0
@username_8 @username_1 I managed to reproduce, it seems the disconnect because not interested issue comes from the webtorrent client never being unchoked unless the choking algorithm is `fixed_slots_choker`. Everything works fine if unchoke slots are ignored for webtorrent: https://github.com/username_1/libtorrent/pull/4123/commits/957352271c8469d1c4744acbc1ed31649507eb0f
Maybe webtorrent has a weird protocol implementation?
comment
created
arvidn
username_1
`fixed_slots_choker` should be the default though. Also, even when it's set to `rate_based_choker`, there should always be at least 2 unchoke slots. And there should always be at least one optimistic-unchoke.

I have a feeling that perhaps something is making these peers not eligible for unchoking. Maybe the choker thinks the peers are still handshaking, or something.

Enabling peer logging (in the alert mask) might reveal something.
comment
created
paullouisageneau
username_0
@username_1 The default in `client_test` seems to be `rate_based_choker`: https://github.com/username_1/libtorrent/blob/2123d466072fb458aa459728645ce1fec96bf527/examples/client_test.cpp#L1207

Your feeling is probably right because I can see `peers: 1 eligible-peers: 0` in the log. I'm investigating.
```
*** UNCHOKE [ did not unchoke, the number of uploads (0) is more than or equal to the available slots (8), limit (8) ]
...
<== BITFIELD [ 00000000 ... ]
<<< ASYNC_READ [ max: 24 bytes ]
*** UPDATE_INTEREST [ not interesting ]
RECALCULATE UNCHOKE SLOTS: [ peers: 1 eligible-peers: 0 allowed-slots: 1 ]
```
comment
created
paullouisageneau
username_0
@username_1 The issue seems to be that webtorrent peers don't send an INTERESTED message at connection, so they can only be unchoked by the preemptive unchoke if the algorithm is `fixed_slots_choker`:
https://github.com/username_1/libtorrent/blob/262279251f2b4f501bf38293e9f1077486e2874c/src/session_impl.cpp#L6402
A way around this could be to mark them interested at connection.
comment
created
arvidn
username_1
yeah, ideally there should be a bug report against the client that doesn't send "INTERESTED" (even when they are) and there could be a special case in libtorrent that assumes the peer is interested if it's running a client that's known to have this issue. There is some precedence for per-client special cases for BitComet.
comment
created
paullouisageneau
username_0
There are basically two existing clients, the browser one (prefix "WW") and the the desktop hybrid one (prefix "WD"). Both basically share the same Javascript implementation. There is also a plugin for Vuze but it's basically just the same Javascript implementation in a Chromium instance... I'll use the peer id prefix to enable the mitigation as you suggest.
comment
created
kak2zz
username_8
@username_0 just now client_test work fine!
```
[May 21 14:39:10] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6881] sending announce (started)
[May 21 14:39:10] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6881] sending announce (started)
[May 21 14:39:20] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6881] received peers: 0
[May 21 14:39:20] video.mp4 (ws://127.0.0.1:8000)[127.0.0.1:6881] received peers: 0
[May 21 14:39:40] video.mp4 peer [ 188.255.14.176:51451 client: WebTorrent 0.0.0.8 ]: incoming request [ piece: 485 start: 0 length: 16384 ]
[May 21 14:39:41] video.mp4 peer [ 188.255.14.176:51451 client: WebTorrent 0.0.0.8 ]: incoming request [ piece: 0 start: 0 length: 16384 ]
[May 21 14:39:41] video.mp4 peer [ 188.255.14.176:51451 client: WebTorrent 0.0.0.8 ]: incoming request [ piece: 0 start: 16384 length: 16384 ]
[May 21 14:39:41] video.mp4 peer [ 188.255.14.176:51451 client: WebTorrent 0.0.0.8 ]: incoming request [ piece: 0 start: 32768 length: 16384 ]
```
Thank you!
comment
created
paullouisageneau
username_0
@username_1 I added unit tests for webRTC signaling, webRTC stream, and websocket tracker. In my view, this PR is finished and ready for review.
comment
created
arvidn
username_1
I will probably not have time to do a thorough review until this weekend.
comment
created
arvidn
username_1
it looks like the libdatachannel `Jamfile` also defines a feature called `crypto`, which conflicts with the one defined in libtorrent now
comment
created
paullouisageneau
username_0
@username_1 I rebased on master (thank you for merging the cxx-17 branch btw) and I think I addressed all your comments.

There is nothing special to create a webtorrent-compatible torrent, any normal torrent file with a websocket tracker (like [wss://tracker.openwebtorrent.com](wss://tracker.openwebtorrent.com)) will work.
comment
created
arvidn
username_1
nice, you got the CI all green! sorry for the delay in reviewing. I'm hoping to have time for a second pass this weekend
comment
created
arvidn
username_1
another thing that has changed in `master` now is that clang_tidy is being run again (I had accidentally broken it a while ago). It won't immediately affect most of this patch, since `webtorrent` is disabled by default. Maybe it would make sense to enable it though, to get more clang-tidy coverage.

It would mean there may be a few things it style issues it complains about. Pperhaps more importantly, it will complain about stuff in `libdatachannel`. I don't know how to disable clang_tidy for dependencies off-hand.
comment
created
paullouisageneau
username_0
@username_1 I rebased and addressed some of your comments, I still have a few left. I'll look into clang_tidy.
comment
created
arvidn
username_1
the way clang_tidy is set up is a bit messy. The key part of it (the checkers that are enabled) are kind of buried in the `.travis.yml` file where the `user-config.jam` is written. I'm not sure it makes sense to hold up this PR on getting all those fixed though
comment
created
arvidn
username_1
this is one consequence of clang-tidy: https://travis-ci.org/github/username_1/libtorrent/jobs/698905732#L2024
comment
created
paullouisageneau
username_0
@username_1 I think I addressed all of your comments, and I added tests for WebSocket message parsing.
comment
created
arvidn
username_1
https://travis-ci.org/github/username_1/libtorrent/jobs/699482064#L1170
comment
created
arvidn
username_1
something that just occurred to me is that appveyor isn't building with webtorrent enabled. Have you tested this on windows?
comment
created
arvidn
username_1
I think webtorrent should be enabled on at least one of the appveyor build jobs as well
comment
created
arvidn
username_1
I installed the python websocket package, the tracker test is getting farther, but it stalls.
There's a log line:
```
*** WEBSOCKET_TRACKER_WRITE [ size: 7925, data: 
```

which prints, what appears to be, JSON. However, the "info_hash" string seems to contain binary data. I was under the impression that you would have to escape that in json, but maybe all you need to escape is `"`.
It doesn't make for a very pretty log though :/

Towards the end of the test (before it stalls), I get:

```
*** WEBSOCKET_TRACKER_READ [ size: 135, data: {"info_hash": "\u00ed\u00af\u00f5\u001dnAb\u00b3 \u00ef\u009d/\u00bad\u00ab\u0084\b\u00bb,\u0085", "interval": 120, "min_interval": 60} ]
```

I notice the info-hash *is* escaped there, but escaped as unicode characters, which seems a bit odd (or at least a not very compact representation).

Actually, I just notice it ends with:

```
00:00:02.028: s: [tracker_reply] temporary (ws://127.0.0.1:7182/announce)[127.0.0.1:6881] received peers: 0
127.0.0.1 - [18/06/2020 00:52:22] WS "{"action":"announce","info_hash":..."
destructing session
```

So it *is* trying to destruct. Rebuilding with `asio-debugging=on`.
comment
created
arvidn
username_1
I just notice `usrsctp` suppresses this warning: `-Wno-address-of-packed-member`. I realize there aren't that many options for sctp support, but that may miscompile, as it's invoking UB
comment
created
arvidn
username_1
when debugging the websocket tracker test, it seems there's some inbalance between calls to `async_write()` and the handler being called, in `websocket_stream`. Maybe the socket fails to be canceled/closed properly, and some of its handlers are left hanging.
comment
created
arvidn
username_1
when shutting down the session, tracker announces are supposed to be cancelled or started with a short timeout (for stopping torrents).

However, when I stall in the test. `m_tracker_manager.empty()` keeps returning true. `m_tracker_manager.m_websocket_conns` still has an entry in it.

The outstanding operation being waited on is:

```
websocket_tracker_connection::on_write: (3)
2: libtorrent::aux::websocket_tracker_connection::do_send(libtorrent::tracker_request const&)
```

The `(3)` in parenthesis means there are 3 concurrent outstanding async operations for this callback. So it seems this async operation is leaking somehow.

`websocket_tracker_connection::on_timeout` is never called. Although, after 100 seconds, the tracker connection appear to close, but shutting down is still stalled on waiting for those 3 `on_write` callbacks.
comment
created
arvidn
username_1
this is not necessarily the issue causing the test to stall for me, but having `asio-debugging=on` builds working is really helpful when debugging issues like these. @username_0 would you mind running the tests with that build option?
comment
created
paullouisageneau
username_0
@username_1 This was caused by a mistake in `tracker_manager::abort_all_requests()`: the websocket connections must always be closed since it's not like the are going the finish at some point. I fixed it so it should not hang anymore. Strangely I'm sure I fixed this issue already, so maybe a rebase mistake on my part :thinking: 

The pending `on_write` were unrelated and were caused by a missing `COMPLETE_ASYNC` in the method.

About the bare UTF-8 encoding of the info_hash, it's indeed very clumsy, however this is how the original author did it, by using a legacy buffer encoding called "binary" in node.js instead of something sensible like base64 or hexadecimal. Let's hope it can be fixed in the future.
comment
created
paullouisageneau
username_0
It can be built for Windows with mingw, but might need a few tweaks to build properly on appveyor depending of the configuration. I'm looking into it.
comment
created
arvidn
username_1
yeah, it occurred to me that the `./configure` step of usrsctp might be non-trivial to get to work on windows too. Maybe it will just not be supported on windows for now
comment
created
arvidn
username_1
I do get a bunch of output from the test (I don't know sufficiently to judge whether it indicates any errors yet), then a "failure".

```
00:00:10.934: s: [torrent_log] temporary: *** tracker error: (1) The WebSocket stream was gracefully closed at both endpoints [sock_read] The WebSocket stream was gracefully closed at both endpoints
00:00:10.934: s: [torrent_log] temporary: *** increment tracker fail count [ep: 127.0.0.1:6883 url: ws://127.0.0.1:4951/announce 1]
00:00:10.934: s: [tracker_error] temporary (ws://127.0.0.1:4951/announce)[127.0.0.1:6883] The WebSocket stream was gracefully closed at both endpoints "The WebSocket stream was gracefully closed at both endpoints" (1)
```

This causes the "current tracker" test to fail:

```
***** test_tracker.cpp:712 "TEST_ERROR: check failed: "!status.current_tracker.empty()"" *****


***** test_tracker.cpp:713 "TEST_ERROR: status.current_tracker:  expected: ws://127.0.0.1:4951/announce" *****
```

I'll try to look into this a bit more
comment
created
paullouisageneau
username_0
@username_1 WebSocket closing was reported as a tracker error, which caused issue depending on timings I guess. It should be fine now.
comment
created
arvidn
username_1
undefined sanitizer reports an invalid cast:
```
../deps/libdatachannel/deps/plog/include/plog/Util.h:520:30: runtime error: downcast of address 0x0000140d7920 which does not point to an object of type 'Logger'
```
here:

```
#3  0x00007ffff68c7135 in __ubsan_handle_dynamic_type_cache_miss_abort () from /usr/lib/x86_64-linux-gnu/libubsan.so.1
#4  0x0000000005812e61 in plog::util::Singleton<plog::Logger<0> >::Singleton (this=0x140d7920 <plog::init<0>(plog::Severity, plog::IAppender*)::logger>) at ../deps/libdatachannel/deps/plog/include/plog/Util.h:520
#5  0x0000000005812177 in plog::Logger<0>::Logger (this=0x140d7920 <plog::init<0>(plog::Severity, plog::IAppender*)::logger>, maxSeverity=plog::none) at ../deps/libdatachannel/deps/plog/include/plog/Logger.h:20
#6  0x000000000581155e in plog::init<0> (maxSeverity=plog::none, appender=0x140d7840 <rtc::InitLogger(plog::Severity, plog::IAppender*)::consoleAppender>) at ../deps/libdatachannel/deps/plog/include/plog/Init.h:29
#7  0x000000000581105f in plog::init (maxSeverity=plog::none, appender=0x140d7840 <rtc::InitLogger(plog::Severity, plog::IAppender*)::consoleAppender>) at ../deps/libdatachannel/deps/plog/include/plog/Init.h:35
#8  0x000000000580fca4 in rtc::InitLogger (severity=plog::none, appender=0x0) at ../deps/libdatachannel/src/log.cpp:33
#9  0x0000000003e75f89 in libtorrent::aux::rtc_signaling::<lambda()>::operator()(void) const (__closure=0x7ffff1d602d0) at ../src/rtc_signaling.cpp:123
```

Looking closer at the `plog` dependency, there appears to be some shady code in `plog/Utils.h`

```
509         template<class T>
510 #ifdef _WIN32
511         class Singleton : NonCopyable
512 #else
513         class PLOG_LINKAGE Singleton : NonCopyable
514 #endif
515         {
516         public:
517             Singleton()
518             {
519                 assert(!m_instance);
520                 m_instance = static_cast<T*>(this);  <======
521             }
522
523             ~Singleton()
524             {
525                 assert(m_instance);
526                 m_instance = 0;
527             }
528
529             static T* getInstance()
530             {
531                 return m_instance;
532             }
533
534         private:
535             static T* m_instance;
536         };
```

line 520 is casting a pointer to itself to a `T*`, where `T` is really an arbitrary type. In this specific instance, it's `plog::Logger<0>`. `Logger` inherits from `Singleton<Logger>`, so a `Logger` has a `Singleton` object, but *not* the other way around. a `Singleton` does not have a `Logger` object.

```
    template<int instanceId>
    class PLOG_LINKAGE Logger : public util::Singleton<Logger<instanceId> >, public IAppender
```
comment
created
arvidn
username_1
address sanitizer reports an issue here:

```
==1123437==ERROR: AddressSanitizer: heap-use-after-free on address 0x628000011108 at pc 0x7f38eb5f1f4e bp 0x7f38e79fba40 sp 0x7f38e79fb1f0
READ of size 3836 at 0x628000011108 thread T11
    #0 0x7f38eb5f1f4d in __interceptor_memcpy ../../../../gcc-9.2.0/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790
    #1 0x31d6d10 in boost::asio::detail::buffer_copy_1(boost::asio::mutable_buffer const&, boost::asio::const_buffer const&) /home/arvid/dev/boost_1_72_0/boost/asio/buffer.hpp:2180
    #2 0x327b6e9 in unsigned long boost::asio::detail::buffer_copy<boost::asio::mutable_buffer const*, boost::beast::buffers_suffix<boost::asio::const_buffer>::const_iterator>(boost::asio::detail::one_buffer, boost::asio::detail::multiple_buffers, boost::asio::mutable_buffer const*, boost::asio::mutable_buffer const*, boost::beast::buffers_suffix<boost::asio::const_buffer>::const_iterator, boost::beast::buffers_suffix<boost::asio::const_buffer>::const_iterator, unsigned long) /home/arvid/dev/boost_1_72_0/boost/asio/buffer.hpp:2217
    #3 0x3275cd1 in unsigned long boost::asio::buffer_copy<boost::asio::mutable_buffer, boost::beast::buffers_suffix<boost::asio::const_buffer> >(boost::asio::mutable_buffer const&, boost::beast::buffers_suffix<boost::asio::const_buffer> const&) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x3275cd1)
    #4 0x3269c9d in boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::write_some_op<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::asio::const_buffer>::operator()(boost::system::error_code, unsigned long, bool) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x3269c9d)
```

```
0x628000011108 is located 4104 bytes inside of 15369-byte region [0x628000010100,0x628000013d09)
freed by thread T11 here:
    #0 0x7f38eb664ef7 in operator delete(void*) ../../../../gcc-9.2.0/libsanitizer/asan/asan_new_delete.cc:165
    #1 0x31f77dd in boost::json::detail::default_impl::deallocate(void*, unsigned long, unsigned long) ../deps/json/include/boost/json/impl/storage_ptr.hpp:49
    #2 0x3362e07 in boost::json::detail::storage_impl<boost::json::detail::default_impl>::deallocate(void*, unsigned long, unsigned long) ../deps/json/include/boost/json/impl/storage.hpp:52
    #3 0x31fa310 in boost::json::detail::string_impl::destroy(boost::json::storage_ptr const&) ../deps/json/include/boost/json/detail/string_impl.hpp:184
    #4 0x31fac56 in boost::json::string::~string() ../deps/json/include/boost/json/string.hpp:127
    #5 0x31cd551 in libtorrent::aux::websocket_tracker_connection::do_send(libtorrent::tracker_request const&) ../src/websocket_tracker_connection.cpp:230
    #6 0x31cb339 in operator()<libtorrent::tracker_request> ../src/websocket_tracker_connection.cpp:186
    #7 0x31d4ce9 in __invoke_impl<void, libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, libtorrent::tracker_request&> /usr/local/include/c++/9.2.0/bits/invoke.h:60
    #8 0x31d4885 in __invoke<libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, libtorrent::tracker_request&> /usr/local/include/c++/9.2.0/bits/invoke.h:95
[...]
    #13 0x31cb8af in visit<libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, std::variant<libtorrent::tracker_request, libtorrent::aux::tracker_answer>&> /usr/local/include/c++/9.2.0/variant:1654
    #14 0x31cbb09 in libtorrent::aux::websocket_tracker_connection::send_pending() ../src/websocket_tracker_connection.cpp:177
    #15 0x31cf88e in libtorrent::aux::websocket_tracker_connection::on_connect(std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, boost::system::error_code const&) ../src/websocket_tracker_connection.cpp:312
```

```
previously allocated by thread T11 here:
    #0 0x7f38eb6640ff in operator new(unsigned long) ../../../../gcc-9.2.0/libsanitizer/asan/asan_new_delete.cc:104
    #1 0x31f77b7 in boost::json::detail::default_impl::allocate(unsigned long, unsigned long) ../deps/json/include/boost/json/impl/storage_ptr.hpp:40
    #2 0x3362dd0 in boost::json::detail::storage_impl<boost::json::detail::default_impl>::allocate(unsigned long, unsigned long) ../deps/json/include/boost/json/impl/storage.hpp:43
    #3 0x31fa83d in boost::json::detail::string_impl::string_impl(unsigned long, boost::json::storage_ptr const&) ../deps/json/include/boost/json/detail/impl/string_impl.ipp:62
    #4 0x31fb568 in boost::json::string::reserve_impl(unsigned long) ../deps/json/include/boost/json/impl/string.ipp:295
    #5 0x31fb321 in boost::json::string::reserve(unsigned long) ../deps/json/include/boost/json/string.hpp:1773
    #6 0x321976d in boost::json::to_string(boost::json::value const&) ../deps/json/include/boost/json/impl/serializer.ipp:538
    #7 0x31cd0e6 in libtorrent::aux::websocket_tracker_connection::do_send(libtorrent::tracker_request const&) ../src/websocket_tracker_connection.cpp:230
    #8 0x31cb339 in operator()<libtorrent::tracker_request> ../src/websocket_tracker_connection.cpp:186
    #9 0x31d4ce9 in __invoke_impl<void, libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, libtorrent::tracker_request&> /usr/local/include/c++/9.2.0/bits/invoke.h:60
    #10 0x31d4885 in __invoke<libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, libtorrent::tracker_request&> /usr/local/include/c++/9.2.0/bits/invoke.h:95
[...]
    #15 0x31cb8af in visit<libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, std::variant<libtorrent::tracker_request, libtorrent::aux::tracker_answer>&> /usr/local/include/c++/9.2.0/variant:1654
    #16 0x31cbb09 in libtorrent::aux::websocket_tracker_connection::send_pending() ../src/websocket_tracker_connection.cpp:177
    #17 0x31cf88e in libtorrent::aux::websocket_tracker_connection::on_connect(std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, boost::system::error_code const&) ../src/websocket_tracker_connection.cpp:312
```

The problem seems to be that `websocket_tracker_connection::do_send()` passes a *local variable* as the buffer to `async_write`, which will go out of scope by the time the underlying operation will access the buffer.

It should be stored in a send buffer that stays alive until the completion handler is called.
comment
created
arvidn
username_1
it seems I may have broken travis building and running tests with the sanitizers too :/
comment
created
paullouisageneau
username_0
@username_1 About the shady cast in plog, `static_cast` should be fine to perform an unchecked downcast from `Singleton<Logger>` to its derived class `Logger<>` though, shouldn't it? Doesn't the sanitizer report the issue only because it's done in constructor, so the pointer to `Logger<>` is not valid yet since it's not constructed at the time of the cast?
comment
created
arvidn
username_1
I see, that's how it's supposed to work. The `Singleton` assumes that it's the base class of Logger.

Doesn't the sanitizer report the issue only because it's done in constructor, so the pointer to Logger<> is not valid yet since it's not constructed at the time of the cast?

I suppose since there's no virtual inheritance involved, any pointer offset would be known statically and would be the same. The questionable part then is the pointer provenance of constructing a pointer to an object before its lifetime has started. 

Either way, something should be done to make it ubsan-clean. It's just too useful to not have working.

Maybe the derived class could pass in the pointer to itself into the `Singleton` constructor, so there is never any cast performed.
comment
created
arvidn
username_1
https://travis-ci.org/github/username_1/libtorrent/jobs/700420541#L824
```
../../include/libtorrent/aux_/session_impl.hpp:1375:9: warning: 'generate_rtc_offers' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
                        void generate_rtc_offers(int /*count*/
                             ^
../../include/libtorrent/tracker_manager.hpp:232:16: note: overridden virtual function is here
                virtual void generate_rtc_offers(int count
                             ^
```

https://travis-ci.org/github/username_1/libtorrent/jobs/700420541#L6912
```
../../src/websocket_tracker_connection.cpp:180:8: error: reference to local binding 'callback' declared in enclosing function 'libtorrent::aux::websocket_tracker_connection::send_pending'
                        if (callback.lock())
                            ^
../../src/websocket_tracker_connection.cpp:174:13: note: 'callback' declared here
        auto [msg, callback] = std::move(m_pending.front());
                   ^
../../src/websocket_tracker_connection.cpp:182:19: error: reference to local binding 'callback' declared in enclosing function 'libtorrent::aux::websocket_tracker_connection::send_pending'
                                m_requester = callback;
                                              ^
```

I think there's some odd logic that considers lambda captures "shadowing" variables from the enclosing scope, even when you don't use a "capture-all" capture.

I think all the warnings in boost headers are best suppressed by:

```
#include "libtorrent/aux_/disable_warnings_push.hpp"
#inclue <boost/...>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
```
comment
created
arvidn
username_1
I'm not sure what's a good solution to things like this:

https://travis-ci.org/github/username_1/libtorrent/jobs/700445154#L762

Ideally the warnings would not be enabled on dependencies, but they are by default.
comment
created
paullouisageneau
username_0
For now I just did a tiny refactoring to prevent unused variables: https://github.com/username_0/libdatachannel/commit/52959ee7001aac6a491a277ddd8a1c484681bc94
comment
created
arvidn
username_1
I'm still seeing this. I'm pretty sure I have all your latest commits. I don't have time to investigate right now.

```
==1420170==ERROR: AddressSanitizer: heap-use-after-free on address 0x628000001108 at pc 0x7ff24abfcf4e bp 0x7ff246ffba40 sp 0x7ff246ffb1f0
READ of size 3818 at 0x628000001108 thread T11
    #0 0x7ff24abfcf4d in __interceptor_memcpy ../../../../gcc-9.2.0/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790
    #1 0x31d6ec6 in boost::asio::detail::buffer_copy_1(boost::asio::mutable_buffer const&, boost::asio::const_buffer const&) /home/arvid/dev/boost_1_72_0/boost/asio/buffer.hpp:2180
    #2 0x327b90d in unsigned long boost::asio::detail::buffer_copy<boost::asio::mutable_buffer const*, boost::beast::buffers_suffix<boost::asio::const_buffer>::const_iterator>(boost::asio::detail::one_buffer, boost::asio::detail::multiple_buffers, boost::asio::mutable_buffer const*, boost::asio::mutable_buffer const*, boost::beast::buffers_suffix<boost::asio::const_buffer>::const_iterator, boost::beast::buffers_suffix<boost::asio::const_buffer>::const_iterator, unsigned long) /home/arvid/dev/boost_1_72_0/boost/asio/buffer.hpp:2217
    #3 0x3275ef5 in unsigned long boost::asio::buffer_copy<boost::asio::mutable_buffer, boost::beast::buffers_suffix<boost::asio::const_buffer> >(boost::asio::mutable_buffer const&, boost::beast::buffers_suffix<boost::asio::const_buffer> const&) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x3275ef5)
    #4 0x3269ec1 in boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::write_some_op<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::asio::const_buffer>::operator()(boost::system::error_code, unsigned long, bool) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x3269ec1)
    #5 0x32a6e08 in boost::asio::detail::write_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, boost::beast::buffers_cat_view<boost::asio::mutable_buffer, boost::asio::mutable_buffer>, boost::beast::buffers_cat_view<boost::asio::mutable_buffer, boost::asio::mutable_buffer>::const_iterator, boost::asio::detail::transfer_all_t, boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::write_some_op<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::asio::const_buffer> >::operator()(boost::system::error_code const&, unsigned long, int) /home/arvid/dev/boost_1_72_0/boost/asio/impl/write.hpp:338
    #6 0x331c770 in boost::asio::detail::binder2<boost::asio::detail::write_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, boost::beast::buffers_cat_view<boost::asio::mutable_buffer, boost::asio::mutable_buffer>, boost::beast::buffers_cat_view<boost::asio::mutable_buffer, boost::asio::mutable_buffer>::const_iterator, boost::asio::detail::transfer_all_t, boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::write_some_op<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::asio::const_buffer> >, boost::system::error_code, unsigned long>::operator()() (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x331c770)
```

```
0x628000001108 is located 4104 bytes inside of 15369-byte region [0x628000000100,0x628000003d09)
freed by thread T11 here:
    #0 0x7ff24ac6fef7 in operator delete(void*) ../../../../gcc-9.2.0/libsanitizer/asan/asan_new_delete.cc:165
    #1 0x31f7993 in boost::json::detail::default_impl::deallocate(void*, unsigned long, unsigned long) ../deps/json/include/boost/json/impl/storage_ptr.hpp:49
    #2 0x336303d in boost::json::detail::storage_impl<boost::json::detail::default_impl>::deallocate(void*, unsigned long, unsigned long) ../deps/json/include/boost/json/impl/storage.hpp:52
    #3 0x31fa4c6 in boost::json::detail::string_impl::destroy(boost::json::storage_ptr const&) ../deps/json/include/boost/json/detail/string_impl.hpp:184
    #4 0x31fae3e in boost::json::string::~string() ../deps/json/include/boost/json/string.hpp:127
    #5 0x31cd6ab in libtorrent::aux::websocket_tracker_connection::do_send(libtorrent::tracker_request const&) ../src/websocket_tracker_connection.cpp:230
    #6 0x31cb493 in operator()<libtorrent::tracker_request> ../src/websocket_tracker_connection.cpp:186
    #7 0x31d4e9f in __invoke_impl<void, libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, libtorrent::tracker_request&> /usr/local/include/c++/9.2.0/bits/invoke.h:60
...
    #13 0x31cba09 in visit<libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, std::variant<libtorrent::tracker_request, libtorrent::aux::tracker_answer>&> /usr/local/include/c++/9.2.0/variant:1654
    #14 0x31cbc63 in libtorrent::aux::websocket_tracker_connection::send_pending() ../src/websocket_tracker_connection.cpp:177
    #15 0x31cfa44 in libtorrent::aux::websocket_tracker_connection::on_connect(std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, boost::system::error_code const&) ../src/websocket_tracker_connection.cpp:314
```

```
previously allocated by thread T11 here:
    #0 0x7ff24ac6f0ff in operator new(unsigned long) ../../../../gcc-9.2.0/libsanitizer/asan/asan_new_delete.cc:104
    #1 0x31f796d in boost::json::detail::default_impl::allocate(unsigned long, unsigned long) ../deps/json/include/boost/json/impl/storage_ptr.hpp:40
    #2 0x3363006 in boost::json::detail::storage_impl<boost::json::detail::default_impl>::allocate(unsigned long, unsigned long) ../deps/json/include/boost/json/impl/storage.hpp:43
    #3 0x31faa25 in boost::json::detail::string_impl::string_impl(unsigned long, boost::json::storage_ptr const&) ../deps/json/include/boost/json/detail/impl/string_impl.ipp:62
    #4 0x31fb78c in boost::json::string::reserve_impl(unsigned long) ../deps/json/include/boost/json/impl/string.ipp:295
    #5 0x31fb545 in boost::json::string::reserve(unsigned long) ../deps/json/include/boost/json/string.hpp:1773
    #6 0x3219991 in boost::json::to_string(boost::json::value const&) ../deps/json/include/boost/json/impl/serializer.ipp:538
    #7 0x31cd240 in libtorrent::aux::websocket_tracker_connection::do_send(libtorrent::tracker_request const&) ../src/websocket_tracker_connection.cpp:230
    #8 0x31cb493 in operator()<libtorrent::tracker_request> ../src/websocket_tracker_connection.cpp:186
    #9 0x31d4e9f in __invoke_impl<void, libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, libtorrent::tracker_request&> /usr/local/include/c++/9.2.0/bits/invoke.h:60
...
    #15 0x31cba09 in visit<libtorrent::aux::websocket_tracker_connection::send_pending()::<lambda(const auto:25&)>, std::variant<libtorrent::tracker_request, libtorrent::aux::tracker_answer>&> /usr/local/include/c++/9.2.0/variant:1654
    #16 0x31cbc63 in libtorrent::aux::websocket_tracker_connection::/() ../src/websocket_tracker_connection.cpp:177
    #17 0x31cfa44 in libtorrent::aux::websocket_tracker_connection::on_connect(std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, boost::system::error_code const&) ../src/websocket_tracker_connection.cpp:314
    #18 0x3279aef in void std::__invoke_impl<void, void (libtorrent::aux::websocket_tracker_connection::*&)(std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, boost::system::error_code const&), libtorrent::aux::websocket_tracker_connection*&, std::weak_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&>(std::__invoke_memfun_deref, void (libtorrent::aux::websocket_tracker_connection::*&)(std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, boost::system::error_code const&), libtorrent::aux::websocket_tracker_connection*&, std::weak_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&) /usr/local/include/c++/9.2.0/bits/invoke.h:73
```
comment
created
paullouisageneau
username_0
@username_1 I had fixed the use-after-free only in one of the two send methods, it should be good now.
comment
created
arvidn
username_1
```
==1431411==ERROR: AddressSanitizer: heap-use-after-free on address 0x61b00017fb80 at pc 0x7ff701448170 bp 0x7ff6fd7fb3f0 sp 0x7ff6fd7faba0
WRITE of size 135 at 0x61b00017fb80 thread T11
    #0 0x7ff70144816f in __interceptor_memcpy ../../../../gcc-9.2.0/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790
    #1 0x31d6f48 in boost::asio::detail::buffer_copy_1(boost::asio::mutable_buffer const&, boost::asio::const_buffer const&) /home/arvid/dev/boost_1_72_0/boost/asio/buffer.hpp:2180
    #2 0x32a2178 in unsigned long boost::asio::detail::buffer_copy<boost::beast::buffers_suffix<boost::asio::mutable_buffer>::const_iterator, boost::asio::mutable_buffer const*>(boost::asio::detail::multiple_buffers, boost::asio::detail::multiple_buffers, boost::beast::buffers_suffix<boost::asio::mutable_buffer>::const_iterator, boost::beast::buffers_suffix<boost::asio::mutable_buffer>::const_iterator, boost::asio::mutable_buffer const*, boost::asio::mutable_buffer const*, unsigned long) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x32a2178)
    #3 0x32940fb in unsigned long boost::asio::buffer_copy<boost::beast::buffers_suffix<boost::asio::mutable_buffer>, boost::beast::detail::buffers_pair<true> >(boost::beast::buffers_suffix<boost::asio::mutable_buffer> const&, boost::beast::detail::buffers_pair<true> const&, unsigned long) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x32940fb)
    #4 0x3281361 in boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::read_some_op<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::read_op<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::beast::basic_flat_buffer<std::allocator<char> > >, boost::asio::mutable_buffer>::operator()(boost::system::error_code, unsigned long, bool) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x3281361)
```

```
0x61b00017fb80 is located 0 bytes inside of 1536-byte region [0x61b00017fb80,0x61b000180180)
freed by thread T11 here:
    #0 0x7ff7014baef7 in operator delete(void*) ../../../../gcc-9.2.0/libsanitizer/asan/asan_new_delete.cc:165
    #1 0x24a4927 in __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) /usr/local/include/c++/9.2.0/ext/new_allocator.h:128
    #2 0x249d567 in std::allocator_traits<std::allocator<char> >::deallocate(std::allocator<char>&, char*, unsigned long) /usr/local/include/c++/9.2.0/bits/alloc_traits.h:470
    #3 0x322804b in boost::beast::basic_flat_buffer<std::allocator<char> >::~basic_flat_buffer() /home/arvid/dev/boost_1_72_0/boost/beast/core/impl/flat_buffer.hpp:35
    #4 0x335f0ee in libtorrent::aux::websocket_tracker_connection::~websocket_tracker_connection() ../include/libtorrent/aux_/websocket_tracker_connection.hpp:77
    #5 0x2f7803b in void __gnu_cxx::new_allocator<libtorrent::aux::websocket_tracker_connection>::destroy<libtorrent::aux::websocket_tracker_connection>(libtorrent::aux::websocket_tracker_connection*) /usr/local/include/c++/9.2.0/ext/new_allocator.h:153
    #6 0x2f77f42 in void std::allocator_traits<std::allocator<libtorrent::aux::websocket_tracker_connection> >::destroy<libtorrent::aux::websocket_tracker_connection>(std::allocator<libtorrent::aux::websocket_tracker_connection>&, libtorrent::aux::websocket_tracker_connection*) /usr/local/include/c++/9.2.0/bits/alloc_traits.h:497
    #7 0x2f778ac in std::_Sp_counted_ptr_inplace<libtorrent::aux::websocket_tracker_connection, std::allocator<libtorrent::aux::websocket_tracker_connection>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/local/include/c++/9.2.0/bits/shared_ptr_base.h:557
    #8 0x2495604 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/local/include/c++/9.2.0/bits/shared_ptr_base.h:155
    #9 0x248ec31 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/local/include/c++/9.2.0/bits/shared_ptr_base.h:730
    #10 0x2f3d785 in std::__shared_ptr<libtorrent::aux::websocket_tracker_connection, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/local/include/c++/9.2.0/bits/shared_ptr_base.h:1169
    #11 0x2f3d7a1 in std::shared_ptr<libtorrent::aux::websocket_tracker_connection>::~shared_ptr() /usr/local/include/c++/9.2.0/bits/shared_ptr.h:103
    #12 0x2f68b24 in void std::_Destroy<std::shared_ptr<libtorrent::aux::websocket_tracker_connection> >(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*) /usr/local/include/c++/9.2.0/bits/stl_construct.h:98
    #13 0x2f60f3b in void std::_Destroy_aux<false>::__destroy<std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*>(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*, std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x2f60f3b)
    #14 0x2f55d23 in void std::_Destroy<std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*>(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*, std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x2f55d23)
    #15 0x2f4adf6 in void std::_Destroy<std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*, std::shared_ptr<libtorrent::aux::websocket_tracker_connection> >(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*, std::shared_ptr<libtorrent::aux::websocket_tracker_connection>*, std::allocator<std::shared_ptr<libtorrent::aux::websocket_tracker_connection> >&) /usr/local/include/c++/9.2.0/bits/stl_construct.h:206
    #16 0x2f43ad7 in std::__cxx1998::vector<std::shared_ptr<libtorrent::aux::websocket_tracker_connection>, std::allocator<std::shared_ptr<libtorrent::aux::websocket_tracker_connection> > >::~vector() (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x2f43ad7)
    #17 0x2f3f765 in std::__debug::vector<std::shared_ptr<libtorrent::aux::websocket_tracker_connection>, std::allocator<std::shared_ptr<libtorrent::aux::websocket_tracker_connection> > >::~vector() /usr/local/include/c++/9.2.0/debug/vector:220
    #18 0x2f39f23 in libtorrent::tracker_manager::abort_all_requests(bool) ../src/tracker_manager.cpp:497
    #19 0x284e337 in libtorrent::aux::session_impl::abort() ../src/session_impl.cpp:1027
    #20 0x274a47d in libtorrent::aux::session_impl::call_abort()::{lambda()#1}::operator()() const (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x274a47d)
```

```
previously allocated by thread T11 here:
    #0 0x7ff7014ba0ff in operator new(unsigned long) ../../../../gcc-9.2.0/libsanitizer/asan/asan_new_delete.cc:104
    #1 0x249d5ac in __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) /usr/local/include/c++/9.2.0/ext/new_allocator.h:114
    #2 0x24958a7 in std::allocator_traits<std::allocator<char> >::allocate(std::allocator<char>&, unsigned long) /usr/local/include/c++/9.2.0/bits/alloc_traits.h:444
    #3 0x328eec9 in boost::beast::basic_flat_buffer<std::allocator<char> >::alloc(unsigned long) /home/arvid/dev/boost_1_72_0/boost/beast/core/impl/flat_buffer.hpp:527
    #4 0x327ccd2 in boost::beast::basic_flat_buffer<std::allocator<char> >::prepare(unsigned long) /home/arvid/dev/boost_1_72_0/boost/beast/core/impl/flat_buffer.hpp:338
    #5 0x3278635 in boost::optional<boost::beast::basic_flat_buffer<std::allocator<char> >::mutable_buffers_type> boost::beast::detail::dynamic_buffer_prepare<boost::beast::basic_flat_buffer<std::allocator<char> >, boost::beast::websocket::error>(boost::beast::basic_flat_buffer<std::allocator<char> >&, unsigned long, boost::system::error_code&, boost::beast::websocket::error) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x3278635)
    #6 0x32711ee in boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::read_op<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::beast::basic_flat_buffer<std::allocator<char> > >::operator()(boost::system::error_code, unsigned long, bool) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x32711ee)
    #7 0x3262b2d in boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::read_op<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::beast::basic_flat_buffer<std::allocator<char> > >::read_op<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)> >(std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>&&, boost::shared_ptr<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::impl_type> const&, boost::beast::basic_flat_buffer<std::allocator<char> >&, unsigned long, bool) /home/arvid/dev/boost_1_72_0/boost/beast/websocket/impl/read.hpp:648
    #8 0x325a48c in void boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::run_read_op::operator()<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::beast::basic_flat_buffer<std::allocator<char> > >(std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>&&, boost::shared_ptr<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::impl_type> const&, boost::beast::basic_flat_buffer<std::allocator<char> >*, unsigned long, bool) (/home/arvid/dev/2/libtorrent/test/bin/test_tracker.test/gcc-9.2/debug-mode/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/export-extra-on/link-static/picker-debugging-on/threading-multi/webtorrent-on/test_tracker+0x325a48c)
    #9 0x324ee2b in void boost::asio::async_result<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, void (boost::system::error_code, unsigned long)>::initiate<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::run_read_op, std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, boost::shared_ptr<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::impl_type>&, boost::beast::basic_flat_buffer<std::allocator<char> >*, int, bool>(boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::run_read_op&&, std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>&&, boost::shared_ptr<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::impl_type>&, boost::beast::basic_flat_buffer<std::allocator<char> >*&&, int&&, bool&&) /home/arvid/dev/boost_1_72_0/boost/asio/async_result.hpp:151
    #10 0x323f292 in std::enable_if<boost::asio::detail::async_result_has_initiate_memfn<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, void (boost::system::error_code, unsigned long)>::value, decltype (boost::asio::async_result<std::decay<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)> >::type, void (boost::system::error_code, unsigned long)>::initiate((declval<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::run_read_op&&>)(), (declval<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>&&>)(), (declval<boost::shared_ptr<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::impl_type>&>)(), (declval<boost::beast::basic_flat_buffer<std::allocator<char> >*&&>)(), (declval<int&&>)(), (declval<bool&&>)()))>::type boost::asio::async_initiate<std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>, void (boost::system::error_code, unsigned long), boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::run_read_op, boost::shared_ptr<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::impl_type>&, boost::beast::basic_flat_buffer<std::allocator<char> >*, int, bool>(boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::run_read_op&&, std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>&, boost::shared_ptr<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::impl_type>&, boost::beast::basic_flat_buffer<std::allocator<char> >*&&, int&&, bool&&) /home/arvid/dev/boost_1_72_0/boost/asio/async_result.hpp:364
    #11 0x322e326 in auto boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::executor>, true>::async_read<boost::beast::basic_flat_buffer<std::allocator<char> >, std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)> >(boost::beast::basic_flat_buffer<std::allocator<char> >&, std::_Bind<void (libtorrent::aux::websocket_stream::*(std::shared_ptr<libtorrent::aux::websocket_stream>, std::_Placeholder<1>, std::_Placeholder<2>, std::function<void (boost::system::error_code const&, unsigned long)>))(boost::system::error_code, unsigned long, std::function<void (boost::system::error_code const&, unsigned long)>)>&&) /home/arvid/dev/boost_1_72_0/boost/beast/websocket/impl/read.hpp:817
    #12 0x322df9a in auto libtorrent::aux::websocket_stream::async_read<boost::beast::basic_flat_buffer<std::allocator<char> >, std::_Bind<void (libtorrent::aux::websocket_tracker_connection::*(libtorrent::aux::websocket_tracker_connection*, std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, std::_Placeholder<1>, std::_Placeholder<2>))(std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, boost::system::error_code, unsigned long)> >(boost::beast::basic_flat_buffer<std::allocator<char> >&, std::_Bind<void (libtorrent::aux::websocket_tracker_connection::*(libtorrent::aux::websocket_tracker_connection*, std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, std::_Placeholder<1>, std::_Placeholder<2>))(std::weak_ptr<libtorrent::aux::websocket_tracker_connection>, boost::system::error_code, unsigned long)>&&)::{lambda(auto:1&)#1}::operator()<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::beast::websocket::stream::ip::tcp, boost::beast::websocket::stream::executor>, true> >(boost::beast::basic_flat_buffer<std::allocator<char> >&) const ../include/libtorrent/aux_/websocket_stream.hpp:153
```

it looks like there's an async write operation that doesn't keep the `websocket_tracker_connection` object alive for the duration of the operation. When the session is closed, the last reference to the websocket tracker connection is removed even though the async write operation is still outstanding, and it explodes. If you're only capturing weak pointers, that would explain it.
comment
created
paullouisageneau
username_0
I have two issues to solve before the appveyor build is working:
- I need to pass the custom openSSL include path for the rule `openssl-include-path` to libdatachannel's Jamfile. What would be the clean way of achieving this?
- By any chance, do you know how to solve that error about `cl` not being found when running commands from  Jamfile `actions`: https://ci.appveyor.com/project/username_1/libtorrent/builds/33650308#L99
comment
created
arvidn
username_1
Good question. I think the *cleanest* way would be fore there to only be a single `openssl` target that both libtorrent and libdatachannel can link to. That makes it a bit difficult given the separation, and that they aren't necessarily always part of the same build tree. Maybe there's a way to conditionally define the `openssl` target in case it doesn't already exist.

beast does t[his](https://github.com/boostorg/beast/blob/develop/tools/user-config.jam) in `user-config.jam`.

It would probably be best if an `ssl` target could be defined in `user-config.jam`, similar to how `using qt ;` and `using python ;` are put in there. I'll look into this, but that's probably a longer term solution.

As a quick fix, I think it would work if you would copy this into your `Jamfile`:

```
# the search path to pick up the openssl libraries from. This is the <search>
# property of those libraries
rule openssl-lib-path ( properties * )
{
    local OPENSSL_LIB = [ feature.get-values <openssl-lib> : $(properties) ] ;

    if <target-os>darwin in $(properties) && $(OPENSSL_LIB) = ""
    {
        # on macOS, default to pick up openssl from the homebrew installation
        # brew install openssl
        OPENSSL_LIB = /usr/local/opt/openssl/lib ;
    }
    else if <target-os>windows in $(properties) && $(OPENSSL_LIB) = ""
    {
        # on windows, assume openssl is installed to c:\OpenSSL-Win32
        if <address-model>64 in $(properties)
        { OPENSSL_LIB = c:\\OpenSSL-Win64\\lib ; }
        else
        { OPENSSL_LIB = c:\\OpenSSL-Win32\\lib ; }
    }

    local result ;
    result += <search>$(OPENSSL_LIB) ;
    return $(result) ;
}

# the include path to pick up openssl headers from. This is the
# usage-requirement for the openssl-related libraries
rule openssl-include-path ( properties * )
{
    local OPENSSL_INCLUDE = [ feature.get-values <openssl-include> : $(properties) ] ;

    if <target-os>darwin in $(properties) && $(OPENSSL_INCLUDE) = ""
    {
        # on macOS, default to pick up openssl from the homebrew installation
        # brew install openssl
        OPENSSL_INCLUDE = /usr/local/opt/openssl/include ;
    }
    else if <target-os>windows in $(properties) && $(OPENSSL_INCLUDE) = ""
    {
        # on windows, assume openssl is installed to c:\OpenSSL-Win32
        if <address-model>64 in $(properties)
        { OPENSSL_INCLUDE = c:\\OpenSSL-Win64\\include ; }
        else
        { OPENSSL_INCLUDE = c:\\OpenSSL-Win32\\include ; }
    }

    local result ;
    result += <include>$(OPENSSL_INCLUDE) ;
    return $(result) ;
}

lib z : : <link>shared <name>z ;
# openssl libraries on windows
alias ssl-deps : advapi32 user32 shell32 gdi32 ;

# pre OpenSSL 1.1 windows
lib crypto : ssl-deps : <target-os>windows <openssl-version>pre1.1 <name>libeay32
    <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;
lib ssl : ssl-deps : <target-os>windows <openssl-version>pre1.1 <name>ssleay32
    <use>crypto <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;

# OpenSSL 1.1+ windows
lib crypto : ssl-deps : <toolset>msvc <openssl-version>1.1 <name>libcrypto
    <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;
lib ssl : ssl-deps : <toolset>msvc <openssl-version>1.1 <name>libssl <use>crypto
    <conditional>@openssl-lib-path : : <conditional>@openssl-include-path ;

# generic OpenSSL
lib crypto : : <name>crypto <use>z <conditional>@openssl-lib-path : :
    <conditional>@openssl-include-path ;
lib ssl : : <name>ssl <use>crypto <conditional>@openssl-lib-path : :
    <conditional>@openssl-include-path ;
```

and add:

```
    <library>ssl
    <library>crypto
```

the the "requirements" of `libdatachannel.
comment
created
arvidn
username_1
Perhaps the shell isn't a "visual studio"-shell. Perhaps the `"Visual Studio 16 2019"` generator will work. That's the one used by the libtorrent appveyor script.
comment
created
arvidn
username_1
this [winsock.h problem](https://ci.appveyor.com/project/username_1/libtorrent/builds/33660992#L198) is a classic. Basically, if the old (as in early 90's) `winsock.h` header is included in a translation unit, there is no way to then include the (modern) winsock 2 headers.

Wouldn't expect anything to include `winsock.h` directly, but I believe it's controlled by the version of windows one is targeting, which (I imagine) defaults to a very old version.

Try defining `_WIN32_WINNT=0x0A00` as part of the build, I think that might fix it.

In libtorrent I even created a Jamfile build feature `windows-version` to set these.

If this used to work, but broke when changing the CMake generator, it could be something else.
comment
created
paullouisageneau
username_0
Yeah I already ran into similar issues and it's kind of a pain. I already define `_WIN32_WINNT=0x0602` if undefined, I think the culprit here is OpenSSL which includes `winsock.h`. Including `winsock2.h` before it should do the trick.
comment
created
paullouisageneau
username_0
@username_1 The appveyor build is nearly working, the last blocking point is the OpenSSL version, as libdatachannel requires version 1.1.0+ whereas the available version is 1.0.2u.
comment
created
arvidn
username_1
regarding [this](https://travis-ci.org/github/username_1/libtorrent/jobs/700951774#L1110).

```
make: *** No rule to make target `usrsctplib-static'.  Stop.
../../deps/libdatachannel/bin/libusrsctp.a
```

As far as I can tell, the `usrsctplib-static` target is disabled by default, and you need to enable the option `sctp_link_programs_static` when generating the makefiles.
comment
created
paullouisageneau
username_0
It's actually a typo, the target name is `usrsctp-static`...
`sctp_link_programs_static` only controls the linking of examples.
comment
created
paullouisageneau
username_0
OK, it seems everything builds and tests run properly now. I changed plog to a fork for now to prevent the invalid `static_cast` issue. I'll just clean up the history, it's a bit of a mess after that epic Windows compilation fight.
comment
created
arvidn
username_1
I just tested `client_test` and could download from WebTorrent peers. Is there a test torrent that *only* has WebTorrent peers I could test with?

The unit tests all pass with sanitizers now. However, `client_test` reported these two leaks:

```
Direct leak of 24320 byte(s) in 380 object(s) allocated from:                                                                                                                                                                                                                   #0 0x7f12951e0bc8 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)                                                                                                                                                                                               #1 0x7f12942f9be9  (/lib/x86_64-linux-gnu/libc.so.6+0x106be9)
    #2 0x7f12942fbf48 in getaddrinfo (/lib/x86_64-linux-gnu/libc.so.6+0x108f48)
    #3 0x7f129518b7c2  (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xb87c2)                                                                                                                                                                                                         #4 0x2c20855 in rtc::Candidate::resolve(rtc::Candidate::ResolveMode) ../deps/libdatachannel/src/candidate.cpp:95
    #5 0x2b0c133 in rtc::PeerConnection::addRemoteCandidate(rtc::Candidate) ../deps/libdatachannel/src/peerconnection.cpp:144                                                                                                                                                   #6 0x2b0b792 in rtc::PeerConnection::setRemoteDescription(rtc::Description) ../deps/libdatachannel/src/peerconnection.cpp:135                                                                                                                                               #7 0x1714ec9 in libtorrent::aux::rtc_signaling::process_offer(libtorrent::aux::rtc_offer const&) ../src/rtc_signaling.cpp:235
    #8 0xf72f84 in libtorrent::torrent::on_rtc_offer(libtorrent::aux::rtc_offer const&) ../src/torrent.cpp:5829
    #9 0x17b171d in libtorrent::aux::websocket_tracker_connection::on_read(boost::system::error_code, unsigned long) ../src/websocket_tracker_connection.cpp:371
    #10 0x191adad in void std::__invoke_impl<void, void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long>(std::__invoke_memfun_deref, void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long&&) /usr/local/include/c++/9.2.0/bits/invoke.h:73
    #11 0x190c79d in std::__invoke_result<void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long>::type std::__invoke<void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long>(void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long&&) (/home/arvid/dev/libtorrent/examples/bin/gcc-9.2/debug/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/link-static/threading-multi/undefined-sanitizer-norecover/webtorrent-on/client_test+0x190c79d)
    #12 0x18e67d2 in void std::_Bind<void (libtorrent::aux::websocket_tracker_connection::*(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>, std::_Placeholder<1>, std::_Placeholder<2>))(boost::system::error_code, unsigned long)>::__call<void, boost::system::error_code const&, unsigned long&&, 0ul, 1ul, 2ul>(std::tuple<boost::system::error_code const&, unsigned long&&>&&, std::_Index_tuple<0ul, 1ul, 2ul>) (/home/arvid/dev/libtorrent/examples/bin/gcc-9.2/debug/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/link-static/threading-multi/undefined-sanitizer-norecover/webtorrent-on/client_test+0x18e67d2)
    #13 0x18d3653 in void std::_Bind<void (libtorrent::aux::websocket_tracker_connection::*(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>, std::_Placeholder<1>, std::_Placeholder<2>))(boost::system::error_code, unsigned long)>::operator()<boost::system::error_code const&, unsigned long, void>(boost::system::error_code const&, unsigned long&&) (/home/arvid/dev/libtorrent/examples/bin/gcc-9.2/debug/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/link-static/threading-multi/undefined-sanitizer-norecover/webtorrent-on/client_test+0x18d3653)
    #14 0x18b9f66 in std::_Function_handler<void (boost::system::error_code const&, unsigned long), std::_Bind<void (libtorrent::aux::websocket_tracker_connection::*(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>, std::_Placeholder<1>, std::_Placeholder<2>))(boost::system::error_code, unsigned long)> >::_M_invoke(std::_Any_data const&, boost::system::error_code const&, unsigned long&&) (/home/arvid/dev/libtorrent/examples/bin/gcc-9.2/debug/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/link-static/threading-multi/undefined-sanitizer-norecover/webtorrent-on/client_test+0x18b9f66)
    #15 0x15ca5fd in std::function<void (boost::system::error_code const&, unsigned long)>::operator()(boost::system::error_code const&, unsigned long) const /usr/local/include/c++/9.2.0/bits/std_function.h:690
    #16 0x15ca2a6 in void std::__invoke_impl<void, std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&>(std::__invoke_other, std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&) /usr/local/include/c++/9.2.0/bits/invoke.h:60
    #17 0x15ca02d in std::__invoke_result<std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&>::type std::__invoke<std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&>(std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&) /usr/local/include/c++/9.2.0/bits/invoke.h:95
    #18 0x17a020e in void std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>::__call<void, , 0ul, 1ul>(std::tuple<>&&, std::_Index_tuple<0ul, 1ul>) /usr/local/include/c++/9.2.0/functional:400
    #19 0x179f692 in void std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>::operator()<, void>() /usr/local/include/c++/9.2.0/functional:484
    #20 0x179f2f7 in void boost::asio::asio_handler_invoke<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >(std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>&, ...) /home/arvid/dev/boost_1_72_0/boost/asio/handler_invoke_hook.hpp:69
    #21 0x179f03f in void boost_asio_handler_invoke_helpers::invoke<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>, std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >(std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>&, std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>&) /home/arvid/dev/boost_1_72_0/boost/asio/detail/handler_invoke_helpers.hpp:37
    #22 0x179ee9c in void boost::asio::system_executor::dispatch<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>, std::allocator<void> >(std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>&&, std::allocator<void> const&) const /home/arvid/dev/boost_1_72_0/boost/asio/impl/system_executor.hpp:39                                                                                                #23 0x179e7e3 in boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >::operator()() /home/arvid/dev/boost_1_72_0/boost/asio/detail/work_dispatcher.hpp:59
    #24 0x179d895 in void boost::asio::asio_handler_invoke<boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> > >(boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >&, ...) /home/arvid/dev/boost_1_72_0/boost/asio/handler_invoke_hook.hpp:69
    #25 0x179c74b in void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >, boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> > >(boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >&, boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >&) /home/arvid/dev/boost_1_72_0/boost/asio/detail/handler_invoke_helpers.hpp:37 
    #26 0x179a0ef in boost::asio::detail::executor_op<boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >, std::allocator<void>, boost::asio::detail::scheduler_operation>::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /home/arvid/dev/boost_1_72_0/boost/asio/detail/executor_op.hpp:70
    #27 0x80aba4 in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /home/arvid/dev/boost_1_72_0/boost/asio/detail/scheduler_operation.hpp:40
    #28 0x816f0c in boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /home/arvid/dev/boost_1_72_0/boost/asio/detail/impl/scheduler.ipp:447
    #29 0x815d85 in boost::asio::detail::scheduler::run(boost::system::error_code&) /home/arvid/dev/boost_1_72_0/boost/asio/detail/impl/scheduler.ipp:200

Direct leak of 832 byte(s) in 13 object(s) allocated from:
    #0 0x7f12951e0bc8 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #1 0x7f12942f9be9  (/lib/x86_64-linux-gnu/libc.so.6+0x106be9)
    #2 0x7f12942fbf48 in getaddrinfo (/lib/x86_64-linux-gnu/libc.so.6+0x108f48)
    #3 0x7f129518b7c2  (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xb87c2)
    #4 0x2c20855 in rtc::Candidate::resolve(rtc::Candidate::ResolveMode) ../deps/libdatachannel/src/candidate.cpp:95
    #5 0x2b0c133 in rtc::PeerConnection::addRemoteCandidate(rtc::Candidate) ../deps/libdatachannel/src/peerconnection.cpp:144
    #6 0x2b0b792 in rtc::PeerConnection::setRemoteDescription(rtc::Description) ../deps/libdatachannel/src/peerconnection.cpp:135
    #7 0x1715afe in libtorrent::aux::rtc_signaling::process_answer(libtorrent::aux::rtc_answer const&) ../src/rtc_signaling.cpp:265
    #8 0xf730b4 in libtorrent::torrent::on_rtc_answer(libtorrent::aux::rtc_answer const&) ../src/torrent.cpp:5835
    #9 0x17b18ed in libtorrent::aux::websocket_tracker_connection::on_read(boost::system::error_code, unsigned long) ../src/websocket_tracker_connection.cpp:376
    #10 0x191adad in void std::__invoke_impl<void, void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long>(std::__invoke_memfun_deref, void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long&&) /usr/local/include/c++/9.2.0/bits/invoke.h:73
    #11 0x190c79d in std::__invoke_result<void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long>::type std::__invoke<void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long>(void (libtorrent::aux::websocket_tracker_connection::*&)(boost::system::error_code, unsigned long), std::shared_ptr<libtorrent::aux::websocket_tracker_connection>&, boost::system::error_code const&, unsigned long&&) (/home/arvid/dev/libtorrent/examples/bin/gcc-9.2/debug/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/link-static/threading-multi/undefined-sanitizer-norecover/webtorrent-on/client_test+0x190c79d)
    #12 0x18e67d2 in void std::_Bind<void (libtorrent::aux::websocket_tracker_connection::*(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>, std::_Placeholder<1>, std::_Placeholder<2>))(boost::system::error_code, unsigned long)>::__call<void, boost::system::error_code const&, unsigned long&&, 0ul, 1ul, 2ul>(std::tuple<boost::system::error_code const&, unsigned long&&>&&, std::_Index_tuple<0ul, 1ul, 2ul>) (/home/arvid/dev/libtorrent/examples/bin/gcc-9.2/debug/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/link-static/threading-multi/undefined-sanitizer-norecover/webtorrent-on/client_test+0x18e67d2)
    #13 0x18d3653 in void std::_Bind<void (libtorrent::aux::websocket_tracker_connection::*(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>, std::_Placeholder<1>, std::_Placeholder<2>))(boost::system::error_code, unsigned long)>::operator()<boost::system::error_code const&, unsigned long, void>(boost::system::error_code const&, unsigned long&&) (/home/arvid/dev/libtorrent/examples/bin/gcc-9.2/debug/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/link-static/threading-multi/undefined-sanitizer-norecover/webtorrent-on/client_test+0x18d3653)
    #14 0x18b9f66 in std::_Function_handler<void (boost::system::error_code const&, unsigned long), std::_Bind<void (libtorrent::aux::websocket_tracker_connection::*(std::shared_ptr<libtorrent::aux::websocket_tracker_connection>, std::_Placeholder<1>, std::_Placeholder<2>))(boost::system::error_code, unsigned long)> >::_M_invoke(std::_Any_data const&, boost::system::error_code const&, unsigned long&&) (/home/arvid/dev/libtorrent/examples/bin/gcc-9.2/debug/address-sanitizer-norecover/crypto-openssl/cxxstd-17-iso/link-static/threading-multi/undefined-sanitizer-norecover/webtorrent-on/client_test+0x18b9f66)
    #15 0x15ca5fd in std::function<void (boost::system::error_code const&, unsigned long)>::operator()(boost::system::error_code const&, unsigned long) const /usr/local/include/c++/9.2.0/bits/std_function.h:690
    #16 0x15ca2a6 in void std::__invoke_impl<void, std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&>(std::__invoke_other, std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&) /usr/local/include/c++/9.2.0/bits/invoke.h:60
    #17 0x15ca02d in std::__invoke_result<std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&>::type std::__invoke<std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&>(std::function<void (boost::system::error_code const&, unsigned long)>&, boost::system::error_code&, unsigned long&) /usr/local/include/c++/9.2.0/bits/invoke.h:95
    #18 0x17a020e in void std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>::__call<void, , 0ul, 1ul>(std::tuple<>&&, std::_Index_tuple<0ul, 1ul>) /usr/local/include/c++/9.2.0/functional:400
    #19 0x179f692 in void std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>::operator()<, void>() /usr/local/include/c++/9.2.0/functional:484                                                        #20 0x179f2f7 in void boost::asio::asio_handler_invoke<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >(std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>&, ...) /home/arvid/dev/boost_1_72_0/boost/asio/handler_invoke_hook.hpp:69
    #21 0x179f03f in void boost_asio_handler_invoke_helpers::invoke<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>, std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >(std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>&, std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>&) /home/arvid/dev/boost_1_72_0/boost/asio/detail/handler_invoke_helpers.hpp:37
    #22 0x179ee9c in void boost::asio::system_executor::dispatch<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>, std::allocator<void> >(std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)>&&, std::allocator<void> const&) const /home/arvid/dev/boost_1_72_0/boost/asio/impl/system_executor.hpp:39
    #23 0x179e7e3 in boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >::operator()() /home/arvid/dev/boost_1_72_0/boost/asio/detail/work_dispatcher.hpp:59
    #24 0x179d895 in void boost::asio::asio_handler_invoke<boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> > >(boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >&, ...) /home/arvid/dev/boost_1_72_0/boost/asio/handler_invoke_hook.hpp:69
    #25 0x179c74b in void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >, boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> > >(boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >&, boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >&) /home/arvid/dev/boost_1_72_0/boost/asio/detail/handler_invoke_helpers.hpp:37 
    #26 0x179a0ef in boost::asio::detail::executor_op<boost::asio::detail::work_dispatcher<std::_Bind<std::function<void (boost::system::error_code const&, unsigned long)> (boost::system::error_code, unsigned long)> >, std::allocator<void>, boost::asio::detail::scheduler_operation>::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /home/arvid/dev/boost_1_72_0/boost/asio/detail/executor_op.hpp:70
    #27 0x80aba4 in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /home/arvid/dev/boost_1_72_0/boost/asio/detail/scheduler_operation.hpp:40
    #28 0x816f0c in boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /home/arvid/dev/boost_1_72_0/boost/asio/detail/impl/scheduler.ipp:447
    #29 0x815d85 in boost::asio::detail::scheduler::run(boost::system::error_code&) /home/arvid/dev/boost_1_72_0/boost/asio/detail/impl/scheduler.ipp:200

SUMMARY: AddressSanitizer: 25152 byte(s) leaked in 393 allocation(s).
```
comment
created
arvidn
username_1
actually, `test_rtc.cpp.signaling_connectivity` just failed for me (on ubuntu) and also reported those same two leaks (but fewer allocations each).

This was the output:

```
Signaling 1: Generating 1 offer
Signaling 1: Generated 1 offer(s)
Signaling 2: Processing the offer
Signaling 2: Generated an answer
Signaling 1: Processing the answer
Test timed out after 30 seconds

***** test_rtc.cpp:93 "TEST_ERROR: check failed: "success == true"" *****
```
comment
created
arvidn
username_1
in `Candidate::resolve()` it looks like you have an early exit from the function where you don't call `freeaddrinfo()`. It almost looks like the first stack trace points to the same issue, but inlined.
comment
created
paullouisageneau
username_0
Yes that's the issue... I'm fixing it.

On the other hand, the signaling connectivity test failure on your Ubuntu is surprising. So what's happening is that `client_test` can connect to webtorrent peers but the test still fail on the same platform?
comment
created
paullouisageneau
username_0
Actually I don't have such a torrent, even when removing the non-websocket trackers it ends up picking up traditional peers (by PEX or DHT), so to test I basically disable everything and block the UDP port.
comment
created
paullouisageneau
username_0
It seems good to me now but there seem to be random failures of `test_transfer` on appveyor, is that normal?
https://ci.appveyor.com/project/username_1/libtorrent/builds/33758259/job/88ee7aj69wlg3p7b?fullLog=true#L2569
comment
created
arvidn
username_1
the appveyor failure seems to have started happening lately, unrelated this patch
comment
created
arvidn
username_1
unfortunately, I'm still seeing this on ubuntu. Do you have any pointers of where to look?

```
[test_rtc.cpp.signaling_connectivity]

Signaling 1: Generating 1 offer
Signaling 1: Generated 1 offer(s)
Signaling 2: Processing the offer
Signaling 2: Generated an answer
Signaling 1: Processing the answer
Test timed out after 30 seconds

***** test_rtc.cpp:93 "TEST_ERROR: check failed: "success == true"" *****
```
comment
created
paullouisageneau
username_0
@username_1 This is rather strange. You can set `DEBUG_RTC` to 1 here https://github.com/username_0/libtorrent/blob/webtorrent/src/rtc_signaling.cpp#L57 to have the library's log passed as session alerts.

However, this is probably an issue with libdatachannel which can't connect locally for some reason. You could try to build it and run the tests since the connectivity test is basically equivalent while simpler to debug.
comment
created
arvidn
username_1
`./tests` in `libdatachannels` work (after building with `cmake`). Although, `ctest` didn't find any tests.
comment
created
paullouisageneau
username_0
Did you try when building with `cmake -DUSE_JUICE=1` to reflect the build configuration used here?
comment
created
arvidn
username_1
yeah, I had to build with with JUICE, nice didn't work (I think it expects me to have installed that package). I was thinking that maybe it had something to do with building against openssl instead of gnutls, so I tried building and running the libtorrent tests with `crypto=gnutls` but that's failing to link now :(

It works if I don't enable webtorrent, but with `webtorrent=on` and `crypto=gnutls` I get this:

```
/usr/bin/ld: ../bin/gcc-9.2/debug/crypto-gnutls/cxxstd-17-iso/export-extra-on/picker-debugging-on/threading-multi/webtorrent-on/libtorrent.so.2.0.0: undefined reference to `EVP_sha1'
/usr/bin/ld: ../bin/gcc-9.2/debug/crypto-gnutls/cxxstd-17-iso/export-extra-on/picker-debugging-on/threading-multi/webtorrent-on/libtorrent.so.2.0.0: undefined reference to `HMAC'
```

Which are openssl symbols, as far as I can tell.
comment
created
paullouisageneau
username_0
I think this happened because the libjuice build with openssl was cached (I was thinking the `juice` alias in Jamfile depending on the `gnutls` option would prevent this though), if you cleanup the bin folder it should work.
comment
created
arvidn
username_1
hm. I'm still getting:

```
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libgnutls.a(pkcs11.o): undefined reference to symbol 'p11_kit_modules_load_and_initialize@@LIBP11_KIT_1.0'
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libp11-kit.so.0: error adding symbols: DSO missing from command line
```

maybe I failed in cleaning all the repos
comment
created
arvidn
username_1
though, it looks like a dependency on `libp11-kit` is missing from the `Jamfile` somewhere. Maybe because it's linking statically against `libgnutls` (which seems a bit surprising). I imagine GnuTLS has a dependency on p11-kit, which then gets exposed when linking statically against it.
comment
created
paullouisageneau
username_0
Yes that explains it, but shouldn't `lib gnutls : : <link>shared <name>gnutls` in the Jamfile result in dynamic linking?
comment
created
arvidn
username_1
I'll look into it. I think that might mean that his specific target won't be used if the build is using `link=static`. Typically the way to declare a dependency that must always be linked shared `gnutls//<link>shared`. That would be how the dependency would be declared on the libtorrent target though.
comment
created
arvidn
username_1
I think you should add `/<link>shared` to the end of `<library>gnutls` on line 85 in `Jamfile`. That fixes the gnutls build with `link=static` for me.
comment
created
arvidn
username_1
however, `test_rtc` only seem to fail when I link the whole program statically. i.e.
```
b2 link=static crypto=openssl webtorrent=on test_rtc
```

Whether I use `openssl` or `gnutls` does not matter.
comment
created
paullouisageneau
username_0
OK thank you for the investigation, I'll try to reproduce the issue and investigate it :+1:
comment
created
arvidn
username_1
works!
I'll do one last pass over what's changed since my last review, then I think we're ready to squashing into tidier commits
comment
created
arvidn
username_1
oh, I missed that I still had my local change to the `Jamfile` to always link against `gnutls` as shared library. I think you'd need to apply that too
comment
created
paullouisageneau
username_0
I pushed the change in libdatachannel itself but forgot to do so in libtorrent!
comment
created
arvidn
username_1
it looks like the default should be 2 minutes, is it different in the tests? https://github.com/username_1/libtorrent/pull/4123/files#diff-8e5f23e1a44ba74e70cdc5067a511ec3R367
comment
created
paullouisageneau
username_0
In the tests it can be way shorter since it connects locally. If the local connection has not happened after a few seconds something is definitely broken.
comment
created
arvidn
username_1
I don't see any place where `settings_pack::webtorrent_connection_timeout` is set to 0..
comment
created
paullouisageneau
username_0
The test is using `session_mock`, which doesn't set the settings.
comment
created
arvidn
username_1
the default constructor of `aux::session_settings` is supposed to default construct `session_settings_single_thread` (which is a member). It, in turn, calls `initialize_default_settings()` on itself.
comment
created
paullouisageneau
username_0
Oh, I didn't know that... Then what could have been wrong? Order of initialization maybe?
comment
created
arvidn
username_1
the problem is that the `session_mock` instances (`ses1` and `ses2`) are global variables, and they are initialized before the default settings are initialized
comment
created
arvidn
username_1
the initialization order is not defined, so linking differently changes the initialization order of the globals
comment
created
arvidn
username_1
I'll need to fix this so the default settings are statically initialized. I'll do that in `RC_2_0`, but I shouldn't merge that into `master` until after this lands, as it might cause conflicts.

So, you could either apply the patch here (just leave it as a separate commit and it should merge cleanly later) or you can make the `session_mock` objects local variables, rather than global.

This is the change that fixes the initialization order:

```
diff --git a/include/libtorrent/aux_/container_wrapper.hpp b/include/libtorrent/aux_/container_wrapper.hpp
index 314a01fff..844f70918 100644
--- a/include/libtorrent/aux_/container_wrapper.hpp
+++ b/include/libtorrent/aux_/container_wrapper.hpp
@@ -51,7 +51,7 @@ namespace libtorrent { namespace aux {
                // pull in constructors from Base class
                using Base::Base;
                container_wrapper() = default;
-               explicit container_wrapper(Base&& b) noexcept : Base(std::move(b)) {}
+               constexpr explicit container_wrapper(Base&& b) noexcept : Base(std::move(b)) {}
 
                explicit container_wrapper(IndexType const s)
                        : Base(numeric_cast<std::size_t>(static_cast<underlying_index>(s))) {}
diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp
index cddb22a8f..b06de6557 100644
--- a/src/settings_pack.cpp
+++ b/src/settings_pack.cpp
@@ -110,7 +110,7 @@ namespace libtorrent {
 
        using aux::session_impl;
 
-       aux::array<str_setting_entry_t, settings_pack::num_string_settings> const str_settings
+       constexpr aux::array<str_setting_entry_t, settings_pack::num_string_settings> const str_settings
        ({{
                SET(user_agent, "libtorrent/" LIBTORRENT_VERSION, &session_impl::update_user_agent),
                SET(announce_ip, nullptr, nullptr),
@@ -127,7 +127,7 @@ namespace libtorrent {
                SET(webtorrent_stun_server, "stun.l.google.com:19302", nullptr)
        }});
 
-       aux::array<bool_setting_entry_t, settings_pack::num_bool_settings> const bool_settings
+       constexpr aux::array<bool_setting_entry_t, settings_pack::num_bool_settings> const bool_settings
        ({{
                SET(allow_multiple_connections_per_ip, false, nullptr),
                DEPRECATED_SET(ignore_limits_on_local_network, true, &session_impl::update_ignore_rate_limits_on_local_network),
@@ -211,7 +211,7 @@ namespace libtorrent {
                SET(validate_https_trackers, false, &session_impl::update_validate_https),
        }});
 
-       aux::array<int_setting_entry_t, settings_pack::num_int_settings> const int_settings
+       constexpr aux::array<int_setting_entry_t, settings_pack::num_int_settings> const int_settings
        ({{
                SET(tracker_completion_timeout, 30, nullptr),
                SET(tracker_receive_timeout, 10, nullptr),
```
comment
created
arvidn
username_1
the `constexpr` [patch](https://github.com/username_1/libtorrent/pull/4811) is failing on msvc, so maybe it's not quite as simple as I thought.
comment
created
arvidn
username_1
I suppose this patch isn't really affected by it since you already worked around it by clamping the timeout to 1
comment
created
paullouisageneau
username_0
@username_1 Don't worry about it, I simply made the variables local, it should be good.
comment
created
arvidn
username_1
https://travis-ci.org/github/username_1/libtorrent/jobs/703487055#L1555
comment
created
paullouisageneau
username_0
Fixed!
comment
created
paullouisageneau
username_0
I squashed the entire PR into a dozen of commits.
comment
created
arvidn
username_1
@username_0 once appveyor is green, is this ready to land?
comment
created
paullouisageneau
username_0
@username_1 I just updated libdatachannel to include a fix in the generation of answers. Otherwise it looks good to me, you can merge it when it's ready :tada:
comment
created
arvidn
username_1
@username_0 Really great work! thanks for your patience!
comment
created
paullouisageneau
username_0
Yeah, thank you! :partying_face:
comment
created
alxhotel
username_9
I think everyone here is super excited for this PR.

Brilliant work @username_0 !! 

And great review @username_1 :)
comment
created
subins2000
username_10
Yes, very excited to see this finally merged. Been following this MR for a while. Thank you @username_0 & @username_1 <3
comment
created
leoherzog
username_3
Agreed, very exciting. So am I understanding that the plan is to include this in a future release after 2.0 launches, @username_1?
comment
created
arvidn
username_1
that's right. it will be in the next major release after 2.0 (which itself hasn't been released just yet).
comment
created
vijayanandnandam
username_4
finally, my watch has ended 😂  Thanks for this feature 👍
comment
created
MasterOfTheTiger
username_2
Awesome! I have been constantly watching this in preparation for my own program that I want to support WebTorrent. Thanks for your hard work!
comment
created
ZenoArrow
username_11
Thanks for all your work on this @username_0 (and thanks to @username_1 for your code review work and @username_6 for the testing you did). Like others, I've been watching this pull request develop for a while and I'm glad to see all the work pay off. Personally, I'm interested in the potential impact this has on a project I'm following (PeerTube uses WebTorrents as a core component of its distributed video sharing platform, and I'm confident libtorrent could help with making the server implementation more efficient), but I'm sure there are plenty of other benefits that will emerge.
comment
created
feross
username_12
This is incredible. Thank you for all the work on this, @username_0. ❤️
comment
created
leoherzog
username_3
If we wanted to [compile](https://github.com/username_1/libtorrent/blob/RC_1_2/docs/building.rst#building-with-cmake) from `master` to have WebTorrent support now, how to we do that? Something like `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=11 webtorrent=on -G Ninja ..`?
comment
created
aldenml
username_13
@username_3  in `master` you need c++17, it should be something like
`-DCMAKE_CXX_STANDARD=17 -Dwebtorrent=ON -DUSE_JUICE=ON`
comment
created
paullouisageneau
username_0
@username_13 You're right, and you can actually omit `-DUSE_JUICE=ON`, it'll be set by default.
comment
created
leoherzog
username_3
So, I ran
```shell
git clone https://github.com/username_1/libtorrent
cd libtorrent
mkdir build
cd build
cmake -DCMAKE_CXX_STANDARD=17 -Dwebtorrent=ON -DUSE_JUICE=ON -python-bindings=ON -G Ninja ..
ninja
```
and I'm getting failures when building. Am I missing something?
comment
created
paullouisageneau
username_0
Actually, the proper commands would be:
```
git clone https://github.com/username_1/libtorrent
cd libtorrent
git checkout master
git submodule update --init
mkdir build
cd build
cmake -DCMAKE_CXX_STANDARD=17 -Dwebtorrent=ON -python-bindings=ON -G Ninja ..
ninja
```
What failures are you experiencing exactly?
comment
created
alexeyvolkoff
username_14
Hi guys,
I got issue with compiling:

Scanning dependencies of target datachannel-static
[ 17%] Building CXX object deps/libdatachannel/CMakeFiles/datachannel-static.dir/src/candidate.cpp.o
[ 17%] Building CXX object deps/libdatachannel/CMakeFiles/datachannel-static.dir/src/certificate.cpp.o
/home/volkoff/Projects/sandbox/libtorrent/deps/libdatachannel/src/certificate.cpp: В функции «rtc::certificate_ptr rtc::{anonymous}::make_certificate_impl(std::__cxx11::string)»:
/home/volkoff/Projects/sandbox/libtorrent/deps/libdatachannel/src/certificate.cpp:205:23: ошибка: нет декларации «**X509_getm_notBefore**» в этой области видимости
  if (!X509_gmtime_adj(X509_getm_notBefore(x509.get()), 3600 * -1) ||
                       ^~~~~~~~~~~~~~~~~~~
/home/volkoff/Projects/sandbox/libtorrent/deps/libdatachannel/src/certificate.cpp:205:23: замечание: предлагаемый вариант: «**X509_get_notBefore**»
  if (!X509_gmtime_adj(X509_getm_notBefore(x509.get()), 3600 * -1) ||
                       ^~~~~~~~~~~~~~~~~~~
                       X509_get_notBefore
/home/volkoff/Projects/sandbox/libtorrent/deps/libdatachannel/src/certificate.cpp:206:23: ошибка: нет декларации «X509_getm_notAfter» в этой области видимости
      !X509_gmtime_adj(X509_getm_notAfter(x509.get()), 3600 * 24 * 365) ||
                       ^~~~~~~~~~~~~~~~~~
/home/volkoff/Projects/sandbox/libtorrent/deps/libdatachannel/src/certificate.cpp:206:23: замечание: предлагаемый вариант: «X509_get_notAfter»
      !X509_gmtime_adj(X509_getm_notAfter(x509.get()), 3600 * 24 * 365) ||
                       ^~~~~~~~~~~~~~~~~~


My openssl version is 1.1.1d
comment
created
paullouisageneau
username_0
@username_14 Could you check you are indeed compiling with OpenSSL 1.1.1d? `X509_getm_notBefore` should be present and ` X509_get_notBefore` should actually be deprecated in favor of `X509_getm_notBefore`.
comment
created
alexeyvolkoff
username_14
Yes. I had a mix of openssl 1.0 and 1.1. Removed package compat-openssl10 and reinstalled openssl-devel (Fedora)

No boost is making trubles:
«make_address_v6(std::string_view&, libtorrent::error_code&)»
    ret.address(make_address_v6(addr, ec));
                                        ^
In file included from /usr/include/boost/asio/ip/address_v6.hpp:335,
                 from /usr/include/boost/asio/ip/address.hpp:25,
                 from /usr/include/boost/asio/ip/basic_endpoint.hpp:19,
                 from /usr/include/boost/asio/ip/tcp.hpp:24,
                 from /home/volkoff/Projects/sandbox/libtorrent/include/libtorrent/socket.hpp:56,
                 from /home/volkoff/Projects/sandbox/libtorrent/src/socket_io.cpp:37:
/usr/include/boost/asio/ip/impl/address_v6.ipp:337:12: замечание: candidate: «boost::asio::ip::address_v6 boost::asio::ip::make_address_v6(boost::asio::ip::v4_mapped_t, const boost::asio::ip::address_v4&)»
 address_v6 make_address_v6(

which bersion should I have?
comment
created
arvidn
username_1
@username_14 1.72 should work, but probably 1.71 and 1.70 as well, I would imagine. But I'm curious what the error message is. That particular function has been in boost since 1.66 ( https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/ip__address_v6/make_address_v6.html )
comment
created
alexeyvolkoff
username_14
@username_1 
The message is  "no candidate to call «make_address_v4(std::string_view&, libtorrent::error_code&)»
    ret.address(make_address_v4(addr, ec));

My boost is
Name         : boost-devel
Version      : 1.66.0
comment
created
alexeyvolkoff
username_14
btw guys @username_1 & @username_0, is there any example how to create a webtorrent seed with the custom ICE  configuration (STUN and TURN servers)?
Basically I want to replace Node.js  webtorrent-hybrid app with the tons of dependencies on my embedded device.
comment
created
paullouisageneau
username_0
The STUN server is a setting of the client, it can be set with the setting `webtorrent_stun_server`, by default it's `stun.l.google.com:19302`. TURN servers are not supported for now, as it's way more efficient to add a web seed rather then having peers connecting through a centralized server.

The only thing you need to add to create a webtorrent-enabled seed is a websocket tracker.
comment
created
alexeyvolkoff
username_14
@username_0 I didn't succeed to get webtorrent  working reliably without TURN server. It may work in my operator's network and in some operators in neighbor countries,  but does not work in another operator or even in my operator's mobile network. Did you guys face such issues?
comment
created
alexeyvolkoff
username_14
Something is not working. I have created a torrent with wss://tracker.openwebtorrent.com and started the client.
When I add magned link to Instant.io I get a bunch of errors  in clonsole log (with debug enabled)


bittorrent-tracker:websocket-tracker send {"numwant":10,"uploaded":0,"downloaded":0,"left":null,"event":"started","action":"announce","info_hash":". I**fM#àù\rï¤ÏÓ{û","peer_id":"-WW0008-HAralb/CAORi",**"offers":[{"offer":{"type":"offer","sdp":"v=0\r\no=- 8135856960574707901 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=msid-semantic: WMS\r\nm=application 60100 DTLS/SCTP 5000\r\nc=IN IP4 45.56.95.146\r\na=candidate:1114595702 1 udp 2113937151 192.168.0.110 41679 typ host generation 0 network-cost 999\r\na=candidate:842163049 1 udp 1677729535 193.77.124.122 41679 typ srflx raddr 192.168.0.110 rport 41679 generation 0 network-cost 999\r\na=candidate:1650739110 1 udp 33562879 45.56.95.146 60100 typ relay raddr 193.77.124.122 rport 41679 generation 0 network-cost 999\r\na=candidate:753384278 1 udp 16785407 45.56.95.146 53190 typ relay raddr 193.77.124.122 rport 37614 generation 0 network-cost 999\r\na=candidate:846657059 1 udp 7935 45.56.95.146 57725 typ relay raddr 193.77.124.122 rport 37672 generation 0 network-cost 999\r\na=ice-ufrag:nOzT\r\na=ice-pwd:/OTQG//bGaEkzY8e19/LVTqU\r\na=fingerprint:sha-256 82:97:D6:C3:EF:29:2B:02:63:D7:23:17:E3:E1:AB:3C:B9:B4:69:5C:23:C2:A7:E9:0B:A3:CC:A2:FD:3B:39:34\r\na=setup:actpass\r\na=mid:0\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"offer_id":"\u0004ª<\u0007B:~ÌÊ-)' é7\u0005\u000bZ"},{"offer":{"type":"offer","sdp":"v=0\r\no=- 5588192257301631911 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=msid-semantic: WMS\r\nm=application 49489 DTLS/SCTP 5000\r\nc=IN IP4 45.56.95.146\r\na=candidate:1114595702 1 udp 2113937151 192.168.0.110 56775 typ host generation 0 network-cost 999\r\na=candidate:842163049 1 udp 1677729535 193.77.124.122 56775 typ srflx raddr 192.168.0.110 rport 56775 generation 0 network-cost 999\r\na=candidate:1650739110 1 udp 33562879 45.56.95.146 49489 typ relay raddr 193.77.124.122 rport 56775 generation 0 network-cost 999\r\na=candidate:753384278 1 udp 16785407 45.56.95.146 51758 typ relay raddr 193.77.124.122 rport 37610 generation 0 network-cost 999\r\na=candidate:846657059 1 udp 7935 45.56.95.146 54712 typ relay raddr 193.77.124.122 rport 37664 generation 0 network-cost 999\r\na=ice-ufrag:sIlI\r\na=ice-pwd:HWc7H20rCpn7CsG7v+0FhB6t\r\na=fingerprint:sha-256 1C:79:59:7D:FE:1D:F0:B2:FB:16:CA:5C:DF:D7:00:E8:AF:DE:29:AC:8A:85:D7:68:A0:B6:D9:65:A7:15:B6:AF\r\na=setup:actpass\r\na=mid:0\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"offer_id":"è¡Rõâ\u0001KºÖÎÄW|\fèHßJiy"},{"offer":{"type":"offer","sdp":"v=0\r\no=- 6237088042246922656 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=msid-semantic: WMS\r\nm=application 50832 DTLS/SCTP 5000\r\nc=IN IP4 45.56.95.146\r\na=candidate:1114595702 1 udp 2113937151 192.168.0.110 45529 typ host generation 0 network-cost 999\r\na=candidate:842163049 1 udp 1677729535 193.77.124.122 45529 typ srflx raddr 192.168.0.110 rport 45529 generation 0 network-cost 999\r\na=candidate:1650739110 1 udp 33562879 45.56.95.146 50832 typ relay raddr 193.77.124.122 rport 45529 generation 0 network-cost 999\r\na=candidate:753384278 1 udp 16785407 45.56.95.146 57587 typ relay raddr 193.77.124.122 rport 37622 generation 0 network-cost 999\r\na=candidate:846657059 1 udp 7935 45.56.95.146 62852 typ relay raddr 193.77.124.122 rport 37660 generation 0 network-cost 999\r\na=ice-ufrag:fp/Q\r\na=ice-pwd:63tbkjAPhgDBvFC26WCvN9Dq\r\na=fingerprint:sha-256 59:9F:4A:15:FE:EE:9D:C1:04:B9:7A:77:BB:A1:BE:9D:36:F9:53:6D:A4:CD:14:43:15:A2:3C:89:80:3F:74:DE\r\na=setup:actpass\r\na=mid:0\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"offer_id":"zð×ë®I'z\u000fhÙf¡që"},{"offer":{"type":"offer","sdp":"v=0\r\no=- 1214075391231452222 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=msid-semantic: WMS\r\nm=application 59035 DTLS/SCTP 5000\r\nc=IN IP4 45.56.95.146\r\na=candidate:1114595702 1 udp 2113937151 192.168.0.110 48540 typ host generation 0 network-cost 999\r\na=candidate:842163049 1 udp 1677729535 193.77.124.122 48540 typ srflx raddr 192.168.0.110 rport 48540 generation 0 network-cost 999\r\na=candidate:1650739110 1 udp 33562879 45.56.95.146 59035 typ relay raddr 193.77.124.122 rport 48540 generation 0 network-cost 999\r\na=candidate:753384278 1 udp 16785407 45.56.95.146 53774 typ relay raddr 193.77.124.122 rport 37638 generation 0 network-cost 999\r\na=candidate:846657059 1 udp 7935 45.56.95.146 55591 typ relay raddr 193.77.124.122 rport 37692 generation 0 network-cost 999\r\na=ice-ufrag:C8c5\r\na=ice-pwd:TWEn3N2APioHaaIilU9N06x4\r\na=fingerprint:sha-256 8B:C0:92:87:89:14:2A:E2:E2:3C:09:D2:7D:16:4A:EB:1C:5B:56:44:29:9D:35:73:72:3D:A7:CB:42:01:E8:FE\r\na=setup:actpass\r\na=mid:0\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"},"offer_id":"Cjð¸U;á¾v- iÏe[ Í+"},{"offer":{"type":"offer","sdp":"v=0\r\no=- 6627651006507106921 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=msid-semantic: WMS\r\nm=application 60266 DTLS/SCTP 5000\r\nc=IN IP4 45.56.95.146\r\na=candidate:1114595702 1 udp 2113937151 192.168.0.110 35757 typ host generation 0 
bittorrent-tracker:websocket-tracker tracker timeout: destroying peer +49s
bundle.js:1 simple-peer [fd31286] destroy (error: undefined) +49s
bundle.js:1 


'info-hash' and other string fields look suspicious, like having encoding issues. Some build options are missing?
comment
created
aldenml
username_13
@username_14, does it work the other way around? creating the torrent in another webtorret client and try to download it with `libtorrent`?
comment
created
paullouisageneau
username_0
@username_14 It should work with STUN only for most home internet access, and often for home-to-mobile. However, mobile-to-mobile connections will probably never work without a TURN server until they finally deploy IPv6 because of IPv4 carrier-grade NATs. I might add the support for TURN servers in the future though.

The errors are from instant.io, right? These are not encoding issues, sadly that's how the other webtorrent implementation encodes binary data. It should definitely use base64 instead of this mess (it would even be shorter) but that's how it works for now. It seems it can't connect to the webtorrent tracker. From what I've seen during tests, `wss://tracker.openwebtorrent.com` is rather unreliable and sometimes goes offline.
comment
created
alexeyvolkoff
username_14
@username_13 I have tried to create a torrent in instatnt.io and download it in libtorrent - it works. When finished, I see "seeding" status in client_test app. But as soon as I close the tab in instant.io and try to download the torrent in a new tab (by the hash id), it is not working. I get only bittorrent-tracker:websocket-tracker send message (as in prior post) having even correct candidate in it. But nothing hapens, tracker timout. Sometimes in 5-10 minutes i get


bundle.js:1 webtorrent:peer Peer 2d5757303030382d727652537555314267743455 got handshake 3daadb1abf719b86862ffce7e57f00289ffbbca1 +28ms
bundle.js:1 webtorrent:torrent [2d57573] [3daadb1] got wire 714ede32 (192.168.0.110:58357) +39ms
bundle.js:1 bittorrent-protocol [714ede32] setTimeout ms=30000 unref=true +3ms
bundle.js:1 bittorrent-protocol [714ede32] setKeepAlive true +1ms
bundle.js:1 bittorrent-protocol [714ede32] use extension.name=ut_metadata +0ms
bundle.js:1 bittorrent-protocol [714ede32] extended ext=0 +1ms
bundle.js:1 webtorrent:torrent [2d57573] [3daadb1] ut_metadata warning: Peer does not have metadata +5ms

but then 
webtorrent:torrent [2d57573] [3daadb1] ignoring peer: duplicate (2d5757303030382d727652537555314267743455) +1m
and again
bundle.js:1 simple-peer [15c1ff2] destroy (error: undefined) +1ms
bundle.js:1 bittorrent-tracker:websocket-tracker tracker timeout: destroying peer +32s

It does not happen if I seed with webtorrent-hybrid even over wss://tracker.openwebtorrent.com
comment
created
alexeyvolkoff
username_14
@username_0 Sounds great! TURN is desirable as last resort option.
Yes, this output is from instant.io. My webtorrent frontend behaves the same way. I also tried to create a torrent with my own wss tracker, with no luck. Seeding with node.js webtorrent app works well though.
comment
created
alexeyvolkoff
username_14
Guys it's working!!  "--" was missing before  "webtorrent_stun_server" option.

Can I push a couple of fixes for socket_io.cpp? relevant for old boost I think

Will try to build it for arm and mips :)
comment
created
alexeyvolkoff
username_14
Hi guys, me again, with the bug report. I get segfault randomly  when the torrents are inactive. Here is gdb trace:

Thread 2 "client_test" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff63d6700 (LWP 21453)]
0x0000000000482390 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x2, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/shared_ptr_base.h:727
727		if (_M_pi != nullptr)
(gdb) bt
#0  0x0000000000482390 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x2, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/shared_ptr_base.h:727
#1  0x00007ffff75669e8 in std::__shared_ptr<libtorrent::dht::dht_tracker, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0xfffffffffffffffa, __in_chrg=<optimized out>)
    at /usr/include/c++/8/bits/shared_ptr_base.h:1167
#2  0x00007ffff7566a04 in std::shared_ptr<libtorrent::dht::dht_tracker>::~shared_ptr (this=0xfffffffffffffffa, __in_chrg=<optimized out>)
    at /usr/include/c++/8/bits/shared_ptr.h:103
#3  0x00007ffff7932880 in std::_Head_base<0ul, std::shared_ptr<libtorrent::dht::dht_tracker>, false>::~_Head_base (this=0xfffffffffffffffa, __in_chrg=<optimized out>)
    at /usr/include/c++/8/tuple:120
#4  0x00007ffff79328a0 in std::_Tuple_impl<0ul, std::shared_ptr<libtorrent::dht::dht_tracker>, libtorrent::aux::listen_socket_handle, std::_Placeholder<1> >::~_Tuple_impl (
    this=0xffffffffffffffea, __in_chrg=<optimized out>) at /usr/include/c++/8/tuple:185
#5  0x00007ffff79328c8 in std::tuple<std::shared_ptr<libtorrent::dht::dht_tracker>, libtorrent::aux::listen_socket_handle, std::_Placeholder<1> >::~tuple (
    this=0xffffffffffffffea, __in_chrg=<optimized out>) at /usr/include/c++/8/tuple:556
#6  0x00007ffff79328e8 in std::_Bind<void (libtorrent::dht::dht_tracker::*(std::shared_ptr<libtorrent::dht::dht_tracker>, libtorrent::aux::listen_socket_handle, std::_Placeholder<1>))(libtorrent::aux::listen_socket_handle const&, boost::system::error_code const&)>::~_Bind() (this=0xffffffffffffffda, __in_chrg=<optimized out>)
    at /usr/include/c++/8/functional:386
#7  0x00007ffff7929301 in libtorrent::dht::dht_tracker::connection_timeout (this=<error reading variable: Cannot access memory at address 0xffffffffffffffb2>, 
    s=<error reading variable: Cannot access memory at address 0xffffffffffffffaa>, e=<error reading variable: Cannot access memory at address 0xffffffffffffffa2>)
    at /home/volkoff/Projects/sandbox/libtorrent/src/kademlia/dht_tracker.cpp:253
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
comment
created
arvidn
username_1
@username_14 would it be possible for you to build with address sanitizer and undefined sanitizer? (if you build with boost-build, specify `address-sanitizer=norecover undefined-sanitizer=norecover` on the command line)
comment
created
alexeyvolkoff
username_14
@username_1 I'm building with cmake, can I pass these options to cmake?
comment
created
arvidn
username_1
I don't know cmake very well. either cmake supports it or you need to specify the actual compiler arguments.
comment
created
alexeyvolkoff
username_14
@username_1 
Got build with 
		-fsanitize=undefined \
		-fsanitize=address \
in CMAKE_CXX_FLAGS.

The client throws these messages, though keeps working:
```
/usr/include/boost/asio/detail/impl/service_registry.ipp:157:40: runtime error: member call on address 0x611000000400 which does not point to an object of type 'service'
0x611000000400: note: object is of type 'boost::asio::detail::scheduler'
 01 00 00 02  c0 1b c3 ff 1a 7f 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  e0 78 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'boost::asio::detail::scheduler'
/usr/include/boost/asio/impl/execution_context.hpp:101:10: runtime error: member access within address 0x611000000400 which does not point to an object of type 'service'
0x611000000400: note: object is of type 'boost::asio::detail::scheduler'
 01 00 00 02  c0 1b c3 ff 1a 7f 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  e0 78 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'boost::asio::detail::scheduler'
/usr/include/boost/asio/detail/impl/service_registry.ipp:172:21: runtime error: member access within address 0x611000000400 which does not point to an object of type 'service'
0x611000000400: note: object is of type 'boost::asio::detail::scheduler'
```

But randomly crashes with this backtrace:

```
  #0 0x7f1afba46846 in boost::asio::detail::scheduler::task_cleanup::~task_cleanup() /usr/include/boost/asio/detail/impl/scheduler.ipp:47
    #1 0x7f1afba4a2ad in boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /usr/include/boost/asio/detail/impl/scheduler.ipp:379
    #2 0x7f1afba49505 in boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/include/boost/asio/detail/impl/scheduler.ipp:154
    #3 0x7f1afba4b6a5 in boost::asio::io_context::run() /usr/include/boost/asio/impl/io_context.ipp:62
    #4 0x7f1afc7119e9 in operator() /home/volkoff/Projects/sandbox/libtorrent/src/session.cpp:317
    #5 0x7f1afc72249f in __invoke_impl<void, libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/invoke.h:60
    #6 0x7f1afc721e39 in __invoke<libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/invoke.h:95
    #7 0x7f1afc723b5f in _M_invoke<0> /usr/include/c++/8/thread:244
    #8 0x7f1afc723aa2 in operator() /usr/include/c++/8/thread:253
    #9 0x7f1afc723a5c in _M_run /usr/include/c++/8/thread:196
    #10 0x7f1af45e69a2 in execute_native_thread_routine ../../../../../libstdc++-v3/src/c++11/thread.cc:80
    #11 0x7f1af38454a9 in start_thread /usr/src/debug/glibc-2.28-110-g57922433fa/nptl/pthread_create.c:479
    #12 0x7f1af37753f2 in __clone (/lib64/libc.so.6+0xfe3f2)

Address 0x7f1aefc1b6a8 is located in stack of thread T1
SUMMARY: AddressSanitizer: stack-use-after-return /usr/include/boost/asio/detail/impl/scheduler.ipp:47 in boost::asio::detail::scheduler::task_cleanup::~task_cleanup()
Shadow bytes around the buggy address:
  0x0fe3ddf7b680: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe3ddf7b690: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe3ddf7b6a0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe3ddf7b6b0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe3ddf7b6c0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
=>0x0fe3ddf7b6d0: f5 f5 f5 f5 f5[f5]00 f2 f2 f2 f2 f2 00 00 00 f2
  0x0fe3ddf7b6e0: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe3ddf7b6f0: f1 f1 f1 f1 f8 f8 f2 f2 f2 f2 f2 f2 00 00 f2 f2
  0x0fe3ddf7b700: f2 f2 f2 f2 00 00 00 f2 f2 f2 f2 f2 00 00 00 00
  0x0fe3ddf7b710: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe3ddf7b720: f1 f1 f1 f1 00 00 f2 f2 f3 f3 f3 f3 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
Thread T1 created by T0 here:
    #0 0x7f1b07513f63 in __interceptor_pthread_create (/lib64/libasan.so.5+0x52f63)
    #1 0x7f1af45e6c88 in __gthread_create /usr/src/debug/gcc-8.3.1-2.fc29.x86_64/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/x86_64-redhat-linux/bits/gthr-default.h:662
    #2 0x7f1af45e6c88 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ../../../../../libstdc++-v3/src/c++11/thread.cc:135
    #3 0x7f1afc721dc9 in construct<std::thread, libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/ext/new_allocator.h:136
    #4 0x7f1afc721d37 in construct<std::thread, libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/alloc_traits.h:475
    #5 0x7f1afc721aaf in _Sp_counted_ptr_inplace<libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/shared_ptr_base.h:545
    #6 0x7f1afc721355 in __shared_count<std::thread, std::allocator<std::thread>, libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/shared_ptr_base.h:677
    #7 0x7f1afc720fdf in __shared_ptr<std::allocator<std::thread>, libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/shared_ptr_base.h:1342
    #8 0x7f1afc720d23 in shared_ptr<std::allocator<std::thread>, libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/shared_ptr.h:359
    #9 0x7f1afc720ba7 in allocate_shared<std::thread, std::allocator<std::thread>, libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/shared_ptr.h:706
    #10 0x7f1afc720ac8 in make_shared<std::thread, libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*)::<lambda()> > /usr/include/c++/8/bits/shared_ptr.h:722
    #11 0x7f1afc71839c in libtorrent::session::start(libtorrent::session_params&&, boost::asio::io_context*) /home/volkoff/Projects/sandbox/libtorrent/src/session.cpp:316
    #12 0x7f1afc719727 in libtorrent::session::session(libtorrent::session_params&&) /home/volkoff/Projects/sandbox/libtorrent/src/session.cpp:346
    #13 0x491806 in main /home/volkoff/Projects/sandbox/libtorrent/examples/client_test.cpp:1366
    #14 0x7f1af369b412 in __libc_start_main ../csu/libc-start.c:308

==2373==ABORTING
```
comment
created
arvidn
username_1
That looks like it could be an ABI compatibility issue. Are you sure all dependencies were built with those options too?
comment
created
alexeyvolkoff
username_14
@username_1 I have fixed segfaults with upgrading boost to version 1.73.0 and linking everything statically.
cmake -DCMAKE_CXX_STANDARD=17 -Dwebtorrent=ON -DUSE_JUICE=ON -DBUILD_SHARED_LIBS=OFF -Dlink=static -Dbuild_examples=ON  -Ddht=OFF -Dboost-link=static -DCMAKE_BUILD_TYPE=Debug  ..

But I'm still facing connectivity issue. webtorrent  seeds work 10-15 minutes after client is restarted.
Then both isntant.io and my web app get no peers, until I restart the client. Then both frontends start downloading
comment
created
arvidn
username_1
Is that a new issue with using boost-1.73?
have you built with undefined-sanitizer and address-sanitizer?
comment
created
alexeyvolkoff
username_14
@username_1 I think the connectivity issue was caused by unreliable trackers.  Now I have limited my torrents to use only my own wss tracker and the connection became more stable. 

regarding the sanitazers - I checked out which exatcly flag does boost build add to CXX_FLAGS and did the same for cmake:
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
		-Wall \
		-Wextra \
		-Wpedantic \
		-Wparentheses \
		-Wvla \
		-Wno-c++11-compat \
		-Wno-format-zero-length \
		-Wno-noexcept-type \
		**-fsanitize=undefined \
		-fno-sanitize-recover=undefined \
		-fsanitize=address \
		-fno-sanitize-recover=address \**
		-ftemplate-depth=512")
	message("CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")

it worked 7-8 hours and crashed. Outdated boost v 1.66 was crashing in 30 minutes for no reason.   
Repeating the test with gdb.
comment
created
alexeyvolkoff
username_14
Crashed after 4 hours.
/home/volkoff/Projects/sandbox/libtorrent/include/libtorrent/aux_/torrent.hpp:1177:12: runtime error: member access within null pointer of type 'struct torrent_peer'
comment
created
arvidn
username_1
@username_14 do you have a corefile? If so, could you provide some more details, like the stack trace?
comment
created
alexeyvolkoff
username_14
5 hours under gdb, but no trace because it exited "normally".
/home/volkoff/Projects/sandbox/libtorrent/include/libtorrent/aux_/torrent.hpp:1177:12: runtime error: member access within null pointer of type 'struct torrent_peer'
[Thread 0x7fffb796f700 (LWP 25330) exited]
[Thread 0x7fffb556f700 (LWP 25331) exited]
[Thread 0x7fffb8d76700 (LWP 25329) exited]
[Thread 0x7fffbc187700 (LWP 25327) exited]
[Thread 0x7fffbd189700 (LWP 25326) exited]
[Thread 0x7fffbf58c700 (LWP 25325) exited]
[Thread 0x7fffc058e700 (LWP 25324) exited]
[Thread 0x7fffc1d9d700 (LWP 25323) exited]
[Thread 0x7fffc35ac700 (LWP 25322) exited]
[Thread 0x7fffc3dad700 (LWP 25321) exited]
[Thread 0x7fffc49b0700 (LWP 25320) exited]
[Thread 0x7fffc75ba700 (LWP 25319) exited]
[Thread 0x7fffc89c1700 (LWP 25318) exited]
[Thread 0x7fffcc420700 (LWP 25317) exited]
[Thread 0x7fffdfc4c700 (LWP 25316) exited]
[Thread 0x7fffe084f700 (LWP 25315) exited]
[Thread 0x7fffe1851700 (LWP 25314) exited]
[Thread 0x7fffe2052700 (LWP 25313) exited]
[Thread 0x7fffe2853700 (LWP 25312) exited]
[Thread 0x7fffe4e0d700 (LWP 25310) exited]
[Thread 0x7fffe560e700 (LWP 25309) exited]
[Thread 0x7fffe8215700 (LWP 25308) exited]
[Thread 0x7fffe9217700 (LWP 25307) exited]
[Thread 0x7fffe9a18700 (LWP 25306) exited]
[Thread 0x7fffeaa1a700 (LWP 25305) exited]
[Thread 0x7fffc55b3700 (LWP 25304) exited]
[Thread 0x7fffbfd8d700 (LWP 25303) exited]
[Thread 0x7fffbe185700 (LWP 25302) exited]
[Thread 0x7fffbc988700 (LWP 25301) exited]
[Thread 0x7fffccc21700 (LWP 25300) exited]
[Thread 0x7fffcdec4700 (LWP 25299) exited]
[Thread 0x7fffd16d4700 (LWP 25298) exited]
[Thread 0x7fffe1050700 (LWP 25297) exited]
[Thread 0x7fffe3e0b700 (LWP 25296) exited]
[Thread 0x7fffea219700 (LWP 25295) exited]
[Thread 0x7fffb416e700 (LWP 25294) exited]
[Thread 0x7fffe360a700 (LWP 25293) exited]
[Thread 0x7fffadf3e700 (LWP 25292) exited]
[Thread 0x7fffcbc1f700 (LWP 25291) exited]
[Thread 0x7fffce6c5700 (LWP 24298) exited]
[Thread 0x7fffcf6ca700 (LWP 24297) exited]
[Thread 0x7fffd02cd700 (LWP 24296) exited]
[Thread 0x7fffd26d9700 (LWP 24295) exited]
[Thread 0x7fffe6211700 (LWP 24294) exited]
[Thread 0x7fffeba34700 (LWP 24293) exited]
[Thread 0x7fffe460c700 (LWP 24292) exited]
[Thread 0x7fffde84b700 (LWP 24291) exited]
[Thread 0x7fffd4adf700 (LWP 24290) exited]
[Thread 0x7fffd2eda700 (LWP 24289) exited]
[Thread 0x7fffd3add700 (LWP 24288) exited]
[Thread 0x7fffd42de700 (LWP 24287) exited]
[Thread 0x7fffdf44b700 (LWP 24286) exited]
[Thread 0x7fffe7213700 (LWP 24285) exited]
[Thread 0x7fffe8a16700 (LWP 24284) exited]
[Thread 0x7fffecadd700 (LWP 24283) exited]
[Thread 0x7fffeb21b700 (LWP 24282) exited]
[Thread 0x7fffe7a14700 (LWP 24281) exited]
[Thread 0x7fffbb983700 (LWP 24280) exited]
[Thread 0x7fffe6a12700 (LWP 24279) exited]
[Thread 0x7fffcd458700 (LWP 17663) exited]
[Thread 0x7fffed2f4700 (LWP 17580) exited]
[Thread 0x7fffedafd700 (LWP 17579) exited]
[Thread 0x7fffee30c700 (LWP 17578) exited]
[Thread 0x7fffeeb23700 (LWP 17577) exited]
[Thread 0x7fffef35c700 (LWP 17576) exited]
[Thread 0x7fffefb73700 (LWP 17575) exited]
[Thread 0x7ffff038a700 (LWP 17574) exited]
[Thread 0x7ffff0ba1700 (LWP 17573) exited]
[Thread 0x7ffff24fc700 (LWP 17570) exited]
[Thread 0x7ffff5de4c40 (LWP 17560) exited]
[Infertt
(gdb) bt
No stack.
(gdb) 

At least we got source file and number:
/libtorrent/include/libtorrent/aux_/torrent.hpp:1177:12:
```
	void inc_num_connecting(torrent_peer* pp)
		{
			++m_num_connecting;
			**if (pp->seed) ++m_num_connecting_seeds;**
		}
```
comment
created
paullouisageneau
username_0
I just had a quick look, it seems `m_peer_info` is not checked here: https://github.com/username_1/libtorrent/blame/adf8943ba926f45b6434d276a8fb4dc1dde2fb5f/src/peer_connection.cpp#L203

But it is just before here: https://github.com/username_1/libtorrent/blame/adf8943ba926f45b6434d276a8fb4dc1dde2fb5f/src/peer_connection.cpp#L195

@username_1 Is this normal ?
comment
created
alexeyvolkoff
username_14
It is just logging. 
I think  checking should be like this:
if (m_connecting && m_peer_info && t) t->inc_num_connecting(m_peer_info);
But is it OK to have dead connection? Question to @username_1
comment
created
arvidn
username_1
I does look suspicious. I don't have time to investigate this right now. the comment in the header file says that `m_peer_info` can be nullptr for incoming connections, where we don't know which torrent it belongs to yet. which suggests that if `t` is non-zero, then `m_peer_info` should be non-zero as well.
comment
created
alexeyvolkoff
username_14
with my fix it is just freezing.
comment
created
alexeyvolkoff
username_14
@username_1  Now it works better but freezes on exit.
libtorrent/src/session.cpp:451, on  m_thread->join();

BTW is the master branch stable?
comment
created
arvidn
username_1
It depends on what you mean by stable. Clearly it's not stable enough :)
but it's not like we land patches that fail CI. I imagine the issue you're experiencing is some interaction with the new webtorrent feature
comment
created
alexeyvolkoff
username_14
Very interesting. Now in another place:
libtorrent/src/torrent.cpp:7232:29: runtime error: member access within null pointer of type 'struct torrent_peer'
Again, it takes 6-7 hours to reproduce. Client is mostly idle.
comment
created
xavier2k6
username_15
@username_1 I know this has been merged in to master but was just wondering if this is targeted to be released for `RC_1_x` , `RC_2_x` or some other branch down the road like `RC_3_x`?
comment
created
arvidn
username_1
some other branch after 2.0
comment
created
xavier2k6
username_15
Thanks.
comment
created
petterreinholdtsen
username_16
Do you have any idea when the webtorrent support will be included in a release?  Any chance it will happen in time for the Debian release freeze around new years eve?
comment
created
arvidn
username_1
it will not have been released by end of year. It's not quite stable yet. For example, this issue has come up: https://github.com/username_1/libtorrent/issues/5100

I welcome anyone to test libtorrent `master` to iron out issues like that, to get it to a stable state sooner!
comment
created
frankenstein91
username_17
is there any info on which clients are already working with it (webtorrent)?
comment
created
tuxayo
username_18
It's not released yet, more info in the previous messages.
comment
created
Clodo76
username_19
I hope in progress of this integration, this world need an implementation to share web-based p2p content.
i just donate 1000€ to the bitcoin address of libtorrent project, i hope can help.
comment
created
paullouisageneau
username_0
@username_19 That's very nice of you, however for now I'm the only one maintaining the integration. Any contribution to help to test and fix issues (for instance https://github.com/username_1/libtorrent/issues/5831) is welcome!
comment