Giter VIP home page Giter VIP logo

picoquic's Introduction

picoquic

Minimalist implementation of the QUIC protocol, as defined by the IETF. The IETF spec started with the version of QUIC defined by Google and implemented in Chrome, but the IETF spec is independent of Chrome, and does not attempt to be backward compatible.

The first goal of this project was to provide feedback on the development of a QUIC standard in the IETF QUIC WG. Information on the WG is available at https://datatracker.ietf.org/wg/quic/charter/. QUIC has been published as RFC 9000, but there is still ongoing work, for example on multipath. Picoquic enables developers to test this new work.

The second goal is to experiment with API for non-HTTP development, such as DNS over QUIC -- see RFC 9250. Then there are plenty of other features we may dream off, such as support for peer-to-peer applications or forward error correction. That's on the horizon, but not there now.

The current version of Picoquic supports the QUIC specifications per RFC 9000, RFC 9001, RFC 9002, and RFC 8999. It also implements the following extensions:

The distribution also includes a minimal implementation of HTTP3 per RFC 9114, including a static implementation of QPACK, compatible with RFC9204 with support for the following extensions:

The code in this repo is stable. Performance work is ongoing -- recent tests showed picoquic sending data at up to 5Gbps.

There are many implementations of Quic, listed at https://github.com/quicwg/base-drafts/wiki/Implementations. Several implementations provide docker images to the "Quic Interop Runner" project, with results updated daily at https://interop.seemann.io/.

Bastian Köcher has developed bindings of the picoquic library to RUST. His repository can be found here. You may want to check it.

Development

Picoquic is currently developed as a Visual Studio 2017 project, and simultaneously tested on Windows and on Linux. It has a dependency on the Picotls implementation of TLS 1.3. Picotls has two modes, a feature rich version that depends on OpenSSL, and a leaner version that only depends on the "minicrypto" library. For now, Picoquic uses the OpenSSL version, and has a dependency on OpenSSL.

The project consists of a core library (picoquic), of a test library (picoquictest), and of a test program (picoquicdemo). All these are written in C. In the Visual Studio project, the test library is wrapped up in the Visual Studio unittest framework, which makes for convenient regression testing during development. In the Linux builds, the tests are run through a command line program.

Milestones

As explained in the Wiki, Picoquic is actively tested against other implementations during the QUIC Interop days. See https://github.com/private-octopus/picoquic/wiki/QUIC-milestones-and-interop-testing. The current version is aligned with version 1, RFC 9000.

An implemention of DNS over QUIC is available as Quicdoq. DNS over Quic is interesting by itself, but it also provides an example for building an application different than HTTP on top of Picoquic.

We are spending time bettering the implementation, and the documentation, including a first pass at documenting architecture and API. Initially the focus has been on correctness rather than performance. We will keep correctness, but we will improve performance, especially in light of practical experience with applications. To facilitate performance tests, the demo program includes an implementation of the quic performance test protocol. Suggestions for documentation, API, performance and more are wellcome. Feel free to open an issue.

Planned developments include support for the standard version of multipath, improved support for Real Time Media over QUIC, as well as various other research issues, in particular related to congestion control.

Building Picoquic

Picoquic is developed in C, and can be built under Windows or Linux. Building the project requires first managing the dependencies, Picotls and OpenSSL. Please note that you will need a recent version of Picotls -- the Picotls API has evolved recently to support the latest version of QUIC. The current code is tested against the Picotls version of Tue Oct 31 11:23:32 2023 +0900, after commit af66fc4aa8853b0725fcb2c18a702e8f1c656cf1. (Note that these last commits changed the Picotls API by removing code for the now obsolete ESNI draft; prior versions will not work with Picoquic.) The code can use OpenSSL version 1.1.1 or OpenSSL version 3.0.

More information can be found in the docs

Picoquic on Windows

