{"id":22281966,"url":"https://github.com/ptrd/kwik","last_synced_at":"2025-10-26T02:08:16.817Z","repository":{"id":37448843,"uuid":"228918951","full_name":"ptrd/kwik","owner":"ptrd","description":"A QUIC client, client library and server implementation in Java. Supports HTTP3 with \"Flupke\" add-on.","archived":false,"fork":false,"pushed_at":"2025-04-16T20:20:04.000Z","size":4989,"stargazers_count":414,"open_issues_count":11,"forks_count":56,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-19T10:16:55.272Z","etag":null,"topics":["http3","java","protocol","quic"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ptrd.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-LESSER.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-12-18T20:46:54.000Z","updated_at":"2025-04-17T16:28:47.000Z","dependencies_parsed_at":"2024-01-01T23:44:19.013Z","dependency_job_id":"aa1e7408-f8bd-4337-86a9-c918f846489b","html_url":"https://github.com/ptrd/kwik","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ptrd%2Fkwik","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ptrd%2Fkwik/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ptrd%2Fkwik/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ptrd%2Fkwik/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ptrd","download_url":"https://codeload.github.com/ptrd/kwik/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471060,"owners_count":22076585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http3","java","protocol","quic"],"created_at":"2024-12-03T16:23:57.431Z","updated_at":"2025-10-26T02:08:16.810Z","avatar_url":"https://github.com/ptrd.png","language":"Java","funding_links":[],"categories":["Java","网络编程"],"sub_categories":[],"readme":"![Kwik](https://bitbucket.org/pjtr/kwik/raw/master/docs/media/Logo_Kwik_rectangle.png)\n\n## A QUIC implementation in Java\n\nKwik is an implementation of the [QUIC](https://en.wikipedia.org/wiki/QUIC) protocol in (100%) Java. \nKwik started as client (library) only, but since May 2021 it supports both client and server.\n\n**If you are upgrading from a version prior to 0.10, read the [CHANGELOG](https://github.com/ptrd/kwik/blob/master/CHANGELOG.md)\nfor upgrade instructions.**\n\nQUIC is a brand-new transport protocol developed by the IETF, and is the transport layer for the (also new) HTTP3 protocol.\nAlthough necessary for HTTP3, QUIC is more than just the transport protocol for HTTP3: most people consider QUIC as the \n\"next generation TCP\". It has similar properties as TCP, e.g. provide a reliable ordered stream, but is better in many ways:\n\n* it can serve multiple streams (concurrently and sequential) over the same QUIC connection\n* it does not suffer from the \"head of line blocking\" problem \n* it's encrypted and secured by TLS (not as a separate layer, but embedded in the protocol)\n* it requires at most only one network roundtrip to setup the connection (the combination of TCP and TLS needs much more)\n\nIf you want to know more about QUIC and are able to understand the dutch language, check out\nmy [presentation on Luminis DevCon 2019](https://youtu.be/eR2tPOLQRws). \n\nIf you're looking for a Java HTTP3 client or server, check out [Flupke](https://github.com/ptrd/flupke), which is built on top of Kwik.\n\nKwik is created and maintained by Peter Doornbosch. \nThe latest greatest can always be found on [BitBucket](https://bitbucket.org/pjtr/kwik)\nor [GitHub](https://github.com/ptrd/kwik).\n\n\n## Status\n\nKwik implements all QUIC features, except that the server does not yet support connection migration (work in progress).\nWith respect to the interface Kwik offers to applications, it provides all necessary operations to exchange data, but\nit does not support specifying stream priorities.\nFor both roles, interoperability is tested with a large number of other implementations, see [automated interoperability tests](https://interop.seemann.io/). \nDue to the fact that most implementations are still in active development, and that some test cases\n(specifically testing behaviour in the context of packet loss and packet corruption) are non-deterministic, the results of the automatic\ninteroperability test vary with each run, but usually, Kwik is amongst the best w.r.t. the number of successful testcases.  \n\nKwik is still in active development, see [git history](https://github.com/ptrd/kwik/commits/master/). \n\nHTTP3 on top of Kwik is supported by [Flupke, the pure Java HTTP3 implementation](https://github.com/ptrd/flupke).\n\nKwik supports QUIC v1 ([RFC 9000](https://www.rfc-editor.org/rfc/rfc9000.html))\nand QUIC v2 ([RFC 9369](https://www.rfc-editor.org/rfc/rfc9369.html)).\n\n\n### Implemented QUIC features\n\n* (QUIC v1) version negotiation\n* handshake based on TLS 1.3\n* data exchange over bidirectional and unidirectional streams\n* stateless retry\n* cipher suites TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384 and TLS_CHACHA20_POLY1305_SHA256\n* key update\n* session resumption\n* 0-RTT\n* Compatible Version Negotiation [RFC 9368](https://www.rfc-editor.org/rfc/rfc9368.html)\n* QUIC V2 [RFC 9369](https://www.rfc-editor.org/rfc/rfc9369.html)\n* Unreliable Datagram Extension [RFC 9221](https://www.rfc-editor.org/rfc/rfc9221.html)\n  \nClient only:\n\n* connection migration (use the interactive mode of the sample client to try it)\n\n\n### Is Kwik ready for production use?\n\nIt really depends on your use-case. \nFirst of all, as with all open source software, there is no guarantee the software will work, it is provided \"as is\".\nHaving said that, interoperability with other implementations is heavily tested and ok, so you can assume it works.\nHowever, Kwik is not tested in various or extreme networking conditions, so your mileage may vary.  \nAs development focus has been on correctness and features (in that order), performance is not optimal yet.\n\nKwik does not yet implement all QUIC requirements. Specifically, it does not enable applications or application \nprotocols to specify the relative priority of streams. Note that this will not introduce interoperability issues,\nbecause the concept of priorities only exists in a peer; it does not affect the wire protocol. However, the division of\nnetwork capacity over streams cannot be influenced and might not even be fair (although in practice it probably will).\nWhen wondering whether limitations would harm your use case: just go ahead and test it! When in doubt, you can \nalways contact the author (see contact details below) for more information or help.\n\n\n### Is Kwik secure?\n\nThe TLS library used by Kwik is also \"home made\". Although all security features are implemented (e.g. certificates are\nchecked as well as the Certificate Verify message that proofs possession of the certificate private key), and only\ncrypto algorithms provided by the JDK are used, it is not security tested nor reviewed by security experts. \nSo if you plan to transfer sensitive data or are afraid of intelligence\nservices trying to spy on you, using Kwik is probably not the best idea.\n\n## Usage\n\n### Maven\n\nKwik is available in the Maven Central Repository. To use it in your project, add the following dependency to your pom.xml:\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003etech.kwik\u003c/groupId\u003e\n        \u003cartifactId\u003ekwik\u003c/artifactId\u003e\n        \u003cversion\u003e0.10.3\u003c/version\u003e\n    \u003c/dependency\u003e\n\n### Java Module System\n\nThe following Kwik artifacts define a Java module with the given name:\n- kwik: `tech.kwik.core`\n- kwik-h09: `tech.kwik.h09`\n- kwik-qlog: `tech.kwik.qlog`\n- kwik-samples: `tech.kwik.samples`\n\n### Client\n\nTo connect to a QUIC server, first create a connection object with the builder, e.g.\n\n    String applicationProtocolId = \"....\";\n    QuicClientConnection connection = QuicClientConnection.newBuilder()\n            .uri(URI.create(\"https://sample.com:443\"))\n            .applicationProtocol(applicationProtocolId)\n            .build();\n\nYou need to provide the ALPN protocol ID of the application protocol that you want to run on top of QUIC (and that the\nserver you connect to supports). On the connection object simply call `connect()`:\n\n    connection.connect();\n\nOnce connected, you can create a stream and start sending/receiving data, e.g.\n\n    QuicStream quicStream = connection.createStream(true);\n    OutputStream output = quicStream.getOutputStream();\n    output.write(...)\n    output.close();\n    InputStream input = quicStream.getInputStream();\n    input.read(...)\n    \nAs QUIC servers generally limit the number of streams that clients can open concurrently, it is wise to close streams\nwhen not used anymore. Kwik does this automatically when you `close()` the `OutputStream` and read *all* data from the\n`InputStream`. If, for some reason, you do not read all data from the `InputStream`, call `QuicStream.abortReading()`\nto free resources and let the server you know you abandoned the stream.\n\nWhen, for example with local development, the server uses self-signed certificates, you need to disable certificate\nchecking. The builder has a method for this:\n\n    builder.noServerCertificateCheck()\n\nThe builder has a lot more methods for configuring the connection, most of which are self-explanatory; see the [Builder interface in QuicClientConnection](https://github.com/ptrd/kwik/blob/master/core/src/main/java/tech/kwik/core/QuicClientConnection.java#L77).\n\nThe builder method `logger()` requires an implementation of the [Logger interface](https://github.com/ptrd/kwik/blob/master/core/src/main/java/tech/kwik/core/log/Logger.java); Kwik provides two convenient implementations\nthat you can use: `SysOutLogger` and `FileLogger`. Various log categories can be enabled or disabled by the \n`logXXX()` methods, e.g. `logger.logInfo(true)`.\n\nTake a look at the samples in the [sample package](https://github.com/ptrd/kwik/tree/master/samples/src/main/java/tech/kwik/sample)\nfor more inspiration.\n\n### Server\n\nCreating a QUIC server with Kwik consist of a few steps. First you need to create an application protocol handler by\nimplementing the [ApplicationProtocolConnectionFactory](https://github.com/ptrd/kwik/blob/master/core/src/main/java/tech/kwik/core/server/ApplicationProtocolConnectionFactory.java) interface. Its `createConnection` method should return an implementation of [ApplicationProtocolConnection](https://github.com/ptrd/kwik/blob/master/core/src/main/java/tech/kwik/core/server/ApplicationProtocolConnection.java) that, as the name suggests,\nrepresents your application protocol connection. It's `acceptPeerInitiatedStream` method is the handler that is called by \nKwik when a client initiates a stream for the given protocol. The implementation of this `acceptPeerInitiatedStream` method\nshould start a stream handler, but should itself return immediately, as it is called on the thread that handles\nincoming QUIC messages. If, for example, your application protocol follows the request-response model, the stream handler\nreads the request from the QUIC stream, processes it, creates a response, writes the response to the QUIC stream and closes the stream.\n\nTo complete the `ApplicationProtocolConnectionFactory` you should at least override the following two methods of the\n[ApplicationProtocolSettings](https://github.com/ptrd/kwik/blob/master/core/src/main/java/tech/kwik/core/server/ApplicationProtocolSettings.java) \ninterface:\n\n    int maxConcurrentPeerInitiatedUnidirectionalStreams()\n    int maxConcurrentPeerInitiatedBidirectionalStreams()\n\nThese methods communicate to Kwik how many (concurrent) streams the protocol needs. In most cases, these methods return either 0 or Long.MAX_VALUE,\nto indicate that unidirectional or bidirectional streams are used (Long.MAX_VALUE) or are not used (value 0) by the application protocol.\nSome protocols define an exact number of unidirectional streams to be used as control stream, for example HTTP/3 needs 3 unidirectional streams, no more, no less.\nIn such cases, the `maxConcurrentUnidirectionalStreams` method should return the exact number.\n\nOnce you have a proper implementations of `ApplicationProtocolConnectionFactory` and `ApplicationProtocolConnection`, \nyou can create a `ServerConnector` and register the `ApplicationProtocolConnectionFactory`. The `ServerConnector` listens \nfor new connections on a given port and handles them according to protocols that are registered on it. \n\nThe `ServerConnector` needs a server certificate and the corresponding private key for authentication. The preferred way\nto provide these, is via a Java `KeyStore` object. However, if your server certificate is of type RSA you can still use the\n(now deprecated) method that takes `FileInputStream`'s for both the certificate and the private key.\n\nIt is not possible to create a Java KeyStore directly from a certificate file in PEM format, but there is a work-around\nusing a .p12. For example, if your certificate is stored in PEM format in `cert.pem` and its corresponding private key in\n'key.pem', you can create a Java KeyStore file with\n\n    openssl pkcs12 -export -clcerts -in cert.pem -inkey key.pem -name servercert -out cert.p12\n    keytool -keystore cert.jks -importkeystore -srckeystore cert.p12 -srcstoretype PKCS12 -deststorepass secret -srcstorepass secret\n\nresulting in a KeyStore file named 'cert.jks', containing the given server certificate with alias `servercert` and `secret` \nas the value for both the container and the key password.\n\nTo create a `ServerConnector`, use the builder, e.g.\n\n    ServerConnector serverConnector = ServerConnector.builder()\n            .withPort(443)\n            .withKeyStore(keyStore, \"servercert\", \"secret\".toCharArray())\n            .withConfiguration(serverConnectionConfig)\n            .withLogger(log)\n            .build(); \n\nregister your protocol handler:\n\n    serverConnector.registerApplicationProtocol(\"myapplicationprotocol\", new MyApplicationProtocolConnectionFactory);\n\nand start the connector:\n\n    serverConnector.start();\n\nThe `serverConnectionConfig` that is needed by the `ServerConnector.Builder` defines the configuration for your server. \nFor most settings you can get away with the defaults, except for one thing: you need to specify how many streams\nthe client is allowed to have open *concurrently* in one QUIC connection. A larger value means your client(s) can\ndo more work in parallel, but also can claim more resources. So `infinite` would be a bad choice, as that would make your\nserver an easy victim for a denial of service attack. Furthermore: only allow the type of stream (unidirectional or bidirectional)\nthat you actually support in the application protocol handler; again, if you fail to do so, you give attackers a change\nto claim resources that are not used. For example, if your application protocol does not use unidirectional streams, \njust don't set `maxOpenUnidirectionalStreams` as the default is 0, and provide a valid value for bidirectional streams, e.g.\n\n    ServerConnectionConfig.builder()\n            .maxOpenPeerInitiatedBidirectionalStreams(50)  // Mandatory setting to maximize concurrent streams on a connection.\n            .build();\n\nThat concludes creating a server. You can find working examples in the\n[sample directory](https://github.com/ptrd/kwik/tree/master/samples/src/main/java/tech/kwik/sample).\n\n\n\n### Development\n\nTo build the project:\n\n- clone the git repository and cd into the directory\n- build with gradle wrapper: `./gradlew build` (or `gradlew.bat build` on Windows).\n\nGradle will write the output to each submodule's `build/libs` directory, e.g. the core library can be found\nin `core/build/libs`.\n\nTo use IntelliJ for development, either just open the project directory in IntelliJ and it will pick up the gradle file,\nor generate IntelliJ project files with `gradle idea` and open the generated kwik.ipr file. The second option will\ngive a better developer experience.\n\n\n### Sample Client\n\nKwik also provides a command line client that can be used to experiment with the QUIC protocol and\neven provides an interactive shell for more QUIC fun.\n\nTo run the sample client, execute the `kwik.sh` script,\nor unzip the cli distribution file in `cli/build/distributions/kwik-cli-*.zip` and run `kwik-cli` or `kwik-cli.bat`.\nIn the latter case, the client will not support HTTP/3, as the run script in the distribution does not have `flupke.jar`\non the classpath (but of course you can modify to script to add that).\nYou can also run the client with `gradle run` (after `cd`-ing to the `cli` directory), but than you have to pass\nthe command line args for the Kwik cli as `--args='-T -H /index.html example.com 4433'`. This option also lacks HTTP/3 support.\n\nUsage of the sample client:\n\n    kwik \u003chost\u003e:\u003cport\u003e OR quic \u003chost\u003e \u003cport\u003e OR kwik http[s]://host:port\n     -A,--alpn \u003carg\u003e                set alpn (default is hq-xx)\n        --aes128gcm                 use AEAD_AES_128_GCM cipher suite\n        --aes256gcm                 use AEAD_AES_256_GCM cipher suite\n     -c,--connectionTimeout \u003carg\u003e   connection timeout in seconds\n        --chacha20                  use ChaCha20 as only cipher suite     \n        --clientCertificate \u003carg\u003e   certificate (file) for client\n                                    authentication\n        --clientKey \u003carg\u003e           private key (file) for client certificate\n     -h,--help                      show help\n     -H,--http \u003carg\u003e                send HTTP GET request, arg is path, e.g.\n                                    '/index.html'\n     -i,--interactive               start interactive shell\n        --initialRtt \u003carg\u003e          custom initial RTT value (default is 500)\n     -k,--keepAlive \u003carg\u003e           connection keep alive time in seconds\n     -l,--log \u003carg\u003e                 logging options: [pdrcsiRSD]: (p)ackets\n                                    received/sent, (d)ecrypted bytes, (r)ecovery,\n                                    (c)ongestion control, (s)tats, (i)nfo, (R)aw\n                                    bytes, (S)ecrets, (D)ebug; default is \"ip\", use\n                                    (n)one to disable\n     -L,--logFile \u003carg\u003e             file to write log message too\n        --noCertificateCheck        do not check server certificate\n     -O,--output \u003carg\u003e              write server response to file\n     -R,--resumption key \u003carg\u003e      session ticket file\n        --reservedVersion           use reserved version to trigger version\n     -S,--storeTickets \u003carg\u003e        basename of file to store new session tickets\n        --saveServerCertificates \u003carg\u003e   store server certificates in given file\n        --secrets \u003carg\u003e             write secrets to file (Wireshark format)\n     -T,--relativeTime              log with time (in seconds) since first packet \n     -v,--version                   show Kwik version\n     -v1                            use Quic version 1           \n     -v1v2                          use Quic version 1, request version 2\n     -v2                            use Quic version 2\n     -Z,--use0RTT                   use 0-RTT if possible (requires -H and -R)\n            \nIf you do not provide the `--http` or the `--keepAlive` option, the Quic connection will be closed immediately after setup.\n\nPlain Kwik will use HTTP 0.9 for http requests. However, if the flupke.jar is on the classpath (when using\nthe kwik.sh script, it will try to load the plugin from the `libs` directory), it will use Flupke HTTP3 client for the\nHTTP request.\n\n### Sample Server\n\nTo run the demo web server, execute `tech.kwik.sample.SampleWebServer` with the following arguments:\n- certificate file\n- private key file\n- port number\n- www directory to serve\nor\n- keystore file containing (only) the server certificate and key\n- keystore password (which should match the key password)\n- port number\n- www directory to serve\n\nThis will start the server in retry-mode (see https://www.rfc-editor.org/rfc/rfc9000.html#name-address-validation-using-re).\nTo run without retry-mode, add the `--noRetry` flag as first argument.\n\n\n## Adding HTTP/3 Support to Kwik client or server.\n\nA plain Kwik client or server will only provide \"HTTP/0.9\", which is a very simplified form of HTTP/1, which the QUIC implementors\nhave been using for early testing. \n\nTo add HTTP/3 to Kwik you should use the flupke plugin `flupke.jar`, which you can download \nfrom [Maven](https://search.maven.org/artifact/tech.kwik/flupke), and add it to the run classpath.\n                                \n## Contact\n\nIf you have questions about this project, please mail the author (peter dot doornbosch) at luminis dot eu.\n\n## Acknowledgements\n\nThanks to Piet van Dongen for creating the marvellous logo!\n\n## License\n\nThis program is open source and licensed under LGPL (see the LICENSE.txt and LICENSE-LESSER.txt files in the distribution). \nThis means that you can use this program for anything you like, and that you can embed it as a library in other applications, even commercial ones. \nIf you do so, the author would appreciate if you include a reference to the original.\n \nAs of the LGPL license, all modifications and additions to the source code must be published as (L)GPL as well.\n\nIf you want to use the source with a different open source license, contact the author.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fptrd%2Fkwik","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fptrd%2Fkwik","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fptrd%2Fkwik/lists"}