debug:初步基本的通讯调试。

This commit is contained in:
taynpg 2025-05-11 21:27:59 +08:00
parent af648087bf
commit 43aedf6f08
19 changed files with 287 additions and 110 deletions

View File

@ -3,7 +3,16 @@
ClientCore::ClientCore() ClientCore::ClientCore()
{ {
socket_ = std::make_shared<wxSocketClient>(); socket_ = new wxSocketClient();
}
ClientCore::~ClientCore()
{
Disconnect();
thRun_ = false;
if (recvThread_.joinable()) {
recvThread_.join();
}
} }
bool ClientCore::Connect(const wxString& host, uint16_t port) bool ClientCore::Connect(const wxString& host, uint16_t port)
@ -13,27 +22,45 @@ bool ClientCore::Connect(const wxString& host, uint16_t port)
addr.Service(port); addr.Service(port);
socket_->SetEventHandler(*this, wxID_ANY); socket_->SetEventHandler(*this, wxID_ANY);
socket_->SetNotify(wxSOCKET_INPUT | wxSOCKET_LOST_FLAG); socket_->SetNotify(wxSOCKET_LOST_FLAG);
socket_->Notify(true);
socket_->SetFlags(wxSOCKET_BLOCK); socket_->SetFlags(wxSOCKET_BLOCK);
socket_->Notify(true);
if (!socket_->Connect(addr)) { if (!socket_->Connect(addr)) {
return false; return false;
} }
Bind(wxEVT_SOCKET, &ClientCore::OnSocketEvent, this);
recvThread_ = std::thread(&ClientCore::Recv, this);
return true; return true;
} }
void ClientCore::Disconnect() void ClientCore::Disconnect()
{ {
socket_->Destroy();
} }
bool ClientCore::GetOnlineList(InfoClientVec& infoClientVec) wxString ClientCore::GetErr() const
{
return err_;
}
void ClientCore::SetLogCallback(const std::function<void(const wxString&)>& callback)
{
logCall_ = callback;
}
bool ClientCore::ReqOnline()
{ {
InfoCommunicate infoCommunicate; InfoCommunicate infoCommunicate;
if (!Send<InfoCommunicate>(infoCommunicate, FBT_SER_MSG_ASKCLIENTS)) { if (!Send<InfoCommunicate>(infoCommunicate, FBT_SER_MSG_ASKCLIENTS)) {
return false; return false;
} }
return false; return true;
}
void ClientCore::ReqOnlineCallback(const std::function<void(const InfoClientVec&)>& callback)
{
onlineCallback_ = callback;
} }
bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec) bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec)
@ -44,33 +71,14 @@ bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileI
void ClientCore::OnSocketEvent(wxSocketEvent& event) void ClientCore::OnSocketEvent(wxSocketEvent& event)
{ {
auto* sock = event.GetSocket(); auto* sock = event.GetSocket();
switch (event.GetSocketEvent()) { auto type = event.GetSocketEvent();
case wxSOCKET_CONNECTION: { switch (type) {
wxLogMessage(_("Client connected."));
break;
}
case wxSOCKET_INPUT: {
sock->Read(buf_.data(), GBUFFER_SIZE);
auto size = sock->LastCount();
if (size > 0) {
buffer_.Push(buf_.data(), size);
while (thRun_) {
auto* frame = Communicate::ParseBuffer(buffer_);
if (!frame) {
break;
}
UseFrame(frame);
delete frame;
}
} else {
wxLogError(_("Read error: %s"), sock->LastError());
}
break;
}
case wxSOCKET_LOST: { case wxSOCKET_LOST: {
logCall_(wxString::Format(_("Lost connection to server.")));
break; break;
} }
default: default:
logCall_(wxString::Format(_T("No Handled Type: %d."), static_cast<int>(type)));
break; break;
} }
} }
@ -83,6 +91,21 @@ void ClientCore::UseFrame(FrameBuffer* buf)
InfoClientVec vec; InfoClientVec vec;
ZeroCopyInput input(buf->dataMut, buf->len); ZeroCopyInput input(buf->dataMut, buf->len);
input.archive() >> vec; input.archive() >> vec;
if (onlineCallback_) {
onlineCallback_(vec);
}
break;
}
case FBT_SER_MSG_YOURID: {
InfoCommunicate info;
ZeroCopyInput input(buf->dataMut, buf->len);
input.archive() >> info;
id_ = wxString::FromUTF8(info.data);
logCall_(wxString::Format(_("Your id is %s."), id_));
break;
}
case FBT_SER_MSG_RESPONSE: {
InfoCommunicate info;
break; break;
} }
default: default:
@ -94,6 +117,23 @@ void ClientCore::HeartBeat()
{ {
} }
void ClientCore::Recv()
{
while (thRun_) {
socket_->Read(buf_.data(), GBUFFER_SIZE);
auto len = socket_->LastCount();
buffer_.Push(buf_.data(), len);
while (true) {
auto* frame = Communicate::ParseBuffer(buffer_);
if (frame == nullptr) {
break;
}
UseFrame(frame);
delete frame;
}
}
}
bool ClientCore::Send(FrameBuffer* buf) bool ClientCore::Send(FrameBuffer* buf)
{ {
if (buf == nullptr) { if (buf == nullptr) {

View File

@ -8,6 +8,8 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <thread>
#include <functional>
#include <wx/socket.h> #include <wx/socket.h>
#include <Communicate.h> #include <Communicate.h>
@ -17,13 +19,18 @@ class ClientCore : public wxEvtHandler
{ {
public: public:
ClientCore(); ClientCore();
~ClientCore();
public: public:
bool Connect(const wxString& host, uint16_t port); bool Connect(const wxString& host, uint16_t port);
void Disconnect(); void Disconnect();
public: public:
bool GetOnlineList(InfoClientVec& infoClientVec); wxString GetErr() const;
void SetLogCallback(const std::function<void(const wxString&)>& callback);
bool ReqOnline();
void ReqOnlineCallback(const std::function<void(const InfoClientVec&)>& callback);
bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec); bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec);
private: private:
@ -34,6 +41,7 @@ private:
private: private:
void HeartBeat(); void HeartBeat();
void Recv();
template <typename T> bool Send(const T& info, FrameBufferType type) template <typename T> bool Send(const T& info, FrameBufferType type)
{ {
std::stringstream ss; std::stringstream ss;
@ -53,9 +61,14 @@ private:
wxString id_; wxString id_;
bool thRun_; bool thRun_;
MutBuffer buffer_; MutBuffer buffer_;
wxString err_;
std::thread recvThread_;
std::array<char, GBUFFER_SIZE> buf_; std::array<char, GBUFFER_SIZE> buf_;
std::shared_ptr<wxSocketClient> socket_; wxSocketClient* socket_;
std::shared_ptr<wxThread> heartsThread_;
private:
std::function<void(const InfoClientVec&)> onlineCallback_;
std::function<void(const wxString&)> logCall_;
}; };
#endif // CLIENTCORE_H #endif // CLIENTCORE_H

View File

@ -9,14 +9,12 @@
constexpr int GBUFFER_SIZE = 256; constexpr int GBUFFER_SIZE = 256;
struct InfoCommunicate { struct InfoCommunicate {
std::string fromID;
std::string toID;
std::string UUID; std::string UUID;
std::string data; std::string data;
uint8_t mark{}; uint8_t mark{};
template <class Archive> void serialize(Archive& archive) template <class Archive> void serialize(Archive& archive)
{ {
archive(CEREAL_NVP(fromID), CEREAL_NVP(toID), CEREAL_NVP(UUID), CEREAL_NVP(data), CEREAL_NVP(mark)); archive(CEREAL_NVP(UUID), CEREAL_NVP(data), CEREAL_NVP(mark));
} }
}; };

View File

@ -26,37 +26,40 @@ FrameBuffer* Communicate::ParseBuffer(MutBuffer& buffer)
return frame; return frame;
} }
int len = 0; int32_t dataLen = 0;
std::memcpy(&len, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64, sizeof(len)); std::memcpy(&dataLen, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64, sizeof(dataLen));
if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint16_t) + 64 + len + sizeof(len) + sizeof(gTail)) || len < 0) { if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint16_t) + 64 + dataLen + sizeof(dataLen) + sizeof(gTail)) ||
dataLen < 0) {
return frame; return frame;
} }
if (std::memcmp(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + len, gTail, if (std::memcmp(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(dataLen) + dataLen, gTail,
sizeof(gTail)) != 0) { sizeof(gTail)) != 0) {
return frame; return frame;
} }
frame = new FrameBuffer(); frame = new FrameBuffer();
frame->len = dataLen;
frame->fid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t), 32); frame->fid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t), 32);
frame->tid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 32, 32); frame->tid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 32, 32);
std::memcpy(&frame->dataType, buffer.GetData() + find + sizeof(gHeader), sizeof(frame->dataType));
if (len > 0) { if (frame->len > 0) {
frame->dataMut = new char[len]; frame->dataMut = new char[frame->len];
std::memcpy(frame->dataMut, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len), len); std::memcpy(frame->dataMut, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(frame->len),
frame->len = len; frame->len);
} }
buffer.RemoveOf(0, find + sizeof(gHeader) + sizeof(uint16_t) + 64 + len + sizeof(len) + sizeof(gTail)); buffer.RemoveOf(0, find + sizeof(gHeader) + sizeof(uint16_t) + 64 + frame->len + sizeof(frame->len) + sizeof(gTail));
return frame; return frame;
} }
bool Communicate::PackBuffer(FrameBuffer* frame, char** buf, int& len) bool Communicate::PackBuffer(FrameBuffer* frame, char** buf, int32_t& len)
{ {
if (frame == nullptr) { if (frame == nullptr) {
return false; return false;
} }
const char* dataPtr = nullptr; const char* dataPtr = nullptr;
if (frame->dataMut == nullptr) { if (frame->dataMut == nullptr && frame->dataConst == nullptr) {
frame->len = 0; frame->len = 0;
} }
if (frame->dataConst) { if (frame->dataConst) {
@ -67,14 +70,14 @@ bool Communicate::PackBuffer(FrameBuffer* frame, char** buf, int& len)
len = sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + frame->len + sizeof(gTail); len = sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + frame->len + sizeof(gTail);
*buf = new char[len]; *buf = new char[len];
std::memcpy(*buf, gHeader, sizeof(gHeader)); std::memcpy(*buf, gHeader, sizeof(gHeader));
std::memcpy(*buf + sizeof(gHeader), &frame->dataType, sizeof(uint16_t)); std::memcpy(*buf + sizeof(gHeader), &frame->dataType, sizeof(frame->dataType));
std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t), frame->fid.c_str(), 32); std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t), frame->fid.c_str(), 32);
std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 32, frame->tid.c_str(), 32); std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 32, frame->tid.c_str(), 32);
std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 64, &frame->len, sizeof(len)); std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 64, &frame->len, sizeof(frame->len));
if (frame->len > 0) { if (frame->len > 0) {
std::memcpy(*buf + sizeof(gHeader) + 64 + sizeof(len), dataPtr, frame->len); std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len), dataPtr, frame->len);
} }
std::memcpy(*buf + sizeof(gHeader) + 64 + sizeof(len) + frame->len, gTail, sizeof(gTail)); std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + frame->len, gTail, sizeof(gTail));
frame->dataConst = nullptr; frame->dataConst = nullptr;
return true; return true;
} }

