Skip to content

Writing XIA Applications

Dan Barrett edited this page Mar 21, 2017 · 32 revisions

Table of Contents

XIA Socket API

Similarities To The BSD Socket Library

  • The Xsocket API was designed to be as similar as possible to the Berkley socket library to make porting applications easier. Parameter lists are in almost all instances identical to the corresponding BSD socket API.
  • XIA supports sockets of type SOCK_STREAM, SOCK_DGRAM, and SOCK_RAW.
Differences From BSD Sockets
  • API calls are prefixed with an X (Xbind, Xpoll, etc...)
  • The address family is AF_XIA instead of AF_INET
  • XIA does not have IP addresses or ports. It uses DAGs in their place
  • XIA uses a sockaddr_x structure instead of sockaddr_in to hold addresses
  • XIA provides additional APIs for content management and DAG manipulation

API Documentation

Example Applications

Coding Examples

TODO: put something here!

  • caching

Working With DAGs

XIA uses Directed Acyclic Graphs (DAG)s as network addresses.

Benefits of DAGs:

  • FILL ME IN!!!!
Several APIs are provided for working with DAGs:
  • Xgetaddrinfo() is used to look up DAGs in the name server similar to how standard DNS works. It can also be used to create local DAGs that can be used to bind to sockets.
  • inet_ntop() is used to convert DAGs contained in a sockaddr_x structure into a printable sting in the DAG format.
  • inet pton() is used to convert strings in the DAG, RE, or URL format into a sockaddr_x.
  • The DAG library
    • The Node class is used to manage individual XIDs that make up the nodes in a Graph
    • The Graph class is used to manage DAGs.
Sometimes it's helpful to be able to see a visual representation of a DAG; to this end, we've created a DAG visualization tool. Please note it currently only works with the DAG string format. RE and URL DAGs are not supported. Source code for the DAG visualizer is located in xia-core/tools/visualizations/dagtool.

How to read a DAG

DAG 2 0 - 
AD:24b1979de47c480b786b45f1c57b4d19d2681a25 1 - 
HID:d5b3cf4904b8f8462fbb916ae54ea55ad7fd8836 2 - 
SID:69276369b5dc391ab12895b928cac945fd82a5d2

In this example, the nodes are implicitly ordered:

  • 0 AD:24b1979de47c480b786b45f1c57b4d19d2681a25
  • 1 HID:d5b3cf4904b8f8462fbb916ae54ea55ad7fd8836
  • 2 SID:69276369b5dc391ab12895b928cac945fd82a5d2
The numbers following each XID indicate to which other nodes a node has outgoing edges (in order of priority). The 2 and 0 in the first line are the implicit starting node's outgoing edges. The service ID is the sink node and thus has no outgoing edges (and is not followed by a '-').

When processing this DAG, the first value is 2, if a route to the node 2 (SID) is present the next pointer in the DAG will be advanced to node 2. Because it is the final intent of the DAG, no further processing is necessary.

Otherwise the next edge will be checked which in this case is 0 (AD). If a route to the AD is found the DAG's next pointer is moved to node 0. Processing then continues on the list of edges in node 0.

If no route to the AD is found, the 3rd edge is checked. Because it is a '-' there are no further fallback paths available and the DAG will be treated as non-routable.

DAG Representations

RE Format

The RE format is simple and relatively easy to use but cannot represent all DAGs. Because of this, RE formatted DAGs are input only, there is no code that returns an RE DAG to the user.

An RE string consists of the characters "RE " followed by a chain of XIDs, each of which can optionally have a fallback path from the previous node in the chain to itself. Nodes are separated by spaces and parens are used to mark fallback paths. Open and close parens must have a space on either side. The "start" node is implicit and does not appear in the string. For example:

RE ( AD:24b1979de47c480b786b45f1c57b4d19d2681a25 HID:d5b3cf4904b8f8462fbb916ae54ea55ad7fd8836 ) SID:69276369b5dc391ab12895b928cac945fd82a5d2

DAG Format

The DAG format is capable of encoding arbitrary graphs but is difficult to construct manually. A DAG string is a list of XIDs and their outgoing edges separated by the '-' character; by convention, we use "- \n" as the separator to make DAG strings easier to read when printed. Nodes are implicitly numbered starting from 0. This index is used by other nodes to denote an outgoing edge to a node. A DAG string begins with the characters "DAG " and is followed by the start node's outgoing edges (separated by spaces). This is followed by the list of XIDs and their outgoing edges.

DAG 2 0 - 
AD:24b1979de47c480b786b45f1c57b4d19d2681a25 1 - 
HID:d5b3cf4904b8f8462fbb916ae54ea55ad7fd8836 2 - 
SID:69276369b5dc391ab12895b928cac945fd82a5d2

URL Format

URL formatted DAGs are essentially identical to the DAG format with the newlines stripped out and URL-safe characters replacing spaces and other problematic characters.

http://DAG.2.0.-.AD$24b1979de47c480b786b45f1c57b4d19d2681a25.1.-.HID$d5b3cf4904b8f8462fbb916ae54ea55ad7fd8836.2.-.SID$69276369b5dc391ab12895b928cac945fd82a5d2

