Git Product home page Git Product logo

quiche's Introduction

quiche

crates.io docs.rs license build

quiche is an implementation of the QUIC transport protocol and HTTP/3 as specified by the IETF. It provides a low level API for processing QUIC packets and handling connection state. The application is responsible for providing I/O (e.g. sockets handling) as well as an event loop with support for timers.

For more information on how quiche came about and some insights into its design you can read a post on Cloudflare's blog that goes into some more detail.

Who uses quiche?

Cloudflare

quiche powers Cloudflare edge network's HTTP/3 support. The cloudflare-quic.com website can be used for testing and experimentation.

Android

Android's DNS resolver uses quiche to implement DNS over HTTP/3.

curl

quiche can be integrated into curl to provide support for HTTP/3.

NGINX (unofficial)

quiche can be integrated into NGINX using an unofficial patch to provide support for HTTP/3.

Getting Started

Command-line apps

Before diving into the quiche API, here are a few examples on how to use the quiche tools provided as part of the quiche-apps crate.

After cloning the project according to the command mentioned in the building section, the client can be run as follows:

 $ cargo run --bin quiche-client -- https://cloudflare-quic.com/

while the server can be run as follows:

 $ cargo run --bin quiche-server -- --cert apps/src/bin/cert.crt --key apps/src/bin/cert.key

(note that the certificate provided is self-signed and should not be used in production)

Use the --help command-line flag to get a more detailed description of each tool's options.

Configuring connections

The first step in establishing a QUIC connection using quiche is creating a Config object:

let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
config.set_application_protos(&[b"example-proto"]);

// Additional configuration specific to application and use case...

The Config object controls important aspects of the QUIC connection such as QUIC version, ALPN IDs, flow control, congestion control, idle timeout and other properties or features.

QUIC is a general-purpose transport protocol and there are several configuration properties where there is no reasonable default value. For example, the permitted number of concurrent streams of any particular type is dependent on the application running over QUIC, and other use-case specific concerns.

quiche defaults several properties to zero, applications most likely need to set these to something else to satisfy their needs using the following:

Config also holds TLS configuration. This can be changed by mutators on the an existing object, or by constructing a TLS context manually and creating a configuration using with_boring_ssl_ctx_builder().

A configuration object can be shared among multiple connections.

Connection setup

On the client-side the connect() utility function can be used to create a new connection, while accept() is for servers:

// Client connection.
let conn = quiche::connect(Some(&server_name), &scid, local, peer, &mut config)?;

// Server connection.
let conn = quiche::accept(&scid, None, local, peer, &mut config)?;

Handling incoming packets

Using the connection's recv() method the application can process incoming packets that belong to that connection from the network:

let to = socket.local_addr().unwrap();

loop {
    let (read, from) = socket.recv_from(&mut buf).unwrap();

    let recv_info = quiche::RecvInfo { from, to };

    let read = match conn.recv(&mut buf[..read], recv_info) {
        Ok(v) => v,

        Err(e) => {
            // An error occurred, handle it.
            break;
        },
    };
}

Generating outgoing packets

Outgoing packet are generated using the connection's send() method instead:

loop {
    let (write, send_info) = match conn.send(&mut out) {
        Ok(v) => v,

        Err(quiche::Error::Done) => {
            // Done writing.
            break;
        },

        Err(e) => {
            // An error occurred, handle it.
            break;
        },
    };

    socket.send_to(&out[..write], &send_info.to).unwrap();
}

When packets are sent, the application is responsible for maintaining a timer to react to time-based connection events. The timer expiration can be obtained using the connection's timeout() method.

let timeout = conn.timeout();

The application is responsible for providing a timer implementation, which can be specific to the operating system or networking framework used. When a timer expires, the connection's on_timeout() method should be called, after which additional packets might need to be sent on the network:

// Timeout expired, handle it.
conn.on_timeout();

// Send more packets as needed after timeout.
loop {
    let (write, send_info) = match conn.send(&mut out) {
        Ok(v) => v,

        Err(quiche::Error::Done) => {
            // Done writing.
            break;
        },

        Err(e) => {
            // An error occurred, handle it.
            break;
        },
    };

    socket.send_to(&out[..write], &send_info.to).unwrap();
}

Pacing

It is recommended that applications pace sending of outgoing packets to avoid creating packet bursts that could cause short-term congestion and losses in the network.

quiche exposes pacing hints for outgoing packets through the [at] field of the [SendInfo] structure that is returned by the send() method. This field represents the time when a specific packet should be sent into the network.

Applications can use these hints by artificially delaying the sending of packets through platform-specific mechanisms (such as the SO_TXTIME socket option on Linux), or custom methods (for example by using user-space timers).

Sending and receiving stream data

After some back and forth, the connection will complete its handshake and will be ready for sending or receiving application data.

Data can be sent on a stream by using the stream_send() method:

if conn.is_established() {
    // Handshake completed, send some data on stream 0.
    conn.stream_send(0, b"hello", true)?;
}

The application can check whether there are any readable streams by using the connection's readable() method, which returns an iterator over all the streams that have outstanding data to read.

The stream_recv() method can then be used to retrieve the application data from the readable stream:

if conn.is_established() {
    // Iterate over readable streams.
    for stream_id in conn.readable() {
        // Stream is readable, read until there's no more data.
        while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
            println!("Got {} bytes on stream {}", read, stream_id);
        }
    }
}

HTTP/3

The quiche HTTP/3 module provides a high level API for sending and receiving HTTP requests and responses on top of the QUIC transport protocol.

Have a look at the [quiche/examples/] directory for more complete examples on how to use the quiche API, including examples on how to use quiche in C/C++ applications (see below for more information).

Calling quiche from C/C++

quiche exposes a thin C API on top of the Rust API that can be used to more easily integrate quiche into C/C++ applications (as well as in other languages that allow calling C APIs via some form of FFI). The C API follows the same design of the Rust one, modulo the constraints imposed by the C language itself.

When running cargo build, a static library called libquiche.a will be built automatically alongside the Rust one. This is fully stand-alone and can be linked directly into C/C++ applications.

Note that in order to enable the FFI API, the ffi feature must be enabled (it is disabled by default), by passing --features ffi to cargo.

Building

quiche requires Rust 1.66 or later to build. The latest stable Rust release can be installed using rustup.

Once the Rust build environment is setup, the quiche source code can be fetched using git:

 $ git clone --recursive https://github.com/cloudflare/quiche

and then built using cargo:

 $ cargo build --examples

cargo can also be used to run the testsuite:

 $ cargo test

Note that BoringSSL, which is used to implement QUIC's cryptographic handshake based on TLS, needs to be built and linked to quiche. This is done automatically when building quiche using cargo, but requires the cmake command to be available during the build process. On Windows you also need NASM. The official BoringSSL documentation has more details.

In alternative you can use your own custom build of BoringSSL by configuring the BoringSSL directory with the QUICHE_BSSL_PATH environment variable:

 $ QUICHE_BSSL_PATH="/path/to/boringssl" cargo build --examples

Alternatively you can use OpenSSL/quictls. To enable quiche to use this vendor the openssl feature can be added to the --feature list. Be aware that 0-RTT is not supported if this vendor is used.

Building for Android

Building quiche for Android (NDK version 19 or higher, 21 recommended), can be done using cargo-ndk (v2.0 or later).

First the Android NDK needs to be installed, either using Android Studio or directly, and the ANDROID_NDK_HOME environment variable needs to be set to the NDK installation path, e.g.:

 $ export ANDROID_NDK_HOME=/usr/local/share/android-ndk

Then the Rust toolchain for the Android architectures needed can be installed as follows:

 $ rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android

Note that the minimum API level is 21 for all target architectures.