View File

@ -19,7 +19,7 @@ struct FrameBuffer {
FrameBuffer(); FrameBuffer();
~FrameBuffer(); ~FrameBuffer();
int len{}; int32_t len{};
char* dataMut; char* dataMut;
std::string fid; std::string fid;
std::string tid; std::string tid;
@ -34,7 +34,7 @@ public:
public: public:
static FrameBuffer* ParseBuffer(MutBuffer& buffer); static FrameBuffer* ParseBuffer(MutBuffer& buffer);
static bool PackBuffer(FrameBuffer* frame, char** buf, int& len); static bool PackBuffer(FrameBuffer* frame, char** buf, int32_t& len);
}; };
#endif // COMMUNICATE_H #endif // COMMUNICATE_H

View File

@ -25,6 +25,7 @@ bool RelayServer::Init(const wxString& ip, unsigned short port)
wxLogError(wxT("Failed to get local address.")); wxLogError(wxT("Failed to get local address."));
return false; return false;
} }
strID_ = wxString::Format("%s:%d", addr.IPAddress(), addr.Service());
wxLogMessage(wxT("Server socket created on %s:%d"), addr.IPAddress(), addr.Service()); wxLogMessage(wxT("Server socket created on %s:%d"), addr.IPAddress(), addr.Service());
// wxLogInfo(wxT("Server socket created on %s:%d"), addr.IPAddress(), addr.Service()); // wxLogInfo(wxT("Server socket created on %s:%d"), addr.IPAddress(), addr.Service());
@ -74,15 +75,8 @@ void RelayServer::OnServerEvent(wxSocketEvent& event)
wxIPV4address addr; wxIPV4address addr;
sock->GetPeer(addr); sock->GetPeer(addr);
wxString id = wxString::Format("%s:%d", addr.IPAddress(), addr.Service()); wxString id = wxString::Format("%s:%d", addr.IPAddress(), addr.Service());
wxLogMessage(wxT("Client disconnected: %s"), id); wxLogMessage(wxT("disconnected: %s"), id);
std::unique_lock<std::shared_mutex> lock(clientsMutex_); ClearClient(id);
if (clients_.find(id) != clients_.end()) {
clients_.erase(id);
}
if (threads_.find(id) != threads_.end()) {
threads_[id].detach();
threads_.erase(id);
}
break; break;
} }
default: default:
@ -100,15 +94,22 @@ void RelayServer::thClientThread(const std::shared_ptr<wxSocketBase>& wxSock, co
client = clients_[id]; client = clients_[id];
} }
// 初次链接,告知对方的ID
InfoCommunicate info;
info.data = id.ToStdString();
Send<InfoCommunicate>(client->wxSock, info, FBT_SER_MSG_YOURID, id.ToStdString(), strID_);
client->wxSock->SetFlags(wxSOCKET_BLOCK); client->wxSock->SetFlags(wxSOCKET_BLOCK);
while (thRun_) { while (thRun_) {
wxSock->Read(client->buf.data(), GBUFFER_SIZE); wxSock->Read(client->buf.data(), GBUFFER_SIZE);
auto br = wxSock->LastCount(); auto br = wxSock->LastCount();
if (br == 0) { if (br == 0) {
wxLogMessage(wxT("Client disconnected: %s"), id); wxLogMessage(wxT("Client disconnected: %s"), id);
ClearClient(id);
break; break;
} else if (wxSock->Error()) { } else if (wxSock->Error()) {
wxLogMessage(wxT("%s Client error: %s"), id, wxSock->LastError()); wxLogMessage(wxT("%s Client error: %s"), id, wxSock->LastError());
ClearClient(id);
break; break;
} }
client->buffer.Push(client->buf.data(), br); client->buffer.Push(client->buf.data(), br);
@ -117,7 +118,9 @@ void RelayServer::thClientThread(const std::shared_ptr<wxSocketBase>& wxSock, co
if (!frame) { if (!frame) {
break; break;
} }
frame->fid = id.ToStdString();
if (frame->dataType <= 30) { if (frame->dataType <= 30) {
frame->tid = strID_;
ReplyRequest(client->wxSock, frame); ReplyRequest(client->wxSock, frame);
delete frame; delete frame;
continue; continue;
@ -151,37 +154,17 @@ bool RelayServer::Forword(const sockPtr& wxSock, FrameBuffer* buf)
return true; return true;
} }
if (fcl) { if (fcl) {
RpyForwordFailed(fcl->wxSock); RpyForwordFailed(fcl->wxSock, buf);
} }
return farward; return farward;
} }
bool RelayServer::Reply(const sockPtr& wxSock, InfoCommunicate& info, FrameBufferType type)
{
switch (type) {
case FBT_SER_MSG_ASKCLIENTS: {
std::swap(info.fromID, info.toID);
info.fromID = strID_;
RpyOnline(wxSock);
break;
}
default:
break;
}
wxLogWarning(_("Unknow message type: %d"), type);
return false;
}
void RelayServer::ReplyRequest(const sockPtr& wxSock, FrameBuffer* frame) void RelayServer::ReplyRequest(const sockPtr& wxSock, FrameBuffer* frame)
{ {
InfoCommunicate info;
switch (frame->dataType) { switch (frame->dataType) {
case FBT_SER_MSG_ASKCLIENTS: { case FBT_SER_MSG_ASKCLIENTS: {
std::stringstream ss; RpyOnline(wxSock, frame);
ss.write(frame->dataMut, frame->len); wxLogDebug(wxT("Reply clients to %s clients list."), frame->fid);
cereal::BinaryInputArchive inputArchive(ss);
inputArchive(info);
Reply(wxSock, info, FBT_SER_MSG_ASKCLIENTS);
break; break;
} }
default: default:
@ -189,7 +172,21 @@ void RelayServer::ReplyRequest(const sockPtr& wxSock, FrameBuffer* frame)
} }
} }
bool RelayServer::RpyOnline(const sockPtr& wxSock) void RelayServer::ClearClient(const wxString& id)
{
std::unique_lock<std::shared_mutex> lock(clientsMutex_);
if (clients_.find(id) != clients_.end()) {
wxLogDebug(wxT("client cleared: %s"), id);
clients_.erase(id);
}
if (threads_.find(id) != threads_.end()) {
wxLogDebug(wxT("client thread detached: %s"), id);
threads_[id].detach();
threads_.erase(id);
}
}
bool RelayServer::RpyOnline(const sockPtr& wxSock, FrameBuffer* frame)
{ {
InfoClientVec infoClients; InfoClientVec infoClients;
{ {
@ -204,13 +201,13 @@ bool RelayServer::RpyOnline(const sockPtr& wxSock)
std::stringstream ss; std::stringstream ss;
cereal::BinaryOutputArchive archive(ss); cereal::BinaryOutputArchive archive(ss);
archive(infoClients); archive(infoClients);
return Send<InfoClientVec>(wxSock, infoClients, FBT_SER_MSG_ASKCLIENTS); return Send<InfoClientVec>(wxSock, infoClients, FBT_SER_MSG_ASKCLIENTS, frame->fid, frame->tid);
} }
bool RelayServer::RpyForwordFailed(const sockPtr& wxSock) bool RelayServer::RpyForwordFailed(const sockPtr& wxSock, FrameBuffer* frame)
{ {
InfoCommunicate info; InfoCommunicate info;
return Send<InfoCommunicate>(wxSock, info, FBT_SER_MSG_RESPONSE); return Send<InfoCommunicate>(wxSock, info, FBT_SER_MSG_RESPONSE, frame->fid, frame->tid);
} }
bool RelayServer::Send(const sockPtr& wxSock, FrameBuffer* buf) bool RelayServer::Send(const sockPtr& wxSock, FrameBuffer* buf)

View File

@ -41,21 +41,26 @@ private:
void OnServerEvent(wxSocketEvent& event); void OnServerEvent(wxSocketEvent& event);
void thClientThread(const std::shared_ptr<wxSocketBase>& wxSock, const wxString& id); void thClientThread(const std::shared_ptr<wxSocketBase>& wxSock, const wxString& id);
bool Forword(const sockPtr& wxSock, FrameBuffer* buf); bool Forword(const sockPtr& wxSock, FrameBuffer* buf);
bool Reply(const sockPtr& wxSock, InfoCommunicate& info, FrameBufferType type);
void ReplyRequest(const sockPtr& wxSock, FrameBuffer* frame); void ReplyRequest(const sockPtr& wxSock, FrameBuffer* frame);
void ClearClient(const wxString& id);
private: private:
bool RpyOnline(const sockPtr& wxSock); bool RpyOnline(const sockPtr& wxSock, FrameBuffer* frame);
bool RpyForwordFailed(const sockPtr& wxSock); bool RpyForwordFailed(const sockPtr& wxSock, FrameBuffer* frame);
private: private:
template <typename T> bool Send(const sockPtr& wxSock, const T& info, FrameBufferType type) template <typename T>
bool Send(const sockPtr& wxSock, const T& info, FrameBufferType type, const std::string& fid, const std::string& tid)
{ {
std::stringstream ss; std::stringstream ss;
cereal::BinaryOutputArchive archive(ss); cereal::BinaryOutputArchive archive(ss);
archive(info); archive(info);
auto buf = std::make_shared<FrameBuffer>(); auto buf = std::make_shared<FrameBuffer>();
buf->fid = fid;
buf->tid = tid;
std::swap(buf->fid, buf->tid);
buf->dataConst = ss.view().data(); buf->dataConst = ss.view().data();
buf->len = ss.str().size(); buf->len = ss.str().size();
buf->dataType = type; buf->dataType = type;

View File

@ -6,4 +6,4 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(wxWidgets CONFIG REQUIRED) find_package(wxWidgets CONFIG REQUIRED)
add_executable(RelayFileTest main.cxx) add_executable(RelayFileTest main.cxx)
target_link_libraries(RelayFileTest PRIVATE wx::base wx::core) target_link_libraries(RelayFileTest PRIVATE wx::base wx::core Protocol Util)

View File

@ -1,5 +1,6 @@
#include <InfoDirFile.hpp> #include <InfoDirFile.hpp>
#include <iostream> #include <iostream>
#include <Communicate.h>
void test1() void test1()
{ {
@ -63,8 +64,30 @@ void test2()
} }
} }
void test3()
{
auto* f = new FrameBuffer();
f->fid = "127.0.0.1:9898";
f->tid = "127.0.0.1:9899";
f->dataType = FBT_CLI_BIN_FILEDATA;
char* d = nullptr;
int len = 0;
if (Communicate::PackBuffer(f, &d, len)) {
MutBuffer buffer;
buffer.Push(d, len);
auto c = Communicate::ParseBuffer(buffer);
if (c != nullptr) {
std::cout << "Parse success\n";
} else {
std::cout << "Parse failed\n";
}
delete[] d;
}
}
int main() int main()
{ {
test2(); test3();
return 0; return 0;
} }

View File

@ -1,18 +1,21 @@
#include "ControlManager.h" #include "ControlManager.h"
#include <ClientCore.h>
ControlManager::ControlManager(wxWindow* parent) : parent_(parent), header_(nullptr), local_(nullptr) ControlManager::ControlManager(wxWindow* parent) : parent_(parent), header_(nullptr), local_(nullptr)
{ {
Init();
} }
void ControlManager::Init() void ControlManager::Init(std::shared_ptr<ClientCore>& clientCore)
{ {
log_ = new LogControl(parent_); log_ = new LogControl(parent_);
header_ = new HeaderControl(parent_); header_ = new HeaderControl(parent_, clientCore);
local_ = new LocalControl(parent_); local_ = new LocalControl(parent_);
remote_ = new RemoteControl(parent_); remote_ = new RemoteControl(parent_);
task_ = new TaskControl(parent_); task_ = new TaskControl(parent_);
online_ = new OnlineControl(parent_); online_ = new OnlineControl(parent_, clientCore);
header_->SetLogControl(log_); header_->SetLogControl(log_);
online_->SetLogControl(log_);
clientCore->SetLogCallback([this](const wxString& msg) { log_->AddLog(msg); });
} }

View File

@ -9,14 +9,15 @@
#include "OnLineControl.h" #include "OnLineControl.h"
#include <memory> #include <memory>
class ClientCore;
class ControlManager class ControlManager
{ {
public: public:
ControlManager(wxWindow* parent); ControlManager(wxWindow* parent);
~ControlManager() = default; ~ControlManager() = default;
private: public:
void Init(); void Init(std::shared_ptr<ClientCore>& clientCore);
private: private:
wxWindow* parent_; wxWindow* parent_;

View File

@ -1,8 +1,9 @@
#include "HeaderControl.h" #include "HeaderControl.h"
#include "InterfaceDefine.hpp" #include "InterfaceDefine.hpp"
#include "LogControl.h" #include "LogControl.h"
#include <ClientCore.h>
HeaderControl::HeaderControl(wxWindow* parent) : wxPanel(parent) HeaderControl::HeaderControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore) : wxPanel(parent), clientCore_(clientCore)
{ {
Init(); Init();
} }
@ -34,6 +35,9 @@ void HeaderControl::Init()
Layout(); Layout();
Bind(wxEVT_BUTTON, &HeaderControl::OnConnect, this, btnConnect_->GetId()); Bind(wxEVT_BUTTON, &HeaderControl::OnConnect, this, btnConnect_->GetId());
textIP_->SetValue(wxT("127.0.0.1"));
textPort_->SetValue(wxT("8080"));
} }
void HeaderControl::OnConnect(wxCommandEvent& event) void HeaderControl::OnConnect(wxCommandEvent& event)
@ -45,7 +49,7 @@ void HeaderControl::OnConnect(wxCommandEvent& event)
return; return;
} }
auto uPort = static_cast<unsigned short>(port); auto uPort = static_cast<unsigned short>(port);
if (!clientCore_.Connect(ip, uPort)) { if (!clientCore_->Connect(ip, uPort)) {
logControl_->AddLog(wxString::Format(_("Connect to %s:%d failed."), ip, uPort)); logControl_->AddLog(wxString::Format(_("Connect to %s:%d failed."), ip, uPort));
return; return;
} }

View File

@ -1,14 +1,14 @@
#ifndef HEADERCONTROL_H #ifndef HEADERCONTROL_H
#define HEADERCONTROL_H #define HEADERCONTROL_H
#include <ClientCore.h>
#include <wx/wx.h> #include <wx/wx.h>
class LogControl; class LogControl;
class ClientCore;
class HeaderControl : public wxPanel class HeaderControl : public wxPanel
{ {
public: public:
HeaderControl(wxWindow* parent); HeaderControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore);
~HeaderControl() override; ~HeaderControl() override;
public: public:
@ -26,7 +26,7 @@ public:
wxTextCtrl* textPort_; wxTextCtrl* textPort_;
wxButton* btnConnect_; wxButton* btnConnect_;
wxButton* btnDisconnect_; wxButton* btnDisconnect_;
ClientCore clientCore_; std::shared_ptr<ClientCore> clientCore_;
private: private:
LogControl* logControl_; LogControl* logControl_;

View File

@ -21,7 +21,7 @@ LogControl::~LogControl()
void LogControl::AddLog(const wxString& log) void LogControl::AddLog(const wxString& log)
{ {
std::lock_guard<std::mutex> lock(mutex_); std::unique_lock<std::mutex> lock(mutex_);
auto now = wxDateTime::UNow(); auto now = wxDateTime::UNow();
auto strTime = now.Format("%H:%M:%S.%l"); auto strTime = now.Format("%H:%M:%S.%l");
listBox_->Append(strTime + wxT(" ") + log); listBox_->Append(strTime + wxT(" ") + log);

View File

@ -1,16 +1,31 @@
#include "OnLineControl.h" #include "OnLineControl.h"
#include "HeaderControl.h"
#include "LogControl.h"
#include <ClientCore.h>
OnlineControl::OnlineControl(wxWindow* parent) : wxPanel(parent) OnlineControl::OnlineControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore) : wxPanel(parent), clientCore_(clientCore)
{ {
Init(); Init();
InitCall();
} }
OnlineControl::~OnlineControl() OnlineControl::~OnlineControl()
{ {
} }
void OnlineControl::SetHeaderControl(HeaderControl* headerControl)
{
headerControl_ = headerControl;
}
void OnlineControl::SetLogControl(LogControl* logControl)
{
logControl_ = logControl;
}
void OnlineControl::Init() void OnlineControl::Init()
{ {
btnFresh_ = new wxButton(this, wxID_ANY, _("Refresh"));
lbCurState_ = new wxStaticText(this, wxID_ANY, _("Current State => ")); lbCurState_ = new wxStaticText(this, wxID_ANY, _("Current State => "));
elbCurState_ = new wxStaticText(this, wxID_ANY, _("Disconnected")); elbCurState_ = new wxStaticText(this, wxID_ANY, _("Disconnected"));
elbCurState_->SetForegroundColour(*wxBLUE); elbCurState_->SetForegroundColour(*wxBLUE);
@ -24,11 +39,42 @@ void OnlineControl::Init()
leveSizerA->Add(lbCurState_, 0, wxEXPAND | wxALL, gBorder + 1); leveSizerA->Add(lbCurState_, 0, wxEXPAND | wxALL, gBorder + 1);
leveSizerA->Add(elbCurState_, 0, wxEXPAND | wxALL, gBorder + 1); leveSizerA->Add(elbCurState_, 0, wxEXPAND | wxALL, gBorder + 1);
auto* leveSizerB = new wxBoxSizer(wxHORIZONTAL);
leveSizerB->Add(lbCurPoint_, 1, wxALL | wxCENTER, gBorder + 1);
leveSizerB->Add(btnFresh_, 0, wxALL | wxCENTER, gBorder + 1);
auto* topSizer = new wxBoxSizer(wxVERTICAL); auto* topSizer = new wxBoxSizer(wxVERTICAL);
topSizer->Add(leveSizerA, 0, wxEXPAND | wxALL, gBorder + 1); topSizer->Add(leveSizerA, 0, wxEXPAND | wxALL, gBorder + 1);
topSizer->Add(lbCurPoint_, 0, wxEXPAND | wxALL, gBorder + 1); topSizer->Add(leveSizerB, 0, wxALL, gBorder + 1);
topSizer->Add(elbCurPoint_, 0, wxEXPAND | wxALL, gBorder + 1); topSizer->Add(elbCurPoint_, 0, wxEXPAND | wxALL, gBorder + 1);
topSizer->Add(onLineList_, 1, wxEXPAND | wxALL, gBorder + 1); topSizer->Add(onLineList_, 1, wxEXPAND | wxALL, gBorder + 1);
SetSizer(topSizer); SetSizer(topSizer);
Layout(); Layout();
Bind(wxEVT_BUTTON, &OnlineControl::OnFreshClients, this, btnFresh_->GetId());
}
void OnlineControl::InitCall()
{
clientCore_->ReqOnlineCallback([this](const InfoClientVec& infoClientVec) { OnFreshClientsCall(infoClientVec); });
}
void OnlineControl::OnFreshClients(wxCommandEvent& event)
{
InfoClientVec vec;
if (!clientCore_->ReqOnline()) {
logControl_->AddLog(_("Request Get online list failed."));
return;
}
logControl_->AddLog(_("Request Get online list success."));
}
void OnlineControl::OnFreshClientsCall(const InfoClientVec& infoClientVec)
{
std::unique_lock<std::mutex> lock(mutex_);
onLineList_->Clear();
for (auto& info : infoClientVec.vec) {
onLineList_->Append(info.id);
}
logControl_->AddLog(_("Get online list success."));
} }

View File

@ -2,22 +2,41 @@
#define ONLINECONTROL_H #define ONLINECONTROL_H
#include "InterfaceDefine.hpp" #include "InterfaceDefine.hpp"
#include <InfoClient.hpp>
#include <mutex>
class HeaderControl;
class LogControl;
class ClientCore;
class OnlineControl : public wxPanel class OnlineControl : public wxPanel
{ {
public: public:
OnlineControl(wxWindow* parent); OnlineControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore);
~OnlineControl() override; ~OnlineControl() override;
public:
void SetHeaderControl(HeaderControl* headerControl);
void SetLogControl(LogControl* logControl);
private: private:
void Init(); void Init();
void InitCall();
void OnFreshClients(wxCommandEvent& event);
private:
void OnFreshClientsCall(const InfoClientVec& infoClientVec);
public: public:
wxButton* btnFresh_;
std::mutex mutex_;
wxStaticText* lbCurState_; wxStaticText* lbCurState_;
wxStaticText* elbCurState_; wxStaticText* elbCurState_;
wxStaticText* lbCurPoint_; wxStaticText* lbCurPoint_;
wxStaticText* elbCurPoint_; wxStaticText* elbCurPoint_;
wxListBox* onLineList_; wxListBox* onLineList_;
HeaderControl* headerControl_;
LogControl* logControl_;
std::shared_ptr<ClientCore> clientCore_;
}; };
#endif // ONLINECONTROL_H #endif // ONLINECONTROL_H

View File

@ -8,11 +8,15 @@ namespace fs = std::filesystem;
UserInterface::UserInterface(const wxString& title) : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600)) UserInterface::UserInterface(const wxString& title) : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600))
{ {
mgr_.SetManagedWindow(this); mgr_.SetManagedWindow(this);
clientCore_ = std::make_shared<ClientCore>();
InitMenu(); InitMenu();
InitUI(); InitUI();
InitData(); InitData();
TryRestoreLayout(); TryRestoreLayout();
Bind(wxEVT_CLOSE_WINDOW, &UserInterface::OnClose, this);
controlMgr_->log_->AddLog(wxT("Welcome to RelayFile.")); controlMgr_->log_->AddLog(wxT("Welcome to RelayFile."));
} }
@ -21,10 +25,20 @@ UserInterface::~UserInterface()
mgr_.UnInit(); mgr_.UnInit();
} }
void UserInterface::OnClose(wxCloseEvent& event)
{
auto* config = new wxFileConfig(wxEmptyString, wxEmptyString, configPath_);
config->Write("StartWidth", GetSize().GetWidth());
config->Write("StartHeigh", GetSize().GetHeight());
delete config;
event.Skip();
}
void UserInterface::InitUI() void UserInterface::InitUI()
{ {
// Add Panel // Add Panel
controlMgr_ = std::make_shared<ControlManager>(this); controlMgr_ = std::make_shared<ControlManager>(this);
controlMgr_->Init(clientCore_);
mgr_.AddPane(controlMgr_->header_, mgr_.AddPane(controlMgr_->header_,
wxAuiPaneInfo().Name("header").Caption(_("header")).CloseButton(false).Floatable(false).MinSize(-1, 40)); wxAuiPaneInfo().Name("header").Caption(_("header")).CloseButton(false).Floatable(false).MinSize(-1, 40));
mgr_.AddPane(controlMgr_->log_, wxAuiPaneInfo().Name("log").Caption(_("log")).CloseButton(false).BestSize(300, 400)); mgr_.AddPane(controlMgr_->log_, wxAuiPaneInfo().Name("log").Caption(_("log")).CloseButton(false).BestSize(300, 400));
@ -69,6 +83,9 @@ void UserInterface::TryRestoreLayout()
if (!perspective.IsEmpty()) { if (!perspective.IsEmpty()) {
mgr_.LoadPerspective(perspective); mgr_.LoadPerspective(perspective);
} }
auto startWidth = config->Read("StartWidth", 800);
auto startHeigh = config->Read("StartHeigh", 600);
SetSize(startWidth, startHeigh);
delete config; delete config;
} }

