Index: sdk/lib/io/websocket_impl.dart |
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart |
index fcbe1ca857dce9f701f2e80bd50c43847917df4a..2d29a5f658dd1c0dee32a68a58f14b5a3840ba23 100644 |
--- a/sdk/lib/io/websocket_impl.dart |
+++ b/sdk/lib/io/websocket_impl.dart |
@@ -50,7 +50,9 @@ class _WebSocketProtocolTransformer extends StreamEventTransformer { |
static const int CLOSED = 5; |
static const int FAILURE = 6; |
- _WebSocketProtocolTransformer() { |
+ bool _serverSide; |
+ |
+ _WebSocketProtocolTransformer([bool this._serverSide = false]) { |
_prepareForNextFrame(); |
_currentMessageType = _WebSocketMessageType.NONE; |
} |
@@ -223,9 +225,15 @@ class _WebSocketProtocolTransformer extends StreamEventTransformer { |
void _lengthDone(EventSink sink) { |
if (_masked) { |
+ if (!_serverSide) { |
+ throw new WebSocketException("Received masked frame from server"); |
+ } |
_state = MASK; |
_remainingMaskingKeyBytes = 4; |
} else { |
+ if (_serverSide) { |
+ throw new WebSocketException("Received unmasked frame from client"); |
+ } |
_remainingPayloadBytes = _len; |
_startPayload(sink); |
} |
@@ -392,7 +400,7 @@ class _WebSocketTransformerImpl implements WebSocketTransformer { |
response.headers.add("Sec-WebSocket-Accept", accept); |
response.headers.contentLength = 0; |
return response.detachSocket() |
- .then((socket) => new _WebSocketImpl._fromSocket(socket)); |
+ .then((socket) => new _WebSocketImpl._fromSocket(socket, true)); |
} |
static bool _isUpgradeRequest(HttpRequest request) { |
@@ -428,6 +436,7 @@ class _WebSocketImpl extends Stream implements WebSocket { |
final StreamController _controller = new StreamController(); |
final Socket _socket; |
+ final bool _serverSide; |
int _readyState = WebSocket.CONNECTING; |
bool _writeClosed = false; |
int _closeCode; |
@@ -505,11 +514,12 @@ class _WebSocketImpl extends Stream implements WebSocket { |
}); |
} |
- _WebSocketImpl._fromSocket(Socket this._socket) { |
+ _WebSocketImpl._fromSocket(Socket this._socket, |
+ [bool this._serverSide = false]) { |
_readyState = WebSocket.OPEN; |
bool closed = false; |
- var transformer = new _WebSocketProtocolTransformer(); |
+ var transformer = new _WebSocketProtocolTransformer(_serverSide); |
_socket.transform(transformer).listen( |
(data) { |
_controller.add(data); |
@@ -631,7 +641,7 @@ class _WebSocketImpl extends Stream implements WebSocket { |
void _sendFrame(int opcode, [List<int> data]) { |
if (_writeClosed) return; |
- bool mask = false; // Masking not implemented for server. |
+ bool mask = !_serverSide; // Masking not implemented for server. |
int dataLength = data == null ? 0 : data.length; |
// Determine the header size. |
int headerSize = (mask) ? 6 : 2; |
@@ -658,6 +668,19 @@ class _WebSocketImpl extends Stream implements WebSocket { |
for (int i = 0; i < lengthBytes; i++) { |
header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF; |
} |
+ if (mask) { |
+ header[1] |= 1 << 7; |
+ var maskBytes = _IOCrypto.getRandomBytes(4); |
+ header.setRange(index, 4, maskBytes); |
+ index += 4; |
+ if (data != null) { |
+ var list = new Uint8List(data.length); |
+ for (int i = 0; i < data.length; i++) { |
+ list[i] = data[i] ^ maskBytes[i % 4]; |
+ } |
+ data = list; |
+ } |
+ } |
assert(index == headerSize); |
try { |
_socket.writeBytes(header); |