@@ -70,7 +70,7 @@ public class PublishFlowHandler extends ChannelDuplexHandler {
70
70
private final @ NotNull IncomingPublishHandler incomingPublishHandler ;
71
71
private final @ NotNull DropOutgoingPublishesHandler dropOutgoingPublishesHandler ;
72
72
73
- private final @ NotNull Map <Integer , Boolean > qos1And2AlreadySentMap ;
73
+ private final @ NotNull Map <Integer , Boolean > qos1AlreadySentMap ;
74
74
75
75
@ VisibleForTesting
76
76
@ Inject
@@ -83,7 +83,7 @@ public PublishFlowHandler(
83
83
this .publishPollService = publishPollService ;
84
84
this .persistence = persistence ;
85
85
this .orderedTopicService = orderedTopicService ;
86
- this .qos1And2AlreadySentMap = new HashMap <>();
86
+ this .qos1AlreadySentMap = new HashMap <>();
87
87
this .incomingPublishHandler = incomingPublishHandler ;
88
88
this .dropOutgoingPublishesHandler = dropOutgoingPublishesHandler ;
89
89
}
@@ -117,13 +117,17 @@ public void write(
117
117
118
118
if (msg instanceof PUBACK ) {
119
119
final PUBACK puback = (PUBACK ) msg ;
120
- final String client = ClientConnection .of (ctx .channel ()).getClientId ();
121
120
final int messageId = puback .getPacketIdentifier ();
122
- persistence .addOrReplace (client , messageId , puback );
123
- promise .addListener (new PUBLISHFlowCompleteListener (messageId ,
124
- client ,
125
- qos1And2AlreadySentMap ,
126
- persistence ));
121
+ promise .addListener ((ChannelFutureListener ) future -> {
122
+ if (future .isSuccess ()) {
123
+ qos1AlreadySentMap .remove (messageId );
124
+ if (log .isTraceEnabled ()) {
125
+ log .trace ("Client '{}' completed a PUBLISH flow with QoS 1 for packet identifier '{}'" ,
126
+ ctx ,
127
+ messageId );
128
+ }
129
+ }
130
+ });
127
131
}
128
132
129
133
final boolean flowComplete = orderedTopicService .handlePublish (ctx .channel (), msg , promise );
@@ -183,22 +187,27 @@ private void handlePublish(
183
187
184
188
if (publish .getQoS () == QoS .AT_MOST_ONCE ) {// do nothing
185
189
incomingPublishHandler .interceptOrDelegate (ctx , publish , clientId );
186
- // QoS 1 or 2 duplicate delivery handling
187
- } else {
190
+ // QoS 1 delivery handling
191
+ } else if ( publish . getQoS () == QoS . AT_LEAST_ONCE ) {
188
192
UNACKNOWLEDGED_PUBLISHES_COUNTER .incrementAndGet ();
193
+ if (publish .isDuplicateDelivery () && qos1AlreadySentMap .get (publish .getPacketIdentifier ()) != null ) {
194
+ log .debug ("Client {} sent a duplicate publish message with id {}. This message is ignored" ,
195
+ clientId ,
196
+ publish .getPacketIdentifier ());
197
+ } else {
198
+ final int packetId = publish .getPacketIdentifier ();
199
+ qos1AlreadySentMap .put (publish .getPacketIdentifier (), true );
200
+ firstPublishForMessageIdReceived (ctx , publish , clientId , packetId );
201
+ }
202
+ // QoS 2 duplicate delivery handling
203
+ } else {
189
204
final int messageId = publish .getPacketIdentifier ();
190
205
final MessageWithID savedMessage = persistence .get (clientId , messageId );
191
-
192
- //No PUBLISH message was found in persistence. This is the standard case since we don't know this message yet
193
206
if (!(savedMessage instanceof PUBLISH )) {
207
+ persistence .addOrReplace (clientId , messageId , publish );
194
208
firstPublishForMessageIdReceived (ctx , publish , clientId , messageId );
195
- //The publish was resent with the DUP flag
196
- } else if (publish .isDuplicateDelivery ()) {
197
- resentWithDUPFlag (ctx , publish , clientId );
198
- //The publish was resent without DUP flag!
199
- } else {
200
- resentWithoutDUPFlag (ctx , publish , clientId );
201
- }
209
+ } else
210
+ ctx .writeAndFlush (new PUBREC (messageId ));
202
211
}
203
212
}
204
213
@@ -207,47 +216,13 @@ private void firstPublishForMessageIdReceived(
207
216
final @ NotNull PUBLISH publish ,
208
217
final @ NotNull String client ,
209
218
final int messageId ) throws Exception {
210
- persistence .addOrReplace (client , messageId , publish );
211
219
incomingPublishHandler .interceptOrDelegate (ctx , publish , client );
212
- qos1And2AlreadySentMap .put (messageId , true );
213
220
log .trace (
214
221
"Client {} sent a publish message with id {} which was not forwarded before. This message is processed normally" ,
215
222
client ,
216
223
messageId );
217
224
}
218
225
219
- private void resentWithDUPFlag (
220
- final @ NotNull ChannelHandlerContext ctx , final @ NotNull PUBLISH publish , final @ NotNull String client )
221
- throws Exception {
222
- final Boolean alreadySent = qos1And2AlreadySentMap .get (publish .getPacketIdentifier ());
223
- if (alreadySent != null && alreadySent ) {
224
-
225
- log .debug ("Client {} sent a duplicate publish message with id {}. This message is ignored" ,
226
- client ,
227
- publish .getPacketIdentifier ());
228
- } else {
229
- super .channelRead (ctx , publish );
230
- log .debug (
231
- "Client {} sent a duplicate publish message with id {} which was not forwarded before. This message is processed normally" ,
232
- client ,
233
- publish .getPacketIdentifier ());
234
- }
235
- qos1And2AlreadySentMap .put (publish .getPacketIdentifier (), true );
236
- }
237
-
238
- private void resentWithoutDUPFlag (
239
- final @ NotNull ChannelHandlerContext ctx , final @ NotNull PUBLISH publish , final @ NotNull String client )
240
- throws Exception {
241
- log .debug (
242
- "Client {} sent a new PUBLISH with QoS {} and a message identifier which is already in process ({}) by another flow! Starting new flow" ,
243
- client ,
244
- publish .getQoS ().getQosNumber (),
245
- publish .getPacketIdentifier ());
246
- persistence .addOrReplace (client , publish .getPacketIdentifier (), publish );
247
- incomingPublishHandler .interceptOrDelegate (ctx , publish , client );
248
- qos1And2AlreadySentMap .put (publish .getPacketIdentifier (), true );
249
- }
250
-
251
226
252
227
private void handlePuback (final @ NotNull ChannelHandlerContext ctx , final PUBACK msg ) {
253
228
@@ -291,7 +266,7 @@ private void handlePubrel(final ChannelHandlerContext ctx, final PUBREL pubrel)
291
266
292
267
persistence .addOrReplace (client , messageId , pubrel );
293
268
ctx .writeAndFlush (new PUBCOMP (messageId ))
294
- .addListener (new PUBLISHFlowCompleteListener (messageId , client , qos1And2AlreadySentMap , persistence ));
269
+ .addListener (new PubcompSentListener (messageId , client , persistence ));
295
270
}
296
271
297
272
private void handlePubcomp (final @ NotNull ChannelHandlerContext ctx , @ NotNull final PUBCOMP msg ) {
@@ -329,31 +304,27 @@ private void returnMessageId(
329
304
}
330
305
331
306
@ Immutable
332
- private static class PUBLISHFlowCompleteListener implements ChannelFutureListener {
307
+ private static class PubcompSentListener implements ChannelFutureListener {
333
308
334
309
private final int messageId ;
335
310
private final @ NotNull String client ;
336
- private final @ NotNull Map <Integer , Boolean > qos1And2AlreadySentMap ;
337
311
private final @ NotNull IncomingMessageFlowPersistence persistence ;
338
312
339
- PUBLISHFlowCompleteListener (
313
+ PubcompSentListener (
340
314
final int messageId ,
341
315
final @ NotNull String client ,
342
- final @ NotNull Map <Integer , Boolean > qos1And2AlreadySentMap ,
343
316
final @ NotNull IncomingMessageFlowPersistence persistence ) {
344
317
this .messageId = messageId ;
345
318
this .client = client ;
346
- this .qos1And2AlreadySentMap = qos1And2AlreadySentMap ;
347
319
this .persistence = persistence ;
348
320
}
349
321
350
322
@ Override
351
- public void operationComplete (final ChannelFuture future ) throws Exception {
323
+ public void operationComplete (final ChannelFuture future ) {
352
324
if (future .isSuccess ()) {
353
325
UNACKNOWLEDGED_PUBLISHES_COUNTER .decrementAndGet ();
354
- qos1And2AlreadySentMap .remove (messageId );
355
326
persistence .remove (client , messageId );
356
- log .trace ("Client '{}' completed a PUBLISH flow with QoS 1 or 2 for packet identifier '{}'" ,
327
+ log .trace ("Client '{}' completed a PUBLISH flow with QoS 2 for packet identifier '{}'" ,
357
328
client ,
358
329
messageId );
359
330
}
0 commit comments