/* * This file is part of the Flowee project * Copyright (C) 2016, 2019-2025 Tom Zander * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "NetworkConnection.h" #include "NetworkManager.h" #include "NetworkManager_p.h" #include NetworkConnection::NetworkConnection() : m_id(-1), m_callbacksId(-1) { } NetworkConnection::NetworkConnection(NetworkManager *parent, int id) : m_id(id), m_callbacksId(-1) { auto priv = parent->priv().lock(); if (priv) { auto iter = priv->connections.find(id); if (iter != priv->connections.end()) m_parent = iter->second; } } NetworkConnection::NetworkConnection(std::shared_ptr &parent, int id) : m_parent(parent), m_id(id), m_callbacksId(-1) { } NetworkConnection::NetworkConnection(NetworkConnection &&other) : m_parent(std::move(other.m_parent)), m_id(other.m_id), m_callbacksId(other.m_callbacksId) { other.m_id = -1; other.m_parent.reset(); } NetworkConnection& NetworkConnection::operator=(NetworkConnection && other) { if (other.m_id != m_id && m_callbacksId != -1) clear(); m_parent = std::move(other.m_parent); other.m_parent.reset(); m_id = other.m_id; other.m_id = -1; m_callbacksId = other.m_callbacksId; other.m_callbacksId = -1; return *this; } void NetworkConnection::dummy() const { // intentionally empty } void NetworkConnection::clear() { auto d = m_parent.lock(); if (d) { if (m_callbacksId >= 0) { d->m_strand.post(std::bind(&NetworkManagerConnection::removeAllCallbacksFor, d, m_callbacksId), std::allocator()); } m_callbacksId = -1; m_parent.reset(); } } NetworkConnection::~NetworkConnection() { clear(); } bool NetworkConnection::isValid() const { if (m_id <= 0) // default constructor called return false; auto d = m_parent.lock(); return d != nullptr; } bool NetworkConnection::isConnected() const { auto d = m_parent.lock(); if (d) return d->isConnected(); return false; } EndPoint NetworkConnection::endPoint() const { auto d = m_parent.lock(); if (d) return d->endPoint(); return EndPoint(); } void NetworkConnection::accept(AcceptLimit cl) { auto d = m_parent.lock(); if (d && d->isConnected()) d->accept(cl); } void NetworkConnection::connect() { auto d = m_parent.lock(); if (d.get()) d->connect(); } void NetworkConnection::disconnect() { auto d = m_parent.lock(); if (d) { if (d->m_strand.running_in_this_thread()) d->disconnect(); else d->m_strand.post(std::bind(&NetworkManagerConnection::disconnect, d), std::allocator()); } } void NetworkConnection::shutdown() { auto d = m_parent.lock(); if (d) d->m_strand.post(std::bind(&NetworkManagerConnection::recycleConnection, d), std::allocator()); } void NetworkConnection::send(const Message &message, MessagePriority priority) { auto d = m_parent.lock(); if (d) d->queueMessage(message, priority); } void NetworkConnection::setOnConnected(const std::function &callback) { auto d = m_parent.lock(); if (d) { if (m_callbacksId < 0) m_callbacksId = d->nextCallbackId(); d->m_strand.dispatch(std::bind(&NetworkManagerConnection::addOnConnectedCallback, d, m_callbacksId, callback), std::allocator()); } } void NetworkConnection::setOnDisconnected(const std::function &callback) { auto d = m_parent.lock(); if (d) { if (m_callbacksId < 0) m_callbacksId = d->nextCallbackId(); d->m_strand.dispatch(std::bind(&NetworkManagerConnection::addOnDisconnectedCallback, d, m_callbacksId, callback), std::allocator()); } } void NetworkConnection::setOnIncomingMessage(const std::function &callback) { auto d = m_parent.lock(); if (d) { if (m_callbacksId < 0) m_callbacksId = d->nextCallbackId(); d->m_strand.dispatch(std::bind(&NetworkManagerConnection::addOnIncomingMessageCallback, d, m_callbacksId, callback), std::allocator()); } } void NetworkConnection::setOnError(const std::function &callback) { auto d = m_parent.lock(); if (d) { if (m_callbacksId < 0) m_callbacksId = d->nextCallbackId(); d->m_strand.dispatch(std::bind(&NetworkManagerConnection::addOnError, d, m_callbacksId, callback), std::allocator()); } } void NetworkConnection::setLoginMessageCreator(const std::function &creator) { auto d = m_parent.lock(); if (d) { d->m_strand.dispatch(std::bind(&NetworkManagerConnection::setLoginCreator, d, creator), std::allocator()); } } void NetworkConnection::punishPeer(int punishment) { auto d = m_parent.lock(); if (d.get()) { d->punish(punishment); } } void NetworkConnection::postOnStrand(const std::function &task) { auto d = m_parent.lock(); if (d) d->runOnStrand(task); } void NetworkConnection::setMessageHeaderLegacy(bool on) { auto d = m_parent.lock(); if (d) d->setMessageHeaderType(on ? NetworkManagerConnection::LegacyP2P : NetworkManagerConnection::FloweeNative); } void NetworkConnection::setMessageQueueSizes(int main, int priority) { assert(main >= 10); assert(priority >= 3); auto d = m_parent.lock(); if (d) d->setMessageQueueSizes(main, priority); } void NetworkConnection::setCertificate(const Streaming::ConstBuffer &buffer) { assert(!buffer.isEmpty()); auto d = m_parent.lock(); if (d) { if (!d->endPoint().encrypted) throw std::runtime_error("Mismatch, not encrypted connection"); d->setCertificate(buffer); } }