add Unix Socket API
This commit is contained in:
111
SocketServer.cpp
Normal file
111
SocketServer.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user