File indexing completed on 2024-06-02 05:05:27

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "authenticatebase.h"
0007 #include <dht/dhtbase.h>
0008 #include <mse/encryptedpacketsocket.h>
0009 #include <peer/peerid.h>
0010 #include <torrent/globals.h>
0011 #include <util/log.h>
0012 #include <util/sha1hash.h>
0013 
0014 namespace bt
0015 {
0016 AuthenticateBase::AuthenticateBase()
0017     : finished(false)
0018     , local(false)
0019 {
0020     connect(&timer, &QTimer::timeout, this, &AuthenticateBase::onTimeout);
0021     timer.setSingleShot(true);
0022     timer.start(5000);
0023     memset(handshake, 0x00, 68);
0024     bytes_of_handshake_received = 0;
0025     ext_support = 0;
0026 }
0027 
0028 AuthenticateBase::AuthenticateBase(mse::EncryptedPacketSocket::Ptr s)
0029     : sock(s)
0030     , finished(false)
0031     , local(false)
0032 {
0033     connect(&timer, &QTimer::timeout, this, &AuthenticateBase::onTimeout);
0034     timer.setSingleShot(true);
0035     timer.start(5000);
0036     memset(handshake, 0x00, 68);
0037     bytes_of_handshake_received = 0;
0038     ext_support = 0;
0039 }
0040 
0041 AuthenticateBase::~AuthenticateBase()
0042 {
0043 }
0044 
0045 void AuthenticateBase::sendHandshake(const SHA1Hash &info_hash, const PeerID &our_peer_id)
0046 {
0047     //  Out() << "AuthenticateBase::sendHandshake" << endl;
0048     if (!sock)
0049         return;
0050 
0051     Uint8 hs[68];
0052     makeHandshake(hs, info_hash, our_peer_id);
0053     sock->sendData(hs, 68);
0054 }
0055 
0056 void AuthenticateBase::makeHandshake(Uint8 *hs, const SHA1Hash &info_hash, const PeerID &our_peer_id)
0057 {
0058     const char *pstr = "BitTorrent protocol";
0059     hs[0] = 19;
0060     memcpy(hs + 1, pstr, 19);
0061     memset(hs + 20, 0x00, 8);
0062     if (Globals::instance().getDHT().isRunning())
0063         hs[27] |= 0x01; // DHT support
0064     hs[25] |= 0x10; // extension protocol
0065     hs[27] |= 0x04; // fast extensions
0066     memcpy(hs + 28, info_hash.getData(), 20);
0067     memcpy(hs + 48, our_peer_id.data(), 20);
0068 }
0069 
0070 void AuthenticateBase::onReadyRead()
0071 {
0072     Uint32 ba = sock->bytesAvailable();
0073     //  Out() << "AuthenticateBase::onReadyRead " << ba << endl;
0074     if (ba == 0) {
0075         onFinish(false);
0076         return;
0077     }
0078 
0079     if (!sock || finished || ba < 48)
0080         return;
0081 
0082     // first see if we already have some bytes from the handshake
0083     if (bytes_of_handshake_received == 0) {
0084         if (ba < 68) {
0085             // read partial
0086             sock->readData(handshake, ba);
0087             bytes_of_handshake_received += ba;
0088             if (ba >= 27 && handshake[27] & 0x01)
0089                 ext_support |= bt::DHT_SUPPORT;
0090             // tell subclasses of a partial handshake
0091             handshakeReceived(false);
0092             return;
0093         } else {
0094             // read full handshake
0095             sock->readData(handshake, 68);
0096         }
0097     } else {
0098         // read remaining part
0099         Uint32 to_read = 68 - bytes_of_handshake_received;
0100         sock->readData(handshake + bytes_of_handshake_received, to_read);
0101     }
0102 
0103     if (handshake[0] != 19) {
0104         onFinish(false);
0105         return;
0106     }
0107 
0108     const char *pstr = "BitTorrent protocol";
0109     if (memcmp(pstr, handshake + 1, 19) != 0) {
0110         onFinish(false);
0111         return;
0112     }
0113 
0114     if (Globals::instance().getDHT().isRunning() && (handshake[27] & 0x01))
0115         ext_support |= bt::DHT_SUPPORT;
0116 
0117     if (handshake[27] & 0x04)
0118         ext_support |= bt::FAST_EXT_SUPPORT;
0119 
0120     if (handshake[25] & 0x10)
0121         ext_support |= bt::EXT_PROT_SUPPORT;
0122 
0123     handshakeReceived(true);
0124 }
0125 
0126 void AuthenticateBase::onError(int)
0127 {
0128     if (finished)
0129         return;
0130     onFinish(false);
0131 }
0132 
0133 void AuthenticateBase::onTimeout()
0134 {
0135     if (finished)
0136         return;
0137 
0138     Out(SYS_CON | LOG_DEBUG) << "Timeout occurred" << endl;
0139     onFinish(false);
0140 }
0141 
0142 void AuthenticateBase::onReadyWrite()
0143 {
0144 }
0145 }
0146 
0147 #include "moc_authenticatebase.cpp"