diff --git a/client/client.cpp b/client/client.cpp index bf1c98c..7c6f323 100644 --- a/client/client.cpp +++ b/client/client.cpp @@ -5,7 +5,6 @@ #include #include #include -#include namespace fs = std::filesystem; CClient::CClient(const std::shared_ptr& logger) : logger_(logger) @@ -51,7 +50,7 @@ void CClient::run(const std::string& ip, const std::string& port) client_->async_recv(); hearts_ = std::thread([&]() { hearts(); }); std::thread thread([&]() { io_context_.run(); }); - logger_->warn("SupportCmd:Get|Up|Down|Cancel"); + logger_->warn("SupportCmd:Get|Up|Down|Cancel|Update(list.txt)"); char line[512]{}; while (std::cin.getline(line, 512)) { @@ -65,23 +64,22 @@ void CClient::run(const std::string& ip, const std::string& port) std::this_thread::sleep_for(std::chrono::milliseconds(10)); break; } - auto vec = COfStr::split(cmd_input, " "); - if (vec.size() < 1) { - logger_->error("input's invalid format."); - continue; - } - std::string cmd{}; - std::string param{}; - if (vec.size() == 1) { - cmd = vec[0]; - } else { - cmd = vec[0]; - param = vec[1]; - } - if (cmd == "Get") { + if (cmd_input == "Get") { get_task_list(); continue; } + if (cmd_input == "Cancel") { + cancel_task(); + continue; + } + auto vec = COfStr::split(cmd_input, " "); + if (vec.size() < 2) { + logger_->error("input's invalid format."); + continue; + } + std::string cmd = vec[0]; + std::string param = vec[1]; + if (cmd == "Down") { down_task(vec[1]); continue; @@ -90,8 +88,8 @@ void CClient::run(const std::string& ip, const std::string& port) up_task(cmd_input); continue; } - if (cmd == "Cancel") { - cancel_task(); + if (cmd == "Update") { + request_update_list("list.txt", std::stoi(param)); continue; } logger_->error("No matched cmd."); @@ -192,7 +190,7 @@ bool CClient::cancel_task() return send_frame(buf.get()); } -bool CClient::down_one_file(const std::string& id, const std::string& file) +bool CClient::down_one_file(const std::string& id, const std::string& file, const std::string& local_dir) { down_->cur_remote_id_ = id; #ifdef _WIN32 @@ -202,7 +200,13 @@ bool CClient::down_one_file(const std::string& id, const std::string& file) #endif fs::path remote_file(ofen::COfPath::normalize(down_->cur_remote_file_)); - down_->cur_file_ = COfPath::to_full(remote_file.filename().string()); + + if (local_dir.empty()) { + down_->cur_file_ = COfPath::to_full(remote_file.filename().string()); + } else { + down_->cur_file_ = fs::path(local_dir).append(remote_file.filename().string()).string(); + } + logger_->warn("Start Down => {} To {}", down_->cur_remote_file_, down_->cur_file_); down_->file_ = fopen(down_->cur_file_.c_str(), "wb"); if (down_->file_ == nullptr) { @@ -217,7 +221,7 @@ bool CClient::down_one_file(const std::string& id, const std::string& file) buf->data_ = new char[file.size() + 1]; buf->len_ = std::snprintf(buf->data_, file.size() + 1, "%s", file.data()); if (!send_frame(buf.get())) { - logger_->error("{} request open file [{}] send failed.", __FUNCTION__, file); + logger_->error("{} request open file [{}] send failed.", __FUNCTION__, down_->cur_remote_file_); down_->cur_remote_id_.clear(); down_->cur_remote_file_.clear(); return false; @@ -270,12 +274,20 @@ void CClient::report_trans_ret(TransState state, const std::string& key) 功能为,请求某个客户端,更新我所列出的文件,右侧是远端需要存储的目录(必须存在,不存在则不理会) */ -bool CClient::request_update_list(const std::string& list_file) +bool CClient::request_update_list(const std::string& list_file, int index) { + if (downloading_) { + logger_->warn("Have Task Downloading, Please wait....."); + return false; + } + if (!task_list_.count(index)) { + logger_->error("No Index Found {}.", index); + return false; + } // 读取list文件 - std::ifstream in(list_file); + std::ifstream in(COfPath::to_full(list_file)); if (!in.is_open()) { - logger_->error("Can't Open File:{}", list_file); + logger_->error("Can't Open File:{}", COfPath::to_full(list_file)); return false; } std::istreambuf_iterator iterf(in); @@ -283,15 +295,15 @@ bool CClient::request_update_list(const std::string& list_file) std::string content(iterf, iter); in.close(); - std::regex rg(R"()"); // 校验格式是否正确 auto vec = COfStr::split(content, "\n"); - bool valid = false; + bool valid = true; std::string handled_content; for (const auto& item : vec) { std::string hitem = COfStr::trim(item); - if (std::regex_match(hitem, rg)) { - handled_content.append(handled_content + "\n"); + auto v = COfStr::split(hitem, "|"); + if (v.size() >= 2) { + handled_content.append(hitem + "\n"); continue; } valid = false; @@ -302,23 +314,66 @@ bool CClient::request_update_list(const std::string& list_file) logger_->error("Judge List File {} Format Not Passed.", list_file); return false; } + list_file_ = list_file; std::shared_ptr buf = std::make_shared(); buf->type_ = TYPE_REQUEST_UPDATE_LIST; buf->data_ = new char[handled_content.size() + 1](); buf->len_ = std::snprintf(buf->data_, handled_content.size() + 1, "%s", handled_content.c_str()); + buf->tid_ = task_list_[index]->id; - return false; + if (!send_frame(buf.get())) { + logger_->error("Send Failed {}", __LINE__); + return false; + } + return true; } bool CClient::check_update_list(const std::string& content, std::map& files) { - return false; + auto vec = COfStr::split(content, "\n"); + bool valid = true; + for (const auto& item : vec) { + if (item.empty()) { + continue; + } + auto vi = COfStr::split(item, "|"); + if (vi.size() != 2) { + logger_->error("Size not 2 {}", item); + valid = true; + break; + } + if (!fs::exists(vi[1])) { + valid = false; + logger_->error("Not exist {}", vi[1]); + break; + } + files[vi[0]] = vi[1]; + } + return valid; } -bool CClient::down_update_file(std::map& files) +bool CClient::down_update_file(std::map files) { - return false; + std::shared_ptr buf = std::make_shared(); + buf->tid_ = list_serve_id_; + down_ = std::make_shared(); + bool suc = true; + for (const auto& item : files) { + if (!down_one_file(list_serve_id_, item.first, item.second)) { + suc = false; + break; + } + } + if (suc) { + buf->type_ = TYPE_DONE_UPDATE_LIST; + logger_->info("Do Task From {} Done!", buf->tid_); + } else { + buf->type_ = TYPE_FAILED_UPDATE_LIST; + logger_->info("Do Task From {} Failed!", buf->tid_); + } + send_frame(buf.get()); + return suc; } bool CClient::send_frame(CFrameBuffer* buf) @@ -345,6 +400,10 @@ void CClient::handle_frame(CFrameBuffer* buf) return; } switch (buf->type_) { + case TYPE_GET_ID: { + logger_->debug("Your ID:{}", buf->tid_); + break; + } case TYPE_GET_LIST: { task_list_.clear(); std::string source(buf->data_, buf->len_); @@ -456,8 +515,12 @@ void CClient::handle_frame(CFrameBuffer* buf) logger_->error("Send Failed {}.", __LINE__); break; } - list_serve_id_ = buf->fid_; - + list_serve_id_ = buf->tid_; + logger_->debug("Do Task From {}.", buf->tid_); + if (update_list_th_.joinable()) { + update_list_th_.join(); + } + update_list_th_ = std::thread([this, files]() { down_update_file(files); }); break; } case TYPE_CONFIRM_UPDATE_LIST: { diff --git a/client/client.h b/client/client.h index 6e65253..24f0c64 100644 --- a/client/client.h +++ b/client/client.h @@ -44,11 +44,11 @@ public: bool down_task(const std::string& param); bool up_task(const std::string& cmd); bool cancel_task(); - bool down_one_file(const std::string& id, const std::string& file); + bool down_one_file(const std::string& id, const std::string& file, const std::string& local_dir = ""); void report_trans_ret(TransState state, const std::string& key = ""); - bool request_update_list(const std::string& list_file); + bool request_update_list(const std::string& list_file, int index); bool check_update_list(const std::string& content, std::map& files); - bool down_update_file(std::map& files); + bool down_update_file(std::map files); private: bool send_frame(CFrameBuffer* buf); @@ -81,4 +81,5 @@ private: std::string update_list_content_; std::string list_file_; std::string list_serve_id_; + std::thread update_list_th_; }; \ No newline at end of file diff --git a/server/server.cpp b/server/server.cpp index 721397d..5884b6f 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -138,19 +138,12 @@ void CTcpServer::trans_data(CFrameBuffer* buf) } break; } - // 两边发送OPEN - case TYPE_OPEN_FILE: - case TYPE_TRANS_DONE: - case TYPE_TRANS_FILE: { + default: if (check_double(buf, fcli, tcli) && tcli && !send_frame(tcli->socket_, buf)) { logger_->error("Send from {} to {} failed Or One Offline.", buf->fid_, buf->tid_); } break; } - default: - logger_->warn("No Mathched type. {}", static_cast(buf->type_)); - break; - } } bool CTcpServer::check_double(CFrameBuffer* buf, std::shared_ptr& fcli, @@ -240,6 +233,12 @@ void CTcpServer::th_client(std::shared_ptr socket, const cache = client_map_[client_key]; } + auto* f = new CFrameBuffer(); + f->type_ = TYPE_GET_ID; + f->tid_ = client_key; + send_frame(socket, f); + delete f; + while (true) { asio::error_code error; size_t length = socket->read_some(asio::buffer(cache->tmp_buf_), error); diff --git a/util/util.h b/util/util.h index 1bbfbaf..065f0b7 100644 --- a/util/util.h +++ b/util/util.h @@ -27,7 +27,8 @@ enum FrameType : int16_t { TYPE_CONFIRM_UPDATE_LIST, TYPE_UNCONFIRM_UPDATE_LIST, TYPE_DONE_UPDATE_LIST, - TYPE_FAILED_UPDATE_LIST + TYPE_FAILED_UPDATE_LIST, + TYPE_GET_ID }; using namespace ofen;