tools/hexnet: Reimplement TCP server, implement TCP client

Both can only receive at the moment as we still don’t handle input.
Soda
BodgeMaster 2022-10-21 22:54:19 +02:00
parent ee0ebb273c
commit f681c54c82
1 changed files with 129 additions and 6 deletions

View File

@ -17,8 +17,12 @@
//If not, see https://www.gnu.org/licenses/agpl-3.0.en.html //If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#include <csignal> #include <csignal>
#include <iomanip>
#include <iostream> #include <iostream>
#include <mutex> #include <mutex>
#include <string>
#include <sockpp/tcp_acceptor.h>
#include <sockpp/tcp_connector.h>
#include <thread> #include <thread>
#include <vector> #include <vector>
@ -30,22 +34,57 @@
#define EXIT_USAGE 2 #define EXIT_USAGE 2
#define EXIT_UNIMPLEMENTED 3 #define EXIT_UNIMPLEMENTED 3
std::mutex mutexStdin; // TCP v4 server
std::mutex mutexStdout; sockpp::tcp_socket tcpSocket;
std::mutex mutexNetIncoming; sockpp::tcp_acceptor tcpAcceptor;
std::mutex mutexNetOutgoing; // TCP v4 client
sockpp::tcp_connector tcpConnector;
bool exitProgram = false;
bool ipv4 = false; bool ipv4 = false;
bool ipv6 = false; bool ipv6 = false;
bool tcp = false; bool tcp = false;
bool udp = false; bool udp = false;
bool outgoing = false;
std::string host;
in_port_t port;
void signalHandler(int signal) { void signalHandler(int signal) {
// shut down gracefully // shut down gracefully
std::cerr << "Received signal " << signal << ", shutting down." << std::endl; exitProgram = true;
// tell sockpp to close TCP socket if open because it blocks when trying
// to read and there is no data
tcpAcceptor.shutdown();
if (tcpSocket) {
tcpSocket.shutdown(SHUT_RD);
}
std::cerr << "Received signal " << signal << ", bye!" << std::endl;
std::exit(signal); std::exit(signal);
} }
void readFromTCPSocket() {
ssize_t byteCount;
uint8_t buffer[1536];
if (outgoing) {
while (!exitProgram && (byteCount = tcpConnector.read(buffer, sizeof(buffer))) > 0) {
for (ssize_t i=0; i<byteCount; i++) {
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) buffer[i] << " ";
}
std::cout.flush();
}
} else {
while (!exitProgram && (byteCount = tcpSocket.read(buffer, sizeof(buffer))) > 0) {
for (ssize_t i=0; i<byteCount; i++) {
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) buffer[i] << " ";
}
std::cout.flush();
}
}
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
std::signal(SIGINT, signalHandler); std::signal(SIGINT, signalHandler);
std::signal(SIGTERM, signalHandler); std::signal(SIGTERM, signalHandler);
@ -101,8 +140,92 @@ int main(int argc, char* argv[]) {
tcp = cliParser.getFlag("tcp").value; tcp = cliParser.getFlag("tcp").value;
udp = cliParser.getFlag("udp").value; udp = cliParser.getFlag("udp").value;
if (!(ipv4 || ipv6) || !(tcp || udp)) { if (cliParser.getOption("connect").errorCode != ErrorCodes::NOT_PRESENT) {
outgoing = true;
host = cliParser.getOption("connect").value;
}
if (!(ipv4 || ipv6) || (ipv4 && ipv6) || !(tcp || udp) || (tcp && udp)) {
std::cout << cliParser.getUsage() << std::endl; std::cout << cliParser.getUsage() << std::endl;
return EXIT_USAGE; return EXIT_USAGE;
} }
port = (in_port_t) std::stoi(cliParser.getArgument(0).value);
if (outgoing) {
if (tcp) {
std::cerr << "Connecting to " << host << " on port " << (int) port << " (TCP)..." << std::endl;
if (ipv4) {
// TCP v4 out
tcpConnector = sockpp::tcp_connector({host, port});
if (!tcpConnector) {
std::cerr << "Error connecting to " << host << " on port " << port << std::endl;
std::cerr << tcpConnector.last_error_str() << std::endl;
return EXIT_RUNTIME;
}
std::thread threadReadFromTCP = std::thread(readFromTCPSocket);
//std::thread threadWriteToTCP = std::thread(writeToTCPSocket);
threadReadFromTCP.join();
//threadWriteToTCP.join();
std::cout << std::endl;
return EXIT_SUCCESS;
} else {
// TCP v6 out
return EXIT_UNIMPLEMENTED;
}
} else {
std::cerr << "Connecting to " << host << " on port " << (int) port << " (UDP)..." << std::endl;
if (ipv4) {
// UDP v4 out
return EXIT_UNIMPLEMENTED;
} else {
// UDP v6 out
return EXIT_UNIMPLEMENTED;
}
}
} else {
if (tcp) {
std::cerr << "Listening on port " << (int) port << " (TCP)..." << std::endl;
if (ipv4) {
// TCP v4 in
tcpAcceptor = sockpp::tcp_acceptor(port);
if (!tcpAcceptor) {
std::cerr << "Error while creating TCP acceptor: " << tcpAcceptor.last_error_str() << std::endl;
return EXIT_RUNTIME;
}
sockpp::inet_address peer;
tcpSocket = tcpAcceptor.accept(&peer);
std::cerr << "Incoming connection from " << peer << std::endl;
if (!tcpSocket) {
std::cerr << "Error on incoming connection: " << tcpAcceptor.last_error_str() << std::endl;
return EXIT_RUNTIME;
}
std::thread threadReadFromTCP = std::thread(readFromTCPSocket);
//std::thread threadWriteToTCP = std::thread(writeToTCPSocket);
threadReadFromTCP.join();
//threadWriteToTCP.join();
std::cout << std::endl;
return EXIT_SUCCESS;
} else {
// TCP v6 in
return EXIT_UNIMPLEMENTED;
}
} else {
std::cerr << "Listening on port " << (int) port << " (UDP)..." << std::endl;
if (ipv4) {
// UDP v4 in
return EXIT_UNIMPLEMENTED;
} else {
// UDP v6 in
return EXIT_UNIMPLEMENTED;
}
}
}
} }