Skip to content

Commit 54c8719

Browse files
abitofevrythingCommit Queue
authored andcommitted
[io] Correct websocket close code upon abnormal closure
TEST=tests/standalone/io/web_socket_abnormal_close_test.dart [email protected] Bug: #60217 Change-Id: I6168abfa9fc0228f98b97f7873449970f59f1a30 Fixes #60217 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/413140 Commit-Queue: Martin Kustermann <[email protected]> Reviewed-by: Martin Kustermann <[email protected]> Auto-Submit: Mylo Fawcett <[email protected]> Reviewed-by: Slava Egorov <[email protected]>
1 parent 91c6e27 commit 54c8719

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

sdk/lib/_http/http_testing.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ part of dart._http;
3737
typedef TestingClass$_Cookie = _Cookie;
3838
typedef TestingClass$_HttpHeaders = _HttpHeaders;
3939
typedef TestingClass$_HttpParser = _HttpParser;
40+
typedef TestingClass$_HttpRequest = _HttpRequest;
4041
typedef TestingClass$_SHA1 = _SHA1;
4142
typedef TestingClass$_WebSocketProtocolTransformer =
4243
_WebSocketProtocolTransformer;
@@ -52,6 +53,14 @@ extension Testing$_HttpHeaders on _HttpHeaders {
5253
List<Cookie> test$_parseCookies() => this._parseCookies();
5354
}
5455

56+
extension Testing$_HttpRequest on _HttpRequest {
57+
_HttpConnection get test$_httpConnection => _httpConnection;
58+
}
59+
60+
extension Testing$_HttpConnection on _HttpConnection {
61+
Socket get test$_socket => _socket;
62+
}
63+
5564
extension Testing$_WebSocketProtocolTransformer
5665
on _WebSocketProtocolTransformer {
5766
int get test$_state => this._state;

sdk/lib/_http/websocket_impl.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class _WebSocketProtocolTransformer
8989
int _remainingPayloadBytes = -1;
9090
int _unmaskingIndex = 0;
9191
int _currentMessageType = _WebSocketMessageType.NONE;
92-
int closeCode = WebSocketStatus.noStatusReceived;
92+
int closeCode = WebSocketStatus.abnormalClosure;
9393
String closeReason = "";
9494

9595
EventSink<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/>? _eventSink;
@@ -316,6 +316,7 @@ class _WebSocketProtocolTransformer
316316
switch (_opcode) {
317317
case _WebSocketOpcode.CLOSE:
318318
_state = CLOSED;
319+
closeCode = WebSocketStatus.noStatusReceived;
319320
_eventSink!.close();
320321
break;
321322
case _WebSocketOpcode.PING:
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
//
5+
// Verify that the close code for an abnormally closed WebSocket is 1006
6+
// (WebSocketStatus.abnormalClosure).
7+
//
8+
// See section 7.1.5 of RFC 6455:
9+
// If _The WebSocket Connection is Closed_ and no Close control frame was
10+
// received by the endpoint (such as could occur if the underlying transport
11+
// connection is lost), _The WebSocket Connection Close Code_ is considered to
12+
// be 1006.
13+
14+
import 'dart:async';
15+
import 'dart:io';
16+
17+
// ignore: IMPORT_INTERNAL_LIBRARY
18+
import "dart:_http"
19+
show
20+
TestingClass$_HttpRequest,
21+
Testing$_HttpRequest,
22+
Testing$_HttpConnection;
23+
24+
import "package:expect/async_helper.dart";
25+
import 'package:expect/expect.dart';
26+
27+
typedef _HttpRequest = TestingClass$_HttpRequest;
28+
29+
void main() {
30+
asyncStart();
31+
32+
HttpRequest closeSocketAfterDelay(HttpRequest request) {
33+
Expect.type<_HttpRequest>(request);
34+
35+
Timer(Duration(seconds: 1), () {
36+
(request as _HttpRequest).test$_httpConnection.test$_socket.destroy();
37+
});
38+
39+
return request;
40+
}
41+
42+
HttpServer.bind('localhost', 0).then((server) {
43+
server.map(closeSocketAfterDelay).transform(WebSocketTransformer()).drain();
44+
45+
WebSocket.connect('ws://localhost:${server.port}').then((ws) {
46+
ws.drain().then((_) {
47+
Expect.equals(ws.closeCode, WebSocketStatus.abnormalClosure);
48+
49+
server.close();
50+
asyncEnd();
51+
});
52+
});
53+
});
54+
}

0 commit comments

Comments
 (0)