public void in_event () 
    {
        
        //  If still handshaking, receive and process the greeting message.
        if (handshaking)
            if (!handshake ())
                return;
        
        assert (decoder != null);
        boolean disconnection = false;

        //  If there's no data to process in the buffer...
        if (insize == 0) {

            //  Retrieve the buffer and read as much data as possible.
            //  Note that buffer can be arbitrarily large. However, we assume
            //  the underlying TCP layer has fixed buffer size and thus the
            //  number of bytes read will be always limited.
            inbuf = decoder.get_buffer ();
            insize = read (inbuf);
            inbuf.flip();

            //  Check whether the peer has closed the connection.
            if (insize == -1) {
                insize = 0;
                disconnection = true;
            }
        }

        //  Push the data to the decoder.
        int processed = decoder.process_buffer (inbuf, insize);

        if (processed == -1) {
            disconnection = true;
        }
        else {

            //  Stop polling for input if we got stuck.
            if (processed < insize)
                io_object.reset_pollin (handle);

            //  Adjust the buffer.
            insize -= processed;
        }

        //  Flush all messages the decoder may have produced.
        session.flush ();

        //  An input error has occurred. If the last decoded message
        //  has already been accepted, we terminate the engine immediately.
        //  Otherwise, we stop waiting for socket events and postpone
        //  the termination until after the message is accepted.
        if (disconnection) {
            if (decoder.stalled ()) {
                io_object.rm_fd (handle);
                io_enabled = false;
            } else
                error ();
        }

    }