# Librecast - Distributed Applications with IPv6 Multicast

![Librecast Logo](https://www.librecast.net/media/librecast-logo_dark.svg)

## README

Librecast is a project to provide fast, efficient and scalable
communication by leveraging IPv6 multicast.

NB: the database functions have been removed from this branch pending a complete
rewrite as part of the next milestone.

Features:
 * IPv6 and multicast supported from the outset
 * light, fast and simple design
 * scalability a design consideration from the outset

There are separate headers and shared libraries for:
 * IPv6 Multicast messaging
 * local database commands and querying
 * remote (multicast) database commands

The library will be extended soon to provide transitional support and tunnelling
such that multicast can function as an overlay network until native multicast
becomes more widely available.

Comments, questions, suggestions, bug reports, and patches welcome.  See CONTRIBUTING.md

Brett Sheffield `<brett@librecast.net>`

### License

This work is dual-licensed under GPL 2.0 and GPL 3.0.

`SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only`

### Website

https://librecast.net/


### IRC channel

`#librecast` on irc.libera.chat

If you have a question, please be patient. An answer might take a few hours
depending on time zones and whether anyone on the team is available at that
moment.  Feel free to raise an issue on the bug tracker.


### Documentation

You can probably figure most things out by looking at the tests and header
files.  There are code samples in `test/` that will show you how to do the most
common things.

Remember to link your program with `-llibrecast`.  If you're using `librecast/db.h` and `librecast/netdb.h` you'll also need `-llsdb` and `-llcdb` respectively.

Lets run through the basic concepts:


#### Getting started

In C, we'll need a header.  Just the first one will do:
```
#include <librecast.h>        /* include all functions */

/* or */

#include <librecast/net.h>    /* just the network (multicast) bits */
#include <librecast/db.h>     /* local database functions */
#include <librecast/netdb.h>  /* remote (multicast) database functions */

/* or, if you just need to refer to a Librecast type in another project */

#include <librecast/types.h>  /* Librecast type declarations */

```

Everything starts with a Librecast Context:

```
lc_ctx_t *lctx;
lctx = lc_ctx_new();

lc_ctx_free(lctx); /* free it when done */
```

Then you probably want a Librecast Socket:
```
lc_socket_t *sock;
sock = lc_socket_new(lctx);

/* you can set whatever underlying socket options you want, such as TTL and LOOPBACK */
/* if you want to receive your own packets, you'll need this: */
lc_socket_setopt(sock, IPV6_MULTICAST_LOOP, &opt, sizeof(opt);

lc_socket_close(sock); /* close this when done */
```

Sockets aren't much use without Channels.  A Channel, in Librecast terms,
represents a multicast group.  You create channels, bind them to sockets, and
join those channels.

```
lc_channel_t *chan;
chan = lc_channel_new(lctx, "example.com");

lc_channel_bind(sock, chan)  /* bind the channel to a socket */
lc_channel_bind(sock, chan2) /* you can bind more than one */

lc_channel_join(chan) /* we need to join a channel if we want to listen */
/* no need to join if we only want to send */

lc_channel_free(chan); /* free when done */
```

To listen on a channel and process messages, we can either use a synchronous
call, or asyncronous with callbacks:

```
void callback_msg(lc_message_t *msg) {
	/* do something with message */
}

void callback_err() {
	/* handle error */
}

/* this starts a listening thread, with callbacks */
lc_socket_listen(sock, callback_msg, callback_err);

/* or, we can do a blocking recv */
size_t bytes = lc_msg_recv(sock, &msg);     /* blocking recv */

```

Now lets create a message and send it:

```
char data[] = "life, the universe, everything";
lc_message_t msg;
lc_msg_init_data(&msg, data, strlen(data), NULL, NULL);
lc_msg_send(chan, &msg);
```


### Installing

See INSTALL.md


### Compilation and Testing Options

The code compiles using either gcc or clang.  There is a `make clang` target.
The default is whatever your default CC is.

NB: Gnu Make is required. On *BSD install and use gmake. The bash shell is also required for `make test
`.

#### Testing
A test runner and a set of test modules exercise the main functions, including
common error conditions.

Logs are output in the test directory (the tests tell you where).
`test/lastlog.log` is a symlink to the logs from the last test run.

`make test` runs all tests.
`make memcheck` runs all tests using valgrind to do leak checking and dynamic
analysis.

Other useful make targets:

`make test/0004` run a single test.

`make memcheck/0004` run a single test with valgrind

`make sparse` compiles the project using cgcc (the sparse static analyser)

`make clang` builds the project using clang

`make coverity` builds the project using the coverity static analyser, creating
a librecast.tgz ready to upload to Coverity Scan for analysis.

`make net-setup` create a virtual pair of connected network interfaces in their
own namespaces for testing. (requires CAP_NET_ADMIN / root)

`make net-teardown` undoes `make net-setup` (requires CAP_NET_ADMIN / root)

`make testshell` remind me what to type to enter a test shell in the correct
namespace

## Questions, Bug reports, Feature Requests

New issues can be raised at:

https://todo.sr.ht/~librecast/librecast

It's okay to raise an issue to ask a question.  You can also email or ask on
IRC.

This project was funded through the NGI0 Discovery (https://nlnet.nl/discovery) and NGI Assure (https://nlnet.nl/assure) Funds, established by NLnet with financial support from the European
Commission's Next Generation Internet (https://ngi.eu) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreements 825322 and 957073. *Applications are still open, you can apply today (https://nlnet.nl/propose)*

