bitmessage-js/lib/net/ws.browser.js

126 lines
3.1 KiB
JavaScript
Raw Normal View History

2015-02-03 21:13:27 +01:00
/**
2015-02-09 22:56:55 +01:00
* WebSocket transport. Used in browser in client-mode only. Server
* handle incoming messages and wrap them into TCP data packets.
2015-02-03 21:13:27 +01:00
*/
"use strict";
2015-02-09 22:56:55 +01:00
var objectAssign = Object.assign || require("object-assign");
2015-02-03 21:13:27 +01:00
var inherits = require("inherits");
var assert = require("../_util").assert;
2015-02-09 22:56:55 +01:00
var structs = require("../structs");
var messages = require("../messages");
2015-02-06 10:47:40 +01:00
var BaseTransport = require("./base");
2015-02-03 21:13:27 +01:00
var ServicesBitfield = structs.ServicesBitfield;
var getmsg = BaseTransport._getmsg;
2015-02-10 13:57:55 +01:00
function WsTransport(opts) {
WsTransport.super_.call(this);
2015-02-09 22:56:55 +01:00
objectAssign(this, opts);
this.seeds = this.seeds || [];
this.services = this.services || ServicesBitfield().set([
ServicesBitfield.NODE_MOBILE,
]);
this.streams = this.streams || [1];
2015-02-03 21:13:27 +01:00
}
2015-02-10 13:57:55 +01:00
inherits(WsTransport, BaseTransport);
2015-02-03 21:13:27 +01:00
2015-02-10 13:57:55 +01:00
WsTransport.prototype.bootstrap = function() {
2015-02-09 22:56:55 +01:00
return Promise.resolve([].concat(this.seeds));
};
2015-02-10 13:57:55 +01:00
WsTransport.prototype.connect = function(url, protocols) {
2015-02-09 22:56:55 +01:00
var self = this;
assert(!self._client, "Already connected");
// TODO(Kagami): Handle timeouts!
var client = self._client = new WebSocket(url, protocols);
client.binaryType = "arraybuffer";
var verackSent = false;
var verackReceived = false;
var established = false;
client.onopen = function() {
self.emit("open");
self.send(messages.version.encode({
services: self.services,
userAgent: self.userAgent,
streams: self.streams,
2015-02-14 16:11:18 +01:00
// This parameters aren't used by the remote node so we fake them
// (because we can't resolve domain name in a Browser).
2015-02-09 22:56:55 +01:00
remoteHost: "127.0.0.1",
remotePort: 8444,
}));
};
client.onmessage = function(e) {
var buf = new Buffer(new Uint8Array(e.data));
var decoded;
try {
decoded = structs.message.decode(buf);
} catch (err) {
return self.emit("warning", new Error(
2015-02-24 09:47:56 +01:00
"Message decoding error: " + err.message
2015-02-09 22:56:55 +01:00
));
}
self.emit("message", decoded.command, decoded.payload, decoded);
};
// High-level message processing.
self.on("message", function(command, payload) {
var version;
2015-02-09 22:56:55 +01:00
if (!established) {
if (command === "version") {
if (verackSent) {
return;
}
try {
2015-02-24 09:47:56 +01:00
version = self._decodeVersion(payload, {gateway: true});
} catch(err) {
self.emit("error", err);
return client.close();
}
2015-02-09 22:56:55 +01:00
self.send("verack");
verackSent = true;
if (verackReceived) {
established = true;
self.emit("established", version);
2015-02-09 22:56:55 +01:00
}
} else if (command === "verack") {
verackReceived = true;
if (verackSent) {
established = true;
self.emit("established", version);
2015-02-09 22:56:55 +01:00
}
}
}
});
client.onerror = function(err) {
self.emit("error", err);
};
client.onclose = function() {
self.emit("close");
delete self._client;
};
};
2015-02-10 13:57:55 +01:00
WsTransport.prototype.send = function() {
2015-02-09 22:56:55 +01:00
if (this._client) {
this._client.send(getmsg(arguments));
2015-02-09 22:56:55 +01:00
} else {
throw new Error("Not connected");
}
};
2015-02-10 13:57:55 +01:00
WsTransport.prototype.close = function() {
2015-02-09 22:56:55 +01:00
if (this._client) {
this._client.close();
}
2015-02-03 21:13:27 +01:00
};
2015-02-10 13:57:55 +01:00
module.exports = WsTransport;