-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Dynamic packet size #282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic packet size #282
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,93 +12,125 @@ PubSubClient::PubSubClient() { | |
| this->_client = NULL; | ||
| this->stream = NULL; | ||
| setCallback(NULL); | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
|
|
||
| PubSubClient::PubSubClient(Client& client) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setClient(client); | ||
| this->stream = NULL; | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
|
|
||
| PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(addr, port); | ||
| setClient(client); | ||
| this->stream = NULL; | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(addr,port); | ||
| setClient(client); | ||
| setStream(stream); | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(addr, port); | ||
| setCallback(callback); | ||
| setClient(client); | ||
| this->stream = NULL; | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(addr,port); | ||
| setCallback(callback); | ||
| setClient(client); | ||
| setStream(stream); | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
|
|
||
| PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(ip, port); | ||
| setClient(client); | ||
| this->stream = NULL; | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(ip,port); | ||
| setClient(client); | ||
| setStream(stream); | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(ip, port); | ||
| setCallback(callback); | ||
| setClient(client); | ||
| this->stream = NULL; | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(ip,port); | ||
| setCallback(callback); | ||
| setClient(client); | ||
| setStream(stream); | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
|
|
||
| PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(domain,port); | ||
| setClient(client); | ||
| this->stream = NULL; | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(domain,port); | ||
| setClient(client); | ||
| setStream(stream); | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(domain,port); | ||
| setCallback(callback); | ||
| setClient(client); | ||
| this->stream = NULL; | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
| PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { | ||
| this->_state = MQTT_DISCONNECTED; | ||
| setServer(domain,port); | ||
| setCallback(callback); | ||
| setClient(client); | ||
| setStream(stream); | ||
| this->buffer_size = MQTT_MAX_PACKET_SIZE; | ||
| this->buffer = (uint8_t*)malloc(MQTT_MAX_PACKET_SIZE); | ||
| } | ||
|
|
||
| PubSubClient::~PubSubClient() { | ||
| free(this->buffer); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should check if this->buffer is NULL or not since setBufferSize() can set it to NULL. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope. according to the spec std::free() should treat a null pointer as a no-op.
(it makes sense because std::malloc returns null pointer on failure.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, sweet, I haven't really coded C/C++ in ages and back then it was a no-no since freeing a null pointer would cause some environments to go belly up. :-) |
||
| } | ||
|
|
||
| boolean PubSubClient::connect(const char *id) { | ||
|
|
@@ -266,13 +298,13 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { | |
| this->stream->write(digit); | ||
| } | ||
| } | ||
| if (len < MQTT_MAX_PACKET_SIZE) { | ||
| if (len < this->buffer_size) { | ||
| buffer[len] = digit; | ||
| } | ||
| len++; | ||
| } | ||
|
|
||
| if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { | ||
| if (!this->stream && len > this->buffer_size) { | ||
| len = 0; // This will cause the packet to be ignored. | ||
| } | ||
|
|
||
|
|
@@ -356,7 +388,7 @@ boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigne | |
|
|
||
| boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { | ||
| if (connected()) { | ||
| if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) { | ||
| if (this->buffer_size < 5 + 2+strlen(topic) + plength) { | ||
| // Too long | ||
| return false; | ||
| } | ||
|
|
@@ -471,7 +503,7 @@ boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { | |
| if (qos < 0 || qos > 1) { | ||
| return false; | ||
| } | ||
| if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { | ||
| if (this->buffer_size < 9 + strlen(topic)) { | ||
| // Too long | ||
| return false; | ||
| } | ||
|
|
@@ -492,7 +524,7 @@ boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { | |
| } | ||
|
|
||
| boolean PubSubClient::unsubscribe(const char* topic) { | ||
| if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { | ||
| if (this->buffer_size < 9 + strlen(topic)) { | ||
| // Too long | ||
| return false; | ||
| } | ||
|
|
@@ -586,3 +618,13 @@ PubSubClient& PubSubClient::setStream(Stream& stream){ | |
| int PubSubClient::state() { | ||
| return this->_state; | ||
| } | ||
|
|
||
| boolean PubSubClient::setBufferSize(uint16_t size) { | ||
| this->buffer = (uint8_t*)realloc(this->buffer, size); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should use a temp variable. If realloc fails it will return a NULL pointer without freeing the original memory. Thus, if NULL is returned this method should not make any change to this->buffer since it is still valid. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. this makes sense. @knolleary is this pull request likely to ever be merged? is it worth me doing this? |
||
| this->buffer_size = size; | ||
| return (this->buffer == NULL); | ||
| } | ||
|
|
||
| uint16_t PubSubClient::getBufferSize() { | ||
| return this->buffer_size; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -160,6 +160,43 @@ int test_receive_oversized_message() { | |
| END_IT | ||
| } | ||
|
|
||
| int test_resize_buffer() { | ||
| IT("receives a message larger than the default maximum"); | ||
| reset_callback(); | ||
|
|
||
| ShimClient shimClient; | ||
| shimClient.setAllowConnect(true); | ||
|
|
||
| byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; | ||
| shimClient.respond(connack,4); | ||
|
|
||
| PubSubClient client(server, 1883, callback, shimClient); | ||
| int rc = client.connect((char*)"client_test1"); | ||
| IS_TRUE(rc); | ||
|
|
||
| int length = MQTT_MAX_PACKET_SIZE+1; | ||
| client.setBufferSize(length); | ||
| byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; | ||
| byte bigPublish[length]; | ||
| memset(bigPublish,'A',length); | ||
| bigPublish[length] = 'B'; | ||
| memcpy(bigPublish,publish,16); | ||
| shimClient.respond(bigPublish,length); | ||
|
|
||
| rc = client.loop(); | ||
|
|
||
| IS_TRUE(rc); | ||
|
|
||
| IS_TRUE(callback_called); | ||
| IS_TRUE(strcmp(lastTopic,"topic")==0); | ||
| IS_TRUE(lastLength == length-9); | ||
| IS_TRUE(memcmp(lastPayload,bigPublish+9,lastLength)==0); | ||
|
|
||
| IS_FALSE(shimClient.error()); | ||
|
|
||
| END_IT | ||
| } | ||
|
|
||
| int test_receive_oversized_stream_message() { | ||
| IT("drops an oversized message"); | ||
| reset_callback(); | ||
|
|
@@ -242,6 +279,7 @@ int main() | |
| test_receive_stream(); | ||
| test_receive_max_sized_message(); | ||
| test_receive_oversized_message(); | ||
| test_resize_buffer(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the merge request contains functionality to dynamically change the buffer size it would be suitable to have tests that verify that this works well. E g:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, all make sense. Let's see if this is likely to be merged first. |
||
| test_receive_oversized_stream_message(); | ||
| test_receive_qos1(); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woudn't it be better to move the buffer allocation to a support function, rather than duplicate the same code in all constructors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i agree in principal but
i was trying to match the existing code style. (ie, explicitly calling everything in each constructor.)
@knolleary any opinion?