Introducing NDNts, Named Data Networking libraries for the Modern Web

I'm creating a new Named Data Networking (NDN) client library, NDNts. The initial NPM release, v0.0.20191223-beta.1, was uploaded yesterday. This article explains why I'm doing this, and why you should consider using my library.

Motivation

I've been developing Named Data Networking (NDN) for several years. Although my specialty is in the forwarding plane, I occasionally build NDN applications, such as a home surveillance camera. A common ingredient of every NDN application is some sort of client libraries, which provides APIs that allow the application to encode/decode NDN packets and communicate over NDN networks in accordance with the NDN protocol. One of these client libraries is the NDN Common Client Libraries (NDN-CCL), which provide a consistent API across several programming languages.

I adopted ndn-js, the JavaScript variant of NDN-CCL, in several projects, and was unhappy about it:

  • The API feels like Java, not JavaScript.
  • Callbacks everywhere, leading to callback hell.
  • The library inserts over 50 symbols to the browser's global scope, causing name conflicts.
  • All features are bundled into a single file that weighs over 500KB.
  • There's no unit testing for the most part, let alone continuous integration.

I made several attempts to improve the situation. For example, I published @types/ndn-js package, enabling using ndn-js in TypeScript projects. However, being constrained by ndn-js's stated goals (especially, inter-language API), what I could do is limited.

In 05 Sep 2019, owner of NDN-CCL announced that they are no longer maintaining the project because their funding has run out:

REMAP has no current support to update the CCL and CNL libraries. We do not intend to abandon either library, but have no funding to do work on them, either.

It's time for The Big Rewrite ™.

Design Decisions

I started working on NDNts shortly after REMAP's announcement.

I decided early on that I should write the library in TypeScript. I encountered TypeScript at a workshop in 2016, used it several times, and then it became my most loved programming language. Writing the library in TypeScript enables compile-time type checking, which greatly reduces the chance of making mistakes regarding variable types. The name of this project, NDNts, reflects this design decision.

Like most of my other projects, I don't care much about backwards compatibility. The beauty of NPM is that, all published versions are available forever, and you can pick any version in your dependencies. Being a personal project, I have to prioritize in developing for the latest and greatest, instead of worrying about backwards compatibility.

NDNts targets the latest platforms. Initially, NDNts supports Node 12.x (Windows and Linux), Firefox (desktop), Chrome (desktop, Android, iOS). By limiting to the latest platforms, I can avoid adding shims and polyfills most of the time, and focus on developing the best features. It also improves application security: all crypto operations in browsers are handled by Web Crypto API, not in JavaScript.

NDNts will be a set of libraries, not a single library. This enables application developers to only pick the features they need, and matches the practice of most projects on NPM today. A drawback is that web applications have to use a module bundler, but this could change in the future when I figure out how to offer standalone bundles of common feature sets.

Test coverage is important. So far I have included unit testing coverage for all library components, except command line interfaces. I even have browser tests that are executed automatically as part of continuous integration.

NDNts Architecture

The initial release of NDNts consists of 22 packages. Each package has a README that describes what's in that package and often contains code samples, but I'd give a big picture here.

We start from packet representation and encoding:

  • @ndn/tlv implements Type-Length-Value structure encoder and decoder.
  • @ndn/packet defines basic packet types including Interest and Data, as well the all important Name.

Now we have packets, we can send and receive them via Transport types:

  • @ndn/node-transport implement transports for Node.
  • @ndn/ws-transport implements a WebSockets transport that works in both Node and browser.
  • Each transport has a pair of async iterables for RX and TX, which receives and transmits TLV elements. I chose async iterables over Node Streams, because it's just as powerful in processing infinite streams, while avoids a heavy dependency on readable-stream.
  • @ndn/l3face wraps a transport into a network layer face, which offers async iterables of Interest/Data packets.

With the ability of sending and receiving packets, we can get to the core:

  • @ndn/fw implements the forwarding plane.
  • The README of that package explains why we need a forwarding plane in the application.
  • Yes, I learned this from NDN-Lite.

If you are writing applications, you'll probably start here:

  • @ndn/endpoint implements Endpoint type, which allows you to express an Interest, or become a producer under a name prefix. This is usually called "face" in other libraries, but we have so much more, so that I think it deserves a different name.
  • @ndn/keychain provides crypto features.

Going a little higher layer:

  • @ndn/segmented-object helps with a common use case of segmenting a large object into right-sized Data packets.
  • @ndn/autoconfig establishes connectivity to the global NDN testbed.
  • @ndn/nfdmgmt allows prefix registration on the NDN Forwarding Daemon (NFD). Currently prefix registration (some of them in @ndn/fw) lacks error recovery; this will be improved in the future.

Finally, there are several command line tools that serve as examples of how APIs can be used in Node:

  • @ndn/cat is netcat for NDN. It demonstrates how to use @ndn/segmented-object to transfer a file.
  • @ndn/keychain-cli is a command line utility to access the @ndn/keychain. Apart from basic features, it can import keys from ndn-cxx KeyChain, or request certificates from NDNCERT Certificate Authority.

The best, however, is the ndn package. It distills the essence of NDN into one emoji. I'm not going to explain, and you just have to see it yourself.

How to Get Started

You'll need a TypeScript or JavaScript web application starter template with a module bundler such as webpack. While I don't have an official "NDNts starter template", you can reference my online demos listed on NDNts homepage.

Then, install relevant NDNts packages via NPM or nightly build, and you can start coding.

Thanks and good luck!