diff --git a/lib/facts/tunnelbroker.js b/lib/facts/tunnelbroker.js new file mode 100644 index 000000000..5c5a7abbd --- /dev/null +++ b/lib/facts/tunnelbroker.js @@ -0,0 +1,9 @@ +// @flow + +import { isDev } from '../utils/dev-utils.js'; + +const tunnnelbrokerURL: string = isDev + ? 'ws://localhost:51001' + : 'https://tunnelbroker.commtechnologies.org'; + +export { tunnnelbrokerURL }; diff --git a/lib/tunnelbroker/tunnelbroker-context.js b/lib/tunnelbroker/tunnelbroker-context.js index 078814e16..05fe2bf19 100644 --- a/lib/tunnelbroker/tunnelbroker-context.js +++ b/lib/tunnelbroker/tunnelbroker-context.js @@ -1,80 +1,107 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; +import { tunnnelbrokerURL } from '../facts/tunnelbroker.js'; import { type TunnelbrokerMessage } from '../types/tunnelbroker/messages.js'; import type { ConnectionInitializationMessage } from '../types/tunnelbroker/session-types.js'; export type ClientMessageToDevice = { +deviceID: string, +payload: string, }; export type TunnelbrokerSocketListener = ( message: TunnelbrokerMessage, ) => mixed; type TunnelbrokerContextType = { +sendMessage: (message: ClientMessageToDevice) => Promise, +addListener: (listener: TunnelbrokerSocketListener) => void, +removeListener: (listener: TunnelbrokerSocketListener) => void, +connected: boolean, }; const TunnelbrokerContext: React.Context = React.createContext(); type Props = { +children: React.Node, +initMessage: ?ConnectionInitializationMessage, }; function TunnelbrokerProvider(props: Props): React.Node { - const { children } = props; - const [connected] = React.useState(false); + const { children, initMessage } = props; + const [connected, setConnected] = React.useState(false); const listeners = React.useRef>(new Set()); + const socket = React.useRef(null); + + React.useEffect(() => { + if (connected || !initMessage) { + return; + } + + const tunnelbrokerSocket = new WebSocket(tunnnelbrokerURL); + + tunnelbrokerSocket.onopen = () => { + tunnelbrokerSocket.send(JSON.stringify(initMessage)); + }; + + tunnelbrokerSocket.onclose = () => { + setConnected(false); + console.error('Connection to Tunnelbroker closed'); + }; + tunnelbrokerSocket.onerror = e => { + console.error('Tunnelbroker socket error:', e.message); + }; + tunnelbrokerSocket.onmessage = (event: MessageEvent) => { + console.log('Received message:', event.data); + }; + + socket.current = tunnelbrokerSocket; + }, [connected, initMessage]); const sendMessage: () => Promise = React.useCallback(() => { return new Promise(() => {}); }, []); const addListener = React.useCallback( (listener: TunnelbrokerSocketListener) => { listeners.current.add(listener); }, [], ); const removeListener = React.useCallback( (listener: TunnelbrokerSocketListener) => { listeners.current.delete(listener); }, [], ); const value: TunnelbrokerContextType = React.useMemo( () => ({ sendMessage, connected, addListener, removeListener, }), [addListener, connected, removeListener, sendMessage], ); return ( {children} ); } function useTunnelbroker(): TunnelbrokerContextType { const context = React.useContext(TunnelbrokerContext); invariant(context, 'TunnelbrokerContext not found'); return context; } export { TunnelbrokerProvider, useTunnelbroker };