User Tools

Site Tools


library-migration

Migration from old library versions to newer versions

This page describes how public API changed between releases.

API changes between 2.1.x and 2.2.x

The library API is compatible with versions 2.0.x and 2.1.x. The following headers/types/functions were added/modified for ROHCv2:

In addition, the applications gained a –rohc-version parameter to use ROHCv1 or ROHCv2 profiles. They defaults to ROHCv1 for compatibility reasons. See man pages:

API changes between 2.0.x and 2.1.x

The library API is compatible with version 2.0.x. The following functions were added:

API changes between 1.7.x and 2.0.x

The library API was changed in an incompatible way. The following functions were removed:

  • Remove deprecated rohc_alloc_compressor()
  • Remove deprecated rohc_free_compressor()
  • Remove deprecated rohc_compress2()
  • Remove deprecated rohc_comp_set_traces_cb()
  • Remove deprecated rohc_alloc_decompressor()
  • Remove deprecated rohc_free_decompressor()
  • Remove deprecated rohc_decompress()
  • Remove deprecated rohc_decomp_set_traces_cb()
  • Remove deprecated rohc_activate_profile()

All of those functions were replaced in the 1.7.x releases by better ones. See the API changes between 1.6.x and 1.7.x to learn how to use the new functions.

API changes between 1.6.x and 1.7.x

Replace rohc_alloc_compressor() by rohc_comp_new2()

The rohc_alloc_compressor() function is deprecated. Use the new rohc_comp_new2() function instead.

Old code:

    struct rohc_comp *compressor;
 
    /* create the ROHC compressor */
    compressor = rohc_alloc_compressor(ROHC_SMALL_CID_MAX, 0, 0, 0);
    if(compressor == NULL)
    {
       /* handle error */
    }
    else
    {
        /* success: configure compressor further, compress IP packets,
           then free the compressor */
    }

New code:

    struct rohc_comp *compressor;
 
    ...
 
    srand(time(NULL)); /* init the pseudo-random number generator */
 
    ...
 
    /* create the ROHC compressor */
    compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX,
                                gen_random_num, NULL);
    if(compressor == NULL)
    {
       /* handle error */
    }
    else
    {
        /* success: configure compressor further, compress IP packets,
           then free the compressor */
    }
 
    ...
 
/* callback that gives a random number to the ROHC library */
int gen_random_num(const struct rohc_comp *const comp,
                   void *const user_context)
{
   return rand();
}

The new API allows to configure a ROHC compressor for large CIDs without calling several functions. See below an example.

Old code (for large CIDs):

    struct rohc_comp *compressor;
 
    /* create the ROHC compressor */
    compressor = rohc_alloc_compressor(ROHC_SMALL_CID_MAX, 0, 0, 0);
    if(compressor == NULL)
    {
       /* handle error */
    }
    else
    {
        /* success: configure compressor further, compress IP packets,
           then free the compressor */
    }
 
    /* set CID type to large CID and MAX_CID to 450 */
    rohc_c_set_large_cid(comp, 1);
    rohc_c_set_max_cid(comp, 450);

New code (for large CIDs):

    struct rohc_comp *compressor;
 
    ...
 
    srand(time(NULL)); /* init the pseudo-random number generator */
 
    ...
 
    /* create the ROHC compressor with large CIDs and MAX_CID = 450 */
    compressor = rohc_comp_new(ROHC_LARGE_CID, 450,
                               gen_random_num, NULL);
    if(compressor == NULL)
    {
       /* handle error */
    }
    else
    {
        /* success: configure compressor further, compress IP packets,
           then free the compressor */
    }
 
 
    ...
 
/* callback that gives a random number to the ROHC library */
int gen_random_num(const struct rohc_comp *const comp,
                   void *const user_context)
{
   return rand();
}

Replace rohc_free_compressor() by rohc_comp_free()

The rohc_free_compressor() function is deprecated. Use the new rohc_comp_free() function instead.

Old code:

    struct rohc_comp *compressor;
 
    ...
 
    /* destroy the ROHC compressor (created with rohc_alloc_compressor()
       or rohc_comp_new() before) */
    rohc_free_compressor(compressor);

