websocket + router + filesytem_service

remixd
yann300 8 years ago
parent 597bdda80c
commit 4f38c81e2d
  1. 2
      .gitignore
  2. 21
      package.json
  3. 16
      src/main.js
  4. 28
      src/router.js
  5. 87
      src/services/sharedFolder.js
  6. 3
      src/servicesList.js
  7. 59
      src/utils.js
  8. 62
      src/websocket.js

2
.gitignore vendored

@ -0,0 +1,2 @@
node_modules
npm-debug.log

@ -1,10 +1,11 @@
{
"name": "remixd",
"version": "0.0.1",
"version": "0.0.9",
"description": "remix server",
"main": "index.js",
"main": "./src/main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node ./src/main.js"
},
"repository": {
"type": "git",
@ -16,10 +17,20 @@
"ethereum",
"solidity"
],
"author": "",
"author": "cpp ethereum team",
"license": "MIT",
"bugs": {
"url": "https://github.com/ethereum/remixd/issues"
},
"homepage": "https://github.com/ethereum/remixd#readme"
"homepage": "https://github.com/ethereum/remixd#readme",
"dependencies": {
"commander": "^2.9.0",
"fs-extra": "^3.0.1",
"isbinaryfile": "^3.0.2",
"watch": "^1.0.2",
"websocket": "^1.0.24"
},
"bin": {
"remixd": "./src/main.js"
}
}

@ -0,0 +1,16 @@
#!/usr/bin/env node
var Router = require('./router')
var program = require('commander')
program
.usage('remix -S <shared folder>')
.description('Provide a two ways connection between the local computer and Remix IDE')
.option('-S, --shared-folder <path>', 'Folder to share with Remix IDE')
.parse(process.argv)
if (!program.sharedFolder) {
program.outputHelp()
process.exit(1)
}
var router = new Router()
router.start(program.sharedFolder)

@ -0,0 +1,28 @@
var servicesList = require('./servicesList')
var Websocket = require('./websocket')
class Router {
start (sharedFolder) {
this.websocket = new Websocket()
this.websocket.start((message) => {
this.call(message.id, message.service, message.fn, message.args)
})
servicesList['sharedfolder'].setupNotifications(this.websocket, sharedFolder)
servicesList['sharedfolder'].sharedFolder(sharedFolder)
}
call (callid, name, fn, args) {
servicesList[name][fn](args, (error, data) => {
var response = {
id: callid,
type: 'reply',
scope: name,
result: data,
error: error
}
this.websocket.send(JSON.stringify(response))
})
}
}
module.exports = Router

@ -0,0 +1,87 @@
var utils = require('../utils')
var isbinaryfile = require('isbinaryfile')
var fs = require('fs-extra')
var watch = require('watch')
module.exports = {
monitors: [],
trackDownStreamUpdate: {},
sharedFolder: function (sharedFolder) {
this.sharedFolder = sharedFolder
},
list: function (args, cb) {
cb(null, utils.walkSync(this.sharedFolder, {}, this.sharedFolder))
},
get: function (args, cb) {
var path = utils.absolutePath(args.path, this.sharedFolder)
isbinaryfile(path, (error, isBinary) => {
if (error) console.log(error)
if (isBinary) {
cb(null, '<binary content not displayed>')
} else {
fs.readFile(path, 'utf8', (error, data) => {
if (error) console.log(error)
cb(error, data)
})
}
})
},
set: function (args, cb) {
var path = utils.absolutePath(args.path, this.sharedFolder)
this.trackDownStreamUpdate[path] = path
fs.writeFile(path, args.content, 'utf8', (error, data) => {
if (error) console.log(error)
cb(error, data)
})
},
rename: function (args, cb) {
var oldpath = utils.absolutePath(args.oldPath, this.sharedFolder)
var newpath = utils.absolutePath(args.newPath, this.sharedFolder)
fs.move(oldpath, newpath, (error, data) => {
if (error) console.log(error)
cb(error, data)
})
},
remove: function (args, cb) {
var path = utils.absolutePath(args.path, this.sharedFolder)
fs.remove(path, (error, data) => {
if (error) console.log(error)
cb(error, data)
})
},
setupNotifications: function (websocket, path) {
watch.createMonitor(path, (monitor) => {
this.monitors.push(monitor)
monitor.on('created', (f, stat) => {
isbinaryfile(f, (error, isBinary) => {
if (error) console.log(error)
if (stat.isDirectory()) {
this.setupNotifications(websocket, f)
}
if (websocket.connection) websocket.send(message('created', { path: utils.relativePath(f, this.sharedFolder), isReadOnly: isBinary, isFolder: stat.isDirectory() }))
})
})
monitor.on('changed', (f, curr, prev) => {
if (this.trackDownStreamUpdate[f]) {
delete this.trackDownStreamUpdate[f]
return
}
if (websocket.connection) websocket.send(message('changed', utils.relativePath(f, this.sharedFolder)))
})
monitor.on('removed', (f, stat) => {
if (websocket.connection) websocket.send(message('removed', { path: utils.relativePath(f, this.sharedFolder), isFolder: stat.isDirectory() }))
})
})
}
}
function message (name, value) {
return JSON.stringify({type: 'notification', scope: 'sharedfolder', name: name, value: value})
}

