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_tcpip_backend_p.h"
5
6#include <QtNetwork/qhostinfo.h>
7
8QT_BEGIN_NAMESPACE
9
10TcpClientIo::TcpClientIo(QObject *parent)
11 : QtROClientIoDevice(parent)
12 , m_socket(new QTcpSocket(this))
13{
14 connect(sender: m_socket, signal: &QTcpSocket::readyRead, context: this, slot: &QtROClientIoDevice::readyRead);
15 connect(sender: m_socket, signal: &QAbstractSocket::errorOccurred, context: this, slot: &TcpClientIo::onError);
16 connect(sender: m_socket, signal: &QTcpSocket::stateChanged, context: this, slot: &TcpClientIo::onStateChanged);
17}
18
19TcpClientIo::~TcpClientIo()
20{
21 close();
22}
23
24QIODevice *TcpClientIo::connection() const
25{
26 return m_socket;
27}
28
29void TcpClientIo::doClose()
30{
31 if (m_socket->isOpen()) {
32 connect(sender: m_socket, signal: &QTcpSocket::disconnected, context: this, slot: &QObject::deleteLater);
33 m_socket->disconnectFromHost();
34 } else {
35 this->deleteLater();
36 }
37}
38
39void TcpClientIo::doDisconnectFromServer()
40{
41 m_socket->disconnectFromHost();
42}
43
44void TcpClientIo::connectToServer()
45{
46 if (isOpen())
47 return;
48 const QString &host = url().host();
49 QHostAddress address(host);
50 if (address.isNull())
51 address = QHostInfo::fromName(name: host).addresses().value(i: 0);
52
53 if (address.isNull())
54 qWarning(msg: "connectToServer(): Failed to resolve host %s", qUtf8Printable(host));
55 else
56 m_socket->connectToHost(address, port: url().port());
57}
58
59bool TcpClientIo::isOpen() const
60{
61 return (!isClosing() && (m_socket->state() == QAbstractSocket::ConnectedState
62 || m_socket->state() == QAbstractSocket::ConnectingState));
63}
64
65void TcpClientIo::onError(QAbstractSocket::SocketError error)
66{
67 qCDebug(QT_REMOTEOBJECT) << "onError" << error;
68
69 switch (error) {
70 case QAbstractSocket::HostNotFoundError: //Host not there, wait and try again
71 case QAbstractSocket::ConnectionRefusedError:
72 case QAbstractSocket::NetworkError:
73 emit shouldReconnect(this);
74 break;
75 case QAbstractSocket::AddressInUseError:
76 //... TODO error reporting
77 break;
78 default:
79 break;
80 }
81}
82
83void TcpClientIo::onStateChanged(QAbstractSocket::SocketState state)
84{
85 if (state == QAbstractSocket::ClosingState && !isClosing()) {
86 m_socket->abort();
87 emit shouldReconnect(this);
88 }
89 if (state == QAbstractSocket::ConnectedState)
90 initializeDataStream();
91}
92
93
94TcpServerIo::TcpServerIo(QTcpSocket *conn, QObject *parent)
95 : QtROServerIoDevice(parent), m_connection(conn)
96{
97 m_connection->setParent(this);
98 connect(sender: conn, signal: &QIODevice::readyRead, context: this, slot: &QtROServerIoDevice::readyRead);
99 connect(sender: conn, signal: &QAbstractSocket::disconnected, context: this, slot: &QtROServerIoDevice::disconnected);
100}
101
102QIODevice *TcpServerIo::connection() const
103{
104 return m_connection;
105}
106
107void TcpServerIo::doClose()
108{
109 m_connection->disconnectFromHost();
110}
111
112
113
114TcpServerImpl::TcpServerImpl(QObject *parent)
115 : QConnectionAbstractServer(parent)
116{
117 connect(sender: &m_server, signal: &QTcpServer::newConnection, context: this, slot: &QConnectionAbstractServer::newConnection);
118}
119
120TcpServerImpl::~TcpServerImpl()
121{
122 close();
123}
124
125QtROServerIoDevice *TcpServerImpl::configureNewConnection()
126{
127 if (!m_server.isListening())
128 return nullptr;
129
130 return new TcpServerIo(m_server.nextPendingConnection(), this);
131}
132
133bool TcpServerImpl::hasPendingConnections() const
134{
135 return m_server.hasPendingConnections();
136}
137
138QUrl TcpServerImpl::address() const
139{
140 return m_originalUrl;
141}
142
143bool TcpServerImpl::listen(const QUrl &address)
144{
145 QHostAddress host(address.host());
146 if (host.isNull()) {
147 if (address.host().isEmpty()) {
148 host = QHostAddress::Any;
149 } else {
150 qCWarning(QT_REMOTEOBJECT) << address.host() << " is not an IP address, trying to resolve it";
151 QHostInfo info = QHostInfo::fromName(name: address.host());
152 if (info.addresses().isEmpty())
153 host = QHostAddress::Any;
154 else
155 host = info.addresses().constFirst();
156 }
157 }
158
159 bool ret = m_server.listen(address: host, port: quint16(address.port()));
160 if (ret) {
161 m_originalUrl.setScheme(QLatin1String("tcp"));
162 m_originalUrl.setHost(host: m_server.serverAddress().toString());
163 m_originalUrl.setPort(m_server.serverPort());
164 }
165 return ret;
166}
167
168QAbstractSocket::SocketError TcpServerImpl::serverError() const
169{
170 return m_server.serverError();
171}
172
173void TcpServerImpl::close()
174{
175 m_server.close();
176}
177
178QT_END_NAMESPACE
179

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