cargo-ndk (v2.0 or later) also needs to be installed:

 $ cargo install cargo-ndk

Finally the quiche library can be built using the following procedure. Note that the -t <architecture> and -p <NDK version> options are mandatory.

 $ cargo ndk -t arm64-v8a -p 21 -- build --features ffi

See build_android_ndk19.sh for more information.

Building for iOS

To build quiche for iOS, you need the following:

  • Install Xcode command-line tools. You can install them with Xcode or with the following command:
 $ xcode-select --install
  • Install the Rust toolchain for iOS architectures:
 $ rustup target add aarch64-apple-ios x86_64-apple-ios
  • Install cargo-lipo:
 $ cargo install cargo-lipo

To build libquiche, run the following command:

 $ cargo lipo --features ffi

or

 $ cargo lipo --features ffi --release

iOS build is tested in Xcode 10.1 and Xcode 11.2.

Building Docker images

In order to build the Docker images, simply run the following command:

 $ make docker-build

You can find the quiche Docker images on the following Docker Hub repositories:

The latest tag will be updated whenever quiche master branch updates.

cloudflare/quiche

Provides a server and client installed in /usr/local/bin.

cloudflare/quiche-qns

Provides the script to test quiche within the quic-interop-runner.

Copyright

Copyright (C) 2018-2019, Cloudflare, Inc.

See COPYING for the license.

quiche's People

Contributors

alpire avatar brbzull0 avatar centminmod avatar dependabot-preview[bot] avatar dependabot[bot] avatar divyabhat1 avatar ebi-yade avatar ehaydenr avatar evanrittenhouse avatar francoismichel avatar ghedo avatar inikulin avatar junhochoi avatar jyn514 avatar kachayev avatar kevinjohna6 avatar lohith-bellad avatar lpardue avatar msoxzw avatar normanmaurer avatar nox avatar nqv avatar psudaemon avatar qdeconinck avatar rreverser avatar schien avatar sile avatar vkrasnov avatar vmatrix1900 avatar xanathar 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  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

quiche's Issues

You can close it after reading it, thanks

You locked conversation, so this is my last open issue here

Another interesting rational for naming

"quiche" for the end user that I am is not easy to remember, to spell and does not convey the information that it's from QUIC phonetically.

Why not just call it:
quick
"quick" is easier to remember, to spell, convey that it is fast (which is the primary goal of QUIC)
And convey phonetically that's it's from quic, which is the most important naming feature

valgrind finds "Invalid read of size 8" in quiche_config_new

(First, I'm perfectly aware that this issue might be caused by something in my end but it doesn't look like that to me.)

I run current curl master built with quiche master in a command line shown below, on an up-to-date Debian Linux 64bit:

$ valgrind ./src/curl --alt-svc altsvc https://quic.tech:8443/ -v -o /dev/null

When the altsvc cache is populated with an h3-22 entry, it uses HTTP/3 to the host and then I get this valgrind report:

==31269== Invalid read of size 8
==31269==    at 0x4D8F5A5: check_free (dlerror.c:188)
==31269==    by 0x4D8FAB1: free_key_mem (dlerror.c:221)
==31269==    by 0x4D8FAB1: __dlerror_main_freeres (dlerror.c:239)
==31269==    by 0x4F38B71: __libc_freeres (in /lib/x86_64-linux-gnu/libc-2.28.so)
==31269==    by 0x482B19E: _vgnU_freeres (vg_preloaded.c:77)
==31269==    by 0x4E09E89: __run_exit_handlers (exit.c:132)
==31269==    by 0x4E09EB9: exit (exit.c:139)
==31269==    by 0x4DF40A1: (below main) (libc-start.c:342)
==31269==  Address 0x577e1f0 is 0 bytes after a block of size 32 alloc'd
==31269==    at 0x483577F: malloc (vg_replace_malloc.c:309)
==31269==    by 0x20E4C4: OPENSSL_malloc (mem.c:106)
==31269==    by 0x214CBA: CRYPTO_set_thread_local (thread_pthread.c:182)
==31269==    by 0x205CB7: err_get_state (err.c:210)
==31269==    by 0x20688D: ERR_put_error (err.c:636)
==31269==    by 0x1FB234: BIO_new_file (file.c:99)
==31269==    by 0x21657F: X509_load_cert_crl_file (by_file.c:250)
==31269==    by 0x21605F: by_file_ctrl (by_file.c:102)
==31269==    by 0x219AD5: X509_LOOKUP_ctrl (x509_lu.c:123)
==31269==    by 0x3C2F5D: X509_STORE_set_default_paths (x509_d2.c:69)
==31269==    by 0x2BDF64: SSL_CTX_set_default_verify_paths (ssl_x509.cc:692)
==31269==    by 0x1E9E25: load_ca_certs (tls.rs:169)
==31269==    by 0x1E9E25: new (tls.rs:140)
==31269==    by 0x1E9E25: new (lib.rs:406)
==31269==    by 0x1E9E25: quiche_config_new (ffi.rs:78)
==31269== 
==31269== Invalid free() / delete / delete[] / realloc()
==31269==    at 0x48369AB: free (vg_replace_malloc.c:540)
==31269==    by 0x4D8FAB9: free_key_mem (dlerror.c:223)
==31269==    by 0x4D8FAB9: __dlerror_main_freeres (dlerror.c:239)
==31269==    by 0x4F38B71: __libc_freeres (in /lib/x86_64-linux-gnu/libc-2.28.so)
==31269==    by 0x482B19E: _vgnU_freeres (vg_preloaded.c:77)
==31269==    by 0x4E09E89: __run_exit_handlers (exit.c:132)
==31269==    by 0x4E09EB9: exit (exit.c:139)
==31269==    by 0x4DF40A1: (below main) (libc-start.c:342)
==31269==  Address 0x577e1d8 is 8 bytes inside a block of size 32 alloc'd
==31269==    at 0x483577F: malloc (vg_replace_malloc.c:309)
==31269==    by 0x20E4C4: OPENSSL_malloc (mem.c:106)
==31269==    by 0x214CBA: CRYPTO_set_thread_local (thread_pthread.c:182)
==31269==    by 0x205CB7: err_get_state (err.c:210)
==31269==    by 0x20688D: ERR_put_error (err.c:636)
==31269==    by 0x1FB234: BIO_new_file (file.c:99)
==31269==    by 0x21657F: X509_load_cert_crl_file (by_file.c:250)
==31269==    by 0x21605F: by_file_ctrl (by_file.c:102)
==31269==    by 0x219AD5: X509_LOOKUP_ctrl (x509_lu.c:123)
==31269==    by 0x3C2F5D: X509_STORE_set_default_paths (x509_d2.c:69)
==31269==    by 0x2BDF64: SSL_CTX_set_default_verify_paths (ssl_x509.cc:692)
==31269==    by 0x1E9E25: load_ca_certs (tls.rs:169)
==31269==    by 0x1E9E25: new (tls.rs:140)
==31269==    by 0x1E9E25: new (lib.rs:406)
==31269==    by 0x1E9E25: quiche_config_new (ffi.rs:78)
==31269== 
==31269== 
==31269== HEAP SUMMARY:
==31269==     in use at exit: 928 bytes in 8 blocks
==31269==   total heap usage: 2,800 allocs, 2,793 frees, 651,598 bytes allocated
==31269== 
==31269== LEAK SUMMARY:
==31269==    definitely lost: 32 bytes in 1 blocks
==31269==    indirectly lost: 712 bytes in 2 blocks
==31269==      possibly lost: 0 bytes in 0 blocks
==31269==    still reachable: 184 bytes in 5 blocks
==31269==                       of which reachable via heuristic:
==31269==                         length64           : 184 bytes in 5 blocks
==31269==         suppressed: 0 bytes in 0 blocks
==31269== Rerun with --leak-check=full to see details of leaked memory
==31269== 
==31269== For lists of detected and suppressed errors, rerun with: -s
==31269== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Willing to test and change things if you have suggestions!

