hsync 0.12.0 → 0.14.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/hsync-web.js CHANGED
@@ -19,6 +19,8 @@ async function dynamicConnect(dynamicHost, useLocalStorage) {
19
19
  if ((Date.now() - localConfig.created) < (localConfig.timeout * 0.66)) {
20
20
  config.hsyncSecret = localConfig.hsyncSecret;
21
21
  config.hsyncServer = localConfig.hsyncServer;
22
+ } else {
23
+ localStorage.removeItem('hsyncConfig');
22
24
  }
23
25
  }
24
26
 
@@ -48,9 +50,14 @@ async function dynamicConnect(dynamicHost, useLocalStorage) {
48
50
 
49
51
  }
50
52
 
53
+ function createConnection(configObj = {}) {
54
+ const fullConfig = {...config, ...configObj};
55
+ return createHsync(fullConfig);
56
+ }
57
+
51
58
 
52
59
  const hsync = globalThis.hsync || {
53
- createConnection: createHsync,
60
+ createConnection,
54
61
  dynamicConnect,
55
62
  net,
56
63
  config,
package/hsync.js CHANGED
@@ -15,8 +15,13 @@ async function dynamicConnect(dynamicHost) {
15
15
  return con;
16
16
  }
17
17
 
18
+ function createConnection(configObj = {}) {
19
+ const fullConfig = {...config, ...configObj};
20
+ return createHsync(fullConfig);
21
+ }
22
+
18
23
  module.exports = {
19
- createConnection: createHsync,
24
+ createConnection,
20
25
  dynamicConnect,
21
26
  config,
22
27
  };
package/lib/fetch.js ADDED
@@ -0,0 +1,61 @@
1
+ const fetch = require('isomorphic-fetch');
2
+
3
+ function getContent(res) {
4
+ const contentType = res.headers.get('content-type');
5
+ if (contentType.startsWith('application/json')) {
6
+ return res.json();
7
+ }
8
+ if (contentType.startsWith('text')) {
9
+ return res.text();
10
+ }
11
+ return res.blob();
12
+ }
13
+
14
+ function handledFetch(path, options) {
15
+ return fetch(path, options)
16
+ .then((res) => {
17
+ if (res.status >= 400) {
18
+ const err = new Error('Bad response from server');
19
+ err.status = res.status;
20
+ return getContent(res)
21
+ .then((content) => {
22
+ err.content = content;
23
+ throw err;
24
+ });
25
+ }
26
+ return res;
27
+ });
28
+ }
29
+
30
+ function apiFetch(path, options = {}) {
31
+ let qs = '';
32
+ if (typeof options.body === 'object') {
33
+ options.body = JSON.stringify(options.body);
34
+ }
35
+ if (options.query) {
36
+ if (Object.keys(options.query).length) {
37
+ qs = `?${(new URLSearchParams(options.query)).toString()}`;
38
+ }
39
+ }
40
+ Object.assign(options, { credentials: 'include' });
41
+ options.headers = {
42
+ 'Content-Type': 'application/json',
43
+ ...options.headers,
44
+ };
45
+ return handledFetch(`${path}${qs}`, options)
46
+ .then(getContent);
47
+ }
48
+
49
+ apiFetch.post = (path, body) => {
50
+ return apiFetch(path, { method: 'POST', body });
51
+ };
52
+
53
+ apiFetch.put = (path, body) => {
54
+ return apiFetch(path, { method: 'PUT', body });
55
+ };
56
+
57
+ apiFetch.del = (path, body = {}) => {
58
+ return apiFetch(path, { method: 'DELETE', body });
59
+ };
60
+
61
+ module.exports = apiFetch;
package/lib/rpc.js CHANGED
@@ -2,26 +2,57 @@ const rawr = require('rawr');
2
2
  const b64id = require('b64id');
3
3
  const debug = require('debug')('hsync:rpc');
4
4
  const EventEmitter = require('events').EventEmitter;
5
+ // const { peerMethods } = require('./peer-methods');
6
+ const fetch = require('./fetch');
7
+
8
+ const peers = {};
9
+
10
+ function getRPCPeer({hostName, temporary, timeout = 10000, hsyncClient}) {
11
+ let peer = peers[hostName];
12
+ if (!peer) {
13
+ debug('creating peer', hostName);
14
+ peer = createRPCPeer({hostName, hsyncClient, timeout, methods: hsyncClient.peerMethods});
15
+ if (temporary) {
16
+ peer.rpcTemporary = true;
17
+ }
18
+ peers[hostName] = peer;
19
+ }
20
+ return peer;
21
+ }
22
+
5
23
 
6
24
  function createRPCPeer({ hostName, hsyncClient, timeout = 10000, methods = {} }) {
7
25
  if (!hostName) {
8
26
  throw new Error('No hostname specified');
9
27
  }
10
- if (hostName === hsyncClient.username) {
28
+ if (hostName === hsyncClient.myHostName) {
11
29
  throw new Error('Peer must be a different host');
12
30
  }
31
+ const myAuth = b64id.generateId();
13
32
  const transport = new EventEmitter();
14
- transport.send = (msg) => {
15
- if(typeof msg === 'object') {
16
- msg = JSON.stringify(msg);
33
+ transport.send = async (msg) => {
34
+ const fullMsg = {
35
+ msg,
36
+ myAuth,
37
+ toHost: hostName,
38
+ fromHost: hsyncClient.webUrl,
39
+ };
40
+ // const toSend = JSON.stringify(fullMsg);
41
+ const topic = `rpc/${hsyncClient.myHostName}`;
42
+ debug('↑ peer rpc', `${hostName}/_hs/rpc`, msg);
43
+ // hsyncClient.mqConn.publish(topic, Buffer.from(toSend));
44
+ try {
45
+ const result = await fetch.post(`${hostName}/_hs/rpc`, fullMsg);
46
+ transport.receiveData({id: msg.id, result, jsonrpc: msg.jsonrpc});
47
+ } catch(e) {
48
+ debug(e);
49
+ transport.receiveData({id: msg.id, error: e, method: msg.method, jsonrpc: msg.jsonrpc});
17
50
  }
18
- const topic = `msg/${hostName}/${hsyncClient.username}/rpc`;
19
- debug('↑ peer rpc reply', msg);
20
- hsyncClient.mqConn.publish(topic, Buffer.from(msg));
51
+
21
52
  };
22
53
  transport.receiveData = (msg) => {
23
54
  debug('↓ peer rpc', msg);
24
- if(msg) {
55
+ if(typeof msg === 'string') {
25
56
  msg = JSON.parse(msg);
26
57
  }
27
58
  if (Array.isArray(msg.params)) {
@@ -30,35 +61,35 @@ function createRPCPeer({ hostName, hsyncClient, timeout = 10000, methods = {} })
30
61
  transport.emit('rpc', msg);
31
62
  };
32
63
 
33
- const peer = rawr({transport, methods: Object.assign({}, methods), timeout});
64
+ const peer = rawr({transport, methods: Object.assign({}, methods), timeout, idGenerator: b64id.generateId});
65
+ peer.myAuth = myAuth;
34
66
  return peer;
35
67
 
36
68
  }
37
69
 
38
- function createServerReplyPeer({ requestId, hsyncClient, methods = {}}) {
39
-
70
+ function createServerPeer(hsyncClient, methods) {
40
71
  const transport = new EventEmitter();
41
72
  transport.send = (msg) => {
42
73
  if(typeof msg === 'object') {
43
74
  msg = JSON.stringify(msg);
44
75
  }
45
- const topic = `ssrpc/${hsyncClient.myHostName}/${requestId}`;
46
- debug('↑ server rpc reply', msg);
76
+ const topic = `srpc/${hsyncClient.myHostName}`;
77
+ debug('↑ server rpc request', msg);
47
78
  hsyncClient.mqConn.publish(topic, Buffer.from(msg));
48
79
  };
49
80
  transport.receiveData = (msg) => {
50
- debug('↓ server rpc', msg);
81
+ debug('↓ server rpc reply', msg);
51
82
  if(msg) {
52
83
  msg = JSON.parse(msg);
53
84
  }
54
85
  transport.emit('rpc', msg);
55
86
  };
56
-
57
- const peer = rawr({transport, methods});
87
+ const peer = rawr({transport, methods, timeout: 5000});
58
88
  return peer;
59
89
  }
60
90
 
61
91
  module.exports = {
62
92
  createRPCPeer,
63
- createServerReplyPeer,
93
+ createServerPeer,
94
+ getRPCPeer,
64
95
  };
@@ -1,51 +1,88 @@
1
+ const b64id = require('b64id');
1
2
  const debug = require('debug')('hsync:listener');
2
3
  const debugError = require('debug')('hsync:error');
4
+ // const { getRTCPeer } = require('./data-channel');
3
5
 
4
- const { createRPCPeer } = require('./rpc');
6
+ const { getRPCPeer } = require('./rpc');
5
7
 
6
- debugError.color = 1;
7
8
  let net;
8
9
 
9
10
  function setNet(netImpl) {
10
11
  net = netImpl;
11
12
  }
12
13
 
14
+
15
+ debugError.color = 1;
16
+
17
+ const sockets = {};
18
+
19
+ // function receiveRelayData(socketId, data) {
20
+ // if (sockets[socketId]) {
21
+ // debug('receiveRelayData', socketId, data.length);
22
+ // sockets[socketId].write(data);
23
+ // }
24
+ // }
25
+
26
+ function receiveRelayData(requestInfo, { socketId, data }) {
27
+ debug('receiveRelayData', socketId, data, 'sockets', Object.keys(sockets));
28
+ if (!sockets[socketId]) {
29
+ throw new Error('listener has no matching socket for relay: ' + socketId);
30
+ }
31
+ let dataBuffer = data;
32
+ if (typeof dataBuffer === 'string') {
33
+ dataBuffer = Buffer.from(dataBuffer, 'base64');
34
+ }
35
+ sockets[socketId].write(dataBuffer);
36
+ return 'ok';
37
+ }
38
+
13
39
  function createSocketListenHandler({hostName, port, targetPort, targetHost, hsyncClient}) {
14
40
  debug('creating handler', hostName, port, targetPort, targetHost);
15
-
16
- const sockets = {};
17
41
 
18
- const peer = createRPCPeer({hostName, hsyncClient});
42
+ const rpcPeer = getRPCPeer({hostName, hsyncClient});
19
43
 
20
44
  debug('peer crated');
21
-
45
+
22
46
  const socketServer = net.createServer(async (socket) => {
23
47
 
24
48
  socket.socketId = b64id.generateId();
25
49
  sockets[socket.socketId] = socket;
50
+ debug('connected to local listener', port, socket.socketId);
26
51
  socket.peerConnected = false;
27
- const pubTopic = `msg/${hostName}/${hsyncClient.username}/socketData/${socket.socketId}`;
28
- const closeTopic = `msg/${hostName}/${hsyncClient.username}/socketClose/${socket.socketId}`;
52
+ const pubTopic = `msg/${hostName}/${hsyncClient.myHostName}/socketData/${socket.socketId}`;
53
+ const closeTopic = `msg/${hostName}/${hsyncClient.myHostName}/socketClose/${socket.socketId}`;
29
54
  const dataQueue = [];
30
55
 
31
- function sendData(data) {
32
- hsyncClient.mqConn.publish(pubTopic, data);
56
+ async function sendData(data) {
57
+ debug('sending data', hostName, data.length);
58
+ // const p = getRTCPeer(hostName, hsyncClient);
59
+ // if (p.connected) {
60
+ // p.send(`socketData/${socket.socketId}`, data);
61
+ // return;
62
+ // }
63
+ // hsyncClient.mqConn.publish(pubTopic, data);
64
+ const result = await rpcPeer.methods.receiveListenerData({
65
+ socketId: socket.socketId,
66
+ data: Buffer.from(data).toString('base64'),
67
+ });
68
+ debug('sendData from Listener', result);
33
69
  }
34
70
 
35
71
  socket.on('data', async (data) => {
36
- if (!socket.peerConnected) {
37
- dataQueue.push(data);
38
- return;
39
- }
72
+ debug('socket data', data?.length);
73
+ // if (!socket.peerConnected) {
74
+ // dataQueue.push(data);
75
+ // return;
76
+ // }
40
77
  sendData(data);
41
78
  });
42
79
 
43
80
  socket.on('close', () => {
44
-
81
+ debug('listener socket closed', port, socket.socketId);
45
82
  if (sockets[socket.socketId]) {
46
83
  delete sockets[socket.socketId];
47
84
  }
48
- hsyncClient.mqConn.publish(closeTopic, '');
85
+ // hsyncClient.mqConn.publish(closeTopic, '');
49
86
  });
50
87
 
51
88
  socket.on('error', (error) => {
@@ -53,12 +90,20 @@ function createSocketListenHandler({hostName, port, targetPort, targetHost, hsyn
53
90
  if (sockets[socket.socketId]) {
54
91
  delete sockets[socket.socketId];
55
92
  }
56
- hsyncClient.mqConn.publish(closeTopic, '');
93
+ // hsyncClient.mqConn.publish(closeTopic, '');
57
94
  });
58
95
 
59
96
  try {
60
- await peer.methods.connectSocket(targetPort, targetHost);
97
+ debug('connecting remotely', socket.socketId, targetPort);
98
+ const result = await rpcPeer.methods.connectSocket({socketId: socket.socketId, port: targetPort});
99
+ debug('connect result', result);
100
+ socket.peerConnected = true;
61
101
  dataQueue.forEach(sendData);
102
+ // const p = getRTCPeer(hostName, hsyncClient);
103
+ // if (p.pc) {
104
+ // p.createDC();
105
+ // }
106
+
62
107
  } catch (e) {
63
108
  debugError('cant connect remotely', hostName, targetPort, e);
64
109
  if (sockets[socket.socketId]) {
@@ -67,6 +112,7 @@ function createSocketListenHandler({hostName, port, targetPort, targetHost, hsyn
67
112
  socket.end();
68
113
  }
69
114
 
115
+
70
116
  });
71
117
 
72
118
  socketServer.listen(port);
@@ -92,7 +138,8 @@ function createSocketListenHandler({hostName, port, targetPort, targetHost, hsyn
92
138
  };
93
139
  }
94
140
 
95
- module.exports = {
141
+ module.exports = {
96
142
  createSocketListenHandler,
143
+ receiveRelayData,
97
144
  setNet,
98
145
  };
@@ -1,7 +1,8 @@
1
+ const b64id = require('b64id');
1
2
  const debug = require('debug')('hsync:relay');
2
3
  const debugError = require('debug')('hsync:error');
3
-
4
- const { createRPCPeer } = require('./rpc');
4
+ // const { getRTCPeer } = require('./data-channel');
5
+ const { getRPCPeer } = require('./rpc');
5
6
 
6
7
  debugError.color = 1;
7
8
 
@@ -11,86 +12,92 @@ function setNet(netImpl) {
11
12
  net = netImpl;
12
13
  }
13
14
 
14
- function createHandler({hostName, port, targetPort, targetHost, hsyncClient}) {
15
-
16
- const sockets = {};
17
-
18
- const peer = createRPCPeer({hostName, hsyncClient});
19
15
 
20
- const socketServer = net.createServer(async (socket) => {
16
+ const relays = {};
17
+ const sockets = {};
21
18
 
22
- socket.socketId = b64id.generateId();
23
- sockets[socket.socketId] = socket;
24
- socket.peerConnected = false;
25
- const pubTopic = `msg/${hostName}/${hsyncClient.username}/socketData/${socket.socketId}`;
26
- const closeTopic = `msg/${hostName}/${hsyncClient.username}/socketClose/${socket.socketId}`;
27
- const dataQueue = [];
19
+ function receiveListenerData(requestInfo, { socketId, data }) {
20
+ debug('receiveListenerData', socketId, data, 'sockets', Object.keys(sockets));
21
+ if (!sockets[socketId]) {
22
+ throw new Error('relay has no matching socket for listener : ' + socketId);
23
+ }
24
+ let dataBuffer = data;
25
+ if (typeof dataBuffer === 'string') {
26
+ dataBuffer = Buffer.from(dataBuffer, 'base64');
27
+ }
28
+ sockets[socketId].write(dataBuffer);
29
+ return 'ok';
30
+ }
28
31
 
29
- function sendData(data) {
30
- hsyncClient.mqConn.publish(pubTopic, data);
31
- }
32
+ function connectSocket({ hsyncClient, fromHost }, {port, socketId}) {
33
+ const relay = relays['p' + port];
34
+ debug('connect relay', port, socketId);
35
+ if (!relay) {
36
+ throw new Error('no relay found for port: ' + port);
37
+ }
38
+ const rpcPeer = getRPCPeer({hostName: fromHost, hsyncClient});
39
+ // const relayDataTopic = `msg/${hostName}/${hsyncClient.myHostName}/relayData/${socketId}`;
40
+ return new Promise((resolve, reject) => {
41
+ const socket = new net.Socket();
42
+ socket.socketId = socketId;
43
+ sockets[socketId] = socket;
44
+ socket.connect(relay.targetPort, relay.targetHost, () => {
45
+ debug(`CONNECTED TO LOCAL SERVER`, socket.socketId, socket.hostName);
46
+ resolve({socketId, targetHost: relay.targetHost, targetPort: relay.targetPort});
47
+ });
32
48
 
33
49
  socket.on('data', async (data) => {
34
- if (!socket.peerConnected) {
35
- dataQueue.push(data);
36
- return;
37
- }
38
- sendData(data);
50
+ debug(`data in ${socket.socketId}`, relay.targetPort, relay.targetHost, data.length);
51
+ const result = await rpcPeer.methods.receiveRelayData({
52
+ socketId,
53
+ data: Buffer.from(data).toString('base64'),
54
+ });
55
+ // const p = getRTCPeer(hostName, hsyncClient);
56
+ // if (p.connected) {
57
+ // p.send(`relayData/${socketId}`, data);
58
+ // return;
59
+ // }
60
+ // hsyncClient.mqConn.publish(relayDataTopic, data);
39
61
  });
40
-
41
62
  socket.on('close', () => {
42
-
43
- if (sockets[socket.socketId]) {
44
- delete sockets[socket.socketId];
45
- }
46
- hsyncClient.mqConn.publish(closeTopic, '');
63
+ debug(`LOCAL CONNECTION CLOSED`, socket.socketId, targetHost, targetPort);
64
+ delete sockets[socket.socketId];
47
65
  });
48
-
49
- socket.on('error', (error) => {
50
- debug('socket error', hostName, socket.socketId, error);
51
- if (sockets[socket.socketId]) {
52
- delete sockets[socket.socketId];
53
- }
54
- hsyncClient.mqConn.publish(closeTopic, '');
66
+
67
+ socket.on('error', (e) => {
68
+ debugError(`LOCAL CONNECTION ERROR`, socket.socketId, targetHost, targetPort, e);
69
+ delete sockets[socket.socketId];
70
+ reject(e);
55
71
  });
56
72
 
57
- try {
58
- await peer.methods.connectSocket(targetPort, targetHost);
59
- dataQueue.forEach(sendData);
60
- } catch (e) {
61
- debugError('cant connect remotely', hostName, targetPort, e);
62
- if (sockets[socket.socketId]) {
63
- delete sockets[socket.socketId];
64
- }
65
- socket.end();
66
- }
67
-
68
73
  });
69
74
 
70
- socketServer.listen(port);
71
-
72
-
73
- function end() {
74
- const sockKeys = Object.keys(sockets);
75
- sockKeys.forEach((sk) => {
76
- try {
77
- sockets[sk].end();
78
- delete sockets[sk];
79
- }
80
- catch(e) {
81
- debug('error closing socket', e);
82
- }
83
- });
84
- }
75
+ }
85
76
 
86
- return {
87
- socketServer,
88
- sockets,
89
- end,
77
+ // function receiveSocketData(socketId, data) {
78
+ // if (sockets[socketId]) {
79
+ // debug('receiveSocketData', socketId, data.length);
80
+ // sockets[socketId].write(data);
81
+ // return 'ok';
82
+ // }
83
+
84
+ // throw new Error('socket not found: ' + socketId);
85
+ // }
86
+
87
+ function createSocketRelayHandler({hostName, port, targetPort, targetHost, hsyncClient}) {
88
+ debug('creating relay', hostName, port, targetPort, targetHost);
89
+ relays['p' + port] = {
90
+ hostName,
91
+ port,
92
+ targetPort,
93
+ targetHost,
90
94
  };
91
95
  }
92
96
 
93
97
  module.exports = {
94
- createHandler,
98
+ createSocketRelayHandler,
99
+ connectSocket,
100
+ // receiveSocketData,
95
101
  setNet,
102
+ receiveListenerData,
96
103
  };
package/lib/web-net.js CHANGED
@@ -35,10 +35,10 @@ function Socket() {
35
35
  function createServer(cb) {
36
36
  const server = new EventEmitter();
37
37
  server.listen = (port) => {
38
- console.log('server.listen', port);
38
+ debug('server.listen', port);
39
39
  listeners['l' + port] = server;
40
40
  events.on('socket_connect_' + port, ({ clientSocket, clientCallback }) => {
41
- console.log('socket_connect_' + port, clientSocket);
41
+ debug('socket_connect_' + port, clientSocket);
42
42
  const serverSocket = new EventEmitter();
43
43
  clientSocket.serverSocket = serverSocket;
44
44
  if (server.cb) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hsync",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "description": "client for hsync-server",
5
5
  "main": "hsync.js",
6
6
  "scripts": {
package/dev_dynamic.sh DELETED
@@ -1,7 +0,0 @@
1
- #!/bin/bash
2
-
3
- export DEBUG="hsync*,errors*";
4
-
5
- export HSYNC_DYNAMIC_HOST="https://foo.hsync.tech";
6
-
7
-
@@ -1,8 +0,0 @@
1
- #!/bin/bash
2
-
3
- export DEBUG="hsync*,errors*";
4
-
5
- export HSYNC_SECRET="f7glV4m_REeimy_TdwjM4w"
6
-
7
- export HSYNC_SERVER="wss://luis-stripe.shiv.to"
8
- export PORT="3021"