diff --git a/modules/java/dicom-java-lib/compile.sh b/modules/java/dicom-java-lib/compile.sh new file mode 100755 index 0000000..f84656f --- /dev/null +++ b/modules/java/dicom-java-lib/compile.sh @@ -0,0 +1,16 @@ +#!/bin/sh +CP="../java-examples/lib/*:classes" +SP=src/ + +/bin/rm -f ../xtrabytes-dicom.jar +/bin/rm -rf classes +/bin/mkdir -p classes/ + +javac -encoding utf8 -sourcepath "${SP}" -classpath "${CP}" -d classes/ src/*.java || exit 1 + +echo "XtraBYtes DICOM java library compiled successfully" + +jar cf ../java-examples/lib/xtrabytes-dicom.jar -C classes . || exit 1 +/bin/rm -rf classes + +echo "XtraBYtes DICOM java library generated successfully" diff --git a/modules/java/dicom-java-lib/src/XtraBYtesDICOM.java b/modules/java/dicom-java-lib/src/XtraBYtesDICOM.java new file mode 100644 index 0000000..c8235eb --- /dev/null +++ b/modules/java/dicom-java-lib/src/XtraBYtesDICOM.java @@ -0,0 +1,167 @@ +package XtraBYtes; + +import XtraBYtes.XtraBYtesDservlet; +import XtraBYtes.XtraBYtesDsignals; + +import java.io.IOException; + +import org.json.simple.JSONObject; +import org.json.simple.JSONArray; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.AbstractHandler; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.ResourceHandler; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.servlet.ServletContextHandler; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class XtraBYtesDICOM extends XtraBYtesDsignals { + + public String ViewPageOverviewContent() { return ""; } + + private static long HeartbeatTimestamp = 0; + + public static void UpdateHeartbeatTimestamp(long timestamp) { + HeartbeatTimestamp = timestamp; + } + + private String AcceptedMSG = "Module accepted"; + private String AcceptedMSG2 = "STOP FLOOD!"; + + private JSONObject ModuleConnectionRequest = new JSONObject(); + + private Server DICOMserver; + + // 0 = Invalid 1 = Connected 2 = Disconnected + private int ModuleStatus=0; + + private boolean ModuleWatchdogStarted = false; + + private ScheduledExecutorService CronThreads = Executors.newScheduledThreadPool(1); + + private final Runnable ModuleWatchdog = new Runnable() { + public void run() { + if (( ModuleStatus == 1 ) && ((System.currentTimeMillis()-HeartbeatTimestamp)>2000)) { + ModuleStatus = 2; + System.out.print("Connection lost. Reconnecting."); + reconnect(); + } + } + }; + + public boolean connect(String ModuleName, String ModuleID, int ModulePort, String[] Signals){ + + if (!ModuleWatchdogStarted) { + CronThreads.scheduleWithFixedDelay(ModuleWatchdog, 0, 1, TimeUnit.SECONDS); + ModuleWatchdogStarted = true; + } + + ModuleConnectionRequest.put("DICOM","Module-Registration"); + ModuleConnectionRequest.put("module-name",ModuleName); + ModuleConnectionRequest.put("module-id",ModuleID); + ModuleConnectionRequest.put("dicom-port",ModulePort); + JSONArray signal_wrapper = new JSONArray(); + for (String signal: Signals) { + signal_wrapper.add(signal); + } + ModuleConnectionRequest.put("signals",signal_wrapper); + + while (true) { + XtraBYtesDservlet listenner = new XtraBYtesDservlet(); + JSONObject response = listenner.SendJsonQuery(ModuleConnectionRequest); + if ((AcceptedMSG.equals((String)response.get("DICOM"))) || (AcceptedMSG2.equals((String)response.get("DICOM")))) { + System.out.println("OK"); + DICOMserver = new Server(); + ServerConnector connector; + connector = new ServerConnector(DICOMserver); + + connector.setPort(ModulePort); + connector.setHost("127.0.0.1"); + connector.setIdleTimeout(15000); + connector.setReuseAddress(true); + DICOMserver.addConnector(connector); + + HandlerList DICOMHandlers = new HandlerList(); + + ServletContextHandler DICOMHandler = new ServletContextHandler(); + + DICOMHandler.addServlet(XtraBYtesDservlet.class, "/dicom"); + + DICOMHandlers.addHandler(DICOMHandler); + + DICOMHandlers.addHandler(new DefaultHandler()); + + DICOMserver.setHandler(DICOMHandlers); + DICOMserver.setStopAtShutdown(true); + + try { + HeartbeatTimestamp = System.currentTimeMillis(); + DICOMserver.start(); + System.out.println(ModuleName + " DICOM server started at " + ModulePort + " port."); + ModuleStatus = 1; + return true; + } catch (Exception e) { + System.out.println("Failed to start DICOM server."); + return false; + } + + } // if + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { } + System.out.print("."); + } + } + + private void reconnect() { + while (true) { + XtraBYtesDservlet listenner = new XtraBYtesDservlet(); + JSONObject response = listenner.SendJsonQuery(ModuleConnectionRequest); + if ((AcceptedMSG.equals((String)response.get("DICOM"))) || (AcceptedMSG2.equals((String)response.get("DICOM")))) { + System.out.println("Reconnected."); + ModuleStatus = 1; + HeartbeatTimestamp = System.currentTimeMillis(); + return; + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { } + System.out.print("."); + } + } + + public void startDICOM(String ModuleName, String ModuleID, int ModulePort, String[] Signals){ + + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + shutdown(); + } + })); + + try { + System.out.println("*** Starting XtraBYtes module."); + if (!connect( ModuleName, ModuleID, ModulePort, Signals )) throw new Exception("Module registration failed."); + System.out.println("*** XtraBYtes module started successfully."); + } catch (Exception e) { + System.out.println("*** ERROR: "+e.toString()); + System.out.println("*** XtraBYtes module start FAILED."); + } + + } + + public void shutdown() { + CronThreads.shutdown(); + System.out.println("*** XtraBYtes module stopped."); + } + +} \ No newline at end of file diff --git a/modules/java/dicom-java-lib/src/XtraBYtesDservlet.java b/modules/java/dicom-java-lib/src/XtraBYtesDservlet.java new file mode 100644 index 0000000..cf44e75 --- /dev/null +++ b/modules/java/dicom-java-lib/src/XtraBYtesDservlet.java @@ -0,0 +1,129 @@ +package XtraBYtes; + +import XtraBYtes.XtraBYtesDICOM; + +import org.json.simple.JSONObject; +import org.json.simple.JSONArray; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.io.*; +import java.io.IOException; + +import javax.servlet.http.*; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; + +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.util.StringContentProvider; + +import java.net.*; +import java.net.InetSocketAddress; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.MalformedURLException; + + +public class XtraBYtesDservlet extends HttpServlet { + + public void doGet(HttpServletRequest request, HttpServletResponse response) + + throws ServletException, IOException { + response.setContentType("text/html"); + PrintWriter ServletOutputStream = response.getWriter(); + ServletOutputStream.println("

" + "The specified method is not allowed." + "

