Compare commits

...

2 Commits

6 changed files with 260 additions and 17 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)
project(transm VERSION 1.3.2 LANGUAGES CXX)
project(transm VERSION 1.4.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

View File

@ -4,6 +4,7 @@
#include <iostream>
#include <of_path.h>
#include <of_str.h>
#include <of_util.h>
#include <version.h>
#ifdef USE_BOOST
@ -53,6 +54,16 @@ void CClient::run(const std::string& ip, const std::string& port, const std::str
{
fs::path fp(config_dir);
config_path_ = fp.append("history.txt").string();
fs::path fp2(config_dir);
uuid_path_ = fp2.append("uuid.txt").string();
save_uuid();
uuid_ = read_uuid();
if (uuid_.empty()) {
TLOGE("uuid is empty!");
return;
}
auto his = load_line_his();
for (const auto& cc : his) {
fc_add_his(cc.c_str());
@ -69,13 +80,7 @@ void CClient::run(const std::string& ip, const std::string& port, const std::str
std::thread thread([&]() { io_context_.run(); });
th_down_active_ = std::thread([&]() { judget_down_active(); });
{
auto* bf = new CFrameBuffer();
bf->type_ = TYPE_GET_ID;
send_frame(bf);
delete bf;
}
get_id();
if (ip == "127.0.0.1") {
get_task_list();
}
@ -83,7 +88,7 @@ void CClient::run(const std::string& ip, const std::string& port, const std::str
TLOGI("version: {}", VERSION_NUM);
TLOGI("opensource: {}", VERSION_URL);
TLOGW("SupportCmd ==>");
TLOGW("Get|Up|Down|Cancel|Update|Who|Where");
TLOGW("Get|Up|Down|Cancel|Update|Who|Where|Ls|Req");
fc_append('|');
while (1) {
@ -146,6 +151,14 @@ void CClient::run(const std::string& ip, const std::string& port, const std::str
up_task(param);
continue;
}
if (scmd == "Ls" || scmd == "ls") {
require_dir_files(param);
continue;
}
if (scmd == "Req" || scmd == "req") {
down_req_list(param);
continue;
}
TLOGE("No matched cmd, May be param size incorrect.");
}
client_->disconnect();
@ -377,12 +390,14 @@ bool CClient::down_one_file(const std::string& id, const std::string& file, cons
return false;
}
// 在这里补充 UUID
std::string uuid_file = uuid_ + "UUID" + file;
// 请求下载文件
std::shared_ptr<CFrameBuffer> buf = std::make_shared<CFrameBuffer>();
buf->type_ = TYPE_OPEN_FILE;
buf->tid_ = id;
buf->data_ = new char[file.size() + 1];
buf->len_ = std::snprintf(buf->data_, file.size() + 1, "%s", file.data());
buf->data_ = new char[uuid_file.size() + 1];
buf->len_ = std::snprintf(buf->data_, uuid_file.size() + 1, "%s", uuid_file.data());
if (!send_frame(buf.get())) {
TLOGE("{} request open file [{}] send failed.", __FUNCTION__, down_->cur_remote_file_);
down_->cur_remote_id_.clear();
@ -634,6 +649,96 @@ bool CClient::down_update_file(const std::map<std::string, std::string>& files)
return suc;
}
bool CClient::get_dir_files(const std::string& dir, std::string& out, std::string& error)
{
fs::path p(dir);
out.clear();
error.clear();
if (!fs::is_directory(p) || !fs::exists(p)) {
error = fmt::format("{} not a dir or not exist", p.string());
return false;
}
// F开头文件,D开头目录,使用前需要去除。
for (const auto& entry : fs::directory_iterator(p)) {
if (fs::is_directory(entry)) {
out += "D" + COfPath::standardize(entry.path().string()) + "\n";
} else {
out += "F" + COfPath::standardize(entry.path().string()) + "\n";
}
}
return true;
}
bool CClient::require_dir_files(const std::string& param)
{
auto tvec = COfStr::split(param, " ");
if (tvec.size() < 2) {
TLOGE("{} invalid param format [{}]", __FUNCTION__, param);
return false;
}
int index = std::stoi(tvec[0]);
std::string path = tvec[1];
if (!task_list_.count(index)) {
TLOGE("No Index Found {}.", index);
return false;
}
const auto& sr = task_list_[index];
std::shared_ptr<CFrameBuffer> buf = std::make_shared<CFrameBuffer>();
buf->type_ = TYPE_GET_DIRFILES;
buf->data_ = new char[path.size() + 1]();
buf->len_ = std::snprintf(buf->data_, path.size() + 1, "%s", path.c_str());
buf->tid_ = sr->id;
if (!send_frame(buf.get())) {
TLOGE("Send Failed {}", __LINE__);
return false;
}
return true;
}
bool CClient::down_req_list(const std::string& param)
{
auto tvec = COfStr::split(param, " ");
if (tvec.size() < 2) {
TLOGE("{} invalid param format [{}]", __FUNCTION__, param);
return false;
}
int index = std::stoi(tvec[0]);
std::string lists = tvec[1];
std::string local = tvec.size() > 2 ? COfPath::to_full(tvec[2]) : COfPath::to_full("");
if (!task_list_.count(index)) {
TLOGE("No Index Found {}.", index);
return false;
}
const auto& sr = task_list_[index];
if (sr->id == own_id_) {
TLOGE("Can't Req Self Task {}.", sr->id);
return false;
}
down_ = std::make_shared<TransInfomation>();
auto vec = COfStr::split(lists, "|");
for (const auto& item : vec) {
auto path = COfStr::trim(item);
if (path.empty()) {
continue;
}
// down_one_file的编码为 UTF8
#if _WIN32
path = CCodec::ansi_to_u8(path);
local = CCodec::ansi_to_u8(local);
#endif
if (!down_one_file(sr->id, path, local)) {
TLOGE("Down Failed {}", __LINE__);
return false;
}
}
return true;
}
bool CClient::send_frame(CFrameBuffer* buf)
{
char* out_buf{};
@ -699,6 +804,52 @@ std::vector<std::string> CClient::load_line_his()
return history;
}
bool CClient::save_uuid()
{
fs::path uuid_path(uuid_path_);
if (fs::exists(uuid_path)) {
return true;
}
std::ofstream out_file(uuid_path.string(), std::ios::out);
if (!out_file.is_open()) {
TLOGE("Open File Failed {}", uuid_path.string());
return false;
}
std::string uuid1 = OfUtil::get_uuid();
std::string uuid2 = OfUtil::get_uuid();
std::string uuid = uuid1 + "-" + uuid2;
out_file << uuid;
out_file.close();
return true;
}
std::string CClient::read_uuid()
{
fs::path uuid_path(uuid_path_);
if (!fs::exists(uuid_path)) {
return std::string();
}
std::ifstream in_file(uuid_path.string(), std::ios::in);
if (!in_file.is_open()) {
TLOGE("Open File Failed {}", uuid_path.string());
return false;
}
std::string uuid;
in_file >> uuid;
in_file.close();
return uuid;
}
void CClient::get_id()
{
auto* bf = new CFrameBuffer();
bf->type_ = TYPE_GET_ID;
bf->data_ = new char[uuid_.size() + 1];
bf->len_ = std::snprintf(bf->data_, uuid_.size() + 1, "%s", uuid_.c_str());
send_frame(bf);
delete bf;
}
void CClient::handle_frame(CFrameBuffer* buf)
{
if (buf == nullptr) {
@ -779,16 +930,94 @@ void CClient::handle_frame(CFrameBuffer* buf)
}
break;
}
case TYPE_GET_DIRFILES: {
std::string path(buf->data_, buf->len_);
#ifdef _WIN32
path = CCodec::u8_to_ansi(path);
#endif
TLOGI("Get Dir Files {}", path);
std::string err;
std::string out;
if (!get_dir_files(path, out, err)) {
TLOGE("Get Dir Files Failed. {}", err);
buf->type_ = TYPE_GET_DIRFILES_FAILED;
delete[] buf->data_;
buf->data_ = new char[err.size() + 1];
buf->len_ = std::snprintf(buf->data_, err.size() + 1, "%s", err.c_str());
} else {
#ifdef _WIN32
out = CCodec::ansi_to_u8(out);
#endif
buf->type_ = TYPE_GET_DIRFILES_DONE;
delete[] buf->data_;
buf->data_ = new char[out.size() + 1];
buf->len_ = std::snprintf(buf->data_, out.size() + 1, "%s", out.c_str());
}
std::swap(buf->tid_, buf->fid_);
if (!send_frame(buf)) {
TLOGE("Send Failed {}.", __LINE__);
break;
}
break;
}
case TYPE_GET_DIRFILES_FAILED: {
std::string err(buf->data_, buf->len_);
TLOGE("Get {} Dir Files Failed. {}", buf->fid_, err);
break;
}
case TYPE_GET_DIRFILES_DONE: {
std::string out(buf->data_, buf->len_);
#ifdef _WIN32
out = CCodec::u8_to_ansi(out);
#endif
auto vec = COfStr::split(out, "\n");
TLOGD("$$$$$$$$$ START $$$$$$$$$");
for (const auto& item : vec) {
std::string real = COfStr::trim(item);
if (real.empty()) {
continue;
}
if (real.find("D") == 0) {
real.erase(0, 1);
TLOGI("d=>{}", real);
} else if (real.find("F") == 0) {
real.erase(0, 1);
TLOGI("f=>{}", real);
} else {
TLOGE("Error Remote List Format {}", real);
}
}
TLOGD("$$$$$$$$$ OVER $$$$$$$$$");
break;
}
case TYPE_OPEN_FILE: {
std::string keys{};
{
std::lock_guard<std::mutex> lock(mutex_);
up_[buf->fid_] = std::make_shared<TransInfomation>();
std::string uuid_file = std::string(buf->data_, buf->len_);
#ifdef _WIN32
up_[buf->fid_]->cur_file_ = CCodec::u8_to_ansi(std::string(buf->data_, buf->len_));
#else
up_[buf->fid_]->cur_file_ = std::string(buf->data_, buf->len_);
uuid_file = CCodec::u8_to_ansi(uuid_file);
#endif
// 拿出 UUID
auto uuid_index = uuid_file.find("UUID");
if (uuid_index == std::string::npos) {
TLOGE("UUID Not Found.");
buf->type_ = TYPE_OPEN_FAILED;
std::swap(buf->tid_, buf->fid_);
if (!send_frame(buf)) {
TLOGE("Send Failed {}.", __LINE__);
}
break;
}
up_[buf->fid_]->cur_remote_uuid_ = uuid_file.substr(0, uuid_index);
uuid_file.erase(0, uuid_index + 4);
up_[buf->fid_]->cur_file_ = uuid_file;
// 这里做校验
if (up_[buf->fid_]->cur_remote_uuid_ == uuid_) {
}
up_[buf->fid_]->file_.open(up_[buf->fid_]->cur_file_, std::ios::in | std::ios::binary);
up_[buf->fid_]->trans_state_ = TRANS_REDAY;
if (!up_[buf->fid_]->file_.is_open()) {
@ -908,8 +1137,10 @@ void CClient::handle_frame(CFrameBuffer* buf)
down_->remote_plat = static_cast<uint16_t>(std::stoul(vec[0]));
}
cur_file_size_ = size;
break;
}
default:
TLOGE("UnSupport Type {}, Current Version v{}", static_cast<int>(buf->type_), VERSION_NUM);
break;
}
}

View File

@ -29,6 +29,7 @@ enum TransState {
struct TransInfomation {
std::string cur_remote_id_;
std::string cur_remote_file_;
std::string cur_remote_uuid_;
std::string cur_file_;
std::fstream file_{};
uint16_t permissions{};
@ -57,11 +58,17 @@ public:
bool request_update_list(const std::string& param);
bool check_update_list(const std::string& content, std::map<std::string, std::string>& files);
bool down_update_file(const std::map<std::string, std::string>& files);
bool get_dir_files(const std::string& dir, std::string& out, std::string& error);
bool require_dir_files(const std::string& param);
bool down_req_list(const std::string& param);
private:
bool send_frame(CFrameBuffer* buf);
void save_line_his(const std::string& input);
std::vector<std::string> load_line_his();
bool save_uuid();
std::string read_uuid();
void get_id();
private:
void handle_frame(CFrameBuffer* buf);
@ -96,6 +103,8 @@ private:
std::thread update_list_th_;
std::string own_id_{};
std::string config_path_{};
std::string uuid_path_{};
std::string uuid_{};
};
class CFileOpr

2
ofen

@ -1 +1 @@
Subproject commit a667080d96395792cd3c6066ef0ebe6c8b508bbe
Subproject commit f6bc83b0de92adb1d5f8de7f1235c1a222c6b84b

View File

@ -48,7 +48,7 @@ bool CTcpServer::start(unsigned short port)
asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port);
try {
acceptor_.open(endpoint.protocol());
//acceptor_.set_option(asio::socket_base::reuse_address(true));
// acceptor_.set_option(asio::socket_base::reuse_address(true));
acceptor_.bind(endpoint);
acceptor_.listen();
} catch (const asio::system_error& e) {

View File

@ -35,7 +35,10 @@ enum FrameType : int16_t {
TYPE_BUSY_UPDATE_LIST,
TYPE_FAILED_UPDATE_LIST,
TYPE_GET_ID,
TYPE_FILE_INFO
TYPE_FILE_INFO,
TYPE_GET_DIRFILES,
TYPE_GET_DIRFILES_DONE,
TYPE_GET_DIRFILES_FAILED,
};
using namespace ofen;