Chromium Code Reviews| Index: sdk/lib/io/websocket_impl.dart |
| diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart |
| index 6a626092fc4f46843f6496721d298c8698ac3551..9234d8af772880793a429ab6e9857b816b2069a0 100644 |
| --- a/sdk/lib/io/websocket_impl.dart |
| +++ b/sdk/lib/io/websocket_impl.dart |
| @@ -393,10 +393,13 @@ class _WebSocketPong { |
| class _WebSocketTransformerImpl implements WebSocketTransformer { |
| final StreamController<WebSocket> _controller = |
| new StreamController<WebSocket>(sync: true); |
| + final Function _protocolSelector; |
| + |
| + _WebSocketTransformerImpl(this._protocolSelector); |
| Stream<WebSocket> bind(Stream<HttpRequest> stream) { |
| stream.listen((request) { |
| - _upgrade(request) |
| + _upgrade(request, _protocolSelector) |
| .then((WebSocket webSocket) => _controller.add(webSocket)) |
| .catchError(_controller.addError); |
| }); |
| @@ -404,31 +407,45 @@ class _WebSocketTransformerImpl implements WebSocketTransformer { |
| return _controller.stream; |
| } |
| - static Future<WebSocket> _upgrade(HttpRequest request) { |
| + static Future<WebSocket> _upgrade(HttpRequest request, _protocolSelector) { |
| var response = request.response; |
| if (!_isUpgradeRequest(request)) { |
| - // Send error response and drain the request. |
| - request.listen((_) {}, onDone: () { |
| - response.statusCode = HttpStatus.BAD_REQUEST; |
| - response.contentLength = 0; |
| - response.close(); |
| - }); |
| + // Send error response. |
| + response.statusCode = HttpStatus.BAD_REQUEST; |
| + response.close(); |
| return new Future.error( |
| new WebSocketException("Invalid WebSocket upgrade request")); |
| } |
|
Søren Gjesse
2013/11/27 10:43:58
Please add a newline before and after the local fu
Anders Johnsen
2013/11/27 11:43:30
Done.
|
| - |
| - // Send the upgrade response. |
| - response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; |
| - response.headers.add(HttpHeaders.CONNECTION, "Upgrade"); |
| - response.headers.add(HttpHeaders.UPGRADE, "websocket"); |
| - String key = request.headers.value("Sec-WebSocket-Key"); |
| - _SHA1 sha1 = new _SHA1(); |
| - sha1.add("$key$_webSocketGUID".codeUnits); |
| - String accept = _CryptoUtils.bytesToBase64(sha1.close()); |
| - response.headers.add("Sec-WebSocket-Accept", accept); |
| - response.headers.contentLength = 0; |
| - return response.detachSocket() |
| - .then((socket) => new _WebSocketImpl._fromSocket(socket, true)); |
| + Future upgrade(String protocol) { |
| + // Send the upgrade response. |
| + response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; |
| + response.headers.add(HttpHeaders.CONNECTION, "Upgrade"); |
| + response.headers.add(HttpHeaders.UPGRADE, "websocket"); |
| + String key = request.headers.value("Sec-WebSocket-Key"); |
| + _SHA1 sha1 = new _SHA1(); |
| + sha1.add("$key$_webSocketGUID".codeUnits); |
| + String accept = _CryptoUtils.bytesToBase64(sha1.close()); |
| + response.headers.add("Sec-WebSocket-Accept", accept); |
| + if (protocol != null && protocol.isNotEmpty) { |
| + response.headers.add("Sec-WebSocket-Protocol", protocol); |
| + } |
| + response.headers.contentLength = 0; |
| + return response.detachSocket() |
| + .then((socket) => new _WebSocketImpl._fromSocket( |
| + socket, protocol, true)); |
| + } |
| + var protocols = request.headers['Sec-WebSocket-Protocol']; |
| + if (protocols != null && _protocolSelector != null) { |
|
Søren Gjesse
2013/11/27 10:43:58
Please explain the handling of
Sec-WebSocket-Prot
Anders Johnsen
2013/11/27 11:43:30
Done.
|
| + protocols = _HttpParser._tokenizeFieldValue(protocols.join(', ')); |
| + return new Future(() => _protocolSelector(protocols)) |
| + .then(upgrade, onError: (error) { |
| + response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR; |
| + response.close(); |
| + throw error; |
| + }); |
| + } else { |
| + return upgrade(null); |
| + } |
| } |
| static bool _isUpgradeRequest(HttpRequest request) { |
| @@ -724,6 +741,8 @@ class _WebSocketConsumer implements StreamConsumer { |
| class _WebSocketImpl extends Stream implements WebSocket { |
| + final String protocol; |
| + |
| StreamController _controller; |
| StreamSubscription _subscription; |
| StreamSink _sink; |
| @@ -743,7 +762,7 @@ class _WebSocketImpl extends Stream implements WebSocket { |
| static final HttpClient _httpClient = new HttpClient(); |
| - static Future<WebSocket> connect(String url, [protocols]) { |
| + static Future<WebSocket> connect(String url, List<String> protocols) { |
| Uri uri = Uri.parse(url); |
| if (uri.scheme != "ws" && uri.scheme != "wss") { |
| throw new WebSocketException("Unsupported URL scheme '${uri.scheme}'"); |
| @@ -774,6 +793,9 @@ class _WebSocketImpl extends Stream implements WebSocket { |
| request.headers.set(HttpHeaders.UPGRADE, "websocket"); |
| request.headers.set("Sec-WebSocket-Key", nonce); |
| request.headers.set("Sec-WebSocket-Version", "13"); |
| + if (protocols.isNotEmpty) { |
| + request.headers.add("Sec-WebSocket-Protocol", protocols); |
| + } |
| return request.close(); |
| }) |
| .then((response) { |
| @@ -808,12 +830,14 @@ class _WebSocketImpl extends Stream implements WebSocket { |
| error("Bad response 'Sec-WebSocket-Accept' header"); |
| } |
| } |
| + var protocol = response.headers.value('Sec-WebSocket-Protocol'); |
| return response.detachSocket() |
| - .then((socket) => new _WebSocketImpl._fromSocket(socket)); |
| + .then((socket) => new _WebSocketImpl._fromSocket(socket, protocol)); |
| }); |
| } |
| _WebSocketImpl._fromSocket(Socket this._socket, |
| + String this.protocol, |
| [bool this._serverSide = false]) { |
| _consumer = new _WebSocketConsumer(this, _socket); |
| _sink = new _StreamSinkImpl(_consumer); |
| @@ -893,7 +917,6 @@ class _WebSocketImpl extends Stream implements WebSocket { |
| int get readyState => _readyState; |
| String get extensions => null; |
| - String get protocol => null; |
| int get closeCode => _closeCode; |
| String get closeReason => _closeReason; |