B4J Question Websocket_Disconnected issue

techknight

Well-Known Member
Licensed User
Longtime User
I am running into a small problem with Jetty's Websockets. (which in my case, is a LARGE problem)

If I close the browser window, the websocket_disconnected event fires no problem.

But if the internet or network drops out on the end-user device, or WiFi is turned off, user walks away out of network range, etc. the Websocket Disconnect event never fires, so I cant run a "reset" routine when the user leaves without ACK.

Oh, I should also note that I am running ABMaterial, so I cant do the ws.runmethod as a "ping" for this.

Edit: I found another thread on this issue, it could take anywhere up to 3 hours? thats way too long and I need to figure out a way to change that. This is all on a local network, locked to a single session. so if someone walks away with their device, nobody else can connect until that "session" goes bye bye.

Any ideas?
 
Last edited:

techknight

Well-Known Member
Licensed User
Longtime User
That situation does not apply here for this application.

Its a control interface to a device that if more than one person is in it, could wreak havok on the operation. So its locked to a per-user session, as its designed to be a single-user system.

But if this user leaves, or walks away, the system needs to be able to know that person isnt around anymore, so the next user that arrives, can get on.
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Even though WebSockets are persistent, they are not super-persistent. Network drops/disruptions should disconnect a WebSocket connection. Since you are using ABMaterial, ABMaterial compensates for this disconnection and will re-establish an previously connected session (via cookies, using something like this https://www.b4x.com/android/forum/threads/server-automatic-reconnecting-websocket.62054/). A workaround may be to set a session variable that contains the last accessed time. Then when the page reconnects in ABM, you can check that and if it is past a certain value, force a logout/login.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Thats why I was trying to implement a guard time. If an operator doesnt return within say 5 minutes, the connection gets booted. cache gets flushed.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
If an operator doesnt return within say 5 minutes, the connection gets booted
That should be doable in the WebSocket_Connected of each page (each page being the key).
cache gets flushed.
You may just need to invalidate the session. At that point, no cached page should be pulled up by ABM.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
B4X:
    Public CacheScavengePeriodSeconds As Int = 30*60 ' 30 Minutes
    ' -1 = immortal but beware! This also means your cache is NEVER emptied!
    Public SessionMaxInactiveIntervalSeconds As Int = 1440*60 ' 24 hours

Thats what I have them set at now, I have been playing with them, and the effects at least for the SessionMaxInactive have been undesirable.

Even if I am still connected, if that process hits, it kills the session even while active. It pops up "expired" and I get booted. Whether I am connected, or not...


I have this in my page websocket connected code:
B4X:
    If ABMShared.NeedsAuthorization Then
        Log("Number of active connections: " & ScoreEngine.Connections.Size)
        If session.GetAttribute2("IsAuthorized", "") = "" Then
            ABMShared.NavigateToPage(ws, ABMPageId, "../")
            Return
        Else
            'Make sure our page is stored in a list of known sessions
            CallSub3(ScoreEngine, "NewConnection", Me, ABMPageId) 'Since we are a valid authenticated user, Add our connection into the table. 
            If ScoreEngine.Connections.Size > 1 Then 'We have more than one connection 
                session.Invalidate
                ABMShared.NavigateToPage(ws, ABMPageId, "../")
                Return
            End If
            SocketTimer.Enabled = True
        End If
    End If

And this is in my ABMApplication websocket connected code:
B4X:
    If ABMShared.NeedsAuthorization Then
        If session.GetAttribute2("IsAuthorized", "") = "" Then 'Not logged in.
            If ScoreEngine.connections.Size = 0 Or ABMShared.LoggedIn = False Then 'No sessions logged in
                AppPage.ShowModalSheet("login")
            Else
                AppPage.ShowModalSheet("error")
            End If
            Return
        Else 'The returning session was logged in, but lets see if someone new has already logged in since then:
            If ABMShared.LoggedIn = True Then 
                session.Invalidate
                AppPage.ShowModalSheet("error")
                Return
            End If
        End If
    End If

This works great and insures that I only ever have a single "authenticated" session, but that is not where my problem is. My problem is this "seat" is never freed if the system has no idea the websocket is broken or somehow the Disconnected event did not get called.
 
Upvote 0
Top