aboutsummaryrefslogtreecommitdiff
path: root/src/Channel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Channel.cpp')
-rw-r--r--src/Channel.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/Channel.cpp b/src/Channel.cpp
index 0bacbc3..41233ad 100644
--- a/src/Channel.cpp
+++ b/src/Channel.cpp
@@ -25,13 +25,60 @@ namespace dchat
// addLocalMessage(u8"ht clic", &systemUser, 0, odhtdb::Hash());
if(database)
+ {
database->seed(databaseNodeInfo);
+
+ pingKey = odhtdb::DhtKey(*databaseNodeInfo.getRequestHash()).getPingKey();
+ // TODO: Ban peers that spam this key (take in account that creator of packets can be forged)
+ pingListener = database->receiveCustomMessage(pingKey, [this](const void *data, usize size)
+ {
+ sibs::SafeSerializer result;
+ try
+ {
+ sibs::SafeDeserializer deserializer((const u8*)data, size);
+ u8 userPublicKeyRaw[odhtdb::PUBLIC_KEY_NUM_BYTES];
+ deserializer.extract(userPublicKeyRaw, odhtdb::PUBLIC_KEY_NUM_BYTES);
+ odhtdb::Signature::PublicKey userPublicKey((const char*)userPublicKeyRaw, odhtdb::PUBLIC_KEY_NUM_BYTES);
+ auto user = getUserByPublicKey(userPublicKey);
+ if(!user)
+ {
+ // TODO: Ban peer if this happens too often
+ return result;
+ }
+
+ string unsignedData = userPublicKey.unsign(odhtdb::DataView((void*)deserializer.getBuffer(), deserializer.getSize()));
+ sibs::SafeDeserializer unsignedDeserializer((const u8*)unsignedData.data(), unsignedData.size());
+ u32 pingCounter = unsignedDeserializer.extract<u32>();
+ u64 pingTimestamp = unsignedDeserializer.extract<u64>();
+ // TODO: A malicious peer can capture the packets and reply them after the user has reconnect and counter has reset, need to fix this somehow.
+ // One solution is for the user to store the counter locally in file and continue using it when reconnecting
+ if(pingCounter > user->pingCounter)
+ {
+ user->pingCounter = pingCounter;
+ user->pingTimestamp = pingTimestamp;
+ }
+ }
+ catch(std::exception &e)
+ {
+ fprintf(stderr, "Failed while deseralizing ping\n");
+ }
+ return result;
+ });
+ }
}
Channel::~Channel()
{
if(database)
+ {
+ database->cancelNodeListener(pingKey, pingListener);
database->stopSeeding(*databaseNodeInfo.getRequestHash());
+ if(database && localUser->type == User::Type::ONLINE_LOCAL_USER)
+ {
+ auto onlineLocalUser = static_cast<OnlineLocalUser*>(localUser);
+ sendPing(onlineLocalUser->pingCounter + 1, 0);
+ }
+ }
for(User *user : users)
{
@@ -208,6 +255,41 @@ namespace dchat
chatbar.draw(window, cache);
}
+ void Channel::update()
+ {
+ if(database && localUser->type == User::Type::ONLINE_LOCAL_USER && pingTimer.getElapsedTime().asMilliseconds() > 5000)
+ {
+ pingTimer.restart();
+ auto onlineLocalUser = static_cast<OnlineLocalUser*>(localUser);
+ sendPing(onlineLocalUser->pingCounter + 1, database->getSyncedTimestampUtc().getCombined());
+ }
+ }
+
+ void Channel::sendPing(u32 pingCounter, u64 pingTimestamp)
+ {
+ if(database && localUser->type == User::Type::ONLINE_LOCAL_USER)
+ {
+ //printf("Sending ping, counter: %u\n", pingCounter);
+ auto onlineLocalUser = static_cast<OnlineLocalUser*>(localUser);
+ sibs::SafeSerializer serializer;
+ serializer.add((const u8*)onlineLocalUser->getPublicKey().getData(), onlineLocalUser->getPublicKey().getSize());
+
+ sibs::SafeSerializer signedSerializer;
+ signedSerializer.add(pingCounter);
+ signedSerializer.add(pingTimestamp);
+ string signedData = onlineLocalUser->keyPair.getPrivateKey().sign(odhtdb::DataView(signedSerializer.getBuffer().data(), signedSerializer.getBuffer().size()));
+ serializer.add((const u8*)signedData.data(), signedData.size());
+ database->sendCustomMessage(pingKey, move(serializer.getBuffer()));
+ }
+ }
+
+ u64 Channel::getSyncedTimestampUtcCombined()
+ {
+ if(!database)
+ return 0;
+ return database->getSyncedTimestampUtc().getCombined();
+ }
+
void Channel::setCurrent(Channel *channel)
{
currentChannel = channel;