Cory Fields
9 years ago
5 changed files with 323 additions and 292 deletions
@ -0,0 +1,218 @@
@@ -0,0 +1,218 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "addrdb.h" |
||||
|
||||
#include "addrman.h" |
||||
#include "chainparams.h" |
||||
#include "clientversion.h" |
||||
#include "hash.h" |
||||
#include "random.h" |
||||
#include "streams.h" |
||||
#include "tinyformat.h" |
||||
#include "util.h" |
||||
|
||||
#include <boost/filesystem.hpp> |
||||
|
||||
CBanDB::CBanDB() |
||||
{ |
||||
pathBanlist = GetDataDir() / "banlist.dat"; |
||||
} |
||||
|
||||
bool CBanDB::Write(const banmap_t& banSet) |
||||
{ |
||||
// Generate random temporary filename
|
||||
unsigned short randv = 0; |
||||
GetRandBytes((unsigned char*)&randv, sizeof(randv)); |
||||
std::string tmpfn = strprintf("banlist.dat.%04x", randv); |
||||
|
||||
// serialize banlist, checksum data up to that point, then append csum
|
||||
CDataStream ssBanlist(SER_DISK, CLIENT_VERSION); |
||||
ssBanlist << FLATDATA(Params().MessageStart()); |
||||
ssBanlist << banSet; |
||||
uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end()); |
||||
ssBanlist << hash; |
||||
|
||||
// open temp output file, and associate with CAutoFile
|
||||
boost::filesystem::path pathTmp = GetDataDir() / tmpfn; |
||||
FILE *file = fopen(pathTmp.string().c_str(), "wb"); |
||||
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); |
||||
if (fileout.IsNull()) |
||||
return error("%s: Failed to open file %s", __func__, pathTmp.string()); |
||||
|
||||
// Write and commit header, data
|
||||
try { |
||||
fileout << ssBanlist; |
||||
} |
||||
catch (const std::exception& e) { |
||||
return error("%s: Serialize or I/O error - %s", __func__, e.what()); |
||||
} |
||||
FileCommit(fileout.Get()); |
||||
fileout.fclose(); |
||||
|
||||
// replace existing banlist.dat, if any, with new banlist.dat.XXXX
|
||||
if (!RenameOver(pathTmp, pathBanlist)) |
||||
return error("%s: Rename-into-place failed", __func__); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
bool CBanDB::Read(banmap_t& banSet) |
||||
{ |
||||
// open input file, and associate with CAutoFile
|
||||
FILE *file = fopen(pathBanlist.string().c_str(), "rb"); |
||||
CAutoFile filein(file, SER_DISK, CLIENT_VERSION); |
||||
if (filein.IsNull()) |
||||
return error("%s: Failed to open file %s", __func__, pathBanlist.string()); |
||||
|
||||
// use file size to size memory buffer
|
||||
uint64_t fileSize = boost::filesystem::file_size(pathBanlist); |
||||
uint64_t dataSize = 0; |
||||
// Don't try to resize to a negative number if file is small
|
||||
if (fileSize >= sizeof(uint256)) |
||||
dataSize = fileSize - sizeof(uint256); |
||||
std::vector<unsigned char> vchData; |
||||
vchData.resize(dataSize); |
||||
uint256 hashIn; |
||||
|
||||
// read data and checksum from file
|
||||
try { |
||||
filein.read((char *)&vchData[0], dataSize); |
||||
filein >> hashIn; |
||||
} |
||||
catch (const std::exception& e) { |
||||
return error("%s: Deserialize or I/O error - %s", __func__, e.what()); |
||||
} |
||||
filein.fclose(); |
||||
|
||||
CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION); |
||||
|
||||
// verify stored checksum matches input data
|
||||
uint256 hashTmp = Hash(ssBanlist.begin(), ssBanlist.end()); |
||||
if (hashIn != hashTmp) |
||||
return error("%s: Checksum mismatch, data corrupted", __func__); |
||||
|
||||
unsigned char pchMsgTmp[4]; |
||||
try { |
||||
// de-serialize file header (network specific magic number) and ..
|
||||
ssBanlist >> FLATDATA(pchMsgTmp); |
||||
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) |
||||
return error("%s: Invalid network magic number", __func__); |
||||
|
||||
// de-serialize address data into one CAddrMan object
|
||||
ssBanlist >> banSet; |
||||
} |
||||
catch (const std::exception& e) { |
||||
return error("%s: Deserialize or I/O error - %s", __func__, e.what()); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
CAddrDB::CAddrDB() |
||||
{ |
||||
pathAddr = GetDataDir() / "peers.dat"; |
||||
} |
||||
|
||||
bool CAddrDB::Write(const CAddrMan& addr) |
||||
{ |
||||
// Generate random temporary filename
|
||||
unsigned short randv = 0; |
||||
GetRandBytes((unsigned char*)&randv, sizeof(randv)); |
||||
std::string tmpfn = strprintf("peers.dat.%04x", randv); |
||||
|
||||
// serialize addresses, checksum data up to that point, then append csum
|
||||
CDataStream ssPeers(SER_DISK, CLIENT_VERSION); |
||||
ssPeers << FLATDATA(Params().MessageStart()); |
||||
ssPeers << addr; |
||||
uint256 hash = Hash(ssPeers.begin(), ssPeers.end()); |
||||
ssPeers << hash; |
||||
|
||||
// open temp output file, and associate with CAutoFile
|
||||
boost::filesystem::path pathTmp = GetDataDir() / tmpfn; |
||||
FILE *file = fopen(pathTmp.string().c_str(), "wb"); |
||||
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); |
||||
if (fileout.IsNull()) |
||||
return error("%s: Failed to open file %s", __func__, pathTmp.string()); |
||||
|
||||
// Write and commit header, data
|
||||
try { |
||||
fileout << ssPeers; |
||||
} |
||||
catch (const std::exception& e) { |
||||
return error("%s: Serialize or I/O error - %s", __func__, e.what()); |
||||
} |
||||
FileCommit(fileout.Get()); |
||||
fileout.fclose(); |
||||
|
||||
// replace existing peers.dat, if any, with new peers.dat.XXXX
|
||||
if (!RenameOver(pathTmp, pathAddr)) |
||||
return error("%s: Rename-into-place failed", __func__); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
bool CAddrDB::Read(CAddrMan& addr) |
||||
{ |
||||
// open input file, and associate with CAutoFile
|
||||
FILE *file = fopen(pathAddr.string().c_str(), "rb"); |
||||
CAutoFile filein(file, SER_DISK, CLIENT_VERSION); |
||||
if (filein.IsNull()) |
||||
return error("%s: Failed to open file %s", __func__, pathAddr.string()); |
||||
|
||||
// use file size to size memory buffer
|
||||
uint64_t fileSize = boost::filesystem::file_size(pathAddr); |
||||
uint64_t dataSize = 0; |
||||
// Don't try to resize to a negative number if file is small
|
||||
if (fileSize >= sizeof(uint256)) |
||||
dataSize = fileSize - sizeof(uint256); |
||||
std::vector<unsigned char> vchData; |
||||
vchData.resize(dataSize); |
||||
uint256 hashIn; |
||||
|
||||
// read data and checksum from file
|
||||
try { |
||||
filein.read((char *)&vchData[0], dataSize); |
||||
filein >> hashIn; |
||||
} |
||||
catch (const std::exception& e) { |
||||
return error("%s: Deserialize or I/O error - %s", __func__, e.what()); |
||||
} |
||||
filein.fclose(); |
||||
|
||||
CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); |
||||
|
||||
// verify stored checksum matches input data
|
||||
uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); |
||||
if (hashIn != hashTmp) |
||||
return error("%s: Checksum mismatch, data corrupted", __func__); |
||||
|
||||
return Read(addr, ssPeers); |
||||
} |
||||
|
||||
bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers) |
||||
{ |
||||
unsigned char pchMsgTmp[4]; |
||||
try { |
||||
// de-serialize file header (network specific magic number) and ..
|
||||
ssPeers >> FLATDATA(pchMsgTmp); |
||||
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) |
||||
return error("%s: Invalid network magic number", __func__); |
||||
|
||||
// de-serialize address data into one CAddrMan object
|
||||
ssPeers >> addr; |
||||
} |
||||
catch (const std::exception& e) { |
||||
// de-serialization has failed, ensure addrman is left in a clean state
|
||||
addr.Clear(); |
||||
return error("%s: Deserialize or I/O error - %s", __func__, e.what()); |
||||
} |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_ADDRDB_H |
||||
#define BITCOIN_ADDRDB_H |
||||
|
||||
#include "serialize.h" |
||||
|
||||
#include <string> |
||||
#include <map> |
||||
#include <boost/filesystem/path.hpp> |
||||
|
||||
class CSubNet; |
||||
class CAddrMan; |
||||
|
||||
typedef enum BanReason |
||||
{ |
||||
BanReasonUnknown = 0, |
||||
BanReasonNodeMisbehaving = 1, |
||||
BanReasonManuallyAdded = 2 |
||||
} BanReason; |
||||
|
||||
class CBanEntry |
||||
{ |
||||
public: |
||||
static const int CURRENT_VERSION=1; |
||||
int nVersion; |
||||
int64_t nCreateTime; |
||||
int64_t nBanUntil; |
||||
uint8_t banReason; |
||||
|
||||
CBanEntry() |
||||
{ |
||||
SetNull(); |
||||
} |
||||
|
||||
CBanEntry(int64_t nCreateTimeIn) |
||||
{ |
||||
SetNull(); |
||||
nCreateTime = nCreateTimeIn; |
||||
} |
||||
|
||||
ADD_SERIALIZE_METHODS; |
||||
|
||||
template <typename Stream, typename Operation> |
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { |
||||
READWRITE(this->nVersion); |
||||
nVersion = this->nVersion; |
||||
READWRITE(nCreateTime); |
||||
READWRITE(nBanUntil); |
||||
READWRITE(banReason); |
||||
} |
||||
|
||||
void SetNull() |
||||
{ |
||||
nVersion = CBanEntry::CURRENT_VERSION; |
||||
nCreateTime = 0; |
||||
nBanUntil = 0; |
||||
banReason = BanReasonUnknown; |
||||
} |
||||
|
||||
std::string banReasonToString() |
||||
{ |
||||
switch (banReason) { |
||||
case BanReasonNodeMisbehaving: |
||||
return "node misbehaving"; |
||||
case BanReasonManuallyAdded: |
||||
return "manually added"; |
||||
default: |
||||
return "unknown"; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
typedef std::map<CSubNet, CBanEntry> banmap_t; |
||||
|
||||
/** Access to the (IP) address database (peers.dat) */ |
||||
class CAddrDB |
||||
{ |
||||
private: |
||||
boost::filesystem::path pathAddr; |
||||
public: |
||||
CAddrDB(); |
||||
bool Write(const CAddrMan& addr); |
||||
bool Read(CAddrMan& addr); |
||||
bool Read(CAddrMan& addr, CDataStream& ssPeers); |
||||
}; |
||||
|
||||
/** Access to the banlist database (banlist.dat) */ |
||||
class CBanDB |
||||
{ |
||||
private: |
||||
boost::filesystem::path pathBanlist; |
||||
public: |
||||
CBanDB(); |
||||
bool Write(const banmap_t& banSet); |
||||
bool Read(banmap_t& banSet); |
||||
}; |
||||
|
||||
#endif // BITCOIN_ADDRDB_H
|
Loading…
Reference in new issue