To build Picoquic on Windows, you need to:

  • Install and build Openssl on your machine

  • Document the location of the Openssl install in the environment variable OPENSSLDIR (OPENSSL64DIR for the x64 builds)

  • Make sure that a copy of libcrypto.lib is available at that location, and that a copy of applink.c is available at the include location: $(OPENSSLDIR)\include
    for win32 builds, $(OPENSSL64DIR)\include\ for the x64 builds.

  • Clone and compile Picotls, using the Picotls for Windows options. The picotls project should be in the same directory level as the picoquic project, and the folder name should be kept as picotls.

  • Clone and compile Picoquic, using the Visual Studio 2017 solution picoquic.sln included in the sources.

  • You can use the unit tests included in the Visual Studio solution to verify the port.

Picoquic on Linux

Thanks to check-ins from Deb Banerjee and Igor Lubashev for the build experience on Linux.

To build Picoquic on Linux, you need can either build picotls separately or use an integrated option. In both cases, you need first to install and build Openssl on your machine

To build step by step, you should:

  • Clone and compile Picotls, using cmake as explained in the Picotls documentation.

  • Clone and compile Picoquic:

   cmake .
   make

Instead of building picotls separately, you can use an integrated option (thanks to Paul E. Jones and Suhas Nandakumar for developing that):

  • Clone and compile Picoquic and Picotls in a single command:
   cmake -DPICOQUIC_FETCH_PTLS=Y .
   make

Either way, you can verify that everything worked:

  • Run the test program picoquic_ct to verify the port.

The tests verify that the code compiles and runs correctly under Ubuntu, using GitHub actions on Intel 64 bit VMs. We rely on user reports to verify behavior on other architecture, e.g. ARM. Thanks to @defermelowie for testing on ARM 32 bits.

Picoquic on MacOSX

Thanks to Frederik Deweerdt for ensuring that Picoquic runs on MacOSX. The build steps are the same as for Linux. The tests verify that the code compiles and runs correctly under MacOS, using GitHub actions on Intel 64 bit VMs. We rely on user reports to verify behavior on other architecture, e.g. M1. Thanks to @defermelowie for testing on M1.

Picoquic on FreeBSD

Same build steps as Linux. Picoquic probably also works on other BSD variants, but only FreeBSD has been tested so far.

Using Picoquic in CLI mode

See Usage for how to use various commands from shell.

Developing applications

Sorry, not all that much documentation yet. This will come as we populate the wiki. Your best bet is to look at the demonstration program "picoquicdemo" that is included in the release. The sources are in "picoquicfirst/picoquicdemo.c". The sample folder contains a code sample for a simplistic file transfer protocol, which might be a good place to start. Look at the README.md file in the sample folder for more details.

Testing previous versions

The code is constantly updated to track the latest version of the specification. It currently conforms to Version 1, and will negotiate support for the corresponding version 0x00000001 -- that is, QUIC Transport version 1. Picoquic will also accept negotiation of previous versions down to draft-27.

Creating QLOG Log Files

See How To Produce QLOG files with picoquic

picoquic's People

Contributors

adventureloop avatar alagoutte avatar alexrabi avatar aneesh-joshi avatar bitfis avatar bkchr avatar clarkzjw avatar cmiller-na avatar davidk-ad8 avatar dbavatar avatar delthas avatar deweerdt avatar ferrieux avatar huitema avatar igorlord avatar ivannardi avatar larseggert avatar lekensteyn avatar levaitamas avatar marcblanchet avatar martinduke avatar msvoelker avatar notbroman avatar paulej avatar pyfisch avatar robertsong2019 avatar steschu77 avatar tatsuhiro-t avatar tbarbette avatar victorstewart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

picoquic's Issues

Number encoding changes in draft-08

Draft-08 is not published yet, but it does incorporate a very big change: PR 877. The coding of integers is unified throughout the specification, using a "self describing" format that can encode numbers in the 0..2^62 - 1 range on 1, 2, 4 or 8 octets. This will affect:

  1. Packet numbers in the packet header;
  2. ACK Frame ID (fixed at 0x0e instead of range) and STREAM Frame ID;
  3. New transport parameter for ACK Delay Exponent;
  4. Encoding of Stream ID in stream related frames
  5. Encoding of Stream Offset in STREAM and Reset frames, and MAX STREAM Data frames
  6. Encoding of reason phrase length in error frames (but NOT the reason code)
  7. Many fields in the ACK frame and STREAM frame

From a spec point of view, this changes only the maximum number of streams, the maximum number of bytes per stream and per connection, and the maximum number of packets per connection. From the code point of view, this is a very big deal.

GET / HTTP/0.9

That's what was sent by mvfst. May want to check that the http09 server supports that syntax.

0-RTT

Will be tested for Interop 3...

Add MTU discovery

Most link MTU are in the1400-1500 bytes range. The default MTU is 1200 bytes. Negotiating the larger MTU would pay off in 5-6 packets, i.e. when sending about 8KB. Better do it...

Detect spurious retransmissions

The current code does not detect spurious retransmissions. This would happen if a packet that is believed lost actually gets acknowledged. Currently, if a packet is believed lost, all traces of it are eliminated. The proposal is no move them from the "retransmit" queue to a new "retransmitted" queue. The life cycle would be:

  • On transmission, packet is added to retransmit queue;
  • Packets in the retransmit queue may be retransmitted if at some point they are believed lost.
  • On retransmission, packet is moved from retransmit queue to retransmitted queue;
  • On ACK, packets in the retransmit queue get processed for ACK-of-ACK or ACK-of-STREAM and recycled.
  • On ACK, packets in the retransmitted queue also get processed for ACK-of-ACK or ACK-of-STREAM and recycled; in addition, they trigger the spurious retransmission logic.
  • On long timer, packets in the retransmitted queue get recycled.

Spurious retransmission indicate a defect in the retransmission logic, caused either by poor timer management or poor estimates of out of sequence deliveries. Some adaptive logic might be needed...

Pacing and better congestion control

The QUIC spec suggests doing pacing of sends, to avoid overloading the network. The current version of Picoquic does not do that -- it implement RENO-like congestion control, meaning that data is sent as soon as the congestion window opens. In theory, this may create peaks of traffic, local congestion, and losses. In practice, it is not clear that it matters all that much.

The implementation of pacing should be part of the performance work. Before we do anything like that, we must instrument the application to detect anomalies like starvation, congestion, packet losses, etc. Then, we have to tune the congestion control and pacing algorithm for performance.

Receive TLS resume session token

Interop with Winquic failed because the TLS code choked on the incoming resume token.

Kazuho suggests looking at code in picotls key/cli.c for examples.

Unify "server clear text" and "client clear text" packet type

The current code distinguished "client" and "server" clear text packet types. This is a legacy of the early QUIC draft. Since draft 08, these two types were unified as a single "handshake" type. Handling a single packet type instead of two would probably make the code simpler.

picoquic replies on the wrong address

A server can, and especially in the case of ipv6 does have multiple addresses. picoquic will have to keep track of which address it is serving data from and reply using that address. I hacked up something quickly for testing v4, but the basic idea is to use cmsg pktinfo to get/set the address

dbavatar@f1db0bd

Spurious retransmission of first packet

During testing of MTU discovery, the client and the server send a first ping packet to test the plausible MTU. I observe that the acknowledgement of that packet arrives very late, causing a spurious retransmission.

Source code formatting

Hi, currently the code is not consistent formatted. Would you be open for a pull request that formats all the code in an uniform way? Maybe with clang-format.

Change stateless reset format.

Move the code to the end, per draft 07.

Need to find a way to also support the draft 05 format as long as we support that version.

Wait for network and console in test app

The current test app is limited. We don't want to block on the UI, but we also want to have a single
threaded app. On Unix, this can be handled by also including FD 0 in the read socket list. But Windows
is different. And it would be nice if we could have some kind of interactive usage.

