#pragma once #include #include #include #include #include #include using namespace std; struct SSHServer { string host; int port; string username; string password; }; class SSHUtil { private: static int _download_file(LIBSSH2_SESSION* session, const std::string& remote_path, const std::string& local_path, std::function progress_callback = nullptr) { LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session); if (!sftp_session) { throw string("Failed to init SFTP session!"); } // ´ò¿ªÔ¶³ÌÎļþ£¨Ö»¶Á£© LIBSSH2_SFTP_HANDLE* sftp_handle = libssh2_sftp_open(sftp_session, remote_path.c_str(), LIBSSH2_FXF_READ, 0); if (!sftp_handle) { throw string("Failed to open remote file : ").append(remote_path); libssh2_sftp_shutdown(sftp_session); return -1; } // »ñÈ¡Îļþ´óС LIBSSH2_SFTP_ATTRIBUTES attrs; if (libssh2_sftp_fstat(sftp_handle, &attrs)) { libssh2_sftp_close(sftp_handle); libssh2_sftp_shutdown(sftp_session); throw string("Unable to get file size"); } const long totalSize = attrs.filesize; // ´´½¨±¾µØÎļþ std::ofstream local_file(local_path, std::ios::binary); if (!local_file) { libssh2_sftp_close(sftp_handle); libssh2_sftp_shutdown(sftp_session); throw string("Failed to create local file: ").append(local_path); } // ¶ÁȡԶ³ÌÎļþ²¢Ð´Èë±¾µØ char buffer[32 * 1024]; long receivedSize = 0; try { while (true) { int rc = libssh2_sftp_read(sftp_handle, buffer, sizeof(buffer)); if (rc == LIBSSH2_ERROR_EAGAIN) { continue; } else if (rc <= 0) { break; // ÏÂÔØÍê³É»ò³ö´í } // дÈë±¾µØÎļþ local_file.write(buffer, rc); if (!local_file) { throw string("Failed to write to local file"); break; } // ¸üнø¶È receivedSize += rc; if (progress_callback) { progress_callback(receivedSize, totalSize); } } if (receivedSize != totalSize) { throw string("The download file sizes are not equal"); } } catch (string msg) { libssh2_sftp_close(sftp_handle); libssh2_sftp_shutdown(sftp_session); local_file.close(); throw msg; } // ¹Ø±Õ×ÊÔ´ libssh2_sftp_close(sftp_handle); libssh2_sftp_shutdown(sftp_session); local_file.close(); return 0; } static int _upload_file(LIBSSH2_SESSION* session, const std::string& local_path, const std::string& remote_path, std::function progress_callback = nullptr) { LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session); if (!sftp_session) { throw string("Failed to init SFTP session!"); } // ´ò¿ªÔ¶³ÌÎļþ£¨Ð´Èë + ´´½¨£© LIBSSH2_SFTP_HANDLE* sftp_handle = libssh2_sftp_open( sftp_session, remote_path.c_str(), LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC, LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR // ȨÏÞ: Óû§¿É¶Á¿Éд ); if (!sftp_handle) { libssh2_sftp_shutdown(sftp_session); throw string("Failed to open remote file:").append(remote_path); } // ´ò¿ª±¾µØÎļþ std::ifstream local_file(local_path, std::ios::binary | std::ios::ate); if (!local_file) { libssh2_sftp_close(sftp_handle); libssh2_sftp_shutdown(sftp_session); throw string("Failed to open local file : ").append(local_path); } // »ñÈ¡×ÜÎļþ´óС uint64_t file_size = local_file.tellg(); local_file.seekg(0, std::ios::beg); // ¶ÁÈ¡±¾µØÎļþ²¢Ð´ÈëÔ¶³Ì uint64_t transferred = 0; char buffer[1024 * 32]; try { while (!local_file.eof()) { local_file.read(buffer, sizeof(buffer)); ssize_t bytes_read = local_file.gcount(); if (bytes_read > 0) { ssize_t bytes_sent = 0; while (bytes_sent < bytes_read) { ssize_t rc = libssh2_sftp_write( sftp_handle, buffer + bytes_sent, bytes_read - bytes_sent ); if (rc < 0) { throw string("Upload error: ").append(local_path); break; } bytes_sent += rc; transferred += rc; if (progress_callback) { progress_callback(transferred, file_size); } } } } } catch (...) { libssh2_sftp_close(sftp_handle); libssh2_sftp_shutdown(sftp_session); local_file.close(); throw string("ÉÏ´«Îļþ³ö´í£¡"); } // ¹Ø±Õ×ÊÔ´ libssh2_sftp_close(sftp_handle); libssh2_sftp_shutdown(sftp_session); local_file.close(); return 0; } public: /** * Ö´ÐÐÃüÁî */ static void excuteCmd(string cmd, SSHServer server) { int port = server.port; libssh2_init(0); // ´´½¨socket int sock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(port); // ʹÓà inet_pton Ìæ´ú inet_addr if (inet_pton(AF_INET, server.host.c_str(), &sin.sin_addr) <= 0) { throw string("IPµØÖ·´íÎó£º").append(server.host); } if (connect(sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { throw string("Á¬½Óʧ°Ü£º").append(server.host); } // ´´½¨SSH»á»° LIBSSH2_SESSION* session = libssh2_session_init(); if (!session) { throw string("ÎÞ·¨´´½¨SSH»á»°£º").append(server.host); } // ÎÕÊÖ if (libssh2_session_handshake(session, sock)) { throw string("SSHÎÕÊÖʧ°Ü£º").append(server.host); } // ÈÏÖ¤ if (libssh2_userauth_password(session, server.username.c_str(), server.password.c_str())) { throw string("ÈÏ֤ʧ°Ü£º").append(server.host); } // Ö´ÐÐÃüÁî LIBSSH2_CHANNEL* channel = libssh2_channel_open_session(session); if (!channel) { throw string("ÎÞ·¨´ò¿ªÍ¨µÀ£º").append(server.host); } if (libssh2_channel_exec(channel, cmd.c_str())) { throw string("Ö´ÐÐÃüÁîʧ°Ü£º").append(server.host); } char buffer[1024]; int nbytes; while ((nbytes = libssh2_channel_read(channel, buffer, sizeof(buffer))) > 0) { std::cout.write(buffer, nbytes); } libssh2_channel_close(channel); libssh2_channel_free(channel); libssh2_session_disconnect(session, "Õý³£Í˳ö"); libssh2_session_free(session); closesocket(sock); } /* * ÏÂÔØÎļþ */ static void downloadFile(string remote_path,string local_path, SSHServer server, std::function progress_callback = nullptr) { int port = 22; libssh2_init(0); // ´´½¨socket int sock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(port); // ʹÓà inet_pton Ìæ´ú inet_addr if (inet_pton(AF_INET, server.host.c_str(), &sin.sin_addr) <= 0) { throw string("IPµØÖ·´íÎó").append(server.host); } if (connect(sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { throw string("Á¬½Óʧ°Ü").append(server.host); } // ´´½¨SSH»á»° LIBSSH2_SESSION* session = libssh2_session_init(); if (!session) { throw string("ÎÞ·¨´´½¨SSH»á»°").append(server.host); } // ÎÕÊÖ if (libssh2_session_handshake(session, sock)) { throw string("SSHÎÕÊÖʧ°Ü").append(server.host); } // ÈÏÖ¤ if (libssh2_userauth_password(session, server.username.c_str(), server.password.c_str())) { throw string("ÈÏ֤ʧ°Ü").append(server.host); } _download_file(session, remote_path, local_path, progress_callback); libssh2_session_disconnect(session, "Õý³£Í˳ö"); libssh2_session_free(session); closesocket(sock); } /** * ÉÏ´«Îļþ */ static void uploadFile(string remote_path, string local_path, SSHServer server, std::function progress_callback = nullptr) { int port = 22; libssh2_init(0); // ´´½¨socket int sock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(port); // ʹÓà inet_pton Ìæ´ú inet_addr if (inet_pton(AF_INET, server.host.c_str(), &sin.sin_addr) <= 0) { throw string("IPµØÖ·´íÎó£º").append(server.host); } if (connect(sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { throw string("Á¬½Óʧ°Ü£º").append(server.host); } // ´´½¨SSH»á»° LIBSSH2_SESSION* session = libssh2_session_init(); if (!session) { throw string("ÎÞ·¨´´½¨SSH»á»°£º").append(server.host); } // ÎÕÊÖ if (libssh2_session_handshake(session, sock)) { throw string("SSHÎÕÊÖʧ°Ü£º").append(server.host); } // ÈÏÖ¤ if (libssh2_userauth_password(session, server.username.c_str(), server.password.c_str())) { throw string("ÈÏ֤ʧ°Ü£º").append(server.host); } _upload_file(session, local_path, remote_path, progress_callback); libssh2_session_disconnect(session, "Õý³£Í˳ö"); libssh2_session_free(session); closesocket(sock); } };