Skip to content

Commit

Permalink
Add Socket Class (#55)
Browse files Browse the repository at this point in the history
* Network - Add Socket Class

* Network - Socket Fixes

* App - Use Socket in Linux IPC Implementation

* Network - Fix Socket and IPC

* Network - Fix Socket Shutdown on Linux

* Version Bump

* Network - Fix `Socket` Build on Windows

* Network - Fix Windows Socket Shutdown

* Network - Add Pipe Support to Socket on Windows

* Check Spell
  • Loading branch information
nlogozzo authored Dec 27, 2024
1 parent 8f1671a commit a5fdc24
Show file tree
Hide file tree
Showing 16 changed files with 578 additions and 186 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 2024.12.1 (next)
### Breaking Changes
None
### New APIs
#### Network
- Added `Nickvision::Network::Socket` class
### Fixes
None

## 2024.12.0
### Breaking Changes
None
Expand Down
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")

#libnick Definition
project ("libnick" LANGUAGES C CXX VERSION 2024.12.0 DESCRIPTION "A cross-platform base for native Nickvision applications.")
project ("libnick" LANGUAGES C CXX VERSION 2024.12.1 DESCRIPTION "A cross-platform base for native Nickvision applications.")
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
include(CTest)
Expand Down Expand Up @@ -64,6 +64,7 @@ add_library (${PROJECT_NAME}
"src/network/macaddress.cpp"
"src/network/networkmonitor.cpp"
"src/network/networkstatechangedeventargs.cpp"
"src/network/socket.cpp"
"src/network/web.cpp"
"src/notifications/notificationsenteventargs.cpp"
"src/notifications/notifyicon.cpp"
Expand Down Expand Up @@ -97,7 +98,7 @@ if(USING_VCPKG)
endif()
if(WIN32)
find_package(sqlcipher CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC sqlcipher::sqlcipher Advapi32 Dnsapi Dwmapi Gdiplus Kernel32 Shell32 UxTheme)
target_link_libraries(${PROJECT_NAME} PUBLIC sqlcipher::sqlcipher Advapi32 Dnsapi Dwmapi Gdiplus Kernel32 Shell32 UxTheme Ws2_32)
elseif(APPLE)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_library(CF_LIBRARY CoreFoundation)
Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = "libnick"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = "2024.12.0"
PROJECT_NUMBER = "2024.12.1"

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
21 changes: 6 additions & 15 deletions include/app/interprocesscommunicator.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,12 @@
#ifndef INTERPROCESSCOMMUNICATOR_H
#define INTERPROCESSCOMMUNICATOR_H

#include <memory>
#include <string>
#include <thread>
#include <vector>
#include "events/event.h"
#include "events/parameventargs.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/un.h>
#endif
#include "network/socket.h"

namespace Nickvision::App
{
Expand Down Expand Up @@ -83,17 +79,12 @@ namespace Nickvision::App
* @brief Runs the IPC server loop.
*/
void runServer();
std::string m_id;
bool m_serverRunning;
Events::Event<Events::ParamEventArgs<std::vector<std::string>>> m_commandReceived;
std::unique_ptr<Network::Socket> m_serverSocket;
std::thread m_server;
std::string m_path;
#ifdef _WIN32
HANDLE m_serverPipe;
#else
struct sockaddr_un m_sockaddr;
int m_serverSocket;
#endif
Events::Event<Events::ParamEventArgs<std::vector<std::string>>> m_commandReceived;
};
}

#endif //INTERPROCESSCOMMUNICATOR_H
#endif //INTERPROCESSCOMMUNICATOR_H
26 changes: 26 additions & 0 deletions include/network/addressfamily.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef ADDRESSFAMILY_H
#define ADDRESSFAMILY_H

#ifdef _WIN32
#include <Winsock2.h>
#else
#include <sys/socket.h>
#endif

namespace Nickvision::Network
{
/**
* @brief Type of address that can be used by a socket.
*/
enum class AddressFamily
{
#ifdef _WIN32
Pipe,
#else
Unix = AF_UNIX,
#endif
IPv4 = AF_INET
};
}

#endif //ADDRESSFAMILY_H
7 changes: 6 additions & 1 deletion include/network/ipv4address.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ namespace Nickvision::Network
* @return The fourth byte of the address
*/
unsigned char getFourth() const;
/**
* @brief Gets the address in network byte order.
* @return The address in network byte order
*/
unsigned long getNetworkByteOrder() const;
/**
* @brief Gets the string representation of the address.
* @return The string representation of the address
Expand All @@ -87,4 +92,4 @@ namespace Nickvision::Network
};
}

#endif //IPV4ADDRESS_H
#endif //IPV4ADDRESS_H
88 changes: 88 additions & 0 deletions include/network/socket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#ifndef SOCKET_H
#define SOCKET_H

#include <memory>
#include <string>
#ifdef _WIN32
#include <Winsock2.h>
#endif
#include "addressfamily.h"
#include "socketpurpose.h"
#include "sockettype.h"

namespace Nickvision::Network
{
/**
* @brief A network socket (an endpoint for communication).
*/
class Socket
{
public:
/**
* @brief Constructs a Socket.
* @param purpose The purpose of the socket
* @param type The SocketType of the socket (Ignored when AddressFamily::Pipe is used)
* @param family The AddressFamily of the socket
* @param address The address to bind/connect the socket to
* @param port The port to bind/connect the socket to (Ignored when AddressFamily::Unix or AddressFamily::Pipe is used)
* @throw std::invalid_argument Thrown if the address is invalid
* @throw std::logic_error Thrown if the socket cannot be binded to (i.e. A server socket already exists)
* @throw std::runtime_error Thrown on Windows if winsock cannot be initialized
* @throw std::runtime_error Thrown if the socket cannot be created or listened
*/
Socket(SocketPurpose purpose, SocketType type, AddressFamily family, const std::string& address, int port);
/**
* @brief Destructs a Socket.
* @brief This will disconnect from a child socket if disconnect was not already called.
*/
~Socket();
/**
* @brief Establishes a connection.
* @brief If the socket's purpose is SocketPurpose::Server, this method will block until a client is connected.
* @brief Is the socket's purpose is SocketPurpose::Client, this method will connect to the server.
* @return True if connected, else false
*/
bool connect();
/**
* @brief Closes a connection.
* @brief If the socket's purpose is SocketPurpose::Server, this method will drop the connection with the client.
* @brief If the socket's purpose is SocketPurpose::Client, this method will have no effect.
* @return True if disconnected, else false
*/
bool disconnect();
/**
* @brief Receives a message.
* @brief connect() must have been called first and have returned true.
* @brief If the socket's purpose is SocketPurpose::Server, this method will receive a message from the client.
* @brief If the socket's purpose is SocketPurpose::Client, this method will receive a message from the server.
* @return The received message
*/
std::string receiveMessage() const;
/**
* @brief Sends a message.
* @brief connect() must have been called first and have returned true.
* @brief If the socket's purpose is SocketPurpose::Server, this method will send a message to the client.
* @brief If the socket's purpose is SocketPurpose::Client, this method will send a message to the server.
* @param message The message to send
* @return True if message sent successfully, else false
*/
bool sendMessage(const std::string& message) const;

private:
SocketPurpose m_purpose;
SocketType m_type;
AddressFamily m_family;
std::string m_address;
int m_port;
#ifdef _WIN32
SOCKET m_socket;
SOCKET m_child;
HANDLE m_pipe;
#else
int m_socket;
int m_child;
#endif
};
}

