Skip to content

Instantly share code, notes, and snippets.

@pulsejet
Created September 19, 2022 01:43
Show Gist options
  • Save pulsejet/f65797d48760b2410169bc8345db4b57 to your computer and use it in GitHub Desktop.
Save pulsejet/f65797d48760b2410169bc8345db4b57 to your computer and use it in GitHub Desktop.
SVS example for MiniNDN
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2012-2022 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 <chrono>
#include <thread>
#include <vector>
#include <ndn-svs/svsync-base.hpp>
#include <ndn-svs/svsync.hpp>
struct Options
{
std::string prefix;
std::string m_id;
};
class Program
{
public:
Program(const Options &options)
: m_options(options)
{
// Use HMAC signing
ndn::svs::SecurityOptions securityOptions(m_keyChain);
securityOptions.interestSigner->signingInfo.setSigningHmacKey("dGhpcyBpcyBhIHNlY3JldCBtZXNzYWdl");
m_svs = std::make_shared<ndn::svs::SVSync>(
ndn::Name(m_options.prefix),
ndn::Name(m_options.m_id),
face,
std::bind(&Program::onMissingData, this, _1),
securityOptions);
std::cout << "SVS client starting:" << m_options.m_id << std::endl;
m_signingInfo.setSha256Signing();
}
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 = "";
int count = 1;
while (count <= 20) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
userInput = "publication#" + std::to_string(count);
std::cout << "Publishing: " << userInput << std::endl;
publishMsg(userInput);
count++;
}
thread_svs.join();
}
protected:
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].nodeId;
m_svs->fetchData(nid, s, [nid] (const ndn::Data& data)
{
const std::string content(reinterpret_cast<const char*>(data.getContent().value()),
data.getContent().value_size());
std::cout << data.getName() << " : " << content << std::endl;
});
}
}
}
void
publishMsg(const std::string& msg)
{
// Content block
auto block = ndn::encoding::makeBinaryBlock(ndn::tlv::Content, msg.data(), msg.size());
m_svs->publishData(block, ndn::time::milliseconds(1000));
}
public:
const Options m_options;
ndn::Face face;
std::shared_ptr<ndn::svs::SVSyncBase> m_svs;
ndn::KeyChain m_keyChain;
ndn::security::SigningInfo m_signingInfo;
};
int
main(int argc, char **argv)
{
if (argc != 2) {
std::cout << "Usage: client <prefix>" << std::endl;
exit(1);
}
Options opt;
opt.prefix = "/ndn/svs";
opt.m_id = argv[1];
Program program(opt);
program.run();
return 0;
}
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2022, The University of Memphis,
# Arizona Board of Regents,
# Regents of the University of California.
#
# This file is part of Mini-NDN.
# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
#
# Mini-NDN is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Mini-NDN 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Mini-NDN, e.g., in COPYING.md file.
# If not, see <http://www.gnu.org/licenses/>.
import time
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.apps.app_manager import AppManager
from minindn.apps.application import Application
from minindn.apps.nfd import Nfd
from minindn.helpers.nfdc import Nfdc
from minindn.helpers.ndn_routing_helper import NdnRoutingHelper
from tqdm import tqdm
class SvsChatApplication(Application):
"""
Wrapper class to run the chat application from each node
"""
def get_svs_identity(self):
# return "/ndn/{0}-site/{0}/svs_chat/{0}".format(self.node.name)
return "/ndn/{0}/chat".format(self.node.name)
def start(self):
# Get arguments
identity = self.get_svs_identity()
exe = "/mini-ndn/ndn-svs/build/examples/demo"
# Build command
run_cmd = "{0} {1}".format(exe, identity, self.node.name)
# Start application with log file
Application.start(self, run_cmd, "svs.log")
if __name__ == '__main__':
setLogLevel('info')
Minindn.cleanUp()
Minindn.verifyDependencies()
ndn = Minindn()
ndn.start()
info('Starting NFD on nodes\n')
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
# Set up Interest forwarding for Sync
info('Setting NFD strategy to multicast on all nodes with prefix')
for node in tqdm(ndn.net.hosts):
Nfdc.setStrategy(node, "/ndn/svs", Nfdc.STRATEGY_MULTICAST)
info('Adding static routes to NFD\n')
grh = NdnRoutingHelper(ndn.net, 'udp', 'link-state')
for host in ndn.net.hosts:
grh.addOrigin([ndn.net[host.name]], ["/ndn/svs/", "/ndn/{}/chat".format(host.name)])
grh.calculateNPossibleRoutes()
# Example: clear cache
info('Clearing content store at all NFDs\n')
for node in tqdm(ndn.net.hosts):
node.cmd('nfdc cs erase /')
# Start application
svs_chat_app = AppManager(ndn, ndn.net.hosts, SvsChatApplication)
# Wait for 10s
time.sleep(10)
ndn.stop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment