123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833 |
- /* This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
- * Copyright 2011 by the AToMPM team and licensed under the LGPL
- * See COPYING.lesser and README.md in the root of this project for full details
- */
- /*********************************** IMPORTS **********************************/
- var _util = require("util"),
- _fs = require('fs'),
- _http = require('http'),
- _path = require('path'),
- _url = require('url'),
- _utils = require('./utils'),
- _sio = require('socket.io'),
- _cp = require('child_process'),
- _fspp = require('./___fs++'),
- _duri = require('./___dataurize');
- /*********************************** GLOBALS **********************************/
- /* an array of WebWorkers
- ... each has its own mmmk instance */
- var workers = new Array();
- /* an array of response objects
- ... for workers to write on when they complete requests */
- var responses = new Array();
- /* a map of worker ids to socket.io socket session ids
- ... each socket is registered to exactly one worker
- ... several sockets may be registered to the same worker */
- var workerIds2socketIds = {};
- /************************************ UTILS ***********************************/
- /** Remove invalid characters from a string. **/
- function __clean_string(s)
- {
- if (s == undefined) {
- return s;
- }
- s = JSON.stringify(s);
- s = s.replace(/'/g, '');
- s = s.replace(/"/g, '');
- s = s.replace(/‘/g, '');
- s = s.replace(/’/g, '');
- s = s.replace(/\\/g, '\\');
- s = s.replace(/\//g, '\/');
- s = s.replace(/\\n/g, ' ');
- return s;
- }
- /** Syntactic sugar to build and send HTTP responses **/
- function __respond(response, statusCode, reason, data, headers)
- {
- response.writeHead(
- statusCode,
- __clean_string(reason),
- (headers || {'Content-Type': 'text/plain',
- 'Access-Control-Allow-Origin': '*'}));
- var encoding =
- (headers &&
- (headers['Content-Type'].match(/image/) ||
- headers['Content-Type'].match(/pdf/) ||
- headers['Content-Type'].match(/zip/) ) ?
- 'binary' :
- 'utf8'),
- content = reason || data;
- if( _utils.isObject(content) )
- response.end(_utils.jsons(content,null,'\t'), encoding);
- else
- response.end(content, encoding);
- }
- /** Syntactic sugar to build and send a socket.io message **/
- function __send(socket, statusCode, reason, data, headers)
- {
- socket.json.emit('message',
- {'statusCode':statusCode,
- 'reason':reason,
- 'headers':(headers || {'Content-Type': 'text/plain',
- 'Access-Control-Allow-Origin': '*'}),
- 'data':data});
- }
- /************************************ LOGIC ***********************************/
- var httpserver = _http.createServer(
- function(req, resp)
- {
- var url = _url.parse(req.url,true);
- url.pathname = decodeURI(url.pathname);
- /* serve client */
- if( req.method == 'GET' && url.pathname == '/atompm' )
- _fs.readFile('./client/atompm.html', 'utf8',
- function(err, data)
- {
- if(err)
- __respond(resp,500,String(err));
- else
- __respond(resp,200,'',data,{'Content-Type': 'text/html'});
- });
-
- else if( req.method == 'GET' && url.pathname == '/favicon.png' )
- _fs.readFile('./favicon.png', 'binary',
- function(err, data)
- {
- if(err)
- __respond(resp,500,String(err));
- else
- __respond(resp,200,'',data,{'Content-Type': 'image/png'});
- });
- /* provide an interface to the unfortunately unavoidable dataurize
- module which returns data URIs for resources at arbitrary URLs */
- else if( req.method == 'GET' && url.pathname == '/datauri' )
- {
- var target = _url.parse(decodeURI(url['query']['target']));
- _duri.dataurize(
- target,
- function(err,datauri)
- {
- if(err)
- __respond(resp,500,_utils.jsons(err));
- else
- __respond(resp,200,'',datauri);
- });
- }
- /* serve metamodels, buttons models and their icons */
- else if( req.method == 'GET' &&
- (url.pathname.match(/\.metamodel$/) ||
- url.pathname.match(/\.buttons.model$/) ||
- url.pathname.match(/\.icon\.png$/i)) )
- {
- var isIcon = url.pathname.match(/\.icon\.png$/i);
- _fs.readFile('./users/'+url.pathname, (isIcon ? 'binary' : 'utf8'),
- function(err, data)
- {
- if(err)
- __respond(resp,500,String(err));
- else
- {
- var contentType =
- (isIcon ?
- {'Content-Type': 'image/png'} :
- {'Content-Type': 'application/json'});
- __respond(resp,200,'',data,contentType);
- }
- });
- }
- /* serve ordinary files (e.g., js includes, images, css)
- NOTE:: distinguish between atompm images (e.g., grid background,
- filebrowser icons) and CS/Images */
- else if( req.method == 'GET' &&
- (url.pathname.match(/\.html$/) ||
- url.pathname.match(/\.css$/) ||
- url.pathname.match(/\.js$/) ||
- url.pathname.match(/\.pdf$/) ||
- url.pathname.match(/\.png$/i) ||
- url.pathname.match(/\.jpg$/i) ||
- url.pathname.match(/\.jpeg$/i) ||
- url.pathname.match(/\.gif$/i) ||
- url.pathname.match(/\.svg$/i)) )
- {
- var isImage = url.pathname.match(/\.png$/i) ||
- url.pathname.match(/\.jpg$/i) ||
- url.pathname.match(/\.jpeg$/i) ||
- url.pathname.match(/\.gif$/i) ||
- url.pathname.match(/\.svg$/i),
- isText = ! isImage && ! url.pathname.match(/\.pdf$/);
- if( isImage && ! url.pathname.match(/^\/client\/media\//) )
- url.pathname = '/users/'+url.pathname;
- _fs.readFile('.'+url.pathname, (isText ? 'utf8' : 'binary'),
- function(err, data)
- {
- if(err)
- __respond(resp,500,String(err));
- else
- {
- var contentType =
- (url.pathname.match(/\.html$/) ?
- {'Content-Type': 'text/html'} :
- url.pathname.match(/\.css$/) ?
- {'Content-Type': 'text/css'} :
- url.pathname.match(/\.js$/) ?
- {'Content-Type': 'application/javascript'} :
- url.pathname.match(/\.pdf$/) ?
- {'Content-Type': 'application/pdf'} :
- url.pathname.match(/\.png$/i) ?
- {'Content-Type': 'image/png'} :
- url.pathname.match(/\.jpg$/i) ||
- url.pathname.match(/\.jpeg$/i) ?
- {'Content-Type': 'image/jpeg'} :
- url.pathname.match(/\.gif$/i) ?
- {'Content-Type': 'image/gif'} :
- url.pathname.match(/\.svg$/i) ?
- {'Content-Type': 'image/svg+xml'} :
- undefined);
- __respond(resp,200,'',data,contentType);
- }
- });
- }
- /* serve encrypted user password */
- else if( req.method == 'GET' && url.pathname == '/passwd' )
- _fs.readFile('./users/'+url['query']['username']+'/passwd', 'utf8',
- function(err, data)
- {
- if(err)
- __respond(resp,500,String(err));
- else
- __respond(resp,200,'',data,{'Content-Type': 'text/html'});
- });
- /* create new user
- 1. make sure user doesn't already exist
- 2. make a new copy of ./users/(default)
- 3. create password file */
- else if( req.method == 'POST' && url.pathname == '/user' )
- {
- var userdir = './users/'+url['query']['username'];
- _fs.exists(userdir,
- function(exists)
- {
- if( exists )
- {
- __respond(resp,500,'username already exists');
- return;
- }
- _fspp.cp('./users/(default)/',userdir,
- function(err, stdout, stderr)
- {
- if( err )
- {
- __respond(resp,500,String(err));
- return;
- }
-
- _fs.writeFile(
- userdir+'/passwd',
- url['query']['password'],
- function(err)
- {
- if( err )
- __respond(resp,500,String(err));
- else
- __respond(resp,200);
- });
- });
- });
- }
- /* serve [a subset of] user preferences */
- else if( req.method == 'GET' && url.pathname.match(/prefs$/) )
- _fs.readFile('./users/'+url.pathname, 'utf8',
- function(err, data)
- {
- if(err)
- __respond(resp,500,String(err));
- else if( url['query']['subset'] == undefined )
- __respond(resp,200,'',data);
- else
- try
- {
- __respond(
- resp,
- 200,
- '',
- _utils.splitDict(
- _utils.jsonp(data),
- _utils.jsonp(url['query']['subset'])));
- }
- catch(err) {__respond(resp,500,String(err));}
- });
- /* update user preferences
- 1 retrieve all post data
- 2 read prefs file from disk
- 3 apply changes
- 4 write updated prefs to disk */
- else if( req.method == 'PUT' && url.pathname.match(/prefs$/) )
- {
- var reqData = '';
- req.addListener("data", function(chunk) {reqData += chunk;});
- req.addListener("end",
- function()
- {
- _fs.readFile('./users/'+url.pathname, 'utf8',
- function(err, prefs)
- {
- if(err)
- __respond(resp,500,String(err));
- else
- {
- try
- {
- prefs = _utils.jsonp(prefs);
- reqData = _utils.jsonp(reqData);
- }
- catch(err)
- {
- __respond(resp,500,String(err));
- return;
- }
- for( var pref in reqData )
- prefs[pref]['value'] = reqData[pref];
- _fs.writeFile(
- './users/'+url.pathname,
- _utils.jsons(prefs,null,'\t'),
- function(err, data)
- {
- if(err)
- __respond(resp,500,String(err));
- else
- __respond(resp,200);
- });
- }
- });
- });
- }
- /* delete specified file/folder */
- else if( req.method == 'DELETE' && url.pathname.match(/\.(file|folder)$/) )
- {
- if (url.pathname.match('_Trash_')) {
- __respond(resp,500,"cannot remove trash!");
- } else {
- var matches = url.pathname.match(/^\/(.*?)\/(.*\/)?(.*)\.(file|folder)$/),
- username = matches[1],
- folder = matches[2] || '',
- fname = matches[3],
- userdir = './users/'+username+'/',
- ondelete =
- function(err, stdout, stderr)
- {
- if( err )
- __respond(resp,500,String(err));
- else
- __respond(resp,200);
- },
- deletef =
- function(response)
- {
- var newname = userdir+'_Trash_/'+folder+fname;
- if (_fs.existsSync(newname)) {
- if (url.pathname.match(/\.folder$/)) {
- _fspp.deleteFolderRecursive(newname);
- } else {
- _fs.unlink(newname);
- }
- }
- _fspp.mv(userdir+folder+fname,userdir+'_Trash_/'+folder,ondelete);
- };
- _fs.exists(userdir+'_Trash_/'+folder,
- function(exists)
- {
- if( ! exists )
- _fspp.mkdirs(userdir+'_Trash_/'+folder,deletef);
- else {
- deletef();
- }
- });
- }
- }
- /* create folder */
- else if( req.method == 'POST' && url.pathname.match(/\.folder$/) )
- {
- var matches = url.pathname.match(/^\/(.*?)\/(.*)\.folder$/),
- username = matches[1],
- folder = matches[2],
- userdir = './users/'+username+'/',
- oncreate =
- function(err, stdout, stderr)
- {
- if( err )
- __respond(resp,500,String(err));
- else
- __respond(resp,200);
- };
- _fs.exists(userdir+folder,
- function(exists)
- {
- if( ! exists )
- _fspp.mkdirs(userdir+folder,oncreate);
- else {
- oncreate("folder " + folder + " already exists");
- }
- });
- }
- /* rename file/folder (or move) */
- else if( req.method == 'PUT' && url.pathname.match(/\.(folder|file)$/) )
- {
- req.setEncoding('utf8');
- var data = '';
- req.addListener("data", function(chunk) {data += chunk;});
- req.addListener("end",
- function() {
- data = _utils.jsonp(data);
- if (data.match(/^\//)) {
- // move
- var matches = url.pathname.match(/^\/(.*?)\/(.*\/)?(.*)\.(file|folder)$/),
- username = matches[1],
- folder = matches[2] || '',
- fname = matches[3],
- userdir = './users/'+username,
- onmove =
- function(err, stdout, stderr)
- {
- if( err )
- __respond(resp,500,String(err));
- else
- __respond(resp,200);
- };
- if (_fs.existsSync(userdir+data+fname)) {
- if (url.pathname.match(/\.folder$/)) {
- _fspp.deleteFolderRecursive(userdir+data+fname);
- } else {
- _fs.unlink(newname);
- }
- }
- _fspp.mv(userdir+"/"+folder+fname,userdir+data,onmove);
- } else {
- // rename
- var matches = url.pathname.match(/^\/(.*?)\/(.*\/)?(.*)\.(file|folder)$/),
- username = matches[1],
- folder = matches[2] || '',
- fname = matches[3],
- userdir = './users/'+username+'/',
- onrename =
- function(err, stdout, stderr)
- {
- if( err )
- __respond(resp,500,String(err));
- else
- __respond(resp,200);
- };
- _fs.rename(userdir+folder+fname,userdir+folder+data,onrename);
- }
- }
- );
-
- }
-
- else if (req.method == 'POST' && url.pathname.match(/\.formalism$/)) {
- // create new formalism
- var matches = url.pathname.match(/^(.*)\/(.*)\.formalism$/),
- username = matches[1],
- formalism = matches[2],
- userdir = './users/'+username+"/",
- oncreatefolder =
- function(err, stdout, stderr)
- {
- if( err )
- __respond(resp,500,String(err));
- else {
- _fs.createReadStream(userdir+"Formalisms/__Templates__/MetamodelTemplate.model").pipe(_fs.createWriteStream(userdir+"Formalisms/"+formalism+"/"+formalism+".model"));
- _fs.createReadStream(userdir+"Formalisms/__Templates__/ConcreteSyntaxTemplate.model").pipe(_fs.createWriteStream(userdir+"Formalisms/"+formalism+"/"+formalism+".defaultIcons.model"));
- _fs.createReadStream(userdir+"Formalisms/__Templates__/MetamodelTemplate.metamodel").pipe(_fs.createWriteStream(userdir+"Formalisms/"+formalism+"/"+formalism+".metamodel"));
- _fs.createReadStream(userdir+"Formalisms/__Templates__/ConcreteSyntaxTemplate.defaultIcons.metamodel").pipe(_fs.createWriteStream(userdir+"Formalisms/"+formalism+"/"+formalism+".defaultIcons.metamodel"));
- _fs.createReadStream(userdir+"Formalisms/__Templates__/T_TransformationTemplate.model").pipe(_fs.createWriteStream(userdir+"Formalisms/"+formalism+"/OperationalSemantics/T_OperationalSemantics.model"));
- _fs.createReadStream(userdir+"Formalisms/__Templates__/T_TransformationTemplate.model").pipe(_fs.createWriteStream(userdir+"Formalisms/"+formalism+"/TranslationalSemantics/T_TranslationalSemantics.model"));
- __respond(resp,200);
- }
- };
- _fs.mkdir(userdir+"Formalisms/"+formalism,function(err, stdout, stderr) {
- if( err )
- __respond(resp,500,String(err));
- else {
- _fs.mkdirSync(userdir+"Formalisms/"+formalism+"/OperationalSemantics");
- _fs.mkdir(userdir+"Formalisms/"+formalism+"/TranslationalSemantics", oncreatefolder);
- }
- });
- }
-
- else if (req.method == 'POST' && url.pathname.match(/\.transformation$/)) {
- // create new transformation
- var matches = url.pathname.match(/^\/(.*?)\/(.*)\.transformation$/),
- username = matches[1],
- userdir = './users/'+username+"/";
-
- _fs.createReadStream(userdir+"Formalisms/__Templates__/T_TransformationTemplate.model").pipe(_fs.createWriteStream('./users/'+url.pathname.slice(0, -(".transformation".length))));
- __respond(resp,200);
- }
-
- else if (req.method == 'POST' && url.pathname.match(/\.rule$/)) {
- // create new rule
- var matches = url.pathname.match(/^\/(.*?)\/(.*)\.rule$/),
- username = matches[1],
- userdir = './users/'+username+"/";
-
- _fs.createReadStream(userdir+"Formalisms/__Templates__/R_RuleTemplate.model").pipe(_fs.createWriteStream('./users/'+url.pathname.slice(0, -(".rule".length))));
- __respond(resp,200);
- }
-
- /* extract user-uploaded archive to specified folder
- 1. read in all data
- 2. make sure destination exists and is a directory
- 3. write data to temp file (upload###.zip)
- 4. extract temp file and remove it
-
- NOTE:: it's not clear why (despite hours of googling) but the
- "req.setEncoding('utf8')" statement makes the difference
- between retrieving correct and corrupted (when non-text
- files in zip) data */
- else if( req.method == 'PUT' && url.pathname.match(/\.file$/) )
- {
- req.setEncoding('utf8');
- let reqData = '',
- tmpzip = 'upload'+Date.now()+'.zip',
- destdir = './users/'+url.pathname.match(/(.*)\.file$/)[1]+'/';
- if( url.pathname.contains("..") || url.pathname.contains(";") ) {
- __respond(resp, 404,
- 'invalid pathname, no semicolons or .. allowed :: ' + url.pathname);
- return;
- }
- req.addListener("data", function(chunk) {reqData += chunk;});
- req.addListener("end",
- function()
- {
- _fs.stat(destdir,
- function(err,stats)
- {
- if( err )
- __respond(resp,404,String(err));
- else if( ! stats.isDirectory() )
- __respond(resp,404,
- 'destination is not a directory :: '+destdir);
- else
- _fs.writeFile(
- destdir+tmpzip,eval('('+reqData+')'),
- 'binary',
- function(err)
- {
- _cp.exec('cd '+destdir+'; unzip -o '+tmpzip,
- function(err, stdout, stderr)
- {
- if( err )
- __respond(resp,500,String(err));
- else
- __respond(resp,200);
- _fs.unlink(destdir+tmpzip, function(err){
- console.log("Unlinked " + destdir + tmpzip);
- }
- );
- });
- });
- });
- });
- }
- /* serve specified file/folder within a zip file */
- else if( req.method == 'GET' && url.pathname.match(/\.file$/) )
- {
- let matches = url.pathname.match(/^\/(.*?)\/(.*)\.file$/),
- username = matches[1],
- fname = './'+matches[2],
- userdir = './users/'+username+'/',
- tmpzip = 'download'+Date.now()+'.zip';
- if( username.contains("..") || username.contains(";") ) {
- __respond(resp, 404,
- 'invalid username, no colons or .. allowed :: ' + username);
- return;
- }
- _fs.exists(userdir+fname,
- function(exists)
- {
- if( ! exists )
- __respond(resp,404,
- 'requested file/folder does not exist :: '+fname);
- else
- _cp.exec('cd '+userdir+'; zip -r '+tmpzip+' "'+fname+'"',
- function(err, stdout, stderr)
- {
- if( err )
- __respond(resp,500,String(err));
- else
- _fs.readFile(userdir+tmpzip,
- function(err, data)
- {
- __respond(resp,200,'',data,
- {'Content-Type':'application/zip',
- 'Content-Disposition':
- 'attachment; filename="'+tmpzip+'"'});
- _fs.unlink(userdir+tmpzip, function(err){
- console.log("Unlinked " + userdir+tmpzip);
- });
- });
- });
- });
- }
- /* serve list of all files */
- else if( req.method == 'GET' &&
- url.pathname.match(/^\/.+\/filelist$/) )
- {
- var matches = url.pathname.match(/^\/(.+)\/filelist$/);
- _fspp.findfiles('./users/'+matches[1],
- function(err, stdout, stderr)
- {
- if( err )
- __respond(resp,404,String(err));
- else
- __respond(resp,200,'',stdout);
- });
- }
- /* spawn new worker */
- else if( (url.pathname == '/csworker' || url.pathname == '/asworker')
- && req.method == 'POST' )
- {
- /* setup and store new worker */
- var worker = _cp.fork(_path.join(__dirname, '__worker.js')),
- wid = workers.push(worker)-1;
- workerIds2socketIds[wid] = [];
- worker.on('message',
- function(msg)
- {
- /* push changes (if any) to registered sockets... even empty
- changelogs are pushed to facilitate sequence number-based
- ordering */
- if( msg['changelog'] != undefined )
- {
- var _msg = {'changelog':msg['changelog'],
- 'sequence#':msg['sequence#'],
- 'hitchhiker':msg['hitchhiker']};
- workerIds2socketIds[wid].forEach(
- function(sid)
- {
- __send(
- wsserver.sockets.sockets[sid],
- undefined,
- undefined,
- _msg);
- });
- }
- /* respond to a request */
- if( msg['respIndex'] != undefined )
- __respond(
- responses[msg['respIndex']],
- msg['statusCode'],
- msg['reason'],
- JSON.stringify(
- {'headers':
- (msg['headers'] ||
- {'Content-Type': 'text/plain',
- 'Access-Control-Allow-Origin': '*'}),
- 'data':msg['data'],
- 'sequence#':msg['sequence#']}),
- {'Content-Type': 'application/json'});
- });
- worker.send(
- {'workerType':url.pathname,
- 'workerId':wid});
- /* respond worker id (used to identify associated worker) */
- __respond(
- resp,
- 201,
- '',
- ''+wid);
- return;
- }
- /* check for worker id and it's validity */
- else if( url['query'] == undefined ||
- url['query']['wid'] == undefined )
- __respond(resp, 400, 'missing worker id');
- else if( workers[url['query']['wid']] == undefined )
- __respond(resp, 400, 'invalid worker id :: '+url['query']['wid']);
-
- /* save resp object and forward request to worker (if request is PUT or
- POST, recover request data first)
-
- TBI:: only registered sockets should be allowed to speak to worker
- ... one way of doing this is forcing request urls to contain
- cid=socket.id## */
- else if( req.method == 'PUT' || req.method == 'POST' )
- {
- var reqData = '';
- req.addListener("data", function(chunk) {reqData += chunk;});
- req.addListener("end",
- function()
- {
- workers[url['query']['wid']].send(
- {'method':req.method,
- 'uri':url.pathname,
- 'reqData':(reqData == '' ?
- undefined :
- eval('('+reqData+')')),
- 'uriData':url['query'],
- 'respIndex':responses.push(resp)-1});
- });
- }
- else
- workers[url['query']['wid']].send(
- {'method':req.method,
- 'uri':url.pathname,
- 'uriData':url['query'],
- 'respIndex':responses.push(resp)-1});
- });
- httpserver.listen(8124);
- var wsserver = _sio.listen(httpserver);
- wsserver.configure(
- function()
- {
- wsserver.set('log level',2);
- });
- wsserver.sockets.on('connection',
- function(socket)
- {
- /* unregister this socket from the specified worker ... when a worker
- has no more registered sockets, terminate it */
- function unregister(wid)
- {
- var i = workerIds2socketIds[wid].indexOf(socket.id);
- if( i == -1 )
- __send(socket,403,'already unregistered from worker');
- else
- {
- workerIds2socketIds[wid].splice(i,1);
- if( workerIds2socketIds[wid].length == 0 )
- {
- workers[wid].kill();
- workers[wid] = undefined;
- delete workerIds2socketIds[wid];
- }
- __send(socket,200);
- }
- }
-
- /* onmessage : on reception of data from client */
- socket.on('message',
- function(msg/*{method:_,url:_}*/)
- {
- var url = _url.parse(msg.url,true);
- /* check for worker id and it's validity */
- if( url['query'] == undefined ||
- url['query']['wid'] == undefined )
- return __send(socket,400,'missing worker id');
- var wid = url['query']['wid'];
- if( workers[wid] == undefined )
- __send(socket,400,'unknown worker id :: '+wid);
- /* register socket for requested worker */
- else if( msg.method == 'POST' &&
- url.pathname.match(/changeListener$/) )
- {
- if( workerIds2socketIds[wid].indexOf(socket.id) > -1 )
- __send(socket,403,'already registered to worker');
- else
- {
- workerIds2socketIds[wid].push(socket.id);
- __send(socket,201);
- }
- }
-
- /* unregister socket for requested worker */
- else if( msg.method == 'DELETE' &&
- url.pathname.match(/changeListener$/) )
- unregister(wid);
- /* unsupported request */
- else
- __send(socket,501);
- });
- /* ondisconnect : on disconnection of socket */
- socket.on('disconnect',
- function()
- {
- for( var wid in workerIds2socketIds )
- for( var i in workerIds2socketIds[wid] )
- if( workerIds2socketIds[wid][i] == socket.id )
- {
- unregister(wid);
- return;
- }
- });
- });
|