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;
87 if (argv
['enable-https']) {
88 var keyFilePath
= argv
['keyfile-path'];
89 var certFilePath
= argv
['certfile-path'];
92 key
: fs
.readFileSync(keyFilePath
),
93 cert
: fs
.readFileSync(certFilePath
)
96 httpsConfigured
= true;
99 console
.log('HTTPS enabled but file paths missing/incorrect');
100 process
.exit(code
= -1);
106 secret
: 'ritio rocks',
108 saveUninitialized
: true
110 app
.use(bodyParser
.json());
112 app
.use(bodyParser
.urlencoded({
116 var socketManager
= new Sockets();
118 httpsConfigured
: httpsConfigured
121 if (httpsConfigured
) {
122 socketConfig
.sslOptions
= sslOptions
;
125 // Rift framework imports
126 var constants
= require('./framework/core/api_utils/constants');
127 var skyquakeEmitter
= require('./framework/core/modules/skyquakeEmitter');
128 var navigation_routes
= require('./framework/core/modules/routes/navigation');
129 var socket_routes
= require('./framework/core/modules/routes/sockets');
130 var restconf_routes
= require('./framework/core/modules/routes/restconf');
131 var inactivity_routes
= require('./framework/core/modules/routes/inactivity');
132 var descriptor_routes
= require('./framework/core/modules/routes/descriptorModel');
133 var configuration_routes
= require('./framework/core/modules/routes/configuration');
134 var configurationAPI
= require('./framework/core/modules/api/configuration');
136 * Processing when a plugin is added or modified
137 * @param {string} plugin_name - Name of the plugin
139 function onPluginAdded(plugin_name
) {
140 // Load plugin config
141 var plugin_config
= reload('./plugins/' + plugin_name
+ '/config.json');
143 // Load all app's views
144 app
.use('/' + plugin_name
, express
.static('./plugins/' + plugin_name
+ '/' + plugin_config
.root
));
146 // Load all app's routes
147 app
.use('/' + plugin_name
, require('./plugins/' + plugin_name
+ '/routes'));
149 // Publish navigation links
150 if (plugin_config
.routes
&& _
.isArray(plugin_config
.routes
)) {
151 skyquakeEmitter
.emit('config_discoverer.navigation_discovered', plugin_name
, plugin_config
);
157 * Start listening on a port
158 * @param {string} port - Port to listen on
159 * @param {object} httpServer - httpServer created with http(s).createServer
161 function startListening(port
, httpServer
) {
162 var server
= httpServer
.listen(port
, function () {
163 var host
= server
.address().address
;
165 var port
= server
.address().port
;
167 console
.log('Express server listening on port', port
);
173 * Initialize skyquake
176 skyquakeEmitter
.on('plugin_discoverer.plugin_discovered', onPluginAdded
);
177 skyquakeEmitter
.on('plugin_discoverer.plugin_updated', onPluginAdded
);
184 // Conigure any globals
185 process
.env
.NODE_TLS_REJECT_UNAUTHORIZED
=0;
187 // Configure navigation router
188 app
.use(navigation_routes
);
190 // Configure restconf router
191 app
.use(restconf_routes
);
193 //Configure inactivity route(s)
194 app
.use(inactivity_routes
);
196 // Configure global config with ssl enabled/disabled
197 configurationAPI
.globalConfiguration
.update({
198 ssl_enabled
: httpsConfigured
201 // Configure configuration route(s)
202 app
.use(configuration_routes
);
204 //Configure descriptor route(s)
205 app
.use(descriptor_routes
);
207 // app.get('/testme', function(req, res) {
208 // res.sendFile(__dirname + '/index.html');
211 // Configure HTTP/HTTPS server and populate socketConfig.
212 if (httpsConfigured
) {
213 console
.log('HTTPS configured. Will create 2 servers');
214 secureHttpServer
= https
.createServer(sslOptions
, app
);
215 // Add redirection on SERVER_PORT
216 httpServer
= http
.createServer(function(req
, res
) {
217 var host
= req
.headers
['host'];
218 host
= host
.replace(/:\d+$/, ":" + constants
.SECURE_SERVER_PORT
);
220 res
.writeHead(301, { "Location": "https://" + host
+ req
.url
});
224 socketConfig
.httpServer
= secureHttpServer
;
226 httpServer
= http
.createServer(app
);
227 socketConfig
.httpServer
= httpServer
;
230 // Configure socket manager
231 socketManager
.configure(socketConfig
);
233 // Configure socket router
234 socket_routes
.routes(socketManager
);
235 app
.use(socket_routes
.router
);
237 // Serve multiplex-client
238 app
.get('/multiplex-client', function(req
, res
) {
239 res
.sendFile(__dirname
+ '/node_modules/websocket-multiplex/multiplex_client.js');
244 * Run skyquake functionality
248 // Start plugin_discoverer
249 var navigation_manager
= require('./framework/core/modules/navigation_manager');
250 var plugin_discoverer
= require('./framework/core/modules/plugin_discoverer');
252 // Initialize asynchronous modules
253 navigation_manager
.init();
254 plugin_discoverer
.init();
256 // Configure asynchronous modules
257 navigation_manager
.config()
258 plugin_discoverer
.config({
259 plugins_path
: './plugins'
262 // Run asynchronous modules
263 navigation_manager
.run();
264 plugin_discoverer
.run();
268 if (httpsConfigured
) {
269 console
.log('HTTPS configured. Will start 2 servers');
270 // Start listening on SECURE_SERVER_PORT (8443)
271 var secureServer
= startListening(constants
.SECURE_SERVER_PORT
, secureHttpServer
);
273 // Start listening on SERVER_PORT (8000)
274 var server
= startListening(constants
.SERVER_PORT
, httpServer
);