protected void processMessage(MessageInfo mi, byte[] buffer, int payloadOffset, int payloadLength) {
        //System.err.print(HexDump.prettyPrintHex(buffer, payloadOffset, payloadLength));
        
        int type = mi.type;
        AMFDecoder ac = new AMFDecoder(buffer, payloadOffset, payloadLength);
        
        try {
            if (type == 0x14) {
                RTMPCommand command = readCommand(ac);

                if (applicationInstance == null) {

                    if (command.getName().equals("connect")) {

                        String appName = (String)command.getCommandObject().get("app");
                        try {
                            Application app = library.getApplication(appName);
                            applicationInstance = app.getInstance();
                        } catch (ApplicationNotFoundException e) {
                            AMFPacket response = new AMFPacket();
                            response.writeString("_error");
                            response.writeMixed(null);
                            response.writeMixed(null);
                            writeCommand(mi.chunkStreamID, mi.messageStreamID, response);
                            return;
                        }
                        applicationInstance.onConnect(this);

                        applicationInstance.invokeCommand(mi, command);

                    } else {

                        AMFPacket response = new AMFPacket();
                        response.writeString("_error");
                        response.writeMixed(null);
                        response.writeMixed(null);
                        writeCommand(mi.chunkStreamID, mi.messageStreamID, response);
                    }
                } else {
                    applicationInstance.invokeCommand(mi, command);
                }

            } else if (type == 0x12) {
                RTMPCommand command = readData(ac);
                applicationInstance.onData(mi, command);
            } else if (type == 0x08 || type == 0x09) {
                applicationInstance.mediaChunk(mi, buffer, payloadOffset, payloadLength);
            }
        } catch (Exception ex) {
            LOG.log(Level.WARNING, clientId, ex);
            
            AMFPacket response = new AMFPacket();
            response.writeString("_error");
            response.writeMixed(null);
            response.writeMixed(null);
            writeCommand(mi.chunkStreamID, mi.messageStreamID, response);
            
            throw new RuntimeException(ex);
        }
        
    }