//network_utils.cpp #include "network_utils.h" #include #include #include #include #include #include #include "protocol_utils.h" int sendData(int sockfd, const std::vector &data) { ssize_t sent = send(sockfd, data.data(), data.size(), 0); if (sent < 0) { perror("Error sending data"); return ERROR_SENDING_DATA; } return SUCCESS; } int receiveData(int sockfd, std::vector &buffer) { buffer.resize(1024); ssize_t bytesReceived = recv(sockfd, buffer.data(), buffer.size(), 0); if (bytesReceived < 0) { perror("Error receiving data"); return ERROR_RECEIVING_DATA; } buffer.resize(bytesReceived); return SUCCESS; } std::string pingMinecraftServer(const std::string &hostname, int port, const std::string &virtualHostname, int virtualPort, int protocolVersionIn, int nextStateIn) { struct addrinfo hints{}, *res, *result; int sockfd, err; (void) memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; err = getaddrinfo(hostname.c_str(), std::to_string(port).c_str(), &hints, &result); if (err != 0) { std::cerr << "Error resolving hostname: " << gai_strerror(err) << std::endl; return "ERROR_RESOLVING_HOSTNAME"; } for (res = result; res != nullptr; res = res->ai_next) { sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd == -1) continue; // Set timeouts struct timeval timeout; timeout.tv_sec = 5; // 5 seconds timeout timeout.tv_usec = 0; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *) &timeout, sizeof(timeout)); setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char *) &timeout, sizeof(timeout)); if (connect(sockfd, res->ai_addr, res->ai_addrlen) != -1) break; (void) close(sockfd); } if (res == nullptr) { freeaddrinfo(result); return "ERROR_CONNECTION_FAILED"; } freeaddrinfo(result); // Handshake std::vector packet; packet.push_back(0x00U); // Packet ID for handshake std::vector protocolVersion = encodeVarint(protocolVersionIn); std::vector serverAddress = encodeString(virtualHostname); std::vector serverPort = {static_cast((virtualPort >> 8) & 0xFF), static_cast(virtualPort & 0xFFU)}; std::vector nextState = encodeVarint(nextStateIn); (void) packet.insert(packet.end(), protocolVersion.begin(), protocolVersion.end()); (void) packet.insert(packet.end(), serverAddress.begin(), serverAddress.end()); (void) packet.insert(packet.end(), serverPort.begin(), serverPort.end()); (void) packet.insert(packet.end(), nextState.begin(), nextState.end()); std::vector handshakeLength = encodeVarint(packet.size()); (void) packet.insert(packet.begin(), handshakeLength.begin(), handshakeLength.end()); if (sendData(sockfd, packet) != SUCCESS) { (void) close(sockfd); return "ERROR_SENDING_DATA"; } // Status request std::vector statusRequest = {0x01U, 0x00U}; // Packet length and Packet ID for status request if (sendData(sockfd, statusRequest) != SUCCESS) { (void) close(sockfd); return "ERROR_SENDING_DATA"; } // Read status response std::vector response; if (receiveData(sockfd, response) != SUCCESS) { (void) close(sockfd); return "ERROR_RECEIVING_DATA"; } // Extract JSON string (assuming it starts from the position of the first '{' found in the response) auto pos = std::find(response.begin(), response.end(), '{'); if (pos != response.end()) { std::string json(pos, response.end()); std::cout << json << std::endl; (void) close(sockfd); return json; } else { (void) close(sockfd); return "ERROR_JSON"; } }