Import the "sofia" modem plug-in from the Phone project
This commit is contained in:
parent
7d514b6091
commit
8c7b49f98b
|
@ -1,4 +1,4 @@
|
|||
targets=purple
|
||||
targets=purple,sofia
|
||||
cflags_force=-W `pkg-config --cflags Phone`
|
||||
cflags=-Wall -g -O2 -pedantic -fPIC
|
||||
ldflags_force=`pkg-config --libs Phone`
|
||||
|
@ -13,3 +13,10 @@ install=$(LIBDIR)/Phone/modem
|
|||
|
||||
[purple.c]
|
||||
depends=../../../config.h
|
||||
|
||||
[sofia]
|
||||
type=plugin
|
||||
sources=sofia.c
|
||||
cflags=`pkg-config --cflags libSystem sofia-sip-ua-glib`
|
||||
ldflags=`pkg-config --libs libSystem sofia-sip-ua-glib`
|
||||
install=$(LIBDIR)/Phone/modem
|
||||
|
|
700
src/Phone/modems/sofia.c
Normal file
700
src/Phone/modems/sofia.c
Normal file
|
@ -0,0 +1,700 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2011-2015 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Phone */
|
||||
/* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <System.h>
|
||||
#include <Desktop/Phone/modem.h>
|
||||
#include <sofia-sip/nua.h>
|
||||
#include <sofia-sip/sip_header.h>
|
||||
#include <sofia-sip/su_glib.h>
|
||||
#include <sofia-sip/url.h>
|
||||
|
||||
|
||||
/* Sofia */
|
||||
/* private */
|
||||
/* types */
|
||||
typedef enum _SofiaHandleType
|
||||
{
|
||||
SOFIA_HANDLE_TYPE_REGISTRATION = 0,
|
||||
SOFIA_HANDLE_TYPE_CALL,
|
||||
SOFIA_HANDLE_TYPE_MESSAGE
|
||||
} SofiaHandleType;
|
||||
|
||||
typedef struct _SofiaHandle
|
||||
{
|
||||
SofiaHandleType type;
|
||||
nua_handle_t * handle;
|
||||
} SofiaHandle;
|
||||
|
||||
typedef struct _ModemPlugin
|
||||
{
|
||||
ModemPluginHelper * helper;
|
||||
|
||||
su_home_t home[1];
|
||||
su_root_t * root;
|
||||
guint source;
|
||||
nua_t * nua;
|
||||
SofiaHandle * handles;
|
||||
size_t handles_cnt;
|
||||
} Sofia;
|
||||
|
||||
|
||||
/* variables */
|
||||
static ModemConfig _sofia_config[] =
|
||||
{
|
||||
{ "username", "Username", MCT_STRING },
|
||||
{ "fullname", "Full name", MCT_STRING },
|
||||
{ NULL, "Network:", MCT_SUBSECTION },
|
||||
{ "bind", "Bind address", MCT_STRING },
|
||||
{ NULL, "Registrar:", MCT_SUBSECTION },
|
||||
{ "registrar_hostname", "Hostname", MCT_STRING },
|
||||
{ "registrar_username", "Username", MCT_STRING },
|
||||
{ "registrar_password", "Password", MCT_PASSWORD },
|
||||
{ NULL, "Proxy:", MCT_SUBSECTION },
|
||||
{ "proxy_hostname", "Hostname", MCT_STRING },
|
||||
{ NULL, NULL, MCT_NONE },
|
||||
};
|
||||
|
||||
|
||||
/* prototypes */
|
||||
/* plug-in */
|
||||
static ModemPlugin * _sofia_init(ModemPluginHelper * helper);
|
||||
static void _sofia_destroy(ModemPlugin * modem);
|
||||
static int _sofia_start(ModemPlugin * modem, unsigned int retry);
|
||||
static int _sofia_stop(ModemPlugin * modem);
|
||||
static int _sofia_request(ModemPlugin * modem, ModemRequest * request);
|
||||
|
||||
/* useful */
|
||||
static nua_handle_t * _sofia_handle_add(Sofia * sofia, SofiaHandleType type,
|
||||
sip_to_t * to);
|
||||
static nua_handle_t * _sofia_handle_lookup(Sofia * sofia, SofiaHandleType type);
|
||||
static int _sofia_handle_remove(Sofia * sofia, nua_handle_t * handle);
|
||||
|
||||
/* callbacks */
|
||||
static void _sofia_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[]);
|
||||
|
||||
|
||||
/* public */
|
||||
/* variables */
|
||||
ModemPluginDefinition plugin =
|
||||
{
|
||||
"Sofia",
|
||||
"applications-development",
|
||||
_sofia_config,
|
||||
_sofia_init,
|
||||
_sofia_destroy,
|
||||
_sofia_start,
|
||||
_sofia_stop,
|
||||
_sofia_request,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/* private */
|
||||
/* functions */
|
||||
/* sofia_init */
|
||||
static ModemPlugin * _sofia_init(ModemPluginHelper * helper)
|
||||
{
|
||||
Sofia * sofia;
|
||||
GSource * gsource;
|
||||
|
||||
if((sofia = object_new(sizeof(*sofia))) == NULL)
|
||||
return NULL;
|
||||
memset(sofia, 0, sizeof(*sofia));
|
||||
sofia->helper = helper;
|
||||
su_init();
|
||||
su_home_init(sofia->home);
|
||||
if((sofia->root = su_glib_root_create(NULL)) == NULL)
|
||||
{
|
||||
_sofia_destroy(sofia);
|
||||
return NULL;
|
||||
}
|
||||
gsource = su_glib_root_gsource(sofia->root);
|
||||
sofia->source = g_source_attach(gsource, g_main_context_default());
|
||||
sofia->handles = NULL;
|
||||
sofia->handles_cnt = 0;
|
||||
return sofia;
|
||||
}
|
||||
|
||||
|
||||
/* sofia_destroy */
|
||||
static void _sofia_destroy(ModemPlugin * modem)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
|
||||
_sofia_stop(modem);
|
||||
if(sofia->source != 0)
|
||||
g_source_remove(sofia->source);
|
||||
sofia->source = 0;
|
||||
su_root_destroy(sofia->root);
|
||||
su_home_deinit(sofia->home);
|
||||
su_deinit();
|
||||
object_delete(sofia);
|
||||
}
|
||||
|
||||
|
||||
/* sofia_start */
|
||||
static int _sofia_start(ModemPlugin * modem, unsigned int retry)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
url_string_t us;
|
||||
char const * p;
|
||||
char const * q;
|
||||
nua_handle_t * handle;
|
||||
ModemEvent mevent;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
if(sofia->nua != NULL) /* already started */
|
||||
return 0;
|
||||
/* bind address */
|
||||
if((p = helper->config_get(helper->modem, "bind")) != NULL
|
||||
&& strlen(p) > 0)
|
||||
snprintf(us.us_str, sizeof(us.us_str), "%s%s", "sip:", p);
|
||||
else
|
||||
p = NULL;
|
||||
/* initialization */
|
||||
if((sofia->nua = nua_create(sofia->root, _sofia_callback, modem,
|
||||
TAG_IF(p, NUTAG_URL(us.us_str)),
|
||||
SOATAG_AF(SOA_AF_IP4_IP6),
|
||||
TAG_END())) == NULL)
|
||||
return -1;
|
||||
/* username */
|
||||
if((p = helper->config_get(helper->modem, "username")) != NULL
|
||||
&& strlen(p) > 0)
|
||||
nua_set_params(sofia->nua, NUTAG_M_USERNAME(p), TAG_END());
|
||||
/* fullname */
|
||||
if((p = helper->config_get(helper->modem, "fullname")) != NULL
|
||||
&& strlen(p) > 0)
|
||||
nua_set_params(sofia->nua, NUTAG_M_DISPLAY(p), TAG_END());
|
||||
/* proxy */
|
||||
if((p = helper->config_get(helper->modem, "proxy_hostname")) != NULL
|
||||
&& strlen(p) > 0)
|
||||
{
|
||||
snprintf(us.us_str, sizeof(us.us_str), "%s%s", "sip:", p);
|
||||
nua_set_params(sofia->nua, NUTAG_PROXY(us.us_str), TAG_END());
|
||||
}
|
||||
/* registration */
|
||||
if((p = helper->config_get(helper->modem, "registrar_username"))
|
||||
!= NULL && strlen(p) > 0
|
||||
&& (q = helper->config_get(helper->modem,
|
||||
"registrar_hostname")) != NULL
|
||||
&& strlen(q) > 0)
|
||||
{
|
||||
if((handle = _sofia_handle_add(sofia,
|
||||
SOFIA_HANDLE_TYPE_REGISTRATION,
|
||||
NULL)) == NULL)
|
||||
return -helper->error(helper->modem,
|
||||
"Cannot create registration handle", 1);
|
||||
snprintf(us.us_str, sizeof(us.us_str), "%s%s", "sip:", q);
|
||||
nua_set_params(sofia->nua, NUTAG_REGISTRAR(us.us_str),
|
||||
TAG_END());
|
||||
snprintf(us.us_str, sizeof(us.us_str), "%s%s@%s", "sip:", p, q);
|
||||
nua_register(handle, SIPTAG_FROM_STR(us.us_str), TAG_END());
|
||||
}
|
||||
else
|
||||
{
|
||||
/* report that we are not registering */
|
||||
memset(&mevent, 0, sizeof(mevent));
|
||||
mevent.type = MODEM_EVENT_TYPE_REGISTRATION;
|
||||
mevent.registration.mode = MODEM_REGISTRATION_MODE_DISABLED;
|
||||
mevent.registration.status
|
||||
= MODEM_REGISTRATION_STATUS_NOT_SEARCHING;
|
||||
helper->event(helper->modem, &mevent);
|
||||
}
|
||||
/* set (and verify) parameters */
|
||||
nua_set_params(sofia->nua, NUTAG_ENABLEMESSAGE(1),
|
||||
NUTAG_ENABLEINVITE(1),
|
||||
NUTAG_AUTOALERT(1), NUTAG_AUTOANSWER(0), TAG_END());
|
||||
nua_get_params(sofia->nua, TAG_ANY(), TAG_END());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* sofia_stop */
|
||||
static void _stop_handle(SofiaHandle * handle);
|
||||
|
||||
static int _sofia_stop(ModemPlugin * modem)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
size_t i;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
for(i = 0; i < sofia->handles_cnt; i++)
|
||||
_stop_handle(&sofia->handles[i]);
|
||||
free(sofia->handles);
|
||||
sofia->handles = NULL;
|
||||
sofia->handles_cnt = 0;
|
||||
if(sofia->nua != NULL)
|
||||
{
|
||||
nua_shutdown(sofia->nua);
|
||||
su_root_run(sofia->root);
|
||||
nua_destroy(sofia->nua);
|
||||
}
|
||||
sofia->nua = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _stop_handle(SofiaHandle * handle)
|
||||
{
|
||||
if(handle->handle == NULL)
|
||||
return;
|
||||
nua_handle_destroy(handle->handle);
|
||||
}
|
||||
|
||||
|
||||
/* sofia_request */
|
||||
static int _request_call(ModemPlugin * modem, ModemRequest * request);
|
||||
static int _request_dtmf_send(ModemPlugin * modem, ModemRequest * request);
|
||||
static int _request_message_send(ModemPlugin * modem, ModemRequest * request);
|
||||
|
||||
static int _sofia_request(ModemPlugin * modem, ModemRequest * request)
|
||||
{
|
||||
switch(request->type)
|
||||
{
|
||||
case MODEM_REQUEST_CALL:
|
||||
return _request_call(modem, request);
|
||||
case MODEM_REQUEST_DTMF_SEND:
|
||||
return _request_dtmf_send(modem, request);
|
||||
case MODEM_REQUEST_MESSAGE_SEND:
|
||||
return _request_message_send(modem, request);
|
||||
#ifndef DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _request_call(ModemPlugin * modem, ModemRequest * request)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
nua_handle_t * handle;
|
||||
url_string_t us;
|
||||
sip_to_t * to;
|
||||
|
||||
snprintf(us.us_str, sizeof(us.us_str), "%s%s", "sip:",
|
||||
request->call.number);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, us.us_str);
|
||||
#endif
|
||||
if((to = sip_to_make(sofia->home, us.us_str)) == NULL)
|
||||
return -helper->error(helper->modem,
|
||||
"Could not initiate the call", 1);
|
||||
if((handle = _sofia_handle_add(sofia, SOFIA_HANDLE_TYPE_CALL, to))
|
||||
== NULL)
|
||||
return -helper->error(helper->modem,
|
||||
"Could not initiate the call", 1);
|
||||
to->a_display = request->call.number;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() nua_invite(\"%s\")\n", __func__,
|
||||
us.us_str);
|
||||
#endif
|
||||
nua_invite(handle, SOATAG_USER_SDP_STR(NULL),
|
||||
SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
|
||||
SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL), TAG_END());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _request_dtmf_send(ModemPlugin * modem, ModemRequest * request)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
nua_handle_t * handle;
|
||||
char buf[] = "Signal=X";
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
/* XXX lookup the first active call */
|
||||
if((handle = _sofia_handle_lookup(sofia, SOFIA_HANDLE_TYPE_CALL))
|
||||
== NULL)
|
||||
return -helper->error(helper->modem, "Could not send DTMF", 1);
|
||||
buf[sizeof(buf) - 2] = request->dtmf_send.dtmf;
|
||||
nua_info(handle, SIPTAG_CONTENT_TYPE_STR("application/dtmf-info"),
|
||||
SIPTAG_PAYLOAD_STR(buf),
|
||||
TAG_END());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _request_message_send(ModemPlugin * modem, ModemRequest * request)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
url_string_t us;
|
||||
sip_to_t * to;
|
||||
nua_handle_t * handle;
|
||||
|
||||
snprintf(us.us_str, sizeof(us.us_str), "%s%s", "sip:",
|
||||
request->message_send.number);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, us.us_str);
|
||||
#endif
|
||||
if((to = sip_to_make(sofia->home, us.us_str)) == NULL)
|
||||
return -helper->error(helper->modem, "Could not send message",
|
||||
1);
|
||||
if((handle = _sofia_handle_add(sofia, SOFIA_HANDLE_TYPE_MESSAGE, to))
|
||||
== NULL)
|
||||
return -helper->error(helper->modem, "Could not send message",
|
||||
1);
|
||||
nua_message(handle, SIPTAG_CONTENT_TYPE_STR("text/plain"),
|
||||
SIPTAG_PAYLOAD_STR(request->message_send.content),
|
||||
TAG_END());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* useful */
|
||||
/* sofia_handle_add */
|
||||
static nua_handle_t * _sofia_handle_add(Sofia * sofia, SofiaHandleType type,
|
||||
sip_to_t * to)
|
||||
{
|
||||
size_t i;
|
||||
SofiaHandle * p;
|
||||
|
||||
for(i = 0; i < sofia->handles_cnt; i++)
|
||||
if(sofia->handles[i].handle == NULL)
|
||||
break;
|
||||
if(i == sofia->handles_cnt)
|
||||
{
|
||||
if((p = realloc(sofia->handles, sizeof(*p) * (i + 1))) == NULL)
|
||||
return NULL;
|
||||
sofia->handles = p;
|
||||
sofia->handles_cnt++;
|
||||
}
|
||||
sofia->handles[i].type = type;
|
||||
sofia->handles[i].handle = nua_handle(sofia->nua, sofia,
|
||||
TAG_IF(to, NUTAG_URL(to->a_url)),
|
||||
TAG_IF(to, SIPTAG_TO(to)), TAG_END());
|
||||
return sofia->handles[i].handle;
|
||||
}
|
||||
|
||||
|
||||
/* sofia_handle_lookup */
|
||||
static nua_handle_t * _sofia_handle_lookup(Sofia * sofia, SofiaHandleType type)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < sofia->handles_cnt; i++)
|
||||
if(sofia->handles[i].type == type)
|
||||
return sofia->handles[i].handle;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* sofia_handle_remove */
|
||||
static int _sofia_handle_remove(Sofia * sofia, nua_handle_t * handle)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < sofia->handles_cnt; i++)
|
||||
if(sofia->handles[i].handle == handle)
|
||||
{
|
||||
/* FIXME also free memory */
|
||||
nua_handle_destroy(sofia->handles[i].handle);
|
||||
sofia->handles[i].handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* callbacks */
|
||||
/* sofia_callback */
|
||||
static void _callback_i_info(ModemPlugin * modem, int status,
|
||||
sip_t const * sip);
|
||||
static void _callback_i_message(ModemPlugin * modem, int status,
|
||||
sip_t const * sip);
|
||||
static void _callback_r_invite(ModemPlugin * modem, int status,
|
||||
char const * phrase, nua_handle_t * handle);
|
||||
static void _callback_r_message(ModemPlugin * modem, int status,
|
||||
char const * phrase);
|
||||
static void _callback_r_register(ModemPlugin * modem, int status,
|
||||
nua_handle_t * nh, sip_t const * sip, tagi_t tags[]);
|
||||
|
||||
static void _sofia_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[])
|
||||
{
|
||||
ModemPlugin * modem = magic;
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = modem->helper;
|
||||
ModemEvent mevent;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, event);
|
||||
#endif
|
||||
switch(event)
|
||||
{
|
||||
case nua_i_error:
|
||||
/* FIXME report error */
|
||||
fprintf(stderr, "i_error %03d %s\n", status, phrase);
|
||||
break;
|
||||
case nua_i_invite:
|
||||
/* FIXME report event: incoming call */
|
||||
fprintf(stderr, "i_invite %03d %s\n", status, phrase);
|
||||
break;
|
||||
case nua_i_cancel:
|
||||
/* FIXME report event: incoming call was cancelled */
|
||||
fprintf(stderr, "i_invite %03d %s\n", status, phrase);
|
||||
break;
|
||||
case nua_i_info:
|
||||
_callback_i_info(modem, status, sip);
|
||||
break;
|
||||
case nua_i_message:
|
||||
_callback_i_message(modem, status, sip);
|
||||
break;
|
||||
case nua_i_notify:
|
||||
/* FIXME report event */
|
||||
fprintf(stderr, "i_notify %03d %s\n", status, phrase);
|
||||
break;
|
||||
case nua_i_outbound:
|
||||
/* FIXME what to do? */
|
||||
fprintf(stderr, "i_outbound %03d %s\n", status, phrase);
|
||||
break;
|
||||
case nua_i_state:
|
||||
/* FIXME report event, particularly if 180 Ringing! */
|
||||
fprintf(stderr, "i_state %03d %s\n", status, phrase);
|
||||
break;
|
||||
case nua_i_terminated:
|
||||
memset(&mevent, 0, sizeof(mevent));
|
||||
mevent.type = MODEM_EVENT_TYPE_CALL;
|
||||
/* FIXME also remember the other fields */
|
||||
mevent.call.status = MODEM_CALL_STATUS_NONE;
|
||||
helper->event(helper->modem, &mevent);
|
||||
break;
|
||||
case nua_r_get_params:
|
||||
if(status == 200)
|
||||
break;
|
||||
/* FIXME what to do? */
|
||||
fprintf(stderr, "r_get_params %03d %s\n", status,
|
||||
phrase);
|
||||
break;
|
||||
case nua_r_info:
|
||||
if(status == 200)
|
||||
break;
|
||||
helper->error(helper->modem, "Could not send DTMF", 1);
|
||||
break;
|
||||
case nua_r_invite:
|
||||
_callback_r_invite(modem, status, phrase, nh);
|
||||
break;
|
||||
case nua_r_message:
|
||||
_callback_r_message(modem, status, phrase);
|
||||
break;
|
||||
case nua_r_register:
|
||||
_callback_r_register(modem, status, nh, sip, tags);
|
||||
break;
|
||||
case nua_r_set_params:
|
||||
if(status == 200)
|
||||
break;
|
||||
/* FIXME implement */
|
||||
fprintf(stderr, "r_set_params %03d %s\n", status,
|
||||
phrase);
|
||||
break;
|
||||
case nua_r_shutdown:
|
||||
/* exit the background loop when ready */
|
||||
if(status == 200)
|
||||
su_root_break(sofia->root);
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() %s%d%s: %03d \"%s\"\n",
|
||||
__func__, "event ", event,
|
||||
" not handled: ", status, phrase);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _callback_i_info(ModemPlugin * modem, int status, sip_t const * sip)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
ModemEvent mevent;
|
||||
sip_from_t const * from;
|
||||
sip_to_t const * to;
|
||||
|
||||
if(status != 200)
|
||||
/* FIXME report whatever that is */
|
||||
return;
|
||||
/* a notification arrived */
|
||||
if(sip == NULL || (from = sip->sip_from) == NULL
|
||||
|| (to = sip->sip_to) == NULL)
|
||||
/* FIXME report whatever that is */
|
||||
return;
|
||||
memset(&mevent, 0, sizeof(mevent));
|
||||
mevent.type = MODEM_EVENT_TYPE_NOTIFICATION;
|
||||
/* FIXME we may want to include more information */
|
||||
mevent.notification.content = sip->sip_payload->pl_data;
|
||||
helper->event(helper->modem, &mevent);
|
||||
}
|
||||
|
||||
static void _callback_i_message(ModemPlugin * modem, int status,
|
||||
sip_t const * sip)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
ModemEvent mevent;
|
||||
sip_from_t const * from;
|
||||
sip_to_t const * to;
|
||||
char buf[256];
|
||||
|
||||
if(status != 200)
|
||||
/* FIXME report whatever that is */
|
||||
return;
|
||||
/* a message arrived */
|
||||
if(sip == NULL || (from = sip->sip_from) == NULL
|
||||
|| (to = sip->sip_to) == NULL)
|
||||
/* FIXME report whatever that is */
|
||||
return;
|
||||
memset(&mevent, 0, sizeof(mevent));
|
||||
mevent.type = MODEM_EVENT_TYPE_MESSAGE;
|
||||
mevent.message.date = time(NULL);
|
||||
/* XXX automatically import as a new contact? (from->a_display) */
|
||||
snprintf(buf, sizeof(buf), URL_FORMAT_STRING,
|
||||
URL_PRINT_ARGS(from->a_url));
|
||||
mevent.message.number = buf;
|
||||
mevent.message.folder = MODEM_MESSAGE_FOLDER_INBOX;
|
||||
mevent.message.status = MODEM_MESSAGE_STATUS_NEW;
|
||||
mevent.message.encoding = MODEM_MESSAGE_ENCODING_ASCII;
|
||||
mevent.message.length = sip->sip_payload->pl_len;
|
||||
mevent.message.content = sip->sip_payload->pl_data;
|
||||
helper->event(helper->modem, &mevent);
|
||||
}
|
||||
|
||||
static void _callback_r_invite(ModemPlugin * modem, int status,
|
||||
char const * phrase, nua_handle_t * handle)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
ModemEvent mevent;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%s() %03d %s\n", __func__, status, phrase);
|
||||
#endif
|
||||
memset(&mevent, 0, sizeof(mevent));
|
||||
mevent.type = MODEM_EVENT_TYPE_CALL;
|
||||
mevent.call.call_type = MODEM_CALL_TYPE_VOICE;
|
||||
mevent.call.direction = MODEM_CALL_DIRECTION_OUTGOING;
|
||||
if(status == 200)
|
||||
{
|
||||
mevent.call.status = MODEM_CALL_STATUS_RINGING;
|
||||
nua_ack(handle, TAG_END());
|
||||
}
|
||||
else
|
||||
{
|
||||
mevent.call.status = MODEM_CALL_STATUS_NONE;
|
||||
/* FIXME report error */
|
||||
fprintf(stderr, "r_invite %03d %s\n", status, phrase);
|
||||
_sofia_handle_remove(sofia, handle);
|
||||
}
|
||||
helper->event(helper->modem, &mevent);
|
||||
}
|
||||
|
||||
static void _callback_r_message(ModemPlugin * modem, int status,
|
||||
char const * phrase)
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
ModemEvent mevent;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%s() %03d %s\n", __func__, status, phrase);
|
||||
#endif
|
||||
memset(&mevent, 0, sizeof(mevent));
|
||||
mevent.type = MODEM_EVENT_TYPE_MESSAGE_SENT;
|
||||
if(status == 200)
|
||||
/* the message could be sent */
|
||||
helper->event(helper->modem, &mevent);
|
||||
else
|
||||
{
|
||||
/* an error occurred */
|
||||
mevent.message_sent.error = phrase;
|
||||
helper->event(helper->modem, &mevent);
|
||||
}
|
||||
}
|
||||
|
||||
static void _callback_r_register(ModemPlugin * modem, int status,
|
||||
nua_handle_t * nh, sip_t const * sip, tagi_t tags[])
|
||||
{
|
||||
Sofia * sofia = modem;
|
||||
ModemPluginHelper * helper = sofia->helper;
|
||||
ModemEvent mevent;
|
||||
sip_www_authenticate_t const * wa;
|
||||
char const * hostname;
|
||||
char const * username;
|
||||
char const * password;
|
||||
char const * scheme;
|
||||
char const * realm;
|
||||
char * authstring;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() %03d %s\n", __func__, status, phrase);
|
||||
#endif
|
||||
memset(&mevent, 0, sizeof(mevent));
|
||||
mevent.type = MODEM_EVENT_TYPE_REGISTRATION;
|
||||
mevent.registration.mode = MODEM_REGISTRATION_MODE_AUTOMATIC;
|
||||
mevent.registration.status = MODEM_REGISTRATION_STATUS_UNKNOWN;
|
||||
hostname = helper->config_get(helper->modem, "registrar_hostname");
|
||||
if(status == 200)
|
||||
{
|
||||
mevent.registration.status
|
||||
= MODEM_REGISTRATION_STATUS_REGISTERED;
|
||||
mevent.registration._operator = hostname;
|
||||
}
|
||||
else if(status == 401 || status == 405)
|
||||
{
|
||||
mevent.registration.status
|
||||
= MODEM_REGISTRATION_STATUS_SEARCHING;
|
||||
wa = (sip != NULL) ? sip->sip_www_authenticate : NULL;
|
||||
tl_gets(tags, SIPTAG_WWW_AUTHENTICATE_REF(wa), TAG_END());
|
||||
username = helper->config_get(helper->modem,
|
||||
"registrar_username");
|
||||
password = helper->config_get(helper->modem,
|
||||
"registrar_password");
|
||||
if(wa != NULL && username != NULL && password != NULL)
|
||||
{
|
||||
scheme = wa->au_scheme;
|
||||
realm = msg_params_find(wa->au_params, "realm=");
|
||||
authstring = su_sprintf(sofia->home, "%s:%s:%s@%s:%s",
|
||||
scheme, realm, username, hostname,
|
||||
password);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() authstring=\"%s\"\n",
|
||||
__func__, authstring);
|
||||
#endif
|
||||
nua_authenticate(nh, NUTAG_AUTH(authstring), TAG_END());
|
||||
su_free(sofia->home, authstring);
|
||||
}
|
||||
}
|
||||
else if(status == 403)
|
||||
mevent.registration.status = MODEM_REGISTRATION_STATUS_DENIED;
|
||||
else if(status >= 400 && status <= 499)
|
||||
mevent.registration.status
|
||||
= MODEM_REGISTRATION_STATUS_NOT_SEARCHING;
|
||||
helper->event(helper->modem, &mevent);
|
||||
}
|
Loading…
Reference in New Issue
Block a user