diff options
Diffstat (limited to 'src/plugins/tracing/qctfserver_p.h')
-rw-r--r-- | src/plugins/tracing/qctfserver_p.h | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/plugins/tracing/qctfserver_p.h b/src/plugins/tracing/qctfserver_p.h new file mode 100644 index 0000000000..3660df7f09 --- /dev/null +++ b/src/plugins/tracing/qctfserver_p.h @@ -0,0 +1,194 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QT_CTFSERVER_H +#define QT_CTFSERVER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#include <qbytearray.h> +#include <qdatastream.h> +#include <qthread.h> +#include <qmutex.h> +#include <qwaitcondition.h> +#include <qeventloop.h> +#include <QtNetwork/qtcpserver.h> +#include <QtNetwork/qtcpsocket.h> +#include <qcborstreamreader.h> +#include <qcborstreamwriter.h> +#include <qlist.h> + +typedef struct ZSTD_CCtx_s ZSTD_CCtx; + +QT_BEGIN_NAMESPACE + +class QCtfServer; +struct TracePacket +{ + static constexpr quint32 PacketMagicNumber = 0x100924da; + static constexpr quint32 PacketSize = 4096 + 9; + QByteArray stream_name; + QByteArray stream_data; + quint32 flags = 0; + + TracePacket() = default; + + TracePacket(const TracePacket &t) + { + stream_name = t.stream_name; + stream_data = t.stream_data; + flags = t.flags; + } + TracePacket &operator = (const TracePacket &t) + { + stream_name = t.stream_name; + stream_data = t.stream_data; + flags = t.flags; + return *this; + } + TracePacket(TracePacket &&t) + { + stream_name = std::move(t.stream_name); + stream_data = std::move(t.stream_data); + flags = t.flags; + } + TracePacket &operator = (TracePacket &&t) + { + stream_name = std::move(t.stream_name); + stream_data = std::move(t.stream_data); + flags = t.flags; + return *this; + } +}; + +auto constexpr operator""_MB(quint64 s) -> quint64 +{ + return s * 1024ul * 1024ul; +} + +struct TraceRequest +{ + quint32 clientId; + quint32 clientVersion; + quint32 flags; + quint32 bufferSize; + QString sessionName; + QString sessionTracepoints; + + static constexpr quint32 MaxBufferSize = 1024_MB; + + bool isValid() const + { + if (clientId != 0 && clientVersion != 0 && !sessionName.isEmpty() + && !sessionTracepoints.isEmpty() && bufferSize < MaxBufferSize) + return true; + return false; + } +}; + +struct TraceResponse +{ + quint32 serverId; + quint32 serverVersion; + QString serverName; +}; + +class QCtfServer : public QThread +{ + Q_OBJECT +public: + enum ServerStatus + { + Uninitialized, + Idle, + Connected, + Error, + }; + enum ServerFlags + { + CompressionMask = 255, + DontBufferOnIdle = 256, // not set -> the server is buffering even without client connection + // set -> the server is buffering only when client is connected + }; + enum RequestIds + { + RequestClientId = 0, + RequestClientVersion, + RequestSessionName, + RequestSessionTracepoints, + RequestFlags, + RequestBufferSize, + RequestCompressionScheme, + }; + + struct ServerCallback + { + virtual void handleSessionChange() = 0; + virtual void handleStatusChange(ServerStatus status) = 0; + }; + QCtfServer(QObject *parent = nullptr); + ~QCtfServer(); + void setCallback(ServerCallback *cb); + void setHost(const QString &address); + void setPort(int port); + void run() override; + void startServer(); + void stopServer(); + void bufferData(const QString &stream, const QByteArray &data, quint32 flags); + QString sessionName() const; + QString sessionTracepoints() const; + bool bufferOnIdle() const; + ServerStatus status() const; +private: + + void initWrite(); + void bytesWritten(qint64 size); + bool waitSocket(); + void readCbor(QCborStreamReader &cbor); + void handleString(QCborStreamReader &cbor); + void handleFixedWidth(QCborStreamReader &cbor); + bool recognizedCompressionScheme() const; + void setStatusAndNotify(ServerStatus status); + void writePacket(TracePacket &packet, QCborStreamWriter &cbor); + + QMutex m_mutex; + QWaitCondition m_bufferHasData; + QList<TracePacket> m_packets; + QString m_address; + QTcpServer *m_server = nullptr; + QTcpSocket *m_socket = nullptr; + QEventLoop *m_eventLoop = nullptr; + QList<QString> m_keySet; + TraceRequest m_req; + ServerCallback *m_cb = nullptr; + ServerStatus m_status = Uninitialized; + qint64 m_waitWriteSize = 0; + qint64 m_writtenSize = 0; + int m_port; + int m_compression = 0; + int m_maxPackets = DefaultMaxPackets; + QAtomicInt m_stopping; + bool m_bufferOnIdle = true; + QString m_currentKey; + QString m_requestedCompressionScheme; +#if QT_CONFIG(zstd) + ZSTD_CCtx *m_zstdCCtx = nullptr; +#endif + + static constexpr quint32 ServerId = 1; + static constexpr quint32 DefaultMaxPackets = 256; // 1 MB +}; + +QT_END_NAMESPACE + +#endif |