extern "C" { #include #include #include #include #include #include #include } #include #include #include #include #include #include #include #include #include #include #include #include using namespace std::chrono_literals; UxClient::UxClient() { sock = 0; family = 0; } std::expected UxClient::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"); } #ifdef CLI_TIMEOUT struct timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout) < 0) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Set timeout error: {}", error)); } if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof timeout) < 0) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Set send timeout error: {}", error)); } #endif if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Connect error: {}", error)); } return {}; } void UxClient::RecvMessages(void) { while (true) { int rsize = 0; std::string rawHeader(msgHeaderSize, 0); if ((rsize = recv(sock, rawHeader.data(), rawHeader.size(), MSG_WAITALL)) < 0) { int errnoCopy = errno; uxlogger.Log(std::format("Read0 header error: {}", errno)); std::string error = std::strerror(errnoCopy); uxlogger.Log(std::format("Read header error: {}", error)); break; } if (rsize < msgHeaderSize) { uxlogger.Log(std::format("Read only {} from {} bytes", rsize, msgHeaderSize)); break; } MessageHeader header; auto decodeRes = header.Decode(rawHeader); if (!decodeRes) { uxlogger.Log(std::format("Decode header error: {}", decodeRes.error())); } auto pSize = header.PayloadSize(); uxlogger.Log(std::format("Receive message with size {}", pSize)); if (pSize == 0) { continue; } std::string rawMessage(pSize, 0); if ((rsize = recv(sock, rawMessage.data(), rawMessage.size(), MSG_WAITALL)) < 0) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); uxlogger.Log(std::format("Read message error: {}", error)); break; } uxcontrol::SimpleMessage meta; meta.ParseFromString(rawMessage); auto metaPart = meta.meta(); auto kind = metaPart.kind(); uxlogger.Debug(std::format("Receive message with call {}", kind)); if (kind == tunAddressMsg) { uxcontrol::AddressMessage addrMessage; addrMessage.ParseFromString(rawMessage); uxlogger.Debug(std::format("Receive address {}", addrMessage.address())); uxlogger.Debug(std::format("Receive prefix {}", addrMessage.prefix())); auto setAddrRes = interface.SetIP4Address(addrMessage.address()); if (!setAddrRes) { uxlogger.Error(setAddrRes.error()); } auto setMaskRes = interface.SetIP4Netmask(addrMessage.prefix()); if (!setMaskRes) { uxlogger.Error(setMaskRes.error()); } } else { uxlogger.Warning("Received unknown kind of message"); } } done.release(); return; } void UxClient::SendMessages(void) { while (true) { std::this_thread::sleep_for(std::chrono::seconds(10)); continue; auto readRes = interface.Read(); if (!readRes) { uxlogger.Log(std::format("Read packet error: {}", readRes.error())); } auto packet = readRes.value(); uxcontrol::PacketMessage intPacket; auto meta = intPacket.mutable_meta(); meta->set_kind(internetPkgMsg); intPacket.set_payload(packet); std::string rawMessage; intPacket.SerializeToString(&rawMessage); MessageHeader header(rawMessage.size()); auto rawHeader = header.Encode(); std::string rawPacket; rawPacket.append(rawHeader); rawPacket.append(rawMessage); int wsize = 0; if ((wsize = send(sock, rawPacket.data(), rawPacket.size(), 0)) < 0) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); uxlogger.Log(std::format("Write packet error: {}", error)); break; } uxlogger.Log("Send message"); } done.release(); return; } std::expected UxClient::Run(void) { auto createRes = interface.Create("uxcli0"); if (!createRes) { return std::unexpected(createRes.error()); } auto setMTURes = interface.SetMTU(1280); if (!setMTURes) { return std::unexpected(setMTURes.error()); } auto upRes = interface.Up(); if (!createRes) { return std::unexpected(createRes.error()); } /* Router router; auto addRouteRes = router.AddRoute("1.1.1.2", 32, "10.1.1.2"); if (!addRouteRes) { return std::unexpected(addRouteRes.error()); } */ std::thread sendThr(&UxClient::SendMessages, this); sendThr.detach(); std::thread recvThr(&UxClient::RecvMessages, this); recvThr.detach(); done.acquire(); uxlogger.Log("Client done"); return {}; } UxClient::~UxClient() { if (sock != 0) { close(sock); } }