📄 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> */#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{ CALL_FORKED, INCOMING_INVITE, INCOMING_REINVITE, CALL_STATE_CHANGED, INCOMING_ACTIVE, CALL_TERMINATED, INCOMING_PRACK, INCOMING_BYE, INCOMING_CANCEL, INCOMING_MESSAGE, INCOMING_INFO, INCOMING_REFER, INCOMING_NOTIFY, ERROR, SHUTDOWN, REGISTER_ANSWERED, UNREGISTER_ANSWERED, PUBLISH_ANSWERED, INVITE_ANSWERED, BYE_ANSWERED, MESSAGE_ANSWERED, INFO_ANSWERED, REFER_ANSWERED, SUBSCRIBE_ANSWERED, UNSUBSCRIBE_ANSWERED, NOTIFY_ANSWERED, OPTIONS_ANSWERED, MEDIA_ANSWERED, GET_ANSWERED, LAST_SIGNAL};static guint signals[LAST_SIGNAL] = {0};enum{ PROP_CONTACT = 1, PROP_ADDRESS, PROP_PROXY, PROP_REGISTRAR, PROP_AUTHINFO, PROP_STUN, PROP_SIP_BIND_ADDR, 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 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"), NUTAG_MEDIA_ENABLE(1), TAG_IF(self->priv->bind_addr, NUTAG_URL(self->priv->bind_addr)), TAG_IF(self->priv->stun, STUNTAG_SERVER(self->priv->stun)), TAG_IF(self->priv->contact, NUTAG_URL(self->priv->contact)), /* NUTAG_MEDIA_ADDRESS(self->priv->media), */ /* SOATAG_USER_SDP_STR(local_caps), */ TAG_NULL()); if (self->priv->nua) { int min_se = 0; int s_e = 0; if (getenv("MIN_SE")) min_se = atoi(getenv("MIN_SE")); if (getenv("SESSION_EXPIRES")) s_e = atoi(getenv("SESSION_EXPIRES")); /* XXX: fix getenvs */ 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); self->priv->authinfo = g_strdup("");}static voidnua_glib_dispose(GObject *obj){ NuaGlib *self = NUA_GLIB(obj); if (self->priv->init) { g_free((gpointer)self->priv->contact); g_free((gpointer)self->priv->authinfo); 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_CONTACT: { STORE_PARAM(self, contact); break; } case PROP_ADDRESS: { if (self->priv->nua) { nua_set_params(self->priv->nua, SIPTAG_FROM_STR(g_value_get_string (value)), 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_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_AUTHINFO: { STORE_PARAM(self, authinfo); break; } case PROP_STUN: { STORE_PARAM(self, stun); break; } case PROP_SIP_BIND_ADDR: { STORE_PARAM(self, bind_addr); 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_CONTACT: { g_value_set_string (value, self->priv->contact); break; } case PROP_ADDRESS: { g_value_set_string (value, self->priv->address); 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_AUTHINFO: { g_value_set_string (value, self->priv->authinfo); 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("contact", "NuaGlib construction property", "The contact url for this UA", NULL, /*default value*/ G_PARAM_READWRITE ); g_object_class_install_property (gobject_class, PROP_CONTACT, param_spec); param_spec = g_param_spec_string("address", "NuaGlib construction property", "The address-of-contact for this UA", "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("proxy", "NuaGlib construction property", "The SIP proxy to use", 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", "The SIP registrar to use", NULL, /*default value*/ G_PARAM_READWRITE ); g_object_class_install_property (gobject_class, PROP_REGISTRAR, param_spec); param_spec = g_param_spec_string("authinfo", "NuaGlib construction property", "Authorization info of form:" "basic digest scheme:\"realm\":user:password ", NULL, /*default value*/ G_PARAM_READWRITE ); g_object_class_install_property (gobject_class, PROP_AUTHINFO, param_spec); param_spec = g_param_spec_string("stun", "NuaGlib construction property", "STUN server address", "", /*default value*/ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (gobject_class, PROP_STUN, param_spec); param_spec = g_param_spec_string("bind_address", "NuaGlib construction property", "Bind address (i.e. sip:[::]:*) for SIP stack", "", /*default value*/ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property(gobject_class, PROP_SIP_BIND_ADDR, 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[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[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[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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -