Monday, March 22, 2010

getting start with osip

As described in rfc3261, sip is a layered protocol. Its layers are shown in the image below.

Unlike other sophisicated sip libiraies, exosip, pjsip, mjsip, which implement all layers of sip protocol, oSip library doesn't implement transport layer. oSip claims it doesn't provide high level api for controlling SIP session, it only provides api for sip message parsing, sdp message parsing and transaction handling. The api contains implementation for syntax, transaction and transaction unit layer.
So, in order to use oSip in our own application, we need to implement transport layer, and hook the transport layer with the oSip library.

Core structures of oSip
oSip library has four core structures, osip_t, osip_transaction_t, osip_event_t, osip_message_t. osip_t is the context of the sip library runs in. osip_transaction_t defines transaction which composes of a request message and all subsequent response messages related to the request. osip_event_t defines event inside transaction pending on handling. osip_message_t is the mapping from sip message syntax to c structure.

osip_t has four lists of transactions, each corresponds to a kind of transaction. For instance, if our sip application makes a call to another sip application, our application runs as uac (User Agent Client). A transaction is created and added to the osip_ict_transactions ( ict is short for invite client transaction) list. In the application being called, a transaction is also created and added to the osip_ist_transactions (ist is short for invite server transaction).
There are three members, msg_callbacks, kill_callbacks and cb_send_message in osip_t. They store callbacks to be called while handling events of transaction. They are designed as internal members. The proper way to add callbacks is using following apis: osip_set_cb_send_message, osip_set_message_callback and osip_set_kill_transaction_callback.

osip_transaction_t contains many members. Among them, the most important ones are:
  • transactionid, which uniquely identifis a transaction
  • state, which shows current state of the transaction
  • transactionff, a fifo containing all events belonging to this transaction
osip_event_t is used to represent an event pending on processing. It doesn't contain much information. It only has the transactionid of the owning transaction, the type of the event and a pointer to the sip_message_t correlate with the event. An event is usually constructed accompany with a sip_message_t instance. For example, upon receiving a incoming request, we can use osip_parse function to parse the received string to a osip_message_t instance, meanwhile, a osip_event_t instance will be created and returned. osip_event_t instance is only useful after it has been added to a transaction's event fifo. This can be done with osip_transaction_add_event or osip_find_transaction_and_add_event functions.

After events have been added to fifo, we need to call osip_xxx_execute functions to actually handle them. There are four osip_xxx_execute functions, each will handle all events belong to a transaction category. For example, osip_ist_execute function will iterate through all IST transactions in osip_ist_transactions list, loop through all events in each transaction's transactionff, call corresponding callback functions depending on the type of the event.

How to use oSip
To use oSip library, we usually follow below steps:
  1. Initialize oSip and setup callback functions
  2. Implement transport layer. In most cases, we create a socket based transport layer.
  3. Create/add events by parsing incoming messages
  4. Call osip_xxx_execute function to process all events
Here is a basic sample:
http://code.google.com/p/rxwen-blog-stuff/source/browse/trunk/protocol/basic_osip_sample/basic_osip_sample.cpp
This sample is a UAS(callee) for windows, and just show the basic steps of using oSip without error handling.

Something useful
  • It's strongly recommended not to run time consuming or indefinite ending tasks inside callback functions, otherwise, the osip main procedure will be blocked until the callback finishes.
  • oSip has provided a wrapper layer above native system apis to make it portable. In order to use its multi-thread feature (which is almost always necessary), we need to define OSIP_MT macro in our application.
  • In most cases, we don't need to concern about freeing of transaction & message instances. Their life time are managed by the osip runtime, through state machine.

10 comments:

Werner said...

Thank you very much for this overview. Im a relative novice programmer and Ive been struggling to get going with osip for a while now. It really takes effort to figure out the whole process by only veiwing the documentation, especially since its hard to find basic example code that still covers all the main features.
Thanks again!

rxwen said...

So glad it helps you a bit. I was in exactly same situation as you're now. I strongly believe osip should provide some tutorials for new learners.
Btw, after you understand the big picture of osip, exosip can be a good reference for you to learn how a mature sip library is implementated on top of osip.

Werner said...

As you suggested, ive been looking at eXosip and ive implemented a very, very simple UAS and UAC (with eXosip) from bits of sample code. The client works absolutely fine and messages are sent to the correct addres, but the server never receives any requests. Ive tried getting help from the mailing lists, but to no avail. Could I maybe send you snippets of the code that ive done?

rxwen said...

sure, you can contact me at rx.wen218 AT gmail.

W. Clifford said...

I keep meaning to try out oSip, but had not been able to find any decent tutorial/sample. That is until I stumbled upon your post. Many thanks for taking the time to do this; with any luck, I'll get a good understanding of the library and post some examples of my own as well. It's a shame that this library does not have more/better documentation.

rxwen said...

I'm glad it helps you a little bit. Looking forward to seeing your posts.

kadir yaşar said...

Hi, I convert your C++ example to C and compiled it with gcc to run in Linux. SIP message comes to PC (I can see it in wireshark and data delivered from socket) but program rises "event has no transaction, create a new one" error. Could you help me? Thanks, regards.

rx wen said...

Hi,

What sip message did you send to pc?

kadir yaşar said...

Hi, It was a socket problem, I solved it. But, I have another problem now. How can I make a call from pc. I mean How can i send invite message to a phone. Thanks.

rx wen said...

You may use linphone on pc to test the sip stack.