working commit

This commit is contained in:
Олег Бородин
2026-05-05 11:37:10 +02:00
parent bd4df1e3da
commit eda9b8986b
62 changed files with 7546 additions and 476 deletions
+33
View File
@@ -0,0 +1,33 @@
extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
}
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <cstring>
#include <expected>
#include <string>
#include <iostream>
#include <sstream>
#include <abrpchandler.hpp>
AbstractRPCHandler::AbstractRPCHandler() {}
std::expected<void, std::string> AbstractRPCHandler::Handle(std::string& req, std::string& res) {
return {};
}
AbstractRPCHandler::~AbstractRPCHandler() {}
+26
View File
@@ -0,0 +1,26 @@
#ifndef NETHANDLER_HPP
#define NETHANDLER_HPP
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <sstream>
#include <netclient.hpp>
class AbstractRPCHandler {
public:
AbstractRPCHandler(void);
virtual std::expected<void, std::string> Handle(std::string& req, std::string& res);
virtual ~AbstractRPCHandler(void);
AbstractRPCHandler(const AbstractRPCHandler&) = delete;
AbstractRPCHandler& operator=(const AbstractRPCHandler&) = delete;
};
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+49
View File
@@ -0,0 +1,49 @@
syntax = "proto3";
package control;
//option optimize_for = LITE_RUNTIME;
//option cc_generic_services = false;
message MsgMeta {
string kind = 1;
}
message Message {
MsgMeta meta = 1;
}
message InternetPacket {
MsgMeta meta = 1;
string payload = 2;
}
message ReqMeta {
string kind = 1;
}
message ResMeta {
bool error = 1;
string message = 2;
}
message Request {
ReqMeta meta = 1;
}
message Result {
ResMeta meta = 1;
}
message HelloRequest {
ReqMeta meta = 1;
string message = 2;
}
message HelloResult {
ResMeta meta = 1;
string message = 2;
}
+12
View File
@@ -0,0 +1,12 @@
#include <expected>
#include <string>
#include <cstring>
#include <interface.hpp>
#include <service.hpp>
int main(int argc, char** argv) {
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
#include <expected>
#include <string>
#include <cstring>
#include <interface.hpp>
#include <service.hpp>
int main(int argc, char** argv) {
return 0;
}
+387
View File
@@ -0,0 +1,387 @@
extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
}
#include <cstring>
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <thread>
#include <chrono>
#include <interface.hpp>
std::expected<void, std::string> Interface::Create(const std::string name) {
if ((tunfd = open("/dev/net/tun", O_RDWR | O_CLOEXEC)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
if (ioctl(tunfd, TUNSETIFF, (void*)(&ifr)) < 0) {
close(tunfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
ifname = ifr.ifr_name;
#if 0
if (ioctl(tunfd, TUNSETPERSIST, 0) < 0) {
close(tunfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
#endif
//struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
close(tunfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) {
close(tunfd);
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
close(sockfd);
mtu = ifr.ifr_mtu;
return {};
}
std::expected<void, std::string> Interface::SetMTU(int ifmtu) {
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set MTU error: " + error);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
ifr.ifr_mtu = ifmtu;
if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set MTU error: " + error);
}
close(sockfd);
return {};
}
std::expected<int, std::string> Interface::GetMTU(void) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
close(sockfd);
return ifr.ifr_mtu;
}
std::expected<std::string, std::string> Interface::GetIP4Address(void) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
close(sockfd);
auto sinaddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
std::string addr = inet_ntoa(sinaddr);
return addr;
}
std::expected<void, std::string> Interface::SetIP4Address(std::string ipaddr) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error);
}
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
struct sockaddr_in* addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
if (inet_pton(AF_INET, ipaddr.c_str(), &addr->sin_addr) <= 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error);
}
if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error);
}
close(sockfd);
return {};
}
std::expected<void, std::string> Interface::SetIP4Netmask(int prefix) {
if (prefix < 0 || prefix > 32) {
return std::unexpected("Invalid prefix");
}
uint32_t mask = (prefix == 0) ? 0 : (~0U << (32 - prefix));
struct in_addr maskaddr;
maskaddr.s_addr = htonl(mask);
char buffer[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &maskaddr, buffer, sizeof(buffer)) == NULL) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set1 netmask error: " + error);
}
auto netmask = std::string(buffer);
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set2 netmask error: " + error);
}
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
struct sockaddr_in* addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
if (inet_pton(AF_INET, netmask.c_str(), &addr->sin_addr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set3 netmask error: " + error);
}
if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set4 netmask error: " + error);
}
close(sockfd);
return {};
}
std::expected<void, std::string> Interface::Up(void) {
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
close(sockfd);
return {};
}
std::expected<void, std::string> Interface::Down(void) {
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
close(sockfd);
return {};
}
std::expected<std::string, std::string> Interface::Read() {
char buffer[mtu];
int rsize = 0;
if ((rsize = read(tunfd, buffer, sizeof(buffer))) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Read interface error: " + error);
}
std::string rdata;
rdata.append(buffer, rsize);
return rdata;
}
std::string Interface::Name() {
return ifname;
}
int Interface::MTU() {
return mtu;
}
Interface::~Interface() {
close(tunfd);
}
std::expected<void, std::string> Interface::UpN(void) {
int netlinkfd = 0;
if ((netlinkfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
struct {
struct nlmsghdr header;
struct ifinfomsg content;
} request;
memset(&request, 0, sizeof request);
request.header.nlmsg_len = NLMSG_LENGTH(sizeof request.content);
request.header.nlmsg_flags = NLM_F_REQUEST;
request.header.nlmsg_type = RTM_NEWLINK;
request.content.ifi_index = if_nametoindex(ifname.c_str());
request.content.ifi_flags = IFF_UP;
request.content.ifi_change = 1;
if (send(netlinkfd, &request, request.header.nlmsg_len, 0) < 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
close(netlinkfd);
return {};
}
std::expected<void, std::string> Interface::SetIP4AddrMask(const std::string address, const int prefix) {
int netlinkfd = 0;
if ((netlinkfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
int rc = 0;
struct sockaddr_nl sockaddr;
memset(&sockaddr, 0, sizeof sockaddr);
sockaddr.nl_family = AF_NETLINK;
if ((rc = bind(netlinkfd, (struct sockaddr*) &sockaddr, sizeof sockaddr))< 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set interface address error: " + error);
}
struct {
struct nlmsghdr header;
struct ifaddrmsg content;
char attributes_buf[64];
} request;
struct rtattr *request_attr;
size_t attributes_buf_avail = sizeof request.attributes_buf;
memset(&request, 0, sizeof request);
request.header.nlmsg_len = NLMSG_LENGTH(sizeof request.content);
request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE;
request.header.nlmsg_type = RTM_NEWADDR;
request.content.ifa_index = if_nametoindex(ifname.c_str());
request.content.ifa_family = AF_INET;
request.content.ifa_prefixlen = prefix;
/* request.attributes[IFA_LOCAL] = address */
request_attr = IFA_RTA(&request.content);
request_attr->rta_type = IFA_LOCAL;
request_attr->rta_len = RTA_LENGTH(sizeof (struct in_addr));
request.header.nlmsg_len += request_attr->rta_len;
inet_pton(AF_INET, address.c_str(), RTA_DATA(request_attr));
/* request.attributes[IFA_ADDRESS] = address */
request_attr = RTA_NEXT(request_attr, attributes_buf_avail);
request_attr->rta_type = IFA_ADDRESS;
request_attr->rta_len = RTA_LENGTH(sizeof (struct in_addr));
request.header.nlmsg_len += request_attr->rta_len;
inet_pton(AF_INET, address.c_str(), RTA_DATA(request_attr));
if (send(netlinkfd, &request, request.header.nlmsg_len, 0) < 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set interface address error: " + error);
}
close(netlinkfd);
return {};
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef INTERFACE_HPP
#define INTERFACE_HPP
class Interface {
private:
int tunfd;
std::string ifname;
int mtu;
public:
std::expected<void, std::string> Create(const std::string name);
std::string Name();
int MTU();
std::expected<void, std::string> SetMTU(int mtu);
std::expected<int, std::string> GetMTU(void);
std::expected<void, std::string> SetIP4Address(std::string ipaddr);
std::expected<void, std::string> SetIP4Netmask(int netmask);
std::expected<std::string, std::string> GetIP4Address(void);
std::expected<void, std::string> Up(void);
std::expected<void, std::string> Down(void);
std::expected<void, std::string> UpN(void);
std::expected<void, std::string> SetIP4AddrMask(const std::string address, const int prefix);
std::expected<std::string, std::string> Read();
~Interface();
};
#endif
+11
View File
@@ -0,0 +1,11 @@
#include <expected>
#include <vector>
#include <iprouter.hpp>
std::expected<Routes, std::string> Router::List() {
std::vector<Route> routes;
return routes;
}
+18
View File
@@ -0,0 +1,18 @@
#include <vector>
#include <expected>
#include <string>
class Route {
public:
std::string dest;
int mask;
};
using Routes = std::vector<Route>;
class Router {
std::expected<Routes, std::string> List();
};
+45
View File
@@ -0,0 +1,45 @@
#include <chrono>
#include <format>
#include <iostream>
#include <mutex>
#include <string>
#include <cstdio>
#include <cstdarg>
#include <logger.hpp>
Logger logger;
static std::mutex mtx;
Logger::Logger(const std::string ilabel) {
label = ilabel;
}
Logger::Logger(void) {
label = "global";
}
void Logger::Log(const std::string& message) {
auto now = std::chrono::system_clock::now();
std::chrono::zoned_time localnow{std::chrono::current_zone(), now};
std::string timenow = std::format("{:%Y-%m-%dT%H:%M:%OS%Z}", localnow);
std::lock_guard<std::mutex> lock(mtx);
std::cout << std::format("{} {} {}\n", timenow, label, message);
}
void Logger::Logf(const std::string& format, ...) {
auto now = std::chrono::system_clock::now();
std::chrono::zoned_time localnow{std::chrono::current_zone(), now};
std::string timenow = std::format("{:%Y-%m-%dT%H:%M:%OS%Z}", localnow);
std::lock_guard<std::mutex> lock(mtx);
std::printf("%s %s ", timenow.c_str(), label.c_str());
va_list args;
va_start(args, format);
std::vprintf(format.data(), args);
va_end(args);
std::printf("\n");
}
+20
View File
@@ -0,0 +1,20 @@
#include <iostream>
#include <fstream>
#include <string>
#include <mutex>
#include <ctime>
class Logger {
private:
std::string label;
public:
Logger(std::string ilabel);
Logger();
void Log(const std::string& message);
void Logf(const std::string& format, ...);
};
extern Logger logger;
+49
View File
@@ -0,0 +1,49 @@
extern "C" {
#include <arpa/inet.h>
}
#include <expected>
#include <string>
#include <cstring>
#include <iostream>
#include <format>
#include <cstdint>
#include <msgheader.hpp>
MessageHeader::MessageHeader(const uint32_t ipSize) {
pSize = ipSize;
}
MessageHeader::MessageHeader(void) {
pSize = 0;
}
std::string MessageHeader::Encode() {
std::string buffer, tmp;
auto magic = htonl(MAGIC);
tmp = std::string(reinterpret_cast<const char*>(&magic), sizeof(magic));
buffer.append(tmp);
auto size = htonl(pSize);
tmp = std::string(reinterpret_cast<const char*>(&size), sizeof(size));
buffer.append(tmp);
return buffer;
}
std::expected<void, std::string> MessageHeader::Decode(const std::string rawHeader) {
uint32_t tmp;
std::memcpy(&tmp, rawHeader.data(), sizeof(uint32_t));
auto magic = ntohl(tmp);
if (magic != MAGIC) {
return std::unexpected("Wrong magic code");
}
std::memcpy(&tmp, rawHeader.data() + sizeof(uint32_t), sizeof(uint32_t));
pSize = ntohl(tmp);
return {};
}
uint32_t MessageHeader::PacketSize() {
return pSize;
}
+17
View File
@@ -0,0 +1,17 @@
#include <string>
constexpr uint32_t MAGIC = 0xABBA;
constexpr int rpcHeaderSize = 8;
class MessageHeader {
private:
uint32_t pSize = 0;
public:
MessageHeader(const uint32_t pSize);
MessageHeader(void);
std::string Encode(void);
std::expected<void, std::string> Decode(const std::string buffer);
uint32_t PacketSize(void);
};
+19
View File
@@ -0,0 +1,19 @@
#include <expected>
#include <string>
#include <cstring>
#include <iostream>
#include <format>
#include <msgheader.hpp>
int main(int argc, char** argv) {
MessageHeader primary(1021);
auto rawHeader = primary.Encode();
MessageHeader second;
second.Decode(rawHeader);
std::cout << std::format("{}\n", second.PacketSize());
assert
}
+41
View File
@@ -0,0 +1,41 @@
extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
}
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <cstring>
#include <expected>
#include <string>
#include <iostream>
#include <sstream>
#include <netclient.hpp>
NetClient::NetClient() {}
std::expected<void, std::string> NetClient::Connect(const std::string naddress, const int port) {
return {};
}
std::expected<int, std::string> NetClient::Write(std::string payload) {
return payload.size();
}
std::expected<int, std::string> NetClient::Read(std::string& res, int size) {
return 0;
}
NetClient::~NetClient() {}
+23
View File
@@ -0,0 +1,23 @@
#ifndef NETCLIENT_HPP
#define NETCLIENT_HPP
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <sstream>
class NetClient {
public:
NetClient(void);
virtual std::expected<void, std::string> Connect(std::string address, const int port);
virtual std::expected<int, std::string> Write(std::string payload);
virtual std::expected<int, std::string> Read(std::string& buffer, int size);
virtual ~NetClient(void);
NetClient(const NetClient&) = delete;
NetClient& operator=(const NetClient&) = delete;
};
#endif
+76
View File
@@ -0,0 +1,76 @@
extern "C" {
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
}
#include <cstring>
#include <expected>
#include <string>
#include <resolver.hpp>
Address::Address(std::string iaddress, int ifamily) {
address = iaddress;
family = ifamily;
}
int Address::GetFamily() {
return family;
}
std::string Address::GetAddress() {
return address;
}
std::expected<Address, std::string> Resolver::Resolve(std::string hostname) {
struct sockaddr_in sa;
if (inet_pton(AF_INET, hostname.c_str(), &(sa.sin_addr)) == 1) {
family = AF_INET;
return Address(hostname, AF_INET);
}
if (inet_pton(AF_INET6, hostname.c_str(), &(sa.sin_addr)) == 1) {
return Address(hostname, AF_INET6);
}
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
int status = 0;
if ((status = getaddrinfo(hostname.c_str(), NULL, &hints, &res)) != 0) {
std::string error = gai_strerror(status);
return std::unexpected("Resolve adress error: " + error);
}
struct addrinfo* p;
char ipaddr[INET6_ADDRSTRLEN + 1];
for (p = res; p != NULL; p = p->ai_next) {
if (p->ai_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
void* addr = &(ipv4->sin_addr);
if (inet_ntop(p->ai_family, addr, ipaddr, sizeof(ipaddr)) == NULL) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Cannot conver address: " + error);
}
std::string address(ipaddr);
return Address(address, AF_INET);;
}
}
for (p = res; p != NULL; p = p->ai_next) {
if (p->ai_family == AF_INET6) {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
void* addr = &(ipv6->sin6_addr);
if (inet_ntop(p->ai_family, addr, ipaddr, sizeof(ipaddr)) == NULL) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Cannot conver address: " + error);
}
std::string address(ipaddr);
return Address(address, AF_INET6);
}
}
return std::unexpected("Cannot resolve hostname " + hostname);
}
+20
View File
@@ -0,0 +1,20 @@
#include <expected>
#include <string>
class Address {
private:
int family;
std::string address;
public:
Address(const std::string iaddress, const int ifamily);
int GetFamily();
std::string GetAddress();
};
class Resolver {
private:
int family;
public:
std::expected<Address, std::string> Resolve(const std::string hostname);
};
+44
View File
@@ -0,0 +1,44 @@
#include <cstring>
#include <expected>
#include <iostream>
#include <span>
#include <string>
#include <vector>
#include <sstream>
#include <google/protobuf/message.h>
#include <control.pb.h>
#include <rpcclient.hpp>
#include <msgheader.hpp>
#include <netclient.hpp>
RPCClient::RPCClient(NetClient& iconnector) {
connector = &iconnector;
}
std::expected<void, std::string> RPCClient::DoTransaction(const pbMessage& pbReq, pbMessage& pbRes) {
std::string rawRequest;
pbReq.SerializeToString(&rawRequest);
MessageHeader reqHeader(rawRequest.size());
auto rawReqHeader = reqHeader.Encode();
std::string reqPacket;
reqPacket.append(rawReqHeader);
reqPacket.append(rawRequest);
connector->Write(reqPacket);
const int headerSize = rpcHeaderSize;
std::string rawResHeader;
connector->Read(rawResHeader, headerSize);
MessageHeader resHeader;
resHeader.Decode(rawResHeader);
std::string rawResponse;
connector->Read(rawResponse, resHeader.PacketSize());
pbRes.ParseFromString(rawResponse);
return {};
}
+23
View File
@@ -0,0 +1,23 @@
#include <cstring>
#include <expected>
#include <iostream>
#include <span>
#include <string>
#include <vector>
#include <google/protobuf/message.h>
#include <netclient.hpp>
using pbMessage = google::protobuf::Message;
using pbMessagePtr = std::unique_ptr<pbMessage>;
class RPCClient {
private:
NetClient* connector;
public:
RPCClient(NetClient& iconnector);
std::expected<void, std::string> DoTransaction(const pbMessage& req, pbMessage& res);
};
+47
View File
@@ -0,0 +1,47 @@
#include <expected>
#include <string>
#include <cstring>
#include <iostream>
#include <format>
#include <control.pb.h>
#include <rpcclient.hpp>
#include <abrpchandler.hpp>
#include <testconnect.hpp>
class TestHandler : public NetHandler {
public:
std::expected<void, std::string> Handle(std::string& req, std::string& res) override;
};
std::expected<void, std::string> TestHandler::Handle(std::string& rawReq, std::string& rawRes) {
control::HelloRequest pbReq;
pbReq.ParseFromString(rawReq);
std::cout << std::format("rpcName: {}\n", pbReq.meta().kind());
std::cout << std::format("req message: {}\n", pbReq.message());
control::HelloResult pbRes;
pbRes.set_message("Johnny!");
auto resMeta = pbRes.mutable_meta();
resMeta->set_error(false);
pbRes.SerializeToString(&rawRes);
return {};
}
int main(int argc, char** argv) {
TestHandler handler;
TestConnector connector(handler);
RPCClient rpcCli(connector);
control::HelloRequest pbReq;
auto reqMeta = pbReq.mutable_meta();
reqMeta->set_kind("getHello");
pbReq.set_message("What's your name?");
control::HelloResult pbRes;
auto trRes = rpcCli.DoTransaction(pbReq, pbRes);
std::cout << std::format("res message: {}\n", pbRes.message());
}
+42
View File
@@ -0,0 +1,42 @@
#include <expected>
#include <string>
#include <cstring>
#include <iostream>
#include <format>
#include <control.pb.h>
#include <rpcclient.hpp>
#include <abrpchandler.hpp>
#include <testconnect.hpp>
class TestRCPHanlder : public AbstractRPCHandler {
public:
std::expected<void, std::string> Handle(std::string& req, std::string& res) override;
};
std::expected<void, std::string> TestRCPHanlder::Handle(std::string& rawReq, std::string& rawRes) {
control::HelloRequest pbReq;
pbReq.ParseFromString(rawReq);
std::cout << std::format("kind: {}\n", pbReq.meta().kind());
std::cout << std::format("req message: {}\n", pbReq.message());
return {};
}
int main(int argc, char** argv) {
TestRCPHanlder handler;
TestConnector connector(handler);
RPCClient rpcCli(connector);
control::HelloRequest pbReq;
auto reqMeta = pbReq.mutable_meta();
reqMeta->set_kind("getHello");
pbReq.set_message("What's your name?");
control::HelloResult pbRes;
auto trRes = rpcCli.DoTransaction(pbReq, pbRes);
std::cout << std::format("res message: {}\n", pbRes.message());
}
+29
View File
@@ -0,0 +1,29 @@
#include <expected>
#include <string>
#include <cstring>
#include <iostream>
#include <format>
#include <control.pb.h>
#include <rpcclient.hpp>
#include <abrpchandler.hpp>
#include <testconnect.hpp>
#include <tcpclient.hpp>
int main(int argc, char** argv) {
TCPClient connector;
connector.Connect("127.0.0.1", 1025);
RPCClient rpcCli(connector);
control::HelloRequest pbReq;
auto reqMeta = pbReq.mutable_meta();
reqMeta->set_kind("getHello");
pbReq.set_message("What's your name?");
control::HelloResult pbRes;
auto trRes = rpcCli.DoTransaction(pbReq, pbRes);
std::cout << std::format("res message: {}\n", pbRes.message());
}
+102
View File
@@ -0,0 +1,102 @@
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/27.0.9 Chrome/134.0.6998.205 Electron/35.4.0 Safari/537.36" version="27.0.9">
<diagram name="Page-1" id="bilFRRFyBUGthtbaxYIo">
<mxGraphModel dx="1880" dy="1393" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" background="#ffffff" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-14" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F0FDFF;glass=0;strokeColor=#0e8088;" vertex="1" parent="1">
<mxGeometry x="150" y="57.5" width="400" height="332.5" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-1" value="SocketHandler" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="260" y="220" width="100" height="60" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-28" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F0FDFF;glass=0;strokeColor=#0e8088;" parent="1" vertex="1">
<mxGeometry x="-120" y="60" width="260" height="330" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-2" value="Service" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="220" y="290" width="90" height="60" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-7" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.75;entryDx=0;entryDy=0;curved=0;strokeColor=#000099;" parent="1" source="t6Klk0bs08zzC_b7PXua-6" target="t6Klk0bs08zzC_b7PXua-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-6" value="TCPClient" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad7ac;strokeColor=#b46504;" parent="1" vertex="1">
<mxGeometry x="40" y="270" width="90" height="60" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-30" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="t6Klk0bs08zzC_b7PXua-2" target="Cg_oyQztf3Ao-l-gTA_1-1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="290" y="165" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-2" value="RPCRouter" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="310" y="150" width="100" height="60" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-3" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="Cg_oyQztf3Ao-l-gTA_1-1" target="Cg_oyQztf3Ao-l-gTA_1-2">
<mxGeometry relative="1" as="geometry">
<mxPoint x="320" y="300" as="sourcePoint" />
<mxPoint x="280" y="210" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-4" value="RPCHandler" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="365" y="80" width="100" height="55" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-5" value="abstract&lt;br&gt;NetHandler" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" vertex="1" parent="1">
<mxGeometry x="270" y="-30" width="100" height="60" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-6" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="Cg_oyQztf3Ao-l-gTA_1-2" target="Cg_oyQztf3Ao-l-gTA_1-4">
<mxGeometry relative="1" as="geometry">
<mxPoint x="240" y="90" as="sourcePoint" />
<mxPoint x="180" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-7" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=1;entryDx=0;entryDy=0;curved=0;exitX=0.25;exitY=0;exitDx=0;exitDy=0;dashed=1;dashPattern=1 2;startArrow=block;startFill=0;endArrow=none;" edge="1" parent="1" source="Cg_oyQztf3Ao-l-gTA_1-2" target="Cg_oyQztf3Ao-l-gTA_1-5">
<mxGeometry relative="1" as="geometry">
<mxPoint x="400" y="215" as="sourcePoint" />
<mxPoint x="360" y="120" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-8" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.75;entryY=1;entryDx=0;entryDy=0;curved=0;exitX=0.25;exitY=0;exitDx=0;exitDy=0;dashed=1;dashPattern=1 2;startArrow=block;startFill=0;endArrow=none;" edge="1" parent="1" source="Cg_oyQztf3Ao-l-gTA_1-4" target="Cg_oyQztf3Ao-l-gTA_1-5">
<mxGeometry relative="1" as="geometry">
<mxPoint x="430" y="54.75" as="sourcePoint" />
<mxPoint x="400" y="-75.25" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-9" value="Logger" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="390" y="330" width="90" height="46" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-10" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.75;entryY=1;entryDx=0;entryDy=0;curved=0;exitX=0.25;exitY=0;exitDx=0;exitDy=0;startArrow=block;startFill=0;endArrow=none;" edge="1" parent="1" source="Cg_oyQztf3Ao-l-gTA_1-9" target="Cg_oyQztf3Ao-l-gTA_1-1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="350" y="250" as="sourcePoint" />
<mxPoint x="320" y="120" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-11" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;curved=0;startArrow=block;startFill=0;endArrow=none;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Cg_oyQztf3Ao-l-gTA_1-9" target="Cg_oyQztf3Ao-l-gTA_1-4">
<mxGeometry relative="1" as="geometry">
<mxPoint x="435" y="350" as="sourcePoint" />
<mxPoint x="450" y="130" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-12" value="RPCClient" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad7ac;strokeColor=#b46504;" vertex="1" parent="1">
<mxGeometry x="5" y="192.5" width="90" height="60" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-13" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;curved=0;strokeColor=#000099;exitX=0;exitY=0.5;exitDx=0;exitDy=0;startArrow=classic;startFill=0;endArrow=none;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-6" target="Cg_oyQztf3Ao-l-gTA_1-12">
<mxGeometry relative="1" as="geometry">
<mxPoint x="180" y="310" as="sourcePoint" />
<mxPoint x="270" y="345" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-16" value="TunInterface" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="520" y="80" width="100" height="55" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-17" value="RouteControl" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="520" y="150" width="100" height="55" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-18" value="TunInterface" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="-100" y="130" width="100" height="55" as="geometry" />
</mxCell>
<mxCell id="Cg_oyQztf3Ao-l-gTA_1-19" value="RouteControl" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="-100" y="270" width="100" height="55" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

+78
View File
@@ -0,0 +1,78 @@
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 <msgheader.hpp>
#include <control.pb.h>
using namespace std::chrono_literals;
void SocketHandler::Handle(int sock) {};
SocketHandler::~SocketHandler(void) {};
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 {};
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef SERVICE_HPP_QWERTY
#define SERVICE_HPP_QWERTY
#include <expected>
#include <string>
class SocketHandler {
public:
virtual void Handle(int sock);
virtual ~SocketHandler(void);
};
class Service {
private:
int port;
int sock;
public:
explicit Service(int port);
std::expected<void, std::string> Bind(void);
std::expected<void, std::string> Listen(SocketHandler *handler);
~Service();
};
#endif
+115
View File
@@ -0,0 +1,115 @@
#include <expected>
#include <string>
#include <cstring>
#include <iostream>
#include <control.pb.h>
#include <rpcclient.hpp>
#include <abrpchandler.hpp>
#include <service.hpp>
#include <logger.hpp>
#include <msgheader.hpp>
class TestRPCHandler : public AbstractRPCHandler {
public:
std::expected<void, std::string> Handle(std::string& req, std::string& res) override;
};
std::expected<void, std::string> TestRPCHandler::Handle(std::string& rawReq, std::string& rawRes) {
control::HelloRequest pbReq;
pbReq.ParseFromString(rawReq);
logger.Log(std::format("rpcName: {}", pbReq.meta().kind()));
logger.Log(std::format("req message: {}", pbReq.message()));
control::HelloResult pbRes;
pbRes.set_message("Johnny!");
logger.Log(std::format("res message: {}", pbRes.message()));
auto resMeta = pbRes.mutable_meta();
resMeta->set_error(false);
pbRes.SerializeToString(&rawRes);
return {};
}
class TestSocketHandler : public SocketHandler {
private:
AbstractRPCHandler* nextHandler;
public:
TestSocketHandler(AbstractRPCHandler& rcpHandler);
virtual void Handle(int sock) override;
virtual ~TestSocketHandler(void) override;
};
TestSocketHandler::TestSocketHandler(AbstractRPCHandler& rpcHandler) {
nextHandler = &rpcHandler;
}
TestSocketHandler::~TestSocketHandler(void) {};
void TestSocketHandler::Handle(int sock) {
logger.Log(std::format("Handler {} start", sock));
const int headerSize = rpcHeaderSize;
std::string inRawHeader(headerSize, '\0');
int rsize = 0;
if ((rsize = read(sock, inRawHeader.data(), inRawHeader.size())) < 0) {
logger.Log("Error read");
close(sock);
return;
}
logger.Log(std::format("header read size {}", rsize));
MessageHeader inHeader;
inHeader.Decode(inRawHeader);
int inPacketSize = inHeader.PacketSize();
logger.Log(std::format("rpc packet size {}", inPacketSize));
std::string inRawRequest(inPacketSize, '\0');
if ((rsize = read(sock, inRawRequest.data(), inRawRequest.size())) < 0) {
logger.Log("Error read");
close(sock);
return;
}
logger.Log(std::format("rpc packet rsize {}", rsize));
std::string outRawResult;
nextHandler->Handle(inRawRequest, outRawResult);
MessageHeader outHeader(outRawResult.size());
auto rawPacket = outHeader.Encode();
rawPacket.append(outRawResult);
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);
}
int main(int argc, char** argv) {
Service svc(1025);
auto bindres = svc.Bind();
if (!bindres) {
std::cerr << bindres.error() << std::endl;
return 1;
}
TestRPCHandler rcpHandler;
TestSocketHandler socketHandler(rcpHandler);
auto listres = svc.Listen(&socketHandler);
if (!listres) {
std::cerr << listres.error() << std::endl;
return 1;
}
}
+96
View File
@@ -0,0 +1,96 @@
extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
}
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <cstring>
#include <expected>
#include <string>
#include <iostream>
#include <tcpclient.hpp>
TCPClient::TCPClient() {
sock = 0;
family = 0;
}
std::expected<void, std::string> TCPClient::Connect(const std::string naddress, const int port) {
struct sockaddr_in sa;
if (inet_pton(AF_INET, naddress.c_str(), &(sa.sin_addr)) == 1) {
family = AF_INET;
} else if (inet_pton(AF_INET6, naddress.c_str(), &(sa.sin_addr)) == 1) {
family = AF_INET6;
} else {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Incorrect address " + naddress);
}
sock = socket(family, SOCK_STREAM, 0);
if (sock < 0) {
return std::unexpected("Error opening socket");
}
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
const char* addr = naddress.data();
if (inet_pton(AF_INET, addr, &serv_addr.sin_addr) <= 0) {
return std::unexpected("Invalid server IP address");
}
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout) < 0) {
return std::unexpected("Set timeout error");
}
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof timeout) < 0) {
return std::unexpected("Set timeout error");
}
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
return std::unexpected("Connecting error");
}
return {};
}
std::expected<int, std::string> TCPClient::Write(std::string payload) {
int n = 0;
if ((n = write(sock, payload.data(), payload.size())) < 0) {
return std::unexpected("Write error");
}
return n;
}
std::expected<int, std::string> TCPClient::Read(std::string& res, int size) {
char buffer[size + 1];
memset(&buffer, 0, size + 1);
int rsize = 0;
if ((rsize = read(sock, &buffer, size)) < 0) {
return std::unexpected("Read error");
}
res.append(buffer, rsize);
return rsize;
}
TCPClient::~TCPClient() {
close(sock);
}
+20
View File
@@ -0,0 +1,20 @@
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <netclient.hpp>
class TCPClient : public NetClient {
private:
int sock;
int family;
public:
TCPClient(void);
std::expected<void, std::string> Connect(std::string address, const int port);
std::expected<int, std::string> Write(std::string payload) override;
std::expected<int, std::string> Read(std::string& buffer, int size) override;
~TCPClient(void);
};
+32
View File
@@ -0,0 +1,32 @@
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <tcpclient.hpp>
int main( int argc, char** argv) {
TCPClient client;
auto res = client.Connect("209.51.188.116", 80);
if (!res) {
std::cerr << res.error() << std::endl;
return 1;
}
auto wSize = client.Write("GET / HTTP/1.1\n\n\n");
if (!wSize) {
std::cerr << wSize.error() << std::endl;
return 1;
}
std::string buffer;
auto rSize = client.Read(buffer, 8);
if (!rSize) {
std::cerr << rSize.error() << std::endl;
return 1;
}
std::cout << std::format("read {} bytes", rSize.value()) << std::endl;
std::cout << std::format("{}", buffer) << std::endl;
}
+56
View File
@@ -0,0 +1,56 @@
#include <cstring>
#include <expected>
#include <iostream>
#include <span>
#include <sstream>
#include <string>
#include <vector>
#include <memory>
#include <testconnect.hpp>
#include <abrpchandler.hpp>
#include <msgheader.hpp>
TestConnector::TestConnector(AbstractRPCHandler& hand) {
handler = &hand;
}
std::expected<int, std::string> TestConnector::Write(std::string reqNetPacket) {
std::stringstream ss(reqNetPacket);
// Read binary header
std::string reqRawHeader;
const int rhSize = rpcHeaderSize;
reqRawHeader.resize(rhSize);
ss.read(reqRawHeader.data(), rhSize);
// Decode header
MessageHeader reqHeader;
reqHeader.Decode(reqRawHeader);
// Read protobuf packet
std::string reqData;
auto pSize = reqHeader.PacketSize();
reqData.resize(pSize);
ss.read(reqData.data(), pSize);
// Call handler
std::string resData;
handler->Handle(reqData, resData);
// Pack result
std::string resNetPacket;
MessageHeader resHeader(resData.size());
resNetPacket.append(resHeader.Encode());
resNetPacket.append(resData);
backss << resNetPacket;
auto size = backss.tellp();
return reqNetPacket.size();
}
std::expected<int, std::string> TestConnector::Read(std::string& resData, int size) {
resData.resize(size);
auto r = backss.readsome(resData.data(), size);
return r;
}
TestConnector::~TestConnector() {}
+27
View File
@@ -0,0 +1,27 @@
#ifndef FAKECLIENT_HPP
#define FAKECLIENT_HPP
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <sstream>
#include <memory>
#include <netclient.hpp>
#include <abrpchandler.hpp>
class TestConnector : public NetClient {
private:
AbstractRPCHandler* handler;
std::stringstream backss;
public:
TestConnector(AbstractRPCHandler& hand);
std::expected<int, std::string> Write(std::string payload) override;
std::expected<int, std::string> Read(std::string& buffer, int size) override;
~TestConnector(void);
};
#endif
+74
View File
@@ -0,0 +1,74 @@
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <sstream>
#include <netclient.hpp>
#include <abrpchandler.hpp>
#include <testconnect.hpp>
#include <msgheader.hpp>
#include <logger.hpp>
#include <control.pb.h>
class TestHandler : public AbstractRPCHandler {
public:
std::expected<void, std::string> Handle(std::string& req, std::string& res) override;
};
std::expected<void, std::string> TestHandler::Handle(std::string& rawReq, std::string& rawRes) {
control::HelloRequest pbReq;
pbReq.ParseFromString(rawReq);
std::cout << std::format("rpcName: {}\n", pbReq.meta().kind());
std::cout << std::format("req message: {}\n", pbReq.message());
control::HelloResult pbRes;
pbRes.set_message("Johnny!");
auto resMeta = pbRes.mutable_meta();
resMeta->set_error(false);
pbRes.SerializeToString(&rawRes);
return {};
}
int main(int argc, char** argv) {
TestHandler handler;
TestConnector conn(handler);
control::HelloRequest pbReq;
auto reqMeta = pbReq.mutable_meta();
reqMeta->set_kind("getHello");
pbReq.set_message("Whats your name?");
std::string rawReq;
pbReq.SerializeToString(&rawReq);
MessageHeader reqHeader(rawReq.size());
auto rawHeader = reqHeader.Encode();
std::string reqPacket;
reqPacket.append(rawHeader);
reqPacket.append(rawReq);
conn.Write(reqPacket);
// Read binary header
std::string resRawHeader;
const int rhSize = rpcHeaderSize;
auto rSize = conn.Read(resRawHeader, rhSize);
MessageHeader resHeader;
resHeader.Decode(resRawHeader);
auto pSize = resHeader.PacketSize();
std::string resData;
rSize = conn.Read(resData, pSize);
control::HelloResult pbRes;
pbRes.ParseFromString(resData);
std::cout << std::format("res message: {}\n", pbRes.message());
std::cout << std::format("error: {}\n", pbRes.meta().error());
}
+61
View File
@@ -0,0 +1,61 @@
extern "C" {
#include <netinet/ip.h>
#include <arpa/inet.h>
}
#include <expected>
#include <string>
#include <iostream>
#include <format>
#include <interface.hpp>
#include <tunclient.hpp>
std::expected<void, std::string> TClient::Create(const std::string name, const std::string addr, const int prefix) {
auto createRes = iface.Create(name);
if (!createRes) {
return std::unexpected(createRes.error());
}
auto setaddrRes = iface.SetIP4Address(addr);
if (!setaddrRes) {
return std::unexpected(setaddrRes.error());
}
auto setprefixRes = iface.SetIP4Netmask(24);
if (!setprefixRes) {
return std::unexpected(setprefixRes.error());
}
auto setmtuRes = iface.SetMTU(1240);
if (!setmtuRes) {
return std::unexpected(setmtuRes.error());
}
auto upRes = iface.Up();
if (!upRes) {
return std::unexpected(upRes.error());
}
return {};
}
std::expected<void, std::string> TClient::Run() {
while (true) {
auto readRes = iface.Read();
if (!readRes) {
std::cerr << std::format("Error: {}\n", readRes.error());
}
auto value = readRes.value();
std::cerr << std::format("Packet size: {}\n", value.size());
struct iphdr* iphdr = (struct iphdr*)(value.data());
struct in_addr src, dest;
src.s_addr = iphdr->saddr;
dest.s_addr = iphdr->daddr;
std::cout << "Source IP: " << inet_ntoa(src) << std::endl;
std::cout << "Dest IP: " << inet_ntoa(dest) << std::endl;
std::cout << "Protocol: " << (int)iphdr->protocol << std::endl;
}
return {};
}
+15
View File
@@ -0,0 +1,15 @@
#include <expected>
#include <string>
#include <cstring>
#include <interface.hpp>
#include <service.hpp>
class TClient {
private:
Interface iface;
public:
std::expected<void, std::string> Create(const std::string name, const std::string addr, const int prefix);
std::expected<void, std::string> Run();
};
+31
View File
@@ -0,0 +1,31 @@
#include <expected>
#include <string>
#include <chrono>
#include <cstring>
#include <thread>
#include <iostream>
#include <tunclient.hpp>
using namespace std::chrono_literals;
int main(int argc, char** argv) {
TClient cli;
auto createRes = cli.Create("tun10", "10.1.2.1", 30);
if (!createRes) {
std::cerr << "Error: " << createRes.error() << std::endl;
return 1;
}
auto runRes = cli.Run();
if (!runRes) {
std::cerr << "Error: " << runRes.error() << std::endl;
return 1;
}
//std::chrono::milliseconds timesleep(20s);
//std::this_thread::sleep_for(timesleep);
return 0;
}
+97
View File
@@ -0,0 +1,97 @@
extern "C" {
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <arpa/inet.h>
}
#include <cstring>
#include <expected>
#include <string>
#include <iostream>
#include <resolver.hpp>
#include <udpclient.hpp>
UDPClient::UDPClient(void) {
sockfd = 0;
rmax = 2024;
};
std::expected<void, std::string> UDPClient::Bind(std::string naddress, int nport) {
port = nport;
address = naddress;
struct sockaddr_in sa;
if (inet_pton(AF_INET, address.c_str(), &(sa.sin_addr)) == 1) {
family = AF_INET;
} else if (inet_pton(AF_INET6, address.c_str(), &(sa.sin_addr)) == 1) {
family = AF_INET6;
} else {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Incorrect address " + naddress);
}
if ((sockfd = socket(family, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create socket error: " + error);
}
return {};
}
std::expected<void, std::string> UDPClient::Send(std::string message) {
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = family;
servaddr.sin_port = htons(port);
servaddr.sin_addr.s_addr = inet_addr(address.c_str());
if (sendto(sockfd, message.data(), message.size(), 0,
(const struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Send datagram error: " + error);
}
return {};
}
std::expected<std::string, std::string> UDPClient::Recv() {
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = family;
servaddr.sin_port = htons(port);
servaddr.sin_addr.s_addr = inet_addr(address.c_str());
socklen_t len = sizeof(servaddr);
int rsize = 0;
std::string buffer(rmax, 0);
if((rsize = recvfrom(sockfd, buffer.data(), buffer.size(),
0, (struct sockaddr *)&servaddr, &len)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Receive datagram error: " + error);
}
std::string reply(buffer.begin(), buffer.begin() + rsize);
return reply;
}
void UDPClient::Close(void) {
if (sockfd > 0) {
close(sockfd);
sockfd = 0;
}
};
UDPClient::~UDPClient(void) {
if (sockfd > 0) {
close(sockfd);
}
};
+21
View File
@@ -0,0 +1,21 @@
#ifndef UPDCLIENT_HPP
#define UPDCLIENT_HPP
class UDPClient {
private:
int sockfd;
std::string address;
int port;
int rmax;
int family;
public:
UDPClient(void);
std::expected<void, std::string> Bind(std::string address, int port);
std::expected<void, std::string> Send(std::string buffer);
std::expected<std::string, std::string> Recv();
void Close(void);
~UDPClient(void);
};
#endif
+36
View File
@@ -0,0 +1,36 @@
#include <expected>
#include <iostream>
#include <format>
#include <udpclient.hpp>
#include <resolver.hpp>
int main(int argc, char** argv) {
UDPClient cli;
std::string message("Hello");
const std::string hostname("www.gnu.org");
Resolver resolver;
auto resolveRes = resolver.Resolve(hostname);
if (!resolveRes) {
auto msg = std::format("Cannot resolve hostname {}: {}", hostname, resolveRes.error());
std::cerr << std::format("Error: {}", msg) << std::endl;
return 1;
}
auto raddr = resolveRes.value();
auto address = raddr.GetAddress();
auto bindRes = cli.Bind(address, 1025);
if (!bindRes) {
std::cerr << std::format("Error: {}", bindRes.error()) << std::endl;
return 1;
}
auto sendRes = cli.Send(message);
if (!sendRes) {
std::cerr << std::format("Error: {}", sendRes.error()) << std::endl;
return 1;
}
return 0;
}