summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/erebos/message.h3
-rw-r--r--include/erebos/network.h1
-rw-r--r--src/main.cpp50
-rw-r--r--src/message.cpp30
-rw-r--r--src/network.cpp14
-rw-r--r--test/message.test45
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