summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt32
-rw-r--r--client/CMakeLists.txt14
-rw-r--r--client/main.cpp19
-rw-r--r--client/resourceaccess.cpp95
-rw-r--r--client/resourceaccess.h33
-rw-r--r--common/console.cpp48
-rw-r--r--common/console.h20
-rw-r--r--resource/CMakeLists.txt15
-rw-r--r--resource/listener.cpp71
-rw-r--r--resource/listener.h37
-rw-r--r--resource/main.cpp23
11 files changed, 407 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..469c5c3
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,32 @@
1cmake_minimum_required(VERSION 2.8)
2
3# ECM setup
4find_package(ECM 0.0.10 REQUIRED NO_MODULE)
5set(CMAKE_MODULE_PATH
6 ${ECM_MODULE_PATH}
7 # ${ECM_KDE_MODULE_DIR}
8 ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules
9 ${CMAKE_MODULE_PATH})
10
11include(FeatureSummary)
12include(GenerateExportHeader)
13#include(ECMSetupVersion)
14include(ECMGenerateHeaders)
15include(ECMPackageConfigHelpers)
16# include(KDEInstallDirs)
17# include(KDEFrameworkCompilerSettings)
18# include(KDECMakeSettings)
19
20find_package(Qt5Core REQUIRED)
21
22set(CMAKE_AUTOMOC ON)
23add_definitions("-Wall -std=c++0x")
24include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
25
26# the client
27add_subdirectory(client)
28
29# the resource
30add_subdirectory(resource)
31
32feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
new file mode 100644
index 0000000..186e3fe
--- /dev/null
+++ b/client/CMakeLists.txt
@@ -0,0 +1,14 @@
1project(toynadi_client)
2
3include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
4
5set(common_path "../common/")
6
7set(toynadiclient_SRCS
8 ${common_path}/console.cpp
9 main.cpp
10 resourceaccess.cpp
11)
12add_executable(${PROJECT_NAME} ${toynadiclient_SRCS})
13qt5_use_modules(${PROJECT_NAME} Widgets Network)
14install(TARGETS ${PROJECT_NAME} DESTINATION bin)
diff --git a/client/main.cpp b/client/main.cpp
new file mode 100644
index 0000000..2fbb8fe
--- /dev/null
+++ b/client/main.cpp
@@ -0,0 +1,19 @@
1
2#include <QApplication>
3
4#include "common/console.h"
5#include "resourceaccess.h"
6
7int main(int argc, char *argv[])
8{
9 QApplication app(argc, argv);
10
11 new Console("Toy Client");
12 ResourceAccess *resAccess = new ResourceAccess("toyResource");
13
14 QObject::connect(&app, &QCoreApplication::aboutToQuit,
15 resAccess, &ResourceAccess::close);
16
17 resAccess->open();
18 return app.exec();
19} \ No newline at end of file
diff --git a/client/resourceaccess.cpp b/client/resourceaccess.cpp
new file mode 100644
index 0000000..1eadc34
--- /dev/null
+++ b/client/resourceaccess.cpp
@@ -0,0 +1,95 @@
1#include "resourceaccess.h"
2
3#include "common/console.h"
4
5#include <QDebug>
6#include <QProcess>
7
8ResourceAccess::ResourceAccess(const QString &resourceName, QObject *parent)
9 : QObject(parent),
10 m_resourceName(resourceName),
11 m_socket(new QLocalSocket(this)),
12 m_startingProcess(false)
13{
14 Console::main()->log(QString("Starting access to %1").arg(m_socket->serverName()));
15 connect(m_socket, &QLocalSocket::connected,
16 this, &ResourceAccess::connected);
17 connect(m_socket, &QLocalSocket::disconnected,
18 this, &ResourceAccess::disconnected);
19 connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
20 this, SLOT(connectionError(QLocalSocket::LocalSocketError)));
21}
22
23ResourceAccess::~ResourceAccess()
24{
25
26}
27
28QString ResourceAccess::resourceName() const
29{
30 return m_resourceName;
31}
32
33bool ResourceAccess::isReady() const
34{
35 return m_socket->isValid();
36}
37
38void ResourceAccess::open()
39{
40 static int count = 0;
41 if (m_startingProcess) {
42 QMetaObject::invokeMethod(this, "open", Qt::QueuedConnection);
43 }
44
45 if (m_socket->isValid()) {
46 return;
47 }
48
49 ++count;
50 if (count > 10000) {
51 return;
52 }
53
54 m_socket->setServerName(m_resourceName);
55 Console::main()->log(QString("Opening: %1").arg(m_socket->serverName()));
56 //FIXME: race between starting the exec and opening the socket?
57 m_socket->open();
58}
59
60void ResourceAccess::close()
61{
62 Console::main()->log(QString("Closing: %1").arg(m_socket->fullServerName()));
63 m_socket->close();
64}
65
66void ResourceAccess::connected()
67{
68 m_startingProcess = false;
69 Console::main()->log(QString("Connected: %1").arg(m_socket->fullServerName()));
70 emit ready(true);
71}
72
73void ResourceAccess::disconnected()
74{
75 Console::main()->log(QString("Disconnected: %1").arg(m_socket->fullServerName()));
76 emit ready(false);
77}
78
79void ResourceAccess::connectionError(QLocalSocket::LocalSocketError error)
80{
81 Console::main()->log(QString("Could not connect to %1 due to error %2").arg(m_socket->serverName()).arg(error));
82 if (m_startingProcess) {
83 QMetaObject::invokeMethod(this, "open", Qt::QueuedConnection);
84 return;
85 }
86
87 m_startingProcess = true;
88 Console::main()->log(QString("Attempting to start resource..."));
89 QStringList args;
90 args << m_resourceName;
91 if (QProcess::startDetached("toynadi_resource", args)) {
92 m_socket->open();
93 }
94}
95
diff --git a/client/resourceaccess.h b/client/resourceaccess.h
new file mode 100644
index 0000000..f4c4ad4
--- /dev/null
+++ b/client/resourceaccess.h
@@ -0,0 +1,33 @@
1#pragma once
2
3#include <QLocalSocket>
4#include <QObject>
5
6class ResourceAccess : public QObject
7{
8 Q_OBJECT
9
10public:
11 ResourceAccess(const QString &resourceName, QObject *parent = 0);
12 ~ResourceAccess();
13
14 QString resourceName() const;
15 bool isReady() const;
16
17public Q_SLOTS:
18 void open();
19 void close();
20
21Q_SIGNALS:
22 void ready(bool isReady);
23
24private Q_SLOTS:
25 void connected();
26 void disconnected();
27 void connectionError(QLocalSocket::LocalSocketError error);
28
29private:
30 QString m_resourceName;
31 QLocalSocket *m_socket;
32 bool m_startingProcess;
33};
diff --git a/common/console.cpp b/common/console.cpp
new file mode 100644
index 0000000..4ed7960
--- /dev/null
+++ b/common/console.cpp
@@ -0,0 +1,48 @@
1#include "console.h"
2
3#include <QLabel>
4#include <QTextBrowser>
5#include <QVBoxLayout>
6
7static Console *s_console = 0;
8
9Console *Console::main()
10{
11 if (!s_console) {
12 s_console = new Console("Stupido!");
13 }
14 return s_console;
15}
16
17Console::Console(const QString &title)
18 : QWidget(0)
19{
20 s_console = this;
21 resize(1000, 1500);
22
23 QVBoxLayout *topLayout = new QVBoxLayout(this);
24
25 QLabel *titleLabel = new QLabel(this);
26 titleLabel->setText(title);
27 QFont font = titleLabel->font();
28 font.setWeight(QFont::Bold);
29 titleLabel->setFont(font);
30 titleLabel->setAlignment(Qt::AlignCenter);
31
32 m_textDisplay = new QTextBrowser(this);
33
34 topLayout->addWidget(titleLabel);
35 topLayout->addWidget(m_textDisplay, 10);
36
37 show();
38}
39
40Console::~Console()
41{
42
43}
44
45void Console::log(const QString &message)
46{
47 m_textDisplay->append(message);
48}
diff --git a/common/console.h b/common/console.h
new file mode 100644
index 0000000..d504fb1
--- /dev/null
+++ b/common/console.h
@@ -0,0 +1,20 @@
1#pragma once
2
3#include <QWidget>
4
5class QTextBrowser;
6
7class Console : public QWidget
8{
9 Q_OBJECT
10public:
11 static Console *main();
12 Console(const QString &title);
13 ~Console();
14
15 void log(const QString &message);
16
17private:
18 QTextBrowser *m_textDisplay;
19 static Console *s_output;
20}; \ No newline at end of file
diff --git a/resource/CMakeLists.txt b/resource/CMakeLists.txt
new file mode 100644
index 0000000..3de51b5
--- /dev/null
+++ b/resource/CMakeLists.txt
@@ -0,0 +1,15 @@
1project(toynadi_resource)
2
3include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
4
5set(common_path "../common/")
6
7set(toynadiresource_SRCS
8 ${common_path}/console.cpp
9 main.cpp
10 listener.cpp
11)
12
13add_executable(${PROJECT_NAME} ${toynadiresource_SRCS})
14qt5_use_modules(${PROJECT_NAME} Widgets Network)
15install(TARGETS ${PROJECT_NAME} DESTINATION bin)
diff --git a/resource/listener.cpp b/resource/listener.cpp
new file mode 100644
index 0000000..efdfe3e
--- /dev/null
+++ b/resource/listener.cpp
@@ -0,0 +1,71 @@
1#include "listener.h"
2
3#include "common/console.h"
4
5#include <QLocalSocket>
6
7Listener::Listener(const QString &resource, QObject *parent)
8 : QObject(parent),
9 m_server(new QLocalServer(this))
10{
11 connect(m_server, &QLocalServer::newConnection,
12 this, &Listener::acceptConnection);
13 Console::main()->log(QString("Trying to open %1").arg(resource));
14 if (!m_server->listen(resource)) {
15 // FIXME: multiple starts need to be handled here
16 m_server->removeServer(resource);
17 if (!m_server->listen(resource)) {
18 Console::main()->log("Utter failure to start server");
19 exit(-1);
20 }
21 }
22
23 if (m_server->isListening()) {
24 Console::main()->log(QString("Listening on %1").arg(m_server->serverName()));
25 }
26}
27
28Listener::~Listener()
29{
30}
31
32void Listener::closeAllConnections()
33{
34 //TODO: close all client connectionsin m_connections
35}
36
37void Listener::acceptConnection()
38{
39 Console::main()->log(QString("Accepting connection"));
40 QLocalSocket *connection = m_server->nextPendingConnection();
41
42 if (!connection) {
43 return;
44 }
45
46 Console::main()->log("Got a connection");
47 Client client(connection);
48 m_connections << client;
49 connect(connection, &QLocalSocket::disconnected,
50 this, &Listener::clientDropped);
51
52}
53
54void Listener::clientDropped()
55{
56 QLocalSocket *connection = qobject_cast<QLocalSocket *>(sender());
57 if (!connection) {
58 return;
59 }
60
61 Console::main()->log("Dropping connection...");
62 QMutableListIterator<Client> it(m_connections);
63 while (it.hasNext()) {
64 const Client &client = it.next();
65 if (client.m_socket == connection) {
66 Console::main()->log(" dropped...");
67 it.remove();
68 break;
69 }
70 }
71}
diff --git a/resource/listener.h b/resource/listener.h
new file mode 100644
index 0000000..79c7ba5
--- /dev/null
+++ b/resource/listener.h
@@ -0,0 +1,37 @@
1#pragma once
2
3#include <QLocalServer>
4#include <QLocalSocket>
5#include <QList>
6#include <QObject>
7
8class Client
9{
10public:
11 Client(QLocalSocket *s)
12 : m_socket(s),
13 m_commanded(false)
14 {
15 }
16
17 QLocalSocket *m_socket;
18 bool m_commanded;
19};
20
21class Listener : public QObject
22{
23public:
24 Listener(const QString &resourceName, QObject *parent = 0);
25 ~Listener();
26
27public Q_SLOTS:
28 void closeAllConnections();
29
30private Q_SLOTS:
31 void acceptConnection();
32 void clientDropped();
33
34private:
35 QLocalServer *m_server;
36 QList<Client> m_connections;
37}; \ No newline at end of file
diff --git a/resource/main.cpp b/resource/main.cpp
new file mode 100644
index 0000000..3bd4656
--- /dev/null
+++ b/resource/main.cpp
@@ -0,0 +1,23 @@
1
2#include <QApplication>
3
4#include "common/console.h"
5#include "listener.h"
6
7int main(int argc, char *argv[])
8{
9 QApplication app(argc, argv);
10
11 new Console(QString("Toy Resource: %1").arg(argv[1]));
12 if (argc < 2) {
13 Console::main()->log("Not enough args");
14 return app.exec();
15 }
16
17 Listener *listener = new Listener(argv[1]);
18
19 QObject::connect(&app, &QCoreApplication::aboutToQuit,
20 listener, &Listener::closeAllConnections);
21
22 return app.exec();
23} \ No newline at end of file