2008-10-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Made socket for dht connections non-blocking
	* src/DHTAbstractMessage.cc
	* src/DHTAbstractMessage.h
	* src/DHTConnection.h
	* src/DHTConnectionImpl.cc
	* src/DHTConnectionImpl.h
	* src/DHTMessage.h
	* src/DHTMessageDispatcherImpl.cc
	* src/DHTMessageDispatcherImpl.h
	* src/DHTUnknownMessage.cc
	* src/DHTUnknownMessage.h
	* src/SocketCore.cc
	* src/SocketCore.h
	* test/MockDHTMessage.h
pull/1/head
Tatsuhiro Tsujikawa 2008-10-05 13:21:14 +00:00
parent 04a2bd3818
commit 389f770008
14 changed files with 110 additions and 42 deletions

View File

@ -1,3 +1,20 @@
2008-10-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Made socket for dht connections non-blocking
* src/DHTAbstractMessage.cc
* src/DHTAbstractMessage.h
* src/DHTConnection.h
* src/DHTConnectionImpl.cc
* src/DHTConnectionImpl.h
* src/DHTMessage.h
* src/DHTMessageDispatcherImpl.cc
* src/DHTMessageDispatcherImpl.h
* src/DHTUnknownMessage.cc
* src/DHTUnknownMessage.h
* src/SocketCore.cc
* src/SocketCore.h
* test/MockDHTMessage.h
2008-10-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2008-10-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Changed the type of offset to int. Changed the type of offset to int.

View File

@ -33,6 +33,9 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DHTAbstractMessage.h" #include "DHTAbstractMessage.h"
#include <cassert>
#include "DHTNode.h" #include "DHTNode.h"
#include "BencodeVisitor.h" #include "BencodeVisitor.h"
#include "DHTConnection.h" #include "DHTConnection.h"
@ -64,13 +67,16 @@ std::string DHTAbstractMessage::getBencodedMessage()
return v.getBencodedData(); return v.getBencodedData();
} }
void DHTAbstractMessage::send() bool DHTAbstractMessage::send()
{ {
std::string message = getBencodedMessage(); std::string message = getBencodedMessage();
_connection->sendMessage(reinterpret_cast<const unsigned char*>(message.c_str()), ssize_t r = _connection->sendMessage
(reinterpret_cast<const unsigned char*>(message.c_str()),
message.size(), message.size(),
_remoteNode->getIPAddress(), _remoteNode->getIPAddress(),
_remoteNode->getPort()); _remoteNode->getPort());
assert(r >= 0);
return r == static_cast<ssize_t>(message.size());
} }
void DHTAbstractMessage::setConnection(const WeakHandle<DHTConnection>& connection) void DHTAbstractMessage::setConnection(const WeakHandle<DHTConnection>& connection)

View File

@ -62,7 +62,7 @@ public:
virtual ~DHTAbstractMessage(); virtual ~DHTAbstractMessage();
virtual void send(); virtual bool send();
virtual std::string getType() const = 0; virtual std::string getType() const = 0;

View File

@ -44,9 +44,11 @@ class DHTConnection {
public: public:
virtual ~DHTConnection() {} virtual ~DHTConnection() {}
virtual ssize_t receiveMessage(unsigned char* data, size_t len, std::string& host, uint16_t& port) = 0; virtual ssize_t receiveMessage(unsigned char* data, size_t len,
std::string& host, uint16_t& port) = 0;
virtual void sendMessage(const unsigned char* data, size_t len, const std::string& host, uint16_t port) = 0; virtual ssize_t sendMessage(const unsigned char* data, size_t len,
const std::string& host, uint16_t port) = 0;
}; };
} // namespace aria2 } // namespace aria2

View File

@ -33,12 +33,14 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DHTConnectionImpl.h" #include "DHTConnectionImpl.h"
#include <utility>
#include "LogFactory.h" #include "LogFactory.h"
#include "Logger.h" #include "Logger.h"
#include "RecoverableException.h" #include "RecoverableException.h"
#include "Util.h" #include "Util.h"
#include "Socket.h" #include "Socket.h"
#include <utility>
namespace aria2 { namespace aria2 {
@ -66,6 +68,7 @@ bool DHTConnectionImpl::bind(uint16_t& port)
{ {
try { try {
_socket->bind(port); _socket->bind(port);
_socket->setNonBlockingMode();
std::pair<std::string, uint16_t> svaddr; std::pair<std::string, uint16_t> svaddr;
_socket->getAddrInfo(svaddr); _socket->getAddrInfo(svaddr);
port = svaddr.second; port = svaddr.second;
@ -77,22 +80,24 @@ bool DHTConnectionImpl::bind(uint16_t& port)
return false; return false;
} }
ssize_t DHTConnectionImpl::receiveMessage(unsigned char* data, size_t len, std::string& host, uint16_t& port) ssize_t DHTConnectionImpl::receiveMessage(unsigned char* data, size_t len,
std::string& host, uint16_t& port)
{ {
if(_socket->isReadable(0)) {
std::pair<std::string, uint16_t> remoteHost; std::pair<std::string, uint16_t> remoteHost;
ssize_t length = _socket->readDataFrom(data, len, remoteHost); ssize_t length = _socket->readDataFrom(data, len, remoteHost);
if(length == 0) {
return length;
} else {
host = remoteHost.first; host = remoteHost.first;
port = remoteHost.second; port = remoteHost.second;
return length; return length;
} else {
return -1;
} }
} }
void DHTConnectionImpl::sendMessage(const unsigned char* data, size_t len, const std::string& host, uint16_t port) ssize_t DHTConnectionImpl::sendMessage(const unsigned char* data, size_t len,
const std::string& host, uint16_t port)
{ {
_socket->writeData(data, len, host, port); return _socket->writeData(data, len, host, port);
} }
SharedHandle<SocketCore> DHTConnectionImpl::getSocket() const SharedHandle<SocketCore> DHTConnectionImpl::getSocket() const

View File

@ -71,9 +71,11 @@ public:
*/ */
bool bind(uint16_t& port); bool bind(uint16_t& port);
virtual ssize_t receiveMessage(unsigned char* data, size_t len, std::string& host, uint16_t& port); virtual ssize_t receiveMessage(unsigned char* data, size_t len,
std::string& host, uint16_t& port);
virtual void sendMessage(const unsigned char* data, size_t len, const std::string& host, uint16_t port); virtual ssize_t sendMessage(const unsigned char* data, size_t len,
const std::string& host, uint16_t port);
SharedHandle<SocketCore> getSocket() const; SharedHandle<SocketCore> getSocket() const;
}; };

View File

@ -36,9 +36,11 @@
#define _D_DHT_MESSAGE_H_ #define _D_DHT_MESSAGE_H_
#include "common.h" #include "common.h"
#include <string>
#include "SharedHandle.h" #include "SharedHandle.h"
#include "A2STR.h" #include "A2STR.h"
#include <string>
namespace aria2 { namespace aria2 {
@ -71,7 +73,7 @@ public:
virtual void doReceivedAction() = 0; virtual void doReceivedAction() = 0;
virtual void send() = 0; virtual bool send() = 0;
virtual bool isReply() const = 0; virtual bool isReply() const = 0;

View File

@ -67,28 +67,38 @@ DHTMessageDispatcherImpl::addMessageToQueue(const SharedHandle<DHTMessage>& mess
addMessageToQueue(message, DHT_MESSAGE_TIMEOUT, callback); addMessageToQueue(message, DHT_MESSAGE_TIMEOUT, callback);
} }
void bool
DHTMessageDispatcherImpl::sendMessage(const SharedHandle<DHTMessageEntry>& entry) DHTMessageDispatcherImpl::sendMessage(const SharedHandle<DHTMessageEntry>& entry)
{ {
try { try {
entry->_message->send(); if(entry->_message->send()) {
if(!entry->_message->isReply()) { if(!entry->_message->isReply()) {
_tracker->addMessage(entry->_message, entry->_timeout, entry->_callback); _tracker->addMessage(entry->_message, entry->_timeout, entry->_callback);
} }
_logger->info("Message sent: %s", entry->_message->toString().c_str()); _logger->info("Message sent: %s", entry->_message->toString().c_str());
} else {
return false;
}
} catch(RecoverableException& e) { } catch(RecoverableException& e) {
_logger->error("Failed to send message: %s", e, entry->_message->toString().c_str()); _logger->error("Failed to send message: %s", e, entry->_message->toString().c_str());
} }
return true;
} }
void DHTMessageDispatcherImpl::sendMessages() void DHTMessageDispatcherImpl::sendMessages()
{ {
// TODO I can't use bind1st and mem_fun here because bind1st cannot bind a // TODO I can't use bind1st and mem_fun here because bind1st cannot bind a
// function which takes a reference as an argument.. // function which takes a reference as an argument..
for(std::deque<SharedHandle<DHTMessageEntry> >::iterator itr = _messageQueue.begin(); itr != _messageQueue.end(); ++itr) { std::deque<SharedHandle<DHTMessageEntry> >::iterator itr =
sendMessage(*itr); _messageQueue.begin();
for(; itr != _messageQueue.end(); ++itr) {
if(!sendMessage(*itr)) {
break;
} }
_messageQueue.clear(); }
_messageQueue.erase(_messageQueue.begin(), itr);
_logger->debug("%lu dht messages remaining in the queue.",
static_cast<unsigned long>(_messageQueue.size()));
} }
size_t DHTMessageDispatcherImpl::countMessageInQueue() const size_t DHTMessageDispatcherImpl::countMessageInQueue() const

View File

@ -52,7 +52,7 @@ private:
Logger* _logger; Logger* _logger;
void sendMessage(const SharedHandle<DHTMessageEntry>& msg); bool sendMessage(const SharedHandle<DHTMessageEntry>& msg);
public: public:
DHTMessageDispatcherImpl(const SharedHandle<DHTMessageTracker>& tracker); DHTMessageDispatcherImpl(const SharedHandle<DHTMessageTracker>& tracker);

View File

@ -33,9 +33,12 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DHTUnknownMessage.h" #include "DHTUnknownMessage.h"
#include <cstring>
#include <cstdlib>
#include "DHTNode.h" #include "DHTNode.h"
#include "Util.h" #include "Util.h"
#include <cstring>
namespace aria2 { namespace aria2 {
@ -66,7 +69,7 @@ DHTUnknownMessage::~DHTUnknownMessage()
void DHTUnknownMessage::doReceivedAction() {} void DHTUnknownMessage::doReceivedAction() {}
void DHTUnknownMessage::send() {} bool DHTUnknownMessage::send() { return true; }
bool DHTUnknownMessage::isReply() const bool DHTUnknownMessage::isReply() const
{ {

View File

@ -57,7 +57,7 @@ public:
virtual void doReceivedAction(); virtual void doReceivedAction();
// do nothing; we don't use this message as outgoing message. // do nothing; we don't use this message as outgoing message.
virtual void send(); virtual bool send();
// always return false // always return false
virtual bool isReply() const; virtual bool isReply() const;

View File

@ -839,8 +839,11 @@ bool SocketCore::initiateSecureConnection()
#endif // __MINGW32__ #endif // __MINGW32__
} }
void SocketCore::writeData(const char* data, size_t len, const std::string& host, uint16_t port) ssize_t SocketCore::writeData(const char* data, size_t len,
const std::string& host, uint16_t port)
{ {
_wantRead = false;
_wantWrite = false;
struct addrinfo hints; struct addrinfo hints;
struct addrinfo* res; struct addrinfo* res;
@ -861,17 +864,25 @@ void SocketCore::writeData(const char* data, size_t len, const std::string& host
if(r == static_cast<ssize_t>(len)) { if(r == static_cast<ssize_t>(len)) {
break; break;
} }
if(r == -1 && errno == EAGAIN) {
_wantWrite = true;
r = 0;
break;
}
} }
freeaddrinfo(res); freeaddrinfo(res);
if(r == -1) { if(r == -1) {
throw DlAbortEx(StringFormat(EX_SOCKET_SEND, errorMsg()).str()); throw DlAbortEx(StringFormat(EX_SOCKET_SEND, errorMsg()).str());
} }
return r;
} }
ssize_t SocketCore::readDataFrom(char* data, size_t len, ssize_t SocketCore::readDataFrom(char* data, size_t len,
std::pair<std::string /* numerichost */, std::pair<std::string /* numerichost */,
uint16_t /* port */>& sender) uint16_t /* port */>& sender)
{ {
_wantRead = false;
_wantWrite = false;
struct sockaddr_storage sockaddr; struct sockaddr_storage sockaddr;
socklen_t sockaddrlen = sizeof(struct sockaddr_storage); socklen_t sockaddrlen = sizeof(struct sockaddr_storage);
struct sockaddr* addrp = reinterpret_cast<struct sockaddr*>(&sockaddr); struct sockaddr* addrp = reinterpret_cast<struct sockaddr*>(&sockaddr);
@ -879,9 +890,15 @@ ssize_t SocketCore::readDataFrom(char* data, size_t len,
while((r = recvfrom(sockfd, data, len, 0, addrp, &sockaddrlen)) == -1 && while((r = recvfrom(sockfd, data, len, 0, addrp, &sockaddrlen)) == -1 &&
EINTR == errno); EINTR == errno);
if(r == -1) { if(r == -1) {
throw DlAbortEx(StringFormat(EX_SOCKET_RECV, errorMsg()).str()); if(errno == EAGAIN) {
_wantRead = true;
r = 0;
} else {
throw DlRetryEx(StringFormat(EX_SOCKET_RECV, errorMsg()).str());
} }
} else {
sender = Util::getNumericNameInfo(addrp, sockaddrlen); sender = Util::getNumericNameInfo(addrp, sockaddrlen);
}
return r; return r;
} }

View File

@ -222,12 +222,14 @@ public:
return writeData(reinterpret_cast<const char*>(data), len); return writeData(reinterpret_cast<const char*>(data), len);
} }
void writeData(const char* data, size_t len, const std::string& host, uint16_t port); ssize_t writeData(const char* data, size_t len,
const std::string& host, uint16_t port);
void writeData(const unsigned char* data, size_t len, const std::string& host, ssize_t writeData(const unsigned char* data, size_t len,
const std::string& host,
uint16_t port) uint16_t port)
{ {
writeData(reinterpret_cast<const char*>(data), len, host, port); return writeData(reinterpret_cast<const char*>(data), len, host, port);
} }
/** /**

View File

@ -2,9 +2,11 @@
#define _D_MOCK_DHT_MESSAGE_H_ #define _D_MOCK_DHT_MESSAGE_H_
#include "DHTMessage.h" #include "DHTMessage.h"
#include <deque>
#include "DHTNode.h" #include "DHTNode.h"
#include "Peer.h" #include "Peer.h"
#include <deque>
namespace aria2 { namespace aria2 {
@ -30,7 +32,7 @@ public:
virtual void doReceivedAction() {} virtual void doReceivedAction() {}
virtual void send() {} virtual bool send() { return true; }
virtual bool isReply() const { return _isReply; } virtual bool isReply() const { return _isReply; }