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

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