1 | // Copyright (C) 2024 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QSOCKETABSTRACTION_P_H |
5 | #define QSOCKETABSTRACTION_P_H |
6 | |
7 | #include <private/qtnetworkglobal_p.h> |
8 | |
9 | #include <QtNetwork/qabstractsocket.h> |
10 | #if QT_CONFIG(localserver) |
11 | # include <QtNetwork/qlocalsocket.h> |
12 | #endif |
13 | |
14 | #include <QtCore/qxpfunctional.h> |
15 | |
16 | // |
17 | // W A R N I N G |
18 | // ------------- |
19 | // |
20 | // This file is not part of the Qt API. It exists for the convenience |
21 | // of the Network Access API. This header file may change from |
22 | // version to version without notice, or even be removed. |
23 | // |
24 | // We mean it. |
25 | // |
26 | |
27 | QT_BEGIN_NAMESPACE |
28 | |
29 | // Helper functions to deal with a QIODevice that is either a socket or a local |
30 | // socket. |
31 | namespace QSocketAbstraction { |
32 | template <typename Fn, typename... Args> |
33 | auto visit(Fn &&fn, QIODevice *socket, Args &&...args) |
34 | { |
35 | if (auto *s = qobject_cast<QAbstractSocket *>(object: socket)) |
36 | return std::forward<Fn>(fn)(s, std::forward<Args>(args)...); |
37 | #if QT_CONFIG(localserver) |
38 | if (auto *s = qobject_cast<QLocalSocket *>(object: socket)) |
39 | return std::forward<Fn>(fn)(s, std::forward<Args>(args)...); |
40 | #endif |
41 | Q_UNREACHABLE(); |
42 | } |
43 | |
44 | // Since QLocalSocket's LocalSocketState's values are defined as being equal |
45 | // to some of QAbstractSocket's SocketState's values, we can use the superset |
46 | // of the two as the return type. |
47 | inline QAbstractSocket::SocketState socketState(QIODevice *device) |
48 | { |
49 | auto getState = [](auto *s) { |
50 | using T = std::remove_pointer_t<decltype(s)>; |
51 | if constexpr (std::is_same_v<T, QAbstractSocket>) { |
52 | return s->state(); |
53 | #if QT_CONFIG(localserver) |
54 | } else if constexpr (std::is_same_v<T, QLocalSocket>) { |
55 | QLocalSocket::LocalSocketState st = s->state(); |
56 | return static_cast<QAbstractSocket::SocketState>(st); |
57 | #endif |
58 | } |
59 | Q_UNREACHABLE(); |
60 | }; |
61 | return visit(fn&: getState, socket: device); |
62 | } |
63 | |
64 | // Same as for socketState(), but for the errors |
65 | inline QAbstractSocket::SocketError socketError(QIODevice *device) |
66 | { |
67 | auto getError = [](auto *s) { |
68 | using T = std::remove_pointer_t<decltype(s)>; |
69 | if constexpr (std::is_same_v<T, QAbstractSocket>) { |
70 | return s->error(); |
71 | #if QT_CONFIG(localserver) |
72 | } else if constexpr (std::is_same_v<T, QLocalSocket>) { |
73 | QLocalSocket::LocalSocketError st = s->error(); |
74 | return static_cast<QAbstractSocket::SocketError>(st); |
75 | #endif |
76 | } |
77 | Q_UNREACHABLE(); |
78 | }; |
79 | return visit(fn&: getError, socket: device); |
80 | } |
81 | |
82 | inline QString socketPeerName(QIODevice *device) |
83 | { |
84 | auto getPeerName = [](auto *s) { |
85 | using T = std::remove_pointer_t<decltype(s)>; |
86 | if constexpr (std::is_same_v<T, QAbstractSocket>) { |
87 | return s->peerName(); |
88 | #if QT_CONFIG(localserver) |
89 | } else if constexpr (std::is_same_v<T, QLocalSocket>) { |
90 | return s->serverName(); |
91 | #endif |
92 | } |
93 | Q_UNREACHABLE(); |
94 | }; |
95 | return visit(fn&: getPeerName, socket: device); |
96 | } |
97 | } // namespace QSocketAbstraction |
98 | |
99 | QT_END_NAMESPACE |
100 | |
101 | #endif // QSOCKETABSTRACTION_P_H |
102 | |