Skip to content

Commit dd64f18

Browse files
committed
Fix subscription identifier out of bounds of mqtt5 specification
Signed-off-by: Gary Tse <gary.garytse@gmail.com>
1 parent bd291f1 commit dd64f18

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.eclipse.paho.mqttv5.client.internal;
2+
3+
import org.junit.Test;
4+
5+
import static org.junit.Assert.*;
6+
7+
public class MqttSessionStateTest {
8+
9+
@Test
10+
public void testClearSessionState() {
11+
MqttSessionState state = new MqttSessionState();
12+
state.clearSessionState();
13+
assertTrue("Clear session state resets subscription identifier", 1 == state.getNextSubscriptionIdentifier());
14+
}
15+
16+
/**
17+
* Test that the subscription identifier is bounded between 1 and 268,435,455
18+
*/
19+
@Test
20+
public void testSubscriptionIdIsBounded() {
21+
MqttSessionState state = new MqttSessionState();
22+
for (int i = 1; i <= 268_435_456; i++) {
23+
assertTrue("Subscription identifier minimum bound", state.getNextSubscriptionIdentifier()>=1);
24+
assertTrue("Subscription identifier maximum bound", state.getNextSubscriptionIdentifier()<=268_435_455);
25+
}
26+
}
27+
28+
}

org.eclipse.paho.mqttv5.client/src/main/java/org/eclipse/paho/mqttv5/client/internal/MqttSessionState.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,34 @@
1414
* <li>Next Subscription Identifier - The next subscription Identifier available
1515
* to use.</li>
1616
* </ul>
17+
*
18+
* Subscription identifier can take values from 1 to 268,435,455 according to MQTTv5 specification
19+
* @see <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901023">MQTTv5 Specification 3.8.2.1.2 Subscription Identifier</a>
1720
*/
1821
public class MqttSessionState {
1922

2023
// ******* Session Specific Properties and counters ******//
2124
private AtomicInteger nextSubscriptionIdentifier = new AtomicInteger(1);
2225
private String clientId;
26+
private Integer SUBSCRIPTION_IDENTIFIER_MAX_LIMIT = 268_435_455;
2327

2428
public void clearSessionState() {
2529
nextSubscriptionIdentifier.set(1);
2630
}
2731

2832
public Integer getNextSubscriptionIdentifier() {
33+
Integer nextValue = nextSubscriptionIdentifier.getAndIncrement();
34+
if (nextValue <= SUBSCRIPTION_IDENTIFIER_MAX_LIMIT) {
35+
return nextValue;
36+
}
37+
38+
// nextValue > SUBSCRIPTION_IDENTIFIER_MAX_LIMIT, so we need to restart the identifier from 1
39+
synchronized(nextSubscriptionIdentifier) {
40+
// read again to make sure no other thread has updated the value
41+
if (nextSubscriptionIdentifier.get() > SUBSCRIPTION_IDENTIFIER_MAX_LIMIT) {
42+
clearSessionState();
43+
}
44+
}
2945
return nextSubscriptionIdentifier.getAndIncrement();
3046
}
3147

0 commit comments

Comments
 (0)