From 65906c07fe8074013a52621fcc467e4bdfa0c51c Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 22 Jul 2009 12:54:35 +0000 Subject: [PATCH] 2009-07-22 Tatsuhiro Tsujikawa Rewritten stream error handling * src/DHTAutoSaveCommand.cc * src/DHTRoutingTableDeserializer.cc * src/DHTRoutingTableSerializer.cc * src/DHTSetup.cc --- ChangeLog | 8 + src/DHTAutoSaveCommand.cc | 21 ++- src/DHTRoutingTableDeserializer.cc | 257 ++++++++++++++++------------- src/DHTRoutingTableSerializer.cc | 84 +++++----- src/DHTSetup.cc | 18 +- 5 files changed, 213 insertions(+), 175 deletions(-) diff --git a/ChangeLog b/ChangeLog index ffd7b25f..40da4e48 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-07-22 Tatsuhiro Tsujikawa + + Rewritten stream error handling + * src/DHTAutoSaveCommand.cc + * src/DHTRoutingTableDeserializer.cc + * src/DHTRoutingTableSerializer.cc + * src/DHTSetup.cc + 2009-07-22 Tatsuhiro Tsujikawa Check stream status after file is opened. diff --git a/src/DHTAutoSaveCommand.cc b/src/DHTAutoSaveCommand.cc index aa4b34e4..11247a1b 100644 --- a/src/DHTAutoSaveCommand.cc +++ b/src/DHTAutoSaveCommand.cc @@ -53,6 +53,8 @@ #include "Logger.h" #include "a2functional.h" #include "FileEntry.h" +#include "DlAbortEx.h" +#include "StringFormat.h" namespace aria2 { @@ -112,21 +114,22 @@ void DHTAutoSaveCommand::save() serializer.setNodes(nodes); try { - std::ofstream o(tempFile.c_str(), std::ios::out|std::ios::binary); - o.exceptions(std::ios::failbit); - - serializer.serialize(o); - + { + std::ofstream o(tempFile.c_str(), std::ios::out|std::ios::binary); + if(!o) { + throw DL_ABORT_EX + (StringFormat("Failed to save DHT routing table to %s. cause:%s", + dhtFile.c_str(), strerror(errno)).str()); + } + serializer.serialize(o); + } if(!File(tempFile).renameTo(dhtFile)) { logger->error("Cannot move file from %s to %s.", tempFile.c_str(), dhtFile.c_str()); } - } catch(std::ios::failure const& e) { - logger->error("Failed to save DHT routing table to %s. cause:%s", - tempFile.c_str(), strerror(errno)); } catch(RecoverableException& e) { logger->error("Exception caught while saving DHT routing table to %s", - e, tempFile.c_str()); + e, dhtFile.c_str()); } } diff --git a/src/DHTRoutingTableDeserializer.cc b/src/DHTRoutingTableDeserializer.cc index c60172d4..73345ad5 100644 --- a/src/DHTRoutingTableDeserializer.cc +++ b/src/DHTRoutingTableDeserializer.cc @@ -56,136 +56,161 @@ DHTRoutingTableDeserializer::DHTRoutingTableDeserializer() {} DHTRoutingTableDeserializer::~DHTRoutingTableDeserializer() {} -static std::istream& readBytes(unsigned char* buf, size_t buflen, - std::istream& in, size_t readlen) +static void readBytes(unsigned char* buf, size_t buflen, + std::istream& in, size_t readlen) { assert(readlen <= buflen); - return in.read(reinterpret_cast(buf), readlen); + in.read(reinterpret_cast(buf), readlen); } +#define CHECK_STREAM(in, length) \ + if(in.gcount() != length) { \ + throw DL_ABORT_EX \ + (StringFormat("Failed to load DHT routing table. cause:%s", \ + "Unexpected EOF").str()); \ + } \ + if(!in) { \ + throw DL_ABORT_EX \ + (StringFormat("Failed to load DHT routing table. cause:%s", \ + strerror(errno)).str()); \ + } + void DHTRoutingTableDeserializer::deserialize(std::istream& in) { - try { - char header[8]; - memset(header, 0, sizeof(header)); - // magic - header[0] = 0xa1; - header[1] = 0xa2; - // format ID - header[2] = 0x02; - // version - header[6] = 0; - header[7] = 0x03; + char header[8]; + memset(header, 0, sizeof(header)); + // magic + header[0] = 0xa1; + header[1] = 0xa2; + // format ID + header[2] = 0x02; + // version + header[6] = 0; + header[7] = 0x03; - char headerCompat[8]; - memset(headerCompat, 0, sizeof(headerCompat)); - // magic - headerCompat[0] = 0xa1; - headerCompat[1] = 0xa2; - // format ID - headerCompat[2] = 0x02; - // version - headerCompat[6] = 0; - headerCompat[7] = 0x02; + char headerCompat[8]; + memset(headerCompat, 0, sizeof(headerCompat)); + // magic + headerCompat[0] = 0xa1; + headerCompat[1] = 0xa2; + // format ID + headerCompat[2] = 0x02; + // version + headerCompat[6] = 0; + headerCompat[7] = 0x02; - char zero[8]; - memset(zero, 0, sizeof(zero)); + char zero[8]; + memset(zero, 0, sizeof(zero)); - int version; + int version; - // If you change the code to read more than the size of buf, then - // expand the buf size here. - array_wrapper buf; + // If you change the code to read more than the size of buf, then + // expand the buf size here. + array_wrapper buf; - // header - readBytes(buf, buf.size(), in, 8); - if(memcmp(header, buf, 8) == 0) { - version = 3; - } else if(memcmp(headerCompat, buf, 8) == 0) { - version = 2; - } else { - throw DL_ABORT_EX - (StringFormat("Failed to load DHT routing table. cause:%s", - "bad header").str()); - } - - uint32_t temp32; - uint64_t temp64; - // time - if(version == 2) { - in.read(reinterpret_cast(&temp32), sizeof(temp32)); - _serializedTime.setTimeInSec(ntohl(temp32)); - // 4bytes reserved - readBytes(buf, buf.size(), in, 4); - } else { - in.read(reinterpret_cast(&temp64), sizeof(temp64)); - _serializedTime.setTimeInSec(ntoh64(temp64)); - } - - // localnode - // 8bytes reserved - readBytes(buf, buf.size(), in, 8); - // localnode ID - readBytes(buf, buf.size(), in, DHT_ID_LENGTH); - SharedHandle localNode(new DHTNode(buf)); - // 4bytes reserved - readBytes(buf, buf.size(), in, 4); - - // number of nodes - in.read(reinterpret_cast(&temp32), sizeof(temp32)); - uint32_t numNodes = ntohl(temp32); - // 4bytes reserved - readBytes(buf, buf.size(), in, 4); - - // nodes - for(size_t i = 0; i < numNodes; ++i) { - // Currently, only IPv4 addresses are supported. - // 1byte compact peer info length - uint8_t peerInfoLen; - in >> peerInfoLen; - if(peerInfoLen != 6) { - // skip this entry - readBytes(buf, buf.size(), in, 42+7+6); - continue; - } - // 7bytes reserved - readBytes(buf, buf.size(), in, 7); - // 6bytes compact peer info - readBytes(buf, buf.size(), in, 6); - if(memcmp(zero, buf, 6) == 0) { - // skip this entry - readBytes(buf, buf.size(), in, 42); - continue; - } - std::pair peer = - PeerMessageUtil::unpackcompact(buf); - if(peer.first.empty()) { - // skip this entry - readBytes(buf, buf.size(), in, 42); - continue; - } - // 2bytes reserved - readBytes(buf, buf.size(), in, 2); - // 16byte reserved - readBytes(buf, buf.size(), in, 16); - // localnode ID - readBytes(buf, buf.size(), in, DHT_ID_LENGTH); - - SharedHandle node(new DHTNode(buf)); - node->setIPAddress(peer.first); - node->setPort(peer.second); - // 4bytes reserved - readBytes(buf, buf.size(), in, 4); - - _nodes.push_back(node); - } - _localNode = localNode; - } catch(std::ios::failure const& exception) { - _nodes.clear(); + // header + readBytes(buf, buf.size(), in, 8); + CHECK_STREAM(in, 8); + if(memcmp(header, buf, 8) == 0) { + version = 3; + } else if(memcmp(headerCompat, buf, 8) == 0) { + version = 2; + } else { throw DL_ABORT_EX (StringFormat("Failed to load DHT routing table. cause:%s", - strerror(errno)).str()); + "bad header").str()); } + + uint32_t temp32; + uint64_t temp64; + // time + if(version == 2) { + in.read(reinterpret_cast(&temp32), sizeof(temp32)); + CHECK_STREAM(in, sizeof(temp32)); + _serializedTime.setTimeInSec(ntohl(temp32)); + // 4bytes reserved + readBytes(buf, buf.size(), in, 4); + CHECK_STREAM(in, 4); + } else { + in.read(reinterpret_cast(&temp64), sizeof(temp64)); + CHECK_STREAM(in, sizeof(temp64)); + _serializedTime.setTimeInSec(ntoh64(temp64)); + } + + // localnode + // 8bytes reserved + readBytes(buf, buf.size(), in, 8); + CHECK_STREAM(in, 8); + // localnode ID + readBytes(buf, buf.size(), in, DHT_ID_LENGTH); + CHECK_STREAM(in, DHT_ID_LENGTH); + SharedHandle localNode(new DHTNode(buf)); + // 4bytes reserved + readBytes(buf, buf.size(), in, 4); + CHECK_STREAM(in, 4); + + // number of nodes + in.read(reinterpret_cast(&temp32), sizeof(temp32)); + CHECK_STREAM(in, sizeof(temp32)); + uint32_t numNodes = ntohl(temp32); + // 4bytes reserved + readBytes(buf, buf.size(), in, 4); + CHECK_STREAM(in, 4); + + std::deque > nodes; + // nodes + for(size_t i = 0; i < numNodes; ++i) { + // Currently, only IPv4 addresses are supported. + // 1byte compact peer info length + uint8_t peerInfoLen; + in >> peerInfoLen; + if(peerInfoLen != 6) { + // skip this entry + readBytes(buf, buf.size(), in, 42+7+6); + CHECK_STREAM(in, 42+7+6); + continue; + } + // 7bytes reserved + readBytes(buf, buf.size(), in, 7); + CHECK_STREAM(in, 7); + // 6bytes compact peer info + readBytes(buf, buf.size(), in, 6); + CHECK_STREAM(in, 6); + if(memcmp(zero, buf, 6) == 0) { + // skip this entry + readBytes(buf, buf.size(), in, 42); + CHECK_STREAM(in, 42); + continue; + } + std::pair peer = + PeerMessageUtil::unpackcompact(buf); + if(peer.first.empty()) { + // skip this entry + readBytes(buf, buf.size(), in, 42); + CHECK_STREAM(in, 42); + continue; + } + // 2bytes reserved + readBytes(buf, buf.size(), in, 2); + CHECK_STREAM(in, 2); + // 16byte reserved + readBytes(buf, buf.size(), in, 16); + CHECK_STREAM(in, 16); + // localnode ID + readBytes(buf, buf.size(), in, DHT_ID_LENGTH); + CHECK_STREAM(in, DHT_ID_LENGTH); + + SharedHandle node(new DHTNode(buf)); + node->setIPAddress(peer.first); + node->setPort(peer.second); + // 4bytes reserved + readBytes(buf, buf.size(), in, 4); + CHECK_STREAM(in, 4); + + nodes.push_back(node); + } + _localNode = localNode; + _nodes = nodes; } } // namespace aria2 diff --git a/src/DHTRoutingTableSerializer.cc b/src/DHTRoutingTableSerializer.cc index 20b4767f..9228bbb4 100644 --- a/src/DHTRoutingTableSerializer.cc +++ b/src/DHTRoutingTableSerializer.cc @@ -76,51 +76,53 @@ void DHTRoutingTableSerializer::serialize(std::ostream& o) char zero[16]; memset(zero, 0, sizeof(zero)); - try { - o.write(header, 8); - // write save date - uint64_t ntime = hton64(Time().getTime()); - o.write(reinterpret_cast(&ntime), sizeof(ntime)); - // localnode - // 8bytes reserved - o.write(zero, 8); - // 20bytes localnode ID - o.write(reinterpret_cast(_localNode->getID()), DHT_ID_LENGTH); - // 4bytes reserved - o.write(zero, 4); + o.write(header, 8); + // write save date + uint64_t ntime = hton64(Time().getTime()); + o.write(reinterpret_cast(&ntime), sizeof(ntime)); - // number of nodes - uint32_t numNodes = htonl(_nodes.size()); - o.write(reinterpret_cast(&numNodes), sizeof(uint32_t)); - // 4bytes reserved - o.write(zero, 4); + // localnode + // 8bytes reserved + o.write(zero, 8); + // 20bytes localnode ID + o.write(reinterpret_cast(_localNode->getID()), DHT_ID_LENGTH); + // 4bytes reserved + o.write(zero, 4); - // nodes - for(std::deque >::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { - const SharedHandle& node = *i; - // Currently, only IPv4 address and IPv4-mapped address are saved. - // 6bytes: write IP address + port in Compact IP-address/port info form. - unsigned char compactPeer[6]; - if(!PeerMessageUtil::createcompact(compactPeer, node->getIPAddress(), node->getPort())) { - memset(compactPeer, 0, 6); - } - // 1byte compact peer format length - o << static_cast(sizeof(compactPeer)); - // 7bytes reserved - o.write(zero, 7); - // 6 bytes compact peer - o.write(reinterpret_cast(compactPeer), 6); - // 2bytes reserved - o.write(zero, 2); - // 16bytes reserved - o.write(zero, 16); - // 20bytes: node ID - o.write(reinterpret_cast(node->getID()), DHT_ID_LENGTH); - // 4bytes reserved - o.write(zero, 4); + // number of nodes + uint32_t numNodes = htonl(_nodes.size()); + o.write(reinterpret_cast(&numNodes), sizeof(uint32_t)); + // 4bytes reserved + o.write(zero, 4); + + // nodes + for(std::deque >::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i) { + const SharedHandle& node = *i; + // Currently, only IPv4 address and IPv4-mapped address are saved. + // 6bytes: write IP address + port in Compact IP-address/port info form. + unsigned char compactPeer[6]; + if(!PeerMessageUtil::createcompact(compactPeer, node->getIPAddress(), node->getPort())) { + memset(compactPeer, 0, 6); } - } catch(std::ios::failure const& exception) { + // 1byte compact peer format length + o << static_cast(sizeof(compactPeer)); + // 7bytes reserved + o.write(zero, 7); + // 6 bytes compact peer + o.write(reinterpret_cast(compactPeer), 6); + // 2bytes reserved + o.write(zero, 2); + // 16bytes reserved + o.write(zero, 16); + // 20bytes: node ID + o.write(reinterpret_cast(node->getID()), DHT_ID_LENGTH); + // 4bytes reserved + o.write(zero, 4); + } + + o.flush(); + if(!o) { throw DL_ABORT_EX (StringFormat("Failed to save DHT routing table. cause:%s", strerror(errno)).str()); diff --git a/src/DHTSetup.cc b/src/DHTSetup.cc index c77adc86..fddf21d6 100644 --- a/src/DHTSetup.cc +++ b/src/DHTSetup.cc @@ -94,16 +94,16 @@ void DHTSetup::setup(std::deque& commands, DHTRoutingTableDeserializer deserializer; std::string dhtFile = option->get(PREF_DHT_FILE_PATH); - if(File(dhtFile).isFile()) { - try { - std::ifstream in(dhtFile.c_str(), std::ios::binary); - in.exceptions(std::ios::failbit); - deserializer.deserialize(in); - localNode = deserializer.getLocalNode(); - } catch(RecoverableException& e) { - _logger->error("Exception caught while loading DHT routing table from %s", - e, dhtFile.c_str()); + try { + std::ifstream in(dhtFile.c_str(), std::ios::binary); + if(!in) { + throw DL_ABORT_EX("Could not open file"); } + deserializer.deserialize(in); + localNode = deserializer.getLocalNode(); + } catch(RecoverableException& e) { + _logger->error("Exception caught while loading DHT routing table from %s", + e, dhtFile.c_str()); } if(localNode.isNull()) { localNode.reset(new DHTNode());