Add chatroom discovery logic
Change-Id: I1b65b7bbcf321c51cb00e8d1c05a42291601a284
diff --git a/src/chatroom-discovery-logic.cpp b/src/chatroom-discovery-logic.cpp
new file mode 100644
index 0000000..048d121
--- /dev/null
+++ b/src/chatroom-discovery-logic.cpp
@@ -0,0 +1,221 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Mengjin Yan <jane.yan0129@gmail.com>
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include "chatroom-discovery-logic.hpp"
+
+
+namespace chronos {
+
+const size_t ChatroomDiscoveryLogic::OFFSET_CHATROOM_NAME = 4;
+const size_t ChatroomDiscoveryLogic::DISCOVERY_INTEREST_NAME_SIZE = 4;
+const size_t ChatroomDiscoveryLogic::REFRESHING_INTEREST_NAME_SIZE = 5;
+const time::milliseconds ChatroomDiscoveryLogic::DEFAULT_REFRESHING_TIMER(10000);
+const Name ChatroomDiscoveryLogic::DISCOVERY_PREFIX("/ndn/broadcast/chronochat/chatroom-list");
+const time::seconds ChatroomDiscoveryLogic::m_discoveryInterval(600);
+
+ChatroomDiscoveryLogic::ChatroomDiscoveryLogic(shared_ptr<ndn::Face> face,
+ const UpdateCallback& updateCallback)
+ : m_face(face)
+ , m_scheduler(face->getIoService())
+ , m_onUpdate(updateCallback)
+{
+
+ m_face->setInterestFilter(DISCOVERY_PREFIX,
+ bind(&ChatroomDiscoveryLogic::onDiscoveryInterest,
+ this, _1, _2),
+ bind(&ChatroomDiscoveryLogic::onPrefixRegistrationFailed,
+ this, _1));
+}
+
+void
+ChatroomDiscoveryLogic::addLocalChatroom(const ChatroomInfo& chatroom)
+{
+ m_localChatrooms[chatroom.getName()] = chatroom;
+ m_chatrooms[chatroom.getName()] = chatroom; // no need to discover local chatroom
+}
+
+void
+ChatroomDiscoveryLogic::removeLocalChatroom(const Name::Component& chatroomName)
+{
+ m_localChatrooms.erase(chatroomName);
+ m_chatrooms.erase(chatroomName);
+}
+
+void
+ChatroomDiscoveryLogic::sendDiscoveryInterest()
+{
+ Interest discovery(DISCOVERY_PREFIX);
+ discovery.setMustBeFresh(true);
+ discovery.setInterestLifetime(time::milliseconds(10000));
+
+ Exclude exclude;
+ Chatrooms::iterator it;
+ for (it = m_chatrooms.begin(); it != m_chatrooms.end(); ++it) {
+ exclude.excludeOne(it->first);
+ }
+ discovery.setExclude(exclude);
+
+ m_face->expressInterest(discovery,
+ bind(&ChatroomDiscoveryLogic::onReceiveData, this,
+ _1, _2, false),
+ bind(&ChatroomDiscoveryLogic::onDiscoveryInterestTimeout, this,
+ _1));
+
+}
+
+void
+ChatroomDiscoveryLogic::onDiscoveryInterest(const Name& name, const Interest& interest)
+{
+ if (m_localChatrooms.empty())
+ return;
+
+ if (interest.getName() == DISCOVERY_PREFIX) {
+ // discovery
+ for (Chatrooms::const_iterator it = m_localChatrooms.begin();
+ it != m_localChatrooms.end(); ++it) {
+
+ if (!interest.getExclude().empty() &&
+ interest.getExclude().isExcluded(it->first))
+ continue;
+
+
+ Name dataName(interest.getName());
+ dataName.append(it->first);
+
+ shared_ptr<Data> chatroomInfo = make_shared<Data>(dataName);
+ chatroomInfo->setFreshnessPeriod(time::seconds(10));
+ chatroomInfo->setContent(it->second.wireEncode());
+
+ m_keyChain.sign(*chatroomInfo);
+ m_face->put(*chatroomInfo);
+ break;
+ }
+ return;
+ }
+
+ if (DISCOVERY_PREFIX.isPrefixOf(interest.getName()) &&
+ interest.getName().size() == REFRESHING_INTEREST_NAME_SIZE) {
+ // refreshing
+ Chatrooms::const_iterator it =
+ m_localChatrooms.find(interest.getName().get(OFFSET_CHATROOM_NAME));
+
+ if (it == m_localChatrooms.end())
+ return;
+
+ shared_ptr<Data> chatroomInfo = make_shared<Data>(interest.getName());
+ chatroomInfo->setFreshnessPeriod(time::seconds(10));
+ chatroomInfo->setContent(it->second.wireEncode());
+
+ m_keyChain.sign(*chatroomInfo);
+ m_face->put(*chatroomInfo);
+
+ return;
+ }
+}
+
+void
+ChatroomDiscoveryLogic::onPrefixRegistrationFailed(const Name& name)
+{
+}
+
+void
+ChatroomDiscoveryLogic::refreshChatroom(const Name::Component& chatroomName)
+{
+ Name name = DISCOVERY_PREFIX;
+ name.append(chatroomName);
+
+ BOOST_ASSERT(name.size() == REFRESHING_INTEREST_NAME_SIZE);
+
+ Interest discovery(name);
+ discovery.setMustBeFresh(true);
+ discovery.setInterestLifetime(time::milliseconds(10000));
+
+ m_face->expressInterest(discovery,
+ bind(&ChatroomDiscoveryLogic::onReceiveData, this,
+ _1, _2, true),
+ bind(&ChatroomDiscoveryLogic::onRefreshingInterestTimeout, this,
+ _1));
+
+}
+
+void
+ChatroomDiscoveryLogic::onReceiveData(const ndn::Interest& interest,
+ const ndn::Data& data,
+ const bool isRefreshing)
+{
+ Name::Component chatroomName = data.getName().get(OFFSET_CHATROOM_NAME);
+
+ ChatroomInfo chatroom;
+ chatroom.wireDecode(data.getContent().blockFromValue());
+ chatroom.setName(chatroomName);
+
+ // Tmp Disabled
+ // if (chatroom.getTrustModel() == ChatroomInfo::TRUST_MODEL_WEBOFTRUST)
+ // addContacts(chatroom);
+
+
+ m_chatrooms[chatroomName] = chatroom;
+ m_onUpdate(chatroom, true); //add
+
+ time::milliseconds refreshingTime;
+ if (data.getFreshnessPeriod() > DEFAULT_REFRESHING_TIMER)
+ refreshingTime = data.getFreshnessPeriod();
+ else
+ refreshingTime = DEFAULT_REFRESHING_TIMER;
+
+ m_scheduler.scheduleEvent(refreshingTime,
+ bind(&ChatroomDiscoveryLogic::refreshChatroom, this, chatroomName));
+
+ if (!isRefreshing)
+ sendDiscoveryInterest();
+}
+
+void
+ChatroomDiscoveryLogic::onRefreshingInterestTimeout(const ndn::Interest& interest)
+{
+ Name::Component chatroomName = interest.getName().get(OFFSET_CHATROOM_NAME);
+
+ Chatrooms::iterator it = m_chatrooms.find(chatroomName);
+ if (it != m_chatrooms.end()) {
+ m_onUpdate(it->second, false); //delete
+ m_chatrooms.erase(it);
+ }
+}
+
+
+void
+ChatroomDiscoveryLogic::onDiscoveryInterestTimeout(const Interest& interest)
+{
+ m_scheduler.scheduleEvent(m_discoveryInterval,
+ bind(&ChatroomDiscoveryLogic::sendDiscoveryInterest, this));
+}
+
+void
+ChatroomDiscoveryLogic::addContacts(ChatroomInfo& chatroom)
+{
+ // Tmp Disabled
+
+ // std::vector<Name>::const_iterator nameIt;
+ // std::vector<shared_ptr<Contact> >::iterator contactIt;
+ // ContactList contactList;
+ // m_contactManager->getContactList(contactList);
+
+ // for (contactIt = contactList.begin();
+ // contactIt != contactList.end(); ++contactIt) {
+ // nameIt = std::find(chatroom.getParticipants().begin(),
+ // chatroom.getParticipants().end(), (*contactIt)->getNameSpace());
+ // if (nameIt != chatroom.getParticipants().end())
+ // chatroom.addContact(*nameIt);
+ // }
+}
+
+
+} //namespace chronos