|
|
|
var stream = require('stream');
|
|
|
|
|
|
|
|
|
|
|
|
function WebSocks(wsurl)
|
|
|
|
{
|
|
|
|
this._wsurl = wsurl;
|
|
|
|
this._ws = null;
|
|
|
|
this._ouraddr = null;
|
|
|
|
this._remoteAddr = null;
|
|
|
|
this._recvbuffer = stream.PassThrough();
|
|
|
|
this._sendbuffer = stream.PassThrough();
|
|
|
|
}
|
|
|
|
|
|
|
|
WebSocks.prototype.createListener = function(callback) {
|
|
|
|
var self = this;
|
|
|
|
self._doAccept(function(err) {
|
|
|
|
if(err) callback(err, null);
|
|
|
|
else {
|
|
|
|
callback(null, self._sendbuffer, self._recvbuffer);
|
|
|
|
}
|
|
|
|
}, function(data) {
|
|
|
|
self._recvbuffer.write(data);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
WebSocks.prototype._doAccept = function(accept_cb, recv_cb) {
|
|
|
|
var self = this;
|
|
|
|
self._socket(function (err, data) {
|
|
|
|
if(!self._remoteAddr)
|
|
|
|
{
|
|
|
|
if(!data)
|
|
|
|
{
|
|
|
|
// send handshake
|
|
|
|
self._ws.send("accept");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// this means handshake read
|
|
|
|
var j = JSON.parse(data);
|
|
|
|
if(j.error) {
|
|
|
|
connect_cb(j.error);
|
|
|
|
} else if(j.success){
|
|
|
|
self._remoteAddr = host;
|
|
|
|
connect_cb(null);
|
|
|
|
}
|
|
|
|
// repeat
|
|
|
|
setTimeout(function() {
|
|
|
|
self._doAccept(connect_cb);
|
|
|
|
}, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
recv_cb(err, data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
WebSocks.prototype._closed = function()
|
|
|
|
{
|
|
|
|
var self = this;
|
|
|
|
self._recvbuffer.close();
|
|
|
|
self._sendbuffer.close();
|
|
|
|
self._ws.close();
|
|
|
|
};
|
|
|
|
|
|
|
|
WebSocks.prototype.connect = function(host, port, connect_cb) {
|
|
|
|
var self = this;
|
|
|
|
self._socket(function (err, data) {
|
|
|
|
if(!self._remoteAddr)
|
|
|
|
{
|
|
|
|
if(!data)
|
|
|
|
{
|
|
|
|
// send handshake
|
|
|
|
self._ws.send("connect "+host+":"+port);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// this means handshake read
|
|
|
|
var j = JSON.parse(data);
|
|
|
|
if(j.error) {
|
|
|
|
connect_cb(j.error, null, null);
|
|
|
|
} else if(j.success){
|
|
|
|
self._remoteAddr = host;
|
|
|
|
connect_cb(null, self._sendbuffer, self._recvbuffer);
|
|
|
|
} else {
|
|
|
|
connect_cb("failed to connect", null, null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
self._recvbuffer.write(data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
WebSocks.prototype._socket = function(cb) {
|
|
|
|
var self = this;
|
|
|
|
self._ws = new WebSocket(self._wsurl);
|
|
|
|
self._ws.onclose = function(ev) {
|
|
|
|
self._closed();
|
|
|
|
};
|
|
|
|
|
|
|
|
self._ws.onopen = function(ev) {
|
|
|
|
console.log("connected to websocks");
|
|
|
|
self._ws.send("getaddr");
|
|
|
|
};
|
|
|
|
|
|
|
|
self._ws.onmessage = function(ev) {
|
|
|
|
if(!self._ouraddr)
|
|
|
|
{
|
|
|
|
var j = JSON.parse(ev.data);
|
|
|
|
if(j.error) {
|
|
|
|
console.log("connect error: "+j.error);
|
|
|
|
cb(j.error, null);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(j.success && j.destination) {
|
|
|
|
self._ouraddr = j.destination;
|
|
|
|
} else {
|
|
|
|
cb("failed to connect", null);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
self._sendbuffer.on("data", function(data) {
|
|
|
|
self._ws.send(data);
|
|
|
|
});
|
|
|
|
cb(null, null);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cb(null, ev.data);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
"WebSocks": WebSocks,
|
|
|
|
};
|