working commit
This commit is contained in:
@@ -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() {}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
#include <expected>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <interface.hpp>
|
||||
#include <service.hpp>
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
#include <expected>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <interface.hpp>
|
||||
#include <service.hpp>
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return 0;
|
||||
}
|
||||
@@ -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 {};
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
#include <expected>
|
||||
#include <vector>
|
||||
|
||||
#include <iprouter.hpp>
|
||||
|
||||
std::expected<Routes, std::string> Router::List() {
|
||||
std::vector<Route> routes;
|
||||
return routes;
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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 {};
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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<br>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 |
@@ -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 {};
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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 {};
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user