Getting started with the library!

You are interested in adding ROHC capabilities to your application, but you don't know how to proceed, what it would look like and how difficult it is? The explanations below should answer all these questions!

The explanations will be based on a simple application that compresses one single IPv4 packet. Think of it as the 'hello, world!' of the ROHC library.

Table of content:

Library installation

On Linux, you may build and install the library as follow:

$ wget [[see download page for the url]]
$ tar -xJf rohc-X.Y.Z.tar.xz
$ cd rohc-X.Y.Z
$ ./configure --prefix=/usr
$ make all
$ sudo make install

For more detailed instructions and/or other platforms, follow the installation manual.

Preparation

Create a directory for the tutorial. Open a text editor and save an empty file named rohc_hello_world.c.

Add the following code in order to start with a minimal C program skeleton:

  1. #include <stdio.h>  /* for the printf() function */
  2.  
  3. /* The main entry point of the program (arguments are not used) */
  4. int main(int argc, char **argv)
  5. {
  6.    /* print the purpose of the program on the console */
  7.    printf("This program will compress one single IPv4 packet\n");
  8.  
  9.    /* leave the program with a success code */
  10.    return 0;
  11. }

Build the program with GCC:

$ gcc -o rohc_hello_world -Wall rohc_hello_world.c

Run the program:

$ ./rohc_hello_world
This program will compress one single IPv4 packet

OK, we have a little skeleton for our program. Let's continue!

Create one IPv4 packet

Before using the library, wee need to create one IPv4 packet that we could compress in the following steps.

We could capture a packet on a network interface, but it is a little bit too complex for a 'hello, world!'. Instead we are going to build one IPv4 packet manually. Don't be afraid, I'll explain all the actions.

First, we include 2 new headers at the very top of the file: one for the definition of the IPv4 header and one for the memcpy() function.

  1. /* includes required to create a fake IP packet */
  2. #include <netinet/ip.h>     /* for the IPv4 header */
  3. #include <string.h>         /* for strlen() */
  4. #include <rohc/rohc_buf.h>  /* for the rohc_buf_*() functions */

Second, we define 2 constants just after the headers we just included: one for the size of the buffer in which we are going to build the IPv4 packet and one for the text we are going to copy in the IPv4 packet as payload.

  1. /* The size (in bytes) of the buffers used in the program */
  2. #define BUFFER_SIZE 2048
  3.  
  4. /* The payload for the fake IP packet */
  5. #define FAKE_PAYLOAD "hello, ROHC world!"

Third, we update the main() function to create one IPv4 packet (header + payload) and to print it one byte after the other on the console.

  1. /* The main entry point of the program (arguments are not used) */
  2. int main(int argc, char **argv)
  3. {
  4.    /* the buffer that will contain the IPv4 packet to compress */
  5.    uint8_t ip_buffer[BUFFER_SIZE];
  6.    /* the packet that will contain the IPv4 packet to compress */
  7.    struct rohc_buf ip_packet = rohc_buf_init_empty(ip_buffer, BUFFER_SIZE);
  8.    /* the header of the IPv4 packet */
  9.    struct iphdr *ip_header;
  10.    size_t i;
  11.  
  12.    /* print the purpose of the program on the console */
  13.    printf("This program will compress one single IPv4 packet\n");
  14.  
  15.    /* create a fake IP packet for the purpose of this simple program */
  16.    printf("build a fake IP packet\n");
  17.    ip_header = (struct iphdr *) rohc_buf_data(ip_packet);
  18.    ip_header->version = 4; /* we create an IP header version 4 */
  19.    ip_header->ihl = 5; /* min. IPv4 header length (in 32-bit words) */
  20.    ip_packet.len += ip_header->ihl * 4;
  21.    ip_header->tos = 0; /* TOS is not important for the example */
  22.    ip_header->tot_len = htons(ip_packet.len + strlen(FAKE_PAYLOAD));
  23.    ip_header->id = 0; /* ID is not important for the example */
  24.    ip_header->frag_off = 0; /* No packet fragmentation */
  25.    ip_header->ttl = 1; /* TTL is not important for the example */
  26.    ip_header->protocol = 134; /* protocol number */
  27.    ip_header->check = 0x3fa9; /* checksum */
  28.    ip_header->saddr = htonl(0x01020304); /* source address 1.2.3.4 */
  29.    ip_header->daddr = htonl(0x05060708); /* destination addr. 5.6.7.8 */
  30.  
  31.    /* copy the payload just after the IP header */
  32.    rohc_buf_append(&ip_packet, (uint8_t *) FAKE_PAYLOAD, strlen(FAKE_PAYLOAD));
  33.  
  34.    /* dump the newly-created IP packet on terminal */
  35.    for(i = 0; i < ip_packet.len; i++)
  36.    {
  37.       printf("0x%02x ", rohc_buf_byte_at(ip_packet, i));
  38.       if(i != 0 && ((i + 1) % 8) == 0)
  39.       {
  40.          printf("\n");
  41.       }
  42.    }
  43.    if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
  44.    {
  45.      printf("\n");
  46.    }
  47.  
  48.    /* leave the program with a success code */
  49.    return 0;
  50. }

