[Service] Upgrade device home as v1.0.2 01/256901/1 submit/tizen/20210414.103328
authorYoungsoo Choi <kenshin.choi@samsung.com>
Wed, 14 Apr 2021 09:14:05 +0000 (02:14 -0700)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Wed, 14 Apr 2021 09:17:26 +0000 (02:17 -0700)
- Improval of web socket connections
- Removal of d2d app dependent logic
- Generating RSA keys in runtime for security reason

Change-Id: Icad70d8f8d267e29810de6c998795fce948af3f4
Signed-off-by: Youngsoo Choi <kenshin.choi@samsung.com>
device_home/client/invited.html
device_home/pincode/js/pincode.js
device_home/pincode/pincode.html
device_home/service/app_proxy.js
device_home/service/app_router.js
device_home/service/relay-server.js
device_home/service/security.js [new file with mode: 0755]
device_home/service/service.js

index 484a9def0348e6a7f8747e36b0334134f55bdddd..55d78219671100198e185be59db850aadf527a2d 100755 (executable)
@@ -5,11 +5,11 @@
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, user-scalable=no">
        <title>My Device App</title>
-       <link href="lib/tau/mobile/theme/default/tau.min.css" rel="stylesheet" />
-       <link rel="stylesheet" href="css/style.css" />
-       <script data-build-remove="false" src="lib/tau/mobile/js/tau.min.js"></script>
-       <script src="js/app.js" type="module"></script>
-       <script src="js/invited.js" type="module"></script>
+       <link href="client/lib/tau/mobile/theme/default/tau.min.css" rel="stylesheet" />
+       <link rel="stylesheet" href="client/css/style.css" />
+       <script data-build-remove="false" src="client/lib/tau/mobile/js/tau.min.js"></script>
+       <script src="client/js/app.js" type="module"></script>
+       <script src="client/js/invited.js" type="module"></script>
 </head>
 
 <body>
index fd1de1b1e1c949b8cdae5200f565d77d786f7cc1..823f68c8d93a9e958377cc223f236a31bb2bae90 100755 (executable)
@@ -1,3 +1,4 @@
+const TAG = '[DeviceHome][pincode]';
 const serverPort = 9000;
 const serverURL = window.location.protocol + '//' + window.location.hostname;
 
@@ -37,6 +38,7 @@ function init() {
             }
             dots[input.length - 1].className += ' active';
             if (input.length >= 4) {
+                console.log(`${TAG} input: ${input}`);
                 sendPinCode(input);
 
                 setTimeout(function () {
@@ -56,7 +58,7 @@ function init() {
     });
 }
 
-function sendPinCode(data) {
+async function sendPinCode(data) {
     var encrypt = new JSEncrypt();
     encrypt.setPublicKey(publicKey);
     var xhr = new XMLHttpRequest();
@@ -69,8 +71,10 @@ function sendPinCode(data) {
         }
     };
     xhr.open('POST', serverURL + ':' + serverPort + '/pincode/pinCodeToServer');
-    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
-    xhr.send(encrypt.encrypt(data));
+    xhr.setRequestHeader("Content-Type", "application/json");
+    var data = encrypt.encrypt(data);
+    console.log(`${TAG} data: ${data}`);
+    xhr.send(JSON.stringify({ pincode: data.toString("utf8") }));
 }
 
 function generatePinCodeNumber() {
index 054e6ac36543c97707fc91e6396d9e1b6598c186..2c5acb4a83af33a1b141cdc7e59830e752df3344 100755 (executable)
@@ -10,7 +10,7 @@
 </head>
 
 <body>
-    <form id="loginForm" action="/d2d" method="post"></form>
+    <form id="loginForm" action="/d2d" method="post">
         <div id="pin">
             <div class="dots">
                 <div class="dot"></div>
index 69f3f9ccca20facc85a800a32799fcf0b8c495c4..3acfa301f3ff59c7d555cb7463a381db4cc52134 100755 (executable)
@@ -1,4 +1,5 @@
-var express = require('express');
+const express = require('express');
+const url = require('url');
 const AppRouter = require('./app_router');
 var appRouters = [];
 var path = null;
@@ -17,10 +18,15 @@ function runApp(appId, port, callback) {
         if (isRunning && currentD2DAppId === appId) {
             callback();
         } else {
-            var appControl = new tizen.ApplicationControl(
+            const urlParam = require('./service').getUrlParam();
+            const urlObj = url.parse(urlParam, true).query;
+            const appControl = new tizen.ApplicationControl(
                 "http://tizen.org/appcontrol/operation/default", null, null, null,
                 [new tizen.ApplicationControlData(
                     "http://tizen.org/appcontrol/data/launch_port", [port]
+                ),
+                new tizen.ApplicationControlData(
+                    "http://tizen.org/appcontrol/data/url_parameter", [JSON.stringify(urlObj)]
                 )]
             );
 
index 4af816b7aa32aa4b21bb456a3f217b553fc03fcd..a5a0c2f94d65793df1e5ede17e5f4e122edac645 100755 (executable)
@@ -1,27 +1,24 @@
-var express = require('express');
+const express = require('express');
+const url = require('url');
+const TAG = '[App Router]'
 
 class AppRouter {
     constructor(app, path) {
-        var appRouter = express.Router();
+        let appRouter = express.Router();
         appRouter.use(express.static(__dirname + '/../../../../' + path + '/shared/res/client'));
 
         appRouter.get('/', (req, res) => {
-            console.log("[GlobalWebServer] appRouter.get(/) ", req.baseUrl);
-            var roomData = require('./service').getUrlParam();
-            console.log("[GlobalWebServer] appRouter.get(/) roomData : ", roomData);
-
-            // [WT] Chatting App
-            if (path === 'NAe4rftRic') {
-                if (roomData.indexOf('roomId') != -1) {
-                    res.redirect('chat.html');
-                }
-                else {
-                    res.redirect('client.html');
-                }
-            }
-            else {
-                res.redirect('client.html');
-            }
+            console.log(`${TAG} req.baseUrl : ${req.baseUrl}`);
+            const urlParam = require('./service').getUrlParam();
+            let urlObj = url.parse(urlParam, true).query;
+            let url_format = {
+                pathname: 'client.html',
+                query: urlObj
+            };
+            console.log(`${TAG} #################################`);
+            console.log(`${TAG} url_format : ${JSON.stringify(url_format)}`);
+            console.log(`${TAG} #################################`);
+            res.redirect(url.format(url_format));
         });
         return appRouter;
     }
index 4f939162caa7b8ff82b962b94440f71d97d34c99..cf5ad34b5d782a41ebf1324d0c4f7b590251b434 100755 (executable)
@@ -1,9 +1,11 @@
 "use strict";
 var WebSocketServer = require('ws').Server;
-const serviceWsClientIp = "1";
+const localClientIp = "1";
+const TAG = '[D2D Relay Server]'
 const TO_ALL = 100;
-let wsClients = [];
-let serviceWs = [];
+let remoteClients = [];
+let localClients = [];
+let localClientsMessageQueue = [];
 
 var RelayServer = function(httpserver, options) {
     var wsServer = new WebSocketServer({ server : httpserver });
@@ -17,26 +19,33 @@ var RelayServer = function(httpserver, options) {
         const ip = rawIp.slice(rawIp.lastIndexOf(":") + 1);
         const pkgId = req.url.slice(1); // get the substring after '/' from req.url
 
-        if (serviceWs[pkgId] === undefined) {
-            serviceWs[pkgId] = null;
-        }
-        if (wsClients[pkgId] === undefined) {
-            wsClients[pkgId] = [];
-        }
-        if (ip === serviceWsClientIp || ip === '127.0.0.1') {
+        if (remoteClients[pkgId] === undefined)
+            remoteClients[pkgId] = [];
+
+        if (ip === localClientIp || ip === '127.0.0.1') {
             console.log("connected from local");
-            serviceWs[pkgId] = ws;
-            if (!wsClients[pkgId].length) {
+            const TAG_LOCAL = `${TAG}[Local Client]`;
+            localClients[pkgId] = ws;
+            if (!remoteClients[pkgId].length) {
                 console.log("connected : no client-clients");
             }
+            if (localClientsMessageQueue[pkgId] !== undefined) {
+                for (let msg of localClientsMessageQueue[pkgId]) {
+                    console.log(`${TAG_LOCAL}[message] #################################`);
+                    console.log(`${TAG_LOCAL}[message] send pending msg : ${msg}`);
+                    console.log(`${TAG_LOCAL}[message] #################################`);
+                    ws.send(msg);
+                }
+            }
             console.log("relay-service: ws", ws);
             ws.on('message', function(msg) {
-                console.log("msg[" + msg + "]");
-                const res_msg = 'Success to send : ' + msg;
+                console.log(`${TAG_LOCAL}[message] #################################`);
+                console.log(`${TAG_LOCAL}[message] msg : ${msg}`);
+                console.log(`${TAG_LOCAL}[message] #################################`);
 
                 let myPkgId = null;
-                for (let key in serviceWs) {
-                    if (serviceWs[key] === ws) {
+                for (let key in localClients) {
+                    if (localClients[key] === ws) {
                         myPkgId = key;
                         break;
                     }
@@ -47,56 +56,110 @@ var RelayServer = function(httpserver, options) {
                     // Do what need to handle in relay server only
                     return;
                 }
-                if (!wsClients[myPkgId].length)
+                if (!remoteClients[myPkgId].length)
                     return;
                 if (id == TO_ALL) {
-                    for (let client of wsClients[myPkgId])
+                    for (let client of remoteClients[myPkgId])
                         client.send(msg);
                 } else {
-                    if (id < wsClients[myPkgId].length)
-                        wsClients[myPkgId][id].send(msg);
+                    if (id < remoteClients[myPkgId].length)
+                        remoteClients[myPkgId][id].send(msg);
+                }
+            });
+            ws.on('close', function(msg) {
+                console.log(`${TAG_LOCAL}[close] #################################`);
+                console.log(`${TAG_LOCAL}[close] msg : ${msg}`);
+                console.log(`${TAG_LOCAL}[close] #################################`);
+                let myPkgId = null;
+                for (let key in localClients) {
+                    if (localClients[key] === ws) {
+                        myPkgId = key;
+                        break;
+                    }
+                }
+                // remote local client
+                delete localClients[myPkgId];
+
+                console.log(`${TAG_LOCAL}[close] remoteClients[${myPkgId}] : ${remoteClients[myPkgId]}`);
+                for (let remoteClient of remoteClients[myPkgId]) {
+                    console.log(`${TAG}[close local client] sent local_client_disconnect`);
+                    remoteClient.send(JSON.stringify({
+                        type: "local_client_disconnect",
+                        data: {
+                            totalcount: localClients.length,
+                            id: 0
+                        },
+                        id: -1
+                    }));
                 }
             });
         } else {
             console.log("connected from", ip);
-            if (wsClients[pkgId].indexOf(ws) == -1) {
-                wsClients[pkgId].push(ws);
-                let index = wsClients[pkgId].length - 1;
+            const TAG_REMOTE = `${TAG}[Remote Client]`;
+            if (remoteClients[pkgId].indexOf(ws) == -1) {
+                remoteClients[pkgId].push(ws);
+                let index = remoteClients[pkgId].length - 1;
                 let res = JSON.stringify({type: "id", data: index, id: -1});
                 ws.send(res);
-                if (serviceWs[pkgId] === null)
+                console.log(`${TAG_REMOTE}[connection] localClients.length : ${localClients.length}`);
+                if (localClients[pkgId] === undefined || localClients.length === 0)
                     console.log("connected : no server-client")
                 else {
-                    serviceWs[pkgId].send(JSON.stringify({type: "new_client", data: index, id: -1}));
+                    localClients[pkgId].send(JSON.stringify({type: "new_client", data: index, id: -1}));
                 }
             }
             ws.on('message', function(msg) {
-                console.log("msg[" + msg + "]");
-                const res_msg = 'Success to send : ' + msg;
+                console.log(`${TAG_REMOTE}[message] #################################`);
+                console.log(`${TAG_REMOTE}[message] msg : ${msg}`);
+                console.log(`${TAG_REMOTE}[message] #################################`);
 
                 let myPkgId = null;
-                for (let key in wsClients) {
-                    if (wsClients[key].indexOf(ws) != -1) {
+                for (let key in remoteClients) {
+                    if (remoteClients[key].indexOf(ws) != -1) {
                         myPkgId = key;
                         break;
                     }
                 }
 
-                if (serviceWs[myPkgId])
-                    serviceWs[myPkgId].send(msg);
+                if (localClients[myPkgId]) {
+                    localClients[myPkgId].send(msg);
+                } else {
+                    console.log(`${TAG_REMOTE}[message] #################################`);
+                    console.log(`${TAG_REMOTE}[message] localClient is not ready`);
+                    console.log(`${TAG_REMOTE}[message] #################################`);
+                    if (localClientsMessageQueue[myPkgId] === undefined)
+                        localClientsMessageQueue[myPkgId] = [];
+                    localClientsMessageQueue[myPkgId].push(msg);
+                    console.log(`${TAG_REMOTE}[message] localClient is not ready : ${localClientsMessageQueue[myPkgId]}`);
+                }
             });
             ws.on('close', function(msg) {
+                console.log(`${TAG_REMOTE}[close] #################################`);
+                console.log(`${TAG_REMOTE}[close] msg : ${msg}`);
+                console.log(`${TAG_REMOTE}[close] #################################`);
                 let myPkgId = null;
-                for (let key in wsClients) {
-                    if (wsClients[key].indexOf(ws) != -1) {
+                for (let key in remoteClients) {
+                    if (remoteClients[key].indexOf(ws) != -1) {
                         myPkgId = key;
                         break;
                     }
                 }
-
-                let index = wsClients[myPkgId].indexOf(ws);
-                wsClients[myPkgId].splice(index, 1);
-                serviceWs[myPkgId].send(JSON.stringify({type: "client_disconnect", data: {totalcount: wsClients[myPkgId].length, id: index}, id: -1}));
+                // remote remote client
+                let index = remoteClients[myPkgId].indexOf(ws);
+                delete remoteClients[myPkgId][index];
+                remoteClients[myPkgId].splice(index, 1);
+                console.log(`${TAG}[close remote client] localClients[${myPkgId}] : ${localClients[myPkgId]}`);
+                if (localClients[myPkgId] !== undefined) {
+                    console.log(`${TAG}[close remote client] sent remote_client_disconnect`);
+                    localClients[myPkgId].send(JSON.stringify({
+                        type: "remote_client_disconnect",
+                        data: {
+                            totalcount: remoteClients[myPkgId].length,
+                            id: index
+                        },
+                        id: -1
+                    }));
+                }
             });
         }
     });
diff --git a/device_home/service/security.js b/device_home/service/security.js
new file mode 100755 (executable)
index 0000000..bf4d447
--- /dev/null
@@ -0,0 +1,93 @@
+const crypto = require("crypto");
+const { generateKeyPair } = require("crypto");
+
+const TAG = '[DeviceHome][security.js]';
+
+module.exports.Security = class Security {
+  constructor() {
+    this.privateKey = '';
+    this.publicKey = '';
+  }
+
+  getKeyPairPromise(pincode) {
+    console.log(`${TAG} getKeyPairPromise`);
+    return new Promise((resolve, reject) => {
+      console.log(`${TAG} Generating key will take some time..`);
+      generateKeyPair("rsa", {
+        modulusLength: 1024,
+        publicKeyEncoding: {
+          type: "spki",
+          format: "pem"
+        },
+        privateKeyEncoding: {
+          type: "pkcs1",
+          format: "pem",
+          // TODO: Enable ciper and passphrase
+          //cipher: "aes-256-cbc",
+          //passphrase: pincode
+        }
+      }, (err, publicKey, privateKey) => {
+        // Handle errors and use the generated key pair.
+        resolve({
+          publicKey: publicKey,
+          privateKey: privateKey
+        });
+      });
+    });
+  }
+
+  awaitKeyPair(pincode) {
+    return this.getKeyPairPromise(pincode).then(r => {
+      this.privateKey = r.privateKey;
+      this.publicKey = r.publicKey;
+      console.log(`${TAG}[awaitKeyPair] RSA keys are generated`);
+    }).catch(err => {
+      console.log(`${TAG} Error : ${err}`);
+    });
+  }
+
+  // TODO: Use following APIs instead of JSEncryptLib
+  decryptWithPrivateKey(encryptedString, pincode) {
+    const key = crypto.createPrivateKey({
+      key: this.privateKey,
+      format: "pem",
+      passphrase: pincode
+    });
+    const encrypted = crypto.privateDecrypt(key, Buffer.from(encryptedString, "base64"));
+    const decryptedString = encrypted.toString("utf8");
+    return decryptedString;
+  }
+
+  encryptWithPrivateKey(plain, pincode) {
+    const keyp = crypto.createPrivateKey({
+      key: this.privateKey,
+      format: "pem",
+      passphrase: pincode
+    });
+    const encrypted = crypto.privateEncrypt(keyp, Buffer.from(plain));
+    const encryptedString = encrypted.toString("base64");
+    return encryptedString;
+  }
+
+  decryptWithPublicKey(encryptedString) {
+    const decrypted = crypto.publicDecrypt(this.publicKey, Buffer.from(encryptedString, "base64"));
+    const decryptedString = decrypted.toString("utf8");
+    return decryptedString;
+  }
+
+  encryptWithPublicKey(plain) {
+    const encrypted = crypto.publicEncrypt(this.publicKey, Buffer.from(plain));
+    const encryptedString = encrypted.toString("base64");
+    return encryptedString;
+  }
+
+  getPrivateKey() {
+    console.log(`${TAG} getPrivateKey`);
+    return this.privateKey;
+  }
+
+  getPublicKey() {
+    console.log(`${TAG} getPublicKey`);
+    return this.publicKey;
+  }
+}
index 7b97f41e87bb391c2cf373d2b865d979f0c2bfdb..b15753f9728a3c9c3a3e901c9024b3dc8fc7229d 100755 (executable)
@@ -6,12 +6,12 @@ const path = require("path");
 const relayServer = require('./relay-server.js');
 const session = require('express-session');
 const EventEmitter = require('events');
-const WebSocket = require('ws');
 const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
 const crypto = require('crypto');
+const { Security } = require('./security.js');
 
-const PUBLIC_DOMAIN = 'http://mydevice.ga';
-const TAG = '[D2D Server]'
+const PUBLIC_DOMAIN = 'http://219.254.222.198';
+const TAG = '[DeviceHome][service.js]'
 const TIZEN_WEB_APP_SHARED_RESOURCES = 'shared/res/';
 const WEBCLIP_DIRECTORY = 'webclip';
 const WEBCLIP_MANIFEST = 'manifest.json';
@@ -21,11 +21,12 @@ const non_ip_list = [
   '127.0.0.1',
   '192.168.250.250'
 ]
+const security = new Security();
 
 var apps = [];
 var dataApps = [];
 var clientRouter = express.Router();
-var httpserver, evtEmit, d2dService;
+var httpserver, evtEmit;
 var platform_app_path = '/opt/usr/globalapps';
 var serverAppId = '';
 var urlParam = '';
@@ -39,19 +40,11 @@ var g = {
 // Watch together doesn't use pincode just for demo.
 var MODE_WT = false;
 
-// manage private key.
-var pvkeyHandle = tizen.filesystem.openFile(path.resolve(__dirname, 'private.key'), 'r');
-var privateKey = pvkeyHandle.readString();
-
-// manage public key.
-var pbkeyHandle = tizen.filesystem.openFile(path.resolve(__dirname, 'public.key'), 'r');
-var publicKey = pbkeyHandle.readString();
-
 function addD2Ddata(appPkgID, appAppID, appName, iconPath) {
   let metaDataArray = tizen.application.getAppMetaData(appAppID),
     app = null,
     metaAppID = '';
-  metaDataArray = metaDataArray.filter(function (metaData) {
+  metaDataArray = metaDataArray.filter(function(metaData) {
     if (metaData.key === "d2dservice") {
       if (metaData.value !== "enable") {
         metaAppID = metaData.value;
@@ -60,7 +53,7 @@ function addD2Ddata(appPkgID, appAppID, appName, iconPath) {
     }
     return false;
   });
-  metaDataArray.forEach(function () {
+  metaDataArray.forEach(function() {
     let appPath = path.join(platform_app_path, appPkgID, TIZEN_WEB_APP_SHARED_RESOURCES);
 
     app = {
@@ -98,7 +91,7 @@ function setData() {
 function getAppList() {
   if (tizen.application) {
     try {
-      tizen.application.getAppsInfo(function (applications) {
+      tizen.application.getAppsInfo(function(applications) {
         apps = applications;
         setData();
         getWebclipsManifest();
@@ -146,16 +139,17 @@ function getWebclipsManifest() {
 
 function setPackageInfoEventListener() {
   var packageEventCallback = {
-    oninstalled: function (packageInfo) {
+    oninstalled: function(packageInfo) {
       console.log(`${TAG} The package ${packageInfo.name} is installed`);
       let app = addD2Ddata(packageInfo.id, packageInfo.appIds[0], packageInfo.name, packageInfo.iconPath);
-      getWebclipsManifestByApp(app);
+      if (app !== null)
+        getWebclipsManifestByApp(app);
       evtEmit.emit("updateapplist", "message", dataApps);
     },
-    onupdated: function (packageInfo) {
+    onupdated: function(packageInfo) {
       console.log(`${TAG} The package ${packageInfo.name} is updated`);
     },
-    onuninstalled: function (packageId) {
+    onuninstalled: function(packageId) {
       console.log(`${TAG} The package ${packageId} is uninstalled`);
       removeD2Ddata(packageId);
       evtEmit.emit("updateapplist", "message", dataApps);
@@ -172,7 +166,7 @@ function getWebClipsList() {
   var result = [];
   var webclips = [];
 
-  dataApps.forEach(function (app) {
+  dataApps.forEach(function(app) {
     webclips = [];
     if (app.webclip && app.webclip.manifest) {
       webclips.push({
@@ -202,7 +196,7 @@ function sendLoginIdAndDeviceName(login_id, device_ip) {
     device_name: device_name,
     device_ip: device_ip
   };
-  xhr.onreadystatechange = function () {
+  xhr.onreadystatechange = function() {
     if (xhr.readyState === xhr.DONE) {
       console.log(`${TAG} xhr text: ${xhr.responseText}`);
       if (xhr.status === 200 || xhr.status === 201) {
@@ -229,13 +223,12 @@ function updateDNSresolver(device_ip) {
 
 function comparePincode(req, res, encrypted) {
   console.log(`${TAG} comparePincode`);
+  console.log(`${TAG} encrypted : ${encrypted}`);
   // Decrypt pincode using private key
   var decrypt = new JSEncryptLib.JSEncrypt();
-  decrypt.setPrivateKey(privateKey);
+  decrypt.setPrivateKey(security.getPrivateKey());
   var decrypted = decrypt.decrypt(encrypted);
-
-  console.log('[WT] input pincode : ' + pincode);
-  console.log('[WT] decrypted : ' + decrypted);
+  console.log(`${TAG} decrypted : ${decrypted}`);
 
   let pincode_passed = decrypted === pincode ? true : false;
   console.log(`${TAG} pincode result : ${pincode_passed}`);
@@ -252,7 +245,7 @@ function generatePinCodeNumber() {
   webapis.postPlainNotification("PIN Code", pinNumber, 10);
 }
 
-var HTTPserverStart = function () {
+var HTTPserverStart = function() {
   evtEmit = new EventEmitter();
   var app = express();
   app.engine('html', require('ejs').renderFile);
@@ -276,19 +269,21 @@ var HTTPserverStart = function () {
     },
   }));
 
-  var sessionChecker = function (req, res, next) {
+  var sessionChecker = function(req, res, next) {
     console.log(`${TAG} url : ${req.url}`);
+    console.log(`${TAG} session : ${JSON.stringify(req.session)}`);
     const rawIp = req.socket.remoteAddress;
     const ip = rawIp.slice(rawIp.lastIndexOf(":") + 1);
     // The pincode page and local connections are allowed without session.
     if (req.session.pincode === undefined &&
-        !req.url.includes('/?id=') &&
+        !req.url.includes('id=') &&
         !req.url.includes('/pincode/') &&
         !non_ip_list.includes(ip)) {
-      console.log(`${TAG} session : ${JSON.stringify(req.session)}`);
+      console.log(`${TAG} Not valid access`);
       res.redirect(401, PUBLIC_DOMAIN);
+    } else {
+      next();
     }
-    next();
   };
 
   if (!MODE_WT)
@@ -310,7 +305,7 @@ var HTTPserverStart = function () {
   g.baseDir = __dirname.split(serverAppId)[0];
   console.log(`${TAG} g.baseDir: ${g.baseDir}`);
 
-  clientRouter.get('/webclip/*', function (req, res) {
+  clientRouter.get('/webclip/*', function(req, res) {
     let file = req.originalUrl.replace('/client/webclip/', '').replace(/\?.+$/, '');
 
     let webclipName = '';
@@ -323,20 +318,21 @@ var HTTPserverStart = function () {
     console.log(`${TAG} webclip name: ${webclipName}`);
 
     // find appId by webclip name
-    let app = dataApps.filter(function (app) {
+    let app = dataApps.filter(function(app) {
       return !!app.webclip && app.webclip.manifest.name === webclipName;
     })[0];
     if (app) {
       appId = app.d2dApp.appPkgID;;
     }
 
+    console.log(`${TAG} root : ${platform_app_path}/${appId}/${TIZEN_WEB_APP_SHARED_RESOURCES}/${WEBCLIP_DIRECTORY}`);
     let options = {
       root: path.join(platform_app_path, appId, TIZEN_WEB_APP_SHARED_RESOURCES, WEBCLIP_DIRECTORY)
     };
 
     // remove weblip name from path
     file = file.replace(webclipName + '/', '');
-    res.sendFile(file, options, function (err) {
+    res.sendFile(file, options, function(err) {
       if (err) {
         console.log(`${TAG} err: ${err}`);
         res.send("err", err);
@@ -346,7 +342,7 @@ var HTTPserverStart = function () {
     });
   });
 
-  clientRouter.get('/updateWebclip', function (req, res) {
+  clientRouter.get('/updateWebclip', function(req, res) {
     console.log(`${TAG} get(/updateWebclip)`);
     var apps = getWebClipsList();
     var result = {
@@ -359,7 +355,7 @@ var HTTPserverStart = function () {
     res.send(result);
   });
 
-  clientRouter.get('/*', function (req, res) {
+  clientRouter.get('/*', function(req, res) {
     let file = req.originalUrl.replace('/client/', '').replace(/\?.+$/, '');
     let pkgId = webapis.getPackageId();
     let fullPath = require('path').join(g.baseDir, pkgId, '/res/wgt/client', file);
@@ -367,21 +363,18 @@ var HTTPserverStart = function () {
     res.sendFile(fullPath);
   });
 
-  app.get('/', function (req, res) {
+  app.get('/', function(req, res) {
     console.log(`${TAG} URL parameter : ${req.originalUrl}`);
     urlParam = req.originalUrl;
 
     if (!MODE_WT) {
-      // Getnerate pincode
-      const crypto = require('crypto');
-      var byteData = crypto.randomBytes(256);
-      pincode = parseInt(byteData.toString('hex').substr(0, 8), 16).toString().substr(0, 4);
-      webapis.postPlainNotification("PIN Code", pincode, 10);
       res.redirect("/pincode/pincode.html");
     } else {
       if (req.query.roomId !== undefined) {
-        res.redirect("/client/invited.html");
+        // FIXME: Remove app logic here
+        res.render("client/invited.html");
       } else {
+        // Device home
         res.render("client/client.html");
       }
     }
@@ -407,16 +400,26 @@ var HTTPserverStart = function () {
     });
   });
 
-  app.get('/pincode/publicKey', (req, res) => {
-    // Send public key
-    res.send(publicKey);
+  app.get('/pincode/publicKey', async (req, res) => {
+    // Getnerate pincode
+    var byteData = crypto.randomBytes(256);
+    pincode = parseInt(byteData.toString('hex').substr(0, 8), 16).toString().substr(0, 4);
+    // Getnerate RSA keys
+    await security.awaitKeyPair();
+    // Show pincode popup
+    webapis.postPlainNotification("Input Pincode: ", pincode, 10);
+
+    const key = security.getPublicKey();
+    console.log(`${TAG} Send public key`);
+    res.send(key);
   });
 
-  app.post('/pincode/pinCodeToServer', (req, res) => {
-    console.log(`${TAG} pinCodeToServer`);
+  app.post('/pincode/pinCodeToServer', express.json(), (req, res) => {
     var revData = JSON.stringify(req.body);
     var resultData = revData.replace(/"/g, "").replace(/{/g, "").replace(/}/g, "").replace(/:/g, "").replace(/[\s]/g, "+");
     // Verify encrypted pincode
+    resultData = req.body['pincode'];
+    console.log(`${TAG} pinCodeToServer resultData : ${resultData}`);
     comparePincode(req, res, resultData);
   });
 
@@ -434,10 +437,6 @@ var HTTPserverStart = function () {
     generatePinCodeNumber();
   });
 
-  app.get('/getRoomId', (req, res) => {
-    res.send(urlParam);
-  });
-
   // receive data or cmd to app on device
   app.post('/app', (req, res) => {
     res.send({
@@ -453,7 +452,7 @@ var HTTPserverStart = function () {
   });
 
   httpserver = http.createServer(app);
-  httpserver.listen(g.port, function () {
+  httpserver.listen(g.port, function() {
     var interfaces = require('os').networkInterfaces();
     for (var devName in interfaces) {
       if (interfaces.hasOwnProperty(devName)) {
@@ -469,19 +468,19 @@ var HTTPserverStart = function () {
   relayServer(httpserver);
 };
 
-module.exports.getUrlParam = function () {
+module.exports.getUrlParam = function() {
   console.log(`${TAG} getUrlParam is called`);
   return urlParam;
 };
 
-module.exports.onStart = function () {
+module.exports.onStart = function() {
   getAppList();
   HTTPserverStart();
   setPackageInfoEventListener();
   console.log(`${TAG} onStart is called in DNS Resolver`);
 };
 
-module.exports.onStop = function () {
+module.exports.onStop = function() {
   if (httpserver) {
     httpserver.close();
     console.log(`${TAG} Server Terminated`);