Remove support for requests not made through dart:io Sockets (#423)

diff --git a/pkgs/shelf_web_socket/CHANGELOG.md b/pkgs/shelf_web_socket/CHANGELOG.md
index d3596ce..5984e06 100644
--- a/pkgs/shelf_web_socket/CHANGELOG.md
+++ b/pkgs/shelf_web_socket/CHANGELOG.md
@@ -1,6 +1,8 @@
-## 1.0.5-wip
+## 2.0.0-wip
 
 * Require Dart `^3.0.0`.
+* **BREAKING:**: Remove support for hijacking WebSocket requests that are not
+  being transported using `dart:io` `Socket`s.
 
 ## 1.0.4
 
diff --git a/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart b/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
index 1728765..a41ed69 100644
--- a/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
+++ b/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
@@ -3,8 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:convert';
+import 'dart:io';
 
 import 'package:shelf/shelf.dart';
+import 'package:web_socket_channel/io.dart';
 import 'package:web_socket_channel/web_socket_channel.dart';
 
 /// A class that exposes a handler for upgrading WebSocket requests.
@@ -78,9 +80,16 @@
       if (protocol != null) sink.add('Sec-WebSocket-Protocol: $protocol\r\n');
       sink.add('\r\n');
 
+      if (channel.sink is! Socket) {
+        throw ArgumentError('channel.sink must be a dart:io `Socket`.');
+      }
+
+      final webSocket = WebSocket.fromUpgradedSocket(channel.sink as Socket,
+          protocol: protocol, serverSide: true)
+        ..pingInterval = _pingInterval;
+
       // ignore: avoid_dynamic_calls
-      _onConnection(
-          WebSocketChannel(channel, pingInterval: _pingInterval), protocol);
+      _onConnection(IOWebSocketChannel(webSocket), protocol);
     });
   }
 
diff --git a/pkgs/shelf_web_socket/pubspec.yaml b/pkgs/shelf_web_socket/pubspec.yaml
index 9c3fd94..2a8f846 100644
--- a/pkgs/shelf_web_socket/pubspec.yaml
+++ b/pkgs/shelf_web_socket/pubspec.yaml
@@ -1,5 +1,5 @@
 name: shelf_web_socket
-version: 1.0.5-wip
+version: 2.0.0-wip
 description: >
   A shelf handler that wires up a listener for every connection.
 repository: https://github.com/dart-lang/shelf/tree/master/pkgs/shelf_web_socket
@@ -20,3 +20,8 @@
   dart_flutter_team_lints: ^2.0.0
   http: '>=0.13.0 <2.0.0'
   test: ^1.16.0
+
+# Remove this when a version of `package:test` is released that is compatible
+# with self_web_socket 2.x
+dependency_overrides:
+  test: 1.25.2
diff --git a/pkgs/shelf_web_socket/test/web_socket_test.dart b/pkgs/shelf_web_socket/test/web_socket_test.dart
index b519592..eb8e00b 100644
--- a/pkgs/shelf_web_socket/test/web_socket_test.dart
+++ b/pkgs/shelf_web_socket/test/web_socket_test.dart
@@ -5,8 +5,10 @@
 import 'dart:io';
 
 import 'package:http/http.dart' as http;
+import 'package:shelf/shelf.dart';
 import 'package:shelf/shelf_io.dart' as shelf_io;
 import 'package:shelf_web_socket/shelf_web_socket.dart';
+import 'package:stream_channel/stream_channel.dart';
 import 'package:test/test.dart';
 import 'package:web_socket_channel/web_socket_channel.dart';
 
@@ -103,6 +105,32 @@
     }
   });
 
+  test('cannot hijack non-Socket StreamChannel', () async {
+    final handler =
+        webSocketHandler((WebSocketChannel webSocket, String? protocol) {
+      expect(protocol, isNull);
+      webSocket.sink.close();
+    });
+
+    expect(
+        () => handler(Request('GET', Uri.parse('ws://example.com/'),
+                protocolVersion: '1.1',
+                headers: {
+                  'Host': 'example.com',
+                  'Upgrade': 'websocket',
+                  'Connection': 'Upgrade',
+                  'Sec-WebSocket-Key': 'x3JJHMbDL1EzLkh9GBhXDw==',
+                  'Sec-WebSocket-Version': '13',
+                  'Origin': 'http://example.com',
+                }, onHijack: (fn) {
+              // `.foreign` is not a Socket so hijacking the request should
+              // fail.
+              expect(() => fn(StreamChannelController<List<int>>().foreign),
+                  throwsArgumentError);
+            })),
+        throwsA(isA<HijackException>()));
+  });
+
   group('with a set of allowed origins', () {
     late HttpServer server;
     late Uri url;