#include #include #include #include #include #include #include #include #include using namespace inaf::oasbo::ConnectionProtocols; TCPProtocol::TCPProtocol() { this->host = std::string("127.0.0.1:9003"); std::string port { }; split_ip_port(host, ip, port); this->port = std::stoi(port); this->srv_sock = -1; this->cli_sock = -1; } TCPProtocol::TCPProtocol(std::string ip, int prt) { this->host = std::string(ip).append(":").append(std::to_string(prt)); this->ip = ip; this->port = prt; this->srv_sock = -1; this->cli_sock = -1; } TCPProtocol::~TCPProtocol() { closeConnectionToClient(); closeConnectionToServer(); } int TCPProtocol::sendToServer(PacketLib::BasePacket &pack) { int val = ::send(cli_sock, pack.getBinaryPointer(), pack.getHeaderSize() + pack.getPayloadSize() + pack.getTailSize(), MSG_CONFIRM); return val; } int TCPProtocol::receiveFromClient(PacketLib::BasePacket &pack) { ssize_t headerSize = pack.getHeaderSize(); uint8_t *buff = new uint8_t[pack.getPacketStructureByteSize()]; ssize_t rec = ::recv(this->srv_sock, &buff[0], headerSize, MSG_WAITALL); if(rec == 0){ // connessione chiusa closeConnectionToClient(); delete buff; return 0; } if(rec != headerSize){ delete buff; return -1; } pack.copyToBinaryPointer(buff, headerSize); if(!pack.isRecognizedHeader()){ resetPacket(pack, headerSize); delete buff; return -1; } int to_be_rcv = pack.getPayloadSize() + pack.getTailSize(); rec += ::recv(this->srv_sock, &buff[headerSize],to_be_rcv, MSG_WAITALL); if(rec != to_be_rcv + headerSize){ resetPacket(pack, headerSize); delete buff; return -1; } pack.copyToBinaryPointer(&buff[headerSize], pack.getPayloadSize() + pack.getTailSize(), headerSize); delete buff; return rec; } int TCPProtocol::connectToClient() { return m_connectToCli(ip, port); } int TCPProtocol::connectToServer() { return m_connectToSrv(ip, port); } int TCPProtocol::closeConnectionToClient() { if (srv_sock != -1) { ::close(srv_sock); srv_sock = -1; } return 1; } int TCPProtocol::closeConnectionToServer() { if (cli_sock != -1) { ::close(cli_sock); cli_sock = -1; } return 1; } bool TCPProtocol::isConnectedToClient() const { return srv_sock > 0; } bool TCPProtocol::isConnectedToServer() const { return cli_sock > 0; } int TCPProtocol::m_connectToCli(std::string ip, int port) { std::cout << "Listening on: " << ip << ":" << port << std::endl; // Creating socket file descriptor if(srv_sock == -1){ if ((srv_sock = socket(AF_INET, SOCK_STREAM, 0)) == 0) { std::cerr << "socket failed" << std::endl;; return -1; } } struct sockaddr_in servaddr; servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = ::inet_addr(ip.c_str()); servaddr.sin_port = htons(port); if (bind(srv_sock, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0) { std::cerr << "TCP CONNECTION: Bind failed" << std::endl;; srv_sock = -1; return -1; } std::cout << "TCP CONNECTION: Waiting for connection" << std::endl; if (listen(srv_sock, 1) < 0) { std::cerr << "TCP CONNECTION: Listen error" << std::endl;; srv_sock = -1; return -1; } int newSocket; int addrlen = sizeof(servaddr); if ((newSocket = accept(srv_sock, (struct sockaddr*) &servaddr, (socklen_t*) &addrlen)) < 0) { std::cerr << "TCP CONNECTION: accept error" << std::endl;; srv_sock = -1; return -1; } ::close(srv_sock); std::cout << "TCP CONNECTION: Connected" << std::endl; srv_sock = newSocket; return srv_sock; } int TCPProtocol::m_connectToSrv(std::string ip, int port) { int sock = 0; struct sockaddr_in cli_addr; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { std::cerr << "TCP CONNECTION: Socket creation error" << std::endl;; this->cli_sock = -1; return -1; } cli_addr.sin_family = AF_INET; cli_addr.sin_port = htons(port); // Convert IPv4 and IPv6 addresses from text to binary form if (inet_pton(AF_INET, ip.c_str(), &cli_addr.sin_addr) <= 0) { std::cerr << "TCP CONNECTION: Invalid address/ Address not supported" << std::endl;; this->cli_sock = -1; return -1; } if (connect(sock, (struct sockaddr*) &cli_addr, sizeof(cli_addr)) < 0) { std::cerr << "TCP CONNECTION: Connection Failed " << std::endl;; this->cli_sock = -1; return -1; } std::cout << "Connected" << std::endl; this->cli_sock = sock; return cli_sock; } void TCPProtocol::split_ip_port(const std::string &ip_port, std::string &ip_address, std::string &port) { // Regex pattern to match IP address and port in the format "xxx.xxx.xxx.xxx:xxxx" std::regex pattern("^(\\d{1,3}\\.){3}\\d{1,3}:(\\d{1,5})$"); // Check if the input string matches the expected format if (!std::regex_match(ip_port, pattern)) { std::cerr << "Error: invalid IP address and port format: " << ip_port << std::endl; exit(EXIT_FAILURE); } // Split the input string into IP address and port int colon_pos = ip_port.find(":"); ip_address = ip_port.substr(0, colon_pos); port = ip_port.substr(colon_pos + 1); } void TCPProtocol::resetPacket(PacketLib::BasePacket &pack, int bytes) { uint8_t *buff = new uint8_t[bytes]; std::memset(buff, 0, bytes); int toBeReset = std::min(static_cast(pack.getPacketStructureByteSize()), bytes); pack.copyToBinaryPointer(buff, toBeReset); delete buff; } class TCPProtocol::Builder { protected: TCPProtocol *protocol; public: std::string ip_key{"ip"}; std::string port_key{"port"}; Builder() { this->reset(); } Builder(std::string ip, int port) { this->protocol = new TCPProtocol(ip, port); } ~Builder() { delete protocol; } void reset() { this->protocol = new TCPProtocol(); } Builder* configFrom(Configurators::BaseConfigurator *conf) { std::map params = conf->readConfig(); if (params.count(ip_key) > 0) protocol->ip = params[ip_key]; if (params.count(port_key) > 0) protocol->port = std::stoi(params[port_key]); return this; } Builder* setIp(std::string ip) { protocol->ip = ip; return this; } Builder* setPort(int port) { protocol->port = port; return this; } TCPProtocol* getProtocol() { TCPProtocol *result = this->protocol; this->reset(); return result; } };