Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions lib/ssh-session.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
let wrtc = require('./webrtc-request');
let Uuid = require('uuid');
let debug = require('debug')('Unifi SSH');
debug.log = console.log.bind(console);

function SSHSession(unifi, mac, uuid, stun, turn, username, password, site, autoclose, webrtc, waiter) {
this.unifi = unifi;
Expand Down Expand Up @@ -80,24 +81,24 @@ SSHSession.prototype.connect = function(connectTimeout, closeCallBack) {
this.password = d.password;
}
}
debug('Building ssh session with params: mac=' + this.mac + ' uuid=' + this.uuid + ' ttl=-1 stun=' + (this.stun instanceof Array && this.stun[0] ? this.stun[0].replace(/stun:/, '') : this.stun) + ' turn=' + (this.turn instanceof Array && this.turn[0] ? this.turn[0].replace(/turn:/, '') : this.turn) + ' username='+this.username + ' password=' + this.password + ' site=' + this.site);
return this.unifi.buildSSHSession(this.mac, this.uuid, "-1", (this.stun instanceof Array && this.stun[0] ? this.stun[0].replace(/stun:/, '') : this.stun), (this.turn instanceof Array && this.turn[0] ? this.turn[0].replace(/turn:/, '') : this.turn), this.username, this.password, this.site);
});
}
firstCall
.then(() => {
.then((r) => {
debug("first call response: " + JSON.stringify(r));
let o = { debug: this.debug };
if (this.waiter) o.waiter = this.waiter;
if (this.webrtc) o.webrtc = this.webrtc;
this.wrtc = new wrtc(o);
debug('Will open peer connection with stun', this.stun, 'turn', this.turn);
this.wrtc.RTCPeerConnection({
iceServers: [{
urls: this.stun,
url: this.stun
urls: this.stun
},
{
urls: this.turn,
url: this.turn,
username: this.username,
credential: this.password
}
Expand All @@ -109,8 +110,8 @@ SSHSession.prototype.connect = function(connectTimeout, closeCallBack) {
]
}); // ICE Servers
let connStateChange = () => {
debug('CAREFUL, Connection state changed');
let state = this.wrtc.peer.iceConnectionState;
debug('CAREFUL, Connection state changed: ' + state);
if (state == 'disconnected' || state == 'failed') {
debug('We are notified for session disconnection');
let rej = this.state != "open";
Expand Down Expand Up @@ -148,6 +149,17 @@ SSHSession.prototype.connect = function(connectTimeout, closeCallBack) {
this.fireQ('onmessage', event);
};
});
this.wrtc.setCallback('onnegotiationneeded', (event) => {
debug("Handling negotiation needed event.");
this.wrtc.createOffer()
.then((offer) => {
debug("Negotiation offer created: " + JSON.stringify(offer));
return this.wrtc.setLocalDescription(offer);
})
.catch((err) => {
debug("Error while negotiating: " + err);
});
});
return this.unifi.getSDPOffer(this.mac, this.uuid, this.site);
})
.then((data) => {
Expand All @@ -159,12 +171,15 @@ SSHSession.prototype.connect = function(connectTimeout, closeCallBack) {
});
})
.then((data) => {
debug("Remote description was set: " + JSON.stringify(data) + "; creating answer");
return this.wrtc.createAnswer(data);
})
.then((data) => {
debug("Answer was created: " + JSON.stringify(data) + "; setting local description");
return this.wrtc.setLocalDescription(data);
})
.then((sdpData) => {
debug("Local description was set: " + JSON.stringify(sdpData) + "; collecting ICE candidates");
return this.wrtc.collectIceCandidates(sdpData);
})
.then((data) => {
Expand All @@ -180,13 +195,16 @@ SSHSession.prototype.connect = function(connectTimeout, closeCallBack) {
return x > y;
}).shift();
let ip = line.match(/udp\s+\d+\s+(\S+)\s/)[1];
debug("Executing ssh-sdp-answer with sdp=" + sdp);
return this.unifi.sshSDPAnswer(this.mac, this.uuid, /*sdp.replace("c=IN IP4 0.0.0.0", "c=IN IP4 " + ip) */ sdp, this.site);
})
// .then((data) => {
// return this.wrtc.openDataChannel('ssh');
// })
.then((data) => {
debug('Channel is supposed to be open now. Lets wait');
debug('ssh-sdp-answer is completed with response: ' + JSON.stringify(data) + '; openning data channel');
return this.wrtc.openDataChannel('ssh');
})
.then((data) => {
debug('Channel is supposed to be open now. Lets wait: ' + JSON.stringify(data));
debug('Set timeout: ' + (connectTimeout || this.connectTimeout || 15000));
timeoutChannel = setTimeout(() => {
debug('Timeout has passed without response, the channel is not open');
this.unifi.closeSSHSession(this.mac, this.uuid, this.site)
Expand Down
17 changes: 14 additions & 3 deletions lib/webrtc-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class WRTC {
this._q = {};
this._channel = {};
this.log = require('debug')(this.debugName || 'WRTCRequest');
this.log.log = console.log.bind(console);
if (this.debug) this.log.enabled = true;
if (this.webrtc && this.webrtc.on) {
this.webrtc.on('error', error => {
Expand Down Expand Up @@ -124,13 +125,18 @@ class WRTC {
}
this.log('WEBRTC_SET_REMOTEDESC', desc);
let w = new this.webrtc.RTCSessionDescription(desc);

wait(this.waiter).then(() => {
this.peer.setRemoteDescription(
w,
(data) => { // Create Answer
resolve(data /*|| desc*/ );
this.log('received answer from setting remote description: ' + JSON.stringify(data));
resolve(data || desc); // data is always null
},
reject
(err) => {
this.log('error while trying to set remote description: ' + err);
reject(err);
}
);
});
});
Expand Down Expand Up @@ -186,6 +192,11 @@ class WRTC {
this.log('Candidate is empty, terminate the gathering');
data.sdp = sdp;
return resolve(data);
}
if (candidate.candidate.type === 'relay') {
this.log('Candidate type is relay, terminate the gathering');
data.sdp = sdp;
return resolve(data);
} // TODO: implement reject
if (candidate && candidate.candidate) {
let cand = candidate.candidate;
Expand Down Expand Up @@ -448,4 +459,4 @@ class WRTC {
}
}

module.exports = WRTC;
module.exports = WRTC;