Hi,

I am trying to write a small program with sofia-sip and glib.


GUI <----> Sofia-SIP Stack <----------------> SIP Media Server


The Sofia-SIP Stack program has a socket control interface fro the GUI that
will provision the commands "INVITE" or "BYE" to the Sofia-SIP Stack. The
other socket is used to communicate with a SIP Media Server.

The Sofia-SIP stack receives the "INVITE" command from the GUI and sends
successfully a SIP INVITE to the media server, but then the 200 OK from the
Media Server are not received (any of the retransmissions) so at the end I
have an ACK timeout at the media server.

The function init_listening_socket creates a socket and bind it to a
IOChannel. I define a io_callback function to handle the GUI commands. The
main procedure initialized the sofia-sip-ua-glib main loop as in the example
I found in the documentation.

The Sofia-SIP stack does not print the nua_i_state "INVITE sent", so
probably the threads do not return correctly to the g_main_loop. What is
missing ? Does anybody have a suggestion ?

Here is the code I am using:



************************

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sofia-sip/nua.h>
#include <sofia-sip/su.h>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/sdp.h>
#include <sofia-sip/su_localinfo.h>
#include <sofia-sip/sdp_tag.h>

#include <sofia-sip/su_glib.h>

#include <glib.h>

#include "conveho_cfg.h"

#define SECONDS_S "15"
#define SMF_LISTEN 5060
#define SMF_LISTEN_S "5060"

#define GUI_SENDPORT 7020


nua_t *nua;
nua_handle_t *handle;

static int local_port;

/* 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[])
{

  switch (event) {
          case nua_i_invite:
                  printf ("nua_i_invite %p: %d %s\n",
                                  nh, status, phrase);

                  break;
          case nua_r_invite:
                  printf ("nua_r_invite %p: %d %s\n",
                                  nh, status, phrase);

                  if (status == 200) {
                          printf ("Received INVITE with status 200 !\n");
                          nua_ack (nh,
                          TAG_END());
                  }

                  break;
          case nua_i_state:
                  printf ("nua_i_state %p: %d %s\n",
                                  nh, status, phrase);
                  break;
          case nua_i_active:
                  printf ("nua_active %p: %d %s\n",
                                  nh, status, phrase);
                  //
                  // handle call
                  //

                  break;
          case nua_i_ack:
                  // this is an ACK to an incoming call event
                  printf ("nua_i_ack %p: %d %s\n",
                                  nh, status, phrase);//mp_i_ack (event,
status, phrase, nua, magic, nh, hmagic, sip, tags);
                  break;
          case nua_r_ack:
                  // this is an ACK to an incoming call event
                  printf ("nua_r_ack %p: %d %s\n",
                                  nh, status, phrase);//mp_r_ack (event,
status, phrase, nua, magic, nh, hmagic, sip, tags);
                  break;
          case nua_r_bye:
                  // this is the response to BYE
                  printf ("nua_r_bye %p: %d %s\n",
                                  nh, status, phrase);//mp_r_bye (event,
status, phrase, nua, magic, nh, hmagic, sip, tags);
                  break;
         case nua_i_terminated:
                  // this is the response to BYE
                  printf ("Terminated %p: %d %s\n",
                                  nh, status, phrase);
                  // destroy handle
                  exit(0);
                  break;
          case nua_r_shutdown:
                  // this is called after a nua_shutdown
                  printf ("[DEBUG] nua_r_shutdown %p: %d %s\n",
                                  nh, status, phrase);
                  printf ("[DEBUG] shutting down...\n");
                  nua_destroy (nua);
                  break;
          default:
                  printf ("Received an event %s status %d %s\n",
                                  nua_event_name (event), status, phrase);
                  break;
  }
}

static void
stream_relay_live ()
{
      char str[128];

      memset(str, 0, sizeof(str));
      sprintf(str, "sip:re...@%s:%s", "127.0.0.1", "7018");

      g_print ("[DEBUG] Sending 'INVITE' to %s\n ", str);
      handle = nua_handle (nua,
                        NULL,
                        SIPTAG_USER_AGENT_STR("Test Program 0.99"),
                        SIPTAG_TO_STR (str),
                        TAG_END()
        );

      if (handle == NULL) {
                    printf ("Can't create operation handle, quitting..\n");
                    exit(1);
      }

        nua_invite (handle,
                        SIPTAG_CONTENT_TYPE_STR("application/sdp"), // must
be present
                        SIPTAG_PAYLOAD_STR( // must be present
                                "v=0\r\n" // protocol version
                                //<username> <session id> <version> <network
type> <address type> <address>
                                "o=SMF 2280 22800 IN IP4 10.147.65.83\r\n"
// creator and session identifier
                                "s=SMF stream from webcam in H.263 and MPEG2
video\r\n" // session name
                                "t=0 0\r\n" // start and stop times
//                              "c=IN IP4 239.255.255.201\r\n" // originator
IP address
                                "c=IN IP4 127.0.0.1\r\n" // originator IP
address
                                "a=sendonly\r\n" // defined by c-mobile
                                "a=crid:koe20090320_westermann.ts\r\n" //
content ID
                                "m=video 1236 RTP/AVP 33\r\n" // MPEGTS
                                "a=rtpmap:33 MP2T/90000\r\n"
                                ),
                        TAG_END()
                   );
}

static void
send_bye ()
{
  g_print ("send_bye: handle: %p\n", handle);
  nua_handle_destroy (handle);
  //nua_bye (handle, TAG_END() );

}


/* Parse GUI command */
void
parse_command (gchar *buf)
{
  if (!strcmp (buf, "INVITE\n")) {
    g_print ("Creating new INVITE handle\n");
    stream_relay_live ();
    return;
  }

  if (!strcmp (buf, "BYE\n")) {
    g_print ("Sending BYE\n");
    send_bye ();
    return;
  }

  g_print ("unknown command !\n");
  return;
}

