add Unix Socket API

This commit is contained in:
Maik Jurischka
2025-12-12 10:46:49 +01:00
parent 2edffd5f76
commit fe0af4dc64
7 changed files with 1033 additions and 19 deletions

111
SocketServer.cpp Normal file
View File

@@ -0,0 +1,111 @@
#include "SocketServer.h"
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
SocketServer::SocketServer(const std::string& socketPath)
: socketPath_(socketPath), serverFd_(-1), running_(false) {}
SocketServer::~SocketServer() {
stop();
}
bool SocketServer::start(CommandCallback callback) {
if (running_) {
return false;
}
commandCallback_ = callback;
// Remove existing socket file if it exists
unlink(socketPath_.c_str());
// Create Unix domain socket
serverFd_ = socket(AF_UNIX, SOCK_STREAM, 0);
if (serverFd_ < 0) {
std::cerr << "Failed to create socket" << std::endl;
return false;
}
// Bind socket
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketPath_.c_str(), sizeof(addr.sun_path) - 1);
if (bind(serverFd_, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
std::cerr << "Failed to bind socket: " << strerror(errno) << std::endl;
close(serverFd_);
return false;
}
// Listen for connections
if (listen(serverFd_, 5) < 0) {
std::cerr << "Failed to listen on socket" << std::endl;
close(serverFd_);
unlink(socketPath_.c_str());
return false;
}
running_ = true;
serverThread_ = std::make_unique<std::thread>(&SocketServer::serverLoop, this);
std::cout << "Socket server started on " << socketPath_ << std::endl;
return true;
}
void SocketServer::stop() {
if (!running_) {
return;
}
running_ = false;
// Close server socket to unblock accept()
if (serverFd_ >= 0) {
shutdown(serverFd_, SHUT_RDWR);
close(serverFd_);
serverFd_ = -1;
}
// Wait for server thread to finish
if (serverThread_ && serverThread_->joinable()) {
serverThread_->join();
}
unlink(socketPath_.c_str());
std::cout << "Socket server stopped" << std::endl;
}
void SocketServer::serverLoop() {
while (running_) {
int clientFd = accept(serverFd_, nullptr, nullptr);
if (clientFd < 0) {
if (running_) {
std::cerr << "Accept failed: " << strerror(errno) << std::endl;
}
continue;
}
handleClient(clientFd);
close(clientFd);
}
}
void SocketServer::handleClient(int clientFd) {
char buffer[4096];
ssize_t bytesRead = recv(clientFd, buffer, sizeof(buffer) - 1, 0);
if (bytesRead > 0) {
buffer[bytesRead] = '\0';
std::string command(buffer);
// Call the command callback
std::string response = commandCallback_(command);
// Send response back to client
send(clientFd, response.c_str(), response.length(), 0);
}
}