paullouisageneau / libjuice

JUICE is a UDP Interactive Connectivity Establishment library
Mozilla Public License 2.0
403 stars 75 forks source link

io_uring and libjuice #231

Open Duna2004 opened 7 months ago

Duna2004 commented 7 months ago

Hello @paullouisageneau I have a program that depends on io uring, is there a way to use libjuice poll with io_uring?

Duna2004 commented 7 months ago

I have already started to implement uring by myself. I've been through all of your code and it is really well written, but not that well documented :). I'm struggle to understand how does the connection and sending works. What I do not understand is:

  1. What is the meaning of conn_interrupt(agent);
  2. What is the meaning of bookkeeping and when should it be called?
  3. How is the initial next_timestamp calculated and what is the meaning of it?

Whould you be that kind and explain these? What I have figured out is that if I gather all the juice_gather_candidates and then right after it agent_bookkeeping with auto ts = current_timestamp(); it starts to work in my uring code but I feel like I need to understand the code more deeply.

Thank you very much for your help

paullouisageneau commented 7 months ago

I have already started to implement uring by myself. I've been through all of your code and it is really well written, but not that well documented :).

Yes indeed, libjuice lacks documentation. It started as an ad-hoc dependency for libdatachannel, so I did not properly document it. It's great that you started to work on uring support! I guess it should be implemented as a concurrency mode with a dedicated conn_uring.c file.

I'm struggle to understand how does the connection and sending works. What I do not understand is:

1. What is the meaning of conn_interrupt(agent);

conn_ functions call the connectivity backend for the agent, which implements a concurrency mode. conn_interrupt() allows the agent to request an interruption of the polling thread. In practice, it means the agent wants agent_conn_update() to be called shortly by the polling thread because something changed due to user action. The reason not to run the agent update synchronously on the user thread is that callbacks may be triggered during update, and callbacks must not be run on the user thread.

2. What is the meaning of bookkeeping and when should it be called?

It's basically an agent update, actually agent_conn_update() just calls agent_bookkeeping(). It takes care of updating transactions and states, handling timeouts, retransmissions, etc. It must be called either after the agent has received one or more packets, after the next_timestamp set by the last call is reached, or after conn_interrupt() is called, whichever happens first.

3. How is the initial next_timestamp calculated and what is the meaning of it?

agent_conn_update() sets the output parameter next_timestamp to indicate when agent_conn_update() must be called again. The update process will set it depending of the next event to handle. You should initialize it to 0 in the connectivity backend as the agent must be updated immediately on creation (This is typically implicitly done by calloc which initializes memory to 0, look at conn_thread.c for instance).