Page MenuHomePhorge

send.cpp
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None

send.cpp

/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2020 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include <debug.hpp>
#include <types.hpp>
#include "send.hpp"
#include "status-utils.hpp"
namespace Kazv
{
ClientResult updateClient(ClientModel m, SendMessageAction a)
{
auto event = std::move(a.event);
auto roomId = a.roomId;
auto origJson = event.originalJson().get();
if (!origJson.contains("type") || !origJson.contains("content")) {
m.addTrigger(InvalidMessageFormat{});
return { std::move(m), lager::noop };
}
if (m.roomList.rooms[a.roomId].encrypted && !event.encrypted()) {
if (!event.isState()) {
return { std::move(m), [](auto &&) {
return EffectStatus{
/* succ = */ false,
json{
{"errorCode", "MOE_KAZV_MXC_SENDING_UNENCRYPTED_EVENT_TO_ENCRYPTED_ROOM"},
{"error", "Cannot send unencrypted event to encrypted room"},
}
};
}};
}
}
// 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 = a.txnId.has_value() ? a.txnId.value() : getTxnId(event, m);
m.roomList = RoomListModel::update(std::move(m.roomList),
UpdateRoomAction{
roomId,
AddLocalEchoAction{{txnId, event}},
}
);
auto job = m.job<SendMessageJob>()
.make(a.roomId, type, txnId, content)
.withData(json{
{"roomId", a.roomId},
{"txnId", txnId},
});
m.addJob(std::move(job));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, SendMessageResponse r)
{
auto roomId = r.dataStr("roomId");
if (! r.success()) {
auto txnId = r.dataStr("txnId");
kzo.client.dbg() << "Send message failed" << std::endl;
m.roomList.rooms = std::move(m.roomList.rooms).update(roomId, [txnId](auto room) {
auto maybeLocalEcho = room.getLocalEchoByTxnId(txnId);
if (!maybeLocalEcho.has_value()) {
kzo.client.warn() << "We do not have local echo with txnId " << txnId << " . Have we time-travelled?" << std::endl;
return room;
}
auto localEcho = std::move(maybeLocalEcho).value();
localEcho.status = LocalEchoDesc::Failed;
return RoomModel::update(std::move(room), AddLocalEchoAction{localEcho});
});
m.addTrigger(SendMessageFailed{roomId, r.errorCode(), r.errorMessage()});
return { std::move(m), failWithResponse(r) };
}
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")) {
return { std::move(m), simpleFail };
}
// We do not use event.type() etc. because we want
// encrypted events stay encrypted.
auto type = origJson["type"];
auto content = origJson["content"];
if (type == "m.room_key" && !a.event.encrypted()) {
kzo.client.err() << "Trying to send room key event unencrypted! Rejecting." << std::endl;
return { std::move(m), [](auto &&) {
return EffectStatus{
/* succ = */ false,
json{
{"errorCode", "MOE_KAZV_MXC_SENDING_ROOM_KEY_EVENT_UNENCRYPTED"},
{"error", "Cannot send room key event unencrypted"},
}
};
}};
}
auto txnId = a.txnId.has_value() ? a.txnId.value() : getTxnId(a.event, m);
kzo.client.info() << "sending to-device message with txnId " << txnId;
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), failWithResponse(r) };
}
m.addTrigger(SendToDeviceMessageSuccessful{devicesToSend, txnId});
return { std::move(m), lager::noop };
}
ClientResult updateClient(ClientModel m, SaveLocalEchoAction a)
{
auto txnId = a.txnId.has_value() ? a.txnId.value() : getTxnId(a.event, m);
m.roomList = RoomListModel::update(m.roomList, UpdateRoomAction{
a.roomId,
AddLocalEchoAction{{txnId, a.event}},
});
return { std::move(m), [txnId](auto) {
return EffectStatus(true, json::object({{"txnId", txnId}}));
}};
}
ClientResult updateClient(ClientModel m, UpdateLocalEchoStatusAction a)
{
auto txnId = a.txnId;
auto maybeLocalEcho = m.roomList.rooms[a.roomId].getLocalEchoByTxnId(txnId);
if (!maybeLocalEcho.has_value()) {
return { std::move(m), [](const auto &) {
return EffectStatus(/* succ = */ false, json{
{"errorCode", "MOE_KAZV_MXC_LOCAL_ECHO_NOT_FOUND"},
{"error", "Local echo not found"},
});
} };
}
auto localEcho = maybeLocalEcho.value();
m.roomList = RoomListModel::update(m.roomList, UpdateRoomAction{
a.roomId,
AddLocalEchoAction{{txnId, localEcho.event, a.status}},
});
return { std::move(m), lager::noop };
}
ClientResult updateClient(ClientModel m, RedactEventAction a)
{
auto txnId = getTxnId(Event{json{
{"room_id", a.roomId},
{"event_id", a.eventId},
}}, m);
auto job = m.job<RedactEventJob>()
.make(a.roomId, a.eventId, txnId, a.reason);
m.addJob(std::move(job));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, RedactEventResponse r)
{
if (!r.success()) {
return { std::move(m), failWithResponse(r) };
}
return { std::move(m), lager::noop };
}
}

File Metadata

Mime Type
text/x-c++
Expires
Thu, Oct 2, 2:25 AM (21 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
470714
Default Alt Text
send.cpp (7 KB)

Event Timeline