Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 final String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 5 final String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
| 6 | 6 |
| 7 class _WebSocketMessageType { | 7 class _WebSocketMessageType { |
| 8 static final int NONE = 0; | 8 static final int NONE = 0; |
| 9 static final int BINARY = 1; | 9 static final int BINARY = 1; |
| 10 static final int TEXT = 2; | 10 static final int TEXT = 2; |
| 11 static final int CLOSE = 3; | |
| 12 } | 11 } |
| 13 | 12 |
| 14 | 13 |
| 15 class _WebSocketOpcode { | 14 class _WebSocketOpcode { |
| 16 static final int CONTINUATION = 0; | 15 static final int CONTINUATION = 0; |
| 17 static final int TEXT = 1; | 16 static final int TEXT = 1; |
| 18 static final int BINARY = 2; | 17 static final int BINARY = 2; |
| 19 static final int RESERVED_3 = 3; | 18 static final int RESERVED_3 = 3; |
| 20 static final int RESERVED_4 = 4; | 19 static final int RESERVED_4 = 4; |
| 21 static final int RESERVED_5 = 5; | 20 static final int RESERVED_5 = 5; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 47 class _WebSocketProtocolProcessor { | 46 class _WebSocketProtocolProcessor { |
| 48 static final int START = 0; | 47 static final int START = 0; |
| 49 static final int LEN_FIRST = 1; | 48 static final int LEN_FIRST = 1; |
| 50 static final int LEN_REST = 2; | 49 static final int LEN_REST = 2; |
| 51 static final int MASK = 3; | 50 static final int MASK = 3; |
| 52 static final int PAYLOAD = 4; | 51 static final int PAYLOAD = 4; |
| 53 static final int CLOSED = 5; | 52 static final int CLOSED = 5; |
| 54 static final int FAILURE = 6; | 53 static final int FAILURE = 6; |
| 55 | 54 |
| 56 _WebSocketProtocolProcessor() { | 55 _WebSocketProtocolProcessor() { |
| 57 _reset(); | 56 _prepareForNextFrame(); |
| 58 _currentMessageType = _WebSocketMessageType.NONE; | 57 _currentMessageType = _WebSocketMessageType.NONE; |
| 59 } | 58 } |
| 60 | 59 |
| 61 /** | 60 /** |
| 62 * Process data received from the underlying communication channel. | 61 * Process data received from the underlying communication channel. |
| 63 */ | 62 */ |
| 64 void update(List<int> buffer, int offset, int count) { | 63 void update(List<int> buffer, int offset, int count) { |
| 65 int index = offset; | 64 int index = offset; |
| 66 int lastIndex = offset + count; | 65 int lastIndex = offset + count; |
| 67 try { | 66 try { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 98 if (_currentMessageType != _WebSocketMessageType.NONE) { | 97 if (_currentMessageType != _WebSocketMessageType.NONE) { |
| 99 throw new WebSocketException("Protocol error"); | 98 throw new WebSocketException("Protocol error"); |
| 100 } | 99 } |
| 101 _currentMessageType = _WebSocketMessageType.BINARY; | 100 _currentMessageType = _WebSocketMessageType.BINARY; |
| 102 if (onMessageStart != null) { | 101 if (onMessageStart != null) { |
| 103 onMessageStart(_WebSocketMessageType.BINARY); | 102 onMessageStart(_WebSocketMessageType.BINARY); |
| 104 } | 103 } |
| 105 break; | 104 break; |
| 106 | 105 |
| 107 case _WebSocketOpcode.CLOSE: | 106 case _WebSocketOpcode.CLOSE: |
| 108 if (_currentMessageType != _WebSocketMessageType.NONE) { | |
| 109 throw new WebSocketException("Protocol error"); | |
| 110 } | |
| 111 _currentMessageType = _WebSocketMessageType.CLOSE; | |
| 112 break; | |
| 113 | |
| 114 case _WebSocketOpcode.PING: | 107 case _WebSocketOpcode.PING: |
| 115 // TODO(sgjesse): Handle ping. | |
| 116 throw new UnsupportedOperationException("Web socket PING"); | |
| 117 break; | |
| 118 | |
| 119 case _WebSocketOpcode.PONG: | 108 case _WebSocketOpcode.PONG: |
| 120 // TODO(sgjesse): Handle pong. | 109 // Control frames cannot be fragmented. |
| 121 throw new UnsupportedOperationException("Web socket PONG"); | 110 if (!_fin) throw new WebSocketException("Protocol error"); |
| 122 break; | 111 break; |
| 123 | 112 |
| 124 default: | 113 default: |
| 125 throw new WebSocketException("Protocol error"); | 114 throw new WebSocketException("Protocol error"); |
| 126 break; | 115 break; |
| 127 } | 116 } |
| 128 _state = LEN_FIRST; | 117 _state = LEN_FIRST; |
| 129 break; | 118 break; |
| 130 | 119 |
| 131 case LEN_FIRST: | 120 case LEN_FIRST: |
| 132 _masked = (byte & 0x80) != 0; | 121 _masked = (byte & 0x80) != 0; |
| 133 _len = byte & 0x7F; | 122 _len = byte & 0x7F; |
| 123 if (_isControlFrame() && _len > 126) { | |
| 124 throw new WebSocketException("Protocol error"); | |
| 125 } | |
| 134 if (_len < 126) { | 126 if (_len < 126) { |
| 135 _lengthDone(); | 127 _lengthDone(); |
| 136 } else if (_len == 126) { | 128 } else if (_len == 126) { |
| 137 _len = 0; | 129 _len = 0; |
| 138 _remainingLenBytes = 2; | 130 _remainingLenBytes = 2; |
| 139 _state = LEN_REST; | 131 _state = LEN_REST; |
| 140 } else if (_len == 127) { | 132 } else if (_len == 127) { |
| 141 _len = 0; | 133 _len = 0; |
| 142 _remainingLenBytes = 8; | 134 _remainingLenBytes = 8; |
| 143 _state = LEN_REST; | 135 _state = LEN_REST; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 161 break; | 153 break; |
| 162 | 154 |
| 163 case PAYLOAD: | 155 case PAYLOAD: |
| 164 // The payload is not handled one byte at a time but in blocks. | 156 // The payload is not handled one byte at a time but in blocks. |
| 165 int payload; | 157 int payload; |
| 166 if (lastIndex - index <= _remainingPayloadBytes) { | 158 if (lastIndex - index <= _remainingPayloadBytes) { |
| 167 payload = lastIndex - index; | 159 payload = lastIndex - index; |
| 168 } else { | 160 } else { |
| 169 payload = _remainingPayloadBytes; | 161 payload = _remainingPayloadBytes; |
| 170 } | 162 } |
| 163 _remainingPayloadBytes -= payload; | |
| 164 | |
| 171 // Unmask payload if masked. | 165 // Unmask payload if masked. |
| 172 if (_masked) { | 166 if (_masked) { |
| 173 for (int i = 0; i < payload; i++) { | 167 for (int i = 0; i < payload; i++) { |
| 174 int maskingByte = | 168 int maskingByte = |
| 175 ((_maskingKey >> ((3 - _unmaskingIndex) * 8)) & 0xFF); | 169 ((_maskingKey >> ((3 - _unmaskingIndex) * 8)) & 0xFF); |
| 176 buffer[index + i] = buffer[index + i] ^ maskingByte; | 170 buffer[index + i] = buffer[index + i] ^ maskingByte; |
| 177 _unmaskingIndex = (_unmaskingIndex + 1) % 4; | 171 _unmaskingIndex = (_unmaskingIndex + 1) % 4; |
| 178 } | 172 } |
| 179 } | 173 } |
| 180 | 174 |
| 181 switch (_currentMessageType) { | 175 if (_isControlFrame()) { |
| 182 case _WebSocketMessageType.NONE: | 176 if (payload > 0) { |
| 183 throw new WebSocketException("Protocol error"); | 177 // Allocate a buffer for collecting the control frame |
| 184 break; | 178 // payload if any. |
| 179 if (_controlPayload == null) { | |
| 180 _controlPayload = new List<int>(); | |
| 181 } | |
| 182 _controlPayload.addAll(buffer.getRange(index, payload)); | |
| 183 index += payload; | |
| 184 } | |
| 185 | 185 |
| 186 case _WebSocketMessageType.TEXT: | 186 if (_remainingPayloadBytes == 0) { |
| 187 case _WebSocketMessageType.BINARY: | 187 _controlFrameEnd(); |
| 188 if (onMessageData != null) { | 188 } |
| 189 onMessageData(buffer, index, payload); | 189 } else { |
| 190 } | 190 switch (_currentMessageType) { |
| 191 _remainingPayloadBytes -= payload; | 191 case _WebSocketMessageType.NONE: |
| 192 index += payload; | 192 throw new WebSocketException("Protocol error"); |
| 193 if (_remainingPayloadBytes == 0) { | 193 break; |
| 194 _frameEnd(); | |
| 195 } | |
| 196 break; | |
| 197 | 194 |
| 198 case _WebSocketMessageType.CLOSE: | 195 case _WebSocketMessageType.TEXT: |
| 199 // Allocate a buffer for holding the close payload if any. | 196 case _WebSocketMessageType.BINARY: |
| 200 if (_closePayload == null) { | 197 if (onMessageData != null) { |
| 201 _closePayload = new List<int>(); | 198 onMessageData(buffer, index, payload); |
| 202 } | |
| 203 _closePayload.addAll(buffer.getRange(index, payload)); | |
| 204 _remainingPayloadBytes -= payload; | |
| 205 index += payload; | |
| 206 if (_fin) { | |
| 207 if (_remainingPayloadBytes != 0) { | |
| 208 throw new WebSocketException("Protocol error"); | |
| 209 } | 199 } |
| 210 int status; | 200 index += payload; |
| 211 String reason; | 201 if (_remainingPayloadBytes == 0) { |
| 212 if (_closePayload.length > 0) { | 202 _messageFrameEnd(); |
| 213 if (_closePayload.length == 1) { | |
| 214 throw new WebSocketException("Protocol error"); | |
| 215 } | |
| 216 status = _closePayload[0] << 8 | _closePayload[1]; | |
| 217 if (_closePayload.length > 2) { | |
| 218 var decoder = _StringDecoders.decoder(Encoding.UTF_8); | |
| 219 decoder.write(_closePayload.getRange( | |
| 220 2, _closePayload.length - 2)); | |
| 221 reason = decoder.decoded; | |
| 222 } | |
| 223 } | 203 } |
| 224 if (onClosed != null) onClosed(status, reason); | 204 break; |
| 225 _currentMessageType = _WebSocketMessageType.NONE; | |
| 226 _state = CLOSED; | |
| 227 } | |
| 228 break; | |
| 229 | 205 |
| 230 default: | 206 default: |
| 231 throw new WebSocketException("Protocol error"); | 207 throw new WebSocketException("Protocol error"); |
| 232 break; | 208 break; |
| 209 | |
| 210 } | |
| 233 } | 211 } |
| 234 | 212 |
| 235 // Hack - as we always do index++ below. | 213 // Hack - as we always do index++ below. |
| 236 index--; | 214 index--; |
| 237 break; | |
| 238 | |
| 239 default: | |
| 240 throw new WebSocketException("Protocol error"); | |
| 241 break; | |
| 242 } | 215 } |
| 243 | 216 |
| 244 // Move to the next byte. | 217 // Move to the next byte. |
| 245 index++; | 218 index++; |
| 246 } | 219 } |
| 247 } catch (var e) { | 220 } catch (var e) { |
| 248 _reportError(e); | 221 _reportError(e); |
| 249 } | 222 } |
| 250 } | 223 } |
| 251 | 224 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 267 _startPayload(); | 240 _startPayload(); |
| 268 } | 241 } |
| 269 } | 242 } |
| 270 | 243 |
| 271 void _maskDone() { | 244 void _maskDone() { |
| 272 _remainingPayloadBytes = _len; | 245 _remainingPayloadBytes = _len; |
| 273 _startPayload(); | 246 _startPayload(); |
| 274 } | 247 } |
| 275 | 248 |
| 276 void _startPayload() { | 249 void _startPayload() { |
| 277 // Check whether there is any payload. If not indicate empty | 250 // Check whether there is any payload. If not handle callbacks |
|
Anders Johnsen
2012/05/22 08:54:34
Weird sentence.
Søren Gjesse
2012/05/22 10:34:28
Rephrased.
| |
| 278 // message or close without state and reason. | 251 // without going through the PAYLOAD state.. |
| 279 if (_remainingPayloadBytes == 0) { | 252 if (_remainingPayloadBytes == 0) { |
| 280 if (_currentMessageType ==_WebSocketMessageType.CLOSE) { | 253 if (_isControlFrame()) { |
| 281 if (onClosed != null) onClosed(null, null); | 254 switch (_opcode) { |
| 282 _state = CLOSED; | 255 case _WebSocketOpcode.CLOSE: |
| 256 if (onClosed != null) onClosed(null, null); | |
| 257 _state = CLOSED; | |
| 258 break; | |
| 259 case _WebSocketOpcode.PING: | |
| 260 if (onPing != null) onPing(null); | |
| 261 break; | |
| 262 case _WebSocketOpcode.PONG: | |
| 263 if (onPong != null) onPong(null); | |
| 264 break; | |
| 265 } | |
| 266 _prepareForNextFrame(); | |
| 283 } else { | 267 } else { |
| 284 _frameEnd(); | 268 _messageFrameEnd(); |
| 285 } | 269 } |
| 286 } else { | 270 } else { |
| 287 _state = PAYLOAD; | 271 _state = PAYLOAD; |
| 288 } | 272 } |
| 289 } | 273 } |
| 290 | 274 |
| 291 void _frameEnd() { | 275 void _messageFrameEnd() { |
| 292 if (_remainingPayloadBytes != 0) { | |
| 293 throw new WebSocketException("Protocol error"); | |
| 294 } | |
| 295 if (_fin) { | 276 if (_fin) { |
| 296 if (onMessageEnd != null) onMessageEnd(); | 277 if (onMessageEnd != null) onMessageEnd(); |
| 297 _currentMessageType = _WebSocketMessageType.NONE; | 278 _currentMessageType = _WebSocketMessageType.NONE; |
| 298 } | 279 } |
| 299 _reset(); | 280 _prepareForNextFrame(); |
| 300 } | 281 } |
| 301 | 282 |
| 302 void _reset() { | 283 void _controlFrameEnd() { |
| 303 _state = START; | 284 switch (_opcode) { |
| 285 case _WebSocketOpcode.CLOSE: | |
| 286 int status; | |
| 287 String reason; | |
| 288 if (_controlPayload.length > 0) { | |
| 289 if (_controlPayload.length == 1) { | |
| 290 throw new WebSocketException("Protocol error"); | |
| 291 } | |
| 292 status = _controlPayload[0] << 8 | _controlPayload[1]; | |
| 293 if (_controlPayload.length > 2) { | |
| 294 var decoder = _StringDecoders.decoder(Encoding.UTF_8); | |
| 295 decoder.write(_controlPayload.getRange( | |
| 296 2, _controlPayload.length - 2)); | |
|
Mads Ager (google)
2012/05/22 09:04:13
Maybe just use four-space indentation here. The ar
Søren Gjesse
2012/05/22 10:34:28
Done.
| |
| 297 reason = decoder.decoded; | |
| 298 } | |
| 299 } | |
| 300 if (onClosed != null) onClosed(status, reason); | |
| 301 _state = CLOSED; | |
| 302 break; | |
| 303 | |
| 304 case _WebSocketOpcode.PING: | |
| 305 if (onPing != null) onPing(_controlPayload); | |
| 306 break; | |
| 307 | |
| 308 case _WebSocketOpcode.PONG: | |
| 309 if (onPong != null) onPong(_controlPayload); | |
| 310 break; | |
| 311 } | |
| 312 _prepareForNextFrame(); | |
| 313 } | |
| 314 | |
| 315 bool _isControlFrame() { | |
| 316 return _opcode == _WebSocketOpcode.CLOSE || | |
| 317 _opcode == _WebSocketOpcode.PING || | |
| 318 _opcode == _WebSocketOpcode.PONG; | |
| 319 } | |
| 320 | |
| 321 void _prepareForNextFrame() { | |
| 322 if (_state != CLOSED && _state != FAILURE) _state = START; | |
| 304 _fin = null; | 323 _fin = null; |
| 305 _opcode = null; | 324 _opcode = null; |
| 306 _len = null; | 325 _len = null; |
| 307 _masked = null; | 326 _masked = null; |
| 308 _maskingKey = 0; | 327 _maskingKey = 0; |
| 309 _remainingLenBytes = null; | 328 _remainingLenBytes = null; |
| 310 _remainingMaskingKeyBytes = null; | 329 _remainingMaskingKeyBytes = null; |
| 311 _remainingPayloadBytes = null; | 330 _remainingPayloadBytes = null; |
| 312 _unmaskingIndex = 0; | 331 _unmaskingIndex = 0; |
| 332 _controlPayload = null; | |
| 313 } | 333 } |
| 314 | 334 |
| 315 void _reportError(e) { | 335 void _reportError(e) { |
| 316 // Report the error through the error callback if any. Otherwise | 336 // Report the error through the error callback if any. Otherwise |
| 317 // throw the error. | 337 // throw the error. |
| 318 if (onError != null) { | 338 if (onError != null) { |
| 319 onError(e); | 339 onError(e); |
| 320 _state = FAILURE; | 340 _state = FAILURE; |
| 321 } else { | 341 } else { |
| 322 throw e; | 342 throw e; |
| 323 } | 343 } |
| 324 } | 344 } |
| 325 | 345 |
| 326 int _state; | 346 int _state; |
| 327 bool _fin; | 347 bool _fin; |
| 328 int _opcode; | 348 int _opcode; |
| 329 int _len; | 349 int _len; |
| 330 bool _masked; | 350 bool _masked; |
| 331 int _maskingKey; | 351 int _maskingKey; |
| 332 int _remainingLenBytes; | 352 int _remainingLenBytes; |
| 333 int _remainingMaskingKeyBytes; | 353 int _remainingMaskingKeyBytes; |
| 334 int _remainingPayloadBytes; | 354 int _remainingPayloadBytes; |
| 335 int _unmaskingIndex; | 355 int _unmaskingIndex; |
| 336 | 356 |
| 337 int _currentMessageType; | 357 int _currentMessageType; |
| 338 List<int> _closePayload; | 358 List<int> _controlPayload; |
| 339 | 359 |
| 340 Function onMessageStart; | 360 Function onMessageStart; |
| 341 Function onMessageData; | 361 Function onMessageData; |
| 342 Function onMessageEnd; | 362 Function onMessageEnd; |
| 363 Function onPing; | |
| 364 Function onPong; | |
| 343 Function onClosed; | 365 Function onClosed; |
| 344 Function onError; | 366 Function onError; |
| 345 } | 367 } |
| 346 | 368 |
| 347 | 369 |
| 348 class _WebSocketConnectionBase { | 370 class _WebSocketConnectionBase { |
| 349 void _socketConnected(Socket socket) { | 371 void _socketConnected(Socket socket) { |
| 350 _socket = socket; | 372 _socket = socket; |
| 351 _socket.onError = (e) { | 373 _socket.onError = (e) { |
| 352 _reportError(e); | 374 _reportError(e); |
| 353 _socket.close(); | 375 _socket.close(); |
| 354 }; | 376 }; |
| 355 } | 377 } |
| 356 | 378 |
| 357 void _startProcessing(List<int> unparsedData) { | 379 void _startProcessing(List<int> unparsedData) { |
| 358 _WebSocketProtocolProcessor processor = new _WebSocketProtocolProcessor(); | 380 _WebSocketProtocolProcessor processor = new _WebSocketProtocolProcessor(); |
| 359 processor.onMessageStart = _onWebSocketMessageStart; | 381 processor.onMessageStart = _onWebSocketMessageStart; |
| 360 processor.onMessageData = _onWebSocketMessageData; | 382 processor.onMessageData = _onWebSocketMessageData; |
| 361 processor.onMessageEnd = _onWebSocketMessageEnd; | 383 processor.onMessageEnd = _onWebSocketMessageEnd; |
| 384 processor.onPing = _onWebSocketPing; | |
| 385 processor.onPong = _onWebSocketPong; | |
| 362 processor.onClosed = _onWebSocketClosed; | 386 processor.onClosed = _onWebSocketClosed; |
| 363 processor.onError = _onWebSocketError; | 387 processor.onError = _onWebSocketError; |
| 364 if (unparsedData != null) { | 388 if (unparsedData != null) { |
| 365 processor.update(unparsedData, 0, unparsedData.length); | 389 processor.update(unparsedData, 0, unparsedData.length); |
| 366 } | 390 } |
| 367 _socket.onData = () { | 391 _socket.onData = () { |
| 368 int available = _socket.available(); | 392 int available = _socket.available(); |
| 369 List<int> data = new List<int>(available); | 393 List<int> data = new List<int>(available); |
| 370 int read = _socket.readList(data, 0, available); | 394 int read = _socket.readList(data, 0, available); |
| 371 processor.update(data, 0, read); | 395 processor.update(data, 0, read); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 479 if (_currentMessageType == _WebSocketMessageType.TEXT) { | 503 if (_currentMessageType == _WebSocketMessageType.TEXT) { |
| 480 _onMessage(_decoder.decoded); | 504 _onMessage(_decoder.decoded); |
| 481 } else { | 505 } else { |
| 482 _onMessage(_outputStream.contents()); | 506 _onMessage(_outputStream.contents()); |
| 483 } | 507 } |
| 484 } | 508 } |
| 485 _decoder = null; | 509 _decoder = null; |
| 486 _outputStream = null; | 510 _outputStream = null; |
| 487 } | 511 } |
| 488 | 512 |
| 513 _onWebSocketPing(List<int> payload) { | |
| 514 _sendFrame(_WebSocketOpcode.PONG, payload); | |
| 515 } | |
| 516 | |
| 517 _onWebSocketPong(List<int> payload) { | |
| 518 // Currently pong messages are ignored. | |
| 519 } | |
| 520 | |
| 489 _onWebSocketClosed(int status, String reason) { | 521 _onWebSocketClosed(int status, String reason) { |
| 490 _closeReceived = true; | 522 _closeReceived = true; |
| 491 if (_onClosed != null) _onClosed(status, reason); | 523 if (_onClosed != null) _onClosed(status, reason); |
| 492 if (_closeSent) { | 524 if (_closeSent) { |
| 493 // Got close frame in response to close frame. Now close the socket. | 525 // Got close frame in response to close frame. Now close the socket. |
| 494 if (_closeTimer != null) _closeTimer.cancel(); | 526 if (_closeTimer != null) _closeTimer.cancel(); |
| 495 _socket.close(); | 527 _socket.close(); |
| 496 } else { | 528 } else { |
| 497 close(status); | 529 close(status); |
| 498 } | 530 } |
| 499 } | 531 } |
| 500 | 532 |
| 501 _onWebSocketError(e) { | 533 _onWebSocketError(e) { |
| 502 _reportError(e); | 534 _reportError(e); |
| 503 _socket.close(); | 535 _socket.close(); |
| 504 } | 536 } |
| 505 | 537 |
| 506 _sendFrame(int opcode, List<int> data) { | 538 _sendFrame(int opcode, [List<int> data]) { |
| 507 bool mask = false; // Masking not implemented for server. | 539 bool mask = false; // Masking not implemented for server. |
| 508 int dataLength = data == null ? 0 : data.length; | 540 int dataLength = data == null ? 0 : data.length; |
| 509 // Determine the header size. | 541 // Determine the header size. |
| 510 int headerSize = (mask) ? 6 : 2; | 542 int headerSize = (mask) ? 6 : 2; |
| 511 if (dataLength > 65535) { | 543 if (dataLength > 65535) { |
| 512 headerSize += 8; | 544 headerSize += 8; |
| 513 } else if (dataLength > 125) { | 545 } else if (dataLength > 125) { |
| 514 headerSize += 2; | 546 headerSize += 2; |
| 515 } | 547 } |
| 516 List<int> header = new List<int>(headerSize); | 548 List<int> header = new List<int>(headerSize); |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 | 881 |
| 850 class _WebSocketCloseEvent implements CloseEvent { | 882 class _WebSocketCloseEvent implements CloseEvent { |
| 851 _WebSocketCloseEvent(this._wasClean, this._code, this._reason); | 883 _WebSocketCloseEvent(this._wasClean, this._code, this._reason); |
| 852 bool get wasClean() => _wasClean; | 884 bool get wasClean() => _wasClean; |
| 853 int get code() => _code; | 885 int get code() => _code; |
| 854 String get reason() => _reason; | 886 String get reason() => _reason; |
| 855 bool _wasClean; | 887 bool _wasClean; |
| 856 int _code; | 888 int _code; |
| 857 String _reason; | 889 String _reason; |
| 858 } | 890 } |
| OLD | NEW |