SofiaTutorial

From OpenSource

Jump to: navigation, search

This is still work in progress, feel free to update it or suggest something

Contents

Introduction

This tutorial describes the use of Sofia-SIP library in creation of simple SIP agent.

Sofia-SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification. It can be used as a building block for SIP client software for uses such as VoIP, IM, and many other real-time and person-to-person communication services. The primary target platform for Sofia-SIP is GNU/Linux although it highly targets embedded world. Sofia-SIP is based on a SIP stack developed at the Nokia Research Center. Sofia-SIP is licensed under the LGPL.

Sofia-SIP library is written in C. So you don't need to have knowledge of other languages. But the experience with Linux development is welcome, since we are using GNU tools.

It would be nice to have idea about what SIP protocol is, what is RTP and how voice over IP is usually transmitted.

Getting started

Of course, we'll start with the "Hello World" application using Sofia-SIP

Hello world using Sofia-SIP. To test:

  1. Run make
  2. Run hello-callee
  3. Run hello-caller

Highlights from this example;

  1. Sofia-SIP uses event driven pattern.
  2. Sofia-SIP uses TAGS to pass arguments.
  3. Sofia-SIP has object-oriented API. su_root_t describes event loop, nua_t describes user agent, nua_handle_t describes communication.

Makefile (don't forget tabs)

CFLAGS = -g -O0

all: hello-caller hello-callee

hello-caller: hello.c
        gcc `pkg-config sofia-sip-ua --cflags --libs` -DCALLER \
        $(CFLAGS) -o hello-caller hello.c

hello-callee: hello.c
        gcc `pkg-config sofia-sip-ua --cflags --libs` \
        $(CFLAGS) -o hello-callee hello.c

clean:
        rm hello-caller hello-callee

Source

/* Hello world in Sofia-SIP.
 * 
 * This application will send a MESSAGE
 * from <sip:localhost:5062> to <sip:localhost:5060>
 */

#include <stdio.h>
#include <sofia-sip/nua.h>

void send_message (nua_t *nua);

void event_callback(nua_event_t   event,
                    int           status,
                    char const   *phrase,
                    nua_t        *nua,
                    nua_magic_t  *magic,
                    nua_handle_t *nh,
                    nua_hmagic_t *hmagic,
                    sip_t const  *sip,
                    tagi_t        tags[]);

int
main (int argc, char *argv[])
{
  su_root_t *root;
  nua_t *nua;

  /* Initialize Sofia-SIP library and create event loop */

  su_init ();
  root = su_root_create (NULL);
  
  /* Create a user agent instance. Caller and callee should bind to different
   * address to avoid conflicts. The stack will call the 'event_callback()' 
   * callback when events such as succesful registration to network, 
   * an incoming call, etc, occur. 
   */
  nua = nua_create(root, /* Event loop */
                   event_callback, /* Callback for processing events */
                   NULL, /* Additional data to pass to callback */
#ifdef CALLER
		   NUTAG_URL("sip:0.0.0.0:5062"), /* Address to bind to */
#else
		   NUTAG_URL("sip:0.0.0.0:5060"),
#endif
                   TAG_END()); /* Last tag should always finish the sequence */

#ifdef CALLER
  send_message (nua);
#endif
 
  /* Run event loop */
  su_root_run (root);

  /* Destroy allocated resources */
  nua_destroy (nua);
  su_root_destroy (root);
  su_deinit ();

  return 0;
}

/* This callback will be called by SIP stack to
 * process incoming events 
 */
void event_callback(nua_event_t   event,
                    int           status,
                    char const   *phrase,
                    nua_t        *nua,
                    nua_magic_t  *magic,
                    nua_handle_t *nh,
                    nua_hmagic_t *hmagic,
                    sip_t const  *sip,
                    tagi_t        tags[])
{
  printf ("Hello world!\n"
          "I have received an event %s status %d %s\n", 
          nua_event_name (event), status, phrase);
}

/* Create a communication handle, send MESSAGE with it and destroy it */
void send_message (nua_t *nua)
{
  nua_handle_t *handle;

  handle = nua_handle(nua, NULL, SIPTAG_TO_STR("sip:test@127.0.0.1:5060"), TAG_END());

  nua_message(handle,
	      SIPTAG_CONTENT_TYPE_STR("text/plain"),
	      SIPTAG_PAYLOAD_STR("Hello callee!!!"),
	      TAG_END());

  nua_handle_destroy (handle);
}


Tags

See the section covering use of tags in Sofia-SIP online reference docs at http://sofia-sip.sourceforge.net/refdocs/su/group__su__tag.html

Event loop

See the section covering use of event loops ('su_root'), timers and waits objects in the Sofia-SIP online reference docs at http://sofia-sip.sourceforge.net/refdocs/su/group__su__wait.html

SIP state machine

See the Sofia-SIP call model documentation at http://sofia-sip.sourceforge.net/refdocs/nua/nua_call_model.html

Memory management

See the section covering use of the provided memory handling functions in the Sofia-SIP online reference docs at http://sofia-sip.sourceforge.net/refdocs/su/group__su__alloc.html

SDP negotiation

See the section covering the Sofia-SIP offer/answer module 'SOA' at: http://sofia-sip.sourceforge.net/refdocs/soa/

The SOA documentation shows how to pass local and remote SDP descriptions over the NUA user-agent interface.

Working with multiple accounts

<to be written -- search the sofia-sip-devel mailing archives for discussions around "NUTAG_IDENTITY" in 2006 >

Personal tools
MediaWiki Resources