build fails because of empty boringssl directory

Trying to follow the basic initial steps from the README results in this for me:
cargo build --examples Compiling memchr v2.1.3 Compiling regex v1.1.0 Compiling proc-macro2 v0.4.26 Compiling smallvec v0.6.8 Compiling serde v1.0.85 Compiling quiche v0.1.0-alpha1 (/Users/nilsohlmeier/src/quiche) Compiling mio v0.6.16 error: failed to run custom build command for quiche v0.1.0-alpha1 (/Users/nilsohlmeier/src/quiche) process didn't exit successfully:/Users/nilsohlmeier/src/quiche/target/debug/build/quiche-bf91909ae6af1da4/build-script-build` (exit code: 101)
--- stdout
running: "cmake" "/Users/nilsohlmeier/src/quiche/deps/boringssl" "-DCMAKE_INSTALL_PREFIX=/Users/nilsohlmeier/src/quiche/target/debug/build/quiche-cc48053fc76c9015/out" "-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_C_COMPILER=/usr/bin/cc" "-DCMAKE_CXX_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_CXX_COMPILER=/usr/bin/c++" "-DCMAKE_BUILD_TYPE=Debug"

--- stderr
CMake Error: The source directory "/Users/nilsohlmeier/src/quiche/deps/boringssl" does not appear to contain CMakeLists.txt.
Specify --help for usage, or press the help button on the CMake GUI.
thread 'main' panicked at '
command did not execute successfully, got: exit code: 1

build script failed, must exit now', /Users/nilsohlmeier/.cargo/registry/src/github.com-1ecc6299db9ec823/cmake-0.1.35/src/lib.rs:778:5
note: Run with RUST_BACKTRACE=1 for a backtrace.

warning: build failed, waiting for other jobs to finish...
error: build failed`

Apparently the boringssl directory is completely empty:
ls -la deps/boringssl/ total 0 drwxr-xr-x 2 nilsohlmeier staff 64 Jan 22 22:55 . drwxr-xr-x 3 nilsohlmeier staff 96 Jan 22 22:55 ..

cmake and go are available on the system.
Is there maybe a git submodule step missing?

Immutable config when creating new connection?

Looks like Config in Connection::with_tls can be immutable nqv@5bab541.
I'm wondering if it's possible to make it immutable in Connection::new as well (e.g. clone tls::Context or something?).
Asked because while working on the C api, I'm not sure if I can free quiche_config after connection is established

Some examples based tokio?

Thanks for your quic project,awesome, really appreciate it.
Is it possible to have some examples that based on tokio using rust's latest futues/async,not mio using state machine?

Windows native builds fail to find crypto.lib and ssl.lib

I thought is would be "fun" to try and build quiche natively on Windows. After getting a bunch of perequisites installed (mainly for BoringSSL), I tried cargo build and saw a failure about linking crypto.lib and ssl.lib. A snipped build log

Running `rustc --edition=2018 --crate-name quiche src\lib.rs --color always --crate-type lib --crate-type staticlib --crate-type cdylib --emit=dep-info,link -C debuginfo=2 -C metadata=8d06e7d205e490ea --out-dir C:\Users\lucas\dev\GitHub\quiche\target\debug\deps -C incremental=C:\Users\lucas\dev\GitHub\quiche\target\debug\incremental -L dependency=C:\Users\lucas\dev\GitHub\quiche\target\debug\deps --extern lazy_static=C:\Users\lucas\dev\GitHub\quiche\target\debug\deps\liblazy_static-bb983748a81ac3f1.rlib --extern libc=C:\Users\lucas\dev\GitHub\quiche\target\debug\deps\liblibc-017498fec30aa81b.rlib --extern log=C:\Users\lucas\dev\GitHub\quiche\target\debug\deps\liblog-59ca255ca262bf24.rlib --extern ring=C:\Users\lucas\dev\GitHub\quiche\target\debug\deps\libring-8cd0ab404e521245.rlib -L native=C:\Users\lucas\dev\GitHub\quiche\target\debug\build\quiche-ef19236eef6de95c\out/build/crypto -L native=C:\Users\lucas\dev\GitHub\quiche\target\debug\build\quiche-ef19236eef6de95c\out/build/ssl -l static=crypto -l static=ssl -L native=C:\Users\lucas\dev\GitHub\quiche\target\debug\build\ring-7f8077d125f4de1f\out`

error: could not find native static library `crypto`, perhaps an -L flag is missing?

This seems to be an issue caused by the way Cmake is building BoringSSL. The files are actually dumped into a Debug folder e.g.

C:\Users\lucas\dev\GitHub\quiche\target\debug\build\quiche-ef19236eef6de95c\out/build/ssl/Debug

and for the release build, the output is dumped in a RelWithDebInfo folder e.g.

C:\Users\lucas\dev\GitHub\quiche\target\release\build\quiche-ef19276eef6de95c\out/build/ssl/RelWithDebInfo

Hacking these values manually into src/build.rs lets me do a successful build e.g.

let crypto_dir = format!("{}/build/crypto/RelWithDebInfo", bssl_dir);

However, that is not a viable solution.

Create C/C++ bindings

Hi. I am trying to write a video streaming application. It pulls video stream from the camera and encodes it(this part is done in C++) then it will send the encoded data to transport protocol(like quiche). So I need a C++ binding for quiche::send(), quiche::connect(), etc. How can I accomplish that?

error: could not find native static library `crypto`, perhaps an -L flag is missing?

I've come back to my quiche dir since a while of absence and now it fails when I build and I could use your help to fix it. It built before, but no longer for some reason.

I build boringssl in a separate directory and I want quiche to pick it up from there. The boringssl dir works fine to build against for other purposes. It only has static libraries built.

$ QUICHE_BSSL_PATH=$HOME/src/boringssl cargo build
   Compiling quiche v0.1.0-alpha3 (/home/daniel/src/quiche)
error: could not find native static library `crypto`, perhaps an -L flag is missing?

error: aborting due to previous error

error: Could not compile `quiche`.

To learn more, run the command again with --verbose.

Semver issues in Cargo.toml

Non-stable crates can go through breaking changes in new minor versions and shouldn't be set as requiring version "0".

http3-client panicked in MacOS

When running the following command line on MacOS (Mojave), http3-client panicked.
It works fine with Linux (Debian Stretch). Seems caused by 7111856

$ RUST_BACKTRACE=1 target/debug/examples/http3-client https://cloudflare-quic.com
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }', src/libcore/result.rs:997:5
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
   1: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at src/libstd/sys_common/backtrace.rs:59
             at src/libstd/panicking.rs:197
   3: std::panicking::default_hook
             at src/libstd/panicking.rs:211
   4: <std::panicking::begin_panic::PanicPayload<A> as core::panic::BoxMeUp>::get
             at src/libstd/panicking.rs:474
   5: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:381
   6: std::panicking::try::do_call
             at src/libstd/panicking.rs:308
   7: <T as core::any::Any>::type_id
             at src/libcore/panicking.rs:85
   8: <docopt::dopt::Value as core::clone::Clone>::clone
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e/src/libcore/macros.rs:18
   9: <docopt::dopt::Value as core::clone::Clone>::clone
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e/src/libcore/result.rs:798
  10: http3_client::main
             at examples/http3-client.rs:77
  11: std::rt::lang_start::{{closure}}
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e/src/libstd/rt.rs:64
  12: std::panicking::try::do_call
             at src/libstd/rt.rs:49
             at src/libstd/panicking.rs:293
  13: panic_unwind::dwarf::eh::read_encoded_pointer
             at src/libpanic_unwind/lib.rs:87
  14: <std::panicking::begin_panic::PanicPayload<A> as core::panic::BoxMeUp>::get
             at src/libstd/panicking.rs:272
             at src/libstd/panic.rs:388
             at src/libstd/rt.rs:48
  15: std::rt::lang_start
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e/src/libstd/rt.rs:64
  16: http3_client::main

Build fails when used as dependency

The error that occurs:

error[E0423]: expected function, found macro `log::set_boxed_logger`
  --> /Users/x/.cargo/registry/src/github.com-1ecc6299db9ec823/quiche-0.1.0-alpha4/src/ffi.rs:66:5
   |
66 |     log::set_boxed_logger(logger).unwrap();
   |     ^^^^^^^^^^^^^^^^^^^^^ help: use `!` to invoke the macro: `log::set_boxed_logger!`

Steps to reproduce:

mkdir quiche-test
cd quiche-test
cargo init
cargo add [email protected] // adding `quiche = "0.1.0-alpha4"` to Cargo.toml
cargo build

The solution I found, add "std" feature to Cargo.toml (on dependent side, not a quiche):

[dependencies]
log  = { version = "0.4.8", features = ["std"] }
quiche = "0.1.0-alpha4"

Example client requires a 'URL' just to ask for help

The example client needs a second argument just to ask for help

Observed

$ ./target/debug/examples/client -h
Invalid arguments.

Usage: client [options] URL

Workaround using second argument xyz

$ ./target/debug/examples/client -h xyz
Usage: client [options] URL

Options:
  -h --help               Show this screen.
  --http1                 Send HTTP/1.1 request instead of HTTP/0.9.
  --wire-version VERSION  The version number to send to the server [default: babababa].
  --no-verify             Don't verify server's certificate.

Using quiche in Android(Calling quiche from Java)

I would like to use the quiche library in my Android app. I am able to use the NDK toolchain to cross-compile quiche(including boringSSL) for Android. Now I need to create a Java binding. Based on my research, there are 2 ways to call Rust from Java:

  1. JNI (writing it manually or use generation tool)
  2. JNA (which hides all complexity of JNI) but may incur some overhead

Which method is preferred? Is there any other option?

CPP examples fail to compile

When I try to build the CPP version of client and server, make all returns error:

Undefined symbols for architecture x86_64:
  "_SecRandomCopyBytes", referenced from:
      ring::rand::darwin::fill::hf5f04717e928fa1c in libquiche.a(ring-b556caff1d96e9fb.ring.99s7mboi-cgu.7.rcgu.o)
  "_kSecRandomDefault", referenced from:
      ring::rand::darwin::fill::hf5f04717e928fa1c in libquiche.a(ring-b556caff1d96e9fb.ring.99s7mboi-cgu.7.rcgu.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

System: Mac OS 10.14.3

Dependence Android minSdkVersion little higher

Our app minSdkVersion is 16, but libquiche depends on minSdkVersion is 21.
I can not compile my App with libquiche.
Could you please modify it to support minSdkVersion 16?
Because some customers may also use the phone of lower android sdk.
Thank you!

image

curl: quiche_conn_recv() == -10

When I build curl with the current quiche code (git master commit a90de02) (with ./configure --with-quiche=[src] in the curl tree, using current curl git master) on 64 bit Debian Linux and run it like this:

./src/curl --http3-direct https://quic.tech:8443 -v

it ends up getting -10 (QUICHE_ERR_TLS_FAIL) returned from the quiche_conn_recv() function.

I don't understand why and would need some help on how to diagnose and get further on this. Can I get more debug info or logging somehow to better understand the details of this failure?

Am I using the wrong end point for my test?

Why is the Connection boxed by default?

Hey,

I was just skimming over the API and I was wondering why connect and accept return a boxed Connection? Connection is neither a trait object nor dynamically sized, so why the need for the box?

Possible usecases for MaybeUninit?

This commit (f454acc) replaced 2 usages of the now deprecated std::mem::uninitialized() with zero initialized arrays. I think it might be worth investigating if it might be worth it to use MaybeUninit where those where used.

Build error on ununtu 16.04

Hey
I tried to build it in Ubuntu 16.04 and had a few build errors. The sequence of commands used is as follow:
git clone https://github.com/cloudflare/quiche.git
cd quiche/
git submodule update --init
finally
cargo build --examples

Got the following output after that:

    Updating crates.io index
   Compiling proc-macro2 v0.4.30
   Compiling unicode-xid v0.1.0
   Compiling syn v0.15.39
   Compiling arrayvec v0.4.11
   Compiling nodrop v0.1.13
   Compiling libc v0.2.59
   Compiling byteorder v1.3.2
   Compiling cfg-if v0.1.9
   Compiling lazy_static v1.3.0
   Compiling scopeguard v0.3.3
   Compiling serde v1.0.94
   Compiling ryu v1.0.0
   Compiling memoffset v0.2.1
   Compiling memchr v2.2.1
   Compiling cc v1.0.37
   Compiling autocfg v0.1.4
   Compiling rayon-core v1.5.0
   Compiling bitflags v1.1.0
   Compiling ucd-util v0.1.3
   Compiling smallvec v0.6.10
   Compiling unicode-width v0.1.5
   Compiling matches v0.1.8
   Compiling either v1.5.2
   Compiling rand_core v0.4.0
   Compiling log v0.4.7
   Compiling regex v1.1.9
   Compiling itoa v0.4.4
   Compiling quick-error v1.2.2
   Compiling untrusted v0.6.2
   Compiling spin v0.5.0
   Compiling cast v0.2.2
   Compiling utf8-ranges v1.0.3
   Compiling same-file v1.0.4
   Compiling strsim v0.9.2
   Compiling slab v0.4.2
   Compiling percent-encoding v1.0.1
   Compiling termcolor v1.0.5
   Compiling crossbeam-utils v0.6.5
   Compiling thread_local v0.3.6
   Compiling num-traits v0.2.8
   Compiling textwrap v0.11.0
   Compiling unicode-bidi v0.3.4
   Compiling regex-syntax v0.6.8
   Compiling humantime v1.2.0
   Compiling itertools v0.8.0
   Compiling unicode-normalization v0.1.8
   Compiling walkdir v2.2.8
   Compiling rand_core v0.3.1
   Compiling ring v0.14.6
   Compiling cmake v0.1.40
   Compiling crossbeam-queue v0.1.2
   Compiling clap v2.33.0
   Compiling crossbeam-epoch v0.7.1
   Compiling regex-automata v0.1.7
   Compiling rand_xoshiro v0.1.0
   Compiling num_cpus v1.10.1
   Compiling net2 v0.2.33
   Compiling iovec v0.1.2
   Compiling atty v0.2.11
   Compiling rand_os v0.1.3
   Compiling criterion-plot v0.3.1
   Compiling quote v0.6.13
   Compiling quiche v0.1.0-alpha3 (/home/ghost/Desktop/Quiche2/quiche)
   Compiling crossbeam-deque v0.6.3
   Compiling mio v0.6.19
   Compiling csv-core v0.1.6
   Compiling aho-corasick v0.7.4
   Compiling rayon v1.1.0
   Compiling serde_derive v1.0.94
   Compiling env_logger v0.6.2
error[E0658]: use of unstable library feature 'duration_as_u128' (see issue #50202)
    --> src/lib.rs:1536:39
     |
1536 |             let ack_delay = ack_delay.as_micros() as u64 /
     |                                       ^^^^^^^^^

error[E0658]: use of unstable library feature 'duration_as_u128' (see issue #50202)
   --> src/ffi.rs:486:34
    |
486 |         Some(timeout) => timeout.as_nanos() as u64,
    |                                  ^^^^^^^^

error[E0658]: use of unstable library feature 'duration_as_u128' (see issue #50202)
   --> src/ffi.rs:533:25
    |
533 |     out.rtt = stats.rtt.as_nanos() as u64;
    |                         ^^^^^^^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0658`.
