[vm/io] Fix pausing read on SecureSocket
Pausing read on the SecureSocket should pause read on the underlying socket, because otherwise we will be stuck calling _readHandler which will not read anything but still schedule an SSL filter wasting CPU time. Fixes https://github.com/dart-lang/sdk/issues/62037 CoreLibraryReviewExempt: No API changes, VM specific implementation change Change-Id: I4144815d34c1e77a68533b6ebcb66c146a6a6964 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/467804 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Slava Egorov <vegorov@google.com>
This commit is contained in:
committed by
Commit Queue
parent
c552af0a9e
commit
7b5bd07e87
@@ -834,6 +834,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
||||
|
||||
void set readEventsEnabled(bool value) {
|
||||
_readEventsEnabled = value;
|
||||
_socket.readEventsEnabled = value;
|
||||
_scheduleReadEvent();
|
||||
}
|
||||
|
||||
@@ -1084,7 +1085,9 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
||||
_secureFilter = null;
|
||||
return;
|
||||
}
|
||||
_socket.readEventsEnabled = true;
|
||||
if (_readEventsEnabled) {
|
||||
_socket.readEventsEnabled = true;
|
||||
}
|
||||
if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) {
|
||||
// Checks for and handles all cases of partially closed sockets.
|
||||
shutdown(SocketDirection.send);
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2026, 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.
|
||||
//
|
||||
// OtherResources=certificates/server_chain.pem
|
||||
// OtherResources=certificates/server_key.pem
|
||||
|
||||
// This test verifies that setting readEventsEnabled to false on
|
||||
// RawSecureSocket correctly updates readEventsEnabled on the underlying
|
||||
// RawSocket.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
String relativeToScript(path) => Platform.script.resolve(path).toFilePath();
|
||||
|
||||
final String serverCert = relativeToScript('certificates/server_chain.pem');
|
||||
final String serverKey = relativeToScript('certificates/server_key.pem');
|
||||
|
||||
void main() {
|
||||
asyncTest(() async {
|
||||
final serverContext = SecurityContext()
|
||||
..useCertificateChain(serverCert)
|
||||
..usePrivateKey(serverKey, password: 'dartdart');
|
||||
|
||||
final secureServer = await SecureServerSocket.bind(
|
||||
InternetAddress.loopbackIPv4,
|
||||
0,
|
||||
serverContext,
|
||||
);
|
||||
|
||||
final connection = secureServer.first;
|
||||
|
||||
final clientSocket = await RawSocket.connect(
|
||||
InternetAddress.loopbackIPv4,
|
||||
secureServer.port,
|
||||
);
|
||||
final clientSecureSocket = await RawSecureSocket.secure(
|
||||
clientSocket,
|
||||
context: SecurityContext()..setTrustedCertificates(serverCert),
|
||||
);
|
||||
|
||||
clientSecureSocket.listen((event) {});
|
||||
|
||||
final connected = await connection;
|
||||
connected.drain();
|
||||
|
||||
Expect.isTrue(clientSocket.readEventsEnabled);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
clientSecureSocket.readEventsEnabled = false;
|
||||
Expect.isFalse(clientSocket.readEventsEnabled);
|
||||
|
||||
clientSecureSocket.readEventsEnabled = true;
|
||||
Expect.isTrue(clientSocket.readEventsEnabled);
|
||||
}
|
||||
|
||||
await Future.wait([
|
||||
clientSecureSocket.close(),
|
||||
secureServer.close(),
|
||||
connected.close(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
@@ -114,6 +114,7 @@ Future runClient(
|
||||
onBadCertificate: badCertificateCallback,
|
||||
);
|
||||
Expect.equals('pass', result); // Is rethrown below
|
||||
socket.drain();
|
||||
await socket.close();
|
||||
} catch (error) {
|
||||
if (error is ExpectException) rethrow;
|
||||
|
||||
@@ -127,7 +127,9 @@ Future testClientCertificate({
|
||||
X509Certificate serverCertificate = clientEnd.peerCertificate!;
|
||||
Expect.isTrue(serverCertificate.subject.contains("localhost"));
|
||||
Expect.isTrue(serverCertificate.issuer.contains("intermediateauthority"));
|
||||
clientEnd.drain();
|
||||
clientEnd.close();
|
||||
serverEnd.drain();
|
||||
serverEnd.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,7 @@ testPauseServerSocket() {
|
||||
var subscription;
|
||||
subscription = server.listen((connection) {
|
||||
Expect.isTrue(resumed);
|
||||
connection.drain();
|
||||
connection.close();
|
||||
if (++acceptCount == 2 * socketCount) {
|
||||
server.close();
|
||||
@@ -133,6 +134,7 @@ testPauseServerSocket() {
|
||||
SecureSocket.connect(HOST, server.port, context: clientContext).then((
|
||||
connection,
|
||||
) {
|
||||
connection.drain();
|
||||
connection.close();
|
||||
});
|
||||
}
|
||||
@@ -143,6 +145,7 @@ testPauseServerSocket() {
|
||||
SecureSocket.connect(HOST, server.port, context: clientContext).then((
|
||||
connection,
|
||||
) {
|
||||
connection.drain();
|
||||
connection.close();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -88,15 +88,19 @@ void testSimpleConnect() {
|
||||
context: clientContext,
|
||||
);
|
||||
server.listen((serverEnd) {
|
||||
clientEndFuture.then((clientEnd) {
|
||||
clientEndFuture.then((clientEnd) async {
|
||||
var x5 = clientEnd.peerCertificate!;
|
||||
print(x5.subject);
|
||||
print(x5.issuer);
|
||||
print(x5.startValidity);
|
||||
print(x5.endValidity);
|
||||
clientEnd.close();
|
||||
serverEnd.close();
|
||||
server.close();
|
||||
await Future.wait([
|
||||
clientEnd.drain(),
|
||||
clientEnd.close(),
|
||||
serverEnd.drain(),
|
||||
serverEnd.close(),
|
||||
server.close(),
|
||||
]);
|
||||
asyncEnd();
|
||||
});
|
||||
});
|
||||
@@ -137,8 +141,8 @@ void testSimpleConnectFail(
|
||||
error is HandshakeException ||
|
||||
error is SocketException,
|
||||
);
|
||||
clientEndFuture.then((_) {
|
||||
if (!cancelOnError) server.close();
|
||||
clientEndFuture.then((_) async {
|
||||
if (!cancelOnError) await server.close();
|
||||
asyncEnd();
|
||||
});
|
||||
},
|
||||
@@ -158,10 +162,14 @@ void testServerListenAfterConnect() {
|
||||
);
|
||||
new Timer(const Duration(milliseconds: 500), () {
|
||||
server.listen((serverEnd) {
|
||||
clientEndFuture.then((clientEnd) {
|
||||
clientEnd.close();
|
||||
serverEnd.close();
|
||||
server.close();
|
||||
clientEndFuture.then((clientEnd) async {
|
||||
await Future.wait([
|
||||
clientEnd.drain(),
|
||||
clientEnd.close(),
|
||||
serverEnd.drain(),
|
||||
serverEnd.close(),
|
||||
server.close(),
|
||||
]);
|
||||
asyncEnd();
|
||||
});
|
||||
});
|
||||
@@ -231,9 +239,9 @@ void testSimpleReadWrite() {
|
||||
dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
|
||||
bytesRead += buffer.length;
|
||||
},
|
||||
onDone: () {
|
||||
onDone: () async {
|
||||
verifyTestData(dataReceived);
|
||||
socket.close();
|
||||
await socket.close();
|
||||
asyncEnd();
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user