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 QHostAddress address(url().host());
49 if (address.isNull()) {
50 const QList<QHostAddress> addresses = QHostInfo::fromName(name: url().host()).addresses();
51 Q_ASSERT_X(addresses.size() >= 1, Q_FUNC_INFO, url().toString().toLatin1().data());
52 address = addresses.first();
53 }
54
55 m_socket->connectToHost(address, port: quint16(url().port()));
56}
57
58bool TcpClientIo::isOpen() const
59{
60 return (!isClosing() && (m_socket->state() == QAbstractSocket::ConnectedState
61 || m_socket->state() == QAbstractSocket::ConnectingState));
62}
63
64void TcpClientIo::onError(QAbstractSocket::SocketError error)
65{
66 qCDebug(QT_REMOTEOBJECT) << "onError" << error;
67
68 switch (error) {
69 case QAbstractSocket::HostNotFoundError: //Host not there, wait and try again
70 case QAbstractSocket::ConnectionRefusedError:
71 case QAbstractSocket::NetworkError:
72 emit shouldReconnect(this);
73 break;
74 case QAbstractSocket::AddressInUseError:
75 //... TODO error reporting
76 break;
77 default:
78 break;
79 }
80}
81
82void TcpClientIo::onStateChanged(QAbstractSocket::SocketState state)
83{
84 if (state == QAbstractSocket::ClosingState && !isClosing()) {
85 m_socket->abort();
86 emit shouldReconnect(this);
87 }
88 if (state == QAbstractSocket::ConnectedState)
89 initializeDataStream();
90}
91
92
93TcpServerIo::TcpServerIo(QTcpSocket *conn, QObject *parent)
94 : QtROServerIoDevice(parent), m_connection(conn)
95{
96 m_connection->setParent(this);
97 connect(sender: conn, signal: &QIODevice::readyRead, context: this, slot: &QtROServerIoDevice::readyRead);
98 connect(sender: conn, signal: &QAbstractSocket::disconnected, context: this, slot: &QtROServerIoDevice::disconnected);
99}
100
101QIODevice *TcpServerIo::connection() const
102{
103 return m_connection;
104}
105
106void TcpServerIo::doClose()
107{
108 m_connection->disconnectFromHost();
109}
110
111
112
113TcpServerImpl::TcpServerImpl(QObject *parent)
114 : QConnectionAbstractServer(parent)
115{
116 connect(sender: &m_server, signal: &QTcpServer::newConnection, context: this, slot: &QConnectionAbstractServer::newConnection);
117}
118
119TcpServerImpl::~TcpServerImpl()
120{
121 close();
122}
123
124QtROServerIoDevice *TcpServerImpl::configureNewConnection()
125{
126 if (!m_server.isListening())
127 return nullptr;
128
129 return new TcpServerIo(m_server.nextPendingConnection(), this);
130}
131
132bool TcpServerImpl::hasPendingConnections() const
133{
134 return m_server.hasPendingConnections();
135}
136
137QUrl TcpServerImpl::address() const
138{
139 return m_originalUrl;
140}
141
142bool TcpServerImpl::listen(const QUrl &address)
143{
144 QHostAddress host(address.host());
145 if (host.isNull()) {
146 if (address.host().isEmpty()) {
147 host = QHostAddress::Any;
148 } else {
149 qCWarning(QT_REMOTEOBJECT) << address.host() << " is not an IP address, trying to resolve it";
150 QHostInfo info = QHostInfo::fromName(name: address.host());
151 if (info.addresses().isEmpty())
152 host = QHostAddress::Any;
153 else
154 host = info.addresses().constFirst();
155 }
156 }
157
158 bool ret = m_server.listen(address: host, port: quint16(address.port()));
159 if (ret) {
160 m_originalUrl.setScheme(QLatin1String("tcp"));
161 m_originalUrl.setHost(host: m_server.serverAddress().toString());
162 m_originalUrl.setPort(m_server.serverPort());
163 }
164 return ret;
165}
166
167QAbstractSocket::SocketError TcpServerImpl::serverError() const
168{
169 return m_server.serverError();
170}
171
172void TcpServerImpl::close()
173{
174 m_server.close();
175}
176
177QT_END_NAMESPACE
178

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