Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix http3 client #267

Merged
merged 6 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion main/lib/index.node.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@

// also edit index.types.js
export { HttpServer, Http3Server, Http2Server } from './server.js'
export { WebTransport } from './webtransport.node.js'
export { WebTransport, quicheLoaded } from './webtransport.node.js'
2 changes: 1 addition & 1 deletion main/lib/index.types.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

// both imports from the browser side and for nodes to generate a joint type file
export { HttpServer, Http3Server, Http2Server } from './server.js'
export { WebTransport } from './webtransport.node.js'
export { WebTransport, quicheLoaded } from './webtransport.node.js'

export {
WebTransportPonyfill,
Expand Down
11 changes: 10 additions & 1 deletion main/lib/webtransport.node.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ let Http3WebTransportClientSocket
* @type {new (arg0: import("./types").HttpWebTransportInit) => any}
*/
let Http3WebTransportClient
/**
* @type {boolean}
*/
let quicheLoadedReady
// @ts-ignore
// eslint-disable-next-line no-unused-vars
const quicheLoaded = new Promise((resolve, reject) => {
export const quicheLoaded = new Promise((resolve, reject) => {
// @ts-ignore
import('@fails-components/webtransport-transport-http3-quiche')
.then(
Expand All @@ -39,6 +43,9 @@ const quicheLoaded = new Promise((resolve, reject) => {
resolve(undefined)
}
)
.finally(() => {
quicheLoadedReady = true
})
.catch((error) => {
log('Problem loading http3-quiche transport', error)
reject(error)
Expand Down Expand Up @@ -102,6 +109,8 @@ export class WebTransport extends WebTransportBase {
*/
createClient(args) {
let createUnreliableClient
if (!quicheLoadedReady)
throw new Error('Lib quiche loading attempt did not end')
if (checkQuicheInit) {
createUnreliableClient = function (/** @type {any} */ _client) {
if (
Expand Down
2 changes: 1 addition & 1 deletion main/lib/webtransportbase.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export class WebTransportBase {
* @abstract
*/
startUpConnection({ client, sessionint, ourl }) {
throw new Error('Implement createClient')
throw new Error('Implement startUpConnection')
}

get reliability() {
Expand Down
14 changes: 13 additions & 1 deletion main/old_test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
// this file runs various tests

import { generateWebTransportCertificate } from '../test/fixtures/certificate.js'
import { Http3Server, Http2Server, WebTransport } from '../lib/index.node.js'
import {
Http3Server,
Http2Server,
WebTransport,
quicheLoaded
} from '../lib/index.node.js'
import { echoTestsConnection, runEchoServer } from './testsuite.js'

let http2 = false
Expand All @@ -15,6 +20,13 @@ if (process.argv.some((el) => el === 'http2')) {
}

async function run() {
if (
process.env.USE_HTTP2 !== 'true' &&
process.env.USE_PONYFILL !== 'true' &&
process.env.USE_POLYFILL !== 'true'
) {
await quicheLoaded
}
console.log('try connecting to server that does not exist')
const badClient = new WebTransport('https://127.0.0.1:49823/echo', {
serverCertificateHashes: [
Expand Down
1 change: 1 addition & 0 deletions main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
},
"browser": {
"./test/fixtures/webtransport.js": "./test/fixtures/webtransport.browser.js",
"./test/fixtures/quiche.js": "./test/fixtures/quiche.browser.js",
"./lib/webstreams.js": "./lib/webstreams.browser.js"
}
}
3 changes: 3 additions & 0 deletions main/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ The `WebTransportSession` should behave most like a WebTransport object on the b
### Using a client
The `WebTransport` object for node or the `WebTransportPonyfill`, `WebTransportPolyfill` objects for the browser, behave like the `WebTransport` client object for the browser with few additions and some missing features.

As the http/3 package is loaded dynamically and the WebTransport object is created synchronously, you may want to make sure, that the modules are already loaded. You can do so, by waiting for the promise `quicheLoaded` exported by the package.


## Specification divergence

This module implements parts of the [WebTransport spec](https://datatracker.ietf.org/doc/html/draft-vvv-webtransport-quic-00) but not all of it.
Expand Down
12 changes: 12 additions & 0 deletions main/test/bidirectional-streams.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { readStream } from './fixtures/read-stream.js'
import { writeStream } from './fixtures/write-stream.js'
import { readCertHash } from './fixtures/read-cert-hash.js'
import WebTransport from './fixtures/webtransport.js'
import { quicheLoaded } from './fixtures/quiche.js'
import * as ui8 from 'uint8arrays'
import {
KNOWN_BYTES,
Expand Down Expand Up @@ -38,6 +39,17 @@ describe('bidirectional streams', function () {
// @ts-ignore
delete wtOptions.serverCertificateHashes

// @ts-ignore
beforeEach(async () => {
if (
process.env.USE_HTTP2 !== 'true' &&
process.env.USE_PONYFILL !== 'true' &&
process.env.USE_POLYFILL !== 'true'
) {
await quicheLoaded
}
})

// @ts-ignore
afterEach(async () => {
if (client != null) {
Expand Down
12 changes: 12 additions & 0 deletions main/test/datagrams.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { expect } from './fixtures/chai.js'
import { readStream } from './fixtures/read-stream.js'
import { readCertHash } from './fixtures/read-cert-hash.js'
import { pTimeout } from './fixtures/p-timeout.js'
import { quicheLoaded } from './fixtures/quiche.js'

/**
* @template T
Expand Down Expand Up @@ -32,6 +33,17 @@ describe('datagrams', function () {
// @ts-ignore
delete wtOptions.serverCertificateHashes

// @ts-ignore
beforeEach(async () => {
if (
process.env.USE_HTTP2 !== 'true' &&
process.env.USE_PONYFILL !== 'true' &&
process.env.USE_POLYFILL !== 'true'
) {
await quicheLoaded
}
})

// @ts-ignore
afterEach(async () => {
if (client != null) {
Expand Down
2 changes: 2 additions & 0 deletions main/test/fixtures/quiche.browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const quicheLoaded = Promise.resolve()
export { quicheLoaded }
1 change: 1 addition & 0 deletions main/test/fixtures/quiche.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { quicheLoaded } from '../../lib/index.node.js'
12 changes: 12 additions & 0 deletions main/test/session.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { readCertHash } from './fixtures/read-cert-hash.js'
import WebTransport from './fixtures/webtransport.js'
import { expect } from './fixtures/chai.js'
import { quicheLoaded } from './fixtures/quiche.js'

/**
* @template T
Expand Down Expand Up @@ -38,6 +39,17 @@ describe('session', function () {
// @ts-ignore
delete wtOptions.serverCertificateHashes

// @ts-ignore
beforeEach(async () => {
if (
process.env.USE_HTTP2 !== 'true' &&
process.env.USE_PONYFILL !== 'true' &&
process.env.USE_POLYFILL !== 'true'
) {
await quicheLoaded
}
})

// @ts-ignore
afterEach(async () => {
if (client != null) {
Expand Down
12 changes: 12 additions & 0 deletions main/test/stream-limits.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { readCertHash } from './fixtures/read-cert-hash.js'
import WebTransport from './fixtures/webtransport.js'
import { expect } from './fixtures/chai.js'
import { quicheLoaded } from './fixtures/quiche.js'

/**
* @template T
Expand Down Expand Up @@ -44,6 +45,17 @@ describe('streamlimits', function () {
// @ts-ignore
delete wtOptions.serverCertificateHashes

// @ts-ignore
beforeEach(async () => {
if (
process.env.USE_HTTP2 !== 'true' &&
process.env.USE_PONYFILL !== 'true' &&
process.env.USE_POLYFILL !== 'true'
) {
await quicheLoaded
}
})

// @ts-ignore
afterEach(async () => {
if (client != null) {
Expand Down
12 changes: 12 additions & 0 deletions main/test/unidirectional-streams.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { writeStream } from './fixtures/write-stream.js'
import { readCertHash } from './fixtures/read-cert-hash.js'
import * as ui8 from 'uint8arrays'
import { KNOWN_BYTES, KNOWN_BYTES_LENGTH } from './fixtures/known-bytes.js'
import { quicheLoaded } from './fixtures/quiche.js'

describe('unidirectional streams', function () {
/** @type {import('../lib/dom').WebTransport | undefined} */
Expand All @@ -29,6 +30,17 @@ describe('unidirectional streams', function () {
// @ts-ignore
delete wtOptions.serverCertificateHashes

// @ts-ignore
beforeEach(async () => {
if (
process.env.USE_HTTP2 !== 'true' &&
process.env.USE_PONYFILL !== 'true' &&
process.env.USE_POLYFILL !== 'true'
) {
await quicheLoaded
}
})

// @ts-ignore
afterEach(async () => {
if (client != null) {
Expand Down
13 changes: 5 additions & 8 deletions transports/http3-quiche/src/http3client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ namespace quic
if (wait_for_encryption_)
{
if (EncryptionBeingEstablished())
return false;
return true;
wait_for_encryption_ = false;
ParsedQuicVersion version = UnsupportedQuicVersion();
if (session_ != nullptr && !CanReconnectWithDifferentVersion(&version) && !session_->connection()->connected())
Expand Down Expand Up @@ -569,11 +569,6 @@ namespace quic
recheck = true;
}

if (checkSession())
{
recheck = true;
}

return recheck;
}

Expand Down Expand Up @@ -826,16 +821,18 @@ namespace quic

if (client_->connectionrecheck_)
{
client_->connectionrecheck_ = !client_->handleConnecting();
client_->connectionrecheck_ = client_->handleConnecting();
}
if (client_->needsToCheckForSession()) client_->checkSession();
}

void Http3ClientJS::onCanWrite(const Napi::CallbackInfo &info)
{
if (client_->connectionrecheck_)
{
client_->connectionrecheck_ = !client_->handleConnecting();
client_->connectionrecheck_ = client_->handleConnecting();
}
if (client_->needsToCheckForSession()) client_->checkSession();
client_->OnCanWrite();
}

Expand Down
4 changes: 4 additions & 0 deletions transports/http3-quiche/src/http3client.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ namespace quic

bool checkSession();

bool needsToCheckForSession() {
return finish_stream_open_.size() > 0 && session_->CanOpenNextOutgoingBidirectionalStream();
}

// Read oldest received response and remove it from closed_stream_states_.
// void ReadNextResponse();

Expand Down
Loading