"); + } + + public void doPost(HttpServletRequest request, HttpServletResponse response) + + throws ServletException, IOException { + JSONObject JsonRequest = new JSONObject(); + try { + JsonRequest = (JSONObject)new JSONParser().parse(request.getReader()); + + } catch (ParseException e) { e.printStackTrace(); } + + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate, private"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 0); + response.setContentType("text/plain; charset=UTF-8"); + + JSONObject JsonResponse = new JSONObject(); + + switch ( (String) JsonRequest.get("DICOM") ) { + case "Heartbeat-Echo-Request": { + JsonResponse = DICOM_HeartbeatReq(JsonRequest); + } break; + case "view-page-overview-content": { + JsonResponse = DICOM_ViewPageOverviewContent(JsonRequest); + } break; + + default: { + JsonResponse.put("error","Bad requestType."); + } break; + } + + response.setContentType("text"); + PrintWriter ServletOutputStream = response.getWriter(); + + ServletOutputStream.print(JsonResponse.toString()); + } + + public synchronized JSONObject SendJsonQuery(JSONObject request) { + + JSONObject JSONresponse = new JSONObject(); + + try { + HttpClient client = new HttpClient(); + client.setBindAddress(new InetSocketAddress( InetAddress.getByName("127.0.0.1") , 0 )); + client.start(); + ContentResponse response = client.POST("http://127.0.0.1:3344/dicom") + .content(new StringContentProvider(request.toString()) , "application/json; charset=UTF-8") + .send(); + client.stop(); + if ( response.getStatus() == HttpURLConnection.HTTP_OK ) { + try { + JSONresponse = (JSONObject)new JSONParser().parse(response.getContentAsString()); + } catch (Exception e) { + JSONresponse.put("Error","Failed parsing returned JSON object."); + } + } + } catch (Exception e) { + JSONresponse.put("Error","Communication error."); + } + + return JSONresponse; + } + + + private JSONObject DICOM_HeartbeatReq( JSONObject JsonRequest ) { + + JSONObject response = new JSONObject(); + + try { + response.put("DICOM", "Heartbeat-Echo-Reply"); + XtraBYtesDICOM.UpdateHeartbeatTimestamp(System.currentTimeMillis()); + } catch (Exception e) { + response.put("error",1); + } + + return response; + } + + + public JSONObject DICOM_ViewPageOverviewContent( JSONObject JsonRequest ) { + + JSONObject response = new JSONObject(); + + try { + response.put("DICOM", "view-page-overview-content"); + response.put("view-page-overview-content", XtraBYtesDICOM.getSignalHandler().ViewPageOverviewContent()); + } catch (Exception e) { + response.put("error",1); + } + + return response; + } + +} diff --git a/modules/java/dicom-java-lib/src/XtraBYtesDsignals.java b/modules/java/dicom-java-lib/src/XtraBYtesDsignals.java new file mode 100644 index 0000000..6af462b --- /dev/null +++ b/modules/java/dicom-java-lib/src/XtraBYtesDsignals.java @@ -0,0 +1,21 @@ +package XtraBYtes; + +import XtraBYtes.XtraBYtesDICOM; + +import org.json.simple.JSONObject; + +public abstract class XtraBYtesDsignals { + + protected static XtraBYtesDsignals SignalHandler; + + public static XtraBYtesDsignals getSignalHandler() { + return SignalHandler; + } + + public void setSignalHandler(XtraBYtesDsignals sh) { + SignalHandler = sh; + } + + public abstract String ViewPageOverviewContent(); + +} \ No newline at end of file diff --git a/modules/java/java-examples/example1/compile.sh b/modules/java/java-examples/example1/compile.sh new file mode 100755 index 0000000..7ecd6da --- /dev/null +++ b/modules/java/java-examples/example1/compile.sh @@ -0,0 +1,16 @@ +#!/bin/sh +CP="../lib/*:classes" +SP=src/ + +/bin/rm -f example1.jar +/bin/rm -rf classes +/bin/mkdir -p classes/ + +javac -encoding utf8 -sourcepath "${SP}" -classpath "${CP}" -d classes/ src/*.java || exit 1 + +echo "XtraBYtes example1 module compiled." + +jar cf example1.jar -C classes . || exit 1 +/bin/rm -rf classes + +echo "The xtrabytes-example1.jar generated successfully." diff --git a/modules/java/java-examples/example1/example1.jar b/modules/java/java-examples/example1/example1.jar new file mode 100644 index 0000000..bf292aa Binary files /dev/null and b/modules/java/java-examples/example1/example1.jar differ diff --git a/modules/java/java-examples/example1/run.bat b/modules/java/java-examples/example1/run.bat new file mode 100644 index 0000000..97c9c9b --- /dev/null +++ b/modules/java/java-examples/example1/run.bat @@ -0,0 +1,7 @@ +@ECHO OFF +IF EXIST java ( + start "XTRABYTES EXAMPLE1" java -cp example1.jar;lib\* XtraBYtes.Example1 +) ELSE ( + ECHO Java software not found on your system. Please go to http://java.com/en/ to download a copy of Java. +) + diff --git a/modules/java/java-examples/example1/run.sh b/modules/java/java-examples/example1/run.sh new file mode 100755 index 0000000..be05628 --- /dev/null +++ b/modules/java/java-examples/example1/run.sh @@ -0,0 +1,2 @@ +#!/bin/sh +java -cp example1.jar:../lib/* XtraBYtes.Example1 diff --git a/modules/java/java-examples/example1/src/Example1.java b/modules/java/java-examples/example1/src/Example1.java new file mode 100644 index 0000000..9808188 --- /dev/null +++ b/modules/java/java-examples/example1/src/Example1.java @@ -0,0 +1,30 @@ +package XtraBYtes; + +import XtraBYtes.XtraBYtesDsignals; +import XtraBYtes.XtraBYtesDICOM; + +public class Example1 { + + public static class XBYsignals extends XtraBYtesDsignals { + + public String ViewPageOverviewContent() { + return "Hello XtraBYtes ;-)"; + } + + } + + public static void main(String[] args) { + + XtraBYtesDICOM module = new XtraBYtesDICOM(); + module.setSignalHandler((XtraBYtesDsignals)new XBYsignals()); + module.startDICOM( + "Example1 Module", // Module name + "example1", // Module ID + 10001, // Module DICOM port + new String[]{ // Signals + "view-page-overview-content" + } + ); + } + +} diff --git a/modules/java/java-examples/example2/compile.sh b/modules/java/java-examples/example2/compile.sh new file mode 100755 index 0000000..b51bbfc --- /dev/null +++ b/modules/java/java-examples/example2/compile.sh @@ -0,0 +1,16 @@ +#!/bin/sh +CP="../lib/*:classes" +SP=src/ + +/bin/rm -f example2.jar +/bin/rm -rf classes +/bin/mkdir -p classes/ + +javac -encoding utf8 -sourcepath "${SP}" -classpath "${CP}" -d classes/ src/*.java || exit 1 + +echo "XtraBYtes example2 module compiled." + +jar cf example2.jar -C classes . || exit 1 +/bin/rm -rf classes + +echo "The example2.jar generated successfully." diff --git a/modules/java/java-examples/example2/example2.jar b/modules/java/java-examples/example2/example2.jar new file mode 100644 index 0000000..1839745 Binary files /dev/null and b/modules/java/java-examples/example2/example2.jar differ diff --git a/modules/java/java-examples/example2/run.bat b/modules/java/java-examples/example2/run.bat new file mode 100644 index 0000000..8c880b3 --- /dev/null +++ b/modules/java/java-examples/example2/run.bat @@ -0,0 +1,7 @@ +@ECHO OFF +IF EXIST java ( + start "XTRABYTES EXAMPLE2" java -cp example2.jar;lib\* XtraBYtes.Example2 +) ELSE ( + ECHO Java software not found on your system. Please go to http://java.com/en/ to download a copy of Java. +) + diff --git a/modules/java/java-examples/example2/run.sh b/modules/java/java-examples/example2/run.sh new file mode 100755 index 0000000..0addbc4 --- /dev/null +++ b/modules/java/java-examples/example2/run.sh @@ -0,0 +1,2 @@ +#!/bin/sh +java -cp example2.jar:../lib/* XtraBYtes.Example2 diff --git a/modules/java/java-examples/example2/src/Example2.java b/modules/java/java-examples/example2/src/Example2.java new file mode 100644 index 0000000..fa915c2 --- /dev/null +++ b/modules/java/java-examples/example2/src/Example2.java @@ -0,0 +1,39 @@ +package XtraBYtes; + +import XtraBYtes.XtraBYtesDsignals; +import XtraBYtes.XtraBYtesDICOM; + +import java.util.Calendar; + +public class Example2 { + + public static class XBYsignals extends XtraBYtesDsignals { + + public String ViewPageOverviewContent() { + + Calendar cal = Calendar.getInstance(); + int hour = cal.get( Calendar.HOUR_OF_DAY ); + + if( hour > 5 && hour < 12 ) return "Good morning XBY!"; + if( hour > 11 && hour < 17 ) return "Good afternoon XBY!"; + if( hour > 17 && hour < 19 ) return "Good evening XBY!"; + return "Good night XBY!"; + + } + } + + public static void main(String[] args) { + + XtraBYtesDICOM module = new XtraBYtesDICOM(); + module.setSignalHandler((XtraBYtesDsignals)new XBYsignals()); + module.startDICOM( + "Example2 Module", // Module name + "example2", // Module ID + 10002, // Module DICOM port + new String[]{ // Signals + "view-page-overview-content" + } + ); + } + +} diff --git a/modules/java/java-examples/lib/jetty-client-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-client-9.2.13.v20150730.jar new file mode 100644 index 0000000..30e2a92 Binary files /dev/null and b/modules/java/java-examples/lib/jetty-client-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/jetty-continuation-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-continuation-9.2.13.v20150730.jar new file mode 100644 index 0000000..a04051f Binary files /dev/null and b/modules/java/java-examples/lib/jetty-continuation-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/jetty-http-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-http-9.2.13.v20150730.jar new file mode 100644 index 0000000..e6ca1ed Binary files /dev/null and b/modules/java/java-examples/lib/jetty-http-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/jetty-io-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-io-9.2.13.v20150730.jar new file mode 100644 index 0000000..3fd1d18 Binary files /dev/null and b/modules/java/java-examples/lib/jetty-io-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/jetty-security-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-security-9.2.13.v20150730.jar new file mode 100644 index 0000000..92428c3 Binary files /dev/null and b/modules/java/java-examples/lib/jetty-security-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/jetty-server-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-server-9.2.13.v20150730.jar new file mode 100644 index 0000000..070ef00 Binary files /dev/null and b/modules/java/java-examples/lib/jetty-server-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/jetty-servlet-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-servlet-9.2.13.v20150730.jar new file mode 100644 index 0000000..46604e1 Binary files /dev/null and b/modules/java/java-examples/lib/jetty-servlet-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/jetty-servlets-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-servlets-9.2.13.v20150730.jar new file mode 100644 index 0000000..311a6a0 Binary files /dev/null and b/modules/java/java-examples/lib/jetty-servlets-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/jetty-util-9.2.13.v20150730.jar b/modules/java/java-examples/lib/jetty-util-9.2.13.v20150730.jar new file mode 100644 index 0000000..93e97ad Binary files /dev/null and b/modules/java/java-examples/lib/jetty-util-9.2.13.v20150730.jar differ diff --git a/modules/java/java-examples/lib/json-simple-1.1.1.jar b/modules/java/java-examples/lib/json-simple-1.1.1.jar new file mode 100644 index 0000000..66347a6 Binary files /dev/null and b/modules/java/java-examples/lib/json-simple-1.1.1.jar differ diff --git a/modules/java/java-examples/lib/servlet-api-3.1.jar b/modules/java/java-examples/lib/servlet-api-3.1.jar new file mode 100644 index 0000000..6b14c3d Binary files /dev/null and b/modules/java/java-examples/lib/servlet-api-3.1.jar differ diff --git a/modules/java/java-examples/lib/xtrabytes-dicom.jar b/modules/java/java-examples/lib/xtrabytes-dicom.jar new file mode 100644 index 0000000..e6f7d4d Binary files /dev/null and b/modules/java/java-examples/lib/xtrabytes-dicom.jar differ diff --git a/src/dicom.cpp b/src/dicom.cpp index 16774b5..50cfae3 100644 --- a/src/dicom.cpp +++ b/src/dicom.cpp @@ -3,3 +3,316 @@ // Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) // Licensed under GNU General Public License Version 3 or later (the "GPL") +// DICOM - Distributed Command Message + + +#include +#include +#include +#include +#include +#include +#include +#include "dicom.h" +#include "modules.h" + +MODULE_SIGNAL GetSignalByName(std::string SignalName) { + for (int signal = unknown_signal_first; signal != unknown_signal_last; ++signal) { + std::string TmpSignalName = GetSignalName((MODULE_SIGNAL)signal); + if(TmpSignalName.compare(SignalName)==0) return (MODULE_SIGNAL)signal; + } + return unknown_signal_last; +} + +std::string GetSignalName(MODULE_SIGNAL signal) { + switch (signal) { + case unknown_signal_first :return "unknown-signal-first"; + case system_blocks_newblock :return "system-blocks-newblock"; + case view_page_overview_content :return "view-page-overview-content"; + default: + return "unknown-signal"; + } +} + +DICOMserver::DICOMserver(const std::string& address, const std::string& port, std::size_t thread_pool_size) + : thread_pool_size_(thread_pool_size), signals_(io_service_), acceptor_(io_service_), new_DICOMconn_() { + + signals_.add(SIGINT); + signals_.add(SIGTERM); + #if defined(SIGQUIT) + signals_.add(SIGQUIT); + #endif // defined(SIGQUIT) + signals_.async_wait(boost::bind(&DICOMserver::handle_stop, this)); + + boost::asio::ip::tcp::resolver resolver(io_service_); + boost::asio::ip::tcp::resolver::query query(address, port); + boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); + acceptor_.open(endpoint.protocol()); + acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor_.bind(endpoint); + acceptor_.listen(); + + start_accept(); +} + +void DICOMserver::start() { + + std::vector > threads; + for (std::size_t i = 0; i < thread_pool_size_; ++i) + { + boost::shared_ptr thread(new boost::thread( + boost::bind(&boost::asio::io_service::run, &io_service_))); + threads.push_back(thread); + } + + for (std::size_t i = 0; i < threads.size(); ++i) + threads[i]->join(); + +} + +void DICOMserver::start_accept() { + new_DICOMconn_.reset(new DICOMconn(io_service_, request_handler_)); + acceptor_.async_accept(new_DICOMconn_->socket(), + boost::bind(&DICOMserver::handle_accept, this, + boost::asio::placeholders::error)); +} + +void DICOMserver::handle_accept(const boost::system::error_code& e) { + + if (!e) { new_DICOMconn_->start(); } + start_accept(); +} + +void DICOMserver::handle_stop() { + + io_service_.stop(); +} + +request_handler::request_handler() {} + +void request_handler::handle_request(const HTTPrequest& req, reply& rep) { + + bool error = false; + + if (req.uri.compare("/dicom") != 0) { + rep.status = reply::bad_request; + return; + } + + std::stringstream ss; + ss << req.data; + boost::property_tree::ptree JSONrequest; + boost::property_tree::read_json(ss, JSONrequest); + std::string DICOM = JSONrequest.get("DICOM"); + + bool DICOM_command_recognised = false; + if(!DICOM.compare("Module-Registration")) { + DICOM_command_recognised = true; + LogPrint(LL_LOG,"DICOM request: Module-Registration ("+JSONrequest.get("module-id")+")"); + boost::property_tree::ptree JSONreply = XBY_Modules.ModuleRegistration(JSONrequest); + std::stringstream ss; + boost::property_tree::json_parser::write_json(ss, JSONreply); + rep.content=ss.str(); + } + + if (!DICOM_command_recognised) { + rep.content="{\"DICOM\":\"Bad command.\"}"; + } + + rep.status = reply::ok; + + rep.headers.resize(2); + rep.headers[0].key = "Content-Length"; + rep.headers[0].value = boost::lexical_cast(rep.content.size()); + rep.headers[1].key = "Content-Type"; + rep.headers[1].value = "application/json"; +} + + +DICOMconn::DICOMconn(boost::asio::io_service& io_service, request_handler& handler) + : strand_(io_service), socket_(io_service), request_handler_(handler) { } + +boost::asio::ip::tcp::socket& DICOMconn::socket() { + + return socket_; +} + +void DICOMconn::start() { + socket_.async_read_some(boost::asio::buffer(buffer_), + strand_.wrap( boost::bind(&DICOMconn::handle_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); +} + +void DICOMconn::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) { + + if (!e) { + boost::tribool result; + + boost::tie(result, boost::tuples::ignore) = request_parser_.parse( + request_, buffer_.data(), buffer_.data() + bytes_transferred); + + if (result) { + request_handler_.handle_request(request_, reply_); + + boost::asio::async_write(socket_, reply_.to_buffers(), + strand_.wrap( + boost::bind(&DICOMconn::handle_write, shared_from_this(), + boost::asio::placeholders::error))); + } else if (!result) { + reply_.status = reply::bad_request; + boost::asio::async_write(socket_, reply_.to_buffers(), + strand_.wrap( + boost::bind(&DICOMconn::handle_write, shared_from_this(), + boost::asio::placeholders::error))); + } else { + socket_.async_read_some(boost::asio::buffer(buffer_), + strand_.wrap( + boost::bind(&DICOMconn::handle_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } + } + +} + +void DICOMconn::handle_write(const boost::system::error_code& e) { + if (!e) { + boost::system::error_code ignored_ec; + socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); + } +} + + +std::vector reply::to_buffers() +{ + std::vector buffers; + + switch (status) { + case reply::ok: + buffers.push_back(boost::asio::buffer(HTTP_STATUS_STR_OK)); break; + case reply::bad_request: + buffers.push_back(boost::asio::buffer(HTTP_STATUS_STR_BAD_REQUEST)); break; + default: + buffers.push_back(boost::asio::buffer(HTTP_STATUS_STR_SERVER_ERROR)); + } + + for (std::size_t i = 0; i < headers.size(); ++i) + { + KeyValue& h = headers[i]; + buffers.push_back(boost::asio::buffer(h.key)); + buffers.push_back(boost::asio::buffer(KEY_VALUE_SEPARATOR_CHARS)); + buffers.push_back(boost::asio::buffer(h.value)); + buffers.push_back(boost::asio::buffer(CRLF_CHARS)); + } + buffers.push_back(boost::asio::buffer(CRLF_CHARS)); + buffers.push_back(boost::asio::buffer(content)); + return buffers; +} + + +DICOMclient::DICOMclient( boost::asio::io_service& s ) :ios(s),sock(s) { + dc = new DICOMclient(s,this); +} + +DICOMclient::DICOMclient( boost::asio::io_service& s, DICOMclient *c ) :ios(s),sock(s) {} + +DICOMclient::~DICOMclient() {} + +boost::property_tree::ptree DICOMclient::request( const std::string& json ) + { + + boost::system::error_code error = boost::asio::error::host_not_found; + sock.close(); + sock.connect( ep, error ); + if( error ) { + throw boost::system::system_error(error); + } + + boost::asio::streambuf request_buf; + std::ostream request_info(&request_buf); + request_info << "POST /dicom HTTP/1.1\n"; + request_info << "Host: 127.0.0.1\n"; + request_info << "Content-Type: application/json-rpc\n"; + request_info << "Content-Length: "<ios); + tcp::resolver::query q("127.0.0.1",NumberToString(module->DICOMport)); + tcp::resolver::iterator epi = resolver.resolve(q); + tcp::resolver::iterator end; + + boost::system::error_code error = boost::asio::error::host_not_found; + int tries = 0; + while( error && epi != end ) + { + if (tries++ > 1) return; + dc->sock.close(); + dc->sock.connect( *epi, error ); + } + if( error ) { return; } + dc->ep = *epi; + + boost::property_tree::ptree pt = dc->request("{\"DICOM\": \"Heartbeat-Echo-Request\" }"); + + module->LastHeartbeat = time(NULL); +} + + +boost::property_tree::ptree DICOMclient::ModuleRequest(XBYmodule* module, boost::property_tree::ptree *req) { + + boost::property_tree::ptree reply; + tcp::resolver resolver(dc->ios); + tcp::resolver::query q("127.0.0.1",NumberToString(module->DICOMport)); + tcp::resolver::iterator epi = resolver.resolve(q); + tcp::resolver::iterator end; + + boost::system::error_code error = boost::asio::error::host_not_found; + int tries = 0; + while( error && epi != end ) + { + if (tries++ > 1) return reply; + dc->sock.close(); + dc->sock.connect( *epi, error ); + } + if( error ) { return reply; } + dc->ep = *epi; + + std::stringstream ss; + write_json(ss, *req); + reply = dc->request(ss.str()); + + return reply; +} \ No newline at end of file diff --git a/src/dicom.h b/src/dicom.h index 170526d..fd66a7d 100644 --- a/src/dicom.h +++ b/src/dicom.h @@ -3,8 +3,124 @@ // Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) // Licensed under GNU General Public License Version 3 or later (the "GPL") +// DICOM - Distributed Command Message + #ifndef XBY_DICOM_H #define XBY_DICOM_H +#ifdef _WIN32 + #include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "util.h" + +class XBYmodule; + +using boost::asio::ip::tcp; + +enum MODULE_SIGNAL { + unknown_signal_first, + system_blocks_newblock, + view_page_overview_content, + unknown_signal_last +}; + +MODULE_SIGNAL GetSignalByName(std::string SignalName); +std::string GetSignalName(MODULE_SIGNAL signal); + +struct reply { + + enum status_type { ok = 200, bad_request = 400, internal_server_error = 500 } status; + + std::vector headers; + std::string content; + std::vector to_buffers(); + +}; + + +class request_handler : private boost::noncopyable { + + public: + explicit request_handler(); + void handle_request(const HTTPrequest& req, reply& rep); + +}; + +class DICOMconn : public boost::enable_shared_from_this, private boost::noncopyable { + + public: + + explicit DICOMconn(boost::asio::io_service& io_service, request_handler& handler); + boost::asio::ip::tcp::socket& socket(); + void start(); + + private: + + void handle_read(const boost::system::error_code& e, std::size_t bytes_transferred); + void handle_write(const boost::system::error_code& e); + + boost::asio::io_service::strand strand_; + boost::asio::ip::tcp::socket socket_; + request_handler& request_handler_; + boost::array buffer_; + HTTPrequest request_; + HTTP_RequestParser request_parser_; + reply reply_; +}; + +typedef boost::shared_ptr DICOMconn_ptr; + +class DICOMserver : private boost::noncopyable { + + public: + explicit DICOMserver(const std::string& address, const std::string& port, std::size_t thread_pool_size); + void start(); + + + private: + void start_accept(); + void handle_accept(const boost::system::error_code& e); + void handle_stop(); + + std::size_t thread_pool_size_; + boost::asio::io_service io_service_; + boost::asio::signal_set signals_; + boost::asio::ip::tcp::acceptor acceptor_; + DICOMconn_ptr new_DICOMconn_; + request_handler request_handler_; + +}; + +class DICOMclient { + + public: + DICOMclient( boost::asio::io_service& s ); + DICOMclient( boost::asio::io_service& s, DICOMclient *c ); + ~DICOMclient(); + + boost::asio::io_service& ios; + tcp::socket sock; + tcp::endpoint ep; + + boost::property_tree::ptree request( const std::string& json ); + boost::property_tree::ptree ModuleRequest(XBYmodule* module, boost::property_tree::ptree *request); + + void HeartbeatEchoRequest(XBYmodule* module); + + private: + DICOMclient* dc; + + +}; #endif // XBY_DICOM_H diff --git a/src/gui.cpp b/src/gui.cpp index 978a32f..cfbd0d3 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -4,30 +4,6 @@ // Licensed under GNU General Public License Version 3 or later (the "GPL") -#include - -#include "gui.h" - -void GUI::displayNumConnections(int i) { - if ( overviewPage != NULL ) { - overviewPage->SetlabelAlerts(QString::number(i)); - } - -} - -void GUI::displayText(std::string text) { - if ( overviewPage != NULL ) { - overviewPage->SetlabelAlerts(QString::fromUtf8(text.c_str())); - } - -} - - -void GUI::initOverviewPage(OverviewPage *op ) { - overviewPage = op; -} - -GUI gui; // XBridgeInterface xbridgeinterface; diff --git a/src/gui.h b/src/gui.h index e768593..546d650 100644 --- a/src/gui.h +++ b/src/gui.h @@ -6,20 +6,5 @@ #ifndef XBY_GUI_H #define XBY_GUI_H -#include "xtrabytesgui.h" -#include "overviewpage.h" - -class GUI { - public: - void displayNumConnections(int i); - void displayText(std::string text); - void initOverviewPage(OverviewPage *op ); - private: - OverviewPage *overviewPage; - XBridgeModel *xbridgemodel; - -}; - -extern GUI gui; #endif // XBY_GUI_H diff --git a/src/gui/forms/modulespage.ui b/src/gui/forms/modulespage.ui new file mode 100644 index 0000000..a51d2c2 --- /dev/null +++ b/src/gui/forms/modulespage.ui @@ -0,0 +1,25 @@ + + + ModulesPage + + + Form + + + + + + true + + + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #CCCCCC, stop:1 #FFFFFF); color:#000000 + + + + + + + + + + diff --git a/src/gui/forms/overviewpage.ui b/src/gui/forms/overviewpage.ui index b253219..99d34a0 100644 --- a/src/gui/forms/overviewpage.ui +++ b/src/gui/forms/overviewpage.ui @@ -7,7 +7,7 @@ - + true diff --git a/src/gui/models/guimodel.cpp b/src/gui/models/guimodel.cpp new file mode 100644 index 0000000..46bc74f --- /dev/null +++ b/src/gui/models/guimodel.cpp @@ -0,0 +1,39 @@ +// XtraBYtes - The Proof of Signature Blocktech Superchain - http://xtrabytes.global +// Copyright (c) 2017, Zoltan Szabo. All rights reserved. +// Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) +// Licensed under GNU General Public License Version 3 or later (the "GPL") + +#include "guimodel.h" +#include "../gui.h" + +GuiModel::GuiModel(QObject *parent ) : + QObject(parent) +{ + ModelSignalsConnected = false; +} + +void GuiModel::init(OverviewPage *overviewPage , ModulesPage *modulesPage ) { + GuiModel::overviewPage = overviewPage; + GuiModel::modulesPage = modulesPage; + ConnectModelSignals(); + ModelSignalsConnected = true; +} + +GuiModel::~GuiModel() +{ + if (ModelSignalsConnected) { + DisconnectModelSignals(); + } + +} + +void GuiModel::ConnectModelSignals(){ + connect( this, SIGNAL(ModuleListChanged()), modulesPage, SLOT(UpdateModuleWidgets())); + connect( this, SIGNAL(OverviewPageContentChanged()), overviewPage, SLOT(UpdateOverviewPageContent())); + + +} + +void GuiModel::DisconnectModelSignals(){ +} + diff --git a/src/gui/models/guimodel.h b/src/gui/models/guimodel.h new file mode 100644 index 0000000..78cec87 --- /dev/null +++ b/src/gui/models/guimodel.h @@ -0,0 +1,41 @@ +// XtraBYtes - The Proof of Signature Blocktech Superchain - http://xtrabytes.global +// Copyright (c) 2017, Zoltan Szabo. All rights reserved. +// Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) +// Licensed under GNU General Public License Version 3 or later (the "GPL") + +#ifndef GUIMODEL_H +#define GUIMODEL_H + +#include + +#include "../overviewpage.h" +#include "../modulespage.h" + + +class GuiModel : public QObject { + + Q_OBJECT + + public: + explicit GuiModel(QObject *parent = 0); + void init(OverviewPage *overviewPage , ModulesPage *modulesPage ); + ~GuiModel(); + + private: + void ConnectModelSignals(); + void DisconnectModelSignals(); + bool ModelSignalsConnected; + OverviewPage *overviewPage; + ModulesPage *modulesPage; + + signals: + void ModuleListChanged(); + void OverviewPageContentChanged(); + +}; + + + + + +#endif // GUIMODEL_H diff --git a/src/gui/models/m-xbridge.cpp b/src/gui/models/m-xbridge.cpp deleted file mode 100644 index 19d3b9d..0000000 --- a/src/gui/models/m-xbridge.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// XtraBYtes - The Proof of Signature Blocktech Superchain - http://xtrabytes.global -// Copyright (c) 2017, Zoltan Szabo. All rights reserved. -// Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) -// Licensed under GNU General Public License Version 3 or later (the "GPL") - -#include "m-xbridge.h" -#include "../gui.h" -#include "overviewpage.h" - -XBridgeModel::XBridgeModel(QObject *parent) : - QObject(parent) -{ - ConnectModelSignals(); -} - -XBridgeModel::~XBridgeModel() -{ - DisconnectModelSignals(); -} - -void XBridgeModel::ConnectModelSignals(){ -} - -void XBridgeModel::DisconnectModelSignals(){ -} - -void XBridgeModel::update_numBlocks(int numBlocks) -{ - emit changed_numBlocks(numBlocks); -} \ No newline at end of file diff --git a/src/gui/models/m-xbridge.h b/src/gui/models/m-xbridge.h deleted file mode 100644 index 148b6cd..0000000 --- a/src/gui/models/m-xbridge.h +++ /dev/null @@ -1,35 +0,0 @@ -// XtraBYtes - The Proof of Signature Blocktech Superchain - http://xtrabytes.global -// Copyright (c) 2017, Zoltan Szabo. All rights reserved. -// Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) -// Licensed under GNU General Public License Version 3 or later (the "GPL") - -#ifndef M_XBRIDGE_H -#define M_XBRIDGE_H - -#include - -class XBridgeModel : public QObject { - - Q_OBJECT - - public: - explicit XBridgeModel(QObject *parent = 0); - ~XBridgeModel(); - - private: - void ConnectModelSignals(); - void DisconnectModelSignals(); - - signals: - void changed_numBlocks(int numBlocks); - - public slots: - void update_numBlocks(int numBlocks); - -}; - - - - - -#endif // M_XBRIDGE_H diff --git a/src/gui/modulespage.cpp b/src/gui/modulespage.cpp new file mode 100644 index 0000000..1872a3d --- /dev/null +++ b/src/gui/modulespage.cpp @@ -0,0 +1,76 @@ +// XtraBYtes - The Proof of Signature Blocktech Superchain - http://xtrabytes.global +// Copyright (c) 2017, Zoltan Szabo. All rights reserved. +// Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) +// Licensed under GNU General Public License Version 3 or later (the "GPL") + +#include "modulespage.h" +#include "ui_modulespage.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +ModulesPage::ModulesPage(QWidget *parent) : + QWidget(parent), + ui(new Ui::ModulesPage) +{ + ui->setupUi(this); + + modulelistlayout = new QGridLayout(); + modulelistlayout->setMargin(10); + ui->contentLayout->addLayout(modulelistlayout); + + //emit ModuleListChanged(); + + QHBoxLayout* bottomLayout = new QHBoxLayout(); + QPushButton* btn1 = new QPushButton(QObject::tr("OK")); + bottomLayout->addStretch(); + bottomLayout->addWidget(btn1); + bottomLayout->addStretch(); + ui->contentLayout->addLayout(bottomLayout); + + +} + +ModulesPage::~ModulesPage() { + + std::map >::iterator itr = ModuleContainerWrapper.begin(); + while (itr != ModuleContainerWrapper.end()) { + std::vector ModuleContainer = (*itr).second; + LogPrint(LL_LOG,"ModulesPage: "+ModuleContainer.back()->module->ModuleID+" removed."); + while(!ModuleContainer.empty()) { + delete ModuleContainer.back(); + ModuleContainer.pop_back(); + } + ModuleContainerWrapper.erase(itr++); + } + + + delete ui; +} + +void ModulesPage::UpdateModuleWidgets() { + + int i = 0; + for( std::vector::iterator itr = XBY_Modules.modules.begin(), itr_end = XBY_Modules.modules.end(); itr != itr_end; ++itr ) { + + ModuleContainer *module_container = new ModuleContainer(*itr); + ModuleContainerWrapper[(*itr)->ModuleID].push_back( module_container ); + + modulelistlayout->addWidget(module_container->GetModuleDescription(),i,0); + modulelistlayout->addWidget(module_container->GetOnOffButtonAddr(),i,1); + + i++; + } + +} + + + \ No newline at end of file diff --git a/src/gui/modulespage.h b/src/gui/modulespage.h new file mode 100644 index 0000000..732f837 --- /dev/null +++ b/src/gui/modulespage.h @@ -0,0 +1,105 @@ +// XtraBYtes - The Proof of Signature Blocktech Superchain - http://xtrabytes.global +// Copyright (c) 2017, Zoltan Szabo. All rights reserved. +// Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) +// Licensed under GNU General Public License Version 3 or later (the "GPL") + +#ifndef MODULESPAGE_H +#define MODULESPAGE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../modules.h" + +class ModuleContainer; +class GuiModel; + +namespace Ui { + class ModulesPage; +} + +class ModulesPage : public QWidget +{ + Q_OBJECT + +public: + explicit ModulesPage(QWidget *parent = 0); + ~ModulesPage(); + + + +private: + Ui::ModulesPage *ui; + GuiModel *gui_model; + QGridLayout *modulelistlayout; + + //std::vector ModuleContainerWrapper; + + std::map< std::string, std::vector > ModuleContainerWrapper; + +public slots: + void UpdateModuleWidgets(); + +}; + + +class ModuleContainer { + public: + ModuleContainer(XBYmodule *m) { + + module = m; + + off = new QState(); + off->assignProperty(&OnOffButton, "text", "Off"); + off->setObjectName("off"); + + on = new QState(); + on->setObjectName("on"); + on->assignProperty(&OnOffButton, "text", "On"); + + off->addTransition(&OnOffButton, SIGNAL(clicked()), on); + on->addTransition(&OnOffButton, SIGNAL(clicked()), off); + + OnOffState.addState(off); + OnOffState.addState(on); + OnOffState.setInitialState(off); + OnOffState.start(); + + OnOffButton.resize(100, 50); + OnOffButton.show(); + + } + + QPushButton* GetOnOffButtonAddr() { + return &OnOffButton; + } + + QLabel* GetModuleDescription() { + + QLabel *description = new QLabel(); + + QString desc; + QTextStream(&desc) << "

