Files
stvpn/service.cpp
T
2026-04-27 11:53:11 +02:00

137 lines
4.2 KiB
C++

extern "C" {
#include <arpa/inet.h>
}
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <thread>
#include <chrono>
#include <cstring>
#include <service.hpp>
#include <logger.hpp>
#include <rpcheader.hpp>
#include <control.pb.h>
using namespace std::chrono_literals;
void SocketHandler::Handle(int sock) {
std::cout << std::format("Handler {} start", sock) << std::endl;
const int headerSize = 8;
std::string rawResHeader;
char buffer[headerSize];
memset(&buffer, 0, headerSize);
int rsize = 0;
if ((rsize = read(sock, &buffer, headerSize)) < 0) {
logger.Log("Error read");
close(sock);
return;
}
logger.Log(std::format("rpc rsize {}", rsize));
RPCHeader inRPCHeader;
std::string i(buffer, headerSize);
inRPCHeader.Decode(i);
int rcpPacketSize = inRPCHeader.PacketSize();
logger.Log(std::format("rpc packet size {}", rcpPacketSize));
char buffer2[rcpPacketSize];
if ((rsize = read(sock, &buffer2, rcpPacketSize)) < 0) {
logger.Log("Error read");
close(sock);
return;
}
logger.Log(std::format("rpc packet rsize {}", rsize));
std::string rawReq(buffer2, rcpPacketSize);
control::HelloRequest pbReq;
pbReq.ParseFromString(rawReq);
logger.Log(std::format("rpcName: {}", pbReq.meta().rpcname()));
logger.Log(std::format("req message: {}\n", pbReq.message()));
control::HelloResult pbRes;
pbRes.set_message("Johnny!");
auto resMeta = pbRes.mutable_meta();
resMeta->set_error(false);
std::string rawRes;
pbRes.SerializeToString(&rawRes);
RPCHeader outRPCHeader(rawRes.size());
auto rawPacket = outRPCHeader.Encode();
rawPacket.append(rawRes);
int wsize = 0;
if ((wsize = write(sock, rawPacket.data(), rawPacket.size())) < 0) {
logger.Log("Error write");
close(sock);
return;
}
logger.Log(std::format("Handler {} done", sock));
close(sock);
}
Service::Service(int svcport) {
port = svcport;
}
Service::~Service() {
close(port);
}
std::expected<void, std::string> Service::Bind(void) {
struct sockaddr_in address;
int srvsock;
if ((srvsock = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create socker error: " + error);
}
int opt = 1;
if (setsockopt(srvsock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set socket option error: " + error);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(srvsock, (struct sockaddr *)&address, sizeof(address)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Bind error: " + error);
}
if (listen(srvsock, 3) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Listen error: " + error);
}
sock = srvsock;
return {};
}
std::expected<void, std::string> Service::Listen(SocketHandler *handler) {
struct sockaddr_in address;
int addrlen = sizeof(address);
int newsock = 0;
for (;;) {
if ((newsock = accept(sock, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Accept error: " + error);
}
std::jthread t(&SocketHandler::Handle, handler, newsock);
t.detach();
}
return {};
}