3 * Copyright 2016 RIFT.IO Inc
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 * Main skyquake module.
22 * @author Kiran Kashalkar <kiran.kashalkar@riftio.com>
25 // Standard library imports for forking
26 var cluster
= require("cluster");
27 var cpu
= require('os').cpus().length
;
28 var clusteredLaunch
= process
.env
.CLUSTER_SUPPORT
|| false;
29 var constants
= require('./framework/core/api_utils/constants');
30 // Uncomment for Replay support
31 // const Replay = require('replay');
33 for (var i
= 0; i
< constants
.SOCKET_POOL_LENGTH
; i
++) {
34 freePorts
[i
] = constants
.SOCKET_BASE_PORT
+ i
;
38 if (cluster
.isMaster
&& clusteredLaunch
) {
39 console
.log(cpu
, 'CPUs found');
40 for (var i
= 0; i
< cpu
; i
++) {
41 var worker
= cluster
.fork();
42 worker
.on('message', function(msg
) {
43 if (msg
&& msg
.getPort
) {
45 port
: freePorts
.shift()
47 console
.log('freePorts after shift for worker', this.process
.pid
, ':', freePorts
);
48 } else if (msg
&& msg
.freePort
) {
49 freePorts
.unshift(msg
.port
);
50 console
.log('freePorts after unshift of', msg
.port
, 'for worker', this.process
.pid
, ':', freePorts
);
55 cluster
.on('online', function(worker
) {
56 console
.log("Worker Started pid : " + worker
.process
.pid
);
58 cluster
.on('exit', function(worker
, code
, signal
) {
59 console
.log('worker ' + worker
.process
.pid
+ ' stopped');
62 // Standard library imports
63 var argv
= require('minimist')(process
.argv
.slice(2));
64 var pid
= process
.pid
;
65 var fs
= require('fs');
66 var https
= require('https');
67 var http
= require('http');
68 var express
= require('express');
69 var session
= require('express-session');
70 var cors
= require('cors');
71 var bodyParser
= require('body-parser');
72 var _
= require('lodash');
73 var reload
= require('require-reload')(require
);
74 var Sockets
= require('./framework/core/api_utils/sockets.js');
76 require('require-json');
78 // SSL related configuration bootstrap
79 var httpServer
= null;
80 var secureHttpServer
= null;
82 var httpsConfigured
= false;
84 var sslOptions
= null;
86 var apiServer
= argv
['api-server'] ? argv
['api-server'] : 'localhost';
87 var uploadServer
= argv
['upload-server'] ? argv
['upload-server'] : null;
90 if (argv
['enable-https']) {
91 var keyFilePath
= argv
['keyfile-path'];
92 var certFilePath
= argv
['certfile-path'];
95 key
: fs
.readFileSync(keyFilePath
),
96 cert
: fs
.readFileSync(certFilePath
)
99 httpsConfigured
= true;
102 console
.log('HTTPS enabled but file paths missing/incorrect');
103 process
.exit(code
= -1);
109 secret
: 'ritio rocks',
111 saveUninitialized
: true
113 app
.use(bodyParser
.json());
115 app
.use(bodyParser
.urlencoded({
119 var socketManager
= new Sockets();
121 httpsConfigured
: httpsConfigured
124 if (httpsConfigured
) {
125 socketConfig
.sslOptions
= sslOptions
;
128 // Rift framework imports
129 var constants
= require('./framework/core/api_utils/constants');
130 var skyquakeEmitter
= require('./framework/core/modules/skyquakeEmitter');
131 var navigation_routes
= require('./framework/core/modules/routes/navigation');
132 var socket_routes
= require('./framework/core/modules/routes/sockets');
133 var restconf_routes
= require('./framework/core/modules/routes/restconf');
134 var inactivity_routes
= require('./framework/core/modules/routes/inactivity');
135 var descriptor_routes
= require('./framework/core/modules/routes/descriptorModel');
136 var configuration_routes
= require('./framework/core/modules/routes/configuration');
137 var configurationAPI
= require('./framework/core/modules/api/configuration');
139 * Processing when a plugin is added or modified
140 * @param {string} plugin_name - Name of the plugin
142 function onPluginAdded(plugin_name
) {
143 // Load plugin config
144 var plugin_config
= reload('./plugins/' + plugin_name
+ '/config.json');
146 // Load all app's views
147 app
.use('/' + plugin_name
, express
.static('./plugins/' + plugin_name
+ '/' + plugin_config
.root
));
149 // Load all app's routes
150 app
.use('/' + plugin_name
, require('./plugins/' + plugin_name
+ '/routes'));
152 // Publish navigation links
153 if (plugin_config
.routes
&& _
.isArray(plugin_config
.routes
)) {
154 skyquakeEmitter
.emit('config_discoverer.navigation_discovered', plugin_name
, plugin_config
);
160 * Start listening on a port
161 * @param {string} port - Port to listen on
162 * @param {object} httpServer - httpServer created with http(s).createServer
164 function startListening(port
, httpServer
) {
165 var server
= httpServer
.listen(port
, function () {
166 var host
= server
.address().address
;
168 var port
= server
.address().port
;
170 console
.log('Express server listening on port', port
);
176 * Initialize skyquake
179 skyquakeEmitter
.on('plugin_discoverer.plugin_discovered', onPluginAdded
);
180 skyquakeEmitter
.on('plugin_discoverer.plugin_updated', onPluginAdded
);
187 // Conigure any globals
188 process
.env
.NODE_TLS_REJECT_UNAUTHORIZED
=0;
190 // Configure navigation router
191 app
.use(navigation_routes
);
193 // Configure restconf router
194 app
.use(restconf_routes
);
196 //Configure inactivity route(s)
197 app
.use(inactivity_routes
);
199 // Configure global config with ssl enabled/disabled
201 ssl_enabled
: httpsConfigured
,
202 api_server
: apiServer
206 globalConfig
.upload_server
= uploadServer
;
209 configurationAPI
.globalConfiguration
.update(globalConfig
);
211 // Configure configuration route(s)
212 app
.use(configuration_routes
);
214 //Configure descriptor route(s)
215 app
.use(descriptor_routes
);
217 // app.get('/testme', function(req, res) {
218 // res.sendFile(__dirname + '/index.html');
221 // Configure HTTP/HTTPS server and populate socketConfig.
222 if (httpsConfigured
) {
223 console
.log('HTTPS configured. Will create 2 servers');
224 secureHttpServer
= https
.createServer(sslOptions
, app
);
225 // Add redirection on SERVER_PORT
226 httpServer
= http
.createServer(function(req
, res
) {
227 var host
= req
.headers
['host'];
228 host
= host
.replace(/:\d+$/, ":" + constants
.SECURE_SERVER_PORT
);
230 res
.writeHead(301, { "Location": "https://" + host
+ req
.url
});
234 socketConfig
.httpServer
= secureHttpServer
;
236 httpServer
= http
.createServer(app
);
237 socketConfig
.httpServer
= httpServer
;
240 // Configure socket manager
241 socketManager
.configure(socketConfig
);
243 // Configure socket router
244 socket_routes
.routes(socketManager
);
245 app
.use(socket_routes
.router
);
247 // Serve multiplex-client
248 app
.get('/multiplex-client', function(req
, res
) {
249 res
.sendFile(__dirname
+ '/node_modules/websocket-multiplex/multiplex_client.js');
252 // handle requests for gzip'd files
253 app
.get('*gzip*', function (req
, res
, next
) {
254 res
.set('Content-Encoding', 'gzip');
261 * Run skyquake functionality
265 // Start plugin_discoverer
266 var navigation_manager
= require('./framework/core/modules/navigation_manager');
267 var plugin_discoverer
= require('./framework/core/modules/plugin_discoverer');
269 // Initialize asynchronous modules
270 navigation_manager
.init();
271 plugin_discoverer
.init();
273 // Configure asynchronous modules
274 navigation_manager
.config()
275 plugin_discoverer
.config({
276 plugins_path
: './plugins'
279 // Run asynchronous modules
280 navigation_manager
.run();
281 plugin_discoverer
.run();
285 if (httpsConfigured
) {
286 console
.log('HTTPS configured. Will start 2 servers');
287 // Start listening on SECURE_SERVER_PORT (8443)
288 var secureServer
= startListening(constants
.SECURE_SERVER_PORT
, secureHttpServer
);
290 // Start listening on SERVER_PORT (8000)
291 var server
= startListening(constants
.SERVER_PORT
, httpServer
);