I am using HL7802 and Cellular library.
I would like to send HTTP GET request with a custom header via secure connection (HTTPS). I need to use TLS implementation in HL7802 since I don’t have enough resources on my MCU to manage PKI cryptography functions inside it.
There is an AT command for that: AT+KHTTPHEADER. When you send this command, the device responds with “CONNECT”, then you send the custom header, finish with EoF pattern and the device sends “OK” as a confirmation (see 9.13.3 of AirPrime HL78xx AT Commands Interface Guide).
I am using Cellular_ATCommandRaw from the cellular library. However, when I send AT+KHTTPHEADER=x (where x is the actual session ID), the board correctly responds with “CONNECT” but the command apparently waits for “OK” or “ERROR” before it returns. I am not able to actually put the header so it times out. I have tried all the CellularATCommandType_t values but nothing seems to work.
I also thought about using Cellular_SocketSend. It would not be as nice but I can construct the HTTP request by myself. However, the socket cannot be created secure. There is no option to use TLS (using TLS implementation inside HL7802).
Is there any solution to this? I would prefer one that would notify me when - or block until - the “CONNECT” arrives so probably a new type of CellularATCommandType_t.
Cellular_ATCommandRaw is designed for AT command without send/recv data.
If you want to send AT command with data, the following API in cellular common can be used.
CellularPktStatus_t _Cellular_TimeoutAtcmdDataSendSuccessToken( CellularContext_t * pContext,
const char ** pCellularSrcTokenSuccessTable,
uint32_t cellularSrcTokenSuccessTableSize );
Take “AT+KHTTPHEADER” for example, the following is the parameter mapping for this API.
AT+KHTTPHEADER=1 # The AT command request in atReq
CONNECT # The success token in pCellularSrcTokenSuccessTable for atReq
...<EOF pattern> # The data request in dataReq
OK # The success token for dataReq
You can also reference the Cellular_SocketSend implementation in HL7802 for the API usage.
Thank you very much. I’ll try that!
OK, so I tried that and it is an improvement. Having said that, it seems like it only works with text data. But I have binary message body in the response to GET method – I am downloading a binary file. Is there a method to get everything between “CONNECT” and “–EOF–Pattern–” as raw binary data? Because using _Cellular_TimeoutAtcmdDataSendSuccessToken seems to strip newline characters as it scans for text lines, corrupting the binary data payload.
I think it will treat everything after CONNECT as binary data.
AT+KHTTPHEADER is very much alike AT+KTCPSND, which doesn’t assume text data payload.
Can you share your code snippet? I can help to provide more information.
Oh yes, sorry, I mixed up two things here. AT+KHTTPHEADER works fine now.
My next problem is with AT+KHTTPGET, where I try to send HTTP GET request. I am using Cellular_ATCommandRaw with CELLULAR_AT_MULTI_DATA_WO_PREFIX and that is probably inappropriate.
When the answer arrives, it is parsed to a linked list of CellularATCommandLine_t. And that is a problem because the header is text but the body is binary.
The _Cellular_TimeoutAtcmdDataRecvRequestWithCallback in cellular_common can be used to retrieve data.
You can reference the HL7802 Cellular_SocketRecv implementation to receive data from modem.
dataPrefix callback function is required to indicate the data start address and data length in the pktio buffer. The data prefix callback implementation in HL7802 can also be referenced.
Since “EOF pattern” is used in AT+KHTTPGET to decide the data length, you probably need to return CELLULAR_PKT_STATUS_SIZE_MISMATCH until “EOF pattern” is observed in data prefix callback function to decide the data length. I haven’t tried using “EOF pattern” to decide the data length before. If you find some problem, please let me know.
Thank you. I will try and report back.
So far, I am trying this:
CellularPktStatus_t status = _Cellular_TimeoutAtcmdDataRecvRequestWithCallback(
- pContext is the CellularContext_t handle returned by Cellular_Init
- atReq is this structure:
CellularAtReq_t atReq =
- getString is “AT+KHTTPGET=1,”/test/sample.png"" (not exactly but I am testing against some PNG file)
- Callback is static callback method with the correct signature
- this is an instance of my wrapper class; I am programming in C++
- 0 - unused datalength
- GETTimeout = 10000 ms
- GetCallback is the callback that searches for data start and end
- this is an instance of my wrapper class
The static function GetCallback is invoked and I am able to find the beginning of message body (the PNG file) and the length is extracted from Content-Length field in the HTTP response to GET method. I am not currently searching for EOF pattern but I will add that later.
I am using range download so I only download 128 bytes of the body at a time.
After I find the start and length, I assign pDataStart pointer and pDataLength pointer in the callback and return CELLULAR_PKT_STATUS_OK.
And that is where it stops. The callback “Callback” from “atReq” is never called and the function _Cellular_TimeoutAtcmdDataRecvRequestWithCallback exits with timeout result.
I will continue after Easter but if you have any ideas, I’ll be happy to hear them.
OK, I got it working. It is far from reliable but I think I now get the idea on how the callback that calculates data length and start of it should behave.
Still, I am considering switching to TCP and use sockets, which have API support. The only thing is that Sockets have hardcoded non-secure setup (Cellular_SocketConnect). Changing it to secure should be easy. Only sending “2” instead of “0” in KTCPCFG (line 536 in cellular_hl7802_api.c, commit #84) and altering the API call to include some “secure” flag. Can this be included in the API?
Glad to hear that you can get the HTTP response with cellular interface.
New APIs are required to offload TLS to cellular modem. Including the following APIs:
- Set credential API to store certificate, private key, root CA in cellular modem.
- Set security profile API to bind the credentials previously stored in one profile to be used in the socket connection
- Set cipher suit API to select algorithm to be used in the socket connection.
- New socket option to select security profile with this connection.
When defining New APIs, we must consider various cellular modem support.
There are some potential risks need to be pointed out. The first is that the private key is transferred through comm interface. And some modem may allow private key to be read from modem. These problems need to be considered by user when using TLS offloaded by cellular modem.
Currently, we are still discussing about this feature. You can also create a PR to the repository. We will read your contribution and discuss with you about this feature.
Yes, it is a quite large topic. I was only thinking of a small subset of this – the situation where root certificates are already loaded into the modem and nothing else needs to be changed and only server is authenticated. In this case I believe, it only needs the one change I mentioned. And I can absolutely change it by myself.
But yes, in general, there are cipher suites to select (or configure) and a bunch of other options. HL7802 allows readout of private keys, which feels like a security hole so these issues are on top of that.