#include #include #include #include #include #include #include #include #include #include using namespace inaf::oasbo::ConnectionProtocols; TCPProtocol::TCPProtocol() : TCPProtocol("localhost", 9003) { } TCPProtocol::TCPProtocol(std::string ip, int prt) : ip(ip), port(prt), srv_sock(-1), cli_sock(-1) { host = ip + ":" + std::to_string(port); memset(&cliaddr, 0, sizeof(cliaddr)); memset(&servaddr, 0, sizeof(servaddr)); } TCPProtocol::~TCPProtocol() { closeConnectionToClient(); ::close(srv_sock); } int TCPProtocol::receiveFromClient(PacketLib::BasePacket &pack) { ssize_t headerSize = pack.getHeaderSize(); uint8_t *buff = new uint8_t[pack.getPacketStructureByteSize()]; ssize_t rec = ::recv(this->cli_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->cli_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::closeConnectionToClient() { if (cli_sock != -1) { ::close(cli_sock); cli_sock = -1; } return 1; } bool TCPProtocol::isConnectedToClient() const { return cli_sock > 0; } int TCPProtocol::m_connectToCli(std::string ip, int port) { // Creating socket file descriptor if (srv_sock == -1) { // bind if ((srv_sock = socket(AF_INET, SOCK_STREAM, 0)) == 0) { time_t now = time(nullptr); std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") << "]\t[TCP Receiver]\t" << "TCP socket on " << host << " failed" << std::endl; exit(EXIT_FAILURE); } 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) { time_t now = time(nullptr); std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") << "]\t[TCP Receiver]\t" << "TCP CONNECTION on " << host << " Bind failed" << std::endl; srv_sock = -1; exit(EXIT_FAILURE); } } time_t now = time(nullptr); std::cout << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") << "]\t[TCP Receiver]\t" << "Waiting for connection on " << host << std::endl; if (listen(srv_sock, 1) < 0) { time_t now = time(nullptr); std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") << "]\t[TCP Receiver]\t" << "Listen error" << std::endl; srv_sock = -1; return -1; } socklen_t clientAddressSize = sizeof(cliaddr); if ((cli_sock = accept(srv_sock, (struct sockaddr*) &cliaddr, (socklen_t*) &clientAddressSize)) < 0) { time_t now = time(nullptr); std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") << "]\t[TCP Receiver]\t" << "accept error" << std::endl; cli_sock = -1; return -1; } now = time(nullptr); std::cout << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") << "]\t[TCP Receiver]\t" << "Connected with " << inet_ntoa(cliaddr.sin_addr) << std::endl; return cli_sock; } 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; } std::string TCPProtocol::getHost() { return ip + ":" + std::to_string(port); } void TCPProtocol::setHost(std::string host) { std::string ip = { }; int port = 0; if (split_ip_port(host, ip, port)) { setIp(ip); setPort(port); } else { time_t now = time(nullptr); std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") <<"]\t[TCP Receiver]\t" << "invalid IP address and port format: " << host << std::endl; } } void TCPProtocol::setIp(std::string ip) { std::regex pattern("^[\\w.-]+$"); // Check if the input string matches the expected format bool ok = true; if (!std::regex_match(ip, pattern)) { time_t now = time(nullptr); std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") <<"]\t[TCP Receiver]\t"<< "invalid IP address: " << ip << ", setting to localhost" << std::endl; ok = false; this->ip = std::string("localhost"); } if (ok) this->ip = ip; this->host = this->ip + ":" + std::to_string(port); } void TCPProtocol::setPort(int port) { if (port > 1023 && port < 65535) this->port = port; else { time_t now = time(nullptr); std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S") <<"]\t[TCP Receiver]\t" << "invalid port: " << port << ", setting to 9003" << std::endl; this->port = 9003; } this->host = this->ip + ":" + std::to_string(this->port); } bool TCPProtocol::split_ip_port(const std::string &ip_port, std::string &ip_address, int &port) { // Regex pattern to match IP address and port in the format "xxx.xxx.xxx.xxx:xxxx" std::regex pattern("^[\\w.-]+:(\\d{1,5})$"); // Check if the input string matches the expected format if (!std::regex_match(ip_port, pattern)) { return false; } // Split the input string into IP address and port int colon_pos = ip_port.find(":"); ip_address = ip_port.substr(0, colon_pos); port = std::stoi(ip_port.substr(colon_pos + 1)); return true; }