low level sync stuff
This commit is contained in:
parent
3b7db97507
commit
45a3915985
@ -5,11 +5,8 @@ project(solanaceae_crdtnotes)
|
|||||||
|
|
||||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||||
set(SOLANACEAE_CRDTNOTES_STANDALONE ON)
|
set(SOLANACEAE_CRDTNOTES_STANDALONE ON)
|
||||||
# why the f do i need this >:(
|
|
||||||
set(NOT_SOLANACEAE_CRDTNOTES_STANDALONE OFF)
|
|
||||||
else()
|
else()
|
||||||
set(SOLANACEAE_CRDTNOTES_STANDALONE OFF)
|
set(SOLANACEAE_CRDTNOTES_STANDALONE OFF)
|
||||||
set(NOT_SOLANACEAE_CRDTNOTES_STANDALONE ON)
|
|
||||||
endif()
|
endif()
|
||||||
message("II SOLANACEAE_CRDTNOTES_STANDALONE " ${SOLANACEAE_CRDTNOTES_STANDALONE})
|
message("II SOLANACEAE_CRDTNOTES_STANDALONE " ${SOLANACEAE_CRDTNOTES_STANDALONE})
|
||||||
|
|
||||||
|
@ -22,3 +22,15 @@ target_link_libraries(plugin_crdtnotes_imgui PUBLIC
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
|
if (TARGET solanaceae_crdtnotes_toxsync)
|
||||||
|
add_library(plugin_crdtnotes_toxsync SHARED
|
||||||
|
./plugin_crdtnotes_toxsync.cpp
|
||||||
|
)
|
||||||
|
target_compile_features(plugin_crdtnotes_toxsync PUBLIC cxx_std_17)
|
||||||
|
target_link_libraries(plugin_crdtnotes_toxsync PUBLIC
|
||||||
|
solanaceae_crdtnotes_toxsync
|
||||||
|
solanaceae_plugin
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
########################################
|
||||||
|
97
plugins/plugin_crdtnotes_toxsync.cpp
Normal file
97
plugins/plugin_crdtnotes_toxsync.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include <solanaceae/plugin/solana_plugin_v1.h>
|
||||||
|
|
||||||
|
#include <solanaceae/crdtnotes/crdtnotes.hpp>
|
||||||
|
#include <solanaceae/crdtnotes_toxsync/crdtnotes_toxsync.hpp>
|
||||||
|
//#include <solanaceae/util/config_model.hpp>
|
||||||
|
#include <solanaceae/contact/contact_model3.hpp>
|
||||||
|
#include <solanaceae/toxcore/tox_interface.hpp>
|
||||||
|
#include <solanaceae/toxcore/tox_event_interface.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define RESOLVE_INSTANCE(x) static_cast<x*>(solana_api->resolveInstance(#x))
|
||||||
|
#define PROVIDE_INSTANCE(x, p, v) solana_api->provideInstance(#x, p, static_cast<x*>(v))
|
||||||
|
|
||||||
|
static std::unique_ptr<CRDTNotesToxSync> g_crdtn_ts = nullptr;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
SOLANA_PLUGIN_EXPORT const char* solana_plugin_get_name(void) {
|
||||||
|
return "CRDTNotesToxSync";
|
||||||
|
}
|
||||||
|
|
||||||
|
SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_get_version(void) {
|
||||||
|
return SOLANA_PLUGIN_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api) {
|
||||||
|
std::cout << "PLUGIN CRDTNTS START()\n";
|
||||||
|
|
||||||
|
if (solana_api == nullptr) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ConfigModelI* conf = nullptr;
|
||||||
|
CRDTNotes* notes = nullptr;
|
||||||
|
Contact3Registry* cr = nullptr;
|
||||||
|
ToxI* t = nullptr;
|
||||||
|
ToxEventProviderI* tep = nullptr;
|
||||||
|
|
||||||
|
{ // make sure required types are loaded
|
||||||
|
//conf = RESOLVE_INSTANCE(ConfigModelI);
|
||||||
|
notes = RESOLVE_INSTANCE(CRDTNotes);
|
||||||
|
cr = RESOLVE_INSTANCE(Contact3Registry);
|
||||||
|
t = RESOLVE_INSTANCE(ToxI);
|
||||||
|
tep = RESOLVE_INSTANCE(ToxEventProviderI);
|
||||||
|
|
||||||
|
//if (conf == nullptr) {
|
||||||
|
//std::cerr << "PLUGIN CRDTN missing ConfigModelI\n";
|
||||||
|
//return 2;
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (notes == nullptr) {
|
||||||
|
std::cerr << "PLUGIN CRDTNTS missing CRDTNotes\n";
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cr == nullptr) {
|
||||||
|
std::cerr << "PLUGIN CRDTNTS missing Contact3Registry\n";
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == nullptr) {
|
||||||
|
std::cerr << "PLUGIN CRDTNTS missing ToxI\n";
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tep == nullptr) {
|
||||||
|
std::cerr << "PLUGIN CRDTNTS missing ToxEventProviderI\n";
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static store, could be anywhere tho
|
||||||
|
// construct with fetched dependencies
|
||||||
|
g_crdtn_ts = std::make_unique<CRDTNotesToxSync>(*notes, *cr, *t, *tep);
|
||||||
|
|
||||||
|
// register types
|
||||||
|
PROVIDE_INSTANCE(CRDTNotesToxSync, "CRDTNotesToxSync", g_crdtn_ts.get());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOLANA_PLUGIN_EXPORT void solana_plugin_stop(void) {
|
||||||
|
std::cout << "PLUGIN CRDTNTS STOP()\n";
|
||||||
|
|
||||||
|
g_crdtn_ts.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
SOLANA_PLUGIN_EXPORT void solana_plugin_tick(float delta) {
|
||||||
|
(void)delta;
|
||||||
|
//std::cout << "PLUGIN CRDTN TICK()\n";
|
||||||
|
g_crdtn_ts->iterate(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern C
|
||||||
|
|
@ -3,11 +3,13 @@ cmake_minimum_required(VERSION 3.24 FATAL_ERROR)
|
|||||||
add_library(solanaceae_crdtnotes
|
add_library(solanaceae_crdtnotes
|
||||||
./solanaceae/crdtnotes/crdtnotes.hpp
|
./solanaceae/crdtnotes/crdtnotes.hpp
|
||||||
./solanaceae/crdtnotes/crdtnotes.cpp
|
./solanaceae/crdtnotes/crdtnotes.cpp
|
||||||
|
./solanaceae/crdtnotes/crdtnotes_contact_sync_model.hpp
|
||||||
)
|
)
|
||||||
target_include_directories(solanaceae_crdtnotes PUBLIC .)
|
target_include_directories(solanaceae_crdtnotes PUBLIC .)
|
||||||
target_compile_features(solanaceae_crdtnotes PUBLIC cxx_std_17)
|
target_compile_features(solanaceae_crdtnotes PUBLIC cxx_std_17)
|
||||||
target_link_libraries(solanaceae_crdtnotes PUBLIC
|
target_link_libraries(solanaceae_crdtnotes PUBLIC
|
||||||
crdt_version3
|
crdt_version3
|
||||||
|
solanaceae_contact
|
||||||
#solanaceae_util
|
#solanaceae_util
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,6 +31,7 @@ target_link_libraries(solanaceae_crdtnotes_imgui PUBLIC
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
|
if (TARGET solanaceae_toxcore AND TARGET solanaceae_tox_contacts)
|
||||||
add_library(solanaceae_crdtnotes_toxsync
|
add_library(solanaceae_crdtnotes_toxsync
|
||||||
./solanaceae/crdtnotes_toxsync/crdtnotes_toxsync.hpp
|
./solanaceae/crdtnotes_toxsync/crdtnotes_toxsync.hpp
|
||||||
./solanaceae/crdtnotes_toxsync/crdtnotes_toxsync.cpp
|
./solanaceae/crdtnotes_toxsync/crdtnotes_toxsync.cpp
|
||||||
@ -40,7 +43,9 @@ target_link_libraries(solanaceae_crdtnotes_toxsync PUBLIC
|
|||||||
#solanaceae_util
|
#solanaceae_util
|
||||||
solanaceae_contact
|
solanaceae_contact
|
||||||
|
|
||||||
#tox
|
solanaceae_toxcore
|
||||||
|
solanaceae_tox_contacts
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
// fwd
|
||||||
|
struct CRDTNotesContactSyncModelI;
|
||||||
|
|
||||||
using ID32 = std::array<uint8_t, 32>;
|
using ID32 = std::array<uint8_t, 32>;
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@ -33,6 +36,10 @@ class CRDTNotes {
|
|||||||
using CRDTAgent = ID32;
|
using CRDTAgent = ID32;
|
||||||
using DocID = ID32;
|
using DocID = ID32;
|
||||||
using Doc = GreenCRDT::V3::TextDocument<CRDTAgent>;
|
using Doc = GreenCRDT::V3::TextDocument<CRDTAgent>;
|
||||||
|
struct Frontier { // newest known seq for given agent
|
||||||
|
CRDTAgent agent;
|
||||||
|
uint64_t seq{0};
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO: add metadata to docs
|
// TODO: add metadata to docs
|
||||||
|
50
src/solanaceae/crdtnotes/crdtnotes_contact_sync_model.hpp
Normal file
50
src/solanaceae/crdtnotes/crdtnotes_contact_sync_model.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./crdtnotes.hpp"
|
||||||
|
|
||||||
|
#include <solanaceae/contact/contact_model3.hpp>
|
||||||
|
|
||||||
|
// send api
|
||||||
|
struct CRDTNotesContactSyncModelI {
|
||||||
|
virtual ~CRDTNotesContactSyncModelI(void) {}
|
||||||
|
|
||||||
|
// gossip
|
||||||
|
public:
|
||||||
|
// notify of doc existing
|
||||||
|
virtual void SendGossip(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual void SendGossip(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
const std::vector<CRDTNotes::Frontier>& selected_frontier
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
// fetch
|
||||||
|
public:
|
||||||
|
// causes the other peer to send gossip with all known frontiers (on cool down)
|
||||||
|
virtual void SendFetchCompleteFrontier(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
// action range request
|
||||||
|
virtual void SendFetchOps(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
const CRDTNotes::CRDTAgent& agent,
|
||||||
|
const uint64_t seq_from,
|
||||||
|
const uint64_t seq_to
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
public: // ops response
|
||||||
|
virtual void SendOps(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
// TODO: optimize this
|
||||||
|
const std::vector<CRDTNotes::Doc::Op>&
|
||||||
|
) = 0;
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,265 @@
|
|||||||
#include "./crdtnotes_toxsync.hpp"
|
#include "./crdtnotes_toxsync.hpp"
|
||||||
|
|
||||||
|
#include <solanaceae/toxcore/tox_interface.hpp>
|
||||||
|
|
||||||
CRDTNotesToxSync::CRDTNotesToxSync(CRDTNotes& notes, Contact3Registry& cr) : _notes(notes), _cr(cr) {
|
#include <solanaceae/tox_contacts/components.hpp>
|
||||||
|
|
||||||
|
enum class NGCEXT_Event : uint8_t {
|
||||||
|
// - DocID
|
||||||
|
CRDTN_GOSSIP = 0x80 | 0x10,
|
||||||
|
|
||||||
|
// - DocID
|
||||||
|
// - array [
|
||||||
|
// - AgentID
|
||||||
|
// - seq (frontier)
|
||||||
|
// - ]
|
||||||
|
CRDTN_GOSSIP_FRONTIER,
|
||||||
|
|
||||||
|
// - DocID
|
||||||
|
CRDTN_FETCH_COMPLETE_FRONTIER,
|
||||||
|
|
||||||
|
// - DocID
|
||||||
|
// - AgentID
|
||||||
|
// - seq_from
|
||||||
|
// - seq_to
|
||||||
|
CRDTN_FETCH_OP_RANGE,
|
||||||
|
|
||||||
|
// - DocID
|
||||||
|
// - array [
|
||||||
|
// - seq
|
||||||
|
// - action date
|
||||||
|
// - ]
|
||||||
|
CRDTN_OPS,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CRDTNotesToxSync::CRDTNotesToxSync(
|
||||||
|
CRDTNotes& notes,
|
||||||
|
Contact3Registry& cr,
|
||||||
|
ToxI& t,
|
||||||
|
ToxEventProviderI& tep
|
||||||
|
) : _notes(notes), _cr(cr), _t(t), _tep(tep) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CRDTNotesToxSync::~CRDTNotesToxSync(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
float CRDTNotesToxSync::iterate(float time_delta) {
|
||||||
|
return 1.f; // TODO: 1sec for now, needs better logic
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRDTNotesToxSync::SendGossip(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id
|
||||||
|
) {
|
||||||
|
if (!c.all_of<Contact::Components::ToxGroupPeerEphemeral>()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> pkg;
|
||||||
|
|
||||||
|
pkg.push_back(static_cast<uint8_t>(NGCEXT_Event::CRDTN_GOSSIP));
|
||||||
|
|
||||||
|
for (const uint8_t v : doc_id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send
|
||||||
|
const auto& gp = c.get<Contact::Components::ToxGroupPeerEphemeral>();
|
||||||
|
_t.toxGroupSendCustomPrivatePacket(
|
||||||
|
gp.group_number, gp.peer_number,
|
||||||
|
true,
|
||||||
|
pkg
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRDTNotesToxSync::SendGossip(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
const std::vector<CRDTNotes::Frontier>& selected_frontier
|
||||||
|
) {
|
||||||
|
if (!c.all_of<Contact::Components::ToxGroupPeerEphemeral>()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> pkg;
|
||||||
|
|
||||||
|
pkg.push_back(static_cast<uint8_t>(NGCEXT_Event::CRDTN_GOSSIP_FRONTIER));
|
||||||
|
// 1
|
||||||
|
|
||||||
|
for (const uint8_t v : doc_id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
// +32
|
||||||
|
|
||||||
|
for (const auto& [f_id, f_seq] : selected_frontier) {
|
||||||
|
for (const uint8_t v : f_id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
// +32
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(f_seq); i++) {
|
||||||
|
pkg.push_back((f_seq >> i*8) & 0xff);
|
||||||
|
}
|
||||||
|
// +8
|
||||||
|
}
|
||||||
|
// +40
|
||||||
|
|
||||||
|
// send
|
||||||
|
const auto& gp = c.get<Contact::Components::ToxGroupPeerEphemeral>();
|
||||||
|
_t.toxGroupSendCustomPrivatePacket(
|
||||||
|
gp.group_number, gp.peer_number,
|
||||||
|
true,
|
||||||
|
pkg
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRDTNotesToxSync::SendFetchCompleteFrontier(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id
|
||||||
|
) {
|
||||||
|
if (!c.all_of<Contact::Components::ToxGroupPeerEphemeral>()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> pkg;
|
||||||
|
|
||||||
|
pkg.push_back(static_cast<uint8_t>(NGCEXT_Event::CRDTN_FETCH_COMPLETE_FRONTIER));
|
||||||
|
|
||||||
|
for (const uint8_t v : doc_id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send
|
||||||
|
const auto& gp = c.get<Contact::Components::ToxGroupPeerEphemeral>();
|
||||||
|
_t.toxGroupSendCustomPrivatePacket(
|
||||||
|
gp.group_number, gp.peer_number,
|
||||||
|
true,
|
||||||
|
pkg
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRDTNotesToxSync::SendFetchOps(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
const CRDTNotes::CRDTAgent& agent,
|
||||||
|
const uint64_t seq_from,
|
||||||
|
const uint64_t seq_to
|
||||||
|
) {
|
||||||
|
if (!c.all_of<Contact::Components::ToxGroupPeerEphemeral>()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> pkg;
|
||||||
|
|
||||||
|
pkg.push_back(static_cast<uint8_t>(NGCEXT_Event::CRDTN_FETCH_OP_RANGE));
|
||||||
|
|
||||||
|
for (const uint8_t v : doc_id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const uint8_t v : agent) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(seq_from); i++) {
|
||||||
|
pkg.push_back((seq_from >> i*8) & 0xff);
|
||||||
|
}
|
||||||
|
// +8
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(seq_to); i++) {
|
||||||
|
pkg.push_back((seq_to >> i*8) & 0xff);
|
||||||
|
}
|
||||||
|
// +8
|
||||||
|
|
||||||
|
|
||||||
|
// send
|
||||||
|
const auto& gp = c.get<Contact::Components::ToxGroupPeerEphemeral>();
|
||||||
|
_t.toxGroupSendCustomPrivatePacket(
|
||||||
|
gp.group_number, gp.peer_number,
|
||||||
|
true,
|
||||||
|
pkg
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRDTNotesToxSync::SendOps(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
const std::vector<CRDTNotes::Doc::Op>& ops
|
||||||
|
) {
|
||||||
|
// ideally this is a file transfer/stream
|
||||||
|
|
||||||
|
if (!c.all_of<Contact::Components::ToxGroupPeerEphemeral>()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> pkg;
|
||||||
|
|
||||||
|
pkg.push_back(static_cast<uint8_t>(NGCEXT_Event::CRDTN_OPS));
|
||||||
|
|
||||||
|
for (const uint8_t v : doc_id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is very inefficent
|
||||||
|
// a full add op is 124bytes like this
|
||||||
|
for (const auto& op : ops) {
|
||||||
|
if(std::holds_alternative<CRDTNotes::Doc::OpAdd>(op)) {
|
||||||
|
const auto& add_op = std::get<CRDTNotes::Doc::OpAdd>(op);
|
||||||
|
pkg.push_back(0x00); // wasteful 1 byte for 1 bit
|
||||||
|
|
||||||
|
for (const uint8_t v : add_op.id.id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(add_op.id.seq); i++) {
|
||||||
|
pkg.push_back((add_op.id.seq >> i*8) & 0xff);
|
||||||
|
}
|
||||||
|
pkg.push_back(add_op.value); // what we actually care for
|
||||||
|
|
||||||
|
if (add_op.parent_left.has_value()) {
|
||||||
|
// exists
|
||||||
|
pkg.push_back(0x01); // wasteful 1 byte for 1 bit
|
||||||
|
for (const uint8_t v : add_op.parent_left.value().id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < sizeof(add_op.parent_left.value().seq); i++) {
|
||||||
|
pkg.push_back((add_op.parent_left.value().seq >> i*8) & 0xff);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pkg.push_back(0x00); // wasteful 1 byte for 1 bit
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_op.parent_right.has_value()) {
|
||||||
|
// exists
|
||||||
|
pkg.push_back(0x01); // wasteful 1 byte for 1 bit
|
||||||
|
for (const uint8_t v : add_op.parent_right.value().id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < sizeof(add_op.parent_right.value().seq); i++) {
|
||||||
|
pkg.push_back((add_op.parent_right.value().seq >> i*8) & 0xff);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pkg.push_back(0x00); // wasteful 1 byte for 1 bit
|
||||||
|
}
|
||||||
|
} else if (std::holds_alternative<CRDTNotes::Doc::OpDel>(op)) {
|
||||||
|
const auto& del_op = std::get<CRDTNotes::Doc::OpDel>(op);
|
||||||
|
pkg.push_back(0x01); // wasteful 1 byte for 1 bit
|
||||||
|
for (const uint8_t v : del_op.id.id) {
|
||||||
|
pkg.push_back(v);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < sizeof(del_op.id.seq); i++) {
|
||||||
|
pkg.push_back((del_op.id.seq >> i*8) & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send
|
||||||
|
const auto& gp = c.get<Contact::Components::ToxGroupPeerEphemeral>();
|
||||||
|
_t.toxGroupSendCustomPrivatePacket(
|
||||||
|
gp.group_number, gp.peer_number,
|
||||||
|
true,
|
||||||
|
pkg
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,61 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <solanaceae/crdtnotes/crdtnotes.hpp>
|
#include <solanaceae/crdtnotes/crdtnotes.hpp>
|
||||||
|
#include <solanaceae/crdtnotes/crdtnotes_contact_sync_model.hpp>
|
||||||
#include <solanaceae/contact/contact_model3.hpp>
|
#include <solanaceae/contact/contact_model3.hpp>
|
||||||
|
#include <solanaceae/toxcore/tox_event_interface.hpp>
|
||||||
|
|
||||||
class CRDTNotesToxSync {
|
// fwd
|
||||||
|
struct ToxI;
|
||||||
|
struct ToxEventProviderI;
|
||||||
|
|
||||||
|
// implements CRDTNotesContactSyncModelI and attaches itself to tox contacts
|
||||||
|
class CRDTNotesToxSync : public CRDTNotesContactSyncModelI, public ToxEventI {
|
||||||
CRDTNotes& _notes;
|
CRDTNotes& _notes;
|
||||||
Contact3Registry& _cr;
|
Contact3Registry& _cr;
|
||||||
|
ToxI& _t;
|
||||||
|
ToxEventProviderI& _tep;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CRDTNotesToxSync(CRDTNotes& notes, Contact3Registry& cr);
|
CRDTNotesToxSync(
|
||||||
|
CRDTNotes& notes,
|
||||||
|
Contact3Registry& cr,
|
||||||
|
ToxI& t,
|
||||||
|
ToxEventProviderI& tep
|
||||||
|
);
|
||||||
|
~CRDTNotesToxSync(void);
|
||||||
|
|
||||||
float iterate(void);
|
float iterate(float time_delta);
|
||||||
|
|
||||||
|
public: // sync api
|
||||||
|
void SendGossip(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id
|
||||||
|
) override;
|
||||||
|
|
||||||
|
void SendGossip(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
const std::vector<CRDTNotes::Frontier>& selected_frontier
|
||||||
|
) override;
|
||||||
|
|
||||||
|
void SendFetchCompleteFrontier(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id
|
||||||
|
) override;
|
||||||
|
|
||||||
|
void SendFetchOps(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
const CRDTNotes::CRDTAgent& agent,
|
||||||
|
const uint64_t seq_from,
|
||||||
|
const uint64_t seq_to
|
||||||
|
) override;
|
||||||
|
|
||||||
|
void SendOps(
|
||||||
|
Contact3Handle c,
|
||||||
|
const CRDTNotes::DocID& doc_id,
|
||||||
|
const std::vector<CRDTNotes::Doc::Op>&
|
||||||
|
) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user