diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2022-12-18 18:56:19 +0100 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2022-12-18 21:37:11 +0100 | 
| commit | 86293ff20d9f8625615e855d98249175e8cd5cd3 (patch) | |
| tree | 7eb1fe3a34ce1d6a24a9338f3dd3008b500fffe0 /src | |
| parent | 77fc16d21158c6542addcbaaff47b801d3b5f5c7 (diff) | |
Contact service and contacts using stored set
Diffstat (limited to 'src')
| -rw-r--r-- | src/contact.cpp | 173 | ||||
| -rw-r--r-- | src/contact.h | 14 | ||||
| -rw-r--r-- | src/main.cpp | 49 | ||||
| -rw-r--r-- | src/set.cpp | 21 | 
4 files changed, 165 insertions, 92 deletions
| diff --git a/src/contact.cpp b/src/contact.cpp index edc33ea..796e896 100644 --- a/src/contact.cpp +++ b/src/contact.cpp @@ -6,42 +6,44 @@ using namespace erebos;  using std::move; -DEFINE_SHARED_TYPE(List<Contact>, +DEFINE_SHARED_TYPE(Set<Contact>,  		"34fbb61e-6022-405f-b1b3-a5a1abecd25e", -		&Contact::loadList, -		[](const List<Contact> & list) { -			if (list.empty()) -				return vector<Ref>(); -			return list.front().refs(); +		&Set<Contact>::load, +		[](const Set<Contact> & set) { +			return set.store();  		}) +static const UUID serviceUUID("d9c37368-0da1-4280-93e9-d9bd9a198084"); -List<Contact> Contact::prepend(const Storage & st, Identity id, List<Contact> list) +Contact::Contact(vector<Stored<ContactData>> data): +	p(shared_ptr<Priv>(new Priv { +		.data = data, +	}))  { -	auto cd = st.store(ContactData { -		.prev = list.empty() ? vector<Stored<ContactData>>() : list.front().p->data, -		.identity = id.data(), -		.name = nullopt, -	}); -	return list.push_front( -			Contact(shared_ptr<Priv>(new Priv { -				.data = { cd }, -				.identity = move(id), -			})) -	);  } -Identity Contact::identity() const +optional<Identity> Contact::identity() const  { +	p->init();  	return p->identity;  } -optional<string> Contact::name() const +optional<string> Contact::customName() const  {  	p->init();  	return p->name;  } +string Contact::name() const +{ +	if (auto cust = customName()) +		return *cust; +	if (auto id = p->identity) +		if (auto idname = id->name()) +			return *idname; +	return ""; +} +  bool Contact::operator==(const Contact & other) const  {  	return p->data == other.p->data; @@ -52,66 +54,18 @@ bool Contact::operator!=(const Contact & other) const  	return p->data != other.p->data;  } -List<Contact> Contact::loadList(const vector<Ref> & refs) -{ -	vector<Stored<ContactData>> cdata; -	cdata.reserve(refs.size()); - -	for (const auto & r : refs) -		cdata.push_back(Stored<ContactData>::load(r)); -	return Priv::loadList(move(cdata), {}); -} - -List<Contact> Contact::Priv::loadList(vector<Stored<ContactData>> && cdata, vector<Identity> && seen) -{ -	if (cdata.empty()) -		return {}; - -	filterAncestors(cdata); - -	for (size_t i = 0; i < cdata.size(); i++) { -		auto id = Identity::load(cdata[i]->identity); -		if (!id) -			continue; - -		bool skip = false; -		for (const auto & sid : seen) { -			if (id->sameAs(sid)) { -				skip = true; -				break; -			} -		} -		if (skip) -			continue; - -		vector<Stored<ContactData>> next; -		next.reserve(cdata.size() - i - 1 + cdata[i]->prev.size()); -		for (size_t j = i + 1; j < cdata.size(); j++) -			next.push_back(cdata[j]); -		for (const auto & x : cdata[i]->prev) -			next.push_back(x); - -		seen.push_back(*id); -		auto p = shared_ptr<Priv>(new Priv { .data = move(cdata), .identity = move(*id) }); -		return List(Contact(p), loadList(move(next), move(seen))); -	} - -	return {}; -} - -vector<Ref> Contact::refs() const +vector<Stored<ContactData>> Contact::data() const  { -	vector<Ref> res; -	res.reserve(p->data.size()); -	for (const auto & x : p->data) -		res.push_back(x.ref()); -	return res; +	return p->data;  }  void Contact::Priv::init()  {  	std::call_once(initFlag, [this]() { -		name = identity.name(); +		// TODO: property lookup +		identity = Identity::load(data[0]->identity); +		if (identity) +			name = identity->name();  	});  } @@ -151,3 +105,74 @@ Ref ContactData::store(const Storage & st) const  	return st.storeObject(Record(std::move(items)));  } + +ContactService::ContactService() = default; +ContactService::~ContactService() = default; + +UUID ContactService::uuid() const +{ +	return serviceUUID; +} + +void ContactService::serverStarted(const Server & s) +{ +	PairingService<ContactAccepted>::serverStarted(s); +	server = &s; +} + +void ContactService::request(const Peer & peer) +{ +	requestPairing(serviceUUID, peer); +} + +Stored<ContactAccepted> ContactService::handlePairingComplete(const Peer & peer) +{ +	server->localHead().update([&] (const Stored<LocalState> & local) { +		auto cdata = local.ref().storage().store(ContactData { +			.prev = {}, +			.identity = peer.identity()->finalOwner().data(), +			.name = std::nullopt, +		}); + +		Contact contact(shared_ptr<Contact::Priv>(new Contact::Priv { +			.data = { cdata }, +		})); + +		auto contacts = local->shared<Set<Contact>>(); + +		return local.ref().storage().store(local->shared<Set<Contact>>( +			contacts.add(local.ref().storage(), contact))); +	}); + +	return peer.tempStorage().store(ContactAccepted {}); +} + +void ContactService::handlePairingResult(Context & ctx, Stored<ContactAccepted>) +{ +	auto cdata = ctx.local().ref().storage().store(ContactData { +		.prev = {}, +		.identity = ctx.peer().identity()->finalOwner().data(), +		.name = std::nullopt, +	}); + +	Contact contact(shared_ptr<Contact::Priv>(new Contact::Priv { +		.data = { cdata }, +	})); + +	auto contacts = ctx.local()->shared<Set<Contact>>(); + +	ctx.local(ctx.local()->shared<Set<Contact>>( +		contacts.add(ctx.local().ref().storage(), contact))); +} + +ContactAccepted ContactAccepted::load(const Ref &) +{ +	return ContactAccepted {}; +} + +Ref ContactAccepted::store(const Storage & st) const +{ +	vector<Record::Item> items; +	items.emplace_back("accept", ""); +	return st.storeObject(Record(std::move(items))); +} diff --git a/src/contact.h b/src/contact.h index 31deceb..6fc0219 100644 --- a/src/contact.h +++ b/src/contact.h @@ -19,24 +19,12 @@ struct IdentityData;  struct Contact::Priv  {  	vector<Stored<ContactData>> data; -	Identity identity;  	void init();  	std::once_flag initFlag {}; +	optional<Identity> identity {};  	optional<string> name {}; - -	static List<Contact> loadList(vector<Stored<ContactData>> &&, vector<Identity> &&); -}; - -struct ContactData -{ -	static ContactData load(const Ref &); -	Ref store(const Storage &) const; - -	vector<Stored<ContactData>> prev; -	vector<Stored<Signed<IdentityData>>> identity; -	optional<string> name;  };  } diff --git a/src/main.cpp b/src/main.cpp index 387fe4a..de4ffbc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@  #include <erebos/attach.h> +#include <erebos/contact.h>  #include <erebos/identity.h>  #include <erebos/network.h>  #include <erebos/set.h> @@ -74,7 +75,7 @@ struct TestPeer  	Peer peer;  	size_t id;  	bool deleted = false; -	promise<bool> attachAnswer {}; +	promise<bool> pairingAnswer {};  };  vector<TestPeer> testPeers; @@ -245,7 +246,7 @@ future<bool> confirmPairing(string prefix, const Peer & peer, string confirm, fu  	promise<bool> promise;  	auto input = promise.get_future(); -	getPeer(peer).attachAnswer = move(promise); +	getPeer(peer).pairingAnswer = move(promise);  	ostringstream ss;  	ss << prefix << " " << getPeer(peer).id << " " << confirm; @@ -264,6 +265,11 @@ void startServer(const vector<string> &)  	atts->onResponse(bind(confirmPairing, "attach-response", _1, _2, _3));  	services.push_back(move(atts)); +	auto conts = make_unique<ContactService>(); +	conts->onRequest(bind(confirmPairing, "contact-request", _1, _2, _3)); +	conts->onResponse(bind(confirmPairing, "contact-response", _1, _2, _3)); +	services.push_back(move(conts)); +  	services.push_back(make_unique<SyncService>());  	server.emplace(*h, move(services)); @@ -416,12 +422,43 @@ void attachTo(const vector<string> & params)  void attachAccept(const vector<string> & params)  { -	getPeer(params.at(0)).attachAnswer.set_value(true); +	getPeer(params.at(0)).pairingAnswer.set_value(true);  }  void attachReject(const vector<string> & params)  { -	getPeer(params.at(0)).attachAnswer.set_value(false); +	getPeer(params.at(0)).pairingAnswer.set_value(false); +} + +void contactRequest(const vector<string> & params) +{ +	server->svc<ContactService>().request(getPeer(params.at(0)).peer); +} + +void contactAccept(const vector<string> & params) +{ +	getPeer(params.at(0)).pairingAnswer.set_value(true); +} + +void contactReject(const vector<string> & params) +{ +	getPeer(params.at(0)).pairingAnswer.set_value(false); +} + +void contactList(const vector<string> &) +{ +	auto cmp = [](const Contact & x, const Contact & y) { +		return x.data() < y.data(); +	}; +	for (const auto & c : h->behavior().lens<SharedState>().lens<Set<Contact>>().get().view(cmp)) { +		ostringstream ss; +		ss << "contact-list-item " << c.name(); +		if (auto id = c.identity()) +			if (auto iname = id->name()) +				ss << " " << *iname; +		printLine(ss.str()); +	} +	printLine("contact-list-done");  }  vector<Command> commands = { @@ -442,6 +479,10 @@ vector<Command> commands = {  	{ "attach-to", attachTo },  	{ "attach-accept", attachAccept },  	{ "attach-reject", attachReject }, +	{ "contact-request", contactRequest }, +	{ "contact-accept", contactAccept }, +	{ "contact-reject", contactReject }, +	{ "contact-list", contactList },  };  } diff --git a/src/set.cpp b/src/set.cpp index 001bce3..d224af3 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -32,7 +32,7 @@ SetBase::SetBase(shared_ptr<const Priv> p_):  {  } -shared_ptr<const SetBase::Priv> SetBase::add(Storage & st, const vector<Ref> & refs) const +shared_ptr<const SetBase::Priv> SetBase::add(const Storage & st, const vector<Ref> & refs) const  {  	auto item = st.store(SetItem {  		.prev = p->items, @@ -122,6 +122,16 @@ vector<vector<Ref>> SetBase::toList() const  	return res;  } +bool SetBase::operator==(const SetBase & other) const +{ +	return p->items == other.p->items; +} + +bool SetBase::operator!=(const SetBase & other) const +{ +	return !(*this == other); +} +  vector<Digest> SetBase::digests() const  {  	vector<Digest> res; @@ -131,6 +141,15 @@ vector<Digest> SetBase::digests() const  	return res;  } +vector<Ref> SetBase::store() const +{ +	vector<Ref> res; +	res.reserve(p->items.size()); +	for (const auto & i : p->items) +		res.push_back(i.ref()); +	return res; +} +  SetItem SetItem::load(const Ref & ref)  {  	if (auto rec = ref->asRecord()) { |