static void test_encoder_factory(uint32_t max_symbols, uint32_t max_symbol_size, int32_t codec, int32_t finite_field) { kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); // Test the max_* properties EXPECT_EQ(max_symbols, kodoc_factory_max_symbols(encoder_factory)); EXPECT_EQ(max_symbol_size, kodoc_factory_max_symbol_size(encoder_factory)); EXPECT_EQ(max_symbol_size * max_symbols, kodoc_factory_max_block_size(encoder_factory)); EXPECT_GT(kodoc_factory_max_payload_size(encoder_factory), max_symbol_size); // Build an encoder with the default settings kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); EXPECT_EQ(max_symbols, kodoc_symbols(encoder)); EXPECT_EQ(max_symbol_size, kodoc_symbol_size(encoder)); // Lower the number of symbols and the symbol_size uint32_t new_symbols = max_symbols / 2; kodoc_factory_set_symbols(encoder_factory, new_symbols); uint32_t new_symbol_size = max_symbol_size - 4; kodoc_factory_set_symbol_size(encoder_factory, new_symbol_size); // Test that the max_* properties are not changed EXPECT_EQ(max_symbols, kodoc_factory_max_symbols(encoder_factory)); EXPECT_EQ(max_symbol_size, kodoc_factory_max_symbol_size(encoder_factory)); EXPECT_EQ(max_symbol_size * max_symbols, kodoc_factory_max_block_size(encoder_factory)); EXPECT_GT(kodoc_factory_max_payload_size(encoder_factory), max_symbol_size); // Build an encoder with the changed settings kodoc_coder_t encoder2 = kodoc_factory_build_coder(encoder_factory); EXPECT_EQ(new_symbols, kodoc_symbols(encoder2)); EXPECT_EQ(new_symbol_size, kodoc_symbol_size(encoder2)); kodoc_delete_coder(encoder); kodoc_delete_coder(encoder2); kodoc_delete_factory(encoder_factory); }
static void test_decoder(uint32_t symbols, uint32_t symbol_size, int32_t codec, int32_t finite_field) { kodoc_factory_t decoder_factory = kodoc_new_decoder_factory( codec, finite_field, symbols, symbol_size); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // Coder methods test_coder(decoder, symbols, symbol_size, codec); // Decoder methods // Some codecs do not provide write_payload, i.e. recoding if (codec == kodoc_seed || codec == kodoc_sparse_seed || codec == kodoc_fulcrum || codec == kodoc_reed_solomon) { EXPECT_TRUE(kodoc_has_write_payload(decoder) == 0); } else { EXPECT_TRUE(kodoc_has_write_payload(decoder) != 0); } EXPECT_EQ(0U, kodoc_symbols_uncoded(decoder)); EXPECT_EQ(0U, kodoc_symbols_partially_decoded(decoder)); if (codec == kodoc_on_the_fly || codec == kodoc_sliding_window) { EXPECT_TRUE(kodoc_has_partial_decoding_interface(decoder) != 0); } else if (codec == kodoc_full_vector) { EXPECT_TRUE(kodoc_has_partial_decoding_interface(decoder) == 0); } kodoc_delete_coder(decoder); kodoc_delete_factory(decoder_factory); }
inline void test_decoder_symbol_status_api(int32_t decoder_type) { uint32_t symbols = 4; uint32_t symbol_size = 40; kodoc_factory_t decoder_factory = kodoc_new_decoder_factory( decoder_type, kodoc_binary8, symbols, symbol_size); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); std::vector<uint8_t> data_out(kodoc_block_size(decoder), '\0'); kodoc_set_mutable_symbols(decoder, data_out.data(), data_out.size()); std::vector<uint8_t> symbol(kodoc_symbol_size(decoder)); std::vector<uint8_t> coefficients(kodoc_coefficient_vector_size(decoder)); coefficients = {1, 0, 0, 0}; kodoc_read_symbol(decoder, symbol.data(), coefficients.data()); EXPECT_EQ(0U, kodoc_symbols_uncoded(decoder)); kodoc_update_symbol_status(decoder); EXPECT_EQ(1U, kodoc_symbols_uncoded(decoder)); kodoc_set_status_updater_on(decoder); coefficients = {0, 1, 0, 0}; kodoc_read_symbol(decoder, symbol.data(), coefficients.data()); EXPECT_EQ(2U, kodoc_symbols_uncoded(decoder)); kodoc_set_status_updater_off(decoder); kodoc_delete_coder(decoder); kodoc_delete_factory(decoder_factory); }
int main() { // Seed the random number generator to produce different data every time srand(time(NULL)); // Set the number of symbols and the symbol size uint32_t max_symbols = 10; uint32_t max_symbol_size = 100; // Here we select the codec we wish to use int32_t codec = kodoc_reed_solomon; // Here we select the finite field to use. // For the Reed-Solomon codec, we need to choose kodoc_binary8 int32_t finite_field = kodoc_binary8; kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // Allocate some storage for a "payload". The payload is what we would // eventually send over a network. uint32_t bytes_used; uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); // Allocate input and output data buffers uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); // Fill the input buffer with random data uint32_t i = 0; for(; i < block_size; ++i) data_in[i] = rand() % 256; // Assign the data buffers to the encoder and decoder kodoc_set_const_symbols(encoder, data_in, block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); // Install a custom trace function for the decoder kodoc_set_trace_callback(decoder, trace_callback, NULL); uint32_t lost_payloads = 0; uint32_t received_payloads = 0; while (!kodoc_is_complete(decoder)) { // The encoder will use a certain amount of bytes of the payload buffer bytes_used = kodoc_write_payload(encoder, payload); printf("Payload generated by encoder, bytes used = %d\n", bytes_used); // Simulate a channel with a 50% loss rate if (rand() % 2) { lost_payloads++; printf("Symbol lost on channel\n\n"); continue; } // Pass the generated packet to the decoder received_payloads++; kodoc_read_payload(decoder, payload); printf("Payload processed by decoder, current rank = %d\n\n", kodoc_rank(decoder)); } printf("Number of lost payloads: %d\n", lost_payloads); printf("Number of received payloads: %d\n", received_payloads); // Check that we properly decoded the data if (memcmp(data_in, data_out, block_size) == 0) { printf("Data decoded correctly\n"); } else { printf("Unexpected failure to decode, please file a bug report :)\n"); } // Free the allocated buffers and the kodo objects free(data_in); free(data_out); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return 0; }
inline void run_test_basic_api(int32_t encoder_type, int32_t decoder_type, int32_t finite_field, uint32_t symbols, uint32_t symbol_size) { kodoc_factory_t encoder_factory = kodoc_new_encoder_factory( encoder_type, finite_field, symbols, symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory( decoder_type, finite_field, symbols, symbol_size); kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); EXPECT_EQ(symbols, kodoc_factory_max_symbols(encoder_factory)); EXPECT_EQ(symbol_size, kodoc_factory_max_symbol_size(encoder_factory)); EXPECT_EQ(symbols, kodoc_symbols(encoder)); EXPECT_EQ(symbol_size, kodoc_symbol_size(encoder)); EXPECT_EQ(symbols, kodoc_factory_max_symbols(decoder_factory)); EXPECT_EQ(symbol_size, kodoc_factory_max_symbol_size(decoder_factory)); EXPECT_EQ(symbols, kodoc_symbols(decoder)); EXPECT_EQ(symbol_size, kodoc_symbol_size(decoder)); EXPECT_EQ(symbols * symbol_size, kodoc_block_size(encoder)); EXPECT_EQ(symbols * symbol_size, kodoc_block_size(decoder)); EXPECT_TRUE(kodoc_factory_max_payload_size(encoder_factory) >= kodoc_payload_size(encoder)); EXPECT_TRUE(kodoc_factory_max_payload_size(decoder_factory) >= kodoc_payload_size(decoder)); EXPECT_EQ(kodoc_factory_max_payload_size(encoder_factory), kodoc_factory_max_payload_size(decoder_factory)); if (encoder_type == kodoc_sparse_full_vector || encoder_type == kodoc_sparse_seed) { // Set the coding vector density on the encoder kodoc_set_density(encoder, 0.2); EXPECT_EQ(0.2, kodoc_density(encoder)); } uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); uint8_t** input_symbols = NULL; uint8_t** output_symbols = NULL; // Allocate symbols in non-contiguous buffers input_symbols = (uint8_t**) malloc(symbols * sizeof(uint8_t*)); output_symbols = (uint8_t**) malloc(symbols * sizeof(uint8_t*)); for (uint32_t i = 0; i < symbols; ++i) { // Create the individual symbols for the encoder input_symbols[i] = (uint8_t*) malloc(symbol_size); // Randomize input data for (uint32_t j = 0; j < symbol_size; ++j) input_symbols[i][j] = rand() % 256; // Store the symbol pointer in the encoder kodoc_set_const_symbol(encoder, i, input_symbols[i], symbol_size); // Create the output symbol buffers for the decoder output_symbols[i] = (uint8_t*) malloc(symbol_size); // Specify the output buffers used for decoding kodoc_set_mutable_symbol(decoder, i, output_symbols[i], symbol_size); } if (kodoc_has_symbol_decoding_status_updater_interface(decoder)) { EXPECT_FALSE(kodoc_is_status_updater_enabled(decoder)); kodoc_set_status_updater_on(decoder); EXPECT_TRUE(kodoc_is_status_updater_enabled(decoder)); kodoc_set_status_updater_off(decoder); EXPECT_FALSE(kodoc_is_status_updater_enabled(decoder)); } else { EXPECT_TRUE( decoder_type == kodoc_fulcrum || decoder_type == kodoc_reed_solomon ); } EXPECT_TRUE(kodoc_is_complete(decoder) == 0); while (!kodoc_is_complete(decoder)) { kodoc_write_payload(encoder, payload); kodoc_read_payload(decoder, payload); } EXPECT_TRUE(kodoc_is_complete(decoder) != 0); EXPECT_EQ(symbols, kodoc_rank(decoder)); EXPECT_EQ(symbols, kodoc_symbols_uncoded(decoder)); EXPECT_EQ(0U, kodoc_symbols_partially_decoded(decoder)); EXPECT_EQ(0U, kodoc_symbols_missing(decoder)); assert(input_symbols); assert(output_symbols); // Compare the input and output symbols one-by-one for (uint32_t i = 0; i < symbols; ++i) { EXPECT_EQ(memcmp(input_symbols[i], output_symbols[i], symbol_size), 0); free(input_symbols[i]); free(output_symbols[i]); } free(input_symbols); free(output_symbols); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); }
int main() { // Seed random number generator to produce different results every time srand(time(NULL)); // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint8_t max_symbols = 10; uint8_t max_symbol_size = 100; int32_t codec = kodoc_full_vector; int32_t finite_field = kodoc_binary8; // In the following we will make an encoder/decoder factory. // The factories are used to build actual encoders/decoder kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(codec, finite_field, max_symbols, max_symbol_size); // If we wanted to build an encoder or decoder with a smaller number of // symbols or a different symbol size, then this can be adjusted using the // following functions: // kodoc_factory_set_symbols(...) // kodoc_factory_set_symbol_size(...) // We cannot exceed the maximum values which was used when building // the factory. kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // Allocate some storage for a "payload" the payload is what we would // eventually send over a network uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(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) uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); // Just for fun - fill the data with random data uint32_t i = 0; for (; i < block_size; ++i) { data_in[i] = rand() % 256; } kodoc_set_const_symbols(encoder, data_in, block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); printf("Starting encoding / decoding\n"); while (!kodoc_is_complete(decoder)) { // If the chosen codec stack supports systematic coding if (kodoc_has_systematic_interface(encoder)) { // With 50% probability toggle systematic if ((rand() % 2) == 0) { if (kodoc_is_systematic_on(encoder)) { printf("Turning systematic OFF\n"); kodoc_set_systematic_off(encoder); } else { printf("Turn systematic ON\n"); kodoc_set_systematic_on(encoder); } } } // Encode a packet into the payload buffer kodoc_write_payload(encoder, payload); if ((rand() % 2) == 0) { printf("Drop packet\n"); continue; } // Pass that packet to the decoder kodoc_read_payload(decoder, payload); printf("Rank of decoder %d\n", kodoc_rank(decoder)); // Symbols that were received in the systematic phase correspond // to the original source symbols and are therefore marked as // decoded printf("Symbols decoded %d\n", kodoc_symbols_uncoded(decoder)); } if (memcmp(data_in, data_out, block_size) == 0) { printf("Data decoded correctly\n"); } else { printf("Unexpected failure to decode, please file a bug report :)\n"); } free(data_in); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return 0; }
int main() { // Seed the random number generator to produce different data every time srand(time(NULL)); // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint32_t max_symbols = 10; uint32_t max_symbol_size = 100; // Here we select the codec we wish to use int32_t codec = kodoc_full_vector; // Here we select the finite field to use. // Some common choices are: kodoc_binary, kodoc_binary4, kodoc_binary8 int32_t finite_field = kodoc_binary; // First, we create an encoder & decoder factory. // The factories are used to build actual encoders/decoders kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(codec, finite_field, max_symbols, max_symbol_size); // If we wanted to build an encoder or decoder with a smaller number of // symbols or a different symbol size, then this can be adjusted using the // following functions: // kodoc_factory_set_symbols(...) and kodoc_factory_set_symbol_size(...) // We can however not exceed the maximum values that were used when // creating the factory. kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); uint32_t bytes_used; uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); uint32_t i = 0; for(; i < block_size; ++i) data_in[i] = rand() % 256; kodoc_set_const_symbols(encoder, data_in, block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); // Most of the network coding algorithms supports a mode of operation // which is known as systematic coding. This basically means that // initially all symbols are sent once un-coded. The rational behind this // is that if no errors occur during the transmission we will not have // performed any unnecessary coding operations. An encoder will exit the // systematic phase automatically once all symbols have been sent un-coded // once. // // With Kodo we can ask an encoder whether it supports systematic encoding // or not using the following functions: if (kodoc_is_systematic_on(encoder)) { printf("Systematic encoding enabled\n"); } else { printf("Systematic encoding disabled\n"); } // If we do not wish to use systematic encoding, but to do full coding // from the beginning we can turn systematic coding off using the following // API: // // if (kodoc_has_set_systematic_off(encoder)) // { // kodoc_set_systematic_off(encoder); // } // Install a custom trace function for the decoder kodoc_set_trace_callback(decoder, trace_callback, NULL); while (!kodoc_is_complete(decoder)) { // The encoder will use a certain amount of bytes of the payload // buffer. It will never use more than payload_size, but it might // use less. bytes_used = kodoc_write_payload(encoder, payload); printf("Payload generated by encoder, rank = %d, bytes used = %d\n", kodoc_rank(encoder), bytes_used); // Pass the generated packet to the decoder kodoc_read_payload(decoder, payload); printf("Payload processed by decoder, current rank = %d\n", kodoc_rank(decoder)); } if (memcmp(data_in, data_out, block_size) == 0) { printf("Data decoded correctly\n"); } else { printf("Unexpected failure to decode, please file a bug report :)\n"); } free(data_in); free(data_out); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return 0; }
int main() { // Seed random number generator to produce different results every time srand(time(NULL)); // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint8_t max_symbols = 6; uint8_t max_symbol_size = 100; int32_t codec = kodoc_sliding_window; int32_t finite_field = kodoc_binary8; // In the following we will make an encoder/decoder factory. // The factories are used to build actual encoders/decoders kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(codec, finite_field, max_symbols, max_symbol_size); // If we wanted to build an encoder or decoder with a smaller number of // symbols or a different symbol size, then this can be adjusted using the // following functions: // kodoc_factory_set_symbols(...) // kodoc_factory_set_symbol_size(...) // We cannot exceed the maximum values which was used when building // the factory. kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // Allocate some storage for a "payload" the payload is what we would // eventually send over a network uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(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) uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); uint8_t feedback_size = (uint8_t) kodoc_feedback_size(encoder); uint8_t* feedback = (uint8_t*) malloc(feedback_size); uint32_t i = 0; //Just for fun - fill data_in with random data for (; i < block_size; ++i) { data_in[i] = rand() % 256; } // Install a custom trace function for the decoder kodoc_set_trace_callback(decoder, trace_callback, NULL); while (!kodoc_is_complete(decoder)) { // Insert a new symbol until the encoder is full if (kodoc_rank(encoder) < max_symbols) { uint32_t rank = kodoc_rank(encoder); uint8_t* symbol = data_in + (rank * max_symbol_size); kodoc_set_const_symbol(encoder, rank, symbol, max_symbol_size); printf("Symbol %d added to the encoder\n", rank); } // Only send packets if the encoder has more data than the decoder if (kodoc_rank(encoder) == kodoc_rank(decoder)) { continue; } // Write an encoded packet into the payload buffer kodoc_write_payload(encoder, payload); printf("Encoded packet generated\n"); // Here we simulate that we are losing 50% of the packets if (rand() % 2) { printf("Packet dropped on channel\n\n"); continue; } printf("Decoder received packet\n"); // Packet got through - pass that packet to the decoder kodoc_read_payload(decoder, payload); printf("Encoder rank = %d\n", kodoc_rank(encoder)); printf("Decoder rank = %d\n", kodoc_rank(decoder)); printf("Decoder uncoded = %d\n", kodoc_symbols_uncoded(decoder)); printf("Decoder partially decoded = %d\n", kodoc_symbols_partially_decoded(decoder)); // Transmit the feedback kodoc_write_feedback(decoder, feedback); // Note that the feedback packets can also be lost in a real network, // but here we deliver all of them for the sake of simplicity printf("Received feedback from decoder\n\n"); kodoc_read_feedback(encoder, feedback); } if (memcmp(data_in, data_out, block_size) == 0) { printf("Data decoded correctly\n"); } else { printf("Unexpected failure to decode, please file a bug report :)\n"); } free(data_in); free(data_out); free(payload); free(feedback); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return 0; }
JNIEXPORT jboolean JNICALL Java_com_steinwurf_dummy_1android_MainActivity_runKodo( JNIEnv* env, jobject thiz) { // Seed random number generator to produce different results every time srand(time(NULL)); // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint32_t max_symbols = 42; uint32_t max_symbol_size = 160; // Select the coding to use int32_t code_type = kodoc_full_vector; // Select the finite field int32_t finite_field = kodoc_binary; // Create the factories kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(code_type, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(code_type, finite_field, max_symbols, max_symbol_size); // Create the coders kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // Generate the data uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint32_t i = 0; for (; i < block_size; ++i) data_in[i] = rand() % 256; // Set the date to encode kodoc_set_const_symbols(encoder, data_in, block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); // Run the decoding while (!kodoc_is_complete(decoder)) { kodoc_write_payload(encoder, payload); kodoc_read_payload(decoder, payload); } // Check if the decoding was successful bool success = false; if (memcmp(data_in, data_out, block_size) == 0) success = true; // Clean up free(data_in); free(data_out); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return success; }
void test_sliding_window(uint32_t max_symbols, uint32_t max_symbol_size, int32_t finite_field) { kodoc_factory_t encoder_factory = kodoc_new_encoder_factory( kodoc_sliding_window, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory( kodoc_sliding_window, finite_field, max_symbols, max_symbol_size); kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); EXPECT_EQ(max_symbols,kodoc_factory_max_symbols(encoder_factory)); EXPECT_EQ(max_symbol_size,kodoc_factory_max_symbol_size(encoder_factory)); EXPECT_EQ(max_symbols, kodoc_symbols(encoder)); EXPECT_EQ(max_symbol_size,kodoc_symbol_size(encoder)); EXPECT_EQ(max_symbols, kodoc_factory_max_symbols(decoder_factory)); EXPECT_EQ(max_symbol_size, kodoc_factory_max_symbol_size(decoder_factory)); EXPECT_EQ(max_symbols, kodoc_symbols(decoder)); EXPECT_EQ(max_symbol_size, kodoc_symbol_size(decoder)); EXPECT_EQ(max_symbols * max_symbol_size, kodoc_block_size(encoder)); EXPECT_EQ(max_symbols * max_symbol_size, kodoc_block_size(decoder)); EXPECT_TRUE(kodoc_factory_max_payload_size(encoder_factory) >= kodoc_payload_size(encoder)); EXPECT_TRUE(kodoc_factory_max_payload_size(decoder_factory) >= kodoc_payload_size(decoder)); EXPECT_EQ(kodoc_factory_max_payload_size(encoder_factory), kodoc_factory_max_payload_size(decoder_factory)); uint32_t feedback_size = 0; EXPECT_EQ(kodoc_feedback_size(encoder), kodoc_feedback_size(decoder)); feedback_size = kodoc_feedback_size(encoder); EXPECT_TRUE(feedback_size > 0); // Allocate some storage for a "payload" the payload is what we would // eventually send over a network uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); uint8_t* feedback = (uint8_t*) malloc(feedback_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) uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); // Just for fun - fill the data with random data for (uint32_t i = 0; i < block_size; ++i) data_in[i] = rand() % 256; // Install a custom trace function for the encoder and decoder kodoc_set_trace_callback(encoder, encoder_trace_callback, NULL); kodoc_set_trace_callback(decoder, decoder_trace_callback, NULL); // Assign the data buffer to the encoder so that we may start // to produce encoded symbols from it kodoc_set_const_symbols(encoder, data_in, block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); EXPECT_TRUE(kodoc_is_complete(decoder) == 0); while (!kodoc_is_complete(decoder)) { // Encode the packet into the payload buffer uint32_t payload_used = kodoc_write_payload(encoder, payload); EXPECT_TRUE(payload_used <= kodoc_payload_size(encoder)); // Pass that packet to the decoder kodoc_read_payload(decoder, payload); // All payloads must be innovative due to the perfect feedback EXPECT_TRUE(kodoc_is_partially_complete(decoder) != 0); kodoc_write_feedback(decoder, feedback); kodoc_read_feedback(encoder, feedback); } EXPECT_TRUE(kodoc_is_complete(decoder) != 0); // Check if we properly decoded the data EXPECT_EQ(memcmp(data_in, data_out, block_size), 0); // Check that the trace functions were called at least once EXPECT_GT(encoder_trace_called, 0U); EXPECT_GT(decoder_trace_called, 0U); free(data_in); free(data_out); free(payload); free(feedback); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); }
int main(int argc, char* argv[]) { // Variables needed for the network / socket usage int32_t socket_descriptor = 0; int32_t return_code = 0; int32_t bytes_received = 0; socklen_t remote_address_size; struct sockaddr_in remote_address; struct sockaddr_in local_address; // Variables needed for the coding uint32_t max_symbols = 32; uint32_t max_symbol_size = 160; uint32_t symbols = 0; int32_t codec = kodoc_on_the_fly; int32_t finite_field = kodoc_binary8; kodoc_factory_t decoder_factory = 0; kodoc_coder_t decoder = 0; // The buffer used to receive incoming packets uint32_t payload_size = 0; uint8_t* payload = 0; // Keeps track of which symbols have been decoded uint8_t* decoded = (uint8_t*) malloc(sizeof(uint8_t) * max_symbols); // Initialize winsock if on Windows #ifdef _WIN32 WORD versionWanted = MAKEWORD(1, 1); WSADATA wsaData; return_code = WSAStartup(versionWanted, &wsaData); if (return_code != 0) { // Tell the user that we could not find a usable // Winsock DLL. printf("WSAStartup failed with error: %d\n", return_code); exit(1); } #endif // Initialize global variables rx_packets = 0; if (argc < 3) { printf("usage : %s <port> <symbols>\n", argv[0]); exit(1); } // Socket creation socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0); if (socket_descriptor < 0) { printf("%s: cannot open socket \n", argv[0]); exit(1); } // Bind local server port local_address.sin_family = AF_INET; local_address.sin_addr.s_addr = htonl(INADDR_ANY); local_address.sin_port = htons(atoi(argv[1])); return_code = bind(socket_descriptor, (struct sockaddr*) &local_address, sizeof(local_address)); if (return_code < 0) { printf("%s: cannot bind port number %d \n", argv[0], atoi(argv[1])); exit(1); } // Install signal handler signal(SIGINT, exit_on_sigint); // Initialize the factory with the chosen symbols and symbol size symbols = atoi(argv[2]); if (symbols > max_symbols) { printf("%s: number of symbols cannot be higher than %d \n", argv[0], max_symbols); exit(1); } // Create the encoder factory decoder_factory = kodoc_new_decoder_factory( codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_set_symbols(decoder_factory, symbols); decoder = kodoc_factory_build_coder(decoder_factory); // Create the buffer needed for the payload payload_size = kodoc_payload_size(decoder); payload = (uint8_t*) malloc(payload_size); uint32_t block_size = kodoc_block_size(decoder); uint8_t* data_out = (uint8_t*) malloc(block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); // Zero initialize the decoded array */ memset(decoded, '\0', sizeof(uint8_t) * max_symbols); printf("%s: waiting for data on UDP port %u\n", argv[0], atoi(argv[1])); // Receiver loop while (!kodoc_is_complete(decoder)) { // Receive message remote_address_size = sizeof(remote_address); bytes_received = recvfrom( socket_descriptor, payload, payload_size, 0, (struct sockaddr*) &remote_address, &remote_address_size); if (bytes_received < 0) { printf("%s: recvfrom error %d\n", argv[0], bytes_received); fflush(stdout); continue; } // Print received message printf("%s: UDP packet from %s:%u : %d\n", argv[0],inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), bytes_received); ++rx_packets; // Packet got through - pass that packet to the decoder kodoc_read_payload(decoder, payload); if (kodoc_has_partial_decoding_interface(decoder) && kodoc_is_partially_complete(decoder)) { uint32_t i = 0; for (; i < kodoc_symbols(decoder); ++i) { if (!kodoc_is_symbol_uncoded(decoder, i)) continue; if (!decoded[i]) { // Update that this symbol now has been decoded, // in a real application we could copy out the symbol // using the kodoc_copy_from_symbol(..) or use the data_out // directly. printf("Symbol %d was decoded\n", i); decoded[i] = 1; } } } } printf("Data decoded!\n"); // Cleanup free(decoded); free(payload); kodoc_delete_coder(decoder); kodoc_delete_factory(decoder_factory); return 0; }
int main() { // Seed random number generator to produce different results every time srand(time(NULL)); // Set the number of symbols (i.e. the generation size in RLNC // terminology) and the size of a symbol in bytes uint32_t max_symbols = 3; uint32_t max_symbol_size = 16; int32_t codec = kodoc_full_vector; int32_t finite_field = kodoc_binary8; // In the following we will make an encoder/decoder factory. // The factories are used to build actual encoders/decoder kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(codec, finite_field, max_symbols, max_symbol_size); // If we wanted to build an encoder or decoder with a smaller number of // symbols or a different symbol size, then this can be adjusted using the // following functions: // kodoc_factory_set_symbols(...) // kodoc_factory_set_symbol_size(...) // We cannot exceed the maximum values which was used when building // the factory. kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // Allocate some storage for a "payload" the payload is what we would // eventually send over a network uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(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) uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); // Just for fun - fill the data with random data uint32_t i = 0; for (; i < block_size; ++i) { data_in[i] = rand() % 256; } // Install the stdout trace function for the encoder (everything will // be printed to stdout without filtering) kodoc_set_trace_stdout(encoder); // Set a custom zone prefix for the encoder (this helps to differentiate // the trace output of the encoder and the decoder) kodoc_set_zone_prefix(encoder, "Encoder"); // Install a custom trace function for the decoder (we can process and // filter the data in our trace callback) kodoc_set_trace_callback(decoder, trace_callback, NULL); // Set a custom zone prefix for the decoder kodoc_set_zone_prefix(decoder, "Decoder"); kodoc_set_const_symbols(encoder, data_in, block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); while (!kodoc_is_complete(decoder)) { kodoc_write_payload(encoder, payload); if ((rand() % 2) == 0) { continue; } kodoc_read_payload(decoder, payload); } if (memcmp(data_in, data_out, block_size) == 0) { printf("Data decoded correctly\n"); } else { printf("Unexpected failure to decode, please file a bug report :)\n"); } free(data_in); free(data_out); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return 0; }
int main() { // Seed the random number generator to produce different data every time srand(time(NULL)); // Set the number of symbols and the symbol size uint32_t max_symbols = 10; uint32_t max_symbol_size = 100; // Here we select the codec we wish to use int32_t codec = kodoc_perpetual; // Here we select the finite field to use. // kodoc_binary8 is common choice for the perpetual codec int32_t finite_field = kodoc_binary8; // First, we create an encoder & decoder factory. // The factories are used to build actual encoders/decoders kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // The perpetual encoder supports three operation modes: // // 1) Random pivot mode (default): // The pivot element is drawn at random // 2) Pseudo-systematic // Pivot elements are generated with indices 0,1,2,...,n // After that, the pivots are drawn at random. // 3) Pre-charging // For the first "width" symbols, the pivot index is 0. After that, /// the pseudo-systematic mode is used. Finally, pivots are drawn at /// random. The resulting indices: 0(width times),1,2,...,n // // The operation mode is set with the following API. // Note that if both pre-charging and pseudo-systematic is enabled, // pre-charging takes precedence. // Enable the pseudo-systematic operation mode - faster kodoc_set_pseudo_systematic(encoder, 1); // Enable the pre-charing operation mode - even faster //kodoc_set_pre_charging(encoder, 1); printf("Pseudo-systematic flag: %d\n", kodoc_pseudo_systematic(encoder)); printf("Pre-charging flag: %d\n", kodoc_pre_charging(encoder)); // The width of the perpetual code can be set either as a number of symbols // using kodoc_set_width(), or as a ratio of the number of symbols using // kodoc_set_width_ratio(). // // The default width is set to 10% of the number of symbols. printf("The width ratio defaults to: %0.2f" " (therefore the calculated width is %d)\n", kodoc_width_ratio(encoder), kodoc_width(encoder)); /// When modifying the width, the width ratio will change as well kodoc_set_width(encoder, 4); printf("The width was set to: %d " " (therefore the calculated width ratio is %0.2f)\n", kodoc_width(encoder), kodoc_width_ratio(encoder)); /// When modifying the width ratio, the width will change as well kodoc_set_width_ratio(encoder, 0.2); printf("The width ratio was set to: %0.2f" " (therefore the calculated width is %d)\n", kodoc_width_ratio(encoder), kodoc_width(encoder)); // Allocate some storage for a "payload". The payload is what we would // eventually send over a network. uint32_t bytes_used; uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); // Allocate input and output data buffers uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); // Fill the input buffer with random data uint32_t i = 0; for (; i < block_size; ++i) data_in[i] = rand() % 256; // Assign the data buffers to the encoder and decoder kodoc_set_const_symbols(encoder, data_in, block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); // Install a custom trace function for the decoder kodoc_set_trace_callback(decoder, trace_callback, NULL); uint32_t lost_payloads = 0; uint32_t received_payloads = 0; while (!kodoc_is_complete(decoder)) { // The encoder will use a certain amount of bytes of the payload buffer bytes_used = kodoc_write_payload(encoder, payload); printf("Payload generated by encoder, bytes used = %d\n", bytes_used); // Simulate a channel with a 50% loss rate if (rand() % 2) { lost_payloads++; printf("Symbol lost on channel\n\n"); continue; } // Pass the generated packet to the decoder received_payloads++; kodoc_read_payload(decoder, payload); printf("Payload processed by decoder, current rank = %d\n\n", kodoc_rank(decoder)); } printf("Number of lost payloads: %d\n", lost_payloads); printf("Number of received payloads: %d\n", received_payloads); // Check that we properly decoded the data if (memcmp(data_in, data_out, block_size) == 0) { printf("Data decoded correctly\n"); } else { printf("Unexpected failure to decode, please file a bug report :)\n"); } // Free the allocated buffers and the kodo objects free(data_in); free(data_out); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return 0; }
int main() { // Seed the random number generator to produce different data every time srand(time(NULL)); // Set the number of symbols and the symbol size uint32_t max_symbols = 10; uint32_t max_symbol_size = 100; // Here we select the codec we wish to use int32_t codec = kodoc_sparse_seed; // Here we select the finite field to use. // For the sparse seed codec, we can choose kodoc_binary, kodoc_binary4 or // kodoc_binary8 (kodoc_binary is recommended for high performance) int32_t finite_field = kodoc_binary8; kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(codec, finite_field, max_symbols, max_symbol_size); kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); // The coding vector density on the encoder is set with // kodoc_set_density(). // Note: the density can be adjusted at any time. This feature can be used // to adapt to changing network conditions. printf("The density defaults to: %0.2f\n", kodoc_density(encoder)); kodoc_set_density(encoder, 0.4); printf("The density was set to: %0.2f\n", kodoc_density(encoder)); // A low density setting can lead to a large number of redundant symbols. // In practice, the value should be tuned to the specific scenario. // Allocate some storage for a "payload". The payload is what we would // eventually send over a network. uint32_t bytes_used; uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); // Allocate input and output data buffers uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); // Fill the input buffer with random data uint32_t i = 0; for(; i < block_size; ++i) data_in[i] = rand() % 256; // Assign the data buffers to the encoder and decoder kodoc_set_const_symbols(encoder, data_in, block_size); kodoc_set_mutable_symbols(decoder, data_out, block_size); // Install a custom trace function for the decoder kodoc_set_trace_callback(decoder, trace_callback, NULL); uint32_t lost_payloads = 0; uint32_t received_payloads = 0; while (!kodoc_is_complete(decoder)) { // The encoder will use a certain amount of bytes of the payload buffer bytes_used = kodoc_write_payload(encoder, payload); printf("Payload generated by encoder, bytes used = %d\n", bytes_used); // Simulate a channel with a 50% loss rate if (rand() % 2) { lost_payloads++; printf("Symbol lost on channel\n\n"); continue; } // Pass the generated packet to the decoder received_payloads++; kodoc_read_payload(decoder, payload); printf("Payload processed by decoder, current rank = %d\n\n", kodoc_rank(decoder)); } printf("Number of lost payloads: %d\n", lost_payloads); printf("Number of received payloads: %d\n", received_payloads); // Check that we properly decoded the data if (memcmp(data_in, data_out, block_size) == 0) { printf("Data decoded correctly\n"); } else { printf("Unexpected failure to decode, please file a bug report :)\n"); } // Free the allocated buffers and the kodo objects free(data_in); free(data_out); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); return 0; }
void test_on_the_fly(uint32_t max_symbols, uint32_t max_symbol_size, int32_t finite_field) { kodoc_factory_t encoder_factory = kodoc_new_encoder_factory( kodoc_on_the_fly, finite_field, max_symbols, max_symbol_size); kodoc_factory_t decoder_factory = kodoc_new_decoder_factory( kodoc_on_the_fly, finite_field, max_symbols, max_symbol_size); kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory); kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory); uint32_t symbol_size = kodoc_symbol_size(encoder); uint32_t payload_size = kodoc_payload_size(encoder); uint8_t* payload = (uint8_t*) malloc(payload_size); uint32_t block_size = kodoc_block_size(encoder); uint8_t* data_in = (uint8_t*) malloc(block_size); uint8_t* data_out = (uint8_t*) malloc(block_size); for (uint32_t i = 0; i < block_size; ++i) data_in[i] = rand() % 256; kodoc_set_mutable_symbols(decoder, data_out, block_size); EXPECT_TRUE(kodoc_is_complete(decoder) == 0); while (!kodoc_is_complete(decoder)) { EXPECT_GE(kodoc_rank(encoder), kodoc_rank(decoder)); // The rank of an encoder indicates how many symbols have been added, // i.e. how many symbols are available for encoding uint32_t encoder_rank = kodoc_rank(encoder); // Randomly choose to add a new symbol (with 50% probability) // if the encoder rank is less than the maximum number of symbols if ((rand() % 2) && encoder_rank < kodoc_symbols(encoder)) { // Calculate the offset to the next symbol to insert uint8_t* symbol = data_in + (encoder_rank * symbol_size); kodoc_set_const_symbol(encoder, encoder_rank, symbol, symbol_size); } // Generate an encoded packet kodoc_write_payload(encoder, payload); // Simulate that 50% of the packets are lost if (rand() % 2) continue; // Packet got through - pass that packet to the decoder kodoc_read_payload(decoder, payload); // Check the decoder rank and symbol counters EXPECT_GE(kodoc_rank(encoder), kodoc_rank(decoder)); EXPECT_GE(kodoc_rank(decoder), kodoc_symbols_uncoded(decoder)); EXPECT_GE(kodoc_rank(decoder), kodoc_symbols_partially_decoded(decoder)); EXPECT_EQ(kodoc_symbols(decoder) - kodoc_rank(decoder), kodoc_symbols_missing(decoder)); // Check the decoder whether it is partially complete // The decoder has to support the partial decoding tracker if (kodoc_has_partial_decoding_interface(decoder) && kodoc_is_partially_complete(decoder)) { for (uint32_t i = 0; i < kodoc_symbols(decoder); ++i) { // Go through all symbols that are already decoded if (kodoc_is_symbol_uncoded(decoder, i)) { // All uncoded symbols must have a pivot EXPECT_TRUE(kodoc_is_symbol_pivot(decoder, i) != 0); // The uncoded symbols cannot be missing EXPECT_TRUE(kodoc_is_symbol_missing(decoder, i) == 0); // The uncoded symbols cannot be partially decoded EXPECT_TRUE( kodoc_is_symbol_partially_decoded(decoder, i) == 0); uint8_t* original = data_in + i * symbol_size; uint8_t* target = data_out + i * symbol_size; // verify the decoded symbol against the original data EXPECT_EQ(memcmp(original, target, symbol_size), 0); } } } } EXPECT_EQ(memcmp(data_in, data_out, block_size), 0); free(data_in); free(data_out); free(payload); kodoc_delete_coder(encoder); kodoc_delete_coder(decoder); kodoc_delete_factory(encoder_factory); kodoc_delete_factory(decoder_factory); }