Build the program with GCC:

$ gcc -o rohc_hello_world -Wall rohc_hello_world.c
ccyR1kJ9.o: In function `main':
rohc_hello_world.c:(.text+0x44): undefined reference to `rohc_buf_data'
rohc_hello_world.c:(.text+0x25f): undefined reference to `rohc_buf_append'
collect2: ld returned 1 exit status

It fails because we have to link with the ROHC library for the rohc_buf_*() functions. Try this command instead:

$ gcc -o rohc_hello_world -Wall \
  $(pkg-config rohc --cflags) \
  rohc_hello_world.c \
  $(pkg-config rohc --libs)

Run the program:

$ ./rohc_hello_world
This program will compress one single IPv4 packet
build a fake IP packet
0x45 0x00 0x00 0x26 0x00 0x00 0x00 0x00
0x01 0x86 0xa9 0x3f 0x01 0x02 0x03 0x04
0x05 0x06 0x07 0x08 0x68 0x65 0x6c 0x6c
0x6f 0x2c 0x20 0x52 0x4f 0x48 0x43 0x20
0x77 0x6f 0x72 0x6c 0x64 0x21

OK, we have a fake IPv4 packet to play with. Let's use the ROHC library in our program!

Create a ROHC compressor

In order to compress our IPv4 packet, we need to create a ROHC compressor.

Include the ROHC header for compression and time.h after the existing #include statements:

  1. /* includes required to create a fake IP packet */
  2. #include <netinet/ip.h>     /* for the IPv4 header */
  3. #include <string.h>         /* for strlen() */
  4. #include <rohc/rohc_buf.h>  /* for the rohc_buf_*() functions */
  5.  
  6. /* includes required to use the compression part of the ROHC library */
  7. #include <time.h>             /* required by time() */
  8. #include <rohc/rohc_comp.h>   /* for rohc_comp_*() functions */

Before the main() function, declare a new function that returns a random number:

  1. /* The payload for the fake IP packet */
  2. #define FAKE_PAYLOAD "hello, ROHC world!"
  3.  
  4. /* return a random number every time it is called */
  5. static int gen_random_num(const struct rohc_comp *const comp,
  6.                           void *const user_context)
  7. {
  8.    return rand();
  9. }
  10.  
  11. /* The main entry point of the program (arguments are not used) */
  12. int main(int argc, char **argv)
  13. {

Declare a new variable of type 'struct rohc_comp' for the compressor:

  1. /* The main entry point of the program (arguments are not used) */
  2. int main(int argc, char **argv)
  3. {
  4.    struct rohc_comp *compressor;  /* the ROHC compressor */
  5.  
  6.    /* the buffer that will contain the IPv4 packet to compress */
  7.    uint8_t ip_buffer[BUFFER_SIZE];

We now add a call to the rohc_comp_new2() function to create a compressor. We place it before the code that builds the IPv4 packet.

  1.    /* print the purpose of the program on the console */
  2.    printf("This program will compress one single IPv4 packet\n");
  3.  
  4.    /* initialize the random generator with the current time */
  5.    srand(time(NULL));
  6.  
  7.    /* create a ROHC compressor with good default parameters */
  8.    printf("create the ROHC compressor\n");
  9.    compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX,
  10.                                gen_random_num, NULL);
  11.    if(compressor == NULL)
  12.    {
  13.       fprintf(stderr, "failed create the ROHC compressor\n");
  14.       /* leave with an error code */
  15.       return 1;
  16.    }
  17.  
  18.    /* create a fake IP packet for the purpose of this simple program */
  19.    printf("build a fake IP packet\n");

As we are conscientious developers, we also add at the end of the program a call to the rohc_comp_free() function to release the resources allocated to the compressor.

  1.    /* dump the newly-created IP packet on terminal */
  2.    for(i = 0; i < ip_packet.len; i++)
  3.    {
  4.       printf("0x%02x ", rohc_buf_byte_at(ip_packet, i));
  5.       if(i != 0 && ((i + 1) % 8) == 0)
  6.       {
  7.          printf("\n");
  8.       }
  9.    }
  10.    if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
  11.    {
  12.       printf("\n");
  13.    }
  14.  
  15.    /* release the ROHC compressor when you do not need it anymore */
  16.    printf("destroy the ROHC decompressor\n");
  17.    rohc_comp_free(compressor);
  18.  
  19.    return 0;
  20. }

Build the program with GCC:

$ gcc -o rohc_hello_world -Wall \
  $(pkg-config rohc --cflags) \
  rohc_hello_world.c \
  $(pkg-config rohc --libs)

Now, run the program:

$ ./rohc_hello_world
This program will compress one single IPv4 packet
create the ROHC compressor
build a fake IP packet
0x45 0x00 0x00 0x26 0x00 0x00 0x00 0x00
0x01 0x86 0xa9 0x3f 0x01 0x02 0x03 0x04
0x05 0x06 0x07 0x08 0x68 0x65 0x6c 0x6c
0x6f 0x2c 0x20 0x52 0x4f 0x48 0x43 0x20
0x77 0x6f 0x72 0x6c 0x64 0x21
destroy the ROHC decompressor

OK, we now have a fake IPv4 packet and a ROHC compressor. Let's compress the former with the latter!

Compress the packet

Declare some more variables at the beginning of the main() function: one buffer to store the ROHC packet we are going to generate and one rohc_buf to encapsulate that buffer for the ROHC library.

  1.    /* the buffer that will contain the IPv4 packet to compress */
  2.    uint8_t ip_buffer[BUFFER_SIZE];
  3.    /* the packet that will contain the IPv4 packet to compress */
  4.    struct rohc_buf ip_packet = rohc_buf_init_empty(ip_buffer, BUFFER_SIZE);
  5.    /* the header of the IPv4 packet */
  6.    struct iphdr *ip_header;
  7.  
  8.    /* the buffer that will contain the resulting ROHC packet */
  9.    uint8_t rohc_buffer[BUFFER_SIZE];
  10.    /* the packet that will contain the resulting ROHC packet */
  11.    struct rohc_buf rohc_packet = rohc_buf_init_empty(rohc_buffer, BUFFER_SIZE);
  12.  
  13.    rohc_status_t rohc_status;
  14.    size_t i;
  15.  
  16.    /* print the purpose of the program on the console */
  17.    printf("This program will compress one single IPv4 packet\n");

Now, add a call to the rohc_compress4() function to build a ROHC packet from our IPv4 packet. Add also some code to print the ROHC packet one byte after the other.

  1.    /* dump the newly-created IP packet on terminal */
  2.    for(i = 0; i < ip_packet.len; i++)
  3.    {
  4.       printf("0x%02x ", rohc_buf_byte_at(ip_packet, i));
  5.       if(i != 0 && ((i + 1) % 8) == 0)
  6.       {
  7.          printf("\n");
  8.       }
  9.    }
  10.    if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
  11.    {
  12.       printf("\n");
  13.    }
  14.  
  15.    /* compress the fake IP packet */
  16.    printf("compress the fake IP packet\n");
  17.    rohc_status = rohc_compress4(compressor, ip_packet, &rohc_packet);
  18.    if(rohc_status != ROHC_STATUS_OK)
  19.    {
  20.       fprintf(stderr, "compression of fake IP packet failed: %s (%d)\n",
  21.               rohc_strerror(rohc_status), rohc_status);
  22.       /* cleanup compressor, then leave with an error code */
  23.       rohc_comp_free(compressor);
  24.       return 1;
  25.    }
  26.  
  27.    /* dump the ROHC packet on terminal */
  28.    printf("ROHC packet resulting from the ROHC compression:\n");
  29.    for(i = 0; i < rohc_packet.len; i++)
  30.    {
  31.       printf("0x%02x ", rohc_buf_byte_at(rohc_packet, i));
  32.       if(i != 0 && ((i + 1) % 8) == 0)
  33.       {
  34.          printf("\n");
  35.       }
  36.    }
  37.    if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
  38.    {
  39.       printf("\n");
  40.    }
  41.  
  42.    /* release the ROHC compressor when you do not need it anymore */
  43.    printf("destroy the ROHC decompressor\n");
  44.    rohc_comp_free(compressor);

Build the program with GCC:

$ gcc -o rohc_hello_world -Wall \
  $(pkg-config rohc --cflags) \
  rohc_hello_world.c \
  $(pkg-config rohc --libs)

Now, run the program:

$ ./rohc_hello_world
This program will compress one single IPv4 packet
create the ROHC compressor
build a fake IP packet
0x45 0x00 0x00 0x26 0x00 0x00 0x00 0x00
0x01 0x86 0xa9 0x3f 0x01 0x02 0x03 0x04
0x05 0x06 0x07 0x08 0x68 0x65 0x6c 0x6c
0x6f 0x2c 0x20 0x52 0x4f 0x48 0x43 0x20
0x77 0x6f 0x72 0x6c 0x64 0x21
compress the fake IP packet
[net_pkt.c:75 net_pkt_parse()] outer IP header: 38 bytes
[net_pkt.c:77 net_pkt_parse()] outer IP header: version 1
[rohc_comp.c:4608 c_get_profile_from_packet()] try to find the best profile for packet with transport protocol 0
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/UDP/RTP' (0x0001)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/UDP' (0x0002)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/UDP-Lite' (0x0008)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/ESP' (0x0003)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/TCP' (0x0006)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP-only' (0x0004)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'Uncompressed' (0x0000)
[rohc_comp.c:4808 rohc_comp_find_ctxt()] no profile found for packet, giving up
[rohc_comp.c:1426 rohc_compress4()] failed to find a matching context or to create a new context
compression of fake IP packet failed: undefined problem (6)

The program fails during the compression! The library complains that it cannot find any compression profile to compress the IPv4 packet. It is normal since we forgot to enable the compression profiles we want to use.

Add a call to the rohc_comp_enable_profile() function just after the creation of the ROHC compressor:

  1.    /* Create a ROHC compressor with good default parameters */
  2.    printf("create the ROHC compressor\n");
  3.    compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX,
  4.                                gen_random_num, NULL);
  5.    if(compressor == NULL)
  6.    {
  7.       fprintf(stderr, "failed create the ROHC compressor\n");
  8.       /* leave with an error code */
  9.       return 1;
  10.    }
  11.  
  12.    /* enable the IP-only compression profile */
  13.    printf("enable the IP-only compression profile\n");
  14.    if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_IP))
  15.    {
  16.       fprintf(stderr, "failed to enable the IP-only profile\n");
  17.       /* cleanup compressor, then leave with an error code */
  18.       rohc_comp_free(compressor);
  19.       return 1;
  20.    }
  21.  
  22.    /* create a fake IP packet for the purpose of this simple program */
  23.    printf("build a fake IP packet\n");
  24.    ip_header = (struct iphdr *) rohc_buf_data(ip_packet);
  25.    ip_header->version = 4; /* we create an IP header version 4 */

You can enable and/or disable profiles with the following functions:

Build (again) the program with GCC:

$ gcc -o rohc_hello_world -Wall \
  $(pkg-config rohc --cflags) \
  rohc_hello_world.c \
  $(pkg-config rohc --libs)

Now, run (again) the program:

$ ./rohc_hello_world
This program will compress one single IPv4 packet
create the ROHC compressor
build a fake IP packet
0x45 0x00 0x00 0x26 0x00 0x00 0x00 0x00
0x01 0x86 0xa9 0x3f 0x01 0x02 0x03 0x04
0x05 0x06 0x07 0x08 0x68 0x65 0x6c 0x6c
0x6f 0x2c 0x20 0x52 0x4f 0x48 0x43 0x20
0x77 0x6f 0x72 0x6c 0x64 0x21
compress the fake IP packet
[net_pkt.c:75 net_pkt_parse()] outer IP header: 38 bytes
[net_pkt.c:77 net_pkt_parse()] outer IP header: version 4
[net_pkt.c:82 net_pkt_parse()] outer IP header: next header is of type 134
[net_pkt.c:87 net_pkt_parse()] outer IP header: next layer is of type 134
[rohc_comp.c:4608 c_get_profile_from_packet()] try to find the best profile for packet with transport protocol 134
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/UDP/RTP' (0x0001)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/UDP' (0x0002)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/UDP-Lite' (0x0008)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/ESP' (0x0003)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/TCP' (0x0006)
[rohc_comp.c:4813 rohc_comp_find_ctxt()] using profile 'IP-only' (0x0004)
[rohc_comp.c:4860 rohc_comp_find_ctxt()] no existing context found for packet, create a new one
[rohc_comp.c:4720 c_create_context()] take the first unused context (CID = 0)
[c_generic.c:502 c_generic_create()] new generic context required for a new stream
[c_generic.c:528 c_generic_create()] use shift parameter -1 for LSB-encoding of SN
[c_ip.c:82 rohc_ip_ctxt_create()] initialize context(SN) = random() = 18043
[rohc_comp.c:4767 c_create_context()] context (CID = 0) created (num_used = 1)
[rohc_comp.c:1435 rohc_compress4()] compress the packet #1
[c_generic.c:1217 c_generic_detect_changes()] SN = 18044
[c_generic.c:6292 detect_ip_id_behaviour()] no previous IP-ID, consider non-random/static and NBO
[c_generic.c:6356 detect_ip_id_behaviour()] NBO = 1, RND = 0, SID = 0
[c_generic.c:6185 detect_changed_fields()] TTL/HL changed from 0x00 to 0x01
[c_generic.c:6193 detect_changed_fields()] Protocol/NH changed from 0x00 to 0x86
[c_generic.c:5901 changed_static_one_hdr()] protocol_count 3
[c_generic.c:5931 changed_dynamic_both_hdr()] check for changed fields in the outer IP header
[c_generic.c:6009 changed_dynamic_one_hdr()] TTL/HL changed in the current packet
[c_generic.c:6070 changed_dynamic_one_hdr()] NBO changed (0x0 -> 0x1) in the current packet
[c_generic.c:1282 c_generic_detect_changes()] send_static = 1, send_dynamic = 2
[c_generic.c:1363 decide_state()] no enough packets transmitted in IR state for the moment (0/3), so stay in IR state
[c_generic.c:1307 periodic_down_transition()] CID 0: timeouts for periodic refreshes: FO = 0 / 700, IR = 0 / 1700
[c_generic.c:6426 encode_uncomp_fields()] compressor is in state 1
[c_generic.c:6431 encode_uncomp_fields()] new SN = 18044 / 0x467c
[c_generic.c:6439 encode_uncomp_fields()] IR state: force using 16 bits to encode new SN
[c_generic.c:6454 encode_uncomp_fields()] 16 bits are required to encode new SN
[c_generic.c:6475 encode_uncomp_fields()] new outer IP-ID delta = 0xb984 / 47492 (NBO = 1, RND = 0, SID = 0)
[c_generic.c:6483 encode_uncomp_fields()] IR state: force using 16 bits to encode new outer IP-ID delta
[c_generic.c:6506 encode_uncomp_fields()] 16 bits are required to encode new outer IP-ID delta
[c_generic.c:1497 decide_packet()] decide packet in IR state
[c_generic.c:1542 decide_packet()] packet 'IR' chosen
[c_generic.c:1719 code_IR_packet()] code IR packet (CID = 0)
[c_generic.c:1738 code_IR_packet()] small CID 0 encoded on 0 byte(s)
[c_generic.c:1750 code_IR_packet()] type of packet + D flag = 0xfd
[c_generic.c:1762 code_IR_packet()] profile ID = 0x04
[c_generic.c:1768 code_IR_packet()] CRC = 0x00 for CRC calculation
[c_generic.c:2089 code_ipv4_static_part()] version = 0x40
[c_generic.c:2094 code_ipv4_static_part()] protocol = 0x86
[c_generic.c:2103 code_ipv4_static_part()] src addr = 01020304 (1.2.3.4)
[c_generic.c:2110 code_ipv4_static_part()] dst addr = 05060708 (5.6.7.8)
[c_generic.c:2339 code_ipv4_dynamic_part()] TOS = 0x00
[c_generic.c:2346 code_ipv4_dynamic_part()] TTL = 0x01
[c_generic.c:2356 code_ipv4_dynamic_part()] IP-ID = 0x00 0x00
[c_generic.c:2377 code_ipv4_dynamic_part()] (DF = 0, RND = 0, NBO = 1, SID = 0) = 0x20
[c_generic.c:2389 code_ipv4_dynamic_part()] Generic extension header list = 0x00
[c_ip.c:508 c_ip_code_ir_remainder()] SN = 18044 -> 0x467c
[c_generic.c:1808 code_IR_packet()] CRC (header length = 21, crc = 0x16)
[rohc_comp.c:1563 rohc_compress4()] copy full 18-byte payload
[rohc_comp.c:1573 rohc_compress4()] ROHC size = 39 bytes (header = 21, payload = 18), output buffer size = 2048
ROHC packet resulting from the ROHC compression:
0xfd 0x04 0x16 0x40 0x86 0x01 0x02 0x03
0x04 0x05 0x06 0x07 0x08 0x00 0x01 0x00
0x00 0x20 0x00 0x46 0x7c 0x68 0x65 0x6c
0x6c 0x6f 0x2c 0x20 0x52 0x4f 0x48 0x43
0x20 0x77 0x6f 0x72 0x6c 0x64 0x21
destroy the ROHC decompressor

We did it! We compressed one IPv4 packet into a ROHC packet!

Careful readers might have detected that the ROHC packet is larger than the IPv4 packet. It is a little bit strange for a compression schemeā€¦ In fact, this is normal: the first ROHC packets are larger than the non-compressed packets because they contains some information that will help better compressing the next packets. You can verify this by compressing more packets in the program, they will be smaller than the original ones.

Want to learn more?

You can find more information on the library:

Full source code

For your convenience, please find the full source code of this tutorial hereafter:

  1. /*
  2.  * Copyright 2011,2012,2013,2014 Didier Barvaux
  3.  * Copyright 2010,2012 Viveris Technologies
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2.1 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public License
  16.  * along with this library; if not, write to the Free Software Foundation,
  17.  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  18.  */
  19.  
  20. /**
  21.  * @file     rohc_hello_world.c
  22.  * @brief    A program that uses the compression part of the ROHC library
  23.  * @author   Didier Barvaux <didier@barvaux.org>
  24.  * @author   Didier Barvaux <didier.barvaux@toulouse.viveris.com>
  25.  *
  26.  * A program to learn how to use the ROHC library.
  27.  *
  28.  * Build with:
  29.  *   gcc -o rohc_hello_world -Wall \
  30.  *      $(pkg-config rohc --cflags) \
  31.  *      rohc_hello_world.c \
  32.  *      $(pkg-config rohc --libs)
  33.  *
  34.  * API documentation:
  35.  *   https://rohc-lib.org/support/documentation/#library-api
  36.  *
  37.  * Tutorials:
  38.  *   https://rohc-lib.org/support/wiki/
  39.  *
  40.  * Mailing list:
  41.  *   https://rohc-lib.org/support/mailing-list/
  42.  */
  43.  
  44. #include <stdio.h>  /* for the printf() function */
  45.  
  46. /* includes required to create a fake IP packet */
  47. #include <netinet/ip.h>  /* for the IPv4 header */
  48. #include <string.h>      /* for the strlen() */
  49. #include <rohc/rohc_buf.h>  /* for the rohc_buf_*() functions */
  50.  
  51. /* includes required to use the compression part of the ROHC library */
  52. #include <time.h>             /* required by time() */
  53. #include <rohc/rohc_comp.h>   /* for rohc_comp_*() functions */
  54.  
  55. /* The size (in bytes) of the buffers used in the program */
  56. #define BUFFER_SIZE 2048
  57.  
  58. /* The payload for the fake IP packet */
  59. #define FAKE_PAYLOAD "hello, ROHC world!"
  60.  
  61. /* return a random number every time it is called */
  62. static int gen_random_num(const struct rohc_comp *const comp,
  63.                           void *const user_context)
  64. {
  65.    return rand();
  66. }
  67.  
  68. /* The main entry point of the program (arguments are not used) */
  69. int main(int argc, char **argv)
  70. {
  71.    struct rohc_comp *compressor;  /* the ROHC compressor */
  72.  
  73.    /* the buffer that will contain the IPv4 packet to compress */
  74.    uint8_t ip_buffer[BUFFER_SIZE];
  75.    /* the packet that will contain the IPv4 packet to compress */
  76.    struct rohc_buf ip_packet = rohc_buf_init_empty(ip_buffer, BUFFER_SIZE);
  77.    /* the header of the IPv4 packet */
  78.    struct iphdr *ip_header;
  79.  
  80.    uint8_t rohc_buffer[BUFFER_SIZE];
  81.    /* the packet that will contain the resulting ROHC packet */
  82.    struct rohc_buf rohc_packet = rohc_buf_init_empty(rohc_buffer, BUFFER_SIZE);
  83.  
  84.    rohc_status_t rohc_status;
  85.    size_t i;
  86.  
  87.    /* print the purpose of the program on the console */
  88.    printf("This program will compress one single IPv4 packet\n");
  89.  
  90.    /* initialize the random generator with the current time */
  91.    srand(time(NULL));
  92.  
  93.    /* create a ROHC compressor with good default parameters */
  94.    printf("create the ROHC compressor\n");
  95.    compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX,
  96.                                gen_random_num, NULL);
  97.    if(compressor == NULL)
  98.    {
  99.       fprintf(stderr, "failed create the ROHC compressor\n");
  100.       /* leave with an error code */
  101.       return 1;
  102.    }
  103.  
  104.    /* enable the IP-only compression profile */
  105.    printf("enable the IP-only compression profile\n");
  106.    if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_IP))
  107.    {
  108.       fprintf(stderr, "failed to enable the IP-only profile\n");
  109.       /* cleanup compressor, then leave with an error code */
  110.       rohc_comp_free(compressor);
  111.       return 1;
  112.    }
  113.  
  114.    /* create a fake IP packet for the purpose of this simple program */
  115.    printf("build a fake IP packet\n");
  116.    ip_header = (struct iphdr *) rohc_buf_data(ip_packet);
  117.    ip_header->version = 4; /* we create an IP header version 4 */
  118.    ip_header->ihl = 5; /* min. IPv4 header length (in 32-bit words) */
  119.    ip_packet.len += ip_header->ihl * 4;
  120.    ip_header->tos = 0; /* TOS is not important for the example */
  121.    ip_header->tot_len = htons(ip_packet.len + strlen(FAKE_PAYLOAD));
  122.    ip_header->id = 0; /* ID is not important for the example */
  123.    ip_header->frag_off = 0; /* No packet fragmentation */
  124.    ip_header->ttl = 1; /* TTL is not important for the example */
  125.    ip_header->protocol = 134; /* protocol number */
  126.    ip_header->check = 0x3fa9; /* checksum */
  127.    ip_header->saddr = htonl(0x01020304); /* source address 1.2.3.4 */
  128.    ip_header->daddr = htonl(0x05060708); /* destination addr. 5.6.7.8 */
  129.  
  130.    /* copy the payload just after the IP header */
  131.    rohc_buf_append(&ip_packet, (uint8_t *) FAKE_PAYLOAD, strlen(FAKE_PAYLOAD));
  132.  
  133.    /* dump the newly-created IP packet on terminal */
  134.    for(i = 0; i < ip_packet.len; i++)
  135.    {
  136.       printf("0x%02x ", rohc_buf_byte_at(ip_packet, i));
  137.       if(i != 0 && ((i + 1) % 8) == 0)
  138.       {
  139.          printf("\n");
  140.       }
  141.    }
  142.    if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
  143.    {
  144.      printf("\n");
  145.    }
  146.  
  147.    /* compress the fake IP packet */
  148.    printf("compress the fake IP packet\n");
  149.    rohc_status = rohc_compress4(compressor, ip_packet, &rohc_packet);
  150.    if(rohc_status != ROHC_STATUS_OK)
  151.    {
  152.       fprintf(stderr, "compression of fake IP packet failed: %s (%d)\n",
  153.               rohc_strerror(rohc_status), rohc_status);
  154.       /* cleanup compressor, then leave with an error code */
  155.       rohc_comp_free(compressor);
  156.       return 1;
  157.    }
  158.  
  159.    /* dump the ROHC packet on terminal */
  160.    printf("ROHC packet resulting from the ROHC compression:\n");
  161.    for(i = 0; i < rohc_packet.len; i++)
  162.    {
  163.       printf("0x%02x ", rohc_buf_byte_at(rohc_packet, i));
  164.       if(i != 0 && ((i + 1) % 8) == 0)
  165.       {
  166.          printf("\n");
  167.       }
  168.    }
  169.    if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
  170.    {
  171.       printf("\n");
  172.    }
  173.  
  174.    printf("destroy the ROHC decompressor\n");
  175.    rohc_comp_free(compressor);
  176.  
  177.    /* leave the program with a success code */
  178.    return 0;
  179. }

Releases

Next major release: 2.4.0 Git branch roadmap

Current stable release: 2.3.1 download release notes

Previous stable release: 2.2.0 download release notes

Sponsors

Viveris logo
Viveris
provides to the ROHC project the skills of its engineering teams in the telecommunications, network and Linux fields.

Viveris is a French engineering company specialized in advanced technologies and IT. For 30 years, Viveris has developed a pole of competences in embedded network services   products.

Viveris proposes its knowledge and expertise on network header compression to companies through the Viveris OpenSource team.

back to top