1 | // Copyright (C) 2017 Ford Motor Company |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qconnection_local_backend_p.h" |
5 | |
6 | QT_BEGIN_NAMESPACE |
7 | |
8 | LocalClientIo::LocalClientIo(QObject *parent) |
9 | : QtROClientIoDevice(parent) |
10 | , m_socket(new QLocalSocket(this)) |
11 | { |
12 | connect(sender: m_socket, signal: &QLocalSocket::readyRead, context: this, slot: &QtROClientIoDevice::readyRead); |
13 | connect(sender: m_socket, signal: &QLocalSocket::errorOccurred, context: this, slot: &LocalClientIo::onError); |
14 | connect(sender: m_socket, signal: &QLocalSocket::stateChanged, context: this, slot: &LocalClientIo::onStateChanged); |
15 | } |
16 | |
17 | LocalClientIo::~LocalClientIo() |
18 | { |
19 | close(); |
20 | } |
21 | |
22 | QIODevice *LocalClientIo::connection() const |
23 | { |
24 | return m_socket; |
25 | } |
26 | |
27 | void LocalClientIo::doClose() |
28 | { |
29 | if (m_socket->isOpen()) { |
30 | connect(sender: m_socket, signal: &QLocalSocket::disconnected, context: this, slot: &QObject::deleteLater); |
31 | m_socket->disconnectFromServer(); |
32 | } else { |
33 | this->deleteLater(); |
34 | } |
35 | } |
36 | |
37 | void LocalClientIo::doDisconnectFromServer() |
38 | { |
39 | m_socket->disconnectFromServer(); |
40 | } |
41 | |
42 | void LocalClientIo::connectToServer() |
43 | { |
44 | #ifdef Q_OS_ANDROID |
45 | if (!m_socket->socketOptions().testFlag(QLocalSocket::AbstractNamespaceOption)) |
46 | qWarning() << "It is recommended to use 'localabstract' over 'local' on Android." ; |
47 | #endif |
48 | if (!isOpen()) |
49 | m_socket->connectToServer(name: url().path()); |
50 | } |
51 | |
52 | bool LocalClientIo::isOpen() const |
53 | { |
54 | return !isClosing() && (m_socket->state() == QLocalSocket::ConnectedState |
55 | || m_socket->state() == QLocalSocket::ConnectingState); |
56 | } |
57 | |
58 | void LocalClientIo::onError(QLocalSocket::LocalSocketError error) |
59 | { |
60 | qCDebug(QT_REMOTEOBJECT) << "onError" << error << m_socket->serverName(); |
61 | |
62 | switch (error) { |
63 | case QLocalSocket::ServerNotFoundError: |
64 | case QLocalSocket::UnknownSocketError: |
65 | case QLocalSocket::PeerClosedError: |
66 | //Host not there, wait and try again |
67 | emit shouldReconnect(this); |
68 | break; |
69 | case QLocalSocket::ConnectionError: |
70 | case QLocalSocket::ConnectionRefusedError: |
71 | //... TODO error reporting |
72 | #ifdef Q_OS_UNIX |
73 | emit shouldReconnect(this); |
74 | #endif |
75 | break; |
76 | default: |
77 | break; |
78 | } |
79 | } |
80 | |
81 | void LocalClientIo::onStateChanged(QLocalSocket::LocalSocketState state) |
82 | { |
83 | if (state == QLocalSocket::ClosingState && !isClosing()) { |
84 | m_socket->abort(); |
85 | emit shouldReconnect(this); |
86 | } |
87 | if (state == QLocalSocket::ConnectedState) |
88 | initializeDataStream(); |
89 | } |
90 | |
91 | LocalServerIo::LocalServerIo(QLocalSocket *conn, QObject *parent) |
92 | : QtROServerIoDevice(parent), m_connection(conn) |
93 | { |
94 | m_connection->setParent(this); |
95 | connect(sender: conn, signal: &QIODevice::readyRead, context: this, slot: &QtROServerIoDevice::readyRead); |
96 | connect(sender: conn, signal: &QLocalSocket::disconnected, context: this, slot: &QtROServerIoDevice::disconnected); |
97 | } |
98 | |
99 | QIODevice *LocalServerIo::connection() const |
100 | { |
101 | return m_connection; |
102 | } |
103 | |
104 | void LocalServerIo::doClose() |
105 | { |
106 | m_connection->disconnectFromServer(); |
107 | } |
108 | |
109 | LocalServerImpl::LocalServerImpl(QObject *parent) |
110 | : QConnectionAbstractServer(parent) |
111 | { |
112 | connect(sender: &m_server, signal: &QLocalServer::newConnection, context: this, slot: &QConnectionAbstractServer::newConnection); |
113 | } |
114 | |
115 | LocalServerImpl::~LocalServerImpl() |
116 | { |
117 | m_server.close(); |
118 | } |
119 | |
120 | QtROServerIoDevice *LocalServerImpl::configureNewConnection() |
121 | { |
122 | if (!m_server.isListening()) |
123 | return nullptr; |
124 | |
125 | return new LocalServerIo(m_server.nextPendingConnection(), this); |
126 | } |
127 | |
128 | bool LocalServerImpl::hasPendingConnections() const |
129 | { |
130 | return m_server.hasPendingConnections(); |
131 | } |
132 | |
133 | QUrl LocalServerImpl::address() const |
134 | { |
135 | QUrl result; |
136 | result.setPath(path: m_server.serverName()); |
137 | result.setScheme(QRemoteObjectStringLiterals::local()); |
138 | |
139 | return result; |
140 | } |
141 | |
142 | bool LocalServerImpl::listen(const QUrl &address) |
143 | { |
144 | #ifdef Q_OS_ANDROID |
145 | if (!m_server.socketOptions().testFlag(QLocalServer::AbstractNamespaceOption)) |
146 | qWarning() << "It is recommended to use 'localabstract' over 'local' on Android." ; |
147 | #endif |
148 | #ifdef Q_OS_UNIX |
149 | bool res = m_server.listen(name: address.path()); |
150 | if (!res) { |
151 | QLocalServer::removeServer(name: address.path()); |
152 | res = m_server.listen(name: address.path()); |
153 | } |
154 | return res; |
155 | #else |
156 | return m_server.listen(address.path()); |
157 | #endif |
158 | } |
159 | |
160 | QAbstractSocket::SocketError LocalServerImpl::serverError() const |
161 | { |
162 | return m_server.serverError(); |
163 | } |
164 | |
165 | void LocalServerImpl::close() |
166 | { |
167 | m_server.close(); |
168 | } |
169 | |
170 | #ifdef Q_OS_LINUX |
171 | |
172 | AbstractLocalClientIo::AbstractLocalClientIo(QObject *parent) |
173 | : LocalClientIo(parent) |
174 | { |
175 | m_socket->setSocketOptions(QLocalSocket::AbstractNamespaceOption); |
176 | } |
177 | |
178 | AbstractLocalServerImpl::AbstractLocalServerImpl(QObject *parent) |
179 | : LocalServerImpl(parent) |
180 | { |
181 | m_server.setSocketOptions(QLocalServer::AbstractNamespaceOption); |
182 | } |
183 | |
184 | QUrl AbstractLocalServerImpl::address() const |
185 | { |
186 | QUrl result; |
187 | result.setPath(path: m_server.serverName()); |
188 | result.setScheme(QRemoteObjectStringLiterals::localabstract()); |
189 | |
190 | return result; |
191 | } |
192 | |
193 | #endif // Q_OS_LINUX |
194 | |
195 | QT_END_NAMESPACE |
196 | |