New code:

    struct rohc_comp *compressor;
 
    ...
 
    /* destroy the ROHC compressor (created with rohc_alloc_compressor()
       or rohc_comp_new() before) */
    rohc_comp_free(compressor);

Replace rohc_compress2() by rohc_compress4()

The rohc_compress2() function is deprecated. Use the new rohc_compress4() function instead.

Old code:

    struct rohc_comp *compressor;
    const size_t ip_packet_len = 42;
    unsigned char ip_packet[ip_packet_len] = "...";
    const size_t rohc_packet_max_len = 100;
    size_t rohc_packet_len;
    unsigned char rohc_packet[rohc_packet_max_len];
    int ret;
 
    ...
 
    /* compress the IP packet */
    ret = rohc_compress2(compressor,
                         ip_packet, ip_packet_len,
                         rohc_packet, rohc_packet_max_len, &rohc_packet_len);
    if(ret == ROHC_OK)
    {
        /* success */
        ...
    }
    else if(ret == ROHC_NEED_SEGMENT)
    {
        /* partial success: packet is segmented, we get the first segment,
           we need to call rohc_comp_get_segment() to retrieve remaining
           segments */
        ...
    }
    else
    {
        /* failure */
        ...
    }

New code:

    struct timespec arrival_time_ts;
    struct rohc_ts arrival_time;
    struct rohc_comp *compressor;
    const size_t ip_packet_len = 42;
    unsigned char ip_packet_buffer[ip_packet_len] = "...";
    const size_t rohc_packet_max_len = 100;
    unsigned char rohc_packet_buffer[rohc_packet_max_len];
    rohc_status_t status;
 
    ...
 
    /* compute the current time at the moment the IP packet is received
       from network (leave it to 0 if you want the same behavior as
       before or if you don't care about the packet/context repair)
 
       Note: source of time must be accurate, so the use of clock_gettime()
             in the example below (-lrt may be required to build).
     */
    ret = clock_gettime(CLOCK_MONOTONIC_RAW, &arrival_time_ts);
    if(ret != 0)
    {
        /* handle failure */
        ...
    }
    arrival_time.sec = arrival_time_ts.tv_sec;
    arrival_time.nsec = arrival_time_ts.tv_nsec;
 
    struct rohc_buf ip_packet =
        rohc_buf_init_full(ip_packet_buffer, ip_packet_len, arrival_time);
 
    struct rohc_buf rohc_packet =
        rohc_buf_init_empty(rohc_packet_buffer, rohc_packet_max_len);
 
    /* compress the IP packet */
    status = rohc_compress4(compressor, ip_packet, &rohc_packet);
    if(status == ROHC_STATUS_OK)
    {
        /* success */
        ...
    }
    else if(ret == ROHC_STATUS_SEGMENT)
    {
        /* partial success: packet is segmented, we get the first segment,
           we need to call rohc_comp_get_segment() to retrieve remaining
           segments */
        ...
    }
    else
    {
        /* handle failure */
        ...
    }

Replace rohc_comp_set_traces_cb() by rohc_comp_set_traces_cb2()

The rohc_comp_set_traces_cb() function is deprecated. Use the new rohc_comp_set_traces_cb2() function instead.

Old code:

    struct rohc_comp *compressor;
    bool ret;
 
    ...
 
    /* create the ROHC compressor here */
 
    ...
 
    /* set a callback to handle library traces */
    ret = rohc_comp_set_traces_cb(compressor, print_rohc_traces);
    if(ret != true)
    {
       /* handle error */
    }
 
    ...    
 
/**
 * @brief Callback to print traces of the ROHC library
 *
 * @param level      The priority level of the trace
 * @param entity     The entity that emitted the trace among:
 *                    \li ROHC_TRACE_COMP
 *                    \li ROHC_TRACE_DECOMP
 * @param profile    The ID of the ROHC compression/decompression profile
 *                   the trace is related to
 * @param format     The format string of the trace
 */
void print_rohc_traces(const rohc_trace_level_t level,
                       const rohc_trace_entity_t entity,
                       const int profile,
                       const char *const format,
                       ...)
{
   va_list args;
 
   va_start(args, format);
   vfprintf(stdout, format, args);
   va_end(args);
}

New code:

struct my_private_context
{
    /* put anything you want to retrieve in the trace callback */
};    
 
    ...
 
    struct rohc_comp *compressor;
    struct my_private_context my_private_context;
    bool ret;
 
    ...
 
    /* create the ROHC compressor here */
 
    ...
 
    /* set a callback to handle library traces */
    ret = rohc_comp_set_traces_cb2(compressor, print_rohc_traces, &my_private_context);
    if(ret != true)
    {
       /* handle error */
    }
 
    ...    
 
/**
 * @brief Callback to print traces of the ROHC library
 *
 * @param priv_ctxt  An optional private context, may be NULL
 * @param level      The priority level of the trace
 * @param entity     The entity that emitted the trace among:
 *                    \li ROHC_TRACE_COMP
 *                    \li ROHC_TRACE_DECOMP
 * @param profile    The ID of the ROHC compression/decompression profile
 *                   the trace is related to
 * @param format     The format string of the trace
 */
void print_rohc_traces(void *const priv_ctxt,
                       const rohc_trace_level_t level,
                       const rohc_trace_entity_t entity,
                       const int profile,
                       const char *const format,
                       ...)
{
   struct my_private_context *const my_private_context =
       (struct my_private_context *) priv_ctxt;
   va_list args;
 
   va_start(args, format);
   vfprintf(stdout, format, args);
   va_end(args);
}

Replace rohc_alloc_decompressor() by rohc_decomp_new2()

The rohc_alloc_decompressor() function is deprecated. Use the new rohc_decomp_new2() function instead.

The new API allows to configure a ROHC decompressor for small/large CIDs and a specific MAX_CID without calling several functions. See below examples for U-mode and O-mode.

The operational mode is now given as a new dedicated parameter, it is not deduced any more from the presence of an associated compressor. The associated compressor is not given to the decompressor any more. Feedback channel is handled while decompressing a packet, see the section about conversion to rohc_decompress3().

Old code for Unidirectional mode:

    struct rohc_decomp *decompressor;
 
    /* create the ROHC decompressor */
    decompressor = rohc_alloc_decompressor(NULL);
    if(decompressor == NULL)
    {
       /* handle error */
    }
    else
    {
        /* success: ROHC decompressor is created */
 
        /* set the CID type to small CID */
        if(!rohc_decomp_set_cid_type(decomp, ROHC_SMALL_CID))
        {
            /* handle error */
        }
 
        /* set MAX_CID to 5 */
        if(!rohc_decomp_set_max_cid(decomp, 5))
        {
            /* handle error */
        }
 
        /* success: configure decompressor further, decompress ROHC packets,
           then free the decompressor */
    }

New code for Unidirectional mode:

    struct rohc_decomp *decompressor;
 
    /* create the ROHC decompressor with small CIDs, MAX_CID = 5,
       and Unidirectional mode */
    decompressor = rohc_decomp_new2(ROHC_SMALL_CID, 5, ROHC_U_MODE);
    if(decompressor == NULL)
    {
       /* handle error */
    }
    else
    {
        /* success: configure decompressor further, decompress ROHC packets,
           then free the decompressor */
    }

Old code for Bidirectional Optimistic mode:

    struct rohc_comp *compressor;
    struct rohc_decomp *decompressor;
 
    ...
 
    /* create a ROHC compressor for the feedback channel of the
       decompressor */
    compressor = rohc_comp_new(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX);
    if(compressor == NULL)
    {
       /* handle error */
    }
 
    ...
 
    /* create the ROHC decompressor */
    decompressor = rohc_alloc_decompressor(compressor);
    if(decompressor == NULL)
    {
       /* handle error */
    }
    else
    {
        /* success: ROHC decompressor is created */
 
        /* set the CID type to small CID */
        if(!rohc_decomp_set_cid_type(decomp, ROHC_SMALL_CID))
        {
            /* handle error */
        }
 
        /* set MAX_CID to 5 */
        if(!rohc_decomp_set_max_cid(decomp, 5))
        {
            /* handle error */
        }
 
        /* success: configure decompressor further, decompress ROHC packets,
           then free the decompressor */
    }

New code for Bidirectional Optimistic mode:

    struct rohc_decomp *decompressor;
 
    ...
 
    /* create the ROHC decompressor with small CIDs, MAX_CID = 5,
       and Bidirectional Optimistic mode */
    decompressor = rohc_decomp_new(ROHC_SMALL_CID, 5, ROHC_O_MODE);
    if(decompressor == NULL)
    {
       /* handle error */
    }
    else
    {
        /* success: configure decompressor further, decompress ROHC packets,
           then free the decompressor */
    }

Replace rohc_free_decompressor() by rohc_decomp_free()

The rohc_free_decompressor() function is deprecated. Use the new rohc_decomp_free() function instead.

Old code:

    struct rohc_decomp *decompressor;
 
    ...
 
    /* destroy the ROHC decompressor (created with rohc_alloc_decompressor()
       or rohc_decomp_new2() before) */
    rohc_free_decompressor(decompressor);

New code:

    struct rohc_decomp *decompressor;
 
    ...
 
    /* destroy the ROHC decompressor (created with rohc_alloc_decompressor()
       or rohc_decomp_new2() before) */
    rohc_decomp_free(decompressor);

Replace rohc_decompress() by rohc_decompress3()

The rohc_decompress() function is deprecated. Use the new rohc_decompress3() function instead.

Old code:

    struct rohc_decomp *decompressor;
    const size_t rohc_packet_len = 42;
    unsigned char rohc_packet[rohc_packet_len] = "...";
    const size_t ip_packet_max_len = 100;
    size_t ip_packet_len;
    unsigned char ip_packet[ip_packet_max_len];
    int ret;
 
    ...
 
    /* decompress the ROHC packet */
    ret = rohc_decompress(decompressor,
                          rohc_packet, rohc_packet_len,
                          ip_packet, ip_packet_max_len);
    if(ret == ROHC_FEEDBACK_ONLY)
    {
        /* success: no decompressed IP data available in ip_packet because
           the ROHC packet contained only feedback data */
        ...
    }
    else if(ret == ROHC_NON_FINAL_SEGMENT)
    {
        /* success: no decompressed IP data available in ip_packet because
           the ROHC packet was a non-final segment (at least another segment
           is required to be able to decompress the full ROHC packet) */
        ...
    }
    else if(ret > 0)
    {
        /* success: ip_packet contains an IP packet of length ret */
        ip_packet_len = ret;
        ...
    }
    else
    {
        /* failure */
        ...
    }

New code:

    struct timespec arrival_time_ts;
    struct rohc_ts arrival_time;
    struct rohc_decomp *decompressor;
    const size_t rohc_packet_len = 42;
    unsigned char rohc_packet_buffer[rohc_packet_len] = "...";
    const size_t ip_packet_max_len = 100;
    unsigned char ip_packet_buffer[ip_packet_max_len];
    rohc_status_t status;
 
    ...
 
    /* compute the current time at the moment the ROHC packet is received
       from network (leave it to 0 if you want the same behavior as
       before or if you don't care about the packet/context repair)
 
       Note: source of time must be accurate, so the use of clock_gettime()
             in the example below (-lrt may be required to build).
     */
    ret = clock_gettime(CLOCK_MONOTONIC_RAW, &arrival_time_ts);
    if(ret != 0)
    {
        /* handle failure */
        ...
    }
    arrival_time.sec = arrival_time_ts.tv_sec;
    arrival_time.nsec = arrival_time_ts.tv_nsec;
 
    ...
 
    struct rohc_buf rohc_packet =
        rohc_buf_init_full(rohc_packet_buffer, rohc_packet_len, arrival_time);
 
    struct rohc_buf ip_packet =
        rohc_buf_init_empty(ip_packet_buffer, ip_packet_max_len);
 
    ...
 
    /* decompress the ROHC packet
     *
     * note: the return value does not mix status code and packet length
     */
    status = rohc_decompress3(decompressor, rohc_packet, &ip_packet,
                              &feedback_received_on_feedback_channel,
                              &feedback_to_send_on_feedback_channel);
    if(status == ROHC_STATUS_OK)
    {
        /* success:
         *  - ip_packet may contain an IP packet (if ROHC packet was not
         *    a feedback-only packet or a non-final segment packet)
         *  - feedback_to_send_on_feedback_channel may contain a feedback
         *    that the decompressor wants to send to the associated
         *    compressor on the remote peer through the feedback channel */
 
        if(ip_packet.len == 0)
        {
            /* do some useful with the decompressed packet */
        }
 
        if(feedback_to_send_on_feedback_channel.len == 0)
        {
            /* send the feedback to the remote peer */
        }
    }
    else
    {
        /* failure */
        ...
    }

