blob: 0c40ee4bdf6bf7f15a4a684141a63e383cd1c3ed [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2020, Regents of the University of California
*
* BSD license, See the LICENSE file for more information
*
* Author: Qiuhan Ding <qiuhanding@cs.ucla.edu>
* Yingdi Yu <yingdi@cs.ucla.edu>
*/
#ifndef CHRONOCHAT_CHATROOM_DISCOVERY_BACKEND_HPP
#define CHRONOCHAT_CHATROOM_DISCOVERY_BACKEND_HPP
#include <QThread>
#ifndef Q_MOC_RUN
#include "common.hpp"
#include "chatroom-info.hpp"
#include <boost/random.hpp>
#include <mutex>
#include <ChronoSync/socket.hpp>
#include <boost/thread.hpp>
#endif
namespace chronochat {
class ChatroomInfoBackend
{
public:
std::string chatroomName;
Name chatroomPrefix;
ChatroomInfo info;
// For a chatroom's user to check whether his own chatroom is alive
ndn::scheduler::EventId localChatroomTimeoutEventId;
// If the manager no longer exist, set a random timer to compete for manager
ndn::scheduler::EventId managerSelectionTimeoutEventId;
// For a user to check the status of the chatroom that he is not in.
ndn::scheduler::EventId remoteChatroomTimeoutEventId;
// If the user is manager, he will need the helloEventId to keep track of hello message
ndn::scheduler::ScopedEventId helloTimeoutEventId;
// To tell whether the user is in this chatroom
bool isParticipant;
// To tell whether the user is the manager
bool isManager;
// Variable to tell whether another manager exists
int count;
// Variable to tell whether to print on the panel
bool isPrint;
};
class ChatroomDiscoveryBackend : public QThread
{
Q_OBJECT
public:
ChatroomDiscoveryBackend(const Name& routingPrefix,
const Name& identity,
QObject* parent = nullptr);
~ChatroomDiscoveryBackend();
protected:
void
run();
private:
void
initializeSync();
void
close();
void
processSyncUpdate(const std::vector<chronosync::MissingDataInfo>& updates);
void
processChatroomData(const ndn::Data& data);
void
localSessionTimeout(const Name::Component& chatroomName);
void
remoteSessionTimeout(const Name::Component& chatroomName);
void
randomSessionTimeout(const Name::Component& chatroomName);
void
sendUpdate(const Name::Component& chatroomName);
void
updatePrefixes();
void
sendChatroomList();
signals:
/**
* @brief request to get chatroom info
*
* This signal will be sent to controller to get chatroom info
*
* @param chatroomName specify which chatroom's info to request
* @param isManager if the user who send the signal is the manager of the chatroom
*/
void
chatroomInfoRequest(std::string chatroomName, bool isManager);
/**
* @brief send chatroom list to front end
*
* @param chatroomList the list of chatrooms
*/
void
chatroomListReady(const QStringList& chatroomList);
/**
* @brief send chatroom info to front end
*
* @param info the chatroom info request by front end
* @param isParticipant if the user is a participant of the chatroom
*/
void
chatroomInfoReady(const ChatroomInfo& info, bool isParticipant);
void
nfdError();
public slots:
/**
* @brief update routing prefix
*
* @param routingPrefix the new routing prefix
*/
void
updateRoutingPrefix(const QString& routingPrefix);
/**
* @brief erase a participant in a chatroom's roster
*
* This slot is called by chat dialog will erase a participant from a chatroom.
* If the user is the manager of this chatroom, he will publish an update.
*
* @param sessionPrefix the prefix of the participant to erase
* @param chatroomName the name of the chatroom
*/
void
onEraseInRoster(ndn::Name sessionPrefix, ndn::Name::Component chatroomName);
/**
* @brief add a participant in a chatroom's roster
*
* This slot is called by chat dialog and will add a participant from a chatroom.
* If the user is the manager of this chatroom, he will publish an update.
*
* @param sessionPrefix the prefix of the participant to erase
* @param chatroomName the name of the chatroom
*/
void
onAddInRoster(ndn::Name sessionPrefix, ndn::Name::Component chatroomName);
/**
* @brief is called when user himself join a chatroom
*
* This slot is called by controller and will modify the chatroom list in discovery
*
* @param chatroomName the name of chatroom the user join
*/
void
onNewChatroomForDiscovery(ndn::Name::Component chatroomName);
/**
* @brief get chatroom info from chat dialog
*
* This slot is called by controller. It get the chatroom info of a chatroom and
* if the user is the manager, he will publish an update
*
* @param chatroomInfo chatroom info
* @param isManager whether the user is the manager of the chatroom
*/
void
onRespondChatroomInfoRequest(ChatroomInfo chatroomInfo, bool isManager);
/**
* @brief reset when the identity updates
*
* This slot is called when the identity is updated, it will update the identity and
* reset the socket
*
* @param identity new identity
*/
void
onIdentityUpdated(const QString& identity);
/**
* @brief prepare chatroom info for discovery panel
*
* This slot is called by discovery panel when it wants to display the info of a chatroom
*
* @param chatroomName the name of chatroom the discovery panel requested
*/
void
onWaitForChatroomInfo(const QString& chatroomName);
void
shutdown();
void
onNfdReconnect();
private:
typedef std::map<ndn::Name::Component, ChatroomInfoBackend> ChatroomList;
bool m_shouldResume;
bool m_isNfdConnected;
Name m_discoveryPrefix;
Name m_routableUserDiscoveryPrefix;
Name m_routingPrefix;
Name m_userDiscoveryPrefix;
Name m_identity;
boost::mt19937 m_randomGenerator;
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_rangeUniformRandom;
shared_ptr<ndn::Face> m_face;
unique_ptr<ndn::Scheduler> m_scheduler; // scheduler
ndn::scheduler::ScopedEventId m_refreshPanelId;
shared_ptr<chronosync::Socket> m_sock; // SyncSocket
ChatroomList m_chatroomList;
std::mutex m_resumeMutex;
std::mutex m_nfdConnectionMutex;
};
} // namespace chronochat
#endif // CHRONOCHAT_CHATROOM_DISCOVERY_BACKEND_HPP