|
|
@ -31,6 +31,7 @@ twister::twister() |
|
|
|
#include "libtorrent/aux_/session_impl.hpp" |
|
|
|
#include "libtorrent/aux_/session_impl.hpp" |
|
|
|
|
|
|
|
|
|
|
|
#define DEBUG_ACCEPT_POST 1 |
|
|
|
#define DEBUG_ACCEPT_POST 1 |
|
|
|
|
|
|
|
#define DEBUG_EXPIRE_DHT_ITEM 1 |
|
|
|
|
|
|
|
|
|
|
|
using namespace libtorrent; |
|
|
|
using namespace libtorrent; |
|
|
|
static session *ses = NULL; |
|
|
|
static session *ses = NULL; |
|
|
@ -41,13 +42,19 @@ static map<sha1_hash, alert_manager*> m_dhtgetMap; |
|
|
|
|
|
|
|
|
|
|
|
static CCriticalSection cs_twister; |
|
|
|
static CCriticalSection cs_twister; |
|
|
|
static map<std::string, bool> m_specialResources; |
|
|
|
static map<std::string, bool> m_specialResources; |
|
|
|
|
|
|
|
enum ExpireResType { SimpleNoExpire, NumberedNoExpire, PostNoExpireRecent }; |
|
|
|
|
|
|
|
static map<std::string, ExpireResType> m_noExpireResources; |
|
|
|
static map<std::string, torrent_handle> m_userTorrent; |
|
|
|
static map<std::string, torrent_handle> m_userTorrent; |
|
|
|
|
|
|
|
|
|
|
|
static std::string m_preferredSpamLang = "[en]"; |
|
|
|
static std::string m_preferredSpamLang = "[en]"; |
|
|
|
static std::string m_receivedSpamMsgStr; |
|
|
|
static std::string m_receivedSpamMsgStr; |
|
|
|
static std::string m_receivedSpamUserStr; |
|
|
|
static std::string m_receivedSpamUserStr; |
|
|
|
|
|
|
|
static int64 m_lastSpamTime = 0; |
|
|
|
static std::map<std::string,UserData> m_users; |
|
|
|
static std::map<std::string,UserData> m_users; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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) |
|
|
|
sha1_hash dhtTargetHash(std::string const &username, std::string const &resource, std::string const &type) |
|
|
|
{ |
|
|
|
{ |
|
|
|
entry target; |
|
|
|
entry target; |
|
|
@ -95,6 +102,47 @@ int lastPostKfromTorrent(std::string const &username) |
|
|
|
return status.last_have; |
|
|
|
return status.last_have; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int saveGlobalData(std::string const& filename) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOCK(cs_twister); |
|
|
|
|
|
|
|
entry globalDict; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
globalDict["preferredSpamLang"] = m_preferredSpamLang; |
|
|
|
|
|
|
|
globalDict["receivedSpamMsg"] = m_receivedSpamMsgStr; |
|
|
|
|
|
|
|
globalDict["receivedSpamUser"] = m_receivedSpamUserStr; |
|
|
|
|
|
|
|
globalDict["lastSpamTime"] = m_lastSpamTime; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<char> buf; |
|
|
|
|
|
|
|
bencode(std::back_inserter(buf), globalDict); |
|
|
|
|
|
|
|
return save_file(filename, buf); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int loadGlobalData(std::string const& filename) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOCK(cs_twister); |
|
|
|
|
|
|
|
std::vector<char> in; |
|
|
|
|
|
|
|
if (load_file(filename, in) == 0) { |
|
|
|
|
|
|
|
lazy_entry userDict; |
|
|
|
|
|
|
|
error_code ec; |
|
|
|
|
|
|
|
if (lazy_bdecode(&in[0], &in[0] + in.size(), userDict, ec) == 0) { |
|
|
|
|
|
|
|
if( userDict.type() != lazy_entry::dict_t ) goto data_error; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_preferredSpamLang = userDict.dict_find_string_value("preferredSpamLang"); |
|
|
|
|
|
|
|
m_receivedSpamMsgStr = userDict.dict_find_string_value("receivedSpamMsg"); |
|
|
|
|
|
|
|
m_receivedSpamUserStr = userDict.dict_find_string_value("receivedSpamUser"); |
|
|
|
|
|
|
|
m_lastSpamTime = userDict.dict_find_int_value("lastSpamTime"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data_error: |
|
|
|
|
|
|
|
printf("loadGlobalData: unexpected bencode type - global_data corrupt!\n"); |
|
|
|
|
|
|
|
return -2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ThreadWaitExtIP() |
|
|
|
void ThreadWaitExtIP() |
|
|
|
{ |
|
|
|
{ |
|
|
|
RenameThread("wait-extip"); |
|
|
|
RenameThread("wait-extip"); |
|
|
@ -159,6 +207,9 @@ void ThreadWaitExtIP() |
|
|
|
//settings.dht_announce_interval = 60; // test
|
|
|
|
//settings.dht_announce_interval = 60; // test
|
|
|
|
//settings.min_announce_interval = 60; // test
|
|
|
|
//settings.min_announce_interval = 60; // test
|
|
|
|
settings.anonymous_mode = false; // (false => send peer_id, avoid connecting to itself)
|
|
|
|
settings.anonymous_mode = false; // (false => send peer_id, avoid connecting to itself)
|
|
|
|
|
|
|
|
// disable read cache => there is still some bug due to twister piece size changes
|
|
|
|
|
|
|
|
settings.use_read_cache = false; |
|
|
|
|
|
|
|
settings.cache_size = 0; |
|
|
|
ses->set_settings(settings); |
|
|
|
ses->set_settings(settings); |
|
|
|
|
|
|
|
|
|
|
|
printf("libtorrent + dht started\n"); |
|
|
|
printf("libtorrent + dht started\n"); |
|
|
@ -171,9 +222,12 @@ void ThreadWaitExtIP() |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boost::filesystem::path globalDataPath = GetDataDir() / GLOBAL_DATA_FILE; |
|
|
|
|
|
|
|
loadGlobalData(globalDataPath.string()); |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs_twister); |
|
|
|
LOCK(cs_twister); |
|
|
|
boost::filesystem::path userDataPath = GetDataDir() / "user_data"; |
|
|
|
boost::filesystem::path userDataPath = GetDataDir() / USER_DATA_FILE; |
|
|
|
loadUserData(userDataPath.string(), m_users); |
|
|
|
loadUserData(userDataPath.string(), m_users); |
|
|
|
printf("loaded user_data for %zd users\n", m_users.size()); |
|
|
|
printf("loaded user_data for %zd users\n", m_users.size()); |
|
|
|
|
|
|
|
|
|
|
@ -389,6 +443,12 @@ void startSessionTorrent(boost::thread_group& threadGroup) |
|
|
|
m_specialResources["tracker"] = true; |
|
|
|
m_specialResources["tracker"] = true; |
|
|
|
m_specialResources["swarm"] = true; |
|
|
|
m_specialResources["swarm"] = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// these are the resources which shouldn't expire
|
|
|
|
|
|
|
|
m_noExpireResources["avatar"] = SimpleNoExpire; |
|
|
|
|
|
|
|
m_noExpireResources["profile"] = SimpleNoExpire; |
|
|
|
|
|
|
|
m_noExpireResources["following"] = NumberedNoExpire; |
|
|
|
|
|
|
|
m_noExpireResources["status"] = SimpleNoExpire; |
|
|
|
|
|
|
|
m_noExpireResources["post"] = PostNoExpireRecent; |
|
|
|
|
|
|
|
|
|
|
|
threadGroup.create_thread(boost::bind(&ThreadWaitExtIP)); |
|
|
|
threadGroup.create_thread(boost::bind(&ThreadWaitExtIP)); |
|
|
|
threadGroup.create_thread(boost::bind(&ThreadMaintainDHTNodes)); |
|
|
|
threadGroup.create_thread(boost::bind(&ThreadMaintainDHTNodes)); |
|
|
@ -442,18 +502,21 @@ void stopSessionTorrent() |
|
|
|
entry session_state; |
|
|
|
entry session_state; |
|
|
|
ses->save_state(session_state); |
|
|
|
ses->save_state(session_state); |
|
|
|
|
|
|
|
|
|
|
|
std::vector<char> out; |
|
|
|
std::vector<char> out; |
|
|
|
bencode(std::back_inserter(out), session_state); |
|
|
|
bencode(std::back_inserter(out), session_state); |
|
|
|
boost::filesystem::path sesStatePath = GetDataDir() / "ses_state"; |
|
|
|
boost::filesystem::path sesStatePath = GetDataDir() / "ses_state"; |
|
|
|
save_file(sesStatePath.string(), out); |
|
|
|
save_file(sesStatePath.string(), out); |
|
|
|
|
|
|
|
|
|
|
|
delete ses; |
|
|
|
delete ses; |
|
|
|
ses = NULL; |
|
|
|
ses = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boost::filesystem::path globalDataPath = GetDataDir() / GLOBAL_DATA_FILE; |
|
|
|
|
|
|
|
saveGlobalData(globalDataPath.string()); |
|
|
|
|
|
|
|
|
|
|
|
if( m_users.size() ) { |
|
|
|
if( m_users.size() ) { |
|
|
|
printf("saving user_data (followers and DMs)...\n"); |
|
|
|
printf("saving user_data (followers and DMs)...\n"); |
|
|
|
boost::filesystem::path userDataPath = GetDataDir() / "user_data"; |
|
|
|
boost::filesystem::path userDataPath = GetDataDir() / USER_DATA_FILE; |
|
|
|
saveUserData(userDataPath.string(), m_users); |
|
|
|
saveUserData(userDataPath.string(), m_users); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -579,9 +642,11 @@ bool processReceivedDM(lazy_entry const* post) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
std::string textOut; |
|
|
|
std::string textOut; |
|
|
|
if( key.Decrypt(sec, textOut) ) { |
|
|
|
if( key.Decrypt(sec, textOut) ) { |
|
|
|
|
|
|
|
/* this printf is good for debug, but bad for security.
|
|
|
|
printf("Received DM for user '%s' text = '%s'\n", |
|
|
|
printf("Received DM for user '%s' text = '%s'\n", |
|
|
|
item.second.username.c_str(), |
|
|
|
item.second.username.c_str(), |
|
|
|
textOut.c_str()); |
|
|
|
textOut.c_str()); |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
std::string n = post->dict_find_string_value("n"); |
|
|
|
std::string n = post->dict_find_string_value("n"); |
|
|
|
|
|
|
|
|
|
|
@ -713,6 +778,15 @@ bool validatePostNumberForUser(std::string const &username, int k) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool usernameExists(std::string const &username) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CTransaction txOut; |
|
|
|
|
|
|
|
uint256 hashBlock; |
|
|
|
|
|
|
|
uint256 userhash = SerializeHash(username); |
|
|
|
|
|
|
|
return GetTransaction(userhash, txOut, hashBlock); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
"userpost" : |
|
|
|
"userpost" : |
|
|
|
{ |
|
|
|
{ |
|
|
@ -808,11 +882,90 @@ int getBestHeight() |
|
|
|
return nBestHeight; |
|
|
|
return nBestHeight; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool shouldDhtResourceExpire(std::string resource, bool multi, int height) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if ((height + BLOCK_AGE_TO_EXPIRE_DHT_ENTRY) < getBestHeight() ) { |
|
|
|
|
|
|
|
if( multi ) { |
|
|
|
|
|
|
|
#ifdef DEBUG_EXPIRE_DHT_ITEM |
|
|
|
|
|
|
|
printf("shouldDhtResourceExpire: expiring resource multi '%s'\n", resource.c_str()); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// extract basic resource string (without numbering)
|
|
|
|
|
|
|
|
std::string resourceBasic; |
|
|
|
|
|
|
|
for(size_t i = 0; i < resource.size() && isalpha(resource.at(i)); i++) { |
|
|
|
|
|
|
|
resourceBasic.push_back(resource.at(i)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int resourceNumber = -1; |
|
|
|
|
|
|
|
if( resource.length() > resourceBasic.length() ) { |
|
|
|
|
|
|
|
// make sure it is a valid number following (all digits)
|
|
|
|
|
|
|
|
if( resource.at(resourceBasic.length()) == '0' && |
|
|
|
|
|
|
|
resource.size() > resourceBasic.length() + 1 ){ |
|
|
|
|
|
|
|
// leading zeros not allowed
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
size_t i; |
|
|
|
|
|
|
|
for(i = resourceBasic.length(); i < resource.size() && |
|
|
|
|
|
|
|
isdigit(resource.at(i)); i++) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(i == resource.size()) { |
|
|
|
|
|
|
|
resourceNumber = atoi( resource.c_str() + resourceBasic.length() ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !m_noExpireResources.count(resourceBasic) ) { |
|
|
|
|
|
|
|
// unknown resource. expire it.
|
|
|
|
|
|
|
|
#ifdef DEBUG_EXPIRE_DHT_ITEM |
|
|
|
|
|
|
|
printf("shouldDhtResourceExpire: expiring non-special resource '%s'\n", resource.c_str()); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if( m_noExpireResources[resourceBasic] == SimpleNoExpire && |
|
|
|
|
|
|
|
resource.length() > resourceBasic.length() ) { |
|
|
|
|
|
|
|
// this resource admits no number. expire it!
|
|
|
|
|
|
|
|
#ifdef DEBUG_EXPIRE_DHT_ITEM |
|
|
|
|
|
|
|
printf("shouldDhtResourceExpire: expiring resource with unexpected numbering '%s'\n", resource.c_str()); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( m_noExpireResources[resourceBasic] == NumberedNoExpire && |
|
|
|
|
|
|
|
(resourceNumber < 0 || resourceNumber > 200) ) { |
|
|
|
|
|
|
|
// try keeping a sane number here, otherwise expire it!
|
|
|
|
|
|
|
|
#ifdef DEBUG_EXPIRE_DHT_ITEM |
|
|
|
|
|
|
|
printf("shouldDhtResourceExpire: expiring numbered resource with no sane number '%s'\n", resource.c_str()); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( m_noExpireResources[resourceBasic] == PostNoExpireRecent && resourceNumber < 0 ) { |
|
|
|
|
|
|
|
#ifdef DEBUG_EXPIRE_DHT_ITEM |
|
|
|
|
|
|
|
printf("shouldDhtResourceExpire: expiring post with invalid numbering '%s'\n", resource.c_str()); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( m_noExpireResources[resourceBasic] == PostNoExpireRecent && |
|
|
|
|
|
|
|
(height + BLOCK_AGE_TO_EXPIRE_DHT_POSTS) < getBestHeight() ) { |
|
|
|
|
|
|
|
#ifdef DEBUG_EXPIRE_DHT_ITEM |
|
|
|
|
|
|
|
printf("shouldDhtResourceExpire: expiring old post resource '%s'\n", resource.c_str()); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void receivedSpamMessage(std::string const &message, std::string const &user) |
|
|
|
void receivedSpamMessage(std::string const &message, std::string const &user) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs_twister); |
|
|
|
LOCK(cs_twister); |
|
|
|
if( !m_receivedSpamMsgStr.length() || |
|
|
|
bool hasSingleLangCode = (message.find("[") == message.rfind("[")); |
|
|
|
(m_preferredSpamLang.length() && message.find(m_preferredSpamLang) != string::npos) ) { |
|
|
|
bool hasPreferredLang = m_preferredSpamLang.length(); |
|
|
|
|
|
|
|
bool isSameLang = hasPreferredLang && hasSingleLangCode && |
|
|
|
|
|
|
|
message.find(m_preferredSpamLang) != string::npos; |
|
|
|
|
|
|
|
bool currentlyEmpty = !m_receivedSpamMsgStr.length(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( currentlyEmpty || (isSameLang && rand() < (RAND_MAX/2)) ) { |
|
|
|
m_receivedSpamMsgStr = message; |
|
|
|
m_receivedSpamMsgStr = message; |
|
|
|
m_receivedSpamUserStr = user; |
|
|
|
m_receivedSpamUserStr = user; |
|
|
|
} |
|
|
|
} |
|
|
@ -904,6 +1057,34 @@ Value dhtget(const Array& params, bool fHelp) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int findLastPublicPostLocalUser( std::string strUsername ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int lastk = -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOCK(cs_twister); |
|
|
|
|
|
|
|
if( strUsername.size() && m_userTorrent.count(strUsername) && |
|
|
|
|
|
|
|
m_userTorrent[strUsername].is_valid() ){ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> pieces; |
|
|
|
|
|
|
|
int max_id = std::numeric_limits<int>::max(); |
|
|
|
|
|
|
|
int since_id = -1; |
|
|
|
|
|
|
|
m_userTorrent[strUsername].get_pieces(pieces, 1, max_id, since_id, USERPOST_FLAG_RT); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pieces.size() ) { |
|
|
|
|
|
|
|
string const& piece = pieces.front(); |
|
|
|
|
|
|
|
lazy_entry v; |
|
|
|
|
|
|
|
int pos; |
|
|
|
|
|
|
|
error_code ec; |
|
|
|
|
|
|
|
if (lazy_bdecode(piece.data(), piece.data()+piece.size(), v, ec, &pos) == 0) { |
|
|
|
|
|
|
|
lazy_entry const* post = v.dict_find_dict("userpost"); |
|
|
|
|
|
|
|
lastk = post->dict_find_int_value("k",-1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return lastk; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value newpostmsg(const Array& params, bool fHelp) |
|
|
|
Value newpostmsg(const Array& params, bool fHelp) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fHelp || (params.size() != 3 && params.size() != 5)) |
|
|
|
if (fHelp || (params.size() != 3 && params.size() != 5)) |
|
|
@ -927,6 +1108,11 @@ Value newpostmsg(const Array& params, bool fHelp) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
entry v; |
|
|
|
entry v; |
|
|
|
|
|
|
|
// [MF] Warning: findLastPublicPostLocalUser requires that we follow ourselves
|
|
|
|
|
|
|
|
int lastk = findLastPublicPostLocalUser(strUsername); |
|
|
|
|
|
|
|
if( lastk >= 0 ) |
|
|
|
|
|
|
|
v["userpost"]["lastk"] = lastk; |
|
|
|
|
|
|
|
|
|
|
|
if( !createSignedUserpost(v, strUsername, k, strMsg, |
|
|
|
if( !createSignedUserpost(v, strUsername, k, strMsg, |
|
|
|
NULL, NULL, NULL, |
|
|
|
NULL, NULL, NULL, |
|
|
|
strReplyN, replyK) ) |
|
|
|
strReplyN, replyK) ) |
|
|
@ -1046,6 +1232,11 @@ Value newrtmsg(const Array& params, bool fHelp) |
|
|
|
entry const *sig_rt= vrt.find_key("sig_userpost"); |
|
|
|
entry const *sig_rt= vrt.find_key("sig_userpost"); |
|
|
|
|
|
|
|
|
|
|
|
entry v; |
|
|
|
entry v; |
|
|
|
|
|
|
|
// [MF] Warning: findLastPublicPostLocalUser requires that we follow ourselves
|
|
|
|
|
|
|
|
int lastk = findLastPublicPostLocalUser(strUsername); |
|
|
|
|
|
|
|
if( lastk >= 0 ) |
|
|
|
|
|
|
|
v["userpost"]["lastk"] = lastk; |
|
|
|
|
|
|
|
|
|
|
|
if( !createSignedUserpost(v, strUsername, k, "", |
|
|
|
if( !createSignedUserpost(v, strUsername, k, "", |
|
|
|
rt, sig_rt, NULL, |
|
|
|
rt, sig_rt, NULL, |
|
|
|
std::string(""), 0) ) |
|
|
|
std::string(""), 0) ) |
|
|
@ -1140,24 +1331,26 @@ Value getposts(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs_twister); |
|
|
|
LOCK(cs_twister); |
|
|
|
if( m_receivedSpamMsgStr.length() ) { |
|
|
|
// we must agree on an acceptable level here
|
|
|
|
// we must agree on an acceptable level here
|
|
|
|
// what about one every eight hours? (not cumulative)
|
|
|
|
if( rand() < (RAND_MAX/10) ) { |
|
|
|
if( m_receivedSpamMsgStr.length() && GetAdjustedTime() > m_lastSpamTime + (8*3600) ) { |
|
|
|
entry v; |
|
|
|
m_lastSpamTime = GetAdjustedTime(); |
|
|
|
entry &userpost = v["userpost"]; |
|
|
|
|
|
|
|
|
|
|
|
entry v; |
|
|
|
userpost["n"] = m_receivedSpamUserStr; |
|
|
|
entry &userpost = v["userpost"]; |
|
|
|
userpost["k"] = 1; |
|
|
|
|
|
|
|
userpost["time"] = GetAdjustedTime(); |
|
|
|
userpost["n"] = m_receivedSpamUserStr; |
|
|
|
userpost["height"] = getBestHeight(); |
|
|
|
userpost["k"] = 1; |
|
|
|
|
|
|
|
userpost["time"] = GetAdjustedTime(); |
|
|
|
userpost["msg"] = m_receivedSpamMsgStr; |
|
|
|
userpost["height"] = getBestHeight(); |
|
|
|
|
|
|
|
|
|
|
|
unsigned char vchSig[65]; |
|
|
|
userpost["msg"] = m_receivedSpamMsgStr; |
|
|
|
RAND_bytes(vchSig,sizeof(vchSig)); |
|
|
|
|
|
|
|
v["sig_userpost"] = std::string((const char *)vchSig, sizeof(vchSig)); |
|
|
|
unsigned char vchSig[65]; |
|
|
|
ret.insert(ret.begin(),entryToJson(v)); |
|
|
|
RAND_bytes(vchSig,sizeof(vchSig)); |
|
|
|
} |
|
|
|
v["sig_userpost"] = std::string((const char *)vchSig, sizeof(vchSig)); |
|
|
|
|
|
|
|
ret.insert(ret.begin(),entryToJson(v)); |
|
|
|
|
|
|
|
|
|
|
|
m_receivedSpamMsgStr = ""; |
|
|
|
m_receivedSpamMsgStr = ""; |
|
|
|
m_receivedSpamUserStr = ""; |
|
|
|
m_receivedSpamUserStr = ""; |
|
|
|
} |
|
|
|
} |
|
|
|