Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassCastException storing message in persistBufferedMessage #1037

Open
2 tasks done
albertoalcolea opened this issue May 14, 2024 · 1 comment
Open
2 tasks done

ClassCastException storing message in persistBufferedMessage #1037

albertoalcolea opened this issue May 14, 2024 · 1 comment

Comments

@albertoalcolea
Copy link

Please fill out the form below before submitting, thank you!

  • Bug exists Release Version 1.2.5 ( Master Branch)
  • Bug exists in MQTTv3 Client on Snapshot Version 1.2.6-SNAPSHOT (Develop Branch)
  • [?] Bug exists in MQTTv5 Client on Snapshot Version 1.2.6-SNAPSHOT (Develop Branch)

This bug relates to:

And this fix:

Under some circunstances, a SUBSCRIBE or UNSUBSCRIBE message might be persisted in the persistBufferedMessage is set when the client has lost the connection with the server.

public void sendNoWait(MqttWireMessage message, MqttToken token) throws MqttException {
	final String methodName = "sendNoWait";
	if (isConnected() ||
			(!isConnected() && message instanceof MqttConnect) ||
			(isDisconnecting() && message instanceof MqttDisconnect)) {
		if(disconnectedMessageBuffer != null && disconnectedMessageBuffer.getMessageCount() != 0){
			//@TRACE 507=Client Connected, Offline Buffer available, but not empty. Adding message to buffer. message={0}
			log.fine(CLASS_NAME, methodName, "507", new Object[] {message.getKey()});
			if(disconnectedMessageBuffer.isPersistBuffer()){
				if (message instanceof MqttPublish) {
					this.clientState.persistBufferedMessage(message);
				}
			}
			disconnectedMessageBuffer.putMessage(message, token);
		} else {
			this.internalSend(message, token);
		}
	} else if(disconnectedMessageBuffer != null) {
		//@TRACE 508=Offline Buffer available. Adding message to buffer. message={0}
		log.fine(CLASS_NAME, methodName, "508", new Object[] {message.getKey()});
		if(disconnectedMessageBuffer.isPersistBuffer()){
			this.clientState.persistBufferedMessage(message);
		}
		disconnectedMessageBuffer.putMessage(message, token);
	} else {
		//@TRACE 208=failed: not connected
		log.fine(CLASS_NAME, methodName, "208");
		throw ExceptionHelper.createMqttException(MqttException.REASON_CODE_CLIENT_NOT_CONNECTED);
	}
}

In this scenario, the message enters in the second branch of the conditional: else if (disconnectedMessageBuffer != null) { ...
And the code tries to persist it in the buffer, what ends up causing a ClassCastException when trying to store the message in the buffer as a MQTTPublish object in the ClientState class:

this.persistence.put(key, (MqttPublish)message);

My suggestion, which may be insufficient in case of a race condition, is to implement the same safe-check that was added in the issue 606 validating the message is an instance of the MqttPublish class:

    (...)
    } else if(disconnectedMessageBuffer != null) {
		//@TRACE 508=Offline Buffer available. Adding message to buffer. message={0}
		log.fine(CLASS_NAME, methodName, "508", new Object[] {message.getKey()});
		if(disconnectedMessageBuffer.isPersistBuffer()){
                        if (message instanceof MqttPublish) {
                            this.clientState.persistBufferedMessage(message);
                        }
		}
		disconnectedMessageBuffer.putMessage(message, token);
    } 
    (...)
@zhubinsheng
Copy link

m

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants