UIBuilder - Get list of open Websockets

I'm working on a multi-user dashboard to login to devices, and am using the sockets IDs output by by UIB to maintain a status array of all the current connections (Idle, processing data etc.) - unfortunately, our company network is a bit flakey, and therefore users end up refreshing the page whilst the terminal is disconnected, or even rebooting the PC which sometimes doesn't give UIB a chance to send the client disconnect message. This means over time a number of dead connections build up. I have each connection timestamped, so not a major issue to get rid of old ones after 72 hours of inactivity etc, but I don't to kill connections that are ok, but haven't been used so it isn't ideal.

Is it possible to get UIB to send out a list of currently open websockets? I have read through the control message page on the Wiki and didn't get anything there, nor make much progress trying to modify stuff in here https://stackoverflow.com/questions/6563885/socket-io-how-do-i-get-a-list-of-connected-sockets-clients

Apologies, this answer is rather rambling as I was thinking as I went along ...

Hi, firstly you need to know, as you probably already do, that Socket.IO creates a new socket ID on a page reload OR on a socket reconnect which could happen if you have an unreliable network connection.

uibuilder will send out a control msg (port 2) every time it senses a connection which should let you reliably log those. But, as you say, if the socket was terminated, there is nothing uibuilder can do to tell you about dead connections.

That means that you really need some kind of session management or at least JWT (note that contrary to common believe, JWT is NOT a security feature, merely a convenient, standards-based token).

The issue with session management and websockets is that you cannot use custom headers with a socket connection once that connection has been "promoted" to a websocket. The initial connection is straight http(s) and you can send headers there, cookies also work. But once the connection promotes, no extra headers can be passed. So even JWT only works on the initial connection. After that, you would need to include the JWT with all of your messages (in both directions). That is what you will find if you look at the security branch of uibuilder which will be the next release.

So, you currently only have a couple of choices:

  1. Do as you have been and keep track of which socket id's have stopped getting updates.
  2. Build a more robust session management feature such as I've been trying to get on with in v3 for far too long now (drat you COVID!).

v3 tries to define a standard data exchange schema for msg's covering authentication and authorisation. It also provides a middleware JavaScript file that defines standard functions for doing identity and authorisation checks. It uses JWT to help but encourages you to think about the limitations of JWT in a security context and the JWT's are exchanged in the msg's automatically once the socket connection has been made.

No, because I don't believe that Socket.IO maintains that information. The security middleware feature of v3 would let you track socket ID's along with the rest of your session info.

Note that v2 also has some middleware features that let you insert your own middleware. But you hid the same problem with websockets. The Socket.IO middleware function can only get called on the initial connection, after that, it cannot be used.

In regard to the Stack Overflow question, I think that the answers all have the same issue - that the server only knows what was connected, not what actually is connected. However, I'll admit that I haven't tested that.

Possibly a trick that could be used would be to use the regular ping/pong messages that Socket.IO issues could be tracked. What I don't know without further testing is whether the Socket.IO server already tracks that. Presumably, the server has a client timeout value so it may dump entries from its connected client list after a set time. Ah, yes, this question has the answer to that.

So, in theory it would indeed be possible to get a list of the "currently alive" client connections. Based on the connection timeout configuration. You could also align your own list to the server's timeout values (I leave them at the defaults) as a workaround.

Sorry, it has been a long 2 days and this answer is terribly meandering because I'm very tired. Let me know whether it makes sense.

Thanks, that is an excellent ramble and more answer than I expected!

Your mention of ping pong messages gave me a brain wave, obviously I have a list of socket IDs which may have clients connected, I just need to send each one a ping, which gets replied to using the standard UIB message handling, if I don't get a pong back before a timeout of a few seconds I can assume the session is gone and can delete it. This will have the effect of keeping alive ones alive as well as dead ones gone.

I've already got an asynchronous timeout function node built up, that'll allow me to check all the sockets at once with some modding.

Then I can modify the function that maintains the client list to check every request ID rather than just the specific connection messages and add it if needed, just in case one gets lost. Should be robust enough.

I'd love to help out with the development, I've been working with UIB lots over the last few months and combined with NR it's an amazing tool, but have yet to delve into the custom nodes side of things. I attempted to solve an issue an MSSQL node a while back, the dev responded to and solved my git issue before I'd even worked out how to pull the node apart!

Socket.IO automatically sends pings every few seconds. Most people just ignore them as I do in uib. Could be exposed though as an option if there is a need.

Well, it would be welcome to be sure.

I have a jktest repo that contains some example code for nodes. I've used it for myself to learn how to do things.

uib is a bit of a rats nest of code. If you fancy having a look, I would clone the security branch. I want to release that as v3. I don't think the security part will be quite complete but it is taking too long and there are some important fixes and improvements in the code. The security branch also has some additional developer documentation.