Binary Format

Binary DAGs are stored in a sockaddr_x which is laid out as follows:

#define CLICK_XIA_ADDR_MAX_NODES   20
#define CLICK_XIA_XID_ID_LEN       20
#define CLICK_XIA_XID_EDGE_NUM     4

struct click_xia_xid {
    uint32_t type;
    uint8_t id[CLICK_XIA_XID_ID_LEN];
};

struct click_xia_xid_edge
{
    unsigned idx : 7;     /* index of node this edge points to */
    unsigned visited : 1; /* visited edge? */
};

struct click_xia_xid_node {
    click_xia_xid xid;
    click_xia_xid_edge edge[CLICK_XIA_XID_EDGE_NUM];
};

typedef struct click_xia_xid xid_t;
typedef struct click_xia_xid_node node_t;

typedef struct {
    unsigned char s_count;
    node_t        s_addr[CLICK_XIA_ADDR_MAX_NODES];
} x_addr_t;

typedef struct {
	unsigned short sx_family;
	x_addr_t      sx_addr;
} sockaddr_x;

Example DAG Handling Code

Lookup a DAG using the nameserver

#include "Xsocket.h"

    Xgetaddrinfo("test.sample.xia", NULL, NULL, &pai);
    
    sockaddr_x *psa = (sockaddr_x*)pai->ai_addr;

    xia_ntop(AF_XIA, psa, s, sizeof(s));
    printf("DAG retrieved from the name server:\n%s\n", s);

    Xfreeaddrinfo(pai);

Convert a DAG into a string

#include "Xsocket.h"
#include "Dagaddr.hpp"

    char str[1024];
    sockaddr_x addr; // assume addr has been filled in earlier

    // get a string in DAG format
    xia_ntop(AF_XIA, &addr, str, sizeof(str));

    // alternatively use the Graph object
    // if a URL formatted string is required, you must use Graph
    Graph g(&addr);

    printf("DAG format:\n%s\n", g.dag_string().c_str());
    printf("URL format:\n%s\n", g.http_url_string().c_str());

Create and register a DAG from a string

#include "Xsocket.h"

    sockaddr_x sax;
    const char *re = "RE ( AD:24b1979de47c480b786b45f1c57b4d19d2681a25 HID:d5b3cf4904b8f8462fbb916ae54ea55ad7fd8836 ) SID:69276369b5dc391ab12895b928cac945fd82a5d2";

    // convert any RE, DAG, or URL formatted string into a sockaddr_x
    xia_pton(AF_XIA, re, &sax);

    // register the DAG with the nameserver
    XregisterName("test.sample.xia", &sax);

Create a sockaddr_x using XgetAddrinfo

Use Xgetaddrinfo to create a DAG for the local host using the newly created SID. If hints is NULL a simple no fallback DAG will be created. If the hints.ai_flags has XIA_FALLBACK flag is set the returned DAG will have a primary path that goes directly to the SID, and A fallback path that first goes through the AD and HID.

#include "Xsocket.h"
#include "Xkeys.h"

    struct addrinfo hints;
    struct addrinfo *pai;

    // create a unique SID
    XmakeNewSID(sid, sizeof(sid));

    bzero(&hints, sizeof(hints));
    hints.ai_family = AF_XIA;
    hints.ai_flags = XAI_FALLBACK;

    Xgetaddrinfo(NULL, sid, &hints, &pai);

    sockaddr_x *psa = (sockaddr_x*)pai->ai_addr;

    Xfreeaddrinfo(&pai);

Create a DAG by hand

#include "dagaddr.hpp"

    Node src;    // dummy node needed to start a Graph
    Node n_ad("AD:1234567890123456789012345678901234567890");
    Node n_hid("HID:1111111111111111111111111111111111111111");
    Node n_sid("SID:2222222222222222222222222222222222222222");

    // create a simple DAG with no fallbacks
    Graph straight = src * n_ad * n_hid * n_sid;

    // add a fallback path to the DAG

    // now create a DAG that just includes the SID. This is a legal DAG on it's own, 
    // but is not very useful by itself unless the SID is in the routing table
    Graph sidonly = src * n_sid;

    // now put them together to create a DAG with a fallback path
    Graph fallback = sidonly + straight;

    // put the address into a sockaddr_x for use elsewhere
    sockaddr_x addr;
    g.fill_sockaddr(&addr);

The straight DAG

DAG 0 - 
AD:1234567890123456789012345678901234567890 1 - 
HID:1111111111111111111111111111111111111111 2 - 
SID:2222222222222222222222222222222222222222
The fallback DAG
fallback DAG created by hand
DAG 2 0 - 
AD:1234567890123456789012345678901234567890 1 - 
HID:1111111111111111111111111111111111111111 2 - 
SID:2222222222222222222222222222222222222222

See DAGs in Action

The XIA Visualizer client can be used to watch how live traffic is routed across the network indicating which part of the DAG is used at each step of the way.

Clone this wiki locally