2021-10-08 19:08:23 -04:00
|
|
|
#include "util/rsdebug.h"
|
2021-11-01 04:16:41 -04:00
|
|
|
#include "util/rsprint.h"
|
|
|
|
#include "util/rsdir.h"
|
|
|
|
#include "util/rsbase64.h"
|
|
|
|
#include "util/radix64.h"
|
2021-10-08 19:08:23 -04:00
|
|
|
|
2021-11-01 05:47:07 -04:00
|
|
|
#include "pgp/rscertificate.h"
|
|
|
|
|
2021-10-08 19:08:23 -04:00
|
|
|
#include "friendserver.h"
|
2021-10-24 14:01:19 -04:00
|
|
|
#include "friend_server/fsitem.h"
|
2021-10-08 19:08:23 -04:00
|
|
|
|
2021-10-31 13:00:43 -04:00
|
|
|
static const rstime_t MAXIMUM_PEER_INACTIVE_DELAY = 600;
|
|
|
|
static const rstime_t DELAY_BETWEEN_TWO_AUTOWASH = 60;
|
|
|
|
static const rstime_t DELAY_BETWEEN_TWO_DEBUG_PRINT = 10;
|
|
|
|
|
2021-10-08 19:08:23 -04:00
|
|
|
void FriendServer::threadTick()
|
|
|
|
{
|
|
|
|
// Listen to the network interface, capture incoming data etc.
|
|
|
|
|
2021-10-09 09:06:06 -04:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
|
|
|
|
2021-10-11 17:40:22 -04:00
|
|
|
RsItem *item;
|
|
|
|
|
2021-10-19 17:24:50 -04:00
|
|
|
while(nullptr != (item = mni->GetItem()))
|
2021-10-11 17:40:22 -04:00
|
|
|
{
|
|
|
|
RsFriendServerItem *fsitem = dynamic_cast<RsFriendServerItem*>(item);
|
|
|
|
|
|
|
|
if(!fsitem)
|
|
|
|
{
|
|
|
|
RsErr() << "Received an item of the wrong type!" ;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
2021-10-19 17:24:50 -04:00
|
|
|
std::cerr << "Received item: " << std::endl << *fsitem << std::endl;
|
2021-10-11 17:40:22 -04:00
|
|
|
|
|
|
|
switch(fsitem->PacketSubType())
|
|
|
|
{
|
|
|
|
case RS_PKT_SUBTYPE_FS_CLIENT_REMOVE: handleClientRemove(dynamic_cast<RsFriendServerClientRemoveItem*>(fsitem));
|
|
|
|
break;
|
|
|
|
case RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH: handleClientPublish(dynamic_cast<RsFriendServerClientPublishItem*>(fsitem));
|
|
|
|
break;
|
|
|
|
default: ;
|
|
|
|
}
|
|
|
|
delete item;
|
|
|
|
}
|
2021-10-31 13:00:43 -04:00
|
|
|
|
|
|
|
static rstime_t last_autowash_TS = time(nullptr);
|
|
|
|
rstime_t now = time(nullptr);
|
|
|
|
|
|
|
|
if(last_autowash_TS + DELAY_BETWEEN_TWO_AUTOWASH < now)
|
|
|
|
{
|
|
|
|
last_autowash_TS = now;
|
|
|
|
autoWash();
|
|
|
|
}
|
|
|
|
|
|
|
|
static rstime_t last_debugprint_TS = time(nullptr);
|
|
|
|
|
|
|
|
if(last_debugprint_TS + DELAY_BETWEEN_TWO_DEBUG_PRINT < now)
|
|
|
|
{
|
|
|
|
last_debugprint_TS = now;
|
|
|
|
debugPrint();
|
|
|
|
}
|
2021-10-08 19:08:23 -04:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:40:22 -04:00
|
|
|
void FriendServer::handleClientPublish(const RsFriendServerClientPublishItem *item)
|
|
|
|
{
|
2021-11-01 04:16:41 -04:00
|
|
|
try
|
|
|
|
{
|
|
|
|
RsDbg() << "Received a client publish item from " << item->PeerId() ;
|
|
|
|
RsDbg() << *item ;
|
|
|
|
|
|
|
|
// First of all, read PGP key and short invites, parse them, and check that they contain the same information
|
|
|
|
|
|
|
|
RsDbg() << " Checking item data...";
|
|
|
|
|
|
|
|
std::string error_string;
|
|
|
|
RsPgpId pgp_id ;
|
|
|
|
std::vector<uint8_t> key_binary_data ;
|
|
|
|
|
|
|
|
key_binary_data = Radix64::decode(item->pgp_public_key_b64);
|
|
|
|
|
|
|
|
if(key_binary_data.empty())
|
|
|
|
throw std::runtime_error(" Cannot decode client pgp public key: \"" + item->pgp_public_key_b64 + "\". Wrong format??");
|
|
|
|
// if(!RsBase64::decode(item->pgp_public_key_b64,key_binary_data))
|
|
|
|
// throw std::runtime_error(" Cannot decode client pgp public key: \"" + item->pgp_public_key_b64 + "\". Wrong format??");
|
|
|
|
|
|
|
|
RsDbg() << " Public key radix is fine." ;
|
|
|
|
|
|
|
|
if(!mPgpHandler->LoadCertificateFromBinaryData(key_binary_data.data(),key_binary_data.size(), pgp_id, error_string))
|
|
|
|
throw std::runtime_error("Cannot load client's pgp public key into keyring: " + error_string) ;
|
|
|
|
|
|
|
|
RsDbg() << " Public key added to keyring.";
|
|
|
|
|
|
|
|
RsPeerDetails shortInviteDetails;
|
|
|
|
uint32_t errorCode = 0;
|
|
|
|
|
2021-11-01 05:47:07 -04:00
|
|
|
if(item->short_invite.empty() || !RsCertificate::decodeRadix64ShortInvite(item->short_invite, shortInviteDetails,errorCode ))
|
2021-11-01 04:16:41 -04:00
|
|
|
throw std::runtime_error("Could not parse short certificate. Error = " + RsUtil::NumberToString(errorCode));
|
|
|
|
|
|
|
|
RsDbg() << " Short invite is fine. PGP fingerprint: " << shortInviteDetails.fpr ;
|
|
|
|
|
|
|
|
RsPgpFingerprint fpr_test;
|
|
|
|
if(!mPgpHandler->getKeyFingerprint(pgp_id,fpr_test))
|
|
|
|
throw std::runtime_error("Cannot get fingerprint from keyring for client public key. Something's really wrong.") ;
|
|
|
|
|
|
|
|
if(fpr_test != shortInviteDetails.fpr)
|
|
|
|
throw std::runtime_error("Cannot get fingerprint from keyring for client public key. Something's really wrong.") ;
|
2021-10-31 07:02:09 -04:00
|
|
|
|
2021-11-01 04:16:41 -04:00
|
|
|
RsDbg() << " Short invite PGP fingerprint matches the public key fingerprint." ;
|
|
|
|
|
|
|
|
// Check the item's data signature
|
|
|
|
|
|
|
|
// All good.
|
|
|
|
#warning TODO
|
|
|
|
|
|
|
|
// Store/update the peer info
|
|
|
|
|
|
|
|
auto& pi(mCurrentClientPeers[shortInviteDetails.id]);
|
|
|
|
|
|
|
|
pi.short_certificate = item->short_invite;
|
|
|
|
pi.last_connection_TS = time(nullptr);
|
|
|
|
|
|
|
|
// Respond with a list of potential friends
|
|
|
|
}
|
|
|
|
catch(std::exception& e)
|
|
|
|
{
|
|
|
|
RsErr() << e.what() ;
|
|
|
|
}
|
2021-10-31 07:02:09 -04:00
|
|
|
|
|
|
|
// Close client connection from server side, to tell the client that nothing more is coming.
|
|
|
|
|
|
|
|
RsDbg() << "Closing client connection." ;
|
|
|
|
|
|
|
|
mni->closeConnection(item->PeerId());
|
2021-10-11 17:40:22 -04:00
|
|
|
}
|
2021-11-01 04:16:41 -04:00
|
|
|
|
2021-10-11 17:40:22 -04:00
|
|
|
void FriendServer::handleClientRemove(const RsFriendServerClientRemoveItem *item)
|
|
|
|
{
|
|
|
|
RsDbg() << "Received a client remove item:" << *item ;
|
|
|
|
}
|
2021-10-08 19:08:23 -04:00
|
|
|
FriendServer::FriendServer(const std::string& base_dir)
|
|
|
|
{
|
2021-10-09 09:06:06 -04:00
|
|
|
RsDbg() << "Creating friend server." ;
|
2021-10-08 19:08:23 -04:00
|
|
|
mBaseDirectory = base_dir;
|
2021-11-01 04:16:41 -04:00
|
|
|
|
|
|
|
// Create a PGP Handler
|
|
|
|
|
|
|
|
std::string pgp_public_keyring_path = RsDirUtil::makePath(base_dir,"pgp_public_keyring") ;
|
|
|
|
std::string pgp_lock_path = RsDirUtil::makePath(base_dir,"pgp_lock") ;
|
|
|
|
|
|
|
|
std::string pgp_private_keyring_path = RsDirUtil::makePath(base_dir,"pgp_private_keyring") ; // not used.
|
|
|
|
std::string pgp_trustdb_path = RsDirUtil::makePath(base_dir,"pgp_trustdb") ; // not used.
|
|
|
|
|
|
|
|
mPgpHandler = new PGPHandler(pgp_public_keyring_path,pgp_private_keyring_path,pgp_trustdb_path,pgp_lock_path);
|
2021-10-08 19:08:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FriendServer::run()
|
|
|
|
{
|
|
|
|
// 1 - create network interface.
|
|
|
|
|
|
|
|
mni = new FsNetworkInterface;
|
2021-10-09 09:06:06 -04:00
|
|
|
mni->start();
|
2021-10-08 19:08:23 -04:00
|
|
|
|
|
|
|
while(!shouldStop()) { threadTick() ; }
|
|
|
|
}
|
|
|
|
|
2021-10-31 13:00:43 -04:00
|
|
|
void FriendServer::autoWash()
|
|
|
|
{
|
|
|
|
rstime_t now = time(nullptr);
|
|
|
|
|
|
|
|
for(std::map<RsPeerId,PeerInfo>::iterator it(mCurrentClientPeers.begin());it!=mCurrentClientPeers.end();)
|
|
|
|
{
|
|
|
|
if(it->second.last_connection_TS + MAXIMUM_PEER_INACTIVE_DELAY < now)
|
|
|
|
{
|
|
|
|
RsDbg() << "Removing client peer " << it->first << " because it's inactive for more than " << MAXIMUM_PEER_INACTIVE_DELAY << " seconds." ;
|
|
|
|
auto tmp = it;
|
|
|
|
++tmp;
|
|
|
|
mCurrentClientPeers.erase(it);
|
|
|
|
it = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FriendServer::debugPrint()
|
|
|
|
{
|
|
|
|
RsDbg() << "========== FriendServer statistics ============";
|
|
|
|
RsDbg() << " Base directory: "<< mBaseDirectory;
|
|
|
|
RsDbg() << " Network interface: ";
|
|
|
|
RsDbg() << " Current peers: " << mCurrentClientPeers.size() ;
|
|
|
|
|
|
|
|
rstime_t now = time(nullptr);
|
|
|
|
|
|
|
|
for(auto& it:mCurrentClientPeers)
|
|
|
|
RsDbg() << " " << it.first << ": " << "last contact: " << now - it.second.last_connection_TS;
|
|
|
|
|
|
|
|
RsDbg() << "===============================================";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|