facilmap/server/lib/server.js

283 wiersze
8.6 KiB
JavaScript
Czysty Zwykły widok Historia

2014-04-07 00:33:49 +00:00
var http = require("http");
var socketIo = require("socket.io");
var config = require("../config");
var listeners = require("./listeners");
var database = require("./database");
2014-04-09 23:58:14 +00:00
var domain = require("domain");
var utils = require("./utils");
var routing = require("./routing");
2016-09-28 12:10:08 +00:00
var gpx = require("./gpx");
2014-04-07 00:33:49 +00:00
2014-12-14 03:43:05 +00:00
Object.defineProperty(Error.prototype, "toJSON", {
value: function() {
2014-12-27 02:47:40 +00:00
var str = this.message;
if(this.errors) {
for(var i=0; i<this.errors.length; i++)
str += "\n"+this.errors[i].message;
}
return str;
2014-12-14 03:43:05 +00:00
},
configurable: true
});
2014-04-18 18:11:50 +00:00
database.connect(function(err) {
if(err)
throw err;
var app = http.createServer();
app.listen(config.port, config.host, function(err) {
if(err)
throw err;
console.log("Server started on " + (config.host || "*" ) + ":" + config.port);
});
2014-04-18 18:11:50 +00:00
var io = socketIo.listen(app);
io.sockets.on("connection", function(socket) {
var d = domain.create();
d.add(socket);
d.on("error", function(err) {
console.error("Uncaught error in socket:", err.stack);
socket.disconnect();
});
2014-04-18 18:11:50 +00:00
var handlers = {
error : function(err) {
console.error("Error! Disconnecting client.");
console.error(err.stack);
socket.disconnect();
},
setPadId : function(padId) {
if(typeof padId != "string" || socket.padId != null)
2014-04-18 18:11:50 +00:00
return;
socket.padId = true;
2014-04-18 18:11:50 +00:00
database.getPadData(padId, function(err, data) {
if(err)
return _sendData(socket, "padData", err);
socket.padId = data.id;
socket.writable = data.writable;
listeners.addPadListener(socket);
_sendData(socket, "padData", null, data);
_sendStreamData(socket, "view", database.getViews(socket.padId));
_sendStreamData(socket, "type", database.getTypes(socket.padId));
_sendStreamData(socket, "line", database.getPadLines(socket.padId));
if(socket.bbox) { // In case bbox is set while fetching pad data
_sendStreamData(socket, "marker", database.getPadMarkers(socket.padId, socket.bbox));
_sendStreamData(socket, "linePoints", database.getLinePoints(socket.padId, socket.bbox));
}
});
2014-04-18 18:11:50 +00:00
},
updateBbox : function(bbox) {
if(!utils.stripObject(bbox, { top: "number", left: "number", bottom: "number", right: "number", zoom: "number" }))
return;
var bboxWithExcept = utils.extend({ }, bbox);
if(socket.bbox && bbox.zoom == socket.bbox.zoom)
bboxWithExcept.except = socket.bbox;
2014-04-18 18:11:50 +00:00
socket.bbox = bbox;
2014-04-18 18:11:50 +00:00
if(socket.padId && socket.padId !== true) {
_sendStreamData(socket, "marker", database.getPadMarkers(socket.padId, bboxWithExcept));
_sendStreamData(socket, "linePoints", database.getLinePoints(socket.padId, bboxWithExcept));
}
2014-04-18 18:11:50 +00:00
},
disconnect : function() {
if(socket.padId)
listeners.removePadListener(socket);
},
editPad : function(data, callback) {
if(!utils.stripObject(data, { name: "string", defaultViewId: "number" }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.updatePadData(socket.padId, data, callback);
},
addMarker : function(data, callback) {
2014-12-12 02:26:55 +00:00
if(!utils.stripObject(data, { lat: "number", lon: "number", name: "string", colour: "string", typeId: "number", data: Object } ))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.createMarker(socket.padId, data, callback);
},
editMarker : function(data, callback) {
if(!utils.stripObject(data, { id: "number", lat: "number", lon: "number", name: "string", colour: "string", typeId: "number", data: Object }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.updateMarker(data.id, data, callback);
},
deleteMarker : function(data, callback) {
if(!utils.stripObject(data, { id: "number" }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.deleteMarker(data.id, callback);
},
2014-12-26 15:51:14 +00:00
getLineTemplate : function(data, callback) {
if(!utils.stripObject(data, { typeId: "number" }) || data.typeId == null)
return callback("Invalid parameters.");
database.getLineTemplate(data, callback);
},
2014-04-18 18:11:50 +00:00
addLine : function(data, callback) {
if(!utils.stripObject(data, { routePoints: [ { lat: "number", lon: "number" } ], mode: "string", colour: "string", width: "number", name: "string", typeId: "number", data: Object }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.createLine(socket.padId, data, callback);
},
editLine : function(data, callback) {
if(!utils.stripObject(data, { id: "number", routePoints: [ { lat: "number", lon: "number" } ], mode: "string", colour: "string", width: "number", name: "string", typeId: "number", data: Object }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.updateLine(data.id, data, callback);
},
deleteLine : function(data, callback) {
if(!utils.stripObject(data, { id: "number" }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.deleteLine(data.id, callback);
},
addView : function(data, callback) {
if(!utils.stripObject(data, { name: "string", baseLayer: "string", layers: [ "string" ], top: "number", left: "number", right: "number", bottom: "number" }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.createView(socket.padId, data, callback);
},
editView : function(data, callback) {
if(!utils.stripObject(data, { id: "number", baseLayer: "string", layers: [ "string" ], top: "number", left: "number", right: "number", bottom: "number" }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.updateView(data.id, data, callback);
},
deleteView : function(data, callback) {
if(!utils.stripObject(data, { id: "number" }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
2014-04-18 18:11:50 +00:00
database.deleteView(data.id, callback);
2014-06-19 00:37:30 +00:00
},
addType : function(data, callback) {
if(!utils.stripObject(data, { id: "number", name: "string", type: "string", fields: [ { name: "string", type: "string", default: "string", controlColour: "boolean", controlWidth: "boolean", options: [ { key: "string", value: "string", colour: "string", width: "number" } ] }] } ))
2014-12-12 02:26:55 +00:00
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
database.createType(socket.padId, data, callback);
},
editType : function(data, callback) {
2014-12-14 03:43:05 +00:00
if(!utils.stripObject(data, { id: "number", name: "string", fields: [ { name: "string", type: "string", default: "string", controlColour: "boolean", controlWidth: "boolean", options: [ { key: "string", value: "string", colour: "string", width: "number" } ] }] } ))
2014-12-12 02:26:55 +00:00
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
database.updateType(data.id, data, callback);
},
deleteType : function(data, callback) {
if(!utils.stripObject(data, { id: "number" }))
return callback("Invalid parameters.");
if(!socket.writable)
return callback("In read-only mode.");
database.deleteType(data.id, callback);
2016-09-28 12:10:08 +00:00
},
exportGpx : function(data, callback) {
gpx.exportGpx(socket.padId, data.useTracks, callback);
}
2016-09-28 12:10:08 +00:00
/*copyPad : function(data, callback) {
if(!utils.stripObject(data, { toId: "string" }))
return callback("Invalid parameters.");
2014-06-19 00:37:30 +00:00
database.copyPad(socket.padId, data.toId, callback);
}*/
2014-04-18 18:11:50 +00:00
};
2014-04-13 23:34:05 +00:00
for(var i in handlers) { (function(i) {
socket.on(i, function(data, callback) {
var d2 = domain.create();
d2.run(function() {
handlers[i](data, callback);
});
d2.on("error", function(err) {
console.error("Uncaught exception in function "+i+":", err.stack);
callback(err);
});
});
})(i); }
2014-04-18 18:11:50 +00:00
});
2014-04-07 00:33:49 +00:00
});
function _sendData(socket, eventName, err, data) {
2014-04-18 17:15:26 +00:00
if(err) {
2014-04-26 16:23:22 +00:00
console.warn("_sendData", err, err.stack);
2014-04-07 00:33:49 +00:00
return socket.emit("error", err);
2014-04-18 17:15:26 +00:00
}
2014-04-07 00:33:49 +00:00
2014-04-13 23:34:05 +00:00
socket.emit(eventName, data);
2014-04-07 00:33:49 +00:00
}
function _sendStreamData(socket, eventName, stream) {
stream.on("data", function(data) {
if(data != null)
socket.emit(eventName, data);
2014-04-07 00:33:49 +00:00
}).on("error", function(err) {
2014-04-26 16:23:22 +00:00
console.warn("_sendStreamData", err, err.stack);
2014-04-07 00:33:49 +00:00
socket.emit("error", err);
})
}