/* ------------------------------------------------------------ */
 public void close() {
   try {
     _generator.flush();
     _endp.close();
   } catch (IOException e) {
     LOG.ignore(e);
   }
 }
  /* ------------------------------------------------------------ */
  public Connection handle() throws IOException {
    try {
      // handle stupid hixie random bytes
      if (_hixieBytes != null) {

        // take any available bytes from the parser buffer, which may have already been read
        Buffer buffer = _parser.getBuffer();
        if (buffer != null && buffer.length() > 0) {
          int l = buffer.length();
          if (l > (8 - _hixieBytes.length())) l = 8 - _hixieBytes.length();
          _hixieBytes.put(buffer.peek(buffer.getIndex(), l));
          buffer.skip(l);
        }

        // while we are not blocked
        while (_endp.isOpen()) {
          // do we now have enough
          if (_hixieBytes.length() == 8) {
            // we have the silly random bytes
            // so let's work out the stupid 16 byte reply.
            doTheHixieHixieShake();
            _endp.flush(_hixieBytes);
            _hixieBytes = null;
            _endp.flush();
            break;
          }

          // no, then let's fill
          int filled = _endp.fill(_hixieBytes);
          if (filled < 0) {
            _endp.flush();
            _endp.close();
            break;
          }
        }

        if (_websocket instanceof OnFrame) ((OnFrame) _websocket).onHandshake(this);
        _websocket.onOpen(this);
        return this;
      }

      // handle the framing protocol
      boolean progress = true;

      while (progress) {
        int flushed = _generator.flush();
        int filled = _parser.parseNext();

        progress = flushed > 0 || filled > 0;

        _endp.flush();

        if (_endp instanceof AsyncEndPoint && ((AsyncEndPoint) _endp).hasProgressed())
          progress = true;
      }
    } catch (IOException e) {
      LOG.debug(e);
      try {
        if (_endp.isOpen()) _endp.close();
      } catch (IOException e2) {
        LOG.ignore(e2);
      }
      throw e;
    } finally {
      if (_endp.isOpen()) {
        if (_endp.isInputShutdown() && _generator.isBufferEmpty()) _endp.close();
        else checkWriteable();

        checkWriteable();
      }
    }
    return this;
  }
 /* ------------------------------------------------------------ */
 private void checkWriteable() {
   if (!_generator.isBufferEmpty() && _endp instanceof AsyncEndPoint)
     ((AsyncEndPoint) _endp).scheduleWrite();
 }
 /* ------------------------------------------------------------ */
 public void sendFrame(byte flags, byte opcode, byte[] content, int offset, int length)
     throws IOException {
   _generator.addFrame((byte) 0, opcode, content, offset, length);
   _generator.flush();
   checkWriteable();
 }
 /* ------------------------------------------------------------ */
 public void sendMessage(byte[] data, int offset, int length) throws IOException {
   _generator.addFrame((byte) 0, LENGTH_FRAME, data, offset, length);
   _generator.flush();
   checkWriteable();
 }
 public void sendMessage(String content) throws IOException {
   byte[] data = content.getBytes(StringUtil.__UTF8);
   _generator.addFrame((byte) 0, SENTINEL_FRAME, data, 0, data.length);
   _generator.flush();
   checkWriteable();
 }
 /* ------------------------------------------------------------ */
 public boolean isIdle() {
   return _parser.isBufferEmpty() && _generator.isBufferEmpty();
 }