#include #include #include #include #include #include #include #include #include #include using namespace inaf::oasbo::ConnectionProtocols; UDPProtocol::UDPProtocol() { 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; memset(&cliaddr, 0, sizeof(cliaddr)); memset(&srvaddr, 0, sizeof(srvaddr)); // Filling server information srvaddr.sin_family = AF_INET; // IPv4 srvaddr.sin_addr.s_addr = inet_addr(ip.c_str()); srvaddr.sin_port = htons(this->port); } UDPProtocol::UDPProtocol(std::string ip, int port) { this->host = std::string(ip).append(":").append(std::to_string(port)); this->ip = ip; this->port = port; this->srv_sock = -1; this->cli_sock = -1; memset(&cliaddr, 0, sizeof(cliaddr)); memset(&srvaddr, 0, sizeof(srvaddr)); // Filling server information srvaddr.sin_family = AF_INET; // IPv4 srvaddr.sin_addr.s_addr = inet_addr(ip.c_str()); srvaddr.sin_port = htons(this->port); } UDPProtocol::~UDPProtocol() { closeConnectionToClient(); closeConnectionToServer(); } int UDPProtocol::sendToServer(PacketLib::BasePacket &pack) { int val = ::sendto(cli_sock, pack.getBinaryPointer(), pack.getHeaderSize() + pack.getPayloadSize() + pack.getTailSize(), MSG_CONFIRM, (struct sockaddr*) &srvaddr, sizeof(srvaddr)); return val; } int UDPProtocol::receiveHeader(PacketLib::BasePacket &pack) { size_t bytercv = 0; uint8_t *buff = new uint8_t[pack.getPacketSize()]; socklen_t len = sizeof(cliaddr); while (bytercv < pack.getHeaderSize()) { int rcv = recvfrom(srv_sock, &buff[bytercv], pack.getPacketSize(), MSG_WAITFORONE, (struct sockaddr*) &cliaddr, &len); if (rcv < 0) { delete buff; return -1; }else{ bytercv+=rcv; } } pack.copyToBinaryPointer(buff, bytercv); delete buff; return bytercv; } int UDPProtocol::receivePayloadAndTail(PacketLib::BasePacket &pack, int offset) { int toBeReceived = pack.getHeaderSize() + pack.getPayloadSize() + pack.getTailSize() - offset; uint8_t *buff = new uint8_t[toBeReceived]; int bytercv = 0; socklen_t len = sizeof(cliaddr); while (bytercv < toBeReceived) { bytercv += recvfrom(srv_sock, &buff[bytercv], pack.getPacketSize(), MSG_WAITFORONE, (struct sockaddr*) &cliaddr, &len); if (bytercv < 0) { delete buff; resetPacket(pack, toBeReceived); return -1; } } if (bytercv != toBeReceived) { delete buff; resetPacket(pack, bytercv); return -1; } else { pack.copyToBinaryPointer(buff, toBeReceived); delete buff; return bytercv; } } void UDPProtocol::resetPacket(PacketLib::BasePacket &pack, int bytes) { uint8_t *buff = new uint8_t[bytes]; std::memset(buff, 0, bytes); pack.copyToBinaryPointer(buff, bytes); delete buff; } int UDPProtocol::receiveFromClient(PacketLib::BasePacket &pack) { bool done = false; int bytercv = 0; while (!done) { bytercv = receiveHeader(pack); if (!isHeaderWellFormed(pack)) { // Reset all resetPacket(pack, bytercv); } else { int payloadSize = receivePayloadAndTail(pack, bytercv); if(payloadSize < 0){ resetPacket(pack, pack.getPacketSize()); } else{ bytercv += payloadSize; done = true; } } } return bytercv; } int UDPProtocol::connectToClient() { int sockfd; // Creating socket file descriptor if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket creation failed"); return -1; } // Set timeout to the socket struct timeval tv; tv.tv_sec = std::numeric_limits::max(); tv.tv_usec = 0; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &tv, sizeof tv); // Bind the socket with the server address if (bind(sockfd, (const struct sockaddr*) &srvaddr, sizeof(srvaddr)) < 0) { perror("bind failed"); return -1; } this->srv_sock = sockfd; return sockfd; } int UDPProtocol::connectToServer() { int sockfd = 0; // Creating socket file descriptor if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } printf("Connection made\n"); this->cli_sock = sockfd; return sockfd; } int UDPProtocol::closeConnectionToClient() { if (srv_sock != -1) { ::close(srv_sock); srv_sock = -1; } return 1; } int UDPProtocol::closeConnectionToServer() { if (cli_sock != -1) { ::close(cli_sock); cli_sock = -1; } return 1; } bool UDPProtocol::isConnectedToClient() const { return srv_sock != -1; } bool UDPProtocol::isConnectedToServer() const { return cli_sock != -1; } bool UDPProtocol::isHeaderWellFormed(PacketLib::BasePacket &pack) { return true; } void UDPProtocol::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); }