protected int read(ByteBuffer buffer) throws RuntimeSocketClosedException, RuntimeSocketTimeoutException
    {
        int start = buffer.position();
        getController().setReadBufferSize(buffer.remaining());

        synchronized (this)
        {
            if (readState == ReadState.REMOTE_CLOSE)
                return -1;

            this.buffer = buffer;
            readState = ReadState.WAIT;
            getController().needsRead(true);
            while (readState == ReadState.WAIT)
            {
                try
                {
                    wait();
                }
                catch (InterruptedException x)
                {
                    close();
                    Thread.currentThread().interrupt();
                    throw new RuntimeSocketClosedException(new ClosedByInterruptException());
                }
            }

            if (buffer.position() == start)
            {
                if (readState == ReadState.TIMEOUT)
                    throw new RuntimeSocketTimeoutException();
                else if (readState == ReadState.CLOSE)
                    throw new RuntimeSocketClosedException();
                else if (readState == ReadState.REMOTE_CLOSE)
                    return -1;
            }
        }

        return buffer.position() - start;
    }