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
6QT_BEGIN_NAMESPACE
7
8LocalClientIo::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
17LocalClientIo::~LocalClientIo()
18{
19 close();
20}
21
22QIODevice *LocalClientIo::connection() const
23{
24 return m_socket;
25}
26
27void 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
37void LocalClientIo::doDisconnectFromServer()
38{
39 m_socket->disconnectFromServer();
40}
41
42void 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
52bool LocalClientIo::isOpen() const
53{
54 return !isClosing() && (m_socket->state() == QLocalSocket::ConnectedState
55 || m_socket->state() == QLocalSocket::ConnectingState);
56}
57
58void 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
81void 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
91LocalServerIo::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
99QIODevice *LocalServerIo::connection() const
100{
101 return m_connection;
102}
103
104void LocalServerIo::doClose()
105{
106 m_connection->disconnectFromServer();
107}
108
109LocalServerImpl::LocalServerImpl(QObject *parent)
110 : QConnectionAbstractServer(parent)
111{
112 connect(sender: &m_server, signal: &QLocalServer::newConnection, context: this, slot: &QConnectionAbstractServer::newConnection);
113}
114
115LocalServerImpl::~LocalServerImpl()
116{
117 m_server.close();
118}
119
120QtROServerIoDevice *LocalServerImpl::configureNewConnection()
121{
122 if (!m_server.isListening())
123 return nullptr;
124
125 return new LocalServerIo(m_server.nextPendingConnection(), this);
126}
127
128bool LocalServerImpl::hasPendingConnections() const
129{
130 return m_server.hasPendingConnections();
131}
132
133QUrl 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
142bool 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
160QAbstractSocket::SocketError LocalServerImpl::serverError() const
161{
162 return m_server.serverError();
163}
164
165void LocalServerImpl::close()
166{
167 m_server.close();
168}
169
170#ifdef Q_OS_LINUX
171
172AbstractLocalClientIo::AbstractLocalClientIo(QObject *parent)
173 : LocalClientIo(parent)
174{
175 m_socket->setSocketOptions(QLocalSocket::AbstractNamespaceOption);
176}
177
178AbstractLocalServerImpl::AbstractLocalServerImpl(QObject *parent)
179 : LocalServerImpl(parent)
180{
181 m_server.setSocketOptions(QLocalServer::AbstractNamespaceOption);
182}
183
184QUrl 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
195QT_END_NAMESPACE
196

source code of qtremoteobjects/src/remoteobjects/qconnection_local_backend.cpp