@Override
  public List<GSChatRoom> getChatRooms() throws RemoteException {
    synchronized (this) {
      logger.debug("query session");

      if (this.userState != GSUserState.Login) {

        logger.debug("query session error");

        return new ArrayList<>();
      }

      List<GSChatRoom> chatRooms = null;
      try {

        chatRooms = binderDataBase.getChatRooms();

        logger.debug("query session -- success");

      } catch (Exception e) {
        logger.error("get chat rooms error", e);
      }

      return chatRooms;
    }
  }
  @Override
  public void Heartbeat(int arg0) throws Exception {
    synchronized (this) {
      if (this.userState != GSUserState.Login) {
        logger.warn("drop heartbeat -- user state({}) error", this.userState);
        return;
      }

      int receivedID = binderDataBase.getReceivedSeqID();

      logger.debug("received heartbeat {} local {}", arg0, receivedID);

      if (receivedID < arg0) {

        imServer.pollMessage(this.client.getToken(), receivedID);
      }
    }
  }
  @Override
  public void RecvMessage(Message message) throws Exception {

    logger.debug("recv message :{}", message.getContent());

    synchronized (this) {
      if (this.userState != GSUserState.Login) {
        // TODO: may lost message
        return;
      }

      Gson gson = new Gson();

      String content = new String(message.getContent(), "UTF8");

      JsonObject json = (JsonObject) new JsonParser().parse(content);

      JsonArray bodies = json.getAsJsonArray("bodies");

      JsonObject object = (JsonObject) bodies.get(0);

      int messageType = object.get("messageBodyType").getAsInt();

      String id = json.get("id").toString();

      IPCMessage ipcMessage =
          new IPCMessage(id, message.getType(), message.getSource(), message.getTarget());

      ipcMessage.setContent(object.toString(), messageType);

      ipcMessage.setDirect(GSDirect.From);

      ipcMessage.setSeqID(message.getSeqID());

      ipcMessage.setState(GSMessageState.LocalApply);

      binderDataBase.saveMessage(ipcMessage, this);

      onMessageStateChanged(ipcMessage, GSError.SUCCESS);

      logger.debug("recv message :{} -- success", ipcMessage);
    }
  }