Home/Support/Support Forum/ussl.wrap_socket truncates sent data

ussl.wrap_socket truncates sent data

+2 votes
I'm using a Digi XBee3 Cellular LTE-M/NB-IoT for data collection and sending data to a web application. I'm using micropython, sockets and ussl.wrap_socket.

I believe I've found a bug in wrap_socket; the problem is that it truncates data sent to the web application. It appears to be sending only the first packet because the truncated size is consistently 1500 bytes. If I use regular sockets (ie. no encryption), all the data is sent.

Things I've tried:
- the write() method (should send all the data)
- the send() method with my own loop to ensure all the data is sent
- setblocking(True)
- checking the return values; wrap_socket.write() reports that it sends all the bytes even though it hasn't

This is a bit difficult to demonstrate because you need a web server to receive the data and the ability to configure it for both HTTP and HTTPS to see the success and failure cases. I can provide minimal code samples for everything, but didn't want to paste them in here unformated...

Firmware version is 11410, and python version info is:
MicroPython v1.9.4-927-g7565eb7 on 2018-11-08; XBC LTE-M/NB-IoT Global with EFR32MG
asked May 23, 2019 in MicroPython by kruthers New to the Community (4 points)
Please try with the 11411 firmware and let us know if it still fails to work correctly.
Hate to tell you, but that didn't fix it.  I get the exact same number of bytes transmitted using the new firmware.

Here's my version info after the update:
FW ver 11411  Prod Bootloader: 181 Build: Apr  9 2019 15:13:14
MicroPython v1.10-1179-g94f4f29 on 2019-04-09; XBC LTE-M/NB-IoT Global with EFR32MG
Thanks for the detailed report.  I've opened a bug in our issue tracker to investigate the problem.
Ok, thanks for looking into it.
A temporary workaround is to wait for a response from the server before closing the socket.
Interesting.  I don't have the xbee available now, but the next time I have a chance I'll try to confirm that.  Thx.

Please log in or register to answer this question.

2 Answers

0 votes
Hmm... no answers. I'll try posting some code then (hopefully bbcode format works...)
host = "example.com" page = "/postlen.php" head = "POST {:s} HTTP/1.1\r\n" \ "Host: {:s}\r\n" \ "Content-Type: application/x-www-form-urlencoded\r\n" \ "Content-Length:{:d}\r\n\r\n" data = "data=" + ("abcdefghijklmnopqrstuvwxyz" * 100) headFmt = head.format(page, host, len(data)) import usocket import ussl sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM, usocket.IPPROTO_SEC) wrap = ussl.wrap_socket(sock) wrap.connect((host, 443)) sent = wrap.write(headFmt + data) if sent < len(headFmt) + len(data): raise RuntimeError("incomplete") wrap.close()

The code above fails to send all the data. Note that the RuntimeError("incomplete") should be triggered but is not, so wrap.write() is reporting that it sends all the data.

If you remove SSL, it works fine:
# (everything above here is unchanged...) import usocket sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM) sock.connect((host, 80)) sent = sock.write(headFmt + data) if sent < len(headFmt) + len(data): raise RuntimeError("incomplete") sock.close()

postlen.php is a minimal PHP script to receive the data and write the number of bytes to the error log. Note this only includes the bytes of "data=..." since PHP can't get the raw HTTP header...
<?php error_log("postlen.php received " . strlen(file_get_contents('php://input')) . " bytes"); ?>
answered May 29, 2019 by kruthers New to the Community (4 points)
I'm possibly having a similar problem in which I don't believe the write call is writing the data it says it is.  See my question over here: https://www.digi.com/support/forum/70190/mutual-tls-authentication-with-azure.

Although, looking at your code I believe the write call requires a byte array, not a string.  Try encoding it as a byte array before calling write like I am in my script and see what happens.
Interesting, it looks like you made it further than me with authentication.  I lost a day or more trying various certificate options for any sort of authentication, but always hit EIO errors.  Eventually gave up hope.

As for your suggestion, I believe my actual code was using bytearrays.  The above examples were just the simplest demonstration I could come up with.  But I'll check just to be sure.  Thanks...

EDIT:  I just checked and no, sending a bytearray made no difference.
0 votes
This has been confirmed as a bug with the LTE-M/NB-IoT product, but I don't know when a fix might be released.

A temporary workaround is to wait for a response from the server before closing the socket.
answered Jun 21, 2019 by TomCollins Veteran of the Digi Community (2,382 points)
edited Jun 24, 2019 by TomCollins