2a80adc2f6
We don't key it on IP address anymore so we can drop the use of QMultiHash. This also requires moving the connections for error and disconnected to readyForUse so we don't remove an active connection when a second connection attempt happens from the same peer process. But since we still need to deallocate those connection attempts if they error out or simply disconnect, we connect their signals to the QObject::deleteLater slot. In some cases we might call deleteLater twice but that's fine. Change-Id: I48c27de1e51a52ef61cfb941a7a81b358ae9ce3f Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Konrad Kujawa <konrad.kujawa@qt.io>
95 lines
2.7 KiB
C++
95 lines
2.7 KiB
C++
// Copyright (C) 2016 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
|
|
#include "client.h"
|
|
#include "connection.h"
|
|
#include "peermanager.h"
|
|
|
|
#include <QHostInfo>
|
|
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
Client::Client()
|
|
: peerManager(new PeerManager(this))
|
|
{
|
|
peerManager->setServerPort(server.serverPort());
|
|
peerManager->startBroadcasting();
|
|
|
|
connect(peerManager, &PeerManager::newConnection,
|
|
this, &Client::newConnection);
|
|
connect(&server, &Server::newConnection,
|
|
this, &Client::newConnection);
|
|
}
|
|
|
|
void Client::sendMessage(const QString &message)
|
|
{
|
|
if (message.isEmpty())
|
|
return;
|
|
|
|
for (Connection *connection : std::as_const(peers))
|
|
connection->sendMessage(message);
|
|
}
|
|
|
|
QString Client::nickName() const
|
|
{
|
|
return peerManager->userName() + '@' + QHostInfo::localHostName()
|
|
+ ':' + QString::number(server.serverPort());
|
|
}
|
|
|
|
bool Client::hasConnection(const QByteArray &peerUniqueId) const
|
|
{
|
|
return peers.contains(peerUniqueId);
|
|
}
|
|
|
|
void Client::newConnection(Connection *connection)
|
|
{
|
|
connection->setGreetingMessage(peerManager->userName(), peerManager->uniqueId());
|
|
connect(connection, &Connection::readyForUse, this, &Client::readyForUse);
|
|
connect(connection, &Connection::errorOccurred, connection, &QObject::deleteLater);
|
|
connect(connection, &Connection::disconnected, connection, &QObject::deleteLater);
|
|
}
|
|
|
|
void Client::readyForUse()
|
|
{
|
|
Connection *connection = qobject_cast<Connection *>(sender());
|
|
if (!connection || hasConnection(connection->uniqueId())) {
|
|
if (connection) {
|
|
connection->disconnectFromHost();
|
|
connection->deleteLater();
|
|
}
|
|
return;
|
|
}
|
|
|
|
connect(connection, &Connection::errorOccurred, this, &Client::connectionError);
|
|
connect(connection, &Connection::disconnected, this, &Client::disconnected);
|
|
connect(connection, &Connection::newMessage, this, &Client::newMessage);
|
|
|
|
peers.insert(connection->uniqueId(), connection);
|
|
QString nick = connection->name();
|
|
if (!nick.isEmpty())
|
|
emit newParticipant(nick);
|
|
}
|
|
|
|
void Client::disconnected()
|
|
{
|
|
if (Connection *connection = qobject_cast<Connection *>(sender()))
|
|
removeConnection(connection);
|
|
}
|
|
|
|
void Client::connectionError(QAbstractSocket::SocketError /* socketError */)
|
|
{
|
|
if (Connection *connection = qobject_cast<Connection *>(sender()))
|
|
removeConnection(connection);
|
|
}
|
|
|
|
void Client::removeConnection(Connection *connection)
|
|
{
|
|
if (peers.remove(connection->uniqueId())) {
|
|
QString nick = connection->name();
|
|
if (!nick.isEmpty())
|
|
emit participantLeft(nick);
|
|
}
|
|
connection->deleteLater();
|
|
}
|