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 }