class RouteHandler extends IMHandler<WFCMessage.RouteRequest> {
    @Override
    public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.RouteRequest request, Qos1PublishHandler.IMCallback callback) {<FILL_FUNCTION_BODY>}
}

        MemorySessionStore.Session session = m_sessionsStore.sessionForClientAndUser(fromUser, clientID);
        if (session == null) {
            ErrorCode errorCode = m_sessionsStore.loadActiveSession(fromUser, clientID);
            if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
                return errorCode;
            }
            session = m_sessionsStore.sessionForClientAndUser(fromUser, clientID);
        }

        if (session == null || session.getDeleted() > 0) {
            if(session == null) {
                LOG.error("Session for <{}, {}> not exist", fromUser, clientID);
            } else {
                LOG.error("Session for <{}, {}> deleted", fromUser, clientID);
            }
            return ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH;
        }

        if(request.getPlatform() != session.getPlatform() && m_messagesStore.existSignatures()) {
            LOG.error("Session <{}, {}> platform is {} mismatch the request {}", session.getUsername(), session.getClientID(), session.getPlatform(), request.getPlatform());
            return ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH;
        }

        String serverIp = mServer.getServerIp();
        String longPort = mServer.getLongPort();
        String shortPort = mServer.getShortPort();

        ClientSession clientSession = m_sessionsStore.sessionForClient(clientID);
        boolean isSessionAlreadyStored = clientSession != null;
        if (!isSessionAlreadyStored) {
            m_sessionsStore.loadActiveSession(fromUser, clientID);
        } else {
            m_sessionsStore.updateExistSession(fromUser, clientID, request, true);
        }

        WFCMessage.RouteResponse response = WFCMessage.RouteResponse.newBuilder().setHost(serverIp).setLongPort(Integer.parseInt(longPort)).setShortPort(Integer.parseInt(shortPort)).build();

        byte[] data = response.toByteArray();
        ackPayload.ensureWritable(data.length).writeBytes(data);
        return ErrorCode.ERROR_CODE_SUCCESS;
    
<methods>public void <init>() ,public abstract cn.wildfirechat.common.ErrorCode action(ByteBuf, java.lang.String, java.lang.String, cn.wildfirechat.proto.ProtoConstants.RequestSourceType, cn.wildfirechat.proto.WFCMessage.RouteRequest, io.moquette.spi.impl.Qos1PublishHandler.IMCallback) ,public void afterAction(java.lang.String, java.lang.String, java.lang.String, io.moquette.spi.impl.Qos1PublishHandler.IMCallback) ,public void doHandler(java.lang.String, java.lang.String, java.lang.String, byte[], io.moquette.spi.impl.Qos1PublishHandler.IMCallback, cn.wildfirechat.proto.ProtoConstants.RequestSourceType) ,public static io.moquette.spi.impl.MessagesPublisher getPublisher() ,public static void init(io.moquette.spi.IMessagesStore, io.moquette.spi.ISessionsStore, io.moquette.spi.impl.MessagesPublisher, cn.wildfirechat.server.ThreadPoolExecutorWrapper, io.moquette.server.Server) ,public cn.wildfirechat.common.ErrorCode preAction(java.lang.String, java.lang.String, java.lang.String, io.moquette.spi.impl.Qos1PublishHandler.IMCallback, cn.wildfirechat.proto.ProtoConstants.RequestSourceType) <variables>protected static final Logger LOG,protected static java.lang.String actionName,private Class#RAW dataCls,private static win.liyufan.im.RateLimiter mLimitCounter,protected static io.moquette.server.Server mServer,private static cn.wildfirechat.server.ThreadPoolExecutorWrapper m_imBusinessExecutor,protected static io.moquette.spi.IMessagesStore m_messagesStore,protected static io.moquette.spi.ISessionsStore m_sessionsStore,private java.lang.reflect.Method parseDataMethod,protected static io.moquette.spi.impl.MessagesPublisher publisher