Page MenuHomePhorge

send.cpp
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

send.cpp

/*
* Copyright (C) 2020 Tusooa Zhu <tusooa@vista.aero>
*
* This file is part of libkazv.
*
* libkazv is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* libkazv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with libkazv. If not, see <https://www.gnu.org/licenses/>.
*/
#include <libkazv-config.hpp>
#include <debug.hpp>
#include <types.hpp>
#include "send.hpp"
namespace Kazv
{
static std::string increaseTxnId(std::string cur)
{
return std::to_string(std::stoull(cur) + 1);
}
ClientResult updateClient(ClientModel m, SendMessageAction a)
{
auto event = std::move(a.event);
auto roomId = a.roomId;
auto beforeEncryption = event.originalJson().get();
if (!beforeEncryption.contains("type") || !beforeEncryption.contains("content")) {
m.addTrigger(InvalidMessageFormat{});
return { std::move(m), lager::noop };
}
auto shouldSendKey = false;
std::string sessionKey;
if (m.crypto) {
if (m.roomList[roomId].encrypted && ! event.encrypted()) {
auto res = m.megOlmEncrypt(std::move(event), roomId);
event = res.first;
shouldSendKey = !! res.second;
if (shouldSendKey) {
sessionKey = res.second.value();
}
}
}
auto origJson = event.originalJson().get();
if (!origJson.contains("type") || !origJson.contains("content")) {
m.addTrigger(InvalidMessageFormat{});
return { std::move(m), lager::noop };
}
// We do not use event.type() etc. because we want
// encrypted events stay encrypted.
auto type = origJson["type"];
auto content = origJson["content"];
kzo.client.dbg() << "Sending message of type " << type
<< " with content " << content.dump()
<< " to " << a.roomId
<< " as #" << m.nextTxnId << std::endl;
// We combine the hash of json, the timestamp,
// and a numeric count in the client to avoid collision.
auto txnId = std::to_string(std::hash<json>{}(origJson))
+ std::to_string(std::chrono::system_clock::now()
.time_since_epoch().count())
+ m.nextTxnId;
m.nextTxnId = increaseTxnId(m.nextTxnId);
auto job = m.job<SendMessageJob>()
.make(a.roomId, type, txnId, content)
.withData(json{{"roomId", a.roomId}});
m.addJob(std::move(job));
auto devicesToSend = immer::map<std::string, immer::flex_vector<std::string>>{};
if (shouldSendKey) {
kzo.client.dbg() << "We should also send the session key." << std::endl;
auto roomMembers = m.roomList[roomId].joinedMemberIds();
kzo.client.dbg() << "room members" << std::endl;
for (auto userId : roomMembers) {
devicesToSend = std::move(devicesToSend)
.set(userId, m.devicesToSendKeys(userId));
}
}
return { std::move(m),
shouldSendKey
? ClientEffect([=, sessionId=content.at("session_id")](auto &&ctx) {
kzo.client.dbg() << "dispatching cliamkeys action" << std::endl;
ctx.dispatch(ClaimKeysAndSendSessionKeyAction{
roomId,
sessionId,
sessionKey,
devicesToSend
});
})
: ClientEffect(lager::noop)
};
}
ClientResult processResponse(ClientModel m, SendMessageResponse r)
{
auto roomId = r.dataStr("roomId");
if (! r.success()) {
kzo.client.dbg() << "Send message failed" << std::endl;
m.addTrigger(SendMessageFailed{roomId, r.errorCode(), r.errorMessage()});
return { std::move(m), lager::noop };
}
m.addTrigger(SendMessageSuccessful{roomId, r.eventId()});
return { std::move(m), lager::noop };
}
ClientResult updateClient(ClientModel m, SendToDeviceMessageAction a)
{
auto origJson = a.event.originalJson().get();
if (!origJson.contains("type") || !origJson.contains("content")) {
m.addTrigger(InvalidMessageFormat{});
return { std::move(m), lager::noop };
}
// We do not use event.type() etc. because we want
// encrypted events stay encrypted.
auto type = origJson["type"];
auto content = origJson["content"];
auto txnId = std::to_string(std::hash<json>{}(origJson))
+ std::to_string(std::chrono::system_clock::now()
.time_since_epoch().count())
+ m.nextTxnId;
m.nextTxnId = increaseTxnId(m.nextTxnId);
auto messages =
immer::map<std::string, immer::map<std::string, JsonWrap>>{};
for (auto [userId, devices] : a.devicesToSend) {
auto deviceIdToContentMap = immer::map<std::string, JsonWrap>{};
for (auto deviceId : devices) {
deviceIdToContentMap = std::move(deviceIdToContentMap).set(deviceId, content);
}
messages = std::move(messages).set(userId, deviceIdToContentMap);
}
auto job = m.job<SendToDeviceJob>()
.make(type, txnId, messages)
.withData(json{{"devicesToSend", a.devicesToSend},
{"txnId", txnId}});
m.addJob(std::move(job));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, SendToDeviceResponse r)
{
auto devicesToSend = r.dataJson("devicesToSend");
auto txnId = r.dataStr("txnId");
if (! r.success()) {
m.addTrigger(SendToDeviceMessageFailed{devicesToSend, txnId, r.errorCode(), r.errorMessage()});
return { std::move(m), lager::noop };
}
m.addTrigger(SendToDeviceMessageSuccessful{devicesToSend, txnId});
return { std::move(m), lager::noop };
}
}

File Metadata

Mime Type
text/x-c++
Expires
Wed, May 14, 11:01 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
134420
Default Alt Text
send.cpp (6 KB)

Event Timeline