" << module->ModuleName.c_str() << "(" << module->ModuleID.c_str() << ")

"; + + description->setText(desc); + + return description; + } + + XBYmodule *module; + QPushButton OnOffButton; + QStateMachine OnOffState; + QState *off; + QState *on; + + }; + +#endif // MODULESPAGE_H diff --git a/src/gui/overviewpage.cpp b/src/gui/overviewpage.cpp index e0ba442..1c1b1ca 100644 --- a/src/gui/overviewpage.cpp +++ b/src/gui/overviewpage.cpp @@ -6,12 +6,18 @@ #include "overviewpage.h" #include "ui_overviewpage.h" +#include "../modules.h" + +#include + + OverviewPage::OverviewPage(QWidget *parent) : QWidget(parent), ui(new Ui::OverviewPage) { - ui->setupUi(this); + ui->setupUi(this); + } OverviewPage::~OverviewPage() @@ -19,8 +25,23 @@ OverviewPage::~OverviewPage() delete ui; } -void OverviewPage::SetlabelAlerts(QString qs) { - ui->labelAlerts->setText(qs); +void OverviewPage::UpdateOverviewPageContent() { + + boost::property_tree::ptree args; + // FIXMEE!! need send back to module the content of this region + args.put("UpdateOverviewPageContent", "UpdateOverviewPageContent-FIXMEE!"); + boost::property_tree::ptree ret = XBY_Modules.ModuleInvoke("*" , view_page_overview_content, &args ); + + std::stringstream ss; + boost::property_tree::ptree::const_iterator end = ret.end(); + for (boost::property_tree::ptree::const_iterator it = ret.begin(); it != end; ++it) { + try { + ss << "

