@@ -228,33 +228,58 @@ static int mqtt_is_topic_equals(const char *topic_filter, const char *topic)
228
228
return 0 ;
229
229
}
230
230
231
- static char mqtt_topic_is_matched (char * topic_filter , MQTTString * topic_name )
231
+ // topic_filter: The filter string used in subscription (may contain +/#), e.g. a/+/c or foo/#
232
+ // topic_name: The actual topic received (should not contain wildcards), e.g. a/b/c or foo/bar
233
+ static char mqtt_topic_is_matched (const char * topic_filter , MQTTString * topic_name )
232
234
{
233
- char * curf = topic_filter ;
234
- char * curn = topic_name -> lenstring .data ;
235
- char * curn_end = curn + topic_name -> lenstring .len ;
236
-
237
- while (* curf && curn < curn_end )
238
- {
239
- if (* curn == '/' && * curf != '/' )
240
- break ;
241
-
242
- /* support wildcards for MQTT topics, such as '#' '+' */
243
- if (* curf != '+' && * curf != '#' && * curf != * curn )
244
- break ;
245
-
246
- if (* curf == '+' ) {
247
- char * nextpos = curn + 1 ;
248
- while (nextpos < curn_end && * nextpos != '/' )
249
- nextpos = ++ curn + 1 ;
235
+ const char * filter = topic_filter ;
236
+ const char * topic = topic_name -> lenstring .data ;
237
+ int topic_len = topic_name == NULL || topic_name -> lenstring .data == NULL || topic_name -> lenstring .len <= 0 ? 0 : strnlen (topic , topic_name -> lenstring .len );
238
+ int filter_len = strlen (filter );
239
+ int i = 0 , j = 0 ;
240
+ while (i < filter_len && j < topic_len ) {
241
+ if (filter [i ] == '#' ) {
242
+ // '#' must be at the end and must be preceded by '/' or be the first character
243
+ if ((i == filter_len - 1 ) && (i == 0 || filter [i - 1 ] == '/' )) {
244
+ return 1 ;
245
+ }
246
+ else {
247
+ return 0 ;
248
+ }
249
+ }
250
+ if (filter [i ] == '+' ) {
251
+ // '+' must occupy an entire level
252
+ if ((i > 0 && filter [i - 1 ] != '/' ) || (i < filter_len - 1 && filter [i + 1 ] != '/' && filter [i + 1 ] != '\0' )) {
253
+ return 0 ;
254
+ }
255
+ // Skip one level in the topic
256
+ while (j < topic_len && topic [j ] != '/' ) j ++ ;
257
+ i ++ ;
250
258
}
251
- else if (* curf == '#' )
252
- curn = curn_end - 1 ;
253
- curf ++ ;
254
- curn ++ ;
255
- };
259
+ else {
260
+ // Ordinary characters match one by one
261
+ if (filter [i ] != topic [j ]) {
262
+ return 0 ;
263
+ }
264
+ i ++ ;
265
+ j ++ ;
266
+ }
267
+ // Skip '/'
268
+ if (i < filter_len && filter [i ] == '/' && j < topic_len && topic [j ] == '/' ) {
269
+ i ++ ;
270
+ j ++ ;
271
+ }
272
+ }
256
273
257
- return (curn == curn_end ) && (* curf == '\0' );
274
+ // Process ending
275
+ if (i == filter_len && j == topic_len ) {
276
+ return 1 ;
277
+ }
278
+ // Allow ending with "/#" and topic is entirely consumed
279
+ if ((i == filter_len - 2 ) && filter [i ] == '/' && filter [i + 1 ] == '#' && j == topic_len ) {
280
+ return 1 ;
281
+ }
282
+ return 0 ;
258
283
}
259
284
260
285
static void mqtt_new_message_data (message_data_t * md , MQTTString * topic_name , mqtt_message_t * message )
@@ -442,8 +467,14 @@ static message_handlers_t *mqtt_msg_handler_create(const char* topic_filter, mqt
442
467
static void mqtt_msg_handler_destory (message_handlers_t * msg_handler )
443
468
{
444
469
if (NULL != & msg_handler -> list ) {
470
+
471
+ if (msg_handler -> list .prev == NULL || msg_handler -> list .next == NULL ) return ;
472
+
445
473
mqtt_list_del (& msg_handler -> list );
474
+ msg_handler -> list .prev == NULL ;
475
+ msg_handler -> list .next == NULL ;
446
476
platform_memory_free (msg_handler );
477
+ msg_handler = NULL ;
447
478
}
448
479
}
449
480
0 commit comments