111 lines
2.8 KiB
C++
111 lines
2.8 KiB
C++
#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_ = std::move(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 = {};
|
|
addr.sun_family = AF_UNIX;
|
|
strncpy(addr.sun_path, socketPath_.c_str(), sizeof(addr.sun_path) - 1);
|
|
|
|
if (bind(serverFd_, reinterpret_cast<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(const int clientFd) {
|
|
char buffer[4096];
|
|
ssize_t bytesRead = recv(clientFd, buffer, sizeof(buffer) - 1, 0);
|
|
|
|
if (bytesRead > 0) {
|
|
buffer[bytesRead] = '\0';
|
|
const std::string command(buffer);
|
|
|
|
// Call the command callback
|
|
const std::string response = commandCallback_(command);
|
|
|
|
// Send response back to client
|
|
send(clientFd, response.c_str(), response.length(), 0);
|
|
}
|
|
}
|