163 lines
3.9 KiB
TypeScript
163 lines
3.9 KiB
TypeScript
import { wantsState, wsState, userState, offersState, acpOffersState } from './store'
|
|
|
|
const SOCKET_URL = `${window.location.protocol === 'https:' ? 'wss://' : 'ws://'}${window.location.host}/api/ws`;
|
|
|
|
export default function createSocket(dispatch) {
|
|
let ws;
|
|
|
|
// -------------
|
|
// Outgoing
|
|
// -------------
|
|
function send(msg) {
|
|
if (msg[0] !== 'Ping') console.log('outgoing msg', msg);
|
|
if (ws.readyState !== 1) return false;
|
|
try {
|
|
ws.send(JSON.stringify(msg));
|
|
} catch (e) {
|
|
console.warn(e);
|
|
}
|
|
}
|
|
|
|
// let ping;
|
|
function sendPing() {
|
|
// ping = Date.now();
|
|
send(['Ping', {}]);
|
|
|
|
// setTimeout(sendPing, 50);
|
|
}
|
|
|
|
function sendOfferStatusSet(id, status) {
|
|
send(['OfferStatusSet', { id, status }]);
|
|
}
|
|
|
|
function sendWantRm(id) {
|
|
send(['WantRm', { id }]);
|
|
}
|
|
|
|
function sendOffers() {
|
|
send(['Offers', {}]);
|
|
}
|
|
|
|
function sendWants() {
|
|
send(['Wants', {}]);
|
|
}
|
|
|
|
function sendAcpOffers() {
|
|
send(['AcpOffers', {}]);
|
|
}
|
|
|
|
function sendAcpOfferStatusSet(id, status) {
|
|
send(['AcpOfferStatusSet', { id, status }]);
|
|
}
|
|
|
|
let pongTimeout;
|
|
function onPong() {
|
|
pongTimeout = setTimeout(sendPing, 5000);
|
|
}
|
|
|
|
// -------------
|
|
// Incoming
|
|
// -------------
|
|
function onUser(user) {
|
|
dispatch(userState.actions.set(user));
|
|
}
|
|
|
|
function onWants(wants) {
|
|
dispatch(wantsState.actions.set(wants));
|
|
}
|
|
|
|
function onOffers(offers) {
|
|
dispatch(offersState.actions.set(offers));
|
|
}
|
|
|
|
function onAcpOffers(offers) {
|
|
dispatch(acpOffersState.actions.set(offers));
|
|
}
|
|
|
|
// -------------
|
|
// Setup
|
|
// -------------
|
|
// when the server sends a reply it will have one of these message types
|
|
// this object wraps the reply types to a function
|
|
const handlers = {
|
|
Wants: onWants,
|
|
Offers: onOffers,
|
|
User: onUser,
|
|
|
|
OfferSamples: onOffers,
|
|
AcpOffers: onAcpOffers,
|
|
|
|
Pong: onPong,
|
|
Error: errHandler,
|
|
};
|
|
|
|
function errHandler(error) {
|
|
// store.dispatch(http.LIBRARY_EVENT, { level: 'error', log: error });
|
|
console.error(error);
|
|
}
|
|
|
|
function onMessage(event) {
|
|
const res = event.data;
|
|
const [msgType, params] = JSON.parse(res);
|
|
if (msgType !== 'Pong') {
|
|
console.log(msgType, params);
|
|
}
|
|
|
|
// check for error and split into response type and data
|
|
if (!handlers[msgType]) return console.error(`${msgType} handler missing`);
|
|
return handlers[msgType](params);
|
|
}
|
|
|
|
// Connection opened
|
|
function onOpen() {
|
|
console.log('websocket connected', SOCKET_URL)
|
|
sendPing();
|
|
sendAcpOffers();
|
|
sendOffers();
|
|
sendWants();
|
|
}
|
|
|
|
function onError(event) {
|
|
console.error('WebSocket error', event);
|
|
}
|
|
|
|
function onClose(event) {
|
|
console.error('WebSocket closed', event);
|
|
return setTimeout(connect, 2000);
|
|
}
|
|
|
|
function connect() {
|
|
if (ws) {
|
|
clearTimeout(pongTimeout);
|
|
ws.removeEventListener('open', onOpen);
|
|
ws.removeEventListener('message', onMessage);
|
|
ws.removeEventListener('error', onError);
|
|
ws.removeEventListener('close', onClose);
|
|
ws = null;
|
|
}
|
|
|
|
console.log('connecting to websocket', SOCKET_URL);
|
|
ws = new WebSocket(SOCKET_URL);
|
|
|
|
// Listen for messages
|
|
ws.addEventListener('open', onOpen);
|
|
ws.addEventListener('message', onMessage);
|
|
ws.addEventListener('error', onError);
|
|
ws.addEventListener('close', onClose);
|
|
|
|
return ws;
|
|
}
|
|
|
|
return {
|
|
connect,
|
|
|
|
sendOfferStatusSet,
|
|
sendWantRm,
|
|
|
|
sendOffers,
|
|
|
|
sendAcpOffers,
|
|
sendAcpOfferStatusSet,
|
|
};
|
|
}
|