" << it->second.get("view-page-overview-content") << "

"; + } catch(...) {} + } + + ui->labelContent->setText(QString::fromStdString(ss.str())); + } diff --git a/src/gui/overviewpage.h b/src/gui/overviewpage.h index 97f13d2..4930090 100644 --- a/src/gui/overviewpage.h +++ b/src/gui/overviewpage.h @@ -19,13 +19,14 @@ class OverviewPage : public QWidget public: explicit OverviewPage(QWidget *parent = 0); - ~OverviewPage(); - - void SetlabelAlerts(QString qs); + ~OverviewPage(); private: Ui::OverviewPage *ui; - + +public slots: + void UpdateOverviewPageContent(); + }; #endif // OVERVIEWPAGE_H diff --git a/src/gui/resources/icons/modules.png b/src/gui/resources/icons/modules.png new file mode 100644 index 0000000..0286ac0 Binary files /dev/null and b/src/gui/resources/icons/modules.png differ diff --git a/src/gui/xtrabytes.qrc b/src/gui/xtrabytes.qrc index 722b8d6..33d3845 100644 --- a/src/gui/xtrabytes.qrc +++ b/src/gui/xtrabytes.qrc @@ -1,6 +1,7 @@ resources/icons/dashboard.png + resources/icons/modules.png resources/icons/about.png resources/icons/exit.png resources/icons/xtrabytes.png diff --git a/src/gui/xtrabytesgui.cpp b/src/gui/xtrabytesgui.cpp index 4dcc335..c24a289 100644 --- a/src/gui/xtrabytesgui.cpp +++ b/src/gui/xtrabytesgui.cpp @@ -13,6 +13,8 @@ #include "xtrabytesgui.h" #include "aboutdialog.h" #include "overviewpage.h" +#include "modulespage.h" +#include "models/guimodel.h" #include "../gui.h" XtraBYtesGUI::XtraBYtesGUI(QWidget *parent): @@ -41,10 +43,15 @@ XtraBYtesGUI::XtraBYtesGUI(QWidget *parent): setUnifiedTitleAndToolBarOnMac(true); overviewPage = new OverviewPage(); - gui.initOverviewPage( overviewPage ); + modulesPage = new ModulesPage(); + + guimodel = new GuiModel(); + guimodel->init( overviewPage, modulesPage ); + centralStackedWidget = new QStackedWidget(this); centralStackedWidget->addWidget(overviewPage); + centralStackedWidget->addWidget(modulesPage); QWidget *centralWidget = new QWidget(); QVBoxLayout *centralLayout = new QVBoxLayout(centralWidget); @@ -74,6 +81,14 @@ void XtraBYtesGUI::createActions() { overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1)); tabGroup->addAction(overviewAction); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); + + modulesAction = new QAction(QIcon(":/icons/modules"), tr("&Modules"), this); + modulesAction->setToolTip(tr("Show general overview of modules.")); + modulesAction->setCheckable(true); + modulesAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1)); + tabGroup->addAction(modulesAction); + connect(modulesAction, SIGNAL(triggered()), this, SLOT(gotoModulesPage())); + exitAction = new QAction( QIcon(":/icons/exit"), tr("E&xit"), this ); exitAction->setShortcut( tr("Ctrl+Q") ); @@ -116,6 +131,7 @@ void XtraBYtesGUI::createToolBars() toolbar->addWidget(l); toolbar->addAction(overviewAction); + toolbar->addAction(modulesAction); toolbar->addAction(aboutAction); toolbar->addAction(exitAction); toolbar->addWidget(makeToolBarSpacer()); @@ -146,9 +162,10 @@ void XtraBYtesGUI::gotoOverviewPage() } -void XtraBYtesGUI::setXBridgeModel(XBridgeModel *model) +void XtraBYtesGUI::gotoModulesPage() { - this->xbridgemodel = model; - if(model) {} -} + centralStackedWidget->setCurrentWidget(modulesPage); +} + + diff --git a/src/gui/xtrabytesgui.h b/src/gui/xtrabytesgui.h index 3f10c8c..9e30708 100644 --- a/src/gui/xtrabytesgui.h +++ b/src/gui/xtrabytesgui.h @@ -8,10 +8,14 @@ #include #include +#include + +#include #include "aboutdialog.h" #include "overviewpage.h" -#include "gui/models/m-xbridge.h" +#include "modulespage.h" +#include "gui/models/guimodel.h" class QAction; class QMenu; @@ -27,8 +31,7 @@ class XtraBYtesGUI : public QMainWindow public: explicit XtraBYtesGUI(QWidget *parent = 0); ~XtraBYtesGUI(); - - void setXBridgeModel(XBridgeModel *model); + GuiModel *guimodel; private: @@ -37,8 +40,7 @@ class XtraBYtesGUI : public QMainWindow QStackedWidget *centralStackedWidget; OverviewPage *overviewPage; - - XBridgeModel *xbridgemodel; + ModulesPage *modulesPage; void createMenus(); void createStatusBar(); @@ -47,12 +49,14 @@ class XtraBYtesGUI : public QMainWindow QAction *aboutAction; QAction *overviewAction; + QAction *modulesAction; QAction *exitAction; private slots: void aboutClicked(); void gotoOverviewPage(); + void gotoModulesPage(); }; diff --git a/src/makefile-test.linux b/src/makefile-test.linux index 257a429..c1e3c97 100644 --- a/src/makefile-test.linux +++ b/src/makefile-test.linux @@ -33,6 +33,7 @@ OBJS= \ obj/crypto.o \ obj/error.o \ obj/redfat.o \ + obj/dicom.o \ obj/threads.o \ obj/vitals.o \ obj/test/test.o diff --git a/src/modules.cpp b/src/modules.cpp new file mode 100644 index 0000000..2f3d973 --- /dev/null +++ b/src/modules.cpp @@ -0,0 +1,111 @@ +// XtraBYtes - The Proof of Signature Blocktech Superchain - http://xtrabytes.global +// Copyright (c) 2017, Zoltan Szabo. All rights reserved. +// Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) +// Licensed under GNU General Public License Version 3 or later (the "GPL") + + +#include "xtrabytes.h" +#include "modules.h" +#include "dicom.h" + + +boost::property_tree::ptree XBYmodules::ModuleRegistration(boost::property_tree::ptree JSONrequest) { + + boost::property_tree::ptree JSONreply; + std::string ModuleID = JSONrequest.get("module-id"); + + bool ModuleExist = false; + for( std::vector::iterator itr = modules.begin(), itr_end = modules.end(); itr != itr_end; ++itr ) { + XBYmodule *m = *itr; + if(!ModuleID.compare(m->ModuleID)) { + ModuleExist = true; + break; + } + } + + if ( ModuleExist ) { + JSONreply.put("DICOM", "STOP FLOOD!"); + } else { + modules.push_back(new XBYmodule()); + XBYmodule *xby_module = modules.back(); + + xby_module->DICOMport = JSONrequest.get("dicom-port"); + xby_module->ModuleName = JSONrequest.get("module-name"); + xby_module->ModuleID = ModuleID; + xby_module->LastHeartbeat = 0; + xby_module->ModuleEnable = false; + boost::property_tree::ptree::value_type v; + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, JSONrequest.get_child("signals")) { + xby_module->ModuleSignals.push_back(GetSignalByName(v.second.data())); + } + + emit xGUI->guimodel->ModuleListChanged(); + + JSONreply.put("DICOM", "Module accepted"); + } + + + return JSONreply; +} + +XBYmodule::XBYmodule() { + +} + +XBYmodules::~XBYmodules() { + while(!modules.empty()) { + delete modules.back(); + modules.pop_back(); + } +} + +void XBYmodules::PingModules() { + + for( std::vector::iterator itr = modules.begin(), itr_end = modules.end(); itr != itr_end; ++itr ) { + boost::asio::io_service ios; + DICOMclient dicomclient( ios ); + dicomclient.HeartbeatEchoRequest(*itr); + if ((time(NULL) - (*itr)->LastHeartbeat) > 4 ) { + if ((*itr)->ModuleAvailable) { + LogPrint(LL_LOG,"Module "+(*itr)->ModuleID+" unavailable. Temporary disabled."); + } + (*itr)->ModuleAvailable = false; + } else { + if (!(*itr)->ModuleAvailable) { + LogPrint(LL_LOG,"Module "+(*itr)->ModuleID+" available. Reenabled."); + } + (*itr)->ModuleAvailable = true; + } + + + } + +} + +boost::property_tree::ptree XBYmodules::ModuleInvoke( std::string moduleID , MODULE_SIGNAL Signal , boost::property_tree::ptree *args ) { + + boost::property_tree::ptree reply_warapper; + for( std::vector::iterator itr = modules.begin(), itr_end = modules.end(); itr != itr_end; ++itr ) { + + if (((moduleID.compare("*")==0) || (moduleID.compare((*itr)->ModuleID)==0)) && (*itr)->ModuleAvailable) { + for( std::vector::iterator sitr = (*itr)->ModuleSignals.begin(), sitr_end = (*itr)->ModuleSignals.end(); sitr != sitr_end; ++sitr ) { + MODULE_SIGNAL ms = *sitr; + if (GetSignalName(Signal).compare(GetSignalName(ms))==0) { + boost::asio::io_service ios; + DICOMclient dicomclient( ios ); + args->put("DICOM", GetSignalName(ms)); + boost::property_tree::ptree module_reply = dicomclient.ModuleRequest( *itr, args); + reply_warapper.put_child((*itr)->ModuleID, module_reply); + } + } + + } + + + } + return reply_warapper; + + +} + +XBYmodules XBY_Modules; diff --git a/src/modules.h b/src/modules.h new file mode 100644 index 0000000..1d00825 --- /dev/null +++ b/src/modules.h @@ -0,0 +1,43 @@ +// XtraBYtes - The Proof of Signature Blocktech Superchain - http://xtrabytes.global +// Copyright (c) 2017, Zoltan Szabo. All rights reserved. +// Copyright (c) 2017, XtraBYtes Founders and Developers ( see AUTHORS ) +// Licensed under GNU General Public License Version 3 or later (the "GPL") + + +#ifndef XBY_MODULES_H +#define XBY_MODULES_H + +#include +#include +#include + +#include "dicom.h" + +class XBYmodule { + + public: + XBYmodule(); + + std::vector ModuleSignals; + int DICOMport; + std::string ModuleName; + std::string ModuleID; + unsigned long int LastHeartbeat; + bool ModuleEnable; + bool ModuleAvailable; +}; + +class XBYmodules { + + public: + ~XBYmodules(); + void PingModules(); + boost::property_tree::ptree ModuleInvoke( std::string moduleID , MODULE_SIGNAL Signal , boost::property_tree::ptree *args ); + boost::property_tree::ptree ModuleRegistration(boost::property_tree::ptree JSONrequest); + std::vector modules; + +}; + +extern XBYmodules XBY_Modules; + +#endif // XBY_MODULES_H diff --git a/src/threads.cpp b/src/threads.cpp index 5a4351f..1cef848 100644 --- a/src/threads.cpp +++ b/src/threads.cpp @@ -4,41 +4,76 @@ // Licensed under GNU General Public License Version 3 or later (the "GPL") #include -#include +#include #include "util.h" #include "gui.h" +#include "dicom.h" +#include "modules.h" #include "threads.h" #include "vitals.h" - +#include "xtrabytes.h" boost::thread_group threads; void StartThreads() { - threads.create_thread(boost::bind(&ThreadWrapper, "ThreadSyncXbridge", &ThreadSyncXbridge)); + threads.create_thread(boost::bind(&ThreadWrapper, "ThreadSyncXbridge", &ThreadSyncXbridge)); + threads.create_thread(boost::bind(&ThreadWrapper, "ThreadServerDICOM", &ThreadServerDICOM)); + threads.create_thread(boost::bind(&ThreadWrapper, "ThreadModuleHeartBeat", &ThreadModuleHeartBeat)); + threads.create_thread(boost::bind(&ThreadWrapper, "ThreadCron_1s", &ThreadCron_1s)); +} + + +void ThreadServerDICOM() { + + DICOMserver dicom("127.0.0.1", "3344", 5); + dicom.start(); + } void ThreadSyncXbridge(){ boost::asio::io_service ios; XBridge xbridge( ios ); - bool connected = xbridge.connect( "localhost:34001", "xbyuser", "xbypass" ); + bool connected; + try { + connected = xbridge.connect( "localhost:34001", "xbyuser", "xbypass" ); + } catch (...) { + LogPrint(LL_LOG,"*** XBRIDGE requires the old client wallet to be running. Please start the old wallet first !"); + throw; + } + int blocks = 0; while (true) { if (connected) { blocks = xbridge.GetBlocks(); - gui.displayNumConnections(blocks); + // FIXMEE gui.displayNumConnections(blocks); } else { - gui.displayText("Connection problem"); + // FIXMEE gui.displayText("Connection problem"); } - boost::this_thread::sleep( boost::posix_time::milliseconds(1000) ); + boost::this_thread::sleep( boost::posix_time::milliseconds(1011) ); } } +void ThreadModuleHeartBeat() { + while (true) { + XBY_Modules.PingModules(); + boost::this_thread::sleep( boost::posix_time::milliseconds(2033) ); + } +} + +void ThreadCron_1s() { + while (true) { + emit xGUI->guimodel->OverviewPageContentChanged(); + boost::this_thread::sleep( boost::posix_time::milliseconds(1000) ); + } +} + + template void ThreadWrapper(std::string ThreadName, Callable ThreadFunc) { diff --git a/src/threads.h b/src/threads.h index 3ab97ff..be85666 100644 --- a/src/threads.h +++ b/src/threads.h @@ -12,6 +12,8 @@ template void ThreadWrapper(std::string ThreadName, Callable ThreadFunc); void ThreadSyncXbridge(); - +void ThreadServerDICOM(); +void ThreadModuleHeartBeat(); +void ThreadCron_1s(); #endif // XBY_THREADS_H diff --git a/src/util.cpp b/src/util.cpp index 06f9e70..ef7a8c9 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -10,11 +10,19 @@ #include #include +#include #include const char* const HEX_CHARS = "0123456789ABCDEF"; const char* const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const std::string KEY_VALUE_SEPARATOR_CHARS = ": "; +const std::string CRLF_CHARS = "\r\n"; + +const std::string HTTP_STATUS_STR_OK = "HTTP/1.0 200 OK\r\n"; +const std::string HTTP_STATUS_STR_BAD_REQUEST = "HTTP/1.0 400 Bad Request\r\n"; +const std::string HTTP_STATUS_STR_SERVER_ERROR = "HTTP/1.0 500 Internal Server Error\r\n"; + // HexString // ------------------------------------------------------------ @@ -241,18 +249,331 @@ void ExceptionPrint(std::exception* e, const char* Thread) throw; } +boost::mutex LOG_mutex; +void LogPrint(LogLevel loglevel, const std::string &str) { + + boost::mutex::scoped_lock scoped_lock(LOG_mutex); + if (WriteConsoleLog) { + switch (loglevel) { + case LL_FATAL_ERROR: std::cout << "FATAL ERROR"; break; + case LL_ERROR: std::cout << "ERROR"; break; + case LL_WARNING: std::cout << "WARNNG"; break; + case LL_LOG: std::cout << "LOG"; break; + } + std::cout << ": " << DateTimeStrFormat("%Y-%m-%d %H:%M:%S", time(NULL)); + std::cout << " " << str << std::endl; + } else { + // FIXMEE !!! + } + +} + + +// HTTP Request parser +// ------------------------------------------------------------ -void LogPrint(LogLevel loglevel, const std::string &str) { - - if (!WriteConsoleLog) return; - switch (loglevel) { - case LL_FATAL_ERROR: std::cout << "FATAL ERROR"; break; - case LL_ERROR: std::cout << "ERROR"; break; - case LL_WARNING: std::cout << "WARNNG"; break; - case LL_LOG: std::cout << "LOG"; break; +HTTP_RequestParser::HTTP_RequestParser() + : state_(method_start) +{ +} + +void HTTP_RequestParser::reset() +{ + state_ = method_start; +} + + +boost::tribool HTTP_RequestParser::parseNextChar(HTTPrequest& req, char input) +{ + switch (state_) + { + case data_start: + case data: + req.data.push_back(input); + state_ = data; + return boost::indeterminate; + + case method_start: + if (!CharType::is_char(input) || CharType::is_ctl(input) || CharType::is_tspecial(input)) + { + return false; + } + else + { + state_ = method; + req.method.push_back(input); + return boost::indeterminate; + } + case method: + if (input == ' ') + { + state_ = uri; + return boost::indeterminate; + } + else if (!CharType::is_char(input) || CharType::is_ctl(input) || CharType::is_tspecial(input)) + { + return false; + } + else + { + req.method.push_back(input); + return boost::indeterminate; + } + case uri: + if (input == ' ') + { + state_ = http_version_h; + return boost::indeterminate; + } + else if (CharType::is_ctl(input)) + { + return false; + } + else + { + req.uri.push_back(input); + return boost::indeterminate; + } + case http_version_h: + if (input == 'H') + { + state_ = http_version_t_1; + return boost::indeterminate; + } + else + { + return false; + } + case http_version_t_1: + if (input == 'T') + { + state_ = http_version_t_2; + return boost::indeterminate; + } + else + { + return false; + } + case http_version_t_2: + if (input == 'T') + { + state_ = http_version_p; + return boost::indeterminate; + } + else + { + return false; + } + case http_version_p: + if (input == 'P') + { + state_ = http_version_slash; + return boost::indeterminate; + } + else + { + return false; + } + case http_version_slash: + if (input == '/') + { + req.http_version_major = 0; + req.http_version_minor = 0; + state_ = http_version_major_start; + return boost::indeterminate; + } + else + { + return false; + } + case http_version_major_start: + if (CharType::is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + state_ = http_version_major; + return boost::indeterminate; + } + else + { + return false; + } + case http_version_major: + if (input == '.') + { + state_ = http_version_minor_start; + return boost::indeterminate; + } + else if (CharType::is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + return boost::indeterminate; + } + else + { + return false; + } + case http_version_minor_start: + if (CharType::is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + state_ = http_version_minor; + return boost::indeterminate; + } + else + { + return false; + } + case http_version_minor: + if (input == '\r') + { + state_ = expecting_newline_1; + return boost::indeterminate; + } + else if (CharType::is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + return boost::indeterminate; + } + else + { + return false; + } + case expecting_newline_1: + if (input == '\n') + { + state_ = header_line_start; + return boost::indeterminate; + } + else + { + return false; + } + case header_line_start: + if (input == '\r') + { + state_ = expecting_newline_3; + return boost::indeterminate; + } + else if (!req.headers.empty() && (input == ' ' || input == '\t')) + { + state_ = header_lws; + return boost::indeterminate; + } + else if (!CharType::is_char(input) || CharType::is_ctl(input) || CharType::is_tspecial(input)) + { + return false; + } + else + { + req.headers.push_back(KeyValue()); + req.headers.back().key.push_back(input); + state_ = header_name; + return boost::indeterminate; + } + case header_lws: + if (input == '\r') + { + state_ = expecting_newline_2; + return boost::indeterminate; + } + else if (input == ' ' || input == '\t') + { + return boost::indeterminate; + } + else if (CharType::is_ctl(input)) + { + return false; + } + else + { + state_ = header_value; + req.headers.back().value.push_back(input); + return boost::indeterminate; + } + case header_name: + if (input == ':') + { + state_ = space_before_header_value; + return boost::indeterminate; } + else if (!CharType::is_char(input) || CharType::is_ctl(input) || CharType::is_tspecial(input)) + { + return false; + } + else + { + req.headers.back().key.push_back(input); + return boost::indeterminate; + } + case space_before_header_value: + if (input == ' ') + { + state_ = header_value; + return boost::indeterminate; + } + else + { + return false; + } + case header_value: + if (input == '\r') + { + state_ = expecting_newline_2; + return boost::indeterminate; + } + else if (CharType::is_ctl(input)) + { + return false; + } + else + { + req.headers.back().value.push_back(input); + return boost::indeterminate; + } + case expecting_newline_2: + if (input == '\n') + { + state_ = header_line_start; + return boost::indeterminate; + } + else + { + return false; + } + case expecting_newline_3: + state_ = data_start; + return boost::indeterminate; + default: + return false; + } +} + +bool CharType::is_char(int c) +{ + return c >= 0 && c <= 127; +} - std::cout << ": " << DateTimeStrFormat("%Y-%m-%d %H:%M:%S", time(NULL)); - std::cout << " " << str << std::endl; +bool CharType::is_ctl(int c) +{ + return (c >= 0 && c <= 31) || (c == 127); +} + +bool CharType::is_tspecial(int c) +{ + switch (c) + { + case '(': case ')': case '<': case '>': case '@': + case ',': case ';': case ':': case '\\': case '"': + case '/': case '[': case ']': case '?': case '=': + case '{': case '}': case ' ': case '\t': + return true; + default: + return false; + } +} + +bool CharType::is_digit(int c) +{ + return c >= '0' && c <= '9'; } diff --git a/src/util.h b/src/util.h index 36da511..26c6a36 100644 --- a/src/util.h +++ b/src/util.h @@ -7,11 +7,46 @@ #define XBY_UTIL_H #include +#include #include +#include +#include +#include +#include extern const char* const HEX_CHARS; extern const char* const BASE64_CHARS; +extern const std::string HTTP_STATUS_STR_OK; +extern const std::string HTTP_STATUS_STR_BAD_REQUEST; +extern const std::string HTTP_STATUS_STR_SERVER_ERROR; +extern const std::string KEY_VALUE_SEPARATOR_CHARS; +extern const std::string CRLF_CHARS; + +template +std::string NumberToString ( T Number ) { + std::ostringstream ss; + ss << Number; + return ss.str(); +} + +struct KeyValue +{ + std::string key; + std::string value; +}; + +struct HTTPrequest +{ + std::string method; + std::string uri; + int http_version_major; + int http_version_minor; + std::vector headers; + std::string data; +}; + + class HexString { private: @@ -57,6 +92,15 @@ class Decoders { }; +class CharType { + + public: + static bool is_char(int c); + static bool is_ctl(int c); + static bool is_tspecial(int c); + static bool is_digit(int c); + +}; extern bool ConsoleLog; @@ -72,4 +116,60 @@ void LogPrint(LogLevel loglevel, const std::string &str); void ExceptionPrint(std::exception* e, const char* Thread); +class HTTP_RequestParser +{ +public: + + HTTP_RequestParser(); + void reset(); + + template + boost::tuple parse(HTTPrequest& req, + InputIterator begin, InputIterator end) +{ + while (begin != end) + { + boost::tribool result = parseNextChar(req, *begin++); + if (state_ == data && begin == end ) { + result = true; + } + if (result || !result) + return boost::make_tuple(result, begin); + } + boost::tribool result = boost::indeterminate; + return boost::make_tuple(result, begin); +}; + + +private: + boost::tribool parseNextChar(HTTPrequest& req, char input); + + enum state + { + method_start, + method, + uri, + http_version_h, + http_version_t_1, + http_version_t_2, + http_version_p, + http_version_slash, + http_version_major_start, + http_version_major, + http_version_minor_start, + http_version_minor, + expecting_newline_1, + header_line_start, + header_lws, + header_name, + space_before_header_value, + header_value, + data_start, + data, + expecting_newline_2, + expecting_newline_3 + } state_; + +}; + #endif // XBY_UTIL_H diff --git a/src/vitals.cpp b/src/vitals.cpp index 147ba99..5a8da0c 100644 --- a/src/vitals.cpp +++ b/src/vitals.cpp @@ -44,7 +44,6 @@ boost::property_tree::ptree XBridge::request( const std::string& json ) request_info << "Content-Length: "< > SettingsMap; +XtraBYtesGUI *xGUI; int main(int argc, char **argv) { - - ParseCommandLine( argc , argv ); - - if ( SettingsMap["nogui"].size() > 0 || SettingsMap["help"].size() > 0 ) { - std::cout << std::endl << "Welcome to XtraBYtes command line mode." << std::endl; - - if ( SettingsMap["help"].size() > 0 ) { - std::cout << std::endl << "Commands:" << std::endl; - std::cout << "help" << std::endl; - std::cout << "getstaticbyid" << std::endl; - std::cout << "getstaticbypubkey" << std::endl << std::endl; - } - - if ( GetSettingsStringValue("getstaticbyid").size() > 0 ) { - - std::cout << std::endl << Genesis_Block::GetSTaTiCbyID(GetSettingsStringValue("getstaticbyid").c_str()) << std::endl; - } - - if ( GetSettingsStringValue("getstaticbypubkey").size() > 0 ) { - - std::cout << std::endl << Genesis_Block::GetSTaTiCbyPubKey(GetSettingsStringValue("getstaticbypubkey").c_str()) << std::endl; - } - - } else { - + QApplication app (argc, argv); - XtraBYtesGUI xtrabytesGUI; - - XBridgeModel xbridgemodel; - - xtrabytesGUI.setXBridgeModel(&xbridgemodel); - + XtraBYtesGUI xtrabytesGUI; xtrabytesGUI.show(); + xGUI = &xtrabytesGUI; StartThreads(); + return app.exec(); - } - - return 1; + } void ParseCommandLine(int argc, const char* const argv[]) @@ -103,18 +75,7 @@ void ParseCommandLine(int argc, const char* const argv[]) SettingsMutex.unlock(); } -// FIXED - onedeveloper/nitroxido - -std::string GetSettingsStringValue(std::string id ) { - std:string result; // the result - try { - result = SettingsMap.at(id); // try to find the id in the map - } - catch (const std::out_of_range& oor) { - result = ""; // not found, use standard value - } - return result; // always return something -} +// FIXMEE!! TMP FUNCTIONS std::string GetSettingsStringValue(std::string id ) { BOOST_FOREACH(std::string str, SettingsMap[id]) { diff --git a/src/xtrabytes.h b/src/xtrabytes.h index 98109c9..de99ce1 100644 --- a/src/xtrabytes.h +++ b/src/xtrabytes.h @@ -6,7 +6,11 @@ #ifndef XBY_XTRABYTES_H #define XBY_XTRABYTES_H +#include "gui/xtrabytesgui.h" + void ParseCommandLine(int argc, const char* const argv[]); std::string GetSettingsStringValue(std::string id ); +extern XtraBYtesGUI *xGUI; + #endif // XBY_XTRABYTES_H diff --git a/xtrabytes.pro b/xtrabytes.pro index 39a69ff..c39232f 100644 --- a/xtrabytes.pro +++ b/xtrabytes.pro @@ -27,10 +27,13 @@ SOURCES += src/xtrabytes.cpp \ src/gui/xtrabytesgui.cpp \ src/gui/aboutdialog.cpp \ src/gui/overviewpage.cpp \ - src/gui/models/m-xbridge.cpp \ + src/gui/modulespage.cpp \ + src/gui/models/guimodel.cpp \ src/util.cpp \ src/vitals.cpp \ src/redfat.cpp \ + src/dicom.cpp \ + src/modules.cpp \ src/crypto.cpp \ src/error.cpp \ src/gui.cpp \ @@ -41,11 +44,13 @@ SOURCES += src/xtrabytes.cpp \ HEADERS += src/gui/xtrabytesgui.h \ src/gui/aboutdialog.h \ - src/gui/models/m-xbridge.h \ - src/gui/overviewpage.h + src/gui/models/guimodel.h \ + src/gui/overviewpage.h \ + src/gui/modulespage.h FORMS += src/gui/forms/aboutdialog.ui \ - src/gui/forms/overviewpage.ui + src/gui/forms/overviewpage.ui \ + src/gui/forms/modulespage.ui RESOURCES += src/gui/xtrabytes.qrc @@ -102,6 +107,9 @@ INCLUDEPATH += $$OPENSSL_INCLUDE_PATH LIBS += $$join(OPENSSL_LIB_PATH,,-L,) LIBS += -lssl -lcrypto +win32 { + LIBS += -lwsock32 +} LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX