Пример #1
0
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;
}
Пример #2
0
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);
}
Пример #3
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);
}