summaryrefslogtreecommitdiffstats
path: root/src/plugins/tracing/qctfserver_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/tracing/qctfserver_p.h')
-rw-r--r--src/plugins/tracing/qctfserver_p.h194
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