Encode Recode Decode SimpleΒΆ

This example shows how to use one encoder and two decoders to simulate a simple relay network where the first decoder sends recoded packets to the second decoder.

The complete example code is shown below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
// Copyright Steinwurf ApS 2011.
// Distributed under the "STEINWURF EVALUATION LICENSE 1.0".
// See accompanying file LICENSE.rst or
// http://www.steinwurf.com/licensing

/// @example encode_recode_decode_simple.cpp
///
/// In Network Coding applications one of the key features is the
/// ability of intermediate nodes in the network to recode packets
/// as they traverse them. In Kodo we both have decoders which can act as
/// recoders, and pure recoders which can only be used for recoding.
///
/// This example shows how to use one encoder and two decoders to
/// simulate a simple relay network as shown below (for simplicity
/// we have error free links, i.e. no data packets are lost when being
/// sent from encoder to decoder_1 or from decoder_1 to decoder_2):
///
///         +-----------+      +-----------+      +------------+
///         |  encoder  |+---->| decoder_1 |+---->|  decoder_2 |
///         +-----------+      | (recoder) |      +------------+
///                            +-----------+
///
/// In a practical application recoding can be used in several different
/// ways. One must consider several different factors, such as
/// reducing linear dependency by coordinating several recoding nodes
/// in the network.
/// Suggestions for dealing with such issues can be found in current
/// research literature (e.g. MORE: A Network Coding Approach to
/// Opportunistic Routing).

#include <cassert>
#include <iostream>
#include <vector>

#include <kodo_rlnc/coders.hpp>

int main()
{
    // Set the number of symbols (i.e. the generation size in RLNC
    // terminology) and the size of a symbol in bytes
    uint32_t symbols = 42;
    uint32_t symbol_size = 160;
    fifi::api::field field = fifi::api::field::binary8;

    // Typdefs for the encoder/decoder type we wish to use
    using rlnc_encoder = kodo_rlnc::encoder;
    using rlnc_decoder = kodo_rlnc::decoder;

    // In the following we will make an encoder/decoder factory.
    // The factories are used to build actual encoders/decoders
    rlnc_encoder::factory encoder_factory(field, symbols, symbol_size);
    auto encoder = encoder_factory.build();

    rlnc_decoder::factory decoder_factory(field, symbols, symbol_size);
    auto decoder_1 = decoder_factory.build();
    auto decoder_2 = decoder_factory.build();

    // Allocate some storage for a "payload" the payload is what we would
    // eventually send over a network
    std::vector<uint8_t> payload(decoder_1->payload_size());

    // Allocate some data to encode. In this case we make a buffer
    // with the same size as the encoder's block size (the max.
    // amount a single encoder can encode)
    std::vector<uint8_t> data_in(encoder->block_size());

    // Just for fun - fill the data with random data
    std::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 it
    encoder->set_const_symbols(storage::storage(data_in));

    // Define data buffers where the symbols should be decoded
    std::vector<uint8_t> data_out_1(decoder_1->block_size());
    std::vector<uint8_t> data_out_2(decoder_2->block_size());

    decoder_1->set_mutable_symbols(storage::storage(data_out_1));
    decoder_2->set_mutable_symbols(storage::storage(data_out_2));

    while (!decoder_2->is_complete())
    {
        // Encode a packet into the payload buffer
        encoder->write_payload(payload.data());

        // Pass that packet to decoder_1
        decoder_1->read_payload(payload.data());

        // Now produce a new recoded packet from the current
        // decoding buffer, and place it into the payload buffer
        decoder_1->write_payload(payload.data());

        // Pass the recoded packet to decoder_2
        decoder_2->read_payload(payload.data());
    }

    // Check if we properly decoded the data
    if (std::equal(data_out_1.begin(), data_out_1.end(), data_in.begin()) &&
        std::equal(data_out_2.begin(), data_out_2.end(), data_in.begin()))
    {
        std::cout << "Data decoded correctly" << std::endl;
    }
    else
    {
        std::cout << "Unexpected failure to decode "
                  << "please file a bug report :)" << std::endl;
    }
}