error: Could not compile `quiche`.
warning: build failed, waiting for other jobs to finish...
error: build failed

I tried to reinstall rustc and rustup but no luck..

any ideas? I'm sorry if I'm missing something silly.

Fix server timeout caused by a packet loss at Handshake

When some of Handshake packet (especially ack of client) is missing, server still received h3 request and prepare to send response, it's not sent to the client. Also in this situation client sent ack to ack from server of Handshake packet which is not allowed.

Certificate verification fails on Windows native build

The http3-client fails certificate verification when built natively, e.g.

$ http3-client https://cloudflare-quic.com
snip...
[2019-06-15T11:43:24.931343300Z TRACE quiche::tls] error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
[2019-06-15T11:43:24.937788700Z ERROR http3_client] 88dab5f9b993280072028d5b4d34d30a4e3c recv failed: TlsFail

The cert for cloudflare-quic.com is trusted by my machine. So I suspect this is something related to building quiche in a way that properly imports my system trust store.

Publish to crates.io

Would be a nice to consume it through cargo install. Either way it's worth reserving the quiche name while it's available for future use

Error when running on windows

--- stderr
CMake Error at C:/Program Files/CMake/share/cmake-3.15/Modules/FindPackageHandleStandardArgs.cmake:137 (message):
  Could NOT find Perl (missing: PERL_EXECUTABLE)
Call Stack (most recent call first):
  C:/Program Files/CMake/share/cmake-3.15/Modules/FindPackageHandleStandardArgs.cmake:378 (_FPHSA_FAILURE_MESSAGE)
  C:/Program Files/CMake/share/cmake-3.15/Modules/FindPerl.cmake:76 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  CMakeLists.txt:38 (find_package)

When I try to use this library and then run cargo build I get this error. Why does it mention Perl? And is it possible to use this only with rust, or do I need extern C libraries?

  • I use windows, haven't configured anything yet.
fn main() {

}

fn client() {
    let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
    let server_name = "quic.tech";
    let scid = [0xba; 16];
    let mut conn = quiche::connect(Some(&server_name), &scid, &mut config)?;

    loop {
        let mut buf = vec![0;500];

        let write = match conn.send(&mut buf) {
            Ok(v) => v,
            _ => break
        };

        println!("written bytes {:?}", write);
    }
}

fn server() {
    let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
    let scid = [0xba; 16];
    let mut conn = quiche::accept(&scid, None, &mut config)?;

    loop {
        let read = conn.recv(&mut buf).unwrap();
        let received = &mut buf[..read];
        println!("{:?}", received);
    }
}

Install library in `cargo install`

cargo install --path . should install the libquiche.so shared library.

This would simplify packaging for Linux distributions and streamline installation for users.

Provide pkg-config file

Build systems use pkg-config (.pc) files to find and use shared libraries.

For example, curl uses it to search for quiche.

Quiche should provide one so users (such as curl) can find quiche.

An example .pc could be:

prefix=/usr
libdir=${prefix}/lib64
includedir=${prefix}/include

Name: quiche
Description: Savoury implementation of the QUIC transport protocol and HTTP/3
URL: https://github.com/cloudflare/quiche/
Version:  0.1.0-alpha4
Libs: -L${prefix}/lib64 -lquiche
Cflags: -I${prefix}/include

and it would be installed to /usr/${libdir}/pkgconfig/quiche.pc

See https://people.freedesktop.org/~dbn/pkg-config-guide.html for more information.

API: custom pointer per (h3) stream?

When doing multiplexed h3 streams over the same QUIC connection.