@ -0,0 +1,3 @@
module.exports = {
sharedfolder: require('./services/sharedFolder')
}

@ -0,0 +1,59 @@
var fs = require('fs-extra')
var path = require('path')
var isbinaryfile = require('isbinaryfile')
var pathModule = require('path')
module.exports = {
absolutePath: absolutePath,
relativePath: relativePath,
walkSync: walkSync
}
/**
* returns the absolute path of the given @arg path
*
* @param {String} path - relative path (Unix style which is the one used by Remix IDE)
* @param {String} sharedFolder - absolute shared path. platform dependent representation.
* @return {String} platform dependent absolute path (/home/user1/.../... for unix, c:\user\...\... for windows)
*/
function absolutePath (path, sharedFolder) {
path = normalizePath(path)
if (path.indexOf(sharedFolder) !== 0) {
path = pathModule.resolve(sharedFolder, path)
}
return path
}
/**
* return the relative path of the given @arg path
*
* @param {String} path - absolute platform dependent path
* @param {String} sharedFolder - absolute shared path. platform dependent representation
* @return {String} relative path (Unix style which is the one used by Remix IDE)
*/
function relativePath (path, sharedFolder) {
var relative = pathModule.relative(sharedFolder, path)
return normalizePath(relative)
}
function normalizePath (path) {
if (process.platform === 'win32') {
return path.replace(/\\/g, '/')
}
return path
}
function walkSync (dir, filelist, sharedFolder) {
var files = fs.readdirSync(dir)
filelist = filelist || {}
files.forEach(function (file) {
var subElement = path.join(dir, file)
if (fs.statSync(subElement).isDirectory()) {
filelist = walkSync(subElement, filelist, sharedFolder)
} else {
var relative = relativePath(subElement, sharedFolder)
filelist[relative] = isbinaryfile.sync(subElement)
}
})
return filelist
}

@ -0,0 +1,62 @@
#!/usr/bin/env node
var WebSocketServer = require('websocket').server
var http = require('http')
class WebSocket {
constructor () {
this.connection = null
}
start (callback) {
var server = http.createServer(function (request, response) {
console.log((new Date()) + ' Received request for ' + request.url)
response.writeHead(404)
response.end()
})
server.listen(65520, function () {
console.log((new Date()) + ' Remixd is listening on port 65520')
})
this.wsServer = new WebSocketServer({
httpServer: server,
autoAcceptConnections: false
})
this.wsServer.on('request', (request) => {
if (!originIsAllowed(request.origin)) {
request.reject()
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.')
return
}
if (this.connection) {
console.log('closing previous connection')
this.wsServer.closeAllConnections()
this.connection = null
return
}
this.connection = request.accept('echo-protocol', request.origin)
console.log((new Date()) + ' Connection accepted.')
this.connection.on('message', (message) => {
if (message.type === 'utf8') {
callback(JSON.parse(message.utf8Data))
}
})
this.connection.on('close', (reasonCode, description) => {
console.log((new Date()) + ' Remix ' + this.connection.remoteAddress + ' disconnected.')
this.connection = null
})
})
}
send (data) {
this.connection.sendUTF(data)
}
}
function originIsAllowed (origin) {
console.log('origin', origin)
return true
}
module.exports = WebSocket
Loading…
Cancel
Save