From 0a58d9b21852c9155985c386582f782eb2ebb0d3 Mon Sep 17 00:00:00 2001
From: taynpg <taynpg@163.com>
Date: Mon, 7 Apr 2025 17:28:50 +0800
Subject: [PATCH] =?UTF-8?q?level1:=20uudi=E6=94=B9=E9=80=A0=E9=98=B6?=
 =?UTF-8?q?=E6=AE=B5=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 client/client.cpp |  29 ++++----
 client/client.h   |   1 +
 server/server.cpp |  36 +++++++---
 server/server.h   |   3 +-
 util/util.cpp     | 166 +++++++++++++++++++++++++++++++++++++++++++++-
 util/util.h       |  28 ++++++--
 6 files changed, 235 insertions(+), 28 deletions(-)

diff --git a/client/client.cpp b/client/client.cpp
index b18e45a..5d84621 100644
--- a/client/client.cpp
+++ b/client/client.cpp
@@ -259,15 +259,14 @@ bool CClient::up_task(const std::string& param)
         return false;
     }
 
-#ifdef _WIN32
-    msg = CCodec::ansi_to_u8(msg);
-#endif
+    CMessageInfo msg_info;
+    msg_info.uuid = uuid_;
+    msg_info.str = msg;
 
     std::shared_ptr<CFrameBuffer> buf = std::make_shared<CFrameBuffer>();
     buf->type_ = TYPE_UP_LIST;
-    buf->data_ = new char[msg.size() + 1];
-    std::memset(buf->data_, 0x0, msg.size() + 1);
-    buf->len_ = std::snprintf(buf->data_, msg.size() + 1, "%s", msg.data());
+
+    serialize(msg_info, &buf->data_, buf->len_);
     return send_frame(buf.get());
 }
 
@@ -844,8 +843,9 @@ 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());
+    CMessageInfo msg_info;
+    msg_info.uuid = uuid_;
+    serialize(msg_info, &bf->data_, bf->len_);
     send_frame(bf);
     delete bf;
 }