Many Windows applications solve the problem by using a local UDP socket for communication. But that
will not work for UWP apps, because the local firewall prevents UWP apps from binding to localhost.

What seems lausible is to use a combination of WSAEventSelect and WSAWaitForMultipleEvents.

WSAEventSelect tells Windows to trigger a specific event when an action (e.g., FD_READ) occurs on a
specific socket. The event is associated with the socket, so we can be arbitrarily complex: one event if
data arrives on any socket, or a specific event per socket. Note that there is at most one event per
socket, thus there cannot be different events for read and write.

WSAWaitForMultipleEvents can be used for waiting on multiple events and a timer. One of those event
could be "UI message", allowing for the required wait on console.

The simplest implementation would be to have one UI event and one network event. Set the events and
the FD_masks at the same time. Wait for multiple event for the duration of the select timeout (ms). Then
either return a UI event, or perform the select code to read data, etc.

In our programming paradigm, we use only UDP, and thus do not need to wait on FD_WRITE. This could
provide a simpler model: one event per socket. Set the events, then wait for multiple events. On return
from an event, perform the recvfrom operation on the socket corresponding to the event.

All this supposes getting some kind of background thread reading the console. This is a slight departure
from the single thread model, but the protocol execution would remain single threaded.

Revise stream retransmission logic

The current code has started managing "ACK of STREAM". On reception of packet ACK, it marks the stream bytes in the packet as received. This points to a revision of the stream data retransmission logic.

Currently, retransmission is triggered by packet loss. If the packet carried a stream frame, that stream frame will be retransmitted. This is slightly incorrect, because it does not account for possible redundant transmissions. The minimal fix would be to check whether the stream data was acknowledged before deciding to retransmit it.

There is a more ambitious fix, in which the stream data is retransmitted directly from the stream context. This should be considered later, as part of a "zero copy" effort.

Need to support chacha20, etc

There were several cases of failed interop with clients that did not present P256 initial shares in the client hello. The main issue there is the lack of negotiation, tagged in issue #59. But that would cost one round trip. It would be preferable to actually support the Chacha20 + Poly1305 suite in addition to P256/AES.

Send connection close on protocol error

The current code is a bit confused when it comes to protocol errors. It needs a simple function to mark an error, setting and error reason and moving the connection to a "disconnecting" state. There also need to be a clearer separation between protocol error and internal errors.

Revision of closing states

Draft-08 brings PR #899, which further specifies the way connections are closed. It defines a "closing period" period, during which nodes can retransmit a closing frame, and a "draining period", during which nodes abstain from sending anything, including a stateless reset. While specific to draft-08, the behavior is compatible with previous versions.

Unit test for ack of ack

ACK of ACK code is complicated and some of it may be wrong. Need to write an unit test to check that the code behaves as expected.

Server side session ticket encryption

Using NULL encryption now. That's really just a place holder. There are several plausible strategies. It might be good to provide hooks so different servers can deploy different logic.

Session resume

Will be tested with Interop 3, should be implemented.

Need to flush the server log

Need to flush the server log at the end of each connection, other wise cannot answer
questions. Also, should add initial connection ID to server log messages.

Separate non-crypto random generator

From a security stand point, it is not desirable to use the crypto random generator for "non crypto" fields, because that may leak the state of the random generator, and be used as an attack vector to get the actual secrets. For things like filling random data in stateless reset, random sequence numbers, or even random connection ID, it would be better to use a separate generator.

Multiple ACK in same frame

Doing client tests without sending anything, observe that the server repeats ACK frames, adding another one after each successive repeat.

Make sure that HRR is generated when negotiation requires it

There were several cases of interop failure during the Melbourne interop. The client would announce its support for multiple encryption protocols, but only provide an initial share for a protocol that Picoquic did not support.

The expected reaction is that Picoquic replies with an HRR message, forcing negotiation.

The current reaction is that Picoquic simply fails the connection, and that's wong.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.