tools/hexnet: Implement ipv6 support.

BodgeMaster-unfinished
Shwoomple 2022-08-11 22:55:12 +05:30
parent ebcf436a18
commit e0648720bb
1 changed files with 122 additions and 41 deletions

View File

@ -19,6 +19,7 @@
#include <cstdint> #include <cstdint>
#include <cctype> #include <cctype>
#include <sockpp/tcp_acceptor.h> #include <sockpp/tcp_acceptor.h>
#include <sockpp/tcp6_acceptor.h>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <csignal> #include <csignal>
@ -40,8 +41,11 @@ int64_t mtu = 1500;
std::string host; std::string host;
in_port_t port; in_port_t port;
sockpp::tcp_socket* tcpSocket; sockpp::tcp_socket* tcpSocket;
sockpp::tcp6_socket* tcp6Socket;
sockpp::tcp_acceptor tcpAcceptor; sockpp::tcp_acceptor tcpAcceptor;
sockpp::tcp6_acceptor tcp6Acceptor;
std::mutex tcpSocketMutex; std::mutex tcpSocketMutex;
std::mutex tcp6SocketMutex;
std::mutex consoleMutex; std::mutex consoleMutex;
// used for coordinated graceful exit across threads // used for coordinated graceful exit across threads
bool exitProgram = false; bool exitProgram = false;
@ -50,12 +54,20 @@ void signalHandler(int signal) {
exitProgram = true; exitProgram = true;
// if still waiting for incoming connection, stop waiting // if still waiting for incoming connection, stop waiting
tcpAcceptor.shutdown(); tcpAcceptor.shutdown();
tcp6Acceptor.shutdown();
// tell sockpp to close TCP socket if open because it blocks when trying // tell sockpp to close TCP socket if open because it blocks when trying
// to read and there is no data // to read and there is no data
if (*tcpSocket) {
if (tcpSocket != nullptr && *tcpSocket) {
// Intentionally not using the mutex here // Intentionally not using the mutex here
std::cout << "test\n";
tcpSocket->shutdown(SHUT_RD); tcpSocket->shutdown(SHUT_RD);
} }
if (tcp6Socket != nullptr && *tcp6Socket) {
// Intentionally not using the mutex here
tcp6Socket->shutdown(SHUT_RD);
}
//TODO: figure out if - and how - this applies to UDP //TODO: figure out if - and how - this applies to UDP
// Priority is to finish up all unfinished business that can be finished up. // Priority is to finish up all unfinished business that can be finished up.
@ -64,32 +76,71 @@ void signalHandler(int signal) {
consoleMutex.lock(); consoleMutex.lock();
std::cerr << "Received signal " << signal << ", shutting down." << std::endl; std::cerr << "Received signal " << signal << ", shutting down." << std::endl;
consoleMutex.unlock(); consoleMutex.unlock();
std::exit(signal);
} }
void readFromTCPSocket(sockpp::tcp_socket* socket, int64_t mtu) { void readFromTCPSocket(sockpp::tcp_socket* socket, int64_t mtu) {
ssize_t numBytes; ssize_t numBytes;
uint8_t buffer[mtu]; uint8_t buffer[mtu];
tcpSocketMutex.lock(); tcpSocketMutex.lock();
while (!exitProgram && (numBytes = socket->read(buffer, sizeof(buffer))) > 0) { while (!exitProgram && (numBytes = socket->read(buffer, sizeof(buffer))) > 0) {
tcpSocketMutex.unlock();
consoleMutex.lock();
for (ssize_t i=0; i<numBytes; i++) {
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) buffer[i];
}
std::cout.flush();
consoleMutex.unlock();
tcpSocketMutex.lock();
}
tcpSocketMutex.unlock(); tcpSocketMutex.unlock();
consoleMutex.lock(); consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl; for (ssize_t i=0; i<numBytes; i++) {
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) buffer[i];
}
std::cout.flush();
consoleMutex.unlock(); consoleMutex.unlock();
tcpSocketMutex.lock();
}
tcpSocketMutex.unlock();
consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl;
consoleMutex.unlock();
}
void readFromTCP6Socket(sockpp::tcp6_socket* socket, int64_t mtu){
ssize_t numBytes;
uint8_t buffer[mtu];
tcp6SocketMutex.lock();
while (!exitProgram && (numBytes = socket->read(buffer, sizeof(buffer))) > 0) {
tcp6SocketMutex.unlock();
consoleMutex.lock();
for (ssize_t i=0; i<numBytes; i++) {
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) buffer[i];
}
std::cout.flush();
consoleMutex.unlock();
tcp6SocketMutex.lock();
}
tcp6SocketMutex.unlock();
consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl;
consoleMutex.unlock();
}
void writeToTCPSocket(sockpp::tcp_socket* socket){
while (!exitProgram) {
//TODO: Implement locking/unlocking/threading shenanigans
}
consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl;
consoleMutex.unlock();
}
void writeToTCP6Socket(sockpp::tcp6_socket* socket){
while (!exitProgram) {
//TODO: Implement locking/unlocking/threading shenanigans
}
consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl;
consoleMutex.unlock();
} }
int main(int argc, char* argv[]){ int main(int argc, char* argv[]){
signal(SIGINT, signalHandler); std::signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler); std::signal(SIGTERM, signalHandler);
std::vector<CLI::Flag> flags; std::vector<CLI::Flag> flags;
flags.push_back(CLI::Flag('4', "ipv4", "use IPv4, defaults to both when -4 and -6 are omitted, otherwise uses what is specified")); flags.push_back(CLI::Flag('4', "ipv4", "use IPv4, defaults to both when -4 and -6 are omitted, otherwise uses what is specified"));
@ -140,42 +191,72 @@ int main(int argc, char* argv[]){
port = (in_port_t) std::stoi(cliParser.getArgument(0).value); port = (in_port_t) std::stoi(cliParser.getArgument(0).value);
if (listenMode) { if (listenMode) {
if (ipv6) {
std::cerr << "IPv6 support is not implented yet." << std::endl;
return EXIT_UNIMPLEMENTED;
}
if (udp) { if (udp) {
std::cerr << "UDP support is not implemented yet." << std::endl; std::cerr << "UDP support is not implemented yet." << std::endl;
return EXIT_UNIMPLEMENTED; return EXIT_UNIMPLEMENTED;
} }
std::cerr << "Listening on port " << port << "." << std::endl;
sockpp::socket_initializer socketInitializer; if (ipv6) {
tcpAcceptor = sockpp::tcp_acceptor(port); //std::cerr << "IPv6 support is not implented yet." << std::endl;
//return EXIT_UNIMPLEMENTED;
std::cerr << "Listening on port " << port << "." << std::endl;
sockpp::socket_initializer socketInitializer;
tcp6Acceptor = sockpp::tcp6_acceptor(port);
if (!tcpAcceptor) { if(!tcp6Acceptor){
std::cerr << "Error while creating TCP acceptor: " << tcpAcceptor.last_error_str() << std::endl; std::cerr << "Error while creating TCP6 acceptor: " << tcp6Acceptor.last_error_str() << std::endl;
return EXIT_RUNTIME; return EXIT_RUNTIME;
}
sockpp::inet6_address peer;
tcp6Socket = new sockpp::tcp6_socket();
*tcp6Socket = tcp6Acceptor.accept(&peer);
std::cerr << "Incoming connection from " << peer << std::endl;
if (!(*tcp6Socket)) {
std::cerr << "Error on incoming connection: " << tcp6Acceptor.last_error_str() << std::endl;
delete tcp6Socket;
return EXIT_RUNTIME;
}
std::thread threadReadFromTCP6 = std::thread(readFromTCP6Socket, tcp6Socket, mtu);
threadReadFromTCP6.join();
delete tcp6Socket;
return EXIT_SUCCESS;
} }
sockpp::inet_address peer; if(ipv4){
tcpSocket = new sockpp::tcp_socket(); std::cerr << "Listening on port " << port << "." << std::endl;
*tcpSocket = tcpAcceptor.accept(&peer);
std::cerr << "Incoming connection from " << peer << std::endl; sockpp::socket_initializer socketInitializer;
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 = new sockpp::tcp_socket();
*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;
delete tcpSocket;
return EXIT_RUNTIME;
}
std::thread threadReadFromTCP = std::thread(readFromTCPSocket, tcpSocket, mtu);
threadReadFromTCP.join();
if (!(*tcpSocket)) {
std::cerr << "Error on incoming connection: " << tcpAcceptor.last_error_str() << std::endl;
delete tcpSocket; delete tcpSocket;
return EXIT_RUNTIME; return EXIT_SUCCESS;
} }
std::thread threadReadTCP = std::thread(readFromTCPSocket, tcpSocket, mtu);
threadReadTCP.join();
delete tcpSocket;
return EXIT_SUCCESS;
} else { } else {
std::cerr << "Client mode is not implemented yet." << std::endl; std::cerr << "Client mode is not implemented yet." << std::endl;
return EXIT_UNIMPLEMENTED; return EXIT_UNIMPLEMENTED;