Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Merge branch 'master' into increaseWindowUpdate
Browse files Browse the repository at this point in the history
  • Loading branch information
mosuem authored Jun 12, 2024
2 parents f1b25be + 5bf22ef commit 4916814
Show file tree
Hide file tree
Showing 41 changed files with 542 additions and 250 deletions.
4 changes: 4 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ updates:
interval: monthly
labels:
- autosubmit
groups:
github-actions:
patterns:
- "*"
15 changes: 15 additions & 0 deletions .github/workflows/health.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Health

on:
pull_request:
branches: [ master ]
types: [opened, synchronize, reopened, labeled, unlabeled]

jobs:
health:
uses: dart-lang/ecosystem/.github/workflows/health.yaml@main
with:
coverage_web: false
sdk: dev
permissions:
pull-requests: write
37 changes: 37 additions & 0 deletions .github/workflows/no-response.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# A workflow to close issues where the author hasn't responded to a request for
# more information; see https://github.com/actions/stale.

name: No Response

# Run as a daily cron.
on:
schedule:
# Every day at 8am
- cron: '0 8 * * *'

# All permissions not specified are set to 'none'.
permissions:
issues: write
pull-requests: write

jobs:
no-response:
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'dart-lang' }}
steps:
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e
with:
# Don't automatically mark inactive issues+PRs as stale.
days-before-stale: -1
# Close needs-info issues and PRs after 14 days of inactivity.
days-before-close: 14
stale-issue-label: "needs-info"
close-issue-message: >
Without additional information we're not able to resolve this issue.
Feel free to add more info or respond to any questions above and we
can reopen the case. Thanks for your contribution!
stale-pr-label: "needs-info"
close-pr-message: >
Without additional information we're not able to resolve this PR.
Feel free to add more info or respond to any questions above.
Thanks for your contribution!
17 changes: 17 additions & 0 deletions .github/workflows/post_summaries.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Comment on the pull request

on:
# Trigger this workflow after the Health workflow completes. This workflow will have permissions to
# do things like create comments on the PR, even if the original workflow couldn't.
workflow_run:
workflows:
- Health
- Publish
types:
- completed

jobs:
upload:
uses: dart-lang/ecosystem/.github/workflows/post_summaries.yaml@main
permissions:
pull-requests: write
17 changes: 17 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# A CI configuration to auto-publish pub packages.

name: Publish

on:
pull_request:
branches: [ master ]
push:
tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ]

jobs:
publish:
if: ${{ github.repository_owner == 'dart-lang' }}
uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main
permissions:
id-token: write # Required for authentication using OIDC
pull-requests: write # Required for writing the pull request note
10 changes: 5 additions & 5 deletions .github/workflows/test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ jobs:
matrix:
sdk: [dev]
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
- uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
- uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30
with:
sdk: ${{ matrix.sdk }}
- id: install
Expand All @@ -47,10 +47,10 @@ jobs:
matrix:
# Add macos-latest and/or windows-latest if relevant for this package.
os: [ubuntu-latest]
sdk: [2.17.0, dev]
sdk: [3.2, dev]
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
- uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
- uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30
with:
sdk: ${{ matrix.sdk }}
- id: install
Expand Down
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
## 2.0.2-dev
## 2.3.1-wip

- Require Dart 3.2
- Add topics to `pubspec.yaml`

## 2.3.0

- Only send updates on frames and pings being received when there are listeners, as to not fill up memory.

## 2.2.0

- Transform headers to lowercase.
- Expose pings to connection to enable the KEEPALIVE feature for gRPC.

## 2.1.0

- Require Dart `3.0.0`
- Require Dart `2.17.0`.
- Send `WINDOW_UPDATE` frames for the connection to account for data being sent on closed streams until the `RST_STREAM` has been processed.

## 2.0.1

Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,32 @@ import 'dart:io';
import 'package:http2/http2.dart';
main() async {
var uri = Uri.parse('https://www.google.com/');
Future<void> main() async {
final uri = Uri.parse('https://www.google.com/');
var transport = new ClientTransportConnection.viaSocket(
final transport = ClientTransportConnection.viaSocket(
await SecureSocket.connect(
uri.host,
uri.port,
supportedProtocols: ['h2'],
),
);
var stream = transport.makeRequest(
final stream = transport.makeRequest(
[
new Header.ascii(':method', 'GET'),
new Header.ascii(':path', uri.path),
new Header.ascii(':scheme', uri.scheme),
new Header.ascii(':authority', uri.host),
Header.ascii(':method', 'GET'),
Header.ascii(':path', uri.path),
Header.ascii(':scheme', uri.scheme),
Header.ascii(':authority', uri.host),
],
endStream: true,
);
await for (var message in stream.incomingMessages) {
if (message is HeadersStreamMessage) {
for (var header in message.headers) {
var name = utf8.decode(header.name);
var value = utf8.decode(header.value);
final name = utf8.decode(header.name);
final value = utf8.decode(header.value);
print('Header: $name: $value');
}
} else if (message is DataStreamMessage) {
Expand Down
12 changes: 3 additions & 9 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
include: package:lints/recommended.yaml
# https://dart.dev/tools/analysis#the-analysis-options-file
include: package:dart_flutter_team_lints/analysis_options.yaml

analyzer:
language:
strict-casts: true
errors:
unused_element: error
unused_import: error
unused_local_variable: error
dead_code: error

linter:
rules:
# Disabled as there are several dozen violations.
constant_identifier_names: false
constant_identifier_names: ignore
4 changes: 4 additions & 0 deletions example/display_headers.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:io';
Expand Down
2 changes: 1 addition & 1 deletion lib/multiprotocol_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class MultiProtocolHttpServer {
///
/// See also [startServing].
static Future<MultiProtocolHttpServer> bind(
address, int port, SecurityContext context,
Object? address, int port, SecurityContext context,
{http2.ServerSettings? settings}) async {
context.setAlpnProtocols(['h2', 'h2-14', 'http/1.1'], true);
var secureServer = await SecureServerSocket.bind(address, port, context);
Expand Down
12 changes: 3 additions & 9 deletions lib/src/async_utils/async_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,9 @@ class BufferedSink {
bufferIndicator.markBuffered();

_controller
..onListen = () {
bufferIndicator.markUnBuffered();
}
..onPause = () {
bufferIndicator.markBuffered();
}
..onResume = () {
bufferIndicator.markUnBuffered();
}
..onListen = bufferIndicator.markUnBuffered
..onPause = bufferIndicator.markBuffered
..onResume = bufferIndicator.markUnBuffered
..onCancel = () {
// TODO: We may want to propagate cancel events as errors.
// Currently `_doneFuture` will just complete normally if the sink
Expand Down
47 changes: 32 additions & 15 deletions lib/src/connection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ abstract class Connection {

final Completer<void> _onInitialPeerSettingsReceived = Completer<void>();

final StreamController<int> _pingReceived = StreamController<int>();

final StreamController<void> _frameReceived = StreamController<void>();

/// Future which completes when the first SETTINGS frame is received from
/// the peer.
Future<void> get onInitialPeerSettingsReceived =>
Expand Down Expand Up @@ -179,12 +183,12 @@ abstract class Connection {
// Setup handlers.
_settingsHandler = SettingsHandler(_hpackContext.encoder, _frameWriter,
acknowledgedSettings, peerSettings);
_pingHandler = PingHandler(_frameWriter);
_pingHandler = PingHandler(_frameWriter, _pingReceived);

var settings = _decodeSettings(settingsObject);

// Do the initial settings handshake (possibly with pushes disabled).
_settingsHandler.changeSettings(settings).catchError((error) {
_settingsHandler.changeSettings(settings).catchError((Object error) {
// TODO: The [error] can contain sensitive information we now expose via
// a [Goaway] frame. We should somehow ensure we're only sending useful
// but non-sensitive information.
Expand Down Expand Up @@ -267,15 +271,15 @@ abstract class Connection {
}

/// Pings the remote peer (can e.g. be used for measuring latency).
Future ping() {
Future<void> ping() {
return _pingHandler.ping().catchError((e, s) {
return Future.error(
return Future<void>.error(
TransportException('The connection has been terminated.'));
}, test: (e) => e is TerminatedException);
}

/// Finishes this connection.
Future finish() {
Future<void> finish() {
_finishing(active: true);

// TODO: There is probably more we need to wait for.
Expand All @@ -284,8 +288,8 @@ abstract class Connection {
}

/// Terminates this connection forcefully.
Future terminate() {
return _terminate(ErrorCode.NO_ERROR);
Future<void> terminate([int? errorCode]) {
return _terminate(errorCode ?? ErrorCode.NO_ERROR);
}

void _activeStateHandler(bool isActive) =>
Expand Down Expand Up @@ -340,6 +344,9 @@ abstract class Connection {
frame.decodedHeaders =
_hpackContext.decoder.decode(frame.headerBlockFragment);
}
if (_frameReceived.hasListener) {
_frameReceived.add(null);
}

// Handle the frame as either a connection or a stream frame.
if (frame.header.streamId == 0) {
Expand Down Expand Up @@ -434,16 +441,15 @@ abstract class Connection {
_settingsHandler.terminate(exception);

return Future.wait([cancelFuture, closeFuture])
.catchError((_) => const []);
.catchError((_) => const <void>[]);
}
return Future.value();
return Future<void>.value();
}
}

class ClientConnection extends Connection implements ClientTransportConnection {
ClientConnection._(Stream<List<int>> incoming, StreamSink<List<int>> outgoing,
Settings settings)
: super(incoming, outgoing, settings, isClientConnection: true);
ClientConnection._(super.incoming, super.outgoing, super.settings)
: super(isClientConnection: true);

factory ClientConnection(Stream<List<int>> incoming,
StreamSink<List<int>> outgoing, ClientSettings clientSettings) {
Expand Down Expand Up @@ -473,12 +479,17 @@ class ClientConnection extends Connection implements ClientTransportConnection {
}
return hStream;
}

@override
Stream<int> get onPingReceived => _pingReceived.stream;

@override
Stream<void> get onFrameReceived => _frameReceived.stream;
}

class ServerConnection extends Connection implements ServerTransportConnection {
ServerConnection._(Stream<List<int>> incoming, StreamSink<List<int>> outgoing,
Settings settings)
: super(incoming, outgoing, settings, isClientConnection: false);
ServerConnection._(super.incoming, super.outgoing, super.settings)
: super(isClientConnection: false);

factory ServerConnection(Stream<List<int>> incoming,
StreamSink<List<int>> outgoing, ServerSettings serverSettings) {
Expand All @@ -489,4 +500,10 @@ class ServerConnection extends Connection implements ServerTransportConnection {
@override
Stream<ServerTransportStream> get incomingStreams =>
_streams.incomingStreams.cast<ServerTransportStream>();

@override
Stream<int> get onPingReceived => _pingReceived.stream;

@override
Stream<void> get onFrameReceived => _frameReceived.stream;
}
17 changes: 8 additions & 9 deletions lib/src/connection_preface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,14 @@ Stream<List<int>> readConnectionPreface(Stream<List<int>> incoming) {
}

result.onListen = () {
subscription = incoming.listen(onData,
onError: (Object e, StackTrace s) => result.addError(e, s),
onDone: () {
if (!connectionPrefaceRead) {
terminate('EOS before connection preface could be read.');
} else {
result.close();
}
});
subscription =
incoming.listen(onData, onError: result.addError, onDone: () {
if (!connectionPrefaceRead) {
terminate('EOS before connection preface could be read.');
} else {
result.close();
}
});
result
..onPause = subscription.pause
..onResume = subscription.resume
Expand Down
Loading

0 comments on commit 4916814

Please sign in to comment.