diff --git a/lib/tunnelbroker/tunnelbroker-context.js b/lib/tunnelbroker/tunnelbroker-context.js --- a/lib/tunnelbroker/tunnelbroker-context.js +++ b/lib/tunnelbroker/tunnelbroker-context.js @@ -60,6 +60,11 @@ const promises = React.useRef({}); const heartbeatTimeoutID = React.useRef(); + const previousInitMessage = + React.useRef(initMessage); + const initMessageChanged = initMessage !== previousInitMessage.current; + previousInitMessage.current = initMessage; + const stopHeartbeatTimeout = React.useCallback(() => { if (heartbeatTimeoutID.current) { clearTimeout(heartbeatTimeoutID.current); @@ -75,7 +80,28 @@ }, tunnelbrokerHeartbeatTimeout); }, [stopHeartbeatTimeout]); + // determine if the socket is active (not closed or closing) + const isSocketActive = + socket.current?.readyState === WebSocket.OPEN || + socket.current?.readyState === WebSocket.CONNECTING; + + // The Tunnelbroker connection can have 4 states: + // - DISCONNECTED: isSocketActive = false, connected = false + // Should be in this state when initMessage is null + // - CONNECTING: isSocketActive = true, connected = false + // This lasts until Tunnelbroker sends ConnectionInitializationResponse + // - CONNECTED: isSocketActive = true, connected = true + // - DISCONNECTING: isSocketActive = false, connected = true + // This lasts between socket.close() and socket.onclose() React.useEffect(() => { + // when initMessage changes, we need to close the socket and open a new one + if ((!initMessage || initMessageChanged) && isSocketActive) { + socket.current?.close(); + return; + } + + // when we're already connected (or pending disconnection), + // or there's no init message to start with, we don't need to do anything if (connected || !initMessage) { return; } @@ -87,6 +113,7 @@ }; tunnelbrokerSocket.onclose = () => { + // this triggers the effect hook again and reconnect setConnected(false); console.log('Connection to Tunnelbroker closed'); }; @@ -193,6 +220,8 @@ }, [ connected, initMessage, + initMessageChanged, + isSocketActive, resetHeartbeatTimeout, stopHeartbeatTimeout, peerToPeerMessageHandler,