@@ -228,33 +228,58 @@ static int mqtt_is_topic_equals(const char *topic_filter, const char *topic)
228228 return 0 ;
229229}
230230
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 )
232234{
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 ++ ;
250258 }
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+ }
256273
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 ;
258283}
259284
260285static 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
442467static void mqtt_msg_handler_destory (message_handlers_t * msg_handler )
443468{
444469 if (NULL != & msg_handler -> list ) {
470+
471+ if (msg_handler -> list .prev == NULL || msg_handler -> list .next == NULL ) return ;
472+
445473 mqtt_list_del (& msg_handler -> list );
474+ msg_handler -> list .prev == NULL ;
475+ msg_handler -> list .next == NULL ;
446476 platform_memory_free (msg_handler );
477+ msg_handler = NULL ;
447478 }
448479}
449480
0 commit comments