util: Add BroadcastLink to DummyClientFace
Change-Id: I2bfe3156016a098b91ff375f2bb83b5e4351317c
Refs: #3913
diff --git a/src/util/dummy-client-face.cpp b/src/util/dummy-client-face.cpp
index 989b455..9f9383a 100644
--- a/src/util/dummy-client-face.cpp
+++ b/src/util/dummy-client-face.cpp
@@ -85,6 +85,16 @@
Signal<Transport, Block> onSendBlock;
};
+struct DummyClientFace::BroadcastLink
+{
+ std::vector<DummyClientFace*> faces;
+};
+
+DummyClientFace::AlreadyLinkedError::AlreadyLinkedError()
+ : Error("Face has already been linked to another face")
+{
+}
+
DummyClientFace::DummyClientFace(const Options& options/* = DummyClientFace::DEFAULT_OPTIONS*/)
: Face(make_shared<DummyClientFace::Transport>())
, m_internalKeyChain(new KeyChain)
@@ -118,6 +128,11 @@
this->construct(options);
}
+DummyClientFace::~DummyClientFace()
+{
+ unlink();
+}
+
void
DummyClientFace::construct(const Options& options)
{
@@ -159,6 +174,40 @@
this->enableRegistrationReply();
m_processEventsOverride = options.processEventsOverride;
+
+ enableBroadcastLink();
+}
+
+void
+DummyClientFace::enableBroadcastLink()
+{
+ this->onSendInterest.connect([this] (const Interest& interest) {
+ if (m_bcastLink != nullptr) {
+ for (auto otherFace : m_bcastLink->faces) {
+ if (otherFace != this) {
+ otherFace->receive(interest);
+ }
+ }
+ }
+ });
+ this->onSendData.connect([this] (const Data& data) {
+ if (m_bcastLink != nullptr) {
+ for (auto otherFace : m_bcastLink->faces) {
+ if (otherFace != this) {
+ otherFace->receive(data);
+ }
+ }
+ }
+ });
+ this->onSendNack.connect([this] (const lp::Nack& nack) {
+ if (m_bcastLink != nullptr) {
+ for (auto otherFace : m_bcastLink->faces) {
+ if (otherFace != this) {
+ otherFace->receive(nack);
+ }
+ }
+ }
+ });
}
void
@@ -241,6 +290,48 @@
}
void
+DummyClientFace::linkTo(DummyClientFace& other)
+{
+ if (m_bcastLink != nullptr && other.m_bcastLink != nullptr) {
+ if (m_bcastLink != other.m_bcastLink) {
+ // already on different links
+ BOOST_THROW_EXCEPTION(AlreadyLinkedError());
+ }
+ }
+ else if (m_bcastLink == nullptr && other.m_bcastLink != nullptr) {
+ m_bcastLink = other.m_bcastLink;
+ m_bcastLink->faces.push_back(this);
+ }
+ else if (m_bcastLink != nullptr && other.m_bcastLink == nullptr) {
+ other.m_bcastLink = m_bcastLink;
+ m_bcastLink->faces.push_back(&other);
+ }
+ else {
+ m_bcastLink = other.m_bcastLink = make_shared<BroadcastLink>();
+ m_bcastLink->faces.push_back(this);
+ m_bcastLink->faces.push_back(&other);
+ }
+}
+
+void
+DummyClientFace::unlink()
+{
+ if (m_bcastLink == nullptr) {
+ return;
+ }
+
+ auto it = std::find(m_bcastLink->faces.begin(), m_bcastLink->faces.end(), this);
+ BOOST_ASSERT(it != m_bcastLink->faces.end());
+ m_bcastLink->faces.erase(it);
+
+ if (m_bcastLink->faces.size() == 1) {
+ m_bcastLink->faces[0]->m_bcastLink = nullptr;
+ m_bcastLink->faces.clear();
+ }
+ m_bcastLink = nullptr;
+}
+
+void
DummyClientFace::doProcessEvents(time::milliseconds timeout, bool keepThread)
{
if (m_processEventsOverride != nullptr) {