This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

mqtt_publish in new SDK cannot handle large payloads.

I'd previously run into this problem with mqtt_publish not being able to handle large payloads, larger than approximately 2k.

At the time, the suggested workaround was to patch mqtt_client_tls_write in mqtt_transport_socket_tls.c.

The patched version of the function looks like:

int mqtt_client_tls_write(struct mqtt_client *client, const u8_t *data,
			  u32_t datalen)
{
	u32_t offset = 0U;
	int ret;

	while (offset < datalen) {
		ret = send(client->transport.tls.sock, data + offset,
            MIN(1024,(datalen - offset)), 0);
		if (ret < 0) {
			return -errno;
		}

		offset += ret;
	}

	return 0;
}

It looks like there's a new config option CONFIG_NRF91_SOCKET_SEND_SPLIT_LARGE_BLOCKS which might render this change unneeded.

However, there's also a change to mqtt_publish in mqtt.c, which now uses client_write_msg instead of client_write. I didn't dig all they way through it, but without CONFIG_NRF91_SOCKET_SEND_SPLIT_LARGE_BLOCKS set causes mqtt_publish to return -22. If you set CONFIG_NRF91_SOCKET_SEND_SPLIT_LARGE_BLOCKS then it appears to work, but never actually sends the data.

For time being, I've reverted the changes to mqtt_publish, but it would be better if mqtt_publish worked correctly.

Parents
  • Hi Joshua

    You can check out the discussion on our Github regarding this workaround and the implementation of CONFIG_NRF_91_SOCKET_SEND_SPLIT_LARGE_BLOCKS here. I hope you find it useful.

    Please note that we're entering the summer vacation period here in Norway, so delays must be expected as we are low on staff for the month of July. Sorry about the inconvenience!

    Best regards,

    Simon

  • It looks to me like CONFIG_NRF_91_SOCKET_SEND_SPLIT_LARGE_BLOCKS is not completely implemented in the 1.3 SDK. If you look at the code, here's what you'll see:

    static ssize_t nrf91_socket_offload_sendto(void *obj, const void *buf,
    					   size_t len, int flags,
    					   const struct sockaddr *to,
    					   socklen_t tolen)
    {
    	int sd = OBJ_TO_SD(obj);
    	ssize_t retval;
    
    	if (IS_ENABLED(CONFIG_NRF91_SOCKET_SEND_SPLIT_LARGE_BLOCKS)) {
    		len = MIN(len, CONFIG_NRF91_SOCKET_BLOCK_LIMIT);
    	}
    
    	if (to == NULL) {
    		retval = nrf_sendto(sd, buf, len, z_to_nrf_flags(flags), NULL,
    				    0);
    	} else if (to->sa_family == AF_INET) {
    		struct nrf_sockaddr_in ipv4;
    		nrf_socklen_t sock_len = sizeof(struct nrf_sockaddr_in);
    
    		z_to_nrf_ipv4(to, &ipv4);
    		retval = nrf_sendto(sd, buf, len, z_to_nrf_flags(flags), &ipv4,
    				    sock_len);
    	} else if (to->sa_family == AF_INET6) {
    		struct nrf_sockaddr_in6 ipv6;
    		nrf_socklen_t sock_len = sizeof(struct nrf_sockaddr_in6);
    
    		z_to_nrf_ipv6(to, &ipv6);
    		retval = nrf_sendto(sd, buf, len, z_to_nrf_flags(flags), &ipv6,
    				    sock_len);
    	} else {
    		goto error;
    	}
    
    	return retval;
    
    error:
    	retval = -1;
    	errno = ENOTSUP;
    	return retval;
    }
    

    You'll note that the length is truncated at the configured length of 2048 bytes, but neither in this function nor in the higher level functions that call it is the call to nrf_sendto repeated with the remainder of the message.

    I've patched my branch of the nrf 1.3 sdk to fix this, but it seems it should be fixed.

    Or perhaps I'm missing something?

  • I'm sorry for the late reply, it is caused by the reasons mentioned by simonr. I'll try to provide you with an answer in the upcoming week.

    Best regards,

    Simon

Reply Children
  • I am not too familiar with this library, but it seems like you have to call nrf91_socket_offload_sendto() several times until all data is sent. If the len argument exceeds CONFIG_NRF91_SOCKET_BLOCK_LIMIT=2048, then it will return the number of bytes sent (2048 if maximum).

    When nrf91_socket_offload_sendto() returns, you move your *buf pointer by that amount and decrement the total amount of byte with the returned number. Repeat this until all data is sent.

    Best regards,

    Simon

  • Simon,

    I gathered that, and have implemented it for my own code. However, the mqtt library that you supply DOES NOT do this. This is a problem because now I need to modify yet another thing that should just work. I've chosen to modify the nrf91_socket_offload_sendto function rather than the mqtt library, as it's logistically easier for me as I've already made my own fork of the nrf repo, and I would prefer not to fork zephry (where the mqtt lib resides) as well.

    I really think you should consider having nrf91_socket_offload_sendto automatically send all segments of a message, or, alternately, find the dozens of places in mqtt libraries and other places where it would need to be implemented.

    Regards,

    Josh

  • It seems like there have been some updates on this. Please check out the master branch and the function nrf91_socket_offload_sendmsg(), as well as the configuration CONFIG_BSD_LIBRARY_SENDMSG_BUF_SIZE

    Best regards,

    Simon

Related