Skip to content

Refactor imquic to use picoquic as the underlying QUIC stack#22

Merged
lminiero merged 4 commits intomainfrom
imquic-picoquic
Mar 3, 2026
Merged

Refactor imquic to use picoquic as the underlying QUIC stack#22
lminiero merged 4 commits intomainfrom
imquic-picoquic

Conversation

@lminiero
Copy link
Member

This is a big refactoring that I had planned for a while but always delayed, because I knew it would take some considerable work.

When I first created imquic, it was based on a QUIC stack I wrote from the grounds up, while I was learning the ropes. This stack, while simple, did the job for a while, and definitely allowed me to do a deep dive in the protocol and experiment with different testbeds, MoQ included. At the same time, though, I always acknowledged it as the weak link in the library: QUIC is not a simple protocol, and it's hard to get right, and as a matter of fact there was a ton of stuff I had not yet added, e.g., congestion control and proper flow control.

Long story short, I eventually decided to replace the QUIC stack part, but keep everything else I had written pretty much the same, to keep the library and its APIs mostly as it was. After a bit of research on existing C stacks, I figured out that either ngtcp2 or picoquic would be the way to go. A few conversations later (at FOSDEM too!), I decided to go the picoquic way, which is what this PR is about.

This PR basically gets rid of all the code related to my native QUIC stack (including the crypto utilities) and replaces that with picoquic integrations. This effort had the nice side effect of simplifying the dependencies too: where before I had an awkward dependency on quictls (awkward simply because of the diffulty to reliably detect and use it as part of my configure scripts), now picoquic is built as a shared object and embedded in the library directly, which makes it way easier.

The end result is that demos are supposed to work pretty much exactly as before, and with pretty much (apart from a few changes) the same APIs too. There are a few things that are done differently, mostly because of how stuff is implemented and exposed in picoquic compared to how I implemented it in my own homemade stack.

A more detailed discussion is available here, but some things to take into account are:

  1. CONNECTION_CLOSE reasons are not supported yet, since picoquic only exposes error codes; not a big deal since my APIs don't expose either, at the moment, but it would be useful to have as I did log the reason before. I plan to have a deeper dive in the picoquic internals, sooner or later, to see if this is something I can contribute myself.
  2. picoquic does support WebTransport, but I haven't approached the related APIs yet. As such, to keep things simple in this first iteration, I decided to only use picoquic for QUIC, and use my existing barebones HTTP/3 layer for WebTransport. This is also needed because picoquic's WebTransport code doesn't currently support negotiating application protocols via WebTransport (which is a requirement for MoQ), but there is a discussion ongoing about that too, so replacing my WebTransport code is definitely on my radar too.
  3. QLOG now works a bit differently too, as before I controlled the whole stack, and now I don't. Since picoquic has its own implementation of QLOG, now when you enable QLOG in imquic you may end up with two different files: one for QUIC (generated by picoquic) and one for the other application layers (HTTP/3, RoQ, MoQ, generated by imquic). A bit awkward but hopefully the file naming conventions I used should make it easier to correlate the two when needed.
  4. Early data may not be working anymore, now, even though to be honest I'm not 100% sure it was working perfectly in my own stack either, for that matter. I think I'm using the picoquic APIs correctly, but some simple tests I made didn't yield the correct results. It's not a priority (I only added it at the time for fun), but I'll keep track of it, since we do have an API for it.

Apart from that, even though from a first cursory run of the demos all seems to be working, this is just a first integration, and I haven't spent much time fine tuning everything. I did notice a bit of instability, for instance, especially when closing connections, which is something I'll have to improve before this is merged.

Once this lands, I plan to dig a bit deeper in things picoquic provides I didn't have access to before. I haven't checked if, as an application, there's anything I need to do in terms of pacing or congestion control, for instance. All this can wait until I have more solid grounds to build from, and opening this PR is a first step towards exactly that.

@lminiero lminiero merged commit f746edb into main Mar 3, 2026
@lminiero lminiero deleted the imquic-picoquic branch March 3, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant