arvidn / libtorrent

an efficient feature complete C++ bittorrent implementation
http://libtorrent.org
Other
5.23k stars 992 forks source link

How to handle async response in on_dht_request #4016

Closed geiseri closed 4 years ago

geiseri commented 5 years ago

libtorrent version (or branch):1.2.1 using vpkg platform/architecture: linux x86_64 (Arch Linux) compiler and compiler version: gcc 9.1.0

I am trying to implement a session plugin that will allow for me to communicate over the krpc between peers. My issue is that in the signature of libtorrent::plugin::on_dht_request(...) the response must be returned to the caller via the last argument. This complicates matters for me as I wish to access information from another thread and do not want to lock anything. Is there a way short of sending back a "correlation id" that can be used later to pair the response?

ssiloti commented 5 years ago

There currently is no provision for performing async operations in a DHT request handler and it would be a fair amount of work to refactor the DHT code to allow for that.

arvidn commented 5 years ago

Do I understand correctly that you would like to not have to produce the response immediately, but you would like to have your other thread process the request and send the response later?

I think there would be a way to do this without too many changes to libtorrent. The response out-parameter that's passed into the on_dht_request() callback, is actually an in-out parameter. It's pre-filled with the basic information required for the response. Things like:

{'y': 'r', 't': <transaction-id>, 'ip': <requestor-ip>, 'r': {'id': <our-node-id>, 'p': <requestor-port>}}

If you'd copy that object and (somehow) tell libtorrent to not send any response. Your other thread could later send the response.

The dht::msg object should contain enough information to send the DHT message to the right node later on. There currently is no way to tell libtorrent to not send a response. But it shouldn't be too much work to add that.

bdecode_node const& message;
udp::endpoint addr;

addr is the return address.

I think you can use session_handle::dht_direct_request() to send the response from your other thread.

Patches are welcome! (even just to clarify the documentation). Keep in mind though that patches against RC_1_2 may not break ABI. Such changes need to go into master.

geiseri commented 5 years ago

I will explore this route. I am adding a custom RPC message that has the potential to take wall clock time, and I am afraid that might have some implications. Does it matter from a protocol point of view if the response goes back to the client later? On the other side, it will fire an alert.

arvidn commented 5 years ago

I'm not sure what you mean by the RPC "taking wall clock time". When a DHT node receives a message, it should respond as soon as possible, but it can probably get away with waiting a second or two to respond. There may be some additional queueing delay along the network path too, and timeouts (off the top of my head) default to 5 or 10 seconds.

geiseri commented 5 years ago

Yes, it should respond immediately, but the thing that it is kicking off and that will inevitably respond from takes "wall clock time." I mean RPC is a pita to do right because of the interfaces pretending that they are local functions. Let me think about this a bit more. I think this is custom behavior enough that it would warrant its own plugin as to not mess with existing protocols. In AMQP land I end up needing to create a temporary subscriber on the caller that will listen for a published message from the receiver to respond with the result. The 't': <transaction-id> might actually provide enough with the 'ip': <requestor-ip> to do that.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.