HOWTO: Porting application to osip2.

 [image of the Head of a GNU] [ English ]

Table of Contents


Introduction.

At the beginning of the year 2003, huge work has been done on oSIP to make it more freindly to use. The source files, the include files, the API and the directory structure have entirely been renamed to make the source more readable and the API easier to understand.

You are now facing a new issue: you have to upgrade your applications!

This files will give you guidelines that will help you to port your application without pain. Even if it seems difficult because of the huge API change, you'll find it easy to port your applications by following the guidelines found in this document.

To upgrade you application, you first have to run a simple script that will magically rename all the osip API in your code. This is possible because only the API have changed since the latest release (0.9.7).

Of course, there are a few exeptions that will require you to make some changes by hand... This is why this file will be very helpfull to you.

Note that you may have additionnal conflicts depending of the naming conventions you have choosen in your applications.

Guidelines for renaming the API.

First, download the archive symbol-osip1-to-osip2.tar.gz.

This file contains the following important elements:

As you see, a default file is provided to rename your source code (symbol-osip1-to-osip2). In fact, this script is not enough because a few additionnal things that depends on your application must be modified by hand. I have provided the modified symbol file that I used to rename the partysip source code. The difference between the two "symbols" files only concern the callback management.

Here is an easy way to process your source. Prior to running the script, BACKUP YOUR SOURCE! Depending on your naming conventions, the script might rename symbols that you don't want to rename! As usual, Use it at your own risk...

#make a copy of your source in a new directory:
  $> mkdir newdirectory
  $> cp -r sources newdirectory
#replace all files in "newdirectory" with the renamed version.
  $> source-upgrade.py symbol-osip1-to-osip2 newdirectory sources/*.h
  $> source-upgrade.py symbol-osip1-to-osip2 newdirectory sources/*.c
  $> source-upgrade.py symbol-osip1-to-osip2 newdirectory sources/*/*.h
  $> source-upgrade.py symbol-osip1-to-osip2 newdirectory sources/*/*.c

The "newdirectory" should now contain your new sources. You'll now have to edit and modify them by following the guidelines provided below on this page.

Include file Issue

With the old osip release, before including some include file, some additionnal "#defines" were needed. (HAVE_STDARG_H, __VXWORKS_OS__, HAVE_PTHREAD...).

With osip2, definitions are kept internal and you don't have to bother anymore with them.

As an example, if you wish to use the thread interface of osip, you just have to write this simple program:

#include <osip2/osip_mt.h>

int main(int argc, char **argv)
{
  struct *osip_thread;
  osip_thread = osip_thread_create (
                      20000,
                      (void *(*)(void *)) my_thread_method,
                      (void *) argv[1])
  osip_thread_join(osip_thread);
  osip_free(osip_thread);
  return 0;
}

With osip2, the old <osip/port.h> has been renamed to <osipparser2/osip_port.h> and the multithreaded interface is available in <osip2/osip_mt.h>. Note that all the multithreaded interface use the keyword "struct" instead of a real typedef. Definitions of typedef are not available any more in the application layer.

#include <osip/port.h> has been splitted in two parts:

 #include <osipparser2/osip_port.h>
 #include <osip2/osip_mt.h>
The second one is used for "thread", "semaphore" and "mutex". The first contains the other porting stuff. (string helper, trace methods...) The script autorename <osip/port.h> to <osipparser2/osip_port.h>, so you have to include <osip2/osip_mt.h> in files where you use thread, mutex or semaphore.

osip_thread_create has a different set of arguments.

If you are using the portable thread interface of osip, there is a change in the API that you have to fix manually.

The method osip_thread_create() now only have 3 arguments. The second argument was useless and has been removed.

osip_global_init/osip_global_free are not necessary anymore

You have to remove the calls to "osip_global_init()" and "osip_global_free()": This is now done for you automaticly.

You have to link with -losip2.

You now have to link with -losip2 only.

If you whish to link with the parser only, you can link with -losipparser2.

The interface to register callback have changed.

The callback initialization have changed a lot.

With osip2, there are 3 arguments when you register callbacks. You have to give an additionnal argument and the script is not able to replace this one magically.

This must be done by hand!

For partysip, I've been able to make a script which is provided as the partsysip-port-osip1-to-osip2-callback. It might help you.

Note that the prototype of the callback methods have changed. They have an additionnal argument showing the type of event announced to the callback. This allows a new way to receive several events through only one callback that you register several times.

All prototypes of callback have to be changed manually. (or again, look at the partsysip-port-osip1-to-osip2-callback to see how I've done this in partysip)

The sdp negotiation API have changed.

An internal element (the context of negotiation) previoulsy defined in osip has been made external. This element must now be allocated by you and must be given as the first argument when calling a method of the sdp negotiation API.

Here is a sample of the old code:

  int i = osip_negotiation_init();
  if (i!=0) return -1;
  osip_negotiation_free();
  osip_negotiation_set_o_username(osip_strdup("userX"));
  osip_negotiation_set_o_session_id(osip_strdup("20000001"));
  osip_negotiation_set_o_session_version(osip_strdup("20000001"));
  osip_negotiation_set_o_nettype(osip_strdup("IN"));
  osip_negotiation_set_o_addrtype(osip_strdup("IP4"));
  osip_negotiation_set_o_addr(osip_strdup(localip));
  ...

The new code will look like:

  osip_negotiation_t *sn;
  int i = osip_negotiation_init(&sn);
  if (i!=0) return -1;
  osip_negotiation_free(sn);
  osip_negotiation_set_o_username(sn, osip_strdup("userX"));
  osip_negotiation_set_o_session_id(sn, osip_strdup("20000001"));
  osip_negotiation_set_o_session_version(sn, osip_strdup("20000001"));
  osip_negotiation_set_o_nettype(sn, osip_strdup("IN"));
  osip_negotiation_set_o_addrtype(sn, osip_strdup("IP4"));
  osip_negotiation_set_o_addr(sn, osip_strdup(localip));
  ...

Releasing resources.

This might be the most difficult issue to resolve. When using the old osip version, releasing ressource allocated with any of the "*_init()" method was done with 2 lines of code:

  url_t *url
  url_init(&url)
  ...
  url_free(url);
  osip_free(url);

This was an error in the design of the osip library. For historical reason, I did not changed this behavior for the matter of keeping backward compatibility. With osip2, this is fixed and you now have to fix your code and remove the extra call to "osip_free()" where it applied.

For example, the above code become (with the new API):

  osip_uri_t *uri;
  osip_uri_init(&uri)
  ...
  osip_uri_free(uri);

Here is the list of method where the additionnal call to "osip_free()" is not needed anymore.

  void osip_body_free (osip_body_t * body);
  void osip_list_special_free (osip_list_t * li, void *(*free_func) (void *));
  void osip_list_ofchar_free (osip_list_t * li);
  void osip_message_free (osip_message_t * sip);
#define osip_generic_param_free(GP)       osip_uri_param_free(GP)
#define osip_generic_param_freelist(LIST) osip_uri_param_freelist(LIST)
  void osip_uri_param_free (osip_uri_param_t * url_param);
  void osip_uri_param_freelist (osip_list_t * url_params);
#define osip_uri_header_free(url_header)  osip_uri_param_free(url_header)
#define osip_uri_header_freelist(LIST)    osip_uri_param_freelist(LIST)
  void osip_uri_free (osip_uri_t * url);
  void sdp_bandwidth_free (sdp_bandwidth_t * elem);
  void sdp_time_descr_free (sdp_time_descr_t * elem);
  void sdp_key_free (sdp_key_t * elem);
  void sdp_attribute_free (sdp_attribute_t * elem);
  void sdp_connection_free (sdp_connection_t * elem);
  void sdp_media_free (sdp_media_t * elem);
  void sdp_message_free (sdp_message_t * sdp);
#define osip_accept_free(header)          osip_content_type_free(header)
  void osip_accept_encoding_free (osip_accept_encoding_t * header);
#define osip_accept_language_free(header) osip_accept_encoding_free(header)
#define osip_alert_info_free(header)      osip_call_info_free(header)
#define osip_allow_free(header)           osip_content_length_free(header)
  void osip_authorization_free (osip_authorization_t * header);
  void osip_call_id_free (osip_call_id_t * header);
  void osip_call_info_free (osip_call_info_t * header);
  void osip_contact_free (osip_contact_t * header);
#define osip_content_disposition_free(header) osip_call_info_free(header)
#define osip_content_encoding_free(header)    osip_content_length_free(header)
  void osip_content_length_free (osip_content_length_t * header);
  void osip_content_type_free (osip_content_type_t * header);
  void osip_cseq_free (osip_cseq_t * header);
#define  osip_error_info_free(header)     osip_call_info_free(header)
  void osip_from_free (osip_from_t * header);
  void osip_header_free (osip_header_t * header);
#define osip_mime_version_free(header)    osip_content_length_free(header)
#define osip_proxy_authenticate_free(header) osip_www_authenticate_free(header)
#define osip_proxy_authorization_free(header) osip_authorization_free(header)
  void osip_record_route_free (osip_record_route_t * header);
  void osip_route_free (osip_route_t * header);
  void osip_to_free (osip_to_t * header);
  void osip_via_free (osip_via_t * header);
  void osip_www_authenticate_free (osip_www_authenticate_t * header);
  int osip_transaction_free (osip_transaction_t * transaction);
  int osip_transaction_free2 (osip_transaction_t * transaction);
  void osip_dialog_free (osip_dialog_t * dialog);
  void osip_fifo_free (osip_fifo_t * ff);
  void osip_negotiation_ctx_free (osip_negotiation_ctx_t * ctx);
  void osip_negotiation_free (osip_negotiation_t *conf);

After those changes, I definitly advise you to test your application with a memory checker. I'm using the "mpatrol" tool on linux. This will definitly help you to quickly validate your new release!

The osip_message_get_reason() method have changed. (NEW 26/05/2003)

This method now returns a string which is not allocated anymore with malloc. You have to call osip_strdup() yourself to allocate the string if you need it. For example, here is a transformation needed for osip2 in partysip:

osip_message_set_reasonphrase (resp, osip_message_get_reason (404));
becomes:
osip_message_set_reason_phrase (resp, osip_strdup(osip_message_get_reason (404)));

The status_code element in osip_message_t is changed to be an integer. (NEW 26/05/2003)

Moving to osip2, status_code has been changed to be an integer instead of an allocated string. You have to fix your code evrywhere this element is used.

Enjoy!


[ English ] Please send comments on these web pages to partysip@wellx.com

Copyright (C) 2002 WellX Telecom.

Copyright (C) 2002 Aymeric MOIZARD.

Updated: 2003/01/27 13:22:50 by Aymeric