Files
frelay/ClientCore/ClientCore.h
2026-03-24 17:20:21 +08:00

207 lines
5.3 KiB
C++

#ifndef CLIENTCORE_H
#define CLIENTCORE_H
#include <InfoClient.h>
#include <InfoDirFile.h>
#include <InfoMsg.h>
#include <InfoPack.hpp>
#include <LocalFile.h>
#include <Protocol.h>
#include <QDataStream>
#include <QHostAddress>
#include <QMutex>
#include <QMutexLocker>
#include <QQueue>
#include <QReadWriteLock>
#include <QThread>
#include <array>
#include <asio.hpp>
#include <queue>
class ClientCore : public QObject
{
Q_OBJECT
public:
ClientCore(QObject* parent, asio::io_context& ioContext);
~ClientCore();
public slots:
void Disconnect();
public slots:
void DoConnect(const QString& ip, quint16 port);
public:
void Instance();
asio::awaitable<bool> Connect(const QString& ip, quint16 port);
bool IsConnect();
const asio::any_io_executor& get_executor();
template <typename T> asio::awaitable<bool> Send(const T& info, FrameBufferType type, const QString& tid)
{
auto f = GetBuffer<T>(info, type, tid);
co_return co_await Send(f);
}
template <typename T> QSharedPointer<FrameBuffer> GetBuffer(const T& info, FrameBufferType type, const QString& tid)
{
auto f = QSharedPointer<FrameBuffer>::create();
f->tid = tid;
f->data = infoPack<T>(info);
f->type = type;
return f;
}
static bool syncInvoke(ClientCore* context, QSharedPointer<FrameBuffer> frame)
{
bool result = false;
try {
std::future<bool> fut = asio::co_spawn(
context->get_executor(), [context, frame]() -> asio::awaitable<bool> { co_return co_await context->Send(frame); },
asio::use_future);
result = fut.get();
} catch (const std::exception& ex) {
// std::cerr << e.what() << '\n';
}
// bool success = QMetaObject::invokeMethod(context, "SendFrame", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool,
// result),
// Q_ARG(QSharedPointer<FrameBuffer>, frame));
// if (!success) {
// return false;
// }
return result;
}
signals:
void sigDisconnect();
void sigPath(const QString& path, const QVector<QString>& drivers);
void sigClients(const InfoClientVec& clients);
void sigFiles(const DirFileInfoVec& files);
void sigReqSend(QSharedPointer<FrameBuffer> frame);
void sigReqDown(QSharedPointer<FrameBuffer> frame);
void sigTransDone(QSharedPointer<FrameBuffer> frame);
void sigCanSend(QSharedPointer<FrameBuffer> frame);
void sigCanotSend(QSharedPointer<FrameBuffer> frame);
void sigCanotDown(QSharedPointer<FrameBuffer> frame);
void sigCanDown(QSharedPointer<FrameBuffer> frame);
void sigFileBuffer(QSharedPointer<FrameBuffer> frame);
void sigTransFailed(QSharedPointer<FrameBuffer> frame);
void sigFileInfo(QSharedPointer<FrameBuffer> frame);
void sigOffline(QSharedPointer<FrameBuffer> frame);
void sigYourId(QSharedPointer<FrameBuffer> frame);
void sigMsgAsk(QSharedPointer<FrameBuffer> frame);
void sigMsgAnswer(QSharedPointer<FrameBuffer> frame);
void sigFlowBack(QSharedPointer<FrameBuffer> frame);
void sigTransInterrupt(QSharedPointer<FrameBuffer> frame);
signals:
void conSuccess();
void connecting();
void conFailed();
private:
void onReadyRead();
void onDisconnected();
asio::awaitable<void> handleAsk(QSharedPointer<FrameBuffer> frame);
private:
asio::awaitable<void> UseFrame(QSharedPointer<FrameBuffer> frame);
public:
void SetRemoteID(const QString& id);
QString GetRemoteID();
QString GetOwnID();
void pushID(const QString& id);
void popID(const QString& id);
public:
QMutex conMutex_;
QString ownID_;
// 这是被动发送时,对方ID。
QReadWriteLock rwIDLock_;
QVector<QString> remoteIDs_;
// 这是主动通信时的对方ID。
QString remoteID_;
QMutex sockMut_;
QByteArray recvBuffer_;
bool connected_{false};
LocalFile localFile_;
// asio变更
private:
asio::io_context& ioContext_;
asio::ip::tcp::socket mSocket_;
std::array<char, CHUNK_BUF_SIZE> mBuffer_;
std::mutex frameMutex_;
std::queue<QSharedPointer<FrameBuffer>> frameQueue_;
private:
asio::awaitable<bool> Send(QSharedPointer<FrameBuffer> frame);
asio::awaitable<bool> Send(const char* data, size_t size);
asio::awaitable<void> recvData();
};
// Socket Worker Thread
class SocketWorker : public QThread
{
Q_OBJECT
public:
SocketWorker(ClientCore* core, QObject* parent = nullptr);
~SocketWorker();
protected:
void run() override;
private:
ClientCore* core_{};
};
// HeatBeat to Server
class HeatBeat : public QThread
{
Q_OBJECT
public:
HeatBeat(ClientCore* core, QObject* parent = nullptr);
~HeatBeat() override;
public:
void Stop();
protected:
void run() override;
private:
bool isRun_{false};
ClientCore* core_{};
};
class WaitThread : public QThread
{
Q_OBJECT
public:
WaitThread(QObject* parent = nullptr);
public:
void SetClient(ClientCore* cli);
bool IsQuit() const;
Q_SIGNALS:
void sigCheckOver();
public Q_SLOTS:
virtual void interrupCheck();
virtual void recvFrame(QSharedPointer<FrameBuffer> frame) = 0;
protected:
bool isRun_;
bool isAlreadyInter_;
ClientCore* cli_{};
};
#endif // CLIENTCORE_H