diff --git a/core/modules/commands/pipe.js b/core/modules/commands/pipe.js index 90f48250e7..a58046f926 100644 --- a/core/modules/commands/pipe.js +++ b/core/modules/commands/pipe.js @@ -48,6 +48,8 @@ Command.prototype.execute = function() { return this.pipeExternalTask(pipeInfo,options); case "socket": return this.pipeSocket(pipeInfo,options); + case "socket-erlang": + return this.pipeSocketErlang(pipeInfo,options); default: return "Invalid pipe specifier '" + name + "'" } @@ -130,6 +132,55 @@ Command.prototype.pipeSocket = function(pipeInfo,options) { return null; }; +Command.prototype.pipeSocketErlang = function(pipeInfo,options) { + var self = this, + net = require("net"), + socket = new net.Socket(), + accumulator = Buffer.alloc(0); + socket.connect(pipeInfo.port,pipeInfo.host || 8081,function() { + self.log("Socket connection",pipeInfo.port,pipeInfo.host); + var lengthBytes = Buffer.alloc(4); + lengthBytes.writeUInt32BE(options.data.length,0) +console.log("Wring butes",options.data.length) + socket.write(lengthBytes); + var typeByte = Buffer.alloc(1); + typeByte.writeUInt8(1,0); + socket.write(typeByte); + socket.write(options.data); + }); + socket.on("error",function(e) { + self.log("Socket error",e) + }); + socket.on("data",function(data) { +console.log("Received data",data.length) + accumulator = Buffer.concat([accumulator,data]); + while(accumulator.length > 5) { + var length = accumulator.readInt32BE(0), + type = accumulator.readUInt8(4); + if(accumulator.length > (length + 5)) { + var data = accumulator.toString("utf8",5,length + 5); +console.log("Got message",length,type) + self.processIncomingData(data,pipeInfo); + accumulator = accumulator.slice(length + 5); +socket.end(); +return self.callback(null); + } else { + break; + } + } + }); + socket.on("end",function() { + self.log("Socket end"); + socket.destroy(); + }); + // Add a "close" event handler for the client socket + socket.on("close",function() { + self.log("Socket closed"); + return self.callback(null); + }); + return null; +}; + Command.prototype.composeOutgoingData = function(filter,pipeInfo) { var self = this, pipeInfoInput = pipeInfo.input || {}, diff --git a/editions/externalpipesdemo/demo-tasks/recaser.js b/editions/externalpipesdemo/demo-tasks/recaser.js new file mode 100755 index 0000000000..cdfdbebf1b --- /dev/null +++ b/editions/externalpipesdemo/demo-tasks/recaser.js @@ -0,0 +1,73 @@ +#!/usr/bin/env node + +/* +A socket server that listens on a host/port for connections and reverses the case of incoming text + + recaser.js + +This utility is provided as an example of using an external task that doesn't have any prior knowledge of +TiddlyWiki. Like many Unix utilities, it just reads and writes to a socket. + +*/ + +var net = require("net"), + port = parseInt(process.argv[2] || "",10) || 8081, // Port + host = process.argv[3] || "127.0.0.1"; // Host + +var server = net.createServer(); + +server.listen(port,host); + +server.on("connection", function(sock) { + console.log("CONNECTED: " + sock.remoteAddress +":"+ sock.remotePort); + // Trap errors + sock.on("error",function(e) { + console.log("ERROR: " + e); + }); + // Read data until the end + var accumulator = Buffer.alloc(0); + sock.on("data",function(data) { + console.log("DATA " + sock.remoteAddress + ": " + data.length); + accumulator = Buffer.concat([accumulator,Buffer.from(data)]); + while(accumulator.length > 5) { + var length = accumulator.readInt32BE(0), + type = accumulator.readUInt8(4); + if(accumulator.length > (length + 5)) { + var data = accumulator.toString("utf8",5,length + 5); + accumulator = accumulator.slice(length + 5); + // Recase it +console.log("MESSAGE",length,type); + var recasedData = recase(data); + // Send it back + var lengthBytes = Buffer.alloc(4); + lengthBytes.writeUInt32BE(recasedData.length,0) +console.log("RESPONSE",1,recasedData.length) + sock.write(lengthBytes); + var typeByte = Buffer.alloc(1); + typeByte.writeUInt8(1,0); + sock.write(typeByte); + sock.write(recasedData); + } else { + break; + } + } + }); + sock.on("end",function() { + console.log("END") + sock.end(); + }); + sock.on("close", function(data) { + console.log("CLOSED: " + sock.remoteAddress +" "+ sock.remotePort); + }); +}); + +function recase(str) { + return str.split("").map(function(char) { + if(char >= "A" && char <= "Z") { + return char.toLowerCase(); + } else { + return char.toUpperCase(); + } + }).join(""); +} + diff --git a/editions/externalpipesdemo/tiddlywiki.info b/editions/externalpipesdemo/tiddlywiki.info index 7e065d941d..dc55fe1855 100644 --- a/editions/externalpipesdemo/tiddlywiki.info +++ b/editions/externalpipesdemo/tiddlywiki.info @@ -7,6 +7,10 @@ "tiddlywiki/vanilla", "tiddlywiki/snowwhite" ], + "build": { + "index": [ + "--rendertiddler","$:/core/save/all","index.html","text/plain"] + }, "config": { "allow-remote-commands": true }, @@ -70,6 +74,25 @@ "MY_VARIABLE": "value" }, "timeout": 100 + }, + "recaser": { + "type": "socket-erlang", + "host": "127.0.0.1", + "port": 8081, + "input": { + "format": "rendered-text" + }, + "output": { + "format": "text", + "tiddler": { + "title": "PipeOutput", + "type": "text/plain" + } + }, + "environment": { + "MY_VARIABLE": "value" + }, + "timeout": 100 } } }