mirror of https://github.com/aria2/aria2
Rewritten NAT check handling.
We simplified PeerConnection::receiveHandshake(). DefaultBtMessageReceiver and PeerReceiverHandshakeCommand look PeerConnection's buffer and do NAT check handling themselves.pull/1/head
parent
1818f2ed55
commit
3e67079087
|
@ -47,6 +47,9 @@
|
||||||
#include "LogFactory.h"
|
#include "LogFactory.h"
|
||||||
#include "bittorrent_helper.h"
|
#include "bittorrent_helper.h"
|
||||||
#include "BtPieceMessage.h"
|
#include "BtPieceMessage.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "fmt.h"
|
||||||
|
#include "DlAbortEx.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -60,24 +63,40 @@ DefaultBtMessageReceiver::DefaultBtMessageReceiver():
|
||||||
SharedHandle<BtHandshakeMessage>
|
SharedHandle<BtHandshakeMessage>
|
||||||
DefaultBtMessageReceiver::receiveHandshake(bool quickReply)
|
DefaultBtMessageReceiver::receiveHandshake(bool quickReply)
|
||||||
{
|
{
|
||||||
|
A2_LOG_DEBUG
|
||||||
|
(fmt("Receiving handshake bufferLength=%lu",
|
||||||
|
static_cast<unsigned long>(peerConnection_->getBufferLength())));
|
||||||
unsigned char data[BtHandshakeMessage::MESSAGE_LENGTH];
|
unsigned char data[BtHandshakeMessage::MESSAGE_LENGTH];
|
||||||
size_t dataLength = BtHandshakeMessage::MESSAGE_LENGTH;
|
size_t dataLength = BtHandshakeMessage::MESSAGE_LENGTH;
|
||||||
bool retval = peerConnection_->receiveHandshake(data, dataLength);
|
SharedHandle<BtHandshakeMessage> msg;
|
||||||
// To handle tracker's NAT-checking feature
|
if(handshakeSent_ || !quickReply || peerConnection_->getBufferLength() < 48) {
|
||||||
if(!handshakeSent_ && quickReply && dataLength >= 48) {
|
if(peerConnection_->receiveHandshake(data, dataLength)) {
|
||||||
handshakeSent_ = true;
|
msg = messageFactory_->createHandshakeMessage(data, dataLength);
|
||||||
// check info_hash
|
msg->validate();
|
||||||
if(memcmp(bittorrent::getInfoHash(downloadContext_), &data[28],
|
|
||||||
INFO_HASH_LENGTH) == 0) {
|
|
||||||
sendHandshake();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!retval) {
|
// Handle tracker's NAT-checking feature
|
||||||
return SharedHandle<BtHandshakeMessage>();
|
if(!handshakeSent_ && quickReply && peerConnection_->getBufferLength() >= 48){
|
||||||
|
handshakeSent_ = true;
|
||||||
|
// check info_hash
|
||||||
|
if(memcmp(bittorrent::getInfoHash(downloadContext_),
|
||||||
|
peerConnection_->getBuffer()+28,
|
||||||
|
INFO_HASH_LENGTH) == 0) {
|
||||||
|
sendHandshake();
|
||||||
|
} else {
|
||||||
|
throw DL_ABORT_EX
|
||||||
|
(fmt("Bad Info Hash %s",
|
||||||
|
util::toHex(peerConnection_->getBuffer()+28,
|
||||||
|
INFO_HASH_LENGTH).c_str()));
|
||||||
|
}
|
||||||
|
if(!msg &&
|
||||||
|
peerConnection_->getBufferLength() ==
|
||||||
|
BtHandshakeMessage::MESSAGE_LENGTH &&
|
||||||
|
peerConnection_->receiveHandshake(data, dataLength)) {
|
||||||
|
msg = messageFactory_->createHandshakeMessage(data, dataLength);
|
||||||
|
msg->validate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SharedHandle<BtHandshakeMessage> msg =
|
|
||||||
messageFactory_->createHandshakeMessage(data, dataLength);
|
|
||||||
msg->validate();
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -182,36 +182,22 @@ bool PeerConnection::receiveHandshake(unsigned char* data, size_t& dataLength,
|
||||||
("More than BtHandshakeMessage::MESSAGE_LENGTH bytes are buffered.");
|
("More than BtHandshakeMessage::MESSAGE_LENGTH bytes are buffered.");
|
||||||
}
|
}
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
if(((!prevPeek_ && peek) || (prevPeek_ && !peek)) && resbufLength_) {
|
size_t remaining = BtHandshakeMessage::MESSAGE_LENGTH-resbufLength_;
|
||||||
// We have data in previous peek.
|
if(remaining > 0) {
|
||||||
// There is a chance that socket is readable because of EOF, for example,
|
size_t temp = remaining;
|
||||||
// official bttrack shutdowns socket after sending first 48 bytes of
|
readData(resbuf_+resbufLength_, remaining, encryptionEnabled_);
|
||||||
// handshake in its NAT checking.
|
if(remaining == 0 && !socket_->wantRead() && !socket_->wantWrite()) {
|
||||||
// So if there are data in resbuf_, return it without checking socket
|
// we got EOF
|
||||||
// status.
|
A2_LOG_DEBUG
|
||||||
//
|
(fmt("CUID#%lld - In PeerConnection::receiveHandshake(), remain=%lu",
|
||||||
// (!prevPeek_ && peek) effectively returns preset buffer.
|
cuid_,
|
||||||
prevPeek_ = false;
|
static_cast<unsigned long>(temp)));
|
||||||
retval = BtHandshakeMessage::MESSAGE_LENGTH <= resbufLength_;
|
peer_->setDisconnectedGracefully(true);
|
||||||
} else {
|
throw DL_ABORT_EX(EX_EOF_FROM_PEER);
|
||||||
prevPeek_ = peek;
|
}
|
||||||
size_t remaining = BtHandshakeMessage::MESSAGE_LENGTH-resbufLength_;
|
resbufLength_ += remaining;
|
||||||
if(remaining > 0) {
|
if(BtHandshakeMessage::MESSAGE_LENGTH > resbufLength_) {
|
||||||
size_t temp = remaining;
|
retval = false;
|
||||||
readData(resbuf_+resbufLength_, remaining, encryptionEnabled_);
|
|
||||||
if(remaining == 0 && !socket_->wantRead() && !socket_->wantWrite()) {
|
|
||||||
// we got EOF
|
|
||||||
A2_LOG_DEBUG
|
|
||||||
(fmt("CUID#%lld - In PeerConnection::receiveHandshake(), remain=%lu",
|
|
||||||
cuid_,
|
|
||||||
static_cast<unsigned long>(temp)));
|
|
||||||
peer_->setDisconnectedGracefully(true);
|
|
||||||
throw DL_ABORT_EX(EX_EOF_FROM_PEER);
|
|
||||||
}
|
|
||||||
resbufLength_ += remaining;
|
|
||||||
if(BtHandshakeMessage::MESSAGE_LENGTH > resbufLength_) {
|
|
||||||
retval = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size_t writeLength = std::min(resbufLength_, dataLength);
|
size_t writeLength = std::min(resbufLength_, dataLength);
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
*/
|
*/
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#include "PeerReceiveHandshakeCommand.h"
|
#include "PeerReceiveHandshakeCommand.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "PeerConnection.h"
|
#include "PeerConnection.h"
|
||||||
#include "DownloadEngine.h"
|
#include "DownloadEngine.h"
|
||||||
#include "BtHandshakeMessage.h"
|
#include "BtHandshakeMessage.h"
|
||||||
|
@ -87,13 +90,15 @@ bool PeerReceiveHandshakeCommand::exitBeforeExecute()
|
||||||
|
|
||||||
bool PeerReceiveHandshakeCommand::executeInternal()
|
bool PeerReceiveHandshakeCommand::executeInternal()
|
||||||
{
|
{
|
||||||
unsigned char data[BtHandshakeMessage::MESSAGE_LENGTH];
|
// Handle tracker's NAT-checking feature
|
||||||
size_t dataLength = BtHandshakeMessage::MESSAGE_LENGTH;
|
if(peerConnection_->getBufferLength() < 48) {
|
||||||
// ignore return value. The received data is kept in PeerConnection object
|
size_t dataLength = 0;
|
||||||
// because of peek = true.
|
// Ignore return value. The received data is kept in
|
||||||
peerConnection_->receiveHandshake(data, dataLength, true);
|
// PeerConnection object because of peek = true.
|
||||||
// To handle tracker's NAT-checking feature
|
peerConnection_->receiveHandshake(0, dataLength, true);
|
||||||
if(dataLength >= 48) {
|
}
|
||||||
|
if(peerConnection_->getBufferLength() >= 48) {
|
||||||
|
const unsigned char* data = peerConnection_->getBuffer();
|
||||||
// check info_hash
|
// check info_hash
|
||||||
std::string infoHash = std::string(&data[28], &data[28+INFO_HASH_LENGTH]);
|
std::string infoHash = std::string(&data[28], &data[28+INFO_HASH_LENGTH]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue