Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quic transport #3376

Closed
totaam opened this issue Dec 4, 2021 · 13 comments
Closed

quic transport #3376

totaam opened this issue Dec 4, 2021 · 13 comments
Labels
enhancement New feature or request network

Comments

@totaam
Copy link
Collaborator

totaam commented Dec 4, 2021

QUIC could easily replace the old UDP transport.
There are frameworks and APIs that wrap QUIC with easy to use callbacks, like https://github.com/aiortc/aioquic documentation
(see also https://github.com/MagicStack/uvloop)
We would get HTTP/3 and encryption almost for free and a reliable event based framework for managing connection state.

Examples include an http3 server and clients, etc..

The re-send / packet-drop callbacks could easily re-use the techniques that were used for UDP (#639) which was removed in 2022238.


Worth noting that aioquic requires Python 3.7 or better, and the OpenSSL development headers so this won't be available on RHEL 8.

@totaam totaam added enhancement New feature or request network labels Dec 4, 2021
@totaam
Copy link
Collaborator Author

totaam commented Jan 11, 2022

aioquic is not available in Fedora and the number of dependencies required to run the http3 server example is a little bit ridiculous: python3-wsproto, python3-httpbin, python3-asgiref, python3-starlette and python3-aiofiles.
Not counting all the dependencies that each one of these packages brings...

@totaam totaam mentioned this issue Jan 12, 2022
@totaam
Copy link
Collaborator Author

totaam commented Feb 22, 2022

It gets worse since we also need to run the GTK main loop until we can drop GTK (#1995).
There are various ways of doing this:

And perhaps soon in pygobject directly: Implement asyncio event loop based on glib

Next, creating asyncio sockets requires using a specific API: asyncio.loop.create_datagram_endpoint / loop.create_connection, which means that socket sharing is going to be more difficult to implement.

This may help in bridging with the rest of the code:

  • trio : a friendly Python library for async concurrency and I/O
  • greenback : allows you to call back into async code from a syntactically synchronous function

This was referenced Apr 3, 2022
@TijZwa
Copy link
Collaborator

TijZwa commented Oct 15, 2022

I've done some testing with Aioquic. Basically I've just glued asyncio with aioquic to the existing codebase.
The main issue is starting a new main loop inside a thread, inside the existing GTK loop.
Also the list of dependencies is way too big (starlette and what not).

The source of aioquic seems pretty neat. I think the best way forward is to use this code as an example to implement our own low-level implementation of a http/3 quic server.

https://github.com/aiortc/aioquic/tree/main/src/aioquic

@totaam
Copy link
Collaborator Author

totaam commented Oct 15, 2022

as an example to implement our own low-level implementation of a http/3 quic server

Yes!
This part of the library looks really clean and, at first glance, without too many dependencies, only things like https://github.com/aiortc/pylsqpack
Gio supports UDP so there is no reason why we can't use the GTK main loop for handling packet events.

totaam added a commit that referenced this issue Oct 24, 2022
try to build on every RPM platform and see what happens
@totaam
Copy link
Collaborator Author

totaam commented Oct 24, 2022

We need an asyncio event loop:
https://github.com/aiortc/aioquic/blob/444be09157aed3c81881d18647484165dd07139c/src/aioquic/asyncio/server.py#L202

The patches for pygobject are still languishing as a PR and asyncio-glib is unmaintained.

And gbulb has had no update since earlier this year.

Then there's also glibcoro: glibcoro makes the GLib / GTK
event loop compatible with Python’s asyncio

Meanwhile, this answer: https://stackoverflow.com/a/26719999/428751 suggests running the aio part in a separate thread. Downside is: One does need to be careful, however, to use thread-safe functions to communicate between the GUI (main) thread and the asyncio thread. This means using loop.call_soon_threadsafe or asyncio.run_coroutine_threadsafe to submit things to asyncio from GTK, and GLib.idle_add to submit things to GTK from asyncio.

Decisions!

totaam added a commit that referenced this issue Oct 24, 2022
totaam added a commit that referenced this issue Oct 24, 2022
totaam added a commit that referenced this issue Nov 2, 2022
@totaam
Copy link
Collaborator Author

totaam commented Nov 2, 2022

There's still a lot to do:

  • try to run with a single aio loop instead of using threading in quic_queue_server? (multiprocessing?)
    • then we don't have to use aioquic.asyncio.server.serve and we can use lower level APIs like QuicServer.datagram_received from GLib IO events?
  • reuse list_directory in the "old" http handler
  • handle POST requests? HEAD?
  • handle quic_socket.close - at least exit quic_queue_server when all sockets are closed
  • websocket handler
  • add options for QuicConfiguration
    • server_name should come from ssl options?
    • max_data / max_stream_data should be higher?
  • redirect quic_logger to our own logging framework (with remote logging)
  • simplify http3_server.py, remove wsproto?
  • override FrameProtocol._serialize_frame with our faster Cython mask version?
  • in WebSocketHandler.send call self.connection.send_data repeatedly instead of concatenating header, mask and data
  • hook http authentication - how!?
  • add quic client support
  • test with a Javascript WebTransport client - see also WebTransport Explainer, Using WebTransport
  • move screen updates to a separate lossy stream?
  • support different session ticket factories?
  • quic can bind to unix socket - not sure what to do with that

xpra start --no-daemon -d quic --start=xterm
    --bind-tcp=0.0.0.0:10000
    --bind-quic=localhost:20000 --ssl-cert=./cert.pem --ssl-key=./key.pem

Allows http3 clients to connect:

./examples/http3_client.py "https://localhost:20000/Sessions?hello=foo&bar=2" -k -v --output-dir=./output

Apparently, chrome needs to be told to use the QUIC protocol

totaam added a commit that referenced this issue Nov 5, 2022
totaam added a commit that referenced this issue Nov 5, 2022
totaam added a commit that referenced this issue Nov 5, 2022
totaam added a commit that referenced this issue Nov 6, 2022
totaam added a commit that referenced this issue Nov 8, 2022
totaam added a commit that referenced this issue Nov 9, 2022
totaam added a commit that referenced this issue Nov 10, 2022
totaam added a commit that referenced this issue Nov 10, 2022
totaam added a commit that referenced this issue Nov 10, 2022
move common connection bits between client and server to a XpraWebSocketConnection class
@totaam
Copy link
Collaborator Author

totaam commented Nov 10, 2022

As of d4c7fc8, I can connect via quic using a self signed cert:

xpra start --bind-quic=localhost:20000 --start=xterm :100 \
    --ssl-cert=./cert.pem --ssl-key=./key.pem
xpra attach quic://localhost:20000/ --ssl-server-verify-mode=none

totaam added a commit that referenced this issue Nov 10, 2022
totaam added a commit that referenced this issue May 14, 2023
so we can preserve the the exit code
totaam added a commit that referenced this issue May 14, 2023
totaam added a commit that referenced this issue May 14, 2023
warn if 'uvloop' is not found since it should now be available on all the platforms it can be installed on (ie: all except MS Windows)
@totaam totaam closed this as completed May 15, 2023
Simba98 added a commit to Simba98/xpra that referenced this issue Mar 25, 2024
@totaam
Copy link
Collaborator Author

totaam commented Apr 6, 2024

Looks like asyncio integration with support to await Gio async functions is going to be merged!
But we'll have to keep the threaded implementation around until all the supported distros ship with the new pygobject... which could take many years.

@totaam
Copy link
Collaborator Author

totaam commented Jun 26, 2024

Looks like asyncio will be integrated with pygobject Gio soon: asyncio integration with support to await Gio async functions so we will be able to drop the ugly asyncio_thread workaround in the future.

totaam added a commit that referenced this issue Jun 29, 2024
@totaam
Copy link
Collaborator Author

totaam commented Jun 29, 2024

WebTransport can now be used with the html5 client:
Xpra-org/xpra-html5#143 (comment)
It would be nice to also support a xpra attach webtransport://host:port/ mode for the Python client.

totaam added a commit that referenced this issue Jul 13, 2024
was added to aioquic 1.2.0
totaam added a commit that referenced this issue Jul 13, 2024
sending a websocket close message to other types of connections is unlikely to work
totaam added a commit that referenced this issue Jul 13, 2024
with aioquic 1.2, we can provide the QuicErrorCode and reason,
and the protocol implementations can send more specific messages before that,
WebSocket and WebTransport protocols have 'close' frames too
@totaam
Copy link
Collaborator Author

totaam commented Sep 9, 2024

TLDR excerpts from the QUIC is not Quick Enough over Fast Internet paper:

  • We find that over fast Internet, the UDP+QUIC+HTTP/3 stack suffers a data rate reduction of up to 45.2% compared to the TCP+TLS+HTTP/2 counterpart
  • QUIC Perceives Much More Packets than HTTP/2
  • QUIC has a much Higher RTT Dominated by Local Processing
  • the root cause to be the pronounced receiver-side processing
    overhead. This overhead manifests in the form of excessive data
    packets observed at Layer 3 and above, as well as QUIC’s distinctive
    user-space ACKs

Fast internet is defined as >500 Mbps
I think this all makes sense. It will get better over time, and we care more about latency than outright maximum throughput.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request network
Projects
None yet
Development

No branches or pull requests

2 participants