Rewritten NAT check handling.

We simplified PeerConnection::receiveHandshake().
DefaultBtMessageReceiver and PeerReceiverHandshakeCommand look
PeerConnection's buffer and do NAT check handling themselves.
pull/1/head
Tatsuhiro Tsujikawa 2011-01-09 23:57:07 +09:00
parent 1818f2ed55
commit 3e67079087
3 changed files with 60 additions and 50 deletions

View File

@ -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)) {
msg = messageFactory_->createHandshakeMessage(data, dataLength);
msg->validate();
}
}
// Handle tracker's NAT-checking feature
if(!handshakeSent_ && quickReply && peerConnection_->getBufferLength() >= 48){
handshakeSent_ = true; handshakeSent_ = true;
// check info_hash // check info_hash
if(memcmp(bittorrent::getInfoHash(downloadContext_), &data[28], if(memcmp(bittorrent::getInfoHash(downloadContext_),
peerConnection_->getBuffer()+28,
INFO_HASH_LENGTH) == 0) { INFO_HASH_LENGTH) == 0) {
sendHandshake(); sendHandshake();
} else {
throw DL_ABORT_EX
(fmt("Bad Info Hash %s",
util::toHex(peerConnection_->getBuffer()+28,
INFO_HASH_LENGTH).c_str()));
} }
} if(!msg &&
if(!retval) { peerConnection_->getBufferLength() ==
return SharedHandle<BtHandshakeMessage>(); BtHandshakeMessage::MESSAGE_LENGTH &&
} peerConnection_->receiveHandshake(data, dataLength)) {
SharedHandle<BtHandshakeMessage> msg = msg = messageFactory_->createHandshakeMessage(data, dataLength);
messageFactory_->createHandshakeMessage(data, dataLength);
msg->validate(); msg->validate();
}
}
return msg; return msg;
} }

View File

@ -182,19 +182,6 @@ 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_) {
// We have data in previous peek.
// There is a chance that socket is readable because of EOF, for example,
// official bttrack shutdowns socket after sending first 48 bytes of
// handshake in its NAT checking.
// So if there are data in resbuf_, return it without checking socket
// status.
//
// (!prevPeek_ && peek) effectively returns preset buffer.
prevPeek_ = false;
retval = BtHandshakeMessage::MESSAGE_LENGTH <= resbufLength_;
} else {
prevPeek_ = peek;
size_t remaining = BtHandshakeMessage::MESSAGE_LENGTH-resbufLength_; size_t remaining = BtHandshakeMessage::MESSAGE_LENGTH-resbufLength_;
if(remaining > 0) { if(remaining > 0) {
size_t temp = remaining; size_t temp = remaining;
@ -213,7 +200,6 @@ bool PeerConnection::receiveHandshake(unsigned char* data, size_t& dataLength,
retval = false; retval = false;
} }
} }
}
size_t writeLength = std::min(resbufLength_, dataLength); size_t writeLength = std::min(resbufLength_, dataLength);
memcpy(data, resbuf_, writeLength); memcpy(data, resbuf_, writeLength);
dataLength = writeLength; dataLength = writeLength;

View File

@ -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]);