@Override
    public void decode(final ByteBuffer buf, final int available, final StringBuilder log) throws Exception
    {
    	// Start decoding
    	final short command_code = buf.getShort();
		final Command command = Command.forCode(command_code);
    	if (command == null)
    		throw new Exception("Received unknown command code " + command_code);
    	if (command != this.command)
    		throw new Exception("Received command " + command + " instead of " + this.command);
    	
    	final short body_size = buf.getShort();
    	
    	final int session = buf.getInt();
    	if (session != this.session)
    	{
    		// If we did not have a session, remember the newly obtained session
    		if (this.session == 0)
    			this.session = session;
    		else // Error: Session changed
    			throw new Exception("Received session " + session + " instead of " + this.session);
    	}

    	final int status = buf.getInt();
    	
    	final byte[] context = new byte[8];
    	buf.get(context);
    	if (!Arrays.equals(context, Encapsulation.context))
    		throw new Exception("Received context " + Hexdump.toAscii(context));
    	
    	final int options = buf.getInt();
    	
        if (log != null)
        {
        	log.append("Encapsulation Header\n");
        	log.append("UINT  command           : ").append(command).append("\n");
        	log.append("UINT  length            : ").append(body_size).append("\n");
        	log.append(String.format("UDINT session           : 0x%08X\n", session));
        	log.append(String.format("UDINT status            : 0x%08X (%s)\n", status, getStatusMessage(status)));
        	log.append("USINT context[8]        : '").append(Hexdump.escapeChars(context)).append("'\n");
        	log.append(String.format("UDINT options           : 0x%08X\n", options));
        }
        
        if (status != 0)
        	throw new Exception(String.format("Received status 0x%08X (%s)\n", status, getStatusMessage(status)));
        if (buf.remaining() < body_size)
        	throw new Exception("Need " + body_size + " more bytes, have " + buf.remaining());
        
        body.decode(buf, body_size, log);
    }