diff --git a/.installer/configuration/config.xml b/.installer/configuration/config.xml
index c3c81bb..bfab375 100644
--- a/.installer/configuration/config.xml
+++ b/.installer/configuration/config.xml
@@ -11,7 +11,7 @@
@HomeDir@/.clipbird
Clipbird Installer
Clipbird
- 1.0.0
+ 1.1.0
Sri Lakshmi Kanthan P
Clipbird
diff --git a/.installer/packages/clipbird/meta/install.qs b/.installer/packages/clipbird/meta/install.qs
index 0b40585..5a46971 100644
--- a/.installer/packages/clipbird/meta/install.qs
+++ b/.installer/packages/clipbird/meta/install.qs
@@ -61,7 +61,7 @@ Component.prototype.createOperations = function () {
"@TargetDir@/clipbird.exe",
"@StartMenuDir@/ClipBird.lnk",
"workingDirectory=@TargetDir@",
- "iconPath=@TargetDir@/logo.png",
+ "iconPath=@TargetDir@/logo.ico",
"IconId=0",
"description=ClipBird"
);
diff --git a/.installer/packages/clipbird/meta/package.xml b/.installer/packages/clipbird/meta/package.xml
index 58bcd0b..9bdaaa7 100644
--- a/.installer/packages/clipbird/meta/package.xml
+++ b/.installer/packages/clipbird/meta/package.xml
@@ -15,7 +15,7 @@
on your network.
2023-07-29
- 1.0.0
+ 1.1.0
diff --git a/.scripts/package.ps1 b/.scripts/package.ps1
index 6cf0954..864d1a5 100644
--- a/.scripts/package.ps1
+++ b/.scripts/package.ps1
@@ -24,11 +24,11 @@ Remove-Item -Recurse -Force $ClipbirDir/* -Exclude .gitignore
# Copy All openssl dlls to the package directory
Write-Host "Copying $env:OPENSSL_ROOT_DIR /bin/*.dll to $ClipbirDir" -ForegroundColor Green
-Copy-Item "$env:OPENSSL_ROOT_DIR /bin/*.dll" $ClipbirDir
+Copy-Item "$env:OPENSSL_ROOT_DIR/bin/*.dll" $ClipbirDir
# copy the Logo to the package directory
-Write-Host "Copying ./assets/images/logo.png to $ClipbirDir" -ForegroundColor Green
-Copy-Item ./assets/images/logo.png $ClipbirDir
+Write-Host "Copying ./assets/images/* to $ClipbirDir" -ForegroundColor Green
+Copy-Item ./assets/images/* $ClipbirDir
# Create the package as BuildType (to lower) version
Write-Host "Creating the package as Release version" -ForegroundColor Green
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index b6b63aa..ad8a802 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -1,28 +1,5 @@
{
"configurations": [
- {
- "compilerPath": "/usr/bin/gcc",
- "name": "linux",
- "includePath": [
- "${workspaceFolder}/build/_deps/singleapplication-src",
- "${workspaceFolder}/build",
- "${workspaceFolder}/",
- "${workspaceFolder}/build/_deps/**",
- "/opt/Qt/6.5.2/gcc_64/include/QtGui",
- "/opt/Qt/6.5.2/gcc_64/include/QtCore",
- "/opt/Qt/6.5.2/gcc_64/include/**",
- "${HOME}/.kderoot/include/KF6/KDNSSD"
- ],
- "defines": [
- "_UNICODE",
- "_DEBUG",
- "UNICODE"
- ],
- "cStandard": "c17",
- "cppStandard": "c++17",
- "intelliSenseMode": "linux-gcc-x64",
- "configurationProvider": "ms-vscode.cpptools"
- },
{
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.33.31629/bin/Hostx64/x64/cl.exe",
"name": "Win32",
@@ -38,11 +15,7 @@
"C:\\Program Files\\Bonjour SDK\\Include",
"C:\\kderoot\\include\\KF6\\KGuiAddons\\**"
],
- "defines": [
- "_UNICODE",
- "_DEBUG",
- "UNICODE"
- ],
+ "defines": [ "_UNICODE", "_DEBUG", "UNICODE" ],
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "msvc-x64",
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 02c288e..1c6dca2 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -14,7 +14,8 @@
"pubkey",
"qobject",
"qvariant",
- "SSLCONFIG"
+ "SSLCONFIG",
+ "unauthed"
],
"files.associations": {
".env*": "dotenv",
@@ -148,6 +149,11 @@
"*.qs": "javascript",
".qs": "javascript",
"qsystemtrayicon": "cpp",
- "qsettings": "cpp"
+ "qsettings": "cpp",
+ "queue": "cpp",
+ "stack": "cpp",
+ "qsslcertificate": "cpp",
+ "qapplication": "cpp",
+ "singleapplication": "cpp"
},
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 37fb66e..0ca572f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
# set project name and version
-project(clipbird VERSION 0.0.1 LANGUAGES CXX)
+project(clipbird VERSION 1.1.0 LANGUAGES CXX)
# set c++ standard 17
set(CMAKE_CXX_STANDARD 17)
@@ -105,6 +105,11 @@ qt_standard_project_setup()
qt_add_resources(RESOURCES
${PROJECT_SOURCE_DIR}/assets/resources.qrc)
+# Add windows.rc to project
+if (WIN32)
+ set (RESOURCES ${RESOURCES} ${PROJECT_SOURCE_DIR}/assets/windows.rc)
+endif()
+
# Add executable
qt_add_executable(clipbird
${main_cpp} ${RESOURCES})
@@ -114,7 +119,6 @@ target_link_libraries(clipbird
PRIVATE SingleApplication::SingleApplication
PRIVATE Qt6::Widgets
PRIVATE Qt6::Network
- PRIVATE Qt6::Sql
PRIVATE OpenSSL::SSL
PRIVATE OpenSSL::Crypto)
@@ -146,10 +150,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
target_compile_options(clipbird PRIVATE -std=c++17)
endif()
-# add target linker options MSVC /NODEFAULTLIB:library
# add target compiler options MSVC /std:c++17
if(MSVC)
- target_link_options(clipbird PRIVATE /NODEFAULTLIB:library)
target_compile_options(clipbird PRIVATE /std:c++17)
endif()
diff --git a/README.md b/README.md
index 09c4432..1f2df85 100644
--- a/README.md
+++ b/README.md
@@ -110,14 +110,6 @@ In the following steps, we will see how to build the project in the Windows plat
* Qt6
* OpenSSL
-#### Installing Qt6
-
-Go to [Qt](https://www.qt.io/download-qt-installer) and download the Qt installer for windows, then install it in your system. After installing Qt, you need to set the environment variable `QT_CMAKE_DIR` to the Qt cmake directory.
-
-#### Installing Bonjour
-
-Just go to [bonjour](https://developer.apple.com/bonjour/) and downlod the bonjour SDK for windows, then install it in your system. It should set the environment variable `BONJOUR_SDK_HOME` to the Bonjour SDK directory.
-
#### Installing OpenSSL
Install OpenSSL using the following command and set the environment variable `OPENSSL_ROOT_DIR` to the OpenSSL installation directory.
@@ -126,6 +118,14 @@ Install OpenSSL using the following command and set the environment variable `OP
choco install openssl
~~~
+#### Installing Qt6
+
+Go to [Qt](https://www.qt.io/download-qt-installer) and download the Qt installer for windows, then install it in your system. After installing Qt, you need to set the environment variable `QT_CMAKE_DIR` to the Qt cmake directory.
+
+#### Installing Bonjour
+
+Just go to [bonjour](https://developer.apple.com/bonjour/) and downlod the bonjour SDK for windows, then install it in your system. It should set the environment variable `BONJOUR_SDK_HOME` to the Bonjour SDK directory.
+
#### Environment Variables
| Variable | Value |
diff --git a/assets/images/logo.ico b/assets/images/logo.ico
new file mode 100644
index 0000000..11658fb
Binary files /dev/null and b/assets/images/logo.ico differ
diff --git a/assets/windows.rc b/assets/windows.rc
new file mode 100644
index 0000000..f49adf4
--- /dev/null
+++ b/assets/windows.rc
@@ -0,0 +1,6 @@
+// Copyright (c) 2023 Sri Lakshmi Kanthan P
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+appIcon ICON "./assets/images/logo.ico"
diff --git a/constants/constants.cpp b/constants/constants.cpp
index ab65515..52e241d 100644
--- a/constants/constants.cpp
+++ b/constants/constants.cpp
@@ -111,7 +111,6 @@ std::string getAppIssuePage() {
* @return std::string
*/
std::string getMDnsServiceName() {
- std::cout << QSysInfo::machineHostName().toStdString() << std::endl;
return QSysInfo::machineHostName().toStdString();
}
diff --git a/controller/clipbird/clipbird.cpp b/controller/clipbird/clipbird.cpp
index 59a9d52..18ea667 100644
--- a/controller/clipbird/clipbird.cpp
+++ b/controller/clipbird/clipbird.cpp
@@ -7,46 +7,82 @@
namespace srilakshmikanthanp::clipbirdesk::controller {
/**
- * @brief Handle On Server Authenticated the Client (From client)
+ * @brief Handle On Client State Changed (From server)
+ */
+void ClipBird::handleClientStateChanged(types::device::Device client, bool connected) {
+ // if the host is not server then throw error
+ if (!std::holds_alternative(m_host)) {
+ throw std::runtime_error("Host is not server");
+ }
+
+ // if not Connected the return
+ if (!connected) return;
+
+ // get the device certificate from the server
+ auto cert = std::get(m_host).getClientCert(client);
+
+ // get the store instance to store certificate
+ auto &store = storage::Storage::instance();
+
+ // store the client certificate
+ store.setClientCert(client.name, cert.toPem());
+
+ // add ca certificates
+ this->m_sslConfig.addCaCertificate(cert);
+
+ // set new config for Server
+ std::get(m_host).setSslConfiguration(this->m_sslConfig);
+}
+
+/**
+ * @brief Handle On Server Disconnect from Client (From client)
*
* @param isConnected is connected to the server
*/
-void ClipBird::handleServerAuthentication(bool isSuccess) {
+void ClipBird::handleServerStatusChanged(bool status) {
// if the host is not client then throw error
if (!std::holds_alternative(m_host)) {
throw std::runtime_error("Host is not client");
}
// get the client and disconnect the signals
- const auto signal = &clipboard::Clipboard::OnClipboardChange;
- auto *client = &std::get(m_host);
- const auto slot_n = &Client::syncItems;
+ auto signal = &clipboard::Clipboard::OnClipboardChange;
+ auto *client = &std::get(m_host);
+ auto slot_n = &Client::syncItems;
+ auto &store = storage::Storage::instance();
// if the client is connected then connect the signals
- if (isSuccess) {
+ if (!status) {
+ disconnect(&m_clipboard, signal, client, slot_n);
+ } else {
connect(&m_clipboard, signal, client, slot_n);
+ auto cert = client->getConnectedServerCertificate();
+ auto name = client->getConnectedServer().name;
+ store.setServerCert(name, cert.toPem());
+ this->m_sslConfig.addCaCertificate(cert);
+ client->setSslConfiguration(this->m_sslConfig);
}
}
/**
- * @brief Handle On Server Disconnect from Client (From client)
- *
- * @param isConnected is connected to the server
+ * @brief Handle the Server Found (From client)
*/
-void ClipBird::handleServerStatusChanged(bool status) {
+void ClipBird::handleServerFound(types::device::Device server) {
// if the host is not client then throw error
if (!std::holds_alternative(m_host)) {
throw std::runtime_error("Host is not client");
}
- // get the client and disconnect the signals
- const auto signal = &clipboard::Clipboard::OnClipboardChange;
- auto *client = &std::get(m_host);
- const auto slot_n = &Client::syncItems;
+ // if already connected then return
+ if (std::get(m_host).isConnected()) return;
- // if the client is connected then connect the signals
- if (!status) {
- disconnect(&m_clipboard, signal, client, slot_n);
+ // get the client and store the server
+ auto *client = &std::get(m_host);
+ auto &store = storage::Storage::instance();
+
+ // if the server is not found then return
+ if (store.hasServerCert(server.name)) {
+ client->connectToServerSecured(server);
}
}
@@ -57,8 +93,7 @@ void ClipBird::handleServerStatusChanged(bool status) {
* @param board clipboard that is managed
* @param parent parent object
*/
-ClipBird::ClipBird(QSslConfiguration config, QObject *parent)
- : QObject(parent), m_clipboard(this), m_sslConfig(config) {}
+ClipBird::ClipBird(QObject *parent) : QObject(parent), m_clipboard(this) {}
//---------------------- public slots -----------------------//
@@ -71,22 +106,25 @@ void ClipBird::setCurrentHostAsServer() {
auto *server = &m_host.emplace(this);
// Set the QSslConfiguration
- server->setSSLConfiguration(m_sslConfig);
+ server->setSslConfiguration(m_sslConfig);
// Connect the onClientStateChanged signal to the signal
+ const auto slot_hcs = &ClipBird::handleClientStateChanged;
const auto signal_cs = &Server::OnCLientStateChanged;
const auto slot_cs = &ClipBird::OnCLientStateChanged;
connect(server, signal_cs, this, slot_cs);
+ connect(server, signal_cs, this, slot_hcs);
- // Connect the onNewHostConnected signal to the signal
- const auto signal_nh = &Server::OnNewHostConnected;
- const auto slot_nh = &ClipBird::OnNewHostConnected;
- connect(server, signal_nh, this, slot_nh);
+ // connect OnAuthRequest to clipbird OnAuthRequest
+ // Connect the onSyncRequest signal to the clipboard
+ const auto signal_sa = &Server::OnAuthRequest;
+ const auto slot_sa = &ClipBird::OnAuthRequest;
+ connect(server, signal_sa, this, slot_sa);
// Connect the onSyncRequest signal to the clipboard
const auto signal_sr = &Server::OnSyncRequest;
- const auto slot_bs = &clipboard::Clipboard::set;
- connect(server, signal_sr, &m_clipboard, slot_bs);
+ const auto slot_sr = &clipboard::Clipboard::set;
+ connect(server, signal_sr, &m_clipboard, slot_sr);
// connect the OnClipboardChange signal to the server
const auto signal_cc = &clipboard::Clipboard::OnClipboardChange;
@@ -103,6 +141,12 @@ void ClipBird::setCurrentHostAsServer() {
const auto slot_ss = &ClipBird::OnServerStateChanged;
connect(server, signal_ss, this, slot_ss);
+ // get the storage instance
+ auto &store = storage::Storage::instance();
+
+ // set the host is client
+ store.setHostIsServer(true);
+
// Start the server to listen and accept the client
server->startServer();
}
@@ -114,6 +158,9 @@ void ClipBird::setCurrentHostAsClient() {
// Emplace the client into the m_host variant variable
auto *client = &m_host.emplace(this);
+ // Set the QSslConfiguration
+ client->setSslConfiguration(m_sslConfig);
+
// Connect the onServerListChanged signal to the signal
const auto signal_sl = &Client::OnServerListChanged;
const auto slot_sl = &ClipBird::OnServerListChanged;
@@ -121,9 +168,16 @@ void ClipBird::setCurrentHostAsClient() {
// Connect the onServerFound signal to the signal
const auto signal_fn = &Client::OnServerFound;
+ const auto slot_hfn = &ClipBird::handleServerFound;
const auto slot_fn = &ClipBird::OnServerFound;
+ connect(client, signal_fn, this, slot_hfn);
connect(client, signal_fn, this, slot_fn);
+ // Connect the OnServerGone signal to the signal
+ const auto signal_sg = &Client::OnServerGone;
+ const auto slot_sg = &ClipBird::OnServerGone;
+ connect(client, signal_sg, this, slot_sg);
+
// Connect the onServerStateChanged signal to the signal
const auto slot_hc = &ClipBird::handleServerStatusChanged;
const auto signal_sc = &Client::OnServerStatusChanged;
@@ -131,22 +185,125 @@ void ClipBird::setCurrentHostAsClient() {
connect(client, signal_sc, this, slot_sc);
connect(client, signal_sc, this, slot_hc);
- // Connect the onServerAuthentication signal to the signal
- const auto slot_ha = &ClipBird::handleServerAuthentication;
- const auto signal_au = &Client::OnServerAuthentication;
- const auto slot_au = &ClipBird::OnServerAuthentication;
- connect(client, signal_au, this, slot_au);
- connect(client, signal_au, this, slot_ha);
-
// Connect the onSyncRequest signal to the clipboard
const auto signal_rq = &Client::OnSyncRequest;
const auto slot_rq = &clipboard::Clipboard::set;
connect(client, signal_rq, &m_clipboard, slot_rq);
+ // get the storage instance
+ auto &store = storage::Storage::instance();
+
+ // set the host is client
+ store.setHostIsServer(false);
+
// Start the Discovery
client->startBrowsing();
}
+/**
+ * @brief Set the SSL Configuration object
+ */
+void ClipBird::setSslConfiguration(QSslConfiguration config) {
+ // storage instance
+ storage::Storage &store = storage::Storage::instance();
+
+ // Ca Certificates
+ QList caCerts;
+
+ // set all ca Client certs from store
+ for (auto certByte : store.getAllClientCert()) {
+ caCerts.append(QSslCertificate(certByte, QSsl::Pem));
+ }
+
+ // set all ca Server certs from store
+ for (auto certByte : store.getAllServerCert()) {
+ caCerts.append(QSslCertificate(certByte, QSsl::Pem));
+ }
+
+ // set ca certificates
+ config.setCaCertificates(caCerts);
+
+ // set the ssl configuration
+ this->m_sslConfig = config;
+}
+
+/**
+ * @brief Get the SSL Configuration object
+ */
+QSslConfiguration ClipBird::getSslConfiguration() const {
+ return m_sslConfig;
+}
+
+/**
+ * @brief Clear the Server Certificates
+ */
+void ClipBird::clearServerCertificates() {
+ // storage instance
+ storage::Storage &store = storage::Storage::instance();
+
+ // Ca Certificates
+ QList caCerts;
+
+ // clear all ca Server certs from m_sslconfig
+ this->m_sslConfig.setCaCertificates(caCerts);
+
+ // set all ca Client certs from store
+ for (auto certByte : store.getAllClientCert()) {
+ caCerts.append(QSslCertificate(certByte, QSsl::Pem));
+ }
+
+ // set the ca certificates
+ this->m_sslConfig.setCaCertificates(caCerts);
+
+ // clear all ca Server certs from store
+ store.clearAllServerCert();
+
+ // if the host is server then set the ssl configuration
+ if (std::holds_alternative(m_host)) {
+ std::get(m_host).setSslConfiguration(this->m_sslConfig);
+ }
+
+ // if the host is client then set the ssl configuration
+ if (std::holds_alternative(m_host)) {
+ std::get(m_host).setSslConfiguration(this->m_sslConfig);
+ }
+}
+
+/**
+ * @brief Clear the Client Certificates
+ */
+void ClipBird::clearClientCertificates() {
+ // storage instance
+ storage::Storage &store = storage::Storage::instance();
+
+ // Ca Certificates
+ QList caCerts;
+
+ // clear all ca Server certs from m_sslconfig
+ this->m_sslConfig.setCaCertificates(caCerts);
+
+ // set all ca Client certs from store
+ for (auto certByte : store.getAllServerCert()) {
+ caCerts.append(QSslCertificate(certByte, QSsl::Pem));
+ }
+
+ // set the ca certificates
+ this->m_sslConfig.setCaCertificates(caCerts);
+
+ // clear all ca Server certs from store
+ store.clearAllServerCert();
+
+ // if the host is server then set the ssl configuration
+ if (std::holds_alternative(m_host)) {
+ std::get(m_host).setSslConfiguration(this->m_sslConfig);
+ }
+
+ // if the host is client then set the ssl configuration
+ if (std::holds_alternative(m_host)) {
+ std::get(m_host).setSslConfiguration(this->m_sslConfig);
+ }
+}
+
//---------------------- Server functions -----------------------//
/**
@@ -154,7 +311,7 @@ void ClipBird::setCurrentHostAsClient() {
*
* @return QList List of clients
*/
-QList> ClipBird::getConnectedClientsList() const {
+QList ClipBird::getConnectedClientsList() const {
if (std::holds_alternative(m_host)) {
return std::get(m_host).getConnectedClientsList();
} else {
@@ -168,7 +325,7 @@ QList> ClipBird::getConnectedClientsList() const {
* @param host ip address of the client
* @param ip port number of the client
*/
-void ClipBird::disconnectClient(const QPair &client) {
+void ClipBird::disconnectClient(const types::device::Device &client) {
// if the host is not server then throw
if (!std::holds_alternative(m_host)) {
throw std::runtime_error("Host is not server");
@@ -176,7 +333,7 @@ void ClipBird::disconnectClient(const QPair &client) {
// find the client with the given host and ip
const auto match = [&](auto i) -> auto{
- return i.first == client.first && i.second == client.second;
+ return (i.ip == client.ip) && (i.port == client.port);
};
// get the list of clients
@@ -205,38 +362,38 @@ void ClipBird::disconnectAllClients() {
}
/**
- * @brief The function that is called when the client is authenticated
- *
- * @param client the client that is currently processed
+ * @brief Get the server QHostAddress and port
*/
-void ClipBird::authSuccess(const QPair &client) {
+types::device::Device ClipBird::getServerInfo() const {
if (std::holds_alternative(m_host)) {
- std::get(m_host).authSuccess(client);
+ return std::get(m_host).getServerInfo();
} else {
throw std::runtime_error("Host is not server");
}
}
/**
- * @brief The function that is called when the client it not
- * authenticated
+ * @brief The function that is called when the client is authenticated
*
* @param client the client that is currently processed
*/
-void ClipBird::authFailed(const QPair &client) {
+void ClipBird::authSuccess(const types::device::Device &client) {
if (std::holds_alternative(m_host)) {
- std::get(m_host).authFailed(client);
+ std::get(m_host).authSuccess(client);
} else {
throw std::runtime_error("Host is not server");
}
}
/**
- * @brief Get the server QHostAddress and port
+ * @brief The function that is called when the client it not
+ * authenticated
+ *
+ * @param client the client that is currently processed
*/
-QPair ClipBird::getServerInfo() const {
+void ClipBird::authFailed(const types::device::Device &client) {
if (std::holds_alternative(m_host)) {
- return std::get(m_host).getServerInfo();
+ std::get(m_host).authFailed(client);
} else {
throw std::runtime_error("Host is not server");
}
@@ -247,9 +404,9 @@ QPair ClipBird::getServerInfo() const {
/**
* @brief Get the Server List object
*
- * @return QList> List of servers
+ * @return QList List of servers
*/
-QList> ClipBird::getServerList() const {
+QList ClipBird::getServerList() const {
if (std::holds_alternative(m_host)) {
return std::get(m_host).getServerList();
} else {
@@ -264,7 +421,7 @@ QList> ClipBird::getServerList() const {
* @param host Host address
* @param port Port number
*/
-void ClipBird::connectToServer(const QPair &host) {
+void ClipBird::connectToServer(const types::device::Device &host) {
if (std::holds_alternative(m_host)) {
std::get(m_host).connectToServer(host);
} else {
@@ -273,26 +430,24 @@ void ClipBird::connectToServer(const QPair &host) {
}
/**
- * @brief get the connected server address and port
- *
- * @return QPair address and port
+ * @brief Is Client Connected
*/
-QPair ClipBird::getConnectedServer() const {
+bool ClipBird::isConnectedToServer() {
if (std::holds_alternative(m_host)) {
- return std::get(m_host).getConnectedServer();
+ return std::get(m_host).isConnected();
} else {
throw std::runtime_error("Host is not client");
}
}
/**
- * @brief get the connected server address and port or empty
+ * @brief get the connected server address and port
*
- * @return QPair address and port
+ * @return types::device::Device address and port
*/
-QPair ClipBird::getConnectedServerOrEmpty() const {
+types::device::Device ClipBird::getConnectedServer() const {
if (std::holds_alternative(m_host)) {
- return std::get(m_host).getConnectedServerOrEmpty();
+ return std::get(m_host).getConnectedServer();
} else {
throw std::runtime_error("Host is not client");
}
@@ -301,7 +456,7 @@ QPair ClipBird::getConnectedServerOrEmpty() const {
/**
* @brief Disconnect from the server
*/
-void ClipBird::disconnectFromServer(const QPair &host) {
+void ClipBird::disconnectFromServer(const types::device::Device &host) {
// if the host is not client then throw error
if (!std::holds_alternative(m_host)) {
throw std::runtime_error("Host is not client");
@@ -309,7 +464,7 @@ void ClipBird::disconnectFromServer(const QPair &host) {
// find the server with the given host and ip
const auto match = [&](auto i) -> auto{
- return i.first == host.first && i.second == host.second;
+ return (i.ip == host.ip) && (i.port == host.port);
};
// get the connected server
@@ -324,26 +479,9 @@ void ClipBird::disconnectFromServer(const QPair &host) {
}
/**
- * @brief Get the Authed Server object
- * @return QPair
- */
-QPair ClipBird::getAuthedServer() const {
- if (std::holds_alternative(m_host)) {
- return std::get(m_host).getAuthedServer();
- } else {
- throw std::runtime_error("Host is not client");
- }
-}
-
-/**
- * @brief Get the Authed Server object Or Empty
- * @return QPair
+ * @brief IS the Host is Lastly Server
*/
-QPair ClipBird::getAuthedServerOrEmpty() const {
- if (std::holds_alternative(m_host)) {
- return std::get(m_host).getAuthedServerOrEmpty();
- } else {
- throw std::runtime_error("Host is not client");
- }
+bool ClipBird::isLastlyHostIsServer() const {
+ return storage::Storage::instance().getHostIsServer();
}
} // namespace srilakshmikanthanp::clipbirdesk::controller
diff --git a/controller/clipbird/clipbird.hpp b/controller/clipbird/clipbird.hpp
index b34541c..b535dde 100644
--- a/controller/clipbird/clipbird.hpp
+++ b/controller/clipbird/clipbird.hpp
@@ -19,6 +19,8 @@
#include "clipboard/clipboard.hpp"
#include "network/syncing/client/client.hpp"
#include "network/syncing/server/server.hpp"
+#include "store/storage.hpp"
+#include "types/device/device.hpp"
namespace srilakshmikanthanp::clipbirdesk::controller {
class ClipBird : public QObject {
@@ -26,37 +28,37 @@ class ClipBird : public QObject {
signals: // signals for this class
/// @brief On Server List Changed (From Client)
- void OnServerListChanged(QList> servers);
+ void OnServerListChanged(QList servers);
signals: // signals for this class
/// @brief On Server Found (From Client)
- void OnServerFound(QPair server);
+ void OnServerFound(types::device::Device server);
signals: // signals for this class
- /// @brief On Server state changed (From Client)
- void OnServerStatusChanged(bool isConnected);
+ /// @brief On Server Gone
+ void OnServerGone(types::device::Device);
signals: // signals for this class
- /// @brief On Server Auth Succeed (From Client)
- void OnServerAuthentication(bool isSuccessful);
+ /// @brief On Server state changed (From Client)
+ void OnServerStatusChanged(bool isConnected);
//----------------------- server Signals ------------------------//
signals: // signals
/// @brief On client state changed (From Server)
- void OnCLientStateChanged(QPair client, bool connected);
-
- signals: // signals for this class
- /// @brief On New Host Connected
- void OnNewHostConnected(QPair client);
+ void OnCLientStateChanged(types::device::Device client, bool connected);
signals: // signals for this class
/// @brief On Server state changed (From Server)
void OnServerStateChanged(bool isStarted);
+ signals: // signals for this class
+ /// @brief On Sync Request
+ void OnAuthRequest(types::device::Device client);
+
signals: // signals for this class
/// @brief On Sync Request (From Server)
- void OnClientListChanged(QList> clients);
+ void OnClientListChanged(QList clients);
private: // typedefs for this class
@@ -75,12 +77,15 @@ class ClipBird : public QObject {
private: // private slots
- /// @brief Handle On Server Authenticated the client (From client)
- void handleServerAuthentication(bool isConnected);
+ /// @brief Handle Client State Changes (From server)
+ void handleClientStateChanged(types::device::Device client, bool connected);
- /// @brief Handle On Server Disconnect from Client (From client)
+ /// @brief Handle On Server Disconnect (From client)
void handleServerStatusChanged(bool status);
+ /// @brief Handle the Server Found (From client)
+ void handleServerFound(types::device::Device server);
+
public: // Member functions
/**
@@ -90,14 +95,14 @@ class ClipBird : public QObject {
* @param board clipboard that is managed
* @param parent parent object
*/
- ClipBird(QSslConfiguration config, QObject *parent = nullptr);
+ ClipBird(QObject *parent = nullptr);
/**
* @brief Destroy the ClipBird object
*/
virtual ~ClipBird() = default;
- //---------------------- public slots ----------------------//
+ //------------------------- public slots -------------------------//
/**
* @brief set the host as server and start listening
@@ -110,14 +115,38 @@ class ClipBird : public QObject {
*/
void setCurrentHostAsClient();
- //---------------------- Server functions -----------------------//
+ //--------------------- General functions ----------------------//
+
+ /**
+ * @brief Set the SSL Configuration object
+ */
+ void setSslConfiguration(QSslConfiguration config);
+
+ /**
+ * @brief Get the SSL Configuration object
+ */
+ QSslConfiguration getSslConfiguration() const;
+
+ //------------------- Store functions ------------------------//
+
+ /**
+ * @brief Clear Server Certificates
+ */
+ void clearServerCertificates();
+
+ /**
+ * @brief Clear Client Certificates
+ */
+ void clearClientCertificates();
+
+ //------------------- Server functions ------------------------//
/**
* @brief Get the Clients that are connected to the server
*
* @return QList List of clients
*/
- QList> getConnectedClientsList() const;
+ QList getConnectedClientsList() const;
/**
* @brief Disconnect the client from the server and delete
@@ -125,19 +154,24 @@ class ClipBird : public QObject {
* @param host ip address of the client
* @param ip port number of the client
*/
- void disconnectClient(const QPair &client);
+ void disconnectClient(const types::device::Device &client);
/**
* @brief Disconnect the all the clients from the server
*/
void disconnectAllClients();
+ /**
+ * @brief Get the server QHostAddress and port
+ */
+ types::device::Device getServerInfo() const;
+
/**
* @brief The function that is called when the client is authenticated
*
* @param client the client that is currently processed
*/
- void authSuccess(const QPair &client);
+ void authSuccess(const types::device::Device &client);
/**
* @brief The function that is called when the client it not
@@ -145,21 +179,16 @@ class ClipBird : public QObject {
*
* @param client the client that is currently processed
*/
- void authFailed(const QPair &client);
-
- /**
- * @brief Get the server QHostAddress and port
- */
- QPair getServerInfo() const;
+ void authFailed(const types::device::Device &client);
//---------------------- Client functions -----------------------//
/**
* @brief Get the Server List object
*
- * @return QList> List of servers
+ * @return QList List of servers
*/
- QList> getServerList() const;
+ QList getServerList() const;
/**
* @brief Connect to the server with the given host and port
@@ -168,37 +197,30 @@ class ClipBird : public QObject {
* @param host Host address
* @param port Port number
*/
- void connectToServer(const QPair &host);
+ void connectToServer(const types::device::Device &host);
/**
- * @brief get the connected server address and port
- *
- * @return QPair address and port
+ * @brief Is Client Connected
*/
- QPair getConnectedServer() const;
+ bool isConnectedToServer();
/**
- * @brief get the connected server address and port or empty
+ * @brief get the connected server address and port
*
- * @return QPair address and port
+ * @return types::device::Device address and port
*/
- QPair getConnectedServerOrEmpty() const;
+ types::device::Device getConnectedServer() const;
/**
* @brief Disconnect from the server
*/
- void disconnectFromServer(const QPair &host);
+ void disconnectFromServer(const types::device::Device &host);
- /**
- * @brief Get the Authed Server object
- * @return QPair
- */
- QPair getAuthedServer() const;
+ //---------------------- General functions -----------------------//
/**
- * @brief Get the Authed Server object Or Empty
- * @return QPair
+ * @brief IS the Host is Lastly Server
*/
- QPair getAuthedServerOrEmpty() const;
+ bool isLastlyHostIsServer() const;
};
} // namespace srilakshmikanthanp::clipbirdesk::controller
diff --git a/docs/design/Protocol.md b/docs/design/Protocol.md
index 9f90820..8f68186 100644
--- a/docs/design/Protocol.md
+++ b/docs/design/Protocol.md
@@ -33,7 +33,7 @@ Clipbird utilizes a variety of packet types for different purposes. These packet
### What are the packets Required for Clipbird
-First we need to Send the authenticate Request to the server, for that we need to send the **Authentication** packet to the server. This packet may contains the JWT token if it has a valid JWT token the server will accept the connection without user intervention. If the token is invalid the server will send the **Authentication** packet with **AuthStatus** set to 0x00. If the token is valid the server will send the **Authentication** packet with **AuthStatus** set to 0x01. If the server is not configured to use JWT token it will send the **Authentication** packet with **AuthStatus** set to 0x01. If the server is configured to use JWT token but the client does not send the **Authentication** packet with JWT token the server will send the **Authentication** packet with **AuthStatus** set to 0x00.
+When Client connected to server The serve need to send an Response Called Authentication Success or failed for this purpose we use **Authentication**.
Once the server has been identified, clipboard data is transmitted between the client and the server using a single type of packet known as the **SyncingPacket**. This packet is responsible for transferring clipboard data from the client to the server and vice versa, ensuring seamless sharing of clipboard content between the two devices.
@@ -71,7 +71,7 @@ The **InvalidRequest** is used to indicate that the packet is invalid. This pack
| Error Code | Error Message |
|------------|---------------|
| 0x01 | Coding Error |
-| 0x02 | TLS Error |
+| 0x02 | InvalidPacket |
### Authentication
@@ -84,9 +84,9 @@ The **Authentication** is used to indicate the authentication process to the cli
#### Body
-- **AuthStatus**: This field specifies the status of the authentication process.
- - AuthFailed: This field specifies the status of the authentication process, which is set to 0x00 if the authentication fails.
- - AuthSuccess: This field specifies the status of the authentication process, which is set to 0x01 if the authentication succeeds.
+- **AuthStatus**: This field specifies the status of the authentication process. it can be one of the following values.
+ - 0x00: Auth Failed
+ - 0x01: Auth Success
#### Structure
diff --git a/main.cpp b/main.cpp
index 61d74e1..c5b1542 100644
--- a/main.cpp
+++ b/main.cpp
@@ -4,6 +4,8 @@
// https://opensource.org/licenses/MIT
// Qt Headers
+#include
+#include
#include
#include
#include
@@ -28,8 +30,82 @@ namespace srilakshmikanthanp::clipbirdesk {
* for ClipBird Application
*/
class ClipbirdApplication : public SingleApplication {
+ private: // Member Variables and Objects
+
+ // file path to store the certificate and key
+ std::string certPath = (std::filesystem::path(constants::getAppHome()) / "cert.pem").string();
+ std::string keyPath = (std::filesystem::path(constants::getAppHome()) / "key.pem").string();
+
private: // Member Functions
+ /**
+ * @brief Get the certificate from App Home
+ */
+ QSslConfiguration getOldSslConfiguration() {
+ // QFile to read the certificate and key
+ QFile certFile(certPath.c_str()), pkeyFile(keyPath.c_str());
+
+ // open the certificate and key
+ if(!certFile.open(QIODevice::ReadOnly) || !pkeyFile.open(QIODevice::ReadOnly)) {
+ throw std::runtime_error("Can't Create Certificate");
+ }
+
+ // read the certificate and key
+ QSslCertificate cert = QSslCertificate(certFile.readAll(), QSsl::Pem);
+ QSslKey key = QSslKey(pkeyFile.readAll(), QSsl::Rsa);
+ QSslConfiguration sslConfig;
+
+ // set the certificate and key
+ sslConfig.setLocalCertificate(cert);
+ sslConfig.setPrivateKey(key);
+
+ // if the configuration is null
+ if (cert.isNull() || key.isNull() || sslConfig.isNull()) {
+ throw std::runtime_error("Can't Create QSslConfiguration");
+ }
+
+ // set peer verify
+ sslConfig.setPeerVerifyMode(QSslSocket::VerifyPeer);
+
+ // return the configuration
+ return sslConfig;
+ }
+
+ /**
+ * @brief Get the certificate by creating new one
+ */
+ QSslConfiguration getNewSslConfiguration() {
+ // QFile to read the certificate and key
+ QFile certFile(certPath.c_str()), pkeyFile(keyPath.c_str());
+
+ // open the certificate and key
+ if(!certFile.open(QIODevice::WriteOnly) || !pkeyFile.open(QIODevice::WriteOnly)) {
+ throw std::runtime_error("Can't Create Certificate");
+ }
+
+ // generate the certificate and key
+ auto sslConfig = utility::functions::getQSslConfiguration();
+
+ // write the certificate and key
+ certFile.write(sslConfig.localCertificate().toPem());
+ pkeyFile.write(sslConfig.privateKey().toPem());
+
+ // return the configuration
+ return sslConfig;
+ }
+
+ /**
+ * @brief Get the certificate from App Home
+ * or generate new one and store it
+ */
+ QSslConfiguration getSslConfiguration() {
+ if (!std::filesystem::exists(certPath) || !std::filesystem::exists(keyPath)) {
+ return getNewSslConfiguration();
+ } else {
+ return getOldSslConfiguration();
+ }
+ }
+
/**
* @brief On Tray Icon Clicked
*/
@@ -69,7 +145,7 @@ class ClipbirdApplication : public SingleApplication {
Q_DISABLE_COPY_MOVE(ClipbirdApplication);
- public: // Constructors and Destructors
+ public: // Constructors and Destructors
/**
* @brief Construct a new Clipbird Application object
@@ -79,9 +155,14 @@ class ClipbirdApplication : public SingleApplication {
*/
ClipbirdApplication(int &argc, char **argv) : SingleApplication(argc, argv) {
// create the objects of the class
- controller = new controller::ClipBird(utility::functions::getQSslConfiguration());
- content = new ui::gui::Content(controller);
- window = new ui::gui::Window();
+ controller = new controller::ClipBird();
+
+ // set the ssl configuration
+ controller->setSslConfiguration(this->getSslConfiguration());
+
+ // create the objects of the class
+ content = new ui::gui::Content(controller);
+ window = new ui::gui::Window();
// set the signal handler for all os
signal(SIGTERM, [](int sig) { qApp->quit(); });
@@ -117,6 +198,11 @@ class ClipbirdApplication : public SingleApplication {
// using some classes
using ui::gui::Content;
+ // tray icon click from content
+ const auto signal_tic = &QSystemTrayIcon::activated;
+ const auto slot_tic = &ClipbirdApplication::onTrayIconClicked;
+ QObject::connect(content->getTrayIcon(), signal_tic, this, slot_tic);
+
// set the signal for instance Started
const auto signal_is = &SingleApplication::instanceStarted;
const auto slot_is = &Content::show;
@@ -126,11 +212,6 @@ class ClipbirdApplication : public SingleApplication {
const auto signal = &QStyleHints::colorSchemeChanged;
const auto slot = &ClipbirdApplication::setQssFile;
QObject::connect(QGuiApplication::styleHints(), signal, this, slot);
-
- // tray icon click from content
- const auto signal_tic = &QSystemTrayIcon::activated;
- const auto slot_tic = &ClipbirdApplication::onTrayIconClicked;
- QObject::connect(content->getTrayIcon(), signal_tic, this, slot_tic);
}
/**
@@ -156,7 +237,7 @@ class ClipbirdApplication : public SingleApplication {
* @return int Status code
*/
auto main(int argc, char **argv) -> int {
- // using ClipbirdApplication class
+ // using ClipbirdApplication class from namespace
using srilakshmikanthanp::clipbirdesk::ClipbirdApplication;
using srilakshmikanthanp::clipbirdesk::constants::getAppHome;
using srilakshmikanthanp::clipbirdesk::constants::getAppLogFile;
@@ -167,14 +248,25 @@ auto main(int argc, char **argv) -> int {
QDir().mkdir(getAppHome().c_str());
}
+#ifdef NDEBUG
// log file to record the logs
QFile logfile(QString::fromStdString(getAppLogFile()));
// open the log file
logfile.open(QIODevice::WriteOnly | QIODevice::Append);
+ // open QStream to write the log file
+ QTextStream logstream(&logfile);
+
// Set the log file
- Logger::setLogFile(&logfile);
+ Logger::setLogStream(&logstream);
+#else
+ // open QStream to write the log file
+ QTextStream logstream(stdout);
+
+ // Set the log file as std::cout
+ Logger::setLogStream(&logstream);
+#endif
// Set the custom message handler
qInstallMessageHandler(Logger::handler);
diff --git a/network/packets/authentication/authentication.cpp b/network/packets/authentication/authentication.cpp
index 6447101..e17ab38 100644
--- a/network/packets/authentication/authentication.cpp
+++ b/network/packets/authentication/authentication.cpp
@@ -52,12 +52,12 @@ quint8 Authentication::getPacketType() const noexcept {
* @param status
*/
void Authentication::setAuthStatus(quint8 status) {
- if (status == types::enums::AuthStatus::AuthFailed) {
+ if (status == types::enums::AuthStatus::AuthFail) {
this->authStatus = status;
return;
}
- if (status == types::enums::AuthStatus::AuthSuccess) {
+ if (status == types::enums::AuthStatus::AuthOkay) {
this->authStatus = status;
return;
}
@@ -125,8 +125,14 @@ QDataStream& operator>>(QDataStream& stream, Authentication& packet) {
// auth status
const auto authStatus = packet.authStatus;
+ // allowed status
+ const QList allowedStatus = {
+ AuthStatus::AuthOkay,
+ AuthStatus::AuthFail,
+ };
+
// Check the auth status
- if (authStatus != AuthStatus::AuthFailed && authStatus != AuthStatus::AuthSuccess) {
+ if (!allowedStatus.contains(authStatus)) {
throw MalformedPacket(ErrorCode::CodingError, "Invalid Auth Status");
}
diff --git a/network/packets/invalidrequest/invalidrequest.cpp b/network/packets/invalidrequest/invalidrequest.cpp
index bceff4d..5977c29 100644
--- a/network/packets/invalidrequest/invalidrequest.cpp
+++ b/network/packets/invalidrequest/invalidrequest.cpp
@@ -50,11 +50,17 @@ quint8 InvalidRequest::getPacketType() const noexcept {
* @param code
*/
void InvalidRequest::setErrorCode(quint8 code) {
- if (code != types::enums::ErrorCode::CodingError) {
- throw std::invalid_argument("Invalid Error Code");
+ if (code == types::enums::ErrorCode::InvalidPacket) {
+ this->errorCode = code;
+ return;
}
- this->errorCode = code;
+ if (code == types::enums::ErrorCode::CodingError) {
+ this->errorCode = code;
+ return;
+ }
+
+ throw std::invalid_argument("Invalid Error Code");
}
/**
@@ -172,8 +178,14 @@ QDataStream& operator>>(QDataStream& stream, InvalidRequest& packet) {
// using some types
using types::enums::ErrorCode;
+ // allowed
+ const auto allowed = std::vector{
+ ErrorCode::InvalidPacket,
+ ErrorCode::CodingError
+ };
+
// check the error code
- if (packet.errorCode != ErrorCode::CodingError && packet.errorCode != ErrorCode::SSLError) {
+ if (std::find(allowed.begin(), allowed.end(), packet.errorCode) == allowed.end()) {
throw MalformedPacket(types::enums::CodingError, "Invalid Error Code");
}
diff --git a/network/service/mdns/browser/browser.cpp b/network/service/mdns/browser/browser.cpp
index eef31bc..15ae2cf 100644
--- a/network/service/mdns/browser/browser.cpp
+++ b/network/service/mdns/browser/browser.cpp
@@ -14,19 +14,21 @@ namespace srilakshmikanthanp::clipbirdesk::network::service::mdns {
* @param isAdded
* @param const QHostInfo& info
*/
-void Browser::onHostResolved(bool isAdded, quint16 port, const QHostInfo& info) {
+void Browser::onHostResolved(bool isAdded, quint16 port, QString srvName, const QHostInfo& info) {
// check for error
if (info.error() != QHostInfo::NoError || info.addresses().isEmpty()) {
- // log the error with qt
qWarning() << LOG("Unable to resolve service");
return;
}
+ // remove the .local from srv name
+ srvName.replace(".local.", "");
+
// get the ip address
auto ip = info.addresses().first();
// emit the signal
- isAdded ? emit onServiceAdded({ip, port}) : emit onServiceRemoved({ip, port});
+ isAdded ? emit onServiceAdded({ip, port, srvName}) : emit onServiceRemoved({ip, port, srvName});
}
/**
@@ -144,6 +146,7 @@ void Browser::addedCallback(
browserObj, // this
true, // Removed
ntohs(port), // port
+ QString::fromUtf8(hosttarget), // srvName
std::placeholders::_1 // QHostInfo
);
@@ -190,6 +193,7 @@ void Browser::removeCallback(
browserObj, // this
false, // Removed
ntohs(port), // port
+ QString::fromUtf8(hosttarget), // srvName
std::placeholders::_1 // QHostInfo
);
diff --git a/network/service/mdns/browser/browser.hpp b/network/service/mdns/browser/browser.hpp
index 7eb35c6..c643f68 100644
--- a/network/service/mdns/browser/browser.hpp
+++ b/network/service/mdns/browser/browser.hpp
@@ -27,6 +27,7 @@
// Local headers
#include "constants/constants.hpp"
#include "types/enums/enums.hpp"
+#include "types/device/device.hpp"
#include "utility/functions/ipconv/ipconv.hpp"
namespace srilakshmikanthanp::clipbirdesk::network::service::mdns {
@@ -59,7 +60,7 @@ class Browser : public QObject {
* @param isAdded
* @param const QHostInfo& info
*/
- void onHostResolved(bool isAdded, quint16 port, const QHostInfo& info);
+ void onHostResolved(bool isAdded, quint16 port, QString srvName, const QHostInfo& info);
/**
* @brief Callback function for DNSServiceBrowse function
@@ -142,7 +143,7 @@ class Browser : public QObject {
* @param host Host address
* @param port Port number
*/
- virtual void onServiceAdded(QPair) = 0;
+ virtual void onServiceAdded(types::device::Device) = 0;
/**
* @brief On Server Removed abstract function that
@@ -151,7 +152,7 @@ class Browser : public QObject {
* @param host Host address
* @param port Port number
*/
- virtual void onServiceRemoved(QPair) = 0;
+ virtual void onServiceRemoved(types::device::Device) = 0;
};
} // namespace srilakshmikanthanp::clipbirdesk::network::service::dnsd
#endif
diff --git a/network/service/index.hpp b/network/service/service.hpp
similarity index 100%
rename from network/service/index.hpp
rename to network/service/service.hpp
diff --git a/network/syncing/client/client.cpp b/network/syncing/client/client.cpp
index 158551f..3ee4b03 100644
--- a/network/syncing/client/client.cpp
+++ b/network/syncing/client/client.cpp
@@ -6,19 +6,141 @@
#include "client.hpp"
namespace srilakshmikanthanp::clipbirdesk::network::syncing {
+/**
+ * @brief Verify Server
+ */
+bool Client::verifyCert(const QSslCertificate& certificate) {
+ // check the basic conditions
+ if (certificate.isNull() || certificate.subjectInfo(QSslCertificate::CommonName).isEmpty()) {
+ return false;
+ }
+
+ // get the client details
+ const auto name = certificate.subjectInfo(QSslCertificate::CommonName).constFirst();
+ const auto addr = this->m_ssl_socket->peerAddress();
+ const auto port = this->m_ssl_socket->peerPort();
+
+ // matcher lambda function
+ auto matcher = [&](const auto &elm) {
+ return elm.ip == addr && elm.port == port;
+ };
+
+ // if name of device not equal to subject name
+ auto device = std::find_if(m_servers.begin(), m_servers.end(), matcher);
+
+ // if device not found
+ if (device == nullptr) {
+ return false;
+ }
+
+ // name matches
+ if (device->name == name) {
+ return true;
+ }
+
+ // name not matches
+ return false;
+}
+
+/**
+ * @brief Process SSL Errors
+ */
+void Client::processSslErrors(const QList& errors) {
+ // List of ignored SslErrors
+ QList ignoredErrors;
+
+ // Ignore the errors
+ ignoredErrors.append(QSslError::SelfSignedCertificate);
+ ignoredErrors.append(QSslError::CertificateUntrusted);
+ ignoredErrors.append(QSslError::HostNameMismatch);
+
+ // make copy of errors
+ auto errorsCopy = errors;
+
+ // remove all the ignored errors
+ auto itr = std::remove_if(errorsCopy.begin(), errorsCopy.end(), [&](auto error) {
+ return ignoredErrors.contains(error.error());
+ });
+
+ // remove the ignored errors
+ errorsCopy.erase(itr, errorsCopy.end());
+
+ // log the errors
+ for (auto error : errorsCopy) {
+ qWarning() << (LOG(std::to_string(error.error()).c_str()));
+ }
+
+ // if errorsCopy is not empty
+ if (!errorsCopy.isEmpty()) {
+ return this->m_ssl_socket->abort();
+ }
+
+ // get certificate
+ const auto certificate = this->m_ssl_socket->peerCertificate();
+
+ // if any error occurred
+ if (errors.length() > 0 && !this->verifyCert(certificate)) {
+ return this->m_ssl_socket->abort();
+ }
+
+ // ignore the errors
+ this->m_ssl_socket->ignoreSslErrors();
+}
+
+/**
+ * @brief Process Ssl Error Secured
+ */
+void Client::processSslErrorsSecured(const QList& errors) {
+ // List of ignored SslErrors
+ QList ignoredErrors;
+
+ // Ignore the errors
+ ignoredErrors.append(QSslError::HostNameMismatch);
+
+ // make copy of errors
+ auto errorsCopy = errors;
+
+ // remove all the ignored errors
+ auto itr = std::remove_if(errorsCopy.begin(), errorsCopy.end(), [&](auto error) {
+ return ignoredErrors.contains(error.error());
+ });
+
+ // remove the ignored errors
+ errorsCopy.erase(itr, errorsCopy.end());
+
+ // log the errors
+ for (auto error : errorsCopy) {
+ qWarning() << (LOG(std::to_string(error.error()).c_str()));
+ }
+
+ if (!errorsCopy.isEmpty()) {
+ return this->m_ssl_socket->abort();
+ } else {
+ this->m_ssl_socket->ignoreSslErrors();
+ }
+}
+
/**
* @brief Process the Authentication Packet from the server
*
* @param packet Authentication
*/
void Client::processAuthentication(const packets::Authentication& packet) {
- if (packet.getAuthStatus() == types::enums::AuthStatus::AuthSuccess) {
- emit OnServerAuthentication((this->m_is_authed = true));
- } else {
- emit OnServerAuthentication((this->m_is_authed = false));
+ if (packet.getAuthStatus() == types::enums::AuthStatus::AuthOkay) {
+ emit OnServerStatusChanged(true);
}
}
+/**
+ * @brief Process the Invalid packet that has been received
+ * from the server and emit the signal
+ *
+ * @param packet Invalid packet
+ */
+void Client::processInvalidPacket(const packets::InvalidRequest& packet) {
+ qWarning() << (LOG(packet.getErrorMessage().toStdString()));
+}
+
/**
* @brief Process the packet that has been received
* from the server and emit the signal
@@ -38,16 +160,6 @@ void Client::processSyncingPacket(const packets::SyncingPacket& packet) {
emit OnSyncRequest(items);
}
-/**
- * @brief Process the Invalid packet that has been received
- * from the server and emit the signal
- *
- * @param packet Invalid packet
- */
-void Client::processInvalidPacket(const packets::InvalidRequest& packet) {
- qWarning() << (LOG(packet.getErrorMessage().toStdString()));
-}
-
/**
* @brief Process the packet that has been received
* from the server
@@ -89,8 +201,7 @@ void Client::processReadyRead() {
auto bytes = get.readRawData(start, toRead);
if (bytes == -1) {
- get.rollbackTransaction();
- return;
+ return get.rollbackTransaction();
}
toRead -= bytes;
@@ -156,31 +267,6 @@ void Client::processReadyRead() {
qWarning() << (LOG("Unknown Packet Found"));
}
-/**
- * @brief Process the SSL error and emit the signal
- *
- * @param errors List of SSL errors
- */
-void Client::processSslError(const QList& errors) {
- for (auto& error : errors) {
- qWarning() << (LOG(error.errorString().toStdString()));
- }
-}
-
-/**
- * @brief Handle client connected
- */
-void Client::handleConnected() {
- emit OnServerStatusChanged(true);
-}
-
-/**
- * @brief Handle client disconnected
- */
-void Client::handleDisconnected() {
- emit OnServerStatusChanged(false);
-}
-
/**
* @brief Construct a new Syncing Client object
* and connect the signals and slots and start
@@ -190,33 +276,31 @@ void Client::handleDisconnected() {
* @param parent Parent
*/
Client::Client(QObject* parent) : service::mdnsBrowser(parent) {
- // connect the signal to emit the signal for
- // server state changed
- const auto signal_c = &QSslSocket::connected;
- const auto slot_c = &Client::handleConnected;
- connect(m_ssl_socket, signal_c, this, slot_c);
-
// connect the signals and slots for the socket
// readyRead signal to process the packet
const auto signal_r = &QSslSocket::readyRead;
const auto slot_r = &Client::processReadyRead;
connect(m_ssl_socket, signal_r, this, slot_r);
- // connect the signals and slots for the socket
- // sslErrors signal to emit the signal for
- // OnErrorOccurred
- const auto signal_s = &QSslSocket::sslErrors;
- const auto slot_s = &Client::processSslError;
- connect(m_ssl_socket, signal_s, this, slot_s);
-
// disconnected signal to emit the signal for
// server state changed
const auto signal_d = &QSslSocket::disconnected;
- const auto slot_d = &Client::handleDisconnected;
+ const auto slot_d = [=] {emit OnServerStatusChanged(false); };
connect(m_ssl_socket, signal_d, this, slot_d);
+}
- // set the peer verify mode to none
- m_ssl_socket->setPeerVerifyMode(QSslSocket::VerifyNone);
+/**
+ * @brief Set SSL configuration
+ */
+void Client::setSslConfiguration(QSslConfiguration config) {
+ this->m_ssl_config = config;
+}
+
+/**
+ * @brief get the SSL configuration
+ */
+QSslConfiguration Client::getSslConfiguration() const {
+ return this->m_ssl_config;
}
/**
@@ -236,7 +320,9 @@ void Client::syncItems(QVector> items) {
using utility::functions::createPacket;
// create the packet
- SyncingPacket packet = createPacket({SyncingPacket::PacketType::SyncPacket, items});
+ SyncingPacket packet = createPacket({
+ SyncingPacket::PacketType::SyncPacket, items
+ });
// send the packet to the server
this->sendPacket(packet);
@@ -247,17 +333,8 @@ void Client::syncItems(QVector> items) {
*
* @return QList> List of servers
*/
-QList> Client::getServerList() const {
- // Host address and port number
- QList> list;
-
- // iterate and add the server
- for (auto& [host, port] : m_servers) {
- list.append({host, port});
- }
-
- // return the list
- return list;
+QList Client::getServerList() const {
+ return m_servers;
}
/**
@@ -267,82 +344,124 @@ QList> Client::getServerList() const {
* @param host Host address
* @param port Port number
*/
-void Client::connectToServer(QPair client) {
- // check if the SSL configuration is set
- if (m_ssl_socket->sslConfiguration().isNull()) {
- throw std::runtime_error("SSL Configuration is not set");
+void Client::connectToServer(types::device::Device server) {
+ // if Discover Configuration is null the return
+ if (this->m_ssl_config.isNull()) {
+ throw std::runtime_error("SSL Config Config is not set");
}
+ // set the ssl Configuration
+ m_ssl_socket->setSslConfiguration(m_ssl_config);
+
// check if the socket is connected
- if (m_ssl_socket->isOpen()) {
+ if (this->isConnected()) {
this->disconnectFromServer();
}
+ // disconnect the signals and slots for the socket
+ const auto signal_ss = &QSslSocket::sslErrors;
+ const auto slot_ss = &Client::processSslErrorsSecured;
+ disconnect(m_ssl_socket, signal_ss, this, slot_ss);
+
+ // connect the signals and slots for the socket
+ const auto signal_su = &QSslSocket::sslErrors;
+ const auto slot_su = &Client::processSslErrors;
+ connect(m_ssl_socket, signal_su, this, slot_su);
+
// create the host address
- const auto host = client.first.toString();
- const auto port = client.second;
+ const auto host = server.ip.toString();
+ const auto port = server.port;
+
+ // log host and port
+ qInfo() << (LOG("Connecting to server: " + host.toStdString() + ":" + std::to_string(port)));
// connect to the server as encrypted
m_ssl_socket->connectToHostEncrypted(host, port);
}
/**
- * @brief Get the Connection Host and Port object
- * @return QPair
+ * @brief Connect to server Secured
*/
-QPair Client::getConnectedServer() const {
- if (this->m_ssl_socket->state() != QAbstractSocket::ConnectedState) {
- throw std::runtime_error("Socket is not connected");
+void Client::connectToServerSecured(types::device::Device server) {
+ // if Discover Configuration is null the return
+ if (this->m_ssl_config.isNull()) {
+ throw std::runtime_error("SSL Config Config is not set");
}
- return {m_ssl_socket->peerAddress(), m_ssl_socket->peerPort()};
-}
+ // set the ssl Configuration
+ m_ssl_socket->setSslConfiguration(m_ssl_config);
-/**
- * @brief Get the Connection Host and Port object Or Empty
- * @return QPair
- */
-QPair Client::getConnectedServerOrEmpty() const {
- try {
- return this->getConnectedServer();
- } catch (const std::exception&) {
- return QPair();
+ // check if the socket is connected
+ if (this->isConnected()) {
+ this->disconnectFromServer();
}
+
+ // disconnect the signals and slots for the socket
+ const auto signal_su = &QSslSocket::sslErrors;
+ const auto slot_su = &Client::processSslErrors;
+ disconnect(m_ssl_socket, signal_su, this, slot_su);
+
+ // connect the signals and slots for the socket
+ const auto signal_ss = &QSslSocket::sslErrors;
+ const auto slot_ss = &Client::processSslErrorsSecured;
+ connect(m_ssl_socket, signal_ss, this, slot_ss);
+
+ // create the host address
+ const auto host = server.ip.toString();
+ const auto port = server.port;
+
+ // log host and port
+ qInfo() << (LOG("Connecting to server: " + host.toStdString() + ":" + std::to_string(port)));
+
+ // connect to the server as encrypted
+ m_ssl_socket->connectToHostEncrypted(host, port);
}
/**
- * @brief Disconnect from the server
+ * @brief IS connected to the server
*/
-void Client::disconnectFromServer() {
- m_ssl_socket->disconnectFromHost();
+bool Client::isConnected() const {
+ return m_ssl_socket->state() == QAbstractSocket::ConnectedState;
}
/**
- * @brief Get the Authed Server object
+ * @brief Get the Connection Host and Port object
* @return QPair
*/
-QPair Client::getAuthedServer() const {
+types::device::Device Client::getConnectedServer() const {
+ // check if the socket is connected else throw error
if (this->m_ssl_socket->state() != QAbstractSocket::ConnectedState) {
throw std::runtime_error("Socket is not connected");
}
- if (!this->m_is_authed) {
- throw std::runtime_error("Socket is not authenticated");
- }
+ // peer server details
+ auto addr = m_ssl_socket->peerAddress();
+ auto port = m_ssl_socket->peerPort();
+ auto cert = m_ssl_socket->peerCertificate();
+ auto name = cert.subjectInfo(QSslCertificate::CommonName).constFirst();
- return {m_ssl_socket->peerAddress(), m_ssl_socket->peerPort()};
+ // return the host address and port number
+ return { addr, port, name };
}
/**
- * @brief Get the Authed Server object Or Empty
- * @return QPair
+ * @brief Disconnect from the server
*/
-QPair Client::getAuthedServerOrEmpty() const {
- try {
- return this->getAuthedServer();
- } catch (const std::exception&) {
- return QPair();
+void Client::disconnectFromServer() {
+ m_ssl_socket->disconnectFromHost();
+}
+
+/**
+ * @brief Get the Server Certificate
+ */
+QSslCertificate Client::getConnectedServerCertificate() const{
+ // if not connected throw error
+ if (!this->isConnected()) {
+ throw std::runtime_error("Socket is not connected");
}
+
+ // return the server certificate
+ return m_ssl_socket->peerCertificate();
}
/**
@@ -352,12 +471,17 @@ QPair Client::getAuthedServerOrEmpty() const {
* @param host Host address
* @param port Port number
*/
-void Client::onServiceAdded(QPair server) {
- // emit the signal for server found event
+void Client::onServiceAdded(types::device::Device server) {
+ // if Discover Configuration is null the return
+ if (this->m_ssl_config.isNull()) {
+ throw std::runtime_error("SSL Config Config is not set");
+ }
+
+ // emit server found
emit OnServerFound(server);
- // add the server to the list
- m_servers.append({server.first, server.second});
+ // add to list
+ this->m_servers.append(server);
// emit the signal
emit OnServerListChanged(getServerList());
@@ -367,12 +491,29 @@ void Client::onServiceAdded(QPair server) {
* @brief On server removed function that That Called by the
* discovery client when the server is removed
*/
-void Client::onServiceRemoved(QPair server) {
- // emit the signal for server gone event
- emit OnServerGone(server);
+void Client::onServiceRemoved(types::device::Device server) {
+ // matcher to get the Device from servers list
+ auto matcher = [server](const types::device::Device& device) {
+ return device == server;
+ };
+
+ // start and end
+ auto start = m_servers.begin();
+ auto end = m_servers.end();
+
+ // Get the Device
+ auto device = std::find_if(start, end, matcher);
+
+ // if device is not found
+ if (device == m_servers.end()) {
+ return;
+ }
+
+ // emit server gone
+ emit OnServerGone(*device);
// remove the server from the list
- m_servers.removeAll({server.first, server.second});
+ m_servers.erase(device);
// emit the signal
emit OnServerListChanged(getServerList());
diff --git a/network/syncing/client/client.hpp b/network/syncing/client/client.hpp
index bfd3407..781f948 100644
--- a/network/syncing/client/client.hpp
+++ b/network/syncing/client/client.hpp
@@ -7,22 +7,26 @@
// Qt headers
#include
+#include
#include
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
// standard headers
#include
#include
// Local headers
-#include "network/service/index.hpp"
+#include "network/service/service.hpp"
#include "types/enums/enums.hpp"
+#include "types/device/device.hpp"
#include "utility/functions/ipconv/ipconv.hpp"
#include "utility/functions/nbytes/nbytes.hpp"
#include "utility/functions/packet/packet.hpp"
@@ -35,24 +39,20 @@ namespace srilakshmikanthanp::clipbirdesk::network::syncing {
class Client : public service::mdnsBrowser {
signals: // signals for this class
/// @brief On Server List Changed
- void OnServerListChanged(QList> servers);
+ void OnServerListChanged(QList servers);
signals: // signals for this class
/// @brief On Server Found
- void OnServerFound(QPair);
+ void OnServerFound(types::device::Device);
signals: // signals for this class
/// @brief On Server Gone
- void OnServerGone(QPair);
+ void OnServerGone(types::device::Device);
signals: // signals for this class
/// @brief On Server state changed
void OnServerStatusChanged(bool isConnected);
- signals: // signals for this class
- /// @brief On Server Auth Succeed
- void OnServerAuthentication(bool isSuccessful);
-
signals: // signals for this class
/// @brief On Sync Request
void OnSyncRequest(QVector> items);
@@ -69,14 +69,14 @@ class Client : public service::mdnsBrowser {
private: // Member variables
- /// @brief List of Found servers and timestamp
- QList> m_servers;
-
- /// @brief SSL socket
+ /// @brief SSL socket for the client
QSslSocket* m_ssl_socket = new QSslSocket(this);
- /// @brief is Server Authenticated Me
- bool m_is_authed = false;
+ /// @brief SSL configuration
+ QSslConfiguration m_ssl_config;
+
+ /// @brief List of Found servers
+ QList m_servers;
private: // private functions
@@ -101,25 +101,27 @@ class Client : public service::mdnsBrowser {
// write the packet length
while (wrote < data.size()) {
- // try to write the data
auto bytes = stream.writeRawData(data.data() + wrote, data.size() - wrote);
-
- // if no error occurred
- if (bytes != -1) {
- wrote += bytes; continue;
- }
-
- // abort the transaction
- stream.abortTransaction();
-
- // log
- qWarning() << LOG(m_ssl_socket->errorString().toStdString());
+ wrote = wrote + bytes;
+ if (bytes == -1) { stream.abortTransaction(); break; }
}
// commit the transaction
stream.commitTransaction();
}
+ void processSslErrorsSecured(const QList& errors);
+
+ /**
+ * @brief Verify Server
+ */
+ bool verifyCert(const QSslCertificate& certificate);
+
+ /**
+ * @brief Process SSL Errors
+ */
+ void processSslErrors(const QList& errors);
+
/**
* @brief Process the Authentication Packet from the server
*
@@ -128,20 +130,20 @@ class Client : public service::mdnsBrowser {
void processAuthentication(const packets::Authentication& packet);
/**
- * @brief Process the packet that has been received
+ * @brief Process the Invalid packet that has been received
* from the server and emit the signal
*
- * @param packet Syncing packet
+ * @param packet Invalid packet
*/
- void processSyncingPacket(const packets::SyncingPacket& packet);
+ void processInvalidPacket(const packets::InvalidRequest& packet);
/**
- * @brief Process the Invalid packet that has been received
+ * @brief Process the packet that has been received
* from the server and emit the signal
*
- * @param packet Invalid packet
+ * @param packet Syncing packet
*/
- void processInvalidPacket(const packets::InvalidRequest& packet);
+ void processSyncingPacket(const packets::SyncingPacket& packet);
/**
* @brief Process the packet that has been received
@@ -149,21 +151,6 @@ class Client : public service::mdnsBrowser {
*/
void processReadyRead();
- /**
- * @brief Process the ssl error
- */
- void processSslError(const QList& errors);
-
- /**
- * @brief Handle client connected
- */
- void handleConnected();
-
- /**
- * @brief Handle client disconnected
- */
- void handleDisconnected();
-
public:
/**
@@ -181,6 +168,16 @@ class Client : public service::mdnsBrowser {
*/
~Client() override = default;
+ /**
+ * @brief Set SSL configuration
+ */
+ void setSslConfiguration(QSslConfiguration config);
+
+ /**
+ * @brief get the SSL configuration
+ */
+ QSslConfiguration getSslConfiguration() const;
+
/**
* @brief Send the items to the server to sync the
* clipboard data
@@ -194,7 +191,7 @@ class Client : public service::mdnsBrowser {
*
* @return QList> List of servers
*/
- QList> getServerList() const;
+ QList getServerList() const;
/**
* @brief Connect to the server with the given host and port
@@ -203,53 +200,36 @@ class Client : public service::mdnsBrowser {
* @param host Host address
* @param port Port number
*/
- void connectToServer(QPair client);
-
- /**
- * @brief Get the Connection Host and Port object
- * @return QPair
- */
- QPair getConnectedServer() const;
+ void connectToServerSecured(types::device::Device server);
/**
- * @brief Get the Connection Host and Port object Or Empty
- * @return QPair
+ * @brief Connect to the server with the given host and port
+ * number
+ *
+ * @param host Host address
+ * @param port Port number
*/
- QPair getConnectedServerOrEmpty() const;
+ void connectToServer(types::device::Device client);
/**
- * @brief Disconnect from the server
+ * @brief IS connected to the server
*/
- void disconnectFromServer();
+ bool isConnected() const;
/**
- * @brief Get the Authed Server object
- * @return QPair
+ * @brief Get the Connection Host and Port object
*/
- QPair getAuthedServer() const;
+ types::device::Device getConnectedServer() const;
/**
- * @brief Get the Authed Server object Or Empty
- * @return QPair
+ * @brief Disconnect from the server
*/
- QPair getAuthedServerOrEmpty() const;
+ void disconnectFromServer();
/**
- * @brief Send To Connected Server
- *
- * @tparam Packet
- * @param pack
+ * @brief Get the Server Certificate
*/
- template
- void sendToConnectedServer(const Packet& pack) {
- // if not connected
- if (m_ssl_socket->state() != QAbstractSocket::ConnectedState) {
- throw std::runtime_error("Not connected to the server");
- }
-
- // send the packet
- sendPacket(pack);
- }
+ QSslCertificate getConnectedServerCertificate() const;
protected: // abstract functions from the base class
@@ -260,7 +240,7 @@ class Client : public service::mdnsBrowser {
* @param host Host address
* @param port Port number
*/
- void onServiceAdded(QPair server) override;
+ void onServiceAdded(types::device::Device server) override;
/**
* @brief On server removed function that That Called by the
@@ -268,6 +248,6 @@ class Client : public service::mdnsBrowser {
*
* @param server
*/
- void onServiceRemoved(QPair server) override;
+ void onServiceRemoved(types::device::Device server) override;
};
} // namespace srilakshmikanthanp::clipbirdesk::network::syncing
diff --git a/network/syncing/server/server.cpp b/network/syncing/server/server.cpp
index 1313a10..4ad5da8 100644
--- a/network/syncing/server/server.cpp
+++ b/network/syncing/server/server.cpp
@@ -6,6 +6,138 @@
#include "server.hpp"
namespace srilakshmikanthanp::clipbirdesk::network::syncing {
+/**
+ * @brief Process the connections that are pending
+ */
+void Server::processPendingConnections() {
+ while (m_server->hasPendingConnections()) {
+ // Get the client that has been connected
+ auto client = qobject_cast(m_server->nextPendingConnection());
+
+ // Connect the disconnected signal to the processDisconnection function
+ const auto signal_d = &QSslSocket::disconnected;
+ const auto slot_d = &Server::processDisconnection;
+ QObject::connect(client, signal_d, this, slot_d);
+
+ // Connect the readyRead signal to the processReadyRead function
+ const auto signal_r = &QSslSocket::readyRead;
+ const auto slot_r = &Server::processReadyRead;
+ QObject::connect(client, signal_r, this, slot_r);
+
+ // get the device info of the client
+ auto addr = client->peerAddress();
+ auto port = client->peerPort();
+ auto cert = client->peerCertificate();
+ auto name = cert.subjectInfo(QSslCertificate::CommonName).constFirst();
+
+ // create device object of the client
+ auto device = types::device::Device {
+ addr, port, name
+ };
+
+ // add to un authenticated list
+ m_unauthenticatedClients.append(client);
+
+ // Add the client to the list of authenticated clients
+ if (!client->sslHandshakeErrors().isEmpty()) {
+ emit OnAuthRequest(device);
+ } else {
+ this->authSuccess(device);
+ }
+ }
+}
+
+/**
+ * @brief Process SSL Errors
+ */
+void Server::processSslErrors(QSslSocket *socket, const QList& errors) {
+ // List of ignored SslErrors
+ QList ignoredErrors;
+
+ // Ignore the errors
+ ignoredErrors.append(QSslError::SelfSignedCertificate);
+ ignoredErrors.append(QSslError::CertificateUntrusted);
+
+ // make copy of errors
+ auto errorsCopy = errors;
+
+ // remove all the ignored errors
+ auto itr = std::remove_if(errorsCopy.begin(), errorsCopy.end(), [&](auto error) {
+ return ignoredErrors.contains(error.error());
+ });
+
+ // remove the ignored errors
+ errorsCopy.erase(itr, errorsCopy.end());
+
+ // log the errors
+ for (auto error : errorsCopy) {
+ qWarning() << (LOG(std::to_string(error.error())));
+ }
+
+ // if errorsCopy is not empty
+ if (!errorsCopy.isEmpty()) {
+ return socket->abort();
+ }
+
+ // peer info of the client that is connected
+ auto addr = socket->peerAddress();
+ auto port = socket->peerPort();
+ auto cert = socket->peerCertificate();
+ auto name = cert.subjectInfo(QSslCertificate::CommonName);
+
+ // if certificate is null or common name is empty
+ if (cert.isNull() || name.isEmpty()) {
+ return socket->abort();
+ }
+
+ // create the device
+ auto device = types::device::Device {
+ addr, port, name.constFirst()
+ };
+
+ // just ignore wait for user
+ socket->ignoreSslErrors();
+}
+
+/**
+ * @brief Process the disconnection from the client
+ */
+void Server::processDisconnection() {
+ // Get the client that was disconnected
+ auto client = qobject_cast(sender());
+
+ // if in unauthenticated list
+ if (m_unauthenticatedClients.removeOne(client)) {
+ return;
+ }
+
+ // if not in authenticated list
+ if (!m_clients.contains(client)) return;
+
+ // peer information of the client
+ auto addr = client->peerAddress();
+ auto port = client->peerPort();
+ auto cert = client->peerCertificate();
+ auto name = cert.subjectInfo(QSslCertificate::CommonName).constFirst();
+
+ // create the device
+ auto device = types::device::Device {
+ addr, port, name
+ };
+
+ // Remove the client from the list of clients
+ m_clients.removeOne(client);
+
+ // Notify the listeners that the client is disconnected
+ emit OnCLientStateChanged(device, false);
+
+ // get connected client list
+ auto list = getConnectedClientsList();
+
+ // Notify the listeners that the client list is changed
+ emit OnClientListChanged(list);
+}
+
/**
* @brief Process the SyncingPacket from the client
*
@@ -22,38 +154,12 @@ void Server::processSyncingPacket(const packets::SyncingPacket &packet) {
// Notify the listeners to sync the data
emit OnSyncRequest(items);
-}
-
-/**
- * @brief Process the connections that are pending
- */
-void Server::processConnections() {
- while (m_ssl_server->hasPendingConnections()) {
- // Get the client that has been connected
- auto client_tcp = (m_ssl_server->nextPendingConnection());
- auto client_tls = qobject_cast(client_tcp);
-
- // If the client is not SSL client then disconnect
- if (client_tls == nullptr) {
- const auto packType = packets::InvalidRequest::PacketType::RequestFailed;
- const auto code = types::enums::ErrorCode::SSLError;
- const auto message = "Client is not SSL client";
-
- using utility::functions::createPacket;
- this->sendPacket(client_tls, createPacket({packType, code, message}));
- client_tcp->disconnectFromHost();
- } else {
- // add the client to unauthenticated list
- m_un_authed_clients.append(client_tls);
- // get the peer address ans port
- const auto peerAddress = client_tls->peerAddress();
- const auto peerPort = client_tls->peerPort();
+ // get the Sender of the packet
+ auto client = qobject_cast(sender());
- // emit the signal that new host is connected
- emit OnNewHostConnected({peerAddress, peerPort});
- }
- }
+ // send the response packet
+ this->sendPacket(packet, client);
}
/**
@@ -64,6 +170,9 @@ void Server::processReadyRead() {
// Get the client that was ready to read
auto client = qobject_cast(sender());
+ // if not authenticated then return
+ if (!m_clients.contains(client)) return;
+
// using the fromQByteArray from namespace
using utility::functions::createPacket;
using utility::functions::fromQByteArray;
@@ -115,10 +224,12 @@ void Server::processReadyRead() {
return;
}
+ // if not in authenticated client
+ if (!this->m_clients.contains(client)) return;
+
// Deserialize the data to SyncingPacket
try {
this->processSyncingPacket(fromQByteArray(data));
- this->sendPacket(fromQByteArray(data), client);
return;
} catch (const types::except::MalformedPacket &e) {
const auto type = packets::InvalidRequest::PacketType::RequestFailed;
@@ -141,33 +252,6 @@ void Server::processReadyRead() {
this->sendPacket(client, createPacket({type, code, msg}));
}
-/**
- * @brief Process the disconnection from the client
- */
-void Server::processDisconnection() {
- // Get the client that was disconnected
- auto client = qobject_cast(sender());
-
- // convert to QPair
- auto info = QPair(client->peerAddress(), client->peerPort());
-
- // Notify the listeners that the client is disconnected
- emit OnCLientStateChanged(info, false);
-
- // Remove the client from the list of clients
- m_authed_clients.removeOne(client);
-
- // Notify the listeners that the client list is changed
- emit OnClientListChanged(getConnectedClientsList());
-}
-
-/**
- * @brief Called when the service is registered
- */
-void Server::OnServiceRegistered() {
- emit OnServerStateChanged(true);
-}
-
/**
* @brief Construct a new Syncing Server object and
* bind to any available port and any available
@@ -181,13 +265,19 @@ Server::Server(QObject *parent) : service::mdnsRegister(parent) {
// process the connections when the socket is ready
// to read so the listener can be notified
const auto signal_c = &QSslServer::pendingConnectionAvailable;
- const auto slot_c = &Server::processConnections;
- QObject::connect(m_ssl_server, signal_c, this, slot_c);
+ const auto slot_c = &Server::processPendingConnections;
+ QObject::connect(m_server, signal_c, this, slot_c);
// Notify the listeners that the server is started
const auto signal = &service::mdnsRegister::OnServiceRegistered;
- const auto slot = &Server::OnServiceRegistered;
+ const auto slot = [=] { emit OnServerStateChanged(true); };
QObject::connect(this, signal, this, slot);
+
+ // Connect the socket to the callback function that
+ // process the SSL errors
+ const auto signal_e = &QSslServer::sslErrors;
+ const auto slot_e = &Server::processSslErrors;
+ QObject::connect(m_server, signal_e, this, slot_e);
}
/**
@@ -205,11 +295,23 @@ void Server::syncItems(QVector> items) {
*
* @return QList List of clients
*/
-QList> Server::getConnectedClientsList() const {
- QList> list;
- for (auto client : m_authed_clients) {
- list.append({client->peerAddress(), client->peerPort()});
+QList Server::getConnectedClientsList() const {
+ // List of clients that are connected
+ QList list;
+
+ // iterate through the list of clients
+ for (auto c : m_clients) {
+ // Peer info of the client that is connected
+ auto addr = c->peerAddress();
+ auto port = c->peerPort();
+ auto cert = c->peerCertificate();
+ auto name = cert.subjectInfo(QSslCertificate::CommonName).constFirst();
+
+ // add the device to the list
+ list.append({addr, port, name});
}
+
+ // return the list
return list;
}
@@ -219,14 +321,14 @@ QList> Server::getConnectedClientsList() const {
*
* @param client Client to disconnect
*/
-void Server::disconnectClient(QPair client) {
+void Server::disconnectClient(types::device::Device client) {
// matcher lambda function to find the client
const auto matcher = [&client](QSslSocket *c) {
- return (c->peerAddress() == client.first) && (c->peerPort() == client.second);
+ return (c->peerAddress() == client.ip) && (c->peerPort() == client.port);
};
// find the client from the list of clients
- for (auto c : m_authed_clients) {
+ for (auto c : m_clients) {
if (matcher(c)) {
return c->disconnectFromHost();
}
@@ -237,16 +339,23 @@ void Server::disconnectClient(QPair client) {
* @brief Disconnect the all the clients from the server
*/
void Server::disconnectAllClients() {
- for (auto client : m_authed_clients) client->disconnectFromHost();
+ for (auto client : m_clients) client->disconnectFromHost();
}
/**
* @brief Get the Server QHostAddress & Port
*
- * @return QPair
+ * @return types::device::Device
*/
-QPair Server::getServerInfo() const {
- return {m_ssl_server->serverAddress(), m_ssl_server->serverPort()};
+types::device::Device Server::getServerInfo() const {
+ // server information
+ auto addr = m_server->serverAddress();
+ auto port = m_server->serverPort();
+ auto cert = m_server->sslConfiguration().localCertificate();
+ auto name = cert.subjectInfo(QSslCertificate::CommonName).constFirst();
+
+ // Return info
+ return { addr, port, name };
}
/**
@@ -254,8 +363,8 @@ QPair Server::getServerInfo() const {
*
* @param config SSL Configuration
*/
-void Server::setSSLConfiguration(QSslConfiguration config) {
- m_ssl_server->setSslConfiguration(config);
+void Server::setSslConfiguration(QSslConfiguration config) {
+ m_server->setSslConfiguration(config);
}
/**
@@ -264,7 +373,65 @@ void Server::setSSLConfiguration(QSslConfiguration config) {
* @return QSslConfiguration
*/
QSslConfiguration Server::getSSLConfiguration() const {
- return m_ssl_server->sslConfiguration();
+ return m_server->sslConfiguration();
+}
+
+/**
+ * @brief Start the server
+ */
+void Server::startServer() {
+ // check if the SSL configuration is set
+ if (m_server->sslConfiguration().isNull()) {
+ throw std::runtime_error("SSL Configuration is not set");
+ }
+
+ // start the server
+ if (!m_server->listen()) {
+ throw std::runtime_error("Failed to start the server");
+ }
+
+ // log port
+ qInfo() << (LOG("Server started at port: " + std::to_string(m_server->serverPort())));
+
+ // start the discovery server
+ this->registerServiceAsync();
+}
+
+/**
+ * @brief Stop the server
+ */
+void Server::stopServer() {
+ // stop the discovery server
+ this->unregisterService();
+
+ // disconnect all the clients
+ this->disconnectAllClients();
+
+ // stop the server
+ m_server->close();
+
+ // Notify the listeners
+ emit OnServerStateChanged(false);
+}
+
+/**
+ * @brief Get the Dei=vice Certificate
+ */
+QSslCertificate Server::getClientCert(types::device::Device device) const {
+ // matcher lambda function to find the client
+ const auto matcher = [&device](QSslSocket *c) {
+ return (c->peerAddress() == device.ip) && (c->peerPort() == device.port);
+ };
+
+ // find the client from the list of clients
+ for (auto c : m_clients) {
+ if (matcher(c)) {
+ return c->peerCertificate();
+ }
+ }
+
+ // if not found
+ throw std::runtime_error("Client not found");
}
/**
@@ -272,54 +439,33 @@ QSslConfiguration Server::getSSLConfiguration() const {
*
* @param client the client that is currently processed
*/
-void Server::authSuccess(const QPair &client) {
+void Server::authSuccess(types::device::Device device) {
// Matcher Lambda Function to find the client
- const auto matcher = [&client](QSslSocket *c) {
- return (c->peerAddress() == client.first) && (c->peerPort() == client.second);
+ const auto matcher = [&device](QSslSocket *c) {
+ return (c->peerAddress() == device.ip) && (c->peerPort() == device.port);
};
// Get the iterator to the start and end of the list
- auto start = m_un_authed_clients.begin();
- auto end = m_un_authed_clients.end();
+ auto start = m_unauthenticatedClients.begin();
+ auto end = m_unauthenticatedClients.end();
// Get the client from the unauthenticated list and remove it
auto client_itr = std::find_if(start, end, matcher);
// If the client is not found then return from the function
- if (client_itr == m_un_authed_clients.end()) return;
+ if (client_itr == m_unauthenticatedClients.end()) return;
// Get the client from the iterator
auto client_tls = *client_itr;
// Remove the client from the unauthenticated list
- m_un_authed_clients.erase(client_itr);
-
- // Connect the client to the callback function that process
- // the disconnection when the client is disconnected
- // so the listener can be notified
- const auto signal_d = &QSslSocket::disconnected;
- const auto slot_d = &Server::processDisconnection;
- QObject::connect(client_tls, signal_d, this, slot_d);
-
- // Connect the socket to the callback function that
- // process the ready read when the socket is ready
- // to read so the listener can be notified
- const auto signal_r = &QSslSocket::readyRead;
- const auto slot_r = &Server::processReadyRead;
- QObject::connect(client_tls, signal_r, this, slot_r);
-
- // Peer info
- const auto peerAddress = client_tls->peerAddress();
- const auto peerPort = client_tls->peerPort();
+ m_unauthenticatedClients.erase(client_itr);
- // convert to QPair
- auto client_info = QPair(peerAddress, peerPort);
+ // Add the client to the list of clients
+ m_clients.append(client_tls);
// Notify the listeners that the client is connected
- emit OnCLientStateChanged(client_info, true);
-
- // Add the client to the list of clients
- m_authed_clients.append(client_tls);
+ emit OnCLientStateChanged(device, true);
// Notify the listeners that the client list is changed
emit OnClientListChanged(getConnectedClientsList());
@@ -330,7 +476,7 @@ void Server::authSuccess(const QPair &client) {
// create the Authentication packet
packets::Authentication packet = createPacket({
packets::Authentication::PacketType::AuthStatus,
- types::enums::AuthStatus::AuthSuccess,
+ types::enums::AuthStatus::AuthOkay,
});
// send the packet to the client
@@ -342,24 +488,24 @@ void Server::authSuccess(const QPair &client) {
*
* @param client the client that is currently processed
*/
-void Server::authFailed(const QPair &client) {
+void Server::authFailed(types::device::Device device) {
// Matcher Lambda Function to find the client
- const auto matcher = [&client](QSslSocket *c) {
- return (c->peerAddress() == client.first) && (c->peerPort() == client.second);
+ const auto matcher = [&device](QSslSocket *c) {
+ return (c->peerAddress() == device.ip) && (c->peerPort() == device.port);
};
// Get the iterator to the start and end of the list
- auto start = m_un_authed_clients.begin();
- auto end = m_un_authed_clients.end();
+ auto start = m_unauthenticatedClients.begin();
+ auto end = m_unauthenticatedClients.end();
// Get the client from the unauthenticated list and remove it
auto client_itr = std::find_if(start, end, matcher);
// If the client is not found then return from the function
- if (client_itr == m_un_authed_clients.end()) return;
+ if (client_itr == m_unauthenticatedClients.end()) return;
// Remove the client from the unauthenticated list
- m_un_authed_clients.erase(client_itr);
+ m_unauthenticatedClients.erase(client_itr);
// using the create packet from namespace
using utility::functions::createPacket;
@@ -367,7 +513,7 @@ void Server::authFailed(const QPair &client) {
// create the Authentication packet
packets::Authentication packet = createPacket({
packets::Authentication::PacketType::AuthStatus,
- types::enums::AuthStatus::AuthFailed,
+ types::enums::AuthStatus::AuthFail,
});
// send the packet to the client
@@ -375,44 +521,6 @@ void Server::authFailed(const QPair &client) {
// disconnect and delete the client
(*client_itr)->disconnectFromHost();
-
- // delete the client after the client is disconnected
- (*client_itr)->deleteLater();
-}
-
-/**
- * @brief Start the server
- */
-void Server::startServer() {
- // check if the SSL configuration is set
- if (m_ssl_server->sslConfiguration().isNull()) {
- throw std::runtime_error("SSL Configuration is not set");
- }
-
- // start the server
- if (!m_ssl_server->listen()) {
- throw std::runtime_error("Failed to start the server");
- }
-
- // start the discovery server
- this->registerServiceAsync();
-}
-
-/**
- * @brief Stop the server
- */
-void Server::stopServer() {
- // stop the discovery server
- this->unregisterService();
-
- // disconnect all the clients
- this->disconnectAllClients();
-
- // stop the server
- m_ssl_server->close();
-
- // Notify the listeners
- emit OnServerStateChanged(false);
}
/**
@@ -425,6 +533,6 @@ void Server::stopServer() {
* @throw Any Exception If any error occurs
*/
quint16 Server::getPort() const {
- return m_ssl_server->serverPort();
+ return m_server->serverPort();
}
} // namespace srilakshmikanthanp::clipbirdesk::network::syncing
diff --git a/network/syncing/server/server.hpp b/network/syncing/server/server.hpp
index 9042009..b72af86 100644
--- a/network/syncing/server/server.hpp
+++ b/network/syncing/server/server.hpp
@@ -13,8 +13,8 @@
#include
#include
-#include "network/packets/authentication/authentication.hpp"
-#include "network/service/index.hpp"
+#include "network/service/service.hpp"
+#include "types/device/device.hpp"
#include "types/enums/enums.hpp"
#include "utility/functions/ipconv/ipconv.hpp"
#include "utility/functions/nbytes/nbytes.hpp"
@@ -28,24 +28,23 @@ namespace srilakshmikanthanp::clipbirdesk::network::syncing {
class Server : public service::mdnsRegister {
signals: // signals
/// @brief On client state changed
- void OnCLientStateChanged(QPair, bool connected);
-
- signals: // signals for this class
- /// @brief On New Host Connected
- void OnNewHostConnected(QPair);
+ void OnCLientStateChanged(types::device::Device, bool connected);
signals: // signals for this class
/// @brief On Server State Changed
void OnServerStateChanged(bool started);
+ signals: // signals for this class
+ /// @brief On Sync Request
+ void OnAuthRequest(types::device::Device client);
+
signals: // signals
/// @brief On Sync Request
void OnSyncRequest(QVector> items);
signals: // signals for this class
/// @brief On Sync Request
- void OnClientListChanged(QList> clients);
-
+ void OnClientListChanged(QList clients);
private: // just for Qt
@@ -58,14 +57,14 @@ class Server : public service::mdnsRegister {
private: // members of the class
- /// @brief SSL server
- QSslServer* m_ssl_server = new QSslServer(this);
-
- /// @brief List of clients unauthenticated
- QList m_un_authed_clients;
+ /// @brief List of clients Unauthenticated
+ QList m_unauthenticatedClients;
/// @brief List of clients Authenticated
- QList m_authed_clients;
+ QList m_clients;
+
+ /// @brief SSL server
+ QSslServer* m_server = new QSslServer(this);
private: // some typedefs
@@ -91,23 +90,13 @@ class Server : public service::mdnsRegister {
stream.startTransaction();
// write the data to the stream
- auto wrote = 0;
+ auto wrote = 0L;
// write the packet length
while (wrote < data.size()) {
- // try to write the data
auto bytes = stream.writeRawData(data.data() + wrote, data.size() - wrote);
-
- // if no error occurred
- if (bytes != -1) {
- wrote += bytes; continue;
- }
-
- // abort the transaction
- stream.abortTransaction();
-
- // Notifies the error occurred
- qWarning() << (LOG(client->errorString().toStdString()));
+ wrote = wrote + bytes;
+ if (bytes == -1) { stream.abortTransaction(); break; }
}
// commit the transaction
@@ -122,28 +111,20 @@ class Server : public service::mdnsRegister {
*/
template
void sendPacket(const Packet& pack, QSslSocket* except = nullptr) {
- for (auto client : m_authed_clients) {
+ for (auto client : m_clients) {
if (client != except) sendPacket(client, pack);
}
}
- /**
- * @brief Process the SyncingPacket from the client
- *
- * @param packet SyncingPacket
- */
- void processSyncingPacket(const packets::SyncingPacket& packet);
-
/**
* @brief Process the connections that are pending
*/
- void processConnections();
+ void processPendingConnections();
/**
- * @brief Callback function that process the ready
- * read from the client
+ * @brief Process SSL Errors
*/
- void processReadyRead();
+ void processSslErrors(QSslSocket *, const QList& errors);
/**
* @brief Process the disconnection from the client
@@ -151,9 +132,17 @@ class Server : public service::mdnsRegister {
void processDisconnection();
/**
- * @brief On Service Registered
+ * @brief Process the SyncingPacket from the client
+ *
+ * @param packet SyncingPacket
*/
- void OnServiceRegistered();
+ void processSyncingPacket(const packets::SyncingPacket& packet);
+
+ /**
+ * @brief Callback function that process the ready
+ * read from the client
+ */
+ void processReadyRead();
public: // constructors and destructors
@@ -181,10 +170,8 @@ class Server : public service::mdnsRegister {
/**
* @brief Get the Clients that are connected to the server
- *
- * @return QList List of clients
*/
- QList> getConnectedClientsList() const;
+ QList getConnectedClientsList() const;
/**
* @brief Disconnect the client from the server and delete
@@ -192,7 +179,7 @@ class Server : public service::mdnsRegister {
*
* @param client Client to disconnect
*/
- void disconnectClient(QPair client);
+ void disconnectClient(types::device::Device client);
/**
* @brief Disconnect the all the clients from the server
@@ -202,16 +189,17 @@ class Server : public service::mdnsRegister {
/**
* @brief Get the Server QHostAddress & Port
*
- * @return QPair
+ * @return types::device::Device
*/
- QPair getServerInfo() const;
+ types::device::Device getServerInfo() const;
/**
* @brief Set the SSL Configuration object
*
* @param config SSL Configuration
*/
- void setSSLConfiguration(QSslConfiguration config);
+ void setSslConfiguration(QSslConfiguration config);
+
/**
* @brief Get the SSL Configuration object
*
@@ -220,58 +208,34 @@ class Server : public service::mdnsRegister {
QSslConfiguration getSSLConfiguration() const;
/**
- * @brief The function that is called when the client is authenticated
- *
- * @param client the client that is currently processed
+ * @brief Start the server
*/
- void authSuccess(const QPair&);
+ void startServer();
/**
- * @brief The function that is called when the client it not
- * authenticated
- *
- * @param client the client that is currently processed
+ * @brief Stop the server
*/
- void authFailed(const QPair&);
+ void stopServer();
/**
- * @brief Start the server
+ * @brief Get the Dei=vice Certificate
*/
- void startServer();
+ QSslCertificate getClientCert(types::device::Device device) const;
/**
- * @brief Stop the server
+ * @brief The function that is called when the client is authenticated
+ *
+ * @param client the client that is currently processed
*/
- void stopServer();
+ void authSuccess(types::device::Device device);
/**
- * @brief Send the packet to the client
+ * @brief The function that is called when the client it not
+ * authenticated
*
- * @param packet Packet to send
- * @param QPair {QHostAddress, port}
+ * @param client the client that is currently processed
*/
- template
- void sendToClient(const Packet &packet, const QPair &client) {
- // Matcher Lambda Function to find the client
- const auto matcher = [&client](QSslSocket *c) {
- return (c->peerAddress() == client.first) && (c->peerPort() == client.second);
- };
-
- // Get the iterator to the start and end of the list
- auto start = m_authed_clients.begin();
- auto end = m_authed_clients.end();
-
- // Get the client from the unauthenticated list and remove it
- auto client_itr = std::find_if(start, end, matcher);
-
- // If the client is not found then return from the function
- if (client_itr == m_authed_clients.end()) {
- throw std::runtime_error("Client not found");
- }
-
- // send the packet to the client
- this->sendPacket(packet, (*client_itr));
- }
+ void authFailed(types::device::Device device);
protected: // override functions from the base class
diff --git a/store/storage.cpp b/store/storage.cpp
index fe37953..a33a0b2 100644
--- a/store/storage.cpp
+++ b/store/storage.cpp
@@ -16,89 +16,139 @@ Storage::Storage(QObject *parent) : QObject(parent) {
}
/**
- * @brief Store Client hostname and JWT token
+ * @brief Store Client name and JWT token
*
- * @param hostname
+ * @param name
* @param token
*/
-void Storage::setClientCert(const QString &hostname, const QString &token) {
+void Storage::setClientCert(const QString &name, const QByteArray &token) {
settings->beginGroup(clientGroup);
- settings->setValue(hostname, token);
+ settings->setValue(name, token);
settings->endGroup();
}
/**
- * @brief has the cert for the hostname
+ * @brief has the cert for the name
*/
-bool Storage::hasClientCert(const QString &hostname) {
+bool Storage::hasClientCert(const QString &name) {
settings->beginGroup(clientGroup);
- auto token = settings->value(hostname);
+ auto token = settings->value(name);
settings->endGroup();
return !token.isNull();
}
/**
- * @brief Get the JWT token for the hostname
+ * @brief Get the JWT token for the name
*
- * @param hostname
+ * @param name
* @return QString
*
- * @throw std::invalid_argument if hostname not found
+ * @throw std::invalid_argument if name not found
*/
-QString Storage::getClientCert(const QString &hostname) {
+QByteArray Storage::getClientCert(const QString &name) {
settings->beginGroup(clientGroup);
- auto token = settings->value(hostname);
+ auto token = settings->value(name);
settings->endGroup();
if (token.isNull()) {
- throw std::invalid_argument("hostname not found");
+ throw std::invalid_argument("name not found");
}
- return token.toString();
+ return token.toByteArray();
}
/**
- * @brief Store the server hostname and JWT token
+ * @brief Get All Client Certificates
+ */
+QList Storage::getAllClientCert() {
+ QList list;
+
+ settings->beginGroup(clientGroup);
+ for (auto &name : settings->childKeys()) {
+ auto cert = settings->value(name);
+ list.append(cert.toByteArray());
+ }
+ settings->endGroup();
+
+ return list;
+}
+
+/**
+ * @brief Store the server name and JWT token
*
- * @param hostname
+ * @param name
* @param token
*/
-void Storage::setServerCert(const QString &hostname, const QString &token) {
+void Storage::setServerCert(const QString &name, const QByteArray &token) {
settings->beginGroup(serverGroup);
- settings->setValue(hostname, token);
+ settings->setValue(name, token);
settings->endGroup();
}
/**
- * @brief has the cert for the hostname
+ * @brief has the cert for the name
*/
-bool Storage::hasServerCert(const QString &hostname) {
+bool Storage::hasServerCert(const QString &name) {
settings->beginGroup(serverGroup);
- auto token = settings->value(hostname);
+ auto token = settings->value(name);
settings->endGroup();
return !token.isNull();
}
/**
- * @brief Get the JWT token for the hostname
+ * @brief Clear the client cert
+ */
+void Storage::clearClientCert(const QString &name) {
+ settings->beginGroup(clientGroup);
+ settings->remove(name);
+ settings->endGroup();
+}
+
+/**
+ * @brief Clear the client cert
+ */
+void Storage::clearAllClientCert() {
+ settings->beginGroup(clientGroup);
+ settings->remove("");
+ settings->endGroup();
+}
+
+/**
+ * @brief Get the JWT token for the name
*
- * @param hostname
+ * @param name
* @return QString
*
- * @throw std::invalid_argument if hostname not found
+ * @throw std::invalid_argument if name not found
*/
-QString Storage::getServerCert(const QString &hostname) {
+QByteArray Storage::getServerCert(const QString &name) {
settings->beginGroup(serverGroup);
- auto token = settings->value(hostname);
+ auto token = settings->value(name);
settings->endGroup();
if (token.isNull()) {
- throw std::invalid_argument("hostname not found");
+ throw std::invalid_argument("name not found");
}
- return token.toString();
+ return token.toByteArray();
+}
+
+/**
+ * @brief Get All Server Certificates
+ */
+QList Storage::getAllServerCert() {
+ QList list;
+
+ settings->beginGroup(serverGroup);
+ for (auto &name : settings->childKeys()) {
+ auto cert = settings->value(name);
+ list.append(cert.toByteArray());
+ }
+ settings->endGroup();
+
+ return list;
}
/**
@@ -112,6 +162,24 @@ void Storage::setHostIsServer(bool isServer) {
settings->endGroup();
}
+/**
+ * @brief Clear the server cert
+ */
+void Storage::clearServerCert(const QString &name) {
+ settings->beginGroup(serverGroup);
+ settings->remove(name);
+ settings->endGroup();
+}
+
+/**
+ * @brief Clear the server cert
+ */
+void Storage::clearAllServerCert() {
+ settings->beginGroup(serverGroup);
+ settings->remove("");
+ settings->endGroup();
+}
+
/**
* @brief Get the current state of the server or client
*
@@ -126,7 +194,15 @@ bool Storage::getHostIsServer() {
if (isServer.isNull()) {
return false;
}
-
+ const auto s = isServer.toBool();
return isServer.toBool();
}
+
+/**
+ * @brief Instance of the storage
+ */
+Storage& Storage::instance() {
+ static Storage instance;
+ return instance;
+}
} // namespace srilakshmikanthanp::clipbirdesk::storage
diff --git a/store/storage.hpp b/store/storage.hpp
index 3fc892e..9d0bf3c 100644
--- a/store/storage.hpp
+++ b/store/storage.hpp
@@ -1,3 +1,5 @@
+#pragma once // Header guard see https://en.wikipedia.org/wiki/Include_guard
+
// Copyright (c) 2023 Sri Lakshmi Kanthan P
//
// This software is released under the MIT License.
@@ -24,47 +26,83 @@ class Storage : public QObject {
Q_OBJECT
- public: // constructor
+ private: // constructor
/**
* @brief Construct a new SQLStore object
*/
Storage(QObject *parent = nullptr);
+ private: // constructor
+
+ Q_DISABLE_COPY_MOVE(Storage)
+
+ public: // methods
+
/**
* @brief Destroy the SQLStore object
*/
virtual ~Storage() = default;
/**
- * @brief Store Client hostname and JWT cert
+ * @brief Store Client name and JWT cert
+ */
+ void setClientCert(const QString &name, const QByteArray &cert);
+
+ /**
+ * @brief has the cert for the name
+ */
+ bool hasClientCert(const QString &name);
+
+ /**
+ * @brief Clear the client cert
+ */
+ void clearClientCert(const QString &name);
+
+ /**
+ * @brief Clear the client cert
*/
- void setClientCert(const QString &hostname, const QString &cert);
+ void clearAllClientCert();
/**
- * @brief has the cert for the hostname
+ * @brief Get the JWT cert for the name
*/
- bool hasClientCert(const QString &hostname);
+ QByteArray getClientCert(const QString &name);
/**
- * @brief Get the JWT cert for the hostname
+ * @brief Get All Client Certificates
*/
- QString getClientCert(const QString &hostname);
+ QList getAllClientCert();
/**
- * @brief Store the server hostname and JWT cert
+ * @brief Store the server name and JWT cert
*/
- void setServerCert(const QString &hostname, const QString &cert);
+ void setServerCert(const QString &name, const QByteArray &cert);
/**
- * @brief has the cert for the hostname
+ * @brief has the cert for the name
*/
- bool hasServerCert(const QString &hostname);
+ bool hasServerCert(const QString &name);
/**
- * @brief Get the JWT cert for the hostname
+ * @brief Clear the server cert
*/
- QString getServerCert(const QString &hostname);
+ void clearServerCert(const QString &name);
+
+ /**
+ * @brief Clear the server cert
+ */
+ void clearAllServerCert();
+
+ /**
+ * @brief Get the JWT cert for the name
+ */
+ QByteArray getServerCert(const QString &name);
+
+ /**
+ * @brief Get All Server Certificates
+ */
+ QList getAllServerCert();
/**
* @brief Set the current state of the server or client
@@ -75,6 +113,11 @@ class Storage : public QObject {
* @brief Get the current state of the server or client
*/
bool getHostIsServer();
+
+ /**
+ * @brief Instance of the storage
+ */
+ static Storage& instance();
};
} // namespace srilakshmikanthanp::clipbirdesk::storage
diff --git a/tests/network/packets/authentication.hpp b/tests/network/packets/authentication.hpp
deleted file mode 100644
index f989fbf..0000000
--- a/tests/network/packets/authentication.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#pragma once // Header guard see https://en.wikipedia.org/wiki/Include_guard
-
-// Copyright (c) 2023 Sri Lakshmi Kanthan P
-//
-// This software is released under the MIT License.
-// https://opensource.org/licenses/MIT
-
-// Google test header files
-#include
-
-// Qt header files
-#include
-
-// Local header files
-#include "network/packets/authentication/authentication.hpp"
-#include "types/enums/enums.hpp"
-#include "utility/functions/nbytes/nbytes.hpp"
-#include "utility/functions/packet/packet.hpp"
-
-/**
- * @brief testing the AuthenticationPacket
- */
-TEST(AuthenticationTest, TestingAuthentication) {
- // using the AuthenticationPacket
- using srilakshmikanthanp::clipbirdesk::network::packets::Authentication;
-
- // using the ErrorCode
- using srilakshmikanthanp::clipbirdesk::types::enums::AuthStatus;
-
- // using functions namespace
- using namespace srilakshmikanthanp::clipbirdesk::utility::functions;
-
- // creating the packet
- Authentication packet_send, packet_recv;
-
- // constant values
- const auto packetType = Authentication::PacketType::AuthStatus;
-
- // setting the packet type
- packet_send = createPacket({ packetType, AuthStatus::AuthSuccess });
-
- // load the packet from network byte order
- packet_recv = fromQByteArray(toQByteArray(packet_send));
-
- // check the packet type
- EXPECT_EQ(packet_recv.getPacketType(), packetType);
-
- // check the packet length
- EXPECT_EQ(packet_recv.getPacketLength(), packet_send.size());
-
- // check the status code
- EXPECT_EQ(packet_recv.getAuthStatus(), AuthStatus::AuthSuccess);
-}
diff --git a/tests/test.cpp b/tests/test.cpp
index 9376c3b..9dca502 100644
--- a/tests/test.cpp
+++ b/tests/test.cpp
@@ -7,7 +7,6 @@
#include
// Local header files
-#include "tests/network/packets/authentication.hpp"
#include "tests/network/packets/invalidrequest.hpp"
#include "tests/network/packets/syncingpacket.hpp"
diff --git a/types/device/device.cpp b/types/device/device.cpp
new file mode 100644
index 0000000..43e406c
--- /dev/null
+++ b/types/device/device.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2023 Sri Lakshmi Kanthan P
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "device.hpp"
+
+namespace srilakshmikanthanp::clipbirdesk::types::device {
+/**
+ * @brief operator overloading for ==
+ */
+bool Device::operator==(const Device& other) const {
+ return ip == other.ip && port == other.port && name == other.name;
+}
+
+/**
+ * @brief operator overloading for !=
+ */
+bool Device::operator!=(const Device& other) const {
+ return !(*this == other);
+}
+} // namespace srilakshmikanthanp::types::device
diff --git a/types/device/device.hpp b/types/device/device.hpp
new file mode 100644
index 0000000..40a7333
--- /dev/null
+++ b/types/device/device.hpp
@@ -0,0 +1,25 @@
+#pragma once // Header guard see https://en.wikipedia.org/wiki/Include_guard
+
+// Copyright (c) 2023 Sri Lakshmi Kanthan P
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include
+#include
+
+namespace srilakshmikanthanp::clipbirdesk::types::device {
+/**
+ * @brief Device Class That Represents Device
+ */
+struct Device {
+ // operator overloading for comparison
+ bool operator==(const Device& other) const;
+ bool operator!=(const Device& other) const;
+
+ // public members
+ QHostAddress ip;
+ quint16 port;
+ QString name;
+};
+} // namespace srilakshmikanthanp::types::device
diff --git a/types/enums/enums.hpp b/types/enums/enums.hpp
index 8b0c6a1..aec36d4 100644
--- a/types/enums/enums.hpp
+++ b/types/enums/enums.hpp
@@ -10,20 +10,25 @@
namespace srilakshmikanthanp::clipbirdesk::types::enums {
/// @brief IP type used in the discovery packet
enum class IPType : quint8 {
- IPv4 = 0,
- IPv6 = 1,
+ IPv4 = 0x00,
+ IPv6 = 0x01,
};
/// @brief Allowed Error Codes
enum ErrorCode : quint8 {
CodingError = 0x01,
- SSLError = 0x02,
- InvalidPacket = 0x03,
+ InvalidPacket = 0x02,
+};
+
+/// @brief Allowed Authentication Types
+enum AuthType : quint8 {
+ AuthReq = 0x00,
+ AuthRes = 0x01,
};
/// @brief Allowed Authentication Status
enum AuthStatus : quint8 {
- AuthFailed = 0x00,
- AuthSuccess = 0x01,
+ AuthOkay = 0x00,
+ AuthFail = 0x01,
};
} // namespace srilakshmikanthanp::clipbirdesk::types::enums
diff --git a/ui/gui/components/device/device.cpp b/ui/gui/components/device/device.cpp
index 1d8574e..5727ff7 100644
--- a/ui/gui/components/device/device.cpp
+++ b/ui/gui/components/device/device.cpp
@@ -6,19 +6,6 @@
#include "device.hpp"
namespace srilakshmikanthanp::clipbirdesk::ui::gui::components {
-/**
- * @brief Called when host is resolved
- *
- * @param info
- */
-void Device::onHostResolved(const QHostInfo &info) {
- if (info.error() != QHostInfo::NoError) {
- this->hostName->setText("Unknown");
- }
-
- this->hostName->setText(info.hostName());
-}
-
/**
* @brief Construct a new Device object
* with parent as QWidget
@@ -27,7 +14,7 @@ void Device::onHostResolved(const QHostInfo &info) {
Device::Device(QWidget *parent) : QWidget(parent) {
// connect the button signal to this signal
QObject::connect(actBtn, &QPushButton::clicked, [this]() {
- emit onAction({address, port, action});
+ emit onAction({device, action});
});
// vertical alignment of the labels as center
@@ -51,17 +38,14 @@ Device::Device(QWidget *parent) : QWidget(parent) {
/**
* @brief Set the Device
- *
- * @param QPair
*/
void Device::setHost(Device::Value host) {
// set the address and port
- this->address = std::get<0>(host);
- this->port = std::get<1>(host);
- this->action = std::get<2>(host);
+ this->device = std::get<0>(host);
+ this->action = std::get<1>(host);
// set the host name
- this->hostName->setText("Resolving...");
+ this->hostName->setText(device.name);
// action text to set
const auto a = action == Action::Disconnect ? disconnect : connect;
@@ -71,17 +55,12 @@ void Device::setHost(Device::Value host) {
// set the object name to identify
this->actBtn->setObjectName(a);
-
- // lookup the host name and change
- QHostInfo::lookupHost(address.toString(), this, &Device::onHostResolved);
}
/**
* @brief Get the Device
- *
- * @return QPair
*/
Device::Value Device::getHost() const {
- return std::make_tuple(address, port, action);
+ return std::make_tuple(device, action);
}
} // namespace srilakshmikanthanp::clipbirdesk::ui::gui::components
diff --git a/ui/gui/components/device/device.hpp b/ui/gui/components/device/device.hpp
index 3538c2c..e3bed3f 100644
--- a/ui/gui/components/device/device.hpp
+++ b/ui/gui/components/device/device.hpp
@@ -17,10 +17,12 @@
#include
#include