-const path = require('path');
-const fs = require('fs');
-const express = require('express');
-const QRCode = require('qrcode');
-const Edge = require('./edge');
-const SocketTizen = require('./socket-tizen');
-const { getMyAddress } = require('./util');
+const { onStart } = require('./service');
-const TAG = 'app.js';
-
-const app = express();
-
-const options = {
- key: fs.readFileSync(path.resolve(__dirname, 'key.pem')),
- cert: fs.readFileSync(path.resolve(__dirname, 'cert.pem'))
-};
-
-console.log(TAG, `platform : ${process.platform}`);
-
-const httpPort = process.env.HTTP_PORT || 9559;
-const httpsPort = process.env.PORT || process.env.HTTPS_PORT || 5443;
-const httpsServer = require('https').createServer(options, app);
-const httpServer = require('http').createServer(app);
-const io = require('socket.io')();
-const isTizen = process.platform === 'tizen';
-const supportMessagePort = isTizen;
-// Implementation for edge orchestration
-const supportEdgeOrchestration =
- typeof webapis !== 'undefined' && webapis.hasOwnProperty('edge');
-console.log(TAG, `supportEdgeOrchestration : ${supportEdgeOrchestration}`);
-
-io.attach(httpServer);
-io.attach(httpsServer);
-
-const clients = new Set();
-const workers = new Map();
-const sockets = new Map();
-let edgeForCastanets = null;
-let forceQuitTimer = null;
-let isMeerkatStarted = false;
-
-app.set('host', '0.0.0.0');
-
-if (isTizen) {
- app.use(express.static(path.join(__dirname, './public')));
-} else {
- app.use(
- '/offload.html',
- express.static(path.join(__dirname, '../../sample/offload.html'))
- );
- // Host offload-worker
- app.use(
- '/offload-worker',
- express.static(path.join(__dirname, '../../offload-worker/src/'))
- );
- app.use(
- '/offload-worker/offload-worker.js',
- express.static(path.join(__dirname, '../../build/offload-worker.js'))
- );
- const serveIndex = require('serve-index');
- app.use(
- '/',
- express.static(path.join(__dirname, '../../build')),
- express.static(path.join(__dirname, '../../sample')),
- serveIndex(path.join(__dirname, '../../sample'))
- );
- app.use(
- '/test',
- express.static(path.join(__dirname, '../../test')),
- serveIndex(path.join(__dirname, '../../test'))
- );
-}
-
-function onConnection(socket) {
- if (isTizen && !isMeerkatStarted) {
- try {
- console.log(TAG, `Try to start Meerkat client.`);
- tizen.application.launch(
- 'org.tizen.meerkat.client',
- () => {
- console.log(TAG, `Meerkat client is started.`);
- isMeerkatStarted = true;
- },
- err => console.error(TAG, 'Failed to launch Meerkat client. ' + err)
- );
- } catch (err) {
- console.error(TAG, 'Failed to launch Meerkat client. ' + err);
- }
- }
- console.log(TAG, `connection from '${socket.id}.`);
- sockets.set(socket.id, socket);
-
- // client creates a session.
- socket.on('create', async function () {
- if (forceQuitTimer !== null) {
- clearTimeout(forceQuitTimer);
- }
-
- if (clients.has(socket.id)) {
- console.log(TAG, `already created by ${socket.id}.`);
- return;
- }
- clients.add(socket.id);
-
- let qr = null;
- const myAddress = getMyAddress();
- if (myAddress) {
- try {
- qr = await QRCode.toDataURL(
- 'https://' + myAddress + ':5443/offload-worker.html'
- );
- } catch (err) {
- console.error(TAG, 'unabled to generate QR: ' + error);
- }
- }
-
- socket.emit('greeting', {
- qrCode: qr,
- workers: Array.from(workers)
- });
-
- console.log(
- TAG,
- `[client] session created by ${socket.id}. workers.size : ${workers.size}`
- );
-
- if (supportEdgeOrchestration) {
- socket.emit(
- 'capabilities',
- Array.from(edgeForCastanets.getCapabilities())
- );
- }
- });
-
- socket.on('getcapabilities', function () {
- console.log(TAG, `getcapabilities`);
- if (supportEdgeOrchestration) {
- socket.emit(
- 'capabilities',
- Array.from(edgeForCastanets.getCapabilities())
- );
- } else {
- socket.emit('capabilities', []);
- }
- });
-
- socket.on('requestService', function (workerId) {
- if (supportEdgeOrchestration) {
- edgeForCastanets.requestService(workerId);
- }
- });
-
- // new worker has been joined.
- socket.on('join', function (worker) {
- if (supportEdgeOrchestration) {
- let deviceIp = socket.request.connection.remoteAddress;
- if (deviceIp.indexOf('::ffff:') !== -1) {
- deviceIp = deviceIp.substr(7, deviceIp.length);
- }
-
- if (deviceIp) {
- edgeForCastanets.joinDevice(deviceIp);
- }
- }
-
- workers.set(worker.id, {
- socketId: socket.id,
- name: worker.name,
- features: worker.features,
- mediaDeviceInfos: worker.mediaDeviceInfos,
- compute_tasks: 0
- });
- console.log(
- TAG,
- `worker[${workers.size}] join: '${worker.id}' - '${socket.id}', '${worker.name}'`,
- worker.features
- );
-
- for (const client of clients) {
- const clientSocket = sockets.get(client);
- clientSocket.emit('worker', {
- event: 'join',
- workerId: worker.id,
- socketId: socket.id,
- name: worker.name,
- features: worker.features,
- mediaDeviceInfos: worker.mediaDeviceInfos
- });
- }
- });
-
- // route message between clients.
- socket.on('message', function (data) {
- console.log(TAG, `message ${JSON.stringify(data)}`);
- let socketId = null;
- if (workers.has(data.to)) {
- socketId = workers.get(data.to).socketId;
- } else if (clients.has(data.to)) {
- socketId = data.to;
- }
-
- if (socketId) {
- const socket = sockets.get(socketId);
- socket.emit('message', data);
- }
- });
-
- socket.on('disconnect', function (reason) {
- const socketId = socket.id;
- sockets.delete(socketId);
- if (clients.has(socketId)) {
- console.log(TAG, `[client] session terminated by client: ${socketId}`);
-
- // broadcast to offload-worker
- for (const socket of sockets.values()) {
- socket.emit('client', {
- event: 'bye',
- socketId: socketId
- });
- }
- clients.delete(socketId);
-
- if (clients.size === 0) {
- if (supportMessagePort) {
- closeServer();
- }
- forceQuitTimer = setTimeout(function () {
- console.log(
- TAG,
- `All clients are destroyed. Broadcast 'forceQuit' to workers`
- );
- for (const socket of sockets.values()) {
- socket.emit('client', {
- event: 'forceQuit',
- socketId: socketId
- });
- }
- }, 5000);
- }
- } else {
- if (supportEdgeOrchestration) {
- let deviceIp = socket.request.connection.remoteAddress;
- if (deviceIp.indexOf('::ffff:') !== -1) {
- deviceIp = deviceIp.substr(7, deviceIp.length);
- }
-
- if (deviceIp) {
- edgeForCastanets.disconnectDevice(deviceIp);
- }
- }
-
- let workerId = null;
- workers.forEach(function (value, key, map) {
- if (value.socketId === socket.id) {
- workerId = key;
- }
- });
-
- if (workerId) {
- for (const client of clients) {
- const socket = sockets.get(client);
- socket.emit('worker', {
- event: 'bye',
- workerId: workerId,
- socketId: socket.id
- });
- }
- workers.delete(workerId);
- console.log(TAG, `worker[${workers.size}] bye: '${workerId}'`);
- }
- }
- });
-}
-
-io.of('/offload-js').on('connection', onConnection);
-
-if (supportEdgeOrchestration) {
- edgeForCastanets = new Edge(
- 'castanets',
- 'android',
- 'com.samsung.android.castanets'
- );
-}
-
-function startServer() {
- console.log(TAG, 'starting server...');
-
- if (!httpsServer.listening) {
- httpsServer.listen(httpsPort, function () {
- console.log(TAG, `server is listening on https ${httpsPort} port.`);
- });
- }
-
- if (!httpServer.listening) {
- httpServer.listen(httpPort, function () {
- console.log(TAG, `server is listening on http ${httpPort} port.`);
- });
- }
-}
-
-function closeServer() {
- console.log(TAG, 'closing server...');
-
- if (httpsServer.listening) {
- httpsServer.close(err => {
- if (err) {
- console.error(`failed to close the https server:`, err);
- }
- });
- }
-
- if (httpServer.listening) {
- httpServer.close(err => {
- if (err) {
- console.error(`failed to close the http server:`, err);
- }
- });
- }
-}
-
-if (supportMessagePort) {
- console.log(TAG, 'listening tizen messageport...');
- const localPort = tizen.messageport.requestLocalMessagePort('offload');
- localPort.addMessagePortListener(messages => {
- if (messages.length === 0) {
- console.error(TAG, 'Not found message');
- return;
- }
-
- const message = messages[0];
- const event = message.key;
- const value = JSON.parse(message.value);
- const id = value.id;
-
- if (event === 'connect') {
- // FIXME: The message port does not guarantee that the connection has
- // been disconnected when the page is reloaded. Therefore, if a new
- // connection occurs with the same id, the existing connection is
- // disconnected.
- if (sockets.has(id)) {
- console.log(TAG, `Disconnect already connected socket: ${id}`);
- const socket = sockets.get(id);
- socket.handleEvents('disconnect');
- }
-
- const socket = new SocketTizen(id, localPort);
- socket.on('connection', onConnection);
- socket.connect();
- sockets.set(id, socket);
- startServer();
- } else {
- const socket = sockets.get(id);
- socket.handleEvents(event, value.data);
- }
- });
-
- // Check the client status
- function checkConnectionStatus() {
- for (const client of clients) {
- const socket = sockets.get(client);
- if (socket.constructor === SocketTizen) {
- try {
- socket.emit('status');
- } catch (e) {
- console.error(TAG, `Failed to check ${client} status`);
- socket.handleEvents('disconnect');
- }
- }
- }
- }
-
- // Prevent to terminate the process
- setInterval(checkConnectionStatus, 1000);
-} else {
- startServer();
-}
+onStart();
);
if (deviceList === null || deviceList.ipaddrs.length === 0) {
- console.log(TAG, `deviceList is null`);
+ console.log(TAG, 'deviceList is null');
return this._capabilities;
}
console.log(TAG, `ReadCapability : ${ipaddr}, ${features.capability}`);
try {
let jsonCapability = JSON.parse(features.capability);
- if (jsonCapability.hasOwnProperty('offloadjs')) {
- jsonCapability = jsonCapability['offloadjs'];
+ if (Object.hasOwnProperty.call(jsonCapability, 'offloadjs')) {
+ jsonCapability = jsonCapability.offloadjs;
}
this._capabilities.set(jsonCapability.id, {
ipaddr: ipaddr,
--- /dev/null
+const path = require('path');
+const fs = require('fs');
+const express = require('express');
+const QRCode = require('qrcode');
+const Edge = require('./edge');
+const SocketTizen = require('./socket-tizen');
+const { getMyAddress } = require('./util');
+
+const TAG = 'service.js';
+
+const app = express();
+
+const options = {
+ key: fs.readFileSync(path.resolve(__dirname, 'key.pem')),
+ cert: fs.readFileSync(path.resolve(__dirname, 'cert.pem'))
+};
+
+console.log(TAG, `platform : ${process.platform}`);
+
+const httpPort = process.env.HTTP_PORT || 9559;
+const httpsPort = process.env.PORT || process.env.HTTPS_PORT || 5443;
+const httpsServer = require('https').createServer(options, app);
+const httpServer = require('http').createServer(app);
+const io = require('socket.io')();
+const isTizen = process.platform === 'tizen';
+const supportMessagePort = isTizen;
+// Implementation for edge orchestration
+const supportEdgeOrchestration =
+ typeof webapis !== 'undefined' && Object.hasOwnProperty.call(webapis, 'edge');
+console.log(TAG, `supportEdgeOrchestration : ${supportEdgeOrchestration}`);
+
+io.attach(httpServer);
+io.attach(httpsServer);
+
+const clients = new Set();
+const workers = new Map();
+const sockets = new Map();
+let edgeForCastanets = null;
+let forceQuitTimer = null;
+let isMeerkatStarted = false;
+let statusIntervalId = null;
+let localPort = null;
+
+app.set('host', '0.0.0.0');
+
+if (isTizen) {
+ app.use(express.static(path.join(__dirname, './public')));
+ app.use(express.static(path.join(__dirname, '../../shared/res')));
+} else {
+ app.use(
+ '/offload.html',
+ express.static(path.join(__dirname, '../../offload/apps/web/offload.html'))
+ );
+ // Host offload-worker
+ app.use(
+ '/offload-worker',
+ express.static(path.join(__dirname, '../../offload-worker/apps/web/'))
+ );
+ app.use(
+ '/offload-worker/offload-worker.js',
+ express.static(path.join(__dirname, '../../dist/offload-worker.js'))
+ );
+ app.use(
+ '/face.webm',
+ express.static(path.join(__dirname, '../../offload-worker/apps/web/face.webm'))
+ );
+ const serveIndex = require('serve-index');
+ app.use(
+ '/',
+ express.static(path.join(__dirname, '../../dist')),
+ express.static(path.join(__dirname, '../../offload/sample')),
+ serveIndex(path.join(__dirname, '../../offload/sample'))
+ );
+ app.use(
+ '/test',
+ express.static(path.join(__dirname, '../../test')),
+ serveIndex(path.join(__dirname, '../../test'))
+ );
+}
+
+function onConnection(socket) {
+ if (isTizen && !isMeerkatStarted) {
+ try {
+ console.log(TAG, 'Try to start Meerkat client.');
+ tizen.application.launch(
+ 'org.tizen.meerkat.client',
+ () => {
+ console.log(TAG, 'Meerkat client is started.');
+ isMeerkatStarted = true;
+ },
+ err => console.error(TAG, 'Failed to launch Meerkat client. ' + err)
+ );
+ } catch (err) {
+ console.error(TAG, 'Failed to launch Meerkat client. ' + err);
+ }
+ }
+ console.log(TAG, `connection from '${socket.id}.`);
+ sockets.set(socket.id, socket);
+
+ // client creates a session.
+ socket.on('create', async function () {
+ if (forceQuitTimer !== null) {
+ clearTimeout(forceQuitTimer);
+ }
+
+ if (clients.has(socket.id)) {
+ console.log(TAG, `already created by ${socket.id}.`);
+ return;
+ }
+ clients.add(socket.id);
+
+ let qr = null;
+ const myAddress = getMyAddress();
+ if (myAddress) {
+ try {
+ qr = await QRCode.toDataURL(
+ 'https://' + myAddress + ':5443/offload-worker.html'
+ );
+ } catch (err) {
+ console.error(TAG, 'unabled to generate QR: ' + err);
+ }
+ }
+
+ socket.emit('greeting', {
+ qrCode: qr,
+ workers: Array.from(workers)
+ });
+
+ console.log(
+ TAG,
+ `[client] session created by ${socket.id}. workers.size : ${workers.size}`
+ );
+
+ if (supportEdgeOrchestration) {
+ socket.emit(
+ 'capabilities',
+ Array.from(edgeForCastanets.getCapabilities())
+ );
+ }
+ });
+
+ socket.on('getcapabilities', function () {
+ console.log(TAG, 'getcapabilities');
+ if (supportEdgeOrchestration) {
+ socket.emit(
+ 'capabilities',
+ Array.from(edgeForCastanets.getCapabilities())
+ );
+ } else {
+ socket.emit('capabilities', []);
+ }
+ });
+
+ socket.on('requestService', function (workerId) {
+ if (supportEdgeOrchestration) {
+ edgeForCastanets.requestService(workerId);
+ }
+ });
+
+ // new worker has been joined.
+ socket.on('join', function (worker) {
+ if (supportEdgeOrchestration) {
+ let deviceIp = socket.request.connection.remoteAddress;
+ if (deviceIp.indexOf('::ffff:') !== -1) {
+ deviceIp = deviceIp.substr(7, deviceIp.length);
+ }
+
+ if (deviceIp) {
+ edgeForCastanets.joinDevice(deviceIp);
+ }
+ }
+
+ workers.set(worker.id, {
+ socketId: socket.id,
+ name: worker.name,
+ features: worker.features,
+ mediaDeviceInfos: worker.mediaDeviceInfos,
+ compute_tasks: 0
+ });
+ console.log(
+ TAG,
+ `worker[${workers.size}] join: '${worker.id}' - '${socket.id}', '${worker.name}'`,
+ worker.features
+ );
+
+ for (const client of clients) {
+ const clientSocket = sockets.get(client);
+ clientSocket.emit('worker', {
+ event: 'join',
+ workerId: worker.id,
+ socketId: socket.id,
+ name: worker.name,
+ features: worker.features,
+ mediaDeviceInfos: worker.mediaDeviceInfos
+ });
+ }
+ });
+
+ // route message between clients.
+ socket.on('message', function (data) {
+ console.log(TAG, `message ${JSON.stringify(data)}`);
+ let socketId = null;
+ if (workers.has(data.to)) {
+ socketId = workers.get(data.to).socketId;
+ } else if (clients.has(data.to)) {
+ socketId = data.to;
+ }
+
+ if (socketId) {
+ const socket = sockets.get(socketId);
+ socket.emit('message', data);
+ }
+ });
+
+ socket.on('disconnect', function (reason) {
+ const socketId = socket.id;
+ sockets.delete(socketId);
+ if (clients.has(socketId)) {
+ console.log(TAG, `[client] session terminated by client: ${socketId}`);
+ clients.delete(socketId);
+
+ // broadcast to offload-worker
+ for (const socket of sockets.values()) {
+ socket.emit('client', {
+ event: 'bye',
+ socketId: socketId
+ });
+ }
+
+ if (clients.size === 0) {
+ if (supportMessagePort) {
+ closeServer();
+ }
+ forceQuitTimer = setTimeout(function () {
+ console.log(
+ TAG,
+ 'All clients are destroyed. Broadcast \'forceQuit\' to workers'
+ );
+ for (const socket of sockets.values()) {
+ socket.emit('client', {
+ event: 'forceQuit',
+ socketId: socketId
+ });
+ }
+ }, 5000);
+ }
+ } else {
+ if (supportEdgeOrchestration) {
+ let deviceIp = socket.request.connection.remoteAddress;
+ if (deviceIp.indexOf('::ffff:') !== -1) {
+ deviceIp = deviceIp.substr(7, deviceIp.length);
+ }
+
+ if (deviceIp) {
+ edgeForCastanets.disconnectDevice(deviceIp);
+ }
+ }
+
+ let workerId = null;
+ workers.forEach(function (value, key, map) {
+ if (value.socketId === socket.id) {
+ workerId = key;
+ }
+ });
+
+ if (workerId) {
+ for (const client of clients) {
+ const socket = sockets.get(client);
+ socket.emit('worker', {
+ event: 'bye',
+ workerId: workerId,
+ socketId: socket.id
+ });
+ }
+ workers.delete(workerId);
+ console.log(TAG, `worker[${workers.size}] bye: '${workerId}'`);
+ }
+ }
+ });
+}
+
+io.of('/offload-js').on('connection', onConnection);
+
+if (supportEdgeOrchestration) {
+ edgeForCastanets = new Edge(
+ 'castanets',
+ 'android',
+ 'com.samsung.android.castanets'
+ );
+}
+
+function startServer() {
+ console.log(TAG, 'starting server...');
+
+ if (!httpsServer.listening) {
+ httpsServer.listen(httpsPort, function () {
+ console.log(TAG, `server is listening on https ${httpsPort} port.`);
+ });
+ }
+
+ if (!httpServer.listening) {
+ httpServer.listen(httpPort, function () {
+ console.log(TAG, `server is listening on http ${httpPort} port.`);
+ });
+ }
+}
+
+function closeServer() {
+ console.log(TAG, 'closing server...');
+
+ if (httpsServer.listening) {
+ httpsServer.close(err => {
+ if (err) {
+ console.error('failed to close the https server:', err);
+ }
+ });
+ }
+
+ if (httpServer.listening) {
+ httpServer.close(err => {
+ if (err) {
+ console.error('failed to close the http server:', err);
+ }
+ });
+ }
+}
+
+// Check the client status
+function checkConnectionStatus() {
+ for (const client of clients) {
+ const socket = sockets.get(client);
+ if (socket.constructor === SocketTizen) {
+ try {
+ socket.emit('status');
+ } catch (e) {
+ console.error(TAG, `Failed to check ${client} status`);
+ socket.handleEvents('disconnect');
+ }
+ }
+ }
+}
+
+function handleMessagePort(messages) {
+ if (messages.length === 0) {
+ console.error(TAG, 'Not found message');
+ return;
+ }
+
+ const message = messages[0];
+ const event = message.key;
+ const value = JSON.parse(message.value);
+ const id = value.id;
+
+ if (event === 'connect') {
+ // FIXME: The message port does not guarantee that the connection has
+ // been disconnected when the page is reloaded. Therefore, if a new
+ // connection occurs with the same id, the existing connection is
+ // disconnected.
+ if (sockets.has(id)) {
+ console.log(TAG, `Disconnect already connected socket: ${id}`);
+ const socket = sockets.get(id);
+ socket.handleEvents('disconnect');
+ }
+
+ const socket = new SocketTizen(id, localPort);
+ socket.on('connection', onConnection);
+ socket.connect();
+ sockets.set(id, socket);
+ startServer();
+ } else {
+ const socket = sockets.get(id);
+ socket.handleEvents(event, value.data);
+ }
+}
+
+module.exports.onStart = () => {
+ console.log(`${TAG} onStart is called`);
+ if (supportMessagePort) {
+ console.log(TAG, 'listening tizen messageport...');
+ localPort = tizen.messageport.requestLocalMessagePort('offload');
+ localPort.addMessagePortListener(handleMessagePort);
+
+ // Prevent to terminate the process
+ statusIntervalId = setInterval(checkConnectionStatus, 1000);
+ } else {
+ startServer();
+ }
+};
+
+module.exports.onStop = () => {
+ console.log(`${TAG} onStop is called`);
+ if (supportMessagePort) {
+ for (const socket of sockets.values()) {
+ socket.close();
+ }
+ if (localPort !== null) {
+ localPort.removeMessagePortListener(handleMessagePort);
+ }
+ if (statusIntervalId !== null) {
+ clearInterval(statusIntervalId);
+ }
+ }
+
+ closeServer();
+};
+
+module.exports.onRequest = () => {
+ console.log(`${TAG} onRequest is called`);
+};
this.handleEvents('connection', this);
this.emit('connect');
} catch (error) {
- console.error(TAG, `Messageport connection failed: ` + error);
+ console.error(TAG, 'Messageport connection failed: ' + error);
}
}
const interfaces = os.networkInterfaces();
const addresses = {};
for (const intf in interfaces) {
- if (interfaces.hasOwnProperty(intf)) {
+ if (Object.hasOwnProperty.call(interfaces, intf)) {
for (const addr in interfaces[intf]) {
- if (interfaces[intf].hasOwnProperty(addr)) {
+ if (Object.hasOwnProperty.call(interfaces[intf], addr)) {
const address = interfaces[intf][addr];
if (address.family === 'IPv4' && !address.internal) {
addresses[intf] = address.address;
<tizen:name>DeviceHomeService</tizen:name>
<tizen:description>DeviceHomeService</tizen:description>
</tizen:service>
+ <tizen:service id="9z6IujVul3.SignalingServer" type="global" auto-restart="true" on-boot="true">
+ <tizen:content src="signaling_server/gen/service.js"/>
+ <tizen:name>SignalingServer</tizen:name>
+ <tizen:description>SignalingServer</tizen:description>
+ </tizen:service>
</widget>
%define _use_nmt 0
%endif
%define _use_category 0
+ %define _use_d2d_offload 1
%endif
BuildRequires: pkgconfig(chromium-efl)