@@ -864,8 +864,12 @@ void CClient::handle_frame(CFrameBuffer* buf)
     }
     case TYPE_GET_LIST: {
         task_list_.clear();
-        std::string source(buf->data_, buf->len_);
-        auto vec = COfStr::split(source, "\n");
+        CMessageInfo msg_info;
+        if (!deserialize(buf->data_, buf->len_, msg_info)) {
+            TLOGE("{} GetList deserialize failed.", __LINE__);
+            break;
+        }
+        auto vec = COfStr::split(msg_info.str, "\n");
         int index = -1;
         size_t num = 0;
         for (const auto& item : vec) {
@@ -875,11 +879,7 @@ void CClient::handle_frame(CFrameBuffer* buf)
             }
             if (real.find('[') == std::string::npos) {
                 if (num < 20) {
-#ifdef _WIN32
-                    TLOGI("FILE ==> {}", CCodec::u8_to_ansi(real));
-#else
                     TLOGI("FILE ==> {}", real);
-#endif
                 }
                 task_list_[index]->files.push_back(real);
                 ++num;
@@ -898,6 +898,7 @@ void CClient::handle_frame(CFrameBuffer* buf)
                 if (!task_list_.count(index)) {
                     task_list_[index] = std::make_shared<DownClientInfo>();
                     task_list_[index]->id = id;
+                    task_list_[index]->uuid = msg_info.uuid;
                 }
                 if (num < 20) {
                     TLOGD("============================================");
diff --git a/client/client.h b/client/client.h
index 540648f..9b652e2 100644
--- a/client/client.h
+++ b/client/client.h
@@ -15,6 +15,7 @@
 using namespace ofen;
 struct DownClientInfo {
     std::vector<std::string> files;
+    std::string uuid;
     std::string id;
 };
 
diff --git a/server/server.cpp b/server/server.cpp
index e2f831b..1e75016 100644
--- a/server/server.cpp
+++ b/server/server.cpp
@@ -90,9 +90,8 @@ std::vector<TaskList> CTcpServer::get_clients()
     return result;
 }
 
-void CTcpServer::get_client_list(CFrameBuffer** buf)
+void CTcpServer::get_client_list(CMessageInfo& msg_info)
 {
-    CFrameBuffer* tbuf = *buf;
     auto vec = get_clients();
     std::string msg;
     int index = 1;
@@ -105,9 +104,7 @@ void CTcpServer::get_client_list(CFrameBuffer** buf)
         msg.append("\n");
         ++index;
     }
-    tbuf->data_ = new char[msg.size() + 1];
-    std::memset(tbuf->data_, 0x0, msg.size() + 1);
-    tbuf->len_ = std::snprintf(tbuf->data_, msg.size() + 1, "%s", msg.data());
+    msg_info.str = msg;
 }
 
 void CTcpServer::trans_data(CFrameBuffer* buf)
@@ -128,16 +125,26 @@ void CTcpServer::trans_data(CFrameBuffer* buf)
     switch (buf->type_) {
     case TYPE_GET_LIST: {
         TLOGI("[{}] GetList.", buf->fid_);
-        get_client_list(&buf);
+        CMessageInfo msg_info;
+        get_client_list(msg_info);
+        if (fcli) {
+            msg_info.uuid = fcli->uuid;
+        }
+        serialize(msg_info, &buf->data_, buf->len_);
         if (fcli && !send_frame(fcli->socket_, buf)) {
             TLOGE("GetList send failed.");
         }
         break;
     }
     case TYPE_UP_LIST: {
-        std::string file_list = std::string(buf->data_, buf->len_);
+        CMessageInfo msg_info;
+        if (!deserialize(buf->data_, buf->len_, msg_info)) {
+            TLOGE("{} GetList deserialize failed.", __LINE__);
+            break;
+        }
         if (fcli) {
-            fcli->task_ = file_list;
+            fcli->task_ = msg_info.str;
+            fcli->uuid = msg_info.uuid;
             fcli->task_time_ = OfUtil::now_time();
         }
         break;
@@ -287,6 +294,19 @@ void CTcpServer::th_client(const std::shared_ptr<asio::ip::tcp::socket>& socket,
                         delete frame;
                         continue;
                     }
+                    if (frame->type_ == TYPE_GET_ID) {
+                        CMessageInfo msg_info;
+                        if (!deserialize(frame->data_, frame->len_, msg_info)) {
+                            TLOGE("{} GetId deserialize failed.", __LINE__);
+                            delete frame;
+                            continue;
+                        }
+                        std::unique_lock<std::shared_mutex> lock(cli_mut_);
+                        if (client_map_.count(client_key)) {
+                            auto& cli = client_map_[client_key];
+                            cli->uuid = msg_info.uuid;
+                        }
+                    }
                     frame->fid_ = client_key;
                     // 直接转发,不加入缓存。
                     trans_data(frame);
diff --git a/server/server.h b/server/server.h
index 0b8e04e..9f1dd5e 100644
--- a/server/server.h
+++ b/server/server.h
@@ -16,6 +16,7 @@ struct ClientCache {
     CMutBuffer buffer_{};
     std::array<char, g_BuffSize> tmp_buf_{};
     std::string task_{};
+    std::string uuid{};
     std::string task_time_{};
     std::string online_time_{};
     high_c last_active_time_;
@@ -40,7 +41,7 @@ public:
 
 private:
     std::vector<TaskList> get_clients();
-    void get_client_list(CFrameBuffer** buf);
+    void get_client_list(CMessageInfo& msg_info);
 
 private:
     void trans_data(CFrameBuffer* buf);
diff --git a/util/util.cpp b/util/util.cpp
index 09163b9..c893ff6 100644
--- a/util/util.cpp
+++ b/util/util.cpp
@@ -1,6 +1,8 @@
 #include "util.h"
+
 #include <cstdint>
 #include <iostream>
+#include <of_util.h>
 #include <thread>
 
 CTransProtocal::CTransProtocal() = default;
@@ -127,4 +129,166 @@ CFrameBuffer::~CFrameBuffer()
 {
     delete[] data_;
     len_ = 0;
-}
\ No newline at end of file
+}
+
+void serialize(const CMessageInfo& msg_info, char** out_buf, int& len)
+{
+    CMessageInfo info(msg_info);
+    info.cmd = localtou8(info.cmd);
+    info.uuid = localtou8(info.uuid);
+    info.str = localtou8(info.str);
+    info.o = localtou8(info.o);
+
+    // 计算总长度
+    len = sizeof(int) * 4 + info.cmd.size() + info.uuid.size() + info.str.size() + info.o.size();
+    *out_buf = new char[len];   // 分配内存(调用方负责释放)
+
+    char* ptr = *out_buf;
+
+    // 序列化 cmd
+    int cmd_size = static_cast<int>(info.cmd.size());
+    memcpy(ptr, &cmd_size, sizeof(int));
+    ptr += sizeof(int);
+    memcpy(ptr, info.cmd.data(), cmd_size);
+    ptr += cmd_size;
+
+    // 序列化 uuid
+    int uuid_size = static_cast<int>(info.uuid.size());
+    memcpy(ptr, &uuid_size, sizeof(int));
+    ptr += sizeof(int);
+    memcpy(ptr, info.uuid.data(), uuid_size);
+    ptr += uuid_size;
+
+    // 序列化 str
+    int str_size = static_cast<int>(info.str.size());
+    memcpy(ptr, &str_size, sizeof(int));
+    ptr += sizeof(int);
+    memcpy(ptr, info.str.data(), str_size);
+    ptr += str_size;
+
+    // 序列化 o
+    int o_size = static_cast<int>(info.o.size());
+    memcpy(ptr, &o_size, sizeof(int));
+    ptr += sizeof(int);
+    memcpy(ptr, info.o.data(), o_size);
+}
+
+bool deserialize(const char* data, int len, CMessageInfo& msg_info)
+{
+    CMessageInfo info;
+    const char* ptr = data;
+    int remaining = len;
+
+    // 反序列化 cmd
+    if (remaining < static_cast<int>(sizeof(int))) {
+        return false;
+    }
+
+    int cmd_size;
+    memcpy(&cmd_size, ptr, sizeof(int));
+    ptr += sizeof(int);
+    remaining -= sizeof(int);
+    if (remaining < cmd_size) {
+        return false;
+    }
+
+    info.cmd.assign(ptr, cmd_size);
+    ptr += cmd_size;
+    remaining -= cmd_size;
+
+    // 反序列化 uuid
+    if (remaining < static_cast<int>(sizeof(int))) {
+        return false;
+    }
+
+    int uuid_size;
+    memcpy(&uuid_size, ptr, sizeof(int));
+    ptr += sizeof(int);
+    remaining -= sizeof(int);
+    if (remaining < uuid_size) {
+        return false;
+    }
+
+    info.uuid.assign(ptr, uuid_size);
+    ptr += uuid_size;
+    remaining -= uuid_size;
+
+    // 反序列化 str
+    if (remaining < static_cast<int>(sizeof(int))) {
+        return false;
+    }
+
+    int str_size;
+    memcpy(&str_size, ptr, sizeof(int));
+    ptr += sizeof(int);
+    remaining -= sizeof(int);
+    if (remaining < str_size) {
+        return false;
+    }
+
+    info.str.assign(ptr, str_size);
+    ptr += str_size;
+    remaining -= str_size;
+
+    // 反序列化 o
+    if (remaining < static_cast<int>(sizeof(int))) {
+        return false;
+    }
+    int o_size;
+    memcpy(&o_size, ptr, sizeof(int));
+    ptr += sizeof(int);
+    remaining -= sizeof(int);
+    if (remaining < o_size) {
+        return false;
+    }
+    info.o.assign(ptr, o_size);
+
+    info.cmd = u8tolocal(info.cmd);
+    info.uuid = u8tolocal(info.uuid);
+    info.str = u8tolocal(info.str);
+    info.o = u8tolocal(info.o);
+    msg_info = info;
+
+    return true;
+}
+
+std::string u8tolocal(const std::string& str)
+{
+#ifdef _WIN32
+    return CCodec::u8_to_ansi(str);
+#else
+    return str;
+#endif
+}
+
+std::string localtou8(const std::string& str)
+{
+#ifdef _WIN32
+    return CCodec::ansi_to_u8(str);
+#else
+    return str;
+#endif
+}
+
+CMessageInfo::CMessageInfo(const CMessageInfo& info)
+{
+    if (&info == this) {
+        return;
+    }
+    cmd = info.cmd;
+    uuid = info.uuid;
+    str = info.str;
+    o = info.o;
+}
+
+CMessageInfo& CMessageInfo::operator=(const CMessageInfo& info)
+{
+    if (&info == this) {
+        return *this;
+    }
+    cmd = info.cmd;
+    uuid = info.uuid;
+    str = info.str;
+    o = info.o;
+    return *this;
+}
diff --git a/util/util.h b/util/util.h
index f954288..c6027fe 100644
--- a/util/util.h
+++ b/util/util.h
@@ -41,6 +41,22 @@ enum FrameType : int16_t {
     TYPE_GET_DIRFILES_FAILED,
 };
 
+// 此结构体成员顺序不可变动,涉及到序列化反序列化。
+struct CMessageInfo {
+    CMessageInfo() = default;
+    CMessageInfo(const CMessageInfo& info);
+    CMessageInfo& operator=(const CMessageInfo& info);
+    std::string cmd;
+    std::string uuid;
+    std::string str;
+    std::string o;
+};
+
+void serialize(const CMessageInfo& msg_info, char** out_buf, int& len);
+bool deserialize(const char* data, int len, CMessageInfo& msg_info);
+std::string u8tolocal(const std::string& str);
+std::string localtou8(const std::string& str);
+
 using namespace ofen;
 class CFrameBuffer
 {
@@ -99,27 +115,31 @@ inline std::string now_str()
 template <typename... Args> void TLOGI(const std::string& format, Args&&... args)
 {
     fc_lock_print();
-    std::cout << ConsoleColor::Green << fmt::format(now_str() + format, std::forward<Args>(args)...) << std::endl;
+    std::cout << ConsoleColor::Green << fmt::format(now_str() + format, std::forward<Args>(args)...)
+              << std::endl;
     fc_unlock_print();
 }
 
 template <typename... Args> void TLOGW(const std::string& format, Args&&... args)
 {
     fc_lock_print();
-    std::cout << ConsoleColor::Yellow << fmt::format(now_str() + format, std::forward<Args>(args)...) << std::endl;
+    std::cout << ConsoleColor::Yellow << fmt::format(now_str() + format, std::forward<Args>(args)...)
+              << std::endl;
     fc_unlock_print();
 }
 
 template <typename... Args> void TLOGE(const std::string& format, Args&&... args)
 {
     fc_lock_print();
-    std::cout << ConsoleColor::Red << fmt::format(now_str() + format, std::forward<Args>(args)...) << std::endl;
+    std::cout << ConsoleColor::Red << fmt::format(now_str() + format, std::forward<Args>(args)...)
+              << std::endl;
     fc_unlock_print();
 }
 
 template <typename... Args> void TLOGD(const std::string& format, Args&&... args)
 {
     fc_lock_print();
-    std::cout << ConsoleColor::Cyan << fmt::format(now_str() + format, std::forward<Args>(args)...) << std::endl;
+    std::cout << ConsoleColor::Cyan << fmt::format(now_str() + format, std::forward<Args>(args)...)
+              << std::endl;
     fc_unlock_print();
 }
\ No newline at end of file