RPCs: Switching from HTTPS to Secure Web Sockets

  1. My goal is:
    Understanding my options regarding responding to RPC connections and closing RPC connections.

  2. My actions are:
    I register an RPC callback and post JSON to it via HTTPS.

  3. The result I see is:
    My response comes back when calling mg_rpc_send_responsef and the connection is closed.

  4. My expectation & question is:
    This works as expected, but I was wondering if there was a way to keep the connection open, accept multiple posts to the endpoint, and then close when I please.
    My dilemma is that TLS takes about a second (give or take) to authenticate the HTTPS connection. Some commands sent require quicker timing. Therefore I was hoping to open a connection and authenticate once, keep the connection open, and then POST to and respond from that REST endpoint until I chose to close it. Is this possible, or is this not how the RPC libraries were designed?

Is there any reason not to use a (secured) websocket connection?

There is no reason. Does using a web socket for an RPC keep the TCP connection open? What API is used to respond without closing it?

Normally yes. I’m not sure if the WS implementation used by Mongoose-OS has the Ping/Pong mechanism implemented, but if, then you may continuosly check for an existing connection. And if you don’t close the WS connection on the side you’ve opened it, it should stay open and useable until you close it. That’s the purpose of a websocket. But I’m not sure if a RPC call to a MOS device may close the socket from the other side after sending the data - this you should test (or perhaps @cpq, @rojer or @nliviu might answer that).

Related to mos, you just have to open the RPC cal with “wss:// …” instead of “https://…” and use the appropriate calls on the other side. For the APi question it depends how you send the data to the device.

1 Like

Thanks @mamuesp !

Once the WSS connection is established, the RPCs should be able to fly on that open connection. Is there any way to avoid that scenario and do an outbound connection instead - e.g. to the local or remote MQTT server?

Keeping the connection open is optimal in this scenario. As long as it is secure and encrypted. So to be clear, as far as the rpc C APIs go, I have a few questions:

  1. Will the RPC handler (mgos_rpc_eh_t) registered with “mg_rpc_add_handler” be called every time data is received on this open web socket connection?

  2. Will “mg_rpc_send_responsef” still be used to respond, and will this response not close the connection?

  3. What API would be used to close the connection if we chose to from the mongoose-os side?

  1. no
  2. yes, yes
  3. https://github.com/mongoose-os-libs/rpc-common/blob/master/include/mg_rpc_channel.h#L54 should suffice

Regarding your response to #1

If the handler registered with mg_rpc_add_handler is not called whenever there is new data, then how do I receive and act on the new data?

@JonathanWitthoeft I was under impression that source code for the library in question is open.

Thanks for the backhanded RTFM. I was in technical support for 3 years before I became an engineer, so I know how frustrating seemingly stupid questions can be. However, I would take the dumb questions over the complicated ones any day.

For anyone interested in the resolution of this forum post:

I removed SSL from my project, ran a WireShark trace, and ran your mos tool to call an RPC using a websocket “ws://IP-ADDR/rpc” port. Figured it out thanks. The handler registered with mg_rpc_add_handler is indeed called whenever there is new data for that RPC method.

I was only using REST endpoints so I did not know the RPC frame format. The payload being explained here:
{ "id": 1932, "method": "GPIO.Write", "params": {"pin": 2, "value": 1} }

This was also a great breakdown of example code:

1 Like