Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit 1849a26

Browse files
authored
Switch to callbacks from streams for ping handling (#137)
* Switch to callbacks from streams for ping handling * Debugging * Revert "Debugging" This reverts commit 910c1e1. * Revert "Switch to callbacks from streams for ping handling" This reverts commit c4f4730. * Fix by using `hasListener` * Rev version * Rerun checks
1 parent 6980f2c commit 1849a26

File tree

5 files changed

+51
-24
lines changed

5 files changed

+51
-24
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.3.0
2+
3+
- Only send updates on frames and pings being received when there are listeners, as to not fill up memory.
4+
15
## 2.2.0
26

37
- Transform headers to lowercase.

lib/src/connection.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ abstract class Connection {
101101

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

104-
final StreamController<void> _receivedFrame = StreamController<void>();
104+
final StreamController<void> _frameReceived = StreamController<void>();
105105

106106
/// Future which completes when the first SETTINGS frame is received from
107107
/// the peer.
@@ -183,7 +183,7 @@ abstract class Connection {
183183
// Setup handlers.
184184
_settingsHandler = SettingsHandler(_hpackContext.encoder, _frameWriter,
185185
acknowledgedSettings, peerSettings);
186-
_pingHandler = PingHandler(_frameWriter, _pingReceived.sink);
186+
_pingHandler = PingHandler(_frameWriter, _pingReceived);
187187

188188
var settings = _decodeSettings(settingsObject);
189189

@@ -344,7 +344,9 @@ abstract class Connection {
344344
frame.decodedHeaders =
345345
_hpackContext.decoder.decode(frame.headerBlockFragment);
346346
}
347-
_receivedFrame.add(null);
347+
if (_frameReceived.hasListener) {
348+
_frameReceived.add(null);
349+
}
348350

349351
// Handle the frame as either a connection or a stream frame.
350352
if (frame.header.streamId == 0) {
@@ -483,7 +485,7 @@ class ClientConnection extends Connection implements ClientTransportConnection {
483485
Stream<int> get onPingReceived => _pingReceived.stream;
484486

485487
@override
486-
Stream<void> get onFrameReceived => _receivedFrame.stream;
488+
Stream<void> get onFrameReceived => _frameReceived.stream;
487489
}
488490

489491
class ServerConnection extends Connection implements ServerTransportConnection {
@@ -505,5 +507,5 @@ class ServerConnection extends Connection implements ServerTransportConnection {
505507
Stream<int> get onPingReceived => _pingReceived.stream;
506508

507509
@override
508-
Stream<void> get onFrameReceived => _receivedFrame.stream;
510+
Stream<void> get onFrameReceived => _frameReceived.stream;
509511
}

lib/src/ping/ping_handler.dart

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,20 @@ class PingHandler extends Object with TerminatableMixin {
1717
final FrameWriter _frameWriter;
1818
final Map<int, Completer> _remainingPings = {};
1919
final Sink<int>? pingReceived;
20+
final bool Function() isListeningToPings;
2021
int _nextId = 1;
2122

22-
PingHandler(this._frameWriter, [this.pingReceived]);
23+
PingHandler(this._frameWriter, StreamController<int> pingStream)
24+
: pingReceived = pingStream.sink,
25+
isListeningToPings = (() => pingStream.hasListener);
2326

2427
@override
2528
void onTerminated(Object? error) {
26-
var values = _remainingPings.values.toList();
29+
final remainingPings = _remainingPings.values.toList();
2730
_remainingPings.clear();
28-
for (var value in values) {
29-
value.completeError(error ?? 'Unspecified error');
31+
for (final ping in remainingPings) {
32+
ping.completeError(
33+
error ?? 'Remaining ping completed with unspecified error');
3034
}
3135
}
3236

@@ -37,7 +41,9 @@ class PingHandler extends Object with TerminatableMixin {
3741
}
3842

3943
if (!frame.hasAckFlag) {
40-
pingReceived?.add(frame.opaqueData);
44+
if (isListeningToPings()) {
45+
pingReceived?.add(frame.opaqueData);
46+
}
4147
_frameWriter.writePingFrame(frame.opaqueData, ack: true);
4248
} else {
4349
var c = _remainingPings.remove(frame.opaqueData);

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: http2
2-
version: 2.2.0
2+
version: 2.3.0
33
description: A HTTP/2 implementation in Dart.
44
repository: https://github.com/dart-lang/http2
55

test/src/ping/ping_handler_test.dart

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void main() {
1515
group('ping-handler', () {
1616
test('successful-ping', () async {
1717
var writer = FrameWriterMock();
18-
var pingHandler = PingHandler(writer);
18+
var pingHandler = instantiateHandler(writer);
1919

2020
var p1 = pingHandler.ping();
2121
var p2 = pingHandler.ping();
@@ -37,7 +37,7 @@ void main() {
3737

3838
test('successful-ack-to-remote-ping', () async {
3939
var writer = FrameWriterMock();
40-
var pingHandler = PingHandler(writer);
40+
var pingHandler = instantiateHandler(writer);
4141

4242
var header = FrameHeader(8, FrameType.PING, 0, 0);
4343
pingHandler.processPingFrame(PingFrame(header, 1));
@@ -53,7 +53,7 @@ void main() {
5353

5454
test('ping-unknown-opaque-data', () async {
5555
var writer = FrameWriterMock();
56-
var pingHandler = PingHandler(writer);
56+
var pingHandler = instantiateHandler(writer);
5757

5858
var future = pingHandler.ping();
5959
verify(writer.writePingFrame(1)).called(1);
@@ -73,7 +73,7 @@ void main() {
7373

7474
test('terminate-ping-handler', () async {
7575
var writer = FrameWriterMock();
76-
var pingHandler = PingHandler(writer);
76+
var pingHandler = instantiateHandler(writer);
7777

7878
pingHandler.terminate('hello world');
7979
expect(
@@ -86,7 +86,7 @@ void main() {
8686

8787
test('ping-non-zero-stream-id', () async {
8888
var writer = FrameWriterMock();
89-
var pingHandler = PingHandler(writer);
89+
var pingHandler = instantiateHandler(writer);
9090

9191
var header = FrameHeader(8, FrameType.PING, PingFrame.FLAG_ACK, 1);
9292
expect(() => pingHandler.processPingFrame(PingFrame(header, 1)),
@@ -95,17 +95,32 @@ void main() {
9595
});
9696

9797
test('receiving-ping-calls-stream', () async {
98-
var writer = FrameWriterMock();
99-
var streamController = StreamController<int>();
100-
var pingHandler = PingHandler(writer, streamController.sink);
98+
final pings = <int>[];
10199

102-
var header = FrameHeader(8, FrameType.PING, 0, 0);
103-
pingHandler.processPingFrame(PingFrame(header, 1));
104-
var header2 = FrameHeader(8, FrameType.PING, 0, 0);
105-
pingHandler.processPingFrame(PingFrame(header2, 2));
106-
await expectLater(streamController.stream, emitsInOrder([1, 2]));
100+
final writer = FrameWriterMock();
101+
final pingStream = StreamController<int>()
102+
..stream.listen((event) => pings.add(event));
103+
104+
PingHandler(writer, pingStream)
105+
..processPingFrame(PingFrame(
106+
FrameHeader(8, FrameType.PING, 0, 0),
107+
1,
108+
))
109+
..processPingFrame(PingFrame(
110+
FrameHeader(8, FrameType.PING, 0, 0),
111+
2,
112+
));
113+
114+
await pingStream.close();
115+
116+
expect(pings, [1, 2]);
107117
});
108118
});
109119
}
110120

121+
PingHandler instantiateHandler(FrameWriterMock writer) {
122+
StreamController<int> controller = StreamController();
123+
return PingHandler(writer, controller);
124+
}
125+
111126
class FrameWriterMock extends Mock implements FrameWriter {}

0 commit comments

Comments
 (0)