Replace rohc_decomp_set_traces_cb() by rohc_decomp_set_traces_cb2()

The rohc_decomp_set_traces_cb() function is deprecated. Use the new rohc_decomp_set_traces_cb2() function instead.

Old code:

    struct rohc_decomp *decompressor;
    bool ret;
 
    ...
 
    /* create the ROHC decompressor here */
 
    ...
 
    /* set a callback to handle library traces */
    ret = rohc_decomp_set_traces_cb(decompressor, print_rohc_traces);
    if(ret != true)
    {
       /* handle error */
    }
 
    ...    
 
/**
 * @brief Callback to print traces of the ROHC library
 *
 * @param level      The priority level of the trace
 * @param entity     The entity that emitted the trace among:
 *                    \li ROHC_TRACE_COMP
 *                    \li ROHC_TRACE_DECOMP
 * @param profile    The ID of the ROHC compression/decompression profile
 *                   the trace is related to
 * @param format     The format string of the trace
 */
void print_rohc_traces(const rohc_trace_level_t level,
                       const rohc_trace_entity_t entity,
                       const int profile,
                       const char *const format,
                       ...)
{
   va_list args;
 
   va_start(args, format);
   vfprintf(stdout, format, args);
   va_end(args);
}

New code:

struct my_private_context
{
    /* put anything you want to retrieve in the trace callback */
};    
 
    ...
 
    struct rohc_decomp *decompressor;
    struct my_private_context my_private_context;
    bool ret;
 
    ...
 
    /* create the ROHC decompressor here */
 
    ...
 
    /* set a callback to handle library traces */
    ret = rohc_decomp_set_traces_cb2(decompressor, print_rohc_traces, &my_private_context);
    if(ret != true)
    {
       /* handle error */
    }
 
    ...    
 
/**
 * @brief Callback to print traces of the ROHC library
 *
 * @param priv_ctxt  An optional private context, may be NULL
 * @param level      The priority level of the trace
 * @param entity     The entity that emitted the trace among:
 *                    \li ROHC_TRACE_COMP
 *                    \li ROHC_TRACE_DECOMP
 * @param profile    The ID of the ROHC compression/decompression profile
 *                   the trace is related to
 * @param format     The format string of the trace
 */
void print_rohc_traces(void *const priv_ctxt,
                       const rohc_trace_level_t level,
                       const rohc_trace_entity_t entity,
                       const int profile,
                       const char *const format,
                       ...)
{
   struct my_private_context *const my_private_context =
       (struct my_private_context *) priv_ctxt;
   va_list args;
 
   va_start(args, format);
   vfprintf(stdout, format, args);
   va_end(args);
}

Replace rohc_activate_profile() by rohc_comp_enable_profile()

The rohc_activate_profile() function is deprecated. Use the new rohc_comp_enable_profile(), rohc_comp_enable_profiles(), rohc_comp_disable_profile() or rohc_comp_disable_profiles() functions instead.

The two latter allows you to disable profiles that you already enabled (that was not possible before). They work the same way the enable functions. The enable functions are described in the examples below.

Old code:

    struct rohc_decomp *decompressor;
 
    ...
 
    rohc_activate_profile(compressor, ROHC_PROFILE_UNCOMPRESSED);
    rohc_activate_profile(compressor, ROHC_PROFILE_UDP);
    rohc_activate_profile(compressor, ROHC_PROFILE_IP);
    rohc_activate_profile(compressor, ROHC_PROFILE_UDPLITE);
    rohc_activate_profile(compressor, ROHC_PROFILE_RTP);
    rohc_activate_profile(compressor, ROHC_PROFILE_ESP);
 
    ...

New code (option #1):

    struct rohc_decomp *decompressor;
 
    ...
 
    /* enable all profiles one by one: if profile is missing (old version
       of library for example), you know it and can act in consequence */
    if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_UNCOMPRESSED))
    {
        /* handle failure */
        ...
    }
    if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_UDP))
    {
        /* handle failure */
        ...
    }
    if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_IP))
    {
        /* handle failure */
        ...
    }
    if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_UDPLITE))
    {
        /* handle failure */
        ...
    }
    if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_RTP))
    {
        /* handle failure */
        ...
    }
    if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_ESP))
    {
        /* handle failure */
        ...
    }
 
    ...

New code (option #2):

    struct rohc_decomp *decompressor;
    bool ret;
 
    ...
 
    /* enable all profiles at once (list must end with -1): if at least one
       profile is missing (old version of library for example), you know it
       and can act in consequence (note that don't know which profile(s)
       is/are missing) */
    ret = rohc_comp_enable_profiles(compressor,
                                    ROHC_PROFILE_UNCOMPRESSED,
                                    ROHC_PROFILE_UDP,
                                    ROHC_PROFILE_IP,
                                    ROHC_PROFILE_UDPLITE,
                                    ROHC_PROFILE_RTP,
                                    ROHC_PROFILE_ESP,
                                    -1);
    if(ret != true)
    {
        /* handle failure */
        ...
    }
 
    ...

API changes between 1.5.x and 1.6.x

Replace rohc_compress() by rohc_compress2()

The rohc_compress() function is deprecated. Use the new rohc_compress2() function instead.

Old code:

    struct rohc_comp *compressor;
    const size_t ip_packet_len = 42;
    unsigned char ip_packet[ip_packet_len] = "...";
    const size_t rohc_packet_max_len = 100;
    size_t rohc_packet_len;
    unsigned char rohc_packet[rohc_packet_max_len];
    int ret;
 
    ...
 
    /* compress the IP packet */
    ret = rohc_compress(compressor,
                        ip_packet, ip_packet_len,
                        rohc_packet, rohc_packet_max_len);
    if(ret > 0)
    {
        /* success: rohc_packet contains a ROHC packet of length ret */
        rohc_packet_len = ret;
        ...
    }
    else
    {
        /* failure */
        ...
    }

New code:

    struct rohc_comp *compressor;
    const size_t ip_packet_len = 42;
    unsigned char ip_packet[ip_packet_len] = "...";
    const size_t rohc_packet_max_len = 100;
    size_t rohc_packet_len;
    unsigned char rohc_packet[rohc_packet_max_len];
    int ret;
 
    ...
 
    /* compress the IP packet
     *
     * Note #1: the return value does not mix status code and packet length
     * 
     * Note #2: a new ROHC_NEED_SEGMENT status code can be returned if the
     *          the compressor was forced to split the ROHC packet into
     *          several chunks (= segments) because of the MRRU set by
     *          rohc_comp_set_mrru() or rohc_c_set_mrru().
     */
    ret = rohc_compress2(compressor,
                         ip_packet, ip_packet_len,
                         rohc_packet, rohc_packet_max_len, &rohc_packet_len);
    if(ret == ROHC_OK)
    {
        /* success: rohc_packet contains a ROHC packet of length rohc_packet_len */
        ...
    }
    else if(ret == ROHC_NEED_SEGMENT)
    {
        /* partial success: packet is segmented, we get the first segment,
           we need to call rohc_comp_get_segment() to retrieve remaining
           segments */
        ...
    }
    else
    {
        /* handle failure */
        ...
    }

Replace rohc_c_set_mrru() by rohc_comp_set_mrru()

The rohc_c_set_mrru() function is deprecated. Use the new rohc_comp_set_mrru() function instead.

Those 2 functions set the Maximum Reconstructed Reception Unit (MRRU) of the ROHC compressor. MRRU is the size limit below which the compressor shall split a ROHC packet into several smaller ROHC segments.

Old code:

    struct rohc_comp *compressor;
 
    ...
 
    /* set MRRU to 1500 bytes */
    rohc_c_set_mrru(compressor, 1500);
 
    ...

New code:

    struct rohc_comp *compressor;
    bool ret;
 
    ...
 
    /* set MRRU to 1500 bytes */
    ret = rohc_comp_set_mrru(compressor, 1500);
    if(ret != true)
    {
        /* handle failure */
        ...
    }
 
    ...

API changes between 1.4.x and 1.5.x

Changes were not documented, ask on mailing list for information.

API changes between 1.3.x and 1.4.x

Changes were not documented, ask on mailing list for information.

library-migration.txt · Last modified: 2018/04/25 19:21 by didier