mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-03-10 04:21:18 +00:00
dhtproxy: tunnel DHT traffic into TCP connections
This commit is contained in:
parent
068a43211a
commit
e52f2c2527
@ -156,6 +156,7 @@ BITCOIN_TWISTER_SOURCES = \
|
||||
src/leveldb.cpp \
|
||||
src/txdb.cpp \
|
||||
src/chainparams.cpp \
|
||||
src/dhtproxy.cpp \
|
||||
src/twister.cpp \
|
||||
src/twister_rss.cpp \
|
||||
src/twister_utils.cpp \
|
||||
|
330
src/dhtproxy.cpp
Normal file
330
src/dhtproxy.cpp
Normal file
@ -0,0 +1,330 @@
|
||||
// Copyright (c) 2014 Miguel Freitas
|
||||
// tunnel DHT requests into tcp connection
|
||||
// see: https://groups.google.com/forum/#!topic/twister-dev/uKjFGSw24yA
|
||||
|
||||
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <algorithm> // std::random_shuffle
|
||||
|
||||
#include "dhtproxy.h"
|
||||
|
||||
#include "libtorrent/alert_manager.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
|
||||
#include "main.h"
|
||||
#include "uint256.h"
|
||||
#include "script.h"
|
||||
#include "init.h"
|
||||
#include "twister.h"
|
||||
#include "twister_utils.h"
|
||||
|
||||
//#define dbgprintf OutputDebugStringF
|
||||
#define dbgprintf(...) // no debug printf
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
namespace DhtProxy
|
||||
{
|
||||
bool fEnabled = true;
|
||||
CCriticalSection cs_dhtProxy;
|
||||
map<sha1_hash, std::list<alert_manager*> > m_dhtgetMap;
|
||||
map<sha1_hash, std::list<CService> > m_dhtgetPeersReq;
|
||||
|
||||
class PeerBanStats {
|
||||
public:
|
||||
PeerBanStats() : active(0), count(0), limit(time_now()) {}
|
||||
int active;
|
||||
int count;
|
||||
ptime limit;
|
||||
};
|
||||
map<CService, PeerBanStats> m_peerBanStats;
|
||||
size_t numProxiesToUse = 4;
|
||||
|
||||
void dhtgetMapAdd(sha1_hash &ih, alert_manager *am)
|
||||
{
|
||||
LOCK(cs_dhtProxy);
|
||||
m_dhtgetMap[ih].push_back(am);
|
||||
}
|
||||
|
||||
void dhtgetMapRemove(sha1_hash &ih, alert_manager *am)
|
||||
{
|
||||
LOCK(cs_dhtProxy);
|
||||
std::map<sha1_hash, std::list<alert_manager*> >::iterator mi = m_dhtgetMap.find(ih);
|
||||
if( mi != m_dhtgetMap.end() ) {
|
||||
std::list<alert_manager *> &amList = (*mi).second;
|
||||
amList.remove(am);
|
||||
if( !amList.size() ) {
|
||||
m_dhtgetMap.erase(ih);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dhtgetMapPost(sha1_hash &ih, const alert &a)
|
||||
{
|
||||
LOCK(cs_dhtProxy);
|
||||
std::map<sha1_hash, std::list<alert_manager*> >::iterator mi = m_dhtgetMap.find(ih);
|
||||
if( mi != m_dhtgetMap.end() ) {
|
||||
std::list<alert_manager *> &amList = (*mi).second;
|
||||
BOOST_FOREACH(alert_manager *am, amList) {
|
||||
am->post_alert(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<CNode*> getRandomDhtProxies()
|
||||
{
|
||||
// (cs_vNodes) lock must be held!
|
||||
vector<CNode*> vNodesProxy;
|
||||
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||
if (pnode->nVersion >= DHT_PROXY_VERSION && !pnode->fNoDhtProxy) {
|
||||
vNodesProxy.push_back(pnode);
|
||||
}
|
||||
}
|
||||
std::random_shuffle(vNodesProxy.begin(),vNodesProxy.end());
|
||||
if(vNodesProxy.size() > numProxiesToUse) {
|
||||
vNodesProxy.resize(numProxiesToUse);
|
||||
}
|
||||
|
||||
return vNodesProxy;
|
||||
}
|
||||
|
||||
vector<CNode*> dhtgetStartRequest(std::string const &username, std::string const &resource, bool multi)
|
||||
{
|
||||
CDHTGetRequest req;
|
||||
req.vchUsername = std::vector<char>(username.begin(), username.end());
|
||||
req.vchResource = std::vector<char>(resource.begin(), resource.end());
|
||||
req.resTypeMulti = multi;
|
||||
req.stopReq = false;
|
||||
|
||||
LOCK(cs_vNodes);
|
||||
vector<CNode*> vNodesReq = getRandomDhtProxies();
|
||||
BOOST_FOREACH(CNode* pnode, vNodesReq) {
|
||||
dbgprintf("DhtProxy::dhtgetStartRequest: pushMessage to %s\n", pnode->addr.ToString().c_str());
|
||||
pnode->PushMessage("dhtgetreq", req);
|
||||
pnode->AddRef();
|
||||
}
|
||||
if( !vNodesReq.size() ) {
|
||||
dbgprintf("DhtProxy::dhtgetStartRequest: sorry, no dht proxy found.\n");
|
||||
|
||||
// fake no data to wakeup listener
|
||||
dht_reply_data_done_alert dd("","",false,false,false);
|
||||
sha1_hash ih = dhtTargetHash(username, resource, multi ? "m" : "s");
|
||||
dhtgetMapPost(ih, dd);
|
||||
}
|
||||
return vNodesReq;
|
||||
}
|
||||
|
||||
void dhtgetStopRequest(vector<CNode*> vNodesReq, std::string const &username, std::string const &resource, bool multi)
|
||||
{
|
||||
CDHTGetRequest req;
|
||||
req.vchUsername = std::vector<char>(username.begin(), username.end());
|
||||
req.vchResource = std::vector<char>(resource.begin(), resource.end());
|
||||
req.resTypeMulti = multi;
|
||||
req.stopReq = true;
|
||||
|
||||
BOOST_FOREACH(CNode* pnode, vNodesReq) {
|
||||
dbgprintf("DhtProxy::dhtgetStopRequest: pushMessage to %s\n", pnode->addr.ToString().c_str());
|
||||
pnode->PushMessage("dhtgetreq", req);
|
||||
pnode->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void dhtgetPeerReqAdd(sha1_hash &ih, const CNode *pnode)
|
||||
{
|
||||
LOCK(cs_dhtProxy);
|
||||
m_dhtgetPeersReq[ih].push_back(pnode->addr);
|
||||
m_peerBanStats[pnode->addr].active++;
|
||||
}
|
||||
|
||||
void dhtgetPeerReqRemove(sha1_hash &ih, const CNode *pnode)
|
||||
{
|
||||
LOCK(cs_dhtProxy);
|
||||
std::map<sha1_hash, std::list<CService> >::iterator mi = m_dhtgetPeersReq.find(ih);
|
||||
if( mi != m_dhtgetPeersReq.end() ) {
|
||||
std::list<CService> &addrList = (*mi).second;
|
||||
addrList.remove(pnode->addr);
|
||||
if( !addrList.size() ) {
|
||||
m_dhtgetPeersReq.erase(ih);
|
||||
}
|
||||
m_peerBanStats[pnode->addr].active--;
|
||||
}
|
||||
}
|
||||
|
||||
void dhtgetPeerReqReply(sha1_hash &ih, const alert *a)
|
||||
{
|
||||
CDHTGetReply reply;
|
||||
reply.vchTargetHash = std::vector<char>(ih.begin(), ih.end());
|
||||
dht_reply_data_alert const* rd = alert_cast<dht_reply_data_alert>(a);
|
||||
if (rd) {
|
||||
bencode(std::back_inserter(reply.vchBencodedData), rd->m_lst);
|
||||
}
|
||||
|
||||
LOCK(cs_dhtProxy);
|
||||
std::map<sha1_hash, std::list<CService> >::iterator mi = m_dhtgetPeersReq.find(ih);
|
||||
if( mi != m_dhtgetPeersReq.end() ) {
|
||||
std::list<CService> &addrList = (*mi).second;
|
||||
BOOST_FOREACH(CService &addr, addrList) {
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||
if ((CService)pnode->addr == addr) {
|
||||
dbgprintf("DhtProxy::dhtgetPeerReqReply: pushMessage to %s\n", pnode->addr.ToString().c_str());
|
||||
pnode->PushMessage("dhtgetreply", reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool checkForAbuse(CNode* pfrom)
|
||||
{
|
||||
LOCK(cs_dhtProxy);
|
||||
|
||||
// logic inspired/copied from dht_tracker.cpp:incoming_packet
|
||||
ptime now = time_now();
|
||||
PeerBanStats *match = &m_peerBanStats[pfrom->addr];
|
||||
match->count++;
|
||||
if( match->count >= 500 ) {
|
||||
if (now < match->limit) {
|
||||
if( match->count == 500 ) {
|
||||
dbgprintf("DhtProxy::checkForAbuse: %s misbehaving, too much requests.\n",
|
||||
pfrom->addr.ToString().c_str());
|
||||
}
|
||||
match->limit = now + minutes(5);
|
||||
return true;
|
||||
}
|
||||
match->count = 0;
|
||||
match->limit = now + seconds(5);
|
||||
}
|
||||
if( match->active > 10 ) {
|
||||
dbgprintf("DhtProxy::checkForAbuse: %s misbehaving, max active requests reached.\n",
|
||||
pfrom->addr.ToString().c_str());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dhtgetRequestReceived(const CDHTGetRequest& req, CNode* pfrom)
|
||||
{
|
||||
if( fEnabled ) {
|
||||
// we are using proxy ourselves, we can't be proxy to anyone else
|
||||
pfrom->PushMessage("nodhtproxy");
|
||||
return true;
|
||||
} else if( !req.stopReq && checkForAbuse(pfrom) ) {
|
||||
return false;
|
||||
} else {
|
||||
std::string username(req.vchUsername.data(), req.vchUsername.size());
|
||||
std::string resource(req.vchResource.data(), req.vchResource.size());
|
||||
bool multi(req.resTypeMulti);
|
||||
|
||||
dbgprintf("DhtProxy::dhtgetRequestReceived: (%s,%s,%d,stop=%d) from %s\n",
|
||||
username.c_str(), resource.c_str(), multi, req.stopReq,
|
||||
pfrom->addr.ToString().c_str());
|
||||
|
||||
sha1_hash ih = dhtTargetHash(username, resource, multi ? "m" : "s");
|
||||
if( !req.stopReq ) {
|
||||
dhtgetPeerReqAdd(ih, pfrom);
|
||||
dhtGetData(username, resource, multi);
|
||||
} else {
|
||||
dhtgetPeerReqRemove(ih, pfrom);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool dhtgetReplyReceived(const CDHTGetReply& reply, CNode* pfrom)
|
||||
{
|
||||
std::string strTargetHash(reply.vchTargetHash.data(), reply.vchTargetHash.size());
|
||||
sha1_hash ih(strTargetHash);
|
||||
|
||||
if( !reply.vchBencodedData.size() ) {
|
||||
dbgprintf("DhtProxy::dhtgetReplyReceived: empty data from %s\n",
|
||||
pfrom->addr.ToString().c_str());
|
||||
|
||||
// No reply - these fields are not used, we just want cast in twister.cpp:dhtget to fail
|
||||
dht_reply_data_done_alert dd("","",false,false,false);
|
||||
dhtgetMapPost(ih, dd);
|
||||
} else {
|
||||
lazy_entry v;
|
||||
int pos;
|
||||
libtorrent::error_code ec;
|
||||
if (lazy_bdecode(reply.vchBencodedData.data(), reply.vchBencodedData.data() +
|
||||
reply.vchBencodedData.size(), v, ec, &pos) == 0 && v.type() == lazy_entry::list_t ) {
|
||||
entry lst;
|
||||
lst = v;
|
||||
dbgprintf("DhtProxy::dhtgetReplyReceived: %zd entries from %s\n",
|
||||
lst.list().size(), pfrom->addr.ToString().c_str());
|
||||
dht_reply_data_alert rd(lst.list());
|
||||
dhtgetMapPost(ih, rd);
|
||||
} else {
|
||||
dbgprintf("DhtProxy::dhtgetReplyReceived: parsing error (data from %s)\n",
|
||||
pfrom->addr.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void dhtputRequest(std::string const &username, std::string const &resource, bool multi,
|
||||
std::string const &str_p, std::string const &sig_p, std::string const &sig_user)
|
||||
{
|
||||
CDHTPutRequest req;
|
||||
req.vchUsername = std::vector<char>(username.begin(), username.end());
|
||||
req.vchResource = std::vector<char>(resource.begin(), resource.end());
|
||||
req.resTypeMulti = multi;
|
||||
req.vchStr_p = std::vector<char>(str_p.begin(), str_p.end());
|
||||
req.vchSig_p = std::vector<char>(sig_p.begin(), sig_p.end());
|
||||
req.vchSig_user = std::vector<char>(sig_user.begin(), sig_user.end());
|
||||
|
||||
LOCK(cs_vNodes);
|
||||
vector<CNode*> vNodesReq = getRandomDhtProxies();
|
||||
BOOST_FOREACH(CNode* pnode, vNodesReq) {
|
||||
dbgprintf("DhtProxy::dhtputRequest: pushMessage to %s\n", pnode->addr.ToString().c_str());
|
||||
pnode->PushMessage("dhtputreq", req);
|
||||
}
|
||||
if( !vNodesReq.size() ) {
|
||||
dbgprintf("DhtProxy::dhtputRequest: sorry, no dht proxy found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool dhtputRequestReceived(const CDHTPutRequest& req, CNode* pfrom)
|
||||
{
|
||||
if( fEnabled ) {
|
||||
// we are using proxy ourselves, we can't be proxy to anyone else
|
||||
pfrom->PushMessage("nodhtproxy");
|
||||
return true;
|
||||
} else if( checkForAbuse(pfrom) ) {
|
||||
return false;
|
||||
} else {
|
||||
std::string username(req.vchUsername.data(), req.vchUsername.size());
|
||||
std::string resource(req.vchResource.data(), req.vchResource.size());
|
||||
bool multi(req.resTypeMulti);
|
||||
|
||||
dbgprintf("DhtProxy::dhtputRequestReceived: (%s,%s,%d) from %s\n",
|
||||
username.c_str(), resource.c_str(), multi,
|
||||
pfrom->addr.ToString().c_str());
|
||||
|
||||
lazy_entry v;
|
||||
int pos;
|
||||
libtorrent::error_code ec;
|
||||
if (lazy_bdecode(req.vchStr_p.data(), req.vchStr_p.data() +
|
||||
req.vchStr_p.size(), v, ec, &pos) == 0 ) {
|
||||
entry p;
|
||||
p = v;
|
||||
std::string sig_p(req.vchSig_p.data(), req.vchSig_p.size());
|
||||
std::string sig_user(req.vchSig_user.data(), req.vchSig_user.size());
|
||||
|
||||
dhtPutDataSigned(username,resource,multi,p,sig_p,sig_user, false);
|
||||
} else {
|
||||
dbgprintf("DhtProxy::dhtputRequestReceived: parsing error (data from %s)\n",
|
||||
pfrom->addr.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
195
src/dhtproxy.h
Normal file
195
src/dhtproxy.h
Normal file
@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2014 Miguel Freitas
|
||||
|
||||
#ifndef DHTPROXY_H
|
||||
#define DHTPROXY_H
|
||||
|
||||
#include "serialize.h"
|
||||
#include "net.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// just a small set of declarations to avoid main.c depending on libtorrent headers
|
||||
namespace libtorrent {
|
||||
class alert_manager;
|
||||
class big_number;
|
||||
typedef big_number sha1_hash;
|
||||
class alert;
|
||||
}
|
||||
|
||||
class CDHTTarget;
|
||||
class CDHTGetRequest;
|
||||
class CDHTGetReply;
|
||||
class CDHTPutRequest;
|
||||
|
||||
/**
|
||||
* DHTGet Sequence:
|
||||
*
|
||||
* Client Server
|
||||
* 1) dhtgetMapAdd
|
||||
* 2) dhtgetStartRequest
|
||||
* => CDHTGetRequest =>
|
||||
* 3) dhtgetRequestReceived(stopReq=False)
|
||||
* 4) (dhtgetPeerReqAdd)
|
||||
* 5) (ses->dht_getData)
|
||||
* 6.1) dhtgetPeerReqReply (from ThreadSessionAlerts)
|
||||
* 6.2) <= CDHTGetReply <=
|
||||
* 6.3) dhtgetReplyReceived
|
||||
* 6.4) (dhtgetMapPost)
|
||||
* [ ..item 6 repeats... ]
|
||||
* 7) dhtgetMapRemove
|
||||
* 8) dhtgetStopRequest
|
||||
* => CDHTGetRequest =>
|
||||
* 9) dhtgetRequestReceived(stopReq=True)
|
||||
* 10) (dhtgetPeerReqRemove)
|
||||
*
|
||||
**
|
||||
* DHTPut Sequence:
|
||||
*
|
||||
* Client Server
|
||||
* 1) dhtputRequest
|
||||
* => CDHTPutRequest =>
|
||||
* 2) dhtputRequestReceived
|
||||
* 3) (ses->dht_putDataSigned)
|
||||
*/
|
||||
namespace DhtProxy
|
||||
{
|
||||
extern bool fEnabled;
|
||||
|
||||
// Register a listener for dhtget requests (client side)
|
||||
void dhtgetMapAdd(libtorrent::sha1_hash &ih, libtorrent::alert_manager *am);
|
||||
|
||||
// Unregister the dhtget listener (client side)
|
||||
void dhtgetMapRemove(libtorrent::sha1_hash &ih, libtorrent::alert_manager *am);
|
||||
|
||||
// Request a dhtget. Returns the list of node the request was sent to. (client side)
|
||||
vector<CNode*> dhtgetStartRequest(std::string const &username, std::string const &resource, bool multi);
|
||||
|
||||
// Stop a dhtget request to the nodes listed. (client side)
|
||||
void dhtgetStopRequest(vector<CNode*> vNodesReq, std::string const &username, std::string const &resource, bool multi);
|
||||
|
||||
// Handle a dhtget request received from TCP. send request to UDP. (server side)
|
||||
// return true if accepted.
|
||||
bool dhtgetRequestReceived(const CDHTGetRequest& req, CNode* pfrom);
|
||||
|
||||
// Handle a dhtget reply received from UDP, send it to the peers that made the request. (server side)
|
||||
void dhtgetPeerReqReply(libtorrent::sha1_hash &ih, const libtorrent::alert *a);
|
||||
|
||||
// Handle a dhtget reply received from TCP. Will call dhtgetMapPost as needed. (client side)
|
||||
// return true if accepted.
|
||||
bool dhtgetReplyReceived(const CDHTGetReply& reply, CNode* pfrom);
|
||||
|
||||
// Request a dhtput.
|
||||
void dhtputRequest(std::string const &username, std::string const &resource, bool multi,
|
||||
std::string const &str_p, std::string const &sig_p, std::string const &sig_user);
|
||||
|
||||
// Handle a dhtput request received from TCP. send request to UDP. (server side)
|
||||
// return true if accepted.
|
||||
bool dhtputRequestReceived(const CDHTPutRequest& req, CNode* pfrom);
|
||||
}
|
||||
|
||||
class CDHTTarget
|
||||
{
|
||||
public:
|
||||
std::vector<char> vchUsername;
|
||||
std::vector<char> vchResource;
|
||||
bool resTypeMulti;
|
||||
|
||||
CDHTTarget()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(vchUsername);
|
||||
READWRITE(vchResource);
|
||||
READWRITE(resTypeMulti);
|
||||
)
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
vchUsername.clear();
|
||||
vchResource.clear();
|
||||
resTypeMulti = false;
|
||||
}
|
||||
};
|
||||
|
||||
class CDHTGetRequest : public CDHTTarget
|
||||
{
|
||||
public:
|
||||
bool stopReq;
|
||||
|
||||
CDHTGetRequest() : CDHTTarget()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
CDHTTarget* pthis = (CDHTTarget*)(this);
|
||||
READWRITE(*pthis);
|
||||
READWRITE(stopReq);
|
||||
)
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
stopReq = false;
|
||||
}
|
||||
};
|
||||
|
||||
class CDHTGetReply
|
||||
{
|
||||
public:
|
||||
std::vector<char> vchTargetHash;
|
||||
std::vector<char> vchBencodedData;
|
||||
|
||||
CDHTGetReply()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(vchTargetHash);
|
||||
READWRITE(vchBencodedData);
|
||||
)
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
vchTargetHash.clear();
|
||||
vchBencodedData.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class CDHTPutRequest : public CDHTTarget
|
||||
{
|
||||
public:
|
||||
std::vector<char> vchStr_p;
|
||||
std::vector<char> vchSig_p;
|
||||
std::vector<char> vchSig_user;
|
||||
|
||||
CDHTPutRequest() : CDHTTarget()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
CDHTTarget* pthis = (CDHTTarget*)(this);
|
||||
READWRITE(*pthis);
|
||||
READWRITE(vchStr_p);
|
||||
READWRITE(vchSig_p);
|
||||
READWRITE(vchSig_user);
|
||||
)
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
vchStr_p.clear();
|
||||
vchSig_p.clear();
|
||||
vchSig_user.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -431,7 +431,11 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
// to protect privacy, do not listen by default if a proxy server is specified
|
||||
SoftSetBoolArg("-listen", false);
|
||||
}
|
||||
|
||||
|
||||
if (mapArgs.count("-proxy") || mapArgs.count("-tor")) {
|
||||
SoftSetBoolArg("-dhtproxy", true);
|
||||
}
|
||||
|
||||
if (!GetBoolArg("-listen", true)) {
|
||||
// do not map ports or try to retrieve public IP when not listening (pointless)
|
||||
SoftSetBoolArg("-upnp", false);
|
||||
|
41
src/main.cpp
41
src/main.cpp
@ -13,6 +13,7 @@
|
||||
#include "ui_interface.h"
|
||||
#include "checkqueue.h"
|
||||
#include "chainparams.h"
|
||||
#include "dhtproxy.h"
|
||||
|
||||
#include "twister.h"
|
||||
#include "utf8core.h"
|
||||
@ -3185,6 +3186,46 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
pfrom->fRelayTxes = true;
|
||||
}
|
||||
|
||||
else if (strCommand == "dhtgetreq")
|
||||
{
|
||||
CDHTGetRequest req;
|
||||
vRecv >> req;
|
||||
|
||||
if( DhtProxy::dhtgetRequestReceived(req, pfrom) ) {
|
||||
// ok
|
||||
} else {
|
||||
pfrom->Misbehaving(20);
|
||||
}
|
||||
}
|
||||
|
||||
else if (strCommand == "dhtputreq")
|
||||
{
|
||||
CDHTPutRequest req;
|
||||
vRecv >> req;
|
||||
|
||||
if( DhtProxy::dhtputRequestReceived(req, pfrom) ) {
|
||||
// ok
|
||||
} else {
|
||||
pfrom->Misbehaving(20);
|
||||
}
|
||||
}
|
||||
|
||||
else if (strCommand == "dhtgetreply")
|
||||
{
|
||||
CDHTGetReply reply;
|
||||
vRecv >> reply;
|
||||
|
||||
if( DhtProxy::dhtgetReplyReceived(reply, pfrom) ) {
|
||||
// ok
|
||||
} else {
|
||||
pfrom->Misbehaving(20);
|
||||
}
|
||||
}
|
||||
|
||||
else if (strCommand == "nodhtproxy")
|
||||
{
|
||||
pfrom->fNoDhtProxy = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
@ -133,6 +133,7 @@ OBJS= \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/chainparams.o \
|
||||
obj/dhtproxy.o \
|
||||
obj/twister.o \
|
||||
obj/twister_rss.o \
|
||||
obj/twister_utils.o
|
||||
|
@ -148,6 +148,7 @@ OBJS= \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/chainparams.o \
|
||||
obj/dhtproxy.o \
|
||||
obj/twister.o \
|
||||
obj/twister_rss.o \
|
||||
obj/twister_utils.o
|
||||
|
@ -148,7 +148,9 @@ OBJS= \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/chainparams.o \
|
||||
obj/dhtproxy.o \
|
||||
obj/twister.o \
|
||||
obj/twister_rss.o \
|
||||
obj/twister_utils.o
|
||||
|
||||
ifdef USE_SSE2
|
||||
|
@ -150,6 +150,7 @@ OBJS= \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/chainparams.o \
|
||||
obj/dhtproxy.o \
|
||||
obj/twister.o \
|
||||
obj/twister_rss.o \
|
||||
obj/twister_utils.o
|
||||
|
@ -203,6 +203,7 @@ public:
|
||||
// b) the peer may tell us in their version message that we should not relay tx invs
|
||||
// until they have initialized their bloom filter.
|
||||
bool fRelayTxes;
|
||||
bool fNoDhtProxy;
|
||||
CSemaphoreGrant grantOutbound;
|
||||
CCriticalSection cs_filter;
|
||||
CBloomFilter* pfilter;
|
||||
@ -266,6 +267,7 @@ public:
|
||||
fGetAddr = false;
|
||||
nMisbehavior = 0;
|
||||
fRelayTxes = false;
|
||||
fNoDhtProxy = false;
|
||||
setInventoryKnown.max_size(SendBufferSize() / 1000);
|
||||
pfilter = NULL;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "twister.h"
|
||||
|
||||
#include "twister_utils.h"
|
||||
#include "dhtproxy.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "init.h"
|
||||
@ -91,18 +92,6 @@ private:
|
||||
#define USER_DATA_FILE "user_data"
|
||||
#define GLOBAL_DATA_FILE "global_data"
|
||||
|
||||
sha1_hash dhtTargetHash(std::string const &username, std::string const &resource, std::string const &type)
|
||||
{
|
||||
entry target;
|
||||
target["n"] = username;
|
||||
target["r"] = resource;
|
||||
target["t"] = type;
|
||||
|
||||
std::vector<char> buf;
|
||||
bencode(std::back_inserter(buf), target);
|
||||
return hasher(buf.data(), buf.size()).final();
|
||||
}
|
||||
|
||||
void dhtgetMapAdd(sha1_hash &ih, alert_manager *am)
|
||||
{
|
||||
LOCK(cs_dhtgetMap);
|
||||
@ -337,7 +326,12 @@ void ThreadWaitExtIP()
|
||||
//dhts.restrict_routing_ips = false;
|
||||
//dhts.restrict_search_ips = false;
|
||||
ses->set_dht_settings(dhts);
|
||||
ses->start_dht();
|
||||
|
||||
if( !DhtProxy::fEnabled ) {
|
||||
ses->start_dht();
|
||||
} else {
|
||||
ses->stop_dht();
|
||||
}
|
||||
}
|
||||
|
||||
session_settings settings;
|
||||
@ -495,7 +489,7 @@ void ThreadMaintainDHTNodes()
|
||||
vNodesSize = vNodes.size();
|
||||
}
|
||||
|
||||
if( !ses->is_paused() ) {
|
||||
if( !ses->is_paused() && !DhtProxy::fEnabled ) {
|
||||
vector<CAddress> vAddr = addrman.GetAddr();
|
||||
int totalNodesCandidates = (int)(vNodesSize + vAddr.size());
|
||||
if( ((!dht_nodes && totalNodesCandidates) ||
|
||||
@ -630,6 +624,7 @@ void ThreadSessionAlerts()
|
||||
t && t->type() == entry::string_t) {
|
||||
sha1_hash ih = dhtTargetHash(n->string(), r->string(), t->string());
|
||||
dhtgetMapPost(ih,*rd);
|
||||
DhtProxy::dhtgetPeerReqReply(ih,rd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -675,7 +670,7 @@ void ThreadSessionAlerts()
|
||||
t->string().c_str());
|
||||
#endif
|
||||
neighborCheck[ih] = false;
|
||||
ses->dht_getData(n->string(), r->string(), t->string() == "m");
|
||||
dhtGetData(n->string(), r->string(), t->string() == "m");
|
||||
} else if( neighborCheck[ih] ) {
|
||||
sha1_hash ihStatus = dhtTargetHash(n->string(), "status", "s");
|
||||
|
||||
@ -686,7 +681,7 @@ void ThreadSessionAlerts()
|
||||
n->string().c_str(), "status", "s");
|
||||
#endif
|
||||
statusCheck[ihStatus] = GetTime();
|
||||
ses->dht_getData(n->string(), "status", false);
|
||||
dhtGetData(n->string(), "status", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -710,6 +705,7 @@ void ThreadSessionAlerts()
|
||||
if( !dd->m_got_data ) {
|
||||
// no data: post alert to return from wait_for_alert in dhtget()
|
||||
dhtgetMapPost(ih,*dd);
|
||||
DhtProxy::dhtgetPeerReqReply(ih,dd);
|
||||
}
|
||||
|
||||
if( neighborCheck.count(ih) ) {
|
||||
@ -721,7 +717,7 @@ void ThreadSessionAlerts()
|
||||
#endif
|
||||
sha1_hash ihStatus = dhtTargetHash(dd->m_username, "status", "s");
|
||||
statusCheck[ihStatus] = GetTime();
|
||||
ses->dht_getData(dd->m_username, "status", false);
|
||||
dhtGetData(dd->m_username, "status", false);
|
||||
}
|
||||
}
|
||||
if( statusCheck.count(ih) ) {
|
||||
@ -765,6 +761,8 @@ void startSessionTorrent(boost::thread_group& threadGroup)
|
||||
m_noExpireResources["following"] = NumberedNoExpire;
|
||||
m_noExpireResources["status"] = SimpleNoExpire;
|
||||
m_noExpireResources["post"] = PostNoExpireRecent;
|
||||
|
||||
DhtProxy::fEnabled = GetBoolArg("-dhtproxy", false);
|
||||
|
||||
m_threadsToJoin = 0;
|
||||
threadGroup.create_thread(boost::bind(&ThreadWaitExtIP));
|
||||
@ -1334,16 +1332,24 @@ entry formatSpamPost(const string &msg, const string &username, uint64_t utcTime
|
||||
}
|
||||
|
||||
|
||||
void dhtGetData(std::string const &username, std::string const &resource, bool multi)
|
||||
{
|
||||
if( DhtProxy::fEnabled ) {
|
||||
printf("dhtGetData: not allowed - using proxy (bug!)\n");
|
||||
return;
|
||||
}
|
||||
boost::shared_ptr<session> ses(m_ses);
|
||||
if( !ses ) {
|
||||
printf("dhtGetData: libtorrent session not ready\n");
|
||||
return;
|
||||
}
|
||||
ses->dht_getData(username,resource,multi);
|
||||
}
|
||||
|
||||
void dhtPutData(std::string const &username, std::string const &resource, bool multi,
|
||||
entry const &value, std::string const &sig_user,
|
||||
boost::int64_t timeutc, int seq)
|
||||
{
|
||||
boost::shared_ptr<session> ses(m_ses);
|
||||
if( !ses ) {
|
||||
printf("dhtPutData: libtorrent session not ready\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// construct p dictionary and sign it
|
||||
entry p;
|
||||
entry& target = p["target"];
|
||||
@ -1365,7 +1371,27 @@ void dhtPutData(std::string const &username, std::string const &resource, bool m
|
||||
return;
|
||||
}
|
||||
|
||||
ses->dht_putDataSigned(username,resource,multi,p,sig_p,sig_user, true);
|
||||
if( !DhtProxy::fEnabled ) {
|
||||
dhtPutDataSigned(username,resource,multi,p,sig_p,sig_user, true);
|
||||
} else {
|
||||
DhtProxy::dhtputRequest(username,resource,multi,str_p,sig_p,sig_user);
|
||||
}
|
||||
}
|
||||
|
||||
void dhtPutDataSigned(std::string const &username, std::string const &resource, bool multi,
|
||||
libtorrent::entry const &p, std::string const &sig_p, std::string const &sig_user, bool local)
|
||||
{
|
||||
if( DhtProxy::fEnabled ) {
|
||||
printf("dhtputDataSigned: not allowed - using proxy (bug!)\n");
|
||||
return;
|
||||
}
|
||||
boost::shared_ptr<session> ses(m_ses);
|
||||
if( !ses ) {
|
||||
printf("dhtPutData: libtorrent session not ready\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ses->dht_putDataSigned(username,resource,multi,p,sig_p,sig_user, local);
|
||||
}
|
||||
|
||||
Value dhtput(const Array& params, bool fHelp)
|
||||
@ -1441,9 +1467,15 @@ Value dhtget(const Array& params, bool fHelp)
|
||||
|
||||
alert_manager am(10, alert::dht_notification);
|
||||
sha1_hash ih = dhtTargetHash(strUsername,strResource,strMulti);
|
||||
dhtgetMapAdd(ih, &am);
|
||||
|
||||
ses->dht_getData(strUsername, strResource, multi);
|
||||
|
||||
vector<CNode*> dhtProxyNodes;
|
||||
if( !DhtProxy::fEnabled ) {
|
||||
dhtgetMapAdd(ih, &am);
|
||||
dhtGetData(strUsername, strResource, multi);
|
||||
} else {
|
||||
DhtProxy::dhtgetMapAdd(ih, &am);
|
||||
dhtProxyNodes = DhtProxy::dhtgetStartRequest(strUsername, strResource, multi);
|
||||
}
|
||||
|
||||
Array ret;
|
||||
std::set<std::string> uniqueSigPs;
|
||||
@ -1488,7 +1520,12 @@ Value dhtget(const Array& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
dhtgetMapRemove(ih,&am);
|
||||
if( !DhtProxy::fEnabled ) {
|
||||
dhtgetMapRemove(ih,&am);
|
||||
} else {
|
||||
DhtProxy::dhtgetMapRemove(ih,&am);
|
||||
DhtProxy::dhtgetStopRequest(dhtProxyNodes, strUsername, strResource, multi);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -13,6 +13,9 @@
|
||||
#define BLOCK_AGE_TO_EXPIRE_DHT_ENTRY (2016) // about 2 weeks
|
||||
#define BLOCK_AGE_TO_EXPIRE_DHT_POSTS (4320*2) // about 2 months
|
||||
|
||||
namespace libtorrent {
|
||||
class entry;
|
||||
}
|
||||
|
||||
class twister
|
||||
{
|
||||
@ -41,4 +44,12 @@ int getDhtNodes(boost::int64_t *dht_global_nodes = NULL);
|
||||
|
||||
void updateSeenHashtags(std::string &message, int64_t msgTime);
|
||||
|
||||
// interface to dht api of the libtorrent current session
|
||||
void dhtGetData(std::string const &username, std::string const &resource, bool multi);
|
||||
void dhtPutData(std::string const &username, std::string const &resource, bool multi,
|
||||
libtorrent::entry const &value, std::string const &sig_user,
|
||||
boost::int64_t timeutc, int seq);
|
||||
void dhtPutDataSigned(std::string const &username, std::string const &resource, bool multi,
|
||||
libtorrent::entry const &p, std::string const &sig_p, std::string const &sig_user, bool local);
|
||||
|
||||
#endif // TWISTER_H
|
||||
|
@ -360,3 +360,16 @@ libtorrent::entry safeGetEntryDict(libtorrent::entry const &e, std::string const
|
||||
}
|
||||
}
|
||||
|
||||
sha1_hash dhtTargetHash(std::string const &username, std::string const &resource, std::string const &type)
|
||||
{
|
||||
entry target;
|
||||
target["n"] = username;
|
||||
target["r"] = resource;
|
||||
target["t"] = type;
|
||||
|
||||
std::vector<char> buf;
|
||||
bencode(std::back_inserter(buf), target);
|
||||
return hasher(buf.data(), buf.size()).final();
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "json/json_spirit.h"
|
||||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -48,4 +49,6 @@ std::string safeGetEntryString(libtorrent::entry const &e, std::string const& ke
|
||||
int safeGetEntryInt(libtorrent::entry const &e, std::string const& key);
|
||||
libtorrent::entry safeGetEntryDict(libtorrent::entry const &e, std::string const& key);
|
||||
|
||||
libtorrent::sha1_hash dhtTargetHash(std::string const &username, std::string const &resource, std::string const &type);
|
||||
|
||||
#endif // TWISTER_UTILS_H
|
||||
|
@ -25,7 +25,7 @@ extern const std::string CLIENT_DATE;
|
||||
// network protocol versioning
|
||||
//
|
||||
|
||||
static const int PROTOCOL_VERSION = 70002;
|
||||
static const int PROTOCOL_VERSION = 70003;
|
||||
|
||||
// earlier versions not supported as of Feb 2012, and are disconnected
|
||||
static const int MIN_PROTO_VERSION = 209;
|
||||
@ -44,6 +44,9 @@ static const int BIP0031_VERSION = 60000;
|
||||
// soft checkpoint min version
|
||||
static const int SOFT_CHECKPOINT_VERSION = 70002;
|
||||
|
||||
// dht proxy min version
|
||||
static const int DHT_PROXY_VERSION = 70003;
|
||||
|
||||
// "mempool" command, enhanced "getdata" behavior starts with this version:
|
||||
static const int MEMPOOL_GD_VERSION = 60002;
|
||||
|
||||
|
@ -200,6 +200,7 @@ HEADERS += \
|
||||
src/limitedmap.h \
|
||||
src/scrypt.h \
|
||||
src/utf8core.h \
|
||||
src/dhtproxy.h \
|
||||
src/twister.h \
|
||||
src/twister_rss.h \
|
||||
src/twister_utils.h
|
||||
@ -277,6 +278,7 @@ SOURCES += \ #src/qt/bitcoin.cpp \
|
||||
src/leveldb.cpp \
|
||||
src/txdb.cpp \
|
||||
src/scrypt.cpp \
|
||||
src/dhtproxy.cpp \
|
||||
src/twister.cpp \
|
||||
src/twister_rss.cpp \
|
||||
src/twister_utils.cpp
|
||||
|
Loading…
x
Reference in New Issue
Block a user