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

            MemorySessionStore.Session session = m_sessionsStore.getSession(clientID);
            session.setPlatform(request.getPlatform());
            session.setAppName(request.getAppName());
            if (request.getPlatform() == ProtoConstants.Platform.Platform_iOS && request.getPushType() == 2) {
                LOG.info("Set device token, userId {}", fromUser);
                session.setVoipDeviceToken(request.getDeviceToken());
                m_sessionsStore.updateSessionToken(session, true);
            } else {
                LOG.info("Set device token, userId {}, platform {}, pushType {}", fromUser, session.getPlatform(), request.getPushType());
                session.setDeviceToken(request.getDeviceToken());
                session.setPushType(request.getPushType());
                m_sessionsStore.updateSessionToken(session, false);
                m_sessionsStore.cleanDuplatedToken(session.getClientID(), session.getPushType(), session.getDeviceToken(), false, session.getAppName());
            }

            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.UploadDeviceTokenRequest, 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