summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2007-04-19 17:17:02 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2007-04-19 17:17:02 +0000
commit90720ee40eb30e2b1c9aa90501391d3a0a411250 (patch)
treee52f63ce4a4144d227f385123fd1ba84e121bdfc
parent3a7f26b9857e9077635aba41e20a590e448bfe11 (diff)
Remove src, data, tests and Gabble-specific parts of configure.ac
-rw-r--r--Makefile.am5
-rw-r--r--configure.ac73
-rw-r--r--data/.git-darcs-dir0
-rw-r--r--data/Makefile.am22
-rw-r--r--data/org.freedesktop.Telepathy.ConnectionManager.gabble.service.in3
-rw-r--r--src/.git-darcs-dir0
-rw-r--r--src/Makefile.am140
-rw-r--r--src/base64.c196
-rw-r--r--src/base64.h28
-rw-r--r--src/capabilities.c100
-rw-r--r--src/capabilities.h81
-rw-r--r--src/conn-aliasing.c378
-rw-r--r--src/conn-aliasing.h33
-rw-r--r--src/conn-avatars.c669
-rw-r--r--src/conn-avatars.h34
-rw-r--r--src/conn-presence.c710
-rw-r--r--src/conn-presence.h36
-rw-r--r--src/debug.c73
-rw-r--r--src/debug.h70
-rw-r--r--src/disco.c919
-rw-r--r--src/disco.h139
-rw-r--r--src/gabble-connection-manager.c286
-rw-r--r--src/gabble-connection-manager.h65
-rw-r--r--src/gabble-connection.c2809
-rw-r--r--src/gabble-connection.h177
-rw-r--r--src/gabble-error.c426
-rw-r--r--src/gabble-error.h85
-rw-r--r--src/gabble-im-channel.c606
-rw-r--r--src/gabble-im-channel.h74
-rw-r--r--src/gabble-media-channel.c1466
-rw-r--r--src/gabble-media-channel.h105
-rw-r--r--src/gabble-media-session.c2928
-rw-r--r--src/gabble-media-session.h170
-rw-r--r--src/gabble-media-stream.c1719
-rw-r--r--src/gabble-media-stream.h143
-rw-r--r--src/gabble-muc-channel.c2807
-rw-r--r--src/gabble-muc-channel.h89
-rw-r--r--src/gabble-register.c548
-rw-r--r--src/gabble-register.h67
-rw-r--r--src/gabble-roomlist-channel.c712
-rw-r--r--src/gabble-roomlist-channel.h69
-rw-r--r--src/gabble-roster-channel.c641
-rw-r--r--src/gabble-roster-channel.h69
-rw-r--r--src/gabble-signals-marshal.list7
-rw-r--r--src/gabble-types.h45
-rw-r--r--src/gabble.c50
-rw-r--r--src/gabble.h31
-rw-r--r--src/im-factory.c483
-rw-r--r--src/im-factory.h62
-rw-r--r--src/libmd5-rfc/.git-darcs-dir0
-rw-r--r--src/libmd5-rfc/md5.c381
-rw-r--r--src/libmd5-rfc/md5.h91
-rw-r--r--src/libmd5-rfc/md5main.c139
-rw-r--r--src/media-factory.c875
-rw-r--r--src/media-factory.h69
-rw-r--r--src/muc-factory.c1004
-rw-r--r--src/muc-factory.h59
-rw-r--r--src/namespaces.h66
-rw-r--r--src/presence-cache.c1266
-rw-r--r--src/presence-cache.h84
-rw-r--r--src/presence.c429
-rw-r--r--src/presence.h106
-rw-r--r--src/roster.c2345
-rw-r--r--src/roster.h92
-rw-r--r--src/sha1/.git-darcs-dir0
-rw-r--r--src/sha1/sha1.c626
-rw-r--r--src/sha1/sha1.h72
-rw-r--r--src/text-mixin.c378
-rw-r--r--src/text-mixin.h64
-rw-r--r--src/util.c491
-rw-r--r--src/util.h54
-rw-r--r--src/vcard-manager.c1470
-rw-r--r--src/vcard-manager.h130
-rw-r--r--src/write-mgr-file.c103
-rw-r--r--tests/.git-darcs-dir0
-rw-r--r--tests/Makefile.am65
-rw-r--r--tests/dbustesting.py609
-rw-r--r--tests/exec-with-log.sh.in9
-rw-r--r--tests/org.freedesktop.Telepathy.ConnectionManager.gabble.service.in3
-rw-r--r--tests/run-with-tmp-session-bus.conf.in30
-rw-r--r--tests/run-with-tmp-session-bus.sh49
-rw-r--r--tests/test-base64.c98
-rw-r--r--tests/test-basic-connect.py90
-rw-r--r--tests/test-basic-connect.sh2
-rw-r--r--tests/test-gabble-presence.c137
-rw-r--r--tests/test-handles.c109
86 files changed, 24 insertions, 32019 deletions
diff --git a/Makefile.am b/Makefile.am
index 6fb4646a7..2dc007505 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = lib src data m4 tests
+SUBDIRS = lib m4
EXTRA_DIST = \
check-coding-style.mk \
@@ -13,6 +13,3 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --disable-debug
dist-hook:
chmod u+w ${distdir}/ChangeLog
if test -d _darcs; then darcs changes >${distdir}/ChangeLog; fi
-
-check-extra: check
- $(MAKE) -C tests check-extra
diff --git a/configure.ac b/configure.ac
index 9724da161..c1578ebf9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,12 +5,14 @@ AC_PREREQ([2.59])
# odd minor -> development series
# even minor -> stable series
# increment micro for each release within a series
-# set gabble_release to 1.
+# set nano_version to 0
+# make the release, tag it
+# set nano_version to 1
-m4_define([gabble_major_version], [0])
-m4_define([gabble_minor_version], [5])
-m4_define([gabble_micro_version], [9])
-m4_define([gabble_nano_version], [1])
+m4_define([tp_glib_major_version], [0])
+m4_define([tp_glib_minor_version], [5])
+m4_define([tp_glib_micro_version], [9])
+m4_define([tp_glib_nano_version], [1])
# If library source has changed since last release, increment revision
# If interfaces have been added, removed or changed since last release,
@@ -23,13 +25,13 @@ m4_define([tp_glib_lt_revision], [0])
m4_define([tp_glib_lt_age], [0])
# Some magic
-m4_define([gabble_base_version],
- [gabble_major_version.gabble_minor_version.gabble_micro_version])
-m4_define([gabble_version],
- [m4_if(gabble_nano_version, 0, [gabble_base_version],
- [gabble_base_version].[gabble_nano_version])])
+m4_define([tp_glib_base_version],
+ [tp_glib_major_version.tp_glib_minor_version.tp_glib_micro_version])
+m4_define([tp_glib_version],
+ [m4_if(tp_glib_nano_version, 0, [tp_glib_base_version],
+ [tp_glib_base_version].[tp_glib_nano_version])])
-AC_INIT([Telepathy Gabble], [gabble_version],
+AC_INIT([Telepathy-GLib], [tp_glib_version],
[https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy])
AC_CONFIG_MACRO_DIR([m4])
@@ -64,7 +66,7 @@ AS_COMPILER_FLAG(-Wno-unused-parameter,
wno_unused_parameter=yes,
wno_unused_parameter=no)
-ifelse(gabble_nano_version, 0, [],
+ifelse(tp_glib_nano_version, 0, [],
[
if test x$werror = xyes; then
ERROR_CFLAGS="$ERROR_CFLAGS -Werror"
@@ -79,29 +81,29 @@ ifelse(gabble_nano_version, 0, [],
AC_SUBST(ERROR_CFLAGS)
AC_ARG_ENABLE(debug,
- AC_HELP_STRING([--disable-debug],[compile without debug code]),
+ AC_HELP_STRING([--disable-debug],[compile without debug code (note that this will disable much of the debug code in all GLib connection managers)]),
enable_debug=$enableval, enable_debug=yes )
AC_ARG_ENABLE(handle-leak-debug,
- AC_HELP_STRING([--enable-handle-leak-debug],[compile with handle leak debugging code]),
+ AC_HELP_STRING([--enable-handle-leak-debug],[compile with handle leak debugging code (the CM should be built with -rdynamic)]),
enable_handle_leak_debug=$enableval, enable_handle_leak_debug=no )
AC_ARG_ENABLE(backtrace,
- AC_HELP_STRING([--enable-backtrace],[enable printing out the backtrace in case of crash]),
+ AC_HELP_STRING([--enable-backtrace],[enable printing out the backtrace in case of crash (in most GLib connection managers)]),
enable_backtrace=$enableval, enable_backtrace=no )
AC_ARG_ENABLE(coverage,
AC_HELP_STRING([--enable-coverage],[compile with coverage info]),
enable_coverage=$enableval, enable_coverage=no )
-ifelse(gabble_nano_version, 0,
- [ # Gabble is version x.y.z - disable coding style checks by default
+ifelse(tp_glib_nano_version, 0,
+ [ # tp-glib is version x.y.z - disable coding style checks by default
AC_ARG_ENABLE(coding-style-checks,
AC_HELP_STRING([--enable-coding-style-checks],
[check coding style using grep]),
[ENABLE_CODING_STYLE_CHECKS=$enableval], [ENABLE_CODING_STYLE_CHECKS=no] )
],
- [ # Gabble is version x.y.z.1 - enable coding style checks by default
+ [ # tp-glib is version x.y.z.1 - enable coding style checks by default
AC_ARG_ENABLE(coding-style-checks,
AC_HELP_STRING([--disable-coding-style-checks],
[don't check coding style using grep]),
@@ -130,14 +132,11 @@ AC_SUBST(COVERAGE_CFLAGS)
AC_SUBST([ENABLE_CODING_STYLE_CHECKS])
-dnl lib/docs/Makefile.am needs to know whether it's an out of tree build
+dnl docs/Makefile.am needs to know whether it's an out of tree build
dnl (srcdir != builddir)
AM_CONDITIONAL([OUT_OF_TREE_BUILD], [test "z$ac_srcdir" != z.])
-dnl Endianness (for the sha1 implementation)
-AC_C_BIGENDIAN
-
-dnl Check for Glib
+dnl Check for Glib
PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.4, gobject-2.0 >= 2.4])
AC_SUBST(GLIB_CFLAGS)
@@ -152,11 +151,6 @@ PKG_CHECK_MODULES(DBUS, [dbus-1 >= 0.61, dbus-glib-1 >= 0.72])
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
-AS_AC_EXPAND(DATADIR, $datadir)
-DBUS_SERVICES_DIR="$DATADIR/dbus-1/services"
-AC_SUBST(DBUS_SERVICES_DIR)
-AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [DBus services directory])
-
dnl Check for code generation tools
XSLTPROC=
AC_CHECK_PROGS([XSLTPROC], [xsltproc])
@@ -174,24 +168,6 @@ if test -z "$PYTHON"; then
AC_MSG_ERROR([Python is required to compile this package])
fi
-dnl Check for Loudmouth
-AC_ARG_ENABLE(loudmouth-versioning,
- AC_HELP_STRING([--disable-loudmouth-versioning],
- [Stops configure checking the version of loudmouth to use.]),
- enable_loudmouth_versioning=$enableval,
- enable_loudmouth_versioning=yes)
-
-if test x$enable_loudmouth_versioning = xyes; then
- LOUDMOUTH_VERSION_STR=" >= 1.1.1"
-else
- LOUDMOUTH_VERSION_STR=""
-fi
-
-PKG_CHECK_MODULES(LOUDMOUTH, loudmouth-1.0$LOUDMOUTH_VERSION_STR)
-
-AC_SUBST(LOUDMOUTH_CFLAGS)
-AC_SUBST(LOUDMOUTH_LIBS)
-
dnl glibc backtrace functions
AC_CHECK_FUNCS(backtrace backtrace_symbols_fd)
AC_CHECK_HEADERS(execinfo.h)
@@ -211,8 +187,5 @@ AC_OUTPUT( Makefile \
lib/tests/Makefile \
lib/tools/Makefile \
lib/tools/update-spec-gen-am.sh \
- src/Makefile \
- m4/Makefile \
- data/Makefile \
- tests/Makefile
+ m4/Makefile \
)
diff --git a/data/.git-darcs-dir b/data/.git-darcs-dir
deleted file mode 100644
index e69de29bb..000000000
--- a/data/.git-darcs-dir
+++ /dev/null
diff --git a/data/Makefile.am b/data/Makefile.am
deleted file mode 100644
index e9ecced9c..000000000
--- a/data/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-# Telepathy manager file
-managerdir = $(datadir)/telepathy/managers
-manager_DATA = gabble.manager
-
-# Dbus service file
-servicedir = $(DBUS_SERVICES_DIR)
-service_in_files = org.freedesktop.Telepathy.ConnectionManager.gabble.service.in
-service_DATA = $(service_in_files:.service.in=.service)
-
-BUILT_FILES = $(service_DATA) $(manager_DATA)
-
-CLEANFILES = $(BUILT_FILES)
-
-EXTRA_DIST = $(service_in_files)
-
-# Rule to make the service file with bindir expanded
-$(service_DATA): $(service_in_files) Makefile
- @sed -e "s|\@bindir\@|$(bindir)|" $< > $@
-
-$(manager_DATA): ../src/gabble-connection-manager.c ../src/write-mgr-file.c
- $(MAKE) -C ../src write-mgr-file
- ../src/write-mgr-file > $@
diff --git a/data/org.freedesktop.Telepathy.ConnectionManager.gabble.service.in b/data/org.freedesktop.Telepathy.ConnectionManager.gabble.service.in
deleted file mode 100644
index 1988259cc..000000000
--- a/data/org.freedesktop.Telepathy.ConnectionManager.gabble.service.in
+++ /dev/null
@@ -1,3 +0,0 @@
-[D-BUS Service]
-Name=org.freedesktop.Telepathy.ConnectionManager.gabble
-Exec=@bindir@/telepathy-gabble
diff --git a/src/.git-darcs-dir b/src/.git-darcs-dir
deleted file mode 100644
index e69de29bb..000000000
--- a/src/.git-darcs-dir
+++ /dev/null
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 8cbc7db10..000000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,140 +0,0 @@
-BUILT_SOURCES = \
- gabble-media-session-enumtypes.h \
- gabble-media-session-enumtypes.c \
- gabble-signals-marshal.h \
- gabble-signals-marshal.c
-
-CLEANFILES = $(BUILT_SOURCES)
-
-bin_PROGRAMS=telepathy-gabble
-noinst_PROGRAMS = write-mgr-file
-
-# These are the bits we wrote, so we can be really strict about coding style
-libgabble_convenience_la_our_sources = \
- base64.h \
- base64.c \
- capabilities.h \
- capabilities.c \
- conn-aliasing.h \
- conn-aliasing.c \
- conn-avatars.h \
- conn-avatars.c \
- conn-presence.h \
- conn-presence.c \
- debug.h \
- debug.c \
- disco.h \
- disco.c \
- gabble-error.c \
- gabble-error.h \
- gabble-connection-manager.h \
- gabble-connection-manager.c \
- gabble-connection.h \
- gabble-connection.c \
- gabble-im-channel.h \
- gabble-im-channel.c \
- gabble-muc-channel.h \
- gabble-muc-channel.c \
- gabble-media-channel.h \
- gabble-media-channel.c \
- gabble-media-session.h \
- gabble-media-session.c \
- gabble-media-stream.h \
- gabble-media-stream.c \
- gabble-register.c \
- gabble-register.h \
- gabble-roster-channel.h \
- gabble-roster-channel.c \
- gabble-roomlist-channel.h \
- gabble-roomlist-channel.c \
- gabble-types.h \
- im-factory.h \
- im-factory.c \
- media-factory.h \
- media-factory.c \
- muc-factory.h \
- muc-factory.c \
- namespaces.h \
- presence.h \
- presence.c \
- presence-cache.h \
- presence-cache.c \
- roster.h \
- roster.c \
- text-mixin.h \
- text-mixin.c \
- util.h \
- util.c \
- vcard-manager.h \
- vcard-manager.c \
- gabble-signals-marshal.list
-
-# we don't want to subject third-party source to whitespace removal -
-# it's more useful to keep it a verbatim copy
-libgabble_convenience_la_SOURCES = \
- libmd5-rfc/md5.c \
- libmd5-rfc/md5.h \
- sha1/sha1.h \
- sha1/sha1.c \
- $(libgabble_convenience_la_our_sources)
-
-nodist_libgabble_convenience_la_SOURCES = \
- $(BUILT_SOURCES)
-
-write_mgr_file_SOURCES = write-mgr-file.c
-
-write_mgr_file_LDADD = libgabble-convenience.la \
- $(top_builddir)/lib/telepathy-glib/libtelepathy-glib.la
-
-telepathy_gabble_SOURCES = \
- gabble.h \
- gabble.c
-
-check_c_sources = \
- $(telepathy_gabble_SOURCES) \
- $(libgabble_convenience_la_our_sources) \
- $(telepathy_gabble_SOURCES) \
- $(write_mgr_file_SOURCES)
-include $(top_srcdir)/check-coding-style.mk
-
-telepathy_gabble_LDADD = libgabble-convenience.la \
- $(top_builddir)/lib/telepathy-glib/libtelepathy-glib.la
-
-noinst_LTLIBRARIES = libgabble-convenience.la
-
-AM_CFLAGS = $(ERROR_CFLAGS) -I$(top_srcdir)/lib -I$(top_builddir)/lib \
- @DBUS_CFLAGS@ @GLIB_CFLAGS@ @LOUDMOUTH_CFLAGS@ \
- @HANDLE_LEAK_DEBUG_CFLAGS@ @COVERAGE_CFLAGS@
-AM_LDFLAGS = @DBUS_LIBS@ @GLIB_LIBS@ @LOUDMOUTH_LIBS@
-
-
-%-signals-marshal.h: %-signals-marshal.list
- glib-genmarshal --header --prefix=$(subst -,_,$*)_marshal $< > $*-signals-marshal.h
-
-%-signals-marshal.c: %-signals-marshal.list
- glib-genmarshal --body --prefix=$(subst -,_,$*)_marshal $< > $*-signals-marshal.c
-
-%-marshal.h: %-marshal.list
- glib-genmarshal --header --prefix=$(subst -,_,$*)_marshal $< > $*-marshal.h
-
-%-marshal.c: %-marshal.list
- glib-genmarshal --body --prefix=$(subst -,_,$*)_marshal $< > $*-marshal.c
-
-
-# rules for making the glib enum objects
-%-enumtypes.h: %.h Makefile.in
- glib-mkenums \
- --fhead "#ifndef __$(shell echo $* | tr [:lower:]- [:upper:]_)_ENUM_TYPES_H__\n#define __$(shell echo $* | tr [:lower:]- [:upper:]_)_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
- --fprod "/* enumerations from \"@filename@\" */\n" \
- --vhead "GType @enum_name@_get_type (void);\n#define $(shell echo $* | tr [:lower:]- [:upper:]_ | sed 's/_.*//')_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
- --ftail "G_END_DECLS\n\n#endif /* __$(shell echo $* | tr [:lower:]- [:upper:]_)_ENUM_TYPES_H__ */" \
- $< > $@
-
-%-enumtypes.c: %.h Makefile.in
- glib-mkenums \
- --fhead "#include <$*.h>\n#include <$*-enumtypes.h>" \
- --fprod "\n/* enumerations from \"@filename@\" */" \
- --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
- --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@VALUENAME@\" }," \
- --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
- $< > $@
diff --git a/src/base64.c b/src/base64.c
deleted file mode 100644
index 2010da1f6..000000000
--- a/src/base64.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * base64.c - Base 64 encoding/decoding implementation
- * Copyright (C) 2006 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
- */
-
-#include "base64.h"
-
-#define DEBUG_FLAG GABBLE_DEBUG_VCARD
-#include "debug.h"
-
-#include <ctype.h>
-#include <string.h>
-
-#include <glib.h>
-
-/*
-|AAAA AABB|BBBB CCCC|CCDD DDDD|
-
-0xFC = 1111 1100
-0x03 = 0000 0011
-0xF0 = 1111 0000
-0x0F = 0000 1111
-0xC0 = 1100 0000
-0x3F = 0011 1111
-
-3 input bytes = 4 output bytes;
-2 input bytes = 2 output bytes;
-1 input byte = 1 output byte.
-*/
-
-static const gchar *encoding =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static const guint decoding[256] =
-{
- /* ... */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,
- /* + */
- 62,
- /* ... */
- 0, 0, 0,
- /* / , 0-9 */
- 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
- /* ... */
- 0, 0, 0, 0, 0, 0, 0,
- /* A */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- /* ... */
- 0, 0, 0, 0, 0, 0,
- /* a */
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
-};
-
-#define GET_6_BITS_0(s) (((s)[0] & 0xFC) >> 2)
-#define GET_6_BITS_1(s) (((s)[0] & 0x03) << 4) | \
- (((s)[1] & 0xF0) >> 4)
-#define GET_6_BITS_2(s) (((s)[1] & 0x0F) << 2) | \
- (((s)[2] & 0xC0) >> 6)
-#define GET_6_BITS_3(s) (((s)[2] & 0x3F) << 0)
-
-#define GET_BYTE_0(s) (((decoding[(guchar)(s)[0]] & 0x3F) << 2) | \
- ((decoding[(guchar)(s)[1]] & 0x30) >> 4))
-#define GET_BYTE_1(s) (((decoding[(guchar)(s)[1]] & 0x0F) << 4) | \
- ((decoding[(guchar)(s)[2]] & 0x3C) >> 2))
-#define GET_BYTE_2(s) (((decoding[(guchar)(s)[2]] & 0x03) << 6) | \
- ((decoding[(guchar)(s)[3]] & 0xFF) << 0))
-
-gchar *base64_encode (const GString *str)
-{
- guint i;
- guint len;
- GString *tmp;
-
- len = str->len;
- /* TODO: calculate requisite output string length and allocate that big a
- * GString */
- tmp = g_string_new ("");
-
- for (i = 0; i < len; i += 3)
- {
- guint c1, c2, c3, c4;
-
- if (i > 0 && (i * 4) % 76 == 0)
- g_string_append_c (tmp, '\n');
-
- switch (i + 3 - len)
- {
- case 1:
- c1 = encoding[GET_6_BITS_0 (str->str + i)];
- c2 = encoding[GET_6_BITS_1 (str->str + i)];
- c3 = encoding[GET_6_BITS_2 (str->str + i)];
- c4 = '=';
- break;
- case 2:
- c1 = encoding[GET_6_BITS_0 (str->str + i)];
- c2 = encoding[GET_6_BITS_1 (str->str + i)];
- c3 = '=';
- c4 = '=';
- break;
- default:
- c1 = encoding[GET_6_BITS_0 (str->str + i)];
- c2 = encoding[GET_6_BITS_1 (str->str + i)];
- c3 = encoding[GET_6_BITS_2 (str->str + i)];
- c4 = encoding[GET_6_BITS_3 (str->str + i)];
- }
-
- g_string_append_printf (tmp, "%c%c%c%c", c1, c2, c3, c4);
- }
-
- return g_string_free (tmp, FALSE);
-}
-
-GString *base64_decode (const gchar *str)
-{
- guint i;
- GString *tmp;
- char group[4];
- guint filled = 0;
-
- for (i = 0; str[i]; i++)
- {
- if (str[i] != 'A' &&
- str[i] != '=' &&
- !isspace (str[i]) &&
- decoding[(guchar) str[i]] == 0)
- {
- DEBUG ("bad character %x at byte %u", (guchar)str[i], i);
- return NULL;
- }
- }
-
- tmp = g_string_new ("");
-
- for (i = 0; str[i]; i++)
- {
- if (isspace (str[i]))
- continue;
-
- group[filled++] = str[i];
-
- if (filled == 4)
- {
- if (group[3] == '=')
- {
- if (group[2] == '=')
- {
- g_string_append_c (tmp, GET_BYTE_0(group));
- }
- else
- {
- g_string_append_c (tmp, GET_BYTE_0(group));
- g_string_append_c (tmp, GET_BYTE_1(group));
- }
- }
- else
- {
- g_string_append_c (tmp, GET_BYTE_0(group));
- g_string_append_c (tmp, GET_BYTE_1(group));
- g_string_append_c (tmp, GET_BYTE_2(group));
- }
- filled = 0;
- }
- }
-
- if (filled)
- {
- DEBUG ("insufficient padding at end of base64 string:\n%s", str);
- g_string_free (tmp, TRUE);
- return NULL;
- }
-
- return tmp;
-}
-
-
diff --git a/src/base64.h b/src/base64.h
deleted file mode 100644
index d73b50ca6..000000000
--- a/src/base64.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * base64.h - Base 64 encoding/decoding implementation
- * Copyright (C) 2006 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
- */
-
-#ifndef __BASE64_H__
-#define __BASE64_H__
-
-#include <glib.h>
-
-gchar *base64_encode (const GString *str);
-GString *base64_decode (const gchar *str);
-
-#endif /* __BASE64_H__ */
diff --git a/src/capabilities.c b/src/capabilities.c
deleted file mode 100644
index 926b1c3ea..000000000
--- a/src/capabilities.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * capabilities.c - Connection.Interface.Capabilities constants and utilities
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#include "capabilities.h"
-
-#include "namespaces.h"
-#include "config.h"
-#include "presence-cache.h"
-#include <telepathy-glib/interfaces.h>
-#include "gabble-media-channel.h"
-
-static const Feature self_advertised_features[] =
-{
- { VERSION, NS_GOOGLE_FEAT_SESSION, 0},
- { VERSION, NS_GOOGLE_TRANSPORT_P2P, PRESENCE_CAP_GOOGLE_TRANSPORT_P2P},
- { VERSION, NS_JINGLE, PRESENCE_CAP_JINGLE},
- { VERSION, NS_CHAT_STATES, PRESENCE_CAP_CHAT_STATES},
-
- { BUNDLE_VOICE_V1, NS_GOOGLE_FEAT_VOICE, PRESENCE_CAP_GOOGLE_VOICE},
- { BUNDLE_JINGLE_AUDIO, NS_JINGLE_DESCRIPTION_AUDIO,
- PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO},
- { BUNDLE_JINGLE_VIDEO, NS_JINGLE_DESCRIPTION_VIDEO,
- PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO},
- { NULL, NULL, 0}
-};
-
-GSList *
-capabilities_get_features (GabblePresenceCapabilities caps)
-{
- GSList *features = NULL;
- const Feature *i;
-
- for (i = self_advertised_features; NULL != i->ns; i++)
- if ((i->caps & caps) == i->caps)
- features = g_slist_append (features, (gpointer) i);
-
- return features;
-}
-
-void
-capabilities_fill_cache (GabblePresenceCache *cache)
-{
- const Feature *feat;
- for (feat = self_advertised_features; NULL != feat->ns; feat++)
- {
- gchar *node = g_strconcat (NS_GABBLE_CAPS "#", feat->bundle, NULL);
- gabble_presence_cache_add_bundle_caps (cache,
- node, feat->caps);
- g_free (node);
- }
-
- gabble_presence_cache_add_bundle_caps (cache,
- "http://www.google.com/xmpp/client/caps#voice-v1",
- PRESENCE_CAP_GOOGLE_VOICE);
-}
-
-GabblePresenceCapabilities
-capabilities_get_initial_caps ()
-{
- GabblePresenceCapabilities ret = 0;
- const Feature *feat;
-
- for (feat = self_advertised_features; NULL != feat->ns; feat++)
- {
- if (g_str_equal (feat->bundle, VERSION))
- {
- /* VERSION == bundle means a fixed feature, which we always
- * advertise */
- ret |= feat->caps;
- }
- }
-
- return ret;
-}
-
-const CapabilityConversionData capabilities_conversions[] =
-{
- { TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
- _gabble_media_channel_typeflags_to_caps,
- _gabble_media_channel_caps_to_typeflags },
- { NULL, NULL, NULL}
-};
-
diff --git a/src/capabilities.h b/src/capabilities.h
deleted file mode 100644
index 5c7bfd00b..000000000
--- a/src/capabilities.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * capabilities.h - Connection.Interface.Capabilities constants and utilities
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_CAPABILITIES__H__
-#define __GABBLE_CAPABILITIES__H__
-
-#include <glib-object.h>
-
-#include "presence.h"
-
-#define BUNDLE_VOICE_V1 "voice-v1"
-#define BUNDLE_JINGLE_AUDIO "jingle-audio"
-#define BUNDLE_JINGLE_VIDEO "jingle-video"
-
-typedef struct _Feature Feature;
-
-struct _Feature
-{
- const gchar *bundle;
- const gchar *ns;
- GabblePresenceCapabilities caps;
-};
-
-/*
- * capabilities_get_features
- *
- * Return a linked list of const Feature structs corresponding to the given
- * GabblePresenceCapabilities.
- */
-GSList *
-capabilities_get_features (GabblePresenceCapabilities caps);
-
-/*
- * capabilities_fill_cache
- *
- * Fill up the given GabblePresenceCache with known feature nodes
- */
-void
-capabilities_fill_cache (GabblePresenceCache *cache);
-
-/*
- * capabilities_get_initial_caps
- *
- * Return the GabblePresenceCapabilities we always have
- */
-GabblePresenceCapabilities
-capabilities_get_initial_caps ();
-
-typedef GabblePresenceCapabilities (*TypeFlagsToCapsFunc) (guint typeflags);
-typedef guint (*CapsToTypeFlagsFunc) (GabblePresenceCapabilities caps);
-
-typedef struct _CapabilityConversionData CapabilityConversionData;
-
-struct _CapabilityConversionData
-{
- const gchar *iface;
- TypeFlagsToCapsFunc tf2c_fn;
- CapsToTypeFlagsFunc c2tf_fn;
-};
-
-extern const CapabilityConversionData capabilities_conversions[];
-
-#endif /* __GABBLE_CAPABILITIES__H__ */
-
diff --git a/src/conn-aliasing.c b/src/conn-aliasing.c
deleted file mode 100644
index 49138cc42..000000000
--- a/src/conn-aliasing.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * conn-aliasing.c - Gabble connection aliasing interface
- * Copyright (C) 2005-2007 Collabora Ltd.
- * Copyright (C) 2005-2007 Nokia Corporation
- *
- * 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
- */
-
-#include "conn-aliasing.h"
-
-#include <telepathy-glib/svc-connection.h>
-
-#include "gabble-connection.h"
-#include "roster.h"
-#include "vcard-manager.h"
-
-#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION
-
-#include "debug.h"
-
-/**
- * gabble_connection_get_alias_flags
- *
- * Implements D-Bus method GetAliasFlags
- * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_get_alias_flags (TpSvcConnectionInterfaceAliasing *iface,
- DBusGMethodInvocation *context)
-{
- TpBaseConnection *base = TP_BASE_CONNECTION (iface);
-
- g_assert (GABBLE_IS_CONNECTION (base));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- tp_svc_connection_interface_aliasing_return_from_get_alias_flags (
- context, TP_CONNECTION_ALIAS_FLAG_USER_SET);
-}
-
-
-typedef struct _AliasesRequest AliasesRequest;
-
-struct _AliasesRequest
-{
- GabbleConnection *conn;
- DBusGMethodInvocation *request_call;
- guint pending_vcard_requests;
- GArray *contacts;
- GabbleVCardManagerRequest **vcard_requests;
- gchar **aliases;
-};
-
-
-static AliasesRequest *
-aliases_request_new (GabbleConnection *conn,
- DBusGMethodInvocation *request_call,
- const GArray *contacts)
-{
- AliasesRequest *request;
-
- request = g_slice_new0 (AliasesRequest);
- request->conn = conn;
- request->request_call = request_call;
- request->contacts = g_array_new (FALSE, FALSE, sizeof (TpHandle));
- g_array_insert_vals (request->contacts, 0, contacts->data, contacts->len);
- request->vcard_requests =
- g_new0 (GabbleVCardManagerRequest *, contacts->len);
- request->aliases = g_new0 (gchar *, contacts->len + 1);
- return request;
-}
-
-
-static void
-aliases_request_free (AliasesRequest *request)
-{
- guint i;
-
- for (i = 0; i < request->contacts->len; i++)
- {
- if (request->vcard_requests[i] != NULL)
- gabble_vcard_manager_cancel_request (request->conn->vcard_manager,
- request->vcard_requests[i]);
- }
-
- g_array_free (request->contacts, TRUE);
- g_free (request->vcard_requests);
- g_strfreev (request->aliases);
- g_slice_free (AliasesRequest, request);
-}
-
-
-static gboolean
-aliases_request_try_return (AliasesRequest *request)
-{
- if (request->pending_vcard_requests == 0)
- {
- /* FIXME: I'm not entirely sure why gcc warns without this cast from
- * (gchar **) to (const gchar **) */
- tp_svc_connection_interface_aliasing_return_from_request_aliases (
- request->request_call, (const gchar **)request->aliases);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-static void
-aliases_request_vcard_cb (GabbleVCardManager *manager,
- GabbleVCardManagerRequest *request,
- TpHandle handle,
- LmMessageNode *vcard,
- GError *error,
- gpointer user_data)
-{
- AliasesRequest *aliases_request = (AliasesRequest *) user_data;
- GabbleConnectionAliasSource source;
- guint i;
- gboolean found = FALSE;
- gchar *alias = NULL;
-
- g_assert (aliases_request->pending_vcard_requests > 0);
-
- /* The index of the vCard request in the vCard request array is the
- * index of the contact/alias in their respective arrays. */
-
- for (i = 0; i < aliases_request->contacts->len; i++)
- if (aliases_request->vcard_requests[i] == request)
- {
- found = TRUE;
- break;
- }
-
- g_assert (found);
- source = _gabble_connection_get_cached_alias (aliases_request->conn,
- g_array_index (aliases_request->contacts, TpHandle, i), &alias);
- g_assert (source != GABBLE_CONNECTION_ALIAS_NONE);
- g_assert (NULL != alias);
-
- aliases_request->pending_vcard_requests--;
- aliases_request->vcard_requests[i] = NULL;
- aliases_request->aliases[i] = alias;
-
- if (aliases_request_try_return (aliases_request))
- aliases_request_free (aliases_request);
-}
-
-
-/**
- * gabble_connection_request_aliases
- *
- * Implements D-Bus method RequestAliases
- * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-static void
-gabble_connection_request_aliases (TpSvcConnectionInterfaceAliasing *iface,
- const GArray *contacts,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
- guint i;
- AliasesRequest *request;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- request = aliases_request_new (self, context, contacts);
-
- for (i = 0; i < contacts->len; i++)
- {
- TpHandle handle = g_array_index (contacts, TpHandle, i);
- GabbleConnectionAliasSource source;
- GabbleVCardManagerRequest *vcard_request;
- gchar *alias;
-
- source = _gabble_connection_get_cached_alias (self, handle, &alias);
- g_assert (source != GABBLE_CONNECTION_ALIAS_NONE);
- g_assert (NULL != alias);
-
- if (source >= GABBLE_CONNECTION_ALIAS_FROM_VCARD ||
- gabble_vcard_manager_has_cached_alias (self->vcard_manager, handle))
- {
- /* Either the alias we got was from a vCard or better, or we already
- * tried getting an alias from a vcard and failed, so there's no
- * point trying again. */
- request->aliases[i] = alias;
- }
- else
- {
- DEBUG ("requesting vCard for alias of contact %s",
- tp_handle_inspect (contact_handles, handle));
-
- g_free (alias);
-
- if (gabble_vcard_manager_get_cached (self->vcard_manager, handle,
- NULL))
- {
- GabbleConnectionAliasSource source;
- source = _gabble_connection_get_cached_alias (self, handle,
- &alias);
- request->vcard_requests[i] = NULL;
- request->aliases[i] = alias;
- request->pending_vcard_requests++;
- continue;
- }
-
- vcard_request = gabble_vcard_manager_request (self->vcard_manager,
- handle, 0, aliases_request_vcard_cb, request, G_OBJECT (self),
- &error);
-
- if (NULL != error)
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- aliases_request_free (request);
- return;
- }
-
- request->vcard_requests[i] = vcard_request;
- request->pending_vcard_requests++;
- }
- }
-
- if (aliases_request_try_return (request))
- aliases_request_free (request);
-}
-
-
-struct _i_hate_g_hash_table_foreach
-{
- GabbleConnection *conn;
- GError **error;
- gboolean retval;
-};
-
-static void
-setaliases_foreach (gpointer key, gpointer value, gpointer user_data)
-{
- struct _i_hate_g_hash_table_foreach *data =
- (struct _i_hate_g_hash_table_foreach *) user_data;
- TpHandle handle = GPOINTER_TO_INT (key);
- gchar *alias = (gchar *) value;
- GError *error = NULL;
- TpBaseConnection *base = (TpBaseConnection *)data->conn;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
-
- if (!tp_handle_is_valid (contact_handles, handle, &error))
- {
- data->retval = FALSE;
- }
- else if (base->self_handle == handle)
- {
- /* only alter the roster if we're already there, e.g. because someone
- * added us with another client
- */
- if (gabble_roster_handle_has_entry (data->conn->roster, handle)
- && !gabble_roster_handle_set_name (data->conn->roster, handle,
- alias, data->error))
- {
- data->retval = FALSE;
- }
- }
- else if (!gabble_roster_handle_set_name (data->conn->roster, handle, alias,
- data->error))
- {
- data->retval = FALSE;
- }
-
- if (base->self_handle == handle)
- {
- /* User has done SetAliases on themselves - patch their vCard.
- * FIXME: because SetAliases is currently synchronous, we ignore errors
- * here, and just let the request happen in the background
- */
- gabble_vcard_manager_edit (data->conn->vcard_manager, 0, NULL, NULL,
- G_OBJECT(data->conn), NULL, "NICKNAME", alias, NULL);
- }
-
- if (NULL != error)
- {
- if (NULL == *(data->error))
- {
- *(data->error) = error;
- }
- else
- {
- g_error_free (error);
- }
- }
-}
-
-/**
- * gabble_connection_set_aliases
- *
- * Implements D-Bus method SetAliases
- * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing
- */
-static void
-gabble_connection_set_aliases (TpSvcConnectionInterfaceAliasing *iface,
- GHashTable *aliases,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- GError *error = NULL;
- struct _i_hate_g_hash_table_foreach data = { NULL, NULL, TRUE };
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- data.conn = self;
- data.error = &error;
-
- g_hash_table_foreach (aliases, setaliases_foreach, &data);
-
- if (data.retval)
- {
- tp_svc_connection_interface_aliasing_return_from_set_aliases (
- context);
- }
- else
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-}
-
-
-void
-conn_aliasing_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcConnectionInterfaceAliasingClass *klass =
- (TpSvcConnectionInterfaceAliasingClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_connection_interface_aliasing_implement_##x (\
- klass, gabble_connection_##x)
- IMPLEMENT(get_alias_flags);
- IMPLEMENT(request_aliases);
- IMPLEMENT(set_aliases);
-#undef IMPLEMENT
-}
-
diff --git a/src/conn-aliasing.h b/src/conn-aliasing.h
deleted file mode 100644
index 51b1a5591..000000000
--- a/src/conn-aliasing.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * conn-aliasing.h - Header for Gabble connection aliasing interface
- * Copyright (C) 2005-2007 Collabora Ltd.
- * Copyright (C) 2005-2007 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __CONN_ALIASING_H__
-#define __CONN_ALIASING_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-void conn_aliasing_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_END_DECLS
-
-#endif /* __CONN_ALIASING_H__ */
-
diff --git a/src/conn-avatars.c b/src/conn-avatars.c
deleted file mode 100644
index 885f661a0..000000000
--- a/src/conn-avatars.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * conn-avatars.c - Gabble connection avatar interface
- * Copyright (C) 2005-2007 Collabora Ltd.
- * Copyright (C) 2005-2007 Nokia Corporation
- *
- * 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
- */
-
-#include "config.h"
-
-#include "conn-avatars.h"
-
-#include <string.h>
-
-#include <loudmouth/loudmouth.h>
-
-#include <telepathy-glib/svc-connection.h>
-
-#include "base64.h"
-#include "presence.h"
-#include "presence-cache.h"
-#include "namespaces.h"
-#include "sha1/sha1.h"
-#include "vcard-manager.h"
-#include "util.h"
-
-#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION
-
-#include "debug.h"
-
-/* If the SHA1 has changed, this function will copy it to self_presence,
- * emit a signal and push it to the server. */
-static gboolean
-update_own_avatar_sha1 (GabbleConnection *conn,
- const gchar *sha1,
- GError **out_error)
-{
- TpBaseConnection *base = (TpBaseConnection *)conn;
- GError *error = NULL;
-
- if (!tp_strdiff (sha1, conn->self_presence->avatar_sha1))
- return TRUE;
-
- tp_svc_connection_interface_avatars_emit_avatar_updated (conn,
- base->self_handle, sha1);
-
- g_free (conn->self_presence->avatar_sha1);
- conn->self_presence->avatar_sha1 = g_strdup (sha1);
-
- if (!_gabble_connection_signal_own_presence (conn, &error))
- {
- if (out_error == NULL)
- {
- DEBUG ("failed to signal changed avatar sha1 to the server: %s",
- error->message);
- g_error_free (error);
- }
-
- g_propagate_error (out_error, error);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static void
-connection_avatar_update_cb (GabblePresenceCache *cache,
- TpHandle handle,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- TpBaseConnection *base = (TpBaseConnection *)conn;
- GabblePresence *presence;
-
- presence = gabble_presence_cache_get (conn->presence_cache, handle);
-
- g_assert (presence != NULL);
-
- gabble_vcard_manager_invalidate_cache (conn->vcard_manager, handle);
-
- if (handle == base->self_handle)
- update_own_avatar_sha1 (conn, presence->avatar_sha1, NULL);
- else
- tp_svc_connection_interface_avatars_emit_avatar_updated (conn,
- handle, presence->avatar_sha1);
-}
-
-/* Called when our vCard is first fetched, so we can start putting the
- * SHA-1 of an existing avatar in our presence. */
-static void
-connection_got_self_initial_avatar_cb (GObject *obj,
- gchar *sha1,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
-
- update_own_avatar_sha1 (conn, sha1, NULL);
-}
-
-
-/**
- * gabble_connection_get_avatar_requirements
- *
- * Implements D-Bus method GetAvatarRequirements
- * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_get_avatar_requirements (TpSvcConnectionInterfaceAvatars *iface,
- DBusGMethodInvocation *context)
-{
- /* Jabber prescribes no MIME type for avatars, but XEP-0153 says support
- * for image/png is REQUIRED, with image/jpeg and image/gif RECOMMENDED */
- static const char *mimetypes[] = {
- "image/png", "image/jpeg", "image/gif", NULL };
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (TP_BASE_CONNECTION (iface),
- context);
-
- /* Jabber has no min/max width/height or max size, but XEP-0153 says
- * you SHOULD use 32-96px either way, and no more than 8K of data */
-
- tp_svc_connection_interface_avatars_return_from_get_avatar_requirements (
- context, mimetypes, 32, 32, 96, 96, 8192);
-}
-
-
-typedef struct {
- DBusGMethodInvocation *invocation;
- gchar **ret;
- guint my_index;
- gulong signal_conn;
-} GetAvatarTokensContext;
-
-
-static void
-_got_self_avatar_for_get_avatar_tokens (GObject *obj,
- gchar *sha1,
- gpointer user_data)
-{
- GetAvatarTokensContext *context = (GetAvatarTokensContext *) user_data;
-
- g_signal_handler_disconnect (obj, context->signal_conn);
- g_free (context->ret[context->my_index]);
- context->ret[context->my_index] = g_strdup (sha1);
-
- /* FIXME: I'm not entirely sure why gcc warns without this cast from
- * (gchar **) to (const gchar **) */
- tp_svc_connection_interface_avatars_return_from_get_avatar_tokens (
- context->invocation, (const gchar **)context->ret);
- g_strfreev (context->ret);
-
- g_slice_free (GetAvatarTokensContext, context);
-}
-
-
-/**
- * gabble_connection_get_avatar_tokens
- *
- * Implements D-Bus method GetAvatarTokens
- * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-static void
-gabble_connection_get_avatar_tokens (TpSvcConnectionInterfaceAvatars *iface,
- const GArray *contacts,
- DBusGMethodInvocation *invocation)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- gboolean wait_for_self_avatar = FALSE;
- gboolean have_self_avatar;
- guint i, my_index = 0;
- gchar **ret;
- GError *err = NULL;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, invocation);
-
- if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &err))
- {
- dbus_g_method_return_error (invocation, err);
- g_error_free (err);
- return;
- }
-
- g_object_get (self->vcard_manager,
- "have-self-avatar", &have_self_avatar,
- NULL);
-
- ret = g_new0 (gchar *, contacts->len + 1);
-
- /* TODO: always call the callback so we can defer presence lookups until
- * we return the method, then we don't need to strdup the strings we're
- * returning. */
-
- for (i = 0; i < contacts->len; i++)
- {
- TpHandle handle;
- GabblePresence *presence = NULL;
-
- handle = g_array_index (contacts, TpHandle, i);
-
- if (base->self_handle == handle)
- {
- if (have_self_avatar)
- {
- presence = self->self_presence;
- }
- else
- {
- wait_for_self_avatar = TRUE;
- my_index = i;
- }
- }
- else
- {
- presence = gabble_presence_cache_get (self->presence_cache, handle);
- }
-
- if (NULL != presence && NULL != presence->avatar_sha1)
- ret[i] = g_strdup (presence->avatar_sha1);
- else
- ret[i] = g_strdup ("");
- }
-
- if (wait_for_self_avatar)
- {
- GetAvatarTokensContext *context = g_slice_new (GetAvatarTokensContext);
-
- context->invocation = invocation;
- context->my_index = my_index;
- context->ret = ret;
- context->signal_conn = g_signal_connect (self->vcard_manager,
- "got-self-initial-avatar",
- G_CALLBACK (_got_self_avatar_for_get_avatar_tokens),
- context);
-
- return;
- }
-
- /* FIXME: I'm not entirely sure why gcc warns without this cast from
- * (gchar **) to (const gchar **) */
- tp_svc_connection_interface_avatars_return_from_get_avatar_tokens (
- invocation, (const gchar **)ret);
- g_strfreev (ret);
-}
-
-
-static void
-_request_avatar_cb (GabbleVCardManager *self,
- GabbleVCardManagerRequest *request,
- TpHandle handle,
- LmMessageNode *vcard,
- GError *vcard_error,
- gpointer user_data)
-{
- DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
- GabbleConnection *conn;
- TpBaseConnection *base;
- LmMessageNode *photo_node, *type_node, *binval_node;
- const gchar *mime_type, *binval_value;
- GArray *arr;
- GError *error = NULL;
- GString *avatar = NULL;
- GabblePresence *presence;
-
- g_object_get (self, "connection", &conn, NULL);
- base = TP_BASE_CONNECTION (conn);
-
- if (NULL == vcard)
- {
- dbus_g_method_return_error (context, vcard_error);
- goto out;
- }
-
- photo_node = lm_message_node_get_child (vcard, "PHOTO");
-
- if (NULL == photo_node)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "contact vCard has no photo");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- goto out;
- }
-
- type_node = lm_message_node_get_child (photo_node, "TYPE");
-
- if (NULL == type_node)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "contact avatar is missing type node");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- goto out;
- }
-
- binval_node = lm_message_node_get_child (photo_node, "BINVAL");
-
- if (NULL == binval_node)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "contact avatar is missing binval node");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- goto out;
- }
-
- binval_value = lm_message_node_get_value (binval_node);
-
- if (NULL == binval_value)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "contact avatar is missing binval content");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- goto out;
- }
-
- avatar = base64_decode (binval_value);
-
- if (NULL == avatar)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "failed to decode avatar from base64");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- goto out;
- }
-
- if (handle == base->self_handle)
- presence = conn->self_presence;
- else
- presence = gabble_presence_cache_get (conn->presence_cache, handle);
-
- if (presence != NULL)
- {
- gchar *sha1;
-
- sha1 = sha1_hex (avatar->str, avatar->len);
-
- if (tp_strdiff (presence->avatar_sha1, sha1))
- {
- /* the thinking here is that we have to return an error, because we
- * can't give the user the vcard they're expecting, which has the
- * hash from the time that they requested it. */
- DEBUG ("treason uncloaked! avatar hash in presence does not match "
- "avatar in vCard for handle %u", handle);
-
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "avatar hash in presence does not match avatar in vCard");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- error = NULL;
-
- if (handle == base->self_handle)
- {
- update_own_avatar_sha1 (conn, sha1, NULL);
- g_free (sha1);
- }
- else
- {
- g_free (presence->avatar_sha1);
- presence->avatar_sha1 = sha1; /* take ownership */
-
- tp_svc_connection_interface_avatars_emit_avatar_updated (
- conn, handle, sha1);
- }
-
- goto out;
- }
-
- g_free (sha1);
- }
-
- mime_type = lm_message_node_get_value (type_node);
- arr = g_array_new (FALSE, FALSE, sizeof (gchar));
- g_array_append_vals (arr, avatar->str, avatar->len);
- tp_svc_connection_interface_avatars_return_from_request_avatar (
- context, arr, mime_type);
- g_array_free (arr, TRUE);
-
-out:
- if (avatar != NULL)
- g_string_free (avatar, TRUE);
-
- g_object_unref (conn);
-}
-
-
-/**
- * gabble_connection_request_avatar
- *
- * Implements D-Bus method RequestAvatar
- * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-static void
-gabble_connection_request_avatar (TpSvcConnectionInterfaceAvatars *iface,
- guint contact,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
- GError *err = NULL;
- LmMessageNode *vcard_node;
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- if (!tp_handle_is_valid (contact_handles, contact, &err))
- {
- dbus_g_method_return_error (context, err);
- g_error_free (err);
- return;
- }
-
- if (gabble_vcard_manager_get_cached (self->vcard_manager,
- contact, &vcard_node))
- {
- _request_avatar_cb (self->vcard_manager, NULL, contact, vcard_node, NULL,
- context);
- }
- else
- {
- gabble_vcard_manager_request (self->vcard_manager, contact, 0,
- _request_avatar_cb, context, NULL, NULL);
- }
-}
-
-
-struct _set_avatar_ctx {
- GabbleConnection *conn;
- DBusGMethodInvocation *invocation;
- LmMessage *new_vcard_msg;
- GString *avatar;
- gchar *mime_type;
-};
-
-
-static void
-_set_avatar_ctx_free (struct _set_avatar_ctx *ctx)
-{
- lm_message_unref (ctx->new_vcard_msg);
- if (ctx->avatar)
- g_string_free (ctx->avatar, TRUE);
- g_free (ctx->mime_type);
- g_free (ctx);
-}
-
-
-static void
-_set_avatar_cb2 (GabbleVCardManager *manager,
- GabbleVCardManagerRequest *request,
- TpHandle handle,
- LmMessageNode *vcard,
- GError *vcard_error,
- gpointer user_data)
-{
- struct _set_avatar_ctx *ctx = (struct _set_avatar_ctx *) user_data;
- TpBaseConnection *base = (TpBaseConnection *)ctx->conn;
-
- if (NULL == vcard)
- {
- dbus_g_method_return_error (ctx->invocation, vcard_error);
- }
- else
- {
- GabblePresence *presence = ctx->conn->self_presence;
- GError *error = NULL;
-
- g_free (presence->avatar_sha1);
- if (ctx->avatar)
- {
- presence->avatar_sha1 = sha1_hex (ctx->avatar->str,
- ctx->avatar->len);
- }
- else
- {
- presence->avatar_sha1 = NULL;
- }
-
- if (_gabble_connection_signal_own_presence (ctx->conn, &error))
- {
- tp_svc_connection_interface_avatars_return_from_set_avatar (
- ctx->invocation, presence->avatar_sha1);
- tp_svc_connection_interface_avatars_emit_avatar_updated (
- ctx->conn, base->self_handle, presence->avatar_sha1);
- }
- else
- {
- dbus_g_method_return_error (ctx->invocation, error);
- g_error_free (error);
- }
- }
-
- _set_avatar_ctx_free (ctx);
-}
-
-
-static void
-_set_avatar_cb1 (GabbleVCardManager *manager,
- GabbleVCardManagerRequest *request,
- TpHandle handle,
- LmMessageNode *vcard,
- GError *vcard_error,
- gpointer user_data)
-{
- struct _set_avatar_ctx *ctx = (struct _set_avatar_ctx *) user_data;
- LmMessageNode *new_vcard, *photo_node, *type_node, *binval_node, *i, *next;
- gchar *encoded;
-
- if (NULL == vcard)
- {
- dbus_g_method_return_error (ctx->invocation, vcard_error);
- _set_avatar_ctx_free (ctx);
- return;
- }
-
- ctx->new_vcard_msg = lm_message_new (NULL, LM_MESSAGE_TYPE_UNKNOWN);
- new_vcard = lm_message_node_add_child (ctx->new_vcard_msg->node,
- "vCard", "");
- lm_message_node_set_attribute (new_vcard, "xmlns", NS_VCARD_TEMP);
- lm_message_node_steal_children (new_vcard, vcard);
-
- for (i = new_vcard->children; i; i = next)
- {
- next = i->next;
- if (0 == strcmp (i->name, "PHOTO"))
- {
- lm_message_node_unlink (i);
- lm_message_node_unref (i);
- }
- }
-
- photo_node = lm_message_node_add_child (new_vcard, "PHOTO", "");
-
- if (ctx->avatar)
- {
-
- type_node = lm_message_node_get_child (photo_node, "TYPE");
-
- if (NULL == type_node)
- type_node = lm_message_node_add_child (photo_node, "TYPE", "");
-
- lm_message_node_set_value (type_node, ctx->mime_type);
-
- binval_node = lm_message_node_get_child (photo_node, "BINVAL");
-
- if (NULL == binval_node)
- binval_node = lm_message_node_add_child (photo_node, "BINVAL", "");
-
- encoded = base64_encode (ctx->avatar);
- lm_message_node_set_value (binval_node, encoded);
- g_free (encoded);
- }
-
- gabble_vcard_manager_replace (
- manager, new_vcard, 0, _set_avatar_cb2, ctx, NULL, NULL);
-}
-
-
-/**
- * gabble_connection_set_avatar
- *
- * Implements D-Bus method SetAvatar
- * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-static void
-gabble_connection_set_avatar (TpSvcConnectionInterfaceAvatars *iface,
- const GArray *avatar,
- const gchar *mime_type,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- struct _set_avatar_ctx *ctx;
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- ctx = g_new0 (struct _set_avatar_ctx, 1);
- ctx->conn = self;
- ctx->invocation = context;
- if (avatar)
- {
- ctx->avatar = g_string_new_len (avatar->data, avatar->len);
- ctx->mime_type = g_strdup (mime_type);
- }
-
- DEBUG ("called");
- gabble_vcard_manager_invalidate_cache (self->vcard_manager,
- base->self_handle);
- gabble_vcard_manager_request (self->vcard_manager,
- base->self_handle, 0, _set_avatar_cb1, ctx, NULL, NULL);
-}
-
-
-/**
- * gabble_connection_clear_avatar
- *
- * Implements D-Bus method ClearAvatar
- * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-void
-gabble_connection_clear_avatar (TpSvcConnectionInterfaceAvatars *iface,
- DBusGMethodInvocation *context)
-{
- gabble_connection_set_avatar (iface, NULL, NULL, context);
-}
-
-
-void
-conn_avatars_init (GabbleConnection *conn)
-{
- g_signal_connect (conn->vcard_manager, "got-self-initial-avatar", G_CALLBACK
- (connection_got_self_initial_avatar_cb), conn);
- g_signal_connect (conn->presence_cache, "avatar-update", G_CALLBACK
- (connection_avatar_update_cb), conn);
-}
-
-
-void
-conn_avatars_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcConnectionInterfaceAvatarsClass *klass =
- (TpSvcConnectionInterfaceAvatarsClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_connection_interface_avatars_implement_##x (\
- klass, gabble_connection_##x)
- IMPLEMENT(get_avatar_requirements);
- IMPLEMENT(get_avatar_tokens);
- IMPLEMENT(request_avatar);
- IMPLEMENT(set_avatar);
- IMPLEMENT(clear_avatar);
-#undef IMPLEMENT
-}
-
diff --git a/src/conn-avatars.h b/src/conn-avatars.h
deleted file mode 100644
index b40e160e2..000000000
--- a/src/conn-avatars.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * conn-avatars.h - Header for Gabble connection avatar interface
- * Copyright (C) 2005-2007 Collabora Ltd.
- * Copyright (C) 2005-2007 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __CONN_AVATARS_H__
-#define __CONN_AVATARS_H__
-
-#include "gabble-connection.h"
-
-G_BEGIN_DECLS
-
-void conn_avatars_init (GabbleConnection *conn);
-void conn_avatars_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_END_DECLS
-
-#endif /* __CONN_AVATARS_H__ */
-
diff --git a/src/conn-presence.c b/src/conn-presence.c
deleted file mode 100644
index cb3e9490f..000000000
--- a/src/conn-presence.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * conn-presence - Gabble connection presence interface
- * Copyright (C) 2005-2007 Collabora Ltd.
- * Copyright (C) 2005-2007 Nokia Corporation
- *
- * 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
- */
-
-#include "conn-presence.h"
-
-#include <string.h>
-
-#include <telepathy-glib/svc-connection.h>
-#include <telepathy-glib/util.h>
-
-#include "gabble-connection.h"
-#include "presence.h"
-#include "presence-cache.h"
-
-#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION
-
-#include "debug.h"
-
-
-typedef struct _StatusInfo StatusInfo;
-
-struct _StatusInfo
-{
- const gchar *name;
- TpConnectionPresenceType presence_type;
- const gboolean self;
- const gboolean exclusive;
-};
-
-/* order must match PresenceId enum in gabble-connection.h */
-/* in increasing order of presence */
-static const StatusInfo gabble_statuses[NUM_GABBLE_PRESENCES] = {
- { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE, TRUE, TRUE },
- { "hidden", TP_CONNECTION_PRESENCE_TYPE_HIDDEN, TRUE, TRUE },
- { "xa", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, TRUE, TRUE },
- { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY, TRUE, TRUE },
- { "dnd", TP_CONNECTION_PRESENCE_TYPE_AWAY, TRUE, TRUE },
- { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE, TRUE },
- { "chat", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE, TRUE }
-};
-
-
-static GHashTable *
-construct_presence_hash (GabbleConnection *self,
- const GArray *contact_handles)
-{
- TpBaseConnection *base = (TpBaseConnection *)self;
- guint i;
- TpHandle handle;
- GHashTable *presence_hash, *contact_status, *parameters;
- GValueArray *vals;
- GValue *message;
- GabblePresence *presence;
- GabblePresenceId status;
- const gchar *status_message;
- /* this is never set at the moment*/
- guint timestamp = 0;
- TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
-
- g_assert (tp_handles_are_valid (handle_repo, contact_handles, FALSE, NULL));
-
- presence_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- (GDestroyNotify) g_value_array_free);
-
- for (i = 0; i < contact_handles->len; i++)
- {
- handle = g_array_index (contact_handles, TpHandle, i);
-
- if (handle == base->self_handle)
- presence = self->self_presence;
- else
- presence = gabble_presence_cache_get (self->presence_cache, handle);
-
- if (presence)
- {
- status = presence->status;
- status_message = presence->status_message;
- }
- else
- {
- status = GABBLE_PRESENCE_OFFLINE;
- status_message = NULL;
- }
-
- parameters = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) tp_g_value_slice_free);
- if (status_message != NULL) {
- message = g_slice_new0 (GValue);
- g_value_init (message, G_TYPE_STRING);
- g_value_set_static_string (message, status_message);
-
-
- g_hash_table_insert (parameters, "message", message);
- }
-
- contact_status = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) g_hash_table_destroy);
- g_hash_table_insert (contact_status,
- (gchar *) gabble_statuses[status].name, parameters);
-
- vals = g_value_array_new (2);
-
- g_value_array_append (vals, NULL);
- g_value_init (g_value_array_get_nth (vals, 0), G_TYPE_UINT);
- g_value_set_uint (g_value_array_get_nth (vals, 0), timestamp);
-
- g_value_array_append (vals, NULL);
- g_value_init (g_value_array_get_nth (vals, 1),
- dbus_g_type_get_map ("GHashTable", G_TYPE_STRING,
- dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)));
- g_value_take_boxed (g_value_array_get_nth (vals, 1), contact_status);
-
- g_hash_table_insert (presence_hash, GINT_TO_POINTER (handle), vals);
- }
-
- return presence_hash;
-}
-
-
-/**
- * emit_presence_update:
- * @self: A #GabbleConnection
- * @contact_handles: A zero-terminated array of #TpHandle for
- * the contacts to emit presence for
- *
- * Emits the Telepathy PresenceUpdate signal with the current
- * stored presence information for the given contact.
- */
-static void
-emit_presence_update (GabbleConnection *self,
- const GArray *contact_handles)
-{
- GHashTable *presence_hash;
-
- presence_hash = construct_presence_hash (self, contact_handles);
- tp_svc_connection_interface_presence_emit_presence_update (self,
- presence_hash);
- g_hash_table_destroy (presence_hash);
-}
-
-
-/**
- * emit_one_presence_update:
- * Convenience function for calling emit_presence_update with one handle.
- */
-
-static void
-emit_one_presence_update (GabbleConnection *self,
- TpHandle handle)
-{
- GArray *handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1);
-
- g_array_insert_val (handles, 0, handle);
- emit_presence_update (self, handles);
- g_array_free (handles, TRUE);
-}
-
-
-
-
-/**
- * gabble_connection_add_status
- *
- * Implements D-Bus method AddStatus
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_add_status (TpSvcConnectionInterfacePresence *iface,
- const gchar *status,
- GHashTable *parms,
- DBusGMethodInvocation *context)
-{
- TpBaseConnection *self = TP_BASE_CONNECTION (iface);
- GError unimpl = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
- "Only one status is possible at a time with this protocol" };
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (self, context);
-
- dbus_g_method_return_error (context, &unimpl);
-}
-
-
-/**
- * gabble_connection_clear_status
- *
- * Implements D-Bus method ClearStatus
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_clear_status (TpSvcConnectionInterfacePresence *iface,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- GError *error = NULL;
- gboolean ok;
- gchar *resource;
- gint8 priority;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- g_object_get (self,
- "resource", &resource,
- "priority", &priority,
- NULL);
- gabble_presence_update (self->self_presence, resource,
- GABBLE_PRESENCE_AVAILABLE, NULL, priority);
- emit_one_presence_update (self, base->self_handle);
- ok = _gabble_connection_signal_own_presence (self, &error);
-
- if (ok)
- {
- tp_svc_connection_interface_presence_return_from_clear_status (context);
- }
- else
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-
- g_free (resource);
-}
-
-
-/**
- * status_is_available
- *
- * Returns a boolean to indicate whether the given gabble status is
- * available on this connection.
- */
-static gboolean
-status_is_available (GabbleConnection *conn, int status)
-{
- g_assert (GABBLE_IS_CONNECTION (conn));
- g_assert (status < NUM_GABBLE_PRESENCES);
-
- if (gabble_statuses[status].presence_type == TP_CONNECTION_PRESENCE_TYPE_HIDDEN &&
- (conn->features & GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE) == 0)
- return FALSE;
- else
- return TRUE;
-}
-
-
-/**
- * gabble_connection_get_presence
- *
- * Implements D-Bus method GetPresence
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-static void
-gabble_connection_get_presence (TpSvcConnectionInterfacePresence *iface,
- const GArray *contacts,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- GHashTable *presence_hash;
- GError *error = NULL;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
-
- if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-
- presence_hash = construct_presence_hash (self, contacts);
- tp_svc_connection_interface_presence_return_from_get_presence (
- context, presence_hash);
- g_hash_table_destroy (presence_hash);
-}
-
-
-static GHashTable *
-get_statuses_arguments ()
-{
- static GHashTable *arguments = NULL;
-
- if (arguments == NULL)
- {
- arguments = g_hash_table_new (g_str_hash, g_str_equal);
-
- g_hash_table_insert (arguments, "message", "s");
- g_hash_table_insert (arguments, "priority", "n");
- }
-
- return arguments;
-}
-
-
-/**
- * gabble_connection_get_statuses
- *
- * Implements D-Bus method GetStatuses
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_get_statuses (TpSvcConnectionInterfacePresence *iface,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- GHashTable *ret;
- GValueArray *status;
- int i;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- DEBUG ("called.");
-
- ret = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, (GDestroyNotify) g_value_array_free);
-
- for (i=0; i < NUM_GABBLE_PRESENCES; i++)
- {
- /* don't report the invisible presence if the server
- * doesn't have the presence-invisible feature */
- if (!status_is_available (self, i))
- continue;
-
- status = g_value_array_new (5);
-
- g_value_array_append (status, NULL);
- g_value_init (g_value_array_get_nth (status, 0), G_TYPE_UINT);
- g_value_set_uint (g_value_array_get_nth (status, 0),
- gabble_statuses[i].presence_type);
-
- g_value_array_append (status, NULL);
- g_value_init (g_value_array_get_nth (status, 1), G_TYPE_BOOLEAN);
- g_value_set_boolean (g_value_array_get_nth (status, 1),
- gabble_statuses[i].self);
-
- g_value_array_append (status, NULL);
- g_value_init (g_value_array_get_nth (status, 2), G_TYPE_BOOLEAN);
- g_value_set_boolean (g_value_array_get_nth (status, 2),
- gabble_statuses[i].exclusive);
-
- g_value_array_append (status, NULL);
- g_value_init (g_value_array_get_nth (status, 3),
- DBUS_TYPE_G_STRING_STRING_HASHTABLE);
- g_value_set_static_boxed (g_value_array_get_nth (status, 3),
- get_statuses_arguments ());
-
- g_hash_table_insert (ret, (gchar*) gabble_statuses[i].name, status);
- }
-
- tp_svc_connection_interface_presence_return_from_get_statuses (
- context, ret);
- g_hash_table_destroy (ret);
-}
-
-
-/**
- * gabble_connection_remove_status
- *
- * Implements D-Bus method RemoveStatus
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_remove_status (TpSvcConnectionInterfacePresence *iface,
- const gchar *status,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- GabblePresence *presence = self->self_presence;
- GError *error = NULL;
- gchar *resource;
- gint8 priority;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- g_object_get (self,
- "resource", &resource,
- "priority", &priority,
- NULL);
-
- if (strcmp (status, gabble_statuses[presence->status].name) == 0)
- {
- gabble_presence_update (presence, resource,
- GABBLE_PRESENCE_AVAILABLE, NULL, priority);
- emit_one_presence_update (self, base->self_handle);
- if (_gabble_connection_signal_own_presence (self, &error))
- {
- tp_svc_connection_interface_presence_return_from_remove_status (
- context);
- }
- else
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
- }
- else
- {
- GError nonexistent = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Attempting to remove non-existent presence." };
- dbus_g_method_return_error (context, &nonexistent);
- }
-
- g_free (resource);
-}
-
-
-/**
- * gabble_connection_request_presence
- *
- * Implements D-Bus method RequestPresence
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- */
-static void
-gabble_connection_request_presence (TpSvcConnectionInterfacePresence *iface,
- const GArray *contacts,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- GError *error = NULL;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-
- if (contacts->len)
- emit_presence_update (self, contacts);
-
- tp_svc_connection_interface_presence_return_from_request_presence (
- context);
-}
-
-
-/**
- * gabble_connection_set_last_activity_time
- *
- * Implements D-Bus method SetLastActivityTime
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- */
-static void
-gabble_connection_set_last_activity_time (TpSvcConnectionInterfacePresence *iface,
- guint time,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- tp_svc_connection_interface_presence_return_from_set_last_activity_time (
- context);
-}
-
-
-struct _i_hate_g_hash_table_foreach
-{
- GabbleConnection *conn;
- GError **error;
- gboolean retval;
-};
-
-
-static void
-setstatuses_foreach (gpointer key, gpointer value, gpointer user_data)
-{
- struct _i_hate_g_hash_table_foreach *data =
- (struct _i_hate_g_hash_table_foreach*) user_data;
- TpBaseConnection *base = (TpBaseConnection *)data->conn;
- gchar *resource;
- int i;
-
- g_object_get (data->conn, "resource", &resource, NULL);
-
- for (i = 0; i < NUM_GABBLE_PRESENCES; i++)
- {
- if (0 == strcmp (gabble_statuses[i].name, (const gchar*) key))
- break;
- }
-
- if (i < NUM_GABBLE_PRESENCES)
- {
- GHashTable *args = (GHashTable *)value;
- GValue *message = g_hash_table_lookup (args, "message");
- GValue *priority = g_hash_table_lookup (args, "priority");
- const gchar *status = NULL;
- gint8 prio;
-
- g_object_get (data->conn, "priority", &prio, NULL);
-
- if (!status_is_available (data->conn, i))
- {
- DEBUG ("requested status %s is not available", (const gchar *) key);
- g_set_error (data->error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "requested status '%s' is not available on this connection",
- (const gchar *) key);
- data->retval = FALSE;
- goto OUT;
- }
-
- if (message)
- {
- if (!G_VALUE_HOLDS_STRING (message))
- {
- DEBUG ("got a status message which was not a string");
- g_set_error (data->error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Status argument 'message' requires a string");
- data->retval = FALSE;
- goto OUT;
- }
- status = g_value_get_string (message);
- }
-
- if (priority)
- {
- if (!G_VALUE_HOLDS_INT (priority))
- {
- DEBUG ("got a priority value which was not a signed integer");
- g_set_error (data->error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Status argument 'priority' requires a signed integer");
- data->retval = FALSE;
- goto OUT;
- }
- prio = CLAMP (g_value_get_int (priority), G_MININT8, G_MAXINT8);
- }
-
- gabble_presence_update (data->conn->self_presence, resource, i, status,
- prio);
- emit_one_presence_update (data->conn, base->self_handle);
- data->retval = _gabble_connection_signal_own_presence (data->conn,
- data->error);
- }
- else
- {
- DEBUG ("got unknown status identifier %s", (const gchar *) key);
- g_set_error (data->error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "unknown status identifier: %s", (const gchar *) key);
- data->retval = FALSE;
- }
-
-OUT:
- g_free (resource);
-}
-
-/**
- * gabble_connection_set_status
- *
- * Implements D-Bus method SetStatus
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_set_status (TpSvcConnectionInterfacePresence *iface,
- GHashTable *statuses,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- struct _i_hate_g_hash_table_foreach data = { NULL, NULL, TRUE };
- GError *error = NULL;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- if (g_hash_table_size (statuses) != 1)
- {
- GError invalid = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Only one status may be set at a time in this protocol" };
- DEBUG ("got more than one status");
- dbus_g_method_return_error (context, &invalid);
- return;
- }
-
- data.conn = self;
- data.error = &error;
- g_hash_table_foreach (statuses, setstatuses_foreach, &data);
-
- if (data.retval)
- {
- tp_svc_connection_interface_presence_return_from_set_status (
- context);
- }
- else
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-}
-
-
-static void
-connection_presence_update_cb (
- GabblePresenceCache *cache,
- TpHandle handle,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
-
- emit_one_presence_update (conn, handle);
-}
-
-
-static void
-connection_status_changed_cb (
- GabbleConnection *conn,
- TpConnectionStatus status,
- TpConnectionStatusReason reason,
- gpointer user_data)
-{
- TpBaseConnection *base = (TpBaseConnection *) conn;
-
- if (status == TP_CONNECTION_STATUS_CONNECTED)
- emit_one_presence_update (conn, base->self_handle);
-}
-
-
-void
-conn_presence_init (GabbleConnection *conn)
-{
- g_signal_connect (conn->presence_cache, "presence-update",
- G_CALLBACK (connection_presence_update_cb), conn);
- g_signal_connect (conn, "status-changed",
- G_CALLBACK (connection_status_changed_cb), conn);
-}
-
-
-void
-conn_presence_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcConnectionInterfacePresenceClass *klass =
- (TpSvcConnectionInterfacePresenceClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_connection_interface_presence_implement_##x (\
- klass, gabble_connection_##x)
- IMPLEMENT(add_status);
- IMPLEMENT(clear_status);
- IMPLEMENT(get_presence);
- IMPLEMENT(get_statuses);
- IMPLEMENT(remove_status);
- IMPLEMENT(request_presence);
- IMPLEMENT(set_last_activity_time);
- IMPLEMENT(set_status);
-#undef IMPLEMENT
-}
diff --git a/src/conn-presence.h b/src/conn-presence.h
deleted file mode 100644
index 50f656159..000000000
--- a/src/conn-presence.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * conn-presence.h - Header for Gabble connection presence interface
- * Copyright (C) 2005-2007 Collabora Ltd.
- * Copyright (C) 2005-2007 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __CONN_PRESENCE_H__
-#define __CONN_PRESENCE_H__
-
-#include <glib.h>
-
-#include "gabble-connection.h"
-
-G_BEGIN_DECLS
-
-void conn_presence_init (GabbleConnection *conn);
-void conn_presence_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_END_DECLS
-
-#endif /* __CONN_PRESENCE_H__ */
-
diff --git a/src/debug.c b/src/debug.c
deleted file mode 100644
index 0c06a77e4..000000000
--- a/src/debug.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include "config.h"
-
-#ifdef ENABLE_DEBUG
-
-#include <stdarg.h>
-
-#include <glib.h>
-
-#include <telepathy-glib/debug.h>
-
-#include "debug.h"
-
-static GabbleDebugFlags flags = 0;
-
-static GDebugKey keys[] = {
- { "presence", GABBLE_DEBUG_PRESENCE },
- { "groups", GABBLE_DEBUG_GROUPS },
- { "roster", GABBLE_DEBUG_ROSTER },
- { "disco", GABBLE_DEBUG_DISCO },
- { "properties", GABBLE_DEBUG_PROPERTIES },
- { "roomlist", GABBLE_DEBUG_ROOMLIST },
- { "media-channel", GABBLE_DEBUG_MEDIA },
- { "im", GABBLE_DEBUG_IM },
- { "muc", GABBLE_DEBUG_MUC },
- { "connection", GABBLE_DEBUG_CONNECTION },
- { "persist", GABBLE_DEBUG_PERSIST },
- { "vcard", GABBLE_DEBUG_VCARD },
- { "jid", GABBLE_DEBUG_JID },
- { 0, },
-};
-
-void gabble_debug_set_flags_from_env ()
-{
- guint nkeys;
- const gchar *flags_string;
-
- for (nkeys = 0; keys[nkeys].value; nkeys++);
-
- flags_string = g_getenv ("GABBLE_DEBUG");
-
- if (flags_string)
- {
- tp_debug_set_flags_from_env ("GABBLE_DEBUG");
- gabble_debug_set_flags (g_parse_debug_string (flags_string, keys,
- nkeys));
- }
-}
-
-void gabble_debug_set_flags (GabbleDebugFlags new_flags)
-{
- flags |= new_flags;
-}
-
-gboolean gabble_debug_flag_is_set (GabbleDebugFlags flag)
-{
- return flag & flags;
-}
-
-void gabble_debug (GabbleDebugFlags flag,
- const gchar *format,
- ...)
-{
- if (flag & flags)
- {
- va_list args;
- va_start (args, format);
- g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args);
- va_end (args);
- }
-}
-
-#endif /* ENABLE_DEBUG */
-
diff --git a/src/debug.h b/src/debug.h
deleted file mode 100644
index 522d1d715..000000000
--- a/src/debug.h
+++ /dev/null
@@ -1,70 +0,0 @@
-
-#ifndef __DEBUG_H__
-#define __DEBUG_H_
-
-#include "config.h"
-
-#ifdef ENABLE_DEBUG
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- GABBLE_DEBUG_PRESENCE = 1 << 0,
- GABBLE_DEBUG_GROUPS = 1 << 1,
- GABBLE_DEBUG_ROSTER = 1 << 2,
- GABBLE_DEBUG_DISCO = 1 << 3,
- GABBLE_DEBUG_PROPERTIES = 1 << 4,
- GABBLE_DEBUG_ROOMLIST = 1 << 5,
- GABBLE_DEBUG_MEDIA = 1 << 6,
- GABBLE_DEBUG_MUC = 1 << 7,
- GABBLE_DEBUG_CONNECTION = 1 << 8,
- GABBLE_DEBUG_IM = 1 << 9,
- GABBLE_DEBUG_PERSIST = 1 << 10,
- GABBLE_DEBUG_VCARD = 1 << 11,
- GABBLE_DEBUG_PIPELINE = 1 << 12,
- GABBLE_DEBUG_JID = 1 << 13,
-} GabbleDebugFlags;
-
-void gabble_debug_set_flags_from_env ();
-void gabble_debug_set_flags (GabbleDebugFlags flags);
-gboolean gabble_debug_flag_is_set (GabbleDebugFlags flag);
-void gabble_debug (GabbleDebugFlags flag, const gchar *format, ...)
- G_GNUC_PRINTF (2, 3);
-
-G_END_DECLS
-
-#ifdef DEBUG_FLAG
-
-#define DEBUG(format, ...) \
- gabble_debug (DEBUG_FLAG, "%s: " format, G_STRFUNC, ##__VA_ARGS__)
-
-#define DEBUGGING gabble_debug_flag_is_set (DEBUG_FLAG)
-
-#define NODE_DEBUG(n, s) \
-G_STMT_START { \
- gchar *debug_tmp = lm_message_node_to_string (n); \
- gabble_debug (DEBUG_FLAG, "%s: " s ":\n%s", G_STRFUNC, debug_tmp); \
- g_free (debug_tmp); \
-} G_STMT_END
-
-#endif /* DEBUG_FLAG */
-
-#else /* ENABLE_DEBUG */
-
-#ifdef DEBUG_FLAG
-
-#define DEBUG(format, ...)
-
-#define DEBUGGING 0
-
-#define NODE_DEBUG(n, s)
-
-#endif /* DEBUG_FLAG */
-
-#endif /* ENABLE_DEBUG */
-
-#endif /* __DEBUG_H__ */
-
diff --git a/src/disco.c b/src/disco.c
deleted file mode 100644
index 6ba6f80bb..000000000
--- a/src/disco.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
- * disco.c - Source for Gabble service discovery
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- *
- * -- LET'S DISCO!!! \o/ \o_ _o/ /\o/\ _/o/- -\o\_ --
- */
-
-#include "disco.h"
-
-#define DBUS_API_SUBJECT_TO_CHANGE
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_DISCO
-
-#include "debug.h"
-#include "gabble-connection.h"
-#include "gabble-error.h"
-#include "namespaces.h"
-#include <telepathy-glib/dbus.h>
-#include "util.h"
-
-#define DEFAULT_REQUEST_TIMEOUT 20000
-#define DISCO_PIPELINE_SIZE 10
-
-/* Properties */
-enum
-{
- PROP_CONNECTION = 1,
- LAST_PROPERTY
-};
-
-G_DEFINE_TYPE(GabbleDisco, gabble_disco, G_TYPE_OBJECT);
-
-typedef struct _GabbleDiscoPrivate GabbleDiscoPrivate;
-struct _GabbleDiscoPrivate
-{
- GabbleConnection *connection;
- GSList *service_cache;
- GList *requests;
- gboolean dispose_has_run;
-};
-
-struct _GabbleDiscoRequest
-{
- GabbleDisco *disco;
- guint timer_id;
-
- GabbleDiscoType type;
- gchar *jid;
- gchar *node;
- GabbleDiscoCb callback;
- gpointer user_data;
- GObject *bound_object;
-};
-
-GQuark
-gabble_disco_error_quark (void)
-{
- static GQuark quark = 0;
- if (!quark)
- quark = g_quark_from_static_string ("gabble-disco-error");
- return quark;
-}
-
-#define GABBLE_DISCO_GET_PRIVATE(o) ((GabbleDiscoPrivate*)((o)->priv));
-
-static void
-gabble_disco_init (GabbleDisco *obj)
-{
- GabbleDiscoPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_DISCO, GabbleDiscoPrivate);
- obj->priv = priv;
-}
-
-static GObject *gabble_disco_constructor (GType type, guint n_props,
- GObjectConstructParam *props);
-static void gabble_disco_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-static void gabble_disco_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-static void gabble_disco_dispose (GObject *object);
-static void gabble_disco_finalize (GObject *object);
-
-static void
-gabble_disco_class_init (GabbleDiscoClass *gabble_disco_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_disco_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_disco_class, sizeof (GabbleDiscoPrivate));
-
- object_class->constructor = gabble_disco_constructor;
-
- object_class->get_property = gabble_disco_get_property;
- object_class->set_property = gabble_disco_set_property;
-
- object_class->dispose = gabble_disco_dispose;
- object_class->finalize = gabble_disco_finalize;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "XMPP Discovery object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-}
-
-static void
-gabble_disco_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleDisco *chan = GABBLE_DISCO (object);
- GabbleDiscoPrivate *priv = GABBLE_DISCO_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->connection);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_disco_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleDisco *chan = GABBLE_DISCO (object);
- GabbleDiscoPrivate *priv = GABBLE_DISCO_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->connection = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_disco_conn_status_changed_cb (GabbleConnection *conn,
- TpConnectionStatus status, TpConnectionStatusReason reason, gpointer data);
-
-static GObject *
-gabble_disco_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleDisco *disco;
- GabbleDiscoPrivate *priv;
-
- obj = G_OBJECT_CLASS (gabble_disco_parent_class)-> constructor (type,
- n_props, props);
- disco = GABBLE_DISCO (obj);
- priv = GABBLE_DISCO_GET_PRIVATE (disco);
-
- g_signal_connect (priv->connection, "status-changed",
- G_CALLBACK (gabble_disco_conn_status_changed_cb), disco);
-
- return obj;
-}
-
-static void cancel_request (GabbleDiscoRequest *request);
-
-void
-gabble_disco_dispose (GObject *object)
-{
- GabbleDisco *self = GABBLE_DISCO (object);
- GabbleDiscoPrivate *priv = GABBLE_DISCO_GET_PRIVATE (self);
- GSList *l;
- DBusGProxy *bus_proxy;
- bus_proxy = tp_get_bus_proxy ();
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- DEBUG ("dispose called");
-
- /* cancel request removes the element from the list after cancelling */
- while (priv->requests)
- cancel_request (priv->requests->data);
-
- for (l = priv->service_cache; l; l = g_slist_next (l))
- {
- GabbleDiscoItem *item = (GabbleDiscoItem *) l->data;
- g_free ((char *) item->jid);
- g_free ((char *) item->name);
- g_free ((char *) item->type);
- g_free ((char *) item->category);
- g_hash_table_destroy (item->features);
- g_free (item);
- }
-
- g_slist_free (priv->service_cache);
- priv->service_cache = NULL;
-
- if (G_OBJECT_CLASS (gabble_disco_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_disco_parent_class)->dispose (object);
-}
-
-void
-gabble_disco_finalize (GObject *object)
-{
- DEBUG ("called with %p", object);
-
- G_OBJECT_CLASS (gabble_disco_parent_class)->finalize (object);
-}
-
-/**
- * gabble_disco_new:
- * @conn: The #GabbleConnection to use for service discovery
- *
- * Creates an object to use for Jabber service discovery (DISCO)
- * There should be one of these per connection
- */
-GabbleDisco *
-gabble_disco_new (GabbleConnection *conn)
-{
- GabbleDisco *disco;
-
- g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL);
-
- disco = GABBLE_DISCO (g_object_new (GABBLE_TYPE_DISCO,
- "connection", conn,
- NULL));
-
- return disco;
-}
-
-
-static void notify_delete_request (gpointer data, GObject *obj);
-
-static void
-delete_request (GabbleDiscoRequest *request)
-{
- GabbleDisco *disco = request->disco;
- GabbleDiscoPrivate *priv;
-
- g_assert (NULL != request);
- g_assert (GABBLE_IS_DISCO (disco));
-
- priv = GABBLE_DISCO_GET_PRIVATE (disco);
-
- g_assert (NULL != g_list_find (priv->requests, request));
-
- priv->requests = g_list_remove (priv->requests, request);
-
- if (NULL != request->bound_object)
- {
- g_object_weak_unref (request->bound_object, notify_delete_request,
- request);
- }
-
- if (0 != request->timer_id)
- {
- g_source_remove (request->timer_id);
- }
-
- g_free (request->jid);
- g_free (request->node);
- g_slice_free (GabbleDiscoRequest, request);
-}
-
-static gboolean
-timeout_request (gpointer data)
-{
- GabbleDiscoRequest *request = (GabbleDiscoRequest*) data;
- GError *err /* doesn't need initializing */;
- g_return_val_if_fail (data != NULL, FALSE);
-
- err = g_error_new (GABBLE_DISCO_ERROR, GABBLE_DISCO_ERROR_TIMEOUT,
- "Request for %s on %s timed out",
- (request->type == GABBLE_DISCO_TYPE_INFO)?"info":"items",
- request->jid);
- (request->callback)(request->disco, request, request->jid, request->node,
- NULL, err, request->user_data);
- g_error_free (err);
-
- request->timer_id = 0;
- delete_request (request);
- return FALSE;
-}
-
-static void
-cancel_request (GabbleDiscoRequest *request)
-{
- GError *err /* doesn't need initializing */;
-
- g_assert (request != NULL);
-
- err = g_error_new (GABBLE_DISCO_ERROR, GABBLE_DISCO_ERROR_CANCELLED,
- "Request for %s on %s cancelled",
- (request->type == GABBLE_DISCO_TYPE_INFO)?"info":"items",
- request->jid);
- (request->callback)(request->disco, request, request->jid, request->node,
- NULL, err, request->user_data);
- g_error_free (err);
-
- delete_request (request);
-}
-
-static LmHandlerResult
-request_reply_cb (GabbleConnection *conn, LmMessage *sent_msg,
- LmMessage *reply_msg, GObject *object, gpointer user_data)
-{
- GabbleDiscoRequest *request = (GabbleDiscoRequest*) user_data;
- GabbleDisco *disco = GABBLE_DISCO (object);
- GabbleDiscoPrivate *priv = GABBLE_DISCO_GET_PRIVATE (disco);
- LmMessageNode *query_node;
- GError *err = NULL;
-
- g_assert (request);
-
- if (!g_list_find (priv->requests, request))
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- query_node = lm_message_node_get_child (reply_msg->node, "query");
-
- if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
- {
- LmMessageNode *error_node;
-
- error_node = lm_message_node_get_child (reply_msg->node, "error");
- if (error_node)
- {
- err = gabble_xmpp_error_to_g_error (
- gabble_xmpp_error_from_node (error_node));
- }
-
- if (err == NULL)
- {
- err = g_error_new (GABBLE_DISCO_ERROR,
- GABBLE_DISCO_ERROR_UNKNOWN,
- "an unknown error occurred");
- }
- }
- else if (NULL == query_node)
- {
- err = g_error_new (GABBLE_DISCO_ERROR, GABBLE_DISCO_ERROR_UNKNOWN,
- "disco response contained no <query> node");
- }
-
- request->callback (request->disco, request, request->jid, request->node,
- query_node, err, request->user_data);
- delete_request (request);
-
- if (err)
- g_error_free (err);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-notify_delete_request (gpointer data, GObject *obj)
-{
- GabbleDiscoRequest *request = (GabbleDiscoRequest *) data;
- request->bound_object = NULL;
- delete_request (request);
-}
-
-/**
- * gabble_disco_request:
- * @self: #GabbleDisco object to use for request
- * @type: type of request
- * @jid: Jabber ID to request on
- * @node: node to request on @jid, or NULL
- * @callback: #GabbleDiscoCb to call on request fullfilment
- * @object: GObject to bind request to. the callback will not be
- * called if this object has been unrefed. NULL if not needed
- * @error: #GError to return a telepathy error in if unable to make
- * request, NULL if unneeded.
- *
- * Make a disco request on the given jid with the default timeout.
- */
-GabbleDiscoRequest *
-gabble_disco_request (GabbleDisco *self, GabbleDiscoType type,
- const gchar *jid, const char *node,
- GabbleDiscoCb callback, gpointer user_data,
- GObject *object, GError **error)
-{
- return gabble_disco_request_with_timeout (self, type, jid, node,
- DEFAULT_REQUEST_TIMEOUT,
- callback, user_data,
- object, error);
-}
-
-/**
- * gabble_disco_request_with_timeout:
- * @self: #GabbleDisco object to use for request
- * @type: type of request
- * @jid: Jabber ID to request on
- * @node: node to request on @jid, or NULL
- * @timeout: the time until the request fails, in milliseconds (1/1000ths of
- * a second)
- * @callback: #GabbleDiscoCb to call on request fullfilment
- * @object: GObject to bind request to. the callback will not be
- * called if this object has been unrefed. NULL if not needed
- * @error: #GError to return a telepathy error in if unable to make
- * request, NULL if unneeded.
- *
- * Make a disco request on the given jid, which will fail unless a reply
- * is received within the given timeout interval.
- */
-GabbleDiscoRequest *
-gabble_disco_request_with_timeout (GabbleDisco *self, GabbleDiscoType type,
- const gchar *jid, const char *node,
- guint timeout, GabbleDiscoCb callback,
- gpointer user_data, GObject *object,
- GError **error)
-{
- GabbleDiscoPrivate *priv = GABBLE_DISCO_GET_PRIVATE (self);
- GabbleDiscoRequest *request;
- LmMessage *msg;
- LmMessageNode *lm_node;
- const gchar *xmlns;
-
- request = g_slice_new0 (GabbleDiscoRequest);
- request->disco = self;
- request->type = type;
- request->jid = g_strdup (jid);
- if (node)
- request->node = g_strdup (node);
- request->callback = callback;
- request->user_data = user_data;
- request->bound_object = object;
-
- if (NULL != object)
- g_object_weak_ref (object, notify_delete_request, request);
-
- DEBUG ("Creating disco request %p for %s",
- request, request->jid);
-
- priv->requests = g_list_prepend (priv->requests, request);
- msg = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_GET);
- lm_node = lm_message_node_add_child (msg->node, "query", NULL);
-
- switch (type) {
- case GABBLE_DISCO_TYPE_INFO:
- xmlns = NS_DISCO_INFO;
- break;
- case GABBLE_DISCO_TYPE_ITEMS:
- xmlns = NS_DISCO_ITEMS;
- break;
- default:
- g_assert_not_reached ();
- return NULL;
- }
-
- lm_message_node_set_attribute (lm_node, "xmlns", xmlns);
-
- if (node)
- {
- lm_message_node_set_attribute (lm_node, "node", node);
- }
-
- if (! _gabble_connection_send_with_reply (priv->connection, msg,
- request_reply_cb, G_OBJECT(self), request, error))
- {
- delete_request (request);
- lm_message_unref (msg);
- return NULL;
- }
- else
- {
- request->timer_id =
- g_timeout_add (timeout, timeout_request, request);
- lm_message_unref (msg);
- return request;
- }
-}
-
-void
-gabble_disco_cancel_request (GabbleDisco *disco, GabbleDiscoRequest *request)
-{
- GabbleDiscoPrivate *priv;
-
- g_return_if_fail (GABBLE_IS_DISCO (disco));
- g_return_if_fail (NULL != request);
-
- priv = GABBLE_DISCO_GET_PRIVATE (disco);
-
- g_return_if_fail (NULL != g_list_find (priv->requests, request));
-
- cancel_request (request);
-}
-
-/* Disco pipeline */
-
-
-typedef struct _GabbleDiscoPipeline GabbleDiscoPipeline;
-struct _GabbleDiscoPipeline {
- GabbleDisco *disco;
- gpointer user_data;
- GabbleDiscoPipelineCb callback;
- GabbleDiscoEndCb end_callback;
- GPtrArray *disco_pipeline;
- GHashTable *remaining_items;
- GabbleDiscoRequest *list_request;
- gboolean running;
-};
-
-static void
-gabble_disco_fill_pipeline (GabbleDisco *disco, GabbleDiscoPipeline *pipeline);
-
-static void
-item_info_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *result,
- GError *error,
- gpointer user_data)
-{
- LmMessageNode *identity, *feature, *field, *value_node;
- const char *category, *type, *var, *name, *value;
- GHashTable *keys;
- GabbleDiscoItem item;
-
- GabbleDiscoPipeline *pipeline = (GabbleDiscoPipeline *) user_data;
-
- g_ptr_array_remove_fast (pipeline->disco_pipeline, request);
-
- if (error)
- {
- DEBUG ("got error %s", error->message);
- goto done;
- }
-
- identity = lm_message_node_get_child (result, "identity");
- if (NULL == identity)
- goto done;
-
- name = lm_message_node_get_attribute (identity, "name");
- if (NULL == name)
- goto done;
-
- category = lm_message_node_get_attribute (identity, "category");
- if (NULL == category)
- goto done;
-
- type = lm_message_node_get_attribute (identity, "type");
- if (NULL == type)
- goto done;
-
- DEBUG ("got item identity, jid=%s, name=%s, category=%s, type=%s",
- jid, name, category, type);
-
- keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
- for (feature = result->children; feature; feature = feature->next)
- {
- if (0 == strcmp (feature->name, "feature"))
- {
- var = lm_message_node_get_attribute (feature, "var");
- if (var)
- g_hash_table_insert (keys, g_strdup (var), NULL);
- }
- else if (0 == strcmp (feature->name, "x"))
- {
- if (lm_message_node_has_namespace (feature, NS_X_DATA, NULL))
- {
- for (field = feature->children;
- field; field = field->next)
- {
- if (0 != strcmp (field->name, "field"))
- continue;
-
- var = lm_message_node_get_attribute (field, "var");
- if (NULL == var)
- continue;
-
- value_node = lm_message_node_get_child (field, "value");
- if (NULL == value_node)
- continue;
-
- value = lm_message_node_get_value (value_node);
- if (NULL == value)
- continue;
-
- g_hash_table_insert (keys, g_strdup (var), g_strdup (value));
- }
- }
- }
- }
-
- item.jid = jid;
- item.name = name;
- item.category = category;
- item.type = type;
- item.features = keys;
-
- pipeline->callback (pipeline, &item, pipeline->user_data);
- g_hash_table_destroy (keys);
-
-done:
- gabble_disco_fill_pipeline (disco, pipeline);
-
- return;
-}
-
-
-static gboolean
-return_true (gpointer key, gpointer value, gpointer data)
-{
- return TRUE;
-}
-
-static void
-gabble_disco_fill_pipeline (GabbleDisco *disco, GabbleDiscoPipeline *pipeline)
-{
- if (!pipeline->running)
- {
- DEBUG ("pipeline not running, not refilling");
- }
- else
- {
- /* send disco requests for the JIDs in the remaining_items hash table
- * until there are DISCO_PIPELINE_SIZE requests in progress */
- while (pipeline->disco_pipeline->len < DISCO_PIPELINE_SIZE)
- {
- gchar *jid;
- GabbleDiscoRequest *request;
-
- jid = (gchar *) g_hash_table_find (pipeline->remaining_items,
- return_true, NULL);
- if (NULL == jid)
- break;
-
- request = gabble_disco_request (disco,
- GABBLE_DISCO_TYPE_INFO, jid, NULL, item_info_cb, pipeline,
- G_OBJECT(disco), NULL);
-
- g_ptr_array_add (pipeline->disco_pipeline, request);
-
- /* frees jid */
- g_hash_table_remove (pipeline->remaining_items, jid);
- }
-
- if (0 == pipeline->disco_pipeline->len)
- {
- /* signal that the pipeline has finished */
- pipeline->running = FALSE;
- pipeline->end_callback (pipeline, pipeline->user_data);
- }
- }
-}
-
-
-static void
-disco_items_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *result,
- GError *error,
- gpointer user_data)
-{
- LmMessageNode *iter;
- const char *item_jid;
- gpointer key, value;
- GabbleDiscoPipeline *pipeline = (GabbleDiscoPipeline *) user_data;
-
- pipeline->list_request = NULL;
-
- if (error)
- {
- DEBUG ("Got error on items request: %s", error->message);
- goto out;
- }
-
- iter = result->children;
-
- for (; iter; iter = iter->next)
- {
- if (0 != strcmp (iter->name, "item"))
- continue;
-
- item_jid = lm_message_node_get_attribute (iter, "jid");
-
- if (NULL != item_jid &&
- !g_hash_table_lookup_extended (pipeline->remaining_items, item_jid,
- &key, &value))
- {
- gchar *tmp = g_strdup (item_jid);
- DEBUG ("discovered service item: %s", tmp);
- g_hash_table_insert (pipeline->remaining_items, tmp, tmp);
- }
- }
-
-out:
- gabble_disco_fill_pipeline (disco, pipeline);
-}
-
-/**
- * gabble_disco_pipeline_init:
- * @disco: disco object to use in the pipeline
- * @callback: GFunc to call on request fullfilment
- * @user_data: the usual
- *
- * Prepares the pipeline for making the ITEM request on the server and
- * subsequent INFO elements on returned items.
- *
- * GabbleDiscoPipeline is opaque structure for the user.
- */
-gpointer gabble_disco_pipeline_init (GabbleDisco *disco,
- GabbleDiscoPipelineCb callback,
- GabbleDiscoEndCb end_callback,
- gpointer user_data)
-{
- GabbleDiscoPipeline *pipeline = g_new (GabbleDiscoPipeline, 1);
- pipeline->user_data = user_data;
- pipeline->callback = callback;
- pipeline->end_callback = end_callback;
- pipeline->disco_pipeline = g_ptr_array_sized_new (DISCO_PIPELINE_SIZE);
- pipeline->remaining_items = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
- pipeline->running = TRUE;
- pipeline->disco = disco;
-
- return pipeline;
-}
-
-/**
- * gabble_disco_pipeline_run:
- * @self: reference to the pipeline structure
- * @server: server to query
- *
- * Makes ITEMS request on the server, and afterwards queries for INFO
- * on each item. INFO queries are pipelined. The item properties are stored
- * in hash table parameter to the callback function. The user is responsible
- * for destroying the hash table after it's done with.
- *
- * Upon returning all the results, the end_callback is called with
- * reference to the pipeline.
- */
-void
-gabble_disco_pipeline_run (gpointer self, const char *server)
-{
- GabbleDiscoPipeline *pipeline = (GabbleDiscoPipeline *) self;
-
- pipeline->running = TRUE;
-
- pipeline->list_request = gabble_disco_request (pipeline->disco,
- GABBLE_DISCO_TYPE_ITEMS, server, NULL, disco_items_cb, pipeline,
- G_OBJECT (pipeline->disco), NULL);
-}
-
-
-/**
- * gabble_disco_pipeline_cancel:
- * @pipeline: pipeline to cancel
- *
- * Flushes the pipeline (cancels all pending disco requests) and
- * destroys it.
- */
-void
-gabble_disco_pipeline_destroy (gpointer self)
-{
- GabbleDiscoPipeline *pipeline = (GabbleDiscoPipeline *) self;
-
- pipeline->running = FALSE;
-
- if (pipeline->list_request != NULL)
- {
- gabble_disco_cancel_request (pipeline->disco, pipeline->list_request);
- pipeline->list_request = NULL;
- }
-
- /* iterate using a while loop otherwise we're modifying
- * the array as we iterate it, and miss things! */
- while (pipeline->disco_pipeline->len > 0)
- {
- GabbleDiscoRequest *request =
- g_ptr_array_index (pipeline->disco_pipeline, 0);
- gabble_disco_cancel_request (pipeline->disco, request);
- }
-
- g_hash_table_destroy (pipeline->remaining_items);
- g_ptr_array_free (pipeline->disco_pipeline, TRUE);
- g_free (pipeline);
-}
-
-
-static void
-service_feature_copy_one (gpointer k, gpointer v, gpointer user_data)
-{
- char *key = (char *) k;
- char *value = (char *) v;
-
- GHashTable *target = (GHashTable *) user_data;
- g_hash_table_insert (target, g_strdup (key), g_strdup (value));
-}
-
-/* Service discovery */
-static void
-services_cb (gpointer pipeline, GabbleDiscoItem *item, gpointer user_data)
-{
- GabbleDisco *disco = GABBLE_DISCO (user_data);
- GabbleDiscoPrivate *priv = GABBLE_DISCO_GET_PRIVATE (disco);
- GabbleDiscoItem *my_item = g_new0 (GabbleDiscoItem, 1);
-
- my_item->jid = g_strdup (item->jid);
- my_item->name = g_strdup (item->name);
- my_item->type = g_strdup (item->type);
- my_item->category = g_strdup (item->category);
-
- my_item->features = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
- NULL);
- g_hash_table_foreach (item->features, service_feature_copy_one,
- my_item->features);
-
- priv->service_cache = g_slist_prepend (priv->service_cache, my_item);
-}
-
-static void
-end_cb (gpointer pipeline, gpointer user_data)
-{
- GabbleDisco *disco = GABBLE_DISCO (user_data);
- GabbleDiscoPrivate *priv = GABBLE_DISCO_GET_PRIVATE (disco);
-
- gabble_disco_pipeline_destroy (pipeline);
- priv->service_cache = g_slist_reverse (priv->service_cache);
-
- /* FIXME - service discovery done - signal that somehow */
-}
-
-static void
-gabble_disco_conn_status_changed_cb (GabbleConnection *conn,
- TpConnectionStatus status,
- TpConnectionStatusReason reason,
- gpointer data)
-{
- GabbleDisco *disco = GABBLE_DISCO (data);
- GabbleDiscoPrivate *priv = GABBLE_DISCO_GET_PRIVATE (disco);
-
- if (status == TP_CONNECTION_STATUS_CONNECTED)
- {
- char *server;
-
- g_object_get (priv->connection, "stream-server", &server, NULL);
-
- g_assert (server != NULL);
-
- DEBUG ("connected, initiating service discovery on %s", server);
- gpointer pipeline = gabble_disco_pipeline_init (disco, services_cb,
- end_cb, disco);
- gabble_disco_pipeline_run (pipeline, server);
-
- g_free (server);
- }
-}
-
-const GabbleDiscoItem *
-gabble_disco_service_find (GabbleDisco *disco,
- const char *type,
- const char *category,
- const char *feature)
-{
- GabbleDiscoPrivate *priv;
- GSList *l;
-
- g_assert (GABBLE_IS_DISCO (disco));
- priv = GABBLE_DISCO_GET_PRIVATE (disco);
-
- for (l = priv->service_cache; l; l = g_slist_next (l))
- {
- GabbleDiscoItem *item = (GabbleDiscoItem *) l->data;
- gboolean selected = TRUE;
-
- if (type != NULL && tp_strdiff (type, item->type))
- selected = FALSE;
-
- if (category != NULL && tp_strdiff (category, item->category))
- selected = FALSE;
-
- if (feature != NULL)
- {
- gpointer k, v;
- if (!g_hash_table_lookup_extended (item->features, feature, &k, &v))
- selected = FALSE;
- }
-
- if (selected)
- return item;
- }
-
- return NULL;
-}
diff --git a/src/disco.h b/src/disco.h
deleted file mode 100644
index 533e4a212..000000000
--- a/src/disco.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * disco.h - Headers for Gabble service discovery
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- *
- * -- LET'S DISCO!!! \o/ \o_ _o/ /\o/\ _/o/- -\o\_ --
- */
-
-#ifndef __GABBLE_DISCO_H__
-#define __GABBLE_DISCO_H__
-
-#include <glib-object.h>
-#include <loudmouth/loudmouth.h>
-
-#include "gabble-types.h"
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- GABBLE_DISCO_TYPE_INFO,
- GABBLE_DISCO_TYPE_ITEMS
-} GabbleDiscoType;
-
-typedef struct _GabbleDiscoClass GabbleDiscoClass;
-typedef struct _GabbleDiscoRequest GabbleDiscoRequest;
-
-/**
- * GabbleDiscoError:
- * @GABBLE_DISCO_ERROR_CANCELLED: The DISCO request was cancelled
- * @GABBLE_DISCO_ERROR_TIMEOUT: The DISCO request timed out
- * @GABBLE_DISCO_ERROR_UNKNOWN: An unknown error occured
- */
-typedef enum
-{
- GABBLE_DISCO_ERROR_CANCELLED,
- GABBLE_DISCO_ERROR_TIMEOUT,
- GABBLE_DISCO_ERROR_UNKNOWN
-} GabbleDiscoError;
-
-GQuark gabble_disco_error_quark (void);
-#define GABBLE_DISCO_ERROR gabble_disco_error_quark ()
-
-GType gabble_disco_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_DISCO \
- (gabble_disco_get_type ())
-#define GABBLE_DISCO(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_DISCO, GabbleDisco))
-#define GABBLE_DISCO_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_DISCO, GabbleDiscoClass))
-#define GABBLE_IS_DISCO(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_DISCO))
-#define GABBLE_IS_DISCO_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_DISCO))
-#define GABBLE_DISCO_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_DISCO, GabbleDiscoClass))
-
-struct _GabbleDiscoClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleDisco {
- GObject parent;
- gpointer priv;
-};
-
-typedef void (*GabbleDiscoCb)(GabbleDisco *self, GabbleDiscoRequest *request,
- const gchar *jid, const gchar *node, LmMessageNode *query_result,
- GError* error, gpointer user_data);
-
-GabbleDisco *gabble_disco_new (GabbleConnection *);
-
-GabbleDiscoRequest *gabble_disco_request (GabbleDisco *self,
- GabbleDiscoType type, const gchar *jid, const char *node,
- GabbleDiscoCb callback, gpointer user_data, GObject *object,
- GError **error);
-GabbleDiscoRequest *gabble_disco_request_with_timeout (GabbleDisco *self,
- GabbleDiscoType type, const gchar *jid, const char *node,
- guint timeout, GabbleDiscoCb callback, gpointer user_data,
- GObject *object, GError **error);
-
-void gabble_disco_cancel_request (GabbleDisco *, GabbleDiscoRequest *);
-
-/* Pipelines */
-
-typedef struct _GabbleDiscoItem GabbleDiscoItem;
-
-struct _GabbleDiscoItem {
- const gchar *jid;
- const char *name;
- const char *type;
- const char *category;
- GHashTable *features;
-};
-
-typedef void (*GabbleDiscoPipelineCb)(gpointer pipeline,
- GabbleDiscoItem *item,
- gpointer user_data);
-
-typedef void (*GabbleDiscoEndCb)(gpointer pipeline,
- gpointer user_data);
-
-gpointer gabble_disco_pipeline_init (GabbleDisco *disco,
- GabbleDiscoPipelineCb callback,
- GabbleDiscoEndCb end_callback,
- gpointer user_data);
-
-void gabble_disco_pipeline_run (gpointer self, const char *server);
-void gabble_disco_pipeline_destroy (gpointer self);
-
-/* Service discovery */
-
-void gabble_disco_service_discovery (GabbleDisco *disco, const char *server);
-const GabbleDiscoItem *
-gabble_disco_service_find (GabbleDisco *disco,
- const char *type,
- const char *category,
- const char *feature);
-
-G_END_DECLS
-
-#endif
diff --git a/src/gabble-connection-manager.c b/src/gabble-connection-manager.c
deleted file mode 100644
index 32fbdd18b..000000000
--- a/src/gabble-connection-manager.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * gabble-connection-manager.c - Source for GabbleConnectionManager
- * Copyright (C) 2005-2007 Collabora Ltd.
- * Copyright (C) 2005-2007 Nokia Corporation
- *
- * 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
- */
-
-#include "gabble-connection-manager.h"
-
-#include <dbus/dbus-protocol.h>
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "gabble-connection.h"
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-
-G_DEFINE_TYPE(GabbleConnectionManager,
- gabble_connection_manager,
- TP_TYPE_BASE_CONNECTION_MANAGER)
-
-/* type definition stuff */
-
-static void
-gabble_connection_manager_init (GabbleConnectionManager *self)
-{
-}
-
-static TpBaseConnection *_gabble_connection_manager_new_connection (
- TpBaseConnectionManager *self, const gchar *proto,
- TpIntSet *params_present, void *parsed_params, GError **error);
-
-static void
-gabble_connection_manager_class_init (GabbleConnectionManagerClass *klass)
-{
- TpBaseConnectionManagerClass *base_class =
- (TpBaseConnectionManagerClass *)klass;
-
- base_class->new_connection = _gabble_connection_manager_new_connection;
- base_class->cm_dbus_name = "gabble";
- base_class->protocol_params = gabble_protocols;
-}
-
-/* private data */
-
-typedef struct _GabbleParams GabbleParams;
-
-struct _GabbleParams {
- gchar *account;
- gchar *password;
- gchar *server;
- gchar *resource;
- gint priority;
- guint port;
- gboolean old_ssl;
- gboolean do_register;
- gboolean low_bandwidth;
- gchar *https_proxy_server;
- guint https_proxy_port;
- gchar *fallback_conference_server;
- gchar *stun_server;
- guint stun_port;
- gboolean ignore_ssl_errors;
- gchar *alias;
- gchar *auth_mac;
- gchar *auth_btid;
-};
-
-enum {
- JABBER_PARAM_ACCOUNT = 0,
- JABBER_PARAM_PASSWORD,
- JABBER_PARAM_SERVER,
- JABBER_PARAM_RESOURCE,
- JABBER_PARAM_PRIORITY,
- JABBER_PARAM_PORT,
- JABBER_PARAM_OLD_SSL,
- JABBER_PARAM_REGISTER,
- JABBER_PARAM_LOW_BANDWIDTH,
- JABBER_PARAM_HTTPS_PROXY_SERVER,
- JABBER_PARAM_HTTPS_PROXY_PORT,
- JABBER_PARAM_FALLBACK_CONFERENCE_SERVER,
- JABBER_PARAM_STUN_SERVER,
- JABBER_PARAM_STUN_PORT,
- JABBER_PARAM_IGNORE_SSL_ERRORS,
- JABBER_PARAM_ALIAS,
- JABBER_PARAM_AUTH_MAC,
- JABBER_PARAM_AUTH_BTID,
- LAST_JABBER_PARAM
-};
-
-static const TpCMParamSpec jabber_params[] = {
- { "account", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER, NULL,
- G_STRUCT_OFFSET(GabbleParams, account),
- /* FIXME: validate the JID according to the RFC */
- tp_cm_param_filter_string_nonempty, NULL },
- { "password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER, NULL,
- G_STRUCT_OFFSET(GabbleParams, password), NULL, NULL },
-
- { "server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
- G_STRUCT_OFFSET(GabbleParams, server),
- /* FIXME: validate the server properly */
- tp_cm_param_filter_string_nonempty, NULL },
-
- { "resource", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GABBLE_PARAMS_DEFAULT_RESOURCE,
- G_STRUCT_OFFSET(GabbleParams, resource),
- /* FIXME: validate the resource according to the RFC */
- tp_cm_param_filter_string_nonempty, NULL },
-
- { "priority", DBUS_TYPE_INT16_AS_STRING, G_TYPE_INT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(0),
- G_STRUCT_OFFSET(GabbleParams, priority), NULL, NULL },
-
- { "port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,
- GINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_PORT),
- G_STRUCT_OFFSET(GabbleParams, port),
- tp_cm_param_filter_uint_nonzero, NULL },
-
- { "old-ssl", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(FALSE),
- G_STRUCT_OFFSET(GabbleParams, old_ssl), NULL, NULL },
-
- { "register", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(FALSE),
- G_STRUCT_OFFSET(GabbleParams, do_register), NULL, NULL },
-
- { "low-bandwidth", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(FALSE),
- G_STRUCT_OFFSET(GabbleParams, low_bandwidth), NULL, NULL },
-
- { "https-proxy-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
- G_STRUCT_OFFSET(GabbleParams, https_proxy_server),
- /* FIXME: validate properly */
- tp_cm_param_filter_string_nonempty, NULL },
- { "https-proxy-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,
- GINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_PORT),
- G_STRUCT_OFFSET(GabbleParams, https_proxy_port),
- tp_cm_param_filter_uint_nonzero, NULL },
-
- { "fallback-conference-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET(GabbleParams, fallback_conference_server),
- /* FIXME: validate properly */
- tp_cm_param_filter_string_nonempty, NULL },
-
- { "stun-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
- G_STRUCT_OFFSET(GabbleParams, stun_server),
- /* FIXME: validate properly */
- tp_cm_param_filter_string_nonempty, NULL },
- { "stun-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,
- GINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_STUN_PORT),
- G_STRUCT_OFFSET(GabbleParams, stun_port),
- tp_cm_param_filter_uint_nonzero, NULL },
-
- { "ignore-ssl-errors", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(FALSE),
- G_STRUCT_OFFSET(GabbleParams, ignore_ssl_errors), NULL, NULL },
-
- { "alias", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
- G_STRUCT_OFFSET(GabbleParams, alias),
- /* setting a 0-length alias makes no sense */
- tp_cm_param_filter_string_nonempty, NULL },
-
- { "mac", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
- G_STRUCT_OFFSET(GabbleParams, auth_mac), NULL, NULL },
- { "btid", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
- G_STRUCT_OFFSET(GabbleParams, auth_btid), NULL, NULL },
-
- { NULL, NULL, 0, 0, NULL, 0 }
-};
-
-static void *
-alloc_params (void)
-{
- return g_slice_new0 (GabbleParams);
-}
-
-static void
-free_params (void *p)
-{
- GabbleParams *params = (GabbleParams *)p;
-
- g_free (params->account);
- g_free (params->password);
- g_free (params->server);
- g_free (params->resource);
- g_free (params->https_proxy_server);
- g_free (params->fallback_conference_server);
- g_free (params->stun_server);
- g_free (params->alias);
- g_free (params->auth_mac);
- g_free (params->auth_btid);
-
- g_slice_free (GabbleParams, params);
-}
-
-const TpCMProtocolSpec gabble_protocols[] = {
- { "jabber", jabber_params, alloc_params, free_params },
- { NULL, NULL }
-};
-
-#define SET_PROPERTY_IF_PARAM_SET(prop, param, member) \
- if (tp_intset_is_member (params_present, param)) \
- { \
- g_object_set (conn, prop, member, NULL); \
- }
-
-static TpBaseConnection *
-_gabble_connection_manager_new_connection (TpBaseConnectionManager *self,
- const gchar *proto,
- TpIntSet *params_present,
- void *parsed_params,
- GError **error)
-{
- GabbleConnection *conn;
- GabbleParams *params = (GabbleParams *)parsed_params;
-
- g_assert (GABBLE_IS_CONNECTION_MANAGER (self));
-
- conn = g_object_new (GABBLE_TYPE_CONNECTION,
- "protocol", proto,
- "password", params->password,
- NULL);
-
- SET_PROPERTY_IF_PARAM_SET ("connect-server", JABBER_PARAM_SERVER,
- params->server);
- SET_PROPERTY_IF_PARAM_SET ("resource", JABBER_PARAM_RESOURCE,
- params->resource);
- SET_PROPERTY_IF_PARAM_SET ("priority", JABBER_PARAM_PRIORITY,
- (gint8) CLAMP (params->priority, G_MININT8, G_MAXINT8));
- SET_PROPERTY_IF_PARAM_SET ("port", JABBER_PARAM_PORT, params->port);
- SET_PROPERTY_IF_PARAM_SET ("old-ssl", JABBER_PARAM_OLD_SSL, params->old_ssl);
- SET_PROPERTY_IF_PARAM_SET ("register", JABBER_PARAM_REGISTER,
- params->do_register);
- SET_PROPERTY_IF_PARAM_SET ("low-bandwidth", JABBER_PARAM_LOW_BANDWIDTH,
- params->low_bandwidth);
- SET_PROPERTY_IF_PARAM_SET ("https-proxy-server",
- JABBER_PARAM_HTTPS_PROXY_SERVER,
- params->https_proxy_server);
- SET_PROPERTY_IF_PARAM_SET ("https-proxy-port", JABBER_PARAM_HTTPS_PROXY_PORT,
- params->https_proxy_port);
- SET_PROPERTY_IF_PARAM_SET ("fallback-conference-server",
- JABBER_PARAM_FALLBACK_CONFERENCE_SERVER,
- params->fallback_conference_server);
- SET_PROPERTY_IF_PARAM_SET ("stun-server", JABBER_PARAM_STUN_SERVER,
- params->stun_server);
- SET_PROPERTY_IF_PARAM_SET ("stun-port", JABBER_PARAM_STUN_PORT,
- params->stun_port);
- SET_PROPERTY_IF_PARAM_SET ("ignore-ssl-errors",
- JABBER_PARAM_IGNORE_SSL_ERRORS,
- params->ignore_ssl_errors);
- SET_PROPERTY_IF_PARAM_SET ("alias", JABBER_PARAM_ALIAS, params->alias);
- SET_PROPERTY_IF_PARAM_SET ("auth-mac", JABBER_PARAM_AUTH_MAC,
- params->auth_mac);
- SET_PROPERTY_IF_PARAM_SET ("auth-btid", JABBER_PARAM_AUTH_BTID,
- params->auth_btid);
-
- /* split up account into username, stream-server and resource */
- if (!_gabble_connection_set_properties_from_account (conn, params->account,
- error))
- {
- g_object_unref (G_OBJECT (conn));
- conn = NULL;
- }
-
- return (TpBaseConnection *)conn;
-}
diff --git a/src/gabble-connection-manager.h b/src/gabble-connection-manager.h
deleted file mode 100644
index 5365ab13b..000000000
--- a/src/gabble-connection-manager.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * gabble-connection-manager.h - Header for GabbleConnectionManager
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_CONNECTION_MANAGER_H__
-#define __GABBLE_CONNECTION_MANAGER_H__
-
-#include <glib-object.h>
-#include <telepathy-glib/base-connection-manager.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleConnectionManager GabbleConnectionManager;
-typedef struct _GabbleConnectionManagerClass GabbleConnectionManagerClass;
-
-struct _GabbleConnectionManagerClass {
- TpBaseConnectionManagerClass parent_class;
-};
-
-struct _GabbleConnectionManager {
- TpBaseConnectionManager parent;
-
- gpointer priv;
-};
-
-extern const TpCMProtocolSpec gabble_protocols[];
-
-GType gabble_connection_manager_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_CONNECTION_MANAGER \
- (gabble_connection_manager_get_type ())
-#define GABBLE_CONNECTION_MANAGER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_CONNECTION_MANAGER, \
- GabbleConnectionManager))
-#define GABBLE_CONNECTION_MANAGER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_CONNECTION_MANAGER, \
- GabbleConnectionManagerClass))
-#define GABBLE_IS_CONNECTION_MANAGER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CONNECTION_MANAGER))
-#define GABBLE_IS_CONNECTION_MANAGER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CONNECTION_MANAGER))
-#define GABBLE_CONNECTION_MANAGER_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CONNECTION_MANAGER, \
- GabbleConnectionManagerClass))
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_CONNECTION_MANAGER_H__*/
diff --git a/src/gabble-connection.c b/src/gabble-connection.c
deleted file mode 100644
index 2c0c38849..000000000
--- a/src/gabble-connection.c
+++ /dev/null
@@ -1,2809 +0,0 @@
-/*
- * gabble-connection.c - Source for GabbleConnection
- * Copyright (C) 2005, 2006 Collabora Ltd.
- * Copyright (C) 2005, 2006 Nokia Corporation
- *
- * 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
- */
-
-#include "config.h"
-
-#include "gabble-connection.h"
-
-#define DBUS_API_SUBJECT_TO_CHANGE
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <glib-object.h>
-#include <loudmouth/loudmouth.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/interfaces.h>
-
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/channel-factory-iface.h>
-
-#include <telepathy-glib/handle-repo-dynamic.h>
-#include <telepathy-glib/handle-repo-static.h>
-
-#include <telepathy-glib/svc-connection.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION
-
-#include "capabilities.h"
-#include "conn-aliasing.h"
-#include "conn-avatars.h"
-#include "conn-presence.h"
-#include "debug.h"
-#include "disco.h"
-#include "presence-cache.h"
-#include "presence.h"
-#include "gabble-register.h"
-#include "im-factory.h"
-#include "media-factory.h"
-#include "muc-factory.h"
-#include "namespaces.h"
-#include "roster.h"
-#include "util.h"
-#include "vcard-manager.h"
-
-#include "gabble-media-channel.h"
-#include "gabble-roomlist-channel.h"
-
-#define TP_ALIAS_PAIR_TYPE (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID))
-#define TP_CAPABILITY_PAIR_TYPE (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID))
-#define TP_CAPABILITIES_CHANGED_MONSTER_TYPE (dbus_g_type_get_struct \
- ("GValueArray", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, \
- G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID))
-#define TP_GET_CAPABILITIES_MONSTER_TYPE (dbus_g_type_get_struct \
- ("GValueArray", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, \
- G_TYPE_INVALID))
-
-static void conn_service_iface_init (gpointer, gpointer);
-static void capabilities_service_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE(GabbleConnection,
- gabble_connection,
- TP_TYPE_BASE_CONNECTION,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION,
- conn_service_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,
- conn_aliasing_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS,
- conn_avatars_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CAPABILITIES,
- capabilities_service_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE,
- conn_presence_iface_init);
- )
-
-/* properties */
-enum
-{
- PROP_CONNECT_SERVER = 1,
- PROP_PORT,
- PROP_OLD_SSL,
- PROP_REGISTER,
- PROP_LOW_BANDWIDTH,
- PROP_STREAM_SERVER,
- PROP_USERNAME,
- PROP_PASSWORD,
- PROP_RESOURCE,
- PROP_PRIORITY,
- PROP_HTTPS_PROXY_SERVER,
- PROP_HTTPS_PROXY_PORT,
- PROP_FALLBACK_CONFERENCE_SERVER,
- PROP_STUN_SERVER,
- PROP_STUN_PORT,
- PROP_IGNORE_SSL_ERRORS,
- PROP_ALIAS,
- PROP_AUTH_MAC,
- PROP_AUTH_BTID,
-
- LAST_PROPERTY
-};
-
-/* private structure */
-typedef struct _GabbleConnectionPrivate GabbleConnectionPrivate;
-
-struct _GabbleConnectionPrivate
-{
- LmMessageHandler *iq_disco_cb;
- LmMessageHandler *iq_unknown_cb;
- LmMessageHandler *stream_error_cb;
-
- /* connection properties */
- gchar *connect_server;
- guint port;
- gboolean old_ssl;
-
- gboolean ignore_ssl_errors;
- TpConnectionStatusReason ssl_error;
-
- gboolean do_register;
-
- gboolean low_bandwidth;
-
- gchar *https_proxy_server;
- guint16 https_proxy_port;
-
- gchar *stun_server;
- guint16 stun_port;
-
- gchar *fallback_conference_server;
-
- /* authentication properties */
- gchar *stream_server;
- gchar *username;
- gchar *password;
- gchar *resource;
- gint8 priority;
- gchar *alias;
- gchar *auth_mac;
- gchar *auth_btid;
-
- /* reference to conference server name */
- const gchar *conference_server;
-
- /* serial number of current advertised caps */
- guint caps_serial;
-
- /* gobject housekeeping */
- gboolean dispose_has_run;
-};
-
-#define GABBLE_CONNECTION_GET_PRIVATE(obj) \
- ((GabbleConnectionPrivate *)obj->priv)
-
-static void connection_nickname_update_cb (GObject *, TpHandle, gpointer);
-static void connection_capabilities_update_cb (GabblePresenceCache *,
- TpHandle, GabblePresenceCapabilities, GabblePresenceCapabilities,
- gpointer);
-
-static GPtrArray *
-_gabble_connection_create_channel_factories (TpBaseConnection *conn)
-{
- GabbleConnection *self = GABBLE_CONNECTION (conn);
-
- GPtrArray *channel_factories = g_ptr_array_sized_new (4);
-
- self->roster = gabble_roster_new (self);
- g_signal_connect (self->roster, "nickname-update", G_CALLBACK
- (connection_nickname_update_cb), self);
-
- g_ptr_array_add (channel_factories, self->roster);
-
- g_ptr_array_add (channel_factories,
- g_object_new (GABBLE_TYPE_MUC_FACTORY,
- "connection", self,
- NULL));
-
- g_ptr_array_add (channel_factories,
- g_object_new (GABBLE_TYPE_MEDIA_FACTORY,
- "connection", self,
- NULL));
-
- g_ptr_array_add (channel_factories,
- g_object_new (GABBLE_TYPE_IM_FACTORY,
- "connection", self,
- NULL));
-
- return channel_factories;
-}
-
-static GObject *
-gabble_connection_constructor (GType type,
- guint n_construct_properties,
- GObjectConstructParam *construct_params)
-{
- GabbleConnection *self = GABBLE_CONNECTION (
- G_OBJECT_CLASS (gabble_connection_parent_class)->constructor (
- type, n_construct_properties, construct_params));
-
- DEBUG("Post-construction: (GabbleConnection *)%p", self);
-
- self->disco = gabble_disco_new (self);
- self->vcard_manager = gabble_vcard_manager_new (self);
- g_signal_connect (self->vcard_manager, "nickname-update", G_CALLBACK
- (connection_nickname_update_cb), self);
-
- self->presence_cache = gabble_presence_cache_new (self);
- g_signal_connect (self->presence_cache, "nickname-update", G_CALLBACK
- (connection_nickname_update_cb), self);
- g_signal_connect (self->presence_cache, "capabilities-update", G_CALLBACK
- (connection_capabilities_update_cb), self);
-
- capabilities_fill_cache (self->presence_cache);
-
- conn_avatars_init (self);
- conn_presence_init (self);
-
- return (GObject *)self;
-}
-
-static void
-gabble_connection_init (GabbleConnection *self)
-{
- GabbleConnectionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_CONNECTION, GabbleConnectionPrivate);
-
- DEBUG("Initializing (GabbleConnection *)%p", self);
-
- self->priv = priv;
- self->lmconn = lm_connection_new (NULL);
-
- /* Set default parameters for optional parameters */
- priv->resource = g_strdup (GABBLE_PARAMS_DEFAULT_RESOURCE);
-
- priv->caps_serial = 1;
-}
-
-static void
-gabble_connection_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleConnection *self = (GabbleConnection *) object;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- switch (property_id) {
- case PROP_CONNECT_SERVER:
- g_value_set_string (value, priv->connect_server);
- break;
- case PROP_STREAM_SERVER:
- g_value_set_string (value, priv->stream_server);
- break;
- case PROP_PORT:
- g_value_set_uint (value, priv->port);
- break;
- case PROP_OLD_SSL:
- g_value_set_boolean (value, priv->old_ssl);
- break;
- case PROP_REGISTER:
- g_value_set_boolean (value, priv->do_register);
- break;
- case PROP_LOW_BANDWIDTH:
- g_value_set_boolean (value, priv->low_bandwidth);
- break;
- case PROP_USERNAME:
- g_value_set_string (value, priv->username);
- break;
- case PROP_PASSWORD:
- g_value_set_string (value, priv->password);
- break;
- case PROP_RESOURCE:
- g_value_set_string (value, priv->resource);
- break;
- case PROP_PRIORITY:
- g_value_set_char (value, priv->priority);
- break;
- case PROP_HTTPS_PROXY_SERVER:
- g_value_set_string (value, priv->https_proxy_server);
- break;
- case PROP_HTTPS_PROXY_PORT:
- g_value_set_uint (value, priv->https_proxy_port);
- break;
- case PROP_FALLBACK_CONFERENCE_SERVER:
- g_value_set_string (value, priv->fallback_conference_server);
- break;
- case PROP_IGNORE_SSL_ERRORS:
- g_value_set_boolean (value, priv->ignore_ssl_errors);
- break;
- case PROP_ALIAS:
- g_value_set_string (value, priv->alias);
- break;
- case PROP_AUTH_MAC:
- g_value_set_string (value, priv->auth_mac);
- break;
- case PROP_AUTH_BTID:
- g_value_set_string (value, priv->auth_btid);
- break;
- case PROP_STUN_SERVER:
- g_value_set_string (value, priv->stun_server);
- break;
- case PROP_STUN_PORT:
- g_value_set_uint (value, priv->stun_port);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_connection_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleConnection *self = (GabbleConnection *) object;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- switch (property_id) {
- case PROP_CONNECT_SERVER:
- g_free (priv->connect_server);
- priv->connect_server = g_value_dup_string (value);
- break;
- case PROP_PORT:
- priv->port = g_value_get_uint (value);
- break;
- case PROP_OLD_SSL:
- priv->old_ssl = g_value_get_boolean (value);
- break;
- case PROP_REGISTER:
- priv->do_register = g_value_get_boolean (value);
- break;
- case PROP_LOW_BANDWIDTH:
- priv->low_bandwidth = g_value_get_boolean (value);
- break;
- case PROP_STREAM_SERVER:
- g_free (priv->stream_server);
- priv->stream_server = g_value_dup_string (value);
- break;
- case PROP_USERNAME:
- g_free (priv->username);
- priv->username = g_value_dup_string (value);
- break;
- case PROP_PASSWORD:
- g_free (priv->password);
- priv->password = g_value_dup_string (value);
- break;
- case PROP_RESOURCE:
- g_free (priv->resource);
- priv->resource = g_value_dup_string (value);
- break;
- case PROP_PRIORITY:
- priv->priority = g_value_get_char (value);
- break;
- case PROP_HTTPS_PROXY_SERVER:
- g_free (priv->https_proxy_server);
- priv->https_proxy_server = g_value_dup_string (value);
- break;
- case PROP_HTTPS_PROXY_PORT:
- priv->https_proxy_port = g_value_get_uint (value);
- break;
- case PROP_FALLBACK_CONFERENCE_SERVER:
- g_free (priv->fallback_conference_server);
- priv->fallback_conference_server = g_value_dup_string (value);
- break;
- case PROP_IGNORE_SSL_ERRORS:
- priv->ignore_ssl_errors = g_value_get_boolean (value);
- break;
- case PROP_ALIAS:
- g_free (priv->alias);
- priv->alias = g_value_dup_string (value);
- break;
- case PROP_AUTH_MAC:
- g_free (priv->auth_mac);
- priv->auth_mac = g_value_dup_string (value);
- break;
- case PROP_AUTH_BTID:
- g_free (priv->auth_btid);
- priv->auth_btid = g_value_dup_string (value);
- break;
- case PROP_STUN_SERVER:
- g_free (priv->stun_server);
- priv->stun_server = g_value_dup_string (value);
- break;
- case PROP_STUN_PORT:
- priv->stun_port = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_connection_dispose (GObject *object);
-static void gabble_connection_finalize (GObject *object);
-static void connect_callbacks (TpBaseConnection *base);
-static void disconnect_callbacks (TpBaseConnection *base);
-static void connection_shut_down (TpBaseConnection *base);
-static gboolean _gabble_connection_connect (TpBaseConnection *base,
- GError **error);
-
-static gchar *
-gabble_connection_get_unique_name (TpBaseConnection *self)
-{
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (
- GABBLE_CONNECTION (self));
-
- return g_strdup_printf ("%s@%s/%s",
- priv->username,
- priv->stream_server,
- priv->resource);
-}
-
-/* must be in the same order as GabbleListHandle in gabble-connection.h */
-static const char *list_handle_strings[] =
-{
- "publish", /* GABBLE_LIST_HANDLE_PUBLISH */
- "subscribe", /* GABBLE_LIST_HANDLE_SUBSCRIBE */
- "known", /* GABBLE_LIST_HANDLE_KNOWN */
- "deny", /* GABBLE_LIST_HANDLE_DENY */
- NULL
-};
-
-/* For the benefit of the unit tests, this will allow the connection to
- * be NULL
- */
-void
-_gabble_connection_create_handle_repos (TpBaseConnection *conn,
- TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])
-{
- repos[TP_HANDLE_TYPE_CONTACT] =
- tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_CONTACT,
- gabble_normalize_contact, GUINT_TO_POINTER (GABBLE_JID_ANY));
- repos[TP_HANDLE_TYPE_ROOM] =
- tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_ROOM, gabble_normalize_room,
- NULL);
- repos[TP_HANDLE_TYPE_GROUP] =
- tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_GROUP, NULL, NULL);
- repos[TP_HANDLE_TYPE_LIST] =
- tp_static_handle_repo_new (TP_HANDLE_TYPE_LIST, list_handle_strings);
-}
-
-static void
-gabble_connection_class_init (GabbleConnectionClass *gabble_connection_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_connection_class);
- TpBaseConnectionClass *parent_class = TP_BASE_CONNECTION_CLASS (
- gabble_connection_class);
- GParamSpec *param_spec;
- static const gchar *interfaces_always_present[] = {
- TP_IFACE_CONNECTION_INTERFACE_ALIASING,
- TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES,
- TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
- TP_IFACE_CONNECTION_INTERFACE_AVATARS,
- NULL };
-
- DEBUG("Initializing (GabbleConnectionClass *)%p", gabble_connection_class);
-
- object_class->get_property = gabble_connection_get_property;
- object_class->set_property = gabble_connection_set_property;
- object_class->constructor = gabble_connection_constructor;
-
- parent_class->create_handle_repos = _gabble_connection_create_handle_repos;
- parent_class->get_unique_connection_name = gabble_connection_get_unique_name;
- parent_class->create_channel_factories =
- _gabble_connection_create_channel_factories;
- parent_class->connecting = connect_callbacks;
- parent_class->disconnected = disconnect_callbacks;
- parent_class->shut_down = connection_shut_down;
- parent_class->start_connecting = _gabble_connection_connect;
- parent_class->interfaces_always_present = interfaces_always_present;
-
- g_type_class_add_private (gabble_connection_class,
- sizeof (GabbleConnectionPrivate));
-
- object_class->dispose = gabble_connection_dispose;
- object_class->finalize = gabble_connection_finalize;
-
- param_spec = g_param_spec_string ("connect-server", "Hostname or IP of Jabber server",
- "The server used when establishing a connection.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECT_SERVER, param_spec);
-
- param_spec = g_param_spec_uint ("port", "Jabber server port",
- "The port used when establishing a connection.",
- 0, G_MAXUINT16, GABBLE_PARAMS_DEFAULT_PORT,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PORT, param_spec);
-
- param_spec = g_param_spec_boolean ("old-ssl", "Old-style SSL tunneled connection",
- "Establish the entire connection to the server "
- "within an SSL-encrypted tunnel. Note that this "
- "is not the same as connecting with TLS, which "
- "is not yet supported.", FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_OLD_SSL, param_spec);
-
- param_spec = g_param_spec_boolean ("register", "Register account on server",
- "Register a new account on server.", FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_REGISTER, param_spec);
-
- param_spec = g_param_spec_boolean ("low-bandwidth", "Low bandwidth mode",
- "Determines whether we are in low "
- "bandwidth mode. This influences "
- "polling behaviour.", FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_LOW_BANDWIDTH, param_spec);
-
- param_spec = g_param_spec_string ("stream-server", "The server name used to initialise the stream.",
- "The server name used when initialising the stream, "
- "which is usually the part after the @ in the user's JID.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STREAM_SERVER, param_spec);
-
- param_spec = g_param_spec_string ("username", "Jabber username",
- "The username used when authenticating.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_USERNAME, param_spec);
-
- param_spec = g_param_spec_string ("password", "Jabber password",
- "The password used when authenticating.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PASSWORD, param_spec);
-
- param_spec = g_param_spec_string ("resource", "Jabber resource",
- "The Jabber resource used when authenticating.",
- "Telepathy",
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_RESOURCE, param_spec);
-
- param_spec = g_param_spec_char ("priority", "Jabber presence priority",
- "The default priority used when reporting our presence.",
- G_MININT8, G_MAXINT8, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PRIORITY, param_spec);
-
- param_spec = g_param_spec_string ("https-proxy-server", "The server name "
- "used as an HTTPS proxy server",
- "The server name used as an HTTPS proxy "
- "server.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_HTTPS_PROXY_SERVER, param_spec);
-
- param_spec = g_param_spec_uint ("https-proxy-port", "The HTTP proxy server "
- "port", "The HTTP proxy server port.",
- 0, G_MAXUINT16, GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_PORT,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_HTTPS_PROXY_PORT, param_spec);
-
- param_spec = g_param_spec_string ("fallback-conference-server",
- "The conference server used as fallback",
- "The conference server used as fallback when "
- "everything else fails.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_FALLBACK_CONFERENCE_SERVER,
- param_spec);
-
- param_spec = g_param_spec_string ("stun-server",
- "STUN server",
- "STUN server.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_SERVER, param_spec);
-
- param_spec = g_param_spec_uint ("stun-port",
- "STUN port",
- "STUN port.",
- 0, G_MAXUINT16, GABBLE_PARAMS_DEFAULT_STUN_PORT,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_PORT, param_spec);
-
- param_spec = g_param_spec_boolean ("ignore-ssl-errors", "Ignore SSL errors",
- "Continue connecting even if the server's "
- "SSL certificate is invalid or missing.",
- FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_IGNORE_SSL_ERRORS, param_spec);
-
- param_spec = g_param_spec_string ("alias",
- "Alias/nick for local user",
- "Alias/nick for local user",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_ALIAS, param_spec);
-
- param_spec = g_param_spec_string ("auth-mac",
- "MAC for authorization",
- "MAC for authorization",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_AUTH_MAC, param_spec);
-
- param_spec = g_param_spec_string ("auth-btid",
- "BTID for authorization",
- "BTID for authorization",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_AUTH_BTID, param_spec);
-}
-
-static gboolean
-_unref_lm_connection (gpointer data)
-{
- LmConnection *conn = (LmConnection *) data;
-
- lm_connection_unref (conn);
- return FALSE;
-}
-
-static void
-gabble_connection_dispose (GObject *object)
-{
- GabbleConnection *self = GABBLE_CONNECTION (object);
- TpBaseConnection *base = (TpBaseConnection *)self;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- DEBUG ("called");
-
- g_assert ((base->status == TP_CONNECTION_STATUS_DISCONNECTED) ||
- (base->status == TP_INTERNAL_CONNECTION_STATUS_NEW));
- g_assert (base->self_handle == 0);
-
- g_object_unref (self->vcard_manager);
- self->vcard_manager = NULL;
-
- /* unreffing channel factories frees the roster */
- self->roster = NULL;
-
- g_object_unref (self->disco);
- self->disco = NULL;
-
- if (self->self_presence != NULL)
- g_object_unref (self->self_presence);
- self->self_presence = NULL;
-
- g_object_unref (self->presence_cache);
- self->presence_cache = NULL;
-
- /* if this is not already the case, we'll crash anyway */
- g_assert (!lm_connection_is_open (self->lmconn));
-
- g_assert (priv->iq_disco_cb == NULL);
- g_assert (priv->iq_unknown_cb == NULL);
- g_assert (priv->stream_error_cb == NULL);
-
- /*
- * The Loudmouth connection can't be unref'd immediately because this
- * function might (indirectly) return into Loudmouth code which expects the
- * connection to always be there.
- */
- g_idle_add (_unref_lm_connection, self->lmconn);
-
- if (G_OBJECT_CLASS (gabble_connection_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_connection_parent_class)->dispose (object);
-}
-
-static void
-gabble_connection_finalize (GObject *object)
-{
- GabbleConnection *self = GABBLE_CONNECTION (object);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- DEBUG ("called with %p", object);
-
- g_free (priv->connect_server);
- g_free (priv->stream_server);
- g_free (priv->username);
- g_free (priv->password);
- g_free (priv->resource);
-
- g_free (priv->https_proxy_server);
- g_free (priv->stun_server);
- g_free (priv->fallback_conference_server);
-
- g_free (priv->alias);
-
- g_free (priv->auth_mac);
- g_free (priv->auth_btid);
-
- G_OBJECT_CLASS (gabble_connection_parent_class)->finalize (object);
-}
-
-/**
- * _gabble_connection_set_properties_from_account
- *
- * Parses an account string which may be one of the following forms:
- * username@server
- * username@server/resource
- * and sets the properties for username, stream server and resource
- * appropriately. Also sets the connect server to the stream server if one has
- * not yet been specified.
- */
-gboolean
-_gabble_connection_set_properties_from_account (GabbleConnection *conn,
- const gchar *account,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- char *username, *server, *resource;
- gboolean result;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
- g_assert (account != NULL);
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- username = server = resource = NULL;
- result = TRUE;
-
- gabble_decode_jid (account, &username, &server, &resource);
-
- if (username == NULL || server == NULL ||
- *username == '\0' || *server == '\0')
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "unable to get username and server from account");
- result = FALSE;
- goto OUT;
- }
-
- g_object_set (G_OBJECT (conn),
- "username", username,
- "stream-server", server,
- NULL);
-
- /* only override the default resource if we actually got one */
- if (resource)
- g_object_set (G_OBJECT (conn), "resource", resource, NULL);
-
-OUT:
- g_free (username);
- g_free (server);
- g_free (resource);
-
- return result;
-}
-
-
-/**
- * _gabble_connection_send
- *
- * Send an LmMessage and trap network errors appropriately.
- */
-gboolean
-_gabble_connection_send (GabbleConnection *conn, LmMessage *msg, GError **error)
-{
- GabbleConnectionPrivate *priv;
- GError *lmerror = NULL;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- if (!lm_connection_send (conn->lmconn, msg, &lmerror))
- {
- DEBUG ("failed: %s", lmerror->message);
-
- g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "message send failed: %s", lmerror->message);
-
- g_error_free (lmerror);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-typedef struct {
- GabbleConnectionMsgReplyFunc reply_func;
-
- GabbleConnection *conn;
- LmMessage *sent_msg;
- gpointer user_data;
-
- GObject *object;
- gboolean object_alive;
-} GabbleMsgHandlerData;
-
-static LmHandlerResult
-message_send_reply_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *reply_msg,
- gpointer user_data)
-{
- GabbleMsgHandlerData *handler_data = user_data;
- LmMessageSubType sub_type;
-
- sub_type = lm_message_get_sub_type (reply_msg);
-
- /* Is it a reply to this message? If we're talking to another loudmouth,
- * they can send us messages which have the same ID as ones we send. :-O */
- if (sub_type != LM_MESSAGE_SUB_TYPE_RESULT &&
- sub_type != LM_MESSAGE_SUB_TYPE_ERROR)
- {
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- if (handler_data->object_alive)
- {
- return handler_data->reply_func (handler_data->conn,
- handler_data->sent_msg,
- reply_msg,
- handler_data->object,
- handler_data->user_data);
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-message_send_object_destroy_notify_cb (gpointer data,
- GObject *where_the_object_was)
-{
- GabbleMsgHandlerData *handler_data = data;
-
- handler_data->object = NULL;
- handler_data->object_alive = FALSE;
-}
-
-static void
-message_send_handler_destroy_cb (gpointer data)
-{
- GabbleMsgHandlerData *handler_data = data;
-
- lm_message_unref (handler_data->sent_msg);
-
- if (handler_data->object != NULL)
- {
- g_object_weak_unref (handler_data->object,
- message_send_object_destroy_notify_cb,
- handler_data);
- }
-
- g_slice_free (GabbleMsgHandlerData, handler_data);
-}
-
-/**
- * _gabble_connection_send_with_reply
- *
- * Send a tracked LmMessage and trap network errors appropriately.
- *
- * If object is non-NULL the handler will follow the lifetime of that object,
- * which means that if the object is destroyed the callback will not be invoked.
- */
-gboolean
-_gabble_connection_send_with_reply (GabbleConnection *conn,
- LmMessage *msg,
- GabbleConnectionMsgReplyFunc reply_func,
- GObject *object,
- gpointer user_data,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- LmMessageHandler *handler;
- GabbleMsgHandlerData *handler_data;
- gboolean ret;
- GError *lmerror = NULL;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- lm_message_ref (msg);
-
- handler_data = g_slice_new (GabbleMsgHandlerData);
- handler_data->reply_func = reply_func;
- handler_data->conn = conn;
- handler_data->sent_msg = msg;
- handler_data->user_data = user_data;
-
- handler_data->object = object;
- handler_data->object_alive = TRUE;
-
- if (object != NULL)
- {
- g_object_weak_ref (object, message_send_object_destroy_notify_cb,
- handler_data);
- }
-
- handler = lm_message_handler_new (message_send_reply_cb, handler_data,
- message_send_handler_destroy_cb);
-
- ret = lm_connection_send_with_reply (conn->lmconn, msg, handler, &lmerror);
- if (!ret)
- {
- DEBUG ("failed: %s", lmerror->message);
-
- if (error)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "message send failed: %s", lmerror->message);
- }
-
- g_error_free (lmerror);
- }
-
- lm_message_handler_unref (handler);
-
- return ret;
-}
-
-static LmHandlerResult connection_iq_disco_cb (LmMessageHandler *,
- LmConnection *, LmMessage *, gpointer);
-static LmHandlerResult connection_iq_unknown_cb (LmMessageHandler *,
- LmConnection *, LmMessage *, gpointer);
-static LmHandlerResult connection_stream_error_cb (LmMessageHandler *,
- LmConnection *, LmMessage *, gpointer);
-static LmSSLResponse connection_ssl_cb (LmSSL *, LmSSLStatus, gpointer);
-static void connection_open_cb (LmConnection *, gboolean, gpointer);
-static void connection_auth_cb (LmConnection *, gboolean, gpointer);
-static void connection_disco_cb (GabbleDisco *, GabbleDiscoRequest *,
- const gchar *, const gchar *, LmMessageNode *, GError *, gpointer);
-static void connection_disconnected_cb (LmConnection *, LmDisconnectReason,
- gpointer);
-
-
-static gboolean
-do_connect (GabbleConnection *conn, GError **error)
-{
- GError *lmerror = NULL;
-
- DEBUG ("calling lm_connection_open");
-
- if (!lm_connection_open (conn->lmconn, connection_open_cb,
- conn, NULL, &lmerror))
- {
- DEBUG ("lm_connection_open failed %s", lmerror->message);
-
- g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "lm_connection_open failed: %s", lmerror->message);
-
- g_error_free (lmerror);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-connect_callbacks (TpBaseConnection *base)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (base);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- g_assert (priv->iq_disco_cb == NULL);
- g_assert (priv->iq_unknown_cb == NULL);
- g_assert (priv->stream_error_cb == NULL);
-
- priv->iq_disco_cb = lm_message_handler_new (connection_iq_disco_cb,
- conn, NULL);
- lm_connection_register_message_handler (conn->lmconn, priv->iq_disco_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_NORMAL);
-
- priv->iq_unknown_cb = lm_message_handler_new (connection_iq_unknown_cb,
- conn, NULL);
- lm_connection_register_message_handler (conn->lmconn, priv->iq_unknown_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_LAST);
-
- priv->stream_error_cb = lm_message_handler_new (connection_stream_error_cb,
- conn, NULL);
- lm_connection_register_message_handler (conn->lmconn, priv->stream_error_cb,
- LM_MESSAGE_TYPE_STREAM_ERROR,
- LM_HANDLER_PRIORITY_LAST);
-}
-
-static void
-disconnect_callbacks (TpBaseConnection *base)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (base);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- g_assert (priv->iq_disco_cb != NULL);
- g_assert (priv->iq_unknown_cb != NULL);
- g_assert (priv->stream_error_cb != NULL);
-
- lm_connection_unregister_message_handler (conn->lmconn, priv->iq_disco_cb,
- LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->iq_disco_cb);
- priv->iq_disco_cb = NULL;
-
- lm_connection_unregister_message_handler (conn->lmconn, priv->iq_unknown_cb,
- LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->iq_unknown_cb);
- priv->iq_unknown_cb = NULL;
-
- lm_connection_unregister_message_handler (conn->lmconn,
- priv->stream_error_cb, LM_MESSAGE_TYPE_STREAM_ERROR);
- lm_message_handler_unref (priv->stream_error_cb);
- priv->stream_error_cb = NULL;
-}
-
-/**
- * _gabble_connection_connect
- *
- * Use the stored server & authentication details to commence
- * the stages for connecting to the server and authenticating. Will
- * re-use an existing LmConnection if it is present, or create it
- * if necessary.
- *
- * Stage 1 is _gabble_connection_connect calling lm_connection_open
- * Stage 2 is connection_open_cb calling lm_connection_authenticate
- * Stage 3 is connection_auth_cb initiating service discovery
- * Stage 4 is connection_disco_cb advertising initial presence, requesting
- * the roster and setting the CONNECTED state
- */
-static gboolean
-_gabble_connection_connect (TpBaseConnection *base,
- GError **error)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (base);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
- char *jid;
-
- g_assert (priv->port > 0 && priv->port <= G_MAXUINT16);
- g_assert (priv->stream_server != NULL);
- g_assert (priv->username != NULL);
- g_assert (priv->password != NULL);
- g_assert (priv->resource != NULL);
- g_assert (lm_connection_is_open (conn->lmconn) == FALSE);
-
- jid = g_strdup_printf ("%s@%s", priv->username, priv->stream_server);
- lm_connection_set_jid (conn->lmconn, jid);
-
- base->self_handle = tp_handle_ensure (contact_handles, jid, NULL, error);
- g_free (jid);
-
- if (base->self_handle == 0)
- {
- return FALSE;
- }
-
- /* set initial presence */
- conn->self_presence = gabble_presence_new ();
- gabble_presence_update (conn->self_presence, priv->resource,
- GABBLE_PRESENCE_AVAILABLE, NULL, priv->priority);
-
- /* set initial capabilities */
- gabble_presence_set_capabilities (conn->self_presence, priv->resource,
- capabilities_get_initial_caps (), priv->caps_serial++);
-
- /* always override server and port if one was forced upon us */
- if (priv->connect_server != NULL)
- {
- lm_connection_set_server (conn->lmconn, priv->connect_server);
- lm_connection_set_port (conn->lmconn, priv->port);
- }
- /* otherwise set the server & port to the stream server,
- * if one didn't appear from a SRV lookup */
- else if (lm_connection_get_server (conn->lmconn) == NULL)
- {
- lm_connection_set_server (conn->lmconn, priv->stream_server);
- lm_connection_set_port (conn->lmconn, priv->port);
- }
-
- if (priv->https_proxy_server)
- {
- LmProxy *proxy;
-
- proxy = lm_proxy_new_with_server (LM_PROXY_TYPE_HTTP,
- priv->https_proxy_server, priv->https_proxy_port);
-
- lm_connection_set_proxy (conn->lmconn, proxy);
-
- lm_proxy_unref (proxy);
- }
-
- if (priv->old_ssl)
- {
- LmSSL *ssl = lm_ssl_new (NULL, connection_ssl_cb, conn, NULL);
- lm_connection_set_ssl (conn->lmconn, ssl);
- lm_ssl_unref (ssl);
- }
-
- /* send whitespace to the server every 30 seconds */
- lm_connection_set_keep_alive_rate (conn->lmconn, 30);
-
- lm_connection_set_disconnect_function (conn->lmconn,
- connection_disconnected_cb,
- conn,
- NULL);
-
- return do_connect (conn, error);
-}
-
-
-
-static void
-connection_disconnected_cb (LmConnection *lmconn,
- LmDisconnectReason lm_reason,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- TpBaseConnection *base = (TpBaseConnection *)user_data;
-
- g_assert (conn->lmconn == lmconn);
-
- DEBUG ("called with reason %u", lm_reason);
-
- /* if we were expecting this disconnection, we're done so can tell
- * the connection manager to unref us. otherwise it's a network error
- * or some other screw up we didn't expect, so we emit the status
- * change */
- if (base->status == TP_CONNECTION_STATUS_DISCONNECTED)
- {
- DEBUG ("expected; emitting DISCONNECTED");
- tp_base_connection_finish_shutdown ((TpBaseConnection *)conn);
- }
- else
- {
- DEBUG ("unexpected; calling tp_base_connection_change_status");
- tp_base_connection_change_status ((TpBaseConnection *)conn,
- TP_CONNECTION_STATUS_DISCONNECTED,
- TP_CONNECTION_STATUS_REASON_NETWORK_ERROR);
- }
-}
-
-
-static void
-connection_shut_down (TpBaseConnection *base)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (base);
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- /* If we're shutting down by user request, we don't want to be
- * unreffed until the LM connection actually closes; the event handler
- * will tell the base class that shutdown has finished.
- *
- * On the other hand, if we're shutting down because the connection
- * suffered a network error, the LM connection will already be closed,
- * so just tell the base class to finish shutting down immediately.
- */
- if (lm_connection_is_open (conn->lmconn))
- {
- DEBUG ("still open; calling lm_connection_close");
- lm_connection_close (conn->lmconn, NULL);
- }
- else
- {
- /* lm_connection_is_open() returns FALSE if LmConnection is in the
- * middle of connecting, so call this just in case */
- lm_connection_cancel_open (conn->lmconn);
- DEBUG ("closed; emitting DISCONNECTED");
- tp_base_connection_finish_shutdown (base);
- }
-}
-
-GabbleConnectionAliasSource
-_gabble_connection_get_cached_alias (GabbleConnection *conn,
- TpHandle handle,
- gchar **alias)
-{
- TpBaseConnection *base = (TpBaseConnection *)conn;
- GabbleConnectionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (conn,
- GABBLE_TYPE_CONNECTION, GabbleConnectionPrivate);
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
- GabbleConnectionAliasSource ret = GABBLE_CONNECTION_ALIAS_NONE;
- GabblePresence *pres;
- const gchar *tmp;
- gchar *user = NULL, *resource = NULL;
-
- g_return_val_if_fail (NULL != conn, GABBLE_CONNECTION_ALIAS_NONE);
- g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), GABBLE_CONNECTION_ALIAS_NONE);
- g_return_val_if_fail (tp_handle_is_valid (contact_handles, handle, NULL),
- GABBLE_CONNECTION_ALIAS_NONE);
-
- tmp = gabble_roster_handle_get_name (conn->roster, handle);
- if (NULL != tmp)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_ROSTER;
-
- if (NULL != alias)
- *alias = g_strdup (tmp);
-
- goto OUT;
- }
-
- pres = gabble_presence_cache_get (conn->presence_cache, handle);
- if (NULL != pres && NULL != pres->nickname)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_PRESENCE;
-
- if (NULL != alias)
- *alias = g_strdup (pres->nickname);
-
- goto OUT;
- }
-
- /* XXX: should this be more important than the ones from presence? */
- /* if it's our own handle, use alias passed to the connmgr, if any */
- if (handle == base->self_handle && priv->alias != NULL)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_CONNMGR;
-
- if (NULL != alias)
- *alias = g_strdup (priv->alias);
-
- goto OUT;
- }
-
- /* if we've seen a nickname in their vCard, use that */
- tmp = gabble_vcard_manager_get_cached_alias (conn->vcard_manager, handle);
- if (NULL != tmp)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_VCARD;
-
- if (NULL != alias)
- *alias = g_strdup (tmp);
-
- goto OUT;
- }
-
- /* fallback to JID */
- tmp = tp_handle_inspect (contact_handles, handle);
- g_assert (NULL != tmp);
-
- gabble_decode_jid (tmp, &user, NULL, &resource);
-
- /* MUC handles have the nickname in the resource */
- if (NULL != resource)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_JID;
-
- if (NULL != alias)
- {
- *alias = resource;
- resource = NULL;
- }
-
- goto OUT;
- }
-
- /* otherwise just take their local part */
- if (NULL != user)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_JID;
-
- if (NULL != alias)
- {
- *alias = user;
- user = NULL;
- }
-
- goto OUT;
- }
-
-OUT:
- g_free (user);
- g_free (resource);
- return ret;
-}
-
-static void
-connection_nickname_update_cb (GObject *object,
- TpHandle handle,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- GabbleConnectionAliasSource signal_source, current_source;
- gchar *alias = NULL;
- GPtrArray *aliases;
- GValue entry = { 0, };
-
- if (object == G_OBJECT (conn->roster))
- {
- signal_source = GABBLE_CONNECTION_ALIAS_FROM_ROSTER;
- }
- else if (object == G_OBJECT (conn->presence_cache))
- {
- signal_source = GABBLE_CONNECTION_ALIAS_FROM_PRESENCE;
- }
- else if (object == G_OBJECT (conn->vcard_manager))
- {
- signal_source = GABBLE_CONNECTION_ALIAS_FROM_VCARD;
- }
- else
- {
- g_assert_not_reached ();
- return;
- }
-
- current_source = _gabble_connection_get_cached_alias (conn, handle, &alias);
-
- g_assert (current_source != GABBLE_CONNECTION_ALIAS_NONE);
-
- /* if the active alias for this handle is already known and from
- * a higher priority, this signal is not interesting so we do
- * nothing */
- if (signal_source < current_source)
- {
- DEBUG ("ignoring boring alias change for handle %u, signal from %u "
- "but source %u has alias \"%s\"", handle, signal_source,
- current_source, alias);
- goto OUT;
- }
-
- g_value_init (&entry, TP_ALIAS_PAIR_TYPE);
- g_value_take_boxed (&entry, dbus_g_type_specialized_construct
- (TP_ALIAS_PAIR_TYPE));
-
- dbus_g_type_struct_set (&entry,
- 0, handle,
- 1, alias,
- G_MAXUINT);
-
- aliases = g_ptr_array_sized_new (1);
- g_ptr_array_add (aliases, g_value_get_boxed (&entry));
-
-
- tp_svc_connection_interface_aliasing_emit_aliases_changed (conn, aliases);
-
- g_value_unset (&entry);
- g_ptr_array_free (aliases, TRUE);
-
-OUT:
- g_free (alias);
-}
-
-/**
- * _gabble_connection_signal_own_presence:
- * @self: A #GabbleConnection
- * @error: pointer in which to return a GError in case of failure.
- *
- * Signal the user's stored presence to the jabber server
- *
- * Retuns: FALSE if an error occurred
- */
-gboolean
-_gabble_connection_signal_own_presence (GabbleConnection *self, GError **error)
-{
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
- GabblePresence *presence = self->self_presence;
- LmMessage *message = gabble_presence_as_message (presence, priv->resource);
- LmMessageNode *node = lm_message_get_node (message);
- gboolean ret;
- gchar *ext_string = NULL;
- GSList *features, *i;
-
- if (presence->status == GABBLE_PRESENCE_HIDDEN)
- {
- if ((self->features & GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE) != 0)
- lm_message_node_set_attribute (node, "type", "invisible");
- }
-
- /* TODO: why is this not part of presence -> msg? */
- features = capabilities_get_features (presence->caps);
-
- for (i = features; NULL != i; i = i->next)
- {
- const Feature *feat = (const Feature *) i->data;
-
- if ((NULL != feat->bundle) && tp_strdiff (VERSION, feat->bundle))
- {
- if (NULL != ext_string)
- {
- gchar *tmp = ext_string;
- ext_string = g_strdup_printf ("%s %s", ext_string, feat->bundle);
- g_free (tmp);
- }
- else
- {
- ext_string = g_strdup (feat->bundle);
- }
- }
- }
-
- node = lm_message_node_add_child (node, "c", NULL);
- lm_message_node_set_attributes (
- node,
- "xmlns", NS_CAPS,
- "node", NS_GABBLE_CAPS,
- "ver", VERSION,
- NULL);
-
- if (NULL != ext_string)
- lm_message_node_set_attribute (node, "ext", ext_string);
-
- ret = _gabble_connection_send (self, message, error);
-
- lm_message_unref (message);
-
- g_free (ext_string);
- g_slist_free (features);
-
- return ret;
-}
-
-static LmMessage *_lm_iq_message_make_result (LmMessage *iq_message);
-
-/**
- * _gabble_connection_send_iq_result
- *
- * Function used to acknowledge an IQ stanza.
- */
-void
-_gabble_connection_acknowledge_set_iq (GabbleConnection *conn,
- LmMessage *iq)
-{
- LmMessage *result;
-
- g_assert (LM_MESSAGE_TYPE_IQ == lm_message_get_type (iq));
- g_assert (LM_MESSAGE_SUB_TYPE_SET == lm_message_get_sub_type (iq));
-
- result = _lm_iq_message_make_result (iq);
-
- if (NULL != result)
- {
- _gabble_connection_send (conn, result, NULL);
- lm_message_unref (result);
- }
-}
-
-
-/**
- * _gabble_connection_send_iq_error
- *
- * Function used to acknowledge an IQ stanza with an error.
- */
-void
-_gabble_connection_send_iq_error (GabbleConnection *conn,
- LmMessage *message,
- GabbleXmppError error,
- const gchar *errmsg)
-{
- const gchar *to, *id;
- LmMessage *msg;
- LmMessageNode *iq_node;
-
- iq_node = lm_message_get_node (message);
- to = lm_message_node_get_attribute (iq_node, "from");
- id = lm_message_node_get_attribute (iq_node, "id");
-
- if (id == NULL)
- {
- NODE_DEBUG (iq_node, "can't acknowledge IQ with no id");
- return;
- }
-
- msg = lm_message_new_with_sub_type (to, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_ERROR);
-
- lm_message_node_set_attribute (msg->node, "id", id);
-
- lm_message_node_steal_children (msg->node, iq_node);
-
- gabble_xmpp_error_to_node (error, msg->node, errmsg);
-
- _gabble_connection_send (conn, msg, NULL);
-
- lm_message_unref (msg);
-}
-
-static LmMessage *
-_lm_iq_message_make_result (LmMessage *iq_message)
-{
- LmMessage *result;
- LmMessageNode *iq, *result_iq;
- const gchar *from_jid, *id;
-
- g_assert (lm_message_get_type (iq_message) == LM_MESSAGE_TYPE_IQ);
- g_assert (lm_message_get_sub_type (iq_message) == LM_MESSAGE_SUB_TYPE_GET ||
- lm_message_get_sub_type (iq_message) == LM_MESSAGE_SUB_TYPE_SET);
-
- iq = lm_message_get_node (iq_message);
- id = lm_message_node_get_attribute (iq, "id");
-
- if (id == NULL)
- {
- NODE_DEBUG (iq, "can't acknowledge IQ with no id");
- return NULL;
- }
-
- from_jid = lm_message_node_get_attribute (iq, "from");
-
- result = lm_message_new_with_sub_type (from_jid, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_RESULT);
- result_iq = lm_message_get_node (result);
- lm_message_node_set_attribute (result_iq, "id", id);
-
- return result;
-}
-
-/**
- * connection_iq_disco_cb
- *
- * Called by loudmouth when we get an incoming <iq>. This handler handles
- * disco-related IQs.
- */
-static LmHandlerResult
-connection_iq_disco_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleConnection *self = GABBLE_CONNECTION (user_data);
- LmMessage *result;
- LmMessageNode *iq, *result_iq, *query, *result_query;
- const gchar *node, *suffix;
- GSList *features;
- GSList *i;
-
- if (lm_message_get_sub_type (message) != LM_MESSAGE_SUB_TYPE_GET)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- iq = lm_message_get_node (message);
- query = lm_message_node_get_child_with_namespace (iq, "query",
- NS_DISCO_INFO);
-
- if (!query)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- node = lm_message_node_get_attribute (query, "node");
-
- if (node && (
- 0 != strncmp (node, NS_GABBLE_CAPS "#", strlen (NS_GABBLE_CAPS) + 1) ||
- strlen (node) < strlen (NS_GABBLE_CAPS) + 2))
- {
- NODE_DEBUG (iq, "got iq disco query with unexpected node attribute");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- if (node == NULL)
- suffix = NULL;
- else
- suffix = node + strlen (NS_GABBLE_CAPS) + 1;
-
- result = _lm_iq_message_make_result (message);
- result_iq = lm_message_get_node (result);
- result_query = lm_message_node_add_child (result_iq, "query", NULL);
- lm_message_node_set_attribute (result_query, "xmlns", NS_DISCO_INFO);
-
- if (node)
- lm_message_node_set_attribute (result_query, "node", node);
-
- DEBUG ("got disco request for bundle %s, caps are %x", node,
- self->self_presence->caps);
- features = capabilities_get_features (self->self_presence->caps);
-
- g_debug ("%s: caps now %u", G_STRFUNC, self->self_presence->caps);
-
- for (i = features; NULL != i; i = i->next)
- {
- const Feature *feature = (const Feature *) i->data;
-
- if (NULL == node || !tp_strdiff (suffix, feature->bundle))
- {
- LmMessageNode *node = lm_message_node_add_child (result_query,
- "feature", NULL);
- lm_message_node_set_attribute (node, "var", feature->ns);
- }
- }
-
- NODE_DEBUG (result_iq, "sending disco response");
-
- if (!lm_connection_send (self->lmconn, result, NULL))
- {
- DEBUG ("sending disco response failed");
- }
-
- lm_message_unref (result);
- g_slist_free (features);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-/**
- * connection_iq_unknown_cb
- *
- * Called by loudmouth when we get an incoming <iq>. This handler is
- * at a lower priority than the others, and should reply with an error
- * about unsupported get/set attempts.
- */
-static LmHandlerResult
-connection_iq_unknown_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
-
- g_assert (connection == conn->lmconn);
-
- NODE_DEBUG (message->node, "got unknown iq");
-
- switch (lm_message_get_sub_type (message))
- {
- case LM_MESSAGE_SUB_TYPE_GET:
- case LM_MESSAGE_SUB_TYPE_SET:
- _gabble_connection_send_iq_error (conn, message,
- XMPP_ERROR_SERVICE_UNAVAILABLE, NULL);
- break;
- default:
- break;
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-/**
- * connection_stream_error_cb
- *
- * Called by loudmouth when we get stream error, which means that
- * we're about to close the connection. The message contains the reason
- * for the connection hangup.
- */
-static LmHandlerResult
-connection_stream_error_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- LmMessageNode *conflict_node;
-
- g_assert (connection == conn->lmconn);
-
- NODE_DEBUG (message->node, "got stream error");
-
- conflict_node = lm_message_node_get_child (message->node, "conflict");
- if (conflict_node)
- {
- DEBUG ("found conflict node, emiting status change");
-
- /* Another client with the same resource just
- * appeared, we're going down. */
- tp_base_connection_change_status ((TpBaseConnection *)conn,
- TP_CONNECTION_STATUS_DISCONNECTED,
- TP_CONNECTION_STATUS_REASON_NAME_IN_USE);
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-}
-
-
-/**
- * connection_ssl_cb
- *
- * If we're doing old SSL, this function gets called if the certificate
- * is dodgy.
- */
-static LmSSLResponse
-connection_ssl_cb (LmSSL *lmssl,
- LmSSLStatus status,
- gpointer data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (data);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- const char *reason;
- TpConnectionStatusReason tp_reason;
-
- switch (status) {
- case LM_SSL_STATUS_NO_CERT_FOUND:
- reason = "The server doesn't provide a certificate.";
- tp_reason = TP_CONNECTION_STATUS_REASON_CERT_NOT_PROVIDED;
- break;
- case LM_SSL_STATUS_UNTRUSTED_CERT:
- reason = "The certificate can not be trusted.";
- tp_reason = TP_CONNECTION_STATUS_REASON_CERT_UNTRUSTED;
- break;
- case LM_SSL_STATUS_CERT_EXPIRED:
- reason = "The certificate has expired.";
- tp_reason = TP_CONNECTION_STATUS_REASON_CERT_EXPIRED;
- break;
- case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
- reason = "The certificate has not been activated.";
- tp_reason = TP_CONNECTION_STATUS_REASON_CERT_NOT_ACTIVATED;
- break;
- case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
- reason = "The server hostname doesn't match the one in the certificate.";
- tp_reason = TP_CONNECTION_STATUS_REASON_CERT_HOSTNAME_MISMATCH;
- break;
- case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH:
- reason = "The fingerprint doesn't match the expected value.";
- tp_reason = TP_CONNECTION_STATUS_REASON_CERT_FINGERPRINT_MISMATCH;
- break;
- case LM_SSL_STATUS_GENERIC_ERROR:
- reason = "An unknown SSL error occurred.";
- tp_reason = TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR;
- break;
- default:
- g_assert_not_reached ();
- reason = "Unknown SSL error code from Loudmouth.";
- tp_reason = TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR;
- break;
- }
-
- DEBUG ("called: %s", reason);
-
- if (priv->ignore_ssl_errors)
- {
- return LM_SSL_RESPONSE_CONTINUE;
- }
- else
- {
- priv->ssl_error = tp_reason;
- return LM_SSL_RESPONSE_STOP;
- }
-}
-
-static void
-do_auth (GabbleConnection *conn)
-{
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- GError *error = NULL;
-
- DEBUG ("authenticating with username: %s, password: <hidden>, resource: %s",
- priv->username, priv->resource);
-
- if (!lm_connection_authenticate (conn->lmconn, priv->username,
- priv->password, priv->resource, connection_auth_cb, conn, NULL,
- &error))
- {
- DEBUG ("failed: %s", error->message);
- g_error_free (error);
-
- /* the reason this function can fail is through network errors,
- * authentication failures are reported to our auth_cb */
- tp_base_connection_change_status ((TpBaseConnection *)conn,
- TP_CONNECTION_STATUS_DISCONNECTED,
- TP_CONNECTION_STATUS_REASON_NETWORK_ERROR);
- }
-}
-
-static void
-registration_finished_cb (GabbleRegister *reg,
- gboolean success,
- gint err_code,
- const gchar *err_msg,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- TpBaseConnection *base = (TpBaseConnection *)conn;
-
- if (base->status != TP_CONNECTION_STATUS_CONNECTING)
- {
- g_assert (base->status == TP_CONNECTION_STATUS_DISCONNECTED);
- return;
- }
-
- DEBUG ("%s", (success) ? "succeeded" : "failed");
-
- g_object_unref (reg);
-
- if (success)
- {
- do_auth (conn);
- }
- else
- {
- DEBUG ("err_code = %d, err_msg = '%s'",
- err_code, err_msg);
-
- tp_base_connection_change_status ((TpBaseConnection *)conn,
- TP_CONNECTION_STATUS_DISCONNECTED,
- (err_code == TP_ERROR_INVALID_ARGUMENT) ?
- TP_CONNECTION_STATUS_REASON_NAME_IN_USE :
- TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED);
- }
-}
-
-static void
-do_register (GabbleConnection *conn)
-{
- GabbleRegister *reg;
-
- reg = gabble_register_new (conn);
-
- g_signal_connect (reg, "finished", (GCallback) registration_finished_cb,
- conn);
-
- gabble_register_start (reg);
-}
-
-/**
- * connection_open_cb
- *
- * Stage 2 of connecting, this function is called by loudmouth after the
- * result of the non-blocking lm_connection_open call is known. It makes
- * a request to authenticate the user with the server, or optionally
- * registers user on the server first.
- */
-static void
-connection_open_cb (LmConnection *lmconn,
- gboolean success,
- gpointer data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (data);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- TpBaseConnection *base = (TpBaseConnection *)conn;
-
- if ((base->status != TP_CONNECTION_STATUS_CONNECTING) &&
- (base->status != TP_INTERNAL_CONNECTION_STATUS_NEW))
- {
- g_assert (base->status == TP_CONNECTION_STATUS_DISCONNECTED);
- return;
- }
-
- g_assert (priv);
- g_assert (lmconn == conn->lmconn);
-
- if (!success)
- {
- if (lm_connection_get_proxy (lmconn))
- {
- DEBUG ("failed, retrying without proxy");
-
- lm_connection_set_proxy (lmconn, NULL);
-
- if (do_connect (conn, NULL))
- {
- return;
- }
- }
- else
- {
- DEBUG ("failed");
- }
-
- if (priv->ssl_error)
- {
- tp_base_connection_change_status ((TpBaseConnection *)conn,
- TP_CONNECTION_STATUS_DISCONNECTED,
- priv->ssl_error);
- }
- else
- {
- tp_base_connection_change_status ((TpBaseConnection *)conn,
- TP_CONNECTION_STATUS_DISCONNECTED,
- TP_CONNECTION_STATUS_REASON_NETWORK_ERROR);
- }
-
- return;
- }
-
- if (!priv->do_register)
- do_auth (conn);
- else
- do_register (conn);
-}
-
-/**
- * connection_auth_cb
- *
- * Stage 3 of connecting, this function is called by loudmouth after the
- * result of the non-blocking lm_connection_authenticate call is known.
- * It sends a discovery request to find the server's features.
- */
-static void
-connection_auth_cb (LmConnection *lmconn,
- gboolean success,
- gpointer data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (data);
- TpBaseConnection *base = (TpBaseConnection *)conn;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- GError *error = NULL;
-
- if (base->status != TP_CONNECTION_STATUS_CONNECTING)
- {
- g_assert (base->status == TP_CONNECTION_STATUS_DISCONNECTED);
- return;
- }
-
- g_assert (priv);
- g_assert (lmconn == conn->lmconn);
-
- if (!success)
- {
- DEBUG ("failed");
-
- tp_base_connection_change_status ((TpBaseConnection *)conn,
- TP_CONNECTION_STATUS_DISCONNECTED,
- TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED);
-
- return;
- }
-
- if (!gabble_disco_request_with_timeout (conn->disco, GABBLE_DISCO_TYPE_INFO,
- priv->stream_server, NULL, 5000,
- connection_disco_cb, conn,
- G_OBJECT (conn), &error))
- {
- DEBUG ("sending disco request failed: %s",
- error->message);
-
- g_error_free (error);
-
- tp_base_connection_change_status ((TpBaseConnection *)conn,
- TP_CONNECTION_STATUS_DISCONNECTED,
- TP_CONNECTION_STATUS_REASON_NETWORK_ERROR);
- }
-}
-
-/**
- * connection_disco_cb
- *
- * Stage 4 of connecting, this function is called by GabbleDisco after the
- * result of the non-blocking server feature discovery call is known. It sends
- * the user's initial presence to the server, marking them as available,
- * and requests the roster.
- */
-static void
-connection_disco_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *result,
- GError *disco_error,
- gpointer user_data)
-{
- GabbleConnection *conn = user_data;
- TpBaseConnection *base = (TpBaseConnection *)conn;
- GabbleConnectionPrivate *priv;
- GError *error = NULL;
-
- if (base->status != TP_CONNECTION_STATUS_CONNECTING)
- {
- g_assert (base->status == TP_CONNECTION_STATUS_DISCONNECTED);
- return;
- }
-
- g_assert (GABBLE_IS_CONNECTION (conn));
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- if (disco_error)
- {
- DEBUG ("got disco error, setting no features: %s", disco_error->message);
- }
- else
- {
- LmMessageNode *iter;
-
- NODE_DEBUG (result, "got");
-
- for (iter = result->children; iter != NULL; iter = iter->next)
- {
- if (0 == strcmp (iter->name, "identity"))
- {
- const gchar *category = lm_message_node_get_attribute (iter,
- "category");
- const gchar *type = lm_message_node_get_attribute (iter, "type");
-
- if (!tp_strdiff (category, "pubsub") &&
- !tp_strdiff (type, "pep"))
- /* XXX: should we also check for specific PubSub <feature>s? */
- conn->features |= GABBLE_CONNECTION_FEATURES_PEP;
- }
- else if (0 == strcmp (iter->name, "feature"))
- {
- const gchar *var = lm_message_node_get_attribute (iter, "var");
-
- if (var == NULL)
- continue;
-
- if (0 == strcmp (var, NS_GOOGLE_JINGLE_INFO))
- conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO;
- else if (0 == strcmp (var, NS_GOOGLE_ROSTER))
- conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER;
- else if (0 == strcmp (var, NS_PRESENCE_INVISIBLE))
- conn->features |= GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE;
- else if (0 == strcmp (var, NS_PRIVACY))
- conn->features |= GABBLE_CONNECTION_FEATURES_PRIVACY;
- }
- }
-
- DEBUG ("set features flags to %d", conn->features);
- }
-
- /* send presence to the server to indicate availability */
- /* TODO: some way for the user to set this */
- if (!_gabble_connection_signal_own_presence (conn, &error))
- {
- DEBUG ("sending initial presence failed: %s", error->message);
- goto ERROR;
- }
-
- /* go go gadget on-line */
- tp_base_connection_change_status (base,
- TP_CONNECTION_STATUS_CONNECTED, TP_CONNECTION_STATUS_REASON_REQUESTED);
-
- return;
-
-ERROR:
- if (error)
- g_error_free (error);
-
- tp_base_connection_change_status (base,
- TP_CONNECTION_STATUS_DISCONNECTED,
- TP_CONNECTION_STATUS_REASON_NETWORK_ERROR);
-
- return;
-}
-
-
-/****************************************************************************
- * D-BUS EXPORTED METHODS *
- ****************************************************************************/
-
-
-static void
-_emit_capabilities_changed (GabbleConnection *conn,
- TpHandle handle,
- GabblePresenceCapabilities old_caps,
- GabblePresenceCapabilities new_caps)
-{
- GPtrArray *caps_arr;
- const CapabilityConversionData *ccd;
- guint i;
-
- if (old_caps == new_caps)
- return;
-
- caps_arr = g_ptr_array_new ();
-
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- {
- if (ccd->c2tf_fn (old_caps | new_caps))
- {
- GValue caps_monster_struct = {0, };
- guint old_tpflags = ccd->c2tf_fn (old_caps);
- guint old_caps = old_tpflags ?
- TP_CONNECTION_CAPABILITY_FLAG_CREATE |
- TP_CONNECTION_CAPABILITY_FLAG_INVITE : 0;
- guint new_tpflags = ccd->c2tf_fn (new_caps);
- guint new_caps = new_tpflags ?
- TP_CONNECTION_CAPABILITY_FLAG_CREATE |
- TP_CONNECTION_CAPABILITY_FLAG_INVITE : 0;
-
- if (0 == (old_tpflags ^ new_tpflags))
- continue;
-
- g_value_init (&caps_monster_struct,
- TP_CAPABILITIES_CHANGED_MONSTER_TYPE);
- g_value_take_boxed (&caps_monster_struct,
- dbus_g_type_specialized_construct
- (TP_CAPABILITIES_CHANGED_MONSTER_TYPE));
-
- dbus_g_type_struct_set (&caps_monster_struct,
- 0, handle,
- 1, ccd->iface,
- 2, old_caps,
- 3, new_caps,
- 4, old_tpflags,
- 5, new_tpflags,
- G_MAXUINT);
-
- g_ptr_array_add (caps_arr, g_value_get_boxed (&caps_monster_struct));
- }
- }
-
- if (caps_arr->len)
- tp_svc_connection_interface_capabilities_emit_capabilities_changed (
- conn, caps_arr);
-
-
- for (i = 0; i < caps_arr->len; i++)
- {
- g_boxed_free (TP_CAPABILITIES_CHANGED_MONSTER_TYPE,
- g_ptr_array_index (caps_arr, i));
- }
- g_ptr_array_free (caps_arr, TRUE);
-}
-
-static void
-connection_capabilities_update_cb (GabblePresenceCache *cache,
- TpHandle handle,
- GabblePresenceCapabilities old_caps,
- GabblePresenceCapabilities new_caps,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
-
- _emit_capabilities_changed (conn, handle, old_caps, new_caps);
-}
-
-/**
- * gabble_connection_advertise_capabilities
- *
- * Implements D-Bus method AdvertiseCapabilities
- * on interface org.freedesktop.Telepathy.Connection.Interface.Capabilities
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *iface,
- const GPtrArray *add,
- const gchar **remove,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- guint i;
- GabblePresence *pres = self->self_presence;
- GabblePresenceCapabilities add_caps = 0, remove_caps = 0, caps, save_caps;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
- const CapabilityConversionData *ccd;
- GPtrArray *ret;
- GError *error = NULL;
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- DEBUG ("caps before: %x", pres->caps);
-
- for (i = 0; i < add->len; i++)
- {
- GValue iface_flags_pair = {0, };
- gchar *iface;
- guint flags;
-
- g_value_init (&iface_flags_pair, TP_CAPABILITY_PAIR_TYPE);
- g_value_set_static_boxed (&iface_flags_pair, g_ptr_array_index (add, i));
-
- dbus_g_type_struct_get (&iface_flags_pair,
- 0, &iface,
- 1, &flags,
- G_MAXUINT);
-
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- if (g_str_equal (iface, ccd->iface))
- add_caps |= ccd->tf2c_fn (flags);
-
- g_free (iface);
- }
-
- for (i = 0; NULL != remove[i]; i++)
- {
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- if (g_str_equal (remove[i], ccd->iface))
- remove_caps |= ccd->tf2c_fn (~0);
- }
-
- save_caps = caps = pres->caps;
-
- caps |= add_caps;
- caps ^= (caps & remove_caps);
-
- DEBUG ("caps to add: %x", add_caps);
- DEBUG ("caps to remove: %x", remove_caps);
- DEBUG ("caps after: %x", caps);
-
- if (caps ^ save_caps)
- {
- DEBUG ("before != after, changing");
- gabble_presence_set_capabilities (pres, priv->resource, caps,
- priv->caps_serial++);
- DEBUG ("set caps: %x", pres->caps);
- }
-
- ret = g_ptr_array_new ();
-
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- {
- if (ccd->c2tf_fn (pres->caps))
- {
- GValue iface_flags_pair = {0, };
-
- g_value_init (&iface_flags_pair, TP_CAPABILITY_PAIR_TYPE);
- g_value_take_boxed (&iface_flags_pair,
- dbus_g_type_specialized_construct (TP_CAPABILITY_PAIR_TYPE));
-
- dbus_g_type_struct_set (&iface_flags_pair,
- 0, ccd->iface,
- 1, ccd->c2tf_fn (pres->caps),
- G_MAXUINT);
-
- g_ptr_array_add (ret, g_value_get_boxed (&iface_flags_pair));
- }
- }
-
- if (caps ^ save_caps)
- {
- if (!_gabble_connection_signal_own_presence (self, &error))
- {
- dbus_g_method_return_error (context, error);
- return;
- }
-
- _emit_capabilities_changed (self, base->self_handle,
- save_caps, caps);
- }
-
- tp_svc_connection_interface_capabilities_return_from_advertise_capabilities (
- context, ret);
- g_ptr_array_free (ret, TRUE);
-}
-
-static const gchar *assumed_caps[] =
-{
- TP_IFACE_CHANNEL_TYPE_TEXT,
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- NULL
-};
-
-
-/**
- * gabble_connection_get_capabilities
- *
- * Implements D-Bus method GetCapabilities
- * on interface org.freedesktop.Telepathy.Connection.Interface.Capabilities
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_connection_get_capabilities (TpSvcConnectionInterfaceCapabilities *iface,
- const GArray *handles,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
- guint i;
- GPtrArray *ret;
- GError *error = NULL;
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- if (!tp_handles_are_valid (contact_handles, handles, TRUE, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-
- ret = g_ptr_array_new ();
-
- for (i = 0; i < handles->len; i++)
- {
- TpHandle handle = g_array_index (handles, guint, i);
- GabblePresence *pres;
- const CapabilityConversionData *ccd;
- guint typeflags;
- const gchar **assumed;
-
- if (0 == handle)
- {
- /* FIXME report the magical channel types available on the
- * connection itself */
- continue;
- }
-
- if (handle == base->self_handle)
- pres = self->self_presence;
- else
- pres = gabble_presence_cache_get (self->presence_cache, handle);
-
- if (NULL != pres)
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- {
- typeflags = ccd->c2tf_fn (pres->caps);
-
- if (typeflags)
- {
- GValue monster = {0, };
-
- g_value_init (&monster, TP_GET_CAPABILITIES_MONSTER_TYPE);
- g_value_take_boxed (&monster,
- dbus_g_type_specialized_construct (
- TP_GET_CAPABILITIES_MONSTER_TYPE));
-
- dbus_g_type_struct_set (&monster,
- 0, handle,
- 1, ccd->iface,
- 2, TP_CONNECTION_CAPABILITY_FLAG_CREATE |
- TP_CONNECTION_CAPABILITY_FLAG_INVITE,
- 3, typeflags,
- G_MAXUINT);
-
- g_ptr_array_add (ret, g_value_get_boxed (&monster));
- }
- }
-
- for (assumed = assumed_caps; NULL != *assumed; assumed++)
- {
- GValue monster = {0, };
-
- g_value_init (&monster, TP_GET_CAPABILITIES_MONSTER_TYPE);
- g_value_take_boxed (&monster,
- dbus_g_type_specialized_construct (TP_GET_CAPABILITIES_MONSTER_TYPE));
-
- dbus_g_type_struct_set (&monster,
- 0, handle,
- 1, *assumed,
- 2, TP_CONNECTION_CAPABILITY_FLAG_CREATE |
- TP_CONNECTION_CAPABILITY_FLAG_INVITE,
- 3, 0,
- G_MAXUINT);
-
- g_ptr_array_add (ret, g_value_get_boxed (&monster));
- }
- }
-
- tp_svc_connection_interface_capabilities_return_from_get_capabilities (
- context, ret);
- g_ptr_array_free (ret, TRUE);
-}
-
-
-const char *
-_gabble_connection_find_conference_server (GabbleConnection *conn)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- if (priv->conference_server == NULL)
- {
- /* Find first server that has NS_MUC feature */
- const GabbleDiscoItem *item = gabble_disco_service_find (conn->disco,
- NULL, NULL, NS_MUC);
- if (item != NULL)
- priv->conference_server = item->jid;
- }
-
- if (priv->conference_server == NULL)
- priv->conference_server = priv->fallback_conference_server;
-
- return priv->conference_server;
-}
-
-
-static gchar *
-_gabble_connection_get_canonical_room_name (GabbleConnection *conn,
- const gchar *name)
-{
- const gchar *server;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- if (index (name, '@'))
- return g_strdup (name);
-
- server = _gabble_connection_find_conference_server (conn);
-
- if (server == NULL)
- return NULL;
-
- return g_strdup_printf ("%s@%s", name, server);
-}
-
-
-typedef struct _RoomVerifyContext RoomVerifyContext;
-
-typedef struct {
- GabbleConnection *conn;
- DBusGMethodInvocation *invocation;
- gboolean errored;
- guint count;
- GArray *handles;
- RoomVerifyContext *contexts;
-} RoomVerifyBatch;
-
-struct _RoomVerifyContext {
- gchar *jid;
- guint index;
- RoomVerifyBatch *batch;
- GabbleDiscoRequest *request;
-};
-
-static void
-room_verify_batch_free (RoomVerifyBatch *batch)
-{
- TpBaseConnection *base = (TpBaseConnection *)(batch->conn);
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_ROOM);
- guint i;
-
- tp_handles_unref (room_handles, batch->handles);
- g_array_free (batch->handles, TRUE);
- for (i = 0; i < batch->count; i++)
- {
- g_free (batch->contexts[i].jid);
- }
- g_free (batch->contexts);
- g_slice_free (RoomVerifyBatch, batch);
-}
-
-/* Frees the error and the batch. */
-static void
-room_verify_batch_raise_error (RoomVerifyBatch *batch,
- GError *error)
-{
- guint i;
-
- dbus_g_method_return_error (batch->invocation, error);
- g_error_free (error);
- batch->errored = TRUE;
- for (i = 0; i < batch->count; i++)
- {
- if (batch->contexts[i].request)
- {
- gabble_disco_cancel_request (batch->conn->disco,
- batch->contexts[i].request);
- }
- }
- room_verify_batch_free (batch);
-}
-
-static RoomVerifyBatch *
-room_verify_batch_new (GabbleConnection *conn,
- DBusGMethodInvocation *invocation,
- guint count,
- const gchar **jids)
-{
- TpBaseConnection *base = (TpBaseConnection *)conn;
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_ROOM);
- RoomVerifyBatch *batch = g_slice_new (RoomVerifyBatch);
- guint i;
-
- batch->errored = FALSE;
- batch->conn = conn;
- batch->invocation = invocation;
- batch->count = count;
- batch->handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), count);
- batch->contexts = g_new0(RoomVerifyContext, count);
- for (i = 0; i < count; i++)
- {
- const gchar *name = jids[i];
- gchar *qualified_name;
- TpHandle handle;
-
- batch->contexts[i].index = i;
- batch->contexts[i].batch = batch;
-
- qualified_name = _gabble_connection_get_canonical_room_name (conn, name);
-
- if (!qualified_name)
- {
- GError *error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "requested room handle %s does not specify a server, but we "
- "have not discovered any local conference servers and no "
- "fallback was provided", name);
- DEBUG ("%s", error->message);
- room_verify_batch_raise_error (batch, error);
- return NULL;
- }
-
- batch->contexts[i].jid = qualified_name;
-
- /* has the handle been verified before? */
- handle = tp_handle_lookup (room_handles, qualified_name, NULL, NULL);
- if (handle)
- tp_handle_ref (room_handles, handle);
- g_array_append_val (batch->handles, handle);
- }
-
- return batch;
-}
-
-/* If all handles in the array have been disco'd or got from cache,
-free the batch and return TRUE. Else return FALSE. */
-static gboolean
-room_verify_batch_try_return (RoomVerifyBatch *batch)
-{
- guint i;
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (
- (TpBaseConnection *)batch->conn, TP_HANDLE_TYPE_ROOM);
- gchar *sender;
- GError *error = NULL;
-
- for (i = 0; i < batch->count; i++)
- {
- if (!g_array_index (batch->handles, TpHandle, i))
- {
- /* we're not ready yet */
- return FALSE;
- }
- }
-
- sender = dbus_g_method_get_sender (batch->invocation);
- if (!tp_handles_client_hold (room_handles, sender, batch->handles, &error))
- {
- g_assert (error != NULL);
- }
- g_free (sender);
-
- if (error == NULL)
- {
- tp_svc_connection_return_from_request_handles (batch->invocation,
- batch->handles);
- }
- else
- {
- dbus_g_method_return_error (batch->invocation, error);
- g_error_free (error);
- }
-
- room_verify_batch_free (batch);
- return TRUE;
-}
-
-static void
-room_jid_disco_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *query_result,
- GError *error,
- gpointer user_data)
-{
- RoomVerifyContext *rvctx = user_data;
- RoomVerifyBatch *batch = rvctx->batch;
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (
- (TpBaseConnection *)batch->conn, TP_HANDLE_TYPE_ROOM);
- LmMessageNode *lm_node;
- gboolean found = FALSE;
- TpHandle handle;
-
- /* stop the request getting cancelled after it's already finished */
- rvctx->request = NULL;
-
- /* if an error is being handled already, quietly go away */
- if (batch->errored)
- {
- return;
- }
-
- if (error != NULL)
- {
- DEBUG ("disco reply error %s", error->message);
-
- /* disco will free the old error, _raise_error will free the new one */
- error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "can't retrieve room info: %s", error->message);
-
- room_verify_batch_raise_error (batch, error);
-
- return;
- }
-
- for (lm_node = query_result->children; lm_node; lm_node = lm_node->next)
- {
- const gchar *var;
-
- if (tp_strdiff (lm_node->name, "feature"))
- continue;
-
- var = lm_message_node_get_attribute (lm_node, "var");
-
- /* for servers who consider schema compliance to be an optional bonus */
- if (var == NULL)
- var = lm_message_node_get_attribute (lm_node, "type");
-
- if (!tp_strdiff (var, NS_MUC))
- {
- found = TRUE;
- break;
- }
- }
-
- if (!found)
- {
- DEBUG ("no MUC support for service name in jid %s", rvctx->jid);
-
- error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "specified server doesn't support MUC");
-
- room_verify_batch_raise_error (batch, error);
-
- return;
- }
-
- /* this refs the handle, so we're putting a ref in batch->handles */
- handle = tp_handle_ensure (room_handles, rvctx->jid, NULL, &error);
- if (handle == 0)
- {
- room_verify_batch_raise_error (batch, error);
- }
-
- DEBUG ("disco reported MUC support for service name in jid %s", rvctx->jid);
- g_array_index (batch->handles, TpHandle, rvctx->index) = handle;
-
- /* if this was the last callback to be run, send off the result */
- room_verify_batch_try_return (batch);
-}
-
-/**
- * room_jid_verify:
- *
- * Utility function that verifies that the service name of
- * the specified jid exists and reports MUC support.
- */
-static gboolean
-room_jid_verify (RoomVerifyBatch *batch,
- guint index,
- DBusGMethodInvocation *context)
-{
- gchar *room, *service;
- gboolean ret;
- GError *error = NULL;
-
- room = service = NULL;
- gabble_decode_jid (batch->contexts[index].jid, &room, &service, NULL);
-
- if (room == NULL || *room == '\0' || service == NULL || *service == '\0')
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "unable to get room name and service from JID %s",
- batch->contexts[index].jid);
-
- ret = FALSE;
-
- goto out;
- }
-
- ret = (gabble_disco_request (batch->conn->disco, GABBLE_DISCO_TYPE_INFO,
- service, NULL, room_jid_disco_cb,
- batch->contexts + index,
- G_OBJECT (batch->conn), &error) != NULL);
-
-out:
- if (!ret)
- {
- room_verify_batch_raise_error (batch, error);
- }
-
- g_free (room);
- g_free (service);
-
- return ret;
-}
-
-
-/**
- * gabble_connection_request_handles
- *
- * Implements D-Bus method RequestHandles
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-static void
-gabble_connection_request_handles (TpSvcConnection *iface,
- guint handle_type,
- const gchar **names,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *self = GABBLE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *)self;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
- if (handle_type == TP_HANDLE_TYPE_ROOM)
- {
- RoomVerifyBatch *batch = NULL;
- guint count = 0, i;
- const gchar **cur_name;
-
- for (cur_name = names; *cur_name != NULL; cur_name++)
- {
- count++;
- }
-
- batch = room_verify_batch_new (self, context, count, names);
- if (!batch)
- {
- /* an error occurred while setting up the batch, and we returned
- error to dbus */
- return;
- }
-
- /* have all the handles been verified already? If so, nothing to do */
- if (room_verify_batch_try_return (batch))
- {
- return;
- }
-
- for (i = 0; i < count; i++)
- {
- if (!room_jid_verify (batch, i, context))
- {
- return;
- }
- }
-
- /* we've set the verification process going - the callback will handle
- returning or raising error */
- return;
- }
-
- /* else it's either an invalid type, or a type we can verify immediately -
- * in either case, let the superclass do it */
- tp_base_connection_dbus_request_handles (iface, handle_type, names, context);
-}
-
-
-/* We reimplement RequestHandles to be able to do async validation on
- * room handles */
-static void
-conn_service_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcConnectionClass *klass = (TpSvcConnectionClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_connection_implement_##x (klass, \
- gabble_connection_##x)
- IMPLEMENT(request_handles);
-#undef IMPLEMENT
-}
-
-static void
-capabilities_service_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcConnectionInterfaceCapabilitiesClass *klass =
- (TpSvcConnectionInterfaceCapabilitiesClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_connection_interface_capabilities_implement_##x (\
- klass, gabble_connection_##x)
- IMPLEMENT(advertise_capabilities);
- IMPLEMENT(get_capabilities);
-#undef IMPLEMENT
-}
-
diff --git a/src/gabble-connection.h b/src/gabble-connection.h
deleted file mode 100644
index d844c13fb..000000000
--- a/src/gabble-connection.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * gabble-connection.h - Header for GabbleConnection
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_CONNECTION_H__
-#define __GABBLE_CONNECTION_H__
-
-#include <dbus/dbus-glib.h>
-#include <glib-object.h>
-#include <loudmouth/loudmouth.h>
-
-#include "gabble-types.h"
-#include "gabble-error.h"
-#include <telepathy-glib/base-connection.h>
-
-G_BEGIN_DECLS
-
-/* Default parameters for optional parameters */
-#define GABBLE_PARAMS_DEFAULT_RESOURCE "Telepathy"
-#define GABBLE_PARAMS_DEFAULT_PORT 5222
-#define GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_PORT 443
-#define GABBLE_PARAMS_DEFAULT_STUN_PORT 3478
-
-/* order must match array of statuses in conn-presence.c */
-/* in increasing order of presence */
-typedef enum
-{
- GABBLE_PRESENCE_OFFLINE = 0,
- GABBLE_PRESENCE_HIDDEN,
- GABBLE_PRESENCE_XA,
- GABBLE_PRESENCE_AWAY,
- GABBLE_PRESENCE_DND,
- GABBLE_PRESENCE_AVAILABLE,
- GABBLE_PRESENCE_CHAT,
- NUM_GABBLE_PRESENCES
-} GabblePresenceId;
-
-typedef enum
-{
- GABBLE_CONNECTION_FEATURES_NONE = 0,
- GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO = 1 << 0,
- GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER = 1 << 1,
- GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE = 1 << 2,
- GABBLE_CONNECTION_FEATURES_PRIVACY = 1 << 3,
- GABBLE_CONNECTION_FEATURES_PEP = 1 << 4,
-} GabbleConnectionFeatures;
-
-typedef struct _GabbleConnectionClass GabbleConnectionClass;
-
-typedef LmHandlerResult (*GabbleConnectionMsgReplyFunc) (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data);
-
-/* must be in the same order as the list_handle_strings in
- * gabble-connection.c */
-typedef enum
-{
- GABBLE_LIST_HANDLE_PUBLISH = 1,
- GABBLE_LIST_HANDLE_SUBSCRIBE,
- GABBLE_LIST_HANDLE_KNOWN,
- GABBLE_LIST_HANDLE_DENY
-} GabbleListHandle;
-
-typedef enum {
- /* The JID could be a "global" JID, or a MUC room member. We'll assume
- * that it's a global JID (and remove the resource) unless we've seen
- * that JID in a MUC before.
- */
- GABBLE_JID_ANY = 0,
- /* The JID is definitely global. Remove the resource. */
- GABBLE_JID_GLOBAL,
- /* The JID is definitely a room member. Assert that there is a "resource"
- * (nickname) and don't remove it. */
- GABBLE_JID_ROOM_MEMBER
-} GabbleNormalizeContactJIDMode;
-
-struct _GabbleConnectionClass {
- TpBaseConnectionClass parent_class;
-};
-
-struct _GabbleConnection {
- TpBaseConnection parent;
-
- /* loudmouth connection */
- LmConnection *lmconn;
-
- /* roster */
- GabbleRoster *roster;
-
- /* DISCO! */
- GabbleDisco *disco;
-
- /* connection feature flags */
- GabbleConnectionFeatures features;
-
- /* presence */
- GabblePresenceCache *presence_cache;
- GabblePresence *self_presence;
-
- /* vCard lookup helper */
- GabbleVCardManager *vcard_manager;
-
- gpointer priv;
-};
-
-typedef enum {
- GABBLE_CONNECTION_ALIAS_NONE = 0,
- GABBLE_CONNECTION_ALIAS_FROM_JID,
- GABBLE_CONNECTION_ALIAS_FROM_VCARD,
- GABBLE_CONNECTION_ALIAS_FROM_CONNMGR,
- GABBLE_CONNECTION_ALIAS_FROM_PRESENCE,
- GABBLE_CONNECTION_ALIAS_FROM_ROSTER
-} GabbleConnectionAliasSource;
-
-GType gabble_connection_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_CONNECTION \
- (gabble_connection_get_type ())
-#define GABBLE_CONNECTION(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_CONNECTION, GabbleConnection))
-#define GABBLE_CONNECTION_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_CONNECTION, \
- GabbleConnectionClass))
-#define GABBLE_IS_CONNECTION(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CONNECTION))
-#define GABBLE_IS_CONNECTION_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CONNECTION))
-#define GABBLE_CONNECTION_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CONNECTION, \
- GabbleConnectionClass))
-
-gboolean _gabble_connection_set_properties_from_account (
- GabbleConnection *conn, const gchar *account, GError **error);
-gboolean _gabble_connection_send (GabbleConnection *conn, LmMessage *msg,
- GError **error);
-gboolean _gabble_connection_send_with_reply (GabbleConnection *conn,
- LmMessage *msg, GabbleConnectionMsgReplyFunc reply_func, GObject *object,
- gpointer user_data, GError **error);
-void _gabble_connection_acknowledge_set_iq (GabbleConnection *conn,
- LmMessage *iq);
-void _gabble_connection_send_iq_error (GabbleConnection *conn,
- LmMessage *message, GabbleXmppError error, const gchar *errmsg);
-
-GabbleConnectionAliasSource _gabble_connection_get_cached_alias (
- GabbleConnection *, TpHandle, gchar **);
-
-const char *_gabble_connection_find_conference_server (GabbleConnection *);
-gboolean _gabble_connection_signal_own_presence (GabbleConnection *,
- GError **);
-
-/* extern only for the benefit of the unit tests */
-void _gabble_connection_create_handle_repos (TpBaseConnection *conn,
- TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES]);
-
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_CONNECTION_H__*/
diff --git a/src/gabble-error.c b/src/gabble-error.c
deleted file mode 100644
index e49412dd8..000000000
--- a/src/gabble-error.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * gabble-error.c - Source for Gabble's error handling API
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#include "gabble-error.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "namespaces.h"
-
-#define MAX_LEGACY_ERRORS 3
-
-typedef struct {
- const gchar *name;
- const gchar *description;
- const gchar *type;
- guint specialises;
- const gchar *namespace;
- const guint16 legacy_errors[MAX_LEGACY_ERRORS];
-} XmppErrorSpec;
-
-static const XmppErrorSpec xmpp_errors[NUM_XMPP_ERRORS] =
-{
- {
- "redirect",
- "the recipient or server is redirecting requests for this information "
- "to another entity",
- "modify",
- 0,
- NULL,
- { 302, 0, },
- },
-
- {
- "gone",
- "the recipient or server can no longer be contacted at this address",
- "modify",
- 0,
- NULL,
- { 302, 0, },
- },
-
- {
- "bad-request",
- "the sender has sent XML that is malformed or that cannot be processed",
- "modify",
- 0,
- NULL,
- { 400, 0, },
- },
- {
- "unexpected-request",
- "the recipient or server understood the request but was not expecting "
- "it at this time",
- "wait",
- 0,
- NULL,
- { 400, 0, },
- },
- {
- "jid-malformed",
- "the sending entity has provided or communicated an XMPP address or "
- "aspect thereof (e.g., a resource identifier) that does not adhere "
- "to the syntax defined in Addressing Scheme (Section 3)",
- "modify",
- 0,
- NULL,
- { 400, 0, },
- },
-
- {
- "not-authorized",
- "the sender must provide proper credentials before being allowed to "
- "perform the action, or has provided improper credentials",
- "auth",
- 0,
- NULL,
- { 401, 0, },
- },
-
- {
- "payment-required",
- "the requesting entity is not authorized to access the requested "
- "service because payment is required",
- "auth",
- 0,
- NULL,
- { 402, 0, },
- },
-
- {
- "forbidden",
- "the requesting entity does not possess the required permissions to "
- "perform the action",
- "auth",
- 0,
- NULL,
- { 403, 0, },
- },
-
- {
- "item-not-found",
- "the addressed JID or item requested cannot be found",
- "cancel",
- 0,
- NULL,
- { 404, 0, },
- },
- {
- "recipient-unavailable",
- "the intended recipient is temporarily unavailable",
- "wait",
- 0,
- NULL,
- { 404, 0, },
- },
- {
- "remote-server-not-found",
- "a remote server or service specified as part or all of the JID of the "
- "intended recipient (or required to fulfill a request) could not be "
- "contacted within a reasonable amount of time",
- "cancel",
- 0,
- NULL,
- { 404, 0, },
- },
-
- {
- "not-allowed",
- "the recipient or server does not allow any entity to perform the action",
- "cancel",
- 0,
- NULL,
- { 405, 0, },
- },
-
- {
- "not-acceptable",
- "the recipient or server understands the request but is refusing to "
- "process it because it does not meet criteria defined by the recipient "
- "or server (e.g., a local policy regarding acceptable words in messages)",
- "modify",
- 0,
- NULL,
- { 406, 0, },
- },
-
- {
- "registration-required",
- "the requesting entity is not authorized to access the requested service "
- "because registration is required",
- "auth",
- 0,
- NULL,
- { 407, 0, },
- },
- {
- "subscription-required",
- "the requesting entity is not authorized to access the requested service "
- "because a subscription is required",
- "auth",
- 0,
- NULL,
- { 407, 0, },
- },
-
- {
- "remote-server-timeout",
- "a remote server or service specified as part or all of the JID of the "
- "intended recipient (or required to fulfill a request) could not be "
- "contacted within a reasonable amount of time",
- "wait",
- 0,
- NULL,
- { 408, 504, 0, },
- },
-
- {
- "conflict",
- "access cannot be granted because an existing resource or session exists "
- "with the same name or address",
- "cancel",
- 0,
- NULL,
- { 409, 0, },
- },
-
- {
- "internal-server-error",
- "the server could not process the stanza because of a misconfiguration "
- "or an otherwise-undefined internal server error",
- "wait",
- 0,
- NULL,
- { 500, 0, },
- },
- {
- "undefined-condition",
- "application-specific condition",
- NULL,
- 0,
- NULL,
- { 500, 0, },
- },
- {
- "resource-constraint",
- "the server or recipient lacks the system resources necessary to service "
- "the request",
- "wait",
- 0,
- NULL,
- { 500, 0, },
- },
-
- {
- "feature-not-implemented",
- "the feature requested is not implemented by the recipient or server and "
- "therefore cannot be processed",
- "cancel",
- 0,
- NULL,
- { 501, 0, },
- },
-
- {
- "service-unavailable",
- "the server or recipient does not currently provide the requested "
- "service",
- "cancel",
- 0,
- NULL,
- { 502, 503, 510, },
- },
-
- {
- "out-of-order",
- "the request cannot occur at this point in the state machine",
- "cancel",
- XMPP_ERROR_UNEXPECTED_REQUEST,
- NS_JINGLE_ERRORS,
- { 0, },
- },
-
- {
- "unknown-session",
- "the 'sid' attribute specifies a session that is unknown to the "
- "recipient",
- "cancel",
- XMPP_ERROR_BAD_REQUEST,
- NS_JINGLE_ERRORS,
- { 0, },
- },
-
- {
- "unsupported-transports",
- "the recipient does not support any of the desired content transport "
- "methods",
- "cancel",
- XMPP_ERROR_FEATURE_NOT_IMPLEMENTED,
- NS_JINGLE_ERRORS,
- { 0, },
- },
-
- {
- "unsupported-content",
- "the recipient does not support any of the desired content description"
- "formats",
- "cancel",
- XMPP_ERROR_FEATURE_NOT_IMPLEMENTED,
- NS_JINGLE_ERRORS,
- { 0, },
- },
-};
-
-GQuark
-gabble_xmpp_error_quark (void)
-{
- static GQuark quark = 0;
- if (!quark)
- quark = g_quark_from_static_string ("gabble-xmpp-error");
- return quark;
-}
-
-GabbleXmppError
-gabble_xmpp_error_from_node (LmMessageNode *error_node)
-{
- gint i, j;
- const gchar *error_code_str;
-
- /* First, try to look it up the modern way */
- if (error_node->children)
- {
- for (i = 0; i < NUM_XMPP_ERRORS; i++)
- {
- if (lm_message_node_get_child (error_node, xmpp_errors[i].name))
- {
- return i;
- }
- }
- }
-
- /* Ok, do it the legacy way */
- error_code_str = lm_message_node_get_attribute (error_node, "code");
- if (error_code_str)
- {
- gint error_code;
-
- error_code = atoi (error_code_str);
-
- for (i = 0; i < NUM_XMPP_ERRORS; i++)
- {
- const XmppErrorSpec *spec = &xmpp_errors[i];
-
- for (j = 0; j < MAX_LEGACY_ERRORS; j++)
- {
- gint cur_code = spec->legacy_errors[j];
- if (cur_code == 0)
- break;
-
- if (cur_code == error_code)
- return i;
- }
- }
- }
-
- return INVALID_XMPP_ERROR;
-}
-
-GError *
-gabble_xmpp_error_to_g_error (GabbleXmppError error)
-{
- if (error >= NUM_XMPP_ERRORS)
- return NULL;
-
- return g_error_new (GABBLE_XMPP_ERROR,
- error,
- xmpp_errors[error].description);
-}
-
-/*
- * See RFC 3920: 4.7 Stream Errors, 9.3 Stanza Errors.
- */
-LmMessageNode *
-gabble_xmpp_error_to_node (GabbleXmppError error,
- LmMessageNode *parent_node,
- const gchar *errmsg)
-{
- const XmppErrorSpec *spec, *extra;
- LmMessageNode *error_node, *node;
- gchar str[6];
-
- if (error >= NUM_XMPP_ERRORS)
- return NULL;
-
- if (xmpp_errors[error].specialises)
- {
- extra = &xmpp_errors[error];
- spec = &xmpp_errors[extra->specialises];
- }
- else
- {
- extra = NULL;
- spec = &xmpp_errors[error];
- }
-
- error_node = lm_message_node_add_child (parent_node, "error", NULL);
-
- sprintf (str, "%d", spec->legacy_errors[0]);
- lm_message_node_set_attribute (error_node, "code", str);
-
- if (spec->type)
- {
- lm_message_node_set_attribute (error_node, "type", spec->type);
- }
-
- node = lm_message_node_add_child (error_node, spec->name, NULL);
- lm_message_node_set_attribute (node, "xmlns", NS_XMPP_STANZAS);
-
- if (extra != NULL)
- {
- node = lm_message_node_add_child (error_node, extra->name, NULL);
- lm_message_node_set_attribute (node, "xmlns", extra->namespace);
- }
-
- if (NULL != errmsg)
- lm_message_node_add_child (error_node, "text", errmsg);
-
- return error_node;
-}
-
-const gchar *
-gabble_xmpp_error_string (GabbleXmppError error)
-{
- if (error < NUM_XMPP_ERRORS)
- return xmpp_errors[error].name;
- else
- return NULL;
-}
-
-const gchar *
-gabble_xmpp_error_description (GabbleXmppError error)
-{
- if (error < NUM_XMPP_ERRORS)
- return xmpp_errors[error].description;
- else
- return NULL;
-}
-
diff --git a/src/gabble-error.h b/src/gabble-error.h
deleted file mode 100644
index 970961a2c..000000000
--- a/src/gabble-error.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * gabble-error.h - Header for Gabble's error handling API
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#ifndef __GABBLE_ERROR_H__
-#define __GABBLE_ERROR_H__
-
-#include <glib.h>
-#include <loudmouth/loudmouth.h>
-
-typedef enum {
- XMPP_ERROR_REDIRECT = 0, /* 302 */
- XMPP_ERROR_GONE, /* 302 */
-
- XMPP_ERROR_BAD_REQUEST, /* 400 */
- XMPP_ERROR_UNEXPECTED_REQUEST, /* 400 */
- XMPP_ERROR_JID_MALFORMED, /* 400 */
-
- XMPP_ERROR_NOT_AUTHORIZED, /* 401 */
-
- XMPP_ERROR_PAYMENT_REQUIRED, /* 402 */
-
- XMPP_ERROR_FORBIDDEN, /* 403 */
-
- XMPP_ERROR_ITEM_NOT_FOUND, /* 404 */
- XMPP_ERROR_RECIPIENT_UNAVAILABLE, /* 404 */
- XMPP_ERROR_REMOTE_SERVER_NOT_FOUND, /* 404 */
-
- XMPP_ERROR_NOT_ALLOWED, /* 405 */
-
- XMPP_ERROR_NOT_ACCEPTABLE, /* 406 */
-
- XMPP_ERROR_REGISTRATION_REQUIRED, /* 407 */
- XMPP_ERROR_SUBSCRIPTION_REQUIRED, /* 407 */
-
- XMPP_ERROR_REMOTE_SERVER_TIMEOUT, /* 408, 504 */
-
- XMPP_ERROR_CONFLICT, /* 409 */
-
- XMPP_ERROR_INTERNAL_SERVER_ERROR, /* 500 */
- XMPP_ERROR_UNDEFINED_CONDITION, /* 500 */
- XMPP_ERROR_RESOURCE_CONSTRAINT, /* 500 */
-
- XMPP_ERROR_FEATURE_NOT_IMPLEMENTED, /* 501 */
-
- XMPP_ERROR_SERVICE_UNAVAILABLE, /* 502, 503, 510 */
-
- XMPP_ERROR_JINGLE_OUT_OF_ORDER,
- XMPP_ERROR_JINGLE_UNKOWN_SESSION,
- XMPP_ERROR_JINGLE_UNSUPPORTED_CONTENT,
- XMPP_ERROR_JINGLE_UNSUPPORTED_TRANSPORT,
-
- NUM_XMPP_ERRORS,
-
- INVALID_XMPP_ERROR,
-} GabbleXmppError;
-
-GQuark gabble_xmpp_error_quark (void);
-#define GABBLE_XMPP_ERROR gabble_xmpp_error_quark ()
-
-GabbleXmppError gabble_xmpp_error_from_node (LmMessageNode *error_node);
-GError *gabble_xmpp_error_to_g_error (GabbleXmppError error);
-LmMessageNode *gabble_xmpp_error_to_node (GabbleXmppError error,
- LmMessageNode *parent_node, const gchar *errmsg);
-const gchar *gabble_xmpp_error_string (GabbleXmppError error);
-const gchar *gabble_xmpp_error_description (GabbleXmppError error);
-
-#endif /* __GABBLE_ERROR_H__ */
diff --git a/src/gabble-im-channel.c b/src/gabble-im-channel.c
deleted file mode 100644
index 961435639..000000000
--- a/src/gabble-im-channel.c
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * gabble-im-channel.c - Source for GabbleIMChannel
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#include "gabble-im-channel.h"
-
-#include <dbus/dbus-glib.h>
-#include <loudmouth/loudmouth.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_IM
-
-#include "debug.h"
-#include "disco.h"
-#include "gabble-connection.h"
-#include "presence.h"
-#include "presence-cache.h"
-#include "roster.h"
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/svc-channel.h>
-
-static void channel_iface_init (gpointer, gpointer);
-static void text_iface_init (gpointer, gpointer);
-static void chat_state_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleIMChannel, gabble_im_channel, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, text_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CHAT_STATE,
- chat_state_iface_init));
-
-
-/* properties */
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_HANDLE_TYPE,
- PROP_HANDLE,
- PROP_CONNECTION,
- LAST_PROPERTY
-};
-
-/* private structure */
-typedef struct _GabbleIMChannelPrivate GabbleIMChannelPrivate;
-
-struct _GabbleIMChannelPrivate
-{
- GabbleConnection *conn;
- char *object_path;
- TpHandle handle;
-
- gchar *peer_jid;
-
- gboolean closed;
- gboolean dispose_has_run;
-};
-
-#define GABBLE_IM_CHANNEL_GET_PRIVATE(obj) \
- ((GabbleIMChannelPrivate *)obj->priv)
-
-static void
-gabble_im_channel_init (GabbleIMChannel *self)
-{
- GabbleIMChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_IM_CHANNEL, GabbleIMChannelPrivate);
-
- self->priv = priv;
-}
-
-static GObject *
-gabble_im_channel_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleIMChannelPrivate *priv;
- TpBaseConnection *conn;
- DBusGConnection *bus;
- gboolean send_nick;
- TpHandleRepoIface *contact_handles;
-
- obj = G_OBJECT_CLASS (gabble_im_channel_parent_class)->
- constructor (type, n_props, props);
- priv = GABBLE_IM_CHANNEL_GET_PRIVATE (GABBLE_IM_CHANNEL (obj));
- conn = (TpBaseConnection *)priv->conn;
- contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- tp_handle_ref (contact_handles, priv->handle);
-
- priv->peer_jid = g_strdup (tp_handle_inspect (contact_handles,
- priv->handle));
-
- bus = tp_get_bus ();
- dbus_g_connection_register_g_object (bus, priv->object_path, obj);
-
- if (gabble_roster_handle_get_subscription (priv->conn->roster, priv->handle)
- & GABBLE_ROSTER_SUBSCRIPTION_FROM)
- send_nick = FALSE;
- else
- send_nick = TRUE;
-
- gabble_text_mixin_init (obj, G_STRUCT_OFFSET (GabbleIMChannel, text),
- contact_handles, send_nick);
-
- tp_text_mixin_set_message_types (obj,
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
- TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION,
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE,
- G_MAXUINT);
-
- return obj;
-}
-
-static void
-gabble_im_channel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleIMChannel *chan = GABBLE_IM_CHANNEL (object);
- GabbleIMChannelPrivate *priv = GABBLE_IM_CHANNEL_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TEXT);
- break;
- case PROP_HANDLE_TYPE:
- g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
- break;
- case PROP_HANDLE:
- g_value_set_uint (value, priv->handle);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_im_channel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleIMChannel *chan = GABBLE_IM_CHANNEL (object);
- GabbleIMChannelPrivate *priv = GABBLE_IM_CHANNEL_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_HANDLE:
- /* we don't ref it here because we don't necessarily have access to the
- * contact repo yet - instead we ref it in the constructor.
- */
- priv->handle = g_value_get_uint (value);
- break;
- case PROP_HANDLE_TYPE:
- /* this property is writable in the interface, but not actually
- * meaningfully changable on this channel, so we do nothing */
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_im_channel_dispose (GObject *object);
-static void gabble_im_channel_finalize (GObject *object);
-
-static void
-gabble_im_channel_class_init (GabbleIMChannelClass *gabble_im_channel_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_im_channel_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_im_channel_class,
- sizeof (GabbleIMChannelPrivate));
-
- object_class->constructor = gabble_im_channel_constructor;
-
- object_class->get_property = gabble_im_channel_get_property;
- object_class->set_property = gabble_im_channel_set_property;
-
- object_class->dispose = gabble_im_channel_dispose;
- object_class->finalize = gabble_im_channel_finalize;
-
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
- g_object_class_override_property (object_class, PROP_HANDLE, "handle");
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "IM channel object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- tp_text_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleIMChannelClass, text_class));
-}
-
-static void
-gabble_im_channel_dispose (GObject *object)
-{
- GabbleIMChannel *self = GABBLE_IM_CHANNEL (object);
- GabbleIMChannelPrivate *priv = GABBLE_IM_CHANNEL_GET_PRIVATE (self);
- GabblePresence *presence;
- GabbleRosterSubscription subscription;
- gboolean cap_chat_states = FALSE;
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- subscription = gabble_roster_handle_get_subscription (priv->conn->roster,
- priv->handle);
-
- presence = gabble_presence_cache_get (priv->conn->presence_cache,
- priv->handle);
-
- if (presence && presence->caps & PRESENCE_CAP_CHAT_STATES)
- {
- cap_chat_states = TRUE;
- }
-
- if ((GABBLE_ROSTER_SUBSCRIPTION_TO & subscription) == 0)
- {
- if (NULL != presence)
- {
- presence->keep_unavailable = FALSE;
- gabble_presence_cache_maybe_remove (priv->conn->presence_cache,
- priv->handle);
- }
- }
-
- if (!priv->closed)
- {
- if (cap_chat_states)
- {
- /* Set the chat state of the channel on gone
- * (Channel.Interface.ChatState) */
- gabble_text_mixin_send (G_OBJECT (self),
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, 0,
- TP_CHANNEL_CHAT_STATE_GONE, priv->peer_jid, NULL, priv->conn,
- FALSE /* emit_signal */, NULL);
- }
-
- tp_svc_channel_emit_closed (self);
- }
-
- if (G_OBJECT_CLASS (gabble_im_channel_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_im_channel_parent_class)->dispose (object);
-}
-
-static void
-gabble_im_channel_finalize (GObject *object)
-{
- GabbleIMChannel *self = GABBLE_IM_CHANNEL (object);
- GabbleIMChannelPrivate *priv = GABBLE_IM_CHANNEL_GET_PRIVATE (self);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- /* free any data held directly by the object here */
-
- DEBUG ("%p", object);
-
- tp_handle_unref (contact_handles, priv->handle);
-
- g_free (priv->object_path);
- g_free (priv->peer_jid);
-
- tp_text_mixin_finalize (object);
-
- G_OBJECT_CLASS (gabble_im_channel_parent_class)->finalize (object);
-}
-
-/**
- * _gabble_im_channel_receive
- *
- */
-void
-_gabble_im_channel_receive (GabbleIMChannel *chan,
- TpChannelTextMessageType type,
- TpHandle sender,
- const char *from,
- time_t timestamp,
- const char *text)
-{
- GabbleIMChannelPrivate *priv;
-
- g_assert (GABBLE_IS_IM_CHANNEL (chan));
- priv = GABBLE_IM_CHANNEL_GET_PRIVATE (chan);
-
- /* update peer's full JID if it's changed */
- if (0 != strcmp (from, priv->peer_jid))
- {
- g_free (priv->peer_jid);
- priv->peer_jid = g_strdup (from);
- }
-
- if (timestamp == 0)
- timestamp = time (NULL);
-
- tp_text_mixin_receive (G_OBJECT (chan), type, sender, timestamp, text);
-}
-
-/**
- * _gabble_im_channel_state_receive
- *
- * Send the D-BUS signal ChatStateChanged
- * on org.freedesktop.Telepathy.Channel.Interface.ChatState
- */
-
-void
-_gabble_im_channel_state_receive (GabbleIMChannel *chan,
- guint state)
-{
- GabbleIMChannelPrivate *priv;
-
- g_assert (state < NUM_TP_CHANNEL_CHAT_STATES);
- g_assert (GABBLE_IS_IM_CHANNEL (chan));
- priv = GABBLE_IM_CHANNEL_GET_PRIVATE (chan);
-
- tp_svc_channel_interface_chat_state_emit_chat_state_changed (
- (TpSvcChannelInterfaceChatState*)chan,
- priv->handle, state);
-}
-
-/**
- * gabble_im_channel_close
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_im_channel_close (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleIMChannel *self = GABBLE_IM_CHANNEL (iface);
- GabbleIMChannelPrivate *priv;
- GabblePresence *presence;
-
- g_assert (GABBLE_IS_IM_CHANNEL (self));
-
- DEBUG ("called on %p", self);
-
- priv = GABBLE_IM_CHANNEL_GET_PRIVATE (self);
-
- presence = gabble_presence_cache_get (priv->conn->presence_cache,
- priv->handle);
-
- if (!priv->closed)
- {
- tp_svc_channel_emit_closed (self);
-
- if (presence && (presence->caps & PRESENCE_CAP_CHAT_STATES))
- {
- /* Set the chat state of the channel on gone
- * (Channel.Interface.ChatState) */
- gabble_text_mixin_send (G_OBJECT (self),
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, 0,
- TP_CHANNEL_CHAT_STATE_GONE, priv->peer_jid, NULL, priv->conn,
- FALSE /* emit_signal */, NULL);
- }
-
- priv->closed = TRUE;
- }
-
- tp_svc_channel_return_from_close (context);
-}
-
-
-/**
- * gabble_im_channel_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_im_channel_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_TEXT);
-}
-
-
-/**
- * gabble_im_channel_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_im_channel_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleIMChannel *self = GABBLE_IM_CHANNEL (iface);
- GabbleIMChannelPrivate *priv;
-
- g_assert (GABBLE_IS_IM_CHANNEL (self));
- priv = GABBLE_IM_CHANNEL_GET_PRIVATE (self);
-
- tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT,
- priv->handle);
-}
-
-
-/**
- * gabble_im_channel_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_im_channel_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- const char *interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE,
- NULL };
-
- tp_svc_channel_return_from_get_interfaces (context, interfaces);
-}
-
-
-/**
- * gabble_im_channel_send
- *
- * Implements D-Bus method Send
- * on interface org.freedesktop.Telepathy.Channel.Type.Text
- */
-static void
-gabble_im_channel_send (TpSvcChannelTypeText *iface,
- guint type,
- const gchar *text,
- DBusGMethodInvocation *context)
-{
- GabbleIMChannel *self = GABBLE_IM_CHANNEL (iface);
- GabbleIMChannelPrivate *priv;
- GabblePresence *presence;
- gint state = -1;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_IM_CHANNEL (self));
- priv = GABBLE_IM_CHANNEL_GET_PRIVATE (self);
-
- presence = gabble_presence_cache_get (priv->conn->presence_cache,
- priv->handle);
-
- if (presence && (presence->caps & PRESENCE_CAP_CHAT_STATES))
- {
- state = TP_CHANNEL_CHAT_STATE_ACTIVE;
- }
-
- if (!gabble_text_mixin_send (G_OBJECT (self), type, 0,
- state, priv->peer_jid, text, priv->conn,
- TRUE /* emit_signal */, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- return;
- }
-
- tp_svc_channel_type_text_return_from_send (context);
-}
-
-/**
- * gabble_im_channel_set_chat_state
- *
- * Implements D-Bus method SetChatState
- * on interface org.freedesktop.Telepathy.Channel.Interface.ChatState
- */
-static void
-gabble_im_channel_set_chat_state (TpSvcChannelInterfaceChatState *iface,
- guint state,
- DBusGMethodInvocation *context)
-{
- GabbleIMChannel *self = GABBLE_IM_CHANNEL (iface);
- GabbleIMChannelPrivate *priv;
- GabblePresence *presence;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_IM_CHANNEL (self));
- priv = GABBLE_IM_CHANNEL_GET_PRIVATE (self);
-
- presence = gabble_presence_cache_get (priv->conn->presence_cache,
- priv->handle);
-
- if (presence && (presence->caps & PRESENCE_CAP_CHAT_STATES))
- {
- if (state >= NUM_TP_CHANNEL_CHAT_STATES)
- {
- DEBUG ("invalid state %u", state);
-
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "invalid state: %u", state);
- }
-
- if (state == TP_CHANNEL_CHAT_STATE_GONE)
- {
- /* We cannot explicitly set the Gone state */
- DEBUG ("you may not explicitly set the Gone state");
-
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "you may not explicitly set the Gone state");
- }
-
- if (error != NULL || !gabble_text_mixin_send (G_OBJECT (self),
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, 0, state, priv->peer_jid, NULL,
- priv->conn, FALSE /* emit_signal */, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- return;
- }
-
- /* Send the ChatStateChanged signal for the local user */
- tp_svc_channel_interface_chat_state_emit_chat_state_changed (iface,
- priv->conn->parent.self_handle, state);
- }
-
- tp_svc_channel_interface_chat_state_return_from_set_chat_state (context);
-}
-
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_implement_##x (\
- klass, gabble_im_channel_##x)
- IMPLEMENT(close);
- IMPLEMENT(get_channel_type);
- IMPLEMENT(get_handle);
- IMPLEMENT(get_interfaces);
-#undef IMPLEMENT
-}
-
-static void
-text_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelTypeTextClass *klass = (TpSvcChannelTypeTextClass *)g_iface;
-
- tp_text_mixin_iface_init (g_iface, iface_data);
-#define IMPLEMENT(x) tp_svc_channel_type_text_implement_##x (\
- klass, gabble_im_channel_##x)
- IMPLEMENT(send);
-#undef IMPLEMENT
-}
-
-static void
-chat_state_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelInterfaceChatStateClass *klass =
- (TpSvcChannelInterfaceChatStateClass *)g_iface;
-#define IMPLEMENT(x) tp_svc_channel_interface_chat_state_implement_##x (\
- klass, gabble_im_channel_##x)
- IMPLEMENT(set_chat_state);
-#undef IMPLEMENT
-}
diff --git a/src/gabble-im-channel.h b/src/gabble-im-channel.h
deleted file mode 100644
index 7c5e2244c..000000000
--- a/src/gabble-im-channel.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * gabble-im-channel.h - Header for GabbleIMChannel
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_IM_CHANNEL_H__
-#define __GABBLE_IM_CHANNEL_H__
-
-#include <glib-object.h>
-#include <time.h>
-
-#include <telepathy-glib/enums.h>
-#include "text-mixin.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleIMChannel GabbleIMChannel;
-typedef struct _GabbleIMChannelClass GabbleIMChannelClass;
-
-struct _GabbleIMChannelClass {
- GObjectClass parent_class;
-
- GabbleTextMixinClass text_class;
-};
-
-struct _GabbleIMChannel {
- GObject parent;
-
- GabbleTextMixin text;
-
- gpointer priv;
-};
-
-GType gabble_im_channel_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_IM_CHANNEL \
- (gabble_im_channel_get_type ())
-#define GABBLE_IM_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_IM_CHANNEL, GabbleIMChannel))
-#define GABBLE_IM_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_IM_CHANNEL,\
- GabbleIMChannelClass))
-#define GABBLE_IS_IM_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_IM_CHANNEL))
-#define GABBLE_IS_IM_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_IM_CHANNEL))
-#define GABBLE_IM_CHANNEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_IM_CHANNEL, \
- GabbleIMChannelClass))
-
-void _gabble_im_channel_receive (GabbleIMChannel *chan,
- TpChannelTextMessageType type, TpHandle sender, const char *from,
- time_t timestamp, const char *text);
-void _gabble_im_channel_state_receive (GabbleIMChannel *chan, guint state);
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_IM_CHANNEL_H__*/
diff --git a/src/gabble-media-channel.c b/src/gabble-media-channel.c
deleted file mode 100644
index c852289cd..000000000
--- a/src/gabble-media-channel.c
+++ /dev/null
@@ -1,1466 +0,0 @@
-/*
- * gabble-media-channel.c - Source for GabbleMediaChannel
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#include "gabble-media-channel.h"
-
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "debug.h"
-#include "gabble-connection.h"
-#include "gabble-media-session.h"
-#include "presence.h"
-#include "presence-cache.h"
-
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-properties-interface.h>
-
-#include "gabble-media-session.h"
-#include "gabble-media-stream.h"
-
-#include "media-factory.h"
-
-#define TP_SESSION_HANDLER_SET_TYPE (dbus_g_type_get_struct ("GValueArray", \
- DBUS_TYPE_G_OBJECT_PATH, \
- G_TYPE_STRING, \
- G_TYPE_INVALID))
-
-#define TP_CHANNEL_STREAM_TYPE (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_INVALID))
-
-static void channel_iface_init (gpointer, gpointer);
-static void media_signalling_iface_init (gpointer, gpointer);
-static void streamed_media_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleMediaChannel, gabble_media_channel,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
- tp_group_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MEDIA_SIGNALLING,
- media_signalling_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_STREAMED_MEDIA,
- streamed_media_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_PROPERTIES_INTERFACE,
- tp_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL));
-
-/* properties */
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_HANDLE_TYPE,
- PROP_HANDLE,
- PROP_CONNECTION,
- PROP_CREATOR,
- PROP_FACTORY,
- /* TP properties (see also below) */
- PROP_NAT_TRAVERSAL,
- PROP_STUN_SERVER,
- PROP_STUN_PORT,
- PROP_GTALK_P2P_RELAY_TOKEN,
- LAST_PROPERTY
-};
-
-/* TP properties */
-enum
-{
- CHAN_PROP_NAT_TRAVERSAL = 0,
- CHAN_PROP_STUN_SERVER,
- CHAN_PROP_STUN_PORT,
- CHAN_PROP_GTALK_P2P_RELAY_TOKEN,
- NUM_CHAN_PROPS,
- INVALID_CHAN_PROP
-};
-
-const TpPropertySignature channel_property_signatures[NUM_CHAN_PROPS] = {
- { "nat-traversal", G_TYPE_STRING },
- { "stun-server", G_TYPE_STRING },
- { "stun-port", G_TYPE_UINT },
- { "gtalk-p2p-relay-token", G_TYPE_STRING }
-};
-
-/* private structure */
-typedef struct _GabbleMediaChannelPrivate GabbleMediaChannelPrivate;
-
-struct _GabbleMediaChannelPrivate
-{
- GabbleConnection *conn;
- gchar *object_path;
- TpHandle creator;
-
- GabbleMediaFactory *factory;
- GabbleMediaSession *session;
- GPtrArray *streams;
-
- guint next_stream_id;
-
- gboolean closed;
- gboolean dispose_has_run;
-};
-
-#define GABBLE_MEDIA_CHANNEL_GET_PRIVATE(obj) \
- ((GabbleMediaChannelPrivate *)obj->priv)
-
-static void
-gabble_media_channel_init (GabbleMediaChannel *self)
-{
- GabbleMediaChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_MEDIA_CHANNEL, GabbleMediaChannelPrivate);
-
- self->priv = priv;
-
- priv->next_stream_id = 1;
-
- /* initialize properties mixin */
- tp_properties_mixin_init (G_OBJECT (self), G_STRUCT_OFFSET (
- GabbleMediaChannel, properties));
-}
-
-static GObject *
-gabble_media_channel_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleMediaChannelPrivate *priv;
- TpBaseConnection *conn;
- DBusGConnection *bus;
- TpIntSet *set;
- TpHandleRepoIface *contact_handles;
-
- obj = G_OBJECT_CLASS (gabble_media_channel_parent_class)->
- constructor (type, n_props, props);
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (GABBLE_MEDIA_CHANNEL (obj));
- conn = (TpBaseConnection *)priv->conn;
- contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- /* register object on the bus */
- bus = tp_get_bus ();
- dbus_g_connection_register_g_object (bus, priv->object_path, obj);
-
- tp_group_mixin_init (obj, G_STRUCT_OFFSET (GabbleMediaChannel, group),
- contact_handles, conn->self_handle);
-
- /* automatically add creator to channel */
- set = tp_intset_new ();
- tp_intset_add (set, priv->creator);
-
- tp_group_mixin_change_members (obj, "", set, NULL, NULL, NULL, 0, 0);
-
- tp_intset_destroy (set);
-
- /* allow member adding */
- tp_group_mixin_change_flags (obj, TP_CHANNEL_GROUP_FLAG_CAN_ADD, 0);
-
- return obj;
-}
-
-static void session_state_changed_cb (GabbleMediaSession *session,
- GParamSpec *arg1, GabbleMediaChannel *channel);
-static void session_stream_added_cb (GabbleMediaSession *session,
- GabbleMediaStream *stream, GabbleMediaChannel *chan);
-static void session_terminated_cb (GabbleMediaSession *session,
- guint terminator, guint reason, gpointer user_data);
-
-/**
- * create_session
- *
- * Creates a GabbleMediaSession object for given peer.
- *
- * If sid is set to NULL a unique sid is generated and
- * the "initiator" property of the newly created
- * GabbleMediaSession is set to our own handle.
- */
-static GabbleMediaSession*
-create_session (GabbleMediaChannel *channel,
- TpHandle peer,
- const gchar *peer_resource,
- const gchar *sid)
-{
- GabbleMediaChannelPrivate *priv;
- GabbleMediaSession *session;
- gchar *object_path;
- JingleInitiator initiator;
-
- g_assert (GABBLE_IS_MEDIA_CHANNEL (channel));
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (channel);
-
- g_assert (priv->session == NULL);
-
- object_path = g_strdup_printf ("%s/MediaSession%u", priv->object_path, peer);
-
- if (sid == NULL)
- {
- initiator = INITIATOR_LOCAL;
- sid = _gabble_media_factory_allocate_sid (priv->factory, channel);
- }
- else
- {
- initiator = INITIATOR_REMOTE;
- _gabble_media_factory_register_sid (priv->factory, sid, channel);
- }
-
- session = g_object_new (GABBLE_TYPE_MEDIA_SESSION,
- "connection", priv->conn,
- "media-channel", channel,
- "object-path", object_path,
- "session-id", sid,
- "initiator", initiator,
- "peer", peer,
- "peer-resource", peer_resource,
- NULL);
-
- g_signal_connect (session, "notify::state",
- (GCallback) session_state_changed_cb, channel);
- g_signal_connect (session, "stream-added",
- (GCallback) session_stream_added_cb, channel);
- g_signal_connect (session, "terminated",
- (GCallback) session_terminated_cb, channel);
-
- priv->session = session;
-
- priv->streams = g_ptr_array_sized_new (1);
-
- tp_svc_channel_interface_media_signalling_emit_new_session_handler (
- channel, object_path, "rtp");
-
- g_free (object_path);
-
- return session;
-}
-
-gboolean
-_gabble_media_channel_dispatch_session_action (GabbleMediaChannel *chan,
- TpHandle peer,
- const gchar *peer_resource,
- const gchar *sid,
- LmMessage *message,
- LmMessageNode *session_node,
- const gchar *action,
- GError **error)
-{
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
- GabbleMediaSession *session = priv->session;
- gboolean session_is_new = FALSE;
-
- if (session == NULL)
- {
- TpGroupMixin *mixin = TP_GROUP_MIXIN (chan);
- TpIntSet *set;
-
- session = create_session (chan, peer, peer_resource, sid);
- session_is_new = TRUE;
-
- /* make us local pending */
- set = tp_intset_new ();
- tp_intset_add (set, mixin->self_handle);
-
- tp_group_mixin_change_members ((GObject *)chan,
- "", NULL, NULL, set, NULL, 0, 0);
-
- tp_intset_destroy (set);
-
- /* and update flags accordingly */
- tp_group_mixin_change_flags ((GObject *)chan,
- TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_CAN_REMOVE,
- 0);
- }
-
- g_object_ref (session);
-
- if (_gabble_media_session_handle_action (session, message, session_node,
- action, error))
- {
- g_object_unref (session);
- return TRUE;
- }
- else
- {
- if (session_is_new)
- _gabble_media_session_terminate (session, INITIATOR_LOCAL,
- TP_CHANNEL_GROUP_CHANGE_REASON_ERROR);
-
- g_object_unref (session);
- return FALSE;
- }
-}
-
-static void
-gabble_media_channel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (object);
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
- const gchar *param_name;
- guint tp_property_id;
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
- break;
- case PROP_HANDLE_TYPE:
- g_value_set_uint (value, TP_HANDLE_TYPE_NONE);
- break;
- case PROP_HANDLE:
- g_value_set_uint (value, 0);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_CREATOR:
- g_value_set_uint (value, priv->creator);
- break;
- case PROP_FACTORY:
- g_value_set_object (value, priv->factory);
- break;
- default:
- param_name = g_param_spec_get_name (pspec);
-
- if (tp_properties_mixin_has_property (object, param_name,
- &tp_property_id))
- {
- GValue *tp_property_value =
- chan->properties.properties[tp_property_id].value;
-
- if (tp_property_value)
- {
- g_value_copy (tp_property_value, value);
- return;
- }
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_media_channel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (object);
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
- const gchar *param_name;
- guint tp_property_id;
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_HANDLE:
- /* this property is writable in the interface, but not actually
- * meaningfully changable on this channel, so we do nothing */
- break;
- case PROP_HANDLE_TYPE:
- /* this property is writable in the interface, but not actually
- * meaningfully changable on this channel, so we do nothing */
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_CREATOR:
- priv->creator = g_value_get_uint (value);
- break;
- case PROP_FACTORY:
- priv->factory = g_value_get_object (value);
- break;
- default:
- param_name = g_param_spec_get_name (pspec);
-
- if (tp_properties_mixin_has_property (object, param_name,
- &tp_property_id))
- {
- tp_properties_mixin_change_value (object, tp_property_id, value,
- NULL);
- tp_properties_mixin_change_flags (object, tp_property_id,
- TP_PROPERTY_FLAG_READ,
- 0, NULL);
-
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_media_channel_dispose (GObject *object);
-static void gabble_media_channel_finalize (GObject *object);
-static gboolean gabble_media_channel_remove_member (GObject *obj,
- TpHandle handle, const gchar *message, GError **error);
-
-static void
-gabble_media_channel_class_init (GabbleMediaChannelClass *gabble_media_channel_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_media_channel_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_media_channel_class,
- sizeof (GabbleMediaChannelPrivate));
-
- object_class->constructor = gabble_media_channel_constructor;
-
- object_class->get_property = gabble_media_channel_get_property;
- object_class->set_property = gabble_media_channel_set_property;
-
- object_class->dispose = gabble_media_channel_dispose;
- object_class->finalize = gabble_media_channel_finalize;
-
- tp_group_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleMediaChannelClass, group_class),
- _gabble_media_channel_add_member, gabble_media_channel_remove_member);
-
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
- g_object_class_override_property (object_class, PROP_HANDLE, "handle");
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "media channel object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_uint ("creator", "Channel creator",
- "The TpHandle representing the contact "
- "who created the channel.",
- 0, G_MAXUINT32, 0,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CREATOR, param_spec);
-
- param_spec = g_param_spec_object ("factory", "GabbleMediaFactory object",
- "The factory that created this object.",
- GABBLE_TYPE_MEDIA_FACTORY,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_FACTORY, param_spec);
-
- param_spec = g_param_spec_string ("nat-traversal",
- "NAT traversal",
- "NAT traversal mechanism.",
- "gtalk-p2p",
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_NAT_TRAVERSAL,
- param_spec);
-
- param_spec = g_param_spec_string ("stun-server",
- "STUN server",
- "IP or address of STUN server.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_SERVER, param_spec);
-
- param_spec = g_param_spec_uint ("stun-port",
- "STUN port",
- "UDP port of STUN server.",
- 0, G_MAXUINT16, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_PORT, param_spec);
-
- param_spec = g_param_spec_string ("gtalk-p2p-relay-token",
- "GTalk P2P Relay Token",
- "Magic token to authenticate with the "
- "Google Talk relay server.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_GTALK_P2P_RELAY_TOKEN,
- param_spec);
-
- tp_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleMediaChannelClass, properties_class),
- channel_property_signatures, NUM_CHAN_PROPS, NULL);
-}
-
-void
-gabble_media_channel_dispose (GObject *object)
-{
- GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (object);
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- /** In this we set the state to ENDED, then the callback unrefs
- * the session
- */
-
- if (!priv->closed)
- gabble_media_channel_close (self);
-
- g_assert (priv->closed);
- g_assert (priv->session == NULL);
- g_assert (priv->streams == NULL);
-
- if (G_OBJECT_CLASS (gabble_media_channel_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_media_channel_parent_class)->dispose (object);
-}
-
-void
-gabble_media_channel_finalize (GObject *object)
-{
- GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (object);
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self);
-
- g_free (priv->object_path);
-
- tp_group_mixin_finalize (object);
-
- G_OBJECT_CLASS (gabble_media_channel_parent_class)->finalize (object);
-}
-
-
-/**
- * gabble_media_channel_close
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_media_channel_close_async (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface);
-
- gabble_media_channel_close (self);
- tp_svc_channel_return_from_close (context);
-}
-
-void
-gabble_media_channel_close (GabbleMediaChannel *self)
-{
- GabbleMediaChannelPrivate *priv;
-
- DEBUG ("called on %p", self);
-
- g_assert (GABBLE_IS_MEDIA_CHANNEL (self));
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self);
-
- if (priv->closed)
- {
- return;
- }
-
- priv->closed = TRUE;
-
- if (priv->session)
- {
- _gabble_media_session_terminate (priv->session, INITIATOR_LOCAL,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- }
-
- tp_svc_channel_emit_closed (self);
-}
-
-
-/**
- * gabble_media_channel_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_media_channel_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
-}
-
-
-/**
- * gabble_media_channel_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_media_channel_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_handle (context, 0, 0);
-}
-
-
-/**
- * gabble_media_channel_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_media_channel_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- const gchar *interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- TP_IFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING,
- TP_IFACE_PROPERTIES_INTERFACE,
- NULL
- };
-
- tp_svc_channel_return_from_get_interfaces (context, interfaces);
-}
-
-
-/**
- * gabble_media_channel_get_session_handlers
- *
- * Implements D-Bus method GetSessionHandlers
- * on interface org.freedesktop.Telepathy.Channel.Interface.MediaSignalling
- */
-static void
-gabble_media_channel_get_session_handlers (TpSvcChannelInterfaceMediaSignalling *iface,
- DBusGMethodInvocation *context)
-{
- GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface);
- GabbleMediaChannelPrivate *priv;
- GPtrArray *ret;
-
- g_assert (GABBLE_IS_MEDIA_CHANNEL (self));
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self);
-
- if (priv->session)
- {
- GValue handler = { 0, };
- TpHandle member;
- gchar *path;
-
- g_value_init (&handler, TP_SESSION_HANDLER_SET_TYPE);
- g_value_take_boxed (&handler,
- dbus_g_type_specialized_construct (TP_SESSION_HANDLER_SET_TYPE));
-
- g_object_get (priv->session,
- "peer", &member,
- "object-path", &path,
- NULL);
-
- dbus_g_type_struct_set (&handler,
- 0, path,
- 1, "rtp",
- G_MAXUINT);
-
- g_free (path);
-
- ret = g_ptr_array_sized_new (1);
- g_ptr_array_add (ret, g_value_get_boxed (&handler));
- }
- else
- {
- ret = g_ptr_array_sized_new (0);
- }
-
- tp_svc_channel_interface_media_signalling_return_from_get_session_handlers (
- context, ret);
- g_ptr_array_free (ret, TRUE);
-}
-
-
-static GPtrArray *
-make_stream_list (GabbleMediaChannel *self,
- GPtrArray *streams)
-{
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self);
- GPtrArray *ret;
- guint i;
-
- ret = g_ptr_array_sized_new (streams->len);
-
- for (i = 0; i < streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (streams, i);
- GValue entry = { 0, };
- guint id;
- TpHandle peer;
- TpMediaStreamType type;
- TpMediaStreamState connection_state;
- CombinedStreamDirection combined_direction;
-
- g_object_get (stream,
- "id", &id,
- "media-type", &type,
- "connection-state", &connection_state,
- "combined-direction", &combined_direction,
- NULL);
-
- g_object_get (priv->session, "peer", &peer, NULL);
-
- g_value_init (&entry, TP_CHANNEL_STREAM_TYPE);
- g_value_take_boxed (&entry,
- dbus_g_type_specialized_construct (TP_CHANNEL_STREAM_TYPE));
-
- dbus_g_type_struct_set (&entry,
- 0, id,
- 1, peer,
- 2, type,
- 3, connection_state,
- 4, COMBINED_DIRECTION_GET_DIRECTION (combined_direction),
- 5, COMBINED_DIRECTION_GET_PENDING_SEND (combined_direction),
- G_MAXUINT);
-
- g_ptr_array_add (ret, g_value_get_boxed (&entry));
- }
-
- return ret;
-}
-
-/**
- * gabble_media_channel_list_streams
- *
- * Implements D-Bus method ListStreams
- * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia
- */
-static void
-gabble_media_channel_list_streams (TpSvcChannelTypeStreamedMedia *iface,
- DBusGMethodInvocation *context)
-{
- GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface);
- GabbleMediaChannelPrivate *priv;
- GPtrArray *ret;
-
- g_assert (GABBLE_IS_MEDIA_CHANNEL (self));
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self);
-
- /* no session yet? return an empty array */
- if (priv->session == NULL)
- {
- ret = g_ptr_array_new ();
- }
- else
- {
- ret = make_stream_list (self, priv->streams);
- }
-
- tp_svc_channel_type_streamed_media_return_from_list_streams (context, ret);
- g_ptr_array_free (ret, TRUE);
-}
-
-
-static GabbleMediaStream *
-_find_stream_by_id (GabbleMediaChannel *chan, guint stream_id)
-{
- GabbleMediaChannelPrivate *priv;
- guint i;
-
- g_assert (GABBLE_IS_MEDIA_CHANNEL (chan));
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
- guint id;
-
- g_object_get (stream, "id", &id, NULL);
- if (id == stream_id)
- return stream;
- }
-
- return NULL;
-}
-
-/**
- * gabble_media_channel_remove_streams
- *
- * Implements DBus method RemoveStreams
- * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia
- */
-static void
-gabble_media_channel_remove_streams (TpSvcChannelTypeStreamedMedia *iface,
- const GArray * streams,
- DBusGMethodInvocation *context)
-{
- GabbleMediaChannel *obj = GABBLE_MEDIA_CHANNEL (iface);
- GabbleMediaChannelPrivate *priv;
- GPtrArray *stream_objs;
- GError *error = NULL;
- guint i;
-
- g_assert (GABBLE_IS_MEDIA_CHANNEL (obj));
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (obj);
-
- stream_objs = g_ptr_array_sized_new (streams->len);
-
- /* check that all stream ids are valid and at the same time build an array
- * of stream objects so we don't have to look them up again after verifying
- * all stream identifiers. */
- for (i = 0; i < streams->len; i++)
- {
- guint id = g_array_index (streams, guint, i);
- GabbleMediaStream *stream;
- guint j;
-
- stream = _find_stream_by_id (obj, id);
- if (stream == NULL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "given stream id %u does not exist", id);
- goto OUT;
- }
-
- /* make sure we don't allow the client to repeatedly remove the same
- stream */
- for (j = 0; j < stream_objs->len; j++)
- {
- GabbleMediaStream *tmp = g_ptr_array_index (stream_objs, j);
-
- if (tmp == stream)
- {
- stream = NULL;
- break;
- }
- }
-
- if (stream != NULL)
- g_ptr_array_add (stream_objs, stream);
- }
-
- /* groovy, it's all good dude, let's remove them */
- if (stream_objs->len > 0)
- _gabble_media_session_remove_streams (priv->session, (GabbleMediaStream **)
- stream_objs->pdata, stream_objs->len);
-
-OUT:
- g_ptr_array_free (stream_objs, TRUE);
-
- if (error)
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
- else
- {
- tp_svc_channel_type_streamed_media_return_from_remove_streams (context);
- }
-}
-
-
-/**
- * gabble_media_channel_request_stream_direction
- *
- * Implements D-Bus method RequestStreamDirection
- * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia
- */
-static void
-gabble_media_channel_request_stream_direction (TpSvcChannelTypeStreamedMedia *iface,
- guint stream_id,
- guint stream_direction,
- DBusGMethodInvocation *context)
-{
- GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface);
- GabbleMediaChannelPrivate *priv;
- GabbleMediaStream *stream;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_MEDIA_CHANNEL (self));
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self);
-
- if (stream_direction > TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "given stream direction %u is not valid", stream_direction);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- stream = _find_stream_by_id (self, stream_id);
- if (stream == NULL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "given stream id %u does not exist", stream_id);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- /* streams with no session? I think not... */
- g_assert (priv->session != NULL);
-
- if (_gabble_media_session_request_stream_direction (priv->session, stream,
- stream_direction, &error))
- {
- tp_svc_channel_type_streamed_media_return_from_request_stream_direction (
- context);
- }
- else
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-}
-
-
-/**
- * gabble_media_channel_request_streams
- *
- * Implements D-Bus method RequestStreams
- * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia
- */
-static void
-gabble_media_channel_request_streams (TpSvcChannelTypeStreamedMedia *iface,
- guint contact_handle,
- const GArray *types,
- DBusGMethodInvocation *context)
-{
- GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface);
- GabbleMediaChannelPrivate *priv;
- TpBaseConnection *conn;
- GPtrArray *streams;
- GError *error = NULL;
- GPtrArray *ret;
- TpHandleRepoIface *contact_handles;
-
- g_assert (GABBLE_IS_MEDIA_CHANNEL (self));
-
- priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self);
- conn = (TpBaseConnection *)priv->conn;
- contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- if (!tp_handle_is_valid (contact_handles, contact_handle, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- if (!tp_handle_set_is_member (self->group.members, contact_handle) &&
- !tp_handle_set_is_member (self->group.remote_pending, contact_handle))
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "given handle %u is not a member of the channel", contact_handle);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- /* if the person is a channel member, we should have a session */
- g_assert (priv->session != NULL);
-
- if (!_gabble_media_session_request_streams (priv->session, types, &streams,
- &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- ret = make_stream_list (self, streams);
-
- g_ptr_array_free (streams, TRUE);
-
- tp_svc_channel_type_streamed_media_return_from_request_streams (context, ret);
- g_ptr_array_free (ret, TRUE);
-}
-
-
-gboolean
-_gabble_media_channel_add_member (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error)
-{
- GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (obj);
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
- TpGroupMixin *mixin = TP_GROUP_MIXIN (obj);
-#ifdef ENABLE_DEBUG
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-#endif
-
- /* did we create this channel? */
- if (priv->creator == mixin->self_handle)
- {
- GabblePresence *presence;
- TpIntSet *set;
-
- /* yes: check the peer's capabilities */
-
- presence = gabble_presence_cache_get (priv->conn->presence_cache, handle);
-
- if (presence == NULL)
- {
- DEBUG ("failed to add contact %d (%s) to media channel: "
- "no presence available", handle,
- tp_handle_inspect (contact_handles, handle));
- goto NO_CAPS;
- }
-
- if (!(presence->caps & PRESENCE_CAP_GOOGLE_VOICE ||
- presence->caps & PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO ||
- presence->caps & PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO))
- {
- DEBUG ("failed to add contact %d (%s) to media channel: "
- "caps %x aren't sufficient", handle,
- tp_handle_inspect (contact_handles, handle),
- presence->caps);
- goto NO_CAPS;
- }
-
- /* yes: invite the peer */
-
- /* create a new session */
- create_session (chan, handle, NULL, NULL);
-
- /* make the peer remote pending */
- set = tp_intset_new ();
- tp_intset_add (set, handle);
-
- tp_group_mixin_change_members (obj, "", NULL, NULL, NULL, set, 0, 0);
-
- tp_intset_destroy (set);
-
- /* and update flags accordingly */
- tp_group_mixin_change_flags (obj,
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | TP_CHANNEL_GROUP_FLAG_CAN_RESCIND,
- TP_CHANNEL_GROUP_FLAG_CAN_ADD);
-
- return TRUE;
- }
- else
- {
- /* no: has a session been created, is the handle being added ours,
- * and are we in local pending? */
-
- if (priv->session &&
- handle == mixin->self_handle &&
- tp_handle_set_is_member (mixin->local_pending, handle))
- {
- /* yes: accept the request */
-
- TpIntSet *set;
-
- /* make us a member */
- set = tp_intset_new ();
- tp_intset_add (set, handle);
-
- tp_group_mixin_change_members (obj,
- "", set, NULL, NULL, NULL, 0, 0);
-
- tp_intset_destroy (set);
-
- /* update flags */
- tp_group_mixin_change_flags (obj,
- 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD);
-
- /* signal acceptance */
- _gabble_media_session_accept (priv->session);
-
- return TRUE;
- }
- }
-
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "handle %u cannot be added in the current state", handle);
- return FALSE;
-
-NO_CAPS:
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "handle %u has no media capabilities", handle);
- return FALSE;
-}
-
-static gboolean
-gabble_media_channel_remove_member (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error)
-{
- GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (obj);
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
- TpGroupMixin *mixin = TP_GROUP_MIXIN (obj);
- TpIntSet *set;
-
- if (priv->session == NULL)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "handle %u cannot be removed in the current state", handle);
-
- return FALSE;
- }
-
- if (priv->creator != mixin->self_handle &&
- handle != mixin->self_handle)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_PERMISSION_DENIED,
- "handle %u cannot be removed because you are not the creator of the"
- " channel", handle);
-
- return FALSE;
- }
-
- _gabble_media_session_terminate (priv->session, INITIATOR_LOCAL,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- /* remove the member */
- set = tp_intset_new ();
- tp_intset_add (set, handle);
-
- tp_group_mixin_change_members (obj, "", NULL, set, NULL, NULL, 0, 0);
-
- tp_intset_destroy (set);
-
- /* and update flags accordingly */
- tp_group_mixin_change_flags (obj, TP_CHANNEL_GROUP_FLAG_CAN_ADD,
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | TP_CHANNEL_GROUP_FLAG_CAN_RESCIND);
-
- return TRUE;
-}
-
-static void
-session_terminated_cb (GabbleMediaSession *session,
- guint terminator,
- guint reason,
- gpointer user_data)
-{
- GabbleMediaChannel *channel = (GabbleMediaChannel *) user_data;
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (channel);
- TpGroupMixin *mixin = TP_GROUP_MIXIN (channel);
- gchar *sid;
- JingleSessionState state;
- TpHandle peer;
- TpIntSet *set;
-
- g_object_get (session,
- "state", &state,
- "peer", &peer,
- NULL);
-
- set = tp_intset_new ();
-
- /* remove us and the peer from the member list */
- tp_intset_add (set, mixin->self_handle);
- tp_intset_add (set, peer);
-
- tp_group_mixin_change_members ((GObject *)channel,
- "", NULL, set, NULL, NULL, terminator, reason);
-
- /* update flags accordingly -- allow adding, deny removal */
- tp_group_mixin_change_flags ((GObject *)channel,
- TP_CHANNEL_GROUP_FLAG_CAN_ADD,
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE);
-
- /* free the session ID */
- g_object_get (priv->session, "session-id", &sid, NULL);
- _gabble_media_factory_free_sid (priv->factory, sid);
- g_free (sid);
-
- /* unref streams */
- if (priv->streams != NULL)
- {
- GPtrArray *tmp = priv->streams;
-
- /* move priv->streams aside so that the stream_close_cb
- * doesn't double unref */
- priv->streams = NULL;
- g_ptr_array_foreach (tmp, (GFunc) g_object_unref, NULL);
- g_ptr_array_free (tmp, TRUE);
- }
-
- /* remove the session */
- g_object_unref (priv->session);
- priv->session = NULL;
-
- /* close the channel */
- gabble_media_channel_close (channel);
-}
-
-
-static void
-session_state_changed_cb (GabbleMediaSession *session,
- GParamSpec *arg1,
- GabbleMediaChannel *channel)
-{
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (channel);
- TpGroupMixin *mixin = TP_GROUP_MIXIN (channel);
- JingleSessionState state;
- TpHandle peer;
- TpIntSet *set;
-
- g_object_get (session,
- "state", &state,
- "peer", &peer,
- NULL);
-
- if (state != JS_STATE_ACTIVE)
- return;
-
- if (priv->creator != mixin->self_handle)
- return;
-
- set = tp_intset_new ();
-
- /* add the peer to the member list */
- tp_intset_add (set, peer);
-
- tp_group_mixin_change_members ((GObject *)channel,
- "", set, NULL, NULL, NULL, 0, 0);
-
- /* update flags accordingly -- allow removal, deny adding and rescinding */
- tp_group_mixin_change_flags ((GObject *)channel,
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE,
- TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_CAN_RESCIND);
-
- tp_intset_destroy (set);
-}
-
-static void
-stream_close_cb (GabbleMediaStream *stream,
- GabbleMediaChannel *chan)
-{
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
- guint id;
-
- g_object_get (stream, "id", &id, NULL);
-
- tp_svc_channel_type_streamed_media_emit_stream_removed (chan, id);
-
- if (priv->streams != NULL)
- {
- g_ptr_array_remove (priv->streams, stream);
- g_object_unref (stream);
- }
-}
-
-static void
-stream_error_cb (GabbleMediaStream *stream,
- TpMediaStreamError errno,
- const gchar *message,
- GabbleMediaChannel *chan)
-{
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
- guint id;
-
- /* emit signal */
- g_object_get (stream, "id", &id, NULL);
- tp_svc_channel_type_streamed_media_emit_stream_error (chan, id, errno,
- message);
-
- /* remove stream from session */
- _gabble_media_session_remove_streams (priv->session, &stream, 1);
-}
-
-static void
-stream_state_changed_cb (GabbleMediaStream *stream,
- GParamSpec *pspec,
- GabbleMediaChannel *chan)
-{
- guint id;
- TpMediaStreamState connection_state;
-
- g_object_get (stream,
- "id", &id,
- "connection-state", &connection_state,
- NULL);
-
- tp_svc_channel_type_streamed_media_emit_stream_state_changed (chan,
- id, connection_state);
-}
-
-static void
-stream_direction_changed_cb (GabbleMediaStream *stream,
- GParamSpec *pspec,
- GabbleMediaChannel *chan)
-{
- guint id;
- CombinedStreamDirection combined;
- TpMediaStreamDirection direction;
- TpMediaStreamPendingSend pending_send;
-
- g_object_get (stream,
- "id", &id,
- "combined-direction", &combined,
- NULL);
-
- direction = COMBINED_DIRECTION_GET_DIRECTION (combined);
- pending_send = COMBINED_DIRECTION_GET_PENDING_SEND (combined);
-
- tp_svc_channel_type_streamed_media_emit_stream_direction_changed (
- chan, id, direction, pending_send);
-}
-
-static void
-session_stream_added_cb (GabbleMediaSession *session,
- GabbleMediaStream *stream,
- GabbleMediaChannel *chan)
-{
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
-
- guint id, handle, type;
-
- /* keep track of the stream */
- g_object_ref (stream);
- g_ptr_array_add (priv->streams, stream);
-
- g_signal_connect (stream, "close",
- (GCallback) stream_close_cb, chan);
- g_signal_connect (stream, "error",
- (GCallback) stream_error_cb, chan);
- g_signal_connect (stream, "notify::connection-state",
- (GCallback) stream_state_changed_cb, chan);
- g_signal_connect (stream, "notify::combined-direction",
- (GCallback) stream_direction_changed_cb, chan);
-
- /* emit StreamAdded */
- g_object_get (session, "peer", &handle, NULL);
- g_object_get (stream, "id", &id, "media-type", &type, NULL);
-
- tp_svc_channel_type_streamed_media_emit_stream_added (
- chan, id, handle, type);
-}
-
-guint
-_gabble_media_channel_get_stream_id (GabbleMediaChannel *chan)
-{
- GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
-
- return priv->next_stream_id++;
-}
-
-#define AUDIO_CAPS \
- ( PRESENCE_CAP_GOOGLE_VOICE | PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO )
-
-#define VIDEO_CAPS \
- ( PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO )
-
-GabblePresenceCapabilities
-_gabble_media_channel_typeflags_to_caps (TpChannelMediaCapabilities flags)
-{
- GabblePresenceCapabilities caps = 0;
-
- if (flags & TP_CHANNEL_MEDIA_CAPABILITY_AUDIO)
- caps |= AUDIO_CAPS;
-
- if (flags & TP_CHANNEL_MEDIA_CAPABILITY_VIDEO)
- caps |= VIDEO_CAPS;
-
- return caps;
-}
-
-TpChannelMediaCapabilities
-_gabble_media_channel_caps_to_typeflags (GabblePresenceCapabilities caps)
-{
- TpChannelMediaCapabilities typeflags = 0;
-
- if (caps & AUDIO_CAPS)
- typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_AUDIO;
-
- if (caps & VIDEO_CAPS)
- typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_VIDEO;
-
- return typeflags;
-}
-
-
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *)g_iface;
-
-#define IMPLEMENT(x, suffix) tp_svc_channel_implement_##x (\
- klass, gabble_media_channel_##x##suffix)
- IMPLEMENT(close,_async);
- IMPLEMENT(get_channel_type,);
- IMPLEMENT(get_handle,);
- IMPLEMENT(get_interfaces,);
-#undef IMPLEMENT
-}
-
-static void
-streamed_media_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelTypeStreamedMediaClass *klass =
- (TpSvcChannelTypeStreamedMediaClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_type_streamed_media_implement_##x (\
- klass, gabble_media_channel_##x)
- IMPLEMENT(list_streams);
- IMPLEMENT(remove_streams);
- IMPLEMENT(request_stream_direction);
- IMPLEMENT(request_streams);
-#undef IMPLEMENT
-}
-
-static void
-media_signalling_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelInterfaceMediaSignallingClass *klass =
- (TpSvcChannelInterfaceMediaSignallingClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_interface_media_signalling_implement_##x (\
- klass, gabble_media_channel_##x)
- IMPLEMENT(get_session_handlers);
-#undef IMPLEMENT
-}
diff --git a/src/gabble-media-channel.h b/src/gabble-media-channel.h
deleted file mode 100644
index e71fe1e0f..000000000
--- a/src/gabble-media-channel.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * gabble-media-channel.h - Header for GabbleMediaChannel
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_MEDIA_CHANNEL_H__
-#define __GABBLE_MEDIA_CHANNEL_H__
-
-#include <glib-object.h>
-
-#include <telepathy-glib/group-mixin.h>
-#include <telepathy-glib/properties-mixin.h>
-
-#include "gabble-media-session.h"
-#include "presence.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleMediaChannel GabbleMediaChannel;
-typedef struct _GabbleMediaChannelClass GabbleMediaChannelClass;
-
-struct _GabbleMediaChannelClass {
- GObjectClass parent_class;
-
- TpGroupMixinClass group_class;
- TpPropertiesMixinClass properties_class;
-};
-
-struct _GabbleMediaChannel {
- GObject parent;
-
- TpGroupMixin group;
- TpPropertiesMixin properties;
-
- gpointer priv;
-};
-
-GType gabble_media_channel_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_MEDIA_CHANNEL \
- (gabble_media_channel_get_type ())
-#define GABBLE_MEDIA_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MEDIA_CHANNEL,\
- GabbleMediaChannel))
-#define GABBLE_MEDIA_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MEDIA_CHANNEL,\
- GabbleMediaChannelClass))
-#define GABBLE_IS_MEDIA_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MEDIA_CHANNEL))
-#define GABBLE_IS_MEDIA_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MEDIA_CHANNEL))
-#define GABBLE_MEDIA_CHANNEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MEDIA_CHANNEL, \
- GabbleMediaChannelClass))
-
-gboolean
-_gabble_media_channel_add_member (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error);
-
-gboolean
-_gabble_media_channel_dispatch_session_action (GabbleMediaChannel *chan,
- TpHandle peer,
- const gchar *peer_resource,
- const gchar *sid,
- LmMessage *message,
- LmMessageNode *session_node,
- const gchar *action,
- GError **error);
-
-void
-_gabble_media_channel_stream_state (GabbleMediaChannel *chan,
- guint state);
-
-guint
-_gabble_media_channel_get_stream_id (GabbleMediaChannel *chan);
-
-GabblePresenceCapabilities
-_gabble_media_channel_typeflags_to_caps (TpChannelMediaCapabilities flags);
-
-TpChannelMediaCapabilities
-_gabble_media_channel_caps_to_typeflags (GabblePresenceCapabilities caps);
-
-void gabble_media_channel_close (GabbleMediaChannel *);
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_MEDIA_CHANNEL_H__*/
diff --git a/src/gabble-media-session.c b/src/gabble-media-session.c
deleted file mode 100644
index f0345533e..000000000
--- a/src/gabble-media-session.c
+++ /dev/null
@@ -1,2928 +0,0 @@
-/*
- * gabble-media-session.c - Source for GabbleMediaSession
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#include "gabble-media-session.h"
-
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include <telepathy-glib/debug-ansi.h>
-#include "debug.h"
-#include "namespaces.h"
-#include "util.h"
-
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/svc-media-interfaces.h>
-
-#include "gabble-connection.h"
-#include "gabble-media-channel.h"
-#include "gabble-media-stream.h"
-#include "presence-cache.h"
-#include "presence.h"
-
-#include "gabble-signals-marshal.h"
-
-static void session_handler_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE(GabbleMediaSession,
- gabble_media_session,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_MEDIA_SESSION_HANDLER,
- session_handler_iface_init)
- )
-
-#define DEFAULT_SESSION_TIMEOUT 50000
-
-#define GTALK_STREAM_NAME "gtalk"
-
-/* 99 streams gives us a max name length of 8 (videoXX\0 or audioXX\0) */
-#define MAX_STREAMS 99
-#define MAX_STREAM_NAME_LEN 8
-
-/* signal enum */
-enum
-{
- STREAM_ADDED,
- TERMINATED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_CONNECTION = 1,
- PROP_MEDIA_CHANNEL,
- PROP_OBJECT_PATH,
- PROP_SESSION_ID,
- PROP_INITIATOR,
- PROP_PEER,
- PROP_PEER_RESOURCE,
- PROP_STATE,
- LAST_PROPERTY
-};
-
-/* private structure */
-typedef struct _GabbleMediaSessionPrivate GabbleMediaSessionPrivate;
-
-struct _GabbleMediaSessionPrivate
-{
- GabbleConnection *conn;
- GabbleMediaChannel *channel;
- GabbleMediaSessionMode mode;
- gchar *object_path;
-
- GPtrArray *streams;
- GPtrArray *remove_requests;
-
- gchar *id;
- TpHandle peer;
- gchar *peer_resource;
-
- JingleSessionState state;
- gboolean ready;
- gboolean locally_accepted;
- gboolean terminated;
-
- guint timer_id;
-
- gboolean dispose_has_run;
-};
-
-#define GABBLE_MEDIA_SESSION_GET_PRIVATE(obj) \
- ((GabbleMediaSessionPrivate *)obj->priv)
-
-typedef struct {
- gchar *name;
- gchar *attributes;
-} SessionStateDescription;
-
-static const SessionStateDescription session_states[] =
-{
- { "JS_STATE_PENDING_CREATED",
- TP_ANSI_BOLD_ON TP_ANSI_FG_BLACK TP_ANSI_BG_WHITE },
- { "JS_STATE_PENDING_INITIATE_SENT",
- TP_ANSI_BOLD_ON TP_ANSI_BG_CYAN },
- { "JS_STATE_PENDING_INITIATED",
- TP_ANSI_BOLD_ON TP_ANSI_BG_MAGENTA },
- { "JS_STATE_PENDING_ACCEPT_SENT",
- TP_ANSI_BOLD_ON TP_ANSI_BG_CYAN },
- { "JS_STATE_ACTIVE",
- TP_ANSI_BOLD_ON TP_ANSI_BG_BLUE },
- { "JS_STATE_ENDED",
- TP_ANSI_BG_RED }
-};
-
-static void
-gabble_media_session_init (GabbleMediaSession *self)
-{
- GabbleMediaSessionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_MEDIA_SESSION, GabbleMediaSessionPrivate);
-
- self->priv = priv;
-
- priv->mode = MODE_JINGLE;
- priv->state = JS_STATE_PENDING_CREATED;
- priv->streams = g_ptr_array_new ();
- priv->remove_requests = g_ptr_array_new ();
-}
-
-static void stream_connection_state_changed_cb (GabbleMediaStream *stream,
- GParamSpec *param,
- GabbleMediaSession *session);
-static void stream_got_local_codecs_changed_cb (GabbleMediaStream *stream,
- GParamSpec *param,
- GabbleMediaSession *session);
-
-static void
-_emit_new_stream (GabbleMediaSession *session,
- GabbleMediaStream *stream)
-{
- gchar *object_path;
- guint id, media_type;
-
- g_object_get (stream,
- "object-path", &object_path,
- "id", &id,
- "media-type", &media_type,
- NULL);
-
- /* all of the streams are bidirectional from farsight's point of view, it's
- * just in the signalling they change */
- tp_svc_media_session_handler_emit_new_stream_handler (session,
- object_path, id, media_type, TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);
-
- g_free (object_path);
-}
-
-
-static GabbleMediaStream *
-_lookup_stream_by_name_and_initiator (GabbleMediaSession *session,
- const gchar *stream_name,
- JingleInitiator stream_initiator)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i;
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (tp_strdiff (stream->name, stream_name))
- continue;
-
- if (stream_initiator != INITIATOR_INVALID &&
- stream_initiator != stream->initiator)
- continue;
-
- return stream;
- }
-
- return NULL;
-}
-
-
-static GabbleMediaStream *
-create_media_stream (GabbleMediaSession *session,
- const gchar *name,
- JingleInitiator initiator,
- guint media_type)
-{
- GabbleMediaSessionPrivate *priv;
- gchar *object_path;
- GabbleMediaStream *stream;
- guint id;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
- g_assert (name != NULL);
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- /* assert that if we're in google mode:
- * - we only try to make one stream
- * - it's an audio stream
- * - it's called GTALK_STREAM_NAME */
- if (priv->mode == MODE_GOOGLE)
- {
- g_assert (priv->streams->len == 0);
- g_assert (media_type == TP_MEDIA_STREAM_TYPE_AUDIO);
- g_assert (!tp_strdiff (name, GTALK_STREAM_NAME));
- }
-
- g_assert (priv->streams->len < MAX_STREAMS);
- g_assert (_lookup_stream_by_name_and_initiator (session, name, initiator) ==
- NULL);
-
- id = _gabble_media_channel_get_stream_id (priv->channel);
-
- GMS_DEBUG_INFO (session,
- "creating new %s %s stream called \"%s\" with id %u",
- priv->mode == MODE_GOOGLE ? "google" : "jingle",
- media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video",
- name, id);
-
- object_path = g_strdup_printf ("%s/MediaStream%u", priv->object_path, id);
-
- stream = g_object_new (GABBLE_TYPE_MEDIA_STREAM,
- "connection", priv->conn,
- "media-session", session,
- "object-path", object_path,
- "mode", priv->mode,
- "name", name,
- "id", id,
- "initiator", initiator,
- "media-type", media_type,
- NULL);
-
- g_signal_connect (stream, "notify::connection-state",
- (GCallback) stream_connection_state_changed_cb,
- session);
- g_signal_connect (stream, "notify::got-local-codecs",
- (GCallback) stream_got_local_codecs_changed_cb,
- session);
-
- g_ptr_array_add (priv->streams, stream);
-
- g_free (object_path);
-
- if (priv->ready)
- _emit_new_stream (session, stream);
-
- g_signal_emit (session, signals[STREAM_ADDED], 0, stream);
-
- return stream;
-}
-
-static void
-destroy_media_stream (GabbleMediaSession *session,
- GabbleMediaStream *stream)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- _gabble_media_stream_close (stream);
- g_ptr_array_remove_fast (priv->streams, stream);
- g_object_unref (stream);
-}
-
-static GObject *
-gabble_media_session_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleMediaSessionPrivate *priv;
- DBusGConnection *bus;
-
- obj = G_OBJECT_CLASS (gabble_media_session_parent_class)->
- constructor (type, n_props, props);
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (GABBLE_MEDIA_SESSION (obj));
-
- bus = tp_get_bus ();
- dbus_g_connection_register_g_object (bus, priv->object_path, obj);
-
- return obj;
-}
-
-static void
-gabble_media_session_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleMediaSession *session = GABBLE_MEDIA_SESSION (object);
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_MEDIA_CHANNEL:
- g_value_set_object (value, priv->channel);
- break;
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_SESSION_ID:
- g_value_set_string (value, priv->id);
- break;
- case PROP_INITIATOR:
- g_value_set_uint (value, session->initiator);
- break;
- case PROP_PEER:
- g_value_set_uint (value, priv->peer);
- break;
- case PROP_PEER_RESOURCE:
- g_value_set_string (value, priv->peer_resource);
- break;
- case PROP_STATE:
- g_value_set_uint (value, priv->state);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void session_state_changed (GabbleMediaSession *session,
- JingleSessionState prev_state,
- JingleSessionState new_state);
-
-static void
-gabble_media_session_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleMediaSession *session = GABBLE_MEDIA_SESSION (object);
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- JingleSessionState prev_state;
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_MEDIA_CHANNEL:
- priv->channel = g_value_get_object (value);
- break;
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_SESSION_ID:
- g_free (priv->id);
- priv->id = g_value_dup_string (value);
- break;
- case PROP_INITIATOR:
- session->initiator = g_value_get_uint (value);
- break;
- case PROP_PEER:
- priv->peer = g_value_get_uint (value);
- break;
- case PROP_PEER_RESOURCE:
- g_free (priv->peer_resource);
- priv->peer_resource = g_value_dup_string (value);
- break;
- case PROP_STATE:
- prev_state = priv->state;
- priv->state = g_value_get_uint (value);
-
- if (priv->state == JS_STATE_ENDED)
- g_assert (priv->terminated);
-
- if (priv->state != prev_state)
- session_state_changed (session, prev_state, priv->state);
-
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_media_session_dispose (GObject *object);
-static void gabble_media_session_finalize (GObject *object);
-
-static void
-gabble_media_session_class_init (GabbleMediaSessionClass *gabble_media_session_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_media_session_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_media_session_class,
- sizeof (GabbleMediaSessionPrivate));
-
- object_class->constructor = gabble_media_session_constructor;
-
- object_class->get_property = gabble_media_session_get_property;
- object_class->set_property = gabble_media_session_set_property;
-
- object_class->dispose = gabble_media_session_dispose;
- object_class->finalize = gabble_media_session_finalize;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "media session's channel.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_object ("media-channel",
- "GabbleMediaChannel object",
- "Gabble media channel object that owns this media session object.",
- GABBLE_TYPE_MEDIA_CHANNEL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_MEDIA_CHANNEL,
- param_spec);
-
- param_spec = g_param_spec_string ("object-path", "D-Bus object path",
- "The D-Bus object path used for this "
- "object on the bus.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_OBJECT_PATH, param_spec);
-
- param_spec = g_param_spec_string ("session-id", "Session ID",
- "A unique session identifier used "
- "throughout all communication.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_SESSION_ID, param_spec);
-
- param_spec = g_param_spec_uint ("initiator", "Session initiator",
- "An enum signifying which end initiated "
- "the session.",
- INITIATOR_LOCAL,
- INITIATOR_REMOTE,
- INITIATOR_LOCAL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_INITIATOR, param_spec);
-
- param_spec = g_param_spec_uint ("peer", "Session peer",
- "The TpHandle representing the contact "
- "with whom this session communicates.",
- 0, G_MAXUINT32, 0,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PEER, param_spec);
-
- param_spec = g_param_spec_string ("peer-resource",
- "Session peer's resource",
- "The resource of the contact "
- "with whom this session communicates, "
- "if applicable",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_WRITABLE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PEER_RESOURCE,
- param_spec);
-
- param_spec = g_param_spec_uint ("state", "Session state",
- "The current state that the session is in.",
- 0, G_MAXUINT32, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- signals[STREAM_ADDED] =
- g_signal_new ("stream-added",
- G_OBJECT_CLASS_TYPE (gabble_media_session_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, G_TYPE_OBJECT);
-
- signals[TERMINATED] =
- g_signal_new ("terminated",
- G_OBJECT_CLASS_TYPE (gabble_media_session_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- gabble_marshal_VOID__UINT_UINT,
- G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
-}
-
-static void
-gabble_media_session_dispose (GObject *object)
-{
- GabbleMediaSession *self = GABBLE_MEDIA_SESSION (object);
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (self);
- guint i;
-
- DEBUG ("called");
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- _gabble_media_session_terminate (self, INITIATOR_LOCAL,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- if (priv->timer_id != 0)
- g_source_remove (priv->timer_id);
-
- if (priv->streams != NULL)
- {
- for (i = 0; i < priv->streams->len; i++)
- g_object_unref (g_ptr_array_index (priv->streams, i));
- g_ptr_array_free (priv->streams, TRUE);
- priv->streams = NULL;
- }
-
- for (i = 0; i < priv->remove_requests->len; i++)
- g_ptr_array_free (g_ptr_array_index (priv->remove_requests, i), TRUE);
- g_ptr_array_free (priv->remove_requests, TRUE);
- priv->remove_requests = NULL;
-
- if (G_OBJECT_CLASS (gabble_media_session_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_media_session_parent_class)->dispose (object);
-}
-
-static void
-gabble_media_session_finalize (GObject *object)
-{
- GabbleMediaSession *self = GABBLE_MEDIA_SESSION (object);
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (self);
-
- g_free (priv->id);
- g_free (priv->object_path);
- g_free (priv->peer_resource);
- G_OBJECT_CLASS (gabble_media_session_parent_class)->finalize (object);
-}
-
-
-/**
- * gabble_media_session_error
- *
- * Implements D-Bus method Error
- * on interface org.freedesktop.Telepathy.Media.SessionHandler
- */
-static void
-gabble_media_session_error (TpSvcMediaSessionHandler *iface,
- guint errno,
- const gchar *message,
- DBusGMethodInvocation *context)
-{
- GabbleMediaSession *self = GABBLE_MEDIA_SESSION (iface);
- GabbleMediaSessionPrivate *priv;
- GPtrArray *tmp;
- guint i;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (self));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (self);
-
- GMS_DEBUG_INFO (self, "Media.SessionHandler::Error called, error %u (%s) -- "
- "emitting error on each stream", errno, message);
-
- if (priv->state == JS_STATE_ENDED)
- {
- tp_svc_media_session_handler_return_from_error (context);
- return;
- }
- else if (priv->state == JS_STATE_PENDING_CREATED)
- {
- /* shortcut to prevent sending remove actions if we haven't sent an
- * initiate yet */
- g_object_set (self, "state", JS_STATE_ENDED, NULL);
- tp_svc_media_session_handler_return_from_error (context);
- return;
- }
-
- g_assert (priv->streams != NULL);
-
- tmp = priv->streams;
- priv->streams = NULL;
-
- for (i = 0; i < tmp->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- gabble_media_stream_error (stream, errno, message, NULL);
- }
-
- g_ptr_array_free (tmp, TRUE);
-
- tp_svc_media_session_handler_return_from_error (context);
-}
-
-
-/**
- * gabble_media_session_ready
- *
- * Implements D-Bus method Ready
- * on interface org.freedesktop.Telepathy.Media.SessionHandler
- */
-static void
-gabble_media_session_ready (TpSvcMediaSessionHandler *iface,
- DBusGMethodInvocation *context)
-{
- GabbleMediaSession *self = GABBLE_MEDIA_SESSION (iface);
- GabbleMediaSessionPrivate *priv;
- guint i;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (self));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (self);
-
- priv->ready = TRUE;
-
- for (i = 0; i < priv->streams->len; i++)
- _emit_new_stream (self, g_ptr_array_index (priv->streams, i));
-
- tp_svc_media_session_handler_return_from_ready (context);
-}
-
-
-static gboolean
-_handle_create (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- GabbleMediaStream *stream,
- LmMessageNode *desc_node,
- LmMessageNode *trans_node,
- GError **error)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- GabbleMediaSessionMode session_mode;
- TpMediaStreamType stream_type;
- gboolean override_existing = FALSE;
-
- if ((priv->state == JS_STATE_PENDING_CREATED) &&
- (session->initiator == INITIATOR_LOCAL))
- {
- DEBUG ("we're trying to call ourselves, rejecting with busy");
- _gabble_media_session_terminate (session, INITIATOR_REMOTE,
- TP_CHANNEL_GROUP_CHANGE_REASON_BUSY);
- return FALSE;
- }
-
-
- if (stream != NULL)
- {
- /* streams added by the session initiator may replace similarly-named
- * streams which we are trying to add (but havn't had acknowledged) */
- if (stream->signalling_state < STREAM_SIG_STATE_ACKNOWLEDGED)
- {
- if (session->initiator == INITIATOR_REMOTE)
- {
- override_existing = TRUE;
- }
- else
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_CONFLICT,
- "session initiator is creating a stream named \"%s\" "
- "already", stream_name);
- return FALSE;
- }
- }
- else
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_CONFLICT,
- "can't create new stream called \"%s\", it already exists, "
- "rejecting", stream_name);
- return FALSE;
- }
- }
-
- if (desc_node == NULL)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "unable to create stream without a content description");
- return FALSE;
- }
-
- if (lm_message_node_has_namespace (desc_node,
- NS_GOOGLE_SESSION_PHONE, NULL))
- {
- session_mode = MODE_GOOGLE;
- stream_type = TP_MEDIA_STREAM_TYPE_AUDIO;
- }
- else if (lm_message_node_has_namespace (desc_node,
- NS_JINGLE_DESCRIPTION_AUDIO, NULL))
- {
- session_mode = MODE_JINGLE;
- stream_type = TP_MEDIA_STREAM_TYPE_AUDIO;
- }
- else if (lm_message_node_has_namespace (desc_node,
- NS_JINGLE_DESCRIPTION_VIDEO, NULL))
- {
- session_mode = MODE_JINGLE;
- stream_type = TP_MEDIA_STREAM_TYPE_VIDEO;
- }
- else
- {
- g_set_error (error, GABBLE_XMPP_ERROR,
- XMPP_ERROR_JINGLE_UNSUPPORTED_CONTENT,
- "refusing to create stream for unsupported content description");
- return FALSE;
- }
-
- /* MODE_GOOGLE is allowed to have a null transport node */
- if (session_mode == MODE_JINGLE && trans_node == NULL)
- {
- g_set_error (error, GABBLE_XMPP_ERROR,
- XMPP_ERROR_JINGLE_UNSUPPORTED_TRANSPORT,
- "refusing to create stream for unsupported transport");
- return FALSE;
- }
-
- if (session_mode != priv->mode)
- {
- if (priv->streams->len > 0)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_UNEXPECTED_REQUEST,
- "refusing to change mode because streams already exist");
- return FALSE;
- }
- else
- {
- GMS_DEBUG_INFO (session, "setting session mode to %s",
- session_mode == MODE_GOOGLE ? "google" : "jingle");
- priv->mode = session_mode;
- }
- }
-
- if (override_existing)
- {
- GMS_DEBUG_INFO (session, "removing our unacknowledged stream \"%s\" "
- "in favour of the session initiator's", stream_name);
-
- /* disappear this stream */
- destroy_media_stream (session, stream);
-
- stream = NULL;
- }
-
- if (priv->streams->len == MAX_STREAMS)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_RESOURCE_CONSTRAINT,
- "refusing to create more than " G_STRINGIFY (MAX_STREAMS)
- " streams");
- return FALSE;
- }
-
- stream = create_media_stream (session, stream_name, INITIATOR_REMOTE,
- stream_type);
-
- /* set the signalling state to ACKNOWLEDGED */
- g_object_set (stream,
- "signalling-state", STREAM_SIG_STATE_ACKNOWLEDGED,
- NULL);
-
- /* for jingle streams, set the direction to none, so that the
- * direction handler adds the right flags */
- if (priv->mode == MODE_JINGLE)
- g_object_set (stream,
- "combined-direction", TP_MEDIA_STREAM_DIRECTION_NONE,
- NULL);
-
- return TRUE;
-}
-
-
-static TpMediaStreamDirection
-_senders_to_direction (GabbleMediaSession *session,
- const gchar *senders)
-{
- TpMediaStreamDirection ret = TP_MEDIA_STREAM_DIRECTION_NONE;
-
- if (!tp_strdiff (senders, "initiator"))
- {
- if (session->initiator == INITIATOR_LOCAL)
- ret = TP_MEDIA_STREAM_DIRECTION_SEND;
- else
- ret = TP_MEDIA_STREAM_DIRECTION_RECEIVE;
- }
- else if (!tp_strdiff (senders, "responder"))
- {
- if (session->initiator == INITIATOR_REMOTE)
- ret = TP_MEDIA_STREAM_DIRECTION_SEND;
- else
- ret = TP_MEDIA_STREAM_DIRECTION_RECEIVE;
- }
- else if (!tp_strdiff (senders, "both"))
- {
- ret = TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
- }
-
- return ret;
-}
-
-static gboolean
-_handle_direction (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- GabbleMediaStream *stream,
- LmMessageNode *desc_node,
- LmMessageNode *trans_node,
- GError **error)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- const gchar *senders;
- CombinedStreamDirection new_combined_dir;
- TpMediaStreamDirection requested_dir, current_dir;
- TpMediaStreamPendingSend pending_send;
-
- if (priv->mode == MODE_GOOGLE)
- return TRUE;
-
- requested_dir = TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
-
- senders = lm_message_node_get_attribute (content_node, "senders");
- if (senders != NULL)
- requested_dir = _senders_to_direction (session, senders);
-
- if (requested_dir == TP_MEDIA_STREAM_DIRECTION_NONE)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "received invalid content senders value \"%s\" on stream \"%s\"; "
- "rejecting", senders, stream_name);
- return FALSE;
- }
-
- current_dir = COMBINED_DIRECTION_GET_DIRECTION (stream->combined_direction);
- pending_send = COMBINED_DIRECTION_GET_PENDING_SEND
- (stream->combined_direction);
-
- GMS_DEBUG_INFO (session, "received request for senders \"%s\" on stream "
- "\"%s\"", senders, stream_name);
-
- /* if local sending has been added, remove it,
- * and set the pending local send flag */
- if (((current_dir & TP_MEDIA_STREAM_DIRECTION_SEND) == 0) &&
- ((requested_dir & TP_MEDIA_STREAM_DIRECTION_SEND) != 0))
- {
- GMS_DEBUG_INFO (session, "setting pending local send flag");
- requested_dir &= ~TP_MEDIA_STREAM_DIRECTION_SEND;
- pending_send |= TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
- }
-
-#if 0
- /* clear any pending remote send */
- if ((pending_send & TP_MEDIA_STREAM_PENDING_REMOTE_SEND) != 0)
- {
- GMS_DEBUG_INFO (session, "setting pending local send flag");
- pending_send &= ~TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
- }
-#endif
-
- /* make any necessary changes */
- new_combined_dir = MAKE_COMBINED_DIRECTION (requested_dir, pending_send);
- if (new_combined_dir != stream->combined_direction)
- {
- g_object_set (stream, "combined-direction", new_combined_dir, NULL);
- _gabble_media_stream_update_sending (stream, FALSE);
- }
-
- return TRUE;
-}
-
-
-static gboolean
-_handle_accept (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- GabbleMediaStream *stream,
- LmMessageNode *desc_node,
- LmMessageNode *trans_node,
- GError **error)
-{
- g_object_set (stream, "playing", TRUE, NULL);
-
- _gabble_media_stream_update_sending (stream, TRUE);
-
- return TRUE;
-}
-
-
-static gboolean
-_handle_codecs (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- GabbleMediaStream *stream,
- LmMessageNode *desc_node,
- LmMessageNode *trans_node,
- GError **error)
-{
- if (desc_node == NULL)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "unable to handle codecs without a content description node");
- return FALSE;
- }
-
- if (!_gabble_media_stream_post_remote_codecs (stream, message, desc_node,
- error))
- return FALSE;
-
- return TRUE;
-}
-
-
-static gboolean
-_handle_candidates (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- GabbleMediaStream *stream,
- LmMessageNode *desc_node,
- LmMessageNode *trans_node,
- GError **error)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- if (trans_node == NULL)
- {
- if (priv->mode == MODE_GOOGLE)
- {
- trans_node = content_node;
- }
- else
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "unable to handle candidates without a transport node");
- return FALSE;
- }
- }
-
- if (!_gabble_media_stream_post_remote_candidates (stream, message,
- trans_node, error))
- return FALSE;
-
- return TRUE;
-}
-
-static guint
-_count_non_removing_streams (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i, ret = 0;
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (stream->signalling_state < STREAM_SIG_STATE_REMOVING)
- ret++;
- }
-
- return ret;
-}
-
-static gboolean
-_handle_remove (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- GabbleMediaStream *stream,
- LmMessageNode *desc_node,
- LmMessageNode *trans_node,
- GError **error)
-{
- /* reducing a session to contain 0 streams is invalid; instead the peer
- * should terminate the session. I guess we'll do it for them... */
- if (_count_non_removing_streams (session) == 1)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "unable to remove the last stream in a Jingle call");
- return FALSE;
- }
-
- /* close the stream */
- destroy_media_stream (session, stream);
-
- return TRUE;
-}
-
-
-static gboolean
-_handle_terminate (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- GabbleMediaStream *stream,
- LmMessageNode *desc_node,
- LmMessageNode *trans_node,
- GError **error)
-{
- DEBUG ("called for %s", stream_name);
-
- _gabble_media_session_terminate (session, INITIATOR_REMOTE,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- return TRUE;
-}
-
-
-typedef gboolean (*StreamHandlerFunc)(GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- GabbleMediaStream *stream,
- LmMessageNode *desc_node,
- LmMessageNode *trans_node,
- GError **error);
-
-typedef struct _Handler Handler;
-
-struct _Handler {
- const gchar *actions[3];
- JingleSessionState min_allowed_state;
- JingleSessionState max_allowed_state;
- StreamHandlerFunc stream_handlers[4];
- JingleSessionState new_state;
-};
-
-static Handler handlers[] = {
- {
- { "initiate", "session-initiate", NULL },
- JS_STATE_PENDING_CREATED,
- JS_STATE_PENDING_CREATED,
- { _handle_create, _handle_direction, _handle_codecs, NULL },
- JS_STATE_PENDING_INITIATED
- },
- {
- { "accept", "session-accept", NULL },
- JS_STATE_PENDING_INITIATED,
- JS_STATE_PENDING_INITIATED,
- { _handle_direction, _handle_codecs, _handle_accept, NULL },
- JS_STATE_ACTIVE
- },
- {
- { "reject", NULL },
- JS_STATE_PENDING_INITIATE_SENT,
- JS_STATE_PENDING_INITIATED,
- { _handle_terminate, NULL },
- JS_STATE_INVALID
- },
- {
- { "terminate", "session-terminate", NULL },
- JS_STATE_PENDING_INITIATED,
- JS_STATE_ENDED,
- { _handle_terminate, NULL },
- JS_STATE_INVALID
- },
- {
- { "candidates", "transport-info", NULL },
- JS_STATE_PENDING_INITIATED,
- JS_STATE_ACTIVE,
- { _handle_candidates, NULL },
- JS_STATE_INVALID
- },
- {
- { "content-add", NULL },
- JS_STATE_ACTIVE,
- JS_STATE_ACTIVE,
- { _handle_create, _handle_direction, _handle_codecs, NULL },
- JS_STATE_INVALID,
- },
- {
- { "content-modify", NULL },
- JS_STATE_PENDING_INITIATED,
- JS_STATE_ACTIVE,
- { _handle_direction, NULL },
- JS_STATE_INVALID
- },
- {
- { "content-accept", NULL },
- JS_STATE_PENDING_INITIATED,
- JS_STATE_ACTIVE,
- { _handle_direction, _handle_codecs, _handle_accept, NULL },
- JS_STATE_INVALID
- },
- {
- { "content-remove", "content-decline", NULL },
- JS_STATE_PENDING_INITIATED,
- JS_STATE_ACTIVE,
- { _handle_remove, NULL },
- JS_STATE_INVALID
- },
- {
- { NULL },
- JS_STATE_INVALID,
- JS_STATE_INVALID,
- { NULL },
- JS_STATE_INVALID
- }
-};
-
-
-static gboolean
-_call_handlers_on_stream (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *content_node,
- const gchar *stream_name,
- JingleInitiator stream_creator,
- StreamHandlerFunc *func,
- GError **error)
-{
- GabbleMediaStream *stream = NULL;
- LmMessageNode *desc_node = NULL, *trans_node = NULL;
- StreamHandlerFunc *tmp;
- gboolean stream_created = FALSE;
-
- if (content_node != NULL)
- {
- desc_node = lm_message_node_get_child (content_node, "description");
-
- trans_node = lm_message_node_get_child_with_namespace (content_node,
- "transport", NS_GOOGLE_TRANSPORT_P2P);
- }
-
- for (tmp = func; *tmp != NULL; tmp++)
- {
- /* handlers may create the stream */
- if (stream == NULL && stream_name != NULL)
- stream = _lookup_stream_by_name_and_initiator (session, stream_name,
- stream_creator);
-
- /* the create handler is able to check whether or not the stream
- * exists, and act accordingly (sometimes it will replace an existing
- * stream, sometimes it will reject). the termination handler
- * also requires no stream to do it's job. */
- if (*tmp != _handle_create && *tmp != _handle_terminate)
- {
- /* all other handlers require the stream to exist */
- if (stream == NULL)
- {
- const gchar *created = "";
-
- if (stream_creator == INITIATOR_LOCAL)
- created = "locally-created ";
- else if (stream_creator == INITIATOR_REMOTE)
- created = "remotely-created ";
-
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_ITEM_NOT_FOUND,
- "unable to handle action for unknown %sstream \"%s\" ",
- created, stream_name);
-
- return FALSE;
- }
- else
- {
- /* don't do anything with actions on streams which have not been
- * acknowledged, or that we're trying to remove, to deal with
- * adding/removing race conditions (actions sent by the other end
- * before they're aware that we've added or removed a stream) */
- if (stream->signalling_state != STREAM_SIG_STATE_ACKNOWLEDGED)
- {
- GMS_DEBUG_WARNING (session, "ignoring action because stream "
- "%s is in state %d, not ACKNOWLEDGED", stream->name,
- stream->signalling_state);
- return TRUE;
- }
- }
- }
-
- if (!(*tmp) (session, message, content_node, stream_name, stream,
- desc_node, trans_node, error))
- {
- /* if we successfully created the stream but failed to do something
- * with it later, remove it */
- if (stream_created)
- destroy_media_stream (session, stream);
-
- return FALSE;
- }
-
- if (*tmp == _handle_create)
- {
- stream_created = TRUE;
- /* force a stream lookup after the create handler, even if we
- * already had one (it has replacement semantics in certain
- * situations) */
- stream = NULL;
- }
- }
-
- return TRUE;
-}
-
-
-static JingleInitiator
-_creator_to_initiator (GabbleMediaSession *session, const gchar *creator)
-{
- if (!tp_strdiff (creator, "initiator"))
- {
- if (session->initiator == INITIATOR_LOCAL)
- return INITIATOR_LOCAL;
- else
- return INITIATOR_REMOTE;
- }
- else if (!tp_strdiff (creator, "responder"))
- {
- if (session->initiator == INITIATOR_LOCAL)
- return INITIATOR_REMOTE;
- else
- return INITIATOR_LOCAL;
- }
- else
- return INITIATOR_INVALID;
-}
-
-
-static gboolean
-_call_handlers_on_streams (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *session_node,
- StreamHandlerFunc *func,
- GError **error)
-{
- LmMessageNode *content_node;
-
- if (lm_message_node_has_namespace (session_node, NS_GOOGLE_SESSION, NULL))
- return _call_handlers_on_stream (session, message, session_node,
- GTALK_STREAM_NAME, INITIATOR_INVALID, func, error);
-
- if (session_node->children == NULL)
- return _call_handlers_on_stream (session, message, NULL, NULL,
- INITIATOR_INVALID, func, error);
-
- for (content_node = session_node->children;
- NULL != content_node;
- content_node = content_node->next)
- {
- const gchar *stream_name, *stream_creator;
- JingleInitiator stream_initiator;
-
- if (tp_strdiff (content_node->name, "content"))
- continue;
-
- stream_name = lm_message_node_get_attribute (content_node, "name");
-
- if (stream_name == NULL)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "rejecting content node with no name");
- return FALSE;
- }
-
- stream_creator = lm_message_node_get_attribute (content_node, "creator");
- stream_initiator = _creator_to_initiator (session, stream_creator);
-
- /* we allow NULL creator to mean INITIATOR_INVALID for backwards
- * compatibility with clients that don't put a creator attribute in */
- if (stream_creator != NULL && stream_initiator == INITIATOR_INVALID)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "rejecting content node with invalid creators value");
- return FALSE;
- }
-
- if (!_call_handlers_on_stream (session, message, content_node,
- stream_name, stream_initiator, func, error))
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-gboolean
-_gabble_media_session_handle_action (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *session_node,
- const gchar *action,
- GError **error)
-{
- GabbleMediaSessionPrivate *priv;
- StreamHandlerFunc *funcs = NULL;
- JingleSessionState new_state = JS_STATE_INVALID;
- Handler *i;
- const gchar **tmp;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- GMS_DEBUG_INFO (session, "got jingle session action \"%s\" from peer",
- action);
-
- /* do the state machine dance */
-
- /* search the table of handlers for the action */
- for (i = handlers; NULL != i->actions[0]; i++)
- {
- for (tmp = i->actions; NULL != *tmp; tmp++)
- if (0 == strcmp (*tmp, action))
- break;
-
- if (NULL == *tmp)
- continue;
-
- /* if we're outside the allowable states for this action, return an error
- * immediately */
- if (priv->state < i->min_allowed_state ||
- priv->state > i->max_allowed_state)
- {
- g_set_error (error, GABBLE_XMPP_ERROR,
- XMPP_ERROR_JINGLE_OUT_OF_ORDER,
- "action \"%s\" not allowed in current state", action);
- goto ERROR;
- }
-
- funcs = i->stream_handlers;
- new_state = i->new_state;
-
- break;
- }
-
- /* pointer is not NULL if we found a matching action */
- if (NULL == funcs)
- {
- g_set_error (error, GABBLE_XMPP_ERROR,
- XMPP_ERROR_FEATURE_NOT_IMPLEMENTED, "action \"%s\" not implemented",
- action);
- goto ERROR;
- }
-
- /* call handlers if there are any (NULL-terminated array) */
- if (NULL != *funcs)
- {
- if (!_call_handlers_on_streams (session, message, session_node, funcs,
- error))
- {
- if (*error == NULL)
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "unknown error encountered with action \"%s\"",
- action);
-
- goto ERROR;
- }
- }
-
- /* acknowledge the IQ before changing the state because the new state
- * could perform some actions which the other end will only accept
- * if this action has been acknowledged */
- _gabble_connection_acknowledge_set_iq (priv->conn, message);
-
- /* if the action specified a new state to go to, set it */
- if (JS_STATE_INVALID != new_state)
- g_object_set (session, "state", new_state, NULL);
-
- return TRUE;
-
-ERROR:
- g_assert (error != NULL);
- GMS_DEBUG_ERROR (session, (*error)->message);
- return FALSE;
-}
-
-static gboolean
-timeout_session (gpointer data)
-{
- GabbleMediaSession *session = data;
-
- DEBUG ("session timed out");
-
- _gabble_media_session_terminate (session, INITIATOR_LOCAL,
- TP_CHANNEL_GROUP_CHANGE_REASON_ERROR);
-
- return FALSE;
-}
-
-static void do_content_add (GabbleMediaSession *, GabbleMediaStream *);
-
-void
-_add_ready_new_streams (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i;
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- GMS_DEBUG_DUMP (session, "pondering accept-time add for stream: %s, got "
- "local codecs: %s, initiator: %s, signalling state: %d",
- stream->name, stream->got_local_codecs ? "true" : "false",
- stream->initiator == INITIATOR_LOCAL ? "local" : "remote",
- stream->signalling_state);
-
- if (stream->got_local_codecs == FALSE)
- continue;
-
- if (stream->initiator == INITIATOR_REMOTE)
- continue;
-
- if (stream->signalling_state > STREAM_SIG_STATE_NEW)
- continue;
-
- do_content_add (session, stream);
- }
-}
-
-static void
-session_state_changed (GabbleMediaSession *session,
- JingleSessionState prev_state,
- JingleSessionState new_state)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- GMS_DEBUG_EVENT (session, "state changed from %s to %s",
- session_states[prev_state].name,
- session_states[new_state].name);
-
- /*
- * If the state goes from CREATED to INITIATED (which means the remote
- * end initiated), set the timer. If, OTOH, we're the end which just sent an
- * initiate, set the timer.
- */
- if ((prev_state == JS_STATE_PENDING_CREATED &&
- new_state == JS_STATE_PENDING_INITIATED) ||
- (new_state == JS_STATE_PENDING_INITIATE_SENT))
- {
- priv->timer_id =
- g_timeout_add (DEFAULT_SESSION_TIMEOUT, timeout_session, session);
- }
- else if (new_state == JS_STATE_ACTIVE)
- {
- g_source_remove (priv->timer_id);
- priv->timer_id = 0;
-
- /* signal any streams to the remote end which were added locally &
- * became ready before the session was accepted, so haven't been
- * mentioned yet */
- _add_ready_new_streams (session);
- }
-}
-
-static void
-_mark_local_streams_sent (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i;
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (stream->initiator == INITIATOR_REMOTE)
- continue;
-
- GMS_DEBUG_INFO (session, "marking local stream %s as signalled",
- stream->name);
-
- g_object_set (stream, "signalling-state", STREAM_SIG_STATE_SENT, NULL);
- }
-}
-
-static void
-_mark_local_streams_acked (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i;
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (stream->initiator == INITIATOR_REMOTE)
- continue;
-
- if (stream->signalling_state != STREAM_SIG_STATE_SENT)
- continue;
-
- GMS_DEBUG_INFO (session, "marking local stream %s as acknowledged",
- stream->name);
-
- g_object_set (stream,
- "signalling-state", STREAM_SIG_STATE_ACKNOWLEDGED,
- NULL);
- }
-}
-
-static void
-_set_remote_streams_playing (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i;
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (stream->initiator == INITIATOR_LOCAL)
- continue;
-
- GMS_DEBUG_INFO (session, "setting remote stream %s as playing",
- stream->name);
-
- g_object_set (stream, "playing", TRUE, NULL);
- }
-}
-
-static const gchar *_direction_to_senders (GabbleMediaSession *,
- TpMediaStreamDirection);
-
-static void
-_add_content_descriptions_one (GabbleMediaSession *session,
- GabbleMediaStream *stream,
- LmMessageNode *session_node)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- LmMessageNode *content_node;
-
- if (priv->mode == MODE_GOOGLE)
- {
- content_node = session_node;
- }
- else
- {
- TpMediaStreamDirection direction;
- TpMediaStreamPendingSend pending_send;
-
- content_node = _gabble_media_stream_add_content_node (stream,
- session_node);
-
- direction = COMBINED_DIRECTION_GET_DIRECTION (stream->combined_direction);
- pending_send = COMBINED_DIRECTION_GET_PENDING_SEND
- (stream->combined_direction);
-
- /* if we have a pending local send flag set, the signalled (ie understood
- * by both ends) direction of the stream is assuming that we are actually
- * sending, so we should OR that into the direction before deciding what
- * to signal the stream with. we don't need to consider pending remote
- * send because it doesn't happen in Jingle */
-
- if ((pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0)
- direction |= TP_MEDIA_STREAM_DIRECTION_SEND;
-
- if (direction != TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL)
- {
- const gchar *senders;
- senders = _direction_to_senders (session, direction);
- lm_message_node_set_attribute (content_node, "senders", senders);
- }
- }
-
- _gabble_media_stream_content_node_add_description (stream, content_node);
-
- _gabble_media_stream_content_node_add_transport (stream, content_node);
-}
-
-static void
-_add_content_descriptions (GabbleMediaSession *session,
- LmMessageNode *session_node,
- JingleInitiator stream_initiator)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i;
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (stream->initiator != stream_initiator)
- {
- GMS_DEBUG_INFO (session,
- "not adding content description for %s stream %s",
- stream->initiator == INITIATOR_LOCAL ? "local" : "remote",
- stream->name);
- continue;
- }
-
- _add_content_descriptions_one (session, stream, session_node);
- }
-}
-
-static LmHandlerResult
-accept_msg_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleMediaSession *session = GABBLE_MEDIA_SESSION (object);
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i;
-
- MSG_REPLY_CB_END_SESSION_IF_NOT_SUCCESSFUL (session, "accept failed");
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (stream->initiator == INITIATOR_LOCAL)
- continue;
-
- _gabble_media_stream_update_sending (stream, TRUE);
- }
-
- g_object_set (session, "state", JS_STATE_ACTIVE, NULL);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static gboolean
-_stream_not_ready_for_accept (GabbleMediaSession *session,
- GabbleMediaStream *stream)
-{
- /* locally initiated streams shouldn't delay acceptance */
- if (stream->initiator == INITIATOR_LOCAL)
- return FALSE;
-
- if (!stream->got_local_codecs)
- {
- GMS_DEBUG_INFO (session, "stream %s does not yet have local codecs",
- stream->name);
-
- return TRUE;
- }
-
- if (stream->connection_state != TP_MEDIA_STREAM_STATE_CONNECTED)
- {
- GMS_DEBUG_INFO (session, "stream %s is not yet connected", stream->name);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-try_session_accept (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- LmMessage *msg;
- LmMessageNode *session_node;
- const gchar *action;
- guint i;
-
- if (priv->state < JS_STATE_ACTIVE && !priv->locally_accepted)
- {
- GMS_DEBUG_INFO (session, "not sending accept yet, waiting for local "
- "user to accept call");
- return;
- }
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (_stream_not_ready_for_accept (session, stream))
- {
- GMS_DEBUG_INFO (session, "not sending accept yet, found a stream "
- "which was not yet connected or was missing local codecs");
- return;
- }
- }
-
- if (priv->mode == MODE_GOOGLE)
- action = "accept";
- else
- action = "session-accept";
-
- /* construct a session acceptance message */
- msg = _gabble_media_session_message_new (session, action, &session_node);
-
- /* only accept REMOTE streams; any LOCAL streams were added by the local
- * user before accepting and should be signalled after the accept */
- _add_content_descriptions (session, session_node, INITIATOR_REMOTE);
-
- GMS_DEBUG_INFO (session, "sending jingle session action \"%s\" to peer",
- action);
-
- /* send the final acceptance message */
- _gabble_connection_send_with_reply (priv->conn, msg, accept_msg_reply_cb,
- G_OBJECT (session), NULL, NULL);
-
- lm_message_unref (msg);
-
- /* set remote streams playing */
- _set_remote_streams_playing (session);
-
- g_object_set (session, "state", JS_STATE_PENDING_ACCEPT_SENT, NULL);
-}
-
-static LmHandlerResult
-content_accept_msg_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleMediaSession *session = GABBLE_MEDIA_SESSION (user_data);
- GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object);
-
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- GMS_DEBUG_ERROR (session, "content-accept failed; removing stream");
- NODE_DEBUG (sent_msg->node, "message sent");
- NODE_DEBUG (reply_msg->node, "message reply");
-
- _gabble_media_session_remove_streams (session, &stream, 1);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- _gabble_media_stream_update_sending (stream, TRUE);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-try_content_accept (GabbleMediaSession *session,
- GabbleMediaStream *stream)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- LmMessage *msg;
- LmMessageNode *session_node;
-
- g_assert (priv->state == JS_STATE_ACTIVE);
- g_assert (priv->mode == MODE_JINGLE);
-
- if (_stream_not_ready_for_accept (session, stream))
- {
- GMS_DEBUG_INFO (session, "not sending content-accept yet, stream %s "
- "is disconnected or missing local codecs", stream->name);
- return;
- }
-
- /* send a content acceptance message */
- msg = _gabble_media_session_message_new (session, "content-accept",
- &session_node);
-
- _add_content_descriptions_one (session, stream, session_node);
-
- GMS_DEBUG_INFO (session, "sending jingle session action \"content-accept\" "
- "to peer for stream %s", stream->name);
-
- _gabble_connection_send_with_reply (priv->conn, msg,
- content_accept_msg_reply_cb, G_OBJECT (stream), session, NULL);
-
- lm_message_unref (msg);
-
- /* set stream playing */
- g_object_set (stream, "playing", TRUE, NULL);
-}
-
-static LmHandlerResult
-initiate_msg_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleMediaSession *session = GABBLE_MEDIA_SESSION (object);
-
- MSG_REPLY_CB_END_SESSION_IF_NOT_SUCCESSFUL (session, "initiate failed");
-
- g_object_set (session, "state", JS_STATE_PENDING_INITIATED, NULL);
-
- /* mark all of the streams that we sent in the initiate as acknowledged */
- _mark_local_streams_acked (session);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static gboolean
-_stream_not_ready_for_initiate (GabbleMediaSession *session,
- GabbleMediaStream *stream)
-{
- if (!stream->got_local_codecs)
- {
- GMS_DEBUG_INFO (session, "stream %s does not yet have local codecs",
- stream->name);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-try_session_initiate (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- LmMessage *msg;
- LmMessageNode *session_node;
- const gchar *action;
- guint i;
-
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (_stream_not_ready_for_initiate (session, stream))
- {
- GMS_DEBUG_INFO (session, "not sending initiate yet, found a stream "
- "which was missing local codecs");
- return;
- }
- }
-
- if (priv->mode == MODE_GOOGLE)
- action = "initiate";
- else
- action = "session-initiate";
-
- msg = _gabble_media_session_message_new (session, action, &session_node);
-
- _add_content_descriptions (session, session_node, INITIATOR_LOCAL);
-
- GMS_DEBUG_INFO (session, "sending jingle action \"%s\" to peer", action);
-
- _gabble_connection_send_with_reply (priv->conn, msg, initiate_msg_reply_cb,
- G_OBJECT (session), NULL, NULL);
-
- lm_message_unref (msg);
-
- /* mark local streams as sent (so that eg candidates will be sent) */
- _mark_local_streams_sent (session);
-
- g_object_set (session, "state", JS_STATE_PENDING_INITIATE_SENT, NULL);
-}
-
-static LmHandlerResult
-content_add_msg_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleMediaSession *session = GABBLE_MEDIA_SESSION (user_data);
- GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object);
-
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- if (session->initiator == INITIATOR_REMOTE &&
- stream->signalling_state == STREAM_SIG_STATE_ACKNOWLEDGED)
- {
- GMS_DEBUG_INFO (session, "ignoring content-add failure, stream has "
- "been successfully created by the session initiator");
- }
- else
- {
- GMS_DEBUG_ERROR (session, "content-add failed; removing stream");
- NODE_DEBUG (sent_msg->node, "message sent");
- NODE_DEBUG (reply_msg->node, "message reply");
-
- _gabble_media_stream_close (stream);
- }
- }
- else
- {
- if (stream->signalling_state == STREAM_SIG_STATE_SENT)
- {
- GMS_DEBUG_INFO (session, "content-add succeeded, marking stream as "
- "ACKNOWLEDGED");
-
- g_object_set (stream,
- "signalling-state", STREAM_SIG_STATE_ACKNOWLEDGED,
- NULL);
- }
- else
- {
- GMS_DEBUG_INFO (session, "content-add succeeded, but not marking"
- "stream as ACKNOWLEDGED, it's in state %d",
- stream->signalling_state);
- }
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-do_content_add (GabbleMediaSession *session,
- GabbleMediaStream *stream)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- LmMessage *msg;
- LmMessageNode *session_node;
-
- g_assert (priv->state == JS_STATE_ACTIVE);
- g_assert (priv->mode == MODE_JINGLE);
-
- if (_stream_not_ready_for_initiate (session, stream))
- {
- GMS_DEBUG_ERROR (session, "trying to send content-add for stream %s "
- "but we have no local codecs. what?!", stream->name);
- g_assert_not_reached ();
- return;
- }
-
- msg = _gabble_media_session_message_new (session, "content-add",
- &session_node);
-
- _add_content_descriptions_one (session, stream, session_node);
-
- GMS_DEBUG_INFO (session, "sending jingle action \"content-add\" to peer for "
- "stream %s", stream->name);
-
- _gabble_connection_send_with_reply (priv->conn, msg,
- content_add_msg_reply_cb, G_OBJECT (stream), session, NULL);
-
- lm_message_unref (msg);
-
- /* mark stream as sent */
- g_object_set (stream, "signalling-state", STREAM_SIG_STATE_SENT, NULL);
-}
-
-static void
-stream_connection_state_changed_cb (GabbleMediaStream *stream,
- GParamSpec *param,
- GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- if (stream->connection_state != TP_MEDIA_STREAM_STATE_CONNECTED)
- return;
-
- GMS_DEBUG_INFO (session, "stream %s has gone connected", stream->name);
-
- if (stream->playing)
- {
- GMS_DEBUG_INFO (session, "doing nothing, stream is already playing");
- return;
- }
-
- /* after session is active, we do things per-stream with content-* actions */
- if (priv->state < JS_STATE_ACTIVE)
- {
- /* send a session accept if the session was initiated by the peer */
- if (session->initiator == INITIATOR_REMOTE)
- {
- try_session_accept (session);
- }
- else
- {
- GMS_DEBUG_INFO (session, "session initiated by us, so we're not "
- "going to consider sending an accept");
- }
- }
- else
- {
- /* send a content accept if the stream was added by the peer */
- if (stream->initiator == INITIATOR_REMOTE)
- {
- try_content_accept (session, stream);
- }
- else
- {
- GMS_DEBUG_INFO (session, "stream added by us, so we're not going "
- "to send an accept");
- }
- }
-}
-
-static void
-stream_got_local_codecs_changed_cb (GabbleMediaStream *stream,
- GParamSpec *param,
- GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- if (!stream->got_local_codecs)
- return;
-
- GMS_DEBUG_INFO (session, "stream %s has got local codecs", stream->name);
-
- if (stream->playing)
- {
- GMS_DEBUG_ERROR (session, "stream was already playing and we got local "
- "codecs. what?!");
- g_assert_not_reached ();
- return;
- }
-
- /* after session is active, we do things per-stream with content-* actions */
- if (priv->state < JS_STATE_ACTIVE)
- {
- if (session->initiator == INITIATOR_REMOTE)
- {
- if (priv->state < JS_STATE_PENDING_ACCEPT_SENT)
- {
- try_session_accept (session);
- }
- else
- {
- GMS_DEBUG_INFO (session, "stream added after sending accept; "
- "not doing content-add until remote end acknowledges");
- }
- }
- else
- {
- if (priv->state < JS_STATE_PENDING_INITIATE_SENT)
- {
- try_session_initiate (session);
- }
- else
- {
- GMS_DEBUG_INFO (session, "stream added after sending initiate; "
- "not doing content-add until remote end accepts");
- }
- }
- }
- else
- {
- if (stream->initiator == INITIATOR_REMOTE)
- {
- try_content_accept (session, stream);
- }
- else
- {
- do_content_add (session, stream);
- }
- }
-}
-
-static gchar *
-get_jid_for_contact (GabbleMediaSession *session,
- TpHandle handle)
-{
- GabbleMediaSessionPrivate *priv;
- TpBaseConnection *conn;
- const gchar *base_jid;
- TpHandle self;
- TpHandleRepoIface *contact_handles;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- conn = (TpBaseConnection *)priv->conn;
- contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
- self = conn->self_handle;
-
- base_jid = tp_handle_inspect (contact_handles, handle);
- g_assert (base_jid != NULL);
-
- if (handle == self)
- {
- gchar *resource, *ret;
- g_object_get (priv->conn, "resource", &resource, NULL);
- g_assert (resource != NULL);
- ret = g_strdup_printf ("%s/%s", base_jid, resource);
- g_free (resource);
- return ret;
- }
- else
- {
- g_assert (priv->peer_resource != NULL);
- return g_strdup_printf ("%s/%s", base_jid, priv->peer_resource);
- }
-}
-
-LmMessage *
-_gabble_media_session_message_new (GabbleMediaSession *session,
- const gchar *action,
- LmMessageNode **session_node)
-{
- GabbleMediaSessionPrivate *priv;
- TpBaseConnection *conn;
- LmMessage *msg;
- LmMessageNode *iq_node, *node;
- gchar *peer_jid, *initiator_jid;
- TpHandle initiator_handle;
- const gchar *element, *xmlns;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- conn = (TpBaseConnection *)priv->conn;
-
- peer_jid = get_jid_for_contact (session, priv->peer);
-
- msg = lm_message_new_with_sub_type (
- peer_jid,
- LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_SET);
-
- g_free (peer_jid);
-
- iq_node = lm_message_get_node (msg);
-
- if (priv->mode == MODE_GOOGLE)
- element = "session";
- else
- element = "jingle";
-
- if (session->initiator == INITIATOR_LOCAL)
- initiator_handle = conn->self_handle;
- else
- initiator_handle = priv->peer;
-
- node = lm_message_node_add_child (iq_node, element, NULL);
- initiator_jid = get_jid_for_contact (session, initiator_handle);
-
- lm_message_node_set_attributes (node,
- (priv->mode == MODE_GOOGLE) ? "id" : "sid", priv->id,
- (priv->mode == MODE_GOOGLE) ? "type" : "action", action,
- "initiator", initiator_jid,
- NULL);
-
- if (priv->mode == MODE_GOOGLE)
- xmlns = NS_GOOGLE_SESSION;
- else
- xmlns = NS_JINGLE;
-
- lm_message_node_set_attribute (node, "xmlns", xmlns);
- g_free (initiator_jid);
-
- if (session_node)
- *session_node = node;
-
- return msg;
-}
-
-void
-_gabble_media_session_accept (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- guint i;
-
- priv->locally_accepted = TRUE;
-
- /* accept any local pending sends */
- for (i = 0; i < priv->streams->len; i++)
- {
- GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
- CombinedStreamDirection combined_dir = stream->combined_direction;
- TpMediaStreamDirection current_dir;
- TpMediaStreamPendingSend pending_send;
-
- current_dir = COMBINED_DIRECTION_GET_DIRECTION (combined_dir);
- pending_send = COMBINED_DIRECTION_GET_PENDING_SEND (combined_dir);
-
- if ((pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0)
- {
- GMS_DEBUG_INFO (session, "accepting pending local send on stream %s",
- stream->name);
-
- current_dir |= TP_MEDIA_STREAM_DIRECTION_SEND;
- pending_send &= ~TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
- combined_dir = MAKE_COMBINED_DIRECTION (current_dir, pending_send);
- g_object_set (stream, "combined-direction", combined_dir, NULL);
- _gabble_media_stream_update_sending (stream, FALSE);
- }
- }
-
- try_session_accept (session);
-}
-
-static LmHandlerResult
-content_remove_msg_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleMediaSession *session = GABBLE_MEDIA_SESSION (object);
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- GPtrArray *removing = (GPtrArray *) user_data;
- guint i;
-
- MSG_REPLY_CB_END_SESSION_IF_NOT_SUCCESSFUL (session,
- "stream removal failed");
-
- for (i = 0; i < removing->len; i++)
- destroy_media_stream (session,
- GABBLE_MEDIA_STREAM (g_ptr_array_index (removing, i)));
-
- g_ptr_array_remove_fast (priv->remove_requests, removing);
- g_ptr_array_free (removing, TRUE);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-void
-_gabble_media_session_remove_streams (GabbleMediaSession *session,
- GabbleMediaStream **streams,
- guint len)
-{
- GabbleMediaSessionPrivate *priv;
- LmMessage *msg = NULL;
- LmMessageNode *session_node;
- GPtrArray *removing = NULL;
- guint i;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- /* end the session if there'd be no streams left after reducing it */
- if (_count_non_removing_streams (session) == len)
- {
- _gabble_media_session_terminate (session, INITIATOR_LOCAL,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- return;
- }
-
- /* construct a remove message if we're in a state greater than CREATED (ie
- * something has been sent/received about this session) */
- if (priv->state > JS_STATE_PENDING_CREATED)
- {
- msg = _gabble_media_session_message_new (session, "content-remove",
- &session_node);
- removing = g_ptr_array_sized_new (len);
- }
-
- /* right, remove them */
- for (i = 0; i < len; i++)
- {
- GabbleMediaStream *stream = streams[i];
-
- switch (stream->signalling_state)
- {
- case STREAM_SIG_STATE_NEW:
- destroy_media_stream (session, stream);
- break;
- case STREAM_SIG_STATE_SENT:
- case STREAM_SIG_STATE_ACKNOWLEDGED:
- {
- LmMessageNode *content_node;
-
- g_assert (msg != NULL);
- g_assert (removing != NULL);
-
- content_node = _gabble_media_stream_add_content_node (stream,
- session_node);
-
- g_object_set (stream,
- "playing", FALSE,
- "signalling-state", STREAM_SIG_STATE_REMOVING,
- NULL);
-
- /* close the stream now, but don't forget about it until the
- * removal message is acknowledged, since we need to be able to
- * detect content-remove cross-talk */
- _gabble_media_stream_close (stream);
- g_ptr_array_add (removing, stream);
- }
- break;
- case STREAM_SIG_STATE_REMOVING:
- break;
- }
- }
-
- /* send the remove message if necessary */
- if (msg != NULL)
- {
- if (removing->len > 0)
- {
- GMS_DEBUG_INFO (session, "sending jingle session action "
- "\"content-remove\" to peer");
-
- _gabble_connection_send_with_reply (priv->conn, msg,
- content_remove_msg_reply_cb, G_OBJECT (session), removing, NULL);
-
- g_ptr_array_add (priv->remove_requests, removing);
- }
- else
- {
- g_ptr_array_free (removing, TRUE);
- }
-
- lm_message_unref (msg);
- }
- else
- {
- GMS_DEBUG_INFO (session, "not sending jingle session action "
- "\"content-remove\" to peer, no initiates or adds sent for "
- "these streams");
- }
-}
-
-/* for when you want the reply to be removed from
- * the handler chain, but don't care what it is */
-static LmHandlerResult
-ignore_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-send_reject_message (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- LmMessage *msg;
- LmMessageNode *session_node;
-
- /* this should only happen in google mode, and we should only arrive in that
- * mode when we've ended up talking to a resource that doesn't support
- * jingle */
- g_assert (priv->mode == MODE_GOOGLE);
- g_assert (priv->peer_resource != NULL);
-
- /* construct a session terminate message */
- msg = _gabble_media_session_message_new (session, "reject", &session_node);
-
- GMS_DEBUG_INFO (session, "sending jingle session action \"reject\" to peer");
-
- /* send it */
- _gabble_connection_send_with_reply (priv->conn, msg, ignore_reply_cb,
- G_OBJECT (session), NULL, NULL);
-
- lm_message_unref (msg);
-}
-
-static void
-send_terminate_message (GabbleMediaSession *session)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- const gchar *action;
- LmMessage *msg;
- LmMessageNode *session_node;
-
- /* construct a session terminate message */
- if (priv->mode == MODE_GOOGLE)
- action = "terminate";
- else
- action = "session-terminate";
-
- msg = _gabble_media_session_message_new (session, action, &session_node);
-
- GMS_DEBUG_INFO (session, "sending jingle session action \"%s\" to peer",
- action);
-
- /* send it */
- _gabble_connection_send_with_reply (priv->conn, msg, ignore_reply_cb,
- G_OBJECT (session), NULL, NULL);
-
- lm_message_unref (msg);
-}
-
-void
-_gabble_media_session_terminate (GabbleMediaSession *session,
- JingleInitiator who,
- TpChannelGroupChangeReason why)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandle actor;
-
- if (priv->state == JS_STATE_ENDED)
- return;
-
- if (who == INITIATOR_REMOTE)
- {
- actor = priv->peer;
- }
- else
- {
- actor = conn->self_handle;
-
- /* Need to tell them that it's all over. */
-
- /* Jingle doesn't have a "reject" action; a termination before an
- * acceptance indicates that the call has been declined */
-
- if (session->initiator == INITIATOR_REMOTE &&
- priv->state == JS_STATE_PENDING_INITIATED &&
- priv->mode == MODE_GOOGLE)
- {
- send_reject_message (session);
- }
-
- /* if we're still in CREATED, then we've not sent or received any
- * messages about this session yet, so no terminate is necessary */
- else if (priv->state > JS_STATE_PENDING_CREATED)
- {
- send_terminate_message (session);
- }
-
- while (priv->streams->len > 0)
- destroy_media_stream (session, g_ptr_array_index (priv->streams, 0));
- }
-
- priv->terminated = TRUE;
- g_object_set (session, "state", JS_STATE_ENDED, NULL);
- g_signal_emit (session, signals[TERMINATED], 0, actor, why);
-}
-
-#if _GMS_DEBUG_LEVEL
-void
-_gabble_media_session_debug (GabbleMediaSession *session,
- DebugMessageType type,
- const gchar *format, ...)
-{
- if (DEBUGGING)
- {
- va_list list;
- gchar buf[512];
- GabbleMediaSessionPrivate *priv;
- time_t curtime;
- struct tm *loctime;
- gchar stamp[10];
- const gchar *type_str;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- curtime = time (NULL);
- loctime = localtime (&curtime);
-
- strftime (stamp, sizeof (stamp), "%T", loctime);
-
- va_start (list, format);
-
- vsnprintf (buf, sizeof (buf), format, list);
-
- va_end (list);
-
- switch (type) {
- case DEBUG_MSG_INFO:
- type_str = TP_ANSI_BOLD_ON TP_ANSI_FG_WHITE;
- break;
- case DEBUG_MSG_DUMP:
- type_str = TP_ANSI_BOLD_ON TP_ANSI_FG_GREEN;
- break;
- case DEBUG_MSG_WARNING:
- type_str = TP_ANSI_BOLD_ON TP_ANSI_FG_YELLOW;
- break;
- case DEBUG_MSG_ERROR:
- type_str = TP_ANSI_BOLD_ON TP_ANSI_FG_WHITE TP_ANSI_BG_RED;
- break;
- case DEBUG_MSG_EVENT:
- type_str = TP_ANSI_BOLD_ON TP_ANSI_FG_CYAN;
- break;
- default:
- g_assert_not_reached ();
- return;
- }
-
- printf ("[%s%s%s] %s%-26s%s %s%s%s\n",
- TP_ANSI_BOLD_ON TP_ANSI_FG_WHITE,
- stamp,
- TP_ANSI_RESET,
- session_states[priv->state].attributes,
- session_states[priv->state].name,
- TP_ANSI_RESET,
- type_str,
- buf,
- TP_ANSI_RESET);
-
- fflush (stdout);
- }
-}
-
-#endif /* _GMS_DEBUG_LEVEL */
-
-static const gchar *
-_name_stream (GabbleMediaSession *session,
- TpMediaStreamType media_type)
-{
- GabbleMediaSessionPrivate *priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- static gchar ret[MAX_STREAM_NAME_LEN] = GTALK_STREAM_NAME;
-
- if (priv->mode != MODE_GOOGLE)
- {
- guint i = 1;
-
- do {
- g_snprintf (ret, MAX_STREAM_NAME_LEN, "%s%u",
- media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video",
- i++);
-
- /* even though we now have seperate namespaces for local and remote,
- * actually check in both so that we can still support clients which
- * have 1 namespace (such as our older selves :D) */
- if (_lookup_stream_by_name_and_initiator (session, ret,
- INITIATOR_INVALID) != NULL)
- {
- ret[0] = '\0';
- }
- } while (ret[0] == '\0');
- }
-
- return ret;
-}
-
-
-gboolean
-_gabble_media_session_request_streams (GabbleMediaSession *session,
- const GArray *media_types,
- GPtrArray **ret,
- GError **error)
-{
- static GabblePresenceCapabilities google_audio_caps =
- PRESENCE_CAP_GOOGLE_VOICE;
- static GabblePresenceCapabilities jingle_audio_caps =
- PRESENCE_CAP_JINGLE | PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO |
- PRESENCE_CAP_GOOGLE_TRANSPORT_P2P;
- static GabblePresenceCapabilities jingle_video_caps =
- PRESENCE_CAP_JINGLE | PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO |
- PRESENCE_CAP_GOOGLE_TRANSPORT_P2P;
-
- GabbleMediaSessionPrivate *priv;
- GabblePresence *presence;
- gboolean want_audio, want_video;
- GabblePresenceCapabilities jingle_desired_caps;
- guint idx;
- gchar *dump;
-
- g_assert (GABBLE_IS_MEDIA_SESSION (session));
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- presence = gabble_presence_cache_get (priv->conn->presence_cache,
- priv->peer);
-
- if (presence == NULL)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "member has no audio/video capabilities");
-
- return FALSE;
- }
-
- dump = gabble_presence_dump (presence);
- GMS_DEBUG_DUMP (session, "presence for peer %d:\n%s", priv->peer, dump);
- g_free (dump);
-
- want_audio = want_video = FALSE;
-
- for (idx = 0; idx < media_types->len; idx++)
- {
- guint media_type = g_array_index (media_types, guint, idx);
-
- if (media_type == TP_MEDIA_STREAM_TYPE_AUDIO)
- {
- want_audio = TRUE;
- }
- else if (media_type == TP_MEDIA_STREAM_TYPE_VIDEO)
- {
- want_video = TRUE;
- }
- else
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "given media type %u is invalid", media_type);
- return FALSE;
- }
- }
-
- /* work out what we'd need to do these streams with jingle */
- jingle_desired_caps = 0;
-
- if (want_audio)
- jingle_desired_caps |= jingle_audio_caps;
-
- if (want_video)
- jingle_desired_caps |= jingle_video_caps;
-
- GMS_DEBUG_INFO (session, "want audio: %s; want video: %s",
- want_audio ? "yes" : "no", want_video ? "yes" : "no");
-
- /* existing call; the recipient and the mode has already been decided */
- if (priv->peer_resource)
- {
- /* is a google call... we have no other option */
- if (priv->mode == MODE_GOOGLE)
- {
- GMS_DEBUG_INFO (session, "already in Google mode; can't add new "
- "stream");
-
- g_assert (priv->streams->len == 1);
-
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Google Talk calls may only contain one stream");
-
- return FALSE;
- }
-
- if (!gabble_presence_resource_has_caps (presence, priv->peer_resource,
- jingle_desired_caps))
- {
- GMS_DEBUG_INFO (session,
- "in Jingle mode but have insufficient caps for requested streams");
-
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "existing call member doesn't support all requested media"
- " types");
-
- return FALSE;
- }
-
- GMS_DEBUG_INFO (session,
- "in Jingle mode, and have necessary caps");
- }
-
- /* no existing call; we should choose a recipient and a mode */
- else
- {
- const gchar *resource;
-
- g_assert (priv->streams->len == 0);
-
- /* see if we have a fully-capable jingle resource; regardless of the
- * desired media type it's best if we can add/remove the others later */
- resource = gabble_presence_pick_resource_by_caps (presence,
- jingle_audio_caps | jingle_video_caps);
-
- if (resource == NULL)
- {
- GMS_DEBUG_INFO (session, "contact is not fully jingle-capable");
-
- /* ok, no problem. see if we can do just what's wanted with jingle */
- resource = gabble_presence_pick_resource_by_caps (presence,
- jingle_desired_caps);
-
- if (resource == NULL && want_audio && !want_video)
- {
- GMS_DEBUG_INFO (session,
- "contact doesn't have desired Jingle capabilities");
-
- /* last ditch... if we want only audio and not video, we can make
- * do with google talk */
- resource = gabble_presence_pick_resource_by_caps (presence,
- google_audio_caps);
-
- if (resource != NULL)
- {
- /* only one stream possible with google */
- if (media_types->len == 1)
- {
- GMS_DEBUG_INFO (session,
- "contact has no Jingle capabilities; "
- "falling back to Google audio call");
- priv->mode = MODE_GOOGLE;
- }
- else
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Google Talk calls may only contain one stream");
-
- return FALSE;
- }
- }
- else
- {
- GMS_DEBUG_INFO (session,
- "contact doesn't have desired Google capabilities");
- }
- }
- }
-
- if (resource == NULL)
- {
- GMS_DEBUG_INFO (session,
- "contact doesn't have a resource with suitable capabilities");
-
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "member does not have the desired audio/video capabilities");
-
- return FALSE;
- }
-
- priv->peer_resource = g_strdup (resource);
- }
-
- /* check it's not a ridiculous number of streams */
- if ((priv->streams->len + media_types->len) > MAX_STREAMS)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "I think that's quite enough streams already");
- return FALSE;
- }
-
- /* if we've got here, we're good to make the streams */
-
- *ret = g_ptr_array_sized_new (media_types->len);
-
- for (idx = 0; idx < media_types->len; idx++)
- {
- guint media_type = g_array_index (media_types, guint, idx);
- GabbleMediaStream *stream;
- const gchar *stream_name;
-
- if (priv->mode == MODE_GOOGLE)
- stream_name = GTALK_STREAM_NAME;
- else
- stream_name = _name_stream (session, media_type);
-
- stream = create_media_stream (session, stream_name, INITIATOR_LOCAL,
- media_type);
-
- g_ptr_array_add (*ret, stream);
- }
-
- return TRUE;
-}
-
-static const gchar *
-_direction_to_senders (GabbleMediaSession *session,
- TpMediaStreamDirection dir)
-{
- const gchar *ret = NULL;
-
- switch (dir)
- {
- case TP_MEDIA_STREAM_DIRECTION_NONE:
- g_assert_not_reached ();
- break;
- case TP_MEDIA_STREAM_DIRECTION_SEND:
- if (session->initiator == INITIATOR_LOCAL)
- ret = "initiator";
- else
- ret = "responder";
- break;
- case TP_MEDIA_STREAM_DIRECTION_RECEIVE:
- if (session->initiator == INITIATOR_REMOTE)
- ret = "initiator";
- else
- ret = "responder";
- break;
- case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL:
- ret = "both";
- break;
- }
-
- g_assert (ret != NULL);
-
- return ret;
-}
-
-static LmHandlerResult
-direction_msg_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleMediaSession *session = GABBLE_MEDIA_SESSION (user_data);
- GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object);
-
- MSG_REPLY_CB_END_SESSION_IF_NOT_SUCCESSFUL (session,
- "direction change failed");
-
- if (stream->playing)
- {
- _gabble_media_stream_update_sending (stream, TRUE);
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static gboolean
-send_direction_change (GabbleMediaSession *session,
- GabbleMediaStream *stream,
- TpMediaStreamDirection dir,
- GError **error)
-{
- GabbleMediaSessionPrivate *priv;
- const gchar *senders;
- LmMessage *msg;
- LmMessageNode *session_node, *content_node;
- gboolean ret;
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
- senders = _direction_to_senders (session, dir);
-
- if (stream->signalling_state == STREAM_SIG_STATE_NEW ||
- stream->signalling_state == STREAM_SIG_STATE_REMOVING)
- {
- GMS_DEBUG_INFO (session, "not sending content-modify for %s stream %s",
- stream->signalling_state == STREAM_SIG_STATE_NEW ? "new" : "removing",
- stream->name);
- return TRUE;
- }
-
- GMS_DEBUG_INFO (session, "sending jingle session action \"content-modify\" "
- "to peer for stream %s (senders=%s)", stream->name, senders);
-
- msg = _gabble_media_session_message_new (session, "content-modify",
- &session_node);
- content_node = _gabble_media_stream_add_content_node (stream, session_node);
-
- lm_message_node_set_attribute (content_node, "senders", senders);
-
- ret = _gabble_connection_send_with_reply (priv->conn, msg,
- direction_msg_reply_cb, G_OBJECT (stream), session, error);
-
- lm_message_unref (msg);
-
- return ret;
-}
-
-gboolean
-_gabble_media_session_request_stream_direction (GabbleMediaSession *session,
- GabbleMediaStream *stream,
- TpMediaStreamDirection requested_dir,
- GError **error)
-{
- GabbleMediaSessionPrivate *priv;
- CombinedStreamDirection new_combined_dir;
- TpMediaStreamDirection current_dir; //, new_dir;
- TpMediaStreamPendingSend pending_send;
-
- priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);
-
- current_dir = COMBINED_DIRECTION_GET_DIRECTION (stream->combined_direction);
- pending_send = COMBINED_DIRECTION_GET_PENDING_SEND
- (stream->combined_direction);
-
- if (priv->mode == MODE_GOOGLE)
- {
- g_assert (current_dir == TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);
-
- if (requested_dir == TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL)
- return TRUE;
-
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Google Talk calls can only be bi-directional");
- return FALSE;
- }
-
- if (requested_dir == TP_MEDIA_STREAM_DIRECTION_NONE)
- {
- GMS_DEBUG_INFO (session, "request for NONE direction; removing stream");
-
- _gabble_media_session_remove_streams (session, &stream, 1);
-
- return TRUE;
- }
-
- /* if we're awaiting a local decision on sending... */
- if ((pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0)
- {
- /* clear the flag */
- pending_send &= ~TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
-
- /* make our current_dir match what other end thinks (he thinks we're
- * bidirectional) so that we send the correct transitions */
- current_dir ^= TP_MEDIA_STREAM_DIRECTION_SEND;
- }
-
-#if 0
- /* if we're asking the remote end to start sending, set the pending flag and
- * don't change our directionality just yet */
- new_dir = requested_dir;
- if (((current_dir & TP_MEDIA_STREAM_DIRECTION_RECEIVE) == 0) &&
- ((new_dir & TP_MEDIA_STREAM_DIRECTION_RECEIVE) != 0))
- {
- pending_send ^= TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
- new_dir &= ~TP_MEDIA_STREAM_DIRECTION_RECEIVE;
- }
-#endif
-
- /* make any necessary changes */
- new_combined_dir = MAKE_COMBINED_DIRECTION (requested_dir, pending_send);
- if (new_combined_dir != stream->combined_direction)
- {
- g_object_set (stream, "combined-direction", new_combined_dir, NULL);
- _gabble_media_stream_update_sending (stream, FALSE);
- }
-
- /* short-circuit sending a request if we're not asking for anything new */
- if (current_dir == requested_dir)
- return TRUE;
-
- /* send request */
- return send_direction_change (session, stream, requested_dir, error);
-}
-
-static void
-session_handler_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcMediaSessionHandlerClass *klass =
- (TpSvcMediaSessionHandlerClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_media_session_handler_implement_##x (\
- klass, gabble_media_session_##x)
- IMPLEMENT(error);
- IMPLEMENT(ready);
-#undef IMPLEMENT
-}
diff --git a/src/gabble-media-session.h b/src/gabble-media-session.h
deleted file mode 100644
index ee80b0a96..000000000
--- a/src/gabble-media-session.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * gabble-media-session.h - Header for GabbleMediaSession
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_MEDIA_SESSION_H__
-#define __GABBLE_MEDIA_SESSION_H__
-
-#include <glib-object.h>
-#include <loudmouth/loudmouth.h>
-
-#include "gabble-types.h"
-#include "gabble-media-stream.h"
-#include <telepathy-glib/enums.h>
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- MODE_GOOGLE,
- MODE_JINGLE
-} GabbleMediaSessionMode;
-
-typedef enum {
- JS_STATE_INVALID = -1,
- JS_STATE_PENDING_CREATED = 0,
- JS_STATE_PENDING_INITIATE_SENT,
- JS_STATE_PENDING_INITIATED,
- JS_STATE_PENDING_ACCEPT_SENT,
- JS_STATE_ACTIVE,
- JS_STATE_ENDED
-} JingleSessionState;
-
-typedef enum {
- DEBUG_MSG_INFO = 0,
- DEBUG_MSG_DUMP,
- DEBUG_MSG_WARNING,
- DEBUG_MSG_ERROR,
- DEBUG_MSG_EVENT
-} DebugMessageType;
-
-typedef struct _GabbleMediaSession GabbleMediaSession;
-typedef struct _GabbleMediaSessionClass GabbleMediaSessionClass;
-
-struct _GabbleMediaSessionClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleMediaSession {
- GObject parent;
-
- JingleInitiator initiator;
-
- gpointer priv;
-};
-
-GType gabble_media_session_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_MEDIA_SESSION \
- (gabble_media_session_get_type ())
-#define GABBLE_MEDIA_SESSION(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MEDIA_SESSION, \
- GabbleMediaSession))
-#define GABBLE_MEDIA_SESSION_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MEDIA_SESSION, \
- GabbleMediaSessionClass))
-#define GABBLE_IS_MEDIA_SESSION(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MEDIA_SESSION))
-#define GABBLE_IS_MEDIA_SESSION_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MEDIA_SESSION))
-#define GABBLE_MEDIA_SESSION_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MEDIA_SESSION, \
- GabbleMediaSessionClass))
-
-/* CONVENIENCE MACROS */
-#define MSG_REPLY_CB_END_SESSION_IF_NOT_SUCCESSFUL(s, m) \
- G_STMT_START { \
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT) \
- { \
- GMS_DEBUG_ERROR (s, m); \
- NODE_DEBUG (sent_msg->node, "message sent"); \
- NODE_DEBUG (reply_msg->node, "message reply"); \
- _gabble_media_session_terminate (s, INITIATOR_LOCAL, \
- TP_CHANNEL_GROUP_CHANGE_REASON_ERROR); \
- return LM_HANDLER_RESULT_REMOVE_MESSAGE; \
- } \
- } G_STMT_END
-
-gboolean
-_gabble_media_session_handle_action (GabbleMediaSession *session,
- LmMessage *message,
- LmMessageNode *session_node,
- const gchar *action,
- GError **error);
-
-LmMessage *_gabble_media_session_message_new (GabbleMediaSession *session,
- const gchar *action,
- LmMessageNode **session_node);
-
-void _gabble_media_session_accept (GabbleMediaSession *session);
-void _gabble_media_session_remove_streams (GabbleMediaSession *session,
- GabbleMediaStream **streams, guint len);
-void _gabble_media_session_terminate (GabbleMediaSession *session,
- JingleInitiator who, TpChannelGroupChangeReason why);
-
-gboolean _gabble_media_session_request_streams (GabbleMediaSession *session,
- const GArray *types,
- GPtrArray **ret,
- GError **error);
-
-gboolean _gabble_media_session_request_stream_direction (GabbleMediaSession *,
- GabbleMediaStream *, TpMediaStreamDirection, GError **);
-
-#ifndef _GMS_DEBUG_LEVEL
-#define _GMS_DEBUG_LEVEL 2
-#endif
-
-#if _GMS_DEBUG_LEVEL
-#ifdef ENABLE_DEBUG
-
-#define GMS_DEBUG_INFO(s, ...) \
- _gabble_media_session_debug (s, DEBUG_MSG_INFO, __VA_ARGS__)
-#if _GMS_DEBUG_LEVEL > 1
-#define GMS_DEBUG_DUMP(s, ...) \
- _gabble_media_session_debug (s, DEBUG_MSG_DUMP, __VA_ARGS__)
-#else
-#define GMS_DEBUG_DUMP(s, ...)
-#endif
-#define GMS_DEBUG_WARNING(s, ...) \
- _gabble_media_session_debug (s, DEBUG_MSG_WARNING, __VA_ARGS__)
-#define GMS_DEBUG_ERROR(s, ...) \
- _gabble_media_session_debug (s, DEBUG_MSG_ERROR, __VA_ARGS__)
-#define GMS_DEBUG_EVENT(s, ...) \
- _gabble_media_session_debug (s, DEBUG_MSG_EVENT, __VA_ARGS__)
-
-void _gabble_media_session_debug (GabbleMediaSession *session,
- DebugMessageType type,
- const gchar *format, ...)
- G_GNUC_PRINTF (3, 4);
-
-#else
-
-#define GMS_DEBUG_INFO(s, ...)
-#define GMS_DEBUG_DUMP(s, ...)
-#define GMS_DEBUG_WARNING(s, ...)
-#define GMS_DEBUG_ERROR(s, ...)
-#define GMS_DEBUG_EVENT(s, ...)
-
-#endif /* ENABLE_DEBUG */
-#endif /* _GMS_DEBUG_LEVEL */
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_MEDIA_SESSION_H__*/
diff --git a/src/gabble-media-stream.c b/src/gabble-media-stream.c
deleted file mode 100644
index 4be1c8b9c..000000000
--- a/src/gabble-media-stream.c
+++ /dev/null
@@ -1,1719 +0,0 @@
-/*
- * gabble-media-stream.c - Source for GabbleMediaStream
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#include "gabble-media-stream.h"
-
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include <telepathy-glib/debug-ansi.h>
-#include "debug.h"
-#include "namespaces.h"
-
-#include "gabble-connection.h"
-#include "gabble-media-channel.h"
-#include "gabble-media-session.h"
-#include "gabble-media-session-enumtypes.h"
-
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/svc-media-interfaces.h>
-
-#include "gabble-signals-marshal.h"
-
-static void stream_handler_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE(GabbleMediaStream,
- gabble_media_stream,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_MEDIA_STREAM_HANDLER,
- stream_handler_iface_init)
- )
-
-/* signal enum */
-enum
-{
- DESTROY,
-
- NEW_ACTIVE_CANDIDATE_PAIR,
- NEW_NATIVE_CANDIDATE,
- SUPPORTED_CODECS,
- ERROR,
-
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_CONNECTION = 1,
- PROP_MEDIA_SESSION,
- PROP_OBJECT_PATH,
- PROP_MODE,
- PROP_NAME,
- PROP_ID,
- PROP_INITIATOR,
- PROP_MEDIA_TYPE,
- PROP_CONNECTION_STATE,
- PROP_READY,
- PROP_GOT_LOCAL_CODECS,
- PROP_SIGNALLING_STATE,
- PROP_PLAYING,
- PROP_COMBINED_DIRECTION,
- LAST_PROPERTY
-};
-
-/* private structure */
-typedef struct _GabbleMediaStreamPrivate GabbleMediaStreamPrivate;
-
-struct _GabbleMediaStreamPrivate
-{
- GabbleConnection *conn;
- GabbleMediaSession *session;
- GabbleMediaSessionMode mode;
- gchar *object_path;
- guint id;
- guint media_type;
-
- gboolean ready;
- gboolean sending;
-
- GValue native_codecs; /* intersected codec list */
- GValue native_candidates;
-
- GValue remote_codecs;
- GValue remote_candidates;
-
- guint remote_candidate_count;
-
- gboolean closed;
- gboolean dispose_has_run;
-};
-
-#define GABBLE_MEDIA_STREAM_GET_PRIVATE(obj) \
- ((GabbleMediaStreamPrivate *)obj->priv)
-
-#ifdef ENABLE_DEBUG
-#if _GMS_DEBUG_LEVEL > 1
-static const char *tp_protocols[] = {
- "TP_MEDIA_STREAM_BASE_PROTO_UDP (0)",
- "TP_MEDIA_STREAM_BASE_PROTO_TCP (1)"
-};
-
-static const char *tp_transports[] = {
- "TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL (0)",
- "TP_MEDIA_STREAM_TRANSPORT_TYPE_DERIVED (1)",
- "TP_MEDIA_STREAM_TRANSPORT_TYPE_RELAY (2)"
-};
-#endif
-#endif
-
-static void push_native_candidates (GabbleMediaStream *stream);
-static void push_remote_codecs (GabbleMediaStream *stream);
-static void push_remote_candidates (GabbleMediaStream *stream);
-static void push_playing (GabbleMediaStream *stream);
-static void push_sending (GabbleMediaStream *stream);
-
-static void
-gabble_media_stream_init (GabbleMediaStream *self)
-{
- GabbleMediaStreamPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_MEDIA_STREAM, GabbleMediaStreamPrivate);
-
- self->priv = priv;
-
- g_value_init (&priv->native_codecs, TP_TYPE_CODEC_LIST);
- g_value_take_boxed (&priv->native_codecs,
- dbus_g_type_specialized_construct (TP_TYPE_CODEC_LIST));
-
- g_value_init (&priv->native_candidates, TP_TYPE_CANDIDATE_LIST);
- g_value_take_boxed (&priv->native_candidates,
- dbus_g_type_specialized_construct (TP_TYPE_CANDIDATE_LIST));
-
- g_value_init (&priv->remote_codecs, TP_TYPE_CODEC_LIST);
- g_value_take_boxed (&priv->remote_codecs,
- dbus_g_type_specialized_construct (TP_TYPE_CODEC_LIST));
-
- g_value_init (&priv->remote_candidates, TP_TYPE_CANDIDATE_LIST);
- g_value_take_boxed (&priv->remote_candidates,
- dbus_g_type_specialized_construct (TP_TYPE_CANDIDATE_LIST));
-}
-
-static GObject *
-gabble_media_stream_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleMediaStreamPrivate *priv;
- DBusGConnection *bus;
-
- /* call base class constructor */
- obj = G_OBJECT_CLASS (gabble_media_stream_parent_class)->
- constructor (type, n_props, props);
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (GABBLE_MEDIA_STREAM (obj));
-
- /* go for the bus */
- bus = tp_get_bus ();
- dbus_g_connection_register_g_object (bus, priv->object_path, obj);
-
- return obj;
-}
-
-static void
-gabble_media_stream_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object);
- GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_MEDIA_SESSION:
- g_value_set_object (value, priv->session);
- break;
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_MODE:
- g_value_set_enum (value, priv->mode);
- break;
- case PROP_NAME:
- g_value_set_string (value, stream->name);
- break;
- case PROP_ID:
- g_value_set_uint (value, priv->id);
- break;
- case PROP_INITIATOR:
- g_value_set_uint (value, stream->initiator);
- break;
- case PROP_MEDIA_TYPE:
- g_value_set_uint (value, priv->media_type);
- break;
- case PROP_CONNECTION_STATE:
- g_value_set_uint (value, stream->connection_state);
- break;
- case PROP_READY:
- g_value_set_boolean (value, priv->ready);
- break;
- case PROP_GOT_LOCAL_CODECS:
- g_value_set_boolean (value, stream->got_local_codecs);
- break;
- case PROP_SIGNALLING_STATE:
- g_value_set_uint (value, stream->signalling_state);
- break;
- case PROP_PLAYING:
- g_value_set_boolean (value, stream->playing);
- break;
- case PROP_COMBINED_DIRECTION:
- g_value_set_uint (value, stream->combined_direction);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_media_stream_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object);
- GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_MEDIA_SESSION:
- priv->session = g_value_get_object (value);
- break;
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_MODE:
- priv->mode = g_value_get_enum (value);
- break;
- case PROP_NAME:
- g_free (stream->name);
- stream->name = g_value_dup_string (value);
- break;
- case PROP_ID:
- priv->id = g_value_get_uint (value);
- break;
- case PROP_INITIATOR:
- stream->initiator = g_value_get_uint (value);
- break;
- case PROP_MEDIA_TYPE:
- priv->media_type = g_value_get_uint (value);
- break;
- case PROP_CONNECTION_STATE:
- GMS_DEBUG_INFO (priv->session, "stream %s connection state %d",
- stream->name, stream->connection_state);
- stream->connection_state = g_value_get_uint (value);
- break;
- case PROP_READY:
- priv->ready = g_value_get_boolean (value);
- break;
- case PROP_GOT_LOCAL_CODECS:
- stream->got_local_codecs = g_value_get_boolean (value);
- break;
- case PROP_SIGNALLING_STATE:
- {
- StreamSignallingState old = stream->signalling_state;
- stream->signalling_state = g_value_get_uint (value);
- GMS_DEBUG_INFO (priv->session, "stream %s sig_state %d->%d",
- stream->name, old, stream->signalling_state);
- if (stream->signalling_state != old)
- push_native_candidates (stream);
- }
- break;
- case PROP_PLAYING:
- {
- gboolean old = stream->playing;
- stream->playing = g_value_get_boolean (value);
- if (stream->playing != old)
- push_playing (stream);
- }
- break;
- case PROP_COMBINED_DIRECTION:
- stream->combined_direction = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_media_stream_dispose (GObject *object);
-static void gabble_media_stream_finalize (GObject *object);
-
-static void
-gabble_media_stream_class_init (GabbleMediaStreamClass *gabble_media_stream_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_media_stream_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_media_stream_class,
- sizeof (GabbleMediaStreamPrivate));
-
- object_class->constructor = gabble_media_stream_constructor;
-
- object_class->get_property = gabble_media_stream_get_property;
- object_class->set_property = gabble_media_stream_set_property;
-
- object_class->dispose = gabble_media_stream_dispose;
- object_class->finalize = gabble_media_stream_finalize;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "media stream's channel.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_object ("media-session",
- "GabbleMediaSession object",
- "Gabble media session object that owns this media stream object.",
- GABBLE_TYPE_MEDIA_SESSION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_MEDIA_SESSION,
- param_spec);
-
- param_spec = g_param_spec_string ("object-path", "D-Bus object path",
- "The D-Bus object path used for this "
- "object on the bus.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_OBJECT_PATH, param_spec);
-
- param_spec = g_param_spec_enum ("mode", "Signalling mode",
- "Which signalling mode used to control the "
- "stream.",
- gabble_media_session_mode_get_type (),
- MODE_JINGLE,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_MODE, param_spec);
-
- param_spec = g_param_spec_string ("name", "Stream name",
- "An opaque name for the stream used in the signalling.", NULL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_NAME, param_spec);
-
- param_spec = g_param_spec_uint ("id", "Stream ID",
- "A stream number for the stream used in the "
- "D-Bus API.",
- 0, G_MAXUINT, 0,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_ID, param_spec);
-
- param_spec = g_param_spec_uint ("initiator", "Stream initiator",
- "An enum signifying which end initiated "
- "the stream.",
- INITIATOR_LOCAL,
- INITIATOR_REMOTE,
- INITIATOR_LOCAL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_INITIATOR, param_spec);
-
- param_spec = g_param_spec_uint ("media-type", "Stream media type",
- "A constant indicating which media type the "
- "stream carries.",
- TP_MEDIA_STREAM_TYPE_AUDIO,
- TP_MEDIA_STREAM_TYPE_VIDEO,
- TP_MEDIA_STREAM_TYPE_AUDIO,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_MEDIA_TYPE, param_spec);
-
- param_spec = g_param_spec_uint ("connection-state",
- "Stream connection state",
- "An integer indicating the state of the stream's connection.",
- TP_MEDIA_STREAM_STATE_DISCONNECTED,
- TP_MEDIA_STREAM_STATE_CONNECTED,
- TP_MEDIA_STREAM_STATE_DISCONNECTED,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION_STATE,
- param_spec);
-
- param_spec = g_param_spec_boolean ("ready", "Ready?",
- "A boolean signifying whether the user "
- "is ready to handle signals from this "
- "object.",
- FALSE,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_READY, param_spec);
-
- param_spec = g_param_spec_boolean ("got-local-codecs", "Got local codecs?",
- "A boolean signifying whether we've got the locally supported codecs "
- "from the user.", FALSE,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_GOT_LOCAL_CODECS,
- param_spec);
-
- param_spec = g_param_spec_uint ("signalling-state", "Signalling state",
- "Whether the stream is newly created, "
- "sent to the peer, or acknowledged.",
- STREAM_SIG_STATE_NEW,
- STREAM_SIG_STATE_REMOVING,
- STREAM_SIG_STATE_NEW,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_SIGNALLING_STATE,
- param_spec);
-
- param_spec = g_param_spec_boolean ("playing", "Set playing",
- "A boolean signifying whether the stream "
- "has been set playing yet.",
- FALSE,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PLAYING, param_spec);
-
- param_spec = g_param_spec_uint ("combined-direction",
- "Combined direction",
- "An integer indicating the directions the stream currently sends in, "
- "and the peers who have been asked to send.",
- TP_MEDIA_STREAM_DIRECTION_NONE,
- MAKE_COMBINED_DIRECTION (TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
- TP_MEDIA_STREAM_PENDING_LOCAL_SEND |
- TP_MEDIA_STREAM_PENDING_REMOTE_SEND),
- TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_COMBINED_DIRECTION,
- param_spec);
-
- /* signals not exported by D-Bus interface */
- signals[DESTROY] =
- g_signal_new ("destroy",
- G_OBJECT_CLASS_TYPE (gabble_media_stream_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[NEW_ACTIVE_CANDIDATE_PAIR] =
- g_signal_new ("new-active-candidate-pair",
- G_OBJECT_CLASS_TYPE (gabble_media_stream_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- gabble_marshal_VOID__STRING_STRING,
- G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
-
- signals[NEW_NATIVE_CANDIDATE] =
- g_signal_new ("new-native-candidate",
- G_OBJECT_CLASS_TYPE (gabble_media_stream_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- gabble_marshal_VOID__STRING_BOXED,
- G_TYPE_NONE, 2, G_TYPE_STRING, TP_TYPE_TRANSPORT_LIST);
-
- signals[SUPPORTED_CODECS] =
- g_signal_new ("supported-codecs",
- G_OBJECT_CLASS_TYPE (gabble_media_stream_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, TP_TYPE_CODEC_LIST);
-
- signals[ERROR] =
- g_signal_new ("error",
- G_OBJECT_CLASS_TYPE (gabble_media_stream_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- gabble_marshal_VOID__UINT_STRING,
- G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
-}
-
-void
-gabble_media_stream_dispose (GObject *object)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (object);
- GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- _gabble_media_stream_close (self);
-
- g_signal_emit (self, signals[DESTROY], 0);
-
- priv->dispose_has_run = TRUE;
-
- if (G_OBJECT_CLASS (gabble_media_stream_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_media_stream_parent_class)->dispose (object);
-}
-
-void
-gabble_media_stream_finalize (GObject *object)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (object);
- GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- g_free (priv->object_path);
-
- g_value_unset (&priv->native_codecs);
- g_value_unset (&priv->native_candidates);
-
- g_value_unset (&priv->remote_codecs);
- g_value_unset (&priv->remote_candidates);
-
- G_OBJECT_CLASS (gabble_media_stream_parent_class)->finalize (object);
-}
-
-/**
- * gabble_media_stream_codec_choice
- *
- * Implements D-Bus method CodecChoice
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_codec_choice (TpSvcMediaStreamHandler *iface,
- guint codec_id,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- tp_svc_media_stream_handler_return_from_codec_choice (context);
-}
-
-
-gboolean
-gabble_media_stream_error (GabbleMediaStream *self,
- guint errno,
- const gchar *message,
- GError **error)
-{
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- GMS_DEBUG_WARNING (priv->session,
- "Media.StreamHandler::Error called, error %u (%s) -- emitting signal",
- errno, message);
-
- g_signal_emit (self, signals[ERROR], 0, errno, message);
-
- return TRUE;
-}
-
-
-/**
- * gabble_media_stream_error
- *
- * Implements D-Bus method Error
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_error_async (TpSvcMediaStreamHandler *iface,
- guint errno,
- const gchar *message,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- GError *error = NULL;
-
- if (gabble_media_stream_error (self, errno, message, &error))
- {
- tp_svc_media_stream_handler_return_from_error (context);
- }
- else
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-}
-
-
-/**
- * gabble_media_stream_native_candidates_prepared
- *
- * Implements D-Bus method NativeCandidatesPrepared
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_native_candidates_prepared (TpSvcMediaStreamHandler *iface,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- tp_svc_media_stream_handler_return_from_native_candidates_prepared (context);
-}
-
-
-/**
- * gabble_media_stream_new_active_candidate_pair
- *
- * Implements D-Bus method NewActiveCandidatePair
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_new_active_candidate_pair (TpSvcMediaStreamHandler *iface,
- const gchar *native_candidate_id,
- const gchar *remote_candidate_id,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- g_signal_emit (self, signals[NEW_ACTIVE_CANDIDATE_PAIR], 0,
- native_candidate_id, remote_candidate_id);
-
- tp_svc_media_stream_handler_return_from_new_active_candidate_pair (context);
-}
-
-
-/**
- * gabble_media_stream_new_native_candidate
- *
- * Implements D-Bus method NewNativeCandidate
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
- const gchar *candidate_id,
- const GPtrArray *transports,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- GabbleMediaStreamPrivate *priv;
- JingleSessionState state;
- GPtrArray *candidates;
- GValue candidate = { 0, };
- GValueArray *transport;
- const gchar *addr;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- g_object_get (priv->session, "state", &state, NULL);
-
- /* FIXME: maybe this should be an assertion in case the channel
- * isn't closed early enough right now? */
- if (state > JS_STATE_ACTIVE)
- {
- DEBUG ("state > JS_STATE_ACTIVE, doing nothing");
- tp_svc_media_stream_handler_return_from_new_native_candidate (context);
- return;
- }
-
- candidates = g_value_get_boxed (&priv->native_candidates);
-
- g_value_init (&candidate, TP_TYPE_CANDIDATE_STRUCT);
- g_value_take_boxed (&candidate,
- dbus_g_type_specialized_construct (TP_TYPE_CANDIDATE_STRUCT));
-
- dbus_g_type_struct_set (&candidate,
- 0, candidate_id,
- 1, transports,
- G_MAXUINT);
-
- if (transports->len != 1)
- {
- GError only_one = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "google p2p "
- "connections only support the concept of one transport per "
- "candidate" };
- GMS_DEBUG_WARNING (priv->session, "%s: number of transports was not 1; "
- "rejecting", G_STRFUNC);
- dbus_g_method_return_error (context, &only_one);
- return;
- }
-
- transport = g_ptr_array_index (transports, 0);
- addr = g_value_get_string (g_value_array_get_nth (transport, 1));
- if (!strcmp (addr, "127.0.0.1"))
- {
- GMS_DEBUG_WARNING (priv->session,
- "%s: ignoring native localhost candidate", G_STRFUNC);
- tp_svc_media_stream_handler_return_from_new_native_candidate (context);
- return;
- }
-
- g_ptr_array_add (candidates, g_value_get_boxed (&candidate));
-
- GMS_DEBUG_INFO (priv->session,
- "put 1 native candidate from stream-engine into cache");
-
- push_native_candidates (self);
-
- g_signal_emit (self, signals[NEW_NATIVE_CANDIDATE], 0,
- candidate_id, transports);
-
- tp_svc_media_stream_handler_return_from_new_native_candidate (context);
-}
-
-static void gabble_media_stream_set_local_codecs (TpSvcMediaStreamHandler *,
- const GPtrArray *codecs, DBusGMethodInvocation *);
-
-/**
- * gabble_media_stream_ready
- *
- * Implements D-Bus method Ready
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_ready (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- GMS_DEBUG_INFO (priv->session, "ready called");
-
- g_object_set (self, "ready", TRUE, NULL);
-
- push_remote_codecs (self);
- push_remote_candidates (self);
- push_playing (self);
- push_sending (self);
-
- /* set_local_codecs and ready return the same thing, so we can do... */
- gabble_media_stream_set_local_codecs (iface, codecs, context);
-}
-
-
-/**
- * gabble_media_stream_set_local_codecs
- *
- * Implements D-Bus method SetLocalCodecs
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_set_local_codecs (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- GMS_DEBUG_INFO (priv->session, "putting list of all %d locally supported "
- "codecs from stream-engine into cache", codecs->len);
-
- g_value_set_boxed (&priv->native_codecs, codecs);
-
- g_object_set (self, "got-local-codecs", TRUE, NULL);
-
- tp_svc_media_stream_handler_return_from_set_local_codecs (context);
-}
-
-
-/**
- * gabble_media_stream_stream_state
- *
- * Implements D-Bus method StreamState
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_stream_state (TpSvcMediaStreamHandler *iface,
- guint connection_state,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- g_object_set (self, "connection-state", connection_state, NULL);
-
- tp_svc_media_stream_handler_return_from_stream_state (context);
-}
-
-
-/**
- * gabble_media_stream_supported_codecs
- *
- * Implements D-Bus method SupportedCodecs
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-gabble_media_stream_supported_codecs (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (self));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (self);
-
- GMS_DEBUG_INFO (priv->session, "got codec intersection containing %d "
- "codecs from stream-engine", codecs->len);
-
- /* store the intersection for later on */
- g_value_set_boxed (&priv->native_codecs, codecs);
-
- g_signal_emit (self, signals[SUPPORTED_CODECS], 0, codecs);
-
- tp_svc_media_stream_handler_return_from_supported_codecs (context);
-}
-
-static LmHandlerResult
-candidates_msg_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object);
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- MSG_REPLY_CB_END_SESSION_IF_NOT_SUCCESSFUL (priv->session,
- "candidates failed");
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-_add_rtp_candidate_node (GabbleMediaSession *session, LmMessageNode *parent,
- GValueArray *candidate)
-{
- gchar *addr;
- gchar *user;
- gchar *pass;
- gchar *port_str;
- gchar *pref_str;
- gchar *xml;
- const gchar *type_str;
- const gchar *candidate_id;
- guint port;
- gdouble pref;
- TpMediaStreamBaseProto proto;
- TpMediaStreamTransportType type;
- const GPtrArray *transports;
- GValue transport = { 0, };
- LmMessageNode *cand_node;
-
- candidate_id = g_value_get_string (g_value_array_get_nth (candidate, 0));
- transports = g_value_get_boxed (g_value_array_get_nth (candidate, 1));
-
- /* jingle audio only supports the concept of one transport per candidate */
- g_assert (transports->len == 1);
-
- g_value_init (&transport, TP_TYPE_TRANSPORT_STRUCT);
- g_value_set_static_boxed (&transport, g_ptr_array_index (transports, 0));
-
- dbus_g_type_struct_get (&transport,
- 1, &addr,
- 2, &port,
- 3, &proto,
- 6, &pref,
- 7, &type,
- 8, &user,
- 9, &pass,
- G_MAXUINT);
-
- port_str = g_strdup_printf ("%d", port);
- pref_str = g_strdup_printf ("%f", pref);
-
- switch (type) {
- case TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL:
- type_str = "local";
- break;
- case TP_MEDIA_STREAM_TRANSPORT_TYPE_DERIVED:
- type_str = "stun";
- break;
- case TP_MEDIA_STREAM_TRANSPORT_TYPE_RELAY:
- type_str = "relay";
- break;
- default:
- g_error ("%s: TpMediaStreamTransportType has an invalid value",
- G_STRFUNC);
- return;
- }
-
- cand_node = lm_message_node_add_child (parent, "candidate", NULL);
- lm_message_node_set_attributes (cand_node,
- "name", "rtp",
- "address", addr,
- "port", port_str,
- "username", user,
- "password", pass,
- "preference", pref_str,
- "protocol", (proto == TP_MEDIA_STREAM_BASE_PROTO_UDP) ? "udp" : "tcp",
- "type", type_str,
- "network", "0",
- "generation", "0",
- NULL);
-
- xml = lm_message_node_to_string (cand_node);
- GMS_DEBUG_DUMP (session,
- " from Telepathy D-Bus struct: [%s\"%s\", %s[%s1, \"%s\", %d, %s, "
- "\"%s\", \"%s\", %f, %s, \"%s\", \"%s\"%s]]",
- TP_ANSI_BOLD_OFF, candidate_id, TP_ANSI_BOLD_ON, TP_ANSI_BOLD_OFF,
- addr, port, tp_protocols[proto], "RTP", "AVP", pref, tp_transports[type],
- user, pass, TP_ANSI_BOLD_ON);
- GMS_DEBUG_DUMP (session,
- " to Jingle XML: [%s%s%s]", TP_ANSI_BOLD_OFF, xml, TP_ANSI_BOLD_ON);
- g_free (xml);
-
- g_free (addr);
- g_free (user);
- g_free (pass);
- g_free (port_str);
- g_free (pref_str);
-}
-
-static LmMessage *
-_gabble_media_stream_message_new (GabbleMediaStream *stream,
- const gchar *action,
- LmMessageNode **content_node)
-{
- GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
- LmMessage *msg;
- LmMessageNode *session_node = NULL;
-
- /* construct a session message */
- msg = _gabble_media_session_message_new (priv->session, action,
- &session_node);
-
- /* add our content node to it if necessary */
- *content_node = _gabble_media_stream_add_content_node (stream, session_node);
-
- return msg;
-}
-
-
-static void
-push_candidate (GabbleMediaStream *stream, GValueArray *candidate)
-{
- GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
- LmMessage *msg;
- LmMessageNode *content_node, *transport_node;
- const gchar *action;
-
- if (priv->mode == MODE_GOOGLE)
- action = "candidates";
- else
- action = "transport-info";
-
- /* construct a base message */
- msg = _gabble_media_stream_message_new (stream, action, &content_node);
-
- /* for jingle, add a transport */
- transport_node = _gabble_media_stream_content_node_add_transport (stream,
- content_node);
-
- /* add transport info to it */
- _add_rtp_candidate_node (priv->session, transport_node, candidate);
-
- GMS_DEBUG_INFO (priv->session, "sending jingle session action \"%s\" to "
- "peer", action);
-
- /* send it */
- _gabble_connection_send_with_reply (priv->conn, msg, candidates_msg_reply_cb,
- G_OBJECT (stream), NULL, NULL);
-
- /* clean up */
- lm_message_unref (msg);
-}
-
-static void
-push_native_candidates (GabbleMediaStream *stream)
-{
- GabbleMediaStreamPrivate *priv;
- GPtrArray *candidates;
- guint i;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- if (stream->signalling_state == STREAM_SIG_STATE_NEW ||
- stream->signalling_state == STREAM_SIG_STATE_REMOVING)
- return;
-
- candidates = g_value_get_boxed (&priv->native_candidates);
-
- for (i = 0; i < candidates->len; i++)
- push_candidate (stream, g_ptr_array_index (candidates, i));
-
- g_value_take_boxed (&priv->native_candidates,
- dbus_g_type_specialized_construct (TP_TYPE_CANDIDATE_LIST));
-}
-
-void
-_gabble_media_stream_close (GabbleMediaStream *stream)
-{
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- if (!priv->closed)
- {
- priv->closed = TRUE;
- tp_svc_media_stream_handler_emit_close (stream);
- }
-}
-
-gboolean
-_gabble_media_stream_post_remote_codecs (GabbleMediaStream *stream,
- LmMessage *message,
- LmMessageNode *desc_node,
- GError **error)
-{
- GabbleMediaStreamPrivate *priv;
- LmMessageNode *node;
- GPtrArray *codecs;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- codecs = g_value_get_boxed (&priv->remote_codecs);
-
- g_assert (codecs->len == 0);
-
- for (node = desc_node->children; node; node = node->next)
- {
- guchar id;
- const gchar *name, *str;
- guint clockrate, channels;
- GHashTable *params;
- GValue codec = { 0, };
-
- if (tp_strdiff (node->name, "payload-type"))
- continue;
-
- /* id of codec */
- str = lm_message_node_get_attribute (node, "id");
- if (str == NULL)
- {
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "description has no ID");
- return FALSE;
- }
-
- id = atoi (str);
-
- /* codec name */
- name = lm_message_node_get_attribute (node, "name");
- if (name == NULL)
- {
- name = "";
- }
-
- /* clock rate: jingle and newer GTalk */
- str = lm_message_node_get_attribute (node, "clockrate"); /* google */
- if (str == NULL)
- str = lm_message_node_get_attribute (node, "rate"); /* jingle */
-
- if (str != NULL)
- {
- clockrate = atoi (str);
- }
- else
- {
- clockrate = 0;
- }
-
- /* number of channels: jingle only */
- str = lm_message_node_get_attribute (node, "channels");
- if (str != NULL)
- {
- channels = atoi (str);
- }
- else
- {
- channels = 1;
- }
-
- params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
-
- /* bitrate: newer GTalk only */
- str = lm_message_node_get_attribute (node, "bitrate");
- if (str != NULL)
- {
- g_hash_table_insert (params, "bitrate", g_strdup (str));
- }
-
- g_value_init (&codec, TP_TYPE_CODEC_STRUCT);
- g_value_take_boxed (&codec,
- dbus_g_type_specialized_construct (TP_TYPE_CODEC_STRUCT));
-
- dbus_g_type_struct_set (&codec,
- 0, id,
- 1, name,
- 2, TP_MEDIA_STREAM_TYPE_AUDIO,
- 3, clockrate,
- 4, channels,
- 5, params,
- G_MAXUINT);
-
- g_ptr_array_add (codecs, g_value_get_boxed (&codec));
- }
-
- GMS_DEBUG_INFO (priv->session, "put %d remote codecs from peer into cache",
- codecs->len);
-
- push_remote_codecs (stream);
-
- return TRUE;
-}
-
-static void
-push_remote_codecs (GabbleMediaStream *stream)
-{
- GabbleMediaStreamPrivate *priv;
- GPtrArray *codecs;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- if (!priv->ready)
- return;
-
- codecs = g_value_get_boxed (&priv->remote_codecs);
- if (codecs->len == 0)
- return;
-
- GMS_DEBUG_EVENT (priv->session, "passing %d remote codecs to stream-engine",
- codecs->len);
-
- tp_svc_media_stream_handler_emit_set_remote_codecs (stream, codecs);
-
- g_value_take_boxed (&priv->remote_codecs,
- dbus_g_type_specialized_construct (TP_TYPE_CODEC_LIST));
-}
-
-gboolean
-_gabble_media_stream_post_remote_candidates (GabbleMediaStream *stream,
- LmMessage *message,
- LmMessageNode *transport_node,
- GError **error)
-{
- GabbleMediaStreamPrivate *priv;
- LmMessageNode *node;
- const gchar *str;
- GPtrArray *candidates;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- candidates = g_value_get_boxed (&priv->remote_candidates);
-
- for (node = transport_node->children; node; node = node->next)
- {
- gchar *candidate_id;
- const gchar *name, *addr;
- guint16 port;
- TpMediaStreamBaseProto proto;
- gdouble pref;
- TpMediaStreamTransportType type;
- const gchar *user, *pass;
- guchar net, gen;
- GValue candidate = { 0, };
- GPtrArray *transports;
- GValue transport = { 0, };
- gchar *xml;
-
- if (tp_strdiff (node->name, "candidate"))
- continue;
-
- /*
- * Candidate
- */
-
- /* stream name */
- name = lm_message_node_get_attribute (node, "name");
- if (name == NULL || strcmp (name, "rtp") != 0)
- goto FAILURE;
-
-
- /*
- * Transport
- */
-
- /* ip address */
- addr = lm_message_node_get_attribute (node, "address");
- if (addr == NULL)
- goto FAILURE;
-
- /* port */
- str = lm_message_node_get_attribute (node, "port");
- if (str == NULL)
- goto FAILURE;
- port = atoi (str);
-
- /* protocol */
- str = lm_message_node_get_attribute (node, "protocol");
- if (str == NULL)
- goto FAILURE;
-
- if (strcmp (str, "udp") == 0)
- {
- proto = TP_MEDIA_STREAM_BASE_PROTO_UDP;
- }
- else if (strcmp (str, "tcp") == 0)
- {
- proto = TP_MEDIA_STREAM_BASE_PROTO_TCP;
- }
- else if (strcmp (str, "ssltcp") == 0)
- {
- GMS_DEBUG_WARNING (priv->session, "%s: ssltcp candidates "
- "not yet supported", G_STRFUNC);
- continue;
- }
- else
- goto FAILURE;
-
- /* protocol profile: hardcoded to "AVP" for now */
-
- /* preference */
- str = lm_message_node_get_attribute (node, "preference");
- if (str == NULL)
- goto FAILURE;
- pref = g_ascii_strtod (str, NULL);
-
- /* type */
- str = lm_message_node_get_attribute (node, "type");
- if (str == NULL)
- goto FAILURE;
-
- if (strcmp (str, "local") == 0)
- {
- type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL;
- }
- else if (strcmp (str, "stun") == 0)
- {
- type = TP_MEDIA_STREAM_TRANSPORT_TYPE_DERIVED;
- }
- else if (strcmp (str, "relay") == 0)
- {
- type = TP_MEDIA_STREAM_TRANSPORT_TYPE_RELAY;
- }
- else
- goto FAILURE;
-
- /* username */
- user = lm_message_node_get_attribute (node, "username");
- if (user == NULL)
- goto FAILURE;
-
- /* password */
- pass = lm_message_node_get_attribute (node, "password");
- if (pass == NULL)
- goto FAILURE;
-
- /* unknown */
- str = lm_message_node_get_attribute (node, "network");
- if (str == NULL)
- goto FAILURE;
- net = atoi (str);
-
- /* unknown */
- str = lm_message_node_get_attribute (node, "generation");
- if (str == NULL)
- goto FAILURE;
- gen = atoi (str);
-
-
- g_value_init (&transport, TP_TYPE_TRANSPORT_STRUCT);
- g_value_take_boxed (&transport,
- dbus_g_type_specialized_construct (TP_TYPE_TRANSPORT_STRUCT));
-
- dbus_g_type_struct_set (&transport,
- 0, 1, /* component number */
- 1, addr,
- 2, port,
- 3, proto,
- 4, "RTP",
- 5, "AVP",
- 6, pref,
- 7, type,
- 8, user,
- 9, pass,
- G_MAXUINT);
-
- transports = g_ptr_array_sized_new (1);
- g_ptr_array_add (transports, g_value_get_boxed (&transport));
-
-
- g_value_init (&candidate, TP_TYPE_CANDIDATE_STRUCT);
- g_value_take_boxed (&candidate,
- dbus_g_type_specialized_construct (TP_TYPE_CANDIDATE_STRUCT));
-
- /* FIXME: is this naming scheme sensible? */
- candidate_id = g_strdup_printf ("R%d", ++priv->remote_candidate_count);
-
- dbus_g_type_struct_set (&candidate,
- 0, candidate_id,
- 1, transports,
- G_MAXUINT);
-
- g_ptr_array_add (candidates, g_value_get_boxed (&candidate));
-
- xml = lm_message_node_to_string (node);
- GMS_DEBUG_INFO (priv->session,
- "put 1 remote candidate from peer into cache");
- GMS_DEBUG_DUMP (priv->session, " from Jingle XML: [%s%s%s]",
- TP_ANSI_BOLD_OFF, xml, TP_ANSI_BOLD_ON);
- GMS_DEBUG_DUMP (priv->session,
- " to Telepathy D-Bus struct: [%s\"%s\", %s[%s1, \"%s\", %d, %s, "
- "\"%s\", \"%s\", %f, %s, \"%s\", \"%s\"%s]]",
- TP_ANSI_BOLD_OFF, candidate_id, TP_ANSI_BOLD_ON,
- TP_ANSI_BOLD_OFF, addr, port, tp_protocols[proto],
- "RTP", "AVP", pref, tp_transports[type],
- user, pass, TP_ANSI_BOLD_ON);
- g_free (xml);
-
- g_free (candidate_id);
- }
-
-/*SUCCESS:*/
- push_remote_candidates (stream);
-
- return TRUE;
-
-FAILURE:
- g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
- "unable to parse candidate");
-
- return FALSE;
-}
-
-static void
-push_remote_candidates (GabbleMediaStream *stream)
-{
- GabbleMediaStreamPrivate *priv;
- GPtrArray *candidates;
- guint i;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- candidates = g_value_get_boxed (&priv->remote_candidates);
-
- if (candidates->len == 0)
- return;
-
- if (!priv->ready)
- return;
-
- for (i = 0; i < candidates->len; i++)
- {
- GValueArray *candidate = g_ptr_array_index (candidates, i);
- const gchar *candidate_id;
- const GPtrArray *transports;
-
- candidate_id = g_value_get_string (g_value_array_get_nth (candidate, 0));
- transports = g_value_get_boxed (g_value_array_get_nth (candidate, 1));
-
- GMS_DEBUG_EVENT (priv->session, "passing 1 remote candidate "
- "to stream-engine");
-
- tp_svc_media_stream_handler_emit_add_remote_candidate (
- stream, candidate_id, transports);
- }
-
- g_value_take_boxed (&priv->remote_candidates,
- dbus_g_type_specialized_construct (TP_TYPE_CANDIDATE_LIST));
-}
-
-static void
-push_playing (GabbleMediaStream *stream)
-{
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- if (!priv->ready)
- return;
-
- GMS_DEBUG_INFO (priv->session, "stream %s emitting SetStreamPlaying(%s)",
- stream->name, stream->playing ? "true" : "false");
-
- tp_svc_media_stream_handler_emit_set_stream_playing (
- stream, stream->playing);
-}
-
-static void
-push_sending (GabbleMediaStream *stream)
-{
- GabbleMediaStreamPrivate *priv;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- if (!priv->ready)
- return;
-
- GMS_DEBUG_INFO (priv->session, "stream %s emitting SetStreamSending(%s)",
- stream->name, priv->sending ? "true" : "false");
-
- tp_svc_media_stream_handler_emit_set_stream_sending (
- stream, priv->sending);
-}
-
-/*
- * oh sweet g_hash_table_foreach how beautiful thou be'st
- *
- * _\ / ^/
- * \/ \// 7_ __
- * ( 7 ) (__) (__)
- * ^\\ |/__/___/
- * \\/_/ | <-- TP-cable kindly provided by Mika N.
- * \ / O
- * || /|\
- * || / \
- * ||
- * ____||_____________
- */
-
-typedef struct {
- GabbleMediaStreamPrivate *priv;
- LmMessageNode *pt_node;
-} CodecParamsFromTpContext;
-
-static const gchar *video_codec_params[] = {
- "x", "y", "width", "height", "layer", "transparent",
-};
-
-static void
-codec_params_from_tp_foreach (gpointer key, gpointer value, gpointer user_data)
-{
- CodecParamsFromTpContext *ctx = user_data;
- GabbleMediaStreamPrivate *priv = ctx->priv;
- const gchar *pname = key, *pvalue = value;
-
- if (priv->media_type == TP_MEDIA_STREAM_TYPE_AUDIO)
- {
- if (priv->mode == MODE_GOOGLE && strcmp (pname, "bitrate") == 0)
- {
- lm_message_node_set_attribute (ctx->pt_node, pname, pvalue);
- return;
- }
- }
- else if (priv->mode == MODE_JINGLE)
- {
- gint i;
-
- for (i = 0; video_codec_params[i] != NULL; i++)
- {
- if (strcmp (pname, video_codec_params[i]) == 0)
- {
- lm_message_node_set_attribute (ctx->pt_node, pname, pvalue);
- return;
- }
- }
- }
-
- DEBUG ("ignoring %s=%s for %s %s stream", pname, pvalue,
- (priv->mode == MODE_JINGLE) ? "jingle" : "google",
- (priv->media_type == TP_MEDIA_STREAM_TYPE_AUDIO) ? "audio" : "video");
-}
-
-LmMessageNode *
-_gabble_media_stream_add_content_node (GabbleMediaStream *stream,
- LmMessageNode *session_node)
-{
- GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
- LmMessageNode *node = session_node;
-
- /* add our content node to it if in jingle mode */
- if (priv->mode == MODE_JINGLE)
- {
- node = lm_message_node_add_child (session_node, "content", NULL);
- lm_message_node_set_attribute (node, "name", stream->name);
-
- if (priv->session->initiator == stream->initiator)
- lm_message_node_set_attribute (node, "creator", "initiator");
- else
- lm_message_node_set_attribute (node, "creator", "responder");
- }
-
- return node;
-}
-
-void
-_gabble_media_stream_content_node_add_description (GabbleMediaStream *stream,
- LmMessageNode *content_node)
-{
- GabbleMediaStreamPrivate *priv;
- const GPtrArray *codecs;
- LmMessageNode *desc_node;
- guint i;
- const gchar *xmlns;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- codecs = g_value_get_boxed (&priv->native_codecs);
-
- desc_node = lm_message_node_add_child (content_node, "description", NULL);
-
- if (priv->mode == MODE_GOOGLE)
- xmlns = NS_GOOGLE_SESSION_PHONE;
- else if (priv->media_type == TP_MEDIA_STREAM_TYPE_VIDEO)
- xmlns = NS_JINGLE_DESCRIPTION_VIDEO;
- else
- xmlns = NS_JINGLE_DESCRIPTION_AUDIO;
-
- lm_message_node_set_attribute (desc_node, "xmlns", xmlns);
-
- for (i = 0; i < codecs->len; i++)
- {
- GValue codec = { 0, };
- guint id, clock_rate, channels;
- gchar *name, buf[16];
- GHashTable *params;
- LmMessageNode *pt_node;
- CodecParamsFromTpContext ctx;
-
- g_value_init (&codec, TP_TYPE_CODEC_STRUCT);
- g_value_set_static_boxed (&codec, g_ptr_array_index (codecs, i));
-
- dbus_g_type_struct_get (&codec,
- 0, &id,
- 1, &name,
- 3, &clock_rate,
- 4, &channels,
- 5, &params,
- G_MAXUINT);
-
- /* create a sub-node called "payload-type" and fill it */
- pt_node = lm_message_node_add_child (desc_node, "payload-type", NULL);
-
- /* id: required */
- sprintf (buf, "%u", id);
- lm_message_node_set_attribute (pt_node, "id", buf);
-
- /* name: optional */
- if (*name != '\0')
- {
- lm_message_node_set_attribute (pt_node, "name", name);
- }
-
- /* clock rate: optional */
- if (clock_rate != 0)
- {
- sprintf (buf, "%u", clock_rate);
- lm_message_node_set_attribute (pt_node,
- (priv->mode == MODE_GOOGLE) ? "clockrate" : "rate", buf);
- }
-
- /* number of channels: optional, jingle only */
- /* FIXME: is it? */
- if (channels != 0 && priv->mode == MODE_JINGLE)
- {
- sprintf (buf, "%u", channels);
- lm_message_node_set_attribute (pt_node, "channels", buf);
- }
-
- /* parse the optional params */
- ctx.priv = priv;
- ctx.pt_node = pt_node;
- g_hash_table_foreach (params, codec_params_from_tp_foreach, &ctx);
-
- /* clean up */
- g_free (name);
- g_hash_table_destroy (params);
- }
-}
-
-LmMessageNode *
-_gabble_media_stream_content_node_add_transport (GabbleMediaStream *stream,
- LmMessageNode *content_node)
-{
- GabbleMediaStreamPrivate *priv;
- LmMessageNode *node;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- if (priv->mode != MODE_JINGLE)
- return content_node;
-
- node = lm_message_node_add_child (content_node, "transport", NULL);
-
- lm_message_node_set_attribute (node, "xmlns", NS_GOOGLE_TRANSPORT_P2P);
-
- return node;
-}
-
-void
-_gabble_media_stream_update_sending (GabbleMediaStream *stream,
- gboolean start_sending)
-{
- GabbleMediaStreamPrivate *priv;
- gboolean new_sending;
-
- g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
- priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
- new_sending =
- ((stream->combined_direction & TP_MEDIA_STREAM_DIRECTION_SEND) != 0);
-
- if (priv->sending == new_sending)
- return;
-
- if (new_sending && !start_sending)
- return;
-
- priv->sending = new_sending;
- push_sending (stream);
-}
-
-static void
-stream_handler_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcMediaStreamHandlerClass *klass =
- (TpSvcMediaStreamHandlerClass *)g_iface;
-
-#define IMPLEMENT(x,suffix) tp_svc_media_stream_handler_implement_##x (\
- klass, gabble_media_stream_##x##suffix)
- IMPLEMENT(codec_choice,);
- IMPLEMENT(error,_async);
- IMPLEMENT(native_candidates_prepared,);
- IMPLEMENT(new_active_candidate_pair,);
- IMPLEMENT(new_native_candidate,);
- IMPLEMENT(ready,);
- IMPLEMENT(set_local_codecs,);
- IMPLEMENT(stream_state,);
- IMPLEMENT(supported_codecs,);
-#undef IMPLEMENT
-}
diff --git a/src/gabble-media-stream.h b/src/gabble-media-stream.h
deleted file mode 100644
index fc96b8b2b..000000000
--- a/src/gabble-media-stream.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * gabble-media-stream.h - Header for GabbleMediaStream
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_MEDIA_STREAM_H__
-#define __GABBLE_MEDIA_STREAM_H__
-
-#include <glib-object.h>
-#include <loudmouth/loudmouth.h>
-
-#include "gabble-types.h"
-#include <telepathy-glib/enums.h>
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- STREAM_SIG_STATE_NEW,
- STREAM_SIG_STATE_SENT,
- STREAM_SIG_STATE_ACKNOWLEDGED,
- STREAM_SIG_STATE_REMOVING
-} StreamSignallingState;
-
-typedef guint32 CombinedStreamDirection;
-
-typedef struct _GabbleMediaStream GabbleMediaStream;
-typedef struct _GabbleMediaStreamClass GabbleMediaStreamClass;
-
-struct _GabbleMediaStreamClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleMediaStream {
- GObject parent;
-
- gchar *name;
-
- JingleInitiator initiator;
- TpMediaStreamState connection_state;
- StreamSignallingState signalling_state;
-
- CombinedStreamDirection combined_direction;
- gboolean got_local_codecs;
- gboolean playing;
-
- gpointer priv;
-};
-
-GType gabble_media_stream_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_MEDIA_STREAM \
- (gabble_media_stream_get_type ())
-#define GABBLE_MEDIA_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MEDIA_STREAM, \
- GabbleMediaStream))
-#define GABBLE_MEDIA_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MEDIA_STREAM, \
- GabbleMediaStreamClass))
-#define GABBLE_IS_MEDIA_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MEDIA_STREAM))
-#define GABBLE_IS_MEDIA_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MEDIA_STREAM))
-#define GABBLE_MEDIA_STREAM_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MEDIA_STREAM, \
- GabbleMediaStreamClass))
-
-#define TP_TYPE_TRANSPORT_STRUCT (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, \
- G_TYPE_STRING, \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_STRING, \
- G_TYPE_STRING, \
- G_TYPE_DOUBLE, \
- G_TYPE_UINT, \
- G_TYPE_STRING, \
- G_TYPE_STRING, \
- G_TYPE_INVALID))
-#define TP_TYPE_TRANSPORT_LIST (dbus_g_type_get_collection ("GPtrArray", \
- TP_TYPE_TRANSPORT_STRUCT))
-#define TP_TYPE_CANDIDATE_STRUCT (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_STRING, \
- TP_TYPE_TRANSPORT_LIST, \
- G_TYPE_INVALID))
-#define TP_TYPE_CANDIDATE_LIST (dbus_g_type_get_collection ("GPtrArray", \
- TP_TYPE_CANDIDATE_STRUCT))
-
-#define TP_TYPE_CODEC_STRUCT (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, \
- G_TYPE_STRING, \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- DBUS_TYPE_G_STRING_STRING_HASHTABLE, \
- G_TYPE_INVALID))
-#define TP_TYPE_CODEC_LIST (dbus_g_type_get_collection ("GPtrArray", \
- TP_TYPE_CODEC_STRUCT))
-
-#define COMBINED_DIRECTION_GET_DIRECTION(d) \
- ((TpMediaStreamDirection) ((d) & TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL))
-#define COMBINED_DIRECTION_GET_PENDING_SEND(d) \
- ((TpMediaStreamPendingSend) ((d) >> 2))
-#define MAKE_COMBINED_DIRECTION(d, p) \
- ((CombinedStreamDirection) ((d) | ((p) << 2)))
-
-gboolean gabble_media_stream_error (GabbleMediaStream *self, guint errno,
- const gchar *message, GError **error);
-
-void _gabble_media_stream_close (GabbleMediaStream *close);
-gboolean _gabble_media_stream_post_remote_codecs (GabbleMediaStream *stream,
- LmMessage *message, LmMessageNode *desc_node, GError **error);
-gboolean _gabble_media_stream_post_remote_candidates (
- GabbleMediaStream *stream, LmMessage *message,
- LmMessageNode *transport_node, GError **error);
-LmMessageNode *_gabble_media_stream_add_content_node (
- GabbleMediaStream *stream, LmMessageNode *session_node);
-void _gabble_media_stream_content_node_add_description (
- GabbleMediaStream *stream, LmMessageNode *content_node);
-LmMessageNode *_gabble_media_stream_content_node_add_transport (
- GabbleMediaStream *stream, LmMessageNode *content_node);
-void _gabble_media_stream_update_sending (GabbleMediaStream *stream,
- gboolean start_sending);
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_MEDIA_STREAM_H__*/
diff --git a/src/gabble-muc-channel.c b/src/gabble-muc-channel.c
deleted file mode 100644
index 7916de5b0..000000000
--- a/src/gabble-muc-channel.c
+++ /dev/null
@@ -1,2807 +0,0 @@
-/*
- * gabble-muc-channel.c - Source for GabbleMucChannel
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#include "gabble-muc-channel.h"
-
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MUC
-
-#include <telepathy-glib/debug-ansi.h>
-#include "debug.h"
-#include "disco.h"
-#include "gabble-connection.h"
-#include "gabble-error.h"
-#include "namespaces.h"
-#include "util.h"
-
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-
-#define DEFAULT_JOIN_TIMEOUT (180 * 1000)
-#define MAX_NICK_RETRIES 3
-
-#define PROPS_POLL_INTERVAL_LOW (60 * 1000 * 5)
-#define PROPS_POLL_INTERVAL_HIGH (60 * 1000)
-
-static void channel_iface_init (gpointer, gpointer);
-static void password_iface_init (gpointer, gpointer);
-static void text_iface_init (gpointer, gpointer);
-static void chat_state_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleMucChannel, gabble_muc_channel,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL,
- channel_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_PROPERTIES_INTERFACE,
- tp_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
- tp_group_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_PASSWORD,
- password_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT,
- text_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CHAT_STATE,
- chat_state_iface_init)
- )
-
-/* signal enum */
-enum
-{
- READY,
- JOIN_ERROR,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_HANDLE_TYPE,
- PROP_HANDLE,
- PROP_CONNECTION,
- PROP_STATE,
- PROP_INVITE_SELF,
- LAST_PROPERTY
-};
-
-typedef enum {
- MUC_STATE_CREATED = 0,
- MUC_STATE_INITIATED,
- MUC_STATE_AUTH,
- MUC_STATE_JOINED,
- MUC_STATE_ENDED,
-} GabbleMucState;
-
-#ifdef ENABLE_DEBUG
-static const gchar *muc_states[] =
-{
- "MUC_STATE_CREATED",
- "MUC_STATE_INITIATED",
- "MUC_STATE_AUTH",
- "MUC_STATE_JOINED",
- "MUC_STATE_ENDED",
-};
-#endif
-
-/* role and affiliation enums */
-typedef enum {
- ROLE_NONE = 0,
- ROLE_VISITOR,
- ROLE_PARTICIPANT,
- ROLE_MODERATOR,
-
- NUM_ROLES,
-
- INVALID_ROLE,
-} GabbleMucRole;
-
-typedef enum {
- AFFILIATION_NONE = 0,
- AFFILIATION_MEMBER,
- AFFILIATION_ADMIN,
- AFFILIATION_OWNER,
-
- NUM_AFFILIATIONS,
-
- INVALID_AFFILIATION,
-} GabbleMucAffiliation;
-
-static const gchar *muc_roles[NUM_ROLES] =
-{
- "none",
- "visitor",
- "participant",
- "moderator",
-};
-
-static const gchar *muc_affiliations[NUM_AFFILIATIONS] =
-{
- "none",
- "member",
- "admin",
- "owner",
-};
-
-/* room properties */
-enum
-{
- ROOM_PROP_ANONYMOUS = 0,
- ROOM_PROP_INVITE_ONLY,
- ROOM_PROP_MODERATED,
- ROOM_PROP_NAME,
- ROOM_PROP_DESCRIPTION,
- ROOM_PROP_PASSWORD,
- ROOM_PROP_PASSWORD_REQUIRED,
- ROOM_PROP_PERSISTENT,
- ROOM_PROP_PRIVATE,
- ROOM_PROP_SUBJECT,
- ROOM_PROP_SUBJECT_CONTACT,
- ROOM_PROP_SUBJECT_TIMESTAMP,
-
- NUM_ROOM_PROPS,
-
- INVALID_ROOM_PROP,
-};
-
-const TpPropertySignature room_property_signatures[NUM_ROOM_PROPS] = {
- { "anonymous", G_TYPE_BOOLEAN }, /* impl: READ, WRITE */
- { "invite-only", G_TYPE_BOOLEAN }, /* impl: READ, WRITE */
- { "moderated", G_TYPE_BOOLEAN }, /* impl: READ, WRITE */
- { "name", G_TYPE_STRING }, /* impl: READ, WRITE */
- { "description", G_TYPE_STRING }, /* impl: READ, WRITE */
- { "password", G_TYPE_STRING }, /* impl: WRITE */
- { "password-required", G_TYPE_BOOLEAN }, /* impl: READ, WRITE */
- { "persistent", G_TYPE_BOOLEAN }, /* impl: READ, WRITE */
- { "private", G_TYPE_BOOLEAN }, /* impl: READ, WRITE */
- { "subject", G_TYPE_STRING }, /* impl: READ, WRITE */
- { "subject-contact", G_TYPE_UINT }, /* impl: READ */
- { "subject-timestamp", G_TYPE_UINT }, /* impl: READ */
-};
-
-/* private structures */
-
-typedef struct _GabbleMucChannelPrivate GabbleMucChannelPrivate;
-
-struct _GabbleMucChannelPrivate
-{
- GabbleConnection *conn;
- gchar *object_path;
-
- GabbleMucState state;
-
- guint join_timer_id;
- guint poll_timer_id;
-
- TpChannelPasswordFlags password_flags;
- DBusGMethodInvocation *password_ctx;
- gchar *password;
-
- TpHandle handle;
- const gchar *jid;
-
- guint nick_retry_count;
- GString *self_jid;
- GabbleMucRole self_role;
- GabbleMucAffiliation self_affil;
-
- guint recv_id;
-
- TpPropertiesContext *properties_ctx;
-
- gboolean ready_emitted;
-
- gboolean closed;
- gboolean dispose_has_run;
-
- gboolean invite_self;
-};
-
-#define GABBLE_MUC_CHANNEL_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_MUC_CHANNEL, \
- GabbleMucChannelPrivate))
-
-static void
-gabble_muc_channel_init (GabbleMucChannel *obj)
-{
- /* do nothing? */
-}
-
-static void contact_handle_to_room_identity (GabbleMucChannel *, TpHandle,
- TpHandle *, GString **);
-
-static GObject *
-gabble_muc_channel_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleMucChannelPrivate *priv;
- TpBaseConnection *conn;
- DBusGConnection *bus;
- TpHandleRepoIface *room_handles, *contact_handles;
- TpHandle self_handle;
-
- obj = G_OBJECT_CLASS (gabble_muc_channel_parent_class)->
- constructor (type, n_props, props);
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (obj);
- conn = (TpBaseConnection *)priv->conn;
-
- room_handles = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_ROOM);
- contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- /* ref our room handle */
- tp_handle_ref (room_handles, priv->handle);
-
- /* get the room's jid */
- priv->jid = tp_handle_inspect (room_handles, priv->handle);
-
- /* get our own identity in the room */
- contact_handle_to_room_identity (GABBLE_MUC_CHANNEL (obj),
- conn->self_handle, &self_handle, &priv->self_jid);
-
- tp_handle_ref (contact_handles, self_handle);
-
- /* initialize our own role and affiliation */
- priv->self_role = ROLE_NONE;
- priv->self_affil = AFFILIATION_NONE;
-
- /* register object on the bus */
- bus = tp_get_bus ();
- dbus_g_connection_register_g_object (bus, priv->object_path, obj);
-
- /* initialize group mixin */
- tp_group_mixin_init (obj,
- G_STRUCT_OFFSET (GabbleMucChannel, group),
- contact_handles, self_handle);
-
- /* set initial group flags */
- tp_group_mixin_change_flags (obj,
- TP_CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES |
- TP_CHANNEL_GROUP_FLAG_CAN_ADD,
- 0);
-
- /* initialize properties mixin */
- tp_properties_mixin_init (obj, G_STRUCT_OFFSET (
- GabbleMucChannel, properties));
-
- /* initialize text mixin */
- gabble_text_mixin_init (obj, G_STRUCT_OFFSET (GabbleMucChannel, text),
- contact_handles, FALSE);
-
- tp_text_mixin_set_message_types (obj,
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
- TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION,
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE,
- G_MAXUINT);
-
- /* add ourselves to group mixin if needed */
- if (priv->invite_self)
- {
- GError *error = NULL;
- GArray *members = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1);
- g_array_append_val (members, self_handle);
- tp_group_mixin_add_members (obj, members,
- "", &error);
- g_assert (error == NULL);
- g_array_free (members, TRUE);
- }
- return obj;
-}
-
-static void
-properties_disco_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *query_result,
- GError *error,
- gpointer user_data)
-{
- GabbleMucChannel *chan = user_data;
- GabbleMucChannelPrivate *priv;
- TpIntSet *changed_props_val, *changed_props_flags;
- LmMessageNode *lm_node;
- const gchar *str;
- GValue val = { 0, };
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- if (error)
- {
- DEBUG ("got error %s", error->message);
- return;
- }
-
- changed_props_val = tp_intset_sized_new (NUM_ROOM_PROPS);
- changed_props_flags = tp_intset_sized_new (NUM_ROOM_PROPS);
-
- /*
- * Update room definition.
- */
-
- /* ROOM_PROP_NAME */
- lm_node = lm_message_node_get_child (query_result, "identity");
- if (lm_node)
- {
- const gchar *type, *category, *name;
-
- type = lm_message_node_get_attribute (lm_node, "type");
- category = lm_message_node_get_attribute (lm_node, "category");
- name = lm_message_node_get_attribute (lm_node, "name");
-
- if (NULL != type && 0 == strcmp (type, "text") &&
- NULL != category && 0 == strcmp (category, "conference") &&
- NULL != name)
- {
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, name);
-
- tp_properties_mixin_change_value (G_OBJECT (chan), ROOM_PROP_NAME,
- &val, changed_props_val);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan), ROOM_PROP_NAME,
- TP_PROPERTY_FLAG_READ,
- 0, changed_props_flags);
-
- g_value_unset (&val);
- }
- }
-
- for (lm_node = query_result->children; lm_node; lm_node = lm_node->next)
- {
- guint prop_id = INVALID_ROOM_PROP;
-
- if (strcmp (lm_node->name, "feature") == 0)
- {
- str = lm_message_node_get_attribute (lm_node, "var");
- if (str == NULL)
- continue;
-
- /* ROOM_PROP_ANONYMOUS */
- if (strcmp (str, "muc_nonanonymous") == 0)
- {
- prop_id = ROOM_PROP_ANONYMOUS;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, FALSE);
- }
- else if (strcmp (str, "muc_semianonymous") == 0 ||
- strcmp (str, "muc_anonymous") == 0)
- {
- prop_id = ROOM_PROP_ANONYMOUS;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, TRUE);
- }
-
- /* ROOM_PROP_INVITE_ONLY */
- else if (strcmp (str, "muc_open") == 0)
- {
- prop_id = ROOM_PROP_INVITE_ONLY;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, FALSE);
- }
- else if (strcmp (str, "muc_membersonly") == 0)
- {
- prop_id = ROOM_PROP_INVITE_ONLY;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, TRUE);
- }
-
- /* ROOM_PROP_MODERATED */
- else if (strcmp (str, "muc_unmoderated") == 0)
- {
- prop_id = ROOM_PROP_MODERATED;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, FALSE);
- }
- else if (strcmp (str, "muc_moderated") == 0)
- {
- prop_id = ROOM_PROP_MODERATED;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, TRUE);
- }
-
- /* ROOM_PROP_PASSWORD_REQUIRED */
- else if (strcmp (str, "muc_unsecure") == 0 ||
- strcmp (str, "muc_unsecured") == 0)
- {
- prop_id = ROOM_PROP_PASSWORD_REQUIRED;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, FALSE);
- }
- else if (strcmp (str, "muc_passwordprotected") == 0)
- {
- prop_id = ROOM_PROP_PASSWORD_REQUIRED;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, TRUE);
- }
-
- /* ROOM_PROP_PERSISTENT */
- else if (strcmp (str, "muc_temporary") == 0)
- {
- prop_id = ROOM_PROP_PERSISTENT;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, FALSE);
- }
- else if (strcmp (str, "muc_persistent") == 0)
- {
- prop_id = ROOM_PROP_PERSISTENT;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, TRUE);
- }
-
- /* ROOM_PROP_PRIVATE */
- else if (strcmp (str, "muc_public") == 0)
- {
- prop_id = ROOM_PROP_PRIVATE;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, FALSE);
- }
- else if (strcmp (str, "muc_hidden") == 0)
- {
- prop_id = ROOM_PROP_PRIVATE;
- g_value_init (&val, G_TYPE_BOOLEAN);
- g_value_set_boolean (&val, TRUE);
- }
-
- /* Ignored */
- else if (strcmp (str, NS_MUC) == 0)
- {
- }
-
- /* Unhandled */
- else
- {
- g_warning ("%s: unhandled feature '%s'", G_STRFUNC, str);
- }
- }
- else if (strcmp (lm_node->name, "x") == 0)
- {
- if (lm_message_node_has_namespace (lm_node, NS_X_DATA, NULL))
- {
- LmMessageNode *field, *value_node;
-
- for (field = lm_node->children; field; field = field->next)
- {
- if (strcmp (field->name, "field") != 0)
- continue;
-
- str = lm_message_node_get_attribute (field, "var");
- if (str == NULL)
- continue;
-
- if (strcmp (str, "muc#roominfo_description") != 0)
- continue;
-
- value_node = lm_message_node_get_child (field, "value");
- if (value_node == NULL)
- continue;
-
- str = lm_message_node_get_value (value_node);
- if (str == NULL)
- {
- str = "";
- }
-
- prop_id = ROOM_PROP_DESCRIPTION;
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, str);
- }
- }
- }
-
- if (prop_id != INVALID_ROOM_PROP)
- {
- tp_properties_mixin_change_value (G_OBJECT (chan), prop_id, &val,
- changed_props_val);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan), prop_id,
- TP_PROPERTY_FLAG_READ,
- 0, changed_props_flags);
-
- g_value_unset (&val);
- }
- }
-
- /*
- * Emit signals.
- */
- tp_properties_mixin_emit_changed (G_OBJECT (chan), changed_props_val);
- tp_properties_mixin_emit_flags (G_OBJECT (chan), changed_props_flags);
- tp_intset_destroy (changed_props_val);
- tp_intset_destroy (changed_props_flags);
-}
-
-static void
-room_properties_update (GabbleMucChannel *chan)
-{
- GabbleMucChannelPrivate *priv;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- if (gabble_disco_request (priv->conn->disco, GABBLE_DISCO_TYPE_INFO,
- priv->jid, NULL, properties_disco_cb, chan, G_OBJECT (chan),
- &error) == NULL)
- {
- g_warning ("%s: disco query failed: '%s'", G_STRFUNC, error->message);
- g_error_free (error);
- }
-}
-
-static void
-contact_handle_to_room_identity (GabbleMucChannel *chan, TpHandle main_handle,
- TpHandle *room_handle, GString **room_jid)
-{
- GabbleMucChannelPrivate *priv;
- TpBaseConnection *conn;
- TpHandleRepoIface *contact_repo;
- const gchar *main_jid;
- gchar *username, *jid;
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
- conn = (TpBaseConnection *)priv->conn;
- contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT);
-
- main_jid = tp_handle_inspect (contact_repo, main_handle);
-
- gabble_decode_jid (main_jid, &username, NULL, NULL);
-
- jid = g_strdup_printf ("%s/%s", priv->jid, username);
-
- g_free (username);
-
- if (room_handle)
- {
- *room_handle = tp_handle_ensure (contact_repo, jid,
- GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL);
- }
-
- if (room_jid)
- {
- *room_jid = g_string_new (jid);
- }
-
- g_free (jid);
-}
-
-static gboolean
-send_join_request (GabbleMucChannel *channel,
- const gchar *password,
- GError **error)
-{
- GabbleMucChannelPrivate *priv;
- LmMessage *msg;
- LmMessageNode *x_node;
- gboolean ret;
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (channel);
-
- /* build the message */
- msg = lm_message_new (priv->self_jid->str, LM_MESSAGE_TYPE_PRESENCE);
-
- x_node = lm_message_node_add_child (msg->node, "x", NULL);
- lm_message_node_set_attribute (x_node, "xmlns", NS_MUC);
-
- g_free (priv->password);
-
- if (password != NULL)
- {
- priv->password = g_strdup (password);
- lm_message_node_add_child (x_node, "password", password);
- }
-
- /* send it */
- ret = _gabble_connection_send (priv->conn, msg, error);
- if (!ret)
- {
- g_warning ("%s: _gabble_connection_send_with_reply failed", G_STRFUNC);
- }
- else
- {
- DEBUG ("join request sent");
- }
-
- lm_message_unref (msg);
-
- return ret;
-}
-
-static gboolean
-send_leave_message (GabbleMucChannel *channel,
- const gchar *reason)
-{
- GabbleMucChannelPrivate *priv;
- LmMessage *msg;
- GError *error = NULL;
- gboolean ret;
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (channel);
-
- /* build the message */
- msg = lm_message_new_with_sub_type (priv->self_jid->str,
- LM_MESSAGE_TYPE_PRESENCE,
- LM_MESSAGE_SUB_TYPE_UNAVAILABLE);
-
- if (reason != NULL)
- {
- lm_message_node_add_child (msg->node, "status", reason);
- }
-
- /* send it */
- ret = _gabble_connection_send (priv->conn, msg, &error);
- if (!ret)
- {
- g_warning ("%s: _gabble_connection_send_with_reply failed", G_STRFUNC);
- g_error_free (error);
- }
- else
- {
- DEBUG ("leave message sent");
- }
-
- lm_message_unref (msg);
-
- return ret;
-}
-
-static void
-gabble_muc_channel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleMucChannel *chan = GABBLE_MUC_CHANNEL (object);
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TEXT);
- break;
- case PROP_HANDLE_TYPE:
- g_value_set_uint (value, TP_HANDLE_TYPE_ROOM);
- break;
- case PROP_HANDLE:
- g_value_set_uint (value, priv->handle);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_STATE:
- g_value_set_uint (value, priv->state);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void channel_state_changed (GabbleMucChannel *chan,
- GabbleMucState prev_state,
- GabbleMucState new_state);
-
-static void
-gabble_muc_channel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleMucChannel *chan = GABBLE_MUC_CHANNEL (object);
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
- GabbleMucState prev_state;
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_HANDLE:
- priv->handle = g_value_get_uint (value);
- break;
- case PROP_HANDLE_TYPE:
- /* this property is writable in the interface, but not actually
- * meaningfully changable on this channel, so we do nothing */
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_STATE:
- prev_state = priv->state;
- priv->state = g_value_get_uint (value);
-
- if (priv->state != prev_state)
- channel_state_changed (chan, prev_state, priv->state);
-
- break;
- case PROP_INVITE_SELF:
- priv->invite_self = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_muc_channel_dispose (GObject *object);
-static void gabble_muc_channel_finalize (GObject *object);
-static gboolean gabble_muc_channel_add_member (GObject *obj, TpHandle handle,
- const gchar *message, GError **error);
-static gboolean gabble_muc_channel_remove_member (GObject *obj,
- TpHandle handle, const gchar *message, GError **error);
-static gboolean gabble_muc_channel_do_set_properties (GObject *obj,
- TpPropertiesContext *ctx, GError **error);
-
-static void
-gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_muc_channel_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_muc_channel_class,
- sizeof (GabbleMucChannelPrivate));
-
- object_class->constructor = gabble_muc_channel_constructor;
-
- object_class->get_property = gabble_muc_channel_get_property;
- object_class->set_property = gabble_muc_channel_set_property;
-
- object_class->dispose = gabble_muc_channel_dispose;
- object_class->finalize = gabble_muc_channel_finalize;
-
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
- g_object_class_override_property (object_class, PROP_HANDLE, "handle");
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "MUC channel object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_uint ("state", "Channel state",
- "The current state that the channel is in.",
- 0, G_MAXUINT32, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- param_spec = g_param_spec_boolean ("invite-self", "Invite self",
- "Whether the user should be added to members list.", FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_INVITE_SELF, param_spec);
-
- signals[READY] =
- g_signal_new ("ready",
- G_OBJECT_CLASS_TYPE (gabble_muc_channel_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[JOIN_ERROR] =
- g_signal_new ("join-error",
- G_OBJECT_CLASS_TYPE (gabble_muc_channel_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-
- tp_group_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleMucChannelClass,
- group_class),
- gabble_muc_channel_add_member,
- gabble_muc_channel_remove_member);
-
- tp_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleMucChannelClass,
- properties_class),
- room_property_signatures, NUM_ROOM_PROPS,
- gabble_muc_channel_do_set_properties);
-
- tp_text_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleMucChannelClass, text_class));
-}
-
-static void clear_join_timer (GabbleMucChannel *chan);
-static void clear_poll_timer (GabbleMucChannel *chan);
-
-void
-gabble_muc_channel_dispose (GObject *object)
-{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (object);
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("called");
-
- priv->dispose_has_run = TRUE;
-
- clear_join_timer (self);
- clear_poll_timer (self);
-
- if (G_OBJECT_CLASS (gabble_muc_channel_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_muc_channel_parent_class)->dispose (object);
-}
-
-void
-gabble_muc_channel_finalize (GObject *object)
-{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (object);
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (self);
- TpHandleRepoIface *room_handles = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_ROOM);
-
- DEBUG ("called");
-
- /* free any data held directly by the object here */
- tp_handle_unref (room_handles, priv->handle);
-
- g_free (priv->object_path);
-
- if (priv->self_jid)
- {
- g_string_free (priv->self_jid, TRUE);
- }
-
- g_free (priv->password);
-
- tp_properties_mixin_finalize (object);
-
- tp_group_mixin_finalize (object);
-
- tp_text_mixin_finalize (object);
-
- G_OBJECT_CLASS (gabble_muc_channel_parent_class)->finalize (object);
-}
-
-static void clear_join_timer (GabbleMucChannel *chan)
-{
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- if (priv->join_timer_id != 0)
- {
- g_source_remove (priv->join_timer_id);
- priv->join_timer_id = 0;
- }
-}
-
-static void clear_poll_timer (GabbleMucChannel *chan)
-{
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- if (priv->poll_timer_id != 0)
- {
- g_source_remove (priv->poll_timer_id);
- priv->poll_timer_id = 0;
- }
-}
-
-static void
-change_password_flags (GabbleMucChannel *chan,
- TpChannelPasswordFlags add,
- TpChannelPasswordFlags remove)
-{
- GabbleMucChannelPrivate *priv;
- TpChannelPasswordFlags added, removed;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- added = add & ~priv->password_flags;
- priv->password_flags |= added;
-
- removed = remove & priv->password_flags;
- priv->password_flags &= ~removed;
-
- if (add != 0 || remove != 0)
- {
- DEBUG ("emitting password flags changed, added 0x%X, removed 0x%X",
- added, removed);
-
- tp_svc_channel_interface_password_emit_password_flags_changed (
- chan, added, removed);
- }
-}
-
-static void
-provide_password_return_if_pending (GabbleMucChannel *chan, gboolean success)
-{
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- if (priv->password_ctx)
- {
- dbus_g_method_return (priv->password_ctx, success);
- priv->password_ctx = NULL;
- }
-
- if (success)
- {
- change_password_flags (chan, 0, TP_CHANNEL_PASSWORD_FLAG_PROVIDE);
- }
-}
-
-static void close_channel (GabbleMucChannel *chan, const gchar *reason,
- gboolean inform_muc, TpHandle actor, guint reason_code);
-
-static gboolean
-timeout_join (gpointer data)
-{
- GabbleMucChannel *chan = data;
-
- DEBUG ("join timed out, closing channel");
-
- provide_password_return_if_pending (chan, FALSE);
-
- close_channel (chan, NULL, FALSE, 0, 0);
-
- return FALSE;
-}
-
-static gboolean
-timeout_poll (gpointer data)
-{
- GabbleMucChannel *chan = data;
-
- DEBUG ("polling for room properties");
-
- room_properties_update (chan);
-
- return TRUE;
-}
-
-static void
-channel_state_changed (GabbleMucChannel *chan,
- GabbleMucState prev_state,
- GabbleMucState new_state)
-{
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- DEBUG ("state changed from %s to %s", muc_states[prev_state],
- muc_states[new_state]);
-
- if (new_state == MUC_STATE_INITIATED)
- {
- priv->join_timer_id =
- g_timeout_add (DEFAULT_JOIN_TIMEOUT, timeout_join, chan);
- }
- else if (new_state == MUC_STATE_JOINED)
- {
- gboolean low_bandwidth;
- gint interval;
-
- provide_password_return_if_pending (chan, TRUE);
-
- clear_join_timer (chan);
-
- g_object_get (priv->conn, "low-bandwidth", &low_bandwidth, NULL);
-
- if (low_bandwidth)
- interval = PROPS_POLL_INTERVAL_LOW;
- else
- interval = PROPS_POLL_INTERVAL_HIGH;
-
- priv->poll_timer_id = g_timeout_add (interval, timeout_poll, chan);
-
- /* no need to keep this around any longer, if it's set */
- g_free (priv->password);
- priv->password = NULL;
- }
- else if (new_state == MUC_STATE_ENDED)
- {
- clear_poll_timer (chan);
- }
-
- if (new_state == MUC_STATE_JOINED || new_state == MUC_STATE_AUTH)
- {
- if (!priv->ready_emitted)
- {
- g_signal_emit (chan, signals[READY], 0);
-
- priv->ready_emitted = TRUE;
- }
- }
-}
-
-
-static void
-close_channel (GabbleMucChannel *chan, const gchar *reason,
- gboolean inform_muc, TpHandle actor, guint reason_code)
-{
- GabbleMucChannelPrivate *priv;
- TpIntSet *set;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- if (priv->closed)
- return;
-
- priv->closed = TRUE;
-
- /* Remove us from member list */
- set = tp_intset_new ();
- tp_intset_add (set, TP_GROUP_MIXIN (chan)->self_handle);
-
- tp_group_mixin_change_members ((GObject *)chan,
- (reason != NULL) ? reason : "",
- NULL, set, NULL, NULL, actor,
- reason_code);
-
- tp_intset_destroy (set);
-
- /* Inform the MUC if requested */
- if (inform_muc && priv->state >= MUC_STATE_INITIATED)
- {
- send_leave_message (chan, reason);
- }
-
- /* Update state and emit Closed signal */
- g_object_set (chan, "state", MUC_STATE_ENDED, NULL);
-
- tp_svc_channel_emit_closed (chan);
-}
-
-gboolean
-_gabble_muc_channel_is_ready (GabbleMucChannel *chan)
-{
- GabbleMucChannelPrivate *priv;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- return priv->ready_emitted;
-}
-
-/**
- * _gabble_muc_channel_presence_error
- */
-void
-_gabble_muc_channel_presence_error (GabbleMucChannel *chan,
- const gchar *jid,
- LmMessageNode *pres_node)
-{
- GabbleMucChannelPrivate *priv;
- LmMessageNode *error_node;
- GabbleXmppError error;
- TpHandle actor = 0;
- guint reason_code = TP_CHANNEL_GROUP_CHANGE_REASON_NONE;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- if (strcmp (jid, priv->self_jid->str) != 0)
- {
- g_warning ("%s: presence error from other jids than self not handled",
- G_STRFUNC);
- return;
- }
-
- error_node = lm_message_node_get_child (pres_node, "error");
- if (error_node == NULL)
- {
- g_warning ("%s: missing required node 'error'", G_STRFUNC);
- return;
- }
-
- error = gabble_xmpp_error_from_node (error_node);
-
- if (priv->state >= MUC_STATE_JOINED)
- {
- g_warning ("%s: presence error while already member of the channel "
- "-- NYI", G_STRFUNC);
- return;
- }
-
- /* We're not a member, find out why the join request failed
- * and act accordingly. */
- if (error == XMPP_ERROR_NOT_AUTHORIZED)
- {
- /* channel can sit requiring a password indefinitely */
- clear_join_timer (chan);
-
- /* Password already provided and incorrect? */
- if (priv->state == MUC_STATE_AUTH)
- {
- provide_password_return_if_pending (chan, FALSE);
-
- return;
- }
-
- DEBUG ("password required to join, changing password flags");
-
- change_password_flags (chan, TP_CHANNEL_PASSWORD_FLAG_PROVIDE, 0);
-
- g_object_set (chan, "state", MUC_STATE_AUTH, NULL);
- }
- else
- {
- GError *tp_error /* doesn't need initializing */;
-
- switch (error) {
- case XMPP_ERROR_FORBIDDEN:
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_CHANNEL_BANNED,
- "banned from room");
- reason_code = TP_CHANNEL_GROUP_CHANGE_REASON_BANNED;
- break;
- case XMPP_ERROR_SERVICE_UNAVAILABLE:
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_CHANNEL_FULL,
- "room is full");
- break;
- case XMPP_ERROR_REGISTRATION_REQUIRED:
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_CHANNEL_INVITE_ONLY,
- "room is invite only");
- break;
- case XMPP_ERROR_CONFLICT:
- if (priv->nick_retry_count < MAX_NICK_RETRIES)
- {
- g_string_append_c (priv->self_jid, '_');
-
- if (send_join_request (chan, priv->password, &tp_error))
- {
- priv->nick_retry_count++;
- return;
- }
- }
- else
- {
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "nickname already in use and retry count exceeded");
- }
- break;
- default:
- if (error != INVALID_XMPP_ERROR)
- {
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- gabble_xmpp_error_description (error));
- }
- else
- {
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "unknown error");
- }
- break;
- }
-
- g_signal_emit (chan, signals[JOIN_ERROR], 0, tp_error);
-
- close_channel (chan, tp_error->message, FALSE, actor, reason_code);
-
- g_error_free (tp_error);
- }
-}
-
-static GabbleMucRole
-get_role_from_string (const gchar *role)
-{
- guint i;
-
- if (role == NULL)
- {
- return ROLE_VISITOR;
- }
-
- for (i = 0; i < NUM_ROLES; i++)
- {
- if (strcmp (role, muc_roles[i]) == 0)
- {
- return i;
- }
- }
-
- g_warning ("%s: unknown role '%s' -- defaulting to ROLE_VISITOR",
- G_STRFUNC, role);
-
- return ROLE_VISITOR;
-}
-
-static GabbleMucAffiliation
-get_affiliation_from_string (const gchar *affil)
-{
- guint i;
-
- if (affil == NULL)
- {
- return AFFILIATION_NONE;
- }
-
- for (i = 0; i < NUM_AFFILIATIONS; i++)
- {
- if (strcmp (affil, muc_affiliations[i]) == 0)
- {
- return i;
- }
- }
-
- g_warning ("%s: unknown affiliation '%s' -- defaulting to "
- "AFFILIATION_NONE", G_STRFUNC, affil);
-
- return AFFILIATION_NONE;
-}
-
-static LmHandlerResult
-room_created_submit_reply_cb (GabbleConnection *conn, LmMessage *sent_msg,
- LmMessage *reply_msg, GObject *object,
- gpointer user_data)
-{
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- g_warning ("%s: failed to submit room config", G_STRFUNC);
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static LmMessageNode *
-config_form_get_form_node (LmMessage *msg)
-{
- LmMessageNode *node;
-
- /* find the query node */
- node = lm_message_node_get_child (msg->node, "query");
- if (node == NULL)
- return NULL;
-
- /* then the form node */
- for (node = node->children; node; node = node->next)
- {
- if (tp_strdiff (node->name, "x"))
- {
- continue;
- }
-
- if (!lm_message_node_has_namespace (node, NS_X_DATA, NULL))
- {
- continue;
- }
-
- if (tp_strdiff (lm_message_node_get_attribute (node, "type"), "form"))
- {
- continue;
- }
-
- return node;
- }
-
- return NULL;
-}
-
-static LmHandlerResult
-perms_config_form_reply_cb (GabbleConnection *conn, LmMessage *sent_msg,
- LmMessage *reply_msg, GObject *object,
- gpointer user_data)
-{
- GabbleMucChannel *chan = GABBLE_MUC_CHANNEL (object);
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
- LmMessageNode *form_node, *node;
-
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- g_warning ("%s: request for config form denied, property permissions "
- "will be inaccurate", G_STRFUNC);
- goto OUT;
- }
-
- /* just in case our affiliation has changed in the meantime */
- if (priv->self_affil != AFFILIATION_OWNER)
- goto OUT;
-
- form_node = config_form_get_form_node (reply_msg);
- if (form_node == NULL)
- {
- g_warning ("%s: form node node found, property permissions will be "
- "inaccurate", G_STRFUNC);
- goto OUT;
- }
-
- for (node = form_node->children; node; node = node->next)
- {
- const gchar *var;
-
- if (strcmp (node->name, "field") != 0)
- continue;
-
- var = lm_message_node_get_attribute (node, "var");
- if (var == NULL)
- continue;
-
- if (strcmp (var, "muc#roomconfig_roomdesc") == 0 ||
- strcmp (var, "muc#owner_roomdesc") == 0)
- {
- if (tp_properties_mixin_is_readable (G_OBJECT (chan),
- ROOM_PROP_DESCRIPTION))
- {
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_DESCRIPTION, TP_PROPERTY_FLAG_WRITE, 0,
- NULL);
-
- goto OUT;
- }
- }
- }
-
-OUT:
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-update_permissions (GabbleMucChannel *chan)
-{
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
- TpChannelGroupFlags grp_flags_add, grp_flags_rem;
- TpPropertyFlags prop_flags_add, prop_flags_rem;
- TpIntSet *changed_props_val, *changed_props_flags;
-
- /*
- * Update group flags.
- */
- grp_flags_add = TP_CHANNEL_GROUP_FLAG_CAN_ADD |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_ADD;
- grp_flags_rem = 0;
-
- if (priv->self_role == ROLE_MODERATOR)
- {
- grp_flags_add |= TP_CHANNEL_GROUP_FLAG_CAN_REMOVE |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE;
- }
- else
- {
- grp_flags_rem |= TP_CHANNEL_GROUP_FLAG_CAN_REMOVE |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE;
- }
-
- tp_group_mixin_change_flags ((GObject *) chan, grp_flags_add, grp_flags_rem);
-
-
- /*
- * Update write capabilities based on room configuration
- * and own role and affiliation.
- */
-
- changed_props_val = tp_intset_sized_new (NUM_ROOM_PROPS);
- changed_props_flags = tp_intset_sized_new (NUM_ROOM_PROPS);
-
- /*
- * Subject
- *
- * FIXME: this might be allowed for participants/moderators only,
- * so for now just rely on the server making that call.
- */
-
- if (priv->self_role >= ROLE_VISITOR)
- {
- prop_flags_add = TP_PROPERTY_FLAG_WRITE;
- prop_flags_rem = 0;
- }
- else
- {
- prop_flags_add = 0;
- prop_flags_rem = TP_PROPERTY_FLAG_WRITE;
- }
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_SUBJECT, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- /* Room definition */
- if (priv->self_affil == AFFILIATION_OWNER)
- {
- prop_flags_add = TP_PROPERTY_FLAG_WRITE;
- prop_flags_rem = 0;
- }
- else
- {
- prop_flags_add = 0;
- prop_flags_rem = TP_PROPERTY_FLAG_WRITE;
- }
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_ANONYMOUS, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_INVITE_ONLY, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_MODERATED, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_NAME, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_PASSWORD, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_PASSWORD_REQUIRED, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_PERSISTENT, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_PRIVATE, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_SUBJECT, prop_flags_add, prop_flags_rem,
- changed_props_flags);
-
- if (priv->self_affil == AFFILIATION_OWNER)
- {
- /* request the configuration form purely to see if the description
- * is writable by us in this room. sigh. GO MUC!!! */
- LmMessage *msg;
- LmMessageNode *node;
- GError *error = NULL;
- gboolean success;
-
- msg = lm_message_new_with_sub_type (priv->jid,
- LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
- node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (node, "xmlns", NS_MUC_OWNER);
-
- success = _gabble_connection_send_with_reply (priv->conn, msg,
- perms_config_form_reply_cb, G_OBJECT (chan), NULL,
- &error);
-
- lm_message_unref (msg);
-
- if (!success)
- {
- g_warning ("%s: failed to request config form: %s",
- G_STRFUNC, error->message);
- g_error_free (error);
- }
- }
- else
- {
- /* mark description unwritable if we're no longer an owner */
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_DESCRIPTION, 0, TP_PROPERTY_FLAG_WRITE,
- changed_props_flags);
- }
-
- /*
- * Emit signals.
- */
- tp_properties_mixin_emit_changed (G_OBJECT (chan), changed_props_val);
- tp_properties_mixin_emit_flags (G_OBJECT (chan), changed_props_flags);
- tp_intset_destroy (changed_props_val);
- tp_intset_destroy (changed_props_flags);
-}
-
-/**
- * _gabble_muc_channel_member_presence_updated
- */
-void
-_gabble_muc_channel_member_presence_updated (GabbleMucChannel *chan,
- TpHandle handle,
- LmMessage *message,
- LmMessageNode *x_node)
-{
- GabbleMucChannelPrivate *priv;
- TpBaseConnection *conn;
- TpIntSet *set;
- TpGroupMixin *mixin;
- LmMessageNode *item_node, *node;
- const gchar *affil, *role, *owner_jid, *status_code;
- TpHandle actor = 0;
- guint reason_code = TP_CHANNEL_GROUP_CHANGE_REASON_NONE;
- TpHandleRepoIface *contact_handles;
-
- DEBUG ("called");
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
- conn = (TpBaseConnection *)priv->conn;
- contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- mixin = TP_GROUP_MIXIN (chan);
-
- item_node = lm_message_node_get_child (x_node, "item");
- if (item_node == NULL)
- {
- g_warning ("%s: node missing 'item' child, ignoring", G_STRFUNC);
- return;
- }
-
- node = lm_message_node_get_child (x_node, "status");
- if (node)
- {
- status_code = lm_message_node_get_attribute (node, "code");
- }
- else
- {
- status_code = NULL;
- }
-
- role = lm_message_node_get_attribute (item_node, "role");
- affil = lm_message_node_get_attribute (item_node, "affiliation");
- owner_jid = lm_message_node_get_attribute (item_node, "jid");
-
- /* update channel members according to presence */
- set = tp_intset_new ();
- tp_intset_add (set, handle);
-
- if (lm_message_get_sub_type (message) != LM_MESSAGE_SUB_TYPE_UNAVAILABLE)
- {
- if (!tp_handle_set_is_member (mixin->members, handle))
- {
- tp_group_mixin_change_members ((GObject *)chan, "", set, NULL,
- NULL, NULL, 0, 0);
-
- if (owner_jid != NULL)
- {
- TpHandle owner_handle;
-
- owner_handle = tp_handle_ensure (contact_handles, owner_jid,
- GUINT_TO_POINTER (GABBLE_JID_GLOBAL), NULL);
- if (owner_handle == 0)
- {
- DEBUG ("ignoring invalid owner JID %s in MUC presence",
- owner_jid);
- }
- else
- {
- tp_group_mixin_add_handle_owner ((GObject *)chan, handle,
- owner_handle);
- tp_handle_unref (contact_handles, owner_handle);
- }
- }
-
- if (handle == mixin->self_handle)
- {
- g_object_set (chan, "state", MUC_STATE_JOINED, NULL);
- }
- }
-
- if (handle == mixin->self_handle)
- {
- GabbleMucRole new_role;
- GabbleMucAffiliation new_affil;
-
- /* accept newly-created room settings before we send anything
- * below which queryies them. */
- if (status_code && strcmp (status_code, "201") == 0)
- {
- LmMessage *msg;
- GError *error = NULL;
-
- msg = lm_message_new_with_sub_type (priv->jid,
- LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET);
-
- node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (node, "xmlns", NS_MUC_OWNER);
-
- node = lm_message_node_add_child (node, "x", NULL);
- lm_message_node_set_attributes (node,
- "xmlns", NS_X_DATA,
- "type", "submit",
- NULL);
-
- if (!_gabble_connection_send_with_reply (priv->conn, msg,
- room_created_submit_reply_cb, G_OBJECT (chan), NULL,
- &error))
- {
- g_warning ("%s: failed to send submit message: %s",
- G_STRFUNC, error->message);
- g_error_free (error);
-
- lm_message_unref (msg);
- close_channel (chan, NULL, TRUE, actor, reason_code);
-
- goto OUT;
- }
-
- lm_message_unref (msg);
- }
-
- /* Update room properties */
- room_properties_update (chan);
-
- /* update permissions after requesting new properties so that if we
- * become an owner, we get our configuration form reply after the
- * discovery reply, so we know whether there is a description
- * property before we try and decide whether we can write to it. */
- new_role = get_role_from_string (role);
- new_affil = get_affiliation_from_string (affil);
-
- if (new_role != priv->self_role || new_affil != priv->self_affil)
- {
- priv->self_role = new_role;
- priv->self_affil = new_affil;
-
- update_permissions (chan);
- }
- }
- }
- else
- {
- LmMessageNode *reason_node, *actor_node;
- const gchar *reason = "", *actor_jid = "";
-
- actor_node = lm_message_node_get_child (item_node, "actor");
- if (actor_node != NULL)
- {
- actor_jid = lm_message_node_get_attribute (actor_node, "jid");
- if (actor_jid != NULL)
- {
- actor = tp_handle_ensure (contact_handles, actor_jid, NULL,
- NULL);
- if (actor == 0)
- {
- DEBUG ("ignoring invalid actor JID %s", actor_jid);
- }
- }
- }
-
- /* Possible reasons we could have been removed from the room:
- * 301 banned
- * 307 kicked
- * 321 "because of an affiliation change" - no reason_code
- * 322 room has become members-only and we're not a member - no
- * reason_code
- * 332 system (server) is being shut down - no reason code
- */
- if (status_code)
- {
- if (strcmp (status_code, "301") == 0)
- {
- reason_code = TP_CHANNEL_GROUP_CHANGE_REASON_BANNED;
- }
- else if (strcmp (status_code, "307") == 0)
- {
- reason_code = TP_CHANNEL_GROUP_CHANGE_REASON_KICKED;
- }
- }
-
- reason_node = lm_message_node_get_child (item_node, "reason");
- if (reason_node != NULL)
- {
- reason = lm_message_node_get_value (reason_node);
- }
-
- if (handle != mixin->self_handle)
- {
- tp_group_mixin_change_members ((GObject *)chan, reason,
- NULL, set, NULL, NULL,
- actor, reason_code);
- }
- else
- {
- close_channel (chan, reason, FALSE, actor, reason_code);
- }
- }
-
-OUT:
- tp_intset_destroy (set);
- if (actor)
- tp_handle_unref (contact_handles, actor);
-}
-
-
-/**
- * _gabble_muc_channel_receive
- */
-void
-_gabble_muc_channel_receive (GabbleMucChannel *chan,
- TpChannelTextMessageType msg_type,
- TpHandleType handle_type,
- TpHandle sender,
- time_t timestamp,
- const gchar *text,
- LmMessage *msg)
-{
- gboolean error;
- GabbleMucChannelPrivate *priv;
- LmMessageNode *subj_node, *node;
- GValue val = { 0, };
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- error = lm_message_get_sub_type (msg) == LM_MESSAGE_SUB_TYPE_ERROR;
-
- subj_node = lm_message_node_get_child (msg->node, "subject");
-
- if (subj_node)
- {
- TpIntSet *changed_values, *changed_flags;
-
- if (priv->properties_ctx)
- {
- tp_properties_context_remove (priv->properties_ctx,
- ROOM_PROP_SUBJECT);
- }
-
- if (error)
- {
- GabbleXmppError xmpp_error = INVALID_XMPP_ERROR;
- const gchar *err_desc = NULL;
-
- node = lm_message_node_get_child (msg->node, "error");
- if (node)
- {
- xmpp_error = gabble_xmpp_error_from_node (node);
- }
-
- if (xmpp_error != INVALID_XMPP_ERROR)
- {
- err_desc = gabble_xmpp_error_description (xmpp_error);
- }
-
- if (priv->properties_ctx)
- {
- GError *error = NULL;
-
- error = g_error_new (TP_ERRORS, TP_ERROR_PERMISSION_DENIED,
- (err_desc) ? err_desc : "failed to change subject");
-
- tp_properties_context_return (priv->properties_ctx, error);
- priv->properties_ctx = NULL;
-
- /* Get the properties into a consistent state. */
- room_properties_update (chan);
- }
-
- return;
- }
-
- changed_values = tp_intset_sized_new (NUM_ROOM_PROPS);
- changed_flags = tp_intset_sized_new (NUM_ROOM_PROPS);
-
- /* ROOM_PROP_SUBJECT */
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, lm_message_node_get_value (subj_node));
-
- tp_properties_mixin_change_value (G_OBJECT (chan),
- ROOM_PROP_SUBJECT, &val, changed_values);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_SUBJECT, TP_PROPERTY_FLAG_READ, 0,
- changed_flags);
-
- g_value_unset (&val);
-
- if (handle_type == TP_HANDLE_TYPE_CONTACT)
- {
- /* ROOM_PROP_SUBJECT_CONTACT */
- g_value_init (&val, G_TYPE_UINT);
- g_value_set_uint (&val, sender);
-
- tp_properties_mixin_change_value (G_OBJECT (chan),
- ROOM_PROP_SUBJECT_CONTACT, &val, changed_values);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_SUBJECT_CONTACT, TP_PROPERTY_FLAG_READ, 0,
- changed_flags);
-
- g_value_unset (&val);
- }
-
- /* ROOM_PROP_SUBJECT_TIMESTAMP */
- g_value_init (&val, G_TYPE_UINT);
- g_value_set_uint (&val, timestamp);
-
- tp_properties_mixin_change_value (G_OBJECT (chan),
- ROOM_PROP_SUBJECT_TIMESTAMP, &val, changed_values);
-
- tp_properties_mixin_change_flags (G_OBJECT (chan),
- ROOM_PROP_SUBJECT_TIMESTAMP, TP_PROPERTY_FLAG_READ, 0,
- changed_flags);
-
- g_value_unset (&val);
-
- /* Emit signals */
- tp_properties_mixin_emit_changed (G_OBJECT (chan), changed_values);
- tp_properties_mixin_emit_flags (G_OBJECT (chan), changed_flags);
- tp_intset_destroy (changed_values);
- tp_intset_destroy (changed_flags);
-
- if (priv->properties_ctx)
- {
- if (tp_properties_context_return_if_done (priv->properties_ctx))
- {
- priv->properties_ctx = NULL;
- }
- }
-
- return;
- }
- else if (handle_type == TP_HANDLE_TYPE_ROOM)
- {
- NODE_DEBUG (msg->node, "ignoring message from channel");
-
- return;
- }
- else if ((sender == chan->group.self_handle) && (timestamp == 0))
- {
- /* If we sent the message and it's not delayed, just emit the sent
- signal */
- timestamp = time (NULL);
- tp_svc_channel_type_text_emit_sent (chan, timestamp, msg_type, text);
-
- return;
- }
-
- /* Receive messages from other contacts and our own if they're delayed, and
- * set the timestamp for non-delayed messages */
- if (timestamp == 0)
- timestamp = time (NULL);
-
- tp_text_mixin_receive (G_OBJECT (chan), msg_type, sender,
- timestamp, text);
-}
-
-void
-_gabble_muc_channel_handle_invited (GabbleMucChannel *chan,
- TpHandle inviter,
- const gchar *message)
-{
- GabbleMucChannelPrivate *priv;
- TpBaseConnection *conn;
- TpHandle self_handle;
- TpIntSet *set_members, *set_pending;
- TpHandleRepoIface *contact_handles;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
- conn = (TpBaseConnection *)priv->conn;
- contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- /* add ourself to local pending and the inviter to members */
- set_members = tp_intset_new ();
- set_pending = tp_intset_new ();
-
- tp_intset_add (set_members, inviter);
-
- /* get our own identity in the room */
- contact_handle_to_room_identity (chan, conn->self_handle,
- &self_handle, &priv->self_jid);
- tp_intset_add (set_pending, self_handle);
-
- tp_group_mixin_change_members ((GObject *)chan, message, set_members,
- NULL, set_pending, NULL, inviter,
- TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
-
- tp_intset_destroy (set_members);
- tp_intset_destroy (set_pending);
- tp_handle_unref (contact_handles, self_handle);
-
- /* queue the message */
- if (message && (message[0] != '\0'))
- {
- tp_text_mixin_receive (G_OBJECT (chan),
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, inviter,
- time (NULL), message);
- }
-
- /* emit READY signal so NewChannel is emitted */
- g_signal_emit (chan, signals[READY], 0);
- priv->ready_emitted = TRUE;
-}
-
-/**
- * _gabble_muc_channel_state_receive
- *
- * Send the D-BUS signal ChatStateChanged
- * on org.freedesktop.Telepathy.Channel.Interface.ChatState
- */
-void
-_gabble_muc_channel_state_receive (GabbleMucChannel *chan,
- guint state,
- guint from_handle)
-{
- GabbleMucChannelPrivate *priv;
-
- g_assert (state < NUM_TP_CHANNEL_CHAT_STATES);
- g_assert (GABBLE_IS_MUC_CHANNEL (chan));
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
-
- tp_svc_channel_interface_chat_state_emit_chat_state_changed (chan,
- from_handle, state);
-}
-
-/**
- * gabble_muc_channel_close
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_muc_channel_close (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface);
- GabbleMucChannelPrivate *priv;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (self));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (self);
-
- DEBUG ("called on %p", self);
-
- if (priv->closed)
- {
- GError already = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Channel already closed"};
- DEBUG ("channel already closed");
-
- dbus_g_method_return_error (context, &already);
- return;
- }
-
- close_channel (self, NULL, TRUE, 0, 0);
-
- tp_svc_channel_return_from_close (context);
-}
-
-
-/**
- * gabble_muc_channel_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_muc_channel_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_TEXT);
-}
-
-
-/**
- * gabble_muc_channel_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_muc_channel_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface);
- GabbleMucChannelPrivate *priv;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (self));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (self);
-
- tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_ROOM,
- priv->handle);
-}
-
-
-/**
- * gabble_muc_channel_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_muc_channel_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- const gchar *interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- TP_IFACE_CHANNEL_INTERFACE_PASSWORD,
- TP_IFACE_PROPERTIES_INTERFACE,
- TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE,
- NULL
- };
-
- tp_svc_channel_return_from_get_interfaces (context, interfaces);
-}
-
-
-/**
- * gabble_muc_channel_get_password_flags
- *
- * Implements D-Bus method GetPasswordFlags
- * on interface org.freedesktop.Telepathy.Channel.Interface.Password
- */
-static void
-gabble_muc_channel_get_password_flags (TpSvcChannelInterfacePassword *iface,
- DBusGMethodInvocation *context)
-{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface);
- GabbleMucChannelPrivate *priv;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (self));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (self);
-
- tp_svc_channel_interface_password_return_from_get_password_flags (context,
- priv->password_flags);
-}
-
-
-/**
- * gabble_muc_channel_provide_password
- *
- * Implements D-Bus method ProvidePassword
- * on interface org.freedesktop.Telepathy.Channel.Interface.Password
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-static void
-gabble_muc_channel_provide_password (TpSvcChannelInterfacePassword *iface,
- const gchar *password,
- DBusGMethodInvocation *context)
-{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface);
- GError *error = NULL;
- GabbleMucChannelPrivate *priv;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (self));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (self);
-
- if ((priv->password_flags & TP_CHANNEL_PASSWORD_FLAG_PROVIDE) == 0 ||
- priv->password_ctx != NULL)
- {
- error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "password cannot be provided in the current state");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- return;
- }
-
- if (!send_join_request (self, password, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- return;
- }
-
- priv->password_ctx = context;
-}
-
-
-/**
- * gabble_muc_channel_send
- *
- * Implements D-Bus method Send
- * on interface org.freedesktop.Telepathy.Channel.Type.Text
- */
-static void
-gabble_muc_channel_send (TpSvcChannelTypeText *iface,
- guint type,
- const gchar *text,
- DBusGMethodInvocation *context)
-{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface);
- GabbleMucChannelPrivate *priv;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (self));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (self);
-
- if (!gabble_text_mixin_send (G_OBJECT (self), type,
- LM_MESSAGE_SUB_TYPE_GROUPCHAT, TP_CHANNEL_CHAT_STATE_ACTIVE, priv->jid,
- text, priv->conn, FALSE /* emit_signal */, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- return;
- }
-
- tp_svc_channel_type_text_return_from_send (context);
-}
-
-
-static gboolean
-gabble_muc_channel_add_member (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error)
-{
- GabbleMucChannelPrivate *priv;
- TpGroupMixin *mixin;
- const gchar *jid;
- LmMessage *msg;
- LmMessageNode *x_node, *invite_node;
- gboolean result;
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (GABBLE_MUC_CHANNEL (obj));
-
- mixin = TP_GROUP_MIXIN (obj);
-
- if (handle == mixin->self_handle)
- {
- TpIntSet *set_empty, *set_members, *set_pending;
- GArray *arr_members;
-
- /* are we already a member or in remote pending? */
- if (tp_handle_set_is_member (mixin->members, handle) ||
- tp_handle_set_is_member (mixin->remote_pending, handle))
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "already a member or in remote pending");
-
- return FALSE;
- }
-
- /* add ourself to remote pending and remove the inviter's
- * main jid from the member list */
- set_empty = tp_intset_new ();
- set_members = tp_intset_new ();
- set_pending = tp_intset_new ();
-
- arr_members = tp_handle_set_to_array (mixin->members);
- if (arr_members->len > 0)
- {
- tp_intset_add (set_members, g_array_index (arr_members, guint, 0));
- }
- g_array_free (arr_members, TRUE);
-
- tp_intset_add (set_pending, handle);
-
- tp_group_mixin_change_members (obj, "", set_empty, set_members,
- set_empty, set_pending, 0, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
-
- tp_intset_destroy (set_empty);
- tp_intset_destroy (set_members);
- tp_intset_destroy (set_pending);
-
- /* seek to enter the room */
- result = send_join_request (GABBLE_MUC_CHANNEL (obj), NULL, error);
-
- g_object_set (obj, "state",
- (result) ? MUC_STATE_INITIATED : MUC_STATE_ENDED,
- NULL);
-
- /* deny adding */
- tp_group_mixin_change_flags (obj, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD);
-
- /* clear message queue (which might contain an invite reason) */
- tp_text_mixin_clear (obj);
-
- return result;
- }
-
- /* check that we're indeed a member when attempting to invite others */
- if (priv->state < MUC_STATE_JOINED)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "channel membership is required for inviting others");
-
- return FALSE;
- }
-
- msg = lm_message_new (priv->jid, LM_MESSAGE_TYPE_MESSAGE);
-
- x_node = lm_message_node_add_child (msg->node, "x", NULL);
- lm_message_node_set_attribute (x_node, "xmlns", NS_MUC_USER);
-
- invite_node = lm_message_node_add_child (x_node, "invite", NULL);
-
- jid = tp_handle_inspect (TP_GROUP_MIXIN (obj)->handle_repo, handle);
-
- lm_message_node_set_attribute (invite_node, "to", jid);
-
- if (*message != '\0')
- {
- lm_message_node_add_child (invite_node, "reason", message);
- }
-
- DEBUG ("sending MUC invitation for room %s to contact %u (%s) with reason "
- "\"%s\"", priv->jid, handle, jid, message);
-
- result = _gabble_connection_send (priv->conn, msg, error);
- lm_message_unref (msg);
-
- return result;
-}
-
-static LmHandlerResult
-kick_request_reply_cb (GabbleConnection *conn, LmMessage *sent_msg,
- LmMessage *reply_msg, GObject *object,
- gpointer user_data)
-{
- const gchar *jid = user_data;
-
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- g_warning ("%s: Failed to kick user %s from room", G_STRFUNC, jid);
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static gboolean
-gabble_muc_channel_remove_member (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error)
-{
- GabbleMucChannelPrivate *priv;
- LmMessage *msg;
- LmMessageNode *query_node, *item_node;
- const gchar *jid, *nick;
- gboolean result;
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (GABBLE_MUC_CHANNEL (obj));
-
- msg = lm_message_new_with_sub_type (priv->jid, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_SET);
-
- query_node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (query_node, "xmlns", NS_MUC_ADMIN);
-
- item_node = lm_message_node_add_child (query_node, "item", NULL);
-
- jid = tp_handle_inspect (TP_GROUP_MIXIN (obj)->handle_repo, handle);
-
- nick = strchr (jid, '/');
-
- lm_message_node_set_attributes (item_node,
- "nick", nick,
- "role", "none",
- NULL);
-
- if (*message != '\0')
- {
- lm_message_node_add_child (item_node, "reason", message);
- }
-
- DEBUG ("sending MUC kick request for contact %u (%s) to room %s with reason "
- "\"%s\"", handle, jid, priv->jid, message);
-
- result = _gabble_connection_send_with_reply (priv->conn, msg,
- kick_request_reply_cb,
- obj, (gpointer) jid,
- error);
-
- lm_message_unref (msg);
-
- return result;
-}
-
-
-static LmHandlerResult request_config_form_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg, LmMessage *reply_msg, GObject *object,
- gpointer user_data);
-
-static gboolean
-gabble_muc_channel_do_set_properties (GObject *obj,
- TpPropertiesContext *ctx,
- GError **error)
-{
- GabbleMucChannelPrivate *priv;
- LmMessage *msg;
- LmMessageNode *node;
- gboolean success;
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (GABBLE_MUC_CHANNEL (obj));
-
- g_assert (priv->properties_ctx == NULL);
-
- /* Changing subject? */
- if (tp_properties_context_has (ctx, ROOM_PROP_SUBJECT))
- {
- const gchar *str;
-
- str = g_value_get_string (tp_properties_context_get (ctx,
- ROOM_PROP_SUBJECT));
-
- msg = lm_message_new_with_sub_type (priv->jid,
- LM_MESSAGE_TYPE_MESSAGE, LM_MESSAGE_SUB_TYPE_GROUPCHAT);
- lm_message_node_add_child (msg->node, "subject", str);
-
- success = _gabble_connection_send (priv->conn, msg, error);
-
- lm_message_unref (msg);
-
- if (!success)
- return FALSE;
- }
-
- /* Changing any other properties? */
- if (tp_properties_context_has_other_than (ctx, ROOM_PROP_SUBJECT))
- {
- msg = lm_message_new_with_sub_type (priv->jid,
- LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
- node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (node, "xmlns", NS_MUC_OWNER);
-
- success = _gabble_connection_send_with_reply (priv->conn, msg,
- request_config_form_reply_cb, G_OBJECT (obj), NULL,
- error);
-
- lm_message_unref (msg);
-
- if (!success)
- return FALSE;
- }
-
- priv->properties_ctx = ctx;
- return TRUE;
-}
-
-static LmHandlerResult request_config_form_submit_reply_cb (
- GabbleConnection *conn, LmMessage *sent_msg, LmMessage *reply_msg,
- GObject *object, gpointer user_data);
-
-static LmHandlerResult
-request_config_form_reply_cb (GabbleConnection *conn, LmMessage *sent_msg,
- LmMessage *reply_msg, GObject *object,
- gpointer user_data)
-{
- GabbleMucChannel *chan = GABBLE_MUC_CHANNEL (object);
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
- TpPropertiesContext *ctx = priv->properties_ctx;
- GError *error = NULL;
- LmMessage *msg = NULL;
- LmMessageNode *submit_node, *form_node, *node;
- guint i, props_left;
-
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- error = g_error_new (TP_ERRORS, TP_ERROR_PERMISSION_DENIED,
- "request for configuration form denied");
-
- goto OUT;
- }
-
- form_node = config_form_get_form_node (reply_msg);
- if (form_node == NULL)
- goto PARSE_ERROR;
-
- /* initialize */
- msg = lm_message_new_with_sub_type (priv->jid, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_SET);
-
- node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (node, "xmlns", NS_MUC_OWNER);
-
- submit_node = lm_message_node_add_child (node, "x", NULL);
- lm_message_node_set_attributes (submit_node,
- "xmlns", NS_X_DATA,
- "type", "submit",
- NULL);
-
- /* we assume that the number of props will fit in a guint on all supported
- * platforms, so fail at compile time if this is no longer the case
- */
-#if NUM_ROOM_PROPS > 32
-#error GabbleMUCChannel request_config_form_reply_cb needs porting to TpIntSet
-#endif
-
- props_left = 0;
- for (i = 0; i < NUM_ROOM_PROPS; i++)
- {
- if (i == ROOM_PROP_SUBJECT)
- continue;
-
- if (tp_properties_context_has (ctx, i))
- props_left |= 1 << i;
- }
-
- for (node = form_node->children; node; node = node->next)
- {
- const gchar *var, *prev_value;
- LmMessageNode *field_node, *value_node;
- guint id;
- GType type;
- gboolean invert;
- gchar buf[16];
- const gchar *val_str;
- gboolean val_bool;
-
- if (strcmp (node->name, "field") != 0)
- {
- DEBUG ("skipping node '%s'", node->name);
- continue;
- }
-
- var = lm_message_node_get_attribute (node, "var");
- if (var == NULL) {
- DEBUG ("skipping node '%s' because of lacking var attribute",
- node->name);
- continue;
- }
-
- value_node = lm_message_node_get_child (node, "value");
- if (value_node == NULL)
- {
- DEBUG ("skipping var '%s' because of lacking value attribute",
- var);
- continue;
- }
-
- prev_value = lm_message_node_get_value (value_node);
-
- /* add the corresponding field node to the reply message */
- field_node = lm_message_node_add_child (submit_node, "field", NULL);
-
- lm_message_node_set_attribute (field_node, "var", var);
-
- val_str = lm_message_node_get_attribute (node, "type");
- if (val_str)
- {
- lm_message_node_set_attribute (field_node, "type", val_str);
- }
-
- value_node = lm_message_node_add_child (field_node, "value", prev_value);
-
- id = INVALID_ROOM_PROP;
- type = G_TYPE_BOOLEAN;
- invert = FALSE;
- val_str = NULL;
-
- if (strcmp (var, "anonymous") == 0)
- {
- id = ROOM_PROP_ANONYMOUS;
- }
- else if (strcmp (var, "muc#roomconfig_whois") == 0)
- {
- id = ROOM_PROP_ANONYMOUS;
-
- if (tp_properties_context_has (ctx, id))
- {
- val_bool = g_value_get_boolean (
- tp_properties_context_get (ctx, id));
- val_str = (val_bool) ? "moderators" : "anyone";
- }
- }
- else if (strcmp (var, "muc#owner_whois") == 0)
- {
- id = ROOM_PROP_ANONYMOUS;
-
- if (tp_properties_context_has (ctx, id))
- {
- val_bool = g_value_get_boolean (
- tp_properties_context_get (ctx, id));
- val_str = (val_bool) ? "admins" : "anyone";
- }
- }
- else if (strcmp (var, "members_only") == 0 ||
- strcmp (var, "muc#roomconfig_membersonly") == 0 ||
- strcmp (var, "muc#owner_inviteonly") == 0)
- {
- id = ROOM_PROP_INVITE_ONLY;
- }
- else if (strcmp (var, "moderated") == 0 ||
- strcmp (var, "muc#roomconfig_moderatedroom") == 0 ||
- strcmp (var, "muc#owner_moderatedroom") == 0)
- {
- id = ROOM_PROP_MODERATED;
- }
- else if (strcmp (var, "title") == 0 ||
- strcmp (var, "muc#roomconfig_roomname") == 0 ||
- strcmp (var, "muc#owner_roomname") == 0)
- {
- id = ROOM_PROP_NAME;
- type = G_TYPE_STRING;
- }
- else if (strcmp (var, "muc#roomconfig_roomdesc") == 0 ||
- strcmp (var, "muc#owner_roomdesc") == 0)
- {
- id = ROOM_PROP_DESCRIPTION;
- type = G_TYPE_STRING;
- }
- else if (strcmp (var, "password") == 0 ||
- strcmp (var, "muc#roomconfig_roomsecret") == 0 ||
- strcmp (var, "muc#owner_roomsecret") == 0)
- {
- id = ROOM_PROP_PASSWORD;
- type = G_TYPE_STRING;
- }
- else if (strcmp (var, "password_protected") == 0 ||
- strcmp (var, "muc#roomconfig_passwordprotectedroom") == 0 ||
- strcmp (var, "muc#owner_passwordprotectedroom") == 0)
- {
- id = ROOM_PROP_PASSWORD_REQUIRED;
- }
- else if (strcmp (var, "persistent") == 0 ||
- strcmp (var, "muc#roomconfig_persistentroom") == 0 ||
- strcmp (var, "muc#owner_persistentroom") == 0)
- {
- id = ROOM_PROP_PERSISTENT;
- }
- else if (strcmp (var, "public") == 0 ||
- strcmp (var, "muc#roomconfig_publicroom") == 0 ||
- strcmp (var, "muc#owner_publicroom") == 0)
- {
- id = ROOM_PROP_PRIVATE;
- invert = TRUE;
- }
- else
- {
- g_warning ("%s: ignoring field '%s'", G_STRFUNC, var);
- continue;
- }
-
- DEBUG ("looking up %s", room_property_signatures[id].name);
-
- if (!tp_properties_context_has (ctx, id))
- continue;
-
- if (!val_str)
- {
- const GValue *provided_value;
-
- provided_value = tp_properties_context_get (ctx, id);
-
- switch (type) {
- case G_TYPE_BOOLEAN:
- val_bool = g_value_get_boolean (provided_value);
- sprintf (buf, "%d", (invert) ? !val_bool : val_bool);
- val_str = buf;
- break;
- case G_TYPE_STRING:
- val_str = g_value_get_string (provided_value);
- break;
- default:
- g_assert_not_reached ();
- }
- }
-
- lm_message_node_set_value (value_node, val_str);
-
- props_left &= ~(1 << id);
- }
-
- if (props_left != 0)
- {
- printf (TP_ANSI_BOLD_ON TP_ANSI_FG_WHITE TP_ANSI_BG_RED
- "\n%s: the following properties were not substituted:\n",
- G_STRFUNC);
-
- for (i = 0; i < NUM_ROOM_PROPS; i++)
- {
- if ((props_left & (1 << i)) != 0)
- {
- printf (" %s\n", room_property_signatures[i].name);
- }
- }
-
- printf ("\nthis is a MUC server compatibility bug in gabble, please "
- "report it with a full debug log attached (running gabble "
- "with LM_DEBUG=net)" TP_ANSI_RESET "\n\n");
- fflush (stdout);
-
- error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "not all properties were substituted");
- goto OUT;
- }
-
- _gabble_connection_send_with_reply (priv->conn, msg,
- request_config_form_submit_reply_cb, G_OBJECT (object),
- NULL, &error);
-
- goto OUT;
-
-PARSE_ERROR:
- error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "error parsing reply from server");
-
-OUT:
- if (error)
- {
- tp_properties_context_return (ctx, error);
- priv->properties_ctx = NULL;
- }
-
- if (msg)
- lm_message_unref (msg);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static LmHandlerResult
-request_config_form_submit_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleMucChannel *chan = GABBLE_MUC_CHANNEL (object);
- GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
- TpPropertiesContext *ctx = priv->properties_ctx;
- GError *error = NULL;
- gboolean returned;
-
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- error = g_error_new (TP_ERRORS, TP_ERROR_PERMISSION_DENIED,
- "submitted configuration form was rejected");
- }
-
- if (!error)
- {
- guint i;
-
- for (i = 0; i < NUM_ROOM_PROPS; i++)
- {
- if (i != ROOM_PROP_SUBJECT)
- tp_properties_context_remove (ctx, i);
- }
-
- returned = tp_properties_context_return_if_done (ctx);
- }
- else
- {
- tp_properties_context_return (ctx, error);
- returned = TRUE;
-
- /* Get the properties into a consistent state. */
- room_properties_update (chan);
- }
-
- if (returned)
- priv->properties_ctx = NULL;
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-/**
- * gabble_muc_channel_set_chat_state
- *
- * Implements D-Bus method SetChatState
- * on interface org.freedesktop.Telepathy.Channel.Interface.ChatState
- */
-static void
-gabble_muc_channel_set_chat_state (TpSvcChannelInterfaceChatState *iface,
- guint state,
- DBusGMethodInvocation *context)
-{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface);
- GabbleMucChannelPrivate *priv;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (self));
-
- priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (self);
-
- if (state >= NUM_TP_CHANNEL_CHAT_STATES)
- {
- DEBUG ("invalid state %u", state);
-
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "invalid state: %u", state);
- }
-
- if (state == TP_CHANNEL_CHAT_STATE_GONE)
- {
- /* We cannot explicitly set the Gone state */
- DEBUG ("you may not explicitly set the Gone state");
-
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "you may not explicitly set the Gone state");
- }
-
- if (error != NULL || !gabble_text_mixin_send (G_OBJECT (self),
- TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, LM_MESSAGE_SUB_TYPE_GROUPCHAT,
- state, priv->jid, NULL, priv->conn, FALSE /* emit_signal */, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- return;
- }
-
- tp_svc_channel_interface_chat_state_return_from_set_chat_state (context);
-}
-
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_implement_##x (\
- klass, gabble_muc_channel_##x)
- IMPLEMENT(close);
- IMPLEMENT(get_channel_type);
- IMPLEMENT(get_handle);
- IMPLEMENT(get_interfaces);
-#undef IMPLEMENT
-}
-
-static void
-text_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelTypeTextClass *klass = (TpSvcChannelTypeTextClass *)g_iface;
-
- tp_text_mixin_iface_init (g_iface, iface_data);
-#define IMPLEMENT(x) tp_svc_channel_type_text_implement_##x (\
- klass, gabble_muc_channel_##x)
- IMPLEMENT(send);
-#undef IMPLEMENT
-}
-
-static void
-password_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelInterfacePasswordClass *klass =
- (TpSvcChannelInterfacePasswordClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_interface_password_implement_##x (\
- klass, gabble_muc_channel_##x)
- IMPLEMENT(get_password_flags);
- IMPLEMENT(provide_password);
-#undef IMPLEMENT
-}
-
-static void
-chat_state_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelInterfaceChatStateClass *klass =
- (TpSvcChannelInterfaceChatStateClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_interface_chat_state_implement_##x (\
- klass, gabble_muc_channel_##x)
- IMPLEMENT(set_chat_state);
-#undef IMPLEMENT
-}
diff --git a/src/gabble-muc-channel.h b/src/gabble-muc-channel.h
deleted file mode 100644
index 66b9dc564..000000000
--- a/src/gabble-muc-channel.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * gabble-muc-channel.h - Header for GabbleMucChannel
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#ifndef __GABBLE_MUC_CHANNEL_H__
-#define __GABBLE_MUC_CHANNEL_H__
-
-#include <glib-object.h>
-
-#include <telepathy-glib/group-mixin.h>
-#include <telepathy-glib/properties-mixin.h>
-#include "text-mixin.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleMucChannel GabbleMucChannel;
-typedef struct _GabbleMucChannelClass GabbleMucChannelClass;
-
-struct _GabbleMucChannelClass {
- GObjectClass parent_class;
-
- TpGroupMixinClass group_class;
- TpPropertiesMixinClass properties_class;
- GabbleTextMixinClass text_class;
-};
-
-struct _GabbleMucChannel {
- GObject parent;
-
- TpGroupMixin group;
- TpPropertiesMixin properties;
- GabbleTextMixin text;
-
- gpointer priv;
-};
-
-GType gabble_muc_channel_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_MUC_CHANNEL \
- (gabble_muc_channel_get_type ())
-#define GABBLE_MUC_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MUC_CHANNEL, \
- GabbleMucChannel))
-#define GABBLE_MUC_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MUC_CHANNEL,\
- GabbleMucChannelClass))
-#define GABBLE_IS_MUC_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MUC_CHANNEL))
-#define GABBLE_IS_MUC_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MUC_CHANNEL))
-#define GABBLE_MUC_CHANNEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MUC_CHANNEL,\
- GabbleMucChannelClass))
-
-gboolean _gabble_muc_channel_is_ready (GabbleMucChannel *chan);
-void _gabble_muc_channel_presence_error (GabbleMucChannel *chan,
- const gchar *jid, LmMessageNode *pres_node);
-void _gabble_muc_channel_member_presence_updated (GabbleMucChannel *chan,
- TpHandle handle, LmMessage *message, LmMessageNode *x_node);
-void _gabble_muc_channel_receive (GabbleMucChannel *chan,
- TpChannelTextMessageType msg_type, TpHandleType handle_type,
- TpHandle sender, time_t timestamp, const gchar *text, LmMessage *msg);
-
-void _gabble_muc_channel_handle_invited (GabbleMucChannel *chan,
- TpHandle inviter, const gchar *message);
-void _gabble_muc_channel_state_receive (GabbleMucChannel *chan,
- guint state, guint from_handle);
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_MUC_CHANNEL_H__*/
diff --git a/src/gabble-register.c b/src/gabble-register.c
deleted file mode 100644
index bba748cf2..000000000
--- a/src/gabble-register.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * gabble-register.c - Source for Gabble account registration
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#include "gabble-register.h"
-
-#define DBUS_API_SUBJECT_TO_CHANGE
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-
-#include "gabble-connection.h"
-#include "gabble-error.h"
-#include "gabble-signals-marshal.h"
-#include "namespaces.h"
-#include "util.h"
-#include "libmd5-rfc/md5.h"
-
-/* signal enum */
-enum
-{
- FINISHED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0, };
-
-/* properties */
-enum
-{
- PROP_CONNECTION = 1,
- LAST_PROPERTY
-};
-
-G_DEFINE_TYPE(GabbleRegister, gabble_register, G_TYPE_OBJECT);
-
-/* private structure */
-typedef struct _GabbleRegisterPrivate GabbleRegisterPrivate;
-struct _GabbleRegisterPrivate
-{
- GabbleConnection *conn;
-
- gboolean dispose_has_run;
-};
-
-#define GABBLE_REGISTER_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_REGISTER,\
- GabbleRegisterPrivate))
-
-static void
-gabble_register_init (GabbleRegister *obj)
-{
-}
-
-static void gabble_register_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-static void gabble_register_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-static void gabble_register_dispose (GObject *object);
-static void gabble_register_finalize (GObject *object);
-
-static void
-gabble_register_class_init (GabbleRegisterClass *gabble_register_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_register_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_register_class,
- sizeof (GabbleRegisterPrivate));
-
- object_class->get_property = gabble_register_get_property;
- object_class->set_property = gabble_register_set_property;
-
- object_class->dispose = gabble_register_dispose;
- object_class->finalize = gabble_register_finalize;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "GabbleRegister object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- signals[FINISHED] =
- g_signal_new ("finished",
- G_OBJECT_CLASS_TYPE (gabble_register_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- gabble_marshal_VOID__BOOLEAN_INT_STRING,
- G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_STRING);
-}
-
-static void
-gabble_register_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleRegister *chan = GABBLE_REGISTER (object);
- GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_register_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleRegister *chan = GABBLE_REGISTER (object);
- GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-void
-gabble_register_dispose (GObject *object)
-{
- GabbleRegister *self = GABBLE_REGISTER (object);
- GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- g_debug ("%s: dispose called", G_STRFUNC);
-
- if (G_OBJECT_CLASS (gabble_register_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_register_parent_class)->dispose (object);
-}
-
-void
-gabble_register_finalize (GObject *object)
-{
- g_debug ("%s called with %p", G_STRFUNC, object);
-
- G_OBJECT_CLASS (gabble_register_parent_class)->finalize (object);
-}
-
-/**
- * gabble_register_new:
- *
- * Creates an object to use for account registration.
- *
- * @conn: The #GabbleConnection to register an account on
- */
-GabbleRegister *
-gabble_register_new (GabbleConnection *conn)
-{
- g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL);
- return GABBLE_REGISTER (g_object_new (GABBLE_TYPE_REGISTER,
- "connection", conn, NULL));
-}
-
-typedef enum { STAGE_NOKIA_IV, STAGE_REGISTER } RegistrationStage;
-static void send_registration (GabbleRegister *, RegistrationStage);
-
-static LmHandlerResult
-nokia_iv_set_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- LmMessageNode *node;
- gint code = TP_ERROR_NOT_AVAILABLE;
- GString *msg;
-
- msg = g_string_sized_new (30);
- g_string_append (msg, "Request failed");
-
- node = lm_message_node_get_child (reply_msg->node, "error");
- if (node)
- {
- GabbleXmppError error;
-
- error = gabble_xmpp_error_from_node (node);
-
- if (error != INVALID_XMPP_ERROR)
- {
- g_string_append_printf (msg, ": %s",
- gabble_xmpp_error_string (error));
- }
- }
-
- g_signal_emit (object, signals[FINISHED], 0, FALSE, code, msg->str);
- g_string_free (msg, TRUE);
- }
- else
- {
- /* IV pre-authorization finished - move on to account registration */
- send_registration (GABBLE_REGISTER (object), STAGE_REGISTER);
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static LmHandlerResult
-nokia_iv_get_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleRegister *reg = GABBLE_REGISTER (object);
- GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (reg);
- GError *error = NULL;
- gint err_code = -1;
- const gchar *err_msg = NULL;
- LmMessage *msg = NULL;
- LmMessageNode *query_node, *challenge_node;
- gchar *auth_mac, *auth_btid;
- gchar *challenge;
- gchar response[33];
- guint i;
- md5_byte_t digest[16];
- md5_state_t calculator;
-
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- /* We tried, but the server doesn't seem to support it. Never mind,
- let's try to log in anyway and see what happens. */
- g_signal_emit (object, signals[FINISHED], 0, TRUE, -1, NULL);
- goto OUT;
- }
-
- /* sanity check the reply to some degree ... */
- query_node = lm_message_node_get_child_with_namespace (reply_msg->node,
- "query", NS_NOKIA_IV);
-
- if (query_node == NULL)
- goto ERROR_MALFORMED_REPLY;
-
- challenge_node = lm_message_node_get_child (query_node, "challenge");
- if (!challenge_node)
- goto ERROR_MALFORMED_REPLY;
- challenge = g_strdup (lm_message_node_get_value (challenge_node));
- if (!challenge)
- goto ERROR_MALFORMED_REPLY;
-
- /* craft a reply */
- msg = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_SET);
-
- query_node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (query_node, "xmlns", NS_NOKIA_IV);
-
- g_object_get (priv->conn,
- "auth-mac", &auth_mac,
- "auth-btid", &auth_btid,
- NULL);
-
- for (i = 0; i < strlen (auth_mac); i++)
- auth_mac[i] = tolower (auth_mac[i]);
-
- for (i = 0; i < strlen (auth_btid); i++)
- auth_btid[i] = tolower (auth_btid[i]);
-
- for (i = 0; i < strlen (challenge); i++)
- challenge[i] = tolower (challenge[i]);
-
- md5_init (&calculator);
- md5_append (&calculator, (const md5_byte_t *)auth_btid,
- strlen (auth_btid));
- md5_append (&calculator, (const md5_byte_t *)":", 1);
- md5_append (&calculator, (const md5_byte_t *)challenge, strlen (challenge));
- md5_finish (&calculator, digest);
-
- for (i = 0; i < 16; i++)
- {
- sprintf (response + i*2, "%02x",digest[i]);
- }
-
- lm_message_node_add_child (query_node, "mac", auth_mac);
- lm_message_node_add_child (query_node, "response", response);
-
- g_free (auth_mac);
- g_free (auth_btid);
- g_free (challenge);
-
- if (!_gabble_connection_send_with_reply (priv->conn, msg,
- nokia_iv_set_reply_cb,
- G_OBJECT (reg), NULL, &error))
- {
- err_code = error->code;
- err_msg = error->message;
- }
-
- goto OUT;
-
-ERROR_MALFORMED_REPLY:
- err_code = TP_ERROR_NOT_AVAILABLE;
- err_msg = "Malformed reply";
-
-OUT:
- if (err_code != -1)
- {
- g_signal_emit (reg, signals[FINISHED], 0, FALSE, err_code, err_msg);
- }
-
- if (msg)
- lm_message_unref (msg);
-
- if (error)
- g_error_free (error);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static LmHandlerResult
-set_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- LmMessageNode *node;
- gint code = TP_ERROR_NOT_AVAILABLE;
- GString *msg;
-
- msg = g_string_sized_new (30);
- g_string_append (msg, "Request failed");
-
- node = lm_message_node_get_child (reply_msg->node, "error");
- if (node)
- {
- GabbleXmppError error;
-
- error = gabble_xmpp_error_from_node (node);
- if (error == XMPP_ERROR_CONFLICT)
- {
- code = TP_ERROR_INVALID_ARGUMENT;
- }
-
- if (error != INVALID_XMPP_ERROR)
- {
- g_string_append_printf (msg, ": %s",
- gabble_xmpp_error_string (error));
- }
- }
-
- g_signal_emit (object, signals[FINISHED], 0, FALSE, code, msg->str);
- g_string_free (msg, TRUE);
- }
- else
- {
- g_signal_emit (object, signals[FINISHED], 0, TRUE, -1, NULL);
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static LmHandlerResult
-get_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleRegister *reg = GABBLE_REGISTER (object);
- GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (reg);
- GError *error = NULL;
- gint err_code = -1;
- const gchar *err_msg = NULL;
- LmMessage *msg = NULL;
- LmMessageNode *query_node;
- gchar *username, *password;
-
- if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
- {
- err_code = TP_ERROR_NOT_AVAILABLE;
- err_msg = "Server doesn't support " NS_REGISTER;
-
- goto OUT;
- }
-
- /* sanity check the reply to some degree ... */
- query_node = lm_message_node_get_child_with_namespace (reply_msg->node,
- "query", NS_REGISTER);
-
- if (query_node == NULL)
- goto ERROR_MALFORMED_REPLY;
-
- if (!lm_message_node_get_child (query_node, "username"))
- goto ERROR_MALFORMED_REPLY;
-
- if (!lm_message_node_get_child (query_node, "password"))
- goto ERROR_MALFORMED_REPLY;
-
- /* craft a reply */
- msg = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_SET);
-
- query_node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (query_node, "xmlns", NS_REGISTER);
-
- g_object_get (priv->conn,
- "username", &username,
- "password", &password,
- NULL);
-
- lm_message_node_add_child (query_node, "username", username);
- lm_message_node_add_child (query_node, "password", password);
-
- g_free (username);
- g_free (password);
-
- if (!_gabble_connection_send_with_reply (priv->conn, msg, set_reply_cb,
- G_OBJECT (reg), NULL, &error))
- {
- err_code = error->code;
- err_msg = error->message;
- }
-
- goto OUT;
-
-ERROR_MALFORMED_REPLY:
- err_code = TP_ERROR_NOT_AVAILABLE;
- err_msg = "Malformed reply";
-
-OUT:
- if (err_code != -1)
- {
- g_signal_emit (reg, signals[FINISHED], 0, FALSE, err_code, err_msg);
- }
-
- if (msg)
- lm_message_unref (msg);
-
- if (error)
- g_error_free (error);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-send_registration (GabbleRegister *reg, RegistrationStage stage)
-{
- GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (reg);
- LmMessage *msg;
- LmMessageNode *node;
- GError *error = NULL;
- GabbleConnectionMsgReplyFunc handler;
-
- msg = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_GET);
- node = lm_message_node_add_child (msg->node, "query", NULL);
- if (stage == STAGE_NOKIA_IV)
- {
- lm_message_node_set_attribute (node, "xmlns", NS_NOKIA_IV);
- handler = nokia_iv_get_reply_cb;
- }
- else
- {
- lm_message_node_set_attribute (node, "xmlns", NS_REGISTER);
- handler = get_reply_cb;
- }
- if (!_gabble_connection_send_with_reply (priv->conn, msg, handler,
- G_OBJECT (reg), NULL, &error))
- {
- g_signal_emit (reg, signals[FINISHED], 0, FALSE, error->code,
- error->message);
- g_error_free (error);
- }
-
- lm_message_unref (msg);
-}
-
-/**
- * gabble_register_start:
- *
- * Start account registration.
- *
- * @reg: The #GabbleRegister object performing the registration
- */
-void gabble_register_start (GabbleRegister *reg)
-{
- GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (reg);
- gchar *auth_mac, *auth_btid;
-
- g_object_get (priv->conn, "auth-mac", &auth_mac, NULL);
- g_object_get (priv->conn, "auth-btid", &auth_btid, NULL);
-
- if (auth_mac && auth_btid)
- {
- send_registration (reg, STAGE_NOKIA_IV);
- }
- else
- {
- if (auth_mac || auth_btid)
- {
- g_warning ("Only one of 'mac', 'btid' supplied - not performing "
- "privileged device authorization");
- }
- send_registration (reg, STAGE_REGISTER);
- }
- g_free (auth_mac);
- g_free (auth_btid);
-}
diff --git a/src/gabble-register.h b/src/gabble-register.h
deleted file mode 100644
index c6fc41c5b..000000000
--- a/src/gabble-register.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * gabble-register.h - Headers for Gabble account registration
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * 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
- */
-
-#ifndef __GABBLE_REGISTER_H__
-#define __GABBLE_REGISTER_H__
-
-#include <glib-object.h>
-
-#include <loudmouth/loudmouth.h>
-
-#include "gabble-connection.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleRegister GabbleRegister;
-typedef struct _GabbleRegisterClass GabbleRegisterClass;
-
-GType gabble_register_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_REGISTER \
- (gabble_register_get_type ())
-#define GABBLE_REGISTER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_REGISTER, GabbleRegister))
-#define GABBLE_REGISTER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_REGISTER, GabbleRegisterClass))
-#define GABBLE_IS_REGISTER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_REGISTER))
-#define GABBLE_IS_REGISTER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_REGISTER))
-#define GABBLE_REGISTER_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_REGISTER,\
- GabbleRegisterClass))
-
-struct _GabbleRegisterClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleRegister {
- GObject parent;
-};
-
-GabbleRegister *gabble_register_new (GabbleConnection *conn);
-void gabble_register_start (GabbleRegister *reg);
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_REGISTER_H__ */
diff --git a/src/gabble-roomlist-channel.c b/src/gabble-roomlist-channel.c
deleted file mode 100644
index 44bc6479b..000000000
--- a/src/gabble-roomlist-channel.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * gabble-roomlist-channel.c - Source for GabbleRoomlistChannel
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#include "gabble-roomlist-channel.h"
-
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_ROOMLIST
-
-#include "debug.h"
-#include "disco.h"
-#include "gabble-connection.h"
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/svc-channel.h>
-#include "namespaces.h"
-#include "util.h"
-
-#define TP_TYPE_ROOM_STRUCT (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, \
- G_TYPE_STRING, \
- dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), \
- G_TYPE_INVALID))
-
-#define TP_TYPE_ROOM_LIST (dbus_g_type_get_collection ("GPtrArray", \
- TP_TYPE_ROOM_STRUCT))
-
-static void channel_iface_init (gpointer, gpointer);
-static void roomlist_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleRoomlistChannel, gabble_roomlist_channel,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_ROOM_LIST,
- roomlist_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL)
- );
-
-/* properties */
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_HANDLE_TYPE,
- PROP_HANDLE,
- PROP_CONNECTION,
- PROP_CONFERENCE_SERVER,
- LAST_PROPERTY
-};
-
-/* private structure */
-typedef struct _GabbleRoomlistChannelPrivate GabbleRoomlistChannelPrivate;
-
-struct _GabbleRoomlistChannelPrivate
-{
- GabbleConnection *conn;
- gchar *object_path;
- gchar *conference_server;
-
- gboolean closed;
- gboolean listing;
-
- gpointer disco_pipeline;
- TpHandleSet *signalled_rooms;
-
- GPtrArray *pending_room_signals;
- guint timer_source_id;
-
- gboolean dispose_has_run;
-};
-
-#define GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE(obj) \
- ((GabbleRoomlistChannelPrivate *)obj->priv)
-
-#define ROOM_SIGNAL_INTERVAL 300
-
-static gboolean emit_room_signal (gpointer data);
-
-static void
-gabble_roomlist_channel_init (GabbleRoomlistChannel *self)
-{
- GabbleRoomlistChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_ROOMLIST_CHANNEL, GabbleRoomlistChannelPrivate);
-
- self->priv = priv;
-
- priv->pending_room_signals = g_ptr_array_new ();
-}
-
-
-static GObject *
-gabble_roomlist_channel_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleRoomlistChannelPrivate *priv;
- DBusGConnection *bus;
-
- obj = G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->
- constructor (type, n_props, props);
- priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (GABBLE_ROOMLIST_CHANNEL (obj));
-
- bus = tp_get_bus ();
- dbus_g_connection_register_g_object (bus, priv->object_path, obj);
-
- return obj;
-}
-
-static void
-gabble_roomlist_channel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleRoomlistChannel *chan = GABBLE_ROOMLIST_CHANNEL (object);
- GabbleRoomlistChannelPrivate *priv =
- GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_ROOM_LIST);
- break;
- case PROP_HANDLE_TYPE:
- g_value_set_uint (value, TP_HANDLE_TYPE_NONE);
- break;
- case PROP_HANDLE:
- g_value_set_uint (value, 0);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_CONFERENCE_SERVER:
- g_value_set_string (value, priv->conference_server);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_roomlist_channel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleRoomlistChannel *chan = GABBLE_ROOMLIST_CHANNEL (object);
- GabbleRoomlistChannelPrivate *priv =
- GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan);
- TpBaseConnection *conn;
- TpHandleRepoIface *room_handles;
- TpHandleSet *new_signalled_rooms;
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_HANDLE:
- /* this property is writable in the interface, but not actually
- * meaningfully changable on this channel, so we do nothing */
- break;
- case PROP_HANDLE_TYPE:
- /* this property is writable in the interface, but not actually
- * meaningfully changable on this channel, so we do nothing */
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- conn = (TpBaseConnection *)priv->conn;
-
- room_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_ROOM);
-
- new_signalled_rooms = tp_handle_set_new (room_handles);
- if (priv->signalled_rooms != NULL)
- {
- const TpIntSet *add;
- TpIntSet *tmp;
- add = tp_handle_set_peek (priv->signalled_rooms);
- tmp = tp_handle_set_update (new_signalled_rooms, add);
- tp_handle_set_destroy (priv->signalled_rooms);
- tp_intset_destroy (tmp);
- }
- priv->signalled_rooms = new_signalled_rooms;
- break;
- case PROP_CONFERENCE_SERVER:
- g_free (priv->conference_server);
- priv->conference_server = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_roomlist_channel_dispose (GObject *object);
-static void gabble_roomlist_channel_finalize (GObject *object);
-
-static void
-gabble_roomlist_channel_class_init (GabbleRoomlistChannelClass *gabble_roomlist_channel_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_roomlist_channel_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_roomlist_channel_class,
- sizeof (GabbleRoomlistChannelPrivate));
-
- object_class->constructor = gabble_roomlist_channel_constructor;
-
- object_class->get_property = gabble_roomlist_channel_get_property;
- object_class->set_property = gabble_roomlist_channel_set_property;
-
- object_class->dispose = gabble_roomlist_channel_dispose;
- object_class->finalize = gabble_roomlist_channel_finalize;
-
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
- g_object_class_override_property (object_class, PROP_HANDLE,
- "handle");
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "room list channel object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_string ("conference-server",
- "Name of conference server to use",
- "Name of the XMPP conference server "
- "on which to list rooms",
- "",
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_WRITABLE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONFERENCE_SERVER,
- param_spec);
-}
-
-static void stop_listing (GabbleRoomlistChannel *self);
-
-void
-gabble_roomlist_channel_dispose (GObject *object)
-{
- GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (object);
- GabbleRoomlistChannelPrivate *priv =
- GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- stop_listing (self);
-
- if (!priv->closed)
- {
- tp_svc_channel_emit_closed ((TpSvcChannel *)object);
- priv->closed = TRUE;
- }
-
- g_assert (priv->pending_room_signals != NULL);
- g_assert (priv->pending_room_signals->len == 0);
- g_ptr_array_free (priv->pending_room_signals, TRUE);
- priv->pending_room_signals = NULL;
-
- if (G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->dispose (object);
-}
-
-void
-gabble_roomlist_channel_finalize (GObject *object)
-{
- GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (object);
- GabbleRoomlistChannelPrivate *priv =
- GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self);
-
- /* free any data held directly by the object here */
-
- g_free (priv->object_path);
- g_free (priv->conference_server);
-
- if (priv->signalled_rooms != NULL)
- tp_handle_set_destroy (priv->signalled_rooms);
-
- G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->finalize (object);
-}
-
-GabbleRoomlistChannel *
-_gabble_roomlist_channel_new (GabbleConnection *conn,
- const gchar *object_path,
- const gchar *conference_server)
-{
- g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL);
- g_return_val_if_fail (object_path != NULL, NULL);
- g_return_val_if_fail (conference_server != NULL, NULL);
-
- return GABBLE_ROOMLIST_CHANNEL (
- g_object_new (GABBLE_TYPE_ROOMLIST_CHANNEL,
- "connection", conn,
- "object-path", object_path,
- "conference-server", conference_server, NULL));
-}
-
-static gboolean
-emit_room_signal (gpointer data)
-{
- GabbleRoomlistChannel *chan = data;
- GabbleRoomlistChannelPrivate *priv =
- GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan);
-
- if (!priv->listing)
- return FALSE;
-
- if (priv->pending_room_signals->len == 0)
- return TRUE;
-
- tp_svc_channel_type_room_list_emit_got_rooms (
- (TpSvcChannelTypeRoomList *)chan, priv->pending_room_signals);
-
- while (priv->pending_room_signals->len != 0)
- {
- gpointer boxed = g_ptr_array_index (priv->pending_room_signals, 0);
- g_boxed_free (TP_TYPE_ROOM_STRUCT, boxed);
- g_ptr_array_remove_index_fast (priv->pending_room_signals, 0);
- }
-
- return TRUE;
-}
-
-static void
-room_info_cb (gpointer pipeline, GabbleDiscoItem *item, gpointer user_data)
-{
- GabbleRoomlistChannel *chan = user_data;
- GabbleRoomlistChannelPrivate *priv;
- TpHandleRepoIface *room_handles;
- const char *jid, *category, *type, *var, *name;
- TpHandle handle;
- GHashTable *keys;
- GValue room = {0,};
- GValue *tmp;
- gpointer k, v;
-
- #define INSERT_KEY(hash, name, type, type2, value) \
- do {\
- tmp = g_slice_new0 (GValue); \
- g_value_init (tmp, (type)); \
- g_value_set_##type2 (tmp, (value)); \
- g_hash_table_insert (hash, (name), tmp); \
- } while (0)
-
- g_assert (GABBLE_IS_ROOMLIST_CHANNEL (chan));
- priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan);
- room_handles = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_ROOM);
-
- jid = item->jid;
- name = item->name;
- category = item->category;
- type = item->type;
-
- if (0 != strcmp (category, "conference") ||
- 0 != strcmp (type, "text"))
- return;
-
- if (!g_hash_table_lookup_extended (item->features,
- "http://jabber.org/protocol/muc", &k, &v))
- {
- /* not muc */
- return;
- }
-
- handle = tp_handle_ensure (room_handles, jid, NULL, NULL);
- if (handle == 0)
- {
- DEBUG ("ignoring listed room with invalid JID '%s'", jid);
- return;
- }
-
- DEBUG ("got room identity, name=%s, category=%s, type=%s", name,
- category, type);
-
- keys = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) tp_g_value_slice_free);
-
- INSERT_KEY (keys, "name", G_TYPE_STRING, string, name);
-
- if (g_hash_table_lookup_extended (item->features, "muc_membersonly", &k, &v))
- INSERT_KEY (keys, "invite-only", G_TYPE_BOOLEAN, boolean, TRUE);
- if (g_hash_table_lookup_extended (item->features, "muc_open", &k, &v))
- INSERT_KEY (keys, "invite-only", G_TYPE_BOOLEAN, boolean, FALSE);
- if (g_hash_table_lookup_extended (item->features,
- "muc_passwordprotected", &k, &v))
- INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, TRUE);
- if (g_hash_table_lookup_extended (item->features, "muc_unsecure", &k, &v))
- INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, FALSE);
- if (g_hash_table_lookup_extended (item->features, "muc_unsecured", &k, &v))
- INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, FALSE);
- if (g_hash_table_lookup_extended (item->features, "muc_hidden", &k, &v))
- INSERT_KEY (keys, "hidden", G_TYPE_BOOLEAN, boolean, TRUE);
- if (g_hash_table_lookup_extended (item->features, "muc_public", &k, &v))
- INSERT_KEY (keys, "hidden", G_TYPE_BOOLEAN, boolean, FALSE);
- if (g_hash_table_lookup_extended (item->features, "muc_membersonly", &k, &v))
- INSERT_KEY (keys, "members-only", G_TYPE_BOOLEAN, boolean, TRUE);
- if (g_hash_table_lookup_extended (item->features, "muc_open", &k, &v))
- INSERT_KEY (keys, "members-only", G_TYPE_BOOLEAN, boolean, FALSE);
- if (g_hash_table_lookup_extended (item->features, "muc_moderated", &k, &v))
- INSERT_KEY (keys, "moderated", G_TYPE_BOOLEAN, boolean, TRUE);
- if (g_hash_table_lookup_extended (item->features, "muc_unmoderated", &k, &v))
- INSERT_KEY (keys, "moderated", G_TYPE_BOOLEAN, boolean, FALSE);
- if (g_hash_table_lookup_extended (item->features,
- "muc_nonanonymous", &k, &v))
- INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, FALSE);
- if (g_hash_table_lookup_extended (item->features, "muc_anonymous", &k, &v))
- INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, TRUE);
- if (g_hash_table_lookup_extended (item->features,
- "muc_semianonymous", &k, &v))
- INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, FALSE);
- if (g_hash_table_lookup_extended (item->features, "muc_persistent", &k, &v))
- INSERT_KEY (keys, "persistent", G_TYPE_BOOLEAN, boolean, TRUE);
- if (g_hash_table_lookup_extended (item->features, "muc_temporary", &k, &v))
- INSERT_KEY (keys, "persistent", G_TYPE_BOOLEAN, boolean, FALSE);
-
- var = g_hash_table_lookup (item->features, "muc#roominfo_description");
- if (var != NULL)
- INSERT_KEY (keys, "description", G_TYPE_STRING, string, var);
-
- var = g_hash_table_lookup (item->features, "muc#roominfo_occupants");
- if (var != NULL)
- INSERT_KEY (keys, "members", G_TYPE_UINT, uint,
- (guint) g_ascii_strtoull (var, NULL, 10));
-
- var = g_hash_table_lookup (item->features, "muc#roominfo_lang");
- if (var != NULL)
- INSERT_KEY (keys, "language", G_TYPE_STRING, string, var);
-
- /* transfer the room handle ref to signalled_rooms */
- tp_handle_set_add (priv->signalled_rooms, handle);
- tp_handle_unref (room_handles, handle);
-
- g_value_init (&room, TP_TYPE_ROOM_STRUCT);
- g_value_take_boxed (&room,
- dbus_g_type_specialized_construct (TP_TYPE_ROOM_STRUCT));
-
- dbus_g_type_struct_set (&room,
- 0, handle,
- 1, "org.freedesktop.Telepathy.Channel.Type.Text",
- 2, keys,
- G_MAXUINT);
-
- DEBUG ("adding new room signal data to pending: %s", jid);
- g_ptr_array_add (priv->pending_room_signals, g_value_get_boxed (&room));
- g_hash_table_destroy (keys);
-}
-
-static void
-rooms_end_cb (gpointer data, gpointer user_data)
-{
- GabbleRoomlistChannel *chan = user_data;
- GabbleRoomlistChannelPrivate *priv =
- GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan);
-
- emit_room_signal (chan);
-
- priv->listing = FALSE;
- tp_svc_channel_type_room_list_emit_listing_rooms (
- (TpSvcChannelTypeRoomList *)chan, FALSE);
-
- g_source_remove (priv->timer_source_id);
- priv->timer_source_id = 0;
-}
-
-static void
-stop_listing (GabbleRoomlistChannel *self)
-{
- GabbleRoomlistChannelPrivate *priv =
- GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self);
-
- if (priv->listing)
- {
- emit_room_signal (self);
- priv->listing = FALSE;
- tp_svc_channel_type_room_list_emit_listing_rooms (
- (TpSvcChannelTypeRoomList *)self, FALSE);
- }
-
- if (priv->disco_pipeline != NULL)
- {
- gabble_disco_pipeline_destroy (priv->disco_pipeline);
- priv->disco_pipeline = NULL;
- }
-
- if (priv->timer_source_id)
- {
- g_source_remove (priv->timer_source_id);
- priv->timer_source_id = 0;
- }
-
- g_assert (priv->pending_room_signals->len == 0);
-}
-
-
-/************************* D-Bus Method definitions **************************/
-
-/**
- * gabble_roomlist_channel_close
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_roomlist_channel_close (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (iface);
- g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self));
-
- DEBUG ("called on %p", self);
-
- g_object_run_dispose (G_OBJECT (self));
-
- tp_svc_channel_return_from_close (context);
-}
-
-
-/**
- * gabble_roomlist_channel_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_roomlist_channel_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_ROOM_LIST);
-}
-
-
-/**
- * gabble_roomlist_channel_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_roomlist_channel_get_handle (TpSvcChannel *self,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_handle (context, 0, 0);
-}
-
-
-/**
- * gabble_roomlist_channel_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_roomlist_channel_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- const char *interfaces[] = { NULL };
-
- tp_svc_channel_return_from_get_interfaces (context, interfaces);
-}
-
-
-/**
- * gabble_roomlist_channel_get_listing_rooms
- *
- * Implements D-Bus method GetListingRooms
- * on interface org.freedesktop.Telepathy.Channel.Type.RoomList
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_roomlist_channel_get_listing_rooms (TpSvcChannelTypeRoomList *iface,
- DBusGMethodInvocation *context)
-{
- GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (iface);
- GabbleRoomlistChannelPrivate *priv;
-
- g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self));
-
- priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self);
- tp_svc_channel_type_room_list_return_from_get_listing_rooms (
- context, priv->listing);
-}
-
-
-/**
- * gabble_roomlist_channel_list_rooms
- *
- * Implements D-Bus method ListRooms
- * on interface org.freedesktop.Telepathy.Channel.Type.RoomList
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-static void
-gabble_roomlist_channel_list_rooms (TpSvcChannelTypeRoomList *iface,
- DBusGMethodInvocation *context)
-{
- GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (iface);
- GabbleRoomlistChannelPrivate *priv;
-
- g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self));
-
- priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self);
-
- priv->listing = TRUE;
- tp_svc_channel_type_room_list_emit_listing_rooms (iface, TRUE);
-
- if (priv->disco_pipeline == NULL)
- priv->disco_pipeline = gabble_disco_pipeline_init (priv->conn->disco,
- room_info_cb, rooms_end_cb, self);
-
- gabble_disco_pipeline_run (priv->disco_pipeline, priv->conference_server);
-
- priv->timer_source_id = g_timeout_add (ROOM_SIGNAL_INTERVAL,
- emit_room_signal, self);
-
- tp_svc_channel_type_room_list_return_from_list_rooms (context);
-}
-
-/**
- * gabble_roomlist_channel_stop_listing
- *
- * Implements D-Bus method StopListing
- * on interface org.freedesktop.Telepathy.Channel.Type.RoomList
- */
-static void
-gabble_roomlist_channel_stop_listing (TpSvcChannelTypeRoomList *iface,
- DBusGMethodInvocation *context)
-{
- GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (iface);
-
- g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self));
-
- stop_listing (self);
-}
-
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_implement_##x (\
- klass, gabble_roomlist_channel_##x)
- IMPLEMENT(close);
- IMPLEMENT(get_channel_type);
- IMPLEMENT(get_handle);
- IMPLEMENT(get_interfaces);
-#undef IMPLEMENT
-}
-
-static void
-roomlist_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelTypeRoomListClass *klass =
- (TpSvcChannelTypeRoomListClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_type_room_list_implement_##x (\
- klass, gabble_roomlist_channel_##x)
- IMPLEMENT(get_listing_rooms);
- IMPLEMENT(list_rooms);
- IMPLEMENT(stop_listing);
-#undef IMPLEMENT
-}
diff --git a/src/gabble-roomlist-channel.h b/src/gabble-roomlist-channel.h
deleted file mode 100644
index 8fd5da2b8..000000000
--- a/src/gabble-roomlist-channel.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * gabble-roomlist-channel.h - Header for GabbleRoomlistChannel
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_ROOMLIST_CHANNEL_H__
-#define __GABBLE_ROOMLIST_CHANNEL_H__
-
-#include <glib-object.h>
-
-#include "gabble-connection.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleRoomlistChannel GabbleRoomlistChannel;
-typedef struct _GabbleRoomlistChannelClass GabbleRoomlistChannelClass;
-
-struct _GabbleRoomlistChannelClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleRoomlistChannel {
- GObject parent;
-
- gpointer priv;
-};
-
-GType gabble_roomlist_channel_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_ROOMLIST_CHANNEL \
- (gabble_roomlist_channel_get_type ())
-#define GABBLE_ROOMLIST_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_ROOMLIST_CHANNEL,\
- GabbleRoomlistChannel))
-#define GABBLE_ROOMLIST_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_ROOMLIST_CHANNEL,\
- GabbleRoomlistChannelClass))
-#define GABBLE_IS_ROOMLIST_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_ROOMLIST_CHANNEL))
-#define GABBLE_IS_ROOMLIST_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_ROOMLIST_CHANNEL))
-#define GABBLE_ROOMLIST_CHANNEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_ROOMLIST_CHANNEL,\
- GabbleRoomlistChannelClass))
-
-
-GabbleRoomlistChannel *_gabble_roomlist_channel_new (GabbleConnection *conn,
- const gchar *object_path, const gchar *conference_server);
-
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_ROOMLIST_CHANNEL_H__*/
diff --git a/src/gabble-roster-channel.c b/src/gabble-roster-channel.c
deleted file mode 100644
index 2f208f8fd..000000000
--- a/src/gabble-roster-channel.c
+++ /dev/null
@@ -1,641 +0,0 @@
-/*
- * gabble-roster-channel.c - Source for GabbleRosterChannel
- * Copyright (C) 2005, 2006 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#include "gabble-roster-channel.h"
-
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_ROSTER
-
-#include "debug.h"
-#include "gabble-connection.h"
-#include <telepathy-glib/group-mixin.h>
-#include "roster.h"
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/svc-channel.h>
-#include "util.h"
-
-static void channel_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleRosterChannel, gabble_roster_channel,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
- tp_group_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_CONTACT_LIST, NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL));
-
-/* properties */
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_HANDLE_TYPE,
- PROP_HANDLE,
- PROP_CONNECTION,
- LAST_PROPERTY
-};
-
-/* private structure */
-typedef struct _GabbleRosterChannelPrivate GabbleRosterChannelPrivate;
-
-struct _GabbleRosterChannelPrivate
-{
- GabbleConnection *conn;
- char *object_path;
- TpHandle handle;
- guint handle_type;
-
- gboolean dispose_has_run;
- gboolean closed;
-};
-
-#define GABBLE_ROSTER_CHANNEL_GET_PRIVATE(obj) \
- ((GabbleRosterChannelPrivate *)obj->priv)
-
-static void
-gabble_roster_channel_init (GabbleRosterChannel *self)
-{
- GabbleRosterChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_ROSTER_CHANNEL, GabbleRosterChannelPrivate);
-
- self->priv = priv;
-
- /* allocate any data required by the object here */
-}
-
-static GObject *
-gabble_roster_channel_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleRosterChannelPrivate *priv;
- DBusGConnection *bus;
- TpBaseConnection *conn;
- TpHandle self_handle;
- guint handle_type;
- TpHandleRepoIface *handle_repo, *contact_repo;
-
- obj = G_OBJECT_CLASS (gabble_roster_channel_parent_class)->
- constructor (type, n_props, props);
- priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (GABBLE_ROSTER_CHANNEL (obj));
- conn = (TpBaseConnection *)priv->conn;
- handle_type = priv->handle_type;
- handle_repo = tp_base_connection_get_handles (conn, handle_type);
- contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT);
- self_handle = conn->self_handle;
-
- /* register object on the bus */
- bus = tp_get_bus ();
- dbus_g_connection_register_g_object (bus, priv->object_path, obj);
-
- g_assert (handle_type == TP_HANDLE_TYPE_GROUP
- || handle_type == TP_HANDLE_TYPE_LIST);
-
- /* ref our list handle */
- tp_handle_ref (handle_repo, priv->handle);
-
- /* initialize group mixin */
- tp_group_mixin_init (obj,
- G_STRUCT_OFFSET (GabbleRosterChannel, group),
- contact_repo,
- self_handle);
-
- if (handle_type == TP_HANDLE_TYPE_GROUP)
- {
- tp_group_mixin_change_flags (obj,
- TP_CHANNEL_GROUP_FLAG_CAN_ADD |
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE,
- 0);
- }
- else if (handle_type != TP_HANDLE_TYPE_LIST)
- {
- g_assert_not_reached ();
- }
- /* magic contact lists from here down... */
- else if (GABBLE_LIST_HANDLE_PUBLISH == priv->handle)
- {
- tp_group_mixin_change_flags (obj,
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_ACCEPT |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE,
- 0);
- }
- else if (GABBLE_LIST_HANDLE_SUBSCRIBE == priv->handle)
- {
- tp_group_mixin_change_flags (obj,
- TP_CHANNEL_GROUP_FLAG_CAN_ADD |
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE |
- TP_CHANNEL_GROUP_FLAG_CAN_RESCIND |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_ADD |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_RESCIND,
- 0);
- }
- else if (GABBLE_LIST_HANDLE_KNOWN == priv->handle)
- {
- tp_group_mixin_change_flags (obj,
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE,
- 0);
- }
- else if (GABBLE_LIST_HANDLE_DENY == priv->handle)
- {
- tp_group_mixin_change_flags (obj,
- TP_CHANNEL_GROUP_FLAG_CAN_ADD |
- TP_CHANNEL_GROUP_FLAG_CAN_REMOVE,
- 0);
- }
- else
- {
- g_assert_not_reached ();
- }
-
- return obj;
-}
-
-static void
-gabble_roster_channel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleRosterChannel *chan = GABBLE_ROSTER_CHANNEL (object);
- GabbleRosterChannelPrivate *priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST);
- break;
- case PROP_HANDLE_TYPE:
- g_value_set_uint (value, priv->handle_type);
- break;
- case PROP_HANDLE:
- g_value_set_uint (value, priv->handle);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_roster_channel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleRosterChannel *chan = GABBLE_ROSTER_CHANNEL (object);
- GabbleRosterChannelPrivate *priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_HANDLE_TYPE:
- priv->handle_type = g_value_get_uint (value);
- break;
- case PROP_HANDLE:
- priv->handle = g_value_get_uint (value);
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_roster_channel_dispose (GObject *object);
-static void gabble_roster_channel_finalize (GObject *object);
-
-static gboolean _gabble_roster_channel_add_member_cb (GObject *obj,
- TpHandle handle, const gchar *message, GError **error);
-static gboolean _gabble_roster_channel_remove_member_cb (GObject *obj,
- TpHandle handle, const gchar *message, GError **error);
-
-static void
-gabble_roster_channel_class_init (GabbleRosterChannelClass *gabble_roster_channel_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_roster_channel_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_roster_channel_class,
- sizeof (GabbleRosterChannelPrivate));
-
- object_class->constructor = gabble_roster_channel_constructor;
-
- object_class->get_property = gabble_roster_channel_get_property;
- object_class->set_property = gabble_roster_channel_set_property;
-
- object_class->dispose = gabble_roster_channel_dispose;
- object_class->finalize = gabble_roster_channel_finalize;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "Roster channel object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
- g_object_class_override_property (object_class, PROP_HANDLE, "handle");
-
- tp_group_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleRosterChannelClass, group_class),
- _gabble_roster_channel_add_member_cb,
- _gabble_roster_channel_remove_member_cb);
-}
-
-void
-gabble_roster_channel_dispose (GObject *object)
-{
- GabbleRosterChannel *self = GABBLE_ROSTER_CHANNEL (object);
- GabbleRosterChannelPrivate *priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- if (!priv->closed)
- tp_svc_channel_emit_closed ((TpSvcChannel *)object);
-
- /* release any references held by the object here */
-
- if (G_OBJECT_CLASS (gabble_roster_channel_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_roster_channel_parent_class)->dispose (object);
-}
-
-void
-gabble_roster_channel_finalize (GObject *object)
-{
- GabbleRosterChannel *self = GABBLE_ROSTER_CHANNEL (object);
- GabbleRosterChannelPrivate *priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (self);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (conn,
- priv->handle_type);
-
- /* free any data held directly by the object here */
-
- g_free (priv->object_path);
-
- tp_handle_unref (handle_repo, priv->handle);
-
- tp_group_mixin_finalize (object);
-
- G_OBJECT_CLASS (gabble_roster_channel_parent_class)->finalize (object);
-}
-
-
-static gboolean
-_gabble_roster_channel_send_presence (GabbleRosterChannel *chan,
- LmMessageSubType sub_type,
- TpHandle handle,
- const gchar *status,
- GError **error)
-{
- GabbleRosterChannelPrivate *priv;
- TpBaseConnection *conn;
- TpHandleRepoIface *repo;
- const char *contact;
- LmMessage *message;
- gboolean result;
-
- priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (chan);
- conn = (TpBaseConnection *)priv->conn;
- repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT);
- contact = tp_handle_inspect (repo, handle);
-
- message = lm_message_new_with_sub_type (contact,
- LM_MESSAGE_TYPE_PRESENCE,
- sub_type);
-
- if (LM_MESSAGE_SUB_TYPE_SUBSCRIBE == sub_type)
- lm_message_node_add_own_nick (message->node, priv->conn);
-
- if (status != NULL && status[0] != '\0')
- lm_message_node_add_child (message->node, "status", status);
-
- result = _gabble_connection_send (priv->conn, message, error);
-
- lm_message_unref (message);
-
- return result;
-}
-
-
-/**
- * _gabble_roster_channel_add_member_cb
- *
- * Called by the group mixin to add one member.
- */
-static gboolean
-_gabble_roster_channel_add_member_cb (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error)
-{
- GabbleRosterChannelPrivate *priv;
- gboolean ret = FALSE;
-#ifdef ENABLE_DEBUG
- TpHandleRepoIface *handle_repo, *contact_repo;
-#endif
-
- priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (GABBLE_ROSTER_CHANNEL (obj));
-#ifdef ENABLE_DEBUG
- handle_repo = tp_base_connection_get_handles ((TpBaseConnection *)priv->conn,
- priv->handle_type);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
-#endif
-
- DEBUG ("called on %s with handle %u (%s) \"%s\"",
- tp_handle_inspect (handle_repo, priv->handle), handle,
- tp_handle_inspect (contact_repo, handle), message);
-
- if (TP_HANDLE_TYPE_GROUP == priv->handle_type)
- {
- ret = gabble_roster_handle_add_to_group (priv->conn->roster,
- handle, priv->handle, error);
- }
- else if (TP_HANDLE_TYPE_LIST != priv->handle_type)
- {
- g_assert_not_reached ();
- return FALSE;
- }
- /* "magic" contact lists, from here down... */
- /* publish list */
- else if (GABBLE_LIST_HANDLE_PUBLISH == priv->handle)
- {
- /* send <presence type="subscribed"> */
- ret = _gabble_roster_channel_send_presence (GABBLE_ROSTER_CHANNEL (obj),
- LM_MESSAGE_SUB_TYPE_SUBSCRIBED, handle, message, error);
- }
- /* subscribe list */
- else if (GABBLE_LIST_HANDLE_SUBSCRIBE == priv->handle)
- {
- /* add item to the roster (GTalk depends on this, clearing the H flag) */
- gabble_roster_handle_add (priv->conn->roster, handle, NULL);
-
- /* send <presence type="subscribe"> */
- ret = _gabble_roster_channel_send_presence (GABBLE_ROSTER_CHANNEL (obj),
- LM_MESSAGE_SUB_TYPE_SUBSCRIBE, handle, message, error);
- }
- /* deny list */
- else if (GABBLE_LIST_HANDLE_DENY == priv->handle)
- {
- /* block contact */
- ret = gabble_roster_handle_set_blocked (priv->conn->roster, handle, TRUE,
- error);
- }
- else
- {
- g_assert_not_reached ();
- }
-
- return ret;
-}
-
-
-/**
- * _gabble_roster_channel_remove_member_cb
- *
- * Called by the group mixin to remove one member.
- */
-static gboolean
-_gabble_roster_channel_remove_member_cb (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error)
-{
- GabbleRosterChannelPrivate *priv;
-#ifdef ENABLE_DEBUG
- TpBaseConnection *conn;
- TpHandleRepoIface *handle_repo, *contact_repo;
-#endif
- gboolean ret = FALSE;
-
- priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (GABBLE_ROSTER_CHANNEL (obj));
-#ifdef ENABLE_DEBUG
- conn = (TpBaseConnection *)priv->conn;
- handle_repo = tp_base_connection_get_handles (conn, priv->handle_type);
- contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT);
-#endif
-
- DEBUG ("called on %s with handle %u (%s) \"%s\"",
- tp_handle_inspect (handle_repo, priv->handle), handle,
- tp_handle_inspect (contact_repo, handle), message);
-
- if (TP_HANDLE_TYPE_GROUP == priv->handle_type)
- {
- ret = gabble_roster_handle_remove_from_group (priv->conn->roster,
- handle, priv->handle, error);
- }
- else if (TP_HANDLE_TYPE_LIST != priv->handle_type)
- {
- g_assert_not_reached ();
- return FALSE;
- }
- /* "magic" contact lists, from here down... */
- /* publish list */
- else if (GABBLE_LIST_HANDLE_PUBLISH == priv->handle)
- {
- /* send <presence type="unsubscribed"> */
- ret = _gabble_roster_channel_send_presence (GABBLE_ROSTER_CHANNEL (obj),
- LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED, handle, message, error);
-
- /* remove it from local_pending here, because roster callback doesn't
- know if it can (subscription='none' is used both during request and
- when it's rejected) */
- if (tp_handle_set_is_member (GABBLE_ROSTER_CHANNEL (obj)->group.local_pending, handle))
- {
- TpIntSet *rem = tp_intset_new ();
-
- tp_intset_add (rem, handle);
- tp_group_mixin_change_members (obj, "", NULL, rem, NULL, NULL,
- 0, 0);
-
- tp_intset_destroy (rem);
- }
- }
- /* subscribe list */
- else if (GABBLE_LIST_HANDLE_SUBSCRIBE == priv->handle)
- {
- /* send <presence type="unsubscribe"> */
- ret = _gabble_roster_channel_send_presence (GABBLE_ROSTER_CHANNEL (obj),
- LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE, handle, message, error);
- }
- /* known list */
- else if (GABBLE_LIST_HANDLE_KNOWN == priv->handle)
- {
- /* send roster subscription=remove IQ */
- ret = gabble_roster_handle_remove (priv->conn->roster, handle, error);
- }
- /* deny list */
- else if (GABBLE_LIST_HANDLE_DENY == priv->handle)
- {
- /* unblock contact */
- ret = gabble_roster_handle_set_blocked (priv->conn->roster, handle,
- FALSE, error);
- }
- else
- {
- g_assert_not_reached ();
- }
-
- return ret;
-}
-
-
-/**
- * gabble_roster_channel_close
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_roster_channel_close (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleRosterChannel *self = GABBLE_ROSTER_CHANNEL (iface);
- GabbleRosterChannelPrivate *priv;
-
- g_assert (GABBLE_IS_ROSTER_CHANNEL (self));
-
- priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (self);
-
- if (priv->handle_type == TP_HANDLE_TYPE_LIST)
- {
- GError e = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
- "you may not close contact list channels" };
-
- dbus_g_method_return_error (context, &e);
- }
- else /* TP_HANDLE_TYPE_GROUP */
- {
- if (tp_handle_set_size (self->group.members) == 0)
- {
- /* deleting groups isn't a concept that exists on XMPP,
- * so just close the channel */
-
- priv->closed = TRUE;
- tp_svc_channel_emit_closed ((TpSvcChannel *)self);
- tp_svc_channel_return_from_close (context);
- return;
- }
-
- else
- {
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "you may not close this group, because it's not empty" };
-
- dbus_g_method_return_error (context, &e);
- }
- }
-}
-
-
-/**
- * gabble_roster_channel_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_roster_channel_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_CONTACT_LIST);
-}
-
-
-/**
- * gabble_roster_channel_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_roster_channel_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleRosterChannel *self = GABBLE_ROSTER_CHANNEL (iface);
- GabbleRosterChannelPrivate *priv;
-
- g_assert (GABBLE_IS_ROSTER_CHANNEL (self));
-
- priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (self);
-
- tp_svc_channel_return_from_get_handle (context, priv->handle_type,
- priv->handle);
-}
-
-
-/**
- * gabble_roster_channel_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_roster_channel_get_interfaces (TpSvcChannel *self,
- DBusGMethodInvocation *context)
-{
- const char *interfaces[] = { TP_IFACE_CHANNEL_INTERFACE_GROUP, NULL };
-
- tp_svc_channel_return_from_get_interfaces (context, interfaces);
-}
-
-
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_implement_##x (\
- klass, gabble_roster_channel_##x)
- IMPLEMENT(close);
- IMPLEMENT(get_channel_type);
- IMPLEMENT(get_handle);
- IMPLEMENT(get_interfaces);
-#undef IMPLEMENT
-}
diff --git a/src/gabble-roster-channel.h b/src/gabble-roster-channel.h
deleted file mode 100644
index 29f8bd5e3..000000000
--- a/src/gabble-roster-channel.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * gabble-roster-channel.h - Header for GabbleRosterChannel
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_ROSTER_CHANNEL_H__
-#define __GABBLE_ROSTER_CHANNEL_H__
-
-#include <glib-object.h>
-#include <telepathy-glib/group-mixin.h>
-#include <telepathy-glib/intset.h>
-
-#include "gabble-types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleRosterChannelClass GabbleRosterChannelClass;
-
-struct _GabbleRosterChannelClass {
- GObjectClass parent_class;
-
- TpGroupMixinClass group_class;
-};
-
-struct _GabbleRosterChannel {
- GObject parent;
-
- TpGroupMixin group;
-
- gpointer priv;
-};
-
-GType gabble_roster_channel_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_ROSTER_CHANNEL \
- (gabble_roster_channel_get_type ())
-#define GABBLE_ROSTER_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_ROSTER_CHANNEL,\
- GabbleRosterChannel))
-#define GABBLE_ROSTER_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_ROSTER_CHANNEL,\
- GabbleRosterChannelClass))
-#define GABBLE_IS_ROSTER_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_ROSTER_CHANNEL))
-#define GABBLE_IS_ROSTER_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_ROSTER_CHANNEL))
-#define GABBLE_ROSTER_CHANNEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_ROSTER_CHANNEL,\
- GabbleRosterChannelClass))
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_ROSTER_CHANNEL_H__*/
diff --git a/src/gabble-signals-marshal.list b/src/gabble-signals-marshal.list
deleted file mode 100644
index 56f418a08..000000000
--- a/src/gabble-signals-marshal.list
+++ /dev/null
@@ -1,7 +0,0 @@
-VOID:BOOLEAN,INT,STRING
-VOID:STRING,BOXED
-VOID:STRING,STRING
-VOID:STRING,UINT,UINT,UINT
-VOID:UINT,STRING
-VOID:UINT,UINT
-VOID:UINT,UINT,UINT
diff --git a/src/gabble-types.h b/src/gabble-types.h
deleted file mode 100644
index b9ee55309..000000000
--- a/src/gabble-types.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * gabble-types.h - Header for Gabble type definitions
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_TYPES_H__
-#define __GABBLE_TYPES_H__
-
-#include <telepathy-glib/handle.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleConnection GabbleConnection;
-typedef struct _GabbleDisco GabbleDisco;
-typedef struct _GabblePresence GabblePresence;
-typedef struct _GabblePresenceCache GabblePresenceCache;
-typedef struct _GabbleRoster GabbleRoster;
-typedef struct _GabbleRosterChannel GabbleRosterChannel;
-typedef struct _GabbleVCardManager GabbleVCardManager;
-
-typedef enum {
- INITIATOR_INVALID = -1,
- INITIATOR_LOCAL = 0,
- INITIATOR_REMOTE,
-} JingleInitiator;
-
-G_END_DECLS
-
-#endif
diff --git a/src/gabble.c b/src/gabble.c
deleted file mode 100644
index e690d3dd5..000000000
--- a/src/gabble.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * gabble.h - entry point and utility functions for telepathy-gabble
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#include <telepathy-glib/debug.h>
-#include <telepathy-glib/run.h>
-#include "debug.h"
-#include "gabble-connection-manager.h"
-
-static TpBaseConnectionManager *
-construct_cm (void)
-{
- return (TpBaseConnectionManager *)g_object_new (
- GABBLE_TYPE_CONNECTION_MANAGER, NULL);
-}
-
-int
-main (int argc,
- char **argv)
-{
-#ifdef ENABLE_DEBUG
- gabble_debug_set_flags_from_env ();
-
- /* backwards compatibility */
- if (g_getenv ("GABBLE_PERSIST"))
- {
- gabble_debug_set_flags (0xffff);
- tp_debug_set_all_flags ();
- }
-#endif
-
- return tp_run_connection_manager ("telepathy-gabble", VERSION,
- construct_cm, argc, argv);
-}
diff --git a/src/gabble.h b/src/gabble.h
deleted file mode 100644
index a426e7c13..000000000
--- a/src/gabble.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * gabble.h - entry point and utility functions for telepathy-gabble
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_H__
-#define __GABBLE_H__
-
-#include <dbus/dbus-glib.h>
-
-G_BEGIN_DECLS
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_H__*/
-
diff --git a/src/im-factory.c b/src/im-factory.c
deleted file mode 100644
index e8c16d152..000000000
--- a/src/im-factory.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * im-factory.c - Source for GabbleImFactory
- * Copyright (C) 2006 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
- */
-
-#include "im-factory.h"
-
-#define DBUS_API_SUBJECT_TO_CHANGE
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <glib.h>
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include <loudmouth/loudmouth.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_IM
-
-#include "debug.h"
-#include "disco.h"
-#include "gabble-connection.h"
-#include "gabble-im-channel.h"
-#include <telepathy-glib/interfaces.h>
-#include "text-mixin.h"
-#include <telepathy-glib/channel-factory-iface.h>
-
-static void gabble_im_factory_iface_init (gpointer g_iface,
- gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleImFactory, gabble_im_factory, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
- gabble_im_factory_iface_init));
-
-/* properties */
-enum
-{
- PROP_CONNECTION = 1,
- LAST_PROPERTY
-};
-
-typedef struct _GabbleImFactoryPrivate GabbleImFactoryPrivate;
-struct _GabbleImFactoryPrivate
-{
- GabbleConnection *conn;
- LmMessageHandler *message_cb;
- GHashTable *channels;
-
- gboolean dispose_has_run;
-};
-
-#define GABBLE_IM_FACTORY_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_IM_FACTORY,\
- GabbleImFactoryPrivate))
-
-static GObject *gabble_im_factory_constructor (GType type, guint n_props,
- GObjectConstructParam *props);
-
-static void
-gabble_im_factory_init (GabbleImFactory *fac)
-{
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
-
- priv->channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
-
- priv->message_cb = NULL;
-
- priv->conn = NULL;
- priv->dispose_has_run = FALSE;
-}
-
-static GObject *
-gabble_im_factory_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- /* GabbleImFactoryPrivate *priv; */
-
- obj = G_OBJECT_CLASS (gabble_im_factory_parent_class)->
- constructor (type, n_props, props);
- /* priv = GABBLE_IM_FACTORY_GET_PRIVATE (obj); */
-
- return obj;
-}
-
-
-static void
-gabble_im_factory_dispose (GObject *object)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (object);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- tp_channel_factory_iface_close_all (TP_CHANNEL_FACTORY_IFACE (object));
- g_assert (priv->channels == NULL);
-
- if (G_OBJECT_CLASS (gabble_im_factory_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_im_factory_parent_class)->dispose (object);
-}
-
-static void
-gabble_im_factory_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (object);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_im_factory_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (object);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_im_factory_class_init (GabbleImFactoryClass *gabble_im_factory_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_im_factory_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_im_factory_class,
- sizeof (GabbleImFactoryPrivate));
-
- object_class->constructor = gabble_im_factory_constructor;
- object_class->dispose = gabble_im_factory_dispose;
-
- object_class->get_property = gabble_im_factory_get_property;
- object_class->set_property = gabble_im_factory_set_property;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "IM channel factory object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
-}
-
-static GabbleIMChannel *new_im_channel (GabbleImFactory *fac, TpHandle handle);
-
-static void im_channel_closed_cb (GabbleIMChannel *chan, gpointer user_data);
-
-
-/**
- * im_factory_message_cb:
- *
- * Called by loudmouth when we get an incoming <message>.
- */
-static LmHandlerResult
-im_factory_message_cb (LmMessageHandler *handler,
- LmConnection *lmconn,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (user_data);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
- const gchar *from, *body;
- time_t stamp;
- TpChannelTextMessageType msgtype;
- TpHandle handle;
- GabbleIMChannel *chan;
- gint state;
- TpChannelTextSendError send_error;
-
- if (!gabble_text_mixin_parse_incoming_message (message, &from, &stamp,
- &msgtype, &body, &state, &send_error))
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-
- if (body == NULL && state == -1)
- {
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- handle = tp_handle_ensure (contact_repo, from, NULL, NULL);
- if (handle == 0)
- {
- NODE_DEBUG (message->node, "ignoring message node from malformed jid");
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- chan = g_hash_table_lookup (priv->channels, GINT_TO_POINTER (handle));
-
- if (chan == NULL)
- {
- if (send_error != TP_CHANNEL_SEND_NO_ERROR)
- {
- DEBUG ("ignoring message error; no sending channel");
- tp_handle_unref (contact_repo, handle);
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- DEBUG ("found no IM channel, creating one");
-
- chan = new_im_channel (fac, handle);
- }
-
- g_assert (chan != NULL);
-
- /* now the channel is referencing the handle, so if we unref it, that's
- * not a problem */
- tp_handle_unref (contact_repo, handle);
-
- if (send_error != TP_CHANNEL_SEND_NO_ERROR)
- {
- if (body == NULL)
- {
- DEBUG ("ignoring error sending chat state to %s (handle %u)", from,
- handle);
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- DEBUG ("got error sending to %s (handle %u), msgtype %u, body:\n%s",
- from, handle, msgtype, body);
-
- tp_svc_channel_type_text_emit_send_error ((TpSvcChannelTypeText *)chan,
- send_error, stamp, msgtype, body);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- if (state != -1)
- _gabble_im_channel_state_receive (chan, state);
-
- if (body != NULL)
- _gabble_im_channel_receive (chan, msgtype, handle, from, stamp, body);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-/**
- * im_channel_closed_cb:
- *
- * Signal callback for when an IM channel is closed. Removes the references
- * that #GabbleConnection holds to them.
- */
-static void
-im_channel_closed_cb (GabbleIMChannel *chan, gpointer user_data)
-{
- GabbleImFactory *conn = GABBLE_IM_FACTORY (user_data);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (conn);
- TpHandle contact_handle;
-
- if (priv->channels)
- {
- g_object_get (chan, "handle", &contact_handle, NULL);
-
- DEBUG ("removing channel with handle %d", contact_handle);
-
- g_hash_table_remove (priv->channels, GINT_TO_POINTER (contact_handle));
- }
-}
-
-/**
- * new_im_channel
- */
-static GabbleIMChannel *
-new_im_channel (GabbleImFactory *fac, TpHandle handle)
-{
- GabbleImFactoryPrivate *priv;
- TpBaseConnection *conn;
- GabbleIMChannel *chan;
- char *object_path;
-
- g_assert (GABBLE_IS_IM_FACTORY (fac));
-
- priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
- conn = (TpBaseConnection *)priv->conn;
-
- object_path = g_strdup_printf ("%s/ImChannel%u",
- conn->object_path, handle);
-
- chan = g_object_new (GABBLE_TYPE_IM_CHANNEL,
- "connection", priv->conn,
- "object-path", object_path,
- "handle", handle,
- NULL);
-
- DEBUG ("object path %s", object_path);
-
- g_signal_connect (chan, "closed", (GCallback) im_channel_closed_cb, fac);
-
- g_hash_table_insert (priv->channels, GINT_TO_POINTER (handle), chan);
-
- tp_channel_factory_iface_emit_new_channel (fac, (TpChannelIface *)chan,
- NULL);
-
- g_free (object_path);
-
- return chan;
-}
-
-static void
-gabble_im_factory_iface_close_all (TpChannelFactoryIface *iface)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (iface);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
-
- DEBUG ("closing channels");
-
- if (priv->channels)
- {
- GHashTable *tmp = priv->channels;
- priv->channels = NULL;
- g_hash_table_destroy (tmp);
- }
-}
-
-static void
-gabble_im_factory_iface_connecting (TpChannelFactoryIface *iface)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (iface);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
-
- DEBUG ("adding callbacks");
-
- g_assert (priv->message_cb == NULL);
-
- priv->message_cb = lm_message_handler_new (im_factory_message_cb, fac, NULL);
- lm_connection_register_message_handler (priv->conn->lmconn, priv->message_cb,
- LM_MESSAGE_TYPE_MESSAGE,
- LM_HANDLER_PRIORITY_LAST);
-}
-
-
-
-static void
-gabble_im_factory_iface_connected (TpChannelFactoryIface *iface)
-{
- /* nothing to do */
-}
-
-static void
-gabble_im_factory_iface_disconnected (TpChannelFactoryIface *iface)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (iface);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
-
- DEBUG ("removing callbacks");
-
- g_assert (priv->message_cb != NULL);
-
- lm_connection_unregister_message_handler (priv->conn->lmconn,
- priv->message_cb, LM_MESSAGE_TYPE_MESSAGE);
- lm_message_handler_unref (priv->message_cb);
- priv->message_cb = NULL;
-}
-
-struct _ForeachData
-{
- TpChannelFunc foreach;
- gpointer user_data;
-};
-
-static void
-_foreach_slave (gpointer key, gpointer value, gpointer user_data)
-{
- struct _ForeachData *data = (struct _ForeachData *) user_data;
- TpChannelIface *chan = TP_CHANNEL_IFACE (value);
-
- data->foreach (chan, data->user_data);
-}
-
-static void
-gabble_im_factory_iface_foreach (TpChannelFactoryIface *iface,
- TpChannelFunc foreach,
- gpointer user_data)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (iface);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
- struct _ForeachData data;
-
- data.user_data = user_data;
- data.foreach = foreach;
-
- g_hash_table_foreach (priv->channels, _foreach_slave, &data);
-}
-
-static TpChannelFactoryRequestStatus
-gabble_im_factory_iface_request (TpChannelFactoryIface *iface,
- const gchar *chan_type,
- TpHandleType handle_type,
- guint handle,
- gpointer request,
- TpChannelIface **ret,
- GError **error)
-{
- GabbleImFactory *fac = GABBLE_IM_FACTORY (iface);
- GabbleImFactoryPrivate *priv = GABBLE_IM_FACTORY_GET_PRIVATE (fac);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleIMChannel *chan;
- TpChannelFactoryRequestStatus status;
-
- if (strcmp (chan_type, TP_IFACE_CHANNEL_TYPE_TEXT))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
-
- if (handle_type != TP_HANDLE_TYPE_CONTACT)
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
-
- if (!tp_handle_is_valid (contact_repo, handle, error))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_ERROR;
-
- chan = g_hash_table_lookup (priv->channels, GINT_TO_POINTER (handle));
-
- status = TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
- if (!chan)
- {
- status = TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
- chan = new_im_channel (fac, handle);
- }
-
- g_assert (chan);
- *ret = TP_CHANNEL_IFACE (chan);
- return status;
-}
-
-static void
-gabble_im_factory_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *) g_iface;
-
- klass->close_all = gabble_im_factory_iface_close_all;
- klass->connecting = gabble_im_factory_iface_connecting;
- klass->connected = gabble_im_factory_iface_connected;
- klass->disconnected = gabble_im_factory_iface_disconnected;
- klass->foreach = gabble_im_factory_iface_foreach;
- klass->request = gabble_im_factory_iface_request;
-}
-
diff --git a/src/im-factory.h b/src/im-factory.h
deleted file mode 100644
index b895ed4aa..000000000
--- a/src/im-factory.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * im-factory.h - Header for GabbleImFactory
- * Copyright (C) 2006 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
- */
-
-#ifndef __IM_FACTORY_H__
-#define __IM_FACTORY_H__
-
-#include <glib-object.h>
-
-#include "gabble-im-channel.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleImFactory GabbleImFactory;
-typedef struct _GabbleImFactoryClass GabbleImFactoryClass;
-
-struct _GabbleImFactoryClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleImFactory {
- GObject parent;
-};
-
-GType gabble_im_factory_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_IM_FACTORY \
- (gabble_im_factory_get_type ())
-#define GABBLE_IM_FACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_IM_FACTORY, GabbleImFactory))
-#define GABBLE_IM_FACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_IM_FACTORY,\
- GabbleImFactoryClass))
-#define GABBLE_IS_IM_FACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_IM_FACTORY))
-#define GABBLE_IS_IM_FACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_IM_FACTORY))
-#define GABBLE_IM_FACTORY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_IM_FACTORY,\
- GabbleImFactoryClass))
-
-
-G_END_DECLS
-
-#endif /* #ifndef __IM_FACTORY_H__ */
-
diff --git a/src/libmd5-rfc/.git-darcs-dir b/src/libmd5-rfc/.git-darcs-dir
deleted file mode 100644
index e69de29bb..000000000
--- a/src/libmd5-rfc/.git-darcs-dir
+++ /dev/null
diff --git a/src/libmd5-rfc/md5.c b/src/libmd5-rfc/md5.c
deleted file mode 100644
index c35d96c5e..000000000
--- a/src/libmd5-rfc/md5.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.c is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
- either statically or dynamically; added missing #include <string.h>
- in library.
- 2002-03-11 lpd Corrected argument list for main(), and added int return
- type, in test program and T value program.
- 2002-02-21 lpd Added missing #include <stdio.h> in test program.
- 2000-07-03 lpd Patched to eliminate warnings about "constant is
- unsigned in ANSI C, signed in traditional"; made test program
- self-checking.
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
- 1999-05-03 lpd Original version.
- */
-
-#include "md5.h"
-#include <string.h>
-
-#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
-#ifdef ARCH_IS_BIG_ENDIAN
-# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
-#else
-# define BYTE_ORDER 0
-#endif
-
-#define T_MASK ((md5_word_t)~0)
-#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
-#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3 0x242070db
-#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
-#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6 0x4787c62a
-#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
-#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9 0x698098d8
-#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
-#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
-#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13 0x6b901122
-#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
-#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16 0x49b40821
-#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
-#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19 0x265e5a51
-#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
-#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22 0x02441453
-#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
-#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25 0x21e1cde6
-#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
-#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28 0x455a14ed
-#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
-#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31 0x676f02d9
-#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
-#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
-#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35 0x6d9d6122
-#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
-#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38 0x4bdecfa9
-#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
-#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41 0x289b7ec6
-#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
-#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44 0x04881d05
-#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
-#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47 0x1fa27cf8
-#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
-#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50 0x432aff97
-#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
-#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53 0x655b59c3
-#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
-#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
-#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57 0x6fa87e4f
-#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
-#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60 0x4e0811a1
-#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
-#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63 0x2ad7d2bb
-#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
- md5_word_t
- a = pms->abcd[0], b = pms->abcd[1],
- c = pms->abcd[2], d = pms->abcd[3];
- md5_word_t t;
-#if BYTE_ORDER > 0
- /* Define storage only for big-endian CPUs. */
- md5_word_t X[16];
-#else
- /* Define storage for little-endian or both types of CPUs. */
- md5_word_t xbuf[16];
- const md5_word_t *X;
-#endif
-
- {
-#if BYTE_ORDER == 0
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
-#endif
-#if BYTE_ORDER <= 0 /* little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if (!((data - (const md5_byte_t *)0) & 3)) {
- /* data are properly aligned */
- X = (const md5_word_t *)data;
- } else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
-#endif
-#if BYTE_ORDER == 0
- else /* dynamic big-endian */
-#endif
-#if BYTE_ORDER >= 0 /* big-endian */
- {
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const md5_byte_t *xp = data;
- int i;
-
-# if BYTE_ORDER == 0
- X = xbuf; /* (dynamic only) */
-# else
-# define xbuf X /* (static only) */
-# endif
- for (i = 0; i < 16; ++i, xp += 4)
- xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
- }
-#endif
- }
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + F(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 7, T1);
- SET(d, a, b, c, 1, 12, T2);
- SET(c, d, a, b, 2, 17, T3);
- SET(b, c, d, a, 3, 22, T4);
- SET(a, b, c, d, 4, 7, T5);
- SET(d, a, b, c, 5, 12, T6);
- SET(c, d, a, b, 6, 17, T7);
- SET(b, c, d, a, 7, 22, T8);
- SET(a, b, c, d, 8, 7, T9);
- SET(d, a, b, c, 9, 12, T10);
- SET(c, d, a, b, 10, 17, T11);
- SET(b, c, d, a, 11, 22, T12);
- SET(a, b, c, d, 12, 7, T13);
- SET(d, a, b, c, 13, 12, T14);
- SET(c, d, a, b, 14, 17, T15);
- SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + G(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 1, 5, T17);
- SET(d, a, b, c, 6, 9, T18);
- SET(c, d, a, b, 11, 14, T19);
- SET(b, c, d, a, 0, 20, T20);
- SET(a, b, c, d, 5, 5, T21);
- SET(d, a, b, c, 10, 9, T22);
- SET(c, d, a, b, 15, 14, T23);
- SET(b, c, d, a, 4, 20, T24);
- SET(a, b, c, d, 9, 5, T25);
- SET(d, a, b, c, 14, 9, T26);
- SET(c, d, a, b, 3, 14, T27);
- SET(b, c, d, a, 8, 20, T28);
- SET(a, b, c, d, 13, 5, T29);
- SET(d, a, b, c, 2, 9, T30);
- SET(c, d, a, b, 7, 14, T31);
- SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + H(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 5, 4, T33);
- SET(d, a, b, c, 8, 11, T34);
- SET(c, d, a, b, 11, 16, T35);
- SET(b, c, d, a, 14, 23, T36);
- SET(a, b, c, d, 1, 4, T37);
- SET(d, a, b, c, 4, 11, T38);
- SET(c, d, a, b, 7, 16, T39);
- SET(b, c, d, a, 10, 23, T40);
- SET(a, b, c, d, 13, 4, T41);
- SET(d, a, b, c, 0, 11, T42);
- SET(c, d, a, b, 3, 16, T43);
- SET(b, c, d, a, 6, 23, T44);
- SET(a, b, c, d, 9, 4, T45);
- SET(d, a, b, c, 12, 11, T46);
- SET(c, d, a, b, 15, 16, T47);
- SET(b, c, d, a, 2, 23, T48);
-#undef SET
-
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + I(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 6, T49);
- SET(d, a, b, c, 7, 10, T50);
- SET(c, d, a, b, 14, 15, T51);
- SET(b, c, d, a, 5, 21, T52);
- SET(a, b, c, d, 12, 6, T53);
- SET(d, a, b, c, 3, 10, T54);
- SET(c, d, a, b, 10, 15, T55);
- SET(b, c, d, a, 1, 21, T56);
- SET(a, b, c, d, 8, 6, T57);
- SET(d, a, b, c, 15, 10, T58);
- SET(c, d, a, b, 6, 15, T59);
- SET(b, c, d, a, 13, 21, T60);
- SET(a, b, c, d, 4, 6, T61);
- SET(d, a, b, c, 11, 10, T62);
- SET(c, d, a, b, 2, 15, T63);
- SET(b, c, d, a, 9, 21, T64);
-#undef SET
-
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- pms->abcd[0] += a;
- pms->abcd[1] += b;
- pms->abcd[2] += c;
- pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
- pms->count[0] = pms->count[1] = 0;
- pms->abcd[0] = 0x67452301;
- pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
- pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
- pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
- const md5_byte_t *p = data;
- int left = nbytes;
- int offset = (pms->count[0] >> 3) & 63;
- md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
- if (nbytes <= 0)
- return;
-
- /* Update the message length. */
- pms->count[1] += nbytes >> 29;
- pms->count[0] += nbits;
- if (pms->count[0] < nbits)
- pms->count[1]++;
-
- /* Process an initial partial block. */
- if (offset) {
- int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
- memcpy(pms->buf + offset, p, copy);
- if (offset + copy < 64)
- return;
- p += copy;
- left -= copy;
- md5_process(pms, pms->buf);
- }
-
- /* Process full blocks. */
- for (; left >= 64; p += 64, left -= 64)
- md5_process(pms, p);
-
- /* Process a final partial block. */
- if (left)
- memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
- static const md5_byte_t pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- md5_byte_t data[8];
- int i;
-
- /* Save the length before padding. */
- for (i = 0; i < 8; ++i)
- data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
- /* Pad to 56 bytes mod 64. */
- md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
- /* Append the length. */
- md5_append(pms, data, 8);
- for (i = 0; i < 16; ++i)
- digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
diff --git a/src/libmd5-rfc/md5.h b/src/libmd5-rfc/md5.h
deleted file mode 100644
index 698c995d8..000000000
--- a/src/libmd5-rfc/md5.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.h is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Removed support for non-ANSI compilers; removed
- references to Ghostscript; clarified derivation from RFC 1321;
- now handles byte order either statically or dynamically.
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
- added conditionalization for C++ compilation from Martin
- Purschke <purschke@bnl.gov>.
- 1999-05-03 lpd Original version.
- */
-
-#ifndef md5_INCLUDED
-# define md5_INCLUDED
-
-/*
- * This package supports both compile-time and run-time determination of CPU
- * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
- * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
- * defined as non-zero, the code will be compiled to run only on big-endian
- * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
- * run on either big- or little-endian CPUs, but will run slightly less
- * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
- */
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
- md5_word_t count[2]; /* message length in bits, lsw first */
- md5_word_t abcd[4]; /* digest buffer */
- md5_byte_t buf[64]; /* accumulate block */
-} md5_state_t;
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* Initialize the algorithm. */
-void md5_init(md5_state_t *pms);
-
-/* Append a string to the message. */
-void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
-
-/* Finish the message and return the digest. */
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
-
-#ifdef __cplusplus
-} /* end extern "C" */
-#endif
-
-#endif /* md5_INCLUDED */
diff --git a/src/libmd5-rfc/md5main.c b/src/libmd5-rfc/md5main.c
deleted file mode 100644
index 625a6198e..000000000
--- a/src/libmd5-rfc/md5main.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- Copyright (C) 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5main.c,v 1.1 2002/04/13 19:20:28 lpd Exp $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.c is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Splits off main program into a separate file, md5main.c.
- */
-
-#include "md5.h"
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-/*
- * This file builds an executable that performs various functions related
- * to the MD5 library. Typical compilation:
- * gcc -o md5main -lm md5main.c md5.c
- */
-static const char *const usage = "\
-Usage:\n\
- md5main --test # run the self-test (A.5 of RFC 1321)\n\
- md5main --t-values # print the T values for the library\n\
- md5main --version # print the version of the package\n\
-";
-static const char *const version = "2002-04-13";
-
-/* Run the self-test. */
-static int
-do_test(void)
-{
- static const char *const test[7*2] = {
- "", "d41d8cd98f00b204e9800998ecf8427e",
- "a", "0cc175b9c0f1b6a831c399e269772661",
- "abc", "900150983cd24fb0d6963f7d28e17f72",
- "message digest", "f96b697d7cb7938d525a2f31aaf161d0",
- "abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "d174ab98d277d9f5a5611c2c9f419d9f",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"
- };
- int i;
- int status = 0;
-
- for (i = 0; i < 7*2; i += 2) {
- md5_state_t state;
- md5_byte_t digest[16];
- char hex_output[16*2 + 1];
- int di;
-
- md5_init(&state);
- md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
- md5_finish(&state, digest);
- for (di = 0; di < 16; ++di)
- sprintf(hex_output + di * 2, "%02x", digest[di]);
- if (strcmp(hex_output, test[i + 1])) {
- printf("MD5 (\"%s\") = ", test[i]);
- puts(hex_output);
- printf("**** ERROR, should be: %s\n", test[i + 1]);
- status = 1;
- }
- }
- if (status == 0)
- puts("md5 self-test completed successfully.");
- return status;
-}
-
-/* Print the T values. */
-static int
-do_t_values(void)
-{
- int i;
- for (i = 1; i <= 64; ++i) {
- unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
-
- /*
- * The following nonsense is only to avoid compiler warnings about
- * "integer constant is unsigned in ANSI C, signed with -traditional".
- */
- if (v >> 31) {
- printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", i,
- v, (unsigned long)(unsigned int)(~v));
- } else {
- printf("#define T%d 0x%08lx\n", i, v);
- }
- }
- return 0;
-}
-
-/* Main program */
-int
-main(int argc, char *argv[])
-{
- if (argc == 2) {
- if (!strcmp(argv[1], "--test"))
- return do_test();
- if (!strcmp(argv[1], "--t-values"))
- return do_t_values();
- if (!strcmp(argv[1], "--version")) {
- puts(version);
- return 0;
- }
- }
- puts(usage);
- return 0;
-}
diff --git a/src/media-factory.c b/src/media-factory.c
deleted file mode 100644
index b24088a71..000000000
--- a/src/media-factory.c
+++ /dev/null
@@ -1,875 +0,0 @@
-/*
- * media-factory.c - Source for GabbleMediaFactory
- * Copyright (C) 2006 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
- */
-
-#include "media-factory.h"
-
-#define DBUS_API_SUBJECT_TO_CHANGE
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <glib.h>
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include <loudmouth/loudmouth.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "debug.h"
-#include "gabble-connection.h"
-#include "gabble-media-channel.h"
-#include "namespaces.h"
-#include <telepathy-glib/interfaces.h>
-#include "text-mixin.h"
-#include <telepathy-glib/channel-factory-iface.h>
-#include "util.h"
-
-static void gabble_media_factory_iface_init (gpointer g_iface,
- gpointer iface_data);
-static LmHandlerResult media_factory_jingle_cb (LmMessageHandler *,
- LmConnection *, LmMessage *, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleMediaFactory, gabble_media_factory,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
- gabble_media_factory_iface_init));
-
-/* properties */
-enum
-{
- PROP_CONNECTION = 1,
- LAST_PROPERTY
-};
-
-typedef struct _GabbleMediaFactoryPrivate GabbleMediaFactoryPrivate;
-struct _GabbleMediaFactoryPrivate
-{
- GabbleConnection *conn;
- LmMessageHandler *jingle_cb;
- LmMessageHandler *jingle_info_cb;
-
- GPtrArray *channels;
- guint channel_index;
-
- GHashTable *session_chans;
-
- gboolean get_stun_from_jingle;
- gchar *stun_server;
- guint16 stun_port;
- gchar *relay_token;
-
- gboolean dispose_has_run;
-};
-
-#define GABBLE_MEDIA_FACTORY_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_MEDIA_FACTORY, \
- GabbleMediaFactoryPrivate))
-
-static GObject *gabble_media_factory_constructor (GType type, guint n_props,
- GObjectConstructParam *props);
-
-static void
-gabble_media_factory_init (GabbleMediaFactory *fac)
-{
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
-
- priv->channels = g_ptr_array_sized_new (1);
- priv->channel_index = 0;
-
- priv->jingle_cb = NULL;
- priv->jingle_info_cb = NULL;
-
- priv->conn = NULL;
- priv->dispose_has_run = FALSE;
-
- priv->session_chans = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
-}
-
-static GObject *
-gabble_media_factory_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleMediaFactoryPrivate *priv;
-
- obj = G_OBJECT_CLASS (gabble_media_factory_parent_class)->
- constructor (type, n_props, props);
- priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (obj);
-
- return obj;
-}
-
-
-static void
-gabble_media_factory_dispose (GObject *object)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (object);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- g_assert (priv->jingle_cb == NULL);
- g_assert (priv->jingle_info_cb == NULL);
-
- tp_channel_factory_iface_close_all (TP_CHANNEL_FACTORY_IFACE (object));
- g_assert (priv->channels == NULL);
-
- if (priv->session_chans)
- {
- g_assert (g_hash_table_size (priv->session_chans) == 0);
- g_hash_table_destroy (priv->session_chans);
- priv->session_chans = NULL;
- }
-
- g_free (priv->stun_server);
- g_free (priv->relay_token);
-
- if (G_OBJECT_CLASS (gabble_media_factory_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_media_factory_parent_class)->dispose (object);
-}
-
-static void
-gabble_media_factory_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (object);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_media_factory_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (object);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_media_factory_class_init (GabbleMediaFactoryClass *gabble_media_factory_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_media_factory_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_media_factory_class,
- sizeof (GabbleMediaFactoryPrivate));
-
- object_class->constructor = gabble_media_factory_constructor;
- object_class->dispose = gabble_media_factory_dispose;
-
- object_class->get_property = gabble_media_factory_get_property;
- object_class->set_property = gabble_media_factory_set_property;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "media channel factory object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
-}
-
-static gboolean _gabble_media_factory_sid_in_use (GabbleMediaFactory *fac,
- const gchar *sid);
-static GabbleMediaChannel *new_media_channel (GabbleMediaFactory *fac,
- TpHandle handle);
-static void media_channel_closed_cb (GabbleMediaChannel *chan,
- gpointer user_data);
-
-/**
- * media_factory_jingle_cb
- *
- * Called by loudmouth when we get an incoming <iq>. This handler
- * is concerned only with jingle session queries, and allows other
- * handlers to be called for other queries.
- */
-static LmHandlerResult
-media_factory_jingle_cb (LmMessageHandler *handler,
- LmConnection *lmconn,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (user_data);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- LmMessageNode *iq_node, *session_node;
- const gchar *from, *id, *action, *sid, *resource;
- TpHandle handle = 0;
- GabbleMediaChannel *chan = NULL;
- gboolean chan_is_new = FALSE;
- GError *error = NULL;
-
- g_assert (lmconn == priv->conn->lmconn);
-
- /* all jingle actions are sets */
- if (LM_MESSAGE_SUB_TYPE_SET != lm_message_get_sub_type (message))
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- /* is it for us? */
- iq_node = lm_message_get_node (message);
- session_node = lm_message_node_get_child_with_namespace (message->node,
- "jingle", NS_JINGLE);
-
- if (session_node != NULL)
- {
- action = lm_message_node_get_attribute (session_node, "action");
- }
- else
- {
- session_node = lm_message_node_get_child_with_namespace (iq_node,
- "session", NS_GOOGLE_SESSION);
-
- if (session_node == NULL)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- action = lm_message_node_get_attribute (session_node, "type");
- }
-
- if (action == NULL)
- {
- NODE_DEBUG (iq_node, "session action not found");
- goto BAD_REQUEST;
- }
-
- from = lm_message_node_get_attribute (iq_node, "from");
- if (from == NULL)
- {
- NODE_DEBUG (iq_node, "'from' attribute not found");
- goto BAD_REQUEST;
- }
-
- handle = tp_handle_ensure (contact_repo, from, NULL, NULL);
- if (handle == 0)
- {
- NODE_DEBUG (iq_node, "unable to get handle for sender");
- goto BAD_REQUEST;
- }
-
- resource = strchr (from, '/');
- if (resource == NULL || *resource == '\0')
- {
- NODE_DEBUG (iq_node, "sender with no resource");
- goto BAD_REQUEST;
- }
-
- id = lm_message_node_get_attribute (iq_node, "id");
- if (id == NULL)
- {
- NODE_DEBUG (iq_node, "'id' attribute not found");
- goto BAD_REQUEST;
- }
-
- /* does the session exist? */
- sid = lm_message_node_get_attribute (session_node, "sid");
- if (sid == NULL)
- sid = lm_message_node_get_attribute (session_node, "id");
-
- if (sid == NULL)
- {
- NODE_DEBUG (iq_node, "unable to get session id");
- goto BAD_REQUEST;
- }
-
- if (_gabble_media_factory_sid_in_use (fac, sid))
- {
- /* if it's media session, we should have it in here */
- chan = g_hash_table_lookup (priv->session_chans, sid);
- }
-
- /* it's a new session */
- if (chan == NULL)
- {
- /* if the session is unknown, the only allowed action is "initiate" */
- if (tp_strdiff (action, "initiate") &&
- tp_strdiff (action, "session-initiate"))
- {
- NODE_DEBUG (iq_node,
- "action is not \"initiate\" or \"session-initiate\", rejecting");
- goto BAD_REQUEST;
- }
-
- DEBUG ("creating media channel");
-
- chan = new_media_channel (fac, handle);
- chan_is_new = TRUE;
- }
-
- g_assert (chan != NULL);
-
- DEBUG ("dispatching to session %s", sid);
- g_object_ref (chan);
-
- if (_gabble_media_channel_dispatch_session_action (chan, handle, resource,
- sid, message, session_node, action, &error))
- {
- if (chan_is_new)
- tp_channel_factory_iface_emit_new_channel (fac,
- (TpChannelIface *)chan, NULL);
- }
- else
- {
- if (chan_is_new)
- gabble_media_channel_close (chan);
-
- g_assert (error != NULL);
- _gabble_connection_send_iq_error (priv->conn, message, error->code,
- error->message);
- }
-
- g_object_unref (chan);
- if (handle)
- tp_handle_unref (contact_repo, handle);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-
-BAD_REQUEST:
- _gabble_connection_send_iq_error (
- priv->conn, message, XMPP_ERROR_BAD_REQUEST, NULL);
-
- if (handle)
- tp_handle_unref (contact_repo, handle);
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static const gchar *
-_gabble_media_factory_get_unique_sid (GabbleMediaFactory *fac)
-{
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- guint32 val;
- gchar *sid = NULL;
- gboolean unique = FALSE;
-
- while (!unique)
- {
- val = g_random_int_range (1000000, G_MAXINT);
-
- g_free (sid);
- sid = g_strdup_printf ("%u", val);
-
- unique = !_gabble_media_factory_sid_in_use (fac, sid);
- }
-
- g_hash_table_insert (priv->session_chans, sid, NULL);
-
- return sid;
-}
-
-static gboolean
-_gabble_media_factory_sid_in_use (GabbleMediaFactory *fac, const gchar *sid)
-{
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- gpointer key, value;
-
- return g_hash_table_lookup_extended (priv->session_chans, sid, &key, &value);
-}
-
-const gchar *
-_gabble_media_factory_allocate_sid (GabbleMediaFactory *fac,
- GabbleMediaChannel *chan)
-{
- const gchar *sid = _gabble_media_factory_get_unique_sid (fac);
-
- g_return_val_if_fail (sid, NULL);
-
- return _gabble_media_factory_register_sid (fac, sid, chan);
-}
-
-const gchar *
-_gabble_media_factory_register_sid (GabbleMediaFactory *fac,
- const gchar *sid,
- GabbleMediaChannel *chan)
-{
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- gchar *sid_copy = g_strdup (sid);
-
- g_hash_table_replace (priv->session_chans, sid_copy, chan);
-
- return sid_copy;
-}
-
-void
-_gabble_media_factory_free_sid (GabbleMediaFactory *fac, const gchar *sid)
-{
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- if (g_hash_table_lookup (priv->session_chans, sid))
- {
- g_hash_table_remove (priv->session_chans, sid);
- }
-}
-
-static gboolean
-_remove_sid_mapping (gpointer key, gpointer value, gpointer user_data)
-{
- GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (value);
- GabbleMediaChannel *target_chan = GABBLE_MEDIA_CHANNEL (user_data);
-
- if (chan == target_chan) return TRUE;
- return FALSE;
-}
-
-/**
- * media_channel_closed_cb:
- *
- * Signal callback for when a media channel is closed. Removes the references
- * that #GabbleMediaFactory holds to them. Also removes all the sessions for
- * the closed channel.
- */
-static void
-media_channel_closed_cb (GabbleMediaChannel *chan, gpointer user_data)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (user_data);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
-
- if (priv->channels)
- {
- DEBUG ("removing media channel %p with ref count %d",
- chan, G_OBJECT (chan)->ref_count);
-
- g_ptr_array_remove (priv->channels, chan);
- g_object_unref (chan);
- }
-
- if (priv->session_chans)
- {
- g_hash_table_foreach_remove (priv->session_chans, _remove_sid_mapping,
- chan);
- }
-}
-
-/**
- * new_media_channel
- *
- * Creates a new empty GabbleMediaChannel.
- */
-static GabbleMediaChannel *
-new_media_channel (GabbleMediaFactory *fac, TpHandle creator)
-{
- GabbleMediaFactoryPrivate *priv;
- TpBaseConnection *conn;
- GabbleMediaChannel *chan;
- gchar *object_path;
-
- g_assert (GABBLE_IS_MEDIA_FACTORY (fac));
-
- priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- conn = (TpBaseConnection *)priv->conn;
-
- object_path = g_strdup_printf ("%s/MediaChannel%u",
- conn->object_path, priv->channel_index);
- priv->channel_index += 1;
-
- chan = g_object_new (GABBLE_TYPE_MEDIA_CHANNEL,
- "connection", priv->conn,
- "factory", fac,
- "object-path", object_path,
- "creator", creator,
- NULL);
-
- if (priv->stun_server != NULL)
- {
- g_object_set ((GObject *) chan, "stun-server", priv->stun_server, NULL);
-
- if (priv->stun_port != 0)
- g_object_set ((GObject *) chan, "stun-port", priv->stun_port, NULL);
- }
-
- if (priv->relay_token != NULL)
- {
- g_object_set ((GObject *) chan, "gtalk-p2p-relay-token",
- priv->relay_token, NULL);
- }
-
- DEBUG ("object path %s", object_path);
-
- g_signal_connect (chan, "closed", (GCallback) media_channel_closed_cb, fac);
-
- g_ptr_array_add (priv->channels, chan);
-
- g_free (object_path);
-
- return chan;
-}
-
-
-static void
-jingle_info_send_request (GabbleMediaFactory *fac)
-{
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *base = (TpBaseConnection *) priv->conn;
- LmMessage *msg;
- LmMessageNode *node;
- const gchar *jid;
- GError *error = NULL;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
- TP_HANDLE_TYPE_CONTACT);
-
- jid = tp_handle_inspect (contact_handles, base->self_handle);
- msg = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_GET);
-
- node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (node, "xmlns", NS_GOOGLE_JINGLE_INFO);
-
- if (!_gabble_connection_send (priv->conn, msg, &error))
- {
- DEBUG ("jingle info send failed: %s\n", error->message);
- g_error_free (error);
- }
-
- lm_message_unref (msg);
-}
-
-
-/**
- * jingle_info_iq_callback
- *
- * Called by loudmouth when we get an incoming <iq>. This handler
- * is concerned only with Jingle info queries.
- */
-LmHandlerResult
-jingle_info_iq_callback (LmMessageHandler *handler,
- LmConnection *lmconn,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (user_data);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- LmMessageSubType sub_type;
- LmMessageNode *query_node, *node;
-
- query_node = lm_message_node_get_child_with_namespace (message->node,
- "query", NS_GOOGLE_JINGLE_INFO);
-
- if (query_node == NULL)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- sub_type = lm_message_get_sub_type (message);
-
- if (sub_type == LM_MESSAGE_SUB_TYPE_ERROR)
- {
- GabbleXmppError xmpp_error = INVALID_XMPP_ERROR;
-
- node = lm_message_node_get_child (message->node, "error");
- if (node != NULL)
- {
- xmpp_error = gabble_xmpp_error_from_node (node);
- }
-
- DEBUG ("jingle info error: %s", xmpp_error == INVALID_XMPP_ERROR ?
- "unknown error" : gabble_xmpp_error_string (xmpp_error));
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- if (sub_type != LM_MESSAGE_SUB_TYPE_RESULT &&
- sub_type != LM_MESSAGE_SUB_TYPE_SET)
- {
- DEBUG ("jingle info: unexpected IQ type, ignoring");
-
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- if (priv->get_stun_from_jingle)
- node = lm_message_node_get_child (query_node, "stun");
- else
- node = NULL;
-
- if (node != NULL)
- {
- node = lm_message_node_get_child (node, "server");
-
- if (node != NULL)
- {
- const gchar *server;
- const gchar *port;
-
- server = lm_message_node_get_attribute (node, "host");
- port = lm_message_node_get_attribute (node, "udp");
-
- if (server != NULL)
- {
- DEBUG ("jingle info: got stun server %s", server);
- g_free (priv->stun_server);
- priv->stun_server = g_strdup (server);
- }
-
- if (port != NULL)
- {
- DEBUG ("jingle info: got stun port %s", port);
- priv->stun_port = atoi (port);
- }
- }
- }
-
- node = lm_message_node_get_child (query_node, "relay");
-
- if (node != NULL)
- {
- node = lm_message_node_get_child (node, "token");
-
- if (node != NULL)
- {
- const gchar *token;
-
- token = lm_message_node_get_value (node);
-
- if (token != NULL)
- {
- DEBUG ("jingle info: got relay token %s", token);
- g_free (priv->relay_token);
- priv->relay_token = g_strdup (token);
- }
- }
- }
-
- if (sub_type == LM_MESSAGE_SUB_TYPE_SET)
- {
- _gabble_connection_acknowledge_set_iq (priv->conn, message);
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-
-static void
-gabble_media_factory_iface_close_all (TpChannelFactoryIface *iface)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (iface);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
-
- DEBUG ("closing channels");
-
- if (priv->channels)
- {
- GPtrArray *tmp = priv->channels;
- priv->channels = NULL;
-
- guint i;
-
- for (i = 0; i < tmp->len; i++)
- {
- GabbleMediaChannel *chan = g_ptr_array_index (tmp, i);
-
- DEBUG ("about to unref channel with ref_count %d",
- G_OBJECT (chan)->ref_count);
-
- g_object_unref (chan);
- }
-
- g_ptr_array_free (tmp, TRUE);
- }
-
- if (priv->session_chans)
- {
- g_hash_table_destroy (priv->session_chans);
- priv->session_chans = NULL;
- }
-}
-
-static void
-gabble_media_factory_iface_connecting (TpChannelFactoryIface *iface)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (iface);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
-
- g_assert (priv->conn != NULL);
- g_assert (priv->conn->lmconn != NULL);
-
- DEBUG ("adding callbacks");
-
- g_assert (priv->jingle_cb == NULL);
- g_assert (priv->jingle_info_cb == NULL);
-
- priv->jingle_cb = lm_message_handler_new (media_factory_jingle_cb, fac,
- NULL);
- lm_connection_register_message_handler (priv->conn->lmconn, priv->jingle_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_NORMAL);
-
- priv->jingle_info_cb = lm_message_handler_new (jingle_info_iq_callback, fac,
- NULL);
- lm_connection_register_message_handler (priv->conn->lmconn,
- priv->jingle_info_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_NORMAL);
-}
-
-static void
-gabble_media_factory_iface_connected (TpChannelFactoryIface *iface)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (iface);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- gchar *stun_server = NULL;
- guint stun_port = 0;
-
- g_object_get (priv->conn,
- "stun-server", &stun_server,
- "stun-port", &stun_port,
- NULL);
-
- if (stun_server == NULL)
- {
- priv->get_stun_from_jingle = TRUE;
- }
- else
- {
- g_free (priv->stun_server);
- priv->stun_server = stun_server;
- priv->stun_port = stun_port;
- }
-
- if (priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO)
- {
- jingle_info_send_request (fac);
- }
-}
-
-static void
-gabble_media_factory_iface_disconnected (TpChannelFactoryIface *iface)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (iface);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
-
- DEBUG ("removing callbacks");
-
- g_assert (priv->jingle_cb != NULL);
- g_assert (priv->jingle_info_cb != NULL);
-
- lm_connection_unregister_message_handler (priv->conn->lmconn,
- priv->jingle_cb, LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->jingle_cb);
- priv->jingle_cb = NULL;
-
- lm_connection_unregister_message_handler (priv->conn->lmconn,
- priv->jingle_info_cb, LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->jingle_info_cb);
- priv->jingle_info_cb = NULL;
-
-}
-
-static void
-gabble_media_factory_iface_foreach (TpChannelFactoryIface *iface,
- TpChannelFunc foreach,
- gpointer user_data)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (iface);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- guint i;
-
- for (i = 0; i < priv->channels->len; i++)
- {
- foreach (TP_CHANNEL_IFACE (g_ptr_array_index (priv->channels, i)),
- user_data);
- }
-}
-
-static TpChannelFactoryRequestStatus
-gabble_media_factory_iface_request (TpChannelFactoryIface *iface,
- const gchar *chan_type,
- TpHandleType handle_type,
- guint handle,
- gpointer request,
- TpChannelIface **ret,
- GError **error)
-{
- GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (iface);
- GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- GabbleMediaChannel *chan = NULL;
-
- if (strcmp (chan_type, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
-
- if (handle_type == 0)
- {
- /* create an empty channel */
- chan = new_media_channel (fac, conn->self_handle);
- }
- else if (handle_type == TP_HANDLE_TYPE_CONTACT)
- {
- chan = new_media_channel (fac, conn->self_handle);
-
- if (!_gabble_media_channel_add_member ((GObject *)chan, handle, "",
- error))
- {
- gabble_media_channel_close (chan);
-
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_ERROR;
- }
- }
- else
- {
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
- }
-
- g_assert (chan != NULL);
- tp_channel_factory_iface_emit_new_channel (fac, (TpChannelIface *)chan,
- request);
-
- *ret = TP_CHANNEL_IFACE (chan);
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
-}
-
-static void
-gabble_media_factory_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *) g_iface;
-
- klass->close_all = gabble_media_factory_iface_close_all;
- klass->connected = gabble_media_factory_iface_connected;
- klass->connecting = gabble_media_factory_iface_connecting;
- klass->disconnected = gabble_media_factory_iface_disconnected;
- klass->foreach = gabble_media_factory_iface_foreach;
- klass->request = gabble_media_factory_iface_request;
-}
-
diff --git a/src/media-factory.h b/src/media-factory.h
deleted file mode 100644
index 90b19c7a3..000000000
--- a/src/media-factory.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * media-factory.h - Header for GabbleMediaFactory
- * Copyright (C) 2006 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
- */
-
-#ifndef __MEDIA_FACTORY_H__
-#define __MEDIA_FACTORY_H__
-
-#include <glib-object.h>
-
-#include "gabble-media-channel.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleMediaFactory GabbleMediaFactory;
-typedef struct _GabbleMediaFactoryClass GabbleMediaFactoryClass;
-
-struct _GabbleMediaFactoryClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleMediaFactory {
- GObject parent;
-};
-
-GType gabble_media_factory_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_MEDIA_FACTORY \
- (gabble_media_factory_get_type ())
-#define GABBLE_MEDIA_FACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MEDIA_FACTORY,\
- GabbleMediaFactory))
-#define GABBLE_MEDIA_FACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MEDIA_FACTORY,\
- GabbleMediaFactoryClass))
-#define GABBLE_IS_MEDIA_FACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MEDIA_FACTORY))
-#define GABBLE_IS_MEDIA_FACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MEDIA_FACTORY))
-#define GABBLE_MEDIA_FACTORY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MEDIA_FACTORY,\
- GabbleMediaFactoryClass))
-
-const gchar * _gabble_media_factory_allocate_sid (GabbleMediaFactory *fac,
- GabbleMediaChannel *chan);
-const gchar * _gabble_media_factory_register_sid (GabbleMediaFactory *fac,
- const gchar *sid, GabbleMediaChannel *chan);
-void _gabble_media_factory_free_sid (GabbleMediaFactory *fac,
- const gchar *sid);
-
-G_END_DECLS
-
-#endif /* #ifndef __MEDIA_FACTORY_H__ */
-
diff --git a/src/muc-factory.c b/src/muc-factory.c
deleted file mode 100644
index 088d434a7..000000000
--- a/src/muc-factory.c
+++ /dev/null
@@ -1,1004 +0,0 @@
-/*
- * muc-factory.c - Source for GabbleMucFactory
- * Copyright (C) 2006 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
- */
-
-#include "muc-factory.h"
-
-#define DBUS_API_SUBJECT_TO_CHANGE
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <glib.h>
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include <loudmouth/loudmouth.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MUC
-
-#include "debug.h"
-#include "disco.h"
-#include "gabble-connection.h"
-#include "presence-cache.h"
-#include "gabble-muc-channel.h"
-#include "gabble-roomlist-channel.h"
-#include "namespaces.h"
-#include <telepathy-glib/interfaces.h>
-#include "text-mixin.h"
-#include <telepathy-glib/channel-factory-iface.h>
-#include "util.h"
-
-static void gabble_muc_factory_iface_init (gpointer g_iface,
- gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleMucFactory, gabble_muc_factory, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
- gabble_muc_factory_iface_init));
-
-/* properties */
-enum
-{
- PROP_CONNECTION = 1,
- LAST_PROPERTY
-};
-
-typedef struct _GabbleMucFactoryPrivate GabbleMucFactoryPrivate;
-struct _GabbleMucFactoryPrivate
-{
- GabbleConnection *conn;
-
- LmMessageHandler *message_cb;
- LmMessageHandler *presence_cb;
-
- GHashTable *channels;
- GabbleRoomlistChannel *roomlist_channel;
-
- GHashTable *disco_requests;
-
- gboolean dispose_has_run;
-};
-
-#define GABBLE_MUC_FACTORY_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_MUC_FACTORY, \
- GabbleMucFactoryPrivate))
-
-static GObject *gabble_muc_factory_constructor (GType type, guint n_props,
- GObjectConstructParam *props);
-
-static void
-gabble_muc_factory_init (GabbleMucFactory *fac)
-{
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
-
- priv->channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
-
- priv->disco_requests = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
-
- priv->message_cb = NULL;
- priv->presence_cb = NULL;
-
- priv->conn = NULL;
- priv->dispose_has_run = FALSE;
-}
-
-static GObject *
-gabble_muc_factory_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- /* GabbleMucFactoryPrivate *priv; */
-
- obj = G_OBJECT_CLASS (gabble_muc_factory_parent_class)->
- constructor (type, n_props, props);
- /* priv = GABBLE_MUC_FACTORY_GET_PRIVATE (obj); */
-
- return obj;
-}
-
-static void
-cancel_disco_request (gpointer key, gpointer value, gpointer user_data)
-{
- GabbleDisco *disco = GABBLE_DISCO (user_data);
- GabbleDiscoRequest *request = (GabbleDiscoRequest *) key;
-
- gabble_disco_cancel_request (disco, request);
-}
-
-static void
-gabble_muc_factory_dispose (GObject *object)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- tp_channel_factory_iface_close_all (TP_CHANNEL_FACTORY_IFACE (object));
-
- g_hash_table_foreach (priv->disco_requests, cancel_disco_request,
- priv->conn->disco);
- g_hash_table_destroy (priv->disco_requests);
-
- if (G_OBJECT_CLASS (gabble_muc_factory_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_muc_factory_parent_class)->dispose (object);
-}
-
-static void
-gabble_muc_factory_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_muc_factory_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_muc_factory_class_init (GabbleMucFactoryClass *gabble_muc_factory_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_muc_factory_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_muc_factory_class,
- sizeof (GabbleMucFactoryPrivate));
-
- object_class->constructor = gabble_muc_factory_constructor;
- object_class->dispose = gabble_muc_factory_dispose;
-
- object_class->get_property = gabble_muc_factory_get_property;
- object_class->set_property = gabble_muc_factory_set_property;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "MUC factory object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-}
-
-
-static GabbleMucChannel *
-get_muc_from_jid (GabbleMucFactory *fac, const gchar *jid)
-{
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *room_repo = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_ROOM);
- TpHandle handle;
- GabbleMucChannel *chan = NULL;
- gchar *room;
-
- room = gabble_remove_resource (jid);
- if (!room)
- return NULL;
-
- handle = tp_handle_lookup (room_repo, room, NULL, NULL);
- g_free (room);
- if (handle)
- chan = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle));
-
- return chan;
-}
-
-
-/**
- * muc_channel_closed_cb:
- *
- * Signal callback for when a MUC channel is closed. Removes the references
- * that MucFactory holds to them.
- */
-static void
-muc_channel_closed_cb (GabbleMucChannel *chan, gpointer user_data)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpHandle room_handle;
-
- if (priv->channels != NULL)
- {
- g_object_get (chan, "handle", &room_handle, NULL);
-
- DEBUG ("removing MUC channel with handle %d", room_handle);
-
- g_hash_table_remove (priv->channels, GINT_TO_POINTER (room_handle));
- }
-}
-
-static void
-muc_ready_cb (GabbleMucChannel *chan,
- gpointer data)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data);
-
- DEBUG ("chan=%p", chan);
-
- tp_channel_factory_iface_emit_new_channel (fac, (TpChannelIface *)chan,
- NULL);
-}
-
-static void
-muc_join_error_cb (GabbleMucChannel *chan,
- GError *error,
- gpointer data)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data);
-
- DEBUG ("error->code=%u, error->message=\"%s\"", error->code, error->message);
-
- tp_channel_factory_iface_emit_channel_error (fac, (TpChannelIface *)chan,
- error, NULL);
-}
-
-/**
- * new_muc_channel
- */
-static GabbleMucChannel *
-new_muc_channel (GabbleMucFactory *fac, TpHandle handle, gboolean invite_self)
-{
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- GabbleMucChannel *chan;
- char *object_path;
-
- g_assert (g_hash_table_lookup (priv->channels, GINT_TO_POINTER (handle)) == NULL);
-
- object_path = g_strdup_printf ("%s/MucChannel%u",
- conn->object_path, handle);
-
- DEBUG ("creating new chan, object path %s", object_path);
-
- chan = g_object_new (GABBLE_TYPE_MUC_CHANNEL,
- "connection", priv->conn,
- "object-path", object_path,
- "handle", handle,
- "invite-self", invite_self,
- NULL);
-
- g_signal_connect (chan, "closed", (GCallback) muc_channel_closed_cb, fac);
-
- g_hash_table_insert (priv->channels, GINT_TO_POINTER (handle), chan);
-
- g_free (object_path);
-
- g_signal_connect (chan, "ready", G_CALLBACK (muc_ready_cb), fac);
- g_signal_connect (chan, "join-error", G_CALLBACK (muc_join_error_cb),
- fac);
-
- return chan;
-}
-
-static void
-do_invite (GabbleMucFactory *fac,
- const gchar *room,
- TpHandle inviter_handle,
- const gchar *reason)
-{
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_ROOM);
- TpHandle room_handle;
-
- room_handle = tp_handle_ensure (room_repo, room, NULL, NULL);
-
- if (room_handle == 0)
- {
- DEBUG ("got a MUC invitation message with invalid room JID \"%s\"; "
- "ignoring", room);
- return;
- }
-
- if (g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (room_handle)) ==
- NULL)
- {
- GabbleMucChannel *chan = new_muc_channel (fac, room_handle, FALSE);
- _gabble_muc_channel_handle_invited (chan, inviter_handle, reason);
- }
- else
- {
- DEBUG ("ignoring invite to room \"%s\"; we're already there", room);
- }
-}
-
-struct DiscoInviteData {
- GabbleMucFactory *factory;
- gchar *reason;
- TpHandle inviter;
-};
-
-/**
- * obsolete_invite_disco_cb:
- *
- * Callback for disco request we fired upon encountering obsolete disco.
- * If the object is in fact MUC room, create a channel for it.
- */
-static void
-obsolete_invite_disco_cb (GabbleDisco *self,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *query_result,
- GError* error,
- gpointer user_data)
-{
- struct DiscoInviteData *data = (struct DiscoInviteData *) user_data;
-
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data->factory);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- LmMessageNode *identity;
- const char *category = NULL, *type = NULL;
-
- g_hash_table_remove (priv->disco_requests, request);
-
- if (error != NULL)
- {
- DEBUG ("ignoring obsolete invite to room '%s'; got disco error: %s",
- jid, error->message);
- goto out;
- }
-
- identity = lm_message_node_get_child (query_result, "identity");
- if (identity != NULL)
- {
- category = lm_message_node_get_attribute (identity, "category");
- type = lm_message_node_get_attribute (identity, "type");
- }
-
- if (tp_strdiff (category, "conference") ||
- tp_strdiff (type, "text"))
- {
- DEBUG ("obsolete invite request specified inappropriate jid '%s' "
- "(not a text conference); ignoring request", jid);
- goto out;
- }
-
- /* OK, it's MUC after all, create a new channel */
- do_invite (fac, jid, data->inviter, data->reason);
-
-out:
- tp_handle_unref (contact_repo, data->inviter);
- g_free (data->reason);
- g_slice_free (struct DiscoInviteData, data);
-}
-
-static gboolean
-process_muc_invite (GabbleMucFactory *fac,
- LmMessage *message,
- const gchar *from,
- TpChannelTextSendError send_error)
-{
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- LmMessageNode *x_node, *invite_node, *reason_node;
- const gchar *invite_from, *reason = NULL;
- TpHandle inviter_handle;
- gchar *room;
-
- /* does it have a muc subnode? */
- x_node = lm_message_node_get_child_with_namespace (message->node, "x",
- NS_MUC_USER);
-
- if (x_node == NULL)
- return FALSE;
-
- /* and an invitation? */
- invite_node = lm_message_node_get_child (x_node, "invite");
-
- if (invite_node == NULL)
- return FALSE;
-
- /* FIXME: do something with these? */
- if (send_error != TP_CHANNEL_SEND_NO_ERROR)
- {
- NODE_DEBUG (message->node, "got a MUC invitation message with a send "
- "error; ignoring");
-
- return TRUE;
- }
-
- invite_from = lm_message_node_get_attribute (invite_node, "from");
- if (invite_from == NULL)
- {
- NODE_DEBUG (message->node, "got a MUC invitation message with no JID; "
- "ignoring");
-
- return TRUE;
- }
-
- inviter_handle = tp_handle_ensure (contact_repo, invite_from,
- NULL, NULL);
- if (inviter_handle == 0)
- {
- NODE_DEBUG (message->node, "got a MUC invitation message with invalid "
- "inviter JID; ignoring");
-
- return TRUE;
- }
-
- reason_node = lm_message_node_get_child (invite_node, "reason");
-
- if (reason_node != NULL)
- reason = lm_message_node_get_value (reason_node);
-
- if (reason == NULL)
- reason = "";
-
- /* create the channel */
- room = gabble_remove_resource (from);
- do_invite (fac, room, inviter_handle, reason);
- g_free (room);
-
- tp_handle_unref (contact_repo, inviter_handle);
-
- return TRUE;
-}
-
-static gboolean
-process_obsolete_invite (GabbleMucFactory *fac,
- LmMessage *message,
- const gchar *from,
- const gchar *body,
- TpChannelTextSendError send_error)
-{
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- LmMessageNode *x_node;
- const gchar *room;
- TpHandle inviter_handle;
- GabbleDiscoRequest *request;
- struct DiscoInviteData *disco_udata;
-
- /* check for obsolete invite method */
- x_node = lm_message_node_get_child_with_namespace (message->node, "x",
- NS_X_CONFERENCE);
- if (x_node == NULL)
- return FALSE;
-
- /* this can only happen if the user sent an obsolete invite with another
- * client or something */
- if (send_error != TP_CHANNEL_SEND_NO_ERROR)
- {
- NODE_DEBUG (message->node, "got an obsolete MUC invitation message with "
- "a send error; ignoring");
-
- return TRUE;
- }
-
- /* the room JID is in x */
- room = lm_message_node_get_attribute (x_node, "jid");
- if (room == NULL)
- {
- NODE_DEBUG (message->node, "got a obsolete MUC invitation with no room "
- "JID; ignoring");
-
- return TRUE;
- }
-
- /* the inviter JID is in "from" */
- inviter_handle = tp_handle_ensure (contact_repo, from, NULL, NULL);
- if (inviter_handle == 0)
- {
- NODE_DEBUG (message->node, "got an obsolete MUC invitation message from "
- "an invalid JID; ignoring");
-
- return TRUE;
- }
-
- disco_udata = g_slice_new0 (struct DiscoInviteData);
- disco_udata->factory = fac;
- disco_udata->reason = g_strdup (body);
- disco_udata->inviter = inviter_handle;
-
- DEBUG ("received obsolete MUC invite from handle %u (%s), discoing room %s",
- inviter_handle, from, room);
-
- request = gabble_disco_request (priv->conn->disco, GABBLE_DISCO_TYPE_INFO,
- room, NULL, obsolete_invite_disco_cb, disco_udata, G_OBJECT (fac), NULL);
-
- if (request != NULL)
- {
- g_hash_table_insert (priv->disco_requests, request, NULL);
- }
- else
- {
- DEBUG ("obsolete MUC invite disco failed, freeing info");
-
- tp_handle_unref (contact_repo, inviter_handle);
- g_free (disco_udata->reason);
- g_slice_free (struct DiscoInviteData, disco_udata);
- }
-
- return TRUE;
-}
-
-/**
- * muc_factory_message_cb:
- *
- * Called by loudmouth when we get an incoming <message>.
- * We filter only groupchat and MUC messages, ignoring the rest.
- */
-static LmHandlerResult
-muc_factory_message_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
- TpHandleRepoIface *room_repo = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_ROOM);
-
- const gchar *from, *body;
- time_t stamp;
- TpChannelTextMessageType msgtype;
- TpHandleRepoIface *handle_source;
- TpHandleType handle_type;
- TpHandle room_handle, handle;
- GabbleMucChannel *chan;
- gint state;
- TpChannelTextSendError send_error;
- gchar *room;
-
- if (!gabble_text_mixin_parse_incoming_message (message, &from, &stamp,
- &msgtype, &body, &state, &send_error))
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-
- if (process_muc_invite (fac, message, from, send_error))
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-
- if (process_obsolete_invite (fac, message, from, body, send_error))
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-
- /* check if a room with the jid exists */
- room = gabble_remove_resource (from);
- room_handle = tp_handle_lookup (room_repo, room, NULL, NULL);
- g_free (room);
-
- /* the message is nothing to do with MUC, do nothing */
- if (room_handle == 0)
- {
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- /* find the MUC channel */
- chan = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (room_handle));
-
- if (chan == NULL)
- {
- NODE_DEBUG (message->node, "ignoring MUC message from known "
- "handle with no corresponding channel");
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- /* get the handle of the sender, which is either the room
- * itself or one of its members */
- if (strchr (from, '/') == NULL)
- {
- handle_source = room_repo;
- handle_type = TP_HANDLE_TYPE_ROOM;
- handle = room_handle;
- tp_handle_ref (room_repo, handle);
- }
- else
- {
- handle_source = contact_repo;
- handle_type = TP_HANDLE_TYPE_CONTACT;
- handle = tp_handle_ensure (contact_repo, from,
- GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL);
-
- if (handle == 0)
- {
- NODE_DEBUG (message->node, "MUC message from invalid JID; ignoring");
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- /* anything other than a type="groupchat" is from the person directly and
- * simply relayed by the MUC, so should be left to the normal handlers */
- if (lm_message_get_sub_type (message) != LM_MESSAGE_SUB_TYPE_GROUPCHAT)
- {
- tp_handle_unref (contact_repo, handle);
-
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
- }
-
- if (send_error != TP_CHANNEL_SEND_NO_ERROR)
- {
- tp_svc_channel_type_text_emit_send_error ((TpSvcChannelTypeText *) chan,
- send_error, stamp, msgtype, body);
- goto done;
- }
-
- if (state != -1 && handle_type == TP_HANDLE_TYPE_CONTACT)
- _gabble_muc_channel_state_receive (chan, state, handle);
-
- if (body != NULL)
- _gabble_muc_channel_receive (chan, msgtype, handle_type, handle, stamp,
- body, message);
-
-done:
- tp_handle_unref (handle_source, handle);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-
-/**
- * connection_presence_muc_cb:
- * @handler: #LmMessageHandler for this message
- * @connection: #LmConnection that originated the message
- * @message: the presence message
- * @user_data: callback data
- *
- * Called by loudmouth when we get an incoming <presence>.
- */
-static LmHandlerResult
-muc_factory_presence_cb (LmMessageHandler *handler,
- LmConnection *lmconn,
- LmMessage *msg,
- gpointer user_data)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- const char *from;
- LmMessageSubType sub_type;
- GabbleMucChannel *muc_chan;
- LmMessageNode *x_node;
-
- g_assert (lmconn == priv->conn->lmconn);
-
- from = lm_message_node_get_attribute (msg->node, "from");
-
- if (from == NULL)
- {
- NODE_DEBUG (msg->node,
- "presence stanza without from attribute, ignoring");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- sub_type = lm_message_get_sub_type (msg);
-
- muc_chan = get_muc_from_jid (fac, from);
-
- /* is it an error and for a MUC? */
- if (sub_type == LM_MESSAGE_SUB_TYPE_ERROR
- && muc_chan != NULL)
- {
- _gabble_muc_channel_presence_error (muc_chan, from, msg->node);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- x_node = lm_message_node_get_child_with_namespace (msg->node, "x",
- NS_MUC_USER);
-
- /* is it a MUC member presence? */
- if (x_node != NULL)
- {
- if (muc_chan != NULL)
- {
- TpHandle handle;
-
- handle = tp_handle_ensure (contact_repo, from,
- GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL);
- if (handle == 0)
- {
- NODE_DEBUG (msg->node,
- "discarding MUC presence from malformed jid");
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- _gabble_muc_channel_member_presence_updated (muc_chan, handle,
- msg, x_node);
- tp_handle_unref (contact_repo, handle);
- }
- else
- {
- NODE_DEBUG (msg->node, "discarding unexpected MUC member presence");
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
- }
-
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
-}
-
-static void
-roomlist_channel_closed_cb (GabbleRoomlistChannel *chan, gpointer data)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
-
- if (priv->roomlist_channel != NULL)
- {
- g_object_unref (priv->roomlist_channel);
- priv->roomlist_channel = NULL;
- }
-}
-
-static gboolean
-make_roomlist_channel (GabbleMucFactory *fac, gpointer request)
-{
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
-
- const gchar *server;
- gchar *object_path;
-
- g_assert (priv->roomlist_channel == NULL);
-
- server = _gabble_connection_find_conference_server (priv->conn);
-
- if (server == NULL)
- return FALSE;
-
- object_path = g_strdup_printf ("%s/RoomlistChannel",
- conn->object_path);
-
- priv->roomlist_channel = _gabble_roomlist_channel_new (priv->conn,
- object_path, server);
-
- g_signal_connect (priv->roomlist_channel, "closed",
- (GCallback) roomlist_channel_closed_cb, fac);
-
- tp_channel_factory_iface_emit_new_channel (fac,
- (TpChannelIface *)priv->roomlist_channel, request);
-
- g_free (object_path);
-
- return TRUE;
-}
-
-
-
-static void
-gabble_muc_factory_iface_close_all (TpChannelFactoryIface *iface)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (iface);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
-
- DEBUG ("closing channels");
-
- if (priv->channels != NULL)
- {
- GHashTable *tmp = priv->channels;
- priv->channels = NULL;
- g_hash_table_destroy (tmp);
- }
-
- if (priv->roomlist_channel != NULL)
- {
- GObject *tmp = G_OBJECT (priv->roomlist_channel);
- priv->roomlist_channel = NULL;
- g_object_unref (tmp);
- }
-}
-
-static void
-gabble_muc_factory_iface_connecting (TpChannelFactoryIface *iface)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (iface);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
-
- DEBUG ("adding callbacks");
-
- g_assert (priv->message_cb == NULL);
- g_assert (priv->presence_cb == NULL);
-
- priv->message_cb = lm_message_handler_new (muc_factory_message_cb, fac,
- NULL);
- lm_connection_register_message_handler (priv->conn->lmconn, priv->message_cb,
- LM_MESSAGE_TYPE_MESSAGE,
- LM_HANDLER_PRIORITY_NORMAL);
-
- priv->presence_cb = lm_message_handler_new (muc_factory_presence_cb,
- fac, NULL);
- lm_connection_register_message_handler (priv->conn->lmconn,
- priv->presence_cb, LM_MESSAGE_TYPE_PRESENCE, LM_HANDLER_PRIORITY_NORMAL);
-}
-
-
-static void
-gabble_muc_factory_iface_connected (TpChannelFactoryIface *iface)
-{
- /* nothing to do */
-}
-
-static void
-gabble_muc_factory_iface_disconnected (TpChannelFactoryIface *iface)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (iface);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
-
- DEBUG ("removing callbacks");
-
- g_assert (priv->message_cb != NULL);
- g_assert (priv->presence_cb != NULL);
-
- lm_connection_unregister_message_handler (priv->conn->lmconn,
- priv->message_cb, LM_MESSAGE_TYPE_MESSAGE);
- lm_message_handler_unref (priv->message_cb);
- priv->message_cb = NULL;
-
- lm_connection_unregister_message_handler (priv->conn->lmconn,
- priv->presence_cb, LM_MESSAGE_TYPE_PRESENCE);
- lm_message_handler_unref (priv->presence_cb);
- priv->presence_cb = NULL;
-}
-
-struct _ForeachData
-{
- TpChannelFunc foreach;
- gpointer user_data;
-};
-
-static void
-_foreach_slave (gpointer key, gpointer value, gpointer user_data)
-{
- struct _ForeachData *data = (struct _ForeachData *) user_data;
- TpChannelIface *chan = TP_CHANNEL_IFACE (value);
-
- data->foreach (chan, data->user_data);
-}
-
-static void
-gabble_muc_factory_iface_foreach (TpChannelFactoryIface *iface,
- TpChannelFunc foreach,
- gpointer user_data)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (iface);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- struct _ForeachData data;
-
- data.user_data = user_data;
- data.foreach = foreach;
-
- g_hash_table_foreach (priv->channels, _foreach_slave, &data);
-
- if (priv->roomlist_channel != NULL)
- foreach (TP_CHANNEL_IFACE (priv->roomlist_channel), user_data);
-}
-
-static TpChannelFactoryRequestStatus
-gabble_muc_factory_iface_request (TpChannelFactoryIface *iface,
- const gchar *chan_type,
- TpHandleType handle_type,
- guint handle,
- gpointer request,
- TpChannelIface **ret,
- GError **error)
-{
- GabbleMucFactory *fac = GABBLE_MUC_FACTORY (iface);
- GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (fac);
- TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_ROOM);
- GabbleMucChannel *chan;
-
- if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_ROOM_LIST))
- {
- if (priv->roomlist_channel != NULL)
- {
- *ret = TP_CHANNEL_IFACE (priv->roomlist_channel);
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
- }
-
- /* FIXME - delay if services aren't discovered yet? */
- if (!make_roomlist_channel (fac, request))
- {
- DEBUG ("no conference server available for roomlist request");
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
- }
- *ret = TP_CHANNEL_IFACE (priv->roomlist_channel);
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
- }
-
- if (strcmp (chan_type, TP_IFACE_CHANNEL_TYPE_TEXT))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
-
- if (handle_type != TP_HANDLE_TYPE_ROOM)
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
-
- if (!tp_handle_is_valid (room_repo, handle, NULL))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
-
- chan = g_hash_table_lookup (priv->channels, GINT_TO_POINTER (handle));
- if (!chan)
- {
- chan = new_muc_channel (fac, handle, TRUE);
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_QUEUED;
- }
-
- if (_gabble_muc_channel_is_ready (chan))
- {
- *ret = TP_CHANNEL_IFACE (chan);
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
- }
- else
- {
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_QUEUED;
- }
-}
-
-static void
-gabble_muc_factory_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *) g_iface;
-
- klass->close_all = gabble_muc_factory_iface_close_all;
- klass->connecting = gabble_muc_factory_iface_connecting;
- klass->connected = gabble_muc_factory_iface_connected;
- klass->disconnected = gabble_muc_factory_iface_disconnected;
- klass->foreach = gabble_muc_factory_iface_foreach;
- klass->request = gabble_muc_factory_iface_request;
-}
-
-
diff --git a/src/muc-factory.h b/src/muc-factory.h
deleted file mode 100644
index 09ec8dbc4..000000000
--- a/src/muc-factory.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * muc-factory.h - Header for GabbleMucFactory
- * Copyright (C) 2006 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
- */
-
-#ifndef __MUC_FACTORY_H__
-#define __MUC_FACTORY_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleMucFactory GabbleMucFactory;
-typedef struct _GabbleMucFactoryClass GabbleMucFactoryClass;
-
-struct _GabbleMucFactoryClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleMucFactory {
- GObject parent;
-};
-
-GType gabble_muc_factory_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_MUC_FACTORY \
- (gabble_muc_factory_get_type ())
-#define GABBLE_MUC_FACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MUC_FACTORY, \
- GabbleMucFactory))
-#define GABBLE_MUC_FACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MUC_FACTORY, \
- GabbleMucFactoryClass))
-#define GABBLE_IS_MUC_FACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MUC_FACTORY))
-#define GABBLE_IS_MUC_FACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MUC_FACTORY))
-#define GABBLE_MUC_FACTORY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MUC_FACTORY, \
- GabbleMucFactoryClass))
-
-G_END_DECLS
-
-#endif /* #ifndef __MUC_FACTORY_H__ */
diff --git a/src/namespaces.h b/src/namespaces.h
deleted file mode 100644
index 91bf40813..000000000
--- a/src/namespaces.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * namespaces.h - XMPP namespace constants
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_NAMESPACES__H__
-#define __GABBLE_NAMESPACES__H__
-
-#define NS_CAPS "http://jabber.org/protocol/caps"
-#define NS_CHAT_STATES "http://jabber.org/protocol/chatstates"
-#define NS_DISCO_INFO "http://jabber.org/protocol/disco#info"
-#define NS_DISCO_ITEMS "http://jabber.org/protocol/disco#items"
-#define NS_GABBLE_CAPS "http://telepathy.freedesktop.org/caps"
-#define NS_GOOGLE_CAPS "http://www.google.com/xmpp/client/caps"
-#define NS_GOOGLE_FEAT_SESSION "http://www.google.com/xmpp/protocol/session"
-#define NS_GOOGLE_FEAT_VOICE "http://www.google.com/xmpp/protocol/voice/v1"
-#define NS_GOOGLE_JINGLE_INFO "google:jingleinfo"
-#define NS_GOOGLE_ROSTER "google:roster"
-#define NS_GOOGLE_SESSION "http://www.google.com/session"
-#define NS_GOOGLE_SESSION_PHONE "http://www.google.com/session/phone"
-#define NS_GOOGLE_TRANSPORT_P2P "http://www.google.com/transport/p2p"
-#define NS_JINGLE "http://jabber.org/protocol/jingle"
-#define NS_JINGLE_DESCRIPTION_AUDIO \
- "http://jabber.org/protocol/jingle/description/audio"
-#define NS_JINGLE_DESCRIPTION_VIDEO \
- "http://jabber.org/protocol/jingle/description/video"
-#define NS_JINGLE_ERRORS "http://jabber.org/protocol/jingle#errors"
-#define NS_JINGLE_TRANSPORT_ICE \
- "http://jabber.org/protocol/jingle/transport/ice"
-#define NS_MUC "http://jabber.org/protocol/muc"
-#define NS_MUC_USER "http://jabber.org/protocol/muc#user"
-#define NS_MUC_ADMIN "http://jabber.org/protocol/muc#admin"
-#define NS_MUC_OWNER "http://jabber.org/protocol/muc#owner"
-#define NS_NICK "http://jabber.org/protocol/nick"
-#define NS_NOKIA_IV \
- "http://videovoip.tableteer.nokia.com/xmpp/privilege"
-#define NS_OLPC_BUDDY_PROPS "http://laptop.org/xmpp/buddy-properties"
-#define NS_OLPC_ACTIVITIES "http://laptop.org/xmpp/activities"
-#define NS_PUBSUB "http://jabber.org/protocol/pubsub"
-#define NS_PRESENCE_INVISIBLE "presence-invisible"
-#define NS_PRIVACY "jabber:iq:privacy"
-#define NS_REGISTER "jabber:iq:register"
-#define NS_ROSTER "jabber:iq:roster"
-#define NS_VCARD_TEMP "vcard-temp"
-#define NS_VCARD_TEMP_UPDATE "vcard-temp:x:update"
-#define NS_X_DATA "jabber:x:data"
-#define NS_X_DELAY "jabber:x:delay"
-#define NS_X_CONFERENCE "jabber:x:conference"
-#define NS_XMPP_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas"
-
-#endif /* __GABBLE_NAMESPACES__H__ */
diff --git a/src/presence-cache.c b/src/presence-cache.c
deleted file mode 100644
index f663d8d91..000000000
--- a/src/presence-cache.c
+++ /dev/null
@@ -1,1266 +0,0 @@
-/*
- * gabble-presence-cache.c - Gabble's contact presence cache
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#include "presence-cache.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/* when five DIFFERENT guys report the same caps for a given bundle, it'll
-be enough */
-#define CAPABILITY_BUNDLE_ENOUGH_TRUST 5
-#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
-
-#include <telepathy-glib/intset.h>
-
-#include "debug.h"
-#include "disco.h" /* \o\ \o/ /o/ */
-#include "namespaces.h"
-#include "util.h"
-
-#include "gabble-signals-marshal.h"
-
-G_DEFINE_TYPE (GabblePresenceCache, gabble_presence_cache, G_TYPE_OBJECT);
-
-/* properties */
-enum
-{
- PROP_CONNECTION = 1,
- LAST_PROPERTY
-};
-
-/* signal enum */
-enum
-{
- PRESENCE_UPDATE,
- NICKNAME_UPDATE,
- CAPABILITIES_UPDATE,
- AVATAR_UPDATE,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-#define GABBLE_PRESENCE_CACHE_PRIV(account) \
- ((GabblePresenceCachePrivate *)account->priv)
-
-typedef struct _GabblePresenceCachePrivate GabblePresenceCachePrivate;
-
-struct _GabblePresenceCachePrivate
-{
- GabbleConnection *conn;
-
- gulong status_changed_cb;
- LmMessageHandler *lm_message_cb;
-
- GHashTable *presence;
- TpHandleSet *presence_handles;
-
- GHashTable *capabilities;
- GHashTable *disco_pending;
- guint caps_serial;
-
- gboolean dispose_has_run;
-};
-
-typedef struct _DiscoWaiter DiscoWaiter;
-
-struct _DiscoWaiter
-{
- TpHandleRepoIface *repo;
- TpHandle handle;
- gchar *resource;
- guint serial;
- gboolean disco_requested;
-};
-
-/**
- * disco_waiter_new ()
- */
-static DiscoWaiter *
-disco_waiter_new (TpHandleRepoIface *repo,
- TpHandle handle,
- const gchar *resource,
- guint serial)
-{
- DiscoWaiter *waiter;
-
- g_assert (repo);
- tp_handle_ref (repo, handle);
-
- waiter = g_slice_new0 (DiscoWaiter);
- waiter->repo = repo;
- waiter->handle = handle;
- waiter->resource = g_strdup (resource);
- waiter->serial = serial;
-
- DEBUG ("created waiter %p for handle %u with serial %u", waiter, handle,
- serial);
-
- return waiter;
-}
-
-static void
-disco_waiter_free (DiscoWaiter *waiter)
-{
- g_assert (NULL != waiter);
-
- DEBUG ("freeing waiter %p for handle %u with serial %u", waiter,
- waiter->handle, waiter->serial);
-
- tp_handle_unref (waiter->repo, waiter->handle);
-
- g_free (waiter->resource);
- g_slice_free (DiscoWaiter, waiter);
-}
-
-static void
-disco_waiter_list_free (GSList *list)
-{
- GSList *i;
-
- DEBUG ("list %p", list);
-
- for (i = list; NULL != i; i = i->next)
- disco_waiter_free ((DiscoWaiter *) i->data);
-
- g_slist_free (list);
-}
-
-static guint
-disco_waiter_list_get_request_count (GSList *list)
-{
- guint c = 0;
- GSList *i;
-
- for (i = list; i; i = i->next)
- {
- DiscoWaiter *waiter = (DiscoWaiter *) i->data;
-
- if (waiter->disco_requested)
- c++;
- }
-
- return c;
-}
-
-typedef struct _CapabilityInfo CapabilityInfo;
-
-struct _CapabilityInfo
-{
- GabblePresenceCapabilities caps;
- TpIntSet *guys;
- guint trust;
-};
-
-static CapabilityInfo *
-capability_info_get (GabblePresenceCache *cache, const gchar *node,
- GabblePresenceCapabilities caps)
-{
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- CapabilityInfo *info = g_hash_table_lookup (priv->capabilities, node);
-
- if (NULL == info)
- {
- info = g_slice_new0 (CapabilityInfo);
- info->caps = caps;
- info->guys = tp_intset_new ();
- g_hash_table_insert (priv->capabilities, g_strdup (node), info);
- }
-
- return info;
-}
-
-static void
-capability_info_free (CapabilityInfo *info)
-{
- tp_intset_destroy (info->guys);
- g_slice_free (CapabilityInfo, info);
-}
-
-static guint
-capability_info_recvd (GabblePresenceCache *cache, const gchar *node,
- TpHandle handle, GabblePresenceCapabilities caps)
-{
- CapabilityInfo *info = capability_info_get (cache, node, caps);
-
- /* Detect inconsistency in reported caps */
- if (info->caps != caps)
- {
- tp_intset_clear (info->guys);
- info->caps = caps;
- info->trust = 0;
- }
-
- if (!tp_intset_is_member (info->guys, handle))
- {
- tp_intset_add (info->guys, handle);
- info->trust++;
- }
-
- return info->trust;
-}
-
-static void gabble_presence_cache_init (GabblePresenceCache *presence_cache);
-static GObject * gabble_presence_cache_constructor (GType type, guint n_props,
- GObjectConstructParam *props);
-static void gabble_presence_cache_dispose (GObject *object);
-static void gabble_presence_cache_finalize (GObject *object);
-static void gabble_presence_cache_set_property (GObject *object, guint
- property_id, const GValue *value, GParamSpec *pspec);
-static void gabble_presence_cache_get_property (GObject *object, guint
- property_id, GValue *value, GParamSpec *pspec);
-static GabblePresence *_cache_insert (GabblePresenceCache *cache,
- TpHandle handle);
-
-static void gabble_presence_cache_status_changed_cb (GabbleConnection *,
- TpConnectionStatus, TpConnectionStatusReason, gpointer);
-static LmHandlerResult gabble_presence_cache_lm_message_cb (LmMessageHandler*,
- LmConnection*, LmMessage*, gpointer);
-
-static void
-gabble_presence_cache_class_init (GabblePresenceCacheClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GParamSpec *param_spec;
-
- g_type_class_add_private (object_class, sizeof (GabblePresenceCachePrivate));
-
- object_class->constructor = gabble_presence_cache_constructor;
-
- object_class->dispose = gabble_presence_cache_dispose;
- object_class->finalize = gabble_presence_cache_finalize;
-
- object_class->get_property = gabble_presence_cache_get_property;
- object_class->set_property = gabble_presence_cache_set_property;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "presence cache.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class,
- PROP_CONNECTION,
- param_spec);
-
- signals[PRESENCE_UPDATE] = g_signal_new (
- "presence-update",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
- signals[NICKNAME_UPDATE] = g_signal_new (
- "nickname-update",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
- signals[CAPABILITIES_UPDATE] = g_signal_new (
- "capabilities-update",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- gabble_marshal_VOID__UINT_UINT_UINT, G_TYPE_NONE,
- 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
- signals[AVATAR_UPDATE] = g_signal_new (
- "avatar-update",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
-}
-
-static void
-gabble_presence_cache_init (GabblePresenceCache *cache)
-{
- GabblePresenceCachePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (cache,
- GABBLE_TYPE_PRESENCE_CACHE, GabblePresenceCachePrivate);
-
- cache->priv = priv;
-
- priv->presence = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
- priv->capabilities = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
- (GDestroyNotify) capability_info_free);
- priv->disco_pending = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) disco_waiter_list_free);
- priv->caps_serial = 1;
-}
-
-static GObject *
-gabble_presence_cache_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabblePresenceCachePrivate *priv;
-
- obj = G_OBJECT_CLASS (gabble_presence_cache_parent_class)->
- constructor (type, n_props, props);
- priv = GABBLE_PRESENCE_CACHE_PRIV (GABBLE_PRESENCE_CACHE (obj));
-
- priv->status_changed_cb = g_signal_connect (priv->conn, "status-changed",
- G_CALLBACK (gabble_presence_cache_status_changed_cb), obj);
-
- return obj;
-}
-
-static void
-gabble_presence_cache_dispose (GObject *object)
-{
- GabblePresenceCache *self = GABBLE_PRESENCE_CACHE (object);
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (self);
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
-
- priv->dispose_has_run = TRUE;
-
- g_assert (priv->lm_message_cb == NULL);
-
- g_signal_handler_disconnect (priv->conn, priv->status_changed_cb);
-
- g_hash_table_destroy (priv->presence);
- priv->presence = NULL;
-
- g_hash_table_destroy (priv->capabilities);
- priv->capabilities = NULL;
-
- g_hash_table_destroy (priv->disco_pending);
- priv->disco_pending = NULL;
-
- tp_handle_set_destroy (priv->presence_handles);
- priv->presence_handles = NULL;
-
- if (G_OBJECT_CLASS (gabble_presence_cache_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_presence_cache_parent_class)->dispose (object);
-}
-
-static void
-gabble_presence_cache_finalize (GObject *object)
-{
- DEBUG ("called with %p", object);
-
- G_OBJECT_CLASS (gabble_presence_cache_parent_class)->finalize (object);
-}
-
-static void
-gabble_presence_cache_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (object);
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_presence_cache_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (object);
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- TpHandleRepoIface *contact_repo;
- TpHandleSet *new_presence_handles;
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- new_presence_handles = tp_handle_set_new (contact_repo);
-
- if (priv->presence_handles)
- {
- const TpIntSet *add;
- TpIntSet *tmp;
- add = tp_handle_set_peek (priv->presence_handles);
- tmp = tp_handle_set_update (new_presence_handles, add);
- tp_handle_set_destroy (priv->presence_handles);
- tp_intset_destroy (tmp);
- }
- priv->presence_handles = new_presence_handles;
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-#if 0
-static gboolean
-_presence_node_has_google_voice (LmMessageNode *pres_node)
-{
- LmMessageNode *node;
- const gchar *cap_ext;
- gchar **features, **tmp;
- gboolean found = FALSE;
-
- node = lm_message_node_get_child_with_namespace (pres_node, "c", NS_CAPS);
-
- if (node == NULL);
- return FALSE;
-
- cap_ext = lm_message_node_get_attribute (node, "ext");
-
- if (cap_ext == NULL);
- return FALSE;
-
- features = g_strsplit (cap_ext, " ", 0);
-
- for (tmp = features; *tmp; tmp++)
- {
- if (!tp_strdiff (tmp, "voice-v1"))
- {
- found = TRUE;
- break;
- }
- }
-
- g_strfreev (features);
-
- return found;
-}
-#endif
-
-static void
-gabble_presence_cache_status_changed_cb (GabbleConnection *conn,
- TpConnectionStatus status,
- TpConnectionStatusReason reason,
- gpointer data)
-{
- GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (data);
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
-
- g_assert (conn == priv->conn);
-
- switch (status)
- {
- case TP_CONNECTION_STATUS_CONNECTING:
- g_assert (priv->lm_message_cb == NULL);
-
- priv->lm_message_cb = lm_message_handler_new (
- gabble_presence_cache_lm_message_cb, cache, NULL);
- lm_connection_register_message_handler (priv->conn->lmconn,
- priv->lm_message_cb,
- LM_MESSAGE_TYPE_PRESENCE,
- LM_HANDLER_PRIORITY_LAST);
- lm_connection_register_message_handler (priv->conn->lmconn,
- priv->lm_message_cb,
- LM_MESSAGE_TYPE_MESSAGE,
- LM_HANDLER_PRIORITY_FIRST);
- break;
- case TP_CONNECTION_STATUS_CONNECTED:
- break;
- case TP_CONNECTION_STATUS_DISCONNECTED:
- if (priv->lm_message_cb != NULL)
- {
- lm_connection_unregister_message_handler (conn->lmconn,
- priv->lm_message_cb,
- LM_MESSAGE_TYPE_PRESENCE);
- lm_connection_unregister_message_handler (conn->lmconn,
- priv->lm_message_cb,
- LM_MESSAGE_TYPE_MESSAGE);
- lm_message_handler_unref (priv->lm_message_cb);
- priv->lm_message_cb = NULL;
- }
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static GabblePresenceId
-_presence_node_get_status (LmMessageNode *pres_node)
-{
- const gchar *presence_show;
- LmMessageNode *child_node = lm_message_node_get_child (pres_node, "show");
-
- if (!child_node)
- {
- /*
- NODE_DEBUG (pres_node,
- "<presence> without <show> received from server, "
- "setting presence to available");
- */
- return GABBLE_PRESENCE_AVAILABLE;
- }
-
- presence_show = lm_message_node_get_value (child_node);
-
- if (!presence_show)
- {
- /*
- NODE_DEBUG (pres_node,
- "empty <show> tag received from server, "
- "setting presence to available");
- */
- return GABBLE_PRESENCE_AVAILABLE;
- }
-
- if (0 == strcmp (presence_show, JABBER_PRESENCE_SHOW_AWAY))
- return GABBLE_PRESENCE_AWAY;
- else if (0 == strcmp (presence_show, JABBER_PRESENCE_SHOW_CHAT))
- return GABBLE_PRESENCE_CHAT;
- else if (0 == strcmp (presence_show, JABBER_PRESENCE_SHOW_DND))
- return GABBLE_PRESENCE_DND;
- else if (0 == strcmp (presence_show, JABBER_PRESENCE_SHOW_XA))
- return GABBLE_PRESENCE_XA;
- else
- {
- NODE_DEBUG (pres_node,
- "unrecognised <show/> value received from server, "
- "setting presence to available");
- return GABBLE_PRESENCE_AVAILABLE;
- }
-}
-
-static void
-_grab_nickname (GabblePresenceCache *cache,
- TpHandle handle,
- const gchar *from,
- LmMessageNode *node)
-{
- const gchar *nickname;
- GabblePresence *presence;
-
- node = lm_message_node_get_child_with_namespace (node, "nick", NS_NICK);
-
- if (NULL == node)
- return;
-
- presence = gabble_presence_cache_get (cache, handle);
-
- if (NULL == presence)
- return;
-
- nickname = lm_message_node_get_value (node);
- DEBUG ("got nickname \"%s\" for %s", nickname, from);
-
- if (tp_strdiff (presence->nickname, nickname))
- {
- if (NULL != presence->nickname)
- g_free (presence->nickname);
-
- presence->nickname = g_strdup (nickname);
- g_signal_emit (cache, signals[NICKNAME_UPDATE], 0, handle);
- }
-}
-
-static void
-_grab_avatar_sha1 (GabblePresenceCache *cache,
- TpHandle handle,
- const gchar *from,
- LmMessageNode *node)
-{
- const gchar *sha1;
- LmMessageNode *x_node, *photo_node;
- GabblePresence *presence;
-
- presence = gabble_presence_cache_get (cache, handle);
-
- if (NULL == presence)
- return;
-
- x_node = lm_message_node_get_child_with_namespace (node, "x",
- NS_VCARD_TEMP_UPDATE);
-
- if (NULL == x_node)
- {
-#if 0
- if (handle == priv->conn->parent.self_handle)
- {
- /* One of my other resources does not support XEP-0153. As per that
- * XEP, I MUST stop advertising the image hash, at least until all
- * instances of non-conforming resources have gone offline.
- * However, we're going to ignore this requirement and hope that
- * non-conforming clients won't alter the <PHOTO>, which should
- * in practice be true.
- */
- presence->avatar_sha1 = NULL;
- }
-#endif
- return;
- }
-
- photo_node = lm_message_node_get_child (x_node, "photo");
-
- /* If there is no photo node, the resource supports XEP-0153, but has
- * nothing in particular to say about the avatar. */
- if (NULL == photo_node)
- return;
-
- sha1 = lm_message_node_get_value (photo_node);
-
- if (tp_strdiff (presence->avatar_sha1, sha1))
- {
- g_free (presence->avatar_sha1);
- presence->avatar_sha1 = g_strdup (sha1);
-
-#if 0
- if (handle == priv->conn->parent.self_handle)
- {
- /* that would be us, then. According to XEP-0153, we MUST
- * immediately send a presence update with an empty update child
- * element (no photo node), then re-download our own vCard;
- * when that arrives, we may start setting the photo node in our
- * presence again.
- *
- * For the moment I'm going to ignore that requirement and
- * trust that our other resource is getting its sha1 right!
- */
- /* TODO: I don't trust anyone to get XMPP right, so let's do
- * this. :D */
- }
-#endif
-
- g_signal_emit (cache, signals[AVATAR_UPDATE], 0, handle);
- }
-}
-
-static GSList *
-_extract_cap_bundles (LmMessageNode *lm_node)
-{
- const gchar *node, *ver, *ext;
- GSList *uris = NULL;
- LmMessageNode *cap_node;
-
- cap_node = lm_message_node_get_child_with_namespace (lm_node, "c", NS_CAPS);
-
- if (NULL == cap_node)
- return NULL;
-
- node = lm_message_node_get_attribute (cap_node, "node");
-
- if (NULL == node)
- return NULL;
-
- ver = lm_message_node_get_attribute (cap_node, "ver");
-
- if (NULL != ver)
- uris = g_slist_prepend (uris, g_strdup_printf ("%s#%s", node, ver));
-
- ext = lm_message_node_get_attribute (cap_node, "ext");
-
- if (NULL != ext)
- {
- gchar **exts, **i;
-
- exts = g_strsplit (ext, " ", 0);
-
- for (i = exts; NULL != *i; i++)
- uris = g_slist_prepend (uris, g_strdup_printf ("%s#%s", node, *i));
-
- g_strfreev (exts);
- }
-
- return uris;
-}
-
-static void
-_caps_disco_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *query_result,
- GError *error,
- gpointer user_data)
-{
- GSList *waiters, *i;
- LmMessageNode *child;
- GabblePresenceCache *cache;
- GabblePresenceCachePrivate *priv;
- TpHandleRepoIface *contact_repo;
- gchar *full_jid = NULL;
- GabblePresenceCapabilities caps = 0;
- guint trust;
- TpHandle handle = 0;
-
- cache = GABBLE_PRESENCE_CACHE (user_data);
- priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- if (NULL == node)
- {
- g_warning ("got disco response with NULL node, ignoring");
- return;
- }
-
- waiters = g_hash_table_lookup (priv->disco_pending, node);
-
- if (NULL != error)
- {
- DiscoWaiter *waiter = NULL;
-
- DEBUG ("disco query failed: %s", error->message);
-
- for (i = waiters; NULL != i; i = i->next)
- {
- waiter = (DiscoWaiter *) i->data;
-
- if (!waiter->disco_requested)
- {
- const gchar *jid;
-
- jid = tp_handle_inspect (contact_repo, waiter->handle);
- full_jid = g_strdup_printf ("%s/%s", jid, waiter->resource);
-
- gabble_disco_request (disco, GABBLE_DISCO_TYPE_INFO, full_jid,
- node, _caps_disco_cb, cache, G_OBJECT(cache), NULL);
- waiter->disco_requested = TRUE;
- break;
- }
- }
-
- if (NULL != i)
- {
- DEBUG ("sent a retry disco request to %s for URI %s", full_jid,
- node);
- }
- else
- {
- DEBUG ("failed to find a suitable candidate to retry disco "
- "request for URI %s", node);
- /* FIXME do something very clever here? */
- g_hash_table_remove (priv->disco_pending, node);
- }
-
- goto OUT;
- }
-
- for (child = query_result->children; NULL != child; child = child->next)
- {
- const gchar *var;
-
- if (0 != strcmp (child->name, "feature"))
- continue;
-
- var = lm_message_node_get_attribute (child, "var");
-
- if (NULL == var)
- continue;
-
- /* TODO: use a table that equates disco features to caps */
- if (0 == strcmp (var, NS_GOOGLE_TRANSPORT_P2P))
- caps |= PRESENCE_CAP_GOOGLE_TRANSPORT_P2P;
- else if (0 == strcmp (var, NS_GOOGLE_FEAT_VOICE))
- caps |= PRESENCE_CAP_GOOGLE_VOICE;
- else if (0 == strcmp (var, NS_JINGLE))
- caps |= PRESENCE_CAP_JINGLE;
- else if (0 == strcmp (var, NS_JINGLE_DESCRIPTION_AUDIO))
- caps |= PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO;
- else if (0 == strcmp (var, NS_JINGLE_DESCRIPTION_VIDEO))
- caps |= PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO;
- else if (0 == strcmp (var, NS_CHAT_STATES))
- caps |= PRESENCE_CAP_CHAT_STATES;
- }
-
- handle = tp_handle_ensure (contact_repo, jid, NULL, NULL);
- if (handle == 0)
- {
- DEBUG ("Ignoring presence from invalid JID %s", jid);
- goto OUT;
- }
- trust = capability_info_recvd (cache, node, handle, caps);
-
- for (i = waiters; NULL != i;)
- {
- DiscoWaiter *waiter;
- GabblePresence *presence;
-
- waiter = (DiscoWaiter *) i->data;
-
- if (trust >= CAPABILITY_BUNDLE_ENOUGH_TRUST || waiter->handle == handle)
- {
- GSList *tmp;
- gpointer key;
- gpointer value;
-
- /* trusted reply */
- presence = gabble_presence_cache_get (cache, waiter->handle);
-
- if (presence)
- {
- GabblePresenceCapabilities save_caps = presence->caps;
- DEBUG ("setting caps for %d (%s) to %d", handle, jid, caps);
- gabble_presence_set_capabilities (presence, waiter->resource,caps,
- waiter->serial);
- DEBUG ("caps for %d (%s) now %d", handle, jid, presence->caps);
- g_signal_emit (cache, signals[CAPABILITIES_UPDATE], 0,
- waiter->handle, save_caps, presence->caps);
- }
-
- tmp = i;
- i = i->next;
-
- waiters = g_slist_delete_link (waiters, tmp);
-
- if (!g_hash_table_lookup_extended (priv->disco_pending, node, &key,
- &value))
- g_assert_not_reached ();
-
- g_hash_table_steal (priv->disco_pending, node);
- g_hash_table_insert (priv->disco_pending, key, waiters);
-
- disco_waiter_free (waiter);
- }
- else if (trust + disco_waiter_list_get_request_count (waiters) - 1
- < CAPABILITY_BUNDLE_ENOUGH_TRUST)
- {
- /* if the possible trust, not counting this guy, is too low,
- * we have been poisoned and reset our trust meters - disco
- * anybody we still haven't to be able to get more trusted replies */
-
- if (!waiter->disco_requested)
- {
- const gchar *jid;
-
- jid = tp_handle_inspect (contact_repo, waiter->handle);
- full_jid = g_strdup_printf ("%s/%s", jid, waiter->resource);
-
- gabble_disco_request (disco, GABBLE_DISCO_TYPE_INFO, full_jid,
- node, _caps_disco_cb, cache, G_OBJECT(cache), NULL);
- waiter->disco_requested = TRUE;
-
- g_free (full_jid);
- full_jid = NULL;
- }
-
- i = i->next;
- }
- else
- {
- /* trust level still uncertain, don't do nothing */
- i = i->next;
- }
- }
-
- if (trust >= CAPABILITY_BUNDLE_ENOUGH_TRUST)
- g_hash_table_remove (priv->disco_pending, node);
-
-OUT:
-
- if (handle)
- tp_handle_unref (contact_repo, handle);
- g_free (full_jid);
-}
-
-static void
-_process_caps_uri (GabblePresenceCache *cache,
- const gchar *from,
- const gchar *uri,
- TpHandle handle,
- const gchar *resource,
- guint serial)
-{
- CapabilityInfo *info;
- GabblePresenceCachePrivate *priv;
- TpHandleRepoIface *contact_repo;
-
- priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- info = capability_info_get (cache, uri, 0);
-
- if (info->trust >= CAPABILITY_BUNDLE_ENOUGH_TRUST
- || tp_intset_is_member (info->guys, handle))
- {
- /* we already have enough trust for this node; apply the cached value to
- * the (handle, resource) */
-
- GabblePresence *presence = gabble_presence_cache_get (cache, handle);
- DEBUG ("enough trust for URI %s, setting caps for %u (%s) to %u",
- uri, handle, from, info->caps);
-
- if (presence)
- {
- GabblePresenceCapabilities save_caps = presence->caps;
- gabble_presence_set_capabilities (presence, resource, info->caps,
- serial);
- g_signal_emit (cache, signals[CAPABILITIES_UPDATE], 0,
- handle, save_caps, presence->caps);
- DEBUG ("caps for %d (%s) now %d", handle, from, presence->caps);
- }
- else
- {
- DEBUG ("presence not found");
- }
- }
- else
- {
- /* Append the (handle, resource) pair to the list of such pairs
- * waiting for capabilities for this uri, and send a disco request
- * if we don't have enough possible trust yet */
-
- GSList *waiters;
- DiscoWaiter *waiter;
- guint possible_trust;
- gpointer key;
- gpointer value = NULL;
-
- DEBUG ("not enough trust for URI %s", uri);
-
- /* If the URI is in the hash table, steal it and its value; we can
- * reuse the same URI for the following insertion. Otherwise, make a
- * copy of the URI for use as a key.
- */
-
- if (g_hash_table_lookup_extended (priv->disco_pending, uri, &key,
- &value))
- {
- g_hash_table_steal (priv->disco_pending, key);
- }
- else
- {
- key = g_strdup (uri);
- }
-
- waiters = (GSList *) value;
- waiter = disco_waiter_new (contact_repo, handle, resource, serial);
- waiters = g_slist_prepend (waiters, waiter);
- g_hash_table_insert (priv->disco_pending, key, waiters);
-
- possible_trust = disco_waiter_list_get_request_count (waiters);
-
- if (!value
- || info->trust + possible_trust < CAPABILITY_BUNDLE_ENOUGH_TRUST)
- {
- /* DISCO */
- DEBUG ("only %u trust out of %u possible thus far, sending "
- "disco for URI %s", info->trust + possible_trust,
- CAPABILITY_BUNDLE_ENOUGH_TRUST, uri);
- gabble_disco_request (priv->conn->disco, GABBLE_DISCO_TYPE_INFO,
- from, uri, _caps_disco_cb, cache, G_OBJECT (cache), NULL);
- /* enough DISCO for you, buddy */
- waiter->disco_requested = TRUE;
- }
- }
-}
-
-static void
-_process_caps (GabblePresenceCache *cache,
- TpHandle handle,
- const gchar *from,
- LmMessageNode *lm_node)
-{
- const gchar *resource;
- GSList *uris, *i;
- GabblePresenceCachePrivate *priv;
- guint serial;
-
- priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- serial = priv->caps_serial++;
-
- resource = strchr (from, '/');
-
- uris = _extract_cap_bundles (lm_node);
-
- for (i = uris; NULL != i; i = i->next)
- {
- _process_caps_uri (cache, from, (gchar *) i->data, handle, resource,
- serial);
- g_free (i->data);
- }
-
- g_slist_free (uris);
-}
-
-static LmHandlerResult
-_parse_presence_message (GabblePresenceCache *cache,
- TpHandle handle,
- const gchar *from,
- LmMessage *message)
-{
- gint8 priority = 0;
- const gchar *resource, *status_message = NULL;
- LmMessageNode *presence_node, *child_node;
- LmHandlerResult ret = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- GabblePresenceId presence_id;
- GabblePresence *presence;
-
- presence_node = message->node;
- g_assert (0 == strcmp (presence_node->name, "presence"));
-
- resource = strchr (from, '/');
-
- presence = gabble_presence_cache_get (cache, handle);
-
- if (NULL != presence)
- /* Once we've received presence from somebody, we don't need to keep the
- * presence around when it's unavailable. */
- presence->keep_unavailable = FALSE;
-
- child_node = lm_message_node_get_child (presence_node, "status");
-
- if (child_node)
- status_message = lm_message_node_get_value (child_node);
-
- child_node = lm_message_node_get_child (presence_node, "priority");
-
- if (child_node)
- {
- const gchar *prio = lm_message_node_get_value (child_node);
-
- if (prio != NULL)
- priority = CLAMP (atoi (prio), G_MININT8, G_MAXINT8);
- }
-
- switch (lm_message_get_sub_type (message))
- {
- case LM_MESSAGE_SUB_TYPE_NOT_SET:
- case LM_MESSAGE_SUB_TYPE_AVAILABLE:
- presence_id = _presence_node_get_status (presence_node);
- gabble_presence_cache_update (cache, handle, resource, presence_id,
- status_message, priority);
-
- _grab_nickname (cache, handle, from, presence_node);
- _grab_avatar_sha1 (cache, handle, from, presence_node);
- _process_caps (cache, handle, from, presence_node);
-
- ret = LM_HANDLER_RESULT_REMOVE_MESSAGE;
- break;
-
- case LM_MESSAGE_SUB_TYPE_ERROR:
- NODE_DEBUG (presence_node, "setting contact offline due to error");
- /* fall through */
-
- case LM_MESSAGE_SUB_TYPE_UNAVAILABLE:
- gabble_presence_cache_update (cache, handle, resource,
- GABBLE_PRESENCE_OFFLINE, status_message, priority);
-
- ret = LM_HANDLER_RESULT_REMOVE_MESSAGE;
- break;
-
- default:
- break;
- }
-
- return ret;
-}
-
-static LmHandlerResult
-_parse_message_message (GabblePresenceCache *cache,
- TpHandle handle,
- const gchar *from,
- LmMessage *message)
-{
- LmMessageNode *node;
- GabblePresence *presence;
-
- presence = gabble_presence_cache_get (cache, handle);
-
- if (NULL == presence)
- {
- presence = _cache_insert (cache, handle);
- presence->keep_unavailable = TRUE;
- }
-
- node = lm_message_get_node (message);
-
- _grab_nickname (cache, handle, from, node);
- _grab_avatar_sha1 (cache, handle, from, node);
- _process_caps (cache, handle, from, node);
-
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-}
-
-
-/**
- * gabble_presence_cache_lm_message_cb:
- * @handler: #LmMessageHandler for this message
- * @connection: #LmConnection that originated the message
- * @message: the presence message
- * @user_data: callback data
- *
- * Called by loudmouth when we get an incoming <presence>.
- */
-static LmHandlerResult
-gabble_presence_cache_lm_message_cb (LmMessageHandler *handler,
- LmConnection *lmconn,
- LmMessage *message,
- gpointer user_data)
-{
- GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (user_data);
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- const char *from;
- LmHandlerResult ret;
- TpHandle handle;
-
- g_assert (lmconn == priv->conn->lmconn);
-
- from = lm_message_node_get_attribute (message->node, "from");
-
- if (NULL == from)
- {
- NODE_DEBUG (message->node, "message without from attribute, ignoring");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- handle = tp_handle_ensure (contact_repo, from, NULL, NULL);
-
- if (0 == handle)
- {
- NODE_DEBUG (message->node, "ignoring message from malformed jid");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- switch (lm_message_get_type (message))
- {
- case LM_MESSAGE_TYPE_PRESENCE:
- ret = _parse_presence_message (cache, handle, from, message);
- break;
- case LM_MESSAGE_TYPE_MESSAGE:
- ret = _parse_message_message (cache, handle, from, message);
- break;
- default:
- ret = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- break;
- }
-
- tp_handle_unref (contact_repo, handle);
- return ret;
-}
-
-
-GabblePresenceCache *
-gabble_presence_cache_new (GabbleConnection *conn)
-{
- return g_object_new (GABBLE_TYPE_PRESENCE_CACHE,
- "connection", conn,
- NULL);
-}
-
-GabblePresence *
-gabble_presence_cache_get (GabblePresenceCache *cache, TpHandle handle)
-{
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- g_assert (tp_handle_is_valid (contact_repo, handle, NULL));
-
- return g_hash_table_lookup (priv->presence, GINT_TO_POINTER (handle));
-}
-
-void
-gabble_presence_cache_maybe_remove (
- GabblePresenceCache *cache,
- TpHandle handle)
-{
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabblePresence *presence;
-
- presence = gabble_presence_cache_get (cache, handle);
-
- if (NULL == presence)
- return;
-
- if (presence->status == GABBLE_PRESENCE_OFFLINE &&
- presence->status_message == NULL &&
- !presence->keep_unavailable)
- {
- const gchar *jid;
-
- jid = tp_handle_inspect (contact_repo, handle);
- DEBUG ("discarding cached presence for unavailable jid %s", jid);
- g_hash_table_remove (priv->presence, GINT_TO_POINTER (handle));
- tp_handle_set_remove (priv->presence_handles, handle);
- }
-}
-
-static GabblePresence *
-_cache_insert (
- GabblePresenceCache *cache,
- TpHandle handle)
-{
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- GabblePresence *presence;
-
- presence = gabble_presence_new ();
- g_hash_table_insert (priv->presence, GINT_TO_POINTER (handle), presence);
- tp_handle_set_add (priv->presence_handles, handle);
- return presence;
-}
-
-void
-gabble_presence_cache_update (
- GabblePresenceCache *cache,
- TpHandle handle,
- const gchar *resource,
- GabblePresenceId presence_id,
- const gchar *status_message,
- gint8 priority)
-{
- GabblePresenceCachePrivate *priv = GABBLE_PRESENCE_CACHE_PRIV (cache);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- const gchar *jid;
- GabblePresence *presence;
-
- jid = tp_handle_inspect (contact_repo, handle);
- DEBUG ("%s (%d) resource %s prio %d presence %d message \"%s\"",
- jid, handle, resource, priority, presence_id, status_message);
-
- presence = gabble_presence_cache_get (cache, handle);
-
- if (presence == NULL)
- presence = _cache_insert (cache, handle);
-
- if (gabble_presence_update (presence, resource, presence_id, status_message,
- priority))
- g_signal_emit (cache, signals[PRESENCE_UPDATE], 0, handle);
-
- gabble_presence_cache_maybe_remove (cache, handle);
-}
-
-void gabble_presence_cache_add_bundle_caps (GabblePresenceCache *cache,
- const gchar *node, GabblePresenceCapabilities new_caps)
-{
- CapabilityInfo *info;
-
- info = capability_info_get (cache, node, 0);
- info->trust = CAPABILITY_BUNDLE_ENOUGH_TRUST;
- info->caps |= new_caps;
-}
-
diff --git a/src/presence-cache.h b/src/presence-cache.h
deleted file mode 100644
index 9b9b5225e..000000000
--- a/src/presence-cache.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * gabble-presence-cache.h - Headers for Gabble's contact presence cache
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_PRESENCE_CACHE_H__
-#define __GABBLE_PRESENCE_CACHE_H__
-
-#include <glib-object.h>
-
-#include "presence.h"
-
-G_BEGIN_DECLS
-
-#define GABBLE_TYPE_PRESENCE_CACHE gabble_presence_cache_get_type ()
-
-#define GABBLE_PRESENCE_CACHE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- GABBLE_TYPE_PRESENCE_CACHE, GabblePresenceCache))
-
-#define GABBLE_PRESENCE_CACHE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), \
- GABBLE_TYPE_PRESENCE_CACHE, GabblePresenceCacheClass))
-
-#define GABBLE_IS_PRESENCE_CACHE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
- GABBLE_TYPE_PRESENCE_CACHE))
-
-#define GABBLE_IS_PRESENCE_CACHE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), \
- GABBLE_TYPE_PRESENCE_CACHE))
-
-#define GABBLE_PRESENCE_CACHE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), \
- GABBLE_TYPE_PRESENCE_CACHE, GabblePresenceCacheClass))
-
-#define JABBER_PRESENCE_SHOW_AWAY "away"
-#define JABBER_PRESENCE_SHOW_CHAT "chat"
-#define JABBER_PRESENCE_SHOW_DND "dnd"
-#define JABBER_PRESENCE_SHOW_XA "xa"
-
-struct _GabblePresenceCache {
- GObject parent;
- gpointer priv;
-};
-
-typedef struct _GabblePresenceCacheClass GabblePresenceCacheClass;
-
-struct _GabblePresenceCacheClass {
- GObjectClass parent_class;
-};
-
-GType gabble_presence_cache_get_type (void);
-
-GabblePresenceCache *gabble_presence_cache_new (GabbleConnection *conn);
-GabblePresence *gabble_presence_cache_get (GabblePresenceCache *cache,
- TpHandle handle);
-void gabble_presence_cache_update (GabblePresenceCache *cache,
- TpHandle handle, const gchar *resource, GabblePresenceId presence_id,
- const gchar *status_message, gint8 priority);
-void gabble_presence_cache_maybe_remove (GabblePresenceCache *cache,
- TpHandle handle);
-void gabble_presence_cache_add_bundle_caps (GabblePresenceCache *cache,
- const gchar *node, GabblePresenceCapabilities caps);
-
-G_END_DECLS
-
-#endif /* __GABBLE_PRESENCE_CACHE_H__ */
-
diff --git a/src/presence.c b/src/presence.c
deleted file mode 100644
index 35e1d7e29..000000000
--- a/src/presence.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * gabble-presence.c - Gabble's per-contact presence structure
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-#include "presence.h"
-
-#include <string.h>
-#include <glib.h>
-
-#include "presence-cache.h"
-#include "namespaces.h"
-#include "util.h"
-
-#include "config.h"
-#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
-#include "debug.h"
-
-G_DEFINE_TYPE (GabblePresence, gabble_presence, G_TYPE_OBJECT);
-
-#define GABBLE_PRESENCE_PRIV(account) ((GabblePresencePrivate *)account->priv)
-
-typedef struct _Resource Resource;
-
-struct _Resource {
- gchar *name;
- GabblePresenceCapabilities caps;
- guint caps_serial;
- GabblePresenceId status;
- gchar *status_message;
- gint8 priority;
-};
-
-typedef struct _GabblePresencePrivate GabblePresencePrivate;
-
-struct _GabblePresencePrivate {
- gchar *no_resource_status_message;
- GSList *resources;
-};
-
-static Resource *
-_resource_new (gchar *name)
-{
- Resource *new = g_slice_new (Resource);
- new->name = name;
- new->caps = PRESENCE_CAP_NONE;
- new->status = GABBLE_PRESENCE_OFFLINE;
- new->status_message = NULL;
- new->priority = 0;
- new->caps_serial = 0;
-
- return new;
-}
-
-static void
-_resource_free (Resource *resource)
-{
- g_free (resource->name);
- g_free (resource->status_message);
- g_slice_free (Resource, resource);
-}
-
-static void
-gabble_presence_finalize (GObject *object)
-{
- GSList *i;
- GabblePresence *presence = GABBLE_PRESENCE (object);
- GabblePresencePrivate *priv = GABBLE_PRESENCE_PRIV (presence);
-
- for (i = priv->resources; NULL != i; i = i->next)
- _resource_free (i->data);
-
- g_slist_free (priv->resources);
- g_free (presence->nickname);
- g_free (presence->avatar_sha1);
- g_free (priv->no_resource_status_message);
-}
-
-static void
-gabble_presence_class_init (GabblePresenceClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- g_type_class_add_private (object_class, sizeof (GabblePresencePrivate));
- object_class->finalize = gabble_presence_finalize;
-}
-
-static void
-gabble_presence_init (GabblePresence *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_PRESENCE, GabblePresencePrivate);
- ((GabblePresencePrivate *)self->priv)->resources = NULL;
-}
-
-GabblePresence*
-gabble_presence_new (void)
-{
- return g_object_new (GABBLE_TYPE_PRESENCE, NULL);
-}
-
-const gchar *
-gabble_presence_pick_resource_by_caps (
- GabblePresence *presence,
- GabblePresenceCapabilities caps)
-{
- GabblePresencePrivate *priv = GABBLE_PRESENCE_PRIV (presence);
- GSList *i;
- Resource *chosen = NULL;
-
- for (i = priv->resources; NULL != i; i = i->next)
- {
- Resource *res = (Resource *) i->data;
-
- if ((res->priority >= 0) &&
- ((res->caps & caps) == caps) &&
- (NULL == chosen || res->priority > chosen->priority))
- chosen = res;
- }
-
- if (chosen)
- return chosen->name;
- else
- return NULL;
-}
-
-gboolean
-gabble_presence_resource_has_caps (GabblePresence *presence,
- const gchar *resource,
- GabblePresenceCapabilities caps)
-{
- GabblePresencePrivate *priv = GABBLE_PRESENCE_PRIV (presence);
- GSList *i;
-
- for (i = priv->resources; NULL != i; i = i->next)
- {
- Resource *res = (Resource *) i->data;
-
- if (!tp_strdiff (res->name, resource) && (res->caps & caps))
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-gabble_presence_set_capabilities (GabblePresence *presence,
- const gchar *resource,
- GabblePresenceCapabilities caps,
- guint serial)
-{
- GabblePresencePrivate *priv = GABBLE_PRESENCE_PRIV (presence);
- GSList *i;
-
- presence->caps = 0;
-
- DEBUG ("about to add caps %u to resource %s with serial %u", caps, resource,
- serial);
-
- for (i = priv->resources; NULL != i; i = i->next)
- {
- Resource *tmp = (Resource *) i->data;
-
- if (0 == strcmp (tmp->name, resource))
- {
- DEBUG ("found resource %s", resource);
-
- if (serial > tmp->caps_serial)
- {
- DEBUG ("new serial %u, old %u, clearing caps", serial,
- tmp->caps_serial);
- tmp->caps = 0;
- tmp->caps_serial = serial;
- }
-
- if (serial >= tmp->caps_serial)
- {
- DEBUG ("adding caps %u to resource %s", caps, resource);
- tmp->caps |= caps;
- DEBUG ("resource %s caps now %u", resource, tmp->caps);
- }
- }
-
- presence->caps |= tmp->caps;
- }
-
- DEBUG ("total caps now %u", presence->caps);
-}
-
-static Resource *
-_find_resource (GabblePresence *presence, const gchar *resource)
-{
- GSList *i;
- GabblePresencePrivate *priv = GABBLE_PRESENCE_PRIV (presence);
-
- for (i = priv->resources; NULL != i; i = i->next)
- {
- Resource *res = (Resource *) i->data;
-
- if (0 == strcmp (res->name, resource))
- return res;
- }
-
- return NULL;
-}
-
-gboolean
-gabble_presence_update (GabblePresence *presence,
- const gchar *resource,
- GabblePresenceId status,
- const gchar *status_message,
- gint8 priority)
-{
- GabblePresencePrivate *priv = GABBLE_PRESENCE_PRIV (presence);
- Resource *res;
- GabblePresenceId old_status;
- gchar *old_status_message;
- GSList *i;
- guint8 prio;
- gboolean ret = FALSE;
-
- /* save our current state */
- old_status = presence->status;
- old_status_message = g_strdup (presence->status_message);
-
- if (NULL == resource)
- {
- /* presence from a JID with no resource: free all resources and set
- * presence directly */
-
- for (i = priv->resources; i; i = i->next)
- _resource_free (i->data);
-
- g_slist_free (priv->resources);
- priv->resources = NULL;
-
- if (tp_strdiff (priv->no_resource_status_message, status_message))
- {
- g_free (priv->no_resource_status_message);
- priv->no_resource_status_message = g_strdup (status_message);
- }
-
- presence->status = status;
- presence->status_message = priv->no_resource_status_message;
- goto OUT;
- }
-
- res = _find_resource (presence, resource);
-
- /* remove, create or update a Resource as appropriate */
- if (GABBLE_PRESENCE_OFFLINE == status &&
- NULL == status_message)
- {
- if (NULL != res)
- {
- priv->resources = g_slist_remove (priv->resources, res);
- _resource_free (res);
- res = NULL;
- }
- }
- else
- {
- if (NULL == res)
- {
- res = _resource_new (g_strdup (resource));
- priv->resources = g_slist_append (priv->resources, res);
- }
-
- res->status = status;
-
- if (tp_strdiff (res->status_message, status_message))
- {
- g_free (res->status_message);
- res->status_message = g_strdup (status_message);
- }
-
- res->priority = priority;
- }
-
- /* select the most preferable Resource and update presence->* based on our
- * choice */
- presence->caps = 0;
- presence->status = GABBLE_PRESENCE_OFFLINE;
-
- /* use the status message from any offline Resource we're
- * keeping around just because it has a message on it */
- presence->status_message = res ? res->status_message : NULL;
-
- prio = -128;
-
- for (i = priv->resources; NULL != i; i = i->next)
- {
- Resource *res = (Resource *) i->data;
-
- presence->caps |= res->caps;
-
- /* trump existing status & message if it's more present
- * or has the same presence and a higher priority */
- if (res->status > presence->status ||
- (res->status == presence->status && res->priority > prio))
- {
- presence->status = res->status;
- presence->status_message = res->status_message;
- prio = res->priority;
- }
- }
-
-OUT:
- /* detect changes */
- if (presence->status != old_status ||
- tp_strdiff (presence->status_message, old_status_message))
- ret = TRUE;
-
- g_free (old_status_message);
- return ret;
-}
-
-LmMessage *
-gabble_presence_as_message (GabblePresence *presence, const gchar *resource)
-{
- LmMessage *message;
- LmMessageNode *node, *subnode;
- LmMessageSubType subtype;
- Resource *res = _find_resource (presence, resource);
-
- g_assert (NULL != res);
-
- if (presence->status == GABBLE_PRESENCE_OFFLINE)
- subtype = LM_MESSAGE_SUB_TYPE_UNAVAILABLE;
- else
- subtype = LM_MESSAGE_SUB_TYPE_AVAILABLE;
-
- message = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_PRESENCE,
- subtype);
- node = lm_message_get_node (message);
-
- switch (presence->status)
- {
- case GABBLE_PRESENCE_AVAILABLE:
- case GABBLE_PRESENCE_OFFLINE:
- case GABBLE_PRESENCE_HIDDEN:
- break;
- case GABBLE_PRESENCE_AWAY:
- lm_message_node_add_child (node, "show", JABBER_PRESENCE_SHOW_AWAY);
- break;
- case GABBLE_PRESENCE_CHAT:
- lm_message_node_add_child (node, "show", JABBER_PRESENCE_SHOW_CHAT);
- break;
- case GABBLE_PRESENCE_DND:
- lm_message_node_add_child (node, "show", JABBER_PRESENCE_SHOW_DND);
- break;
- case GABBLE_PRESENCE_XA:
- lm_message_node_add_child (node, "show", JABBER_PRESENCE_SHOW_XA);
- break;
- default:
- g_critical ("%s: Unexpected Telepathy presence type", G_STRFUNC);
- break;
- }
-
- if (presence->status_message)
- lm_message_node_add_child (node, "status", presence->status_message);
-
- if (res->priority)
- {
- gchar *priority = g_strdup_printf ("%d", res->priority);
- lm_message_node_add_child (node, "priority", priority);
- g_free (priority);
- }
-
- subnode = lm_message_node_add_child (node, "x", "");
- lm_message_node_set_attribute (subnode, "xmlns", NS_VCARD_TEMP_UPDATE);
- /* NULL means we make no particular assertion about the avatar. */
- if (presence->avatar_sha1 != NULL)
- {
- lm_message_node_add_child (subnode, "photo", presence->avatar_sha1);
- }
-
- return message;
-}
-
-gchar *
-gabble_presence_dump (GabblePresence *presence)
-{
- GSList *i;
- GString *ret = g_string_new ("");
- GabblePresencePrivate *priv = GABBLE_PRESENCE_PRIV (presence);
-
- g_string_append_printf (ret,
- "nickname: %s\n"
- "accumulated status: %d\n"
- "accumulated status msg: %s\n"
- "accumulated capabilities: %d\n"
- "kept while unavailable: %d\n"
- "resources:\n", presence->nickname, presence->status,
- presence->status_message, presence->caps,
- presence->keep_unavailable);
-
- for (i = priv->resources; i; i = i->next)
- {
- Resource *res = (Resource *) i->data;
-
- g_string_append_printf (ret,
- " %s\n"
- " capabilities: %d\n"
- " status: %d\n"
- " status msg: %s\n"
- " priority: %d\n", res->name, res->caps, res->status,
- res->status_message, res->priority);
- }
-
- if (priv->resources == NULL)
- g_string_append_printf (ret, " (none)\n");
-
- return g_string_free (ret, FALSE);
-}
diff --git a/src/presence.h b/src/presence.h
deleted file mode 100644
index 5dedcb26c..000000000
--- a/src/presence.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * gabble-presence.h - Headers for Gabble's per-contact presence structure
- * Copyright (C) 2005 Collabora Ltd.
- * Copyright (C) 2005 Nokia Corporation
- *
- * 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
- */
-
-
-#ifndef __GABBLE_PRESENCE_H__
-#define __GABBLE_PRESENCE_H__
-
-#include <glib-object.h>
-
-#include "gabble-connection.h"
-#include "gabble-types.h"
-
-G_BEGIN_DECLS
-
-#define GABBLE_TYPE_PRESENCE gabble_presence_get_type ()
-
-#define GABBLE_PRESENCE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- GABBLE_TYPE_PRESENCE, GabblePresence))
-
-#define GABBLE_PRESENCE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), \
- GABBLE_TYPE_PRESENCE, GabblePresenceClass))
-
-#define GABBLE_IS_PRESENCE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
- GABBLE_TYPE_PRESENCE))
-
-#define GABBLE_IS_PRESENCE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), \
- GABBLE_TYPE_PRESENCE))
-
-#define GABBLE_PRESENCE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), \
- GABBLE_TYPE_PRESENCE, GabblePresenceClass))
-
-typedef enum {
- PRESENCE_CAP_NONE = 0,
- PRESENCE_CAP_GOOGLE_TRANSPORT_P2P = 1 << 0,
- PRESENCE_CAP_GOOGLE_VOICE = 1 << 1,
- PRESENCE_CAP_JINGLE = 1 << 2,
- PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO = 1 << 3,
- PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO = 1 << 4,
- PRESENCE_CAP_CHAT_STATES = 1 << 5,
-} GabblePresenceCapabilities;
-
-struct _GabblePresence {
- GObject parent;
- GabblePresenceCapabilities caps;
- GabblePresenceId status;
- gchar *status_message;
- gchar *nickname;
- gchar *avatar_sha1;
- gboolean keep_unavailable;
- gpointer priv;
-};
-
-typedef struct _GabblePresenceClass GabblePresenceClass;
-
-struct _GabblePresenceClass {
- GObjectClass parent_class;
-};
-
-GType gabble_presence_get_type (void);
-
-GabblePresence* gabble_presence_new (void);
-
-gboolean gabble_presence_update (GabblePresence *presence,
- const gchar *resource, GabblePresenceId status,
- const gchar *status_message, gint8 priority);
-
-void gabble_presence_set_capabilities (GabblePresence *presence,
- const gchar *resource, GabblePresenceCapabilities caps, guint serial);
-
-const gchar *gabble_presence_pick_resource_by_caps (GabblePresence *presence,
- GabblePresenceCapabilities caps);
-
-gboolean gabble_presence_resource_has_caps (GabblePresence *presence,
- const gchar *resource,
- GabblePresenceCapabilities caps);
-
-LmMessage *gabble_presence_as_message (GabblePresence *presence,
- const gchar *resource);
-gchar *gabble_presence_dump (GabblePresence *presence);
-
-G_END_DECLS
-
-#endif /* __GABBLE_PRESENCE_H__ */
-
diff --git a/src/roster.c b/src/roster.c
deleted file mode 100644
index 99de617bf..000000000
--- a/src/roster.c
+++ /dev/null
@@ -1,2345 +0,0 @@
-/*
- * roster.c - Source for Gabble roster helper
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#include "roster.h"
-
-#define DBUS_API_SUBJECT_TO_CHANGE
-
-#include <dbus/dbus-glib.h>
-#include <string.h>
-
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-factory-iface.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_ROSTER
-
-#include "debug.h"
-#include "gabble-connection.h"
-#include "gabble-roster-channel.h"
-#include "namespaces.h"
-#include "util.h"
-
-#define GOOGLE_ROSTER_VERSION "2"
-
-/* Properties */
-enum
-{
- PROP_CONNECTION = 1,
- LAST_PROPERTY
-};
-
-/* signal enum */
-enum
-{
- NICKNAME_UPDATE,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-typedef struct _GabbleRosterPrivate GabbleRosterPrivate;
-struct _GabbleRosterPrivate
-{
- GabbleConnection *conn;
-
- LmMessageHandler *iq_cb;
- LmMessageHandler *presence_cb;
-
- GHashTable *list_channels;
- GHashTable *group_channels;
- GHashTable *items;
-
- gboolean roster_received;
- gboolean dispose_has_run;
-};
-
-typedef enum
-{
- GOOGLE_ITEM_TYPE_INVALID = -1,
- GOOGLE_ITEM_TYPE_NORMAL = 0,
- GOOGLE_ITEM_TYPE_BLOCKED,
- GOOGLE_ITEM_TYPE_HIDDEN,
- GOOGLE_ITEM_TYPE_PINNED,
-} GoogleItemType;
-
-typedef struct _GabbleRosterItemEdit GabbleRosterItemEdit;
-struct _GabbleRosterItemEdit
-{
- /* if these are ..._INVALID, that means don't edit */
- GabbleRosterSubscription new_subscription;
- GoogleItemType new_google_type;
- /* owned by the item; if NULL, that means don't edit */
- gchar *new_name;
- TpHandleSet *add_to_groups;
- TpHandleSet *remove_from_groups;
-};
-
-typedef struct _GabbleRosterItem GabbleRosterItem;
-struct _GabbleRosterItem
-{
- GabbleRosterSubscription subscription;
- gboolean ask_subscribe;
- GoogleItemType google_type;
- gchar *name;
- TpHandleSet *groups;
- /* if not NULL, an edit attempt is already "in-flight" so instead of
- * sending off another, store required edits here until the one we
- * already sent is acknowledged - this prevents some race conditions
- */
- GabbleRosterItemEdit *unsent_edits;
-};
-
-static void gabble_roster_factory_iface_init ();
-static void gabble_roster_init (GabbleRoster *roster);
-static GObject * gabble_roster_constructor (GType type, guint n_props,
- GObjectConstructParam *props);
-static void gabble_roster_dispose (GObject *object);
-static void gabble_roster_finalize (GObject *object);
-static void gabble_roster_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-static void gabble_roster_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-
-static void _gabble_roster_item_free (GabbleRosterItem *item);
-static void item_edit_free (GabbleRosterItemEdit *edits);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleRoster, gabble_roster, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
- gabble_roster_factory_iface_init));
-
-#define GABBLE_ROSTER_GET_PRIVATE(o) ((GabbleRosterPrivate*) ((o)->priv));
-
-static void
-gabble_roster_class_init (GabbleRosterClass *gabble_roster_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_roster_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_roster_class, sizeof (GabbleRosterPrivate));
-
- object_class->constructor = gabble_roster_constructor;
-
- object_class->dispose = gabble_roster_dispose;
- object_class->finalize = gabble_roster_finalize;
-
- object_class->get_property = gabble_roster_get_property;
- object_class->set_property = gabble_roster_set_property;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "XMPP roster object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class,
- PROP_CONNECTION,
- param_spec);
-
- signals[NICKNAME_UPDATE] = g_signal_new (
- "nickname-update",
- G_TYPE_FROM_CLASS (gabble_roster_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
-}
-
-static void
-gabble_roster_init (GabbleRoster *obj)
-{
- GabbleRosterPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj,
- GABBLE_TYPE_ROSTER, GabbleRosterPrivate);
-
- obj->priv = priv;
-
- priv->list_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
-
- priv->group_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
-
- priv->items = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) _gabble_roster_item_free);
-}
-
-static GObject *
-gabble_roster_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- /* GabbleRosterPrivate *priv; */
-
- obj = G_OBJECT_CLASS (gabble_roster_parent_class)->
- constructor (type, n_props, props);
- /* priv = GABBLE_ROSTER_GET_PRIVATE (GABBLE_ROSTER (obj)); */
-
- return obj;
-}
-
-void
-gabble_roster_dispose (GObject *object)
-{
- GabbleRoster *self = GABBLE_ROSTER (object);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
-
- priv->dispose_has_run = TRUE;
-
- g_assert (priv->iq_cb == NULL);
- g_assert (priv->presence_cb == NULL);
-
- tp_channel_factory_iface_close_all (TP_CHANNEL_FACTORY_IFACE (object));
- g_assert (priv->group_channels == NULL);
- g_assert (priv->list_channels == NULL);
-
- if (G_OBJECT_CLASS (gabble_roster_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_roster_parent_class)->dispose (object);
-}
-
-static void
-item_handle_unref_foreach (gpointer key, gpointer data, gpointer user_data)
-{
- TpHandle handle = (TpHandle) key;
- GabbleRosterPrivate *priv = (GabbleRosterPrivate *) user_data;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- tp_handle_unref (contact_repo, handle);
-}
-
-void
-gabble_roster_finalize (GObject *object)
-{
- GabbleRoster *self = GABBLE_ROSTER (object);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (self);
-
- DEBUG ("called with %p", object);
-
- g_hash_table_foreach (priv->items, item_handle_unref_foreach, priv);
- g_hash_table_destroy (priv->items);
-
- G_OBJECT_CLASS (gabble_roster_parent_class)->finalize (object);
-}
-
-static void
-gabble_roster_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleRoster *roster = GABBLE_ROSTER (object);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_roster_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleRoster *roster = GABBLE_ROSTER (object);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-_gabble_roster_item_free (GabbleRosterItem *item)
-{
- g_assert (item != NULL);
-
- tp_handle_set_destroy (item->groups);
- item_edit_free (item->unsent_edits);
- g_free (item->name);
- g_slice_free (GabbleRosterItem, item);
-}
-
-static const gchar *
-_subscription_to_string (GabbleRosterSubscription subscription)
-{
- switch (subscription)
- {
- case GABBLE_ROSTER_SUBSCRIPTION_NONE:
- return "none";
- case GABBLE_ROSTER_SUBSCRIPTION_FROM:
- return "from";
- case GABBLE_ROSTER_SUBSCRIPTION_TO:
- return "to";
- case GABBLE_ROSTER_SUBSCRIPTION_BOTH:
- return "both";
- case GABBLE_ROSTER_SUBSCRIPTION_REMOVE:
- return "remove";
- default:
- g_assert_not_reached ();
- return NULL;
- }
-}
-
-static GabbleRosterSubscription
-_parse_item_subscription (LmMessageNode *item_node)
-{
- const gchar *subscription;
-
- g_assert (item_node != NULL);
-
- subscription = lm_message_node_get_attribute (item_node, "subscription");
-
- if (NULL == subscription || 0 == strcmp (subscription, "none"))
- return GABBLE_ROSTER_SUBSCRIPTION_NONE;
- else if (0 == strcmp (subscription, "from"))
- return GABBLE_ROSTER_SUBSCRIPTION_FROM;
- else if (0 == strcmp (subscription, "to"))
- return GABBLE_ROSTER_SUBSCRIPTION_TO;
- else if (0 == strcmp (subscription, "both"))
- return GABBLE_ROSTER_SUBSCRIPTION_BOTH;
- else if (0 == strcmp (subscription, "remove"))
- return GABBLE_ROSTER_SUBSCRIPTION_REMOVE;
- else
- {
- NODE_DEBUG (item_node, "got unexpected subscription value");
- return GABBLE_ROSTER_SUBSCRIPTION_NONE;
- }
-}
-
-static TpHandleSet *
-_parse_item_groups (LmMessageNode *item_node, TpBaseConnection *conn)
-{
- LmMessageNode *group_node;
- TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
- conn, TP_HANDLE_TYPE_GROUP);
- TpHandleSet *groups = tp_handle_set_new (group_repo);
- TpHandle handle;
-
- for (group_node = item_node->children;
- NULL != group_node;
- group_node = group_node->next)
- {
- if (0 != strcmp (group_node->name, "group"))
- continue;
-
- if (NULL == group_node->value)
- continue;
-
- handle = tp_handle_ensure (group_repo, group_node->value, NULL, NULL);
- if (!handle)
- continue;
- tp_handle_set_add (groups, handle);
- tp_handle_unref (group_repo, handle);
- }
-
- return groups;
-}
-
-static const gchar *
-_google_item_type_to_string (GoogleItemType google_type)
-{
- switch (google_type)
- {
- case GOOGLE_ITEM_TYPE_NORMAL:
- return NULL;
- case GOOGLE_ITEM_TYPE_BLOCKED:
- return "B";
- case GOOGLE_ITEM_TYPE_HIDDEN:
- return "H";
- case GOOGLE_ITEM_TYPE_PINNED:
- return "P";
- case GOOGLE_ITEM_TYPE_INVALID:
- g_assert_not_reached ();
- return NULL;
- }
-
- g_assert_not_reached ();
-
- return NULL;
-}
-
-static GoogleItemType
-_parse_google_item_type (LmMessageNode *item_node)
-{
- const gchar *google_type;
-
- g_assert (item_node != NULL);
-
- google_type = lm_message_node_get_attribute (item_node, "gr:t");
-
- if (NULL == google_type)
- return GOOGLE_ITEM_TYPE_NORMAL;
- else if (!tp_strdiff (google_type, "B"))
- return GOOGLE_ITEM_TYPE_BLOCKED;
- else if (!tp_strdiff (google_type, "H"))
- return GOOGLE_ITEM_TYPE_HIDDEN;
- else if (!tp_strdiff (google_type, "P"))
- return GOOGLE_ITEM_TYPE_PINNED;
-
- NODE_DEBUG (item_node, "got unexpected google contact type value");
-
- return GOOGLE_ITEM_TYPE_NORMAL;
-}
-
-static gboolean
-_google_roster_item_should_keep (LmMessageNode *item_node,
- GabbleRosterItem *item)
-{
- const gchar *attr;
-
- /* skip automatically subscribed Google roster items */
- attr = lm_message_node_get_attribute (item_node, "gr:autosub");
-
- if (!tp_strdiff (attr, "true"))
- return FALSE;
-
- /* skip email addresses that replied to an invite */
- attr = lm_message_node_get_attribute (item_node, "gr:alias-for");
-
- if (attr != NULL)
- return FALSE;
-
- /* allow items that we've requested a subscription from */
- if (item->ask_subscribe)
- return TRUE;
-
- if (item->subscription != GABBLE_ROSTER_SUBSCRIPTION_NONE)
- return TRUE;
-
- /* discard anything else */
- return FALSE;
-}
-
-static GabbleRosterItem *
-_gabble_roster_item_get (GabbleRoster *roster,
- TpHandle handle)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_GROUP);
- GabbleRosterItem *item;
-
- g_assert (roster != NULL);
- g_assert (GABBLE_IS_ROSTER (roster));
- g_assert (tp_handle_is_valid (contact_repo, handle, NULL));
-
- item = g_hash_table_lookup (priv->items, GINT_TO_POINTER (handle));
-
- if (NULL == item)
- {
- item = g_slice_new0 (GabbleRosterItem);
- item->groups = tp_handle_set_new (group_repo);
- tp_handle_ref (contact_repo, handle);
- g_hash_table_insert (priv->items, GINT_TO_POINTER (handle), item);
- }
-
- return item;
-}
-
-static void
-_gabble_roster_item_remove (GabbleRoster *roster,
- TpHandle handle)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- g_assert (roster != NULL);
- g_assert (GABBLE_IS_ROSTER (roster));
- g_assert (tp_handle_is_valid (contact_repo, handle, NULL));
-
- g_hash_table_remove (priv->items, GINT_TO_POINTER (handle));
- tp_handle_unref (contact_repo, handle);
-}
-
-/* the TpHandleType must be GROUP or LIST */
-static GabbleRosterChannel *_gabble_roster_get_channel (GabbleRoster *,
- TpHandleType, TpHandle, gboolean *created);
-
-typedef struct
-{
- GHashTable *group_mem_updates;
- guint contact_handle;
-} GroupsUpdateContext;
-
-typedef struct
-{
- TpIntSet *contacts_added;
- TpIntSet *contacts_removed;
-#ifdef ENABLE_DEBUG
- guint group_handle;
-#endif
-} GroupMembershipUpdate;
-
-static GroupMembershipUpdate *
-group_mem_update_ensure (GroupsUpdateContext *ctx, TpHandle group_handle)
-{
- GroupMembershipUpdate *update = g_hash_table_lookup (ctx->group_mem_updates,
- GUINT_TO_POINTER (group_handle));
-
- if (update) return update;
-
- DEBUG ("Creating new hash table entry for group#%u", group_handle);
- update = g_slice_new0 (GroupMembershipUpdate);
-#ifdef ENABLE_DEBUG
- update->group_handle = group_handle;
-#endif
- update->contacts_added = tp_intset_new ();
- update->contacts_removed = tp_intset_new ();
- g_hash_table_insert (ctx->group_mem_updates,
- GUINT_TO_POINTER (group_handle),
- update);
- return update;
-}
-
-static void
-_update_add_to_group (guint group_handle, gpointer user_data)
-{
- GroupsUpdateContext *ctx = (GroupsUpdateContext *)user_data;
- GroupMembershipUpdate *update = group_mem_update_ensure (ctx, group_handle);
-
- DEBUG ("- contact#%u added to group#%u", ctx->contact_handle,
- group_handle);
- tp_intset_add (update->contacts_added, ctx->contact_handle);
-}
-
-static void
-_update_remove_from_group (guint group_handle, gpointer user_data)
-{
- GroupsUpdateContext *ctx = (GroupsUpdateContext *)user_data;
- GroupMembershipUpdate *update = group_mem_update_ensure (ctx, group_handle);
-
- DEBUG ("- contact#%u removed from group#%u", ctx->contact_handle,
- group_handle);
- tp_intset_add (update->contacts_removed, ctx->contact_handle);
-}
-
-static GabbleRosterItem *
-_gabble_roster_item_update (GabbleRoster *roster,
- TpHandle contact_handle,
- LmMessageNode *node,
- GHashTable *group_updates,
- gboolean google_roster_mode)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleRosterItem *item;
- const gchar *ask, *name;
- TpIntSet *old_groups, *new_groups, *added_to, *removed_from, *removed_from2;
- TpHandleSet *new_groups_handle_set;
- GroupsUpdateContext ctx = { group_updates, contact_handle };
-
- g_assert (roster != NULL);
- g_assert (GABBLE_IS_ROSTER (roster));
- g_assert (tp_handle_is_valid (contact_repo, contact_handle, NULL));
- g_assert (node != NULL);
-
- item = _gabble_roster_item_get (roster, contact_handle);
-
- item->subscription = _parse_item_subscription (node);
-
- ask = lm_message_node_get_attribute (node, "ask");
- if (NULL != ask && 0 == strcmp (ask, "subscribe"))
- item->ask_subscribe = TRUE;
- else
- item->ask_subscribe = FALSE;
-
- if (google_roster_mode)
- {
- item->google_type = _parse_google_item_type (node);
-
- /* discard roster item if strange, just hide it if it's hidden */
- if (item->google_type == GOOGLE_ITEM_TYPE_HIDDEN)
- {
- DEBUG ("Google roster: caching hidden contact %d (%s)",
- contact_handle,
- lm_message_node_get_attribute (node, "jid"));
- item->subscription = GABBLE_ROSTER_SUBSCRIPTION_NONE;
- }
- else if (!_google_roster_item_should_keep (node, item))
- {
- DEBUG ("Google roster: discarding odd contact %d (%s)",
- contact_handle,
- lm_message_node_get_attribute (node, "jid"));
- item->subscription = GABBLE_ROSTER_SUBSCRIPTION_REMOVE;
- }
- }
-
- if (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE)
- name = NULL;
- else
- name = lm_message_node_get_attribute (node, "name");
-
- if (tp_strdiff (item->name, name))
- {
- g_free (item->name);
- item->name = g_strdup (name);
-
- DEBUG ("name for contact#%u changed to %s", contact_handle,
- name);
- g_signal_emit (G_OBJECT (roster), signals[NICKNAME_UPDATE], 0,
- contact_handle);
- }
-
- old_groups = tp_handle_set_peek (item->groups); /* borrowed */
- new_groups_handle_set = _parse_item_groups (node,
- (TpBaseConnection *)priv->conn);
- new_groups = tp_handle_set_peek (new_groups_handle_set);
-
- removed_from = tp_intset_difference (old_groups, new_groups);
- added_to = tp_handle_set_update (item->groups, new_groups);
- removed_from2 = tp_handle_set_difference_update (item->groups, removed_from);
-
- DEBUG ("Checking which groups contact#%u was just added to:",
- contact_handle);
- tp_intset_foreach (added_to, _update_add_to_group, &ctx);
- DEBUG ("Checking which groups contact#%u was just removed from:",
- contact_handle);
- tp_intset_foreach (removed_from, _update_remove_from_group, &ctx);
-
- tp_intset_destroy (added_to);
- tp_intset_destroy (removed_from);
- tp_intset_destroy (removed_from2);
- new_groups = NULL;
- tp_handle_set_destroy (new_groups_handle_set);
-
- return item;
-}
-
-
-#ifdef ENABLE_DEBUG
-static void
-_gabble_roster_item_dump_group (guint handle, gpointer user_data)
-{
- g_string_append_printf ((GString *)user_data, "group#%u ", handle);
-}
-
-static gchar *
-_gabble_roster_item_dump (GabbleRosterItem *item)
-{
- GString *str;
-
- g_assert (item != NULL);
-
- str = g_string_new ("subscription: ");
-
- g_string_append (str, _subscription_to_string (item->subscription));
-
- if (item->ask_subscribe)
- g_string_append (str, ", ask: subscribe");
-
- if (item->google_type != GOOGLE_ITEM_TYPE_NORMAL)
- g_string_append_printf (str, ", google_type: %s",
- _google_item_type_to_string (item->google_type));
-
- if (item->name)
- g_string_append_printf (str, ", name: %s", item->name);
-
- if (item->groups)
- {
- tp_intset_foreach (tp_handle_set_peek (item->groups),
- _gabble_roster_item_dump_group, str);
- }
-
- return g_string_free (str, FALSE);
-}
-#endif /* ENABLE_DEBUG */
-
-
-static LmMessage *
-_gabble_roster_message_new (GabbleRoster *roster,
- LmMessageSubType sub_type,
- LmMessageNode **query_return)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- LmMessage *message;
- LmMessageNode *query_node;
-
- g_assert (roster != NULL);
- g_assert (GABBLE_IS_ROSTER (roster));
-
- message = lm_message_new_with_sub_type (NULL,
- LM_MESSAGE_TYPE_IQ,
- sub_type);
-
- query_node = lm_message_node_add_child (message->node, "query", NULL);
-
- if (NULL != query_return)
- *query_return = query_node;
-
- lm_message_node_set_attribute (query_node, "xmlns", NS_ROSTER);
-
- if (priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER)
- {
- lm_message_node_set_attributes (query_node,
- "xmlns:gr", NS_GOOGLE_ROSTER,
- "gr:ext", GOOGLE_ROSTER_VERSION,
- "gr:include", "all",
- NULL);
- }
-
- return message;
-}
-
-
-struct _ItemToMessageContext {
- TpBaseConnection *conn;
- LmMessageNode *item_node;
-};
-
-static void
-_gabble_roster_item_put_group_in_message (guint handle, gpointer user_data)
-{
- struct _ItemToMessageContext *ctx =
- (struct _ItemToMessageContext *)user_data;
- TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
- ctx->conn, TP_HANDLE_TYPE_GROUP);
- const char *name = tp_handle_inspect (group_repo, handle);
-
- lm_message_node_add_child (ctx->item_node, "group", name);
-}
-
-/* Return a message representing the current state of the item for contact
- * @handle on the roster @roster.
- *
- * If item_return is not NULL, populate it with the <item/> node.
- *
- * If item is not NULL, it represents the state we would like the contact's
- * roster item to have - use it instead of the contact's actual roster item
- * when composing the message.
- */
-static LmMessage *
-_gabble_roster_item_to_message (GabbleRoster *roster,
- TpHandle handle,
- LmMessageNode **item_return,
- GabbleRosterItem *item)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- LmMessage *message;
- LmMessageNode *query_node, *item_node;
- const gchar *jid;
- struct _ItemToMessageContext ctx = {
- (TpBaseConnection *)priv->conn,
- };
-
- g_assert (roster != NULL);
- g_assert (GABBLE_IS_ROSTER (roster));
- g_assert (tp_handle_is_valid (contact_repo, handle, NULL));
-
- if (!item)
- item = _gabble_roster_item_get (roster, handle);
-
- message = _gabble_roster_message_new (roster, LM_MESSAGE_SUB_TYPE_SET,
- &query_node);
-
- item_node = lm_message_node_add_child (query_node, "item", NULL);
- ctx.item_node = item_node;
-
- if (NULL != item_return)
- *item_return = item_node;
-
- jid = tp_handle_inspect (contact_repo, handle);
- lm_message_node_set_attribute (item_node, "jid", jid);
-
- if (item->subscription != GABBLE_ROSTER_SUBSCRIPTION_NONE)
- {
- const gchar *subscription = _subscription_to_string (item->subscription);
- lm_message_node_set_attribute (item_node, "subscription", subscription);
- }
-
- if (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE)
- goto DONE;
-
- if ((priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER) &&
- item->google_type != GOOGLE_ITEM_TYPE_NORMAL)
- lm_message_node_set_attribute (item_node, "gr:t",
- _google_item_type_to_string (item->google_type));
-
- if (item->ask_subscribe)
- lm_message_node_set_attribute (item_node, "ask", "subscribe");
-
- if (item->name)
- lm_message_node_set_attribute (item_node, "name", item->name);
-
- if (item->groups)
- {
- tp_intset_foreach (tp_handle_set_peek (item->groups),
- _gabble_roster_item_put_group_in_message,
- (void *)&ctx);
- }
-
-DONE:
- return message;
-}
-
-static GabbleRosterChannel *
-_gabble_roster_create_channel (GabbleRoster *roster,
- guint handle_type,
- TpHandle handle)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (conn,
- handle_type);
- GabbleRosterChannel *chan;
- const char *name;
- char *mangled_name;
- char *object_path;
- GHashTable *channels = (handle_type == TP_HANDLE_TYPE_LIST
- ? priv->list_channels
- : priv->group_channels);
-
- /* if this assertion succeeds, we know we have the right handle repo */
- g_assert (handle_type == TP_HANDLE_TYPE_LIST ||
- handle_type == TP_HANDLE_TYPE_GROUP);
- g_assert (channels != NULL);
- g_assert (g_hash_table_lookup (channels, GINT_TO_POINTER (handle)) == NULL);
-
- name = tp_handle_inspect (handle_repo, handle);
- DEBUG ("Instantiating channel %u:%u \"%s\"", handle_type, handle, name);
- mangled_name = tp_escape_as_identifier (name);
- object_path = g_strdup_printf ("%s/RosterChannel/%s/%s",
- conn->object_path,
- handle_type == TP_HANDLE_TYPE_LIST ? "List"
- : "Group",
- mangled_name);
- g_free (mangled_name);
- mangled_name = NULL;
-
- chan = g_object_new (GABBLE_TYPE_ROSTER_CHANNEL,
- "connection", priv->conn,
- "object-path", object_path,
- "handle", handle,
- "handle-type", handle_type,
- NULL);
-
- DEBUG ("created %s", object_path);
-
- g_hash_table_insert (channels, GINT_TO_POINTER (handle), chan);
-
- if (priv->roster_received)
- {
- DEBUG ("roster already received, emitting signal for %s",
- object_path);
-
- tp_channel_factory_iface_emit_new_channel (roster,
- (TpChannelIface *)chan, NULL);
- }
- else
- {
- DEBUG ("roster not yet received, not emitting signal for %s list "
- "channel", name);
- }
- g_free (object_path);
-
- return chan;
-}
-
-static GabbleRosterChannel *
-_gabble_roster_get_channel (GabbleRoster *roster,
- guint handle_type,
- TpHandle handle,
- gboolean *created)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, handle_type);
- GabbleRosterChannel *chan;
- GHashTable *channels = (handle_type == TP_HANDLE_TYPE_LIST
- ? priv->list_channels
- : priv->group_channels);
-
- /* if this assertion succeeds, we know we have the right handle repos */
- g_assert (handle_type == TP_HANDLE_TYPE_LIST ||
- handle_type == TP_HANDLE_TYPE_GROUP);
- g_assert (channels != NULL);
- g_assert (tp_handle_is_valid (handle_repo, handle, NULL));
-
- DEBUG ("Looking up channel %u:%u \"%s\"", handle_type, handle,
- tp_handle_inspect (handle_repo, handle));
- chan = g_hash_table_lookup (channels, GINT_TO_POINTER (handle));
-
- if (chan == NULL)
- {
- if (created)
- *created = TRUE;
- chan = _gabble_roster_create_channel (roster, handle_type, handle);
- }
- else
- {
- if (created)
- *created = FALSE;
- }
-
- return chan;
-}
-
-struct _EmitOneData {
- GabbleRoster *roster;
- guint handle_type; /* must be GROUP or LIST */
-};
-
-static void
-_gabble_roster_emit_one (gpointer key,
- gpointer value,
- gpointer data)
-{
- struct _EmitOneData *data_struct = (struct _EmitOneData *)data;
- GabbleRoster *roster = data_struct->roster;
- GabbleRosterChannel *chan = GABBLE_ROSTER_CHANNEL (value);
-#ifdef ENABLE_DEBUG
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, data_struct->handle_type);
- TpHandle handle = GPOINTER_TO_INT (key);
- const gchar *name;
-
- g_assert (data_struct->handle_type == TP_HANDLE_TYPE_GROUP ||
- data_struct->handle_type == TP_HANDLE_TYPE_LIST);
- g_assert (handle_repo != NULL);
- name = tp_handle_inspect (handle_repo, handle);
-
- DEBUG ("roster now received, emitting signal signal for %s list channel",
- name);
-#endif
-
- tp_channel_factory_iface_emit_new_channel (roster, (TpChannelIface *)chan,
- NULL);
-}
-
-static void
-_gabble_roster_received (GabbleRoster *roster)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
-
- g_assert (priv->list_channels != NULL);
-
- if (!priv->roster_received)
- {
- struct _EmitOneData data = { roster, TP_HANDLE_TYPE_LIST };
-
- priv->roster_received = TRUE;
-
- g_hash_table_foreach (priv->list_channels, _gabble_roster_emit_one,
- &data);
- data.handle_type = TP_HANDLE_TYPE_GROUP;
- g_hash_table_foreach (priv->group_channels, _gabble_roster_emit_one,
- &data);
- }
-}
-
-static void
-_group_mem_update_destroy (GroupMembershipUpdate *update)
-{
- tp_intset_destroy (update->contacts_added);
- tp_intset_destroy (update->contacts_removed);
- g_slice_free (GroupMembershipUpdate, update);
-}
-
-static gboolean
-_update_group (gpointer key, gpointer value, gpointer user_data)
-{
- guint group_handle = GPOINTER_TO_UINT (key);
- GabbleRoster *roster = GABBLE_ROSTER (user_data);
- GroupMembershipUpdate *update = (GroupMembershipUpdate *)value;
- GabbleRosterChannel *group_channel = _gabble_roster_get_channel (
- roster, TP_HANDLE_TYPE_GROUP, group_handle, NULL);
- TpIntSet *empty = tp_intset_new ();
-
-#ifdef ENABLE_DEBUG
- g_assert (group_handle == update->group_handle);
-#endif
-
- DEBUG ("Updating group channel %u now message has been received",
- group_handle);
- tp_group_mixin_change_members ((GObject *)group_channel,
- "", update->contacts_added, update->contacts_removed, empty, empty,
- 0, 0);
-
- tp_intset_destroy (empty);
-
- return TRUE;
-}
-
-/**
- * gabble_roster_iq_cb
- *
- * Called by loudmouth when we get an incoming <iq>. This handler
- * is concerned only with roster queries, and allows other handlers
- * if queries other than rosters are received.
- */
-static LmHandlerResult
-gabble_roster_iq_cb (LmMessageHandler *handler,
- LmConnection *lmconn,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleRoster *roster = GABBLE_ROSTER (user_data);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
- LmMessageNode *iq_node, *query_node;
- LmMessageSubType sub_type;
- const gchar *from;
- gboolean google_roster = FALSE;
-
- g_assert (lmconn == priv->conn->lmconn);
-
- if (priv->list_channels == NULL)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- iq_node = lm_message_get_node (message);
- query_node = lm_message_node_get_child_with_namespace (iq_node, "query",
- NS_ROSTER);
-
- if (query_node == NULL)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- from = lm_message_node_get_attribute (message->node, "from");
-
- if (from != NULL)
- {
- TpHandle sender;
-
- sender = tp_handle_lookup (contact_repo, from, NULL, NULL);
-
- if (sender != conn->self_handle)
- {
- NODE_DEBUG (iq_node, "discarding roster IQ which is not from "
- "ourselves or the server");
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
- }
-
- if (priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER)
- {
- const char *gr_ext;
-
- gr_ext = lm_message_node_get_attribute (query_node, "gr:ext");
-
- if (!tp_strdiff (gr_ext, GOOGLE_ROSTER_VERSION))
- google_roster = TRUE;
- }
-
- sub_type = lm_message_get_sub_type (message);
-
- /* if this is a result, it's from our initial query. if it's a set,
- * it's a roster push. either way, parse the items. */
- switch (sub_type)
- {
- LmMessageNode *item_node;
- TpIntSet *pub_add, *pub_rem,
- *sub_add, *sub_rem, *sub_rp,
- *known_add, *known_rem,
- *deny_add, *deny_rem;
- TpHandleSet *referenced_handles;
- GArray *removed;
- TpHandle handle;
- GabbleRosterChannel *chan;
- GHashTable *group_update_table;
- guint i;
-
- case LM_MESSAGE_SUB_TYPE_RESULT:
- case LM_MESSAGE_SUB_TYPE_SET:
- /* asymmetry is because we don't get locally pending subscription
- * requests via <roster>, we get it via <presence> */
- pub_add = tp_intset_new ();
- pub_rem = tp_intset_new ();
- sub_add = tp_intset_new ();
- sub_rem = tp_intset_new ();
- sub_rp = tp_intset_new ();
- known_add = tp_intset_new ();
- known_rem = tp_intset_new ();
- group_update_table = g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify)_group_mem_update_destroy);
- removed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
- referenced_handles = tp_handle_set_new (contact_repo);
-
- if (google_roster)
- {
- deny_add = tp_intset_new ();
- deny_rem = tp_intset_new ();
- }
- else
- {
- deny_add = NULL;
- deny_rem = NULL;
- }
-
- /* get the publish channel first because we need it when processing */
- handle = GABBLE_LIST_HANDLE_PUBLISH;
- chan = _gabble_roster_get_channel (roster, TP_HANDLE_TYPE_LIST, handle,
- NULL);
-
- /* iterate every sub-node, which we expect to be <item>s */
- for (item_node = query_node->children;
- item_node;
- item_node = item_node->next)
- {
- const char *jid;
- GabbleRosterItem *item;
-
- if (strcmp (item_node->name, "item"))
- {
- NODE_DEBUG (item_node, "query sub-node is not item, skipping");
- continue;
- }
-
- jid = lm_message_node_get_attribute (item_node, "jid");
- if (!jid)
- {
- NODE_DEBUG (item_node, "item node has no jid, skipping");
- continue;
- }
-
- handle = tp_handle_ensure (contact_repo, jid, NULL, NULL);
- if (handle == 0)
- {
- NODE_DEBUG (item_node, "item jid is malformed, skipping");
- continue;
- }
- /* transfer ownership of the reference to referenced_handles */
- tp_handle_set_add (referenced_handles, handle);
- tp_handle_unref (contact_repo, handle);
-
- item = _gabble_roster_item_update (roster, handle, item_node,
- group_update_table,
- google_roster);
-#ifdef ENABLE_DEBUG
- if (DEBUGGING)
- {
- gchar *dump = _gabble_roster_item_dump (item);
- DEBUG ("jid: %s, %s", jid, dump);
- g_free (dump);
- }
-#endif
-
- /* handle publish list changes */
- switch (item->subscription)
- {
- case GABBLE_ROSTER_SUBSCRIPTION_FROM:
- case GABBLE_ROSTER_SUBSCRIPTION_BOTH:
- tp_intset_add (pub_add, handle);
- break;
- case GABBLE_ROSTER_SUBSCRIPTION_NONE:
- case GABBLE_ROSTER_SUBSCRIPTION_TO:
- case GABBLE_ROSTER_SUBSCRIPTION_REMOVE:
- /* publish channel is a bit odd, the roster item doesn't tell us
- * if someone is awaiting our approval - we get this via presence
- * type=subscribe, so we have to not remove them if they're
- * already local_pending in our publish channel */
- if (!tp_handle_set_is_member (chan->group.local_pending, handle))
- {
- tp_intset_add (pub_rem, handle);
- }
- break;
- default:
- g_assert_not_reached ();
- }
-
- /* handle subscribe list changes */
- switch (item->subscription)
- {
- case GABBLE_ROSTER_SUBSCRIPTION_TO:
- case GABBLE_ROSTER_SUBSCRIPTION_BOTH:
- tp_intset_add (sub_add, handle);
- break;
- case GABBLE_ROSTER_SUBSCRIPTION_NONE:
- case GABBLE_ROSTER_SUBSCRIPTION_FROM:
- if (item->ask_subscribe)
- tp_intset_add (sub_rp, handle);
- else
- tp_intset_add (sub_rem, handle);
- break;
- case GABBLE_ROSTER_SUBSCRIPTION_REMOVE:
- tp_intset_add (sub_rem, handle);
- break;
- default:
- g_assert_not_reached ();
- }
-
- /* handle known list changes */
- switch (item->subscription)
- {
- case GABBLE_ROSTER_SUBSCRIPTION_NONE:
- case GABBLE_ROSTER_SUBSCRIPTION_TO:
- case GABBLE_ROSTER_SUBSCRIPTION_FROM:
- case GABBLE_ROSTER_SUBSCRIPTION_BOTH:
- if (item->google_type == GOOGLE_ITEM_TYPE_HIDDEN)
- tp_intset_add (known_rem, handle);
- else
- tp_intset_add (known_add, handle);
- break;
- case GABBLE_ROSTER_SUBSCRIPTION_REMOVE:
- tp_intset_add (known_rem, handle);
- break;
- default:
- g_assert_not_reached ();
- }
-
- /* handle deny list changes */
- if (google_roster)
- {
- switch (item->subscription)
- {
- case GABBLE_ROSTER_SUBSCRIPTION_NONE:
- case GABBLE_ROSTER_SUBSCRIPTION_TO:
- case GABBLE_ROSTER_SUBSCRIPTION_FROM:
- case GABBLE_ROSTER_SUBSCRIPTION_BOTH:
- if (item->google_type == GOOGLE_ITEM_TYPE_BLOCKED)
- tp_intset_add (deny_add, handle);
- else
- tp_intset_add (deny_rem, handle);
- break;
- case GABBLE_ROSTER_SUBSCRIPTION_REMOVE:
- tp_intset_add (deny_rem, handle);
- break;
- default:
- g_assert_not_reached ();
- }
- }
-
- /* delay removing items from roster until signals have been emitted;
- * otherwise handles go out of scope!
- * FIXME: this probably isn't true any more because of
- * referenced_handles */
- if (GABBLE_ROSTER_SUBSCRIPTION_REMOVE == item->subscription)
- g_array_append_val (removed, handle);
- }
-
- /* chan was initialised to the publish channel before the for loop */
-
- DEBUG ("calling change members on publish channel");
- tp_group_mixin_change_members ((GObject *)chan,
- "", pub_add, pub_rem, NULL, NULL, 0, 0);
-
- handle = GABBLE_LIST_HANDLE_SUBSCRIBE;
- chan = _gabble_roster_get_channel (roster, TP_HANDLE_TYPE_LIST, handle,
- NULL);
-
- DEBUG ("calling change members on subscribe channel");
- tp_group_mixin_change_members ((GObject *)chan,
- "", sub_add, sub_rem, NULL, sub_rp, 0, 0);
-
- handle = GABBLE_LIST_HANDLE_KNOWN;
- chan = _gabble_roster_get_channel (roster, TP_HANDLE_TYPE_LIST, handle,
- NULL);
-
- DEBUG ("calling change members on known channel");
- tp_group_mixin_change_members ((GObject *)chan,
- "", known_add, known_rem, NULL, NULL, 0, 0);
-
- DEBUG ("calling change members on any group channels");
- g_hash_table_foreach_remove (group_update_table, _update_group, roster);
-
- if (google_roster)
- {
- handle = GABBLE_LIST_HANDLE_DENY;
- chan = _gabble_roster_get_channel (roster, TP_HANDLE_TYPE_LIST,
- handle, NULL);
-
- DEBUG ("calling change members on deny channel");
- tp_group_mixin_change_members ((GObject *)chan,
- "", deny_add, deny_rem, NULL, NULL, 0, 0);
-
- tp_intset_destroy (deny_add);
- tp_intset_destroy (deny_rem);
- }
-
- for (i = 0; i < removed->len; i++)
- _gabble_roster_item_remove (roster,
- g_array_index (removed, TpHandle, i));
-
- tp_intset_destroy (pub_add);
- tp_intset_destroy (pub_rem);
- tp_intset_destroy (sub_add);
- tp_intset_destroy (sub_rem);
- tp_intset_destroy (sub_rp);
- tp_intset_destroy (known_add);
- tp_intset_destroy (known_rem);
- g_array_free (removed, TRUE);
- g_hash_table_destroy (group_update_table);
- tp_handle_set_destroy (referenced_handles);
- break;
- default:
- NODE_DEBUG (iq_node, "unhandled roster IQ");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- switch (sub_type)
- {
- case LM_MESSAGE_SUB_TYPE_RESULT:
- /* result means it's a roster push, so the roster is now complete and we
- * can emit signals */
- _gabble_roster_received (roster);
- break;
- case LM_MESSAGE_SUB_TYPE_SET:
- /* acknowledge roster */
- _gabble_connection_acknowledge_set_iq (priv->conn, message);
- break;
- default:
- break;
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-
-static void
-_gabble_roster_send_presence_ack (GabbleRoster *roster,
- const gchar *from,
- LmMessageSubType sub_type,
- gboolean changed)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- LmMessage *reply;
-
- if (!changed)
- {
- DEBUG ("not sending ack to avoid loop with buggy server");
- return;
- }
-
- switch (sub_type)
- {
- case LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE:
- sub_type = LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED;
- break;
- case LM_MESSAGE_SUB_TYPE_SUBSCRIBED:
- sub_type = LM_MESSAGE_SUB_TYPE_SUBSCRIBE;
- break;
- case LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED:
- sub_type = LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE;
- break;
- default:
- g_assert_not_reached ();
- return;
- }
-
- reply = lm_message_new_with_sub_type (from,
- LM_MESSAGE_TYPE_PRESENCE,
- sub_type);
-
- _gabble_connection_send (priv->conn, reply, NULL);
-
- lm_message_unref (reply);
-}
-
-
-/**
- * connection_presence_roster_cb:
- * @handler: #LmMessageHandler for this message
- * @connection: #LmConnection that originated the message
- * @message: the presence message
- * @user_data: callback data
- *
- * Called by loudmouth when we get an incoming <presence>.
- */
-static LmHandlerResult
-gabble_roster_presence_cb (LmMessageHandler *handler,
- LmConnection *lmconn,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleRoster *roster = GABBLE_ROSTER (user_data);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
- LmMessageNode *pres_node, *child_node;
- const char *from;
- LmMessageSubType sub_type;
- TpIntSet *tmp;
- TpHandle handle, list_handle;
- const gchar *status_message = NULL;
- GabbleRosterChannel *chan = NULL;
- gboolean changed;
- LmHandlerResult ret;
-
- g_assert (lmconn == priv->conn->lmconn);
-
- if (priv->list_channels == NULL)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- pres_node = lm_message_get_node (message);
-
- from = lm_message_node_get_attribute (pres_node, "from");
-
- if (from == NULL)
- {
- NODE_DEBUG (pres_node, "presence stanza without from attribute, "
- "ignoring");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- sub_type = lm_message_get_sub_type (message);
-
- handle = tp_handle_ensure (contact_repo, from, NULL, NULL);
-
- if (handle == 0)
- {
- NODE_DEBUG (pres_node, "ignoring presence from malformed jid");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- if (handle == conn->self_handle)
- {
- NODE_DEBUG (pres_node, "ignoring presence from ourselves on another "
- "resource");
- ret = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- goto OUT;
- }
-
- g_assert (handle != 0);
-
- child_node = lm_message_node_get_child (pres_node, "status");
- if (child_node)
- status_message = lm_message_node_get_value (child_node);
-
- switch (sub_type)
- {
- case LM_MESSAGE_SUB_TYPE_SUBSCRIBE:
- DEBUG ("making %s (handle %u) local pending on the publish channel",
- from, handle);
-
- tmp = tp_intset_new ();
- tp_intset_add (tmp, handle);
-
- list_handle = GABBLE_LIST_HANDLE_PUBLISH;
- chan = _gabble_roster_get_channel (roster, TP_HANDLE_TYPE_LIST,
- list_handle, NULL);
- tp_group_mixin_change_members ((GObject *)chan, status_message,
- NULL, NULL, tmp, NULL, 0, 0);
-
- tp_intset_destroy (tmp);
-
- ret = LM_HANDLER_RESULT_REMOVE_MESSAGE;
- break;
- case LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE:
- DEBUG ("removing %s (handle %u) from the publish channel",
- from, handle);
-
- tmp = tp_intset_new ();
- tp_intset_add (tmp, handle);
-
- list_handle = GABBLE_LIST_HANDLE_PUBLISH;
- chan = _gabble_roster_get_channel (roster, TP_HANDLE_TYPE_LIST,
- list_handle, NULL);
- changed = tp_group_mixin_change_members ((GObject *)chan,
- status_message, NULL, tmp, NULL, NULL, 0, 0);
-
- _gabble_roster_send_presence_ack (roster, from, sub_type, changed);
-
- tp_intset_destroy (tmp);
-
- ret = LM_HANDLER_RESULT_REMOVE_MESSAGE;
- break;
- case LM_MESSAGE_SUB_TYPE_SUBSCRIBED:
- DEBUG ("adding %s (handle %u) to the subscribe channel",
- from, handle);
-
- tmp = tp_intset_new ();
- tp_intset_add (tmp, handle);
-
- list_handle = GABBLE_LIST_HANDLE_SUBSCRIBE;
- chan = _gabble_roster_get_channel (roster, TP_HANDLE_TYPE_LIST,
- list_handle, NULL);
- changed = tp_group_mixin_change_members ((GObject *)chan,
- status_message, tmp, NULL, NULL, NULL, 0, 0);
-
- _gabble_roster_send_presence_ack (roster, from, sub_type, changed);
-
- tp_intset_destroy (tmp);
-
- ret = LM_HANDLER_RESULT_REMOVE_MESSAGE;
- break;
- case LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED:
- DEBUG ("removing %s (handle %u) from the subscribe channel",
- from, handle);
-
- tmp = tp_intset_new ();
- tp_intset_add (tmp, handle);
-
- list_handle = GABBLE_LIST_HANDLE_SUBSCRIBE;
- chan = _gabble_roster_get_channel (roster, TP_HANDLE_TYPE_LIST,
- list_handle, NULL);
- changed = tp_group_mixin_change_members ((GObject *)chan,
- status_message, NULL, tmp, NULL, NULL, 0, 0);
-
- _gabble_roster_send_presence_ack (roster, from, sub_type, changed);
-
- tp_intset_destroy (tmp);
-
- ret = LM_HANDLER_RESULT_REMOVE_MESSAGE;
- break;
- default:
- ret = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
-OUT:
- tp_handle_unref (contact_repo, handle);
- return ret;
-}
-
-static void
-gabble_roster_factory_iface_close_all (TpChannelFactoryIface *iface)
-{
- GabbleRoster *roster = GABBLE_ROSTER (iface);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
-
- DEBUG ("closing channels");
-
- if (priv->group_channels)
- {
- g_hash_table_destroy (priv->group_channels);
- priv->group_channels = NULL;
- }
-
- if (priv->list_channels)
- {
- g_hash_table_destroy (priv->list_channels);
- priv->list_channels = NULL;
- }
-}
-
-static void
-gabble_roster_factory_iface_connecting (TpChannelFactoryIface *iface)
-{
- GabbleRoster *roster = GABBLE_ROSTER (iface);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
-
- DEBUG ("adding callbacks");
-
- g_assert (priv->iq_cb == NULL);
- g_assert (priv->presence_cb == NULL);
-
- priv->iq_cb = lm_message_handler_new (gabble_roster_iq_cb,
- roster, NULL);
- lm_connection_register_message_handler (priv->conn->lmconn,
- priv->iq_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_NORMAL);
-
- priv->presence_cb = lm_message_handler_new (gabble_roster_presence_cb,
- roster, NULL);
- lm_connection_register_message_handler (priv->conn->lmconn,
- priv->presence_cb,
- LM_MESSAGE_TYPE_PRESENCE,
- LM_HANDLER_PRIORITY_LAST);
-}
-
-static void
-gabble_roster_factory_iface_connected (TpChannelFactoryIface *iface)
-{
- GabbleRoster *roster = GABBLE_ROSTER (iface);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- LmMessage *message;
-
- DEBUG ("requesting roster");
-
- message = _gabble_roster_message_new (roster, LM_MESSAGE_SUB_TYPE_GET, NULL);
-
- _gabble_connection_send (priv->conn, message, NULL);
-
- lm_message_unref (message);
-}
-
-static void
-gabble_roster_factory_iface_disconnected (TpChannelFactoryIface *iface)
-{
- GabbleRoster *roster = GABBLE_ROSTER (iface);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
-
- DEBUG ("removing callbacks");
-
- g_assert (priv->iq_cb != NULL);
- g_assert (priv->presence_cb != NULL);
-
- lm_connection_unregister_message_handler (priv->conn->lmconn,
- priv->iq_cb,
- LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->iq_cb);
- priv->iq_cb = NULL;
-
- lm_connection_unregister_message_handler (priv->conn->lmconn,
- priv->presence_cb,
- LM_MESSAGE_TYPE_PRESENCE);
- lm_message_handler_unref (priv->presence_cb);
- priv->presence_cb = NULL;
-}
-
-struct foreach_data {
- TpChannelFunc func;
- gpointer data;
-};
-
-static void
-_gabble_roster_factory_iface_foreach_one (gpointer key,
- gpointer value,
- gpointer data)
-{
- TpChannelIface *chan = TP_CHANNEL_IFACE (value);
- struct foreach_data *foreach = (struct foreach_data *) data;
-
- foreach->func (chan, foreach->data);
-}
-
-static void
-gabble_roster_factory_iface_foreach (TpChannelFactoryIface *iface,
- TpChannelFunc func,
- gpointer data)
-{
- GabbleRoster *roster = GABBLE_ROSTER (iface);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- struct foreach_data foreach;
-
- foreach.func = func;
- foreach.data = data;
-
- g_hash_table_foreach (priv->group_channels,
- _gabble_roster_factory_iface_foreach_one, &foreach);
- g_hash_table_foreach (priv->list_channels,
- _gabble_roster_factory_iface_foreach_one, &foreach);
-}
-
-static TpChannelFactoryRequestStatus
-gabble_roster_factory_iface_request (TpChannelFactoryIface *iface,
- const gchar *chan_type,
- TpHandleType handle_type,
- guint handle,
- gpointer request,
- TpChannelIface **ret,
- GError **error)
-{
- GabbleRoster *roster = GABBLE_ROSTER (iface);
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, handle_type);
- gboolean created;
-
- if (strcmp (chan_type, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
-
- if (handle_type != TP_HANDLE_TYPE_LIST &&
- handle_type != TP_HANDLE_TYPE_GROUP)
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
-
- if (!tp_handle_is_valid (handle_repo, handle, NULL))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
-
- /* disallow "deny" channels if we don't have google:roster support */
- if (handle == GABBLE_LIST_HANDLE_DENY &&
- handle_type == TP_HANDLE_TYPE_LIST &&
- !(priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
-
- if (priv->roster_received)
- {
- GabbleRosterChannel *chan;
- chan = _gabble_roster_get_channel (roster, handle_type, handle,
- &created);
- *ret = TP_CHANNEL_IFACE (chan);
- return created ? TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED
- : TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
- }
- else
- {
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_QUEUED;
- }
-}
-
-static void
-gabble_roster_factory_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *) g_iface;
-
- klass->close_all = gabble_roster_factory_iface_close_all;
- klass->connecting = gabble_roster_factory_iface_connecting;
- klass->connected = gabble_roster_factory_iface_connected;
- klass->disconnected = gabble_roster_factory_iface_disconnected;
- klass->foreach = gabble_roster_factory_iface_foreach;
- klass->request = gabble_roster_factory_iface_request;
-}
-
-GabbleRoster *
-gabble_roster_new (GabbleConnection *conn)
-{
- g_return_val_if_fail (conn != NULL, NULL);
-
- return g_object_new (GABBLE_TYPE_ROSTER,
- "connection", conn,
- NULL);
-}
-
-static GabbleRosterItemEdit *
-item_edit_new (void)
-{
- GabbleRosterItemEdit *self = g_slice_new0 (GabbleRosterItemEdit);
- self->new_subscription = GABBLE_ROSTER_SUBSCRIPTION_INVALID;
- self->new_google_type = GOOGLE_ITEM_TYPE_INVALID;
- return self;
-}
-
-static void
-item_edit_free (GabbleRosterItemEdit *edits)
-{
- if (!edits)
- return;
-
- if (edits->add_to_groups)
- tp_handle_set_destroy (edits->add_to_groups);
- if (edits->remove_from_groups)
- tp_handle_set_destroy (edits->remove_from_groups);
- g_free (edits->new_name);
- g_slice_free (GabbleRosterItemEdit, edits);
-}
-
-static LmHandlerResult roster_edited_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *roster_obj,
- gpointer user_data);
-
-/* Apply the unsent edits to the given roster item.
- *
- * \param roster The roster
- * \param contact The contact handle
- * \param item contact's roster item on roster
- */
-static void
-roster_item_apply_edits (GabbleRoster *roster,
- TpHandle contact,
- GabbleRosterItem *item)
-{
- gboolean altered = FALSE, ret;
- GabbleRosterItem edited_item;
- TpIntSet *intset;
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_GROUP);
- GabbleRosterItemEdit *edits = item->unsent_edits;
- LmMessage *message;
-
- DEBUG ("Applying edits to contact#%u", contact);
-
- g_return_if_fail (item->unsent_edits);
-
- memcpy (&edited_item, item, sizeof (GabbleRosterItem));
-
-#ifdef ENABLE_DEBUG
- if (DEBUGGING)
- {
- gchar *dump = _gabble_roster_item_dump (&edited_item);
- DEBUG ("Before, contact#%u: %s", contact, dump);
- g_free (dump);
- }
-#endif
-
- if (edits->new_subscription != GABBLE_ROSTER_SUBSCRIPTION_INVALID
- && edits->new_subscription != item->subscription)
- {
- DEBUG ("Changing subscription from %d to %d",
- item->subscription, edits->new_subscription);
- altered = TRUE;
- edited_item.subscription = edits->new_subscription;
- }
-
- if (edits->new_name != NULL && tp_strdiff (item->name, edits->new_name))
- {
- DEBUG ("Changing name from %s to %s", item->name, edits->new_name);
- altered = TRUE;
- edited_item.name = edits->new_name;
- }
-
- if (edits->new_google_type != GOOGLE_ITEM_TYPE_INVALID
- && edits->new_google_type != item->google_type)
- {
- DEBUG ("Changing Google type from %d to %d", item->google_type,
- edits->new_google_type);
- altered = TRUE;
- edited_item.google_type = edits->new_google_type;
- }
-
- if (edits->add_to_groups || edits->remove_from_groups)
- {
-#ifdef ENABLE_DEBUG
- if (DEBUGGING)
- {
- if (edits->add_to_groups)
- {
- GString *str = g_string_new ("Adding to groups: ");
- tp_intset_foreach (tp_handle_set_peek (edits->add_to_groups),
- _gabble_roster_item_dump_group, str);
- DEBUG("%s", g_string_free (str, FALSE));
- }
- else
- {
- DEBUG ("Not adding to any groups");
- }
- if (edits->remove_from_groups)
- {
- GString *str = g_string_new ("Removing from groups: ");
- tp_intset_foreach (tp_handle_set_peek (edits->remove_from_groups),
- _gabble_roster_item_dump_group, str);
- DEBUG("%s", g_string_free (str, FALSE));
- }
- else
- {
- DEBUG ("Not removing from any groups");
- }
- }
-#endif
- edited_item.groups = tp_handle_set_new (group_repo);
- intset = tp_handle_set_update (edited_item.groups,
- tp_handle_set_peek (item->groups));
- tp_intset_destroy (intset);
-
- if (edits->add_to_groups)
- {
- intset = tp_handle_set_update (edited_item.groups,
- tp_handle_set_peek (edits->add_to_groups));
- if (tp_intset_size (intset) > 0)
- {
- altered = TRUE;
- }
- tp_intset_destroy (intset);
- }
-
- if (edits->remove_from_groups)
- {
- intset = tp_handle_set_difference_update (edited_item.groups,
- tp_handle_set_peek (edits->remove_from_groups));
- if (tp_intset_size (intset) > 0)
- {
- altered = TRUE;
- }
- tp_intset_destroy (intset);
- }
- }
-
-#ifdef ENABLE_DEBUG
- if (DEBUGGING)
- {
- gchar *dump = _gabble_roster_item_dump (&edited_item);
- DEBUG ("After, contact#%u: %s", contact, dump);
- g_free (dump);
- }
-#endif
-
- if (!altered)
- {
- DEBUG ("Contact#%u not actually changed - nothing to do", contact);
- item_edit_free (item->unsent_edits);
- item->unsent_edits = NULL;
- return;
- }
-
- DEBUG ("Contact#%u did change, sending message", contact);
- message = _gabble_roster_item_to_message (roster, contact, NULL,
- &edited_item);
- ret = _gabble_connection_send_with_reply (priv->conn,
- message, roster_edited_cb, G_OBJECT (roster),
- GUINT_TO_POINTER(contact), NULL);
- if (ret)
- {
- /* assume everything will be OK */
- item_edit_free (item->unsent_edits);
- item->unsent_edits = NULL;
- }
- else
- {
- /* FIXME: somehow have another try at it later? leave the
- * edits in unsent_edits for this purpose, anyway
- */
- }
-
- if (edited_item.groups != item->groups)
- {
- tp_handle_set_destroy (edited_item.groups);
- }
-}
-
-/* Called when an edit to the roster item has either succeeded or failed. */
-static LmHandlerResult
-roster_edited_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *roster_obj,
- gpointer user_data)
-{
- GabbleRoster *roster = GABBLE_ROSTER (roster_obj);
- TpHandle contact = GPOINTER_TO_UINT(user_data);
- GabbleRosterItem *item = _gabble_roster_item_get (roster, contact);
-
- if (item->unsent_edits)
- {
- /* more edits have been queued since we sent this batch */
- roster_item_apply_edits (roster, contact, item);
- }
-
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-}
-
-GabbleRosterSubscription
-gabble_roster_handle_get_subscription (GabbleRoster *roster,
- TpHandle handle)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleRosterItem *item;
-
- g_return_val_if_fail (roster != NULL, GABBLE_ROSTER_SUBSCRIPTION_NONE);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster),
- GABBLE_ROSTER_SUBSCRIPTION_NONE);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- GABBLE_ROSTER_SUBSCRIPTION_NONE);
-
- item = g_hash_table_lookup (priv->items, GINT_TO_POINTER (handle));
-
- if (NULL == item)
- return GABBLE_ROSTER_SUBSCRIPTION_NONE;
-
- return item->subscription;
-}
-
-gboolean
-gabble_roster_handle_set_blocked (GabbleRoster *roster,
- TpHandle handle,
- gboolean blocked,
- GError **error)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleRosterItem *item;
- GoogleItemType orig_type;
- LmMessage *message;
- gboolean ret;
-
- g_return_val_if_fail (roster != NULL, FALSE);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
- g_return_val_if_fail (priv->conn->features &
- GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER, FALSE);
-
- item = _gabble_roster_item_get (roster, handle);
- orig_type = item->google_type;
-
- if (item->unsent_edits)
- {
- DEBUG ("queue edit to contact#%u - change subscription to blocked=%d",
- handle, blocked);
- /* an edit is pending - make the change afterwards and
- * assume it'll be OK
- */
- if (blocked)
- {
- item->unsent_edits->new_google_type = GOOGLE_ITEM_TYPE_BLOCKED;
- }
- else
- {
- item->unsent_edits->new_google_type = GOOGLE_ITEM_TYPE_NORMAL;
- }
- return TRUE;
- }
- else
- {
- item->unsent_edits = item_edit_new ();
- }
-
- if (blocked == (orig_type == GOOGLE_ITEM_TYPE_BLOCKED))
- return TRUE;
-
- /* temporarily set the desired block state and generate a message */
- if (blocked)
- item->google_type = GOOGLE_ITEM_TYPE_BLOCKED;
- else
- item->google_type = GOOGLE_ITEM_TYPE_NORMAL;
- message = _gabble_roster_item_to_message (roster, handle, NULL, NULL);
- item->google_type = orig_type;
-
- ret = _gabble_connection_send_with_reply (priv->conn,
- message, roster_edited_cb, G_OBJECT (roster),
- GUINT_TO_POINTER(handle), error);
-
- lm_message_unref (message);
-
- return ret;
-}
-
-gboolean
-gabble_roster_handle_has_entry (GabbleRoster *roster,
- TpHandle handle)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleRosterItem *item;
-
- g_return_val_if_fail (roster != NULL, FALSE);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
-
- item = g_hash_table_lookup (priv->items, GINT_TO_POINTER (handle));
-
- return (NULL != item);
-}
-
-const gchar *
-gabble_roster_handle_get_name (GabbleRoster *roster,
- TpHandle handle)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleRosterItem *item;
-
- g_return_val_if_fail (roster != NULL, NULL);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster), NULL);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- NULL);
-
- item = g_hash_table_lookup (priv->items, GINT_TO_POINTER (handle));
-
- if (NULL == item)
- return NULL;
-
- return item->name;
-}
-
-gboolean
-gabble_roster_handle_set_name (GabbleRoster *roster,
- TpHandle handle,
- const gchar *name,
- GError **error)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleRosterItem *item;
- LmMessage *message;
- LmMessageNode *item_node;
- gboolean ret;
-
- g_return_val_if_fail (roster != NULL, FALSE);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- item = _gabble_roster_item_get (roster, handle);
- g_return_val_if_fail (item != NULL, FALSE);
-
- if (item->unsent_edits)
- {
- DEBUG ("queue edit to contact#%u - change name to \"%s\"",
- handle, name);
- /* an edit is pending - make the change afterwards and
- * assume it'll be OK
- */
- g_free (item->unsent_edits->new_name);
- item->unsent_edits->new_name = g_strdup (name);
- return TRUE;
- }
- else
- {
- DEBUG ("immediate edit to contact#%u - change name to \"%s\"",
- handle, name);
- item->unsent_edits = item_edit_new ();
- }
-
- message = _gabble_roster_item_to_message (roster, handle, &item_node, NULL);
-
- lm_message_node_set_attribute (item_node, "name", name);
-
- ret = _gabble_connection_send_with_reply (priv->conn,
- message, roster_edited_cb, G_OBJECT (roster),
- GUINT_TO_POINTER(handle), error);
-
- lm_message_unref (message);
-
- return ret;
-}
-
-gboolean
-gabble_roster_handle_remove (GabbleRoster *roster,
- TpHandle handle,
- GError **error)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleRosterItem *item;
- GabbleRosterSubscription subscription;
- LmMessage *message;
- gboolean ret;
-
- g_return_val_if_fail (roster != NULL, FALSE);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
-
- item = _gabble_roster_item_get (roster, handle);
-
- if (item->unsent_edits)
- {
- DEBUG ("queue edit to contact#%u - change subscription to REMOVE",
- handle);
- /* an edit is pending - make the change afterwards and
- * assume it'll be OK
- */
- item->unsent_edits->new_subscription = GABBLE_ROSTER_SUBSCRIPTION_REMOVE;
- return TRUE;
- }
- else
- {
- DEBUG ("immediate edit to contact#%u - change subscription to REMOVE",
- handle);
- item->unsent_edits = item_edit_new ();
- }
-
- subscription = item->subscription;
- item->subscription = GABBLE_ROSTER_SUBSCRIPTION_REMOVE;
-
- message = _gabble_roster_item_to_message (roster, handle, NULL, NULL);
- ret = _gabble_connection_send_with_reply (priv->conn,
- message, roster_edited_cb, G_OBJECT (roster),
- GUINT_TO_POINTER(handle), error);
- lm_message_unref (message);
-
- item->subscription = subscription;
-
- return ret;
-}
-
-gboolean
-gabble_roster_handle_add (GabbleRoster *roster,
- TpHandle handle,
- GError **error)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleRosterItem *item;
- LmMessage *message;
- gboolean do_add = FALSE;
- gboolean ret;
-
- g_return_val_if_fail (roster != NULL, FALSE);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
-
- if (!gabble_roster_handle_has_entry (roster, handle))
- do_add = TRUE;
-
- item = _gabble_roster_item_get (roster, handle);
-
- if (item->google_type == GOOGLE_ITEM_TYPE_HIDDEN)
- do_add = TRUE;
-
- if (!do_add)
- return TRUE;
-
- if (item->unsent_edits)
- {
- DEBUG ("queue edit to contact#%u - change google type to NORMAL",
- handle);
- /* an edit is pending - make the change afterwards and
- * assume it'll be OK.
- */
- item->unsent_edits->new_google_type = GOOGLE_ITEM_TYPE_NORMAL;
- return TRUE;
- }
- else
- {
- DEBUG ("immediate edit to contact#%u - change google type to NORMAL",
- handle);
- if (item->google_type == GOOGLE_ITEM_TYPE_HIDDEN)
- item->google_type = GOOGLE_ITEM_TYPE_NORMAL;
- item->unsent_edits = item_edit_new ();
- }
-
- message = _gabble_roster_item_to_message (roster, handle, NULL, NULL);
- ret = _gabble_connection_send_with_reply (priv->conn,
- message, roster_edited_cb, G_OBJECT (roster),
- GUINT_TO_POINTER(handle), error);
- lm_message_unref (message);
-
- return ret;
-}
-
-gboolean
-gabble_roster_handle_add_to_group (GabbleRoster *roster,
- TpHandle handle,
- TpHandle group,
- GError **error)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_GROUP);
- GabbleRosterItem *item;
- LmMessage *message;
- gboolean ret;
-
- g_return_val_if_fail (roster != NULL, FALSE);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
- g_return_val_if_fail (tp_handle_is_valid (group_repo, group, NULL),
- FALSE);
-
- item = _gabble_roster_item_get (roster, handle);
-
- if (item->unsent_edits)
- {
- DEBUG ("queue edit to contact#%u - add to group#%u", handle, group);
- /* an edit is pending - make the change afterwards and
- * assume it'll be OK
- */
- if (!item->unsent_edits->add_to_groups)
- {
- item->unsent_edits->add_to_groups = tp_handle_set_new (group_repo);
- }
- tp_handle_set_add (item->unsent_edits->add_to_groups, group);
- if (item->unsent_edits->remove_from_groups)
- {
- tp_handle_set_remove (item->unsent_edits->remove_from_groups, group);
- }
- return TRUE;
- }
- else
- {
- DEBUG ("immediate edit to contact#%u - add to group#%u", handle, group);
- item->unsent_edits = item_edit_new ();
- }
-
- tp_handle_set_add (item->groups, group);
- message = _gabble_roster_item_to_message (roster, handle, NULL, NULL);
- NODE_DEBUG (message->node, "Roster item as message");
- tp_handle_set_remove (item->groups, group);
-
- ret = _gabble_connection_send_with_reply (priv->conn,
- message, roster_edited_cb, G_OBJECT (roster),
- GUINT_TO_POINTER(handle), error);
- lm_message_unref (message);
-
- return ret;
-}
-
-gboolean
-gabble_roster_handle_remove_from_group (GabbleRoster *roster,
- TpHandle handle,
- TpHandle group,
- GError **error)
-{
- GabbleRosterPrivate *priv = GABBLE_ROSTER_GET_PRIVATE (roster);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_CONTACT);
- TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->conn, TP_HANDLE_TYPE_GROUP);
- GabbleRosterItem *item;
- LmMessage *message;
- gboolean ret, was_in_group;
- const gchar *name;
-
- g_return_val_if_fail (roster != NULL, FALSE);
- g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE);
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
- g_return_val_if_fail (tp_handle_is_valid (group_repo, group, NULL),
- FALSE);
-
- item = _gabble_roster_item_get (roster, handle);
-
- if (item->unsent_edits)
- {
- DEBUG ("queue edit to contact#%u - remove from group#%u", handle, group);
- /* an edit is pending - make the change afterwards and
- * assume it'll be OK
- */
- if (!item->unsent_edits->remove_from_groups)
- {
- item->unsent_edits->remove_from_groups = tp_handle_set_new (
- group_repo);
- }
- tp_handle_set_add (item->unsent_edits->remove_from_groups, group);
- if (item->unsent_edits->add_to_groups)
- {
- tp_handle_set_remove (item->unsent_edits->add_to_groups, group);
- }
- return TRUE;
- }
- else
- {
- DEBUG ("immediate edit to contact#%u - remove from group#%u", handle,
- group);
- item->unsent_edits = item_edit_new ();
- }
-
- name = tp_handle_inspect (group_repo, group);
-
- /* temporarily remove the handle from the set (taking a reference),
- * make the message, and put it back afterwards
- */
- tp_handle_ref (group_repo, group);
- was_in_group = tp_handle_set_remove (item->groups, group);
- message = _gabble_roster_item_to_message (roster, handle, NULL, NULL);
- if (was_in_group)
- tp_handle_set_add (item->groups, group);
- tp_handle_unref (group_repo, group);
-
- ret = _gabble_connection_send_with_reply (priv->conn,
- message, roster_edited_cb, G_OBJECT (roster),
- GUINT_TO_POINTER(handle), error);
- lm_message_unref (message);
-
- return ret;
-}
diff --git a/src/roster.h b/src/roster.h
deleted file mode 100644
index a5749adf1..000000000
--- a/src/roster.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * roster.h - Headers for Gabble roster helper
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __ROSTER_H__
-#define __ROSTER_H__
-
-#include <glib-object.h>
-
-#include "gabble-types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleRosterClass GabbleRosterClass;
-
-GType gabble_roster_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_ROSTER \
- (gabble_roster_get_type ())
-#define GABBLE_ROSTER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_ROSTER, GabbleRoster))
-#define GABBLE_ROSTER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_ROSTER, GabbleRosterClass))
-#define GABBLE_IS_ROSTER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_ROSTER))
-#define GABBLE_IS_ROSTER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_ROSTER))
-#define GABBLE_ROSTER_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_ROSTER, GabbleRosterClass))
-
-struct _GabbleRosterClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleRoster {
- GObject parent;
- gpointer priv;
-};
-
-typedef enum
-{
- GABBLE_ROSTER_SUBSCRIPTION_NONE = 0,
- GABBLE_ROSTER_SUBSCRIPTION_FROM = 1 << 0,
- GABBLE_ROSTER_SUBSCRIPTION_TO = 1 << 1,
- GABBLE_ROSTER_SUBSCRIPTION_BOTH = GABBLE_ROSTER_SUBSCRIPTION_FROM |
- GABBLE_ROSTER_SUBSCRIPTION_TO,
- GABBLE_ROSTER_SUBSCRIPTION_REMOVE = 1 << 2,
- GABBLE_ROSTER_SUBSCRIPTION_INVALID = 1 << 3,
-} GabbleRosterSubscription;
-
-GabbleRoster *gabble_roster_new (GabbleConnection *);
-
-GabbleRosterSubscription gabble_roster_handle_get_subscription (GabbleRoster *,
- TpHandle);
-gboolean gabble_roster_handle_set_blocked (GabbleRoster *, TpHandle, gboolean,
- GError **);
-const gchar *gabble_roster_handle_get_name (GabbleRoster *, TpHandle);
-gboolean gabble_roster_handle_set_name (GabbleRoster *, TpHandle,
- const gchar *, GError **);
-gboolean gabble_roster_handle_remove (GabbleRoster *, TpHandle, GError **);
-gboolean gabble_roster_handle_add (GabbleRoster *, TpHandle, GError **);
-gboolean gabble_roster_handle_has_entry (GabbleRoster *, TpHandle);
-gboolean gabble_roster_handle_add_to_group (GabbleRoster *roster,
- TpHandle handle,
- TpHandle group,
- GError **error);
-gboolean gabble_roster_handle_remove_from_group (GabbleRoster *roster,
- TpHandle handle,
- TpHandle group,
- GError **error);
-
-G_END_DECLS
-
-#endif /* __ROSTER_H__ */
diff --git a/src/sha1/.git-darcs-dir b/src/sha1/.git-darcs-dir
deleted file mode 100644
index e69de29bb..000000000
--- a/src/sha1/.git-darcs-dir
+++ /dev/null
diff --git a/src/sha1/sha1.c b/src/sha1/sha1.c
deleted file mode 100644
index 513e4e0b7..000000000
--- a/src/sha1/sha1.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*-
- * Copyright (c) 2001-2003 Allan Saddi <allan@saddi.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $Id: sha1.c 680 2003-07-25 21:57:38Z asaddi $
- */
-
-/*
- * Define WORDS_BIGENDIAN if compiling on a big-endian architecture.
- *
- * Define SHA1_TEST to test the implementation using the NIST's
- * sample messages. The output should be:
- *
- * a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d
- * 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1
- * 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#include <string.h>
-
-#include "sha1.h"
-
-#ifndef lint
-static const char rcsid[] =
- "$Id: sha1.c 680 2003-07-25 21:57:38Z asaddi $";
-#endif /* !lint */
-
-#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
-
-#define F_0_19(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define F_20_39(x, y, z) ((x) ^ (y) ^ (z))
-#define F_40_59(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
-#define F_60_79(x, y, z) ((x) ^ (y) ^ (z))
-
-#define DO_ROUND(F, K) { \
- temp = ROTL(a, 5) + F(b, c, d) + e + *(W++) + K; \
- e = d; \
- d = c; \
- c = ROTL(b, 30); \
- b = a; \
- a = temp; \
-}
-
-#define K_0_19 0x5a827999L
-#define K_20_39 0x6ed9eba1L
-#define K_40_59 0x8f1bbcdcL
-#define K_60_79 0xca62c1d6L
-
-#ifndef RUNTIME_ENDIAN
-
-#ifdef WORDS_BIGENDIAN
-
-#define BYTESWAP(x) (x)
-#define BYTESWAP64(x) (x)
-
-#else /* WORDS_BIGENDIAN */
-
-#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
- (ROTL((x), 8) & 0x00ff00ffL))
-#define BYTESWAP64(x) _byteswap64(x)
-
-static inline uint64_t _byteswap64(uint64_t x)
-{
- uint32_t a = x >> 32;
- uint32_t b = (uint32_t) x;
- return ((uint64_t) BYTESWAP(b) << 32) | (uint64_t) BYTESWAP(a);
-}
-
-#endif /* WORDS_BIGENDIAN */
-
-#else /* !RUNTIME_ENDIAN */
-
-#define BYTESWAP(x) _byteswap(sc->littleEndian, x)
-#define BYTESWAP64(x) _byteswap64(sc->littleEndian, x)
-
-#define _BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
- (ROTL((x), 8) & 0x00ff00ffL))
-#define _BYTESWAP64(x) __byteswap64(x)
-
-static inline uint64_t __byteswap64(uint64_t x)
-{
- uint32_t a = x >> 32;
- uint32_t b = (uint32_t) x;
- return ((uint64_t) _BYTESWAP(b) << 32) | (uint64_t) _BYTESWAP(a);
-}
-
-static inline uint32_t _byteswap(int littleEndian, uint32_t x)
-{
- if (!littleEndian)
- return x;
- else
- return _BYTESWAP(x);
-}
-
-static inline uint64_t _byteswap64(int littleEndian, uint64_t x)
-{
- if (!littleEndian)
- return x;
- else
- return _BYTESWAP64(x);
-}
-
-static inline void setEndian(int *littleEndianp)
-{
- union {
- uint32_t w;
- uint8_t b[4];
- } endian;
-
- endian.w = 1L;
- *littleEndianp = endian.b[0] != 0;
-}
-
-#endif /* !RUNTIME_ENDIAN */
-
-static const uint8_t padding[64] = {
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-void
-SHA1Init (SHA1Context *sc)
-{
-#ifdef RUNTIME_ENDIAN
- setEndian (&sc->littleEndian);
-#endif /* RUNTIME_ENDIAN */
-
- sc->totalLength = 0LL;
- sc->hash[0] = 0x67452301L;
- sc->hash[1] = 0xefcdab89L;
- sc->hash[2] = 0x98badcfeL;
- sc->hash[3] = 0x10325476L;
- sc->hash[4] = 0xc3d2e1f0L;
- sc->bufferLength = 0L;
-}
-
-static void
-burnStack (int size)
-{
- char buf[128];
-
- memset (buf, 0, sizeof (buf));
- size -= sizeof (buf);
- if (size > 0)
- burnStack (size);
-}
-
-static void
-SHA1Guts (SHA1Context *sc, const uint32_t *cbuf)
-{
- uint32_t buf[80];
- uint32_t *W, *W3, *W8, *W14, *W16;
- uint32_t a, b, c, d, e, temp;
- int i;
-
- W = buf;
-
- for (i = 15; i >= 0; i--) {
- *(W++) = BYTESWAP(*cbuf);
- cbuf++;
- }
-
- W16 = &buf[0];
- W14 = &buf[2];
- W8 = &buf[8];
- W3 = &buf[13];
-
- for (i = 63; i >= 0; i--) {
- *W = *(W3++) ^ *(W8++) ^ *(W14++) ^ *(W16++);
- *W = ROTL(*W, 1);
- W++;
- }
-
- a = sc->hash[0];
- b = sc->hash[1];
- c = sc->hash[2];
- d = sc->hash[3];
- e = sc->hash[4];
-
- W = buf;
-
-#ifndef SHA1_UNROLL
-#define SHA1_UNROLL 20
-#endif /* !SHA1_UNROLL */
-
-#if SHA1_UNROLL == 1
- for (i = 19; i >= 0; i--)
- DO_ROUND(F_0_19, K_0_19);
-
- for (i = 19; i >= 0; i--)
- DO_ROUND(F_20_39, K_20_39);
-
- for (i = 19; i >= 0; i--)
- DO_ROUND(F_40_59, K_40_59);
-
- for (i = 19; i >= 0; i--)
- DO_ROUND(F_60_79, K_60_79);
-#elif SHA1_UNROLL == 2
- for (i = 9; i >= 0; i--) {
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- }
-
- for (i = 9; i >= 0; i--) {
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- }
-
- for (i = 9; i >= 0; i--) {
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- }
-
- for (i = 9; i >= 0; i--) {
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- }
-#elif SHA1_UNROLL == 4
- for (i = 4; i >= 0; i--) {
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- }
-
- for (i = 4; i >= 0; i--) {
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- }
-
- for (i = 4; i >= 0; i--) {
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- }
-
- for (i = 4; i >= 0; i--) {
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- }
-#elif SHA1_UNROLL == 5
- for (i = 3; i >= 0; i--) {
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- }
-
- for (i = 3; i >= 0; i--) {
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- }
-
- for (i = 3; i >= 0; i--) {
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- }
-
- for (i = 3; i >= 0; i--) {
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- }
-#elif SHA1_UNROLL == 10
- for (i = 1; i >= 0; i--) {
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- }
-
- for (i = 1; i >= 0; i--) {
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- }
-
- for (i = 1; i >= 0; i--) {
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- }
-
- for (i = 1; i >= 0; i--) {
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- }
-#elif SHA1_UNROLL == 20
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
- DO_ROUND(F_0_19, K_0_19);
-
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
- DO_ROUND(F_20_39, K_20_39);
-
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
- DO_ROUND(F_40_59, K_40_59);
-
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
- DO_ROUND(F_60_79, K_60_79);
-#else /* SHA1_UNROLL */
-#error SHA1_UNROLL must be 1, 2, 4, 5, 10 or 20!
-#endif
-
- sc->hash[0] += a;
- sc->hash[1] += b;
- sc->hash[2] += c;
- sc->hash[3] += d;
- sc->hash[4] += e;
-}
-
-void
-SHA1Update (SHA1Context *sc, const void *vdata, uint32_t len)
-{
- const uint8_t *data = vdata;
- uint32_t bufferBytesLeft;
- uint32_t bytesToCopy;
- int needBurn = 0;
-
-#ifdef SHA1_FAST_COPY
- if (sc->bufferLength) {
- bufferBytesLeft = 64L - sc->bufferLength;
-
- bytesToCopy = bufferBytesLeft;
- if (bytesToCopy > len)
- bytesToCopy = len;
-
- memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
-
- sc->totalLength += bytesToCopy * 8L;
-
- sc->bufferLength += bytesToCopy;
- data += bytesToCopy;
- len -= bytesToCopy;
-
- if (sc->bufferLength == 64L) {
- SHA1Guts (sc, sc->buffer.words);
- needBurn = 1;
- sc->bufferLength = 0L;
- }
- }
-
- while (len > 63) {
- sc->totalLength += 512L;
-
- SHA1Guts (sc, data);
- needBurn = 1;
-
- data += 64L;
- len -= 64L;
- }
-
- if (len) {
- memcpy (&sc->buffer.bytes[sc->bufferLength], data, len);
-
- sc->totalLength += len * 8L;
-
- sc->bufferLength += len;
- }
-#else /* SHA1_FAST_COPY */
- while (len) {
- bufferBytesLeft = 64L - sc->bufferLength;
-
- bytesToCopy = bufferBytesLeft;
- if (bytesToCopy > len)
- bytesToCopy = len;
-
- memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
-
- sc->totalLength += bytesToCopy * 8L;
-
- sc->bufferLength += bytesToCopy;
- data += bytesToCopy;
- len -= bytesToCopy;
-
- if (sc->bufferLength == 64L) {
- SHA1Guts (sc, sc->buffer.words);
- needBurn = 1;
- sc->bufferLength = 0L;
- }
- }
-#endif /* SHA1_FAST_COPY */
-
- if (needBurn)
- burnStack (sizeof (uint32_t[86]) + sizeof (uint32_t *[5]) + sizeof (int));
-}
-
-void
-SHA1Final (SHA1Context *sc, uint8_t hash[SHA1_HASH_SIZE])
-{
- uint32_t bytesToPad;
- uint64_t lengthPad;
- int i;
-
- bytesToPad = 120L - sc->bufferLength;
- if (bytesToPad > 64L)
- bytesToPad -= 64L;
-
- lengthPad = BYTESWAP64(sc->totalLength);
-
- SHA1Update (sc, padding, bytesToPad);
- SHA1Update (sc, &lengthPad, 8L);
-
- if (hash) {
- for (i = 0; i < SHA1_HASH_WORDS; i++) {
-#ifdef SHA1_FAST_COPY
- *((uint32_t *) hash) = BYTESWAP(sc->hash[i]);
-#else /* SHA1_FAST_COPY */
- hash[0] = (uint8_t) (sc->hash[i] >> 24);
- hash[1] = (uint8_t) (sc->hash[i] >> 16);
- hash[2] = (uint8_t) (sc->hash[i] >> 8);
- hash[3] = (uint8_t) sc->hash[i];
-#endif /* SHA1_FAST_COPY */
- hash += 4;
- }
- }
-}
-
-#ifdef SHA1_TEST
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-int
-main (int argc, char *argv[])
-{
- SHA1Context foo;
- uint8_t hash[SHA1_HASH_SIZE];
- char buf[1000];
- int i;
-
- SHA1Init (&foo);
- SHA1Update (&foo, "abc", 3);
- SHA1Final (&foo, hash);
-
- for (i = 0; i < SHA1_HASH_SIZE;) {
- printf ("%02x", hash[i++]);
- if (!(i % 4))
- printf (" ");
- }
- printf ("\n");
-
- SHA1Init (&foo);
- SHA1Update (&foo,
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- 56);
- SHA1Final (&foo, hash);
-
- for (i = 0; i < SHA1_HASH_SIZE;) {
- printf ("%02x", hash[i++]);
- if (!(i % 4))
- printf (" ");
- }
- printf ("\n");
-
- SHA1Init (&foo);
- memset (buf, 'a', sizeof (buf));
- for (i = 0; i < 1000; i++)
- SHA1Update (&foo, buf, sizeof (buf));
- SHA1Final (&foo, hash);
-
- for (i = 0; i < SHA1_HASH_SIZE;) {
- printf ("%02x", hash[i++]);
- if (!(i % 4))
- printf (" ");
- }
- printf ("\n");
-
- exit (0);
-}
-
-#endif /* SHA1_TEST */
diff --git a/src/sha1/sha1.h b/src/sha1/sha1.h
deleted file mode 100644
index 7a6beb7f5..000000000
--- a/src/sha1/sha1.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * Copyright (c) 2001-2003 Allan Saddi <allan@saddi.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $Id: sha1.h 347 2003-02-23 22:11:49Z asaddi $
- */
-
-#ifndef _SHA1_H
-#define _SHA1_H
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#define SHA1_HASH_SIZE 20
-
-/* Hash size in 32-bit words */
-#define SHA1_HASH_WORDS 5
-
-struct _SHA1Context {
- uint64_t totalLength;
- uint32_t hash[SHA1_HASH_WORDS];
- uint32_t bufferLength;
- union {
- uint32_t words[16];
- uint8_t bytes[64];
- } buffer;
-#ifdef RUNTIME_ENDIAN
- int littleEndian;
-#endif /* RUNTIME_ENDIAN */
-};
-
-typedef struct _SHA1Context SHA1Context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void SHA1Init (SHA1Context *sc);
-void SHA1Update (SHA1Context *sc, const void *data, uint32_t len);
-void SHA1Final (SHA1Context *sc, uint8_t hash[SHA1_HASH_SIZE]);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SHA1_H */
diff --git a/src/text-mixin.c b/src/text-mixin.c
deleted file mode 100644
index 730628bb9..000000000
--- a/src/text-mixin.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * text-mixin.c - Gabble-specific bits for TpTextMixin
- * Copyright (C) 2006, 2007 Collabora Ltd.
- * Copyright (C) 2006, 2007 Nokia Corporation
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- * @author Robert McQueen <robert.mcqueen@collabora.co.uk>
- * @author Senko Rasic <senko@senko.net>
- *
- * 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
- */
-
-#define _GNU_SOURCE /* Needed for strptime (_XOPEN_SOURCE can also be used). */
-
-#include "text-mixin.h"
-
-#include <loudmouth/loudmouth.h>
-#include <dbus/dbus-glib.h>
-#include <string.h>
-#include <time.h>
-
-#include <telepathy-glib/text-mixin.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_IM
-
-#include "debug.h"
-#include "gabble-connection.h"
-#include "namespaces.h"
-#include "roster.h"
-#include "util.h"
-
-/**
- * gabble_text_mixin_init:
- * @obj_cls: The class of the implementation that uses this mixin
- * @offset: The offset of the GabbleTextMixinClass within the class structure
- * @send_nick: %TRUE if the user's nick should be included in messages
- * sent through this channel
- *
- * Initialize the text mixin. Should be called instead of #tp_text_mixin_init
- * from the implementation's init function.
- */
-void
-gabble_text_mixin_init (GObject *obj,
- glong offset,
- TpHandleRepoIface *contacts_repo,
- gboolean send_nick)
-{
- GabbleTextMixin *mixin;
-
- tp_text_mixin_init (obj, offset, contacts_repo);
-
- mixin = GABBLE_TEXT_MIXIN (obj);
-
- mixin->send_nick = send_nick;
-}
-
-/**
- * gabble_text_mixin_send
- *
- * Indirectly, implements D-Bus method Send
- * on interface org.freedesktop.Telepathy.Channel.Type.Text.
- *
- * @param type The Telepathy message type
- * @param subtype The Loudmouth message subtype
- * @param state The Telepathy chat state type
- * @param recipient The recipient's JID
- * @param text The text of the message (if NULL, the message won't have body)
- * @param conn The Connection
- * @param emit_signal If true, emit Sent; if false, assume we'll get an
- * echo of the message and will emit Sent at that point
- * @param error The GError
- */
-gboolean
-gabble_text_mixin_send (GObject *obj,
- guint type,
- guint subtype,
- gint state,
- const char *recipient,
- const gchar *text,
- GabbleConnection *conn,
- gboolean emit_signal,
- GError **error)
-{
- GabbleTextMixin *mixin = GABBLE_TEXT_MIXIN (obj);
- LmMessage *msg;
- LmMessageNode *node;
- gboolean result;
- time_t timestamp;
-
- if (type >= NUM_TP_CHANNEL_TEXT_MESSAGE_TYPES)
- {
- DEBUG ("invalid message type %u", type);
-
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "invalid message type: %u", type);
-
- return FALSE;
- }
-
- if (!subtype)
- {
- switch (type)
- {
- case TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
- case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
- subtype = LM_MESSAGE_SUB_TYPE_CHAT;
- break;
- case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
- subtype = LM_MESSAGE_SUB_TYPE_NORMAL;
- break;
- }
- }
-
- msg = lm_message_new_with_sub_type (recipient, LM_MESSAGE_TYPE_MESSAGE,
- subtype);
-
- if (mixin->send_nick)
- {
- lm_message_node_add_own_nick (msg->node, conn);
- mixin->send_nick = FALSE;
- }
-
- if (text != NULL)
- {
- if (type == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION)
- {
- gchar *tmp;
- tmp = g_strconcat ("/me ", text, NULL);
- lm_message_node_add_child (msg->node, "body", tmp);
- g_free (tmp);
- }
- else
- {
- lm_message_node_add_child (msg->node, "body", text);
- }
- }
-
- node = NULL;
-
- switch (state)
- {
- case TP_CHANNEL_CHAT_STATE_GONE:
- node = lm_message_node_add_child (msg->node, "gone", NULL);
- break;
- case TP_CHANNEL_CHAT_STATE_INACTIVE:
- node = lm_message_node_add_child (msg->node, "inactive", NULL);
- break;
- case TP_CHANNEL_CHAT_STATE_ACTIVE:
- node = lm_message_node_add_child (msg->node, "active", NULL);
- break;
- case TP_CHANNEL_CHAT_STATE_PAUSED:
- node = lm_message_node_add_child (msg->node, "paused", NULL);
- break;
- case TP_CHANNEL_CHAT_STATE_COMPOSING:
- node = lm_message_node_add_child (msg->node, "composing", NULL);
- break;
- }
-
- if (node != NULL)
- {
- lm_message_node_set_attributes (node, "xmlns", NS_CHAT_STATES, NULL);
- }
-
- result = _gabble_connection_send (conn, msg, error);
- lm_message_unref (msg);
-
- if (!result)
- {
- return FALSE;
- }
-
- if (emit_signal && text != NULL)
- {
- timestamp = time (NULL);
-
- tp_svc_channel_type_text_emit_sent (obj, timestamp, type, text);
- }
- return TRUE;
-}
-
-gboolean
-gabble_text_mixin_parse_incoming_message (LmMessage *message,
- const gchar **from,
- time_t *stamp,
- TpChannelTextMessageType *msgtype,
- const gchar **body_ret,
- gint *state,
- TpChannelTextSendError *send_error)
-{
- const gchar *type, *body;
- LmMessageNode *node;
-
- *send_error = TP_CHANNEL_SEND_NO_ERROR;
-
- if (lm_message_get_sub_type (message) == LM_MESSAGE_SUB_TYPE_ERROR)
- {
- LmMessageNode *error_node;
-
- error_node = lm_message_node_get_child (message->node, "error");
- if (error_node)
- {
- GabbleXmppError err = gabble_xmpp_error_from_node (error_node);
- DEBUG ("got xmpp error: %s: %s", gabble_xmpp_error_string (err),
- gabble_xmpp_error_description (err));
-
- /* these are based on descriptions of errors, and some testing */
- switch (err)
- {
- case XMPP_ERROR_SERVICE_UNAVAILABLE:
- case XMPP_ERROR_RECIPIENT_UNAVAILABLE:
- *send_error = TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE;
- break;
-
- case XMPP_ERROR_ITEM_NOT_FOUND:
- case XMPP_ERROR_JID_MALFORMED:
- case XMPP_ERROR_REMOTE_SERVER_TIMEOUT:
- *send_error = TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT;
- break;
-
- case XMPP_ERROR_FORBIDDEN:
- *send_error = TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED;
- break;
-
- case XMPP_ERROR_RESOURCE_CONSTRAINT:
- *send_error = TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG;
- break;
-
- case XMPP_ERROR_FEATURE_NOT_IMPLEMENTED:
- *send_error = TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED;
- break;
-
- default:
- *send_error = TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN;
- }
- }
- else
- {
- *send_error = TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN;
- }
- }
-
- *from = lm_message_node_get_attribute (message->node, "from");
- if (*from == NULL)
- {
- NODE_DEBUG (message->node, "got a message without a from field");
- return FALSE;
- }
-
- type = lm_message_node_get_attribute (message->node, "type");
-
- /*
- * Parse timestamp of delayed messages. For non-delayed, it's
- * 0 and the channel code should set the current timestamp.
- */
- *stamp = 0;
-
- node = lm_message_node_get_child_with_namespace (message->node, "x",
- NS_X_DELAY);
- if (node != NULL)
- {
- const gchar *stamp_str, *p;
- struct tm stamp_tm = { 0, };
-
- stamp_str = lm_message_node_get_attribute (node, "stamp");
- if (stamp_str != NULL)
- {
- p = strptime (stamp_str, "%Y%m%dT%T", &stamp_tm);
- if (p == NULL || *p != '\0')
- {
- g_warning ("%s: malformed date string '%s' for jabber:x:delay",
- G_STRFUNC, stamp_str);
- }
- else
- {
- *stamp = timegm (&stamp_tm);
- }
- }
- }
-
- /*
- * Parse body if it exists.
- */
- node = lm_message_node_get_child (message->node, "body");
-
- if (node)
- {
- body = lm_message_node_get_value (node);
- }
- else
- {
- body = NULL;
- }
-
- /* Messages starting with /me are ACTION messages, and the /me should be
- * removed. type="chat" messages are NORMAL. everything else is
- * something that doesn't necessarily expect a reply or ongoing
- * conversation ("normal") or has been auto-sent, so we make it NOTICE in
- * all other cases. */
-
- *msgtype = TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
- *body_ret = body;
-
- if (body != NULL)
- {
- if (0 == strncmp (body, "/me ", 4))
- {
- *msgtype = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
- *body_ret = body + 4;
- }
- else if (type != NULL && (0 == strcmp (type, "chat") ||
- 0 == strcmp (type, "groupchat")))
- {
- *msgtype = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
- *body_ret = body;
- }
- }
-
- /*
- * Parse chat state if it exists.
- */
-
- node = lm_message_node_get_child_with_namespace (message->node, "active",
- NS_CHAT_STATES);
- if (node)
- {
- *state = TP_CHANNEL_CHAT_STATE_ACTIVE;
- return TRUE;
- }
-
- node = lm_message_node_get_child_with_namespace (message->node, "composing",
- NS_CHAT_STATES);
- if (node)
- {
- *state = TP_CHANNEL_CHAT_STATE_COMPOSING;
- return TRUE;
- }
-
- node = lm_message_node_get_child_with_namespace (message->node, "inactive",
- NS_CHAT_STATES);
- if (node)
- {
- *state = TP_CHANNEL_CHAT_STATE_INACTIVE;
- return TRUE;
- }
-
- node = lm_message_node_get_child_with_namespace (message->node, "paused",
- NS_CHAT_STATES);
- if (node)
- {
- *state = TP_CHANNEL_CHAT_STATE_PAUSED;
- return TRUE;
- }
-
- node = lm_message_node_get_child_with_namespace (message->node, "gone",
- NS_CHAT_STATES);
- if (node)
- {
- *state = TP_CHANNEL_CHAT_STATE_GONE;
- return TRUE;
- }
-
- *state = -1;
-
- return TRUE;
-}
diff --git a/src/text-mixin.h b/src/text-mixin.h
deleted file mode 100644
index 336982fee..000000000
--- a/src/text-mixin.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * text-mixin.h - Header for GabbleTextMixin
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_TEXT_MIXIN_H__
-#define __GABBLE_TEXT_MIXIN_H__
-
-#include <telepathy-glib/text-mixin.h>
-#include "util.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleTextMixinClass GabbleTextMixinClass;
-struct _GabbleTextMixinClass
-{
- TpTextMixinClass parent_class;
-};
-
-typedef struct _GabbleTextMixin GabbleTextMixin;
-struct _GabbleTextMixin
-{
- TpTextMixin parent;
- gboolean send_nick;
-};
-
-#define GABBLE_TEXT_MIXIN_CLASS(o) \
- ((GabbleTextMixinClass *) tp_mixin_offset_cast (o,\
- TP_TEXT_MIXIN_CLASS_OFFSET (o)))
-#define GABBLE_TEXT_MIXIN(o) \
- ((GabbleTextMixin *) tp_mixin_offset_cast (o, TP_TEXT_MIXIN_OFFSET (o)))
-
-#define TP_CHANNEL_SEND_NO_ERROR ((TpChannelTextSendError)-1)
-
-void gabble_text_mixin_init (GObject *obj, glong offset,
- TpHandleRepoIface *contacts_repo, gboolean send_nick);
-
-gboolean gabble_text_mixin_send (GObject *obj, guint type, guint subtype,
- gint state, const char *recipient, const gchar *text,
- GabbleConnection *conn, gboolean emit_signal, GError **error);
-
-gboolean gabble_text_mixin_parse_incoming_message (LmMessage *message,
- const gchar **from, time_t *stamp, TpChannelTextMessageType *msgtype,
- const gchar **body_ret, gint *state, TpChannelTextSendError *send_error);
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_TEXT_MIXIN_H__ */
-
diff --git a/src/util.c b/src/util.c
deleted file mode 100644
index ec5c4b537..000000000
--- a/src/util.c
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * util.c - Source for Gabble utility functions
- * Copyright (C) 2006-2007 Collabora Ltd.
- * Copyright (C) 2006-2007 Nokia Corporation
- * @author Robert McQueen <robert.mcqueen@collabora.co.uk>
- * @author Simon McVittie <simon.mcvittie@collabora.co.uk>
- *
- * 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
- */
-
-#include "config.h"
-
-#include "util.h"
-
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <telepathy-glib/handle-repo-dynamic.c>
-
-#include "sha1/sha1.h"
-#include "namespaces.h"
-#include "gabble-connection.h"
-
-#define DEBUG_FLAG GABBLE_DEBUG_JID
-#include "debug.h"
-
-gchar *
-sha1_hex (const gchar *bytes, guint len)
-{
- SHA1Context sc;
- uint8_t hash[SHA1_HASH_SIZE];
- gchar *hex_hash = g_malloc (SHA1_HASH_SIZE*2 + 1);
- int i;
-
- SHA1Init (&sc);
- SHA1Update (&sc, bytes, len);
- SHA1Final (&sc, hash);
-
- for (i = 0; i < SHA1_HASH_SIZE; i++)
- {
- sprintf (hex_hash + 2 * i, "%02x", (unsigned int) hash[i]);
- }
-
- return hex_hash;
-}
-
-static void
-lm_message_node_add_nick (LmMessageNode *node, const gchar *nick)
-{
- LmMessageNode *nick_node;
-
- nick_node = lm_message_node_add_child (node, "nick", nick);
- lm_message_node_set_attribute (nick_node, "xmlns", NS_NICK);
-}
-
-void
-lm_message_node_add_own_nick (LmMessageNode *node,
- GabbleConnection *connection)
-{
- gchar *nick;
- GabbleConnectionAliasSource source;
- TpBaseConnection *base = (TpBaseConnection *)connection;
-
- source = _gabble_connection_get_cached_alias (connection,
- base->self_handle, &nick);
-
- if (source > GABBLE_CONNECTION_ALIAS_FROM_JID)
- lm_message_node_add_nick (node, nick);
-
- g_free (nick);
-}
-
-void
-lm_message_node_unlink (LmMessageNode *orphan)
-{
- if (orphan->parent && orphan == orphan->parent->children)
- orphan->parent->children = orphan->next;
- if (orphan->prev)
- orphan->prev->next = orphan->next;
- if (orphan->next)
- orphan->next->prev = orphan->prev;
-}
-
-void
-lm_message_node_steal_children (LmMessageNode *snatcher,
- LmMessageNode *mum)
-{
- LmMessageNode *baby;
-
- g_return_if_fail (snatcher->children == NULL);
-
- if (mum->children == NULL)
- return;
-
- snatcher->children = mum->children;
- mum->children = NULL;
-
- for (baby = snatcher->children;
- baby != NULL;
- baby = baby->next)
- baby->parent = snatcher;
-}
-
-gboolean
-lm_message_node_has_namespace (LmMessageNode *node,
- const gchar *ns,
- const gchar *tag)
-{
- gchar *attribute = NULL;
- const gchar *node_ns;
- gboolean ret;
-
- if (tag != NULL)
- attribute = g_strconcat ("xmlns:", tag, NULL);
-
- node_ns = lm_message_node_get_attribute (node,
- tag != NULL ? attribute : "xmlns");
-
- ret = !tp_strdiff (node_ns, ns);
-
- g_free (attribute);
-
- return ret;
-}
-
-LmMessageNode *
-lm_message_node_get_child_with_namespace (LmMessageNode *node,
- const gchar *name,
- const gchar *ns)
-{
- LmMessageNode *tmp;
-
- for (tmp = node->children;
- tmp != NULL;
- tmp = tmp->next)
- {
- gchar *tag = NULL;
- gboolean found;
-
- if (tp_strdiff (tmp->name, name))
- {
- const gchar *suffix;
-
- suffix = strchr (tmp->name, ':');
-
- if (suffix == NULL)
- continue;
- else
- suffix++;
-
- if (tp_strdiff (suffix, name))
- continue;
-
- tag = g_strndup (tmp->name, suffix - tmp->name - 1);
- }
-
- found = lm_message_node_has_namespace (tmp, ns, tag);
-
- g_free (tag);
-
- if (found)
- return tmp;
- }
-
- return NULL;
-}
-
-/* note: these are only used internally for readability, not part of the API
- */
-enum {
- BUILD_END = '\0',
- BUILD_ATTRIBUTE = '@',
- BUILD_CHILD = '(',
- BUILD_CHILD_END = ')',
- BUILD_POINTER = '*',
-};
-
-/**
- * lm_message_build:
- *
- * Build an LmMessageNode from a list of arguments employing an
- * S-expression-like notation. Example:
- *
- * lm_message_build ("bob@jabber.org", LM_MESSAGE_TYPE_IQ,
- * '(', 'query', 'lala',
- * '@', 'xmlns', 'http://jabber.org/protocol/foo',
- * ')',
- * NULL);
- *
- * --> <iq to="bob@jabber.org">
- * <query xmlns="http://jabber.org/protocol/foo">lala</query>
- * </iq>
- */
-G_GNUC_NULL_TERMINATED
-LmMessage *
-lm_message_build (const gchar *to, LmMessageType type, guint spec, ...)
-{
- LmMessage *msg;
- va_list ap;
- GSList *stack = NULL;
- guint arg = spec;
-
- msg = lm_message_new (to, type);
- stack = g_slist_prepend (stack, msg->node);
-
- va_start (ap, spec);
-
- while (arg != BUILD_END)
- {
- switch (arg)
- {
- case BUILD_END:
- goto END;
-
- case BUILD_ATTRIBUTE:
- {
- gchar *key = va_arg (ap, gchar *);
- gchar *value = va_arg (ap, gchar *);
-
- g_return_val_if_fail (key != NULL, NULL);
- g_return_val_if_fail (value != NULL, NULL);
- lm_message_node_set_attribute (stack->data, key, value);
- }
- break;
-
- case BUILD_CHILD:
- {
- gchar *name = va_arg (ap, gchar *);
- gchar *value = va_arg (ap, gchar *);
- LmMessageNode *child;
-
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (value != NULL, NULL);
- child = lm_message_node_add_child (stack->data, name, value);
- stack = g_slist_prepend (stack, child);
- }
- break;
-
- case BUILD_CHILD_END:
- {
- GSList *tmp;
-
- tmp = stack;
- stack = stack->next;
- tmp->next = NULL;
- g_slist_free (tmp);
- }
- break;
-
- case BUILD_POINTER:
- {
- LmMessageNode **node = va_arg (ap, LmMessageNode **);
-
- g_return_val_if_fail (node != NULL, NULL);
- *node = stack->data;
- }
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- /* Note that we pull out an int-sized value here, whereas our sentinel,
- * NULL, is pointer-sized. However, sizeof (void *) should always be >=
- * sizeof (uint), so this shouldn't cause a problem.
- */
- arg = va_arg (ap, guint);
- }
-
- va_end (ap);
-
-END:
- g_slist_free (stack);
-
- return msg;
-}
-
-/**
- * gabble_decode_jid
- *
- * Parses a JID which may be one of the following forms:
- * server
- * server/resource
- * username@server
- * username@server/resource
- * room@service/nick
- * and sets the caller's username_room, server_service and resource_nick
- * pointers to the username/room, server/service and resource/nick parts
- * respectively, if available in the provided JID. The caller may set any of
- * the pointers to NULL if they are not interested in a certain component.
- *
- * The returned values may be NULL or zero-length if a component was either
- * not present or zero-length respectively in the given JID. The username/room
- * and server/service are lower-cased because the Jabber protocol treats them
- * case-insensitively.
- */
-void
-gabble_decode_jid (const gchar *jid,
- gchar **username_room,
- gchar **server_service,
- gchar **resource_nick)
-{
- char *tmp_jid, *tmp_username, *tmp_server, *tmp_resource;
-
- g_assert (jid != NULL);
-
- if (username_room != NULL)
- *username_room = NULL;
-
- if (server_service != NULL)
- *server_service = NULL;
-
- if (resource_nick != NULL)
- *resource_nick = NULL;
-
- /* take a local copy so we don't modify the caller's string */
- tmp_jid = g_strdup (jid);
-
- /* find an @ in username, truncate username to that length, and point
- * 'server' to the byte afterwards */
- tmp_server = strchr (tmp_jid, '@');
- if (tmp_server)
- {
- tmp_username = tmp_jid;
-
- *tmp_server = '\0';
- tmp_server++;
-
- /* store the username if the user provided a pointer */
- if (username_room != NULL)
- *username_room = g_utf8_strdown (tmp_username, -1);
- }
- else
- {
- tmp_username = NULL;
- tmp_server = tmp_jid;
- }
-
- /* if we have a server, find a / in it, truncate it to that length, and point
- * 'resource' to the byte afterwards. otherwise, do the same to username to
- * find any resource there. */
- tmp_resource = strchr (tmp_server, '/');
- if (tmp_resource)
- {
- *tmp_resource = '\0';
- tmp_resource++;
-
- /* store the resource if the user provided a pointer */
- if (resource_nick != NULL)
- *resource_nick = g_strdup (tmp_resource);
- }
-
- /* the server must be stored after the resource, in case we truncated a
- * resource from it */
- if (server_service != NULL)
- *server_service = g_utf8_strdown (tmp_server, -1);
-
- /* free our working copy */
- g_free (tmp_jid);
-}
-
-#define INVALID_ARGUMENT(e, f, ...) \
- G_STMT_START { \
- DEBUG (f, ##__VA_ARGS__); \
- g_set_error (e, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, f, ##__VA_ARGS__);\
- } G_STMT_END
-
-gchar *
-gabble_normalize_room (TpHandleRepoIface *repo,
- const gchar *jid,
- gpointer context,
- GError **error)
-{
- char *at = strchr (jid, '@');
- char *slash = strchr (jid, '/');
-
- /* there'd better be an @ somewhere after the first character */
- if (at == NULL)
- {
- INVALID_ARGUMENT (error,
- "invalid room JID %s: does not contain '@'", jid);
- return NULL;
- }
- if (at == jid)
- {
- INVALID_ARGUMENT (error,
- "invalid room JID %s: room name before '@' may not be empty", jid);
- return NULL;
- }
-
- /* room names can't contain the nick part */
- if (slash != NULL)
- {
- INVALID_ARGUMENT (error,
- "invalid room JID %s: contains nickname part after '/' too", jid);
- return NULL;
- }
-
- /* the room and service parts are both case-insensitive, so lowercase
- * them both; gabble_decode_jid is overkill here
- */
- return g_utf8_strdown (jid, -1);
-}
-
-gchar *
-gabble_remove_resource (const gchar *jid)
-{
- char *slash = strchr (jid, '/');
- gchar *buf;
-
- if (slash == NULL)
- return g_strdup (jid);
-
- /* The user and domain parts can't contain '/', assuming it's valid */
- buf = g_malloc (slash - jid + 1);
- strncpy (buf, jid, slash - jid);
- buf[slash - jid] = '\0';
-
- return buf;
-}
-
-gchar *
-gabble_normalize_contact (TpHandleRepoIface *repo,
- const gchar *jid,
- gpointer context,
- GError **error)
-{
- guint mode = GPOINTER_TO_UINT (context);
- gchar *username = NULL, *server = NULL, *resource = NULL;
- gchar *ret = NULL;
-
- gabble_decode_jid (jid, &username, &server, &resource);
-
- if (!username || !server || !username[0] || !server[0])
- {
- INVALID_ARGUMENT (error,
- "jid %s has invalid username or server", jid);
- goto OUT;
- }
-
- if (mode == GABBLE_JID_ROOM_MEMBER && resource == NULL)
- {
- INVALID_ARGUMENT (error,
- "jid %s can't be a room member - it has no resource", jid);
- goto OUT;
- }
-
- if (mode != GABBLE_JID_GLOBAL && resource != NULL)
- {
- ret = g_strdup_printf ("%s@%s/%s", username, server, resource);
-
- if (mode == GABBLE_JID_ROOM_MEMBER
- || (repo != NULL
- && tp_dynamic_handle_repo_lookup_exact (repo, ret)))
- {
- /* either we know from context that it's a room member, or we
- * already saw that contact in a room. Use ret as our answer
- */
- goto OUT;
- }
- else
- {
- g_free (ret);
- }
- }
-
- /* if we get here, we suspect it's a global JID, either because the context
- * says it is, or because the context isn't sure and we haven't seen it in
- * use as a room member
- */
- ret = g_strdup_printf ("%s@%s", username, server);
-
-OUT:
- g_free (username);
- g_free (server);
- g_free (resource);
- return ret;
-}
diff --git a/src/util.h b/src/util.h
deleted file mode 100644
index efd8fe958..000000000
--- a/src/util.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * util.h - Headers for Gabble utility functions
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- * @author Robert McQueen <robert.mcqueen@collabora.co.uk>
- *
- * 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
- */
-
-#ifndef __GABBLE_UTIL_H__
-#define __GABBLE_UTIL_H__
-
-#include <glib.h>
-#include <telepathy-glib/handle-repo.h>
-#include <telepathy-glib/util.h>
-#include <loudmouth/loudmouth.h>
-
-#include "gabble-types.h"
-
-gchar *sha1_hex (const gchar *bytes, guint len);
-void lm_message_node_add_own_nick (LmMessageNode *node,
- GabbleConnection *conn);
-void lm_message_node_unlink (LmMessageNode *orphan);
-void lm_message_node_steal_children (LmMessageNode *snatcher,
- LmMessageNode *mum);
-gboolean lm_message_node_has_namespace (LmMessageNode *node, const gchar *ns,
- const gchar *tag);
-LmMessageNode *lm_message_node_get_child_with_namespace (LmMessageNode *node,
- const gchar *name, const gchar *ns);
-G_GNUC_NULL_TERMINATED LmMessage *lm_message_build (const gchar *to,
- LmMessageType type, guint spec, ...);
-
-/* format: a@b/c */
-void gabble_decode_jid (const gchar *jid, gchar **a, gchar **b, gchar **c);
-
-gchar *gabble_remove_resource (const gchar *jid);
-gchar *gabble_normalize_contact (TpHandleRepoIface *repo, const gchar *jid,
- gpointer userdata, GError **error);
-gchar *gabble_normalize_room (TpHandleRepoIface *repo, const gchar *jid,
- gpointer context, GError **error);
-
-#endif /* __GABBLE_UTIL_H__ */
diff --git a/src/vcard-manager.c b/src/vcard-manager.c
deleted file mode 100644
index 837ff6ffd..000000000
--- a/src/vcard-manager.c
+++ /dev/null
@@ -1,1470 +0,0 @@
-/*
- * vcard-manager.c - Source for Gabble vCard lookup helper
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#include "vcard-manager.h"
-
-#include <telepathy-glib/dbus.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_VCARD
-
-#include "base64.h"
-#include "debug.h"
-#include "gabble-connection.h"
-#include "namespaces.h"
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/heap.h>
-#include "time.h"
-#include "util.h"
-
-#define DEFAULT_REQUEST_TIMEOUT 20000
-#define VCARD_CACHE_ENTRY_TTL 30
-#define VCARD_PIPELINE_SIZE 3
-
-static const gchar *NO_ALIAS = "none";
-
-/* signal enum */
-enum
-{
- NICKNAME_UPDATE,
- GOT_SELF_INITIAL_AVATAR,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* Properties */
-enum
-{
- PROP_CONNECTION = 1,
- PROP_HAVE_SELF_AVATAR,
- LAST_PROPERTY
-};
-
-G_DEFINE_TYPE(GabbleVCardManager, gabble_vcard_manager, G_TYPE_OBJECT);
-
-typedef struct _GabbleVCardCacheEntry GabbleVCardCacheEntry;
-
-typedef struct _GabbleVCardManagerPrivate GabbleVCardManagerPrivate;
-struct _GabbleVCardManagerPrivate
-{
- GabbleConnection *connection;
- GSList *requests;
- GSList *request_pipeline;
- GSList *reqs_in_flight;
-
- GHashTable *cache;
- TpHeap *timed_cache;
- guint cache_timer;
-
- gboolean have_self_avatar;
- gboolean dispose_has_run;
-};
-
-struct _GabbleVCardManagerRequest
-{
- GabbleVCardManager *manager;
- guint timer_id;
- guint timeout;
-
- TpHandle handle;
- gchar **edit_args;
-
- GabbleVCardManagerCb callback;
- gpointer user_data;
- GObject *bound_object;
-};
-
-struct _GabbleVCardCacheEntry
-{
- GabbleVCardManager *manager;
- TpHandle handle;
- GabbleVCardManagerRequest *request;
- GSList *pending_requests;
- time_t received;
- LmMessage *message;
-};
-
-typedef struct _GabbleVCardPipelineItem GabbleVCardPipelineItem;
-struct _GabbleVCardPipelineItem {
- GabbleVCardManagerRequest *request;
- LmMessage *msg;
- gpointer callback;
-};
-
-GQuark
-gabble_vcard_manager_error_quark (void)
-{
- static GQuark quark = 0;
- if (!quark)
- quark = g_quark_from_static_string ("gabble-vcard-manager-error");
- return quark;
-}
-
-GQuark
-gabble_vcard_manager_cache_quark (void)
-{
- static GQuark quark = 0;
- if (!quark)
- quark = g_quark_from_static_string ("gabble-vcard-manager-cache");
- return quark;
-}
-
-#define GABBLE_VCARD_MANAGER_GET_PRIVATE(o)\
- ((GabbleVCardManagerPrivate*)((o)->priv));
-
-static void cache_entry_free (void *data);
-static gint cache_entry_compare (gconstpointer a, gconstpointer b);
-
-static void
-gabble_vcard_manager_init (GabbleVCardManager *obj)
-{
- GabbleVCardManagerPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_VCARD_MANAGER,
- GabbleVCardManagerPrivate);
- obj->priv = priv;
-
- priv->cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- cache_entry_free);
- /* no destructor here - the hash table is responsible for freeing it */
- priv->timed_cache = tp_heap_new (cache_entry_compare, NULL);
-}
-
-static void gabble_vcard_manager_set_property (GObject *object,
- guint property_id, const GValue *value, GParamSpec *pspec);
-static void gabble_vcard_manager_get_property (GObject *object,
- guint property_id, GValue *value, GParamSpec *pspec);
-static void gabble_vcard_manager_dispose (GObject *object);
-static void gabble_vcard_manager_finalize (GObject *object);
-
-static void
-gabble_vcard_manager_class_init (GabbleVCardManagerClass *gabble_vcard_manager_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_vcard_manager_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_vcard_manager_class,
- sizeof (GabbleVCardManagerPrivate));
-
- object_class->get_property = gabble_vcard_manager_get_property;
- object_class->set_property = gabble_vcard_manager_set_property;
-
- object_class->dispose = gabble_vcard_manager_dispose;
- object_class->finalize = gabble_vcard_manager_finalize;
-
- param_spec = g_param_spec_object ("connection", "GabbleConnection object",
- "Gabble connection object that owns this "
- "vCard lookup helper object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_boolean ("have-self-avatar", "Have our own avatar",
- "TRUE after the local user's own vCard "
- "has been retrieved in order to get"
- "their initial avatar.",
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_HAVE_SELF_AVATAR,
- param_spec);
-
- /* signal definitions */
-
- signals[NICKNAME_UPDATE] =
- g_signal_new ("nickname-update",
- G_TYPE_FROM_CLASS (gabble_vcard_manager_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE, 1, G_TYPE_UINT);
-
- signals[GOT_SELF_INITIAL_AVATAR] =
- g_signal_new ("got-self-initial-avatar",
- G_TYPE_FROM_CLASS (gabble_vcard_manager_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
-}
-
-static void
-gabble_vcard_manager_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleVCardManager *chan = GABBLE_VCARD_MANAGER (object);
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->connection);
- break;
- case PROP_HAVE_SELF_AVATAR:
- g_value_set_boolean (value, priv->have_self_avatar);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_vcard_manager_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleVCardManager *chan = GABBLE_VCARD_MANAGER (object);
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (chan);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->connection = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void delete_request (GabbleVCardManagerRequest *request);
-static void cancel_request (GabbleVCardManagerRequest *request);
-
-static gint
-cache_entry_compare (gconstpointer a, gconstpointer b)
-{
- const GabbleVCardCacheEntry *foo = a;
- const GabbleVCardCacheEntry *bar = b;
- return foo->received - bar->received;
-}
-
-static void
-cache_entry_free (void *data)
-{
- GabbleVCardManagerPrivate *priv;
- TpHandleRepoIface *contact_repo;
- GabbleVCardCacheEntry *entry = (GabbleVCardCacheEntry *) data;
-
- g_assert (entry != NULL);
-
- while (entry->pending_requests)
- {
- cancel_request (entry->pending_requests->data);
- }
-
- if (entry->request)
- {
- delete_request (entry->request);
- }
-
- g_slist_free (entry->pending_requests);
-
- if (entry->message)
- lm_message_unref (entry->message);
-
- priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (entry->manager);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->connection, TP_HANDLE_TYPE_CONTACT);
-
- tp_handle_unref (contact_repo, entry->handle);
-
- g_slice_free (GabbleVCardCacheEntry, entry);
-}
-
-static GabbleVCardCacheEntry *
-cache_entry_get (GabbleVCardManager *manager, TpHandle handle)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->connection, TP_HANDLE_TYPE_CONTACT);
- GabbleVCardCacheEntry *entry;
-
- entry = g_hash_table_lookup (priv->cache, GUINT_TO_POINTER (handle));
- if (entry)
- return entry;
-
- entry = g_slice_new0 (GabbleVCardCacheEntry);
-
- entry->manager = manager;
- entry->handle = handle;
- tp_handle_ref (contact_repo, handle);
- g_hash_table_insert (priv->cache, GUINT_TO_POINTER (handle), entry);
-
- return entry;
-}
-
-static gboolean
-cache_entry_timeout (gpointer data)
-{
- GabbleVCardManager *manager = data;
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- GabbleVCardCacheEntry *entry;
-
- time_t now = time (NULL);
-
- while (NULL != (entry = tp_heap_peek_first (priv->timed_cache)))
- {
- if ((entry->received + VCARD_CACHE_ENTRY_TTL) > now)
- break;
-
- /* shouldn't have in-flight request nor any pending requests */
- g_assert (entry->request == NULL);
-
- gabble_vcard_manager_invalidate_cache (manager, entry->handle);
- }
-
- priv->cache_timer = 0;
-
- if (entry)
- {
- priv->cache_timer = g_timeout_add (
- 1000 * (entry->received + VCARD_CACHE_ENTRY_TTL - time (NULL)),
- cache_entry_timeout, manager);
- }
-
- return FALSE;
-}
-
-
-static void
-cache_entry_attempt_to_free (GabbleVCardManager *manager, TpHandle handle)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- GabbleVCardCacheEntry *entry = g_hash_table_lookup (priv->cache,
- GUINT_TO_POINTER (handle));
-
- if (!entry || entry->message || entry->pending_requests)
- return;
-
- tp_heap_remove (priv->timed_cache, entry);
-
- g_hash_table_remove (priv->cache, GUINT_TO_POINTER (entry->handle));
-}
-
-void
-gabble_vcard_manager_invalidate_cache (GabbleVCardManager *manager,
- TpHandle handle)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- GabbleVCardCacheEntry *entry = g_hash_table_lookup (priv->cache,
- GUINT_TO_POINTER (handle));
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->connection, TP_HANDLE_TYPE_CONTACT);
-
- g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL));
-
- if (!entry)
- return;
-
- tp_heap_remove (priv->timed_cache, entry);
-
- if (entry->message)
- {
- lm_message_unref (entry->message);
- entry->message = NULL;
- }
-
- cache_entry_attempt_to_free (manager, handle);
-}
-
-static void
-cache_entry_fill (GabbleVCardManager *manager, LmMessage *msg, TpHandle handle)
-{
- GabbleVCardCacheEntry *entry = cache_entry_get (manager, handle);
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
-
- /* the upstream request should be finished by now */
- g_assert (entry->request == NULL);
-
- g_assert (entry->message == NULL);
- entry->message = lm_message_new ("", LM_MESSAGE_TYPE_IQ);
- lm_message_node_steal_children (entry->message->node, msg->node);
- entry->received = time (NULL);
- tp_heap_add (priv->timed_cache, entry);
-
- if (priv->cache_timer == 0)
- {
- GabbleVCardCacheEntry *first = tp_heap_peek_first (priv->timed_cache);
- priv->cache_timer = g_timeout_add ((first->received +
- VCARD_CACHE_ENTRY_TTL - time (NULL)) * 1000, cache_entry_timeout,
- manager);
- }
-}
-
-static void
-complete_pending_requests (GabbleVCardManager *manager,
- TpHandle handle,
- GError *err)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- GabbleVCardCacheEntry *entry =
- g_hash_table_lookup (priv->cache, GUINT_TO_POINTER (handle));
- LmMessageNode *vcard_node = NULL;
-
- g_assert (entry);
-
- /* the upstream request should be finished by now */
- g_assert (entry->request == NULL);
-
- if (entry->message)
- vcard_node = lm_message_node_get_child (entry->message->node, "vCard");
-
- while (entry->pending_requests)
- {
- GabbleVCardManagerRequest *req = entry->pending_requests->data;
-
- if (req->callback)
- {
- DEBUG ("invoking callback %p for pending request %p (handle %u)",
- req->callback, req, handle);
- (req->callback)(req->manager, req, handle,
- vcard_node, err, req->user_data);
- }
- delete_request (req);
- }
-
- cache_entry_attempt_to_free (manager, handle);
-
- if (err)
- g_error_free (err);
-}
-
-static void
-complete_one_request (GabbleVCardManagerRequest *request,
- gpointer data,
- GError *err)
-{
- GabbleVCardManager *manager = request->manager;
- TpHandle handle = request->handle;
-
- if (request->callback)
- {
- DEBUG ("invoking callback %p for request %p (handle %u)",
- request->callback, request, handle);
- (request->callback)(manager, request, handle,
- data, err, request->user_data);
- }
- delete_request (request);
-
- cache_entry_attempt_to_free (manager, handle);
-
- if (err)
- g_error_free (err);
-}
-
-void
-gabble_vcard_manager_dispose (GObject *object)
-{
- GabbleVCardManager *self = GABBLE_VCARD_MANAGER (object);
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self);
- DBusGProxy *bus_proxy;
- bus_proxy = tp_get_bus_proxy ();
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- if (priv->cache_timer)
- g_source_remove (priv->cache_timer);
-
- /* cancel request removes the element from the list after cancelling */
- while (priv->requests)
- cancel_request (priv->requests->data);
-
- tp_heap_destroy (priv->timed_cache);
- g_hash_table_destroy (priv->cache);
-
- /* should've been cleared by delete_request already */
- g_assert (priv->reqs_in_flight == NULL);
- g_assert (priv->request_pipeline == NULL);
-
- if (G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->dispose (object);
-}
-
-void
-gabble_vcard_manager_finalize (GObject *object)
-{
- G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->finalize (object);
-}
-
-/* Called during connection. */
-static void
-initial_request_cb (GabbleVCardManager *self,
- GabbleVCardManagerRequest *request,
- TpHandle handle,
- LmMessageNode *vcard,
- GError *error,
- gpointer user_data)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self);
- gchar *alias = (gchar *)user_data;
- LmMessageNode *node;
-
- if (!vcard)
- {
- g_free (alias);
- return;
- }
-
- /* We now have our own avatar (or lack thereof) so can answer
- * GetAvatarTokens([self_handle])
- */
- priv->have_self_avatar = TRUE;
-
- /* try to patch the alias, if one was provided */
- if (alias)
- {
- DEBUG ("Patching our vCard to have alias \"%s\"", alias);
- node = lm_message_node_get_child (vcard, "NICKNAME");
- if (node)
- {
- lm_message_node_set_value (node, alias);
- }
- else
- {
- lm_message_node_add_child (vcard, "NICKNAME", alias);
- }
-
- /* basically ignore error here, there's not a lot we can do about it */
- gabble_vcard_manager_replace (self, vcard, 0, NULL, NULL,
- G_OBJECT (priv->connection), NULL);
- }
-
- /* Do we have an avatar already? If so, the presence cache ought to be
- * told (anyone else's avatar SHA-1 we'd get from their presence,
- * but unless we have another XEP-0153 resource connected, we never
- * see our own presence)
- */
- node = lm_message_node_get_child (vcard, "PHOTO");
- if (node)
- {
- DEBUG ("Our vCard has a PHOTO %p", node);
- LmMessageNode *binval = lm_message_node_get_child (node, "BINVAL");
-
- if (binval)
- {
- const gchar *binval_value;
-
- binval_value = lm_message_node_get_value (binval);
-
- if (binval_value)
- {
- gchar *sha1;
- GString *avatar;
-
- avatar = base64_decode (binval_value);
-
- if (avatar)
- {
- sha1 = sha1_hex (avatar->str, avatar->len);
- DEBUG ("Successfully decoded PHOTO.BINVAL, SHA-1 %s", sha1);
- g_signal_emit (self, signals[GOT_SELF_INITIAL_AVATAR], 0,
- sha1);
- g_free (sha1);
- }
- else
- {
- DEBUG ("Avatar is in garbled Base64, ignoring it:\n%s",
- lm_message_node_get_value (binval));
- }
-
- g_string_free (avatar, TRUE);
- }
- }
- }
-
- g_free (alias);
-}
-
-static void
-status_changed_cb (GObject *object,
- guint status,
- guint reason,
- gpointer user_data)
-{
- GabbleVCardManager *self = GABBLE_VCARD_MANAGER (user_data);
- GabbleConnection *conn = GABBLE_CONNECTION (object);
- TpBaseConnection *base = (TpBaseConnection *)conn;
-
- if (status == TP_CONNECTION_STATUS_CONNECTED)
- {
- gchar *alias;
- GabbleConnectionAliasSource alias_src;
-
- /* if we have a better alias, patch it into our vCard on the server */
- alias_src = _gabble_connection_get_cached_alias (conn,
- base->self_handle,
- &alias);
- if (alias_src < GABBLE_CONNECTION_ALIAS_FROM_VCARD)
- {
- /* this alias isn't reliable enough to want to patch it in */
- g_free (alias);
- alias = NULL;
- }
-
- /* fetch our vCard, and possibly patch it to include our new alias */
- gabble_vcard_manager_request (self, base->self_handle, 0,
- initial_request_cb, alias,
- G_OBJECT (conn), NULL);
- }
-}
-
-/**
- * gabble_vcard_manager_new:
- * @conn: The #GabbleConnection to use for vCard lookup
- *
- * Creates an object to use for Jabber vCard lookup (JEP 0054).
- * There should be one of these per connection
- */
-GabbleVCardManager *
-gabble_vcard_manager_new (GabbleConnection *conn)
-{
- GabbleVCardManager *self;
-
- g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL);
-
- self = GABBLE_VCARD_MANAGER (g_object_new (GABBLE_TYPE_VCARD_MANAGER,
- "connection", conn, NULL));
- g_signal_connect (conn, "status-changed",
- G_CALLBACK (status_changed_cb), self);
- return self;
-}
-
-static void notify_delete_request (gpointer data, GObject *obj);
-static void vcard_pipeline_go (GabbleVCardManager *manager);
-
-static void
-delete_request (GabbleVCardManagerRequest *request)
-{
- GabbleVCardManager *manager = request->manager;
- GabbleVCardManagerPrivate *priv;
- TpHandleRepoIface *contact_repo;
- GabbleVCardCacheEntry *entry;
- GSList *l;
-
- DEBUG ("Discarding request %p", request);
-
- g_assert (NULL != request);
- g_assert (GABBLE_IS_VCARD_MANAGER (manager));
-
- priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->connection, TP_HANDLE_TYPE_CONTACT);
-
- g_assert (NULL != g_slist_find (priv->requests, request));
-
- priv->requests = g_slist_remove (priv->requests, request);
-
- for (l = priv->request_pipeline; l; l = g_slist_next (l))
- {
- GabbleVCardPipelineItem *item = l->data;
- if (item->request == request)
- {
- priv->request_pipeline = g_slist_remove (priv->request_pipeline,
- item);
- lm_message_unref (item->msg);
- g_free (item);
- break;
- }
- }
-
- if (g_slist_find (priv->reqs_in_flight, request))
- {
- priv->reqs_in_flight = g_slist_remove (priv->reqs_in_flight, request);
- vcard_pipeline_go (manager);
- }
-
- if (NULL != request->bound_object)
- {
- g_object_weak_unref (request->bound_object, notify_delete_request,
- request);
- }
-
- if (0 != request->timer_id)
- {
- g_source_remove (request->timer_id);
- }
-
- tp_handle_unref (contact_repo, request->handle);
-
- entry = g_hash_table_lookup (priv->cache,
- GUINT_TO_POINTER (request->handle));
- if (entry)
- {
- if (request == entry->request)
- {
- entry->request = NULL;
- }
- else
- {
- entry->pending_requests = g_slist_remove (entry->pending_requests,
- request);
- }
- }
-
- g_strfreev (request->edit_args);
-
- g_slice_free (GabbleVCardManagerRequest, request);
-}
-
-static gboolean
-timeout_request (gpointer data)
-{
- GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest*) data;
- GError *err /* doesn't need initializing */;
- g_return_val_if_fail (data != NULL, FALSE);
-
- err = g_error_new (GABBLE_VCARD_MANAGER_ERROR,
- GABBLE_VCARD_MANAGER_ERROR_TIMEOUT, "Request timed out");
- DEBUG ("Request %p timed out, notifying callback %p",
- request, request->callback);
-
- request->timer_id = 0;
- complete_one_request (request, NULL, err);
- return FALSE;
-}
-
-static void
-cancel_request (GabbleVCardManagerRequest *request)
-{
- GError *err = g_error_new (GABBLE_VCARD_MANAGER_ERROR,
- GABBLE_VCARD_MANAGER_ERROR_CANCELLED, "Request cancelled");
-
- g_assert (request != NULL);
-
- DEBUG ("Request %p cancelled, notifying callback %p",
- request, request->callback);
-
- complete_one_request (request, NULL, err);
-}
-
-static gchar *
-extract_nickname (LmMessageNode *vcard_node)
-{
- LmMessageNode *node;
- const gchar *nick;
- gchar **bits;
- gchar *ret;
-
- node = lm_message_node_get_child (vcard_node, "NICKNAME");
-
- if (node == NULL)
- return NULL;
-
- nick = lm_message_node_get_value (node);
-
- /* nick is comma-separated, we want the first one. rule out corner cases of
- * the entire string or the first value being empty before we g_strsplit */
- if (nick == NULL || *nick == '\0' || *nick == ',')
- return NULL;
-
- bits = g_strsplit (nick, ",", 2);
-
- ret = g_strdup (bits[0]);
-
- g_strfreev (bits);
-
- return ret;
-}
-
-static void
-observe_vcard (GabbleConnection *conn,
- GabbleVCardManager *manager,
- TpHandle handle,
- LmMessageNode *vcard_node)
-{
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)conn, TP_HANDLE_TYPE_CONTACT);
- const gchar *field = "<NICKNAME>";
- gchar *alias;
- const gchar *old_alias;
-
- alias = extract_nickname (vcard_node);
-
- if (alias == NULL)
- {
- LmMessageNode *fn_node = lm_message_node_get_child (vcard_node, "FN");
-
- if (fn_node != NULL)
- {
- const gchar *fn = lm_message_node_get_value (fn_node);
-
- if (fn != NULL && *fn != '\0')
- {
- field = "<FN>";
- alias = g_strdup (fn);
- }
- }
- }
-
- old_alias = gabble_vcard_manager_get_cached_alias (manager, handle);
-
- if (!tp_strdiff (alias, old_alias))
- {
-#ifdef ENABLE_DEBUG
- if (alias != NULL)
- DEBUG ("no change to vCard alias \"%s\" for handle %u", alias, handle);
- else
- DEBUG ("still no vCard alias for handle %u", handle);
-#endif
-
- g_free (alias);
- return;
- }
-
- if (alias != NULL)
- {
- DEBUG ("got vCard alias \"%s\" for handle %u from %s", alias,
- handle, field);
-
- /* takes ownership of alias */
- tp_handle_set_qdata (contact_repo, handle,
- gabble_vcard_manager_cache_quark (), alias, g_free);
- }
- else
- {
- DEBUG ("got no vCard alias for handle %u", handle);
-
- tp_handle_set_qdata (contact_repo, handle,
- gabble_vcard_manager_cache_quark (), (gchar *) NO_ALIAS, NULL);
- }
-
- g_signal_emit (G_OBJECT (manager), signals[NICKNAME_UPDATE], 0, handle);
-}
-
-static LmHandlerResult
-replace_reply_cb (GabbleConnection *conn, LmMessage *sent_msg,
- LmMessage *reply_msg, GObject *object, gpointer user_data)
-{
- GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest*) user_data;
- GabbleVCardManager *manager = GABBLE_VCARD_MANAGER (object);
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)conn, TP_HANDLE_TYPE_CONTACT);
- GError *err = NULL;
-
- g_assert (request);
-
- DEBUG ("Replace request got a reply: conn@%p, sent_msg@%p, reply_msg@%p, "
- "bound object@%p, request@%p", conn, sent_msg, reply_msg, object,
- user_data);
-
- if (!g_slist_find (priv->requests, request))
- {
- DEBUG ("I don't care about that request any more");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- g_assert (tp_handle_is_valid (contact_repo, request->handle, NULL));
-
- if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
- {
- LmMessageNode *error_node;
-
- error_node = lm_message_node_get_child (reply_msg->node, "error");
- if (error_node)
- {
- err = gabble_xmpp_error_to_g_error (
- gabble_xmpp_error_from_node (error_node));
- }
-
- if (err == NULL)
- {
- err = g_error_new (GABBLE_VCARD_MANAGER_ERROR,
- GABBLE_VCARD_MANAGER_ERROR_UNKNOWN,
- "an unknown error occurred");
- }
- }
-
- DEBUG ("Request %p %s, notifying callback %p", request,
- err ? "failed" : "succeeded", request->callback);
-
- complete_one_request (request, sent_msg, err);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static GabbleVCardManagerRequest *request_send (GabbleVCardManagerRequest *,
- LmMessageNode *replacement, const gchar *jid, GError **error);
-
-static LmHandlerResult
-request_reply_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *object,
- gpointer user_data)
-{
- GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest*) user_data;
- GabbleVCardManager *manager = GABBLE_VCARD_MANAGER (object);
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)conn, TP_HANDLE_TYPE_CONTACT);
- LmMessageNode *vcard_node = NULL;
- GError *err = NULL;
-
- g_assert (request);
-
- DEBUG ("Fetch request got a reply: conn@%p, sent_msg@%p, reply_msg@%p, "
- "bound object@%p, request@%p", conn, sent_msg, reply_msg, object,
- user_data);
-
- if (!g_slist_find (priv->requests, request))
- {
- DEBUG ("I don't care about that request any more");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- g_assert (tp_handle_is_valid (contact_repo, request->handle, NULL));
-
- if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
- {
- LmMessageNode *error_node;
-
- vcard_node = NULL;
-
- error_node = lm_message_node_get_child (reply_msg->node, "error");
- if (error_node)
- {
- err = gabble_xmpp_error_to_g_error (
- gabble_xmpp_error_from_node (error_node));
- }
-
- if (err == NULL)
- {
- err = g_error_new (GABBLE_VCARD_MANAGER_ERROR,
- GABBLE_VCARD_MANAGER_ERROR_UNKNOWN,
- "an unknown error occurred");
- }
- }
- else
- {
- vcard_node = lm_message_node_get_child (reply_msg->node, "vCard");
-
- if (NULL == vcard_node)
- {
- DEBUG ("successful lookup response contained no <vCard> node, "
- "creating an empty one");
-
- vcard_node = lm_message_node_add_child (reply_msg->node, "vCard",
- NULL);
- lm_message_node_set_attribute (vcard_node, "xmlns", NS_VCARD_TEMP);
- }
-
- if (!request->edit_args)
- {
- observe_vcard (conn, manager, request->handle, vcard_node);
- }
- /* else we'll observe the vcard after editing it if we intend
- * to modify it */
- }
-
- if (vcard_node && request->edit_args)
- {
- gchar **ptr;
- for (ptr = request->edit_args; *ptr; ptr++)
- {
- gchar *key = *ptr;
- gchar *value = *(++ptr);
- LmMessageNode *node;
-
- if (!value)
- {
- /* oops, someone passed in an odd number of args. */
- g_assert_not_reached ();
- break;
- }
-
- node = lm_message_node_get_child (vcard_node, key);
- if (node)
- {
- lm_message_node_set_value (node, value);
- }
- else
- {
- node = lm_message_node_add_child (vcard_node, key, value);
- }
- }
-
- observe_vcard (conn, manager, request->handle, vcard_node);
-
- /* XXX: Manually remove the request from the list of requests in flight,
- * so that it's not in there twice when we send it a second time. The
- * correct fix is to remove it from reqs_in_flight as soon as we get the
- * result IQ.
- */
- priv->reqs_in_flight = g_slist_remove (priv->reqs_in_flight, request);
-
- request_send (request, vcard_node, NULL, &err);
-
- if (err)
- {
- complete_one_request (request, NULL, err);
- }
- else
- {
- DEBUG ("Request %p fetch succeeded", request);
- }
- }
- else
- {
- GabbleVCardCacheEntry *entry = g_hash_table_lookup (priv->cache,
- GUINT_TO_POINTER (request->handle));
-
- if (entry)
- {
- DEBUG ("entry == %p, entry->request == %p, request == %p",
- entry, entry->request, request);
- g_assert (entry->request == request);
-
- entry->request = NULL;
- cache_entry_fill (manager, reply_msg, request->handle);
- complete_pending_requests (manager, request->handle, err);
- delete_request (request);
- }
- else
- {
- complete_one_request (request, vcard_node, err);
- }
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-vcard_pipeline_send_next_request (GabbleVCardManager *manager)
-{
- GError *error = NULL;
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
-
- if (priv->request_pipeline == NULL)
- return;
-
- GabbleVCardPipelineItem *item = priv->request_pipeline->data;
- priv->request_pipeline = g_slist_remove (priv->request_pipeline, item);
-
- DEBUG ("launching request %p", item->request);
-
- if (!_gabble_connection_send_with_reply (priv->connection, item->msg,
- item->callback, G_OBJECT(manager), item->request, &error))
- {
- GabbleVCardCacheEntry *entry = g_hash_table_lookup (priv->cache,
- GUINT_TO_POINTER (item->request->handle));
- if (entry && entry->request == item->request)
- {
- entry->request = NULL;
- complete_pending_requests (manager, item->request->handle, error);
- delete_request (item->request);
- }
- else
- {
- complete_one_request (item->request, NULL, error);
- }
- vcard_pipeline_send_next_request (manager);
- }
- else
- {
- priv->reqs_in_flight = g_slist_prepend (priv->reqs_in_flight,
- item->request);
- }
-
- lm_message_unref (item->msg);
- g_free (item);
-}
-
-static void
-vcard_pipeline_go (GabbleVCardManager *manager)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
-
- DEBUG ("called");
-
- while (priv->request_pipeline &&
- (g_slist_length (priv->reqs_in_flight) < VCARD_PIPELINE_SIZE))
- {
- vcard_pipeline_send_next_request (manager);
- }
-}
-
-static void
-vcard_pipeline_enqueue (GabbleVCardManagerRequest *request, LmMessage *msg,
- gpointer callback)
-{
- GabbleVCardManager *self = request->manager;
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self);
- GabbleVCardPipelineItem *item = g_new0 (GabbleVCardPipelineItem, 1);
-
- item->request = request;
- item->msg = msg;
- item->callback = callback;
-
- DEBUG ("enqueue request %p", request);
-
- priv->request_pipeline = g_slist_append (priv->request_pipeline, item);
- if (request->timeout && (0 == request->timer_id))
- {
- request->timer_id =
- g_timeout_add (request->timeout, timeout_request, request);
- }
-}
-
-/* If @replacement is NULL sends a request, calling request_reply_cb when
- * it returns.
- *
- * Otherwise steals its children and sends an update, calling
- * replace_reply_cb when it returns.
- *
- * Frees the @request on error, returns it on success. */
-static GabbleVCardManagerRequest *
-request_send (GabbleVCardManagerRequest *request,
- LmMessageNode *replacement,
- const gchar *jid,
- GError **error)
-{
- GabbleVCardManager *self = request->manager;
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->connection, TP_HANDLE_TYPE_CONTACT);
- LmMessage *msg;
- LmMessageNode *lm_node;
-
- DEBUG ("Sending off request %p to %s for %s", request,
- replacement ? "replace vCard" : "retrieve vCard",
- jid ? jid : "myself");
- msg = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ,
- (replacement
- ? LM_MESSAGE_SUB_TYPE_SET
- : LM_MESSAGE_SUB_TYPE_GET));
- lm_node = lm_message_node_add_child (msg->node, "vCard", NULL);
- lm_message_node_set_attribute (lm_node, "xmlns", NS_VCARD_TEMP);
-
- if (replacement)
- lm_message_node_steal_children (lm_node, replacement);
-
- g_assert (tp_handle_is_valid (contact_repo, request->handle, NULL));
-
- vcard_pipeline_enqueue (request, msg,
- (replacement ? replace_reply_cb : request_reply_cb));
-
- vcard_pipeline_go (self);
-
- return request;
-}
-
-static void
-notify_delete_request (gpointer data, GObject *obj)
-{
- GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest *) data;
- GabbleVCardManager *manager = request->manager;
- TpHandle handle = request->handle;
-
- request->bound_object = NULL;
- delete_request (request);
- cache_entry_attempt_to_free (manager, handle);
-}
-
-/* Request the vCard for the given handle. When it arrives, call the given
- * callback.
- *
- * The callback may be NULL if you just want the side-effect of this
- * operation, which is to update the cached alias.
- */
-GabbleVCardManagerRequest *
-gabble_vcard_manager_request (GabbleVCardManager *self,
- TpHandle handle,
- guint timeout,
- GabbleVCardManagerCb callback,
- gpointer user_data,
- GObject *object,
- GError **error)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *connection = (TpBaseConnection *)priv->connection;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- connection, TP_HANDLE_TYPE_CONTACT);
- GabbleVCardManagerRequest *request;
- GabbleVCardCacheEntry *entry;
- const gchar *jid;
-
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), NULL);
-
- if (timeout == 0)
- timeout = DEFAULT_REQUEST_TIMEOUT;
-
- request = g_slice_new0 (GabbleVCardManagerRequest);
- DEBUG ("Created request %p to retrieve <%u>'s vCard", request, handle);
- request->timeout = timeout;
- request->manager = self;
- tp_handle_ref (contact_repo, handle);
- request->handle = handle;
- request->callback = callback;
- request->user_data = user_data;
- request->bound_object = object;
-
- if (NULL != object)
- g_object_weak_ref (object, notify_delete_request, request);
-
- priv->requests = g_slist_prepend (priv->requests, request);
- if (handle == connection->self_handle)
- {
- jid = NULL;
- }
- else
- {
- jid = tp_handle_inspect (contact_repo, handle);
- }
-
- entry = cache_entry_get (self, handle);
- if (entry->request)
- {
- DEBUG ("adding pending request to existing cache entry %p", entry);
- entry->pending_requests = g_slist_prepend (entry->pending_requests,
- request);
- }
- else
- {
- entry->request = g_slice_new0 (GabbleVCardManagerRequest);
- entry->request->manager = self;
- entry->request->handle = handle;
- tp_handle_ref (contact_repo, handle);
- priv->requests = g_slist_prepend (priv->requests, entry->request);
-
- entry->pending_requests = g_slist_prepend (entry->pending_requests,
- request);
- DEBUG ("adding the request to new entry %p and sending the request",
- entry);
-
- if (!request_send (entry->request, NULL, jid, error))
- {
- DEBUG ("some kind of error happened");
-
- delete_request (entry->request);
- entry->request = NULL;
- gabble_vcard_manager_invalidate_cache (self, entry->handle);
-
- delete_request (request);
- return NULL;
- }
- }
-
- return request;
-}
-
-GabbleVCardManagerRequest *
-gabble_vcard_manager_replace (GabbleVCardManager *self,
- LmMessageNode *replacement,
- guint timeout,
- GabbleVCardManagerCb callback,
- gpointer user_data,
- GObject *object,
- GError **error)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *connection = (TpBaseConnection *)priv->connection;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- connection, TP_HANDLE_TYPE_CONTACT);
- GabbleVCardManagerRequest *request;
-
- if (timeout == 0)
- timeout = DEFAULT_REQUEST_TIMEOUT;
-
- request = g_slice_new0 (GabbleVCardManagerRequest);
- DEBUG ("Created request %p to replace my vCard, callback = %p",
- request, callback);
- request->timeout = timeout;
- request->manager = self;
- tp_handle_ref (contact_repo, connection->self_handle);
- request->handle = connection->self_handle;
- request->callback = callback;
- request->user_data = user_data;
- request->bound_object = object;
-
- if (NULL != object)
- g_object_weak_ref (object, notify_delete_request, request);
-
- priv->requests = g_slist_prepend (priv->requests, request);
-
- gabble_vcard_manager_invalidate_cache (self, request->handle);
-
- return request_send (request, replacement, NULL, error);
-}
-
-GabbleVCardManagerRequest *
-gabble_vcard_manager_edit (GabbleVCardManager *self,
- guint timeout,
- GabbleVCardManagerCb callback,
- gpointer user_data,
- GObject *object,
- GError **error,
- ...)
-{
- va_list ap;
- size_t i, argc;
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *connection = (TpBaseConnection *)priv->connection;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- connection, TP_HANDLE_TYPE_CONTACT);
- GabbleVCardManagerRequest *request;
-
- if (timeout == 0)
- timeout = DEFAULT_REQUEST_TIMEOUT;
-
- request = g_slice_new0 (GabbleVCardManagerRequest);
- DEBUG ("Created request %p to edit my vCard", request);
- request->timeout = timeout;
- request->manager = self;
- tp_handle_ref (contact_repo, connection->self_handle);
- request->handle = connection->self_handle;
- request->callback = callback;
- request->user_data = user_data;
- request->bound_object = object;
-
- if (NULL != object)
- g_object_weak_ref (object, notify_delete_request, request);
-
- priv->requests = g_slist_prepend (priv->requests, request);
-
- argc = 0;
- va_start (ap, error);
- while (va_arg (ap, const gchar *) != NULL)
- {
- argc++;
- }
- va_end (ap);
- g_return_val_if_fail (argc % 2 == 0, NULL);
-
- request->edit_args = g_new (gchar *, argc + 1);
-
- va_start (ap, error);
- for (i = 0; i < argc; i++)
- {
- request->edit_args[i] = g_strdup (va_arg (ap, const gchar *));
- }
- request->edit_args[argc] = NULL;
- va_end (ap);
-
- return request_send (request, NULL, NULL, error);
-}
-
-void
-gabble_vcard_manager_cancel_request (GabbleVCardManager *manager,
- GabbleVCardManagerRequest *request)
-{
- GabbleVCardManagerPrivate *priv;
-
- g_return_if_fail (GABBLE_IS_VCARD_MANAGER (manager));
- g_return_if_fail (NULL != request);
-
- priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
-
- g_return_if_fail (NULL != g_slist_find (priv->requests, request));
-
- cancel_request (request);
-}
-
-/**
- * Return cached message for the handle's VCard if it's available.
- */
-gboolean
-gabble_vcard_manager_get_cached (GabbleVCardManager *self, TpHandle handle,
- LmMessageNode **node)
-{
- GabbleVCardManagerPrivate *priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (self);
- GabbleVCardCacheEntry *entry = g_hash_table_lookup (priv->cache,
- GUINT_TO_POINTER (handle));
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->connection, TP_HANDLE_TYPE_CONTACT);
-
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
-
- if ((entry == NULL) || (entry->message == NULL))
- return FALSE;
-
- if (node != NULL)
- *node = lm_message_node_get_child (entry->message->node, "vCard");
-
- return TRUE;
-}
-
-/**
- * Return the cached alias derived from the vCard for the given handle,
- * if any. If there is no cached alias, return NULL.
- */
-const gchar *
-gabble_vcard_manager_get_cached_alias (GabbleVCardManager *manager,
- TpHandle handle)
-{
- GabbleVCardManagerPrivate *priv;
- TpHandleRepoIface *contact_repo;
- const gchar *s;
-
- g_return_val_if_fail (GABBLE_IS_VCARD_MANAGER (manager), NULL);
-
- priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->connection, TP_HANDLE_TYPE_CONTACT);
-
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), NULL);
-
- s = tp_handle_get_qdata (contact_repo, handle,
- gabble_vcard_manager_cache_quark ());
-
- if (s == NO_ALIAS)
- s = NULL;
-
- return s;
-}
-
-/**
- * Return TRUE if we've tried looking up an alias for this handle before.
- */
-gboolean
-gabble_vcard_manager_has_cached_alias (GabbleVCardManager *manager,
- TpHandle handle)
-{
- GabbleVCardManagerPrivate *priv;
- TpHandleRepoIface *contact_repo;
- gpointer p;
-
- g_return_val_if_fail (GABBLE_IS_VCARD_MANAGER (manager), FALSE);
-
- priv = GABBLE_VCARD_MANAGER_GET_PRIVATE (manager);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *)priv->connection, TP_HANDLE_TYPE_CONTACT);
-
- g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL),
- FALSE);
-
- p = tp_handle_get_qdata (contact_repo, handle,
- gabble_vcard_manager_cache_quark ());
-
- return p != NULL;
-}
-
diff --git a/src/vcard-manager.h b/src/vcard-manager.h
deleted file mode 100644
index 8d3acb74b..000000000
--- a/src/vcard-manager.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * vcard-manager.h - vCard lookup helper for Gabble connections
- *
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#ifndef __GABBLE_VCARD_MANAGER_H__
-#define __GABBLE_VCARD_MANAGER_H__
-
-#include <glib-object.h>
-#include <loudmouth/loudmouth.h>
-
-#include "gabble-types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleVCardManagerClass GabbleVCardManagerClass;
-typedef struct _GabbleVCardManagerRequest GabbleVCardManagerRequest;
-
-/**
- * GabbleVCardManagerError:
- * @GABBLE_VCARD_MANAGER_ERROR_CANCELLED: The vCard request was cancelled
- * @GABBLE_VCARD_MANAGER_ERROR_TIMEOUT: The vCard request timed out
- * @GABBLE_VCARD_MANAGER_ERROR_UNKNOWN: An unknown error occured
- */
-typedef enum
-{
- GABBLE_VCARD_MANAGER_ERROR_CANCELLED,
- GABBLE_VCARD_MANAGER_ERROR_TIMEOUT,
- GABBLE_VCARD_MANAGER_ERROR_UNKNOWN
-} GabbleVCardManagerError;
-
-GQuark gabble_vcard_manager_error_quark (void);
-#define GABBLE_VCARD_MANAGER_ERROR gabble_vcard_manager_error_quark ()
-
-GType gabble_vcard_manager_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_VCARD_MANAGER \
- (gabble_vcard_manager_get_type ())
-#define GABBLE_VCARD_MANAGER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_VCARD_MANAGER, \
- GabbleVCardManager))
-#define GABBLE_VCARD_MANAGER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_VCARD_MANAGER, \
- GabbleVCardManagerClass))
-#define GABBLE_IS_VCARD_MANAGER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_VCARD_MANAGER))
-#define GABBLE_IS_VCARD_MANAGER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_VCARD_MANAGER))
-#define GABBLE_VCARD_MANAGER_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_VCARD_MANAGER, \
- GabbleVCardManagerClass))
-
-struct _GabbleVCardManagerClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleVCardManager {
- GObject parent;
- gpointer priv;
-};
-
-typedef void (*GabbleVCardManagerCb)(GabbleVCardManager *self,
- GabbleVCardManagerRequest *request,
- TpHandle handle,
- LmMessageNode *vcard,
- GError *error,
- gpointer user_data);
-
-GabbleVCardManager *gabble_vcard_manager_new (GabbleConnection *);
-
-GQuark gabble_vcard_manager_cache_quark (void);
-
-GabbleVCardManagerRequest *gabble_vcard_manager_request (GabbleVCardManager *,
- TpHandle,
- guint timeout,
- GabbleVCardManagerCb,
- gpointer user_data,
- GObject *object,
- GError **error);
-
-GabbleVCardManagerRequest *gabble_vcard_manager_replace (GabbleVCardManager *,
- LmMessageNode *,
- guint timeout,
- GabbleVCardManagerCb,
- gpointer user_data,
- GObject *object,
- GError **error);
-
-GabbleVCardManagerRequest *gabble_vcard_manager_edit (GabbleVCardManager *,
- guint timeout,
- GabbleVCardManagerCb,
- gpointer user_data,
- GObject *object,
- GError **error,
- ...)
- G_GNUC_NULL_TERMINATED;
-
-void gabble_vcard_manager_cancel_request (GabbleVCardManager *manager,
- GabbleVCardManagerRequest *request);
-
-const gchar *gabble_vcard_manager_get_cached_alias (GabbleVCardManager *,
- TpHandle);
-gboolean gabble_vcard_manager_has_cached_alias (GabbleVCardManager *manager,
- TpHandle handle);
-
-gboolean gabble_vcard_manager_get_cached (GabbleVCardManager *,
- TpHandle,
- LmMessageNode **);
-void gabble_vcard_manager_invalidate_cache (GabbleVCardManager *, TpHandle);
-
-G_END_DECLS
-
-#endif
diff --git a/src/write-mgr-file.c b/src/write-mgr-file.c
deleted file mode 100644
index fd61ef6b0..000000000
--- a/src/write-mgr-file.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * write_mgr_file.c - utility to produce gabble.manager. Part of Gabble.
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * 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
- */
-
-#include <stdio.h>
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-protocol.h>
-
-#include <telepathy-glib/enums.h>
-#include "gabble-connection-manager.h"
-
-static gchar *
-mgr_file_contents (const char *busname,
- const char *objpath,
- const TpCMProtocolSpec protocols[],
- GError **error)
-{
- GKeyFile *f = g_key_file_new ();
- const TpCMProtocolSpec *protocol;
- const TpCMParamSpec *row;
-
- g_key_file_set_string (f, "ConnectionManager", "BusName", busname);
- g_key_file_set_string (f, "ConnectionManager", "ObjectPath", objpath);
-
- for (protocol = protocols; protocol->name; protocol++)
- {
- gchar *section_name = g_strdup_printf ("Protocol %s", protocol->name);
-
- for (row = protocol->parameters; row->name; row++)
- {
- gchar *param_name = g_strdup_printf ("param-%s", row->name);
- gchar *param_value = g_strdup_printf ("%s%s%s", row->dtype,
- (row->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED ? " required" : ""),
- (row->flags & TP_CONN_MGR_PARAM_FLAG_REGISTER ? " register" : ""));
- g_key_file_set_string (f, section_name, param_name, param_value);
- g_free (param_value);
- g_free (param_name);
- }
-
- for (row = protocol->parameters; row->name; row++)
- {
- if (row->flags & TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT)
- {
- gchar *default_name = g_strdup_printf ("default-%s", row->name);
-
- switch (row->gtype)
- {
- case G_TYPE_STRING:
- g_key_file_set_string (f, section_name, default_name,
- row->def);
- break;
- case G_TYPE_INT:
- case G_TYPE_UINT:
- g_key_file_set_integer (f, section_name, default_name,
- GPOINTER_TO_INT(row->def));
- break;
- case G_TYPE_BOOLEAN:
- g_key_file_set_boolean (f, section_name, default_name,
- GPOINTER_TO_INT(row->def) ? 1 : 0);
- }
- g_free (default_name);
- }
- }
- g_free (section_name);
- }
- return g_key_file_to_data (f, NULL, error);
-}
-
-int
-main (void)
-{
- GError *error = NULL;
-
- gchar *s = mgr_file_contents (TP_CM_BUS_NAME_BASE "gabble",
- TP_CM_OBJECT_PATH_BASE "gabble",
- gabble_protocols, &error);
- if (!s)
- {
- fprintf (stderr, error->message);
- g_error_free (error);
- return 1;
- }
- printf ("%s", s);
- g_free (s);
- return 0;
-}
diff --git a/tests/.git-darcs-dir b/tests/.git-darcs-dir
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/.git-darcs-dir
+++ /dev/null
diff --git a/tests/Makefile.am b/tests/Makefile.am
deleted file mode 100644
index d5de5b88d..000000000
--- a/tests/Makefile.am
+++ /dev/null
@@ -1,65 +0,0 @@
-noinst_PROGRAMS = \
- test-gabble-presence \
- test-base64 \
- test-handles
-
-python_tests = \
- test-basic-connect
-
-python_tests_pythonfiles = $(python_tests:=.py)
-python_tests_shfiles = $(python_tests:=.sh)
-
-test_gabble_presence_LDADD = \
- $(top_builddir)/src/libgabble-convenience.la \
- $(top_builddir)/lib/telepathy-glib/libtelepathy-glib.la
-
-test_base64_LDADD = \
- $(top_builddir)/src/libgabble-convenience.la \
- $(top_builddir)/lib/telepathy-glib/libtelepathy-glib.la
-
-test_handles_LDADD = \
- $(top_builddir)/src/libgabble-convenience.la \
- $(top_builddir)/lib/telepathy-glib/libtelepathy-glib.la
-
-AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_CFLAGS@ @GLIB_CFLAGS@ @LOUDMOUTH_CFLAGS@ \
- @COVERAGE_CFLAGS@ \
- -I $(top_srcdir)/lib -I $(top_builddir)/lib \
- -I $(top_srcdir)/src -I $(top_builddir)/src
-AM_LDFLAGS = @DBUS_LIBS@ @GLIB_LIBS@ @LOUDMOUTH_LIBS@
-
-TESTS = $(noinst_PROGRAMS)
-EXTRA_TESTS = $(python_tests_shfiles)
-
-check-extra: $(BUILT_SOURCES)
- chmod +x run-with-tmp-session-bus.sh $(python_tests_shfiles) \
- $(python_tests_pythonfiles) exec-with-log.sh
- $(MAKE) check TESTS="$(EXTRA_TESTS)"
-
-exec-with-log.sh: exec-with-log.sh.in
- @sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@
-
-%.conf: %.conf.in
- @sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@
-
-%.service: %.service.in
- @sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@
-
-# D-Bus service file for testing
-service_in_files = org.freedesktop.Telepathy.ConnectionManager.gabble.service.in
-service_files = $(service_in_files:.service.in=.service)
-
-# D-Bus config file for testing
-conf_in_files = run-with-tmp-session-bus.conf.in
-conf_files = $(conf_in_files:.conf.in=.conf)
-
-BUILT_SOURCES = $(service_files) $(conf_files) exec-with-log.sh
-
-EXTRA_DIST = $(service_in_files) $(conf_in_files) exec-with-log.sh.in
-
-CLEANFILES = $(BUILT_SOURCES) gabble-[1-9]*.log
-
-check_c_sources = *.c
-check_misc_sources = \
- $(python_tests_shfiles) \
- $(python_tests_pythonfiles)
-include $(top_srcdir)/check-coding-style.mk
diff --git a/tests/dbustesting.py b/tests/dbustesting.py
deleted file mode 100644
index 3186510cd..000000000
--- a/tests/dbustesting.py
+++ /dev/null
@@ -1,609 +0,0 @@
-import sys
-import traceback
-
-import dbus
-import dbus.glib
-import dbus.service
-from dbus.proxies import ProxyObject
-import gobject
-
-# The default timeout for all blocking calls
-DEFAULT_TIMEOUT=10
-
-# The session bus used for the tests
-session_bus = dbus.SessionBus()
-
-# The loop used for the tests, if needed provide another one.
-LOOP = gobject.MainLoop()
-
-class MainloopClock:
- def __init__(self, callback=None):
- self._ticks = None
- self._callback = callback
-
- def _tick(self):
- self._ticks[1] -= 1
- return True
-
- def _reset(self):
- if self._ticks != None:
- gobject.source_remove(self._ticks[0])
- self._ticks = None
-
- def sleep(self, timeout):
- """
- Sleeps for 'timeout' seconds without blocking the Mainloop. Blocking call.
- """
- if self._callback == None:
- print 'Sleeping for %d seconds' % (timeout)
- self._reset()
-
- self._ticks = [gobject.timeout_add(timeout*1000, self._tick), timeout]
- while self._ticks[1] > 0 and (self._callback == None or self._callback()):
- LOOP.get_context().iteration(True)
-
-class TestCase:
- """
- Subclass this class to create your TestCase. then pass the class to the run()
- function to execute the tests.
- """
- def __init__(self):
- pass
-
- def Sleep(self, timeout):
- """
- Calling this method will block for 'timeout' seconds, without hanging the process.
- """
- MainloopClock().sleep(timeout)
-
- def run(self):
- """
- This method is called when the test must be run. Override it to implement your
- test script. Any exception thrown in this method will be reported as a test failure.
- """
- raise NotImplementedError()
-
- def __repr__(self):
- return str(self.__class__)
-
-def run(cases):
- """
- Call this method with a TestCase sub-class, or a list of TestCase sub-classes.
- Warning !
- As the proxy objects and various signal connections aren't destroyed after a test, it is
- not a good idea to run more than one test after the other, better launch one process per test.
-
- The test case to run will be given on the command line, if not, a help notice is printed
- """
- if type(cases) != list:
- cases = [cases]
-
- # Command line foo
- def class_name(name):
- i = name.rfind(".")
- if i == -1:
- return name
- else:
- return name[i+1:]
-
- print 'These are the available test cases:', [class_name(str(case)) for case in cases]
- if len(sys.argv) != 2:
- print 'You must run a single test case by appending its name on the command line'
- sys.exit(0)
-
- cases = [case for case in cases if class_name(str(case)) in sys.argv]
- print 'Running the following test case:', [class_name(str(case)) for case in cases]
-
- results = []
- def finish():
- LOOP.quit()
- print 'Test Case ended.'
- for result in results:
- success, reason = result
- print '-------\nTestCase:\n%s\n--------' % (reason)
- if not success:
- sys.exit(1)
-
- def run_case(case_class):
- print '----\nTestCase: Creating from class %s' % (str(case_class))
- case = case_class()
- print 'TestCase: Starting %s' % (case)
- try:
- case.run()
- results.append((True, "Success"))
- except Exception, msg:
- print 'TestCase: Failing %s----' % (case)
- print msg
- results.append((False, traceback.format_exc()))
-
- print 'TestCase: Ending %s\n-----' % (case)
-
- def run_all_cases():
- for case in cases:
- run_case(case)
- finish()
-
- gobject.idle_add(run_all_cases)
- LOOP.run()
-
-class TestingException(Exception):
- pass
-
-
-#-----------Start of Client Side Scripting -------------------------------------
-
-
-class ClientSignalProxy:
- def __init__ (self, provider, proxy, name):
- self.provider = provider
- self.proxy = proxy
- self.name = name
- self.connected = False
-
- def _signal_emitted(self, *args):
- print "%s: Signal '%s' emitted with args:%s" % (self.provider, self.name, args)
- self.results.append(args)
-
- def listen(self):
- """
- Starts listening for the requested signal. The effect is to reset all counters for this
- signal.
- """
- if not self.connected:
- print '%s: Connecting to signal "%s"' % (self.provider, self.name)
- self.proxy.connect_to_signal(self.name, self._signal_emitted)
- self.connected = True
-
- print "%s: Listening to signal '%s'" % (self.provider, self.name)
- self.results = []
-
- def wait(self, n=1, timeout=DEFAULT_TIMEOUT):
- """
- Wait for the signal to happen n times. This method is blocking. If after 'timeout'
- seconds the signal hasn't happened 'n' times, an exception is thrown.
- Returns the list (or the single if n = 1) of values returned by successive
- signal emissions
- """
- if not self.connected:
- raise TestingException("Waiting for a signal before it's listening")
-
- print "%s: Waiting for signal '%s'" % (self.provider, self.name)
- if len(self.results) != n:
- MainloopClock(lambda: (len(self.results) != n)).sleep(timeout)
-
- results = self.results
- if len(results) != n:
- raise TestingException("%s: Signal '%s' failed to happen %d times: %s" % (self.provider, self.name, n, results))
-
- if n == 1:
- results = self.results[0]
-
- print "%s: Signal '%s' happened %d times: %s" % (self.provider, self.name, n, results)
- return results
-
-class ClientProxy:
- def __init__ (self, provider, proxy, name):
- self.provider = provider
- self.name = name
- self.proxy = proxy
- self.signal_proxy = ClientSignalProxy(provider, proxy, name)
- self.async_reply = None
-
- def _reset(self):
- ret = self.async_reply
- self.async_reply = None
- return ret
-
- def _handle_reply(self, *args):
- if len(args) == 1:
- args = args[0]
- print '%s: Got method return value: %s' % (self.provider, args)
- self.async_reply = args
-
- def _handle_error(self, e):
- print e
-
- def _call_async(self, *args, **kwargs):
- print "%s: Calling method %s(%s, %s)" % (self.provider, self.name, args, kwargs)
- if "timeout" not in kwargs:
- kwargs["timeout"] = DEFAULT_TIMEOUT*1000
- getattr(self.proxy, self.name)(reply_handler=self._handle_reply, error_handler=self._handle_error, *args, **kwargs)
-
- # Wait to receive the return value
- while self.async_reply == None:
- LOOP.get_context().iteration(True)
-
- ret = self._reset()
- print "%s: Method %s returned: %s" % (self.provider, self.name, ret)
- return ret
-
- def call(self, *args, **kwargs):
- """
- Call this method with the given arguments. If timeout=xx is used, the method
- will wait at most xx msecs before returning an error. If it's not used
- the default timeout value is used.
- """
- print "%s: Calling method %s(%s, %s)" % (self.provider, self.name, args, kwargs)
- if "timeout" not in kwargs:
- kwargs["timeout"] = DEFAULT_TIMEOUT*1000
-
- ret = getattr(self.proxy, self.name)(*args, **kwargs)
- print "%s: Method %s returned: %s" % (self.provider, self.name, ret)
- return ret
-
- def listen(self):
- """
- Start listening for this signal to happen (reset counters, etc). See ClientSignalProxy.listen
- """
- # Lazy signal connection
- self.signal_proxy.listen()
-
- def wait(self, n=1, timeout=DEFAULT_TIMEOUT):
- """
- Wait and block until this signal happens. See ClientSignalProxy.wait
- """
- # Lazy signal wait
- return self.signal_proxy.wait(n, timeout)
-
-class ClientProxyProvider:
- def __init__ (self, provider, interface):
- self.provider = provider
- self.interface = interface
- self.cache = {}
-
- def __getitem__(self, name):
- """
- Return the ClientProxy for the method or signal named 'name'.
- """
- if name in self.cache:
- return self.cache[name]
-
- proxy = ClientProxy(self.provider, self.interface, name)
-
- # Cache for future reuses
- self.cache[name] = proxy
-
- return proxy
-
- def __str__(self):
- return str(self.provider)
-
-class ClientInterfaceProvider:
- def __init__ (self, provider, proxy, interfaces):
- self.provider = provider
- self.interfaces = {}
-
- for nick, iface in interfaces.items():
- self.interfaces[nick] = ClientProxyProvider(self, dbus.Interface(proxy, iface))
-
- def __getitem__(self, name):
- """
- Return the ClientProxyProvider for the interface nicknamed 'name'.
- """
- return self.interfaces[name]
-
- def __str__(self):
- return str(self.provider)
-
-class ClientProvider:
- def __init__ (self, introspect=True):
- self.proxies = {}
- self.introspect = introspect
- # FIXME: this should be solved, the deadlock/introspect thing
- #self.introspect = True
-
- def __getitem__(self, name):
- """
- Return the ClientInterfaceProvider or ClientProxy for the service nicknamed 'name'
- """
- return self.proxies[name]
-
- def __setitem__(self, name, value):
- """
- Create a new Client with the given value. value must be a tuple with three items:
- service: text of the dbus service,
- obj: path of the dbus remote object,
- ifaces: either a string of the interface name implemented by the object OR
- a dictionnary of name:iface pairs, name being a nickname for the interface, and
- iface one of the interfaces implemented by the object.
- """
- service, obj, ifaces = value
- print "%s: Adding service '%s': %s,%s,%s" % (self, name, service, obj, ifaces)
- proxy = ProxyObject(session_bus, service, obj, self.introspect)
- if type(ifaces) == dict:
- self.proxies[name] = ClientInterfaceProvider(self, proxy, ifaces)
- else:
- self.proxies[name] = ClientProxyProvider(self, dbus.Interface(proxy, ifaces))
-
- def __str__(self):
- return str(self.__class__)
-
-#-----------End of Client Side scripting ---------------------------------------
-
-#-----------Start of Service Side Scripting ------------------------------------
-
-# This one intercepts calls to the remote dbus object and log the call, register the arguments
-# and sometimes override return value
-def intercept(obj):
- """
- This decorator is to be used on exported MockService method and must be applied *after* the
- @dbus.service.method decorator (that means be written *before* it in source code) for example:
-
- @intercept
- @dbus.service.method("foo.bar.baz")
- def Foobar(self, arg):
- blah
-
- This is used so the testing framework can wrap the actual method call and do some voodoo around it.
- """
- def _meth_wrapper(self, *args, **kwargs):
- override = self._called(*args, **kwargs)
- real = obj(self, *args, **kwargs)
- if override != None:
- return override
- return real
-
- # FIXME: HACK: this is a hack to get the dbus method decorator working even if we wrap it
- for i in dir(obj):
- if i.startswith("_dbus"):
- setattr(_meth_wrapper, i, getattr(obj, i))
-
- return _meth_wrapper
-
-class MockService(dbus.service.Object):
- """
- This class is the super class for services definition. Each service you want to use
- must define the exported methods and signals by subclassing this class and using
- the appropriate dbus decorators and @intercept when it's a method.
- """
- def __init__(self, service, obj):
- service = dbus.service.BusName(service, bus=session_bus)
- dbus.service.Object.__init__(self, service, obj)
-
- def _called(self, *args, **kwargs):
- # To be overridden by ServiceProxy implementation
- # Called by the @intercept decorator on method call
- pass
-
-class ServiceProxy:
- def __init__ (self, provider, service, name):
- self.provider = provider
- self.name = name
- self.service = service
- service._called = self._called
- self._reset()
-
- def _reset(self):
- self.received_call = None
- self.return_value = None
-
- def _called(self, *args, **kwargs):
- # Dbus callback
- print '%s: Got method call "%s" with args: %s %s' % (self.provider, self.name, args, kwargs)
- self.received_call = (args, kwargs)
- if self.return_value != None:
- return self.return_value(*args, **kwargs)
-
- def _wait_listening_call(self, timeout=DEFAULT_TIMEOUT):
- print '%s: Waiting for Method Call "%s"' % (self.provider, self.name)
-
- MainloopClock(lambda: self.received_call == None).sleep(timeout)
- if self.received_call == None:
- raise TestingException("%s: Method Call '%s' failed to happen" % (self.provider, self.name))
-
- def listen_call(self, return_val=None):
- """
- Starts listening for a method call on this service side. Resets counters and stuff.
- If return_val is not None but is a callable, it will be called with the method
- call arguments, and the return value will override the return value as defined in the MockService Subclass.
-
- use like:
- xxx.listen_call(lambda *args, **kwargs: 3)
-
- will return 3 for this method whatever was defined in the MockService imoplementation
- """
- self._reset()
- if return_val != None:
- print '%s: Listening for Method Call "%s" with overriden return val' % (self.provider, self.name)
- self.return_value = return_val
- else:
- print '%s: Listening for Method Call "%s"' % (self.provider, self.name)
-
- def wait_call(self, listening=False, return_val=None, timeout=DEFAULT_TIMEOUT):
- """
- This will block waiting for the method call to effectively happen on service side.
-
- If listening is False, it will automatically starts listening for the call and then block
- while the method isn't called.
-
- If listening is True, it will only wait for a previously listened call to happen (after having called
- manually listen_call())
-
- See listen_call for return_val definition.
-
- timeout is the number of seconds to block at most before throwing an Exception
- """
- if not listening:
- self.listen_call(return_val)
-
- self._wait_listening_call(timeout)
-
- def emit(self, *args, **kwargs):
- """
- Make the service emit this signal with the given arguments.
- """
- print '%s: Emitting signal "%s" with args: %s %s' % (self.provider, self.name, args, kwargs)
- getattr(self.service, self.name)(*args, **kwargs)
-
-
-class ServiceProxyProvider:
- def __init__ (self, provider, service):
- self.provider = provider
- self.service = service
- self.cache = {}
-
- def __getitem__(self, name):
- """
- Return the ServiceProxy for the method or signal named 'name'
- """
- if name in self.cache:
- return self.cache[name]
-
- proxy = ServiceProxy(self.provider, self.service, name)
-
- # Cache for future reuses
- self.cache[name] = proxy
-
- return proxy
-
- def __str__(self):
- return str(self.provider)
-
-class ServiceProvider:
- def __init__(self):
- self.services = {}
-
- def __setitem__(self, name, value):
- """
- Creates a service implementation with the given value.
- value must be a 3-tuple whith:
- klass: the class of the MockService subclass defining the service
- service: the name of the dbus service (eg. org.foo.bar)
- obj: the path for this exported object on Dbus
- """
- klass, service, obj = value
- print "%s: Adding service '%s': %s,%s,%s" % (self, name, klass, service, obj)
- self.services[name] = ServiceProxyProvider(self, klass(service, obj))
-
- def __getitem__(self, name):
- """
- Return the ServiceProxyProvider for service nicknamed 'name'
- """
- return self.services[name]
-
- def __str__(self):
- return str(self.__class__)
-
-#-----------End of Service Side scripting --------------------------------------
-
-#-----------Start of Mixed Side Scripting ------------------------------------
-
-# The classes defined below are used to adapt service/client interfaces to a mixed mode.
-# That means you can use both API's depending on wether the nickname refers
-# to a client or a service or a mixed object.
-# Mixed object are both a service and a client and implement both capabilities.
-# see MixedProvider.__setitem__ for how to construct such objects.
-# If you want your test case to use both client and service objects, you should use the
-# MixedTestCase superclass.
-class MixedProxy:
- def __init__(self, provider, client, service, name):
- self.provider = provider
- self.client = client
- self.service = service
- self.name = name
-
- # Mirror the client+service api's
- def emit(self, *args, **kwargs):
- self.service.emit(*args, **kwargs)
-
- def wait_call(self, listening=False, return_val=None, timeout=DEFAULT_TIMEOUT):
- return self.service.wait_call(listening, return_val, timeout)
-
- def listen_call(self, return_val=None):
- self.service.listen_call(return_val)
-
- def call(self, *args, **kwargs):
- return self.client._call_async(*args, **kwargs)
-
- def listen(self):
- self.client.listen()
-
- def wait(self, n=1, timeout=DEFAULT_TIMEOUT):
- return self.client.wait(n, timeout)
-
-class MixedProxyProvider:
- def __init__(self, provider, client, service):
- self.provider = provider
- self.client = client
- self.service = service
- self.cache = {}
-
- def __getitem__(self, name):
- if name in self.cache:
- return self.cache[name]
-
- proxy = MixedProxy(self.provider, self.client[name], self.service[name], name)
-
- # Cache for future reuses
- self.cache[name] = proxy
-
- return proxy
-
- def __str__(self):
- return str(self.provider)
-
-class MixedProvider:
- def __init__(self):
- # FIXME: the introspect=True causes a massive deadlock, introspect=False is likely to break things too :)
- self.client = ClientProvider(introspect=False)
- self.service = ServiceProvider()
- self.mappings = {}
-
- def __setitem__(self, name, value):
- """
- Construct a mixed Proxy, depending on the value a client, a service, or a mixed proxy will be created.
- if value is a 3-uple with first elements being a MockService subclass, a service is created
- (as defined in ServiceProvider.__setitem__)
- if value is a 3-uple with first element being a string, a client is created
- (as defined in ClientProvider.__setitem__)
- if value is a 4-uple with:
- klass: the MockProxy subclass of the service to implement
- service: the name of dbus service to export
- object: the name of dbus object to export
- ifaces: either a dic or a string describing the interfaces implemented by this object
- then a mixed client/service is created allowing to use both API's on it.
- """
- if len(value) == 4:
- self.service[name] = value[:3]
- self.client[name] = value[1:]
- self.mappings[name] = MixedProxyProvider(self, self.client[name], self.service[name])
- elif issubclass(value[0], MockService):
- # New service
- self.service[name] = value
- self.mappings[name] = self.service
- else:
- self.client[name] = value
- self.mappings[nickname] = self.client
-
- def __getitem__(self, name):
- return self.mappings[name]
-
- def __str__(self):
- return str(self.__class__)
-
-#-----------End of Mixed Side scripting --------------------------------------
-
-class ClientTestCase(ClientProvider, TestCase):
- """
- Subclass this to build a test case using only clients
- """
- def __init__(self):
- TestCase.__init__(self)
- ClientProvider.__init__(self)
-
-class ServiceTestCase(ServiceProvider, TestCase):
- """
- Subclass this to build a test case using only services
- """
- def __init__(self):
- TestCase.__init__(self)
- ServiceProvider.__init__(self)
-
-class MixedTestCase(MixedProvider, TestCase):
- """
- Subclass this to build a test case that uses both clients and services
- """
- def __init__(self):
- TestCase.__init__(self)
- MixedProvider.__init__(self)
-
diff --git a/tests/exec-with-log.sh.in b/tests/exec-with-log.sh.in
deleted file mode 100644
index bcbc61eeb..000000000
--- a/tests/exec-with-log.sh.in
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-cd "@abs_top_builddir@/tests"
-
-export GABBLE_DEBUG=all LM_DEBUG=net
-ulimit -c unlimited
-exec > gabble-$$.log 2>&1
-
-exec ../src/telepathy-gabble
diff --git a/tests/org.freedesktop.Telepathy.ConnectionManager.gabble.service.in b/tests/org.freedesktop.Telepathy.ConnectionManager.gabble.service.in
deleted file mode 100644
index 1d1933c65..000000000
--- a/tests/org.freedesktop.Telepathy.ConnectionManager.gabble.service.in
+++ /dev/null
@@ -1,3 +0,0 @@
-[D-BUS Service]
-Name=org.freedesktop.Telepathy.ConnectionManager.gabble
-Exec=@abs_top_builddir@/tests/exec-with-log.sh
diff --git a/tests/run-with-tmp-session-bus.conf.in b/tests/run-with-tmp-session-bus.conf.in
deleted file mode 100644
index 1d3c399dc..000000000
--- a/tests/run-with-tmp-session-bus.conf.in
+++ /dev/null
@@ -1,30 +0,0 @@
-<!-- This configuration file controls the per-user-login-session message bus.
- Add a session-local.conf and edit that rather than changing this
- file directly. -->
-
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
- <!-- Our well-known bus type, don't change this -->
- <type>session</type>
-
- <listen>unix:tmpdir=/tmp</listen>
-
- <servicedir>@abs_top_builddir@/tests</servicedir>
-
- <policy context="default">
- <!-- Allow everything to be sent -->
- <allow send_destination="*"/>
- <!-- Allow everything to be received -->
- <allow eavesdrop="true"/>
- <!-- Allow anyone to own anything -->
- <allow own="*"/>
- </policy>
-
- <!-- This is included last so local configuration can override what's
- in this standard file -->
-
-
-
-
-</busconfig>
diff --git a/tests/run-with-tmp-session-bus.sh b/tests/run-with-tmp-session-bus.sh
deleted file mode 100644
index 1021723c4..000000000
--- a/tests/run-with-tmp-session-bus.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#! /bin/sh
-
-SCRIPTNAME=$0
-WRAPPED_SCRIPT=$1
-shift
-
-die()
-{
- if ! test -z "$DBUS_SESSION_BUS_PID" ; then
- echo "killing message bus "$DBUS_SESSION_BUS_PID >&2
- kill -9 $DBUS_SESSION_BUS_PID
- fi
- echo $SCRIPTNAME: $* >&2
- exit 1
-}
-
-## convenient to be able to ctrl+C without leaking the message bus process
-trap 'die "Received SIGINT"' INT
-
-CONFIG_FILE=./run-with-tmp-session-bus.conf
-
-unset DBUS_SESSION_BUS_ADDRESS
-unset DBUS_SESSION_BUS_PID
-
-echo "Running dbus-launch --sh-syntax --config-file=$CONFIG_FILE" >&2
-
-eval `dbus-launch --sh-syntax --config-file=$CONFIG_FILE`
-
-if test -z "$DBUS_SESSION_BUS_PID" ; then
- die "Failed to launch message bus for test script to run"
-fi
-
-echo "Started bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS" >&2
-
-#Uncomment the following for debugging
-#GABBLE_DEBUG=all ../src/telepathy-gabble &
-
-# Execute wrapped script
-echo "Running $WRAPPED_SCRIPT $@" >&2
-$WRAPPED_SCRIPT "$@" || die "script \"$WRAPPED_SCRIPT\" failed"
-
-kill -TERM $DBUS_SESSION_BUS_PID || die "Message bus vanished! should not have happened" && echo "Killed daemon $DBUS_SESSION_BUS_PID" >&2
-
-sleep 0.1
-
-## be sure it really died
-kill -9 $DBUS_SESSION_BUS_PID > /dev/null 2>&1 || true
-
-exit 0
diff --git a/tests/test-base64.c b/tests/test-base64.c
deleted file mode 100644
index 40d694847..000000000
--- a/tests/test-base64.c
+++ /dev/null
@@ -1,98 +0,0 @@
-
-#include <base64.h>
-
-struct test {
- gchar *str;
- gchar *encoded;
-};
-
-struct test tests[] = {
- { "c", "Yw==" },
- { "ca", "Y2E=" },
- { "car", "Y2Fy" },
- { "carnal pleasure.", "Y2FybmFsIHBsZWFzdXJlLg==" },
- { "carnal pleasure", "Y2FybmFsIHBsZWFzdXJl" },
- { "carnal pleasur", "Y2FybmFsIHBsZWFzdXI=" },
- { "carnal pleasu", "Y2FybmFsIHBsZWFzdQ==" },
- { NULL, NULL }
-};
-
-int
-main (void)
-{
- gchar *s;
- GString *tmp1, *tmp2;
- struct test *t;
-
- for (t = tests; t->str != NULL; t++)
- {
- tmp1 = g_string_new (t->str);
- s = base64_encode (tmp1);
- g_string_free (tmp1, TRUE);
- tmp1 = g_string_new (s);
- tmp2 = g_string_new (t->encoded);
- g_assert (g_string_equal (tmp1, tmp2));
- g_free (s);
- g_string_free (tmp1, TRUE);
- g_string_free (tmp2, TRUE);
- }
-
- /* test long (> 76 / 4 * 3) string */
- tmp1 = g_string_new (
- "1234567890"
- "1234567890"
- "1234567890"
- "1234567890"
- "1234567890"
- "1234567890");
- s = base64_encode (tmp1);
- g_assert (g_str_equal (s,
- "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM"
- "0NTY3\nODkw"));
- g_free (s);
- g_string_free (tmp1, TRUE);
-
- /* test string with valid characters but invalid length */
- tmp1 = base64_decode ("AAA");
- g_assert (tmp1 == NULL);
-
- /* test string with valid length but invalid characters */
- tmp1 = base64_decode ("????");
- g_assert (tmp1 == NULL);
-
- /* test string with embedded newline */
- tmp1 = base64_decode ("bWF6\ndWxlbQ==");
- tmp2 = g_string_new ("mazulem");
- g_assert (tmp1);
- g_assert (g_string_equal (tmp1, tmp2));
- g_string_free (tmp1, TRUE);
- g_string_free (tmp2, TRUE);
-
- /* test string with misc whitespace */
- tmp1 = base64_decode ("bW F\r6\r\ndW\nxlbQ==\r\n");
- tmp2 = g_string_new ("mazulem");
- g_assert (tmp1);
- g_assert (g_string_equal (tmp1, tmp2));
- g_string_free (tmp1, TRUE);
- g_string_free (tmp2, TRUE);
-
- /* test string with embedded NULL */
- tmp1 = base64_decode ("Zm9vAGJhcg==");
- tmp2 = g_string_new_len ("foo\0bar", 7);
- g_assert (g_string_equal (tmp1, tmp2));
- g_string_free (tmp1, TRUE);
- g_string_free (tmp2, TRUE);
-
- for (t = tests; t->str != NULL; t++)
- {
- tmp1 = base64_decode (t->encoded);
- g_assert (tmp1);
- tmp2 = g_string_new (t->str);
- g_assert (g_string_equal (tmp1, tmp2));
- g_string_free (tmp1, TRUE);
- g_string_free (tmp2, TRUE);
- }
-
- return 0;
-}
-
diff --git a/tests/test-basic-connect.py b/tests/test-basic-connect.py
deleted file mode 100644
index 2dee7b9f2..000000000
--- a/tests/test-basic-connect.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/python
-from dbustesting import *
-
-service = "org.freedesktop.Telepathy.ConnectionManager.gabble"
-path = "/org/freedesktop/Telepathy/ConnectionManager/gabble"
-iface_conn_mgr = "org.freedesktop.Telepathy.ConnectionManager"
-iface_conn = "org.freedesktop.Telepathy.Connection"
-iface_chan = "org.freedesktop.Telepathy.Channel"
-chan_type_text = "org.freedesktop.Telepathy.Channel.Type.Text"
-
-class BasicConnectTest(ClientTestCase):
-
- def start_manager(self, nick):
- self[nick] = (service, path, iface_conn_mgr)
-
- def connect(self, nick, proto, params):
- # Connect to the manager
- conn, obj = self[nick]["RequestConnection"].call(proto, params)
- # register connection as self.nick_conn
- self[nick+"_conn"] = (conn, obj, iface_conn)
- self[nick+"_conn"]["Connect"].call(timeout=30000)
-
- # Retrieve connection status, and wait until connected
- self[nick+"_conn"]["StatusChanged"].listen()
- status = self[nick+"_conn"]["GetStatus"].call()
- while status != 0:
- if status == 2:
- raise Exception("Could not connect")
- status, reason = self[nick+"_conn"]["StatusChanged"].wait()
-
- return conn
-
- def run(self):
- # Test Setup
- self.start_manager("client1")
- self.start_manager("client2")
-
- # Connect the two accounts
- conn1 = self.connect("client1", "jabber",
- {"account": "telepathytest1@jabber.org", "password": "telepathy"})
- conn2 = self.connect("client2", "jabber",
- { "account": "telepathytest2@jabber.org","password": "telepathy"})
-
- # Start listening to NewChannel signal emitted when client2 starts to talk to client1
- self["client1_conn"]["NewChannel"].listen()
-
- # Create a text channel
- self["client2_chan"] = (
- # The connection service
- conn2,
- # A new text channel to the client 1
- self["client2_conn"]["RequestChannel"].call(chan_type_text, 1,
- self["client2_conn"]["RequestHandles"].call (1, ["telepathytest1@jabber.org"])[0], False),
- # The interfaces for this text channel
- {"text": chan_type_text, "chan": iface_chan})
-
- # Send a test message to client 1 from client 2
- self["client2_chan"]["text"]["Send"].call (0, "Test")
-
- # We got a newchannel from client 1
- obj, channel_type, handle_type, handle, suppress_handler = self["client1_conn"]["NewChannel"].wait()
-
- assert channel_type == chan_type_text
- assert handle_type == 1
- assert suppress_handler == False
-
- # Create the channel structure for client 1
- self["client1_chan"] = (
- conn1,
- obj,
- {"text": chan_type_text, "chan": iface_chan})
-
- # Retreive pending messages
- messages = self["client1_chan"]["text"]["ListPendingMessages"].call(True)
-
- id, stamp, from_handle, msg_type, flags, string = messages[0]
- assert len(messages) == 1
- assert from_handle == handle
- assert msg_type == 0
- assert flags == 0
- assert string == "Test"
-
- # Close/Disconnect stuff
- self["client2_chan"]["chan"]["Close"].call()
- self["client1_chan"]["chan"]["Close"].call()
- self["client2_conn"]["Disconnect"].call()
- self["client1_conn"]["Disconnect"].call()
-
-
-run(BasicConnectTest)
diff --git a/tests/test-basic-connect.sh b/tests/test-basic-connect.sh
deleted file mode 100644
index 93af74d54..000000000
--- a/tests/test-basic-connect.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-./run-with-tmp-session-bus.sh `pwd`/test-basic-connect.py BasicConnectTest
diff --git a/tests/test-gabble-presence.c b/tests/test-gabble-presence.c
deleted file mode 100644
index b39d934b8..000000000
--- a/tests/test-gabble-presence.c
+++ /dev/null
@@ -1,137 +0,0 @@
-
-#include <string.h>
-
-#include <glib.h>
-#include <presence.h>
-
-int main (int argc, char **argv)
-{
- const gchar *resource;
- gchar *dump;
- GabblePresence *presence;
-
- g_type_init ();
-
- presence = gabble_presence_new ();
- g_assert (GABBLE_PRESENCE_OFFLINE == presence->status);
- g_assert (NULL == presence->status_message);
-
- /* offline presence from unknown resource: no change */
- g_assert (FALSE == gabble_presence_update (presence, "foo",
- GABBLE_PRESENCE_OFFLINE, NULL, 0));
- /* available presence from unknown resource: change */
- g_assert (TRUE == gabble_presence_update (presence, "foo",
- GABBLE_PRESENCE_AVAILABLE, NULL, 0));
-
- /* accumulated presence has changed; status message unchanged */
- g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status);
- g_assert (NULL == presence->status_message);
-
- /* available presence again; no change */
- g_assert (FALSE == gabble_presence_update (presence, "foo",
- GABBLE_PRESENCE_AVAILABLE, NULL, 0));
- /* available presence again, but with status message: change */
- g_assert (TRUE == gabble_presence_update (presence, "foo",
- GABBLE_PRESENCE_AVAILABLE, "status message", 0));
-
- /* accumulated presence unchanged; status message changed */
- g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status);
- g_assert (0 == strcmp ("status message", presence->status_message));
-
- /* same presence again; no change */
- g_assert (FALSE == gabble_presence_update (presence, "foo",
- GABBLE_PRESENCE_AVAILABLE, "status message", 0));
-
- /* presence from different resource, but equal present-ness; unchanged */
- g_assert (FALSE == gabble_presence_update (presence, "bar",
- GABBLE_PRESENCE_AVAILABLE, "dingoes", 0));
-
- g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status);
- g_assert (0 == strcmp ("status message", presence->status_message));
-
- /* presence with higher priority; presence and message changed */
- g_assert (TRUE == gabble_presence_update (presence, "bar",
- GABBLE_PRESENCE_AVAILABLE, "dingoes", 1));
-
- g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status);
- g_assert (0 == strcmp ("dingoes", presence->status_message));
-
- /* presence from first resource with greated present-ness: change */
- g_assert (TRUE == gabble_presence_update (presence, "foo",
- GABBLE_PRESENCE_CHAT, "status message", 0));
-
- g_assert (GABBLE_PRESENCE_CHAT == presence->status);
- g_assert (0 == strcmp ("status message", presence->status_message));
-
- /* no resource has the Google voice cap */
- resource = gabble_presence_pick_resource_by_caps (presence,
- PRESENCE_CAP_GOOGLE_VOICE);
- g_assert (NULL == resource);
-
- /* give voice cap to second resource, but make priority negative */
- g_assert (FALSE == gabble_presence_update (presence, "bar",
- GABBLE_PRESENCE_AVAILABLE, "dingoes", -1));
- gabble_presence_set_capabilities (presence, "bar",
- PRESENCE_CAP_GOOGLE_VOICE, 0);
-
- dump = gabble_presence_dump (presence);
- g_assert (0 == strcmp (dump,
- "nickname: (null)\n"
- "accumulated status: 6\n"
- "accumulated status msg: status message\n"
- "accumulated capabilities: 2\n"
- "kept while unavailable: 0\n"
- "resources:\n"
- " foo\n"
- " capabilities: 0\n"
- " status: 6\n"
- " status msg: status message\n"
- " priority: 0\n"
- " bar\n"
- " capabilities: 2\n"
- " status: 5\n"
- " status msg: dingoes\n"
- " priority: -1\n"));
- g_free (dump);
-
- /* no resource with non-negative priority has the Google voice cap */
- resource = gabble_presence_pick_resource_by_caps (presence,
- PRESENCE_CAP_GOOGLE_VOICE);
- g_assert (NULL == resource);
-
- /* give voice cap to first resource */
- gabble_presence_set_capabilities (presence, "foo",
- PRESENCE_CAP_GOOGLE_VOICE, 0);
-
- /* resource has voice cap */
- resource = gabble_presence_pick_resource_by_caps (presence,
- PRESENCE_CAP_GOOGLE_VOICE);
- g_assert (0 == strcmp ("foo", resource));
-
- /* presence turns up from null resource; it trumps other presence regardless
- * of whether status is more present or not */
- g_assert (TRUE == gabble_presence_update (presence, NULL,
- GABBLE_PRESENCE_OFFLINE, "gone", 0));
- g_assert (GABBLE_PRESENCE_OFFLINE == presence->status);
- g_assert (0 == strcmp ("gone", presence->status_message));
-
- /* caps are gone too */
- resource = gabble_presence_pick_resource_by_caps (presence,
- PRESENCE_CAP_GOOGLE_VOICE);
- g_assert (NULL == resource);
-
- dump = gabble_presence_dump (presence);
- g_assert (0 == strcmp (dump,
- "nickname: (null)\n"
- "accumulated status: 0\n"
- "accumulated status msg: gone\n"
- "accumulated capabilities: 2\n"
- "kept while unavailable: 0\n"
- "resources:\n"
- " (none)\n"));
- g_free (dump);
-
-
- return 0;
-}
-
diff --git a/tests/test-handles.c b/tests/test-handles.c
deleted file mode 100644
index c9bc51931..000000000
--- a/tests/test-handles.c
+++ /dev/null
@@ -1,109 +0,0 @@
-#include <string.h>
-#include <glib.h>
-#include <glib-object.h>
-#include <gabble-connection.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/errors.h>
-
-void test_handles (guint handle_type)
-{
- TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES];
- TpHandleRepoIface *tp_repo = NULL;
- GError *error = NULL;
- guint i;
-
- TpHandle handle = 0;
- const gchar *jid = "handle.test@foobar";
- const gchar *return_jid;
-
- for (i = 0; i < NUM_TP_HANDLE_TYPES; i++)
- {
- repos[i] = NULL;
- }
- _gabble_connection_create_handle_repos (NULL, repos);
- tp_repo = repos[handle_type];
- g_assert (tp_repo != NULL);
-
- /* Handle zero is never valid */
- g_assert (tp_handle_is_valid (tp_repo, 0, &error) == FALSE);
- g_assert (error->code == TP_ERROR_INVALID_ARGUMENT);
-
- g_error_free (error);
- error = NULL;
-
- /* Properly return error when handle isn't in the repo */
- g_assert (tp_handle_is_valid (tp_repo, 65536, &error) == FALSE);
- g_assert (error->code == TP_ERROR_INVALID_ARGUMENT);
-
- g_error_free (error);
- error = NULL;
-
- /* Properly return when error out argument isn't provided */
- g_assert (tp_handle_is_valid (tp_repo, 65536, NULL) == FALSE);
-
- if (handle_type == TP_HANDLE_TYPE_LIST)
- {
- /* for the static repo we need a name that's actually valid */
- jid = "deny";
- }
- else
- {
- /* It's not there to start with, unless we're using the static repo */
- handle = tp_handle_lookup (tp_repo, jid, NULL, NULL);
- g_assert (handle == 0);
- }
- /* ... but when we call tp_handle_ensure we get a new ref to it */
- handle = tp_handle_ensure (tp_repo, jid, NULL, NULL);
- g_assert (handle != 0);
-
- /* Try to inspect it */
- return_jid = tp_handle_inspect (tp_repo, handle);
- g_assert (!strcmp (return_jid, jid));
-
- if (handle_type != TP_HANDLE_TYPE_LIST)
- {
- /* Hold the handle */
- g_assert (tp_handle_client_hold (tp_repo, "TestSuite", handle, NULL) == TRUE);
-
- /* Now unref it */
- tp_handle_unref (tp_repo, handle);
-
- /* Validate it, should be all healthy because client holds it still */
- g_assert (tp_handle_is_valid (tp_repo, handle, NULL) == TRUE);
-
- /* Ref it again */
- tp_handle_ref (tp_repo, handle);
-
- /* Client releases it */
- g_assert (tp_handle_client_release (tp_repo, "TestSuite", handle, NULL) == TRUE);
- }
-
- /* Now unref it */
- tp_handle_unref (tp_repo, handle);
-
- if (handle_type != TP_HANDLE_TYPE_LIST)
- {
- /* Try to unref it again, should fail */
- g_assert (tp_handle_is_valid (tp_repo, handle, NULL) == FALSE);
- }
-
- for (i = 0; i < NUM_TP_HANDLE_TYPES; i++)
- {
- if (repos[i])
- g_object_unref ((GObject *)repos[i]);
- }
-}
-
-int main (int argc, char **argv)
-{
- g_type_init ();
-
- g_debug ("Testing contact handles");
- test_handles (TP_HANDLE_TYPE_CONTACT);
- g_debug ("Testing room handles");
- test_handles (TP_HANDLE_TYPE_ROOM);
- g_debug ("Testing list handles");
- test_handles (TP_HANDLE_TYPE_LIST);
- return 0;
-}