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 - New Free Runtime and 30 Day Trial
Check out the new simplified licensign option that enables unlimited
royalty-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