Skip to content

Instantly share code, notes, and snippets.

@pulsejet
Created February 17, 2021 10:23
Show Gist options
  • Save pulsejet/0a60e7f28f9ad36148a89b534e5fc368 to your computer and use it in GitHub Desktop.
Save pulsejet/0a60e7f28f9ad36148a89b534e5fc368 to your computer and use it in GitHub Desktop.
Chat application serving on separate prefix on ndn-svs
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2012-2021 University of California, Los Angeles
*
* This file is part of ndn-svs, synchronization library for distributed realtime
* applications for NDN.
*
* ndn-svs 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, in version 2.1 of the License.
*
* ndn-svs 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.
*/
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <ndn-svs/socket.hpp>
#include <ndn-cxx/ims/in-memory-storage-persistent.hpp>
class Options
{
public:
Options() : prefix("/ndn/svs") {}
public:
std::string prefix;
std::string m_id;
};
class Program
{
public:
Program(const Options &options)
: m_options(options)
{
m_registeredDataPrefix =
face.setInterestFilter(getDataName(m_options.m_id, 0).getPrefix(-1),
[this] (const ndn::Name& prefix, const ndn::Interest& interest) {
auto data = m_ims.find(interest);
if (data != nullptr)
face.put(*data);
},
[] (const ndn::Name& prefix, const std::string& msg) {});
m_logic = std::make_shared<ndn::svs::Logic>(
face,
keychain,
ndn::Name(m_options.prefix),
std::bind(&Program::onMissingData, this, _1),
"dGhpcyBpcyBhIHNlY3JldCBtZXNzYWdl",
ndn::Name(m_options.m_id).toUri());
std::cout << "SVS client stared:" << m_options.m_id << std::endl;
}
void
run()
{
std::thread thread_svs([this] { face.processEvents(); });
std::string init_msg = "User " + m_options.m_id + " has joined the groupchat";
publishMsg(init_msg);
std::string userInput = "";
while (true) {
std::getline(std::cin, userInput);
publishMsg(userInput);
}
thread_svs.join();
}
private:
void
onMissingData(const std::vector<ndn::svs::MissingDataInfo>& v)
{
for (size_t i = 0; i < v.size(); i++)
{
for (ndn::svs::SeqNo s = v[i].low; s <= v[i].high; ++s)
{
ndn::svs::NodeID nid = v[i].session;
ndn::Interest interest(getDataName(nid, s));
face.expressInterest(interest, [nid] (const ndn::Interest& interest, const ndn::Data& data)
{
size_t data_size = data.getContent().value_size();
std::string content_str((char *)data.getContent().value(), data_size);
content_str = nid + " : " + content_str;
std::cout << content_str << std::endl;
}, nullptr, nullptr);
}
}
}
void
publishMsg(std::string msg)
{
ndn::svs::SeqNo seq = m_logic->getSeqNo();
ndn::Name name = getDataName(m_options.m_id, seq + 1);
std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(name);
data->setContent(reinterpret_cast<const uint8_t*>(msg.c_str()), msg.size());
data->setFreshnessPeriod(ndn::time::milliseconds(1000));
keychain.sign(*data);
m_ims.insert(*data);
m_logic->updateSeqNo(seq + 1);
}
ndn::Name
getDataName(ndn::svs::NodeID nid, ndn::svs::SeqNo seq)
{
return ndn::Name(nid).append(ndn::Name(m_options.prefix))
.appendNumber(seq);
}
public:
const Options m_options;
ndn::Face face;
ndn::KeyChain keychain;
std::shared_ptr<ndn::svs::Logic> m_logic;
ndn::InMemoryStoragePersistent m_ims;
ndn::ScopedRegisteredPrefixHandle m_registeredDataPrefix;
};
int
main(int argc, char **argv)
{
if (argc != 2) {
std::cout << "Usage: client <prefix>" << std::endl;
exit(1);
}
Options opt;
opt.m_id = argv[1];
Program program(opt);
program.run();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment