File indexing completed on 2025-01-05 04:37:22

0001 /*
0002     SPDX-FileCopyrightText: 2010 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "peerconnector.h"
0008 #include "authenticationmonitor.h"
0009 #include "peermanager.h"
0010 #include <QPointer>
0011 #include <QSet>
0012 #include <interfaces/serverinterface.h>
0013 #include <mse/encryptedauthenticate.h>
0014 #include <torrent/torrent.h>
0015 #include <util/functions.h>
0016 
0017 namespace bt
0018 {
0019 static ResourceManager half_open_connections(50);
0020 
0021 class PeerConnector::Private
0022 {
0023 public:
0024     Private(PeerConnector *p, const net::Address &addr, bool local, PeerManager *pman, ConnectionLimit::Token::Ptr token)
0025         : p(p)
0026         , addr(addr)
0027         , local(local)
0028         , pman(pman)
0029         , stopping(false)
0030         , do_not_start(false)
0031         , token(token)
0032     {
0033     }
0034 
0035     ~Private()
0036     {
0037         if (auth.data()) {
0038             stopping = true;
0039             auth.data()->stop();
0040             stopping = false;
0041         }
0042     }
0043 
0044     void start(Method method);
0045     void authenticationFinished(Authenticate *auth, bool ok);
0046 
0047 public:
0048     PeerConnector *p;
0049     QSet<Method> tried_methods;
0050     Method current_method;
0051     net::Address addr;
0052     bool local;
0053     QPointer<PeerManager> pman;
0054     QPointer<Authenticate> auth;
0055     bool stopping;
0056     bool do_not_start;
0057     PeerConnector::WPtr self;
0058     ConnectionLimit::Token::Ptr token;
0059 };
0060 
0061 PeerConnector::PeerConnector(const net::Address &addr, bool local, bt::PeerManager *pman, ConnectionLimit::Token::Ptr token)
0062     : Resource(&half_open_connections, pman->getTorrent().getInfoHash().toString())
0063     , d(new Private(this, addr, local, pman, token))
0064 {
0065 }
0066 
0067 PeerConnector::~PeerConnector()
0068 {
0069     delete d;
0070 }
0071 
0072 void PeerConnector::setWeakPointer(PeerConnector::WPtr ptr)
0073 {
0074     d->self = ptr;
0075 }
0076 
0077 void PeerConnector::setMaxActive(Uint32 mc)
0078 {
0079     half_open_connections.setMaxActive(mc);
0080 }
0081 
0082 void PeerConnector::start()
0083 {
0084     half_open_connections.add(this);
0085 }
0086 
0087 void PeerConnector::acquired()
0088 {
0089     PeerManager *pm = d->pman.data();
0090     if (!pm || !pm->isStarted())
0091         return;
0092 
0093     bt::TransportProtocol primary = ServerInterface::primaryTransportProtocol();
0094     bool encryption = ServerInterface::isEncryptionEnabled();
0095     bool utp = ServerInterface::isUtpEnabled();
0096 
0097     if (encryption) {
0098         if (utp && primary == bt::UTP)
0099             d->start(UTP_WITH_ENCRYPTION);
0100         else
0101             d->start(TCP_WITH_ENCRYPTION);
0102     } else {
0103         if (utp && primary == bt::UTP)
0104             d->start(UTP_WITHOUT_ENCRYPTION);
0105         else
0106             d->start(TCP_WITHOUT_ENCRYPTION);
0107     }
0108 }
0109 
0110 void PeerConnector::authenticationFinished(Authenticate *auth, bool ok)
0111 {
0112     d->authenticationFinished(auth, ok);
0113 }
0114 
0115 void PeerConnector::Private::authenticationFinished(Authenticate *auth, bool ok)
0116 {
0117     this->auth.clear();
0118     if (stopping)
0119         return;
0120 
0121     PeerManager *pm = pman.data();
0122     if (!pm)
0123         return;
0124 
0125     if (ok) {
0126         pm->peerAuthenticated(auth, self, ok, token);
0127         return;
0128     }
0129 
0130     tried_methods.insert(current_method);
0131 
0132     bt::TransportProtocol primary = ServerInterface::primaryTransportProtocol();
0133     //      QList<Method> allowed;
0134 
0135     bool tcp_allowed = OpenFileAllowed();
0136     bool encryption = ServerInterface::isEncryptionEnabled();
0137     bool only_use_encryption = !ServerInterface::unencryptedConnectionsAllowed();
0138     bool utp = ServerInterface::isUtpEnabled();
0139     bool only_use_utp = ServerInterface::onlyUseUtp();
0140 
0141     if (primary == bt::UTP) {
0142         if (utp && encryption && !tried_methods.contains(UTP_WITH_ENCRYPTION))
0143             start(UTP_WITH_ENCRYPTION);
0144         else if (utp && !only_use_encryption && !tried_methods.contains(UTP_WITHOUT_ENCRYPTION))
0145             start(UTP_WITHOUT_ENCRYPTION);
0146         else if (!only_use_utp && encryption && !tried_methods.contains(TCP_WITH_ENCRYPTION) && tcp_allowed)
0147             start(TCP_WITH_ENCRYPTION);
0148         else if (!only_use_utp && !only_use_encryption && !tried_methods.contains(TCP_WITHOUT_ENCRYPTION) && tcp_allowed)
0149             start(TCP_WITHOUT_ENCRYPTION);
0150         else
0151             pm->peerAuthenticated(auth, self, false, token);
0152     } else { // Primary is TCP
0153         if (!only_use_utp && encryption && !tried_methods.contains(TCP_WITH_ENCRYPTION) && tcp_allowed)
0154             start(TCP_WITH_ENCRYPTION);
0155         else if (!only_use_utp && !only_use_encryption && !tried_methods.contains(TCP_WITHOUT_ENCRYPTION) && tcp_allowed)
0156             start(TCP_WITHOUT_ENCRYPTION);
0157         else if (utp && encryption && !tried_methods.contains(UTP_WITH_ENCRYPTION))
0158             start(UTP_WITH_ENCRYPTION);
0159         else if (utp && !only_use_encryption && !tried_methods.contains(UTP_WITHOUT_ENCRYPTION))
0160             start(UTP_WITHOUT_ENCRYPTION);
0161         else
0162             pm->peerAuthenticated(auth, self, false, token);
0163     }
0164 }
0165 
0166 void PeerConnector::Private::start(PeerConnector::Method method)
0167 {
0168     PeerManager *pm = pman.data();
0169     if (!pm)
0170         return;
0171 
0172     current_method = method;
0173     const Torrent &tor = pm->getTorrent();
0174     TransportProtocol proto = (method == TCP_WITH_ENCRYPTION || method == TCP_WITHOUT_ENCRYPTION) ? TCP : UTP;
0175     if (method == TCP_WITH_ENCRYPTION || method == UTP_WITH_ENCRYPTION)
0176         auth = new mse::EncryptedAuthenticate(addr, proto, tor.getInfoHash(), tor.getPeerID(), self);
0177     else
0178         auth = new Authenticate(addr, proto, tor.getInfoHash(), tor.getPeerID(), self);
0179 
0180     if (local)
0181         auth.data()->setLocal(true);
0182 
0183     AuthenticationMonitor::instance().add(auth.data());
0184 }
0185 
0186 }