Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(720)

Unified Diff: sdk/lib/io/websocket.dart

Issue 1390353005: Web Socket compression - take two (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/io/websocket.dart
diff --git a/sdk/lib/io/websocket.dart b/sdk/lib/io/websocket.dart
index 599e295c60ac92923dc620303830b986b8522f96..1bac00b6ccc2466acc2659a8d539d428083cc011 100644
--- a/sdk/lib/io/websocket.dart
+++ b/sdk/lib/io/websocket.dart
@@ -12,7 +12,7 @@ abstract class WebSocketStatus {
static const int GOING_AWAY = 1001;
static const int PROTOCOL_ERROR = 1002;
static const int UNSUPPORTED_DATA = 1003;
- static const int RESERVED_1004 = 1004;
+ static const int RESERVED_1004 = 1004;
static const int NO_STATUS_RECEIVED = 1005;
static const int ABNORMAL_CLOSURE = 1006;
static const int INVALID_FRAME_PAYLOAD_DATA = 1007;
@@ -24,6 +24,136 @@ abstract class WebSocketStatus {
}
/**
+ * The [CompressionOptions] class allows you to control
+ * the options of WebSocket compression.
+ */
+class CompressionOptions {
+ /**
+ * Default WebSocket Compression options.
+ * Compression will be enabled with the following options:
+ * clientNoContextTakeover: false
+ * serverNoContextTakeover: false
+ * clientMaxWindowBits: 15
+ * serverMaxWindowBits: 15
+ */
+ static const CompressionOptions DEFAULT = const CompressionOptions();
+
+ /**
+ * Disables WebSocket Compression.
+ */
+ static const CompressionOptions OFF =
+ const CompressionOptions(enabled: false);
+
+ /**
+ * Control whether the client will reuse it's compression instances.
+ */
+ final bool clientNoContextTakeover;
+
+ /**
+ * Control whether the server will reuse it's compression instances.
+ */
+ final bool serverNoContextTakeover;
+
+ /**
+ * Sets the Max Window Bits for the Client.
+ */
+ final int clientMaxWindowBits;
+
+ /**
+ * Sets the Max Window Bits for the Server.
+ */
+ final int serverMaxWindowBits;
+
+ /**
+ * Enables or disables WebSocket compression.
+ */
+ final bool enabled;
+
+ const CompressionOptions(
+ {this.clientNoContextTakeover: false,
+ this.serverNoContextTakeover: false,
+ this.clientMaxWindowBits,
Søren Gjesse 2015/10/19 16:53:20 Assign default value _WebSocketImpl.DEFAULT_WINDOW
butlermatt 2015/10/22 19:36:08 Done.
+ this.serverMaxWindowBits,
+ this.enabled: true});
+
+ /// Parses list of requested server headers to return server compression
+ /// response headers. Uses [serverMaxWindowBits] value if set, otherwise will
+ /// attempt to use value from headers. Defaults to
+ /// [WebSocket.DEFAULT_WINDOW_BITS]
+ List _createServerResponseHeader(HeaderValue requested) {
+ var info = new List(2);
+
+ if (requested.parameters["server_max_window_bits"] != null) {
Søren Gjesse 2015/10/19 16:53:19 Please make the values "server_no_context_takeover
butlermatt 2015/10/22 19:36:08 Done.
+ var part = requested.parameters["server_max_window_bits"];
Søren Gjesse 2015/10/19 16:53:19 Move this 'var part ...' up before the if, and tes
butlermatt 2015/10/22 19:36:08 Done.
+ var mwb = serverMaxWindowBits == null
+ ? int.parse(part,
Søren Gjesse 2015/10/19 16:53:19 According to https://tools.ietf.org/html/draft-iet
butlermatt 2015/10/22 19:36:08 Done.
+ onError: (source) => _WebSocketImpl.DEFAULT_WINDOW_BITS)
Søren Gjesse 2015/10/19 16:53:20 Please indent with 4 - or all the way to align wit
butlermatt 2015/10/22 19:36:08 Done.
+ : serverMaxWindowBits;
+ info[0] = "; server_max_window_bits=${mwb}";
+ info[1] = mwb;
+ } else {
+ info[1] = _WebSocketImpl.DEFAULT_WINDOW_BITS;
+ }
+ return info;
+ }
+
+ /// Returns default values for client compression request headers.
+ List _createClientRequestHeader(HeaderValue requested) {
+ var info = new List(2);
+
+ info[1] = _WebSocketImpl.DEFAULT_WINDOW_BITS;
+ if (requested != null &&
+ requested.parameters["client_max_window_bits"] != null) {
+ info[0] = "; client_max_window_bits=${info[1]}";
+ } else {
+ info[0] = "; client_max_window_bits";
+ }
+
+ return info;
+ }
+
+ /// Create a Compression Header. If [requested] is null or contains
+ /// client request headers, returns Client compression request headers.
+ /// If [requested] contains server response headers this method returns
+ /// a Server compression response header.
+ List _createHeader([HeaderValue requested]) {
+ if (!enabled) {
+ return ["", 0];
+ }
+
+ var info = new List(2);
+ var header = _WebSocketImpl.PER_MESSAGE_DEFLATE;
+
+ if (clientNoContextTakeover &&
+ (requested != null &&
+ requested.parameters.containsKey("client_no_context_takeover"))) {
+ header += "; client_no_context_takeover";
+ }
+
+ if (serverNoContextTakeover &&
+ (requested != null &&
+ requested.parameters.containsKey("server_no_context_takeover"))) {
+ header += "; server_no_context_takeover";
+ }
+
+ if (requested == null ||
+ requested.parameters.containsKey("client_max_window_bits")) {
+ var clientList = _createClientRequestHeader(requested);
+ header += clientList[0];
+ info[1] = clientList[1];
+ } else {
+ var headerList = _createServerResponseHeader(requested);
+ header += headerList[0];
+ info[1] = headerList[1];
+ }
+
+ info[0] = header;
+
+ return info;
+ }
+}
+
+/**
* The [WebSocketTransformer] provides the ability to upgrade a
* [HttpRequest] to a [WebSocket] connection. It supports both
* upgrading a single [HttpRequest] and upgrading a stream of
@@ -53,7 +183,6 @@ abstract class WebSocketStatus {
*/
abstract class WebSocketTransformer
implements StreamTransformer<HttpRequest, WebSocket> {
-
/**
* Create a new [WebSocketTransformer].
*
@@ -63,8 +192,10 @@ abstract class WebSocketTransformer
* completing with a [String]. The [String] must exist in the list of
* protocols.
Søren Gjesse 2015/10/19 16:53:20 Please update the dartdoc comment here with inform
butlermatt 2015/10/22 19:36:08 Done.
*/
- factory WebSocketTransformer({protocolSelector(List<String> protocols)})
- => new _WebSocketTransformerImpl(protocolSelector);
+ factory WebSocketTransformer(
+ {protocolSelector(List<String> protocols),
+ CompressionOptions compression: CompressionOptions.DEFAULT}) =>
+ new _WebSocketTransformerImpl(protocolSelector, compression);
/**
* Upgrades a [HttpRequest] to a [WebSocket] connection. If the
@@ -80,8 +211,10 @@ abstract class WebSocketTransformer
* protocols.
Søren Gjesse 2015/10/19 16:53:19 ditto.
butlermatt 2015/10/22 19:36:08 Done.
*/
static Future<WebSocket> upgrade(HttpRequest request,
- {protocolSelector(List<String> protocols)}) {
- return _WebSocketTransformerImpl._upgrade(request, protocolSelector);
+ {protocolSelector(List<String> protocols),
+ CompressionOptions compression: CompressionOptions.DEFAULT}) {
+ return _WebSocketTransformerImpl._upgrade(
+ request, protocolSelector, compression);
}
/**
@@ -92,7 +225,6 @@ abstract class WebSocketTransformer
}
}
-
/**
* A two-way HTTP communication object for client or server applications.
*
@@ -152,9 +284,10 @@ abstract class WebSocket implements Stream, StreamSink {
* authentication when setting up the connection.
*/
static Future<WebSocket> connect(String url,
- {Iterable<String> protocols,
- Map<String, dynamic> headers}) =>
- _WebSocketImpl.connect(url, protocols, headers);
+ {Iterable<String> protocols,
+ Map<String, dynamic> headers,
+ CompressionOptions compression: CompressionOptions.DEFAULT}) =>
+ _WebSocketImpl.connect(url, protocols, headers, compression: compression);
@Deprecated('This constructor will be removed in Dart 2.0. Use `implements`'
' instead of `extends` if implementing this abstract class.')
@@ -175,13 +308,16 @@ abstract class WebSocket implements Stream, StreamSink {
* act as the client and mask the messages it sends. If it's `true`, it will
* act as the server and will not mask its messages.
Søren Gjesse 2015/10/19 16:53:20 ditto.
butlermatt 2015/10/22 19:36:08 Done.
*/
- factory WebSocket.fromUpgradedSocket(Socket socket, {String protocol,
- bool serverSide}) {
+ factory WebSocket.fromUpgradedSocket(Socket socket,
+ {String protocol,
+ bool serverSide,
+ CompressionOptions compression: CompressionOptions.DEFAULT}) {
if (serverSide == null) {
throw new ArgumentError("The serverSide argument must be passed "
"explicitly to WebSocket.fromUpgradedSocket.");
}
- return new _WebSocketImpl._fromSocket(socket, protocol, serverSide);
+ return new _WebSocketImpl._fromSocket(
+ socket, protocol, compression, serverSide);
}
/**
@@ -238,9 +374,10 @@ abstract class WebSocket implements Stream, StreamSink {
Future addStream(Stream stream);
}
-
class WebSocketException implements IOException {
final String message;
+
const WebSocketException([this.message = ""]);
+
String toString() => "WebSocketException: $message";
}

Powered by Google App Engine
This is Rietveld 408576698