📄 nua_glib.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005-2006 Nokia Corporation. * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * Copyright (C) 2005 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@file nua_glib.c Interface towards libsofia-sip-ua. * * @author Kai Vehmanen <kai.vehmanen@nokia.com> * @author Rob Taylor <rob.taylor@collabora.co.uk> * @author Pekka Pessi <pekka.pessi@nokia.com> * @author Martti Mela <martti.mela@nokia.com> */#include <stddef.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <stdarg.h>#include <assert.h>#include <glib.h>#include "sofia-sip/nua_glib.h"#include "nua_glib_priv.h"#include "nua_glib_marshal.h"/*=============== Class and Object init ===============*/G_DEFINE_TYPE(NuaGlib, nua_glib, G_TYPE_OBJECT); /*signal enum*/enum{ NGSIG_CALL_FORKED = 1, NGSIG_INCOMING_INVITE, NGSIG_INCOMING_REINVITE, NGSIG_CALL_STATE_CHANGED, NGSIG_INCOMING_ACTIVE, NGSIG_CALL_TERMINATED, NGSIG_INCOMING_PRACK, NGSIG_INCOMING_BYE, NGSIG_INCOMING_CANCEL, NGSIG_INCOMING_MESSAGE, NGSIG_INCOMING_INFO, NGSIG_INCOMING_REFER, NGSIG_INCOMING_NOTIFY, NGSIG_ERROR, NGSIG_SHUTDOWN, NGSIG_REGISTER_ANSWERED, NGSIG_UNREGISTER_ANSWERED, NGSIG_PUBLISH_ANSWERED, NGSIG_INVITE_ANSWERED, NGSIG_BYE_ANSWERED, NGSIG_MESSAGE_ANSWERED, NGSIG_INFO_ANSWERED, NGSIG_REFER_ANSWERED, NGSIG_SUBSCRIBE_ANSWERED, NGSIG_UNSUBSCRIBE_ANSWERED, NGSIG_NOTIFY_ANSWERED, NGSIG_OPTIONS_ANSWERED, NGSIG_AUTH_REQUIRED, NGSIG_LAST_SIGNAL};static guint signals[NGSIG_LAST_SIGNAL] = {0};enum{ PROP_ADDRESS = 1, PROP_PASSWORD, PROP_CONTACT, PROP_PROXY, PROP_REGISTRAR, PROP_STUN_SERVER, LAST_PROPERTY};void final_shutdown(NuaGlib *self){ g_object_unref(self);}static GObjectClass *parent_class=NULL; static int sof_init(NuaGlibPrivate *priv, const char *contact);static void priv_submit_authlist(NuaGlibOp *op);static void priv_oper_handle_auth (NuaGlib *self, NuaGlibOp *op, sip_t const *sip, tagi_t *tags);static void priv_oper_check_response_for_auth(NuaGlib *self, NuaGlibOp *op, int status, sip_t const *sip, tagi_t *tags);static GObject *nua_glib_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties){ GObject *obj; int res = 0; GSource *gsource; { /* Invoke parent constructor. * this calls our init, and then set_property with any * CONSTRUCT params */ NuaGlibClass *klass; klass = NUA_GLIB_CLASS (g_type_class_peek (NUA_GLIB_TYPE)); parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); obj = parent_class->constructor (type, n_construct_properties, construct_properties); } NuaGlib *self = NUA_GLIB(obj); /* create a su event loop and connect it to glib */ self->priv->root = su_root_source_create(self); assert(self->priv->root); gsource = su_root_gsource(self->priv->root); assert(gsource); g_source_attach(gsource, NULL); /*check address has been set*/ g_assert(strcmp(self->priv->address, "no-address-set")!=0); res = sof_init(self->priv, self->priv->contact); if (res != -1) { self->priv->nua = nua_create(self->priv->root, sof_callback, self, NUTAG_SOA_NAME("default"), TAG_IF(self->priv->stun_server, STUNTAG_SERVER(self->priv->stun_server)), TAG_IF(self->priv->contact, NUTAG_URL(self->priv->contact)), /* XXX: SOATAG_CAPS_SDP_STR(local_caps), */ TAG_NULL()); if (self->priv->nua) { nua_set_params(self->priv->nua, TAG_IF(self->priv->proxy, NUTAG_PROXY(self->priv->proxy)), TAG_IF(self->priv->registrar, NUTAG_REGISTRAR(self->priv->registrar)), NUTAG_ENABLEMESSAGE(1), NUTAG_ENABLEINVITE(1), /* NUTAG_SESSION_TIMER(s_e), */ /* NUTAG_MIN_SE(min_se), */ SOATAG_AF(SOA_AF_IP4_IP6), SIPTAG_FROM_STR(self->priv->address), /* NUTAG_CERTIFICATE_DIR(getenv("SIPCERTDIR")),*/ TAG_NULL()); nua_get_params(self->priv->nua, TAG_ANY(), TAG_NULL()); self->priv->init=TRUE; g_signal_connect_after(self, "shutdown", (GCallback)final_shutdown, NULL); } } return obj;}static voidnua_glib_init(NuaGlib *self){ self->priv = g_new0(NuaGlibPrivate, 1); /* initialize sofia su OS abstraction layer */ su_init(); su_home_init(self->priv->home);}static voidnua_glib_dispose(GObject *obj){ NuaGlib *self = NUA_GLIB(obj); if (self->priv->init) { g_free((gpointer)self->priv->contact); nua_shutdown(self->priv->nua); self->priv->init = FALSE; /*now hold a ref to ourselves that we drop when distruction is complete*/ g_object_ref (obj); /* TODO:some start/stop nua funtions to do su_init/de_init? su_deinit();*/ } /* Chain up to the parent class */ G_OBJECT_CLASS (parent_class)->dispose (obj);}static voidnua_glib_finalize (GObject *obj){ NuaGlib *self = NUA_GLIB(obj); su_root_break(self->priv->root); nua_destroy(self->priv->nua); su_root_destroy(self->priv->root), self->priv->root = NULL; su_home_deinit(self->priv->home); g_free(self->priv); /* Chain up to the parent class */ G_OBJECT_CLASS (parent_class)->finalize (obj); }staticvoid nua_glib_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec){ NuaGlib *self = (NuaGlib*) object;#define STORE_PARAM(s, x) \ g_free ((gpointer)(s)->priv->x); \ (s)->priv->x = g_value_dup_string (value) switch (property_id) { case PROP_ADDRESS: { if (self->priv->nua) { nua_set_params(self->priv->nua, SIPTAG_FROM_STR(self->priv->address), TAG_NULL()); nua_get_params(self->priv->nua, TAG_ANY(), TAG_NULL()); } else /*setting in constructor*/ { self->priv->address = su_strdup(self->priv->home, g_value_get_string (value)); } break; } case PROP_PASSWORD: { STORE_PARAM(self, password); break; } case PROP_CONTACT: { STORE_PARAM(self, contact); break; } case PROP_PROXY: { STORE_PARAM(self, proxy); if (self->priv->nua) { nua_set_params(self->priv->nua, NUTAG_PROXY(self->priv->proxy), TAG_NULL()); } break; } case PROP_REGISTRAR: { STORE_PARAM(self, registrar); if (self->priv->nua) { nua_set_params(self->priv->nua, NUTAG_REGISTRAR(self->priv->registrar), TAG_NULL()); } break; } case PROP_STUN_SERVER: { STORE_PARAM(self, stun_server); break; } default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); break; }}static voidnua_glib_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec){ NuaGlib *self = (NuaGlib *) object; switch (property_id) { case PROP_ADDRESS: { g_value_set_string (value, self->priv->address); break; } case PROP_PASSWORD: { g_value_set_string (value, self->priv->password); break; } case PROP_CONTACT: { g_value_set_string (value, self->priv->contact); break; } case PROP_PROXY: { g_value_set_string (value, self->priv->proxy); break; } case PROP_REGISTRAR: { g_value_set_string (value, self->priv->registrar); break; } case PROP_STUN_SERVER: { g_value_set_string (value, self->priv->stun_server); break; } default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); break; }}static voidnua_glib_class_init (NuaGlibClass *nua_glib_class){ GObjectClass *gobject_class = G_OBJECT_CLASS(nua_glib_class); GParamSpec *param_spec; gobject_class->constructor = nua_glib_constructor; gobject_class->dispose = nua_glib_dispose; gobject_class->finalize = nua_glib_finalize; gobject_class->set_property = nua_glib_set_property; gobject_class->get_property = nua_glib_get_property; param_spec = g_param_spec_string("address", "NuaGlib construction property", "The address-of-record for this UA (e.g. 'sip:first.surname@myprovider.com')", "no-address-set", /*default value*/ G_PARAM_READWRITE | G_PARAM_CONSTRUCT); g_object_class_install_property (gobject_class, PROP_ADDRESS, param_spec); param_spec = g_param_spec_string("password", "NuaGlib construction property", "SIP account password", NULL, /*default value*/ G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_PASSWORD, param_spec); param_spec = g_param_spec_string("contact", "NuaGlib construction property", "local bind interface (e.g. 'sip:0.0.0.0:*') [optional]", NULL, /*default value*/ G_PARAM_READWRITE ); g_object_class_install_property (gobject_class, PROP_CONTACT, param_spec); param_spec = g_param_spec_string("proxy", "NuaGlib construction property", "SIP outgoing proxy URI (e.g. 'sip:sipproxy.myprovider.com') [optional]", NULL, /*default value*/ G_PARAM_READWRITE ); g_object_class_install_property (gobject_class, PROP_PROXY, param_spec); param_spec = g_param_spec_string("registrar", "NuaGlib construction property", "SIP registrar URI (e.g. 'sip:sip.myprovider.com') [optional]", NULL, /*default value*/ G_PARAM_READWRITE ); g_object_class_install_property (gobject_class, PROP_REGISTRAR, param_spec); param_spec = g_param_spec_string("stun-server", "NuaGlib construction property", "STUN server address (FQDN or dotted-decimal) [optional]", "", /*default value*/ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (gobject_class, PROP_STUN_SERVER, param_spec); /** * NuaGlib::call-forked: * @nua_glib: the object that received the signal * @op: pointer to the operation representing the call that was forked * @status: SIP status of fork (see SIP RFC) * @phrase: Reason for fork * * Emitted when an outgoing call has been forked. * This is when an INVITE request is answered with multiple 200 responses. */ signals[NGSIG_CALL_FORKED] = g_signal_new("call-forked", G_OBJECT_CLASS_TYPE (nua_glib_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, nua_glib_marshal_VOID__POINTER_INT_STRING, G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_STRING); /** * NuaGlib::incoming-invite: * @nua_glib: the object that received the signal * @op: pointer to the operation created to represent this call * @display: the display name of the invite recipient * @url: the url of the invite recipient * @subject: the subject of the invite (can be NULL) * * Emitted when an call invite is received * Should be answered with nua_glib_answer or nua_glib_decline */ signals[NGSIG_INCOMING_INVITE] = g_signal_new("incoming-invite", G_OBJECT_CLASS_TYPE (nua_glib_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, nua_glib_marshal_VOID__POINTER_STRING_STRING_STRING, G_TYPE_NONE, 4, G_TYPE_POINTER , G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); /** * NuaGlib::incoming-reinvite: * @nua_glib: the object that received the signal * @op: pointer to the operation representing the existing call * * Emitted when an call invite is received for a call already in progress * Usually represents */ signals[NGSIG_INCOMING_REINVITE] = g_signal_new("incoming-reinvite", G_OBJECT_CLASS_TYPE (nua_glib_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * NuaGlib::call-state-changed: * @nua_glib: the object that received the signal * @op: pointer to the operation representing the existing call * @audio: #NuaGlibMediaActive describing audio availiablity * @video: #NuaGlibMediaActive describing video availiablity * @image: #NuaGlibMediaActive describing image availiablity * @chat: #NuaGlibMediaActive describing chat availiablity * @l_sdp: String containing any new local caps as SDP, can be NULL * @r_sdp: String containing any new remote cap as SDP, can be NULL * * Emitted when call state changes.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -