Comments (5)
Hi Liam,
you missed to fix application_message_size in mqtt.c after line 1167
1163 if (response->qos_level > 0) {
1116 response->packet_id = (uint16_t) MQTT_PAL_NTOHS(*(uint16_t*) buf);
1165 buf += 2;
1166 }
1167
1168 /* get payload */
1169 response->application_message = buf;
1170 if ( response->qos_level > 0)
1171 response->application_message_size = fixed_header->remaining_length - response->topic_name_size - 4;
1172 else response->application_message_size = fixed_header->remaining_length - response->topic_name_size - 2;
Now mqtt.c is working very well for subscribing topics, Thanks a lot.
Best Regards,
Jedidiahuang
from mqtt-c.
Hi Liam
For mqtt_publish() , there is still have 1 bug code in mqtt.c line 1093
1092 /* calculate remaining length */
1093 remaining_length = __mqtt_packed_cstrlen(topic_name) + 2; /* variable header size */
This bug will cause an error: MQTT_ERROR_SOCKET_ERROR if publishing QoS 0 topic.
I corrected line 1093 as below, and it works well now
1093 remaining_length = __mqtt_packed_cstrlen(topic_name);
1094 if ((publish_flags & 0x06) != 0) remaining_length +=2;
Best Regards,
Jedidiahuang
from mqtt-c.
Hi Jedidiahuang,
Thanks for the issue submission, this is a bug and I've managed to locate it. First I'll highlight how I reproduced your error, then I'll explain the bug.
Reproducing the bug
You are correct, it looks like something is wrong with the first two bytes of the application message. I was able to reproduce what you see using a local Mosquitto broker. This is what I see.
Broker:
$ mosquitto -v -p 1884
1525878911: mosquitto version 1.4.8 (build date Thu, 01 Mar 2018 09:34:49 -0500) starting
1525878911: Using default config.
1525878911: Opening ipv4 listen socket on port 1884.
1525878911: Opening ipv6 listen socket on port 1884.
1525878935: New connection from 127.0.0.1 on port 1884.
1525878935: New client connected from 127.0.0.1 as publishing_client (c0, k400).
1525878935: Sending CONNACK to publishing_client (0, 0)
1525878948: New connection from 127.0.0.1 on port 1884.
1525878948: New client connected from 127.0.0.1 as subscribing_client (c0, k400).
1525878948: Sending CONNACK to subscribing_client (0, 0)
1525878948: Received SUBSCRIBE from subscribing_client
1525878948: datetime (QoS 0)
1525878948: subscribing_client 0 datetime
1525878948: Sending SUBACK to subscribing_client
1525878959: New connection from 127.0.0.1 on port 1884.
1525878959: New client connected from 127.0.0.1 as mosqsub/5264-workstatio (c1, k60).
1525878959: Sending CONNACK to mosqsub/5264-workstatio (0, 0)
1525878959: Received SUBSCRIBE from mosqsub/5264-workstatio
1525878959: datetime (QoS 0)
1525878959: mosqsub/5264-workstatio 0 datetime
1525878959: Sending SUBACK to mosqsub/5264-workstatio
1525878967: Received PUBLISH from publishing_client (d0, q0, r0, m0, 'datetime', ... (34 bytes))
1525878967: Sending PUBLISH to subscribing_client (d0, q0, r0, m0, 'datetime', ... (34 bytes))
1525878967: Sending PUBLISH to mosqsub/5264-workstatio (d0, q0, r0, m0, 'datetime', ... (34 bytes))
1525878969: Received PUBLISH from publishing_client (d0, q0, r0, m0, 'datetime', ... (34 bytes))
1525878969: Sending PUBLISH to subscribing_client (d0, q0, r0, m0, 'datetime', ... (34 bytes))
1525878969: Sending PUBLISH to mosqsub/5264-workstatio (d0, q0, r0, m0, 'datetime', ... (34 bytes))
^C1525878978: mosquitto version 1.4.8 terminating
Publisher (simple_publisher.c):
$ ./bin/simple_publisher 0.0.0.0 1884
./bin/simple_publisher is ready to begin publishing the time.
Press ENTER to publish the current time.
Press CTRL-D (or any other key) to exit.
./bin/simple_publisher published : "The time is 2018-05-09 09:16:07"
./bin/simple_publisher published : "The time is 2018-05-09 09:16:09"
./bin/simple_publisher disconnecting from 0.0.0.0
Mosquitto Subscriber:
$ mosquitto_sub -h localhost -p 1884 -v -t datetime
datetime �QThe time is 2018-05-09 09:16:07
datetime �(The time is 2018-05-09 09:16:09
I found that I could reproduce these bad characters with simple_subscriber.c by changing this line
MQTT-C/examples/simple_subscriber.c
Line 123 in 5e18fed
to
printf("Received publish('%s'): %s\n", topic_name, (const char*) published->application_message - 2);
The resulting output was this:
$ ./bin/simple_subscriber 0.0.0.0 1884
./bin/simple_subscriber listening for 'datetime' messages.
Press CTRL-D to exit.
Received publish('datetime'): �QThe time is 2018-05-09 09:16:07
Received publish('datetime'): �(The time is 2018-05-09 09:16:09
Diagnosing the bug
One thing to notice is that the first character is always "�Q" and the second character is "�(". The last two characters of the variable header (two bytes preceding the payload) are the packet ID. MQTT-C uses an LFSR to generate packet ID's which would explain why the same sequence of bad characters shows up.
It turns our packet ID's are only supposed to be included in the variable header for PUBLISH's with QOS > 0 (see mqtt-v3.1.1.pdf line 799-801). In mqtt_pack_publish_request
packet ID's are being included in the variable header for all QoS levels (see snippet below). This means that this bug should only be present for PUBLISH's with QoS 0.
Lines 1124 to 1131 in 5e18fed
How to fix
This is actually an easy fix. We only want to include the variable header iff (publish_flags & 0x06) != 0
(i.e. QoS is not 0). This means that changing lines 1126-1127 to:
1126 if ((publish_flags & 0x06) != 0) {
1127 *(uint16_t*) buf = (uint16_t) MQTT_PAL_HTONS(packet_id);
1128 buf += 2;
1129 }
Additionally, the PUBLISH response unpacker (mqtt_unpack_publish_response
lines 1163-1164) needs to be updated to only unpack PID's if QoS > 0.
1163 if (response->qos_level > 0) {
1116 response->packet_id = (uint16_t) MQTT_PAL_NTOHS(*(uint16_t*) buf);
1165 buf += 2;
1166 }
Thanks for bringing this up! I will fix this tonight or tomorrow.
Best regards,
Liam
from mqtt-c.
from mqtt-c.
Hi Jedidiahuang,
Oh right, thanks, I forgot both of those will need to be updated.
Do you want to make a pull request with the updates? If not, I can implement those changes this weekend.
Liam
from mqtt-c.
Related Issues (20)
- Would reconnect_publisher be a thing? HOT 3
- Adding contex to callbacks HOT 1
- Insufficient validation of PUBLISH message HOT 2
- Possible undefined behaviour/bad memory access after reconnect HOT 2
- MQTT_ERROR_SEND_BUFFER_IS_FULL due to transient MQTT_ERROR_SOCKET_ERROR
- FPU-Trap when calculating client->typical_response_time
- mqtt_publish return value causes mqtt_error_str when not connected
- mqtt_publish seems to only send QoS 0 HOT 1
- Possible bug in MQTT_CLIENT_TRY_PACK macro
- MQTT-C Security Issue Report (mqtt_unpack_publish_response) HOT 2
- swap use of double variables to float HOT 1
- How to check the client has received a Connack from the Broker after connect() HOT 7
- how to check network connection state in inspector callback
- Signed integer overflow in `mqtt_error_str()` HOT 2
- We cannot pass the context of the program to mqtt publish_callback HOT 2
- Mingw compile error
- Memory alignment in Keil ARM Compiler (thumb instruction set)
- mqtt_connect does not generate a client.error if wrong username and/or password is provided
- Unable to connect openssl_publisher example to HiveMQ HOT 2
- Windows MSYS2 MINGW64: Examples fail with "MQTT_ERROR_SOCKET_ERROR" or "Failed to open socket: : No error"
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mqtt-c.