anchor.diff:      _outputStream = null;
     }
   
  +  _onWebSocketPing(List<int> payload) {
  +    _sendFrame(_WebSocketOpcode.PONG, payload);
  +  }
  +
  +  _onWebSocketPong(List<int> payload) {
  +    // Currently pong messages are ignored.
  +  }
  +
     _onWebSocketClosed(int status, String reason) {
       _closeReceived = true;
       if (_onClosed != null) _onClosed(status, reason);
  
positive.code:               }
              }
  
              switch (_currentMessageType) {
                case _WebSocketMessageType.NONE:
                  throw new WebSocketException("Protocol error");
                  break;
  
                case _WebSocketMessageType.TEXT:
                case _WebSocketMessageType.BINARY:
                  if (onMessageData != null) {
                    onMessageData(buffer, index, payload);
                  }
                  _remainingPayloadBytes -= payload;
                  index += payload;
                  if (_remainingPayloadBytes == 0) {
                    _frameEnd();
                  }
                  break;
  
                case _WebSocketMessageType.CLOSE:
                  // Allocate a buffer for holding the close payload if any.
                  if (_closePayload == null) {
                    _closePayload = new List<int>();
                  }
                  _closePayload.addAll(buffer.getRange(index, payload));
                  _remainingPayloadBytes -= payload;
                  index += payload;
                  if (_fin) {
                    if (_remainingPayloadBytes != 0) {
                      throw new WebSocketException("Protocol error");
                    }
                    int status;
                    String reason;
                    if (_closePayload.length > 0) {
                      if (_closePayload.length == 1) {
                        throw new WebSocketException("Protocol error");
                      }
                      status = _closePayload[0] << 8 | _closePayload[1];
                      if (_closePayload.length > 2) {
                        var decoder = _StringDecoders.decoder(Encoding.UTF_8);
                        decoder.write(_closePayload.getRange(
                            2, _closePayload.length - 2));
                        reason = decoder.decoded;
                      }
                    }
                    if (onClosed != null) onClosed(status, reason);
                    _currentMessageType = _WebSocketMessageType.NONE;
                    _state = CLOSED;
                  }
                  break;
  
                default:
                  throw new WebSocketException("Protocol error");
                  break;
              }
  
              // Hack - as we always do index++ below.
              index--;
              break;
  
            default:
              throw new WebSocketException("Protocol error");
              break;
          }
  
          // Move to the next byte.
  
negative.code:     processor.onMessageStart = _onWebSocketMessageStart;
      processor.onMessageData = _onWebSocketMessageData;
      processor.onMessageEnd = _onWebSocketMessageEnd;
      processor.onPing = _onWebSocketPing;
      processor.onPong = _onWebSocketPong;
      processor.onClosed = _onWebSocketClosed;
      processor.onError = _onWebSocketError;
      if (unparsedData != null) {
  