diff options
Diffstat (limited to 'src/Channel.cpp')
-rw-r--r-- | src/Channel.cpp | 82 |
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; |