One of the key features of RLNC is the ability to recode. Recoding means that
the encoded data is re-encoded. This is very useful in scenarios where the data
is to be transmitted through a chain of nodes. Here the data can be re-encoded
at each node. Examples of such networks include:

Relay networks

P2P networks

multi-path networks

mesh networks.

In this example, a total of three nodes is in the network. At each link a loss
can occur with a 50% chance. The complete example code for this is as follows.

// Copyright Steinwurf ApS 2016.// Distributed under the "STEINWURF EVALUATION LICENSE 1.0".// See accompanying file LICENSE.rst or// http://www.steinwurf.com/licensing#include<cstdint>#include<cstdlib>#include<ctime>#include<algorithm>#include<iostream>#include<vector>#include<kodocpp/kodocpp.hpp>intmain(){// Seed the random number generator to produce different data every timesrand((uint32_t)time(0));// Set the number of symbols (i.e. the generation size in RLNC// terminology) and the size of a symbol in bytesuint32_tmax_symbols=16;uint32_tmax_symbol_size=1400;//! [0]// In the following we will make an encoder/decoder factory.// The factories are used to build actual encoders/decoderskodocpp::encoder_factoryencoder_factory(kodocpp::codec::full_vector,kodocpp::field::binary8,max_symbols,max_symbol_size);kodocpp::encoderencoder=encoder_factory.build();kodocpp::decoder_factorydecoder_factory(kodocpp::codec::full_vector,kodocpp::field::binary8,max_symbols,max_symbol_size);kodocpp::decoderdecoder1=decoder_factory.build();kodocpp::decoderdecoder2=decoder_factory.build();//! [1]std::vector<uint8_t>payload(encoder.payload_size());std::vector<uint8_t>data_in(encoder.block_size());// Just for fun - fill the data with random datastd::generate(data_in.begin(),data_in.end(),rand);// Assign the data buffer to the encoder so that we may start// to produce encoded symbols from itencoder.set_const_symbols(data_in.data(),encoder.block_size());// Create a buffer which will contain the decoded data, and we assign// that buffer to the decoderstd::vector<uint8_t>data_out1(decoder1.block_size());std::vector<uint8_t>data_out2(decoder2.block_size());decoder1.set_mutable_symbols(data_out1.data(),decoder1.block_size());decoder2.set_mutable_symbols(data_out2.data(),decoder2.block_size());uint32_tencoded_count=0;uint32_tdropped_count=0;// We switch any systematic operations off so the encoder produces// coded symbols from the beginningif(encoder.is_systematic_on())encoder.set_systematic_off();//! [2]while(!decoder2.is_complete()){// Encode a packet into the payload bufferencoder.write_payload(payload.data());++encoded_count;if(rand()%2){++dropped_count;}else{// Pass that packet to the decoder1decoder1.read_payload(payload.data());}// Create a recoded packet from decoder1decoder1.write_payload(payload.data());if(rand()%2){++dropped_count;}else{// Pass the recoded packet to decoder twodecoder2.read_payload(payload.data());}}//! [3]std::cout<<"Encoded count = "<<encoded_count<<std::endl;std::cout<<"Dropped count = "<<dropped_count<<std::endl;// Check if we properly decoded the dataif(data_in==data_out2){std::cout<<"Data decoded correctly"<<std::endl;}return0;}

Compared to the basic example, the setup and decoding loop has changed.
In the setup phase two decoders are now created, instead of just one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

// In the following we will make an encoder/decoder factory.// The factories are used to build actual encoders/decoderskodocpp::encoder_factoryencoder_factory(kodocpp::codec::full_vector,kodocpp::field::binary8,max_symbols,max_symbol_size);kodocpp::encoderencoder=encoder_factory.build();kodocpp::decoder_factorydecoder_factory(kodocpp::codec::full_vector,kodocpp::field::binary8,max_symbols,max_symbol_size);kodocpp::decoderdecoder1=decoder_factory.build();kodocpp::decoderdecoder2=decoder_factory.build();

while(!decoder2.is_complete()){// Encode a packet into the payload bufferencoder.write_payload(payload.data());++encoded_count;if(rand()%2){++dropped_count;}else{// Pass that packet to the decoder1decoder1.read_payload(payload.data());}// Create a recoded packet from decoder1decoder1.write_payload(payload.data());if(rand()%2){++dropped_count;}else{// Pass the recoded packet to decoder twodecoder2.read_payload(payload.data());}}

The encoder encodes data which is then “transmitted” to decoder1.
This data is then both decoded and recoded by decoder1. The resulting
recoded data is then finally “transmitted” to decoder2 where it is decoded.
Both the channel from encoder to decoder1 and the channel from
decoder1 to decoder2 is simulated to have a 50% success rate.

In a network without recoding, the overall success rate would be the product of
all the networks success rates, i.e., for this network the success rate would be
50% * 50% = 25%.
When using recoding the overall success rate will be the minimum success rate
for any of the nodes, i.e., 50% in this example.

The output of this example looks like this (the outcome is randomized):