diff --git a/ClientCore/ClientCore.cxx b/ClientCore/ClientCore.cxx index 04a06f9..ee257a3 100644 --- a/ClientCore/ClientCore.cxx +++ b/ClientCore/ClientCore.cxx @@ -3,7 +3,16 @@ ClientCore::ClientCore() { - socket_ = std::make_shared(); + socket_ = new wxSocketClient(); +} + +ClientCore::~ClientCore() +{ + Disconnect(); + thRun_ = false; + if (recvThread_.joinable()) { + recvThread_.join(); + } } 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); socket_->SetEventHandler(*this, wxID_ANY); - socket_->SetNotify(wxSOCKET_INPUT | wxSOCKET_LOST_FLAG); - socket_->Notify(true); + socket_->SetNotify(wxSOCKET_LOST_FLAG); socket_->SetFlags(wxSOCKET_BLOCK); + socket_->Notify(true); if (!socket_->Connect(addr)) { return false; } + Bind(wxEVT_SOCKET, &ClientCore::OnSocketEvent, this); + recvThread_ = std::thread(&ClientCore::Recv, this); return true; } void ClientCore::Disconnect() { + socket_->Destroy(); } -bool ClientCore::GetOnlineList(InfoClientVec& infoClientVec) +wxString ClientCore::GetErr() const +{ + return err_; +} + +void ClientCore::SetLogCallback(const std::function& callback) +{ + logCall_ = callback; +} + +bool ClientCore::ReqOnline() { InfoCommunicate infoCommunicate; if (!Send(infoCommunicate, FBT_SER_MSG_ASKCLIENTS)) { return false; } - return false; + return true; +} + +void ClientCore::ReqOnlineCallback(const std::function& callback) +{ + onlineCallback_ = callback; } 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) { auto* sock = event.GetSocket(); - switch (event.GetSocketEvent()) { - case wxSOCKET_CONNECTION: { - 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; - } + auto type = event.GetSocketEvent(); + switch (type) { case wxSOCKET_LOST: { + logCall_(wxString::Format(_("Lost connection to server."))); break; } default: + logCall_(wxString::Format(_T("No Handled Type: %d."), static_cast(type))); break; } } @@ -83,6 +91,21 @@ void ClientCore::UseFrame(FrameBuffer* buf) InfoClientVec vec; ZeroCopyInput input(buf->dataMut, buf->len); 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; } 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) { if (buf == nullptr) { diff --git a/ClientCore/ClientCore.h b/ClientCore/ClientCore.h index 8d58bc8..bc66399 100644 --- a/ClientCore/ClientCore.h +++ b/ClientCore/ClientCore.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include @@ -17,13 +19,18 @@ class ClientCore : public wxEvtHandler { public: ClientCore(); + ~ClientCore(); public: bool Connect(const wxString& host, uint16_t port); void Disconnect(); public: - bool GetOnlineList(InfoClientVec& infoClientVec); + wxString GetErr() const; + + void SetLogCallback(const std::function& callback); + bool ReqOnline(); + void ReqOnlineCallback(const std::function& callback); bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec); private: @@ -34,6 +41,7 @@ private: private: void HeartBeat(); + void Recv(); template bool Send(const T& info, FrameBufferType type) { std::stringstream ss; @@ -53,9 +61,14 @@ private: wxString id_; bool thRun_; MutBuffer buffer_; + wxString err_; + std::thread recvThread_; std::array buf_; - std::shared_ptr socket_; - std::shared_ptr heartsThread_; + wxSocketClient* socket_; + +private: + std::function onlineCallback_; + std::function logCall_; }; #endif // CLIENTCORE_H \ No newline at end of file diff --git a/Information/InfoCommunicate.hpp b/Information/InfoCommunicate.hpp index 6d1a147..d961083 100644 --- a/Information/InfoCommunicate.hpp +++ b/Information/InfoCommunicate.hpp @@ -9,14 +9,12 @@ constexpr int GBUFFER_SIZE = 256; struct InfoCommunicate { - std::string fromID; - std::string toID; std::string UUID; std::string data; uint8_t mark{}; template 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)); } }; diff --git a/Protocol/Communicate.cxx b/Protocol/Communicate.cxx index ec3fbb5..22c76d0 100644 --- a/Protocol/Communicate.cxx +++ b/Protocol/Communicate.cxx @@ -26,37 +26,40 @@ FrameBuffer* Communicate::ParseBuffer(MutBuffer& buffer) return frame; } - int len = 0; - std::memcpy(&len, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64, sizeof(len)); - if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint16_t) + 64 + len + sizeof(len) + sizeof(gTail)) || len < 0) { + int32_t dataLen = 0; + std::memcpy(&dataLen, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64, sizeof(dataLen)); + if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint16_t) + 64 + dataLen + sizeof(dataLen) + sizeof(gTail)) || + dataLen < 0) { 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) { return frame; } frame = new FrameBuffer(); + frame->len = dataLen; 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); + std::memcpy(&frame->dataType, buffer.GetData() + find + sizeof(gHeader), sizeof(frame->dataType)); - if (len > 0) { - frame->dataMut = new char[len]; - std::memcpy(frame->dataMut, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len), len); - frame->len = len; + if (frame->len > 0) { + frame->dataMut = new char[frame->len]; + std::memcpy(frame->dataMut, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(frame->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; } -bool Communicate::PackBuffer(FrameBuffer* frame, char** buf, int& len) +bool Communicate::PackBuffer(FrameBuffer* frame, char** buf, int32_t& len) { if (frame == nullptr) { return false; } const char* dataPtr = nullptr; - if (frame->dataMut == nullptr) { + if (frame->dataMut == nullptr && frame->dataConst == nullptr) { frame->len = 0; } 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); *buf = new char[len]; 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) + 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) { - 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; return true; } diff --git a/Protocol/Communicate.h b/Protocol/Communicate.h index a4f1a41..94e0e98 100644 --- a/Protocol/Communicate.h +++ b/Protocol/Communicate.h @@ -19,7 +19,7 @@ struct FrameBuffer { FrameBuffer(); ~FrameBuffer(); - int len{}; + int32_t len{}; char* dataMut; std::string fid; std::string tid; @@ -34,7 +34,7 @@ public: public: 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 \ No newline at end of file diff --git a/RelayServer/RelayServer.cxx b/RelayServer/RelayServer.cxx index b60b19d..dddc09c 100644 --- a/RelayServer/RelayServer.cxx +++ b/RelayServer/RelayServer.cxx @@ -25,6 +25,7 @@ bool RelayServer::Init(const wxString& ip, unsigned short port) wxLogError(wxT("Failed to get local address.")); return false; } + strID_ = wxString::Format("%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()); @@ -74,15 +75,8 @@ void RelayServer::OnServerEvent(wxSocketEvent& event) wxIPV4address addr; sock->GetPeer(addr); wxString id = wxString::Format("%s:%d", addr.IPAddress(), addr.Service()); - wxLogMessage(wxT("Client disconnected: %s"), id); - std::unique_lock lock(clientsMutex_); - if (clients_.find(id) != clients_.end()) { - clients_.erase(id); - } - if (threads_.find(id) != threads_.end()) { - threads_[id].detach(); - threads_.erase(id); - } + wxLogMessage(wxT("disconnected: %s"), id); + ClearClient(id); break; } default: @@ -100,15 +94,22 @@ void RelayServer::thClientThread(const std::shared_ptr& wxSock, co client = clients_[id]; } + // 初次链接,告知对方的ID + InfoCommunicate info; + info.data = id.ToStdString(); + Send(client->wxSock, info, FBT_SER_MSG_YOURID, id.ToStdString(), strID_); + client->wxSock->SetFlags(wxSOCKET_BLOCK); while (thRun_) { wxSock->Read(client->buf.data(), GBUFFER_SIZE); auto br = wxSock->LastCount(); if (br == 0) { wxLogMessage(wxT("Client disconnected: %s"), id); + ClearClient(id); break; } else if (wxSock->Error()) { wxLogMessage(wxT("%s Client error: %s"), id, wxSock->LastError()); + ClearClient(id); break; } client->buffer.Push(client->buf.data(), br); @@ -117,7 +118,9 @@ void RelayServer::thClientThread(const std::shared_ptr& wxSock, co if (!frame) { break; } + frame->fid = id.ToStdString(); if (frame->dataType <= 30) { + frame->tid = strID_; ReplyRequest(client->wxSock, frame); delete frame; continue; @@ -151,37 +154,17 @@ bool RelayServer::Forword(const sockPtr& wxSock, FrameBuffer* buf) return true; } if (fcl) { - RpyForwordFailed(fcl->wxSock); + RpyForwordFailed(fcl->wxSock, buf); } 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) { - InfoCommunicate info; switch (frame->dataType) { case FBT_SER_MSG_ASKCLIENTS: { - std::stringstream ss; - ss.write(frame->dataMut, frame->len); - cereal::BinaryInputArchive inputArchive(ss); - inputArchive(info); - Reply(wxSock, info, FBT_SER_MSG_ASKCLIENTS); + RpyOnline(wxSock, frame); + wxLogDebug(wxT("Reply clients to %s clients list."), frame->fid); break; } 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 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; { @@ -204,13 +201,13 @@ bool RelayServer::RpyOnline(const sockPtr& wxSock) std::stringstream ss; cereal::BinaryOutputArchive archive(ss); archive(infoClients); - return Send(wxSock, infoClients, FBT_SER_MSG_ASKCLIENTS); + return Send(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; - return Send(wxSock, info, FBT_SER_MSG_RESPONSE); + return Send(wxSock, info, FBT_SER_MSG_RESPONSE, frame->fid, frame->tid); } bool RelayServer::Send(const sockPtr& wxSock, FrameBuffer* buf) diff --git a/RelayServer/RelayServer.h b/RelayServer/RelayServer.h index 670c9e7..ebefdb6 100644 --- a/RelayServer/RelayServer.h +++ b/RelayServer/RelayServer.h @@ -41,21 +41,26 @@ private: void OnServerEvent(wxSocketEvent& event); void thClientThread(const std::shared_ptr& wxSock, const wxString& id); bool Forword(const sockPtr& wxSock, FrameBuffer* buf); - bool Reply(const sockPtr& wxSock, InfoCommunicate& info, FrameBufferType type); void ReplyRequest(const sockPtr& wxSock, FrameBuffer* frame); + void ClearClient(const wxString& id); private: - bool RpyOnline(const sockPtr& wxSock); - bool RpyForwordFailed(const sockPtr& wxSock); + bool RpyOnline(const sockPtr& wxSock, FrameBuffer* frame); + bool RpyForwordFailed(const sockPtr& wxSock, FrameBuffer* frame); private: - template bool Send(const sockPtr& wxSock, const T& info, FrameBufferType type) + template + bool Send(const sockPtr& wxSock, const T& info, FrameBufferType type, const std::string& fid, const std::string& tid) { std::stringstream ss; cereal::BinaryOutputArchive archive(ss); archive(info); auto buf = std::make_shared(); + buf->fid = fid; + buf->tid = tid; + std::swap(buf->fid, buf->tid); + buf->dataConst = ss.view().data(); buf->len = ss.str().size(); buf->dataType = type; diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt index 1121ab9..6972283 100644 --- a/Test/CMakeLists.txt +++ b/Test/CMakeLists.txt @@ -6,4 +6,4 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(wxWidgets CONFIG REQUIRED) add_executable(RelayFileTest main.cxx) -target_link_libraries(RelayFileTest PRIVATE wx::base wx::core) \ No newline at end of file +target_link_libraries(RelayFileTest PRIVATE wx::base wx::core Protocol Util) \ No newline at end of file diff --git a/Test/main.cxx b/Test/main.cxx index 84f7be7..3575b98 100644 --- a/Test/main.cxx +++ b/Test/main.cxx @@ -1,5 +1,6 @@ #include #include +#include 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() { - test2(); + test3(); return 0; } \ No newline at end of file diff --git a/UserInterface/ControlManager.cxx b/UserInterface/ControlManager.cxx index 0e09ef6..fcf3ae5 100644 --- a/UserInterface/ControlManager.cxx +++ b/UserInterface/ControlManager.cxx @@ -1,18 +1,21 @@ #include "ControlManager.h" +#include ControlManager::ControlManager(wxWindow* parent) : parent_(parent), header_(nullptr), local_(nullptr) { - Init(); } -void ControlManager::Init() +void ControlManager::Init(std::shared_ptr& clientCore) { log_ = new LogControl(parent_); - header_ = new HeaderControl(parent_); + header_ = new HeaderControl(parent_, clientCore); local_ = new LocalControl(parent_); remote_ = new RemoteControl(parent_); task_ = new TaskControl(parent_); - online_ = new OnlineControl(parent_); + online_ = new OnlineControl(parent_, clientCore); header_->SetLogControl(log_); + online_->SetLogControl(log_); + + clientCore->SetLogCallback([this](const wxString& msg) { log_->AddLog(msg); }); } \ No newline at end of file diff --git a/UserInterface/ControlManager.h b/UserInterface/ControlManager.h index 77e2ef3..a7b5729 100644 --- a/UserInterface/ControlManager.h +++ b/UserInterface/ControlManager.h @@ -9,14 +9,15 @@ #include "OnLineControl.h" #include +class ClientCore; class ControlManager { public: ControlManager(wxWindow* parent); ~ControlManager() = default; -private: - void Init(); +public: + void Init(std::shared_ptr& clientCore); private: wxWindow* parent_; diff --git a/UserInterface/HeaderControl.cxx b/UserInterface/HeaderControl.cxx index c4f9ace..1aecd03 100644 --- a/UserInterface/HeaderControl.cxx +++ b/UserInterface/HeaderControl.cxx @@ -1,8 +1,9 @@ #include "HeaderControl.h" #include "InterfaceDefine.hpp" #include "LogControl.h" +#include -HeaderControl::HeaderControl(wxWindow* parent) : wxPanel(parent) +HeaderControl::HeaderControl(wxWindow* parent, std::shared_ptr& clientCore) : wxPanel(parent), clientCore_(clientCore) { Init(); } @@ -34,6 +35,9 @@ void HeaderControl::Init() Layout(); Bind(wxEVT_BUTTON, &HeaderControl::OnConnect, this, btnConnect_->GetId()); + + textIP_->SetValue(wxT("127.0.0.1")); + textPort_->SetValue(wxT("8080")); } void HeaderControl::OnConnect(wxCommandEvent& event) @@ -45,7 +49,7 @@ void HeaderControl::OnConnect(wxCommandEvent& event) return; } auto uPort = static_cast(port); - if (!clientCore_.Connect(ip, uPort)) { + if (!clientCore_->Connect(ip, uPort)) { logControl_->AddLog(wxString::Format(_("Connect to %s:%d failed."), ip, uPort)); return; } diff --git a/UserInterface/HeaderControl.h b/UserInterface/HeaderControl.h index 7ecc67d..e2df5de 100644 --- a/UserInterface/HeaderControl.h +++ b/UserInterface/HeaderControl.h @@ -1,14 +1,14 @@ #ifndef HEADERCONTROL_H #define HEADERCONTROL_H -#include #include class LogControl; +class ClientCore; class HeaderControl : public wxPanel { public: - HeaderControl(wxWindow* parent); + HeaderControl(wxWindow* parent, std::shared_ptr& clientCore); ~HeaderControl() override; public: @@ -26,7 +26,7 @@ public: wxTextCtrl* textPort_; wxButton* btnConnect_; wxButton* btnDisconnect_; - ClientCore clientCore_; + std::shared_ptr clientCore_; private: LogControl* logControl_; diff --git a/UserInterface/LogControl.cxx b/UserInterface/LogControl.cxx index 9c4c4fe..539493c 100644 --- a/UserInterface/LogControl.cxx +++ b/UserInterface/LogControl.cxx @@ -21,7 +21,7 @@ LogControl::~LogControl() void LogControl::AddLog(const wxString& log) { - std::lock_guard lock(mutex_); + std::unique_lock lock(mutex_); auto now = wxDateTime::UNow(); auto strTime = now.Format("%H:%M:%S.%l"); listBox_->Append(strTime + wxT(" ") + log); diff --git a/UserInterface/OnLineControl.cxx b/UserInterface/OnLineControl.cxx index 0a0c08c..e13f7ba 100644 --- a/UserInterface/OnLineControl.cxx +++ b/UserInterface/OnLineControl.cxx @@ -1,16 +1,31 @@ #include "OnLineControl.h" +#include "HeaderControl.h" +#include "LogControl.h" +#include -OnlineControl::OnlineControl(wxWindow* parent) : wxPanel(parent) +OnlineControl::OnlineControl(wxWindow* parent, std::shared_ptr& clientCore) : wxPanel(parent), clientCore_(clientCore) { Init(); + InitCall(); } OnlineControl::~OnlineControl() { } +void OnlineControl::SetHeaderControl(HeaderControl* headerControl) +{ + headerControl_ = headerControl; +} + +void OnlineControl::SetLogControl(LogControl* logControl) +{ + logControl_ = logControl; +} + void OnlineControl::Init() { + btnFresh_ = new wxButton(this, wxID_ANY, _("Refresh")); lbCurState_ = new wxStaticText(this, wxID_ANY, _("Current State => ")); elbCurState_ = new wxStaticText(this, wxID_ANY, _("Disconnected")); elbCurState_->SetForegroundColour(*wxBLUE); @@ -24,11 +39,42 @@ void OnlineControl::Init() leveSizerA->Add(lbCurState_, 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); 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(onLineList_, 1, wxEXPAND | wxALL, gBorder + 1); SetSizer(topSizer); 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 lock(mutex_); + onLineList_->Clear(); + for (auto& info : infoClientVec.vec) { + onLineList_->Append(info.id); + } + logControl_->AddLog(_("Get online list success.")); } diff --git a/UserInterface/OnLineControl.h b/UserInterface/OnLineControl.h index 7008a7e..1ccc8a3 100644 --- a/UserInterface/OnLineControl.h +++ b/UserInterface/OnLineControl.h @@ -2,22 +2,41 @@ #define ONLINECONTROL_H #include "InterfaceDefine.hpp" +#include +#include +class HeaderControl; +class LogControl; +class ClientCore; class OnlineControl : public wxPanel { public: - OnlineControl(wxWindow* parent); + OnlineControl(wxWindow* parent, std::shared_ptr& clientCore); ~OnlineControl() override; +public: + void SetHeaderControl(HeaderControl* headerControl); + void SetLogControl(LogControl* logControl); + private: void Init(); + void InitCall(); + void OnFreshClients(wxCommandEvent& event); + +private: + void OnFreshClientsCall(const InfoClientVec& infoClientVec); public: + wxButton* btnFresh_; + std::mutex mutex_; wxStaticText* lbCurState_; wxStaticText* elbCurState_; wxStaticText* lbCurPoint_; wxStaticText* elbCurPoint_; wxListBox* onLineList_; + HeaderControl* headerControl_; + LogControl* logControl_; + std::shared_ptr clientCore_; }; #endif // ONLINECONTROL_H \ No newline at end of file diff --git a/UserInterface/UserInterface.cxx b/UserInterface/UserInterface.cxx index bfbafaa..d84180b 100644 --- a/UserInterface/UserInterface.cxx +++ b/UserInterface/UserInterface.cxx @@ -8,11 +8,15 @@ namespace fs = std::filesystem; UserInterface::UserInterface(const wxString& title) : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600)) { mgr_.SetManagedWindow(this); + + clientCore_ = std::make_shared(); + InitMenu(); InitUI(); InitData(); TryRestoreLayout(); + Bind(wxEVT_CLOSE_WINDOW, &UserInterface::OnClose, this); controlMgr_->log_->AddLog(wxT("Welcome to RelayFile.")); } @@ -21,10 +25,20 @@ UserInterface::~UserInterface() 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() { // Add Panel controlMgr_ = std::make_shared(this); + controlMgr_->Init(clientCore_); mgr_.AddPane(controlMgr_->header_, 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)); @@ -69,6 +83,9 @@ void UserInterface::TryRestoreLayout() if (!perspective.IsEmpty()) { mgr_.LoadPerspective(perspective); } + auto startWidth = config->Read("StartWidth", 800); + auto startHeigh = config->Read("StartHeigh", 600); + SetSize(startWidth, startHeigh); delete config; } diff --git a/UserInterface/UserInterface.h b/UserInterface/UserInterface.h index e9442f5..b7c999a 100644 --- a/UserInterface/UserInterface.h +++ b/UserInterface/UserInterface.h @@ -6,6 +6,7 @@ #include #include "ControlManager.h" +#include enum MenuID { ID_SaveLayout = 1000, @@ -17,6 +18,9 @@ public: explicit UserInterface(const wxString& title); ~UserInterface() override; +public: + void OnClose(wxCloseEvent& event); + private: void InitUI(); void InitMenu(); @@ -33,6 +37,7 @@ private: wxMenuBar* menuBar_; wxString configDir_; wxString configPath_; + std::shared_ptr clientCore_; std::shared_ptr controlMgr_; }; diff --git a/UserInterface/main.cxx b/UserInterface/main.cxx index d62f52f..ec3bb0f 100644 --- a/UserInterface/main.cxx +++ b/UserInterface/main.cxx @@ -8,8 +8,8 @@ public: { SetProcessDPIAware(); loadLocale(); - auto* f = new UserInterface(_("RelayFile")); - f->Show(); + f_ = new UserInterface(_("RelayFile")); + f_->Show(); return true; } @@ -20,6 +20,9 @@ private: locale->AddCatalogLookupPathPrefix(wxT(".")); locale->AddCatalog(wxT("internat")); } + +private: + UserInterface* f_; }; IMPLEMENT_APP(RelayFileApp);