View File

@ -6,6 +6,7 @@
#include <wx/wx.h> #include <wx/wx.h>
#include "ControlManager.h" #include "ControlManager.h"
#include <ClientCore.h>
enum MenuID { enum MenuID {
ID_SaveLayout = 1000, ID_SaveLayout = 1000,
@ -17,6 +18,9 @@ public:
explicit UserInterface(const wxString& title); explicit UserInterface(const wxString& title);
~UserInterface() override; ~UserInterface() override;
public:
void OnClose(wxCloseEvent& event);
private: private:
void InitUI(); void InitUI();
void InitMenu(); void InitMenu();
@ -33,6 +37,7 @@ private:
wxMenuBar* menuBar_; wxMenuBar* menuBar_;
wxString configDir_; wxString configDir_;
wxString configPath_; wxString configPath_;
std::shared_ptr<ClientCore> clientCore_;
std::shared_ptr<ControlManager> controlMgr_; std::shared_ptr<ControlManager> controlMgr_;
}; };

View File

@ -8,8 +8,8 @@ public:
{ {
SetProcessDPIAware(); SetProcessDPIAware();
loadLocale(); loadLocale();
auto* f = new UserInterface(_("RelayFile")); f_ = new UserInterface(_("RelayFile"));
f->Show(); f_->Show();
return true; return true;
} }
@ -20,6 +20,9 @@ private:
locale->AddCatalogLookupPathPrefix(wxT(".")); locale->AddCatalogLookupPathPrefix(wxT("."));
locale->AddCatalog(wxT("internat")); locale->AddCatalog(wxT("internat"));
} }
private:
UserInterface* f_;
}; };
IMPLEMENT_APP(RelayFileApp); IMPLEMENT_APP(RelayFileApp);