Files
ComfyUI_frontend/src/nodes/network.js
amfl d134ab73f0 bugfix: Websocket checks parsed payload data
We parse the JSON payload, but then it wasn't being referred to when we
were checking the data type, which could lead to looking at the `type`
attribute of a string.
2020-01-14 14:31:34 +13:00

366 lines
11 KiB
JavaScript

//event related nodes
(function(global) {
var LiteGraph = global.LiteGraph;
function LGWebSocket() {
this.size = [60, 20];
this.addInput("send", LiteGraph.ACTION);
this.addOutput("received", LiteGraph.EVENT);
this.addInput("in", 0);
this.addOutput("out", 0);
this.properties = {
url: "",
room: "lgraph", //allows to filter messages,
only_send_changes: true
};
this._ws = null;
this._last_sent_data = [];
this._last_received_data = [];
}
LGWebSocket.title = "WebSocket";
LGWebSocket.desc = "Send data through a websocket";
LGWebSocket.prototype.onPropertyChanged = function(name, value) {
if (name == "url") {
this.connectSocket();
}
};
LGWebSocket.prototype.onExecute = function() {
if (!this._ws && this.properties.url) {
this.connectSocket();
}
if (!this._ws || this._ws.readyState != WebSocket.OPEN) {
return;
}
var room = this.properties.room;
var only_changes = this.properties.only_send_changes;
for (var i = 1; i < this.inputs.length; ++i) {
var data = this.getInputData(i);
if (data == null) {
continue;
}
var json;
try {
json = JSON.stringify({
type: 0,
room: room,
channel: i,
data: data
});
} catch (err) {
continue;
}
if (only_changes && this._last_sent_data[i] == json) {
continue;
}
this._last_sent_data[i] = json;
this._ws.send(json);
}
for (var i = 1; i < this.outputs.length; ++i) {
this.setOutputData(i, this._last_received_data[i]);
}
if (this.boxcolor == "#AFA") {
this.boxcolor = "#6C6";
}
};
LGWebSocket.prototype.connectSocket = function() {
var that = this;
var url = this.properties.url;
if (url.substr(0, 2) != "ws") {
url = "ws://" + url;
}
this._ws = new WebSocket(url);
this._ws.onopen = function() {
console.log("ready");
that.boxcolor = "#6C6";
};
this._ws.onmessage = function(e) {
that.boxcolor = "#AFA";
var data = JSON.parse(e.data);
if (data.room && data.room != that.properties.room) {
return;
}
if (data.type == 1) {
if (
data.data.object_class &&
LiteGraph[data.data.object_class]
) {
var obj = null;
try {
obj = new LiteGraph[data.data.object_class](data.data);
that.triggerSlot(0, obj);
} catch (err) {
return;
}
} else {
that.triggerSlot(0, data.data);
}
} else {
that._last_received_data[data.channel || 0] = data.data;
}
};
this._ws.onerror = function(e) {
console.log("couldnt connect to websocket");
that.boxcolor = "#E88";
};
this._ws.onclose = function(e) {
console.log("connection closed");
that.boxcolor = "#000";
};
};
LGWebSocket.prototype.send = function(data) {
if (!this._ws || this._ws.readyState != WebSocket.OPEN) {
return;
}
this._ws.send(JSON.stringify({ type: 1, msg: data }));
};
LGWebSocket.prototype.onAction = function(action, param) {
if (!this._ws || this._ws.readyState != WebSocket.OPEN) {
return;
}
this._ws.send({
type: 1,
room: this.properties.room,
action: action,
data: param
});
};
LGWebSocket.prototype.onGetInputs = function() {
return [["in", 0]];
};
LGWebSocket.prototype.onGetOutputs = function() {
return [["out", 0]];
};
LiteGraph.registerNodeType("network/websocket", LGWebSocket);
//It is like a websocket but using the SillyServer.js server that bounces packets back to all clients connected:
//For more information: https://github.com/jagenjo/SillyServer.js
function LGSillyClient() {
//this.size = [60,20];
this.room_widget = this.addWidget(
"text",
"Room",
"lgraph",
this.setRoom.bind(this)
);
this.addWidget(
"button",
"Reconnect",
null,
this.connectSocket.bind(this)
);
this.addInput("send", LiteGraph.ACTION);
this.addOutput("received", LiteGraph.EVENT);
this.addInput("in", 0);
this.addOutput("out", 0);
this.properties = {
url: "tamats.com:55000",
room: "lgraph",
only_send_changes: true
};
this._server = null;
this.connectSocket();
this._last_sent_data = [];
this._last_received_data = [];
if(typeof(SillyClient) == "undefined")
console.warn("remember to add SillyClient.js to your project: https://tamats.com/projects/sillyserver/src/sillyclient.js");
}
LGSillyClient.title = "SillyClient";
LGSillyClient.desc = "Connects to SillyServer to broadcast messages";
LGSillyClient.prototype.onPropertyChanged = function(name, value) {
if (name == "room") {
this.room_widget.value = value;
}
this.connectSocket();
};
LGSillyClient.prototype.setRoom = function(room_name) {
this.properties.room = room_name;
this.room_widget.value = room_name;
this.connectSocket();
};
//force label names
LGSillyClient.prototype.onDrawForeground = function() {
for (var i = 1; i < this.inputs.length; ++i) {
var slot = this.inputs[i];
slot.label = "in_" + i;
}
for (var i = 1; i < this.outputs.length; ++i) {
var slot = this.outputs[i];
slot.label = "out_" + i;
}
};
LGSillyClient.prototype.onExecute = function() {
if (!this._server || !this._server.is_connected) {
return;
}
var only_send_changes = this.properties.only_send_changes;
for (var i = 1; i < this.inputs.length; ++i) {
var data = this.getInputData(i);
var prev_data = this._last_sent_data[i];
if (data != null) {
if (only_send_changes)
{
var is_equal = true;
if( data && data.length && prev_data && prev_data.length == data.length && data.constructor !== String)
{
for(var j = 0; j < data.length; ++j)
if( prev_data[j] != data[j] )
{
is_equal = false;
break;
}
}
else if(this._last_sent_data[i] != data)
is_equal = false;
if(is_equal)
continue;
}
this._server.sendMessage({ type: 0, channel: i, data: data });
if( data.length && data.constructor !== String )
{
if( this._last_sent_data[i] )
{
this._last_sent_data[i].length = data.length;
for(var j = 0; j < data.length; ++j)
this._last_sent_data[i][j] = data[j];
}
else //create
{
if(data.constructor === Array)
this._last_sent_data[i] = data.concat();
else
this._last_sent_data[i] = new data.constructor( data );
}
}
else
this._last_sent_data[i] = data; //should be cloned
}
}
for (var i = 1; i < this.outputs.length; ++i) {
this.setOutputData(i, this._last_received_data[i]);
}
if (this.boxcolor == "#AFA") {
this.boxcolor = "#6C6";
}
};
LGSillyClient.prototype.connectSocket = function() {
var that = this;
if (typeof SillyClient == "undefined") {
if (!this._error) {
console.error(
"SillyClient node cannot be used, you must include SillyServer.js"
);
}
this._error = true;
return;
}
this._server = new SillyClient();
this._server.on_ready = function() {
console.log("ready");
that.boxcolor = "#6C6";
};
this._server.on_message = function(id, msg) {
var data = null;
try {
data = JSON.parse(msg);
} catch (err) {
return;
}
if (data.type == 1) {
//EVENT slot
if (
data.data.object_class &&
LiteGraph[data.data.object_class]
) {
var obj = null;
try {
obj = new LiteGraph[data.data.object_class](data.data);
that.triggerSlot(0, obj);
} catch (err) {
return;
}
} else {
that.triggerSlot(0, data.data);
}
} //for FLOW slots
else {
that._last_received_data[data.channel || 0] = data.data;
}
that.boxcolor = "#AFA";
};
this._server.on_error = function(e) {
console.log("couldnt connect to websocket");
that.boxcolor = "#E88";
};
this._server.on_close = function(e) {
console.log("connection closed");
that.boxcolor = "#000";
};
if (this.properties.url && this.properties.room) {
try {
this._server.connect(this.properties.url, this.properties.room);
} catch (err) {
console.error("SillyServer error: " + err);
this._server = null;
return;
}
this._final_url = this.properties.url + "/" + this.properties.room;
}
};
LGSillyClient.prototype.send = function(data) {
if (!this._server || !this._server.is_connected) {
return;
}
this._server.sendMessage({ type: 1, data: data });
};
LGSillyClient.prototype.onAction = function(action, param) {
if (!this._server || !this._server.is_connected) {
return;
}
this._server.sendMessage({ type: 1, action: action, data: param });
};
LGSillyClient.prototype.onGetInputs = function() {
return [["in", 0]];
};
LGSillyClient.prototype.onGetOutputs = function() {
return [["out", 0]];
};
LiteGraph.registerNodeType("network/sillyclient", LGSillyClient);
})(this);