hsync 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +1 -1
- package/connection.js +33 -13
- package/dist/hsync.js +3 -3
- package/dist/hsync.min.js +1 -1
- package/lib/peers.js +27 -4
- package/lib/rtc-node.js +17 -14
- package/lib/rtc-web.js +15 -4
- package/package.json +1 -1
package/Readme.md
CHANGED
|
@@ -41,7 +41,7 @@ However you can pass flags to the command line or configure env variables:
|
|
|
41
41
|
| ---- | --------------------- | ------- | ------------------ | ---------------------------------------------------------- |
|
|
42
42
|
| -p | -port | number | PORT | port for local webserver |
|
|
43
43
|
| -d | --dynamic-host | url | HSYNC_DYNAMIC_HOST | host to get a dynamic connection from |
|
|
44
|
-
| -s | --hsync-server | url | HSYNC_SERVER | hsync-server location ex:
|
|
44
|
+
| -s | --hsync-server | url | HSYNC_SERVER | hsync-server location ex: https://sub.mydomain.com |
|
|
45
45
|
| -hs | --hsync-secret | string | HSYNC_SECRET | password to connect to hsync-server |
|
|
46
46
|
| -llp | --listener-local-port | number | HSYNC_LLP | local port to open for listener |
|
|
47
47
|
| -lth | --listener-target-host | url | HSYNC_LTH | target host for listener |
|
package/connection.js
CHANGED
|
@@ -67,6 +67,7 @@ async function createHsync(config) {
|
|
|
67
67
|
const hsyncClient = {
|
|
68
68
|
setNet,
|
|
69
69
|
config,
|
|
70
|
+
status: 'connecting',
|
|
70
71
|
};
|
|
71
72
|
|
|
72
73
|
hsyncClient.peers = initPeers(hsyncClient);
|
|
@@ -75,12 +76,24 @@ async function createHsync(config) {
|
|
|
75
76
|
|
|
76
77
|
const events = new EventEmitter();
|
|
77
78
|
|
|
78
|
-
hsyncClient.on = events.on;
|
|
79
|
-
hsyncClient.emit = events.emit;
|
|
79
|
+
hsyncClient.on = events.on.bind(events);
|
|
80
|
+
hsyncClient.emit = events.emit.bind(events);
|
|
81
|
+
hsyncClient.removeListener = events.removeListener.bind(events);
|
|
82
|
+
hsyncClient.removeAllListeners = events.removeAllListeners.bind(events);
|
|
80
83
|
|
|
81
84
|
let lastConnect;
|
|
82
|
-
const
|
|
83
|
-
|
|
85
|
+
const hsu = new URL(hsyncServer.toLowerCase());
|
|
86
|
+
// console.log(hsu);
|
|
87
|
+
let protocol = hsu.protocol;
|
|
88
|
+
if (hsu.protocol === 'https:') {
|
|
89
|
+
protocol = 'wss:';
|
|
90
|
+
} else if (hsu.protocol === 'http:') {
|
|
91
|
+
protocol = 'ws:';
|
|
92
|
+
}
|
|
93
|
+
const connectURL = `${protocol}//${hsu.hostname}${hsu.port ? `:${hsu.port}` : ''}/${hsyncBase}`;
|
|
94
|
+
// const connectURL = `${hsyncServer}${hsyncServer.endsWith('/') ? '' : '/'}${hsyncBase}`;
|
|
95
|
+
// console.log('connectURL', connectURL);
|
|
96
|
+
const myHostName = hsu.hostname;
|
|
84
97
|
hsyncClient.myHostName = myHostName;
|
|
85
98
|
|
|
86
99
|
debug('connecting to', connectURL, '…' );
|
|
@@ -96,6 +109,7 @@ async function createHsync(config) {
|
|
|
96
109
|
debug('connected to', myHostName, lastConnect ? (now - lastConnect) : '', lastConnect ? 'since last connect' : '');
|
|
97
110
|
lastConnect = now;
|
|
98
111
|
hsyncClient.emit('connected', config);
|
|
112
|
+
hsyncClient.status = 'connected';
|
|
99
113
|
});
|
|
100
114
|
|
|
101
115
|
mqConn.on('error', (error) => {
|
|
@@ -103,9 +117,10 @@ async function createHsync(config) {
|
|
|
103
117
|
if ((error.code === 4) || (error.code === 5)) {
|
|
104
118
|
debug('ending');
|
|
105
119
|
mqConn.end();
|
|
106
|
-
if (globalThis.process) {
|
|
107
|
-
|
|
108
|
-
}
|
|
120
|
+
// if (globalThis.process) {
|
|
121
|
+
// process.exit(1);
|
|
122
|
+
// }
|
|
123
|
+
hsyncClient.emit('connect_error', error);
|
|
109
124
|
}
|
|
110
125
|
});
|
|
111
126
|
|
|
@@ -140,12 +155,14 @@ async function createHsync(config) {
|
|
|
140
155
|
function endClient(force, callback) {
|
|
141
156
|
if (force) {
|
|
142
157
|
mqConn.end(force);
|
|
158
|
+
hsyncClient.status = 'disconnected';
|
|
143
159
|
if (webHandler.end) {
|
|
144
160
|
webHandler.end();
|
|
145
161
|
}
|
|
146
162
|
return;
|
|
147
163
|
}
|
|
148
164
|
mqConn.end(force, (a, b) => {
|
|
165
|
+
hsyncClient.status = 'disconnected';
|
|
149
166
|
if (webHandler.end) {
|
|
150
167
|
webHandler.end();
|
|
151
168
|
}
|
|
@@ -217,7 +234,7 @@ async function createHsync(config) {
|
|
|
217
234
|
hsyncClient.emit('external_message', msg);
|
|
218
235
|
});
|
|
219
236
|
hsyncClient.getPeer = (hostName) => {
|
|
220
|
-
return peers.getRPCPeer({ hostName });
|
|
237
|
+
return hsyncClient.peers.getRPCPeer({ hostName });
|
|
221
238
|
};
|
|
222
239
|
hsyncClient.hsyncBase = hsyncBase;
|
|
223
240
|
hsyncClient.endClient = endClient;
|
|
@@ -227,13 +244,16 @@ async function createHsync(config) {
|
|
|
227
244
|
hsyncClient.hsyncSecret = hsyncSecret;
|
|
228
245
|
hsyncClient.hsyncServer = hsyncServer;
|
|
229
246
|
hsyncClient.dynamicTimeout = dynamicTimeout;
|
|
230
|
-
const { host, protocol } = new URL(hsyncServer);
|
|
231
|
-
if (protocol === 'wss:') {
|
|
232
|
-
hsyncClient.webUrl = `https://${host}`;
|
|
247
|
+
// const { host, protocol } = new URL(hsyncServer);
|
|
248
|
+
if (hsu.protocol === 'wss:') {
|
|
249
|
+
hsyncClient.webUrl = `https://${hsu.host}`;
|
|
250
|
+
} else if (hsu.protocol === 'ws:') {
|
|
251
|
+
hsyncClient.webUrl = `http://${hsu.host}`;
|
|
233
252
|
} else {
|
|
234
|
-
hsyncClient.webUrl =
|
|
253
|
+
hsyncClient.webUrl = hsyncServer;
|
|
235
254
|
}
|
|
236
|
-
|
|
255
|
+
|
|
256
|
+
debug('URL', hsu.host, hsu.protocol, hsyncClient.webUrl);
|
|
237
257
|
hsyncClient.webAdmin = `${hsyncClient.webUrl}/${hsyncBase}/admin`;
|
|
238
258
|
hsyncClient.webBase = `${hsyncClient.webUrl}/${hsyncBase}`;
|
|
239
259
|
hsyncClient.port = port;
|
package/dist/hsync.js
CHANGED
|
@@ -25,7 +25,7 @@ eval("let process = __webpack_require__.g.process || {env: {}};\n\nconst baseCon
|
|
|
25
25
|
\***********************/
|
|
26
26
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
27
27
|
|
|
28
|
-
eval("const EventEmitter = (__webpack_require__(/*! events */ \"./node_modules/events/events.js\").EventEmitter);\nconst debug = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:info');\nconst debugVerbose = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:verbose');\nconst debugError = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:error');\nconst { initPeers } = __webpack_require__(/*! ./lib/peers */ \"./lib/peers.js\");\nconst { createWebHandler, setNet: webSetNet } = __webpack_require__(/*! ./lib/web-handler */ \"./lib/web-handler.js\");\nconst { \n setNet: listenSetNet,\n initListeners,\n} = __webpack_require__(/*! ./lib/socket-listeners */ \"./lib/socket-listeners.js\");\nconst {\n setNet: relaySetNet,\n initRelays,\n} = __webpack_require__(/*! ./lib/socket-relays */ \"./lib/socket-relays.js\");\nconst fetch = __webpack_require__(/*! ./lib/fetch */ \"./lib/fetch.js\");\n\ndebug.color = 3;\ndebugVerbose.color = 2;\ndebugError.color = 1;\n\nlet mqtt;\n\nconsole.log('connection from hsync');\n\nfunction setNet(netImpl) {\n webSetNet(netImpl);\n listenSetNet(netImpl);\n relaySetNet(netImpl);\n}\n\nfunction setMqtt(mqttImpl) {\n mqtt = mqttImpl;\n}\n\nasync function createHsync(config) {\n let {\n hsyncServer,\n hsyncSecret,\n localHost,\n port,\n hsyncBase,\n keepalive,\n dynamicHost,\n listenerLocalPort,\n listenerTargetHost,\n listenerTargetPort,\n relayInboundPort,\n relayTargetHost,\n relayTargetPort,\n } = config;\n\n // console.log('config', config);\n\n let dynamicTimeout;\n\n if (dynamicHost && !hsyncSecret) {\n const result = await fetch.post(`${dynamicHost}/${hsyncBase}/dyn`, {});\n if (dynamicHost.toLowerCase().startsWith('https')) {\n hsyncServer = `wss://${result.url}`;\n } else {\n hsyncServer = `ws://${result.url}`;\n }\n hsyncSecret = result.secret;\n dynamicTimeout = result.timeout;\n }\n\n const hsyncClient = {\n setNet,\n config,\n };\n\n hsyncClient.peers = initPeers(hsyncClient);\n hsyncClient.listeners = initListeners(hsyncClient);\n hsyncClient.relays = initRelays(hsyncClient);\n\n const events = new EventEmitter();\n \n hsyncClient.on = events.on;\n hsyncClient.emit = events.emit;\n \n let lastConnect;\n const connectURL = `${hsyncServer}${hsyncServer.endsWith('/') ? '' : '/'}${hsyncBase}`;\n const myHostName =
|
|
28
|
+
eval("const EventEmitter = (__webpack_require__(/*! events */ \"./node_modules/events/events.js\").EventEmitter);\nconst debug = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:info');\nconst debugVerbose = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:verbose');\nconst debugError = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:error');\nconst { initPeers } = __webpack_require__(/*! ./lib/peers */ \"./lib/peers.js\");\nconst { createWebHandler, setNet: webSetNet } = __webpack_require__(/*! ./lib/web-handler */ \"./lib/web-handler.js\");\nconst { \n setNet: listenSetNet,\n initListeners,\n} = __webpack_require__(/*! ./lib/socket-listeners */ \"./lib/socket-listeners.js\");\nconst {\n setNet: relaySetNet,\n initRelays,\n} = __webpack_require__(/*! ./lib/socket-relays */ \"./lib/socket-relays.js\");\nconst fetch = __webpack_require__(/*! ./lib/fetch */ \"./lib/fetch.js\");\n\ndebug.color = 3;\ndebugVerbose.color = 2;\ndebugError.color = 1;\n\nlet mqtt;\n\nconsole.log('connection from hsync');\n\nfunction setNet(netImpl) {\n webSetNet(netImpl);\n listenSetNet(netImpl);\n relaySetNet(netImpl);\n}\n\nfunction setMqtt(mqttImpl) {\n mqtt = mqttImpl;\n}\n\nasync function createHsync(config) {\n let {\n hsyncServer,\n hsyncSecret,\n localHost,\n port,\n hsyncBase,\n keepalive,\n dynamicHost,\n listenerLocalPort,\n listenerTargetHost,\n listenerTargetPort,\n relayInboundPort,\n relayTargetHost,\n relayTargetPort,\n } = config;\n\n // console.log('config', config);\n\n let dynamicTimeout;\n\n if (dynamicHost && !hsyncSecret) {\n const result = await fetch.post(`${dynamicHost}/${hsyncBase}/dyn`, {});\n if (dynamicHost.toLowerCase().startsWith('https')) {\n hsyncServer = `wss://${result.url}`;\n } else {\n hsyncServer = `ws://${result.url}`;\n }\n hsyncSecret = result.secret;\n dynamicTimeout = result.timeout;\n }\n\n const hsyncClient = {\n setNet,\n config,\n status: 'connecting',\n };\n\n hsyncClient.peers = initPeers(hsyncClient);\n hsyncClient.listeners = initListeners(hsyncClient);\n hsyncClient.relays = initRelays(hsyncClient);\n\n const events = new EventEmitter();\n \n hsyncClient.on = events.on.bind(events);\n hsyncClient.emit = events.emit.bind(events);\n hsyncClient.removeListener = events.removeListener.bind(events);\n hsyncClient.removeAllListeners = events.removeAllListeners.bind(events);\n \n let lastConnect;\n const hsu = new URL(hsyncServer.toLowerCase());\n // console.log(hsu);\n let protocol = hsu.protocol;\n if (hsu.protocol === 'https:') {\n protocol = 'wss:';\n } else if (hsu.protocol === 'http:') {\n protocol = 'ws:';\n }\n const connectURL = `${protocol}//${hsu.hostname}${hsu.port ? `:${hsu.port}` : ''}/${hsyncBase}`;\n // const connectURL = `${hsyncServer}${hsyncServer.endsWith('/') ? '' : '/'}${hsyncBase}`;\n // console.log('connectURL', connectURL);\n const myHostName = hsu.hostname;\n hsyncClient.myHostName = myHostName;\n \n debug('connecting to', connectURL, '…' );\n const mqConn = mqtt.connect(connectURL, { password: hsyncSecret, username: myHostName, keepalive });\n mqConn.myHostName = myHostName;\n hsyncClient.mqConn = mqConn;\n\n const webHandler = config.webHandler || createWebHandler({myHostName, localHost, port, mqConn});\n hsyncClient.webHandler = webHandler;\n\n mqConn.on('connect', () => {\n const now = Date.now();\n debug('connected to', myHostName, lastConnect ? (now - lastConnect) : '', lastConnect ? 'since last connect' : '');\n lastConnect = now;\n hsyncClient.emit('connected', config);\n hsyncClient.status = 'connected';\n });\n\n mqConn.on('error', (error) => {\n debugError('error on mqConn', myHostName, error.code, error);\n if ((error.code === 4) || (error.code === 5)) {\n debug('ending');\n mqConn.end();\n // if (globalThis.process) {\n // process.exit(1);\n // }\n hsyncClient.emit('connect_error', error);\n }\n });\n\n mqConn.on('message', (topic, message) => {\n if (!topic) {\n return;\n }\n // message is Buffer\n const [name, hostName, segment3, action, segment5] = topic.split('/');\n debugVerbose('\\n↓ MQTT' , topic);\n if (name === 'web') {\n webHandler.handleWebRequest(hostName, segment3, action, message);\n return;\n } else if (name === 'msg') {\n const from = segment3;\n if (action === 'json') {\n try {\n const msg = JSON.parse(message.toString());\n msg.from = from;\n hsyncClient.emit('json', msg);\n } catch (e) {\n debugError('error parsing json message');\n }\n }\n else if (!action && (segment3 === 'srpc')) {\n hsyncClient.serverPeer.transport.receiveData(message.toString());\n }\n }\n\n });\n\n function endClient(force, callback) {\n if (force) {\n mqConn.end(force);\n hsyncClient.status = 'disconnected';\n if (webHandler.end) {\n webHandler.end();\n }\n return;\n }\n mqConn.end(force, (a, b) => {\n hsyncClient.status = 'disconnected';\n if (webHandler.end) {\n webHandler.end();\n }\n if (callback) {\n callback(a, b);\n }\n })\n }\n\n const serverReplyMethods = {\n ping: (greeting) => {\n return `${greeting} back atcha from client. ${Date.now()}`;\n },\n addSocketListener: hsyncClient.addSocketListener,\n getSocketListeners: hsyncClient.getSocketListeners,\n addSocketRelay: hsyncClient.addSocketRelay,\n getSocketRelays: hsyncClient.getSocketRelays,\n peerRpc: async (requestInfo) => {\n requestInfo.hsyncClient = hsyncClient;\n const { msg } = requestInfo;\n debug('peerRpc handler', requestInfo.fromHost, msg.method);\n const peer = hsyncClient.peers.getRPCPeer({hostName: requestInfo.fromHost, hsyncClient});\n if (!msg.id) {\n // notification\n if (Array.isArray(msg.params)) {\n msg.params.unshift(peer);\n }\n peer.transport.emit('rpc', msg);\n return { result: {}, id: msg.id};\n }\n const reply = {id: msg.id, jsonrpc:'2.0'};\n try {\n if (!peer.localMethods[msg.method]) {\n const notFoundError = new Error('method not found');\n notFoundError.code = -32601;\n throw notFoundError;\n }\n const result = await peer.localMethods[msg.method](requestInfo, ...msg.params);\n reply.result = result;\n return result;\n } catch (e) {\n debug('peer rpc error', e, msg);\n reply.error = {\n code: e.code || 500,\n message: e.toString(),\n };\n return reply;\n }\n }\n };\n\n const peerMethods = {\n ping: (remotePeer, greeting) => {\n debug('ping called', remotePeer.hostName, greeting);\n return `${greeting} back atcha, ${remotePeer.hostName}.`;\n },\n validatePeer: (remotePeer, secret) => {\n return hsyncClient.getPeer(remotePeer.hostName).myAuth === secret;\n },\n connectSocket: hsyncClient.connectSocket,\n // closeListenerSocket: hsyncClient.closeListenerSocket,\n // closeRelaySocket: hsyncClient.closeRelaySocket,\n // receiveListenerData: hsyncClient.receiveListenerData,\n // receiveRelayData: hsyncClient.receiveRelayData,\n };\n\n hsyncClient.serverPeer = hsyncClient.peers.createServerPeer(hsyncClient, serverReplyMethods);\n hsyncClient.serverPeer.notifications.onexternal_message((msg) => {\n hsyncClient.emit('external_message', msg);\n });\n hsyncClient.getPeer = (hostName) => {\n return hsyncClient.peers.getRPCPeer({ hostName });\n };\n hsyncClient.hsyncBase = hsyncBase;\n hsyncClient.endClient = endClient;\n hsyncClient.serverReplyMethods = serverReplyMethods;\n hsyncClient.getRPCPeer = hsyncClient.peers.getRPCPeer;\n hsyncClient.peerMethods = peerMethods;\n hsyncClient.hsyncSecret = hsyncSecret;\n hsyncClient.hsyncServer = hsyncServer;\n hsyncClient.dynamicTimeout = dynamicTimeout;\n // const { host, protocol } = new URL(hsyncServer);\n if (hsu.protocol === 'wss:') {\n hsyncClient.webUrl = `https://${hsu.host}`;\n } else if (hsu.protocol === 'ws:') {\n hsyncClient.webUrl = `http://${hsu.host}`;\n } else {\n hsyncClient.webUrl = hsyncServer;\n }\n \n debug('URL', hsu.host, hsu.protocol, hsyncClient.webUrl);\n hsyncClient.webAdmin = `${hsyncClient.webUrl}/${hsyncBase}/admin`;\n hsyncClient.webBase = `${hsyncClient.webUrl}/${hsyncBase}`;\n hsyncClient.port = port;\n\n if (listenerLocalPort) {\n listenerLocalPort.forEach((llp, i) => {\n let lth = listenerTargetHost ? listenerTargetHost[i] || listenerTargetHost[0] : null;\n if (lth) {\n if (lth.endsWith('/')) {\n lth = lth.substring(0, lth.length - 1);\n }\n const ltp = listenerTargetPort ? listenerTargetPort[i] : llp;\n hsyncClient.addSocketListener({ port: llp, targetPort: ltp, targetHost: lth });\n debug('relaying local', llp, 'to', lth, ltp);\n }\n });\n }\n\n if (relayInboundPort) {\n relayInboundPort.forEach((rip, i) => {\n debug('relayInboundPort', rip, i, relayTargetHost);\n const firstRth = relayTargetHost ? relayTargetHost[0] : null;\n const rth = relayTargetHost ? relayTargetHost[i] : firstRth || 'localhost';\n if (rth) {\n if (rth.endsWith('/')) {\n rth = rth.substring(0, rth.length - 1);\n }\n const rtp = relayTargetPort ? relayTargetPort[i] : rip;\n hsyncClient.addSocketRelay({ port: rip, targetHost: rth, targetPort: rtp });\n debug('relaying inbound', rip, 'to', rth, rtp);\n }\n });\n }\n\n return hsyncClient;\n}\n\nmodule.exports = {\n createHsync,\n setNet,\n setMqtt,\n};\n\n\n//# sourceURL=webpack://hsync/./connection.js?");
|
|
29
29
|
|
|
30
30
|
/***/ }),
|
|
31
31
|
|
|
@@ -55,7 +55,7 @@ eval("const fetch = __webpack_require__(/*! isomorphic-fetch */ \"./node_modules
|
|
|
55
55
|
\**********************/
|
|
56
56
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
57
57
|
|
|
58
|
-
eval("const rawr = __webpack_require__(/*! rawr */ \"./node_modules/rawr/index.js\");\nconst b64id = __webpack_require__(/*! b64id */ \"./node_modules/b64id/index.js\");\nconst debug = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:peers');\nconst EventEmitter = (__webpack_require__(/*! events */ \"./node_modules/events/events.js\").EventEmitter);\nconst buffer = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\");\nconst mqttPacket = __webpack_require__(/*! mqtt-packet-web */ \"./node_modules/mqtt-packet-web/index.js\");\n\nglobalThis.Buffer = buffer.Buffer;\n\nconst { handleSocketPacket } = __webpack_require__(/*! ./socket-map */ \"./lib/socket-map.js\");\nconst fetch = __webpack_require__(/*! ./fetch */ \"./lib/fetch.js\");\n\nfunction createPacket(topic, payload) {\n let payloadStr = payload;\n const packet = mqttPacket.generate({\n qos: 0,\n cmd: 'publish',\n topic,\n payload: payloadStr,\n });\n // console.log('packet', packet);\n return packet;\n}\n\nfunction parsePacket(packet) {\n const parser = mqttPacket.parser();\n return new Promise((resolve, reject) => {\n parser.on('packet', resolve);\n parser.on('error', reject);\n parser.parse(packet);\n });\n}\n\n\nlet rtc;\n\nfunction setRTC(rtcImpl) {\n rtc = rtcImpl;\n}\n\nfunction initPeers(hsyncClient) {\n const cachedPeers = {};\n function getRPCPeer(options = {}) {\n const { hostName, temporary, timeout = 10000, hsyncClient } = options;\n let peer = cachedPeers[hostName];\n if (!peer) {\n debug('CREATING peer', hostName);\n peer = createRPCPeer({hostName, hsyncClient, timeout});\n peer.myAuth = b64id.generateId();\n if (temporary) {\n peer.rpcTemporary = true;\n }\n cachedPeers[hostName] = peer;\n }\n return peer;\n }\n \n function createRPCPeer(options = {}) {\n const { hostName, timeout = 10000, useRTC = true } = options;\n if (!hostName) {\n throw new Error('No hostname specified');\n }\n if (hostName === hsyncClient.myHostName) {\n throw new Error('Peer must be a different host');\n }\n const myAuth = b64id.generateId();\n const transport = new EventEmitter();\n const peer = rawr({transport, methods: Object.assign({}, hsyncClient.peerMethods), timeout, idGenerator: b64id.generateId});\n peer.hostName = hostName;\n peer.rtcEvents = new EventEmitter();\n peer.localMethods = Object.assign({}, hsyncClient.peerMethods);\n peer.sockets = {};\n \n peer.localMethods.rtcSignal = (peerInfo, signal) => {\n debug('rtcSignal', signal.type);\n if (signal.type === 'offer' && !peer.rtcCon && !signal.alreadySent) {\n rtc.answerPeer(peer, signal);\n } else if (signal.type === 'answer') {\n peer.handleRtcAnswer(signal);\n }\n return
|
|
58
|
+
eval("const rawr = __webpack_require__(/*! rawr */ \"./node_modules/rawr/index.js\");\nconst b64id = __webpack_require__(/*! b64id */ \"./node_modules/b64id/index.js\");\nconst debug = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:peers');\nconst EventEmitter = (__webpack_require__(/*! events */ \"./node_modules/events/events.js\").EventEmitter);\nconst buffer = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\");\nconst mqttPacket = __webpack_require__(/*! mqtt-packet-web */ \"./node_modules/mqtt-packet-web/index.js\");\n\nglobalThis.Buffer = buffer.Buffer;\n\nconst { handleSocketPacket } = __webpack_require__(/*! ./socket-map */ \"./lib/socket-map.js\");\nconst fetch = __webpack_require__(/*! ./fetch */ \"./lib/fetch.js\");\n\nfunction createPacket(topic, payload) {\n let payloadStr = payload;\n const packet = mqttPacket.generate({\n qos: 0,\n cmd: 'publish',\n topic,\n payload: payloadStr,\n });\n // console.log('packet', packet);\n return packet;\n}\n\nfunction parsePacket(packet) {\n const parser = mqttPacket.parser();\n return new Promise((resolve, reject) => {\n parser.on('packet', resolve);\n parser.on('error', reject);\n parser.parse(packet);\n });\n}\n\n\nlet rtc;\n\nfunction setRTC(rtcImpl) {\n rtc = rtcImpl;\n}\n\nfunction initPeers(hsyncClient) {\n const cachedPeers = {};\n function getRPCPeer(options = {}) {\n const { hostName, temporary, timeout = 10000, hsyncClient } = options;\n let peer = cachedPeers[hostName];\n if (!peer) {\n debug('CREATING peer', hostName);\n peer = createRPCPeer({hostName, hsyncClient, timeout});\n peer.myAuth = b64id.generateId();\n if (temporary) {\n peer.rpcTemporary = true;\n }\n cachedPeers[hostName] = peer;\n }\n return peer;\n }\n \n function createRPCPeer(options = {}) {\n const { hostName, timeout = 10000, useRTC = true } = options;\n if (!hostName) {\n throw new Error('No hostname specified');\n }\n if (hostName === hsyncClient.myHostName) {\n throw new Error('Peer must be a different host');\n }\n const myAuth = b64id.generateId();\n const transport = new EventEmitter();\n const peer = rawr({transport, methods: Object.assign({}, hsyncClient.peerMethods), timeout, idGenerator: b64id.generateId});\n peer.hostName = hostName;\n peer.rtcEvents = new EventEmitter();\n peer.localMethods = Object.assign({}, hsyncClient.peerMethods);\n peer.sockets = {};\n \n peer.localMethods.rtcSignal = (peerInfo, signal) => {\n debug('rtcSignal', signal.type);\n if (signal.type === 'offer') { // && !peer.rtcCon && !signal.alreadySent) {\n peer.rtcStatus = 'connecting';\n rtc.answerPeer(peer, signal);\n } else if (signal.type === 'answer') {\n peer.handleRtcAnswer(signal);\n }\n return `rtcSignal ${signal.type} handled ok`;\n }\n \n peer.rtcEvents.on('packet', async (packet) => {\n debug('↓ on packet', packet);\n let toParse = packet;\n try {\n if (packet instanceof Blob) {\n toParse = await packet.arrayBuffer();\n }\n const msg = await parsePacket(toParse);\n const [p1, p2, p3] = msg.topic.split('/');\n if (p1 === 'rpc') {\n const rpcMsg = JSON.parse(msg.payload.toString());\n debug('↓ peer RTC rpc', rpcMsg);\n // if (rpcMsg.method) {\n transport.receiveData(rpcMsg);\n // return;\n // }\n } else if (p1 === 'jsonMsg') {\n try {\n const jsonMsg = JSON.parse(msg.payload.toString());\n peer.rtcEvents.emit('jsonMsg', jsonMsg);\n } catch (e) {\n debug('error parsing jsonMsg', e);\n }\n } else if (p1 === 'socketData') {\n handleSocketPacket(msg);\n } else if (p1 === 'test') {\n debug('test topic', msg.payload);\n } else {\n debug('other topic', msg.topic);\n }\n } catch (e) {\n debug('bad packet', e, packet);\n }\n });\n \n peer.rtcEvents.on('dcOpen', () => {\n debug(peer.answerer ? 'answerer' : 'offerer', 'dcOpen');\n peer.packAndSend = (topic, payload) => {\n const packet = createPacket(topic, payload);\n if (topic === 'test') {\n debug('sending test packet', packet);\n }\n peer.rtcSend(packet);\n }\n // firefox is weird about the first bit of data, so send a test packet\n peer.packAndSend('test', 'test');\n });\n \n peer.rtcEvents.on('closed', () => {\n peer.dcOpen = false;\n delete peer.packAndSend;\n debug('rtc closed');\n for (s in peer.sockets) {\n try {\n debug('closing socket', s);\n peer.sockets[s].destroy();\n delete peer.sockets[s];\n } catch (e) {\n debug('error closing socket', e);\n }\n }\n });\n \n peer.rtcEvents.on('disconnected', () => {\n peer.dcOpen = false;\n delete peer.packAndSend;\n debug('rtc disconnected');\n for (s in peer.sockets) {\n try {\n debug('closing socket', s);\n peer.sockets[s].destroy();\n delete peer.sockets[s];\n } catch (e) {\n debug('error closing socket', e);\n }\n }\n });\n \n peer.connectRTC = async () => {\n debug('connectRTC');\n peer.rtcStatus = 'connecting';\n peer.rtcEvents.emit('connecting');\n return new Promise(async (resolve, reject) => {\n try {\n const offer = await rtc.offerPeer(peer);\n debug('offer', offer);\n peer.rtcEvents.once('dcOpen', () => {\n peer.rtcStatus = 'connected';\n debug('offerer dcOpen!');\n resolve(offer);\n });\n } catch (e) {\n debug('error connecting to rtc', e);\n peer.rtcStatus = 'error';\n reject(e);\n }\n });\n };\n\n peer.sendJSONMsg = (msg) => {\n if (typeof msg !== 'object') {\n throw new Error('sendJSONMsg requires an object');\n }\n if (!peer.packAndSend) {\n throw new Error('peer not connected');\n }\n const payload = JSON.stringify(msg);\n peer.packAndSend('jsonMsg', payload);\n };\n \n transport.send = async (msg) => {\n const fullMsg = {\n msg,\n myAuth,\n toHost: hostName,\n fromHost: hsyncClient.webUrl,\n };\n \n debug('↑ peer rpc', peer.dcOpen ? 'RTC' : 'REST', `${hostName}/_hs/rpc`, msg.method);\n \n if (peer.dcOpen) {\n let payload = msg;\n if (typeof msg === 'object') {\n payload = JSON.stringify(payload);\n }\n const packet = createPacket('rpc', payload);\n peer.rtcSend(packet);\n return;\n }\n \n try {\n const path = `${hostName}/_hs/rpc`;\n debug('fetching', path, fullMsg, useRTC);\n const result = await fetch.post(path, fullMsg);\n debug('fetch result', result);\n if (msg.id) {\n transport.receiveData({id: msg.id, result, jsonrpc: msg.jsonrpc});\n }\n } catch(e) {\n debug('error sending peer RPC request', e);\n if (msg.id) { // only send error if it's a request, not a notification\n transport.receiveData({\n id: msg.id,\n error: e.message,\n method: msg.method,\n jsonrpc: msg.jsonrpc\n });\n }\n }\n \n };\n \n transport.receiveData = (msg) => {\n debug('↓ transport.receiveData', msg);\n if(typeof msg === 'string') {\n msg = JSON.parse(msg);\n }\n debug('↓ peer rpc receivedData', msg);\n if (msg.params && Array.isArray(msg.params)) {\n debug('unshifting', msg.params);\n msg.params.unshift(peer);\n }\n transport.emit('rpc', msg);\n // debug('transport emitted', msg);\n };\n \n peer.myAuth = myAuth;\n peer.hostName = hostName;\n return peer;\n }\n \n function createServerPeer(hsyncClient, methods) {\n const transport = new EventEmitter();\n transport.send = (msg) => {\n if(typeof msg === 'object') {\n msg = JSON.stringify(msg);\n }\n const topic = `srpc/${hsyncClient.myHostName}`;\n debug('↑ server rpc outbound', msg);\n hsyncClient.mqConn.publish(topic, Buffer.from(msg));\n };\n transport.receiveData = (msg) => {\n if(msg) {\n msg = JSON.parse(msg);\n }\n debug('↓ server rpc inbound', msg);\n transport.emit('rpc', msg);\n };\n const peer = rawr({transport, methods, timeout: 5000});\n return peer;\n }\n\n hsyncClient.cachedPeers = cachedPeers;\n hsyncClient.getRPCPeer = getRPCPeer;\n hsyncClient.createServerPeer = createServerPeer;\n\n return {\n getRPCPeer,\n createRPCPeer,\n createServerPeer,\n };\n}\n\nmodule.exports = {\n initPeers,\n setRTC,\n};\n\n\n//# sourceURL=webpack://hsync/./lib/peers.js?");
|
|
59
59
|
|
|
60
60
|
/***/ }),
|
|
61
61
|
|
|
@@ -65,7 +65,7 @@ eval("const rawr = __webpack_require__(/*! rawr */ \"./node_modules/rawr/index.j
|
|
|
65
65
|
\************************/
|
|
66
66
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
67
67
|
|
|
68
|
-
eval("const debug = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:rtc-web');\nconst debugError = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('errors');\n\nconst rtc = {\n PeerConnection: RTCPeerConnection,\n};\n\n\nconst defaultOptions = {\n // Recommended for libdatachannel\n // bundlePolicy: \"max-bundle\",\n iceServers: [{ 'urls': 'stun:stun.l.google.com:19302' }] \n};\n\nconst GATHERING_TIMEOUT = 4000;\n\nasync function offerPeer(peer) {\n return new Promise(async (resolve, reject) => {\n const con = new RTCPeerConnection(defaultOptions);\n // window.rtc = rtc;\n\n peer.rtcCon = con;\n peer.rtcOfferer = true;\n \n let gatheringComplete = false;\n let offerSent = false;\n const start = Date.now();\n\n async function sendOffer(alreadySent) {\n debug('send offer', alreadySent);\n const desc = con.localDescription;\n try {\n const resp = await peer.methods.rtcSignal({type: desc.type, sdp: desc.sdp, alreadySent});\n resolve(resp);\n } catch (e) {\n debugError('error sending offer', e);\n reject(e);\n }\n }\n\n con.onicegatheringstatechange = (state) => {\n debug('state change', con.iceGatheringState);\n if (con.iceGatheringState === 'complete') {\n debug('icegathering done', Date.now() - start);\n gatheringComplete = true;\n // We only want to provide an answer once all of our candidates have been added to the SDP.\n sendOffer(offerSent);\n }\n }\n\n con.onicecandidate = (ice) => {\n debug('ice candidate', ice);\n };\n\n con.onconnectionstatechange = (event) => {\n debug('connection state', con.connectionState, event);\n if(con.connectionState === 'connected') {\n peer.connected = true;\n peer.rtcEvents.emit('connected', con);\n }\n };\n\n con.ondatachannel = (event) => {\n debug('dc from answerer', event);\n peer.dc = event.channel;\n };\n\n const dc = con.createDataChannel('from web');\n\n peer.dc = dc;\n dc.onmessage = (event) => { \n debug('dc.onmessage', event.data);\n peer.rtcEvents.emit('packet', event.data);\n };\n dc.onopen = (event) => { \n peer.dcOpen = true;\n peer.dc = dc;\n peer.rtcSend = (packet) => {\n dc.send(packet);\n };\n peer.rtcEvents.emit('dcOpen', dc);\n // dc.send('yo waddup from the browser');\n };\n\n const offer = await con.createOffer({offerToReceiveAudio:true, offerToReceiveVideo:true});\n await con.setLocalDescription(offer);\n\n setTimeout(() => {\n if (!gatheringComplete) {\n debug('didnt finish gathering');\n sendOffer();\n offerSent = true;\n }\n }, GATHERING_TIMEOUT);\n\n peer.handleRtcAnswer = (answer) => {\n debug('
|
|
68
|
+
eval("const debug = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('hsync:rtc-web');\nconst debugError = __webpack_require__(/*! debug */ \"./node_modules/debug/src/browser.js\")('errors');\n\nconst rtc = {\n PeerConnection: RTCPeerConnection,\n};\n\n\nconst defaultOptions = {\n // Recommended for libdatachannel\n // bundlePolicy: \"max-bundle\",\n iceServers: [{ 'urls': 'stun:stun.l.google.com:19302' }] \n};\n\nconst GATHERING_TIMEOUT = 4000;\n\nasync function offerPeer(peer) {\n return new Promise(async (resolve, reject) => {\n const con = new RTCPeerConnection(defaultOptions);\n // window.rtc = rtc;\n\n peer.rtcCon = con;\n peer.rtcOfferer = true;\n \n let gatheringComplete = false;\n let offerSent = false;\n const start = Date.now();\n\n async function sendOffer(alreadySent) {\n debug('send offer', alreadySent);\n const desc = con.localDescription;\n try {\n const resp = await peer.methods.rtcSignal({type: desc.type, sdp: desc.sdp, alreadySent});\n resolve(resp);\n } catch (e) {\n debugError('error sending offer', e);\n reject(e);\n }\n }\n\n con.onicegatheringstatechange = (state) => {\n debug('state change', con.iceGatheringState);\n if (con.iceGatheringState === 'complete') {\n debug('icegathering done', Date.now() - start);\n gatheringComplete = true;\n // We only want to provide an answer once all of our candidates have been added to the SDP.\n sendOffer(offerSent);\n }\n }\n\n con.onicecandidate = (ice) => {\n debug('ice candidate', ice);\n };\n\n con.onconnectionstatechange = (event) => {\n debug('offerer connection state', con.connectionState, event);\n if(con.connectionState === 'connected') {\n peer.connected = true;\n peer.rtcEvents.emit('connected', con);\n } else if (con.connectionState === 'disconnected') {\n peer.connected = false;\n peer.rtcEvents.emit('disconnected', con);\n peer.rtcCon = null;\n peer.dc = null;\n } else if (con.connectionState === 'closed') {\n peer.connected = false;\n peer.rtcEvents.emit('closed', con);\n peer.rtcCon = null;\n peer.dc = null;\n }\n };\n\n con.ondatachannel = (event) => {\n debug('dc from answerer', event);\n peer.dc = event.channel;\n };\n\n const dc = con.createDataChannel('from web');\n\n peer.dc = dc;\n dc.onmessage = (event) => { \n debug('dc.onmessage', event.data);\n peer.rtcEvents.emit('packet', event.data);\n };\n dc.onopen = (event) => { \n peer.dcOpen = true;\n peer.dc = dc;\n peer.rtcSend = (packet) => {\n dc.send(packet);\n };\n peer.rtcEvents.emit('dcOpen', dc);\n // dc.send('yo waddup from the browser');\n };\n\n const offer = await con.createOffer({offerToReceiveAudio:true, offerToReceiveVideo:true});\n await con.setLocalDescription(offer);\n\n setTimeout(() => {\n if (!gatheringComplete) {\n debug('didnt finish gathering');\n sendOffer();\n offerSent = true;\n }\n }, GATHERING_TIMEOUT);\n\n peer.handleRtcAnswer = (answer) => {\n debug('web handle RtcAnswer', answer.sdp.length);\n con.setRemoteDescription(answer);\n return 'web handle RtcAnswer ok';\n }\n });\n}\n\nasync function answerPeer(peer, offer) {\n const options = {...defaultOptions, bundlePolicy: \"max-bundle\"};\n const con = new RTCPeerConnection(options);\n // window.rtc = rtc;\n\n peer.rtcCon = con;\n peer.answerer = true;\n \n let gatheringComplete = false;\n const start = Date.now();\n\n function sendAnswer() {\n const desc = con.localDescription;\n peer.methods.rtcSignal({type: desc.type, sdp: desc.sdp});\n }\n\n con.onicegatheringstatechange = (state) => {\n if (con.iceGatheringState === 'complete') {\n gatheringComplete = true;\n debug('answerer icegathering done', Date.now() - start);\n sendAnswer();\n }\n }\n await con.setRemoteDescription(offer);\n\n let answer = await con.createAnswer();\n await con.setLocalDescription(answer);\n\n con.onicecandidate = (ice) => {\n debug('ice candidate', ice);\n };\n\n con.onconnectionstatechange = (event) => {\n debug('answerer connection state', con.connectionState, event);\n if(con.connectionState === 'connected') {\n peer.connected = true;\n peer.rtcEvents.emit('connected', con);\n } else if (con.connectionState === 'disconnected') {\n peer.connected = false;\n peer.rtcEvents.emit('disconnected', con);\n peer.rtcCon = null;\n peer.dc = null;\n } else if (con.connectionState === 'closed') {\n peer.connected = false;\n peer.rtcEvents.emit('closed', con);\n peer.rtcCon = null;\n peer.dc = null;\n }\n };\n\n con.ondatachannel = (event) => {\n debug('ondatachannel', event);\n peer.dcOpen = true;\n peer.dc = event.channel;\n peer.rtcSend = (packet) => {\n peer.dc.send(packet);\n };\n peer.rtcEvents.emit('dcOpen', peer.dc);\n peer.dc.onmessage = (event) => {\n peer.rtcEvents.emit('packet', event.data);\n };\n };\n\n setTimeout(() => {\n if (!gatheringComplete) {\n debug('didnt finish gathering');\n sendAnswer();\n }\n }, GATHERING_TIMEOUT);\n\n}\n\n\nrtc.offerPeer = offerPeer;\nrtc.answerPeer = answerPeer;\n\nmodule.exports = rtc;\n\n//# sourceURL=webpack://hsync/./lib/rtc-web.js?");
|
|
69
69
|
|
|
70
70
|
/***/ }),
|
|
71
71
|
|