#endif //SOCKET_H
16 changes: 16 additions & 0 deletions include/network/socketpurpose.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef SOCKETPURPOSE_H
#define SOCKETPURPOSE_H

namespace Nickvision::Network
{
/**
* @brief Purposes of sockets.
*/
enum class SocketPurpose
{
Server,
Client
};
}

#endif // SOCKETPURPOSE_H
25 changes: 25 additions & 0 deletions include/network/sockettype.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef SOCKETTYPE_H
#define SOCKETTYPE_H

#ifdef _WIN32
#include <Winsock2.h>
#else
#include <sys/socket.h>
#endif

namespace Nickvision::Network
{
/**
* @brief Type of sockets.
*/
enum class SocketType
{
Stream = SOCK_STREAM,
Datagram = SOCK_DGRAM,
#ifdef __linux__
SequencedPacket = SOCK_SEQPACKET
#endif
};
}

#endif // SOCKETTYPE_H
10 changes: 4 additions & 6 deletions manual/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@

libnick provides Nickvision apps with a common set of cross-platform APIs for managing system and desktop app functionality such as network management, taskbar icons, translations, app updates, and more.

## 2024.12.0
## 2024.12.1 (next)
### Breaking Changes
None
### New APIs
None
#### Network
- Added `Nickvision::Network::Socket` class
### Fixes
#### Notifications
- Fixed an issue where `ShellNotification::send()` did not work on non-GTK linux applications
#### System
- Fixed an issue where `Environment::getExecutableDirectory()` did not return the correct path on macOS
None

## Dependencies
The following are a list of dependencies used by libnick.
Expand Down
8 changes: 4 additions & 4 deletions src/app/datafilebase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ namespace Nickvision::App
m_path = UserDirectories::get(ApplicationUserDirectory::Config, appName) / (m_key + ".json");
if (std::filesystem::exists(m_path))
{
std::ifstream in{ m_path };
boost::json::stream_parser parser;
std::string line;
try
{
std::ifstream in{ m_path };
boost::json::stream_parser parser;
std::string line;
while(std::getline(in, line))
{
parser.write(line);
Expand Down Expand Up @@ -58,4 +58,4 @@ namespace Nickvision::App
m_saved({});
return true;
}
}
}
Loading

0 comments on commit a5fdc24

Please sign in to comment.