It would be helpful for my code (and presumably others') if we could assign an opaque pointer to the h3 stream when such is created, and then quiche could deliver that pointer when it returns events for that stream. It will save me from having to implement the same stream-to-pointer hash lookup.

Send Trait for Connection

I'm trying to use this library from a multi-threaded context.
Is there any particular reason the Connection struct can't implement Send?

[Bug] Long RTT when sending many streams.

Environment setup:
Client sends a new stream every 100ms to server. stream size = 500KB.
Both client and server are running in the same machine.
The RTT printed by quiche trace can be as high as 60+ms. While the TCP running in same machine can keep the RTT as low as 20us.

quiche::recovery: 04a8f6b83afe7a3b5ef959516b05efc0 timer=109.584411ms crypto=0 inflight=952666 cwnd=19135708 latest_rtt=68.657609ms srtt=Some(72.192584ms) min_rtt=546.442µs rttvar=3.136639ms probes=0
sent 1345 bytes
quiche: 04a8f6b83afe7a3b5ef959516b05efc0 tx pkt Short dcid=568e60d761e22d8887f6c95ccb4e893d token=7175696368651002dde97f00000100000000000000008b5209a67eff91b44364dc6c16395b43 key_phase=false len=1326 pn=14983
quiche: 04a8f6b83afe7a3b5ef959516b05efc0 tx frm STREAM id=156 off=421524 len=1301 fin=false
quiche::recovery: 04a8f6b83afe7a3b5ef959516b05efc0 timer=109.544382ms crypto=0 inflight=954011 cwnd=19135708 latest_rtt=68.657609ms srtt=Some(72.192584ms) min_rtt=546.442µs rttvar=3.136639ms probes=0
sent 1345 bytes
quiche: 04a8f6b83afe7a3b5ef959516b05efc0 tx pkt Short dcid=568e60d761e22d8887f6c95ccb4e893d token=7175696368651002dde97f00000100000000000000008b5209a67eff91b44364dc6c16395b43 key_phase=false len=1326 pn=14984

I wonder what leads to the big RTT inflation? Is it due to the splitting of state machine and IO overhead?
I put the test code on my branch long RTT. Feel free to do your own test.

quiche example doesn't work with quinn example and vice versa

This works great in quiche:

cargo run --example server -- --name localhost --root ./
cargo run --example client -- --no-verify https://localhost:4433/Cargo.toml

This works great in quinn:

cargo run --example server ./
cargo run --example client https://localhost:4433/Cargo.toml

But trying to use the quinn client example to talk to the quiche server yields in a timeout from the quinn client, and trying to use the quiche client with the quinn server gives you a "Connection refused" error.
The two clients expose the same behaviour as if the server wasn't present at all.

cc @Ralith @djc

clippy::cast-possible-truncation generates warnings

We don't normally run the rule -W clippy::cast-possible-truncation but if I try we see a few messages such as :

warning: casting u64 to usize may truncate the value on targets with 32-bit wide pointers
   --> src/lib.rs:950:13
    |
950 |             config.local_transport_params.initial_max_streams_bidi as usize,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-W clippy::cast-possible-truncation` implied by `-W clippy::pedantic`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation

warning: casting u64 to usize may truncate the value on targets with 32-bit wide pointers
   --> src/lib.rs:954:13
    |
954 |             config.local_transport_params.initial_max_streams_uni as usize,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation

warning: casting u64 to usize may truncate the value on targets with 32-bit wide pointers
    --> src/lib.rs:1173:13
     |
1173 |             b.get_varint()? as usize
     |             ^^^^^^^^^^^^^^^^^^^^^^^^

example client and server can not establish connection

After fix server build errors(see #94 #93 ), I build the client and server on my Macbook.
I run them using

./server 127.0.0.1 4433
./client 127.0.0.1 4433

But they can not establish connection.
Server side output:

version negotiation
sent 43 bytes
version negotiation
sent 43 bytes
version negotiation
sent 43 bytes
version negotiation
sent 43 bytes
version negotiation
sent 43 bytes
version negotiation
sent 43 bytes
^C

client side output:

quiche::tls: ba8d2efbf34063e8e056a591af8c289e tls write message lvl=Initial len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=babababa dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=0
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=998.279357ms crypto=1200 inflight=1200 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
done writing
quiche: ba8d2efbf34063e8e056a591af8c289e rx pkt VersionNegotiation version=0 dcid=ba8d2efbf34063e8e056a591af8c289e scid=e4b11e80a2f9b9306f9f1fb443f9a776 versions=[ff000016]
done reading
quiche::tls: ba8d2efbf34063e8e056a591af8c289e tls write message lvl=Initial len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=1
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=999.430655ms crypto=1200 inflight=1200 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
done writing
done reading
done writing
quiche: ba8d2efbf34063e8e056a591af8c289e loss detection timeout expired
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e resend unacked crypto data (timer=exp crypto=1200 inflight=1200 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0 )
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=999.595813ms crypto=1200 inflight=1200 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
timeout
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=2
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=1.999590969s crypto=2400 inflight=2400 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
done writing
done reading
done writing
quiche: ba8d2efbf34063e8e056a591af8c289e loss detection timeout expired
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e resend unacked crypto data (timer=exp crypto=2400 inflight=2400 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0 )
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=1.998589366s crypto=2400 inflight=2400 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
timeout
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=3
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=3.999792532s crypto=3600 inflight=3600 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=4
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=3.999825678s crypto=4800 inflight=4800 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
done writing
done reading
done writing
done reading
done writing
quiche: ba8d2efbf34063e8e056a591af8c289e loss detection timeout expired
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e resend unacked crypto data (timer=exp crypto=4800 inflight=4800 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0 )
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=3.996320063s crypto=4800 inflight=4800 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
timeout
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=5
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=7.999690619s crypto=6000 inflight=6000 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=6
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=7.999674743s crypto=7200 inflight=7200 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=7
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=7.999718366s crypto=8400 inflight=8400 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=8
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=7.999777576s crypto=9600 inflight=9600 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
done writing
done reading
done writing
done reading
done writing
done reading
done writing
done reading
done writing
quiche: ba8d2efbf34063e8e056a591af8c289e loss detection timeout expired
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e resend unacked crypto data (timer=exp crypto=9600 inflight=9600 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0 )
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=7.999110019s crypto=9600 inflight=9600 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
timeout
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=9
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=15.99950984s crypto=10800 inflight=10800 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=10
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=15.999658912s crypto=12000 inflight=12000 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=11
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=15.999676497s crypto=13200 inflight=13200 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=1157 pn=12
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=512
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=625
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=15.999546938s crypto=14400 inflight=14400 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 1200 bytes
quiche: ba8d2efbf34063e8e056a591af8c289e tx pkt Initial version=ff000016 dcid=e4b11e80a2f9b9306f9f1fb443f9a776 scid=ba8d2efbf34063e8e056a591af8c289e len=77 pn=13
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm CRYPTO off=0 len=53
quiche: ba8d2efbf34063e8e056a591af8c289e tx frm PADDING len=5
quiche::recovery: ba8d2efbf34063e8e056a591af8c289e timer=15.998600067s crypto=14520 inflight=14520 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
sent 120 bytes
done writing
done reading
done writing
done reading
done writing
done reading
done writing
done reading
done writing
done reading
done writing
^C

It seems like they can not establish connection. What is wrong?

Macros in src/octet.rs may have unexpected unsafe behavior

quiche/src/octets.rs

Lines 69 to 73 in d646a60

unsafe {
let dst = &mut out as *mut $ty as *mut u8;
let off = (mem::size_of::<$ty>() - $len) as isize;
ptr::copy_nonoverlapping(src.as_ptr(), dst.offset(off), $len);

quiche/src/octets.rs

Lines 99 to 103 in d646a60

unsafe {
let src = &<$ty>::to_be($v) as *const $ty as *const u8;
let off = (mem::size_of::<$ty>() - $len) as isize;
ptr::copy_nonoverlapping(src.offset(off), dst.as_mut_ptr(), $len);

These both evaluate some of their parameters in an unsafe block. This allows the callers of these macros to use an unsafe expression there, without needing to specify an unsafe block.

This is almost always unintended (and indeed, there's no comments suggesting it was intended). I'd suggest doing let len = $len; outside of the unsafe block to avoid this.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=578b803a28085939cd5a4791a4fb4dd4 is an example of how this can fail.

use of unstable library feature 'duration_float'

cargo build --examples
Compiling quiche v0.1.0 (/home/pi/quiche-master)
error[E0658]: use of unstable library feature 'duration_float'
--> src/recovery.rs:380:43
|
380 | self.rttvar = self.rttvar.mul_f64(3.0 / 4.0) +
| ^^^^^^^
|
= note: for more information, see rust-lang/rust#54361

error[E0658]: use of unstable library feature 'duration_float'
--> src/recovery.rs:381:49
|
381 | sub_abs(srtt, adjusted_rtt).mul_f64(1.0 / 4.0);
| ^^^^^^^
|
= note: for more information, see rust-lang/rust#54361

error[E0658]: use of unstable library feature 'duration_float'
--> src/recovery.rs:384:26
|
384 | srtt.mul_f64(7.0 / 8.0) + adjusted_rtt.mul_f64(1.0 / 8.0),
| ^^^^^^^
|
= note: for more information, see rust-lang/rust#54361

error[E0658]: use of unstable library feature 'duration_float'
--> src/recovery.rs:384:60
|
384 | srtt.mul_f64(7.0 / 8.0) + adjusted_rtt.mul_f64(1.0 / 8.0),
| ^^^^^^^
|
= note: for more information, see rust-lang/rust#54361

error[E0658]: use of unstable library feature 'duration_float'
--> src/recovery.rs:447:51
|
447 | cmp::max(self.latest_rtt, self.rtt()).mul_f64(TIME_THRESHOLD);
| ^^^^^^^
|
= note: for more information, see rust-lang/rust#54361

error: aborting due to 5 previous errors

For more information about this error, try rustc --explain E0658.
error: Could not compile quiche.

example server can't handle http1

When starting the example client and server with --http1, the server log writes:

[2019-04-05T10:12:45Z INFO  server] 5687c7b0ef36c31903268dfb0ac3e7e8 got GET request for "examples/root/foo HTTP/1.1" ("examples/root/foo HTTP/1.1") on stream 4

We can see that "HTTP/1.1" is taken as part of the path.
I guess that the intention is to strip that off the path.

[Bug] When sending 100K data every 100ms, memory access error happens.

I am testing quiche under different application usage patterns. I find a weird bug under following pattern:

  1. client send HTTP request on different stream every 100ms.
  2. when server receive request, it responses with 100K random data.

Run the test multiple times, you will find following error when processing 29th request:

recv 58 bytes
stream 116 is readable
GET /index.html
AddressSanitizer:DEADLYSIGNAL
=================================================================
==37271==ERROR: AddressSanitizer: SEGV on unknown address 0x000000001218 (pc 0x00010d55ec8c bp 0x7ffee28df530 sp 0x7ffee28df4f0 T0)
==37271==The signal is caused by a READ memory access.
    #0 0x10d55ec8b in quiche::stream::RecvBuf::ready::h40a1ee28a639b042 stream.rs:374
    #1 0x10d55d6d4 in quiche::stream::Stream::readable::he9cf796bf8ad4155 stream.rs:154
    #2 0x10d55d8d0 in _$LT$quiche..stream..Readable$LT$$u27$a$GT$$u20$as$u20$core..iter..iterator..Iterator$GT$::next::h6751a44ad82f9cc6 stream.rs:192
    #3 0x10d556ba8 in quiche_readable_next ffi.rs:440
    #4 0x10d324445 in recv_cb server.c:336
    #5 0x10dc09542 in ev_invoke_pending (libev.4.dylib:x86_64+0x2542)
    #6 0x10dc099c5 in ev_run (libev.4.dylib:x86_64+0x29c5)
    #7 0x10d325d1a in ev_loop ev.h:835
    #8 0x10d3213ca in main server.c:452
    #9 0x7fff6f98c3d4 in start (libdyld.dylib:x86_64+0x163d4)

==37271==Register values:
rax = 0x0000000000001200  rbx = 0x00007ffee28df980  rcx = 0x00007ffee28df001  rdx = 0x0000000000000001
rdi = 0x0000000000000000  rsi = 0x0000000000001200  rbp = 0x00007ffee28df530  rsp = 0x00007ffee28df4f0
 r8 = 0x0000000000000027   r9 = 0x0000000000000000  r10 = 0x00006190003f1a48  r11 = 0x0000000000000028
r12 = 0x00007ffee28df930  r13 = 0x00007ffee28df930  r14 = 0x00007ffee28df7d0  r15 = 0x00007ffee28df850
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV stream.rs:374 in quiche::stream::RecvBuf::ready::h40a1ee28a639b042
==37271==ABORTING
[1]    37271 abort      ./server 4433

The code is shown in my forked repo.

The step to reproduce the bug is as follows:

# use C code
cd examples
make server client
# Run server in terminal 1
./server 4433
# Run client in another terminal
./client 127.0.0.1 4433

Run the test multiple times, you will get the above error.

I can reproduce the bug both on MacOS 10.14.4 and Linux 18.04.

Make project a workspace?

Hey there, while checking the code I saw that there are 2 things that could be used as separate crates, they are the h3 encode/decoder and octets.
What do you think of making this project a workspace and make it build smaller crates that could be published separately?
Let me know if you would like to see that implemented and I can try and make it as a first contribution to the project.

soname versioning

Currently, there's just the library file libquiche.so

It would be better if soname versioning was implemented so libquiche.so is a symlink to, for example, the actual library file named libquiche.so.0.0.0
The library should also have DT_SONAME set appropriately.

Could you please implement soname versioning?

Create release

It's been a while since the last release and there have been some significant changes since then.

Could you please make a new release?

http3-server example on native windows build

Running latest master on Windows, I find that the http3-server.rs example crashes when doing a simple test on 127.0.01. The backtrace points at the line socket.send_to(&out[..write], &peer).unwrap();

@RReverser did you ever try quiche natively on Windows?

C:\Users\lucas\dev\GitHub\quiche>"target/debug/examples/http3-server.exe" --listen 127.0.0.1:4433
[2019-06-01T21:45:54.254247500Z TRACE mio::poll] registering with poller
[2019-06-01T21:45:54.254509800Z TRACE mio::sys::windows::selector] register Token(0) Readable
[2019-06-01T21:45:54.255245800Z TRACE mio::sys::windows::selector] set readiness to (empty)
[2019-06-01T21:45:54.256242500Z TRACE mio::sys::windows::udp] scheduling a read
[2019-06-01T21:45:54.259233900Z TRACE mio::sys::windows::selector] select; timeout=None
[2019-06-01T21:45:54.259233900Z TRACE mio::sys::windows::selector] polling IOCP
[2019-06-01T21:45:56.720233000Z TRACE mio::sys::windows::selector] select; -> got overlapped
[2019-06-01T21:45:56.720233000Z TRACE mio::sys::windows::udp] finished a recv 1200
[2019-06-01T21:45:56.722211900Z TRACE mio::sys::windows::selector] set readiness to Readable
[2019-06-01T21:45:56.722211900Z TRACE mio::sys::windows::selector] returning
[2019-06-01T21:45:56.723394300Z TRACE mio::sys::windows::selector] set readiness to (empty)
[2019-06-01T21:45:56.724216400Z TRACE mio::sys::windows::udp] scheduling a read
[2019-06-01T21:45:56.734439100Z DEBUG http3_server] got 1200 bytes
[2019-06-01T21:45:56.735476100Z TRACE http3_server] got packet Initial version=babababa dcid=7db9b2ea15a41ae97c49562ff0b509cc scid=06641db5127f32f20fdf0b0369239fcd2a22 token=
[2019-06-01T21:45:56.736452700Z WARN  http3_server] Doing version negotiation
[2019-06-01T21:45:56.741790400Z TRACE mio::sys::windows::selector] set readiness to (empty)
[2019-06-01T21:45:56.750760200Z TRACE mio::sys::windows::udp] scheduling a send
[2019-06-01T21:45:56.757742200Z DEBUG http3_server] recv() would block
[2019-06-01T21:45:56.764726100Z TRACE mio::sys::windows::selector] select; timeout=None
[2019-06-01T21:45:56.766724700Z TRACE mio::sys::windows::selector] polling IOCP
[2019-06-01T21:45:56.772197100Z TRACE mio::sys::windows::selector] select; -> got overlapped
[2019-06-01T21:45:56.778186600Z TRACE mio::sys::windows::udp] finished a send 44
[2019-06-01T21:45:56.778186600Z TRACE mio::sys::windows::selector] set readiness to Writable
[2019-06-01T21:45:56.779177400Z TRACE mio::sys::windows::selector] returning
[2019-06-01T21:45:56.788179700Z DEBUG http3_server] timed out
[2019-06-01T21:45:56.789153500Z TRACE mio::sys::windows::selector] select; timeout=None
[2019-06-01T21:45:56.802886300Z TRACE mio::sys::windows::selector] polling IOCP
[2019-06-01T21:45:56.854628300Z TRACE mio::sys::windows::selector] select; -> got overlapped
[2019-06-01T21:45:56.855646000Z TRACE mio::sys::windows::udp] finished a recv 1200
[2019-06-01T21:45:56.860923200Z TRACE mio::sys::windows::selector] set readiness to Readable | Writable
[2019-06-01T21:45:56.861613000Z TRACE mio::sys::windows::selector] returning
[2019-06-01T21:45:56.861613000Z TRACE mio::sys::windows::selector] set readiness to Writable
[2019-06-01T21:45:56.862606600Z TRACE mio::sys::windows::udp] scheduling a read
[2019-06-01T21:45:56.863603700Z DEBUG http3_server] got 1200 bytes
[2019-06-01T21:45:56.864603200Z TRACE http3_server] got packet Initial version=ff000014 dcid=7db9b2ea15a41ae97c49562ff0b509cc scid=06641db5127f32f20fdf0b0369239fcd2a22 token=
[2019-06-01T21:45:56.874334000Z WARN  http3_server] Doing stateless retry
[2019-06-01T21:45:56.878450900Z TRACE mio::sys::windows::selector] set readiness to (empty)
[2019-06-01T21:45:56.880314800Z TRACE mio::sys::windows::udp] scheduling a send
[2019-06-01T21:45:56.887407000Z DEBUG http3_server] recv() would block
[2019-06-01T21:45:56.889291400Z TRACE mio::sys::windows::selector] select; timeout=None
[2019-06-01T21:45:56.891288400Z TRACE mio::sys::windows::selector] polling IOCP
[2019-06-01T21:45:56.901945600Z TRACE mio::sys::windows::selector] select; -> got overlapped
[2019-06-01T21:45:56.902942400Z TRACE mio::sys::windows::udp] finished a send 84
[2019-06-01T21:45:56.913543500Z TRACE mio::sys::windows::selector] set readiness to Writable
[2019-06-01T21:45:56.921259400Z TRACE mio::sys::windows::selector] returning
[2019-06-01T21:45:56.925885600Z DEBUG http3_server] timed out
[2019-06-01T21:45:56.928044600Z TRACE mio::sys::windows::selector] select; timeout=None
[2019-06-01T21:45:56.929041700Z TRACE mio::sys::windows::selector] polling IOCP
[2019-06-01T21:45:56.983124500Z TRACE mio::sys::windows::selector] select; -> got overlapped
[2019-06-01T21:45:56.983257200Z TRACE mio::sys::windows::udp] finished a recv 1200
[2019-06-01T21:45:56.988341300Z TRACE mio::sys::windows::selector] set readiness to Readable | Writable
[2019-06-01T21:45:56.989106500Z TRACE mio::sys::windows::selector] returning
[2019-06-01T21:45:56.989784000Z TRACE mio::sys::windows::selector] set readiness to Writable
[2019-06-01T21:45:56.990151900Z TRACE mio::sys::windows::udp] scheduling a read
[2019-06-01T21:45:57.000907400Z DEBUG http3_server] got 1200 bytes
[2019-06-01T21:45:57.003711900Z TRACE http3_server] got packet Initial version=ff000014 dcid=0fb4280f7fad9fd01e570195cf23022bc393 scid=06641db5127f32f20fdf0b0369239fcd2a22 token=7175696368657f0000017db9b2ea15a41ae97c49562ff0b509cc
[2019-06-01T21:45:57.013065000Z DEBUG http3_server] New connection: dcid=0fb4280f7fad9fd01e570195cf23022bc393 scid=0fb4280f7fad9fd01e570195cf23022bc393
[2019-06-01T21:45:57.015027700Z TRACE quiche] 0fb4280f7fad9fd01e570195cf23022bc393 rx pkt Initial version=ff000014 dcid=0fb4280f7fad9fd01e570195cf23022bc393 scid=06641db5127f32f20fdf0b0369239fcd2a22 token=7175696368657f0000017db9b2ea15a41ae97c49562ff0b509cc len=1129 pn=2
[2019-06-01T21:45:57.026211500Z TRACE quiche] 0fb4280f7fad9fd01e570195cf23022bc393 rx frm CRYPTO off=0 len=512
[2019-06-01T21:45:57.032249200Z TRACE quiche::tls] 0fb4280f7fad9fd01e570195cf23022bc393 tls write message lvl=Initial len=122
[2019-06-01T21:45:57.033212800Z TRACE quiche::tls] 0fb4280f7fad9fd01e570195cf23022bc393 tls set encryption secret lvl=Handshake
[2019-06-01T21:45:57.042167300Z TRACE quiche::tls] 0fb4280f7fad9fd01e570195cf23022bc393 tls set encryption secret lvl=Application
[2019-06-01T21:45:57.045617300Z TRACE quiche::tls] 0fb4280f7fad9fd01e570195cf23022bc393 tls write message lvl=Handshake len=1345
[2019-06-01T21:45:57.051590700Z TRACE quiche] 0fb4280f7fad9fd01e570195cf23022bc393 rx frm PADDING len=596
[2019-06-01T21:45:57.052729200Z DEBUG http3_server] 0fb4280f7fad9fd01e570195cf23022bc393 processed 1200 bytes
[2019-06-01T21:45:57.053584900Z DEBUG http3_server] recv() would block
[2019-06-01T21:45:57.054622000Z TRACE quiche] 0fb4280f7fad9fd01e570195cf23022bc393 tx pkt Initial version=ff000014 dcid=06641db5127f32f20fdf0b0369239fcd2a22 scid=0fb4280f7fad9fd01e570195cf23022bc393 len=148 pn=0
[2019-06-01T21:45:57.055582000Z TRACE quiche] 0fb4280f7fad9fd01e570195cf23022bc393 tx frm ACK delay=5076 blocks=[2..2][2019-06-01T21:45:57.056577100Z TRACE quiche] 0fb4280f7fad9fd01e570195cf23022bc393 tx frm CRYPTO off=0 len=122
[2019-06-01T21:45:57.057575500Z TRACE quiche::recovery] 0fb4280f7fad9fd01e570195cf23022bc393 timer=997.174123ms crypto=194 inflight=194 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
[2019-06-01T21:45:57.058929700Z TRACE mio::sys::windows::selector] set readiness to (empty)
[2019-06-01T21:45:57.062562700Z TRACE mio::sys::windows::udp] scheduling a send
[2019-06-01T21:45:57.063558700Z DEBUG http3_server] 0fb4280f7fad9fd01e570195cf23022bc393 written 194 bytes
[2019-06-01T21:45:57.065556500Z TRACE quiche] 0fb4280f7fad9fd01e570195cf23022bc393 tx pkt Handshake version=ff000014 dcid=06641db5127f32f20fdf0b0369239fcd2a22 scid=0fb4280f7fad9fd01e570195cf23022bc393 len=1151 pn=0
[2019-06-01T21:45:57.067558700Z TRACE quiche] 0fb4280f7fad9fd01e570195cf23022bc393 tx frm CRYPTO off=0 len=1131
[2019-06-01T21:45:57.080512700Z TRACE quiche::recovery] 0fb4280f7fad9fd01e570195cf23022bc393 timer=985.608691ms crypto=1390 inflight=1390 cwnd=14520 latest_rtt=0ns srtt=None min_rtt=0ns rttvar=0ns probes=0
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Kind(WouldBlock)', src\libcore\result.rs:997:5stack backtrace:
   0: std::sys::windows::backtrace::set_frames
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\sys\windows\backtrace\mod.rs:95
   1: std::sys::windows::backtrace::unwind_backtrace
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\sys\windows\backtrace\mod.rs:82
   2: std::sys_common::backtrace::_print
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\sys_common\backtrace.rs:71
   3: std::sys_common::backtrace::print
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\sys_common\backtrace.rs:59
   4: std::panicking::default_hook::{{closure}}
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\panicking.rs:197
   5: std::panicking::default_hook
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\panicking.rs:211
   6: std::panicking::rust_panic_with_hook
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\panicking.rs:474
   7: std::panicking::continue_panic_fmt
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\panicking.rs:381
   8: std::panicking::rust_begin_panic
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\panicking.rs:308
   9: core::panicking::panic_fmt
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libcore\panicking.rs:85
  10: core::result::unwrap_failed<std::io::error::Error>
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libcore\macros.rs:18
  11: core::result::Result<usize, std::io::error::Error>::unwrap<usize,std::io::error::Error>
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libcore\result.rs:798
  12: http3_server::main
             at .\examples\http3-server.rs:336
  13: std::rt::lang_start::{{closure}}<()>
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libstd\rt.rs:64
  14: std::rt::lang_start_internal::{{closure}}
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\rt.rs:49
  15: std::panicking::try::do_call<closure,i32>
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\panicking.rs:293
  16: panic_unwind::__rust_maybe_catch_panic
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libpanic_unwind\lib.rs:87
  17: std::panicking::try
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\panicking.rs:272
  18: std::panic::catch_unwind
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\panic.rs:388
  19: std::rt::lang_start_internal
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\/src\libstd\rt.rs:48
  20: std::rt::lang_start<()>
             at /rustc/3c235d5600393dfe6c36eeed34042efad8d4f26e\src\libstd\rt.rs:64
  21: main
  22: invoke_main
             at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  23: __scrt_common_main_seh
             at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:288
  24: BaseThreadInitThunk
  25: RtlUserThreadStart

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.