From 225be4ad6139c240799ba34947aded2808519696 Mon Sep 17 00:00:00 2001 From: rdkartono Date: Tue, 17 Dec 2024 16:08:39 +0700 Subject: [PATCH] Working ! 06/12/2024 --- Properties/config.properties | 4 +- WebContentt/public/assets/js/app.js | 360 ++++++++++++---------------- WebContentt/public/index.html | 10 +- WebContentt/public/login.html | 6 +- WebContentt/public/setting.html | 16 +- src/Main.java | 103 ++++---- src/SBC/DiskInfo.java | 13 + src/SBC/SystemInformation.java | 36 +++ src/SIP/jSIPClient.java | 1 - src/Webpage/AllSetting.java | 10 + src/Webpage/SocketioResponse.java | 26 +- src/Webpage/SocketioServer.java | 24 +- src/Webpage/WebServer.java | 101 +++++++- src/code/common.java | 44 +++- tinylog.properties | 4 + 15 files changed, 464 insertions(+), 294 deletions(-) create mode 100644 src/SBC/DiskInfo.java create mode 100644 src/Webpage/AllSetting.java create mode 100644 tinylog.properties diff --git a/Properties/config.properties b/Properties/config.properties index 3e48dfd..489f2ce 100644 --- a/Properties/config.properties +++ b/Properties/config.properties @@ -4,4 +4,6 @@ WebListenPort = 8080 SipServer=192.168.10.2 SipPort=5060 SipUsername=101 -SipPassword=password101 \ No newline at end of file +SipPassword=password101 +AudioInputDevice=Default +AudioOutputDevice=Default diff --git a/WebContentt/public/assets/js/app.js b/WebContentt/public/assets/js/app.js index 2bb0c80..5841b73 100644 --- a/WebContentt/public/assets/js/app.js +++ b/WebContentt/public/assets/js/app.js @@ -1,232 +1,170 @@ let socket; -let index_setinterval; -/** - * Executed when document is ready - */ -$(document).ready(function(){ - socket = io(":9092/socketio"); - socket.on("connect", () => {console.log("Connected to server")}); - socket.on("disconnect", (reason) => {console.log("Disconnected from server because of " + reason)}); -}); -/** - * Executed when index page is loaded - */ function indexload(){ console.log("Index loaded"); - index_setinterval = setInterval(()=>{ - if (socket.connected){ - $("#sipStatus").css("color", "green"); - $("#cpuStatus").css("color", "green"); - $("#ramStatus").css("color", "green"); - $("#storageStatus").css("color", "green"); - $("#networkStatus").css("color", "green"); - $("#dialButton").prop("disabled", false); - $("#hangupButton").prop("disabled", false); - $("#dialNumber").prop("disabled",false); - } else { - $("#sipStatus").text("Not connected to server").css("color", "red"); - $("#cpuStatus").text("Not connected to server").css("color", "red"); - $("#ramStatus").text("Not connected to server").css("color", "red"); - $("#storageStatus").text("Not connected to server").css("color", "red"); - $("#networkStatus").text("Not connected to server").css("color", "red"); - $("#dialButton").prop("disabled", true); - $("#hangupButton").prop("disabled", true); - $("#dialNumber").prop("disabled", true); + socket = io.connect(':9092/socketio'); + + let intervalhandle; + socket.on('connect', function() { + console.log("Connected, id: " + socket.id); + intervalhandle = setInterval(function(){ + socket.emit('command', requestdata('getCpuInfo',''), (response)=>{ + let data = isSuccess(response); + if (data) { + let cpuUsage = JSON.parse(data.cpuUsage); + $('#cpuStatus').text('Temp: ' + data.cpuTemperature + ' °C, Usage: ' + cpuUsage.cpu + '%'); + } + }); + socket.emit('command', requestdata('getRamInfo','') , (response)=>{ + let data = isSuccess(response); + if (data) { + $('#ramStatus').text('Total: ' + data.totalKB + ' , Free: ' + data.availableKB + ' , Usage: ' + data.usedKB); + } + }); + socket.emit('command', requestdata('getSipStatus',''), (response)=>{ + let data = isSuccess(response); + if (data) { + $('#sipStatus').text(data); + } + }); + socket.emit('command', requestdata('getNetworkInfo',''), (response)=>{ + let data = isSuccess(response); + if (data) { + let txmap = JSON.parse(data.txmap); + let rxmap = JSON.parse(data.rxmap); + $('#networkStatus').text('TX: '+txmap.eth0+', RX: '+rxmap.eth0); + } + }); + socket.emit('command', requestdata('getDiskInfo',''), (response)=>{ + let data = isSuccess(response); + if (data) { + $('#storageStatus').text('Total: ' + data.total + ' , Free: ' + data.free); + } + }); + }, 5000); + }); + socket.on('disconnect', function() { + console.log("Disconnected"); + clearInterval(intervalhandle); + }); + + +} + +/** + * Create Socketio RequestData + * @param {string} request + * @param {string }data + * @returns JsonObject + */ +function requestdata(request, data){ + return {request: request, data: data}; +} + +/** + * Check if response is success + * @param {Object} value response data to check + * @return {null} if failed, Object if success + */ +function isSuccess(value){ + if (value){ + if (value.hasOwnProperty('response') && value.hasOwnProperty('data')){ + if (value.response && value.response.length>0){ + if (value.response==='success'){ + let len = value.data.length; + if (len>0){ + if (value.data[0]==='{'){ + if (value.data[len-1]==='}'){ + return JSON.parse(value.data); + } + } + } + return value.data; + } + } } - }, 2000); + + } + return null; } -/** - * Executed when index page is unloaded - */ -function indexunload(){ - console.log("Index unloaded"); - clearInterval(index_setinterval); +function dialClick(){ + console.log("Dial clicked"); + let number = $('#dialNumber').val(); + if (socket && socket.connected) socket.emit('command', requestdata('dial',number), (response)=>{ + console.log("Dial response: "+response); + }); +} + +function hangupClick(){ + console.log("Hangup clicked"); + if (socket && socket.connected) socket.emit('command', requestdata('hangup',''), (response)=>{ + console.log("Hangup response: "+response); + }); } -/** - * Executed when setting page is loaded - */ function settingload(){ console.log("Setting loaded"); - if (socket.connected){ - $("#btnSaveLogin") - .prop("disabled", false) - .on("click", () =>{ - let username = $("#webUsername").text(); - let password = $("#webPassword").text(); - if (isValidString(username) && isValidString(password)){ - setLogin(username, password); - } else { - alert("Please enter valid username and password"); - } - }); - $("#btnSaveSIP") - .prop("disabled", false) - .on("click", () =>{ - let server = $("#sipServer").text(); - let port = $("#sipPort").text(); - let username = $("#sipUsername").text(); - let password = $("#sipPassword").text(); - if (isValidString(server) && isValidPort(port) && isValidString(username) && isValidString(password)){ - setSipSetting(server, port, username, password); - } else { - alert("Please enter valid server, port, username and password"); - } - }); - getLogin(); - getSipSetting(); - } else { - $("#webUsername").text("Not connected to server").css("color", "red"); - $("#webPassword").text("Not connected to server").css("color", "red"); - $("#sipServer").text("Not connected to server").css("color", "red"); - $("#sipPort").text("Not connected to server").css("color", "red"); - $("#sipUsername").text("Not connected to server").css("color", "red"); - $("#sipPassword").text("Not connected to server").css("color", "red"); - $("#btnSaveLogin").prop("disabled", true); - $("#btnSaveSIP").prop("disabled", true); - } - - /** - * Get LoginUsername and LoginPassword data from server - */ - function getLogin(){ - socket.emit( - "command", - {request: "getLogin", data:""}, - (reply)=>{ - if (reply.response==="success"){ - /** - * @type {Object} - * @property {string} Username - * @property {string} Password - */ - let data = JSON.parse(reply.data); - $("#webUsername").text(data.Username).css("color", "black"); - $("#webPassword").text(data.Password).css("color", "black"); - } else { - $("#webUsername").text("Error").css("color", "red"); - $("#webPassword").text("Error").css("color", "red"); - } - } - ); - } - - /** - * Set LoginUsername and LoginPassword data to server - * - * @param {string} username Login Username - * @param {string} password Login Password - */ - function setLogin(username, password){ - socket.emit( - "command", - {request: "setLogin", data:JSON.stringify({Username:username, Password:password})}, - (reply)=>{ - if (reply.response==="success"){ - alert("Login saved successfully"); - } else { - alert("Failed to save login"); - } - }); - } - - /** - * Get SIP Setting data from server - */ - function getSipSetting(){ - socket.emit( - "command", - {request: "getSipSetting", data:""}, - (reply)=>{ - if (reply.response==="success"){ - /** - * @type {Object} - * @property {string} Server - * @property {number} Port - * @property {string} Username - * @property {string} Password - */ - let data = JSON.parse(reply.data); - $("#sipServer").text(data.Server).css("color", "black"); - $("#sipPort").text(data.Port).css("color", "black"); - $("#sipUsername").text(data.Username).css("color", "black"); - $("#sipPassword").text(data.Password).css("color", "black"); - } else { - $("#sipServer").text("Error").css("color", "red"); - $("#sipPort").text("Error").css("color", "red"); - $("#sipUsername").text("Error").css("color", "red"); - $("#sipPassword").text("Error").css("color", "red"); - } - } - ); - } - - /** - * Set SIP Setting data to server - * @param {string} server - * @param {number} port - * @param {string} username - * @param {string} password - */ - function setSipSetting(server, port, username, password){ - socket.emit( - "command", - {request: "setSipSetting", data:JSON.stringify({Server:server, Port:port, Username:username, Password:password})}, - (reply)=>{ - if (reply.response==="success"){ - alert("SIP setting saved successfully"); - } else { - alert("Failed to save SIP setting"); - } - } - ) + if (socket && socket.connected) { + socket.disconnect(); } + fetch('/setting', {method: 'GET'}).then((response)=>{ + response.json().then((data)=>{ + //console.log(JSON.stringify(data)); + $('#webUsername').val(data.loginSetting.Username); + $('#webPassword').val(data.loginSetting.Password); + $('#sipServer').val(data.sipSetting.Server); + $('#sipPort').val(data.sipSetting.Port); + $('#sipUsername').val(data.sipSetting.Username); + $('#sipPassword').val(data.sipSetting.Password); + }); + }); } -/** - * Executed when setting page unloaded - */ -function settingunload(){ - console.log("Setting unloaded"); +function sendLoginData(){ + console.log("Send login data"); + let loginData = { + Username: $('#webUsername').val(), + Password: $('#webPassword').val() + }; + fetch('/logindata', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(loginData) + }).then((response)=>{ + response.text().then((msg)=>{ + alert(msg); + }); + }); +} + +function sendSipData(){ + console.log("Send SIP data"); + let sipData = { + Server: $('#sipServer').val(), + Port: $('#sipPort').val(), + Username: $('#sipUsername').val(), + Password: $('#sipPassword').val() + }; + fetch('/sipdata', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(sipData) + }).then((response)=>{ + response.text().then((msg)=>{ + alert(msg); + }); + }); } -/** - * Executed when login page is loaded - */ function loginload(){ console.log("Login loaded"); -} - -/** - * Executed when login page is unloaded - */ -function loginunload(){ - console.log("Login unloaded"); -} - -/** - * Check if the string is valid - * @param {string} str String to check - * @return {boolean} True if the string is not empty - */ -function isValidString(str){ - return typeof str === "string" && str.trim().length > 0; -} - -/** - * Check if the port is valid - * @param str {string|number} Port to check - * @return {boolean} True if the port is between 0 and 65535 - */ -function isValidPort(str){ - if (typeof str === "number"){ - return str > 0 && str <= 65535; - } else if (typeof str === "string"){ - let port = parseInt(str); - return port > 0 && port <= 65535; + if (socket && socket.connected) { + socket.disconnect(); } - return false; } \ No newline at end of file diff --git a/WebContentt/public/index.html b/WebContentt/public/index.html index 54be7cd..b8651eb 100644 --- a/WebContentt/public/index.html +++ b/WebContentt/public/index.html @@ -17,7 +17,7 @@ - +
@@ -83,8 +85,8 @@
-
-
+
+
diff --git a/WebContentt/public/login.html b/WebContentt/public/login.html index e550fc2..1768785 100644 --- a/WebContentt/public/login.html +++ b/WebContentt/public/login.html @@ -17,7 +17,7 @@ - +
-
+
@@ -47,7 +49,7 @@
-
@@ -56,14 +58,14 @@
-
+
-
+
@@ -74,7 +76,7 @@
-
diff --git a/src/Main.java b/src/Main.java index ca82728..b853462 100644 --- a/src/Main.java +++ b/src/Main.java @@ -6,7 +6,6 @@ import SIP.jSIPClient; import SIP.javaSipEvents; import Webpage.*; import code.common; -import com.google.gson.JsonSyntaxException; import org.pmw.tinylog.Logger; import java.io.File; @@ -39,16 +38,20 @@ public class Main { private static String SipStatus = "Idle"; private static int cpuTemperature; private static RamInformation ramInformation; + private static DiskInfo diskInformation; private static ProcessorStatus[] previousCpuInfo; private static final Map cpuUsage = new HashMap<>(); private static NetworkTransmitReceiveInfo[] previousNetworkInfo; private static final Map networkTX = new HashMap<>(); private static final Map networkRX = new HashMap<>(); - private static Properties config; + public static Properties config; + + private static Thread sipThread; public static void main(String[] args) { common.ExtractProperties(currentDir,"config.properties", false); config = common.LoadProperties(currentDir,"config.properties"); + common.ExtractProperties(currentDir,"tinylog.properties", false); // Timer Section timer = new Timer(); @@ -78,12 +81,16 @@ public class Main { if (callLight!=null && callLight.isInitialized()) callLight.Close(); if (timer!=null) timer.cancel(); if (system_monitoring_timer!=null) system_monitoring_timer.cancel(); + + // force kill PID + if (webserver!=null) killPID(webserver.getProcessID()); + if (socketioserver!=null) killPID(socketioserver.getProcessID()); })); } private static void SIPClient_Section(){ // initialize pakai thread, biar cepat - new Thread(()->{ + sipThread = new Thread(()->{ client = new jSIPClient(config); // event dari sisi Bass Sound Manager client.SetBassSoundManagerEvent(new BassSoundManagerEvent() { @@ -210,7 +217,8 @@ public class Main { } else Logger.error("No IP Address found, please check your network connection"); } else Logger.error("No network interface found, please check your network connection"); - }).start(); + }); + sipThread.start(); } @@ -219,6 +227,39 @@ public class Main { new Thread(()->{ webserver = new WebServer(config); webserver.Start(); + webserver.setOnLoginSettingChanged(loginsetting ->{ + config.setProperty("WebUsername", loginsetting.Username); + config.setProperty("WebPassword", loginsetting.Password); + SaveProperties(currentDir,"config.properties",config); + }); + webserver.setOnSipSettingChanged(sipsetting ->{ + config.setProperty("SipServer", sipsetting.Server); + config.setProperty("SipPort", String.valueOf(sipsetting.Port)); + config.setProperty("SipUsername", sipsetting.Username); + config.setProperty("SipPassword", sipsetting.Password); + SaveProperties(currentDir,"config.properties",config); + if (client!=null) { + Logger.info("Disconnecting from SIP Server"); + client.Disconnect(); + client = null; + } + if (sipThread!=null){ + try { + Logger.info("Waiting for SIP Thread to finish"); + sipThread.interrupt(); + sipThread.join(); + Logger.info("SIP Thread finished"); + } catch (InterruptedException e) { + Logger.error(e); + } + sipThread = null; + + } + Logger.info("Re-initiate SIP Section"); + // re-initiate SIP Section + SIPClient_Section(); + }); + socketioserver = new SocketioServer("0.0.0.0", 9092); socketioserver.Start(); socketioserver.setOnRequest(req ->{ @@ -227,46 +268,6 @@ public class Main { if (networkLight!=null && networkLight.isInitialized()) networkLight.BlinkON(100); switch(req.getRequest()){ - case "setLogin": - try{ - LoginSetting login = gson.fromJson(req.getData(), LoginSetting.class); - if (ValidString(login.Username) && ValidString(login.Password)){ - config.setProperty("WebUsername", login.Username); - config.setProperty("WebPassword", login.Password); - if (SaveProperties(currentDir,"config.properties",config)){ - resp = new SocketioResponse("success", "Login Setting"); - } else throw new Exception("Failed to save properties"); - } else throw new Exception("Invalid Username or Password"); - } catch (JsonSyntaxException e){ - resp = new SocketioResponse("error", "Invalid JSON"); - } catch (Exception e){ - resp = new SocketioResponse("error", e.getMessage()); - } - break; - case "getLogin": - resp = SocketioResponse.fromLoginSetting("success", new LoginSetting(config.getProperty("WebUsername"), config.getProperty("WebPassword"))); - break; - case "setSipSetting": - try{ - SipSetting sip = gson.fromJson(req.getData(), SipSetting.class); - if (ValidString(sip.Server) && ValidString(sip.Username) && ValidString(sip.Password)){ - config.setProperty("SipServer", sip.Server); - config.setProperty("SipPort", String.valueOf(sip.Port)); - config.setProperty("SipUsername", sip.Username); - config.setProperty("SipPassword", sip.Password); - if (SaveProperties(currentDir,"config.properties",config)){ - resp = new SocketioResponse("success", "SIP Setting"); - } else throw new Exception("Failed to save properties"); - } else throw new Exception("Invalid SIP Setting"); - } catch (JsonSyntaxException e){ - resp = new SocketioResponse("error", "Invalid JSON"); - } catch (Exception e){ - resp = new SocketioResponse("error", e.getMessage()); - } - break; - case "getSipSetting": - resp = SocketioResponse.fromSipSetting("success", new SipSetting(config.getProperty("SipServer"), Integer.parseInt(config.getProperty("SipPort")), config.getProperty("SipUsername"), config.getProperty("SipPassword"))); - break; case "getSipStatus": resp = new SocketioResponse("success", SipStatus); break; @@ -281,6 +282,13 @@ public class Main { resp = new SocketioResponse("error", "Failed to get RAM Information"); } break; + case "getDiskInfo": + if (diskInformation!=null){ + resp = SocketioResponse.fromDiskInfo("success", diskInformation); + } else { + resp = new SocketioResponse("error", "Failed to get Disk Information"); + } + break; case "getCpuInfo": if (cpuTemperature>0 && !cpuUsage.isEmpty()){ resp = SocketioResponse.fromCpuStatus("success", cpuTemperature, cpuUsage); @@ -295,7 +303,7 @@ public class Main { resp = new SocketioResponse("error", "Failed to get Network Information"); } break; - case "call": + case "dial": int extension = ParseInt(req.getData(),-1) ; if (extension>0){ if (Call(""+extension)){ @@ -305,9 +313,7 @@ public class Main { } } else resp = new SocketioResponse("error", "Invalid Extension"); break; - case "getDiskInfo": - resp = new SocketioResponse("error", "Not Implemented"); - break; + default: resp = new SocketioResponse("error", "Invalid Request"); break; @@ -573,6 +579,7 @@ public class Main { public void run() { cpuTemperature = SystemInformation.getCPUTemperature(); ramInformation = SystemInformation.getRAMInformation(); + diskInformation = SystemInformation.getDiskInfo("/"); ProcessorStatus[] cpuinfo = SystemInformation.getProcStat(); if (cpuinfo.length>0){ if (previousCpuInfo==null || !Objects.equals(previousCpuInfo.length, cpuinfo.length)){ diff --git a/src/SBC/DiskInfo.java b/src/SBC/DiskInfo.java new file mode 100644 index 0000000..d5111ae --- /dev/null +++ b/src/SBC/DiskInfo.java @@ -0,0 +1,13 @@ +package SBC; + +public class DiskInfo { + public String path; + public long totalSpace; + public long freeSpace; + public long usableSpace; + + @Override + public String toString(){ + return "path: " + path + ", totalSpace: " + totalSpace + ", freeSpace: " + freeSpace + ", usableSpace: " + usableSpace; + } +} diff --git a/src/SBC/SystemInformation.java b/src/SBC/SystemInformation.java index 8d6541e..dd668b3 100644 --- a/src/SBC/SystemInformation.java +++ b/src/SBC/SystemInformation.java @@ -10,7 +10,43 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class SystemInformation { + static long KB_threshold = 1024; + static long MB_threshold = 1024 * KB_threshold; + static long GB_threshold = 1024 * MB_threshold; + public static String DiskSize_to_String(long value){ + if (value < KB_threshold){ + return value + " B"; + } else if (value < MB_threshold){ + return String.format("%.2f", (double)value / KB_threshold) + " KB"; + } else if (value < GB_threshold){ + return String.format("%.2f", (double)value / MB_threshold) + " MB"; + } else { + return String.format("%.2f", (double)value / GB_threshold) + " GB"; + } + } + + public static String RamKB_to_String(int value){ + if (value < 1024){ + return value + " KB"; + } else if (value < 1024 * 1024){ + return String.format("%.2f", (double)value / 1024) + " MB"; + } else { + return String.format("%.2f", (double)value / (1024 * 1024)) + " GB"; + } + } + + public static DiskInfo getDiskInfo(String path){ + DiskInfo result = new DiskInfo(); + result.path = path; + File ff = new File(path); + if (ff.isDirectory()){ + result.usableSpace = ff.getUsableSpace(); + result.totalSpace = ff.getTotalSpace(); + result.freeSpace = ff.getFreeSpace(); + } + return result; + } public static int getCPUTemperature() { diff --git a/src/SIP/jSIPClient.java b/src/SIP/jSIPClient.java index b1c6e6d..034e8a2 100644 --- a/src/SIP/jSIPClient.java +++ b/src/SIP/jSIPClient.java @@ -1,6 +1,5 @@ package SIP; -import java.net.InetAddress; import java.net.SocketException; import java.util.Properties; import java.util.concurrent.ExecutorService; diff --git a/src/Webpage/AllSetting.java b/src/Webpage/AllSetting.java new file mode 100644 index 0000000..14fe910 --- /dev/null +++ b/src/Webpage/AllSetting.java @@ -0,0 +1,10 @@ +package Webpage; + +public class AllSetting { + public LoginSetting loginSetting; + public SipSetting sipSetting; + public AllSetting(LoginSetting loginSetting, SipSetting sipSetting){ + this.loginSetting = loginSetting; + this.sipSetting = sipSetting; + } +} diff --git a/src/Webpage/SocketioResponse.java b/src/Webpage/SocketioResponse.java index f43e39e..c21cd28 100644 --- a/src/Webpage/SocketioResponse.java +++ b/src/Webpage/SocketioResponse.java @@ -1,12 +1,16 @@ package Webpage; +import SBC.DiskInfo; import SBC.RamInformation; import com.google.gson.JsonObject; import lombok.Getter; import lombok.Setter; +import org.pmw.tinylog.Logger; import java.util.Map; +import static SBC.SystemInformation.DiskSize_to_String; +import static SBC.SystemInformation.RamKB_to_String; import static code.common.gson; @Getter @@ -40,14 +44,34 @@ public class SocketioResponse { public static SocketioResponse fromSipSetting(String response, SipSetting sipSetting){ SocketioResponse socketioResponse = new SocketioResponse(); socketioResponse.setResponse(response); + socketioResponse.setData(gson.toJson(sipSetting)); return socketioResponse; } + public static SocketioResponse fromDiskInfo(String response, DiskInfo diskInfo){ + SocketioResponse socketioResponse = new SocketioResponse(); + socketioResponse.setResponse(response); + + + JsonObject jo = new JsonObject(); + jo.addProperty("total",DiskSize_to_String(diskInfo.totalSpace)); + jo.addProperty("usage",DiskSize_to_String(diskInfo.usableSpace)); + jo.addProperty("free",DiskSize_to_String(diskInfo.freeSpace)); + socketioResponse.setData(jo.toString()); + return socketioResponse; + } + public static SocketioResponse fromRamInformation(String response, RamInformation ramInformation){ SocketioResponse socketioResponse = new SocketioResponse(); socketioResponse.setResponse(response); - socketioResponse.setData(gson.toJson(ramInformation)); + JsonObject jo = new JsonObject(); + + jo.addProperty("totalKB",RamKB_to_String(ramInformation.totalKB)); + jo.addProperty("availableKB",RamKB_to_String(ramInformation.availableKB)); + jo.addProperty("usedKB",RamKB_to_String(ramInformation.usedKB)); + + socketioResponse.setData(jo.toString()); return socketioResponse; } diff --git a/src/Webpage/SocketioServer.java b/src/Webpage/SocketioServer.java index 3fadece..2aa42b9 100644 --- a/src/Webpage/SocketioServer.java +++ b/src/Webpage/SocketioServer.java @@ -3,15 +3,22 @@ package Webpage; import com.corundumstudio.socketio.Configuration; import com.corundumstudio.socketio.SocketIONamespace; import com.corundumstudio.socketio.SocketIOServer; +import lombok.Getter; import lombok.NonNull; import lombok.Setter; import org.pmw.tinylog.Logger; + import java.util.function.Function; + +import static code.common.*; + public class SocketioServer { private final SocketIOServer server; private @Setter Function<@NonNull SocketioRequest, @NonNull SocketioResponse> onRequest; + private @Getter int ProcessID; + /** * Create Socket.io Server @@ -21,8 +28,12 @@ public class SocketioServer { public SocketioServer(String localip,int listenport){ if (localip==null || localip.isEmpty()) localip="0.0.0.0"; if (listenport<=0 || listenport>65535) listenport=9092; + + int PID = GetPID(listenport); + if (PID!=0) killPID(PID); + Configuration config = new Configuration(); - config.setHostname(localip); + //config.setHostname(localip); config.setPort(listenport); server = new SocketIOServer(config); @@ -30,14 +41,20 @@ public class SocketioServer { socketio.addConnectListener(client -> Logger.info("Client id={} remoteaddress={} Connected to /socketio: " , client.getSessionId(), client.getRemoteAddress())); socketio.addDisconnectListener(client -> Logger.info("Client id={} remoteaddress={} Disconnected from /socketio: ", client.getSessionId(), client.getRemoteAddress())); socketio.addEventListener("command", SocketioRequest.class, (client, data, ackRequest) -> { - Logger.info("Client id={} remoteaddress={} request: {}", client.getSessionId(), client.getRemoteAddress(), data); + //Logger.info("Client id={} remoteaddress={} request: {}", client.getSessionId(), client.getRemoteAddress(), data); if (onRequest!=null){ SocketioResponse response = onRequest.apply(data); - Logger.info("Client id={} remoteaddress={} response: {}", client.getSessionId(), client.getRemoteAddress(), response); + //Logger.info("Client id={} remoteaddress={} response: {}", client.getSessionId(), client.getRemoteAddress(), response); ackRequest.sendAckData(response); } }); + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + Logger.info("Shutting down Socket.io Server"); + server.stop(); + })); + + } /** @@ -45,6 +62,7 @@ public class SocketioServer { */ public void Start(){ if (server!=null) server.start(); + ProcessID = GetPID(server.getConfiguration().getPort()); } /** diff --git a/src/Webpage/WebServer.java b/src/Webpage/WebServer.java index adb084a..37b962c 100644 --- a/src/Webpage/WebServer.java +++ b/src/Webpage/WebServer.java @@ -1,23 +1,35 @@ package Webpage; import io.javalin.Javalin; +import io.javalin.http.HttpCode; import io.javalin.http.staticfiles.Location; +import lombok.Getter; +import lombok.Setter; +import org.pmw.tinylog.Logger; import java.util.Objects; import java.util.Properties; +import java.util.function.Consumer; import static code.common.*; public class WebServer { private final Javalin app; private final int listenport; - private final String webusername; - private final String webpassword; + private String webusername; + private String webpassword; + private @Setter Consumer onLoginSettingChanged; + private @Setter Consumer onSipSettingChanged; + private @Getter int ProcessID; + public WebServer(Properties prop) { listenport = GetProperties_IntValue(prop,"WebListenPort", 8080); webusername = GetProperties_StringValue(prop,"WebUsername", "admin"); webpassword = GetProperties_StringValue(prop,"WebPassword", "admin"); + int PID = GetPID(listenport); + if (PID!=0) killPID(PID); + app = Javalin.create(config -> config.addStaticFiles("/public", Location.CLASSPATH)); app.get("/", ctx ->{ if (Objects.equals(ctx.sessionAttribute("username"), webusername)){ @@ -27,18 +39,36 @@ public class WebServer { ctx.redirect("/login.html"); } }); + app.before("/index.html", ctx -> { + if (!Objects.equals(ctx.sessionAttribute("username"), webusername)){ + ctx.redirect("/login.html"); + } + }); + app.before("/setting.html", ctx -> { + if (!Objects.equals(ctx.sessionAttribute("username"), webusername)){ + ctx.redirect("/login.html"); + } + }); app.get("/logout", ctx -> { ctx.sessionAttribute("username", null); ctx.redirect("/login.html"); }); - app.get("/setting", ctx -> { - if (Objects.equals(ctx.sessionAttribute("username"), webusername)){ - //TODO Setting Page - ctx.result("Setting Page"); - } else { + app.before("/setting", ctx -> { + if (!Objects.equals(ctx.sessionAttribute("username"), webusername)){ ctx.redirect("/login.html"); } }); + app.get("/setting", ctx -> { + if (Objects.equals(ctx.sessionAttribute("username"), webusername)) { + AllSetting allSetting = new AllSetting(new LoginSetting(webusername, webpassword), new SipSetting( + GetProperties_StringValue(prop, "SipServer", "sip.example.com"), + GetProperties_IntValue(prop, "SipPort", 5060), + GetProperties_StringValue(prop, "SipUsername", "username"), + GetProperties_StringValue(prop, "SipPassword", "password") + )); + ctx.json(allSetting); + } + }); app.post("/login", ctx -> { String username = ctx.formParam("username"); String password = ctx.formParam("password"); @@ -49,14 +79,60 @@ public class WebServer { ctx.redirect("/login.html"); } }); - app.post("/setting", ctx -> { - if (Objects.equals(ctx.sessionAttribute("username"), webusername)){ - //TODO Setting Page - ctx.result("Setting Page"); - } else { + app.before("/logindata", ctx -> { + if (!Objects.equals(ctx.sessionAttribute("username"), webusername)){ ctx.redirect("/login.html"); } }); + app.post("/logindata", ctx -> { + if (Objects.equals(ctx.sessionAttribute("username"), webusername)){ + LoginSetting value = gson.fromJson(ctx.body(), LoginSetting.class); + Logger.info("Login Data: Username: {}, Password: {}", value.Username, value.Password); + if (ValidString(value.Username)) { + if (ValidString(value.Password)) { + if (value.Username.equals(webusername) && value.Password.equals(webpassword)) { + ctx.result("Same as current login data").status(HttpCode.OK); + } else { + if (onLoginSettingChanged != null) onLoginSettingChanged.accept(value); + webusername = value.Username; + webpassword = value.Password; + ctx.sessionAttribute("username", value.Username); + ctx.result("Login Data Changed").status(HttpCode.OK); + } + } else ctx.result("Invalid Password").status(HttpCode.BAD_REQUEST); + } else ctx.result("Invalid Username").status(HttpCode.BAD_REQUEST); + + } + }); + app.before("/sipdata", ctx -> { + if (!Objects.equals(ctx.sessionAttribute("username"), webusername)){ + ctx.redirect("/login.html"); + } + }); + app.post("/sipdata", ctx -> { + if (Objects.equals(ctx.sessionAttribute("username"), webusername)){ + SipSetting value = gson.fromJson(ctx.body(), SipSetting.class); + Logger.info("SIP Data: Server: {}, Port: {}, Username: {}, Password: {}", value.Server, value.Port, value.Username, value.Password); + if (ValidString(value.Server)) { + if (ValidPortNumber(value.Port)) { + if (ValidString(value.Username)) { + if (ValidString(value.Password)) { + if (value.Username.equals(GetProperties_StringValue(prop, "SipUsername", "101")) && + value.Password.equals(GetProperties_StringValue(prop, "SipPassword", "password101")) && + value.Server.equals(GetProperties_StringValue(prop, "SipServer", "192.168.10.2")) && + value.Port == GetProperties_IntValue(prop, "SipPort", 5060)) { + ctx.result("Same as current SIP data").status(HttpCode.OK); + } else { + if (onSipSettingChanged != null) onSipSettingChanged.accept(value); + ctx.result("SIP Data Changed").status(HttpCode.OK); + } + } else ctx.result("Invalid SIP Password").status(HttpCode.BAD_REQUEST); + } else ctx.result("Invalid SIP Username").status(HttpCode.BAD_REQUEST); + } else ctx.result("Invalid SIP Port").status(HttpCode.BAD_REQUEST); + } else ctx.result("Invalid SIP Server").status(HttpCode.BAD_REQUEST); + + } + }); } /** @@ -64,6 +140,7 @@ public class WebServer { */ public void Start(){ if (app!=null) app.start(listenport); + ProcessID = GetPID(listenport); } /** diff --git a/src/code/common.java b/src/code/common.java index cffab8d..bde935d 100644 --- a/src/code/common.java +++ b/src/code/common.java @@ -8,13 +8,13 @@ import peers.sip.syntaxencoding.SipHeaderFieldName; import peers.sip.syntaxencoding.SipHeaderFieldValue; import peers.sip.syntaxencoding.SipHeaders; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; +import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class common { public static String currentDir = System.getProperty("user.dir"); @@ -26,6 +26,44 @@ public class common { public static final double MB_threshold = 1024.0 * 1024.0; public static final double GB_threshold = 1024.0 * 1024.0 * 1024.0; + public static int GetPID(int listenport){ + final String regex = ".*?:"+listenport+".*?LISTEN.*?(\\d+)/java"; + final Pattern pattern = Pattern.compile(regex); + int PID = 0; + + try{ + Process p = Runtime.getRuntime().exec("netstat -nlp | grep :"+listenport); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + Matcher matcher = pattern.matcher(line); + if (matcher.find()) { + PID = Integer.parseInt(matcher.group(1)); + System.out.println("PID: "+PID); + break; + } + } + } + } catch (Exception e){ + Logger.error("Failed to get PID on port {}, Message : ", listenport, e.getMessage()); + } + + return PID; + + } + + public static void killPID(int PID){ + try{ + if (PID!=0){ + Process pkill = Runtime.getRuntime().exec("kill -9 "+PID); + pkill.waitFor(); + Logger.info("Killed PID {}", PID); + } + } catch (Exception e){ + Logger.error("Failed to kill PID {}, Message : ", PID, e.getMessage()); + } + } + public static int RandomInt(int min, int max){ return (int) (Math.random() * (max - min + 1) + min); } diff --git a/tinylog.properties b/tinylog.properties new file mode 100644 index 0000000..0c4bb17 --- /dev/null +++ b/tinylog.properties @@ -0,0 +1,4 @@ +exception = unpack, strip: jdk.internal +writer = console +writer.exception = drop cause +writer.format = {date:dd-MM-yyyy HH:mm:ss} {class}.{method}() \ No newline at end of file