#define BUFSIZE 64

gboolean
io_callback(GIOChannel *ioch, GIOCondition cond, gpointer data)
{
  GIOStatus ret;
  gsize bytes_read;
  gchar *buf;

  GError *err = NULL;

  g_print ("io_callback. handle: %p\n", handle);

  if (cond & G_IO_ERR) {
    g_print ("GUI socket connection error\n");
    exit(EXIT_FAILURE);
  }

  ret = g_io_channel_read_line (ioch, &buf, &bytes_read, NULL, &err);
  if (ret == G_IO_STATUS_ERROR)
    g_error ("error reading: %s\n", err->message);

  if (bytes_read) {
    g_print ("[DEBUG] received gui command: %s\n", buf);
    parse_command (buf);
    g_free (buf);
  }

  g_print ("leaving io_callback\n");

  return TRUE;
}

void init_listening_socket (void)
{
  int sock = 0;
  GIOChannel *gui_read;

  struct sockaddr_in sa;

  memset(&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_addr.s_addr = INADDR_ANY;
  sa.sin_port = htons(GUI_SENDPORT);

  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

  if (-1 == bind(sock,(struct sockaddr *)&sa, sizeof(struct sockaddr)))
  {
    perror("error bind failed");
    close(sock);
    exit(EXIT_FAILURE);
  }

 // create IOChannel
  gui_read =  g_io_channel_unix_new (sock);
  if (!g_io_add_watch (gui_read, G_IO_IN | G_IO_ERR, io_callback, NULL))
    g_error ("Cannot add watch on GIOChannel!\n");

  g_print ("[DEBUG] Listening socket ready...\n");

  return;
}

int
main (int argc, char *argv[])
{
  GMainLoop *ptr = g_main_loop_new(NULL, FALSE);
  GSource *gsource;
  su_root_t *sofia_event_loop;
  su_timer_t *timer;

  /* create a sofia event loop using su-glib function
su_glib_root_source_create() */
  sofia_event_loop = su_glib_root_create(NULL);

  /* attach the created GSource to glib event loop */
  gsource = su_glib_root_gsource(sofia_event_loop);
  g_source_attach(gsource, g_main_loop_get_context(ptr));

  /* use the sofia event loop with libsofia-sip-ua modules */
  timer = su_timer_create(su_root_task(sofia_event_loop), 200L);

  local_port = SMF_LISTEN;
  printf ("ConVeHo application listening on %d\n", local_port);
  /* 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(sofia_event_loop, /* Event loop */
                   event_callback, /* Callback for processing events */
                   NULL, /* Additional data to pass to callback */
                   NUTAG_URL("sip:0.0.0.0:" SMF_LISTEN_S), /* Address to
bind to IPv4 */
//                   NUTAG_URL("sip:[::]:5060"), /* Address to bind to IPv6
*/
                   NUTAG_MEDIA_ENABLE(0), /* disable built-in SDP
offer-answer model */
                   NUTAG_AUTOACK(0), /* no automatic ACK send */
                   TAG_END()); /* Last tag should always finish the sequence
*/

  /* open second control socket and bind it to g_main_loop */
  init_listening_socket ();

  /* Run event loop */
  printf ("[DEBUG] Entering main loop\n");
  /* run the glib mainloop */
  g_main_loop_run(ptr);

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

  return 0;
}


************

Best regards,

Jordi
------------------------------------------------------------------------------
Crystal Reports &#45; New Free Runtime and 30 Day Trial
Check out the new simplified licensign option that enables unlimited
royalty&#45;free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
Sofia-sip-devel mailing list
Sofia-sip-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sofia-sip-devel

Reply via email to