Skip to content

Known Limitations - Possible Future Improvements #8

Closed
@PaulZC

Description

@PaulZC

These are notes based on v1.0.3 of the library, summarizing its known limitations and setting out possible future improvements:

Internet Protocol Sockets: Write Socket Data

The SARA-R5 has two "write socket data" commands: +USOWR and +USOST.
+USOWR will work for both TCP and UDP connections, but +USOST is preferred for UDP.

+USOWR (socketWrite)

+USOWR supports three syntaxes: Base, Base HEX; and Binary Extended.
With Base syntax, some characters (like carriage return and line feed) are forbidden.
With Base HEX, the data is provided in hexadecimal format. The module converts it to binary before sending to the socket.
Base HEX needs to be enabled (configured) through +UDCONF=1. HEX mode is disabled by default. The library currently supports UDCONF=5/6/7/8 for Direct Link connections. It would be easy to add a setHEXModeConfiguration(bool enable) function.
Base HEX doesn't seem to offer any significant advantage over Binary Extended - except there is no need to wait for the "@" before transferring the data.
I don't propose to add support for Base HEX.

socketWrite is overloaded, you can provide the data as const char * or String:

  SARA_R5_error_t socketWrite(int socket, const char *str);
  SARA_R5_error_t socketWrite(int socket, String str);

The const char * function cannot be used for binary data - especially because it uses strlen to get the length of the data (any 0x0 bytes would cause that to fail). The String function could be used for binary data, but the code currently converts the data to const char * using .c_str() (ref) and then passes it to the const char * function which uses strlen to determine the length...

In summary: socketWrite does not currently support binary data.

Action: correct this! Add a len parameter to socketWrite so it can handle Binary Extended data correctly. Update the String function so the length is passed correctly.

  socketWrite(int socket, const char *data, int len = -1)

+USOST (socketWriteUDP)

For UDP sockets, there is no need to open the socket before writing to it.

The library provides support for writing data to UDP sockets with:

  SARA_R5_error_t socketWriteUDP(int socket, const char *address, int port, const char *str, int len = -1);
  SARA_R5_error_t socketWriteUDP(int socket, String address, int port, String str, int len = -1);

The String function converts the data to const char * using .c_str() (ref) and then passes it to the const char * function. This is OK for binary data as the length ( len ) is preserved. (The function does use strlen to determine the length - but only if len is -1. If the user provides len, all is well.)

Internet Protocol Sockets: Read Socket Data

The SARA-R5 has two "write socket data" commands: +USORD and +USORF.
+USORF is for UDP connections only.

The library provides two ways to read the data: read functions and a (single) callback.

Socket Read Functions

The read functions are:

  SARA_R5_error_t socketRead(int socket, int length, char *readDest);
  SARA_R5_error_t socketReadUDP(int socket, int length, char *readDest);

socketRead can be used to read data from UDP sockets, but socketReadUDP is preferred.

socketRead handles binary data correctly.

socketReadUDP has some major limitations: the UDP remote IP address and port are lost.

I think we can solve the socketReadUDP limitations - and maintain backward-compatibility - by changing it to:

  SARA_R5_error_t socketReadUDP(int socket, int length, char *readDest, IPAddress *remoteIPAddress = NULL, int *remotePort = NULL);

Action: change the function and implement it nicely.

If the read length is set to zero, both +USORD and +USORF will return the total amount of data in the SARA's network buffer. The library does not currently support this. If len is set to zero, Both socketRead and socketReadUDP will (I think) return SARA_R5_ERROR_UNEXPECTED_RESPONSE as no quote will be found. This needs to be improved.
Action: Add additional functions / features to support requesting the buffer length.

Socket Read Callback

The callback is configured with setSocketReadCallback:

  void setSocketReadCallback(void (*socketReadCallback)(int, String));

int is the socket. String contains the data.

There are some major limitations here:

The same callback is used for TCP and UDP data. This is a major limitation as the UDP remote IP address and port are lost.

Going forward, I propose we provide a separate callback for UDP data.

For TCP:

The data is returned in a String. This is OK for binary data. The length can be determined correctly using the .length() command. But it is not an elegant solution for binary data.

We could provide an extra set function and an extra callback:

  void setSocketReadCallback(void (*socketReadCallback)(int, const char *, int)); // socket, data, dataLength

where: int is the socket, const char * contains the data, int is the length.

We would need to change processURCEvent (specifically parseSocketReadIndication ) so it would know which of the two callbacks to call. But that would be easy to do. We'd just need to make sure that calling one set function sets the callback pointer for the other to NULL. parseSocketReadIndication would call the callback that isn't NULL.

Action: think more about this - then almost certainly implement it.

For UDP:

UDP needs its own callback. Action: add one!

  void setSocketReadUDPCallback(void (*socketReadUDPCallback)(int, const char *, int, IPAddress, int)); // socket, data, dataLength, remoteIPAddress, remotePort

Note: this would break backward-compatibility for anyone currently using setSocketReadCallback for UDP sockets. They won't get their data any more...

Or, even better - maintaining backward-compatibility - change the new extra set function to:

  void setSocketReadCallback(void (*socketReadCallback)(int, const char *, int, IPAddress, int)); // socket, data, dataLength, remoteIPAddress, remotePort

where: int is the socket, const char * contains the data, int is the length. remoteIPAddress and remotePort would be set to zero for TCP. Users using the original setSocketReadCallback for UDP sockets could still get their data (minus the remote address and port).

Action: think more about this - then almost certainly implement it.

+UUOST

processURCEvent does not currently support the +UUOST URC - the UDP write result. It would be nice to add support for this, including a callback.

Action: think more about this - then almost certainly implement it.

Direct Link Mode

With:

  SARA_R5_error_t socketDirectLinkMode(int socket);
  SARA_R5_error_t socketDirectLinkTimeTrigger(int socket, unsigned long timerTrigger);
  SARA_R5_error_t socketDirectLinkDataLengthTrigger(int socket, int dataLengthTrigger);
  SARA_R5_error_t socketDirectLinkCharacterTrigger(int socket, int characterTrigger);
  SARA_R5_error_t socketDirectLinkCongestionTimer(int socket, unsigned long congestionTimer);

I believe the library includes everything needed for direct link mode? Except, it might be nice to add a endSocketDirectLink() function:

  • Wait two seconds (in a thread-friendly way)
  • Send +++

Action: think more about this.

+USOER

Socket errors are reported through +USOER. The library provides the socketGetLastError function. No improvements necessary?

+USOCLCFG

Dormant sockets can be closed automatically through +USOCLCFG. The library does not currently support this command, but closing dormant sockets is enabled by default. It would be easy to add a setDormantSocketCloseBehaviour(bool enable) function.

Action: think more about this - then almost certainly implement it.

+USOCTL

The library does not currently support for +USOCTL. It would be nice to add support so that the total amount of bytes transferred, socket type, remote IP address, socket status, etc. could be queried. To make it easy for the user, it would be best to provide multiple functions:

  SARA_R5_error_t querySocketType(int socket, SARA_R5_socket_protocol_t *protocol)
  SARA_R5_error_t querySocketLastError(int socket, int *error)
  SARA_R5_error_t querySocketTotalBytesSent(int socket, uint32_t *total)
  SARA_R5_error_t querySocketTotalBytesReceived(int socket, uint32_t *total)
  SARA_R5_error_t querySocketRemoteIPAddress(int socket, IPAddress address, int *port)
  SARA_R5_error_t querySocketRemoteIPAddress(int socket, String address, int *port)
  SARA_R5_error_t querySocketRemoteIPAddress(int socket, char *address, int *port)
  SARA_R5_error_t querySocketStatusTCP(int socket, int *status)
  SARA_R5_error_t querySocketOutUnackData(int socket, uint32_t *total)

Action: think more about this - then almost certainly implement it.

Other improvements:

I'd like to try and standardize on using IPAddress for all IP address parameters. Action: Add IPAddress-based functions/overloads:

  SARA_R5_error_t socketConnect(int socket, IPAddress address, int port);
  SARA_R5_error_t socketWriteUDP(int socket, IPAddress address, int port, const char *str, int len = -1);

Action: think more about this - then almost certainly implement it.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions