hsync 0.30.1 → 0.31.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/.github/workflows/ci.yml +32 -0
- package/.husky/pre-commit +1 -0
- package/.prettierrc +7 -0
- package/Readme.md +1 -0
- package/cli.js +103 -56
- package/config.js +6 -6
- package/connection.js +44 -48
- package/dist/hsync.js +1082 -831
- package/dist/hsync.min.js +28862 -1
- package/dist/hsync.min.js.LICENSE.txt +11 -1
- package/eslint.config.js +26 -0
- package/hsync-web.js +18 -17
- package/hsync.js +14 -18
- package/index.js +3 -3
- package/lib/fetch.js +2 -4
- package/lib/peers.js +69 -68
- package/lib/rtc-node.js +35 -34
- package/lib/rtc-web.js +60 -58
- package/lib/socket-listeners.js +16 -22
- package/lib/socket-map.js +5 -5
- package/lib/socket-relays.js +12 -17
- package/lib/web-handler.js +8 -14
- package/package.json +61 -18
- package/shell.js +4 -8
- package/test/mocks/mqtt.mock.js +25 -0
- package/test/mocks/net.mock.js +34 -0
- package/test/mocks/rtc.mock.js +9 -0
- package/test/setup.js +10 -0
- package/test/unit/config.test.js +36 -0
- package/test/unit/fetch.test.js +189 -0
- package/test/unit/peers.test.js +275 -0
- package/test/unit/socket-listeners.test.js +319 -0
- package/test/unit/socket-map.test.js +64 -0
- package/test/unit/socket-relays.test.js +315 -0
- package/test/unit/web-handler.test.js +223 -0
- package/todo.md +324 -0
- package/vitest.config.js +15 -0
- package/webpack.config.js +24 -8
package/lib/rtc-node.js
CHANGED
|
@@ -1,48 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import createDebug from 'debug';
|
|
2
|
+
|
|
3
|
+
const debug = createDebug('hsync:rtc-node');
|
|
4
|
+
const debugError = createDebug('errors');
|
|
5
|
+
|
|
3
6
|
let nodeDataChannel;
|
|
4
7
|
try {
|
|
5
|
-
nodeDataChannel =
|
|
8
|
+
nodeDataChannel = await import('node-datachannel');
|
|
9
|
+
// Handle both default export and named export
|
|
10
|
+
if (nodeDataChannel.default) {
|
|
11
|
+
nodeDataChannel = nodeDataChannel.default;
|
|
12
|
+
}
|
|
6
13
|
} catch (e) {
|
|
7
|
-
debugError(e);
|
|
14
|
+
debugError('node-datachannel not installed:', e.message);
|
|
8
15
|
}
|
|
9
16
|
|
|
10
17
|
const rtc = {
|
|
11
18
|
PeerConnection: nodeDataChannel?.PeerConnection,
|
|
12
19
|
};
|
|
13
20
|
|
|
14
|
-
|
|
15
21
|
const defaultOptions = { iceServers: ['stun:stun.l.google.com:19302'] };
|
|
16
22
|
|
|
17
23
|
const GATHERING_TIMEOUT = 4000;
|
|
18
24
|
|
|
19
|
-
function offerPeer(peer) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
async function offerPeer(peer) {
|
|
26
|
+
if (!rtc.PeerConnection) {
|
|
27
|
+
throw new Error('node-datachannel not installed');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
26
31
|
const con = new rtc.PeerConnection('pc', defaultOptions);
|
|
27
32
|
// window.rtc = rtc;
|
|
28
|
-
|
|
33
|
+
|
|
29
34
|
peer.rtcCon = con;
|
|
30
35
|
peer.rtcOfferer = true;
|
|
31
|
-
|
|
36
|
+
|
|
32
37
|
let gatheringComplete = false;
|
|
33
|
-
|
|
38
|
+
// offerSent tracking removed - not currently used
|
|
34
39
|
const start = Date.now();
|
|
35
40
|
|
|
36
41
|
peer.handleRtcAnswer = async (answer) => {
|
|
37
42
|
debug('node handle RtcAnswer', answer.sdp.length);
|
|
38
43
|
await peer.rtcCon.setRemoteDescription(answer.sdp, answer.type);
|
|
39
44
|
return 'node handle RtcAnswer ok';
|
|
40
|
-
}
|
|
41
|
-
|
|
45
|
+
};
|
|
46
|
+
|
|
42
47
|
async function sendOffer() {
|
|
43
48
|
const desc = con.localDescription();
|
|
44
49
|
try {
|
|
45
|
-
const resp = await peer.methods.rtcSignal({type: desc.type, sdp: desc.sdp});
|
|
50
|
+
const resp = await peer.methods.rtcSignal({ type: desc.type, sdp: desc.sdp });
|
|
46
51
|
resolve(resp);
|
|
47
52
|
} catch (e) {
|
|
48
53
|
debugError('error sending offer', e);
|
|
@@ -50,7 +55,7 @@ function offerPeer(peer) {
|
|
|
50
55
|
}
|
|
51
56
|
// peer.methods.rtcSignal({type: desc.type, sdp: desc.sdp});
|
|
52
57
|
}
|
|
53
|
-
|
|
58
|
+
|
|
54
59
|
con.onGatheringStateChange = (state) => {
|
|
55
60
|
debug('onGatheringStateChange', state);
|
|
56
61
|
if (state === 'complete') {
|
|
@@ -59,8 +64,8 @@ function offerPeer(peer) {
|
|
|
59
64
|
// We only want to provide an answer once all of our candidates have been added to the SDP.
|
|
60
65
|
sendOffer();
|
|
61
66
|
}
|
|
62
|
-
}
|
|
63
|
-
|
|
67
|
+
};
|
|
68
|
+
|
|
64
69
|
con.onStateChange((state) => {
|
|
65
70
|
debug('offerer onStateChange: ', state);
|
|
66
71
|
if (state === 'connected') {
|
|
@@ -78,12 +83,12 @@ function offerPeer(peer) {
|
|
|
78
83
|
peer.dc = null;
|
|
79
84
|
}
|
|
80
85
|
});
|
|
81
|
-
|
|
86
|
+
|
|
82
87
|
con.onDataChannel((dc) => {
|
|
83
88
|
debug('offerer onDataChannel', dc);
|
|
84
89
|
peer.dc = dc;
|
|
85
90
|
});
|
|
86
|
-
|
|
91
|
+
|
|
87
92
|
const dc = con.createDataChannel('fromofferer');
|
|
88
93
|
dc.onOpen(() => {
|
|
89
94
|
peer.dc = dc;
|
|
@@ -94,22 +99,20 @@ function offerPeer(peer) {
|
|
|
94
99
|
peer.rtcEvents.emit('dcOpen', dc);
|
|
95
100
|
debug('keys', Object.keys(dc));
|
|
96
101
|
});
|
|
97
|
-
|
|
102
|
+
|
|
98
103
|
dc.onMessage((msg) => {
|
|
99
104
|
debug('node offerer received msg:', msg.length);
|
|
100
105
|
peer.rtcEvents.emit('packet', msg);
|
|
101
106
|
});
|
|
102
|
-
|
|
107
|
+
|
|
103
108
|
con.setLocalDescription();
|
|
104
|
-
|
|
109
|
+
|
|
105
110
|
setTimeout(() => {
|
|
106
111
|
if (!gatheringComplete) {
|
|
107
112
|
debug('didnt finish gathering');
|
|
108
113
|
sendOffer();
|
|
109
|
-
offerSent = true;
|
|
110
114
|
}
|
|
111
115
|
}, GATHERING_TIMEOUT);
|
|
112
|
-
|
|
113
116
|
});
|
|
114
117
|
}
|
|
115
118
|
|
|
@@ -121,10 +124,10 @@ async function answerPeer(peer, offer) {
|
|
|
121
124
|
const con = new rtc.PeerConnection('pc', defaultOptions);
|
|
122
125
|
peer.rtcCon = con;
|
|
123
126
|
peer.answerer = true;
|
|
124
|
-
|
|
127
|
+
|
|
125
128
|
function sendAnswer() {
|
|
126
129
|
const desc = con.localDescription();
|
|
127
|
-
peer.methods.rtcSignal({type: desc.type, sdp: desc.sdp});
|
|
130
|
+
peer.methods.rtcSignal({ type: desc.type, sdp: desc.sdp });
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
con.onStateChange((state) => {
|
|
@@ -157,7 +160,7 @@ async function answerPeer(peer, offer) {
|
|
|
157
160
|
con.setLocalDescription();
|
|
158
161
|
|
|
159
162
|
con.onDataChannel((dc) => {
|
|
160
|
-
debug(
|
|
163
|
+
debug('answerer onDataChannel', dc.getLabel());
|
|
161
164
|
dc.onMessage((msg) => {
|
|
162
165
|
debug('node answerer Received Msg:', msg.length);
|
|
163
166
|
peer.rtcEvents.emit('packet', msg);
|
|
@@ -171,11 +174,9 @@ async function answerPeer(peer, offer) {
|
|
|
171
174
|
};
|
|
172
175
|
peer.rtcEvents.emit('dcOpen', dc);
|
|
173
176
|
});
|
|
174
|
-
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
rtc.offerPeer = offerPeer;
|
|
178
180
|
rtc.answerPeer = answerPeer;
|
|
179
181
|
|
|
180
|
-
|
|
181
|
-
module.exports = rtc;
|
|
182
|
+
export default rtc;
|
package/lib/rtc-web.js
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import createDebug from 'debug';
|
|
2
|
+
|
|
3
|
+
const debug = createDebug('hsync:rtc-web');
|
|
4
|
+
const debugError = createDebug('errors');
|
|
3
5
|
|
|
4
6
|
const rtc = {
|
|
5
7
|
PeerConnection: RTCPeerConnection,
|
|
6
8
|
};
|
|
7
9
|
|
|
8
|
-
|
|
9
10
|
const defaultOptions = {
|
|
10
11
|
// Recommended for libdatachannel
|
|
11
12
|
// bundlePolicy: "max-bundle",
|
|
12
|
-
iceServers: [{
|
|
13
|
+
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
const GATHERING_TIMEOUT = 4000;
|
|
16
17
|
|
|
17
18
|
async function offerPeer(peer) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// window.rtc = rtc;
|
|
19
|
+
const con = new RTCPeerConnection(defaultOptions);
|
|
20
|
+
// window.rtc = rtc;
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
let gatheringComplete = false;
|
|
26
|
-
let offerSent = false;
|
|
27
|
-
const start = Date.now();
|
|
22
|
+
peer.rtcCon = con;
|
|
23
|
+
peer.rtcOfferer = true;
|
|
28
24
|
|
|
25
|
+
let gatheringComplete = false;
|
|
26
|
+
let offerSent = false;
|
|
27
|
+
const start = Date.now();
|
|
28
|
+
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
29
30
|
async function sendOffer(alreadySent) {
|
|
30
31
|
debug('send offer', alreadySent);
|
|
31
32
|
const desc = con.localDescription;
|
|
32
33
|
try {
|
|
33
|
-
const resp = await peer.methods.rtcSignal({type: desc.type, sdp: desc.sdp, alreadySent});
|
|
34
|
+
const resp = await peer.methods.rtcSignal({ type: desc.type, sdp: desc.sdp, alreadySent });
|
|
34
35
|
resolve(resp);
|
|
35
36
|
} catch (e) {
|
|
36
37
|
debugError('error sending offer', e);
|
|
@@ -38,15 +39,15 @@ async function offerPeer(peer) {
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
con.onicegatheringstatechange = (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
42
|
+
con.onicegatheringstatechange = (_state) => {
|
|
43
|
+
debug('state change', con.iceGatheringState);
|
|
44
|
+
if (con.iceGatheringState === 'complete') {
|
|
45
|
+
debug('icegathering done', Date.now() - start);
|
|
46
|
+
gatheringComplete = true;
|
|
47
|
+
// We only want to provide an answer once all of our candidates have been added to the SDP.
|
|
48
|
+
sendOffer(offerSent);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
50
51
|
|
|
51
52
|
con.onicecandidate = (ice) => {
|
|
52
53
|
debug('ice candidate', ice);
|
|
@@ -54,7 +55,7 @@ async function offerPeer(peer) {
|
|
|
54
55
|
|
|
55
56
|
con.onconnectionstatechange = (event) => {
|
|
56
57
|
debug('offerer connection state', con.connectionState, event);
|
|
57
|
-
if(con.connectionState === 'connected') {
|
|
58
|
+
if (con.connectionState === 'connected') {
|
|
58
59
|
peer.connected = true;
|
|
59
60
|
peer.rtcEvents.emit('connected', con);
|
|
60
61
|
} else if (con.connectionState === 'disconnected') {
|
|
@@ -78,11 +79,11 @@ async function offerPeer(peer) {
|
|
|
78
79
|
const dc = con.createDataChannel('from web');
|
|
79
80
|
|
|
80
81
|
peer.dc = dc;
|
|
81
|
-
dc.onmessage = (event) => {
|
|
82
|
+
dc.onmessage = (event) => {
|
|
82
83
|
debug('dc.onmessage', event.data);
|
|
83
84
|
peer.rtcEvents.emit('packet', event.data);
|
|
84
85
|
};
|
|
85
|
-
dc.onopen = (
|
|
86
|
+
dc.onopen = (_event) => {
|
|
86
87
|
peer.dcOpen = true;
|
|
87
88
|
peer.dc = dc;
|
|
88
89
|
peer.rtcSend = (packet) => {
|
|
@@ -92,61 +93,64 @@ async function offerPeer(peer) {
|
|
|
92
93
|
peer.rtcEvents.emit('dcOpen', dc);
|
|
93
94
|
// dc.send('yo waddup from the browser');
|
|
94
95
|
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
96
|
+
|
|
97
|
+
con
|
|
98
|
+
.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true })
|
|
99
|
+
.then((offer) => {
|
|
100
|
+
return con.setLocalDescription(offer);
|
|
101
|
+
})
|
|
102
|
+
.then(() => {
|
|
103
|
+
setTimeout(() => {
|
|
104
|
+
if (!gatheringComplete) {
|
|
105
|
+
debug('didnt finish gathering');
|
|
106
|
+
sendOffer();
|
|
107
|
+
offerSent = true;
|
|
108
|
+
}
|
|
109
|
+
}, GATHERING_TIMEOUT);
|
|
110
|
+
|
|
111
|
+
peer.handleRtcAnswer = async (answer) => {
|
|
112
|
+
debug('web handle RtcAnswer', answer.sdp.length);
|
|
113
|
+
await con.setRemoteDescription(answer);
|
|
114
|
+
return 'web handle RtcAnswer ok';
|
|
115
|
+
};
|
|
116
|
+
})
|
|
117
|
+
.catch((e) => {
|
|
118
|
+
debugError('error creating data channel', e);
|
|
119
|
+
reject(e);
|
|
120
|
+
});
|
|
117
121
|
});
|
|
118
122
|
}
|
|
119
123
|
|
|
120
124
|
async function answerPeer(peer, offer) {
|
|
121
|
-
const options = {...defaultOptions, bundlePolicy:
|
|
125
|
+
const options = { ...defaultOptions, bundlePolicy: 'max-bundle' };
|
|
122
126
|
const con = new RTCPeerConnection(options);
|
|
123
127
|
// window.rtc = rtc;
|
|
124
128
|
|
|
125
129
|
peer.rtcCon = con;
|
|
126
130
|
peer.answerer = true;
|
|
127
|
-
|
|
131
|
+
|
|
128
132
|
let gatheringComplete = false;
|
|
129
133
|
const start = Date.now();
|
|
130
134
|
|
|
131
135
|
async function sendAnswer() {
|
|
132
136
|
const desc = con.localDescription;
|
|
133
137
|
try {
|
|
134
|
-
await peer.methods.rtcSignal({type: desc.type, sdp: desc.sdp});
|
|
138
|
+
await peer.methods.rtcSignal({ type: desc.type, sdp: desc.sdp });
|
|
135
139
|
} catch (e) {
|
|
136
140
|
debugError('error sending answer', e);
|
|
137
141
|
}
|
|
138
142
|
}
|
|
139
143
|
|
|
140
|
-
con.onicegatheringstatechange = (
|
|
144
|
+
con.onicegatheringstatechange = (_state) => {
|
|
141
145
|
if (con.iceGatheringState === 'complete') {
|
|
142
146
|
gatheringComplete = true;
|
|
143
147
|
debug('answerer icegathering done', Date.now() - start);
|
|
144
148
|
sendAnswer();
|
|
145
149
|
}
|
|
146
|
-
}
|
|
150
|
+
};
|
|
147
151
|
await con.setRemoteDescription(offer);
|
|
148
152
|
|
|
149
|
-
|
|
153
|
+
const answer = await con.createAnswer();
|
|
150
154
|
await con.setLocalDescription(answer);
|
|
151
155
|
|
|
152
156
|
con.onicecandidate = (ice) => {
|
|
@@ -155,7 +159,7 @@ async function answerPeer(peer, offer) {
|
|
|
155
159
|
|
|
156
160
|
con.onconnectionstatechange = (event) => {
|
|
157
161
|
debug('answerer connection state', con.connectionState, event);
|
|
158
|
-
if(con.connectionState === 'connected') {
|
|
162
|
+
if (con.connectionState === 'connected') {
|
|
159
163
|
peer.connected = true;
|
|
160
164
|
peer.rtcEvents.emit('connected', con);
|
|
161
165
|
} else if (con.connectionState === 'disconnected') {
|
|
@@ -201,11 +205,9 @@ async function answerPeer(peer, offer) {
|
|
|
201
205
|
sendAnswer();
|
|
202
206
|
}
|
|
203
207
|
}, GATHERING_TIMEOUT);
|
|
204
|
-
|
|
205
208
|
}
|
|
206
209
|
|
|
207
|
-
|
|
208
210
|
rtc.offerPeer = offerPeer;
|
|
209
211
|
rtc.answerPeer = answerPeer;
|
|
210
212
|
|
|
211
|
-
|
|
213
|
+
export default rtc;
|
package/lib/socket-listeners.js
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import b64id from 'b64id';
|
|
2
|
+
import createDebug from 'debug';
|
|
3
|
+
import { sockets } from './socket-map.js';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const debug = createDebug('hsync:listener');
|
|
6
|
+
const debugError = createDebug('hsync:error');
|
|
7
|
+
|
|
8
|
+
debugError.color = 1;
|
|
6
9
|
|
|
7
10
|
let net;
|
|
8
11
|
|
|
9
|
-
function setNet(netImpl) {
|
|
12
|
+
export function setNet(netImpl) {
|
|
10
13
|
net = netImpl;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function initListeners(hsyncClient) {
|
|
16
|
+
export function initListeners(hsyncClient) {
|
|
16
17
|
const socketListeners = {};
|
|
17
18
|
|
|
18
19
|
function getSocketListeners() {
|
|
19
20
|
const hKeys = Object.keys(socketListeners);
|
|
20
21
|
debug('getSocketListeners', hKeys);
|
|
21
|
-
|
|
22
|
+
const retVal = hKeys.map((hk) => {
|
|
22
23
|
const l = socketListeners[hk];
|
|
23
24
|
return {
|
|
24
25
|
port: l.port,
|
|
@@ -46,11 +47,10 @@ function initListeners(hsyncClient) {
|
|
|
46
47
|
if (cleanHost !== targetHost) {
|
|
47
48
|
debug('targetHost cleaned UP', targetHost, cleanHost);
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
+
|
|
50
51
|
const rpcPeer = hsyncClient.getRPCPeer({ hostName: cleanHost });
|
|
51
52
|
|
|
52
53
|
const socketServer = net.createServer(async (socket) => {
|
|
53
|
-
|
|
54
54
|
if (!rpcPeer.rtcCon) {
|
|
55
55
|
try {
|
|
56
56
|
debug('initiating connectRTC from socket listener');
|
|
@@ -106,7 +106,7 @@ function initListeners(hsyncClient) {
|
|
|
106
106
|
// }
|
|
107
107
|
sendData(data);
|
|
108
108
|
});
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
socket.on('close', (a, b, c) => {
|
|
111
111
|
debug('listener socket closed', port, socket.socketId, a, b, c);
|
|
112
112
|
if (sockets[socket.socketId]) {
|
|
@@ -120,14 +120,14 @@ function initListeners(hsyncClient) {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
socket.on('error', (error) => {
|
|
125
125
|
debug('socket error', targetHost, socket.socketId, error);
|
|
126
126
|
if (sockets[socket.socketId]) {
|
|
127
127
|
delete sockets[socket.socketId];
|
|
128
128
|
}
|
|
129
129
|
});
|
|
130
|
-
|
|
130
|
+
|
|
131
131
|
try {
|
|
132
132
|
debug('connecting remotely', socket.socketId, targetPort, rpcPeer.hostName, targetHost);
|
|
133
133
|
const result = await rpcPeer.methods.connectSocket({
|
|
@@ -137,7 +137,7 @@ function initListeners(hsyncClient) {
|
|
|
137
137
|
});
|
|
138
138
|
debug('connect result', result);
|
|
139
139
|
socket.peerConnected = true;
|
|
140
|
-
dataQueue.forEach(sendData);
|
|
140
|
+
dataQueue.forEach(sendData);
|
|
141
141
|
} catch (e) {
|
|
142
142
|
debugError('cant connect remotely', targetHost, targetPort, e);
|
|
143
143
|
if (sockets[socket.socketId]) {
|
|
@@ -157,8 +157,7 @@ function initListeners(hsyncClient) {
|
|
|
157
157
|
sockets[sk].end();
|
|
158
158
|
delete sockets[sk];
|
|
159
159
|
}
|
|
160
|
-
}
|
|
161
|
-
catch(e) {
|
|
160
|
+
} catch (e) {
|
|
162
161
|
debug('error closing socket', e);
|
|
163
162
|
}
|
|
164
163
|
});
|
|
@@ -189,8 +188,3 @@ function initListeners(hsyncClient) {
|
|
|
189
188
|
getSocketListeners,
|
|
190
189
|
};
|
|
191
190
|
}
|
|
192
|
-
|
|
193
|
-
module.exports = {
|
|
194
|
-
initListeners,
|
|
195
|
-
setNet,
|
|
196
|
-
};
|
package/lib/socket-map.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import createDebug from 'debug';
|
|
2
|
+
|
|
3
|
+
const debug = createDebug('hsync:socket-map');
|
|
4
|
+
|
|
2
5
|
const sockets = {};
|
|
3
6
|
|
|
4
7
|
function handleSocketPacket(packet) {
|
|
@@ -13,7 +16,4 @@ function handleSocketPacket(packet) {
|
|
|
13
16
|
}
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
sockets,
|
|
18
|
-
handleSocketPacket,
|
|
19
|
-
};
|
|
19
|
+
export { sockets, handleSocketPacket };
|
package/lib/socket-relays.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import createDebug from 'debug';
|
|
2
|
+
import { sockets } from './socket-map.js';
|
|
3
|
+
|
|
4
|
+
const debug = createDebug('hsync:relay');
|
|
5
|
+
const debugError = createDebug('hsync:error');
|
|
4
6
|
|
|
5
7
|
debugError.color = 1;
|
|
6
8
|
|
|
7
9
|
let net;
|
|
8
10
|
|
|
9
|
-
function setNet(netImpl) {
|
|
11
|
+
export function setNet(netImpl) {
|
|
10
12
|
net = netImpl;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
function initRelays(hsyncClient) {
|
|
15
|
+
export function initRelays(hsyncClient) {
|
|
14
16
|
const cachedRelays = {};
|
|
15
17
|
|
|
16
18
|
function getSocketRelays() {
|
|
17
19
|
const hKeys = Object.keys(cachedRelays);
|
|
18
20
|
debug('getSocketListeners', hKeys);
|
|
19
|
-
|
|
21
|
+
const retVal = hKeys.map((hk) => {
|
|
20
22
|
const l = cachedRelays[hk];
|
|
21
23
|
return {
|
|
22
24
|
port: l.port,
|
|
@@ -58,7 +60,7 @@ function initRelays(hsyncClient) {
|
|
|
58
60
|
sockets[socketId] = socket;
|
|
59
61
|
socket.connect(relay.targetPort, relay.targetHost, () => {
|
|
60
62
|
debug(`CONNECTED TO LOCAL SERVER`, socket.socketId, socket.hostName, port);
|
|
61
|
-
resolve({socketId, targetHost: relay.targetHost, targetPort: relay.targetPort});
|
|
63
|
+
resolve({ socketId, targetHost: relay.targetHost, targetPort: relay.targetPort });
|
|
62
64
|
});
|
|
63
65
|
|
|
64
66
|
socket.on('data', async (data) => {
|
|
@@ -74,7 +76,7 @@ function initRelays(hsyncClient) {
|
|
|
74
76
|
debug(`LOCAL CONNECTION CLOSED`, socket.socketId);
|
|
75
77
|
if (sockets[socket.socketId]) {
|
|
76
78
|
try {
|
|
77
|
-
await peer.notifiers.closeListenerSocket({socketId});
|
|
79
|
+
await peer.notifiers.closeListenerSocket({ socketId });
|
|
78
80
|
} catch (e) {
|
|
79
81
|
debug('error closing socket', e);
|
|
80
82
|
}
|
|
@@ -87,12 +89,10 @@ function initRelays(hsyncClient) {
|
|
|
87
89
|
delete sockets[socket.socketId];
|
|
88
90
|
reject(e);
|
|
89
91
|
});
|
|
90
|
-
|
|
91
92
|
});
|
|
92
|
-
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
function addSocketRelay({whitelist, blacklist, port, targetPort, targetHost}) {
|
|
95
|
+
function addSocketRelay({ whitelist, blacklist, port, targetPort, targetHost }) {
|
|
96
96
|
targetPort = targetPort || port;
|
|
97
97
|
targetHost = targetHost || 'localhost';
|
|
98
98
|
debug('creating relay', whitelist, blacklist, port, targetPort, targetHost);
|
|
@@ -112,7 +112,7 @@ function initRelays(hsyncClient) {
|
|
|
112
112
|
hsyncClient.addSocketRelay = addSocketRelay;
|
|
113
113
|
hsyncClient.getSocketRelays = getSocketRelays;
|
|
114
114
|
hsyncClient.connectSocket = connectSocket;
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
return {
|
|
117
117
|
// receiveListenerData,
|
|
118
118
|
getSocketRelays,
|
|
@@ -120,8 +120,3 @@ function initRelays(hsyncClient) {
|
|
|
120
120
|
addSocketRelay,
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
-
|
|
124
|
-
module.exports = {
|
|
125
|
-
initRelays,
|
|
126
|
-
setNet,
|
|
127
|
-
};
|
package/lib/web-handler.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import createDebug from 'debug';
|
|
2
|
+
|
|
3
|
+
const debug = createDebug('hsync:web');
|
|
4
|
+
const debugError = createDebug('hsync:error');
|
|
3
5
|
|
|
4
6
|
debugError.color = 1;
|
|
5
7
|
|
|
6
8
|
let net;
|
|
7
9
|
|
|
8
|
-
function setNet(netImpl) {
|
|
10
|
+
export function setNet(netImpl) {
|
|
9
11
|
net = netImpl;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
function createWebHandler({myHostName, localHost, port, mqConn}) {
|
|
13
|
-
|
|
14
|
+
export function createWebHandler({ myHostName, localHost, port, mqConn }) {
|
|
14
15
|
const sockets = {};
|
|
15
16
|
|
|
16
17
|
function handleWebRequest(hostName, socketId, action, message) {
|
|
@@ -39,7 +40,7 @@ function createWebHandler({myHostName, localHost, port, mqConn}) {
|
|
|
39
40
|
} else {
|
|
40
41
|
debug(`→ ${socket.socketId}`, data.length, '↑');
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
+
|
|
43
44
|
mqConn.publish(`reply/${myHostName}/${socketId}`, data);
|
|
44
45
|
});
|
|
45
46
|
socket.on('close', () => {
|
|
@@ -62,7 +63,6 @@ function createWebHandler({myHostName, localHost, port, mqConn}) {
|
|
|
62
63
|
debug('←', socketId, message.length);
|
|
63
64
|
socket.write(message);
|
|
64
65
|
}
|
|
65
|
-
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function end() {
|
|
@@ -71,8 +71,7 @@ function createWebHandler({myHostName, localHost, port, mqConn}) {
|
|
|
71
71
|
try {
|
|
72
72
|
sockets[sk].end();
|
|
73
73
|
delete sockets[sk];
|
|
74
|
-
}
|
|
75
|
-
catch(e) {
|
|
74
|
+
} catch (e) {
|
|
76
75
|
debug('error closing socket', e);
|
|
77
76
|
}
|
|
78
77
|
});
|
|
@@ -84,8 +83,3 @@ function createWebHandler({myHostName, localHost, port, mqConn}) {
|
|
|
84
83
|
end,
|
|
85
84
|
};
|
|
86
85
|
}
|
|
87
|
-
|
|
88
|
-
module.exports = {
|
|
89
|
-
createWebHandler,
|
|
90
|
-
setNet,
|
|
91
|
-
};
|