diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2023-05-23 22:11:42 +0200 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2023-05-23 22:32:01 +0200 | 
| commit | 15ad6ae7bd64d8d7319d75dbbb0827addd22fef2 (patch) | |
| tree | c5f7ac828f4c1d5f51c461ad332b83e570ce3b26 | |
| parent | fce349f8f1c53d3e205a8d86b79784fdfd2b7b7a (diff) | |
Message sending to identity or contact
| -rw-r--r-- | include/erebos/message.h | 3 | ||||
| -rw-r--r-- | include/erebos/network.h | 1 | ||||
| -rw-r--r-- | src/main.cpp | 50 | ||||
| -rw-r--r-- | src/message.cpp | 30 | ||||
| -rw-r--r-- | src/network.cpp | 14 | ||||
| -rw-r--r-- | test/message.test | 45 | 
6 files changed, 116 insertions, 27 deletions
| diff --git a/include/erebos/message.h b/include/erebos/message.h index 497b536..011007a 100644 --- a/include/erebos/message.h +++ b/include/erebos/message.h @@ -12,6 +12,7 @@ namespace erebos {  using std::unique_ptr; +class Contact;  class Identity;  class DirectMessage @@ -94,6 +95,8 @@ public:  	DirectMessageThread thread(const Identity &); +	DirectMessage send(const Identity &, const std::string &); +	DirectMessage send(const Contact &, const std::string &);  	DirectMessage send(const Peer &, const std::string &);  private: diff --git a/include/erebos/network.h b/include/erebos/network.h index 66edfa4..6a3112a 100644 --- a/include/erebos/network.h +++ b/include/erebos/network.h @@ -34,6 +34,7 @@ public:  	template<class S> S & svc();  	class PeerList & peerList() const; +	optional<erebos::Peer> peer(const Identity &) const;  	void addPeer(const string & node) const;  	void addPeer(const string & node, const string & service) const; diff --git a/src/main.cpp b/src/main.cpp index f33bcc4..cc02b55 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -104,6 +104,22 @@ TestPeer & getPeer(const Peer & peer)  	throw invalid_argument("peer not found");  } +Contact getContact(const string & id) +{ +	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)) { +		if (string(c.leastRoot()) == id) { +			return c; +		} +	} + +	ostringstream ss; +	ss << "contact '" << id << "' not found"; +	throw invalid_argument(ss.str().c_str()); +} +  struct Command  {  	string name; @@ -505,22 +521,16 @@ void contactSetName(const vector<string> & args)  	auto id = args.at(0);  	auto name = args.at(1); -	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)) { -		if (string(c.leastRoot()) == id) { -			auto nh = h->update([&] (const Stored<LocalState> & loc) { -				auto st = loc.ref().storage(); -				auto cc = c.customName(st, name); -				auto contacts = loc->shared<Set<Contact>>(); -				return st.store(loc->shared<Set<Contact>>(contacts.add(st, cc))); -			}); -			if (nh) -				*h = *nh; -			break; -		} -	} +	auto c = getContact(id); +	auto nh = h->update([&] (const Stored<LocalState> & loc) { +		auto st = loc.ref().storage(); +		auto cc = c.customName(st, name); +		auto contacts = loc->shared<Set<Contact>>(); +		return st.store(loc->shared<Set<Contact>>(contacts.add(st, cc))); +	}); +	if (nh) +		*h = *nh; +  	printLine("contact-set-name-done");  } @@ -531,6 +541,13 @@ void dmSendPeer(const vector<string> & args)  			args.at(1));  } +void dmSendContact(const vector<string> & args) +{ +	server->svc<DirectMessageService>().send( +			getContact(args.at(0)), +			args.at(1)); +} +  vector<Command> commands = {  	{ "store", store },  	{ "stored-generation", storedGeneration }, @@ -556,6 +573,7 @@ vector<Command> commands = {  	{ "contact-list", contactList },  	{ "contact-set-name", contactSetName },  	{ "dm-send-peer", dmSendPeer }, +	{ "dm-send-contact", dmSendContact },  };  } diff --git a/src/message.cpp b/src/message.cpp index dd4f9d5..ff8e05b 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -1,5 +1,6 @@  #include "message.h" +#include <erebos/contact.h>  #include <erebos/network.h>  using namespace erebos; @@ -246,26 +247,37 @@ DirectMessageThread DirectMessageService::thread(const Identity & peer)  	return DirectMessageThread::Priv::getThreadLocked(peer.finalOwner());  } -DirectMessage DirectMessageService::send(const Peer & peer, const string & text) +DirectMessage DirectMessageService::send(const Identity & to, const string & text)  { -	auto pid = peer.identity(); -	if (!pid) -		throw std::runtime_error("Peer without known identity"); -	auto powner = pid->finalOwner(); -  	scoped_lock lock(threadLock);  	auto msg = server.localHead().ref().storage().store(DirectMessageData { -		.prev = DirectMessageThread::Priv::getThreadLocked(powner).p->head, +		.prev = DirectMessageThread::Priv::getThreadLocked(to).p->head,  		.from = server.identity().finalOwner(),  		.time = ZonedTime::now(),  		.text = text,  	}); -	DirectMessageThread::Priv::updateThreadLocked(powner, { msg }); -	peer.send(myUUID, msg.ref()); +	DirectMessageThread::Priv::updateThreadLocked(to, { msg }); + +	if (auto peer = server.peer(to)) +		peer->send(myUUID, msg.ref());  	return DirectMessage(new DirectMessage::Priv {  		.data = msg,  	});  } + +DirectMessage DirectMessageService::send(const Contact & to, const string & text) +{ +	if (auto id = to.identity()) +		return send(*id, text); +	throw std::runtime_error("contact without erebos identity"); +} + +DirectMessage DirectMessageService::send(const Peer & to, const string & text) +{ +	if (auto id = to.identity()) +		return send(id->finalOwner(), text); +	throw std::runtime_error("peer without known identity"); +} diff --git a/src/network.cpp b/src/network.cpp index 1eb33d0..929908a 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -73,6 +73,20 @@ PeerList & Server::peerList() const  	return p->plist;  } +optional<Peer> Server::peer(const Identity & identity) const +{ +	scoped_lock lock(p->dataMutex); + +	for (auto & peer : p->peers) { +		const auto & pid = peer->identity; +		if (holds_alternative<Identity>(pid)) +			if (std::get<Identity>(pid).finalOwner().sameAs(identity)) +				return peer->lpeer; +	} + +	return nullopt; +} +  void Server::addPeer(const string & node) const  {  	return addPeer(node, to_string(Priv::discoveryPort)); diff --git a/test/message.test b/test/message.test index 9567611..3f108d3 100644 --- a/test/message.test +++ b/test/message.test @@ -14,16 +14,57 @@ test DirectMessage:  		/peer ([0-9]+) addr ${p1.node.ip} 29665/ capture peer2_1  		/peer $peer2_1 id Device1 Owner1/ +	# Send messages to peers +  	for i in [1..2]:  		send "dm-send-peer $peer1_2 hello$i" to p1  		expect /dm-received from Owner1 text hello$i/ from p2  	for i in [1..2]: -		send "dm-send-peer $peer1_2 hello$i" to p2 +		send "dm-send-peer $peer2_1 hello$i" to p2  		expect /dm-received from Owner2 text hello$i/ from p1  	for i in [3..4]:  		send "dm-send-peer $peer1_2 hello$i" to p1  		expect /dm-received from Owner1 text hello$i/ from p2 -		send "dm-send-peer $peer1_2 hello$i" to p2 +		send "dm-send-peer $peer2_1 hello$i" to p2 +		expect /dm-received from Owner2 text hello$i/ from p1 + +	# Create contacts + +	local: +		send "contact-request $peer1_2" to p1 +		expect /contact-request $peer2_1 ([0-9]*)/ from p2 capture code2 +		expect /contact-response $peer1_2 ([0-9]*)/ from p1 capture code1 +		guard (code1 == code2) + +	send "contact-accept $peer1_2" to p1 +	send "contact-accept $peer2_1" to p2 +	expect /contact-request-done $peer2_1/ from p2 +	expect /contact-response-done $peer1_2/ from p1 + +	send "contact-list" to p1 +	expect from p1: +		/contact-list-item ([a-z0-9#]+) Owner2 Owner2/ capture c1_2 +		/contact-list-(.*)/ capture done1_1 + +	send "contact-list" to p2 +	expect from p2: +		/contact-list-item ([a-z0-9#]+) Owner1 Owner1/ capture c2_1 +		/contact-list-(.*)/ capture done1_2 + +	# Send messages to contacts + +	for i in [1..2]: +		send "dm-send-contact $c1_2 hello$i" to p1 +		expect /dm-received from Owner1 text hello$i/ from p2 + +	for i in [1..2]: +		send "dm-send-contact $c2_1 hello$i" to p2 +		expect /dm-received from Owner2 text hello$i/ from p1 + +	for i in [3..4]: +		send "dm-send-contact $c1_2 hello$i" to p1 +		expect /dm-received from Owner1 text hello$i/ from p2 +		send "dm-send-contact $c2_1 hello$i" to p2  		expect /dm-received from Owner2 text hello$i/ from p1 |