Files
frelay/ClientCore/ClientCore.h

136 lines
3.6 KiB
C
Raw Normal View History

2025-06-16 23:41:35 +08:00
#ifndef CLIENTCORE_H
2025-06-14 23:25:16 +08:00
#define CLIENTCORE_H
2025-06-15 14:31:54 +08:00
#include <InfoClient.h>
#include <InfoDirFile.h>
2025-06-15 23:13:30 +08:00
#include <InfoMsg.h>
#include <InfoPack.hpp>
#include <LocalFile.h>
2025-06-14 23:25:16 +08:00
#include <Protocol.h>
#include <QDataStream>
#include <QFuture>
2025-06-14 23:25:16 +08:00
#include <QHostAddress>
#include <QMutex>
#include <QMutexLocker>
#include <QPromise>
#include <QQueue>
2025-06-14 23:25:16 +08:00
#include <QTcpSocket>
#include <QThread>
2025-06-16 20:06:49 +08:00
#include <array>
2025-06-14 23:25:16 +08:00
class ClientCore : public QObject
{
Q_OBJECT
public:
ClientCore(QObject* parent = nullptr);
~ClientCore();
public:
void Instance();
2025-06-14 23:25:16 +08:00
bool Connect(const QString& ip, quint16 port);
void DoConnect(const QString& ip, quint16 port);
2025-06-14 23:25:16 +08:00
void Disconnect();
2025-06-15 14:31:54 +08:00
bool Send(QSharedPointer<FrameBuffer> frame);
bool Send(const char* data, qint64 len);
2025-06-15 23:13:30 +08:00
template <typename T> bool Send(const T& info, FrameBufferType type, const QString& tid)
{
auto f = GetBuffer<T>(info, type, tid);
return Send(f);
}
template <typename T> QSharedPointer<FrameBuffer> GetBuffer(const T& info, FrameBufferType type, const QString& tid)
2025-06-15 23:13:30 +08:00
{
auto f = QSharedPointer<FrameBuffer>::create();
f->tid = tid;
f->data = infoPack<T>(info);
f->type = type;
return f;
2025-06-15 23:13:30 +08:00
}
/*
When calling syncInvoke of ClientCore, the ClientCore should not be in the GUI's event loop thread.
In other words, if a ClientCore instance is created in the GUI thread, it should be moved to another thread;
otherwise, it will cause a deadlock and freeze the interface.
*/
template <typename Callable> static bool syncInvoke(QObject* context, Callable&& func)
{
auto promise = QSharedPointer<QPromise<bool>>::create();
QFuture<bool> future = promise->future();
QMetaObject::invokeMethod(
context,
[func = std::forward<Callable>(func), promise]() mutable {
try {
promise->addResult(func());
} catch (...) {
promise->addResult(false);
}
promise->finish();
},
Qt::QueuedConnection);
future.waitForFinished();
return future.result();
}
signals:
void sigDisconnect();
void sigPath(const QString& path);
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);
2025-06-20 09:45:39 +08:00
void sigFileInfo(QSharedPointer<FrameBuffer> frame);
2025-06-14 23:25:16 +08:00
signals:
void conSuccess();
void connecting();
void conFailed();
2025-06-14 23:44:13 +08:00
private:
void onReadyRead();
void onDisconnected();
2025-06-14 23:25:16 +08:00
2025-06-14 23:44:13 +08:00
private:
void UseFrame(QSharedPointer<FrameBuffer> frame);
2025-06-15 14:31:54 +08:00
public:
void SetRemoteID(const QString& id);
QString GetRemoteID();
2025-06-18 14:53:56 +08:00
QString GetOwnID();
2025-06-14 23:25:16 +08:00
2025-06-14 23:44:13 +08:00
public:
QMutex conMutex_;
QString ownID_;
2025-06-14 23:25:16 +08:00
QString remoteID_;
2025-06-17 11:48:13 +08:00
QMutex sockMut_;
QTcpSocket* socket_{};
2025-06-14 23:25:16 +08:00
QByteArray recvBuffer_;
2025-06-14 23:44:13 +08:00
bool connected_{ false };
2025-06-15 23:13:30 +08:00
LocalFile localFile_;
2025-06-14 23:25:16 +08:00
};
class SocketWorker : public QThread
{
Q_OBJECT
public:
SocketWorker(ClientCore* core, QObject* parent = nullptr);
~SocketWorker();
protected:
void run() override;
private:
ClientCore* core_{};
};
2025-06-14 23:25:16 +08:00
#endif // CLIENTCORE_H