Exemplo n.º 1
0
  public void processConnect(ServerChannel session, ConnectMessage msg) {
    LOG.debug("CONNECT for client <{}>", msg.getClientID());
    if (msg.getProtocolVersion() != VERSION_3_1 && msg.getProtocolVersion() != VERSION_3_1_1) {
      ConnAckMessage badProto = new ConnAckMessage();
      badProto.setReturnCode(ConnAckMessage.UNNACEPTABLE_PROTOCOL_VERSION);
      LOG.warn("processConnect sent bad proto ConnAck");
      session.write(badProto);
      session.close(false);
      return;
    }

    if (msg.getClientID() == null || msg.getClientID().length() == 0) {
      ConnAckMessage okResp = new ConnAckMessage();
      okResp.setReturnCode(ConnAckMessage.IDENTIFIER_REJECTED);
      session.write(okResp);
      m_interceptor.notifyClientConnected(msg);
      return;
    }

    // handle user authentication
    if (msg.isUserFlag()) {
      byte[] pwd = null;
      if (msg.isPasswordFlag()) {
        pwd = msg.getPassword();
      } else if (!this.allowAnonymous) {
        failedCredentials(session);
        return;
      }
      if (!m_authenticator.checkValid(msg.getUsername(), pwd)) {
        failedCredentials(session);
        return;
      }
      session.setAttribute(NettyChannel.ATTR_KEY_USERNAME, msg.getUsername());
    } else if (!this.allowAnonymous) {
      failedCredentials(session);
      return;
    }

    // if an old client with the same ID already exists close its session.
    if (m_clientIDs.containsKey(msg.getClientID())) {
      LOG.info(
          "Found an existing connection with same client ID <{}>, forcing to close",
          msg.getClientID());
      // clean the subscriptions if the old used a cleanSession = true
      ServerChannel oldSession = m_clientIDs.get(msg.getClientID()).session;
      ClientSession oldClientSession = m_sessionsStore.sessionForClient(msg.getClientID());
      oldClientSession.disconnect();
      oldSession.setAttribute(NettyChannel.ATTR_KEY_SESSION_STOLEN, true);
      oldSession.close(false);
      LOG.debug("Existing connection with same client ID <{}>, forced to close", msg.getClientID());
    }

    ConnectionDescriptor connDescr =
        new ConnectionDescriptor(msg.getClientID(), session, msg.isCleanSession());
    m_clientIDs.put(msg.getClientID(), connDescr);

    int keepAlive = msg.getKeepAlive();
    LOG.debug("Connect with keepAlive {} s", keepAlive);
    session.setAttribute(NettyChannel.ATTR_KEY_KEEPALIVE, keepAlive);
    session.setAttribute(NettyChannel.ATTR_KEY_CLEANSESSION, msg.isCleanSession());
    // used to track the client in the subscription and publishing phases.
    session.setAttribute(NettyChannel.ATTR_KEY_CLIENTID, msg.getClientID());
    LOG.debug("Connect create session <{}>", session);

    session.setIdleTime(Math.round(keepAlive * 1.5f));

    // Handle will flag
    if (msg.isWillFlag()) {
      AbstractMessage.QOSType willQos = AbstractMessage.QOSType.valueOf(msg.getWillQos());
      byte[] willPayload = msg.getWillMessage();
      ByteBuffer bb = (ByteBuffer) ByteBuffer.allocate(willPayload.length).put(willPayload).flip();
      // save the will testament in the clientID store
      WillMessage will = new WillMessage(msg.getWillTopic(), bb, msg.isWillRetain(), willQos);
      m_willStore.put(msg.getClientID(), will);
    }

    ConnAckMessage okResp = new ConnAckMessage();
    okResp.setReturnCode(ConnAckMessage.CONNECTION_ACCEPTED);

    ClientSession clientSession = m_sessionsStore.sessionForClient(msg.getClientID());
    boolean isSessionAlreadyStored = clientSession != null;
    if (!msg.isCleanSession() && isSessionAlreadyStored) {
      okResp.setSessionPresent(true);
    }
    session.write(okResp);
    m_interceptor.notifyClientConnected(msg);

    if (!isSessionAlreadyStored) {
      LOG.info("Create persistent session for clientID <{}>", msg.getClientID());
      clientSession = m_sessionsStore.createNewSession(msg.getClientID(), msg.isCleanSession());
    }
    clientSession.activate();
    if (msg.isCleanSession()) {
      clientSession.cleanSession();
    }
    LOG.info(
        "Connected client ID <{}> with clean session {}", msg.getClientID(), msg.isCleanSession());
    if (!msg.isCleanSession()) {
      // force the republish of stored QoS1 and QoS2
      republishStoredInSession(clientSession);
    }
    LOG.info("CONNECT processed");
  }