Add chatroom discovery logic
Change-Id: I1b65b7bbcf321c51cb00e8d1c05a42291601a284
diff --git a/src/chat-dialog.cpp b/src/chat-dialog.cpp
index 442e866..93d7dd0 100644
--- a/src/chat-dialog.cpp
+++ b/src/chat-dialog.cpp
@@ -78,6 +78,8 @@
, m_sock(NULL)
, m_session(static_cast<uint64_t>(time::toUnixTimestamp(time::system_clock::now()).count()))
, m_inviteListDialog(new InviteListDialog)
+ //ymj
+ //, m_trustModel(withSecurity)
{
qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
qRegisterMetaType<ndn::shared_ptr<const ndn::Data> >("ndn.DataPtr");
@@ -155,7 +157,11 @@
m_inviteListDialog, SLOT(onContactAliasListReady(const QStringList&)));
connect(m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
m_inviteListDialog, SLOT(onContactIdListReady(const QStringList&)));
+
+ m_trustModel = ChatroomInfo::TRUST_MODEL_WEBOFTRUST;
}
+ else
+ m_trustModel = ChatroomInfo::TRUST_MODEL_NONE;
initializeSync();
}
@@ -180,7 +186,7 @@
void
ChatDialog::addSyncAnchor(const Invitation& invitation)
{
- // _LOG_DEBUG("Add sync anchor from invation");
+ // _LOG_DEBUG("Add sync anchor from invitation");
// Add inviter certificate as trust anchor.
m_sock->addParticipant(invitation.getInviterCertificate());
plotTrustTree();
@@ -228,7 +234,7 @@
"system tray. To close the chatroom, "
"choose <b>Close chatroom</b> in the "
"context memu of the system tray entry."));
- hide();
+ hide();//ymj
e->ignore();
}
@@ -282,6 +288,7 @@
if (m_certListPrefixId)
m_face->unsetInterestFilter(m_certListPrefixId);
+
m_certListPrefixId = m_face->setInterestFilter(m_certListPrefix,
bind(&ChatDialog::onCertListInterest,
this, _1, _2),
@@ -522,7 +529,7 @@
}
void
-ChatDialog::onCertListInterest(const Name& prefix, const Interest& interest)
+ChatDialog::onCertListInterest(const ndn::Name& prefix, const ndn::Interest& interest)
{
vector<Name> certNameList;
m_sock->getIntroCertNames(certNameList);
@@ -545,7 +552,7 @@
}
void
-ChatDialog::onCertListRegisterFailed(const Name& prefix, const string& msg)
+ChatDialog::onCertListRegisterFailed(const ndn::Name& prefix, const std::string& msg)
{
// _LOG_DEBUG("ChatDialog::onCertListRegisterFailed failed: " + msg);
}
@@ -567,7 +574,7 @@
}
void
-ChatDialog::onCertSingleRegisterFailed(const Name& prefix, const string& msg)
+ChatDialog::onCertSingleRegisterFailed(const Name& prefix, const std::string& msg)
{
// _LOG_DEBUG("ChatDialog::onCertListRegisterFailed failed: " + msg);
}
@@ -719,7 +726,7 @@
msg.set_to(m_chatroomName);
msg.set_data(text.toStdString());
int32_t seconds =
- static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count()/1000000000);
+ static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count()/1000);
msg.set_timestamp(seconds);
msg.set_type(SyncDemo::ChatMessage::CHAT);
}
@@ -731,7 +738,7 @@
msg.set_from(m_nick);
msg.set_to(m_chatroomName);
int32_t seconds =
- static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count()/1000000000);
+ static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count()/1000);
msg.set_timestamp(seconds);
msg.set_type(type);
}
@@ -924,6 +931,26 @@
}
}
+shared_ptr<ChatroomInfo>
+ChatDialog::getChatroomInfo() const
+{
+ shared_ptr<ChatroomInfo> chatroom = make_shared<ChatroomInfo>();
+ chatroom->setName(Name::Component(m_chatroomName));
+
+ Roster roster = m_scene->getRosterFull();
+ Roster_iterator it = roster.begin();
+
+ for(it = roster.begin(); it != roster.end(); ++it )
+ {
+ Name participant = Name(it.key().toStdString()).getPrefix(-3);
+ chatroom->addParticipant(participant);
+ }
+
+ chatroom->setTrustModel(m_trustModel);
+ return chatroom;
+}
+
+
// public slots:
void
ChatDialog::onLocalPrefixUpdated(const QString& localPrefix)
@@ -1052,7 +1079,7 @@
}
void
-ChatDialog::onProcessData(const shared_ptr<const Data>& data, bool show, bool isHistory)
+ChatDialog::onProcessData(const ndn::shared_ptr<const ndn::Data>& data, bool show, bool isHistory)
{
SyncDemo::ChatMessage msg;
bool corrupted = false;
@@ -1065,6 +1092,9 @@
corrupted = true;
}
+ //std::cout << "onProcessData: " << show << std::endl;
+ //std::cout << "onProcessData: " << corrupted << std::endl;
+
// display msg received from network
// we have to do so; this function is called by ccnd thread
// so if we call appendMsg directly
@@ -1153,6 +1183,8 @@
appendMessage(msg);
}
plotTrustTree();
+
+ emit rosterChanged(*getChatroomInfo());
}
void
@@ -1180,7 +1212,7 @@
ChatDialog::sendHello()
{
int64_t now = time::toUnixTimestamp(time::system_clock::now()).count();
- int elapsed = (now - m_lastMsgTime) / 1000000000;
+ int elapsed = (now - m_lastMsgTime) / 1000;
if (elapsed >= m_randomizedInterval / 1000) {
SyncDemo::ChatMessage msg;
formControlMessage(msg, SyncDemo::ChatMessage::HELLO);
@@ -1262,7 +1294,7 @@
}
void
-ChatDialog::onReplyTimeout(const Interest& interest,
+ChatDialog::onReplyTimeout(const ndn::Interest& interest,
size_t routablePrefixOffset)
{
Name interestName;
@@ -1279,7 +1311,7 @@
}
void
-ChatDialog::onIntroCert(const Interest& interest, const shared_ptr<const Data>& data)
+ChatDialog::onIntroCert(const ndn::Interest& interest, const ndn::shared_ptr<const ndn::Data>& data)
{
Data innerData;
innerData.wireDecode(data->getContent().blockFromValue());
@@ -1289,13 +1321,14 @@
}
void
-ChatDialog::onIntroCertTimeout(const Interest& interest, int retry, const QString& msg)
+ChatDialog::onIntroCertTimeout(const ndn::Interest& interest, int retry, const QString& msg)
{
// _LOG_DEBUG("onIntroCertTimeout: " << msg.toStdString());
}
} // namespace chronos
+
#if WAF
#include "chat-dialog.moc"
// #include "chat-dialog.cpp.moc"
diff --git a/src/chat-dialog.hpp b/src/chat-dialog.hpp
index 12051f1..9c4008e 100644
--- a/src/chat-dialog.hpp
+++ b/src/chat-dialog.hpp
@@ -9,8 +9,8 @@
* Yingdi Yu <yingdi@cs.ucla.edu>
*/
-#ifndef CHRONOS_CHAT_DIALOG_HPP
-#define CHRONOS_CHAT_DIALOG_HPP
+#ifndef CHRONOCHAT_CHAT_DIALOG_HPP
+#define CHRONOCHAT_CHAT_DIALOG_HPP
#include <QDialog>
#include <QTextTable>
@@ -36,6 +36,7 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/thread.hpp>
+#include "chatroom-info.hpp"
#endif
#include "invite-list-dialog.hpp"
@@ -81,7 +82,10 @@
void
processRemoveWrapper(const std::string& prefix);
-protected:
+ //ymj
+ shared_ptr<ChatroomInfo>
+ getChatroomInfo() const;
+
void
closeEvent(QCloseEvent* e);
@@ -116,12 +120,12 @@
size_t routablePrefixOffset);
void
- onReplyValidated(const shared_ptr<const Data>& data,
+ onReplyValidated(const ndn::shared_ptr<const ndn::Data>& data,
size_t inviteeRoutablePrefixOffset,
bool isIntroduce);
void
- onReplyValidationFailed(const shared_ptr<const Data>& data,
+ onReplyValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
const std::string& failureInfo);
void
@@ -147,10 +151,10 @@
introCertTimeoutWrapper(const Interest& interest, int retry, const QString& msg);
void
- onCertListInterest(const Name& prefix, const Interest& interest);
+ onCertListInterest(const ndn::Name& prefix, const ndn::Interest& interest);
void
- onCertListRegisterFailed(const Name& prefix, const std::string& msg);
+ onCertListRegisterFailed(const ndn::Name& prefix, const std::string& msg);
void
onCertSingleInterest(const Name& prefix, const Interest& interest);
@@ -206,7 +210,8 @@
signals:
void
- processData(const shared_ptr<const Data>& data, bool show, bool isHistory);
+ processData(const ndn::shared_ptr<const ndn::Data>& data,
+ bool show, bool isHistory);
void
processTreeUpdate(const std::vector<Sync::MissingDataInfo>);
@@ -224,21 +229,24 @@
resetIcon();
void
- reply(const Interest& interest, const shared_ptr<const Data>& data,
+ reply(const ndn::Interest& interest, const ndn::shared_ptr<const ndn::Data>& data,
size_t routablePrefixOffset, bool isIntroducer);
void
- replyTimeout(const Interest& interest, size_t routablePrefixOffset);
+ replyTimeout(const ndn::Interest& interest, size_t routablePrefixOffset);
void
- introCert(const Interest& interest, const shared_ptr<const Data>& data);
+ introCert(const ndn::Interest& interest, const ndn::shared_ptr<const ndn::Data>& data);
void
- introCertTimeout(const Interest& interest, int retry, const QString& msg);
+ introCertTimeout(const ndn::Interest& interest, int retry, const QString& msg);
void
waitForContactList();
+ void
+ rosterChanged(const chronos::ChatroomInfo& info);
+
public slots:
void
onLocalPrefixUpdated(const QString& localPrefix);
@@ -257,7 +265,7 @@
onTrustTreeButtonPressed();
void
- onProcessData(const shared_ptr<const Data>& data, bool show, bool isHistory);
+ onProcessData(const ndn::shared_ptr<const ndn::Data>& data, bool show, bool isHistory);
void
onProcessTreeUpdate(const std::vector<Sync::MissingDataInfo>&);
@@ -290,17 +298,17 @@
onSendInvitation(QString invitee);
void
- onReply(const Interest& interest, const shared_ptr<const Data>& data,
+ onReply(const ndn::Interest& interest, const ndn::shared_ptr<const ndn::Data>& data,
size_t routablePrefixOffset, bool isIntroducer);
void
- onReplyTimeout(const Interest& interest, size_t routablePrefixOffset);
+ onReplyTimeout(const ndn::Interest& interest, size_t routablePrefixOffset);
void
- onIntroCert(const Interest& interest, const shared_ptr<const Data>& data);
+ onIntroCert(const ndn::Interest& interest, const ndn::shared_ptr<const ndn::Data>& data);
void
- onIntroCertTimeout(const Interest& interest, int retry, const QString& msg);
+ onIntroCertTimeout(const ndn::Interest& interest, int retry, const QString& msg);
private:
Ui::ChatDialog *ui;
@@ -345,8 +353,11 @@
boost::recursive_mutex m_sceneMutex;
QList<QString> m_zombieList;
int m_zombieIndex;
+
+ //ymj
+ ChatroomInfo::TrustModel m_trustModel;
};
} // namespace chronos
-#endif // CHRONOS_CHAT_DIALOG_HPP
+#endif // CHRONOCHAT_CHAT_DIALOG_HPP
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
diff --git a/src/chatroom-discovery-logic.hpp b/src/chatroom-discovery-logic.hpp
new file mode 100644
index 0000000..32b9c89
--- /dev/null
+++ b/src/chatroom-discovery-logic.hpp
@@ -0,0 +1,118 @@
+/* -*- 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>
+ */
+
+#ifndef CHRONOCHAT_CHATROOM_DISCOVERY_LOGIC_HPP
+#define CHRONOCHAT_CHATROOM_DISCOVERY_LOGIC_HPP
+
+#include "chatroom-info.hpp"
+#include <ndn-cxx/util/scheduler.hpp>
+
+namespace chronos {
+
+class ChatroomDiscoveryLogic : noncopyable
+{
+public:
+ typedef function<void(const ChatroomInfo& chatroomName, bool isAdd)> UpdateCallback;
+
+ typedef std::map<Name::Component, chronos::ChatroomInfo> Chatrooms;
+ static const size_t OFFSET_CHATROOM_NAME;
+ static const size_t DISCOVERY_INTEREST_NAME_SIZE;
+ static const size_t REFRESHING_INTEREST_NAME_SIZE;
+ static const time::milliseconds DEFAULT_REFRESHING_TIMER;
+ static const Name DISCOVERY_PREFIX;
+
+public:
+ explicit
+ ChatroomDiscoveryLogic(shared_ptr<ndn::Face> face,
+ const UpdateCallback& updateCallback);
+
+
+ /** \brief obtain the ongoing chatroom list
+ */
+ const Chatrooms&
+ getChatrooms() const;
+
+ /** \brief add a local chatroom in the ongoing chatroom list
+ */
+ void
+ addLocalChatroom(const ChatroomInfo& chatroom);
+
+ void
+ removeLocalChatroom(const Name::Component& chatroomName);
+
+ /** \brief send discovery interest
+ */
+ void
+ sendDiscoveryInterest();
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ */
+ void
+ onDiscoveryInterest(const Name& name, const Interest& interest);
+
+ /**
+ */
+ void
+ onPrefixRegistrationFailed(const Name& name);
+
+ /** \brief schedule another discovery
+ */
+ void
+ onDiscoveryInterestTimeout(const Interest& interest);
+
+ /** \brief send interest to find if the certain chatroom exists
+ */
+ void
+ refreshChatroom(const Name::Component& chatroomName);
+
+ /** \brief copy the contact from the participants of the chatroom to contacts of the chatroom
+ */
+ void
+ addContacts(ChatroomInfo& chatroom);
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+
+ /** \brief erase the chatroom from the ongoing chatroom list
+ */
+ void
+ onRefreshingInterestTimeout(const Interest& interest);
+
+ /** \brief operate the chatroom data and schedule discovery and refreshing process
+ */
+ void
+ onReceiveData(const ndn::Interest& interest, const ndn::Data& data, const bool isRefreshing);
+
+private:
+ static const time::seconds m_discoveryInterval;
+
+ shared_ptr<ndn::Face> m_face;
+
+ ndn::KeyChain m_keyChain;
+
+ Chatrooms m_chatrooms;
+ Chatrooms m_localChatrooms;
+
+ ndn::Scheduler m_scheduler;
+
+ UpdateCallback m_onUpdate;
+
+};
+
+inline const ChatroomDiscoveryLogic::Chatrooms&
+ChatroomDiscoveryLogic::getChatrooms() const
+{
+ return m_chatrooms;
+}
+
+} // namespace chronos
+
+#endif // CHRONOCHAT_CHATROOM_DISCOVERY_LOGIC_HPP
diff --git a/src/chatroom-info.cpp b/src/chatroom-info.cpp
new file mode 100644
index 0000000..2b23719
--- /dev/null
+++ b/src/chatroom-info.cpp
@@ -0,0 +1,136 @@
+/* -*- 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-info.hpp"
+
+namespace chronos {
+
+ChatroomInfo::ChatroomInfo()
+{
+}
+
+ChatroomInfo::ChatroomInfo(const Block& chatroomWire)
+{
+ this->wireDecode(chatroomWire);
+}
+
+template<bool T>
+size_t
+ChatroomInfo::wireEncode(ndn::EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+
+ //Chatroom := CHATROOM-TYPE TLV-LENGTH
+ // TrustModel
+ // Participant+
+
+ //Participants
+ for (std::vector<Name>::const_reverse_iterator it = m_participants.rbegin();
+ it != m_participants.rend(); ++it) {
+ size_t entryLength = 0;
+
+ entryLength += it->wireEncode(block);
+ entryLength += block.prependVarNumber(entryLength);
+ entryLength += block.prependVarNumber(tlv::PARTICIPANT);
+ totalLength += entryLength;
+ }
+
+ //TrustModel
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::TRUSTMODEL, m_trustModel);
+
+ //type = TYPE_CHATROOM;
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::CHATROOM);
+
+ return totalLength;
+}
+
+const Block&
+ChatroomInfo::wireEncode() const
+{
+ ndn::EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ ndn::EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ m_wire.parse();
+
+ return m_wire;
+}
+
+void
+ChatroomInfo::wireDecode(const Block& chatroomWire)
+{
+ m_wire = chatroomWire;
+ m_wire.parse();
+
+ m_participants.clear();
+
+ //Chatroom := CHATROOM-TYPE TLV-LENGTH
+ // TrustModel
+ // Participant+
+
+ if (m_wire.type() != tlv::CHATROOM)
+ throw Error("Unexpected TLV number when decoding chatroom packet");
+
+ Block::element_const_iterator i = m_wire.elements_begin();
+
+ //TrustModel
+ if (i == m_wire.elements_end() || i->type() != tlv::TRUSTMODEL)
+ throw Error("Missing TrustModel");
+ m_trustModel =
+ static_cast<TrustModel>(readNonNegativeInteger(*i));
+
+ ++i;
+
+ //Participants
+ for (; i != m_wire.elements_end() && i->type() == tlv::PARTICIPANT; ++i) {
+ Name name;
+ name.wireDecode(i->blockFromValue());
+ m_participants.push_back(name);
+ }
+ if (m_participants.empty())
+ throw Error("Missing Participant");
+ if (i != m_wire.elements_end()) {
+ throw Error("Unexpected element");
+ }
+}
+
+void
+ChatroomInfo::addParticipant(const Name& participant)
+{
+ m_wire.reset();
+ m_participants.push_back(participant);
+}
+
+void
+ChatroomInfo::addContact(const Name& contact)
+{
+ m_wire.reset();
+ m_contacts.push_back(contact);
+}
+
+void
+ChatroomInfo::setName(const Name::Component& name)
+{
+ m_wire.reset();
+ m_name = name;
+}
+
+void
+ChatroomInfo::setTrustModel(const TrustModel trustModel)
+{
+ m_wire.reset();
+ m_trustModel = trustModel;
+}
+
+} //namespace chronos
diff --git a/src/chatroom-info.hpp b/src/chatroom-info.hpp
new file mode 100644
index 0000000..e182713
--- /dev/null
+++ b/src/chatroom-info.hpp
@@ -0,0 +1,135 @@
+/* -*- 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>
+ */
+#ifndef CHRONOCHAT_CHATROOM_INFO_HPP
+#define CHRONOCHAT_CHATROOM_INFO_HPP
+
+#include "common.hpp"
+#include "chatroom-tlv.hpp"
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/name-component.hpp>
+#include <ndn-cxx/util/time.hpp>
+#include <ndn-cxx/util/concepts.hpp>
+#include <ndn-cxx/encoding/block.hpp>
+#include <ndn-cxx/encoding/encoding-buffer.hpp>
+#include <ndn-cxx/exclude.hpp>
+#include <boost/concept_check.hpp>
+
+namespace chronos {
+
+/** \brief store a chatroom's information with encode and decode method.
+ \sa docs/design.rst
+ */
+
+class ChatroomInfo
+{
+
+public:
+
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+
+ enum TrustModel {
+ TRUST_MODEL_HIERARCHICAL = 2,
+ TRUST_MODEL_WEBOFTRUST = 1,
+ TRUST_MODEL_NONE = 0
+ };
+
+public:
+
+ ChatroomInfo();
+
+ explicit
+ ChatroomInfo(const Block& chatroomWire);
+
+ const Block&
+ wireEncode() const;
+
+ void
+ wireDecode(const Block& chatroomWire);
+
+ const Name::Component&
+ getName() const;
+
+ void
+ setName(const Name::Component& name);
+
+ const std::vector<Name>&
+ getParticipants() const;
+
+ void
+ addParticipant(const Name& participant);
+
+ const std::vector<Name>&
+ getContacts() const;
+
+ void
+ addContact(const Name& contact);
+
+ const TrustModel
+ getTrustModel() const;
+
+ void
+ setTrustModel(const TrustModel trustModel);
+
+private:
+ template<bool T>
+ size_t
+ wireEncode(ndn::EncodingImpl<T>& block) const;
+
+private:
+ mutable Block m_wire;
+ Name::Component m_name;
+ std::vector<Name> m_participants;
+ TrustModel m_trustModel;
+ std::vector<Name> m_contacts;
+
+};
+
+inline const Name::Component&
+ChatroomInfo::getName() const
+{
+ return m_name;
+}
+
+inline const std::vector<Name>&
+ChatroomInfo::getParticipants() const
+{
+ return m_participants;
+}
+
+inline const std::vector<Name>&
+ChatroomInfo::getContacts() const
+{
+ return m_contacts;
+}
+
+inline const ChatroomInfo::TrustModel
+ChatroomInfo::getTrustModel() const
+{
+ return m_trustModel;
+}
+
+BOOST_CONCEPT_ASSERT((ndn::WireEncodable<ChatroomInfo>));
+BOOST_CONCEPT_ASSERT((ndn::WireDecodable<ChatroomInfo>));
+
+
+} // namespace chronos
+
+#endif //CHRONOCHAT_CHATROOM_INFO_HPP
diff --git a/src/chatroom-tlv.hpp b/src/chatroom-tlv.hpp
new file mode 100644
index 0000000..954fbb5
--- /dev/null
+++ b/src/chatroom-tlv.hpp
@@ -0,0 +1,18 @@
+#ifndef CHRONOCHAT_CHATROOM_TLV_HPP
+#define CHRONOCHAT_CHATROOM_TLV_HPP
+
+namespace chronos {
+
+namespace tlv {
+
+enum {
+ PARTICIPANT = 128,
+ CHATROOM = 129,
+ TRUSTMODEL = 130
+};
+
+} //namespace tlv
+
+} //namespace chronos
+
+#endif //CHRONOCHAT_CHATROOM_TLV_HPP
diff --git a/src/controller.hpp b/src/controller.hpp
index d445171..6641b20 100644
--- a/src/controller.hpp
+++ b/src/controller.hpp
@@ -79,7 +79,7 @@
onLocalPrefixTimeout(const Interest& interest);
void
- onInvitationInterestWrapper(const Name& prefix, const Interest& interest,
+ onInvitationInterestWrapper(const ndn::Name& prefix, const ndn::Interest& interest,
size_t routingPrefixOffset);
void
@@ -182,7 +182,8 @@
onError(const QString& msg);
void
- onInvitationInterest(const Name& prefix, const Interest& interest, size_t routingPrefixOffset);
+ onInvitationInterest(const ndn::Name& prefix, const ndn::Interest& interest,
+ size_t routingPrefixOffset);
private: // private member
typedef std::map<std::string, QAction*> ChatActionList;
diff --git a/src/digest-tree-scene.cpp b/src/digest-tree-scene.cpp
index a253384..07e5dea 100644
--- a/src/digest-tree-scene.cpp
+++ b/src/digest-tree-scene.cpp
@@ -47,7 +47,7 @@
// std::cout << "processUpdate v[" << i << "]: " << prefix.toStdString() << std::endl;
rePlot = true;
DisplayUserPtr p(new DisplayUser());
- time_t tempTime = ::time(NULL) - FRESHNESS + 1;
+ time_t tempTime = ::time(0) + 1;
p->setReceived(tempTime);
p->setPrefix(prefix);
p->setSeq(v[i].high);
@@ -115,7 +115,7 @@
// std::cout << "Updating for prefix = " << prefix.toStdString() <<
// " nick = " << nick.toStdString() << std::endl;
DisplayUserPtr p = it.value();
- p->setReceived(::time(NULL));
+ p->setReceived(::time(0) + 1);
if (nick != p->getNick()) {
// std::cout << "old nick = " << p->getNick().toStdString() << std::endl;
p->setNick(nick);
diff --git a/src/digest-tree-scene.hpp b/src/digest-tree-scene.hpp
index 434ee07..138f7f4 100644
--- a/src/digest-tree-scene.hpp
+++ b/src/digest-tree-scene.hpp
@@ -34,16 +34,17 @@
class User;
class DisplayUser;
typedef boost::shared_ptr<DisplayUser> DisplayUserPtr;
+typedef QMap<QString, DisplayUserPtr> Roster;
+typedef QMap<QString, DisplayUserPtr>::iterator Roster_iterator;
+typedef QMapIterator<QString, DisplayUserPtr> RosterIterator;
+
static DisplayUserPtr DisplayUserNullPtr;
+
class DigestTreeScene : public QGraphicsScene
{
Q_OBJECT
-typedef QMap<QString, DisplayUserPtr> Roster;
-typedef QMap<QString, DisplayUserPtr>::iterator Roster_iterator;
-typedef QMapIterator<QString, DisplayUserPtr> RosterIterator;
-
public:
DigestTreeScene(QWidget *parent = 0);
diff --git a/test/dummy-client-face.hpp b/test/dummy-client-face.hpp
new file mode 100644
index 0000000..52e871e
--- /dev/null
+++ b/test/dummy-client-face.hpp
@@ -0,0 +1,141 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_TESTS_UNIT_TESTS_DUMMY_CLIENT_FACE_HPP
+#define NDN_TESTS_UNIT_TESTS_DUMMY_CLIENT_FACE_HPP
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/transport/transport.hpp>
+
+namespace chronos {
+namespace test {
+
+class DummyClientTransport : public ndn::Transport
+{
+public:
+ void
+ receive(const Block& block)
+ {
+ if (static_cast<bool>(m_receiveCallback))
+ m_receiveCallback(block);
+ }
+
+ virtual void
+ close()
+ {
+ }
+
+ virtual void
+ pause()
+ {
+ }
+
+ virtual void
+ resume()
+ {
+ }
+
+ virtual void
+ send(const Block& wire)
+ {
+ if (wire.type() == tlv::Interest) {
+ m_sentInterests->push_back(Interest(wire));
+ }
+ else if (wire.type() == tlv::Data) {
+ m_sentDatas->push_back(Data(wire));
+ }
+ }
+
+ virtual void
+ send(const Block& header, const Block& payload)
+ {
+ this->send(payload);
+ }
+
+public:
+ std::vector<Interest>* m_sentInterests;
+ std::vector<Data>* m_sentDatas;
+};
+
+
+/** \brief a client-side face for unit testing
+ */
+class DummyClientFace : public ndn::Face
+{
+public:
+ explicit
+ DummyClientFace(shared_ptr<DummyClientTransport> transport)
+ : Face(transport)
+ , m_transport(transport)
+ {
+ m_transport->m_sentInterests = &m_sentInterests;
+ m_transport->m_sentDatas = &m_sentDatas;
+ }
+
+ DummyClientFace(shared_ptr<DummyClientTransport> transport, boost::asio::io_service& ioService)
+ : Face(transport, ioService)
+ , m_transport(transport)
+ {
+ m_transport->m_sentInterests = &m_sentInterests;
+ m_transport->m_sentDatas = &m_sentDatas;
+ }
+
+ /** \brief cause the Face to receive a packet
+ */
+ template<typename Packet>
+ void
+ receive(const Packet& packet)
+ {
+ m_transport->receive(packet.wireEncode());
+ }
+
+public:
+ /** \brief sent Interests
+ * \note After .expressInterest, .processEvents must be called before
+ * the Interest would show up here.
+ */
+ std::vector<Interest> m_sentInterests;
+ /** \brief sent Datas
+ * \note After .put, .processEvents must be called before
+ * the Interest would show up here.
+ */
+ std::vector<Data> m_sentDatas;
+
+private:
+ shared_ptr<DummyClientTransport> m_transport;
+};
+
+inline shared_ptr<DummyClientFace>
+makeDummyClientFace()
+{
+ return make_shared<DummyClientFace>(make_shared<DummyClientTransport>());
+}
+
+inline shared_ptr<DummyClientFace>
+makeDummyClientFace(boost::asio::io_service& ioService)
+{
+ return make_shared<DummyClientFace>(make_shared<DummyClientTransport>(), ref(ioService));
+}
+
+} // namespace tests
+} // namespace ndn
+
+#endif // NDN_TESTS_UNIT_TESTS_DUMMY_CLIENT_FACE_HPP
diff --git a/test/test-chatroom-discovery-logic.cpp b/test/test-chatroom-discovery-logic.cpp
new file mode 100644
index 0000000..1714e8a
--- /dev/null
+++ b/test/test-chatroom-discovery-logic.cpp
@@ -0,0 +1,328 @@
+#include "chatroom-discovery-logic.hpp"
+#include <boost/test/unit_test.hpp>
+#include "dummy-client-face.hpp"
+
+namespace chronos {
+
+namespace test {
+
+using std::string;
+
+BOOST_AUTO_TEST_SUITE(TestChatroomDiscoveryLogic)
+
+class Fixture
+{
+public:
+ Fixture()
+ : face(makeDummyClientFace())
+ {
+ }
+
+ void
+ update(const ChatroomInfo& chatroomName, bool isAdd)
+ {
+ }
+
+public:
+ shared_ptr<DummyClientFace> face;
+};
+
+BOOST_FIXTURE_TEST_CASE(AddLocalChatroom, Fixture)
+{
+ ChatroomDiscoveryLogic chatroomDiscoveryLogic(face, bind(&Fixture::update, this, _1, _2));
+
+ ChatroomInfo chatroom;
+ chatroom.setName(ndn::Name::Component("lunch-talk"));
+ chatroom.addParticipant(Name("/ndn/ucla/ymj"));
+ chatroom.addParticipant(Name("/ndn/ucla/alice"));
+ chatroom.setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+ chatroomDiscoveryLogic.addLocalChatroom(chatroom);
+
+ ndn::Name::Component chatroomName("lunch-talk");
+
+ BOOST_CHECK_EQUAL(chatroomDiscoveryLogic.getChatrooms().size(), 1);
+ BOOST_CHECK_EQUAL(chatroom.getName(),
+ chatroomDiscoveryLogic.getChatrooms().find(chatroomName)
+ ->second.getName());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants().size(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second.getParticipants().size());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[0].toUri(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second
+ .getParticipants()[0].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[1].toUri(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second
+ .getParticipants()[1].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getTrustModel(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second.getTrustModel());
+}
+
+BOOST_FIXTURE_TEST_CASE(RemoveLocalChatroom, Fixture)
+{
+ ChatroomDiscoveryLogic chatroomDiscoveryLogic(face, bind(&Fixture::update, this, _1, _2));
+
+ ChatroomInfo chatroom;
+ chatroom.setName(ndn::Name::Component("lunch-talk"));
+ chatroom.addParticipant(Name("/ndn/ucla/ymj"));
+ chatroom.addParticipant(Name("/ndn/ucla/alice"));
+ chatroom.setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+ chatroomDiscoveryLogic.addLocalChatroom(chatroom);
+
+ ndn::Name::Component chatroomName1("lunch-talk");
+ ndn::Name::Component chatroomName2("supper-talk");
+
+ chatroomDiscoveryLogic.removeLocalChatroom(chatroomName2);
+
+ BOOST_CHECK_EQUAL(chatroomDiscoveryLogic.getChatrooms().size(), 1);
+ BOOST_CHECK_EQUAL(chatroom.getName(),
+ chatroomDiscoveryLogic.getChatrooms().find(chatroomName1)
+ ->second.getName());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants().size(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName1)->second.getParticipants().size());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[0].toUri(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName1)->second
+ .getParticipants()[0].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[1].toUri(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName1)->second
+ .getParticipants()[1].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getTrustModel(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName1)->second.getTrustModel());
+
+ chatroomDiscoveryLogic.removeLocalChatroom(chatroomName1);
+ BOOST_CHECK_EQUAL(chatroomDiscoveryLogic.getChatrooms().size(), 0);
+}
+
+BOOST_FIXTURE_TEST_CASE(sendChatroomInterestFunction, Fixture)
+{
+ ChatroomDiscoveryLogic chatroomDiscoveryLogic(face, bind(&Fixture::update, this, _1, _2));
+ chatroomDiscoveryLogic.sendDiscoveryInterest();
+
+ face->processEvents(time::milliseconds(100));
+
+ //with no exclude filter
+ BOOST_CHECK_EQUAL(face->m_sentInterests.size(), 2);//first is nfd register interest
+ BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 0);
+ BOOST_CHECK_EQUAL(face->m_sentInterests[1].getName().toUri(),
+ ChatroomDiscoveryLogic::DISCOVERY_PREFIX.toUri());
+ BOOST_CHECK_EQUAL(face->m_sentInterests[1].getExclude().size(), 0);
+
+ face->m_sentInterests.clear();
+
+ //with exclude filter
+ ChatroomInfo chatroom;
+ chatroom.setName(ndn::Name::Component("lunch-talk"));
+ chatroom.addParticipant(Name("/ndn/ucla/ymj"));
+ chatroom.addParticipant(Name("/ndn/ucla/alice"));
+ chatroom.setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+ chatroomDiscoveryLogic.addLocalChatroom(chatroom);
+
+ chatroomDiscoveryLogic.sendDiscoveryInterest();
+ face->processEvents(time::milliseconds(100));
+
+ BOOST_CHECK_EQUAL(face->m_sentInterests.size(), 1);
+ BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 0);
+ BOOST_CHECK_EQUAL(face->m_sentInterests[0].getName().toUri(),
+ ChatroomDiscoveryLogic::DISCOVERY_PREFIX.toUri());
+ BOOST_CHECK_EQUAL(face->m_sentInterests[0].getExclude().size(), 1);
+ BOOST_CHECK_EQUAL(face->m_sentInterests[0].getExclude().toUri(), "lunch-talk");
+}
+
+BOOST_FIXTURE_TEST_CASE(onDiscoveryInterest, Fixture)
+{
+ face->m_sentInterests.clear();
+ face->m_sentDatas.clear();
+
+ Interest discovery(ChatroomDiscoveryLogic::DISCOVERY_PREFIX);
+ discovery.setMustBeFresh(true);
+ discovery.setInterestLifetime(time::milliseconds(10000));
+
+ Exclude exclude;
+ exclude.excludeOne(ndn::Name::Component("lunch-talk"));
+ discovery.setExclude(exclude);
+
+ ChatroomDiscoveryLogic chatroomDiscoveryLogic(face, bind(&Fixture::update, this, _1, _2));
+
+ ChatroomInfo chatroom1;
+ chatroom1.setName(ndn::Name::Component("lunch-talk"));
+ chatroom1.addParticipant(Name("/ndn/ucla/ymj"));
+ chatroom1.addParticipant(Name("/ndn/ucla/alice"));
+ chatroom1.setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+ chatroomDiscoveryLogic.addLocalChatroom(chatroom1);
+
+ ChatroomInfo chatroom2;
+ chatroom2.setName(ndn::Name::Component("supper-talk"));
+ chatroom2.addParticipant(Name("/ndn/ucla/bob"));
+ chatroom2.addParticipant(Name("/ndn/ucla/peter"));
+ chatroom2.setTrustModel(ChatroomInfo::TRUST_MODEL_HIERARCHICAL);
+ chatroomDiscoveryLogic.addLocalChatroom(chatroom2);
+
+ //discovery
+ chatroomDiscoveryLogic.onDiscoveryInterest(ChatroomDiscoveryLogic::DISCOVERY_PREFIX, discovery);
+
+ face->processEvents(time::milliseconds(100));
+
+ BOOST_CHECK_EQUAL(face->m_sentInterests.size(), 1);//the interest is for nfd register
+ BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 1);
+
+ ChatroomInfo chatroom;
+ chatroom.wireDecode(face->m_sentDatas[0].getContent().blockFromValue());
+ chatroom.setName(face->m_sentDatas[0].getName()
+ .get(ChatroomDiscoveryLogic::OFFSET_CHATROOM_NAME));
+
+ BOOST_CHECK_EQUAL(chatroom.getName(), chatroom2.getName());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants().size(),
+ chatroom2.getParticipants().size());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[0].toUri(),
+ chatroom2.getParticipants()[0].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[1].toUri(),
+ chatroom2.getParticipants()[1].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getTrustModel(),
+ chatroom2.getTrustModel());
+
+ //refreshing
+ face->m_sentInterests.clear();
+ face->m_sentDatas.clear();
+
+ Name name = ChatroomDiscoveryLogic::DISCOVERY_PREFIX;
+ name.append(Name("supper-talk"));
+
+ Interest refreshing(name);
+ refreshing.setMustBeFresh(true);
+ refreshing.setInterestLifetime(time::milliseconds(10000));
+
+ chatroomDiscoveryLogic.onDiscoveryInterest(name, refreshing);
+ face->processEvents(time::milliseconds(100));
+
+ BOOST_CHECK_EQUAL(face->m_sentInterests.size(), 0);
+ BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 1);
+
+ chatroom.wireDecode(face->m_sentDatas[0].getContent().blockFromValue());
+ chatroom.setName(face->m_sentDatas[0].getName()
+ .get(ChatroomDiscoveryLogic::OFFSET_CHATROOM_NAME));
+
+ BOOST_CHECK_EQUAL(chatroom.getName(), chatroom2.getName());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants().size(),
+ chatroom2.getParticipants().size());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[0].toUri(),
+ chatroom2.getParticipants()[0].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[1].toUri(),
+ chatroom2.getParticipants()[1].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getTrustModel(),
+ chatroom2.getTrustModel());
+}
+
+BOOST_FIXTURE_TEST_CASE(refreshChatroomFunction, Fixture)
+{
+ ChatroomDiscoveryLogic chatroomDiscoveryLogic(face, bind(&Fixture::update, this, _1, _2));
+
+ ChatroomInfo chatroom1;
+ chatroom1.setName(ndn::Name::Component("lunch-talk"));
+ chatroom1.addParticipant(Name("/ndn/ucla/ymj"));
+ chatroom1.addParticipant(Name("/ndn/ucla/alice"));
+ chatroom1.setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+ chatroomDiscoveryLogic.addLocalChatroom(chatroom1);
+
+ chatroomDiscoveryLogic.refreshChatroom(ndn::Name::Component("lunch-talk"));
+ face->processEvents(time::milliseconds(100));
+
+ BOOST_CHECK_EQUAL(face->m_sentInterests.size(), 2);
+ BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 0);
+
+ Name name = ChatroomDiscoveryLogic::DISCOVERY_PREFIX;
+ name.append(Name("lunch-talk"));
+
+ BOOST_CHECK_EQUAL(face->m_sentInterests[1].getName().toUri(), name.toUri());
+ BOOST_CHECK_EQUAL(face->m_sentInterests[1].getExclude().size(), 0);
+}
+
+BOOST_FIXTURE_TEST_CASE(onReceiveData, Fixture)
+{
+ ChatroomDiscoveryLogic chatroomDiscoveryLogic(face, bind(&Fixture::update, this, _1, _2));
+
+ //discovery
+ Interest discovery(ChatroomDiscoveryLogic::DISCOVERY_PREFIX);
+ discovery.setMustBeFresh(true);
+ discovery.setInterestLifetime(time::milliseconds(10000));
+
+ Name dataName(ChatroomDiscoveryLogic::DISCOVERY_PREFIX);
+ dataName.append(ndn::Name::Component("lunch-talk"));
+
+ ChatroomInfo chatroom1;
+ chatroom1.setName(ndn::Name::Component("lunch-talk"));
+ chatroom1.addParticipant(Name("/ndn/ucla/ymj"));
+ chatroom1.addParticipant(Name("/ndn/ucla/alice"));
+ chatroom1.setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+
+ shared_ptr<Data> chatroomInfo = make_shared<Data>(dataName);
+ chatroomInfo->setFreshnessPeriod(time::seconds(10));
+ chatroomInfo->setContent(chatroom1.wireEncode());
+
+ chatroomDiscoveryLogic.onReceiveData(discovery, *chatroomInfo, false);
+
+ face->processEvents(time::milliseconds(1000));
+
+ ndn::Name::Component chatroomName("lunch-talk");
+
+ BOOST_CHECK_EQUAL(chatroomDiscoveryLogic.getChatrooms().size(), 1);
+ BOOST_CHECK_EQUAL(chatroom1.getName(),
+ chatroomDiscoveryLogic.getChatrooms().find(chatroomName)
+ ->second.getName());
+ BOOST_CHECK_EQUAL(chatroom1.getParticipants().size(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second.getParticipants().size());
+ BOOST_CHECK_EQUAL(chatroom1.getParticipants()[0].toUri(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second
+ .getParticipants()[0].toUri());
+ BOOST_CHECK_EQUAL(chatroom1.getParticipants()[1].toUri(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second
+ .getParticipants()[1].toUri());
+ BOOST_CHECK_EQUAL(chatroom1.getTrustModel(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second.getTrustModel());
+
+ //refreshing
+ Name name = ChatroomDiscoveryLogic::DISCOVERY_PREFIX;
+ name.append(Name("lunch-talk"));
+
+ Interest refreshing(name);
+ refreshing.setMustBeFresh(true);
+ refreshing.setInterestLifetime(time::milliseconds(10000));
+
+ chatroomDiscoveryLogic.onReceiveData(discovery, *chatroomInfo, false);
+
+ face->processEvents(time::milliseconds(1000));
+
+ BOOST_CHECK_EQUAL(chatroomDiscoveryLogic.getChatrooms().size(), 1);
+ BOOST_CHECK_EQUAL(chatroom1.getName(),
+ chatroomDiscoveryLogic.getChatrooms().find(chatroomName)
+ ->second.getName());
+ BOOST_CHECK_EQUAL(chatroom1.getParticipants().size(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second.getParticipants().size());
+ BOOST_CHECK_EQUAL(chatroom1.getParticipants()[0].toUri(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second
+ .getParticipants()[0].toUri());
+ BOOST_CHECK_EQUAL(chatroom1.getParticipants()[1].toUri(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second
+ .getParticipants()[1].toUri());
+ BOOST_CHECK_EQUAL(chatroom1.getTrustModel(),
+ chatroomDiscoveryLogic
+ .getChatrooms().find(chatroomName)->second.getTrustModel());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+
+} // namespace chronos
diff --git a/test/test-chatroom-info.cpp b/test/test-chatroom-info.cpp
new file mode 100644
index 0000000..a1b444e
--- /dev/null
+++ b/test/test-chatroom-info.cpp
@@ -0,0 +1,175 @@
+#include "chatroom-info.hpp"
+#include <boost/test/unit_test.hpp>
+#include <ndn-cxx/encoding/block.hpp>
+
+namespace chronos {
+
+namespace test {
+
+using std::string;
+
+BOOST_AUTO_TEST_SUITE(TestChatroomInfo)
+
+const uint8_t chatroomInfo[] = {
+ 0x81, 0x2d, // ChatroomInfo
+ 0x82, 0x01, // TrustModel
+ 0x01,
+ 0x80, 0x14,// Participant1
+ 0x07, 0x12,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x04,
+ 0x75, 0x63, 0x6c, 0x61,
+ 0x08, 0x05,
+ 0x61, 0x6c, 0x69, 0x63, 0x65,
+ 0x80, 0x12, // Participant2
+ 0x07, 0x10,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x04,
+ 0x75, 0x63, 0x6c, 0x61,
+ 0x08, 0x03,
+ 0x79, 0x6d, 0x6a
+};
+
+BOOST_AUTO_TEST_CASE(EncodeChatroom)
+{
+ //Chatroom := CHATROOM-TYPE TLV-LENGTH
+ // TrustModel
+ // Participant+
+
+ ChatroomInfo chatroom;
+ chatroom.setName(ndn::Name::Component("lunch-talk"));
+ chatroom.addParticipant(Name("/ndn/ucla/alice"));
+ chatroom.addParticipant(Name("/ndn/ucla/ymj"));
+ chatroom.setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+
+ const Block& encoded = chatroom.wireEncode();
+ Block chatroomInfoBlock(chatroomInfo, sizeof(chatroomInfo));
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(chatroomInfoBlock.wire(),
+ chatroomInfoBlock.wire() + chatroomInfoBlock.size(),
+ encoded.wire(),
+ encoded.wire() + encoded.size());
+}
+
+BOOST_AUTO_TEST_CASE(DecodeChatroomCorrect)
+{
+ ChatroomInfo chatroom;
+ chatroom.setName(ndn::Name::Component("lunch-talk"));
+ chatroom.addParticipant(Name("/ndn/ucla/alice"));
+ chatroom.addParticipant(Name("/ndn/ucla/ymj"));
+ chatroom.setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+
+ Block chatroomInfoBlock(chatroomInfo, sizeof(chatroomInfo));
+ ChatroomInfo dechatroom;
+ dechatroom.wireDecode(chatroomInfoBlock);
+ dechatroom.setName(ndn::Name::Component("lunch-talk"));
+
+ BOOST_CHECK_EQUAL(chatroom.getName(), dechatroom.getName());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants().size(), dechatroom.getParticipants().size());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[0].toUri(), dechatroom.getParticipants()[0].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getParticipants()[1].toUri(), dechatroom.getParticipants()[1].toUri());
+ BOOST_CHECK_EQUAL(chatroom.getTrustModel(), dechatroom.getTrustModel());
+}
+
+BOOST_AUTO_TEST_CASE(DecodeChatroomError)
+{
+ const uint8_t error1[] = {
+ 0x80, 0x2d, // Wrong ChatroomInfo Type (0x81, 0x2d)
+ 0x82, 0x01, // TrustModel
+ 0x01,
+ 0x80, 0x14,// Participant1
+ 0x07, 0x12,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x04,
+ 0x75, 0x63, 0x6c, 0x61,
+ 0x08, 0x05,
+ 0x61, 0x6c, 0x69, 0x63, 0x65,
+ 0x80, 0x12, // Participant2
+ 0x07, 0x10,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x04,
+ 0x75, 0x63, 0x6c, 0x61,
+ 0x08, 0x03,
+ 0x79, 0x6d, 0x6a
+ };
+
+ Block errorBlock1(error1, sizeof(error1));
+ BOOST_CHECK_THROW(ChatroomInfo chatroom(errorBlock1), ChatroomInfo::Error);
+
+ const uint8_t error2[] = {
+ 0x81, 0x2d, // ChatroomInfo
+ 0x81, 0x01, // Wrong TrustModel Type (0x82, 0x01)
+ 0x01,
+ 0x80, 0x14,// Participant1
+ 0x07, 0x12,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x04,
+ 0x75, 0x63, 0x6c, 0x61,
+ 0x08, 0x05,
+ 0x61, 0x6c, 0x69, 0x63, 0x65,
+ 0x80, 0x12, // Participant2
+ 0x07, 0x10,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x04,
+ 0x75, 0x63, 0x6c, 0x61,
+ 0x08, 0x03,
+ 0x79, 0x6d, 0x6a
+ };
+
+ Block errorBlock2(error2, sizeof(error2));
+ BOOST_CHECK_THROW(ChatroomInfo chatroom(errorBlock2), ChatroomInfo::Error);
+
+ const uint8_t error3[] = {
+ 0x81, 0x2d, // ChatroomInfo
+ 0x82, 0x01, // TrustModel
+ 0x01,
+ 0x80, 0x14,// Participant1
+ 0x07, 0x12,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x04,
+ 0x75, 0x63, 0x6c, 0x61,
+ 0x08, 0x05,
+ 0x61, 0x6c, 0x69, 0x63, 0x65,
+ 0x81, 0x12, // Wrong Participant Type (0x80, 0x12)
+ 0x07, 0x10,
+ 0x08, 0x03,
+ 0x6e, 0x64, 0x6e,
+ 0x08, 0x04,
+ 0x75, 0x63, 0x6c, 0x61,
+ 0x08, 0x03,
+ 0x79, 0x6d, 0x6a
+ };
+
+ Block errorBlock3(error3, sizeof(error3));
+ BOOST_CHECK_THROW(ChatroomInfo chatroom(errorBlock3), ChatroomInfo::Error);
+
+ const uint8_t error4[] = {
+ 0x81, 0x00 // Empty ChatroomInfo
+ };
+
+ Block errorBlock4(error4, sizeof(error4));
+ BOOST_CHECK_THROW(ChatroomInfo chatroom(errorBlock4), ChatroomInfo::Error);
+
+ const uint8_t error5[] = {
+ 0x81, 0x03, // ChatroomInfo
+ 0x82, 0x01, // TrustModel
+ 0x01
+ //zero Participant
+ };
+
+ Block errorBlock5(error5, sizeof(error5));
+ BOOST_CHECK_THROW(ChatroomInfo chatroom(errorBlock5), ChatroomInfo::Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} //namespace test
+
+} //namespace chronos