summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS138
-rw-r--r--configure.ac11
-rw-r--r--extensions/Makefile.am48
-rw-r--r--gabble/caps-channel-manager.h4
-rw-r--r--gabble/connection.h3
-rw-r--r--gabble/plugin-connection.h3
-rw-r--r--gabble/plugin.h3
m---------lib/ext/wocky0
-rw-r--r--plugins/console.c31
-rw-r--r--plugins/console.h2
-rw-r--r--plugins/gateways.c12
-rw-r--r--plugins/test.c5
-rw-r--r--src/Makefile.am26
-rw-r--r--src/addressing-util.c34
-rw-r--r--src/addressing-util.h2
-rw-r--r--src/auth-manager.c234
-rw-r--r--src/auth-manager.h4
-rw-r--r--src/base-call-channel.c17
-rw-r--r--src/base-call-channel.h9
-rw-r--r--src/base64.c196
-rw-r--r--src/base64.h28
-rw-r--r--src/bytestream-factory.c100
-rw-r--r--src/bytestream-factory.h8
-rw-r--r--src/bytestream-ibb.c18
-rw-r--r--src/bytestream-ibb.h2
-rw-r--r--src/bytestream-muc.c18
-rw-r--r--src/bytestream-muc.h2
-rw-r--r--src/bytestream-multiple.c11
-rw-r--r--src/bytestream-socks5.c187
-rw-r--r--src/bytestream-socks5.h2
-rw-r--r--src/call-channel.c97
-rw-r--r--src/call-content.c47
-rw-r--r--src/call-content.h6
-rw-r--r--src/call-member-content.c51
-rw-r--r--src/call-member-content.h13
-rw-r--r--src/call-member.c70
-rw-r--r--src/call-member.h14
-rw-r--r--src/call-muc-channel.c42
-rw-r--r--src/call-muc-channel.h4
-rw-r--r--src/call-stream.c103
-rw-r--r--src/call-stream.h7
-rw-r--r--src/capabilities.c46
-rw-r--r--src/caps-channel-manager.c4
-rw-r--r--src/caps-hash.c1
-rw-r--r--src/conn-addressing.c6
-rw-r--r--src/conn-aliasing.c38
-rw-r--r--src/conn-avatars.c64
-rw-r--r--src/conn-client-types.c3
-rw-r--r--src/conn-contact-info.c25
-rw-r--r--src/conn-location.c21
-rw-r--r--src/conn-mail-notif.c28
-rw-r--r--src/conn-olpc.c168
-rw-r--r--src/conn-presence.c236
-rw-r--r--src/conn-sidecars.c22
-rw-r--r--src/connection-manager.c8
-rw-r--r--src/connection-manager.h2
-rw-r--r--src/connection.c246
-rw-r--r--src/connection.h10
-rw-r--r--src/debug.c4
-rw-r--r--src/disco.c2
-rw-r--r--src/error.c16
-rw-r--r--src/ft-channel.c113
-rw-r--r--src/ft-channel.h2
-rw-r--r--src/ft-manager.c47
-rw-r--r--src/gabble.c7
-rw-r--r--src/google-relay.c325
-rw-r--r--src/google-relay.h45
-rw-r--r--src/gtalk-file-collection.c172
-rw-r--r--src/gtalk-file-collection.h6
-rw-r--r--src/im-channel.c284
-rw-r--r--src/im-channel.h9
-rw-r--r--src/im-factory.c88
-rw-r--r--src/jingle-content.c1409
-rw-r--r--src/jingle-content.h163
-rw-r--r--src/jingle-factory.c604
-rw-r--r--src/jingle-factory.h90
-rw-r--r--src/jingle-info.c600
-rw-r--r--src/jingle-info.h116
-rw-r--r--src/jingle-media-rtp.c1516
-rw-r--r--src/jingle-media-rtp.h124
-rw-r--r--src/jingle-mint.c54
-rw-r--r--src/jingle-mint.h9
-rw-r--r--src/jingle-session.c2457
-rw-r--r--src/jingle-session.h139
-rw-r--r--src/jingle-share.c52
-rw-r--r--src/jingle-share.h11
-rw-r--r--src/jingle-tp-util.c26
-rw-r--r--src/jingle-tp-util.h6
-rw-r--r--src/jingle-transport-google.c644
-rw-r--r--src/jingle-transport-google.h68
-rw-r--r--src/jingle-transport-iceudp.c617
-rw-r--r--src/jingle-transport-iceudp.h64
-rw-r--r--src/jingle-transport-iface.c283
-rw-r--r--src/jingle-transport-iface.h109
-rw-r--r--src/jingle-transport-rawudp.c404
-rw-r--r--src/jingle-transport-rawudp.h64
-rw-r--r--src/jingle-types.h126
-rw-r--r--src/legacy-caps.c2
-rw-r--r--src/media-channel-hold.c19
-rw-r--r--src/media-channel-internal.h9
-rw-r--r--src/media-channel.c354
-rw-r--r--src/media-channel.h3
-rw-r--r--src/media-factory.c37
-rw-r--r--src/media-stream.c212
-rw-r--r--src/media-stream.h12
-rw-r--r--src/message-util.c23
-rw-r--r--src/message-util.h2
-rw-r--r--src/muc-channel.c917
-rw-r--r--src/muc-channel.h32
-rw-r--r--src/muc-factory.c587
-rw-r--r--src/muc-factory.h5
-rw-r--r--src/muc-tube-dbus.c20
-rw-r--r--src/muc-tube-stream.c20
-rw-r--r--src/namespaces.h5
-rw-r--r--src/olpc-activity.c31
-rw-r--r--src/olpc-activity.h3
-rw-r--r--src/plugin-connection.c2
-rw-r--r--src/plugin-loader.c5
-rw-r--r--src/plugin-loader.h3
-rw-r--r--src/plugin.c10
-rw-r--r--src/presence-cache.c167
-rw-r--r--src/presence-cache.h2
-rw-r--r--src/presence.c2
-rw-r--r--src/private-tubes-factory.c882
-rw-r--r--src/private-tubes-factory.h10
-rw-r--r--src/protocol.c25
-rw-r--r--src/protocol.h2
-rw-r--r--src/request-pipeline.c4
-rw-r--r--src/room-config.c1
-rw-r--r--src/room-config.h2
-rw-r--r--src/roomlist-channel.c17
-rw-r--r--src/roomlist-channel.h2
-rw-r--r--src/roomlist-manager.c11
-rw-r--r--src/roster.c83
-rw-r--r--src/roster.h2
-rw-r--r--src/search-channel.c48
-rw-r--r--src/search-channel.h2
-rw-r--r--src/search-manager.c18
-rw-r--r--src/server-sasl-channel.c253
-rw-r--r--src/server-sasl-channel.h5
-rw-r--r--src/server-tls-channel.c11
-rw-r--r--src/server-tls-channel.h2
-rw-r--r--src/server-tls-manager.c5
-rw-r--r--src/server-tls-manager.h3
-rw-r--r--src/tls-certificate.c8
-rw-r--r--src/tls-certificate.h2
-rw-r--r--src/tube-dbus.c117
-rw-r--r--src/tube-dbus.h8
-rw-r--r--src/tube-iface.c9
-rw-r--r--src/tube-iface.h2
-rw-r--r--src/tube-stream.c106
-rw-r--r--src/tube-stream.h7
-rw-r--r--src/tubes-channel.c2398
-rw-r--r--src/tubes-channel.h93
-rw-r--r--src/types.h2
-rw-r--r--src/util.c74
-rw-r--r--src/util.h12
-rw-r--r--src/vcard-manager.c619
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/README5
-rw-r--r--tests/test-base64.c106
-rw-r--r--tests/test-handles.c8
-rw-r--r--tests/tp-error-from-wocky.c2
-rw-r--r--tests/twisted/Makefile.am9
-rw-r--r--tests/twisted/caps/advertise-contact-caps.py23
-rw-r--r--tests/twisted/caps/jingle-caps.py51
-rw-r--r--tests/twisted/cm/protocol.py5
-rw-r--r--tests/twisted/console.py14
-rw-r--r--tests/twisted/constants.py14
-rw-r--r--tests/twisted/file-transfer/file_transfer_helper.py12
-rw-r--r--tests/twisted/gabbletest.py39
-rw-r--r--tests/twisted/jingle-share/file_transfer_helper.py12
-rw-r--r--tests/twisted/jingle-share/jingleshareutils.py7
-rw-r--r--tests/twisted/jingle-share/test-multift.py62
-rw-r--r--tests/twisted/jingle/call-muc-cancel.py4
-rw-r--r--tests/twisted/jingle/call-muc-re-re-request.py16
-rw-r--r--tests/twisted/jingle/decloak-peer.py22
-rw-r--r--tests/twisted/jingle/google-relay.py20
-rw-r--r--tests/twisted/jingle/incoming-gmail-modern-jingle.py9
-rw-r--r--tests/twisted/jingle/jingletest.py227
-rw-r--r--tests/twisted/jingle/jingletest2.py27
-rw-r--r--tests/twisted/jingle/outgoing-ensure.py7
-rw-r--r--tests/twisted/jingle/outgoing-many-streams.py27
-rw-r--r--tests/twisted/jingle/payload-types.py47
-rw-r--r--tests/twisted/jingle/stream-handler-error.py8
-rw-r--r--tests/twisted/jingle/stun-server.py213
-rw-r--r--tests/twisted/jingle/test-wait-for-caps-incomplete.py20
-rw-r--r--tests/twisted/jingle/test-wait-for-caps.py31
-rw-r--r--tests/twisted/jingle/unknown-session.py38
-rw-r--r--tests/twisted/main-debug.c64
-rw-r--r--tests/twisted/muc/chat-states.py108
-rw-r--r--tests/twisted/muc/only-text-when-needed.py416
-rw-r--r--tests/twisted/muc/send-error.py122
-rw-r--r--tests/twisted/mucutil.py2
-rw-r--r--tests/twisted/ns.py3
-rw-r--r--tests/twisted/presence/__init__.py0
-rw-r--r--tests/twisted/presence/invisible_xep_0126.py60
-rw-r--r--tests/twisted/run-test.sh.in19
-rw-r--r--tests/twisted/sasl/abort.py174
-rw-r--r--tests/twisted/sasl/saslutil.py31
-rw-r--r--tests/twisted/servicetest.py21
-rw-r--r--tests/twisted/test-resolver.h1
-rw-r--r--tests/twisted/text/receipts.py197
-rw-r--r--tests/twisted/text/test-chat-state.py95
-rw-r--r--tests/twisted/tls/server-tls-channel.py16
-rw-r--r--tests/twisted/tools/exec-with-log.sh.in2
-rw-r--r--tests/twisted/tubes/accept-muc-dbus-tube.py19
-rw-r--r--tests/twisted/tubes/accept-muc-stream-tube.py78
-rw-r--r--tests/twisted/tubes/accept-private-dbus-tube.py59
-rw-r--r--tests/twisted/tubes/accept-private-stream-tube.py139
-rw-r--r--tests/twisted/tubes/check-create-tube-return.py24
-rw-r--r--tests/twisted/tubes/close-muc-with-closed-tube.py49
-rw-r--r--tests/twisted/tubes/crash-on-list-channels.py62
-rw-r--r--tests/twisted/tubes/ensure-si-tube.py66
-rw-r--r--tests/twisted/tubes/muc-presence.py19
-rw-r--r--tests/twisted/tubes/muctubeutil.py89
-rw-r--r--tests/twisted/tubes/offer-muc-dbus-tube.py230
-rw-r--r--tests/twisted/tubes/offer-muc-stream-tube.py218
-rw-r--r--tests/twisted/tubes/offer-no-caps.py22
-rw-r--r--tests/twisted/tubes/offer-private-dbus-tube.py126
-rw-r--r--tests/twisted/tubes/offer-private-stream-tube.py180
-rw-r--r--tests/twisted/tubes/test-get-available-tubes.py62
-rw-r--r--tests/twisted/tubes/test-socks5-muc.py24
-rw-r--r--tests/twisted/tubes/tubetestutil.py18
-rw-r--r--tests/twisted/vcard/clear-avatar.py27
-rw-r--r--tests/twisted/vcard/overlapping-sets.py15
-rw-r--r--tests/twisted/vcard/set-avatar.py55
-rw-r--r--tests/twisted/vcard/set-set-disconnect.py8
-rw-r--r--tests/twisted/vcard/supported-fields.py1
-rw-r--r--tests/twisted/vcard/test-vcard-race.py6
-rw-r--r--tools/Makefile.am59
-rw-r--r--tools/c-constants-gen.py37
-rw-r--r--tools/check-c-style.sh7
-rw-r--r--tools/flymake.mk4
-rw-r--r--tools/git-which-branch.sh25
-rw-r--r--tools/glib-client-gen.py1269
-rw-r--r--tools/glib-client-marshaller-gen.py60
-rw-r--r--tools/glib-errors-check-gen.py58
-rw-r--r--tools/glib-errors-str-gen.py83
-rw-r--r--tools/glib-ginterface-gen.py25
-rw-r--r--tools/glib-gtypes-generator.py28
-rw-r--r--tools/glib-interfaces-gen.py22
-rw-r--r--tools/glib-signals-marshal-gen.py55
-rw-r--r--tools/gobject-foo.py90
-rw-r--r--tools/lcov.am1
-rw-r--r--tools/libtpcodegen.py14
-rw-r--r--tools/make-version-script.py208
-rw-r--r--tools/manager-file.py187
-rw-r--r--tools/shave.mk1
-rw-r--r--tools/telepathy-glib-env.in9
-rw-r--r--tools/telepathy-glib.supp390
-rwxr-xr-xtools/test-wrapper.sh30
-rw-r--r--tools/valgrind.mk13
-rwxr-xr-xtools/with-session-bus.sh100
254 files changed, 9014 insertions, 18519 deletions
diff --git a/NEWS b/NEWS
index f3e8ff0b7..67b1ece9c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,14 +1,38 @@
-telepathy-gabble 0.16.7 (UNRELEASED)
+telepathy-gabble 0.17.6 (UNRELEASED)
====================================
...
-telepathy-gabble 0.16.6 (2013-05-30)
+telepathy-gabble 0.17.5 (2013-06-06)
====================================
-The “repeated gas boiler replacement” release.
+The “4.5kg of laptops” release.
-This release fixes a man-in-the-middle attack. You should upgrade.
+Dependencies:
+
+• GLib 2.32 is now directly required. It was already indirectly required
+ by telepathy-glib 0.19.x.
+
+Fixes:
+
+• update Wocky:
+ · fd.o #65131: interoperate with non-XMPP-Core-compliant Jingle IQs
+ sent by Google's webmail UI (Simon)
+ · improve reference-counting for better stability (Simon)
+
+• fd.o #65296: initialize libdbus for thread-safety (Simon)
+
+• fd.o #64285: avoid running the same commands twice in parallel when doing a
+ highly parallel build (Simon)
+
+• fd.o #49595: disable an unreliable test-case (Simon)
+
+telepathy-gabble 0.17.4 (2013-05-30)
+====================================
+
+The “unattainably high curry standards” release.
+
+This development release fixes the same man-in-the-middle attack as 0.16.6.
If you use an unencrypted connection to a "legacy Jabber" (pre-XMPP)
server, this version of Gabble will not connect until you make
@@ -20,18 +44,27 @@ one of these configuration changes:
Fixes:
-• fd.o #65036 (CVE-2013-1431): update Wocky to respect the tls-required
- flag on legacy Jabber servers (Simon)
+• update Wocky:
+ · fd.o #61792: fix linking an example program with ld versions that
+ default to --no-copy-dt-needed-entries
+ · fd.o #65036 (CVE-2013-1431): update Wocky to respect the tls-required
+ flag on legacy Jabber servers
• fd.o #63119: improve regression tests' isolation from the session bus
(Simon)
-telepathy-gabble 0.16.5 (2013-03-01)
+• fd.o #64319: consider the <URL> field to be "supported" on Google servers
+ (it's currently read-only and contains a Google+ URL) (Xavier)
+
+• fd.o #64354: don't claim we support X-TELEPATHY-PASSWORD if we don't
+ know the username (Xavier)
+
+telepathy-gabble 0.17.3 (2013-03-01)
====================================
-The “In Actuality You Are A Gigantic, Bloodthirsty Grizzly Bear”
-release. This fixes a remotely-triggered denial-of-service bug. You
-should upgrade.
+The “less resplendent backup ruffs” release. This includes the fixes
+from telepathy-gabble 0.16.5, including fixing a remotely-triggered
+denial-of-service bug. You should upgrade.
Fixes:
@@ -45,9 +78,37 @@ Fixes:
is just a NULL pointer dereference, rather than allowing the attacker
to do anything more nefarious like execute code. (wjt)
-telepathy-gabble 0.16.4 (2012-11-09)
+• fd.o#43166: handle rate-limiting by MUCs better, including disabling
+ typing notifications if we get rate-limited, and including the error
+ message from the server in the D-Bus signal so that the user interface
+ could, in principle, show it to the user. (wjt)
+
+Enhancements:
+
+• fd.o#58198: the Jingle protocol code now lives in Wocky. This should make no
+ functional difference to Gabble. (wjt)
+
+
+telepathy-gabble 0.17.2 (2012-12-07)
====================================
+Hooray! Hooray! Hooray!
+
+Dependencies:
+
+• telepathy-glib 0.19.9 is now required.
+
+Enhancements:
+
+• fd.o#54760, fd.o#57080: Gabble now uses GLib's base64 implementation
+ rather than including its own. (Heiher, Alban Browaeys)
+
+• fd.o#25961, fd.o#25385: Gabble now looks up a STUN server from the
+ _stun._udp SRV record for the user's domain. (Maiku, wjt)
+
+• fd.o#47378: XEP-0184 delivery reports are now supported. Note that
+ Empathy neither requests nor displays them. (wjt)
+
Fixes:
• fd.o#56181: don't inadvertantly disable creating Call1 channels. (rishi)
@@ -55,13 +116,33 @@ Fixes:
• fd.o#52362: hopefully, don't crash if we disconnect in the middle of trying
to change our Google Talk presence. (wjt)
-telepathy-gabble 0.16.3 (2012-09-11)
+• The Jingle code now sends back unknown-session errors correctly, as
+ mentioned on fd.o#33789. (wjt)
+
+• fd.o#57267: File transfer channels now include FileTransfer.FUTURE and
+ FileTransfer.METADATA in their Interfaces property (Daniele
+ Domenichelli)
+
+• fd.o#57521: Don't crash when connecting to the League of Legends XMPP
+ server. (wjt)
+
+• fd.o#52146: Don't crash in sympathy if the auth channel handler
+ crashes. (wjt)
+
+telepathy-gabble 0.17.1 (2012-09-11)
====================================
-Fixes:
+Dependencies:
-• Turn off deprecation warnings: we're not going to fix them on a
- stable branch (Simon)
+• telepathy-glib 0.19.7 is now required. (sorry about that)
+
+Enhancements:
+
+• fd.o#32612: Old-style Tubes channels have been removed. (Jonny)
+
+• Tube and Text channels are no longer announced together. (Jonny)
+
+Fixes:
• Make sure capability discovery works for the camera-v1 capability bundle,
avoiding an iChat bug in which it repeats failed capability discovery
@@ -69,28 +150,25 @@ Fixes:
• Fix some race conditions and other brokenness in the tests (Sjoerd)
-telepathy-gabble 0.16.2 (2012-08-14)
-====================================
-
-Fixes:
+• Make sure capability discovery works for the camera-v1 capability bundle,
+ avoiding an iChat bug in which it repeats failed capability discovery
+ requests in a rapid loop (fd.o #54634, Simon)
-• fd.o#53087 - Crash in tp_base_channel_close
+• Fix some race conditions and other brokenness in the tests (Sjoerd)
-telepathy-gabble 0.16.1 (2012-06-20)
+telepathy-gabble 0.17.0 (2012-08-14)
====================================
-Requirements:
-
-• glib 2.30 is now required.
-
-Enhancements:
+Dependencies:
-• "see-other-host" stream error is now supported. This fix connection issue
- with Windows Live XMPP server.
+• telepathy-glib 0.19.2 is now required.
-Fixes:
+Changes since 0.16.2:
-• fd.o#36998: Fail to establish a video call with Android
+• Fix calls with android devices (Marcus)
+• Implement WLM jidlookup. This makes possible to add MSN contacts using XMPP.
+ (Xavier)
+• Fix google caps parsing (Jonny)
telepathy-gabble 0.16.0 (2012-04-02)
====================================
diff --git a/configure.ac b/configure.ac
index 38b4a552e..645524a9d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,8 +8,8 @@ AC_PREREQ([2.59])
# set gabble_nano_version to 0.
m4_define([gabble_major_version], [0])
-m4_define([gabble_minor_version], [16])
-m4_define([gabble_micro_version], [6])
+m4_define([gabble_minor_version], [17])
+m4_define([gabble_micro_version], [5])
m4_define([gabble_nano_version], [1])
# Some magic
@@ -93,7 +93,6 @@ TP_COMPILER_WARNINGS([ERROR_CFLAGS], [test "x$official_release" = xno],
format-security \
init-self],
[missing-field-initializers \
- deprecated-declarations \
unused-parameter])
AC_SUBST([ERROR_CFLAGS])
@@ -296,7 +295,11 @@ PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82])
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
-PKG_CHECK_MODULES(TP_GLIB, [telepathy-glib >= 0.18.0])
+AC_DEFINE(TP_SEAL_ENABLE, [], [Prevent to use sealed variables])
+AC_DEFINE(TP_DISABLE_SINGLE_INCLUDE, [], [Disable single header include])
+AC_DEFINE(TP_VERSION_MIN_REQUIRED, TP_VERSION_0_18, [Ignore post 0.18 deprecations])
+AC_DEFINE(TP_VERSION_MAX_ALLOWED, TP_VERSION_0_20, [Prevent post 0.20 APIs])
+PKG_CHECK_MODULES(TP_GLIB, [telepathy-glib >= 0.19.9])
AC_SUBST(TP_GLIB_CFLAGS)
AC_SUBST(TP_GLIB_LIBS)
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 8e50ffbce..b435ae3f4 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -20,9 +20,6 @@ libgabble_extensions_la_SOURCES = \
extensions.h
nodist_libgabble_extensions_la_SOURCES = \
- _gen/signals-marshal.c \
- _gen/signals-marshal.h \
- _gen/signals-marshal.list \
_gen/enums.h \
_gen/enums-gtk-doc.h \
_gen/gtypes.h \
@@ -62,40 +59,37 @@ extensions.html: _gen/all.xml $(tools_dir)/doc-generator.xsl Makefile.am
$(tools_dir)/doc-generator.xsl \
$< > $@
-_gen/svc.c _gen/svc.h _gen/svc-gtk-doc.h: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py \
- Makefile.am
+_gen/svc.h: _gen/svc.c
+ @: # do nothing, output as a side-effect
+_gen/svc-gtk-doc.h: _gen/svc.c
+ @: # do nothing, output as a side-effect
+_gen/svc.c: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py Makefile.am
$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \
- --filename=_gen/svc --signal-marshal-prefix=_gabble_ext \
- --include='<telepathy-glib/dbus.h>' \
- --include='"_gen/signals-marshal.h"' \
+ --filename=_gen/svc \
+ --include='<telepathy-glib/telepathy-glib.h>' \
--allow-unstable \
--not-implemented-func='tp_dbus_g_method_return_not_implemented' \
$< Gabble_Svc_
-_gen/signals-marshal.list: _gen/all.xml \
- $(tools_dir)/glib-signals-marshal-gen.py \
- Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-signals-marshal-gen.py $< > $@
-
-_gen/signals-marshal.h: _gen/signals-marshal.list Makefile.am
- $(AM_V_GEN)$(GLIB_GENMARSHAL) --header --prefix=_gabble_ext_marshal $< > $@
-
-_gen/signals-marshal.c: _gen/signals-marshal.list Makefile.am
- $(AM_V_GEN){ echo '#include "_gen/signals-marshal.h"' && \
- $(GLIB_GENMARSHAL) --body --prefix=_gabble_ext_marshal $< ; } > $@
-
-_gen/enums.h _gen/enums-gtk-doc.h: _gen/all.xml $(tools_dir)/c-constants-gen.py \
- Makefile.am
+_gen/enums-gtk-doc.h: _gen/enums.h
+ @: # do nothing, output as a side-effect
+_gen/enums.h: _gen/all.xml $(tools_dir)/c-constants-gen.py Makefile.am
$(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py Gabble $< _gen/enums
-_gen/interfaces.h _gen/interfaces-body.h _gen/interfaces-gtk-doc.h: _gen/all.xml \
- $(tools_dir)/glib-interfaces-gen.py \
- Makefile.am
+_gen/interfaces-body.h: _gen/interfaces.h
+ @: # do nothing, output as a side-effect
+_gen/interfaces-gtk-doc.h: _gen/interfaces.h
+ @: # do nothing, output as a side-effect
+_gen/interfaces.h: _gen/all.xml $(tools_dir)/glib-interfaces-gen.py Makefile.am
$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-interfaces-gen.py \
Gabble _gen/interfaces-body.h _gen/interfaces.h $<
-_gen/gtypes.h _gen/gtypes-body.h _gen/gtypes-gtk-doc.h: _gen/all.xml \
- $(tools_dir)/glib-gtypes-generator.py Makefile.am
+_gen/gtypes.h: _gen/gtypes-body.h
+ @: # do nothing, output as a side-effect
+_gen/gtypes-gtk-doc.h: _gen/gtypes-body.h
+ @: # do nothing, output as a side-effect
+
+_gen/gtypes-body.h: _gen/all.xml $(tools_dir)/glib-gtypes-generator.py Makefile.am
$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-gtypes-generator.py \
$< _gen/gtypes Gabble
diff --git a/gabble/caps-channel-manager.h b/gabble/caps-channel-manager.h
index a41bd20a6..898529fe0 100644
--- a/gabble/caps-channel-manager.h
+++ b/gabble/caps-channel-manager.h
@@ -24,8 +24,7 @@
#define GABBLE_CAPS_CHANNEL_MANAGER_H
#include <glib-object.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/handle.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "capabilities.h"
@@ -90,7 +89,6 @@ void gabble_caps_channel_manager_represent_client (
struct _GabbleCapsChannelManagerInterface {
GTypeInterface parent;
- GabbleCapsChannelManagerResetCapsFunc reset_caps;
GabbleCapsChannelManagerGetContactCapsFunc get_contact_caps;
GabbleCapsChannelManagerRepresentClientFunc represent_client;
diff --git a/gabble/connection.h b/gabble/connection.h
index 5c7bf51e7..0365699d1 100644
--- a/gabble/connection.h
+++ b/gabble/connection.h
@@ -21,8 +21,7 @@
#ifndef GABBLE_PLUGINS_CONNECTION_H
#define GABBLE_PLUGINS_CONNECTION_H
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/base-contact-list.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <gabble/capabilities-set.h>
#include <gabble/types.h>
diff --git a/gabble/plugin-connection.h b/gabble/plugin-connection.h
index 66302a746..1dd0638c2 100644
--- a/gabble/plugin-connection.h
+++ b/gabble/plugin-connection.h
@@ -22,8 +22,7 @@
#include <glib-object.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/base-contact-list.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <gabble/capabilities-set.h>
#include <gabble/types.h>
diff --git a/gabble/plugin.h b/gabble/plugin.h
index faf72a9e4..fcc7290e0 100644
--- a/gabble/plugin.h
+++ b/gabble/plugin.h
@@ -24,8 +24,7 @@
#include <glib-object.h>
#include <gio/gio.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/presence-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
#include <gabble/plugin-connection.h>
diff --git a/lib/ext/wocky b/lib/ext/wocky
-Subproject ff317a2783058e8e90fac21bd8ba18359c5401f
+Subproject 7f139058d3323d99b11667f93cb4abcb3ccc9c4
diff --git a/plugins/console.c b/plugins/console.c
index 7dde24fac..fd49d0bd8 100644
--- a/plugins/console.c
+++ b/plugins/console.c
@@ -95,7 +95,7 @@ gabble_console_plugin_create_sidecar_async (
}
else
{
- g_simple_async_result_set_error (result, TP_ERRORS,
+ g_simple_async_result_set_error (result, TP_ERROR,
TP_ERROR_NOT_IMPLEMENTED, "'%s' not implemented", sidecar_interface);
}
@@ -206,7 +206,8 @@ gabble_console_sidecar_init (GabbleConsoleSidecar *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CONSOLE_SIDECAR,
GabbleConsoleSidecarPrivate);
- self->priv->reader = wocky_xmpp_reader_new_no_stream ();
+ self->priv->reader = wocky_xmpp_reader_new_no_stream_ns (
+ WOCKY_XMPP_NS_JABBER_CLIENT);
self->priv->writer = wocky_xmpp_writer_new_no_stream ();
}
@@ -492,7 +493,7 @@ get_iq_type (const gchar *type_str,
return TRUE;
}
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Type must be 'get' or 'set', not '%s'", type_str);
return FALSE;
}
@@ -510,14 +511,15 @@ validate_jid (const gchar **to,
if (wocky_decode_jid (*to, NULL, NULL, NULL))
return TRUE;
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid (or empty) JID", *to);
return FALSE;
}
/*
* @xml: doesn't actually have to be a top-level stanza. It can be the body of
- * an IQ or whatever.
+ * an IQ or whatever. If it has no namespace, it's assumed to be in
+ * jabber:client.
*/
static gboolean
parse_me_a_stanza (
@@ -541,7 +543,7 @@ parse_me_a_stanza (
if (stanza == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Incomplete stanza! Bad person.");
return FALSE;
}
@@ -620,27 +622,20 @@ stanza_looks_coherent (
if (t == WOCKY_STANZA_TYPE_UNKNOWN)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "I don't know what a <%s/> is", top_node->name);
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ "I don't know what a <%s xmlns='%s'/> is", top_node->name,
+ g_quark_to_string (top_node->ns));
return FALSE;
}
else if (st == WOCKY_STANZA_SUB_TYPE_UNKNOWN)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"I don't know what type='%s' means",
wocky_node_get_attribute (top_node, "type"));
return FALSE;
}
- else
- {
- if (top_node->ns == g_quark_from_static_string (""))
- {
- /* So... Wocky puts an empty string in as the namespace. Greaaat. */
- top_node->ns = g_quark_from_static_string (WOCKY_XMPP_NS_JABBER_CLIENT);
- }
- return TRUE;
- }
+ return TRUE;
}
static void
diff --git a/plugins/console.h b/plugins/console.h
index 9a3d5d619..e646d067e 100644
--- a/plugins/console.h
+++ b/plugins/console.h
@@ -21,7 +21,7 @@
#include <gio/gio.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/dbus-properties-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
typedef struct _GabbleConsolePlugin GabbleConsolePlugin;
typedef struct _GabbleConsolePluginClass GabbleConsolePluginClass;
diff --git a/plugins/gateways.c b/plugins/gateways.c
index c40dc5191..eae683518 100644
--- a/plugins/gateways.c
+++ b/plugins/gateways.c
@@ -95,7 +95,7 @@ gabble_gateway_plugin_create_sidecar_async (
}
else
{
- g_simple_async_result_set_error (result, TP_ERRORS,
+ g_simple_async_result_set_error (result, TP_ERROR,
TP_ERROR_NOT_IMPLEMENTED, "'%s' not implemented", sidecar_interface);
}
@@ -422,12 +422,12 @@ register_cb (GObject *source,
switch (error->code)
{
case WOCKY_XMPP_ERROR_CONFLICT:
- g_set_error (&tp_error, TP_ERRORS, TP_ERROR_REGISTRATION_EXISTS,
+ g_set_error (&tp_error, TP_ERROR, TP_ERROR_REGISTRATION_EXISTS,
"someone else registered that username: %s", error->message);
break;
case WOCKY_XMPP_ERROR_NOT_ACCEPTABLE:
- g_set_error (&tp_error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&tp_error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"registration not acceptable: %s", error->message);
break;
@@ -487,21 +487,21 @@ gateways_register (
if (strchr (gateway, '@') != NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Gateway names cannot contain '@': %s", gateway);
goto error;
}
if (strchr (gateway, '/') != NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Gateway names cannot contain '/': %s", gateway);
goto error;
}
if (!wocky_decode_jid (gateway, NULL, &normalized_gateway, NULL))
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Invalid gateway name: %s", gateway);
goto error;
}
diff --git a/plugins/test.c b/plugins/test.c
index b145373f4..bb6b71959 100644
--- a/plugins/test.c
+++ b/plugins/test.c
@@ -1,4 +1,5 @@
#include "config.h"
+
#include "test.h"
#include <stdio.h>
@@ -113,7 +114,7 @@ test_plugin_create_sidecar_async (
/* This deliberately doesn't check for IFACE_TEST_BUGGY, to test Gabble's
* reactions to buggy plugins. :)
*/
- g_simple_async_result_set_error (result, TP_ERRORS,
+ g_simple_async_result_set_error (result, TP_ERROR,
TP_ERROR_NOT_IMPLEMENTED, "'%s' not implemented", sidecar_interface);
}
@@ -442,7 +443,7 @@ iq_cb (
if (t == WOCKY_STANZA_SUB_TYPE_RESULT)
g_simple_async_result_set_op_res_gboolean (result, TRUE);
else
- g_simple_async_result_set_error (result, TP_ERRORS,
+ g_simple_async_result_set_error (result, TP_ERROR,
TP_ERROR_NOT_AVAILABLE, "server said no!");
g_object_unref (reply);
diff --git a/src/Makefile.am b/src/Makefile.am
index c0f831d46..22a0278db 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,8 +17,6 @@ libgabble_convenience_la_SOURCES = \
addressing-util.c \
auth-manager.h \
auth-manager.c \
- base64.h \
- base64.c \
bytestream-factory.h \
bytestream-factory.c \
bytestream-ibb.h \
@@ -125,8 +123,6 @@ libgabble_convenience_la_SOURCES = \
tls-certificate.c \
tube-iface.h \
tube-iface.c \
- tubes-channel.h \
- tubes-channel.c \
tube-dbus.h \
tube-dbus.c \
tube-stream.h \
@@ -161,33 +157,12 @@ libgabble_convenience_la_SOURCES += \
call-member-content.c \
call-stream.h \
call-stream.c \
- google-relay.c \
- google-relay.h \
- jingle-content.h \
- jingle-content.c \
- jingle-factory.h \
- jingle-factory.c \
- jingle-info.c \
- jingle-info.h \
jingle-share.h \
jingle-share.c \
- jingle-media-rtp.h \
- jingle-media-rtp.c \
jingle-mint.h \
jingle-mint.c \
- jingle-session.h \
- jingle-session.c \
jingle-tp-util.h \
jingle-tp-util.c \
- jingle-transport-google.h \
- jingle-transport-google.c \
- jingle-transport-rawudp.h \
- jingle-transport-rawudp.c \
- jingle-transport-iceudp.h \
- jingle-transport-iceudp.c \
- jingle-transport-iface.h \
- jingle-transport-iface.c \
- jingle-types.h \
media-channel.h \
media-channel-internal.h \
media-channel.c \
@@ -206,7 +181,6 @@ endif
enumtype_sources = \
$(top_srcdir)/src/connection.h \
- $(top_srcdir)/src/jingle-types.h \
$(top_srcdir)/src/room-config.h \
$(top_srcdir)/src/presence.h
diff --git a/src/addressing-util.c b/src/addressing-util.c
index 0f1b3ffcc..049c566c6 100644
--- a/src/addressing-util.c
+++ b/src/addressing-util.c
@@ -85,7 +85,7 @@ gabble_uri_to_jid (const gchar *uri,
if (scheme == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid URI", uri);
goto OUT;
}
@@ -106,7 +106,7 @@ gabble_uri_to_jid (const gchar *uri,
}
else
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"'%s' URI scheme is not supported by this protocol",
scheme);
goto OUT;
@@ -137,7 +137,7 @@ gabble_jid_to_uri (const gchar *scheme,
if (!wocky_decode_jid (jid, &node, &domain, &resource))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid JID", jid);
return NULL;
}
@@ -234,7 +234,7 @@ gabble_vcard_address_to_jid (const gchar *vcard_field,
if (gabble_error != NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is an invalid address: %s", vcard_address,
gabble_error->message);
g_error_free (gabble_error);
@@ -249,7 +249,7 @@ gabble_vcard_address_to_jid (const gchar *vcard_field,
s++;
if (G_UNLIKELY (*s != '\0'))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is an invalid facebook chat address", vcard_address);
goto OUT;
}
@@ -258,7 +258,7 @@ gabble_vcard_address_to_jid (const gchar *vcard_field,
}
else
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"'%s' vCard field is not supported by this protocol", vcard_field);
}
@@ -286,7 +286,7 @@ gabble_jid_to_vcard_address (const gchar *vcard_field,
if (gabble_error != NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is an invalid address: %s", jid,
gabble_error->message);
g_error_free (gabble_error);
@@ -312,13 +312,13 @@ gabble_jid_to_vcard_address (const gchar *vcard_field,
s++;
if (G_UNLIKELY (*s != '\0'))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is an invalid facebook chat address", jid);
}
}
else
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is an invalid facebook chat address", jid);
}
@@ -326,7 +326,7 @@ gabble_jid_to_vcard_address (const gchar *vcard_field,
}
else
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"'%s' vCard field is not supported by this protocol", vcard_field);
}
@@ -438,7 +438,7 @@ gabble_parse_xmpp_uri (const gchar *uri,
if (scheme == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid URI", uri);
goto OUT;
}
@@ -447,7 +447,7 @@ gabble_parse_xmpp_uri (const gchar *uri,
if (!wocky_decode_jid (jid, &tmp_node, &tmp_domain, &tmp_resource))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid XMPP URI", uri);
goto OUT;
}
@@ -458,7 +458,7 @@ gabble_parse_xmpp_uri (const gchar *uri,
unescaped_node = g_uri_unescape_string (tmp_node, NULL);
if (unescaped_node == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid XMPP URI", uri);
goto OUT;
}
@@ -468,7 +468,7 @@ gabble_parse_xmpp_uri (const gchar *uri,
unescaped_domain = g_uri_unescape_string (tmp_domain, NULL);
if (unescaped_domain == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid XMPP URI", uri);
goto OUT;
}
@@ -478,7 +478,7 @@ gabble_parse_xmpp_uri (const gchar *uri,
unescaped_resource = g_uri_unescape_string (tmp_resource, NULL);
if (unescaped_resource == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid XMPP URI", uri);
goto OUT;
}
@@ -491,7 +491,7 @@ gabble_parse_xmpp_uri (const gchar *uri,
if (gabble_error != NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid XMPP URI: %s", uri,
gabble_error->message);
g_error_free (gabble_error);
@@ -500,7 +500,7 @@ gabble_parse_xmpp_uri (const gchar *uri,
if (!wocky_decode_jid (normalized_jid, node, domain, resource))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is not a valid XMPP URI", uri);
goto OUT;
}
diff --git a/src/addressing-util.h b/src/addressing-util.h
index 9835e0d70..378d1fe78 100644
--- a/src/addressing-util.h
+++ b/src/addressing-util.h
@@ -20,7 +20,7 @@
#ifndef __GABBLE_UTIL_ADDRESSING_H__
#define __GABBLE_UTIL_ADDRESSING_H__
-#include <telepathy-glib/handle-repo-dynamic.h>
+#include <telepathy-glib/telepathy-glib.h>
const gchar * const * gabble_get_addressable_uri_schemes (void);
diff --git a/src/auth-manager.c b/src/auth-manager.c
index 57a8bbd62..ad60d0883 100644
--- a/src/auth-manager.c
+++ b/src/auth-manager.c
@@ -20,9 +20,8 @@
#include "config.h"
#include "auth-manager.h"
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
@@ -54,6 +53,7 @@ typedef struct {
gchar *name;
GHashTable *details;
TpConnectionStatusReason reason;
+ GError *wocky_error;
} SavedError;
struct _GabbleAuthManagerPrivate
@@ -62,7 +62,10 @@ struct _GabbleAuthManagerPrivate
GabbleServerSaslChannel *channel;
gulong closed_id;
- gboolean falling_back;
+ /* TRUE if we are authenticating using our parent class's methods (because we
+ * have a username and password).
+ */
+ gboolean chaining_up;
GSList *mechanisms;
gchar *server;
@@ -109,7 +112,7 @@ static void
auth_channel_closed_cb (GabbleServerSaslChannel *channel,
GabbleAuthManager *self)
{
- SavedError tmp = { NULL, NULL, 0 };
+ SavedError tmp = { NULL, NULL, 0, NULL };
tp_channel_manager_emit_channel_closed_for_object (self,
TP_EXPORTABLE_CHANNEL (channel));
@@ -118,7 +121,7 @@ auth_channel_closed_cb (GabbleServerSaslChannel *channel,
/* this is our last chance to find out why it failed */
if (gabble_server_sasl_channel_get_failure_details (channel,
- &tmp.name, &tmp.details, &tmp.reason))
+ &tmp.name, &tmp.details, &tmp.reason, &tmp.wocky_error))
self->priv->error = g_slice_dup (SavedError, &tmp);
g_signal_handler_disconnect (self->priv->channel, self->priv->closed_id);
@@ -218,7 +221,7 @@ gabble_auth_manager_set_property (GObject *object,
}
static void
-gabble_auth_manager_start_fallback_cb (GObject *self_object,
+gabble_auth_manager_start_parent_cb (GObject *self_object,
GAsyncResult *result,
gpointer user_data)
{
@@ -261,7 +264,7 @@ gabble_auth_manager_start_auth_cb (GObject *channel,
/* restart authentication using our own base class */
g_assert (start_data->initial_response != NULL);
- self->priv->falling_back = TRUE;
+ self->priv->chaining_up = TRUE;
WOCKY_AUTH_REGISTRY_CLASS (
gabble_auth_manager_parent_class)->start_auth_async_func (
WOCKY_AUTH_REGISTRY (self), self->priv->mechanisms,
@@ -270,7 +273,7 @@ gabble_auth_manager_start_auth_cb (GObject *channel,
start_data->initial_response->str,
self->priv->server,
self->priv->session_id,
- gabble_auth_manager_start_fallback_cb, user_data);
+ gabble_auth_manager_start_parent_cb, user_data);
/* we've transferred ownership of the result */
goto finally;
}
@@ -294,7 +297,7 @@ finally:
static void
gabble_auth_manager_start_auth_async (WockyAuthRegistry *registry,
- const GSList *mechanisms,
+ GSList *mechanisms,
gboolean allow_plain,
gboolean is_secure_channel,
const gchar *username,
@@ -305,6 +308,8 @@ gabble_auth_manager_start_auth_async (WockyAuthRegistry *registry,
gpointer user_data)
{
GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry);
+ GSimpleAsyncResult *result = g_simple_async_result_new ((GObject *) self,
+ callback, user_data, gabble_auth_manager_start_auth_async);
/* assumption: Wocky's API guarantees that we never have more than one
* auth request outstanding */
@@ -313,7 +318,18 @@ gabble_auth_manager_start_auth_async (WockyAuthRegistry *registry,
if (password == NULL || username == NULL)
{
GPtrArray *mech_array = g_ptr_array_new ();
- const GSList *iter;
+ GSList *iter;
+
+ if (username == NULL)
+ {
+ g_object_get (self->priv->conn,
+ "username", &self->priv->username,
+ NULL);
+ }
+ else
+ {
+ self->priv->username = g_strdup (username);
+ }
for (iter = mechanisms; iter != NULL; iter = iter->next)
{
@@ -325,7 +341,8 @@ gabble_auth_manager_start_auth_async (WockyAuthRegistry *registry,
g_ptr_array_add (mech_array, iter->data);
}
- if (wocky_auth_registry_supports_one_of (registry, mechanisms,
+ if (self->priv->username != NULL &&
+ wocky_auth_registry_supports_one_of (registry, mechanisms,
allow_plain))
g_ptr_array_add (mech_array, X_TELEPATHY_PASSWORD);
@@ -339,17 +356,6 @@ gabble_auth_manager_start_auth_async (WockyAuthRegistry *registry,
self->priv->server = g_strdup (server);
self->priv->session_id = g_strdup (session_id);
- if (username == NULL)
- {
- g_object_get (self->priv->conn,
- "username", &self->priv->username,
- NULL);
- }
- else
- {
- self->priv->username = g_strdup (username);
- }
-
self->priv->channel = gabble_server_sasl_channel_new (self->priv->conn,
(GStrv) mech_array->pdata, is_secure_channel, session_id);
g_ptr_array_unref (mech_array);
@@ -359,8 +365,7 @@ gabble_auth_manager_start_auth_async (WockyAuthRegistry *registry,
gabble_server_sasl_channel_start_auth_async (self->priv->channel,
gabble_auth_manager_start_auth_cb,
- g_simple_async_result_new ((GObject *) self,
- callback, user_data, gabble_auth_manager_start_auth_async));
+ result);
g_assert (!tp_base_channel_is_destroyed (
(TpBaseChannel *) self->priv->channel));
@@ -371,10 +376,12 @@ gabble_auth_manager_start_auth_async (WockyAuthRegistry *registry,
}
else
{
+ self->priv->chaining_up = TRUE;
WOCKY_AUTH_REGISTRY_CLASS (
gabble_auth_manager_parent_class)->start_auth_async_func (
registry, mechanisms, allow_plain, is_secure_channel,
- username, password, server, session_id, callback, user_data);
+ username, password, server, session_id,
+ gabble_auth_manager_start_parent_cb, result);
}
}
@@ -386,19 +393,31 @@ gabble_auth_manager_start_auth_finish (WockyAuthRegistry *registry,
{
GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry);
- if (self->priv->channel != NULL)
- {
- wocky_implement_finish_copy_pointer (self,
- gabble_auth_manager_start_auth_async,
- wocky_auth_registry_start_data_dup, start_data);
- }
+ wocky_implement_finish_copy_pointer (self,
+ gabble_auth_manager_start_auth_async,
+ wocky_auth_registry_start_data_dup, start_data);
+}
+
+static void
+channel_challenge_cb (
+ GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GabbleServerSaslChannel *channel = GABBLE_SERVER_SASL_CHANNEL (source);
+ GSimpleAsyncResult *our_result = G_SIMPLE_ASYNC_RESULT (user_data);
+ GString *response_data = NULL;
+ GError *error = NULL;
+
+ if (gabble_server_sasl_channel_challenge_finish (channel, result,
+ &response_data, &error))
+ g_simple_async_result_set_op_res_gpointer (our_result, response_data,
+ (GDestroyNotify) wocky_g_string_free);
else
- {
- return WOCKY_AUTH_REGISTRY_CLASS
- (gabble_auth_manager_parent_class)->start_auth_finish_func (
- registry, result, start_data, error);
- }
+ g_simple_async_result_take_error (our_result, error);
+ g_simple_async_result_complete (our_result);
+ g_object_unref (our_result);
}
static void
@@ -409,17 +428,31 @@ gabble_auth_manager_challenge_async (WockyAuthRegistry *registry,
{
GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry);
- if (self->priv->channel != NULL && !self->priv->falling_back)
- {
- gabble_server_sasl_channel_challenge_async (self->priv->channel,
- challenge_data, callback, user_data);
- }
- else
+ if (self->priv->chaining_up)
{
WOCKY_AUTH_REGISTRY_CLASS (
gabble_auth_manager_parent_class)->challenge_async_func (
registry, challenge_data, callback, user_data);
}
+ else
+ {
+ GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self),
+ callback, user_data, gabble_auth_manager_challenge_async);
+
+ if (self->priv->channel != NULL)
+ {
+ gabble_server_sasl_channel_challenge_async (self->priv->channel,
+ challenge_data, channel_challenge_cb, result);
+ }
+ else
+ {
+ g_assert (self->priv->error != NULL);
+
+ g_simple_async_result_set_from_error (result, self->priv->error->wocky_error);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ }
+ }
}
static gboolean
@@ -430,36 +463,110 @@ gabble_auth_manager_challenge_finish (WockyAuthRegistry *registry,
{
GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry);
- if (self->priv->channel != NULL && !self->priv->falling_back)
- {
- return gabble_server_sasl_channel_challenge_finish (self->priv->channel,
- result, response, error);
- }
- else
+ if (self->priv->chaining_up)
{
return WOCKY_AUTH_REGISTRY_CLASS
(gabble_auth_manager_parent_class)->challenge_finish_func (
registry, result, response, error);
}
+ else
+ {
+ wocky_implement_finish_copy_pointer (self,
+ gabble_auth_manager_challenge_async,
+ wocky_g_string_dup, response);
+ }
}
static void
-gabble_auth_manager_success_async (WockyAuthRegistry *registry,
- GAsyncReadyCallback callback,
+channel_success_cb (
+ GObject *source,
+ GAsyncResult *result,
gpointer user_data)
{
- GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry);
+ GabbleServerSaslChannel *channel = GABBLE_SERVER_SASL_CHANNEL (source);
+ GSimpleAsyncResult *our_result = G_SIMPLE_ASYNC_RESULT (user_data);
+ GError *error = NULL;
- if (self->priv->channel != NULL)
+ if (!gabble_server_sasl_channel_success_finish (channel, result, &error))
+ g_simple_async_result_take_error (our_result, error);
+
+ g_simple_async_result_complete (our_result);
+ g_object_unref (our_result);
+}
+
+static void
+gabble_auth_manager_channel_success (
+ GabbleAuthManager *self,
+ GSimpleAsyncResult *our_result,
+ gboolean need_idle)
+{
+ GabbleAuthManagerPrivate *priv = self->priv;
+
+ if (priv->channel != NULL)
{
gabble_server_sasl_channel_success_async (self->priv->channel,
- callback, user_data);
+ channel_success_cb, our_result);
+ return;
+ }
+
+ if (priv->error != NULL)
+ g_simple_async_result_set_from_error (our_result, priv->error->wocky_error);
+
+ if (need_idle)
+ g_simple_async_result_complete_in_idle (our_result);
+ else
+ g_simple_async_result_complete (our_result);
+
+ g_object_unref (our_result);
+}
+
+static void
+gabble_auth_manager_success_parent_cb (
+ GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GabbleAuthManager *self = GABBLE_AUTH_MANAGER (source);
+ WockyAuthRegistry *registry = WOCKY_AUTH_REGISTRY (source);
+ GSimpleAsyncResult *our_result = G_SIMPLE_ASYNC_RESULT (user_data);
+ GError *error = NULL;
+
+ if (!WOCKY_AUTH_REGISTRY_CLASS (gabble_auth_manager_parent_class)->
+ success_finish_func (registry, result, &error))
+ {
+ g_simple_async_result_take_error (our_result, error);
+ g_simple_async_result_complete (our_result);
+ g_object_unref (our_result);
}
else
{
+ gabble_auth_manager_channel_success (self, our_result, FALSE);
+ }
+}
+
+static void
+gabble_auth_manager_success_async (WockyAuthRegistry *registry,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry);
+ GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self),
+ callback, user_data, gabble_auth_manager_success_async);
+
+ /* Annoyingly, in the X-TELEPATHY-PASSWORD case we actually want to both
+ * chain up to the parent class, *and* pass the success notification out to
+ * the client for consistency with other mechanisms.
+ */
+
+ if (self->priv->chaining_up)
+ {
WOCKY_AUTH_REGISTRY_CLASS (
gabble_auth_manager_parent_class)->success_async_func (
- registry, callback, user_data);
+ registry, gabble_auth_manager_success_parent_cb, result);
+ }
+ else
+ {
+ gabble_auth_manager_channel_success (self, result, TRUE);
}
}
@@ -470,17 +577,7 @@ gabble_auth_manager_success_finish (WockyAuthRegistry *registry,
{
GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry);
- if (self->priv->channel != NULL)
- {
- return gabble_server_sasl_channel_success_finish (self->priv->channel,
- result, error);
- }
- else
- {
- return WOCKY_AUTH_REGISTRY_CLASS
- (gabble_auth_manager_parent_class)->success_finish_func (
- registry, result, error);
- }
+ wocky_implement_finish_void (self, gabble_auth_manager_success_async);
}
static void
@@ -493,7 +590,8 @@ gabble_auth_manager_failure (WockyAuthRegistry *registry,
{
gabble_server_sasl_channel_fail (self->priv->channel, error);
}
- else
+
+ if (self->priv->chaining_up)
{
void (*chain_up)(WockyAuthRegistry *, GError *) =
WOCKY_AUTH_REGISTRY_CLASS (gabble_auth_manager_parent_class)->
@@ -576,7 +674,7 @@ gabble_auth_manager_get_failure_details (GabbleAuthManager *self,
if (self->priv->channel != NULL)
{
return gabble_server_sasl_channel_get_failure_details (
- self->priv->channel, dbus_error, details, reason);
+ self->priv->channel, dbus_error, details, reason, NULL);
}
else if (self->priv->error != NULL)
{
diff --git a/src/auth-manager.h b/src/auth-manager.h
index bdf7ebfe2..dad5115f9 100644
--- a/src/auth-manager.h
+++ b/src/auth-manager.h
@@ -22,7 +22,9 @@
#include <glib-object.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/handle.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
G_BEGIN_DECLS
diff --git a/src/base-call-channel.c b/src/base-call-channel.c
index 5ea79b27b..3a1c8045a 100644
--- a/src/base-call-channel.c
+++ b/src/base-call-channel.c
@@ -25,23 +25,14 @@
#include <gio/gio.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/dtmf.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/exportable-channel.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 <telepathy-glib/base-connection.h>
-#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "util.h"
#include "call-content.h"
#include "base-call-channel.h"
#include "connection.h"
-#include "jingle-session.h"
#include "jingle-tp-util.h"
#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
@@ -209,7 +200,7 @@ gabble_base_call_channel_finalize (GObject *object)
GabbleCallContent *
gabble_base_call_channel_add_content (GabbleBaseCallChannel *self,
const gchar *name,
- JingleMediaType mtype,
+ WockyJingleMediaType mtype,
TpCallContentDisposition disposition)
{
TpBaseChannel *base = TP_BASE_CHANNEL (self);
@@ -229,7 +220,7 @@ gabble_base_call_channel_add_content (GabbleBaseCallChannel *self,
"connection", tp_base_channel_get_connection (base),
"object-path", object_path,
"disposition", disposition,
- "media-type", jingle_media_type_to_tp (mtype),
+ "media-type", wocky_jingle_media_type_to_tp (mtype),
"name", name,
NULL);
diff --git a/src/base-call-channel.h b/src/base-call-channel.h
index 068b2dada..065b03786 100644
--- a/src/base-call-channel.h
+++ b/src/base-call-channel.h
@@ -23,11 +23,10 @@
#include <glib-object.h>
-#include <telepathy-glib/base-channel.h>
-#include <telepathy-glib/base-call-channel.h>
-#include <telepathy-glib/base-media-call-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+#include <wocky/wocky.h>
-#include "jingle-content.h"
#include "call-member.h"
#include "call-content.h"
@@ -84,7 +83,7 @@ GabbleCallMember * gabble_base_call_channel_get_member_from_handle (
GabbleCallContent * gabble_base_call_channel_add_content (
GabbleBaseCallChannel *self,
const gchar *name,
- JingleMediaType mtype,
+ WockyJingleMediaType mtype,
TpCallContentDisposition disposition);
void gabble_base_call_channel_remove_content (GabbleBaseCallChannel *self,
diff --git a/src/base64.c b/src/base64.c
deleted file mode 100644
index 600fa3950..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 "config.h"
-#include "base64.h"
-
-#define DEBUG_FLAG GABBLE_DEBUG_VCARD
-#include "debug.h"
-
-#include <ctype.h>
-#include <string.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 (guint len, const gchar *str, gboolean split_lines)
-{
- guint i;
- GString *tmp;
-
- /* 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 (split_lines && 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 + i)];
- c2 = encoding[GET_6_BITS_1 (str + i)];
- /* can't use GET_6_BITS_2 because str[i+2] is out of range */
- c3 = encoding[(str[i + 1] & 0x0f) << 2];
- c4 = '=';
- break;
- case 2:
- c1 = encoding[GET_6_BITS_0 (str + i)];
- /* can't use GET_6_BITS_1 because str[i+1] is out of range */
- c2 = encoding[(str[i] & 0x03) << 4];
- c3 = '=';
- c4 = '=';
- break;
- default:
- c1 = encoding[GET_6_BITS_0 (str + i)];
- c2 = encoding[GET_6_BITS_1 (str + i)];
- c3 = encoding[GET_6_BITS_2 (str + i)];
- c4 = encoding[GET_6_BITS_3 (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 35bd8f4c6..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 (guint len, const gchar *str, gboolean split_lines);
-GString *base64_decode (const gchar *str);
-
-#endif /* __BASE64_H__ */
diff --git a/src/bytestream-factory.c b/src/bytestream-factory.c
index 725f06e9f..b3d50fc2a 100644
--- a/src/bytestream-factory.c
+++ b/src/bytestream-factory.c
@@ -26,7 +26,8 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM
@@ -36,6 +37,7 @@
#include "bytestream-multiple.h"
#include "bytestream-socks5.h"
#include "connection.h"
+#include "conn-util.h"
#include "debug.h"
#include "disco.h"
#include "namespaces.h"
@@ -1298,8 +1300,6 @@ out:
g_slist_free (stream_methods);
g_free (peer_resource);
g_free (self_jid);
- if (peer_handle != 0)
- tp_handle_unref (contact_repo, peer_handle);
return TRUE;
}
@@ -1987,37 +1987,23 @@ streaminit_get_bytestream (GabbleBytestreamFactory *self,
struct _streaminit_reply_cb_data
{
+ GabbleBytestreamFactory *self;
gchar *stream_id;
GabbleBytestreamFactoryNegotiateReplyFunc func;
- gpointer user_data;
- GObject *object;
- gboolean object_alive;
+ TpWeakRef *weak_object;
};
-static void
-negotiate_stream_object_destroy_notify_cb (gpointer _data,
- GObject *where_the_object_was)
-{
- struct _streaminit_reply_cb_data *data =
- (struct _streaminit_reply_cb_data*) _data;
-
- data->object = NULL;
- data->object_alive = FALSE;
-}
-
/* Called when we receive the reply of a SI request */
static void
-streaminit_reply_cb (GabbleConnection *conn,
- WockyStanza *sent_msg,
- WockyStanza *reply_msg,
- GObject *obj,
- gpointer user_data)
+streaminit_reply_cb (
+ GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (obj);
- GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (
- self);
- struct _streaminit_reply_cb_data *data =
- (struct _streaminit_reply_cb_data*) user_data;
+ GabbleConnection *conn = GABBLE_CONNECTION (source);
+ struct _streaminit_reply_cb_data *data = user_data;
+ GabbleBytestreamFactory *self = data->self;
+ GabbleBytestreamFactoryPrivate *priv = self->priv;
GabbleBytestreamIface *bytestream = NULL;
gchar *peer_resource = NULL;
WockyNode *si;
@@ -2030,20 +2016,16 @@ streaminit_reply_cb (GabbleConnection *conn,
TpHandle room_handle;
gboolean success = FALSE;
gchar *self_jid = NULL;
+ GObject *object = tp_weak_ref_dup_object (data->weak_object);
+ WockyStanza *reply_msg = NULL;
- if (data->object != NULL)
- {
- g_object_weak_unref (data->object,
- negotiate_stream_object_destroy_notify_cb, data);
- }
-
- if (!data->object_alive)
+ if (object == NULL)
{
DEBUG ("Object which requested the bytestream was disposed. Ignoring");
goto END;
}
- if (wocky_stanza_extract_errors (reply_msg, NULL, NULL, NULL, NULL))
+ if (!conn_util_send_iq_finish (conn, result, &reply_msg, NULL))
{
DEBUG ("stream %s declined", data->stream_id);
goto END;
@@ -2139,18 +2121,21 @@ END:
}
/* user callback */
- if (data->object_alive)
- data->func (bytestream, (const gchar*) data->stream_id, reply_msg,
- data->object, data->user_data);
+ if (object != NULL)
+ {
+ data->func (bytestream, reply_msg,
+ object, tp_weak_ref_get_user_data (data->weak_object));
+ g_clear_object (&object);
+ }
if (peer_resource != NULL)
g_free (peer_resource);
- if (peer_handle != 0)
- tp_handle_unref (contact_repo, peer_handle);
-
+ g_clear_object (&reply_msg);
+ g_clear_object (&data->self);
g_free (self_jid);
g_free (data->stream_id);
+ tp_weak_ref_destroy (data->weak_object);
g_slice_free (struct _streaminit_reply_cb_data, data);
}
@@ -2162,54 +2147,37 @@ END:
* @stream_id: the stream identifier
* @func: the callback to call when we receive the answser of the request
* @user_data: user data to pass to the callback
- * @object: if non-NULL the handler will follow the lifetime of that object,
+ * @object: the handler will follow the lifetime of this object,
* which means that if the object is destroyed the callback will not be invoked.
- * @error: pointer in which to return a GError in case of failure.
*
* Send a Stream Initiation (XEP-0095) request.
*/
-gboolean
+void
gabble_bytestream_factory_negotiate_stream (GabbleBytestreamFactory *self,
WockyStanza *msg,
const gchar *stream_id,
GabbleBytestreamFactoryNegotiateReplyFunc func,
gpointer user_data,
- GObject *object,
- GError **error)
+ GObject *object)
{
GabbleBytestreamFactoryPrivate *priv;
struct _streaminit_reply_cb_data *data;
- gboolean result;
g_assert (GABBLE_IS_BYTESTREAM_FACTORY (self));
g_assert (stream_id != NULL);
g_assert (func != NULL);
+ g_assert (object != NULL);
priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self);
data = g_slice_new (struct _streaminit_reply_cb_data);
+ data->self = g_object_ref (self);
data->stream_id = g_strdup (stream_id);
data->func = func;
- data->user_data = user_data;
- data->object_alive = TRUE;
- data->object = object;
-
- if (object != NULL)
- {
- g_object_weak_ref (object, negotiate_stream_object_destroy_notify_cb,
- data);
- }
-
- result = _gabble_connection_send_with_reply (priv->conn, msg,
- streaminit_reply_cb, G_OBJECT (self), data, error);
-
- if (!result)
- {
- g_free (data->stream_id);
- g_slice_free (struct _streaminit_reply_cb_data, data);
- }
+ data->weak_object = tp_weak_ref_new (object, user_data, NULL);
- return result;
+ conn_util_send_iq_async (priv->conn, msg, NULL,
+ streaminit_reply_cb, data);
}
/*
diff --git a/src/bytestream-factory.h b/src/bytestream-factory.h
index 7a86cd4f8..76287e0d3 100644
--- a/src/bytestream-factory.h
+++ b/src/bytestream-factory.h
@@ -21,7 +21,7 @@
#define __BYTESTREAM_FACTORY_H__
#include <glib-object.h>
-#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "types.h"
#include "bytestream-iface.h"
#include "bytestream-ibb.h"
@@ -71,7 +71,7 @@ typedef struct {
} GabbleSocks5Proxy;
typedef void (* GabbleBytestreamFactoryNegotiateReplyFunc) (
- GabbleBytestreamIface *bytestream, const gchar *stream_id, WockyStanza *msg,
+ GabbleBytestreamIface *bytestream, WockyStanza *msg,
GObject *object, gpointer user_data);
GabbleBytestreamFactory *gabble_bytestream_factory_new (
@@ -97,10 +97,10 @@ WockyStanza *gabble_bytestream_factory_make_multi_accept_iq (
const gchar *full_jid, const gchar *stream_init_id,
GList *stream_methods);
-gboolean gabble_bytestream_factory_negotiate_stream (
+void gabble_bytestream_factory_negotiate_stream (
GabbleBytestreamFactory *fac, WockyStanza *msg, const gchar *stream_id,
GabbleBytestreamFactoryNegotiateReplyFunc func,
- gpointer user_data, GObject *object, GError **error);
+ gpointer user_data, GObject *object);
gchar *gabble_bytestream_factory_generate_stream_id (void);
diff --git a/src/bytestream-ibb.c b/src/bytestream-ibb.c
index bfa1b5641..c413beb6a 100644
--- a/src/bytestream-ibb.c
+++ b/src/bytestream-ibb.c
@@ -24,11 +24,11 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM
-#include "base64.h"
#include "bytestream-factory.h"
#include "bytestream-iface.h"
#include "connection.h"
@@ -124,16 +124,12 @@ gabble_bytestream_ibb_dispose (GObject *object)
{
GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (object);
GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
if (priv->dispose_has_run)
return;
priv->dispose_has_run = TRUE;
- tp_handle_unref (contact_repo, priv->peer_handle);
-
if (priv->state != GABBLE_BYTESTREAM_STATE_CLOSED)
{
gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL);
@@ -285,8 +281,6 @@ gabble_bytestream_ibb_constructor (GType type,
contact_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- tp_handle_ref (contact_repo, priv->peer_handle);
-
jid = tp_handle_inspect (contact_repo, priv->peer_handle);
if (priv->peer_resource != NULL)
@@ -511,7 +505,7 @@ send_data (GabbleBytestreamIBB *self,
send_now = remaining;
}
- encoded = base64_encode (send_now, str + sent, FALSE);
+ encoded = g_base64_encode ((const guchar *) str + sent, send_now);
seq = g_strdup_printf ("%u", priv->seq++);
iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
@@ -613,6 +607,8 @@ gabble_bytestream_ibb_receive (GabbleBytestreamIBB *self,
GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self);
WockyNode *data;
GString *str;
+ guchar *st;
+ gsize outlen;
TpHandle sender;
/* caller must have checked for this in order to know which bytestream to
@@ -638,7 +634,9 @@ gabble_bytestream_ibb_receive (GabbleBytestreamIBB *self,
/* FIXME: check sequence number */
- str = base64_decode (data->content);
+ st = g_base64_decode (data->content, &outlen);
+ str = g_string_new_len ((gchar *) st, outlen);
+ g_free (st);
if (str == NULL)
{
DEBUG ("base64 decoding failed");
diff --git a/src/bytestream-ibb.h b/src/bytestream-ibb.h
index fa1af3a2e..2d96baf12 100644
--- a/src/bytestream-ibb.h
+++ b/src/bytestream-ibb.h
@@ -22,7 +22,7 @@
#include <glib-object.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
G_BEGIN_DECLS
diff --git a/src/bytestream-muc.c b/src/bytestream-muc.c
index 4a803bc58..6c0d28e47 100644
--- a/src/bytestream-muc.c
+++ b/src/bytestream-muc.c
@@ -24,11 +24,11 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM
-#include "base64.h"
#include "bytestream-factory.h"
#include "bytestream-iface.h"
#include "connection.h"
@@ -100,16 +100,12 @@ gabble_bytestream_muc_dispose (GObject *object)
{
GabbleBytestreamMuc *self = GABBLE_BYTESTREAM_MUC (object);
GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self);
- TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM);
if (priv->dispose_has_run)
return;
priv->dispose_has_run = TRUE;
- tp_handle_unref (room_repo, priv->peer_handle);
-
if (priv->state != GABBLE_BYTESTREAM_STATE_CLOSED)
{
gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL);
@@ -228,8 +224,6 @@ gabble_bytestream_muc_constructor (GType type,
room_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM);
- tp_handle_ref (room_repo, priv->peer_handle);
-
priv->peer_jid = tp_handle_inspect (room_repo,
priv->peer_handle);
@@ -345,7 +339,7 @@ send_data_to (GabbleBytestreamMuc *self,
frag = FRAG_LAST;
}
- encoded = base64_encode (send_now, str + sent, FALSE);
+ encoded = g_base64_encode ((const guchar *) str + sent, send_now);
wocky_node_set_content (data, encoded);
switch (frag)
@@ -411,6 +405,8 @@ gabble_bytestream_muc_receive (GabbleBytestreamMuc *self,
const gchar *from;
WockyNode *data;
GString *str;
+ guchar *st;
+ gsize outlen;
TpHandle sender;
GString *buffer;
const gchar *frag_val;
@@ -459,7 +455,9 @@ gabble_bytestream_muc_receive (GabbleBytestreamMuc *self,
return;
}
- str = base64_decode (data->content);
+ st = g_base64_decode (data->content, &outlen);
+ str = g_string_new_len ((const gchar *) st, outlen);
+ g_free (st);
if (str == NULL)
{
DEBUG ("base64 decoding failed");
diff --git a/src/bytestream-muc.h b/src/bytestream-muc.h
index 06dcd2689..393410eec 100644
--- a/src/bytestream-muc.h
+++ b/src/bytestream-muc.h
@@ -22,7 +22,7 @@
#include <glib-object.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
G_BEGIN_DECLS
diff --git a/src/bytestream-multiple.c b/src/bytestream-multiple.c
index 07243e1f1..49bdc5907 100644
--- a/src/bytestream-multiple.c
+++ b/src/bytestream-multiple.c
@@ -22,11 +22,12 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/interfaces.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM
-#include "base64.h"
#include "bytestream-factory.h"
#include "bytestream-iface.h"
#include "connection.h"
@@ -100,16 +101,12 @@ gabble_bytestream_multiple_dispose (GObject *object)
GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (object);
GabbleBytestreamMultiplePrivate *priv =
GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
if (priv->dispose_has_run)
return;
priv->dispose_has_run = TRUE;
- tp_handle_unref (contact_repo, priv->peer_handle);
-
if (priv->state != GABBLE_BYTESTREAM_STATE_CLOSED)
{
gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL);
@@ -263,8 +260,6 @@ gabble_bytestream_multiple_constructor (GType type,
contact_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- tp_handle_ref (contact_repo, priv->peer_handle);
-
jid = tp_handle_inspect (contact_repo, priv->peer_handle);
if (priv->peer_resource != NULL)
diff --git a/src/bytestream-socks5.c b/src/bytestream-socks5.c
index 12bd7c509..48686d35f 100644
--- a/src/bytestream-socks5.c
+++ b/src/bytestream-socks5.c
@@ -44,7 +44,9 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/interfaces.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <gibber/gibber-transport.h>
#include <gibber/gibber-tcp-transport.h>
@@ -52,10 +54,10 @@
#define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM
-#include "base64.h"
#include "bytestream-factory.h"
#include "bytestream-iface.h"
#include "connection.h"
+#include "conn-util.h"
#include "debug.h"
#include "disco.h"
#include "gabble-signals-marshal.h"
@@ -232,8 +234,6 @@ gabble_bytestream_socks5_dispose (GObject *object)
GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (object);
GabbleBytestreamSocks5Private *priv =
GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
if (priv->dispose_has_run)
return;
@@ -242,8 +242,6 @@ gabble_bytestream_socks5_dispose (GObject *object)
stop_timer (self);
- tp_handle_unref (contact_repo, priv->peer_handle);
-
if (priv->bytestream_state != GABBLE_BYTESTREAM_STATE_CLOSED)
{
gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL);
@@ -398,8 +396,6 @@ gabble_bytestream_socks5_constructor (GType type,
room_repo = tp_base_connection_get_handles (base_conn,
TP_HANDLE_TYPE_ROOM);
- tp_handle_ref (contact_repo, priv->peer_handle);
-
jid = tp_handle_inspect (contact_repo, priv->peer_handle);
if (priv->peer_resource != NULL)
@@ -766,17 +762,22 @@ target_got_connect_reply (GabbleBytestreamSocks5 *self)
}
static void
-socks5_activation_reply_cb (GabbleConnection *conn,
- WockyStanza *sent_msg,
- WockyStanza *reply_msg,
- GObject *obj,
- gpointer user_data)
+socks5_activation_reply_cb (
+ GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (user_data);
- GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (
- self);
+ TpWeakRef *weak_ref = user_data;
+ GabbleBytestreamSocks5 *self = tp_weak_ref_dup_object (weak_ref);
+ GabbleBytestreamSocks5Private *priv;
+ WockyStanza *reply_msg = NULL;
+
+ tp_weak_ref_destroy (weak_ref);
+ if (self == NULL)
+ return;
+ priv = self->priv;
- if (wocky_stanza_extract_errors (reply_msg, NULL, NULL, NULL, NULL))
+ if (!conn_util_send_iq_finish (GABBLE_CONNECTION (source), result, &reply_msg, NULL))
{
DEBUG ("Activation failed");
goto activation_failed;
@@ -795,11 +796,15 @@ socks5_activation_reply_cb (GabbleConnection *conn,
g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL);
/* We can read data from the sock5 socket now */
gibber_transport_block_receiving (priv->transport, FALSE);
+ goto out;
- return;
activation_failed:
g_signal_emit_by_name (self, "connection-error");
g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL);
+
+out:
+ g_clear_object (&reply_msg);
+ g_object_unref (self);
}
static void
@@ -825,15 +830,8 @@ initiator_got_connect_reply (GabbleBytestreamSocks5 *self)
/* Block reading while waiting for the activation reply */
gibber_transport_block_receiving (priv->transport, TRUE);
- if (!_gabble_connection_send_with_reply (priv->conn, iq,
- socks5_activation_reply_cb, G_OBJECT (self), self, NULL))
- {
- DEBUG ("Sending activation IQ failed");
-
- g_signal_emit_by_name (self, "connection-error");
- g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL);
- }
-
+ conn_util_send_iq_async (priv->conn, iq, NULL,
+ socks5_activation_reply_cb, tp_weak_ref_new (self, NULL, NULL));
g_object_unref (iq);
}
@@ -1543,17 +1541,22 @@ initiator_connected_to_proxy (GabbleBytestreamSocks5 *self)
}
static void
-socks5_init_reply_cb (GabbleConnection *conn,
- WockyStanza *sent_msg,
- WockyStanza *reply_msg,
- GObject *obj,
- gpointer user_data)
+socks5_init_reply_cb (
+ GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (obj);
- GabbleBytestreamSocks5Private *priv =
- GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self);
+ TpWeakRef *weak_ref = user_data;
+ GabbleBytestreamSocks5 *self = tp_weak_ref_dup_object (weak_ref);
+ GabbleBytestreamSocks5Private *priv;
+ WockyStanza *reply_msg = NULL;
+
+ tp_weak_ref_destroy (weak_ref);
+ if (self == NULL)
+ return;
+ priv = self->priv;
- if (!wocky_stanza_extract_errors (reply_msg, NULL, NULL, NULL, NULL))
+ if (conn_util_send_iq_finish (GABBLE_CONNECTION (source), result, &reply_msg, NULL))
{
WockyNode *query, *streamhost = NULL;
const gchar *jid;
@@ -1590,7 +1593,7 @@ socks5_init_reply_cb (GabbleConnection *conn,
priv->proxy_jid = g_strdup (jid);
initiator_connected_to_proxy (self);
- return;
+ goto out;
}
/* No proxy used */
@@ -1609,7 +1612,7 @@ socks5_init_reply_cb (GabbleConnection *conn,
g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL);
/* We can read data from the sock5 socket now */
gibber_transport_block_receiving (priv->transport, FALSE);
- return;
+ goto out;
}
socks5_init_error:
@@ -1617,6 +1620,10 @@ socks5_init_error:
g_signal_emit_by_name (self, "connection-error");
g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL);
+
+out:
+ g_clear_object (&reply_msg);
+ g_object_unref (self);
}
#ifdef G_OS_WIN32
@@ -1866,49 +1873,19 @@ new_connection_cb (GibberListener *listener,
}
/*
- * gabble_bytestream_socks5_initiate
- *
- * Implements gabble_bytestream_iface_initiate on GabbleBytestreamIface
+ * Consumes @ips.
*/
-static gboolean
-gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
+static void
+send_streamhosts (
+ GabbleBytestreamSocks5 *self,
+ GSList *ips,
+ gint port_num)
{
- GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (iface);
- GabbleBytestreamSocks5Private *priv =
- GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self);
+ GabbleBytestreamSocks5Private *priv = self->priv;
gchar *port;
- gint port_num;
WockyStanza *msg;
WockyNode *query_node;
- GSList *ips, *ip;
-
- if (priv->bytestream_state != GABBLE_BYTESTREAM_STATE_INITIATING)
- {
- DEBUG ("bytestream is not is the initiating state (state %d)",
- priv->bytestream_state);
- return FALSE;
- }
- ips = get_local_interfaces_ips ();
- if (ips == NULL)
- {
- DEBUG ("Can't get IP addresses");
- return FALSE;
- }
-
- g_assert (priv->listener == NULL);
- priv->listener = gibber_listener_new ();
-
- g_signal_connect (priv->listener, "new-connection",
- G_CALLBACK (new_connection_cb), self);
-
- if (!gibber_listener_listen_tcp (priv->listener, 0, NULL))
- {
- DEBUG ("can't listen for incoming connection");
- return FALSE;
- }
-
- port_num = gibber_listener_get_port (priv->listener);
port = g_strdup_printf ("%d", port_num);
msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
@@ -1920,17 +1897,17 @@ gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
'*', &query_node,
')', NULL);
- for (ip = ips; ip != NULL; ip = g_slist_next (ip))
+ for (; port_num != 0 && ips != NULL; ips = g_slist_delete_link (ips, ips))
{
WockyNode *node = wocky_node_add_child (query_node, "streamhost");
wocky_node_set_attributes (node,
"jid", priv->self_full_jid,
- "host", ip->data,
+ "host", ips->data,
"port", port,
NULL);
- g_free (ip->data);
+ g_free (ips->data);
}
g_slist_free (ips);
@@ -1958,7 +1935,7 @@ gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
NULL);
g_free (portstr);
}
- g_slist_free (proxies);
+ g_slist_free (proxies);
}
else
{
@@ -1968,17 +1945,57 @@ gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
priv->socks5_state = SOCKS5_STATE_INITIATOR_OFFER_SENT;
- if (!_gabble_connection_send_with_reply (priv->conn, msg,
- socks5_init_reply_cb, G_OBJECT (self), NULL, NULL))
- {
- DEBUG ("Error when sending Socks5 init stanza");
+ conn_util_send_iq_async (priv->conn, msg, NULL,
+ socks5_init_reply_cb, tp_weak_ref_new (self, NULL, NULL));
+ g_object_unref (msg);
+}
+
+/*
+ * gabble_bytestream_socks5_initiate
+ *
+ * Implements gabble_bytestream_iface_initiate on GabbleBytestreamIface
+ */
+static gboolean
+gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface)
+{
+ GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (iface);
+ GabbleBytestreamSocks5Private *priv =
+ GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self);
+ GSList *ips;
+ guint port_num = 0;
- g_object_unref (msg);
+ if (priv->bytestream_state != GABBLE_BYTESTREAM_STATE_INITIATING)
+ {
+ DEBUG ("bytestream is not is the initiating state (state %d)",
+ priv->bytestream_state);
return FALSE;
}
- g_object_unref (msg);
+ ips = get_local_interfaces_ips ();
+ if (ips == NULL)
+ {
+ DEBUG ("Can't get IP addresses; will send empty offer.");
+ }
+ else
+ {
+ g_assert (priv->listener == NULL);
+ priv->listener = gibber_listener_new ();
+
+ g_signal_connect (priv->listener, "new-connection",
+ G_CALLBACK (new_connection_cb), self);
+
+ if (!gibber_listener_listen_tcp (priv->listener, 0, NULL))
+ {
+ DEBUG ("can't listen for incoming connection; will send empty offer.");
+ g_slist_foreach (ips, (GFunc) g_free, NULL);
+ g_slist_free (ips);
+ ips = NULL;
+ }
+
+ port_num = gibber_listener_get_port (priv->listener);
+ }
+ send_streamhosts (self, ips, port_num);
return TRUE;
}
diff --git a/src/bytestream-socks5.h b/src/bytestream-socks5.h
index 524812f32..f3704e469 100644
--- a/src/bytestream-socks5.h
+++ b/src/bytestream-socks5.h
@@ -24,7 +24,7 @@
#include <glib-object.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
G_BEGIN_DECLS
diff --git a/src/call-channel.c b/src/call-channel.c
index 8e7b4bce2..6e247aa0d 100644
--- a/src/call-channel.c
+++ b/src/call-channel.c
@@ -26,20 +26,15 @@
#include <gio/gio.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+#include <wocky/wocky.h>
#include "util.h"
#include "call-channel.h"
#include "call-content.h"
#include "connection.h"
-#include "jingle-session.h"
#include "jingle-tp-util.h"
#include "presence-cache.h"
@@ -49,15 +44,15 @@
static void async_initable_iface_init (GAsyncInitableIface *iface);
-static void call_session_state_changed_cb (GabbleJingleSession *session,
+static void call_session_state_changed_cb (WockyJingleSession *session,
GParamSpec *param, GabbleCallChannel *self);
static void call_member_content_added_cb (GabbleCallMember *member,
GabbleCallMemberContent *content, GabbleCallChannel *self);
static void call_member_content_removed_cb (GabbleCallMember *member,
GabbleCallMemberContent *mcontent,
GabbleBaseCallChannel *self);
-static void call_session_terminated_cb (GabbleJingleSession *session,
- gboolean locally_terminated, JingleReason termination_reason,
+static void call_session_terminated_cb (WockyJingleSession *session,
+ gboolean locally_terminated, WockyJingleReason termination_reason,
gchar *reason_text, GabbleCallChannel *self);
static void call_channel_accept (TpBaseMediaCallChannel *channel);
@@ -91,7 +86,7 @@ struct _GabbleCallChannelPrivate
/* Our only call member, owned by the base channel */
GabbleCallMember *member;
- GabbleJingleSession *session;
+ WockyJingleSession *session;
};
static void
@@ -227,9 +222,9 @@ gabble_call_channel_class_init (
tp_base_media_call_class->hold_state_changed =
call_channel_hold_state_changed;
- param_spec = g_param_spec_object ("session", "GabbleJingleSession object",
+ param_spec = g_param_spec_object ("session", "WockyJingleSession object",
"Jingle session associated with this media channel object.",
- GABBLE_TYPE_JINGLE_SESSION,
+ WOCKY_TYPE_JINGLE_SESSION,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_SESSION, param_spec);
}
@@ -258,8 +253,8 @@ gabble_call_channel_finalize (GObject *object)
}
static void
-call_session_terminated_cb (GabbleJingleSession *session,
- gboolean locally_terminated, JingleReason termination_reason,
+call_session_terminated_cb (WockyJingleSession *session,
+ gboolean locally_terminated, WockyJingleReason termination_reason,
gchar *reason_text, GabbleCallChannel *self)
{
TpHandle actor;
@@ -283,66 +278,66 @@ call_session_terminated_cb (GabbleJingleSession *session,
switch (termination_reason)
{
- case JINGLE_REASON_UNKNOWN:
+ case WOCKY_JINGLE_REASON_UNKNOWN:
call_reason = TP_CALL_STATE_CHANGE_REASON_UNKNOWN;
break;
- case JINGLE_REASON_BUSY:
+ case WOCKY_JINGLE_REASON_BUSY:
call_reason = TP_CALL_STATE_CHANGE_REASON_BUSY;
break;
- case JINGLE_REASON_CANCEL:
+ case WOCKY_JINGLE_REASON_CANCEL:
if (locally_terminated)
call_reason = TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED;
else
call_reason = TP_CALL_STATE_CHANGE_REASON_REJECTED;
break;
- case JINGLE_REASON_CONNECTIVITY_ERROR:
+ case WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR:
call_reason = TP_CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR;
break;
- case JINGLE_REASON_FAILED_APPLICATION:
+ case WOCKY_JINGLE_REASON_FAILED_APPLICATION:
call_reason = TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR;
dbus_detail = TP_ERROR_STR_MEDIA_CODECS_INCOMPATIBLE;
break;
- case JINGLE_REASON_GENERAL_ERROR:
+ case WOCKY_JINGLE_REASON_GENERAL_ERROR:
call_reason = TP_CALL_STATE_CHANGE_REASON_SERVICE_ERROR;
break;
- case JINGLE_REASON_GONE:
+ case WOCKY_JINGLE_REASON_GONE:
/* This one is only in the media channel, we don't have a
* Call reason to match */
call_reason = TP_CALL_STATE_CHANGE_REASON_UNKNOWN;
break;
- case JINGLE_REASON_MEDIA_ERROR:
+ case WOCKY_JINGLE_REASON_MEDIA_ERROR:
call_reason = TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR;
break;
- case JINGLE_REASON_SUCCESS:
+ case WOCKY_JINGLE_REASON_SUCCESS:
call_reason = TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED;
break;
- case JINGLE_REASON_TIMEOUT:
+ case WOCKY_JINGLE_REASON_TIMEOUT:
call_reason = TP_CALL_STATE_CHANGE_REASON_NO_ANSWER;
break;
- case JINGLE_REASON_DECLINE:
+ case WOCKY_JINGLE_REASON_DECLINE:
call_reason = TP_CALL_STATE_CHANGE_REASON_REJECTED;
break;
- case JINGLE_REASON_ALTERNATIVE_SESSION:
+ case WOCKY_JINGLE_REASON_ALTERNATIVE_SESSION:
break;
- case JINGLE_REASON_UNSUPPORTED_TRANSPORTS:
+ case WOCKY_JINGLE_REASON_UNSUPPORTED_TRANSPORTS:
call_reason = TP_CALL_STATE_CHANGE_REASON_NETWORK_ERROR;
break;
- case JINGLE_REASON_FAILED_TRANSPORT:
+ case WOCKY_JINGLE_REASON_FAILED_TRANSPORT:
call_reason = TP_CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR;
dbus_detail = TP_ERROR_STR_CONNECTION_FAILED;
break;
- case JINGLE_REASON_INCOMPATIBLE_PARAMETERS:
+ case WOCKY_JINGLE_REASON_INCOMPATIBLE_PARAMETERS:
call_reason = TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR;
dbus_detail = TP_ERROR_STR_MEDIA_CODECS_INCOMPATIBLE;
break;
- case JINGLE_REASON_SECURITY_ERROR:
+ case WOCKY_JINGLE_REASON_SECURITY_ERROR:
call_reason = TP_CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR;
break;
- case JINGLE_REASON_UNSUPPORTED_APPLICATIONS:
+ case WOCKY_JINGLE_REASON_UNSUPPORTED_APPLICATIONS:
call_reason = TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR;
dbus_detail = TP_ERROR_STR_MEDIA_UNSUPPORTED_TYPE;
break;
- case JINGLE_REASON_EXPIRED:
+ case WOCKY_JINGLE_REASON_EXPIRED:
/* No matching error in our spec */
call_reason = TP_CALL_STATE_CHANGE_REASON_UNKNOWN;
break;
@@ -357,16 +352,16 @@ call_session_terminated_cb (GabbleJingleSession *session,
}
static void
-call_session_state_changed_cb (GabbleJingleSession *session,
+call_session_state_changed_cb (WockyJingleSession *session,
GParamSpec *param,
GabbleCallChannel *self)
{
TpBaseCallChannel *cbase = TP_BASE_CALL_CHANNEL (self);
- JingleState state;
+ WockyJingleState state;
g_object_get (session, "state", &state, NULL);
- if (state == JINGLE_STATE_ACTIVE && !tp_base_call_channel_is_accepted (cbase))
+ if (state == WOCKY_JINGLE_STATE_ACTIVE && !tp_base_call_channel_is_accepted (cbase))
{
tp_base_call_channel_remote_accept (cbase);
}
@@ -379,13 +374,13 @@ call_member_content_added_cb (GabbleCallMember *member,
GabbleCallChannel *self)
{
GabbleBaseCallChannel *cbase = GABBLE_BASE_CALL_CHANNEL (self);
- GabbleJingleContent *jingle_content;
+ WockyJingleContent *jingle_content;
GabbleCallContent *c;
jingle_content = gabble_call_member_content_get_jingle_content (content);
if (jingle_content == NULL ||
- gabble_jingle_content_is_created_by_us (jingle_content))
+ wocky_jingle_content_is_created_by_us (jingle_content))
return;
c = gabble_base_call_channel_add_content (cbase,
@@ -435,11 +430,11 @@ contact_is_media_capable (GabbleCallChannel *self,
*wait_ret = wait;
if (presence == NULL)
- g_set_error (error, TP_ERRORS, TP_ERROR_OFFLINE,
+ g_set_error (error, TP_ERROR, TP_ERROR_OFFLINE,
"contact %d (%s) has no presence available", handle,
tp_handle_inspect (contact_handles, handle));
else
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_CAPABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE,
"contact %d (%s) doesn't have sufficient media caps", handle,
tp_handle_inspect (contact_handles, handle));
@@ -649,7 +644,7 @@ static void
call_channel_accept (TpBaseMediaCallChannel *channel)
{
GabbleCallChannel *self = GABBLE_CALL_CHANNEL (channel);
- gabble_jingle_session_accept (self->priv->session);
+ wocky_jingle_session_accept (self->priv->session);
}
static TpBaseCallContent *
@@ -662,12 +657,12 @@ call_channel_add_content (TpBaseCallChannel *base,
GabbleCallChannel *self = GABBLE_CALL_CHANNEL (base);
GabbleCallContent *content = NULL;
GabbleCallMemberContent *mcontent;
- JingleContentSenders senders;
+ WockyJingleContentSenders senders;
gboolean initiated_by_us;
if (initial_direction == TP_MEDIA_STREAM_DIRECTION_NONE)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Jingle can not do contents with direction = NONE");
return NULL;
}
@@ -679,25 +674,25 @@ call_channel_add_content (TpBaseCallChannel *base,
{
case TP_MEDIA_STREAM_DIRECTION_SEND:
senders = initiated_by_us ?
- JINGLE_CONTENT_SENDERS_INITIATOR : JINGLE_CONTENT_SENDERS_RESPONDER;
+ WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR : WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER;
break;
case TP_MEDIA_STREAM_DIRECTION_RECEIVE:
senders = initiated_by_us ?
- JINGLE_CONTENT_SENDERS_RESPONDER : JINGLE_CONTENT_SENDERS_INITIATOR;
+ WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER : WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR;
break;
default:
case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL:
- senders = JINGLE_CONTENT_SENDERS_BOTH;
+ senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH;
}
mcontent = gabble_call_member_create_content (self->priv->member, name,
- jingle_media_type_from_tp (type), senders, error);
+ wocky_jingle_media_type_from_tp (type), senders, error);
if (mcontent != NULL)
{
content = gabble_base_call_channel_add_content (
GABBLE_BASE_CALL_CHANNEL (base),
- name, jingle_media_type_from_tp (type),
+ name, wocky_jingle_media_type_from_tp (type),
TP_CALL_CONTENT_DISPOSITION_NONE);
gabble_call_content_add_member_content (content, mcontent);
}
@@ -715,10 +710,10 @@ call_channel_hold_state_changed (TpBaseMediaCallChannel *bmcc,
{
case TP_LOCAL_HOLD_STATE_HELD:
case TP_LOCAL_HOLD_STATE_PENDING_HOLD:
- gabble_jingle_session_set_local_hold (self->priv->session, TRUE);
+ wocky_jingle_session_set_local_hold (self->priv->session, TRUE);
break;
case TP_LOCAL_HOLD_STATE_UNHELD:
- gabble_jingle_session_set_local_hold (self->priv->session, FALSE);
+ wocky_jingle_session_set_local_hold (self->priv->session, FALSE);
break;
case TP_LOCAL_HOLD_STATE_PENDING_UNHOLD:
break;
diff --git a/src/call-content.c b/src/call-content.c
index 8550b82fc..827dc2445 100644
--- a/src/call-content.c
+++ b/src/call-content.c
@@ -23,19 +23,12 @@
#include <stdio.h>
#include <stdlib.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/svc-properties-interface.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "call-member.h"
#include "call-content.h"
#include "call-stream.h"
-#include "jingle-content.h"
-#include "jingle-session.h"
-#include "jingle-media-rtp.h"
#include "jingle-tp-util.h"
#include "connection.h"
#include "util.h"
@@ -167,7 +160,7 @@ gabble_call_content_new_offer (GabbleCallContent *self,
codecs = gabble_call_member_content_get_remote_codecs (content);
for (l = codecs; l != NULL; l = g_list_next (l))
{
- JingleCodec *c = l->data;
+ WockyJingleCodec *c = l->data;
tp_call_content_media_description_append_codec (md,
c->id, c->name, c->clockrate, c->channels,
@@ -184,12 +177,12 @@ gabble_call_content_new_offer (GabbleCallContent *self,
g_free (path);
}
-JingleMediaType
+WockyJingleMediaType
gabble_call_content_get_media_type (GabbleCallContent *self)
{
TpBaseCallContent *base = TP_BASE_CALL_CONTENT (self);
- return jingle_media_type_from_tp (
+ return wocky_jingle_media_type_from_tp (
tp_base_call_content_get_media_type (base));
}
@@ -214,7 +207,7 @@ codec_array_to_list (GPtrArray *codecs)
for (i = 0; i < codecs->len ; i++)
{
- JingleCodec *c;
+ WockyJingleCodec *c;
GValueArray *va;
va = g_ptr_array_index (codecs, i);
@@ -241,7 +234,7 @@ call_content_local_media_description_updated (GabbleCallContent *self,
gpointer data)
{
GList *l;
- JingleMediaDescription *md = jingle_media_description_new ();
+ WockyJingleMediaDescription *md = wocky_jingle_media_description_new ();
md->codecs = codec_array_to_list (tp_asv_get_boxed (properties,
TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_CODECS,
@@ -250,22 +243,22 @@ call_content_local_media_description_updated (GabbleCallContent *self,
for (l = self->priv->contents; l != NULL; l = g_list_next (l))
{
GabbleCallMemberContent *c = GABBLE_CALL_MEMBER_CONTENT (l->data);
- GabbleJingleContent *j =
+ WockyJingleContent *j =
gabble_call_member_content_get_jingle_content (c);
if (j == NULL)
continue;
/* FIXME react properly on errors ? */
- jingle_media_rtp_set_local_media_description (GABBLE_JINGLE_MEDIA_RTP (j),
- jingle_media_description_copy (md), TRUE, NULL);
+ jingle_media_rtp_set_local_media_description (WOCKY_JINGLE_MEDIA_RTP (j),
+ wocky_jingle_media_description_copy (md), TRUE, NULL);
}
- jingle_media_description_free (md);
+ wocky_jingle_media_description_free (md);
}
static TpStreamTransportType
-_jingle_to_tp_transport (JingleTransportType jt)
+_jingle_to_tp_transport (WockyJingleTransportType jt)
{
switch (jt)
{
@@ -285,11 +278,11 @@ call_content_setup_jingle (GabbleCallContent *self,
GabbleCallMemberContent *mcontent)
{
TpBaseCallContent *base = TP_BASE_CALL_CONTENT (self);
- GabbleJingleContent *jingle;
+ WockyJingleContent *jingle;
GabbleCallStream *stream;
gchar *path;
- JingleTransportType transport;
- JingleMediaDescription *md;
+ WockyJingleTransportType transport;
+ WockyJingleMediaDescription *md;
GHashTable *tp_md;
TpHandle contact;
@@ -298,7 +291,7 @@ call_content_setup_jingle (GabbleCallContent *self,
if (jingle == NULL)
return;
- transport = gabble_jingle_content_get_transport_type (jingle);
+ transport = wocky_jingle_content_get_transport_type (jingle);
path = g_strdup_printf ("%s/Stream%p",
tp_base_call_content_get_object_path (base),
jingle);
@@ -310,7 +303,7 @@ call_content_setup_jingle (GabbleCallContent *self,
NULL);
g_free (path);
- md = jingle_media_description_new ();
+ md = wocky_jingle_media_description_new ();
/* FIXME: correct??? */
contact = gabble_call_member_get_handle (
@@ -326,9 +319,9 @@ call_content_setup_jingle (GabbleCallContent *self,
if (md->codecs != NULL)
jingle_media_rtp_set_local_media_description (
- GABBLE_JINGLE_MEDIA_RTP (jingle), md, TRUE, NULL);
+ WOCKY_JINGLE_MEDIA_RTP (jingle), md, TRUE, NULL);
else
- jingle_media_description_free (md);
+ wocky_jingle_media_description_free (md);
tp_base_call_content_add_stream (base, TP_BASE_CALL_STREAM (stream));
gabble_call_stream_update_member_states (stream);
@@ -350,7 +343,7 @@ member_content_removed_cb (GabbleCallMemberContent *mcontent,
GabbleCallContent *self = GABBLE_CALL_CONTENT (user_data);
GabbleCallContentPrivate *priv = self->priv;
TpBaseCallContent *base = TP_BASE_CALL_CONTENT (self);
- GabbleJingleContent *content;
+ WockyJingleContent *content;
GList *l;
priv->contents = g_list_remove (priv->contents, mcontent);
diff --git a/src/call-content.h b/src/call-content.h
index ff3205f55..e675d57fa 100644
--- a/src/call-content.h
+++ b/src/call-content.h
@@ -23,9 +23,9 @@
#include <glib-object.h>
-#include <telepathy-glib/base-media-call-content.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <wocky/wocky.h>
-#include "jingle-content.h"
#include "call-member-content.h"
G_BEGIN_DECLS
@@ -63,7 +63,7 @@ GType gabble_call_content_get_type (void);
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
GABBLE_TYPE_CALL_CONTENT, GabbleCallContentClass))
-JingleMediaType gabble_call_content_get_media_type (GabbleCallContent *self);
+WockyJingleMediaType gabble_call_content_get_media_type (GabbleCallContent *self);
void gabble_call_content_new_offer (GabbleCallContent *self,
GabbleCallMemberContent *content);
diff --git a/src/call-member-content.c b/src/call-member-content.c
index 8899b0f58..4500de14c 100644
--- a/src/call-member-content.c
+++ b/src/call-member-content.c
@@ -25,7 +25,6 @@
#include "call-member.h"
#include "call-member-content.h"
-#include "jingle-media-rtp.h"
#include "util.h"
#include "namespaces.h"
@@ -62,9 +61,9 @@ struct _GabbleCallMemberContentPrivate
GabbleCallMember *member;
- GabbleJingleContent *jingle_content;
+ WockyJingleContent *jingle_content;
gchar *name;
- JingleMediaType media_type;
+ WockyJingleMediaType media_type;
GList *remote_codecs;
gboolean removed;
@@ -136,7 +135,7 @@ gabble_call_member_content_set_property (GObject *object,
break;
case PROP_MEDIA_TYPE:
priv->media_type = g_value_get_uint (value);
- g_assert (priv->media_type != JINGLE_MEDIA_TYPE_NONE);
+ g_assert (priv->media_type != WOCKY_JINGLE_MEDIA_TYPE_NONE);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -152,8 +151,8 @@ gabble_call_member_content_add_to_session (GabbleCallMemberContent *self)
{
GabbleCallMemberContentPrivate *priv = self->priv;
const gchar *content_ns;
- GabbleJingleSession *session;
- GabbleJingleContent *content;
+ WockyJingleSession *session;
+ WockyJingleContent *content;
const gchar *peer_resource;
const gchar *transport_ns;
@@ -170,7 +169,7 @@ gabble_call_member_content_add_to_session (GabbleCallMemberContent *self)
g_assert (session != NULL);
- peer_resource = gabble_jingle_session_get_peer_resource (session);
+ peer_resource = wocky_jingle_session_get_peer_resource (session);
if (peer_resource != NULL)
DEBUG ("existing call, using peer resource %s", peer_resource);
@@ -180,8 +179,8 @@ gabble_call_member_content_add_to_session (GabbleCallMemberContent *self)
DEBUG ("Creating new jingle content with ns %s : %s",
content_ns, transport_ns);
- content = gabble_jingle_session_add_content (session,
- priv->media_type, JINGLE_CONTENT_SENDERS_BOTH,
+ content = wocky_jingle_session_add_content (session,
+ priv->media_type, WOCKY_JINGLE_CONTENT_SENDERS_BOTH,
priv->name, content_ns, transport_ns);
gabble_call_member_content_set_jingle_content (self, content);
@@ -237,16 +236,16 @@ gabble_call_member_content_class_init (
param_spec = g_param_spec_uint ("media-type", "MediaType",
"The media type of this jingle content",
- JINGLE_MEDIA_TYPE_NONE,
- JINGLE_MEDIA_TYPE_VIDEO,
- JINGLE_MEDIA_TYPE_NONE,
+ WOCKY_JINGLE_MEDIA_TYPE_NONE,
+ WOCKY_JINGLE_MEDIA_TYPE_VIDEO,
+ WOCKY_JINGLE_MEDIA_TYPE_NONE,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_MEDIA_TYPE,
param_spec);
param_spec = g_param_spec_object ("jingle-content", "JingleContent",
"The jingle content corresponding to this members content",
- GABBLE_TYPE_JINGLE_CONTENT,
+ WOCKY_TYPE_JINGLE_CONTENT,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_JINGLE_CONTENT,
param_spec);
@@ -311,7 +310,7 @@ gabble_call_member_content_finalize (GObject *object)
G_OBJECT_CLASS (gabble_call_member_content_parent_class)->finalize (object);
}
-JingleMediaType
+WockyJingleMediaType
gabble_call_member_content_get_media_type (GabbleCallMemberContent *self)
{
return self->priv->media_type;
@@ -323,7 +322,7 @@ gabble_call_member_content_get_name (GabbleCallMemberContent *self)
return self->priv->name;
}
-GabbleJingleContent *
+WockyJingleContent *
gabble_call_member_content_get_jingle_content (
GabbleCallMemberContent *self)
{
@@ -332,7 +331,7 @@ gabble_call_member_content_get_jingle_content (
GabbleCallMemberContent *
gabble_call_member_content_new (const gchar *name,
- JingleMediaType type,
+ WockyJingleMediaType type,
GabbleCallMember *member)
{
return GABBLE_CALL_MEMBER_CONTENT (g_object_new (
@@ -344,7 +343,7 @@ gabble_call_member_content_new (const gchar *name,
}
static void
-call_member_content_jingle_removed_cb (GabbleJingleContent *jingle_content,
+call_member_content_jingle_removed_cb (WockyJingleContent *jingle_content,
GabbleCallMemberContent *content)
{
if (!content->priv->removed)
@@ -355,8 +354,8 @@ call_member_content_jingle_removed_cb (GabbleJingleContent *jingle_content,
}
static void
-call_member_content_jingle_media_description_cb (GabbleJingleMediaRtp *media,
- JingleMediaDescription *md,
+call_member_content_jingle_media_description_cb (WockyJingleMediaRtp *media,
+ WockyJingleMediaDescription *md,
gpointer user_data)
{
GabbleCallMemberContent *self = GABBLE_CALL_MEMBER_CONTENT (user_data);
@@ -368,12 +367,12 @@ call_member_content_jingle_media_description_cb (GabbleJingleMediaRtp *media,
GabbleCallMemberContent *
gabble_call_member_content_from_jingle_content (
- GabbleJingleContent *jingle_content,
+ WockyJingleContent *jingle_content,
GabbleCallMember *member)
{
GabbleCallMemberContent *content;
gchar *name;
- JingleMediaType mtype;
+ WockyJingleMediaType mtype;
g_object_get (jingle_content,
"name", &name,
@@ -403,9 +402,9 @@ gabble_call_member_content_get_remote_codecs (GabbleCallMemberContent *self)
if (self->priv->jingle_content != NULL)
{
- JingleMediaDescription *md;
- md = gabble_jingle_media_rtp_get_remote_media_description (
- GABBLE_JINGLE_MEDIA_RTP (self->priv->jingle_content));
+ WockyJingleMediaDescription *md;
+ md = wocky_jingle_media_rtp_get_remote_media_description (
+ WOCKY_JINGLE_MEDIA_RTP (self->priv->jingle_content));
if (md != NULL)
jcodecs = md->codecs;
}
@@ -447,7 +446,7 @@ gabble_call_member_content_get_member (GabbleCallMemberContent *self)
void
gabble_call_member_content_set_jingle_content (GabbleCallMemberContent *self,
- GabbleJingleContent *content)
+ WockyJingleContent *content)
{
g_assert (self->priv->jingle_content == NULL);
@@ -478,7 +477,7 @@ gabble_call_member_content_remove (GabbleCallMemberContent *self)
g_object_ref (self);
/* Remove ourselves from the sesison */
if (priv->jingle_content != NULL)
- gabble_jingle_session_remove_content (priv->jingle_content->session,
+ wocky_jingle_session_remove_content (priv->jingle_content->session,
priv->jingle_content);
g_signal_emit (self, signals[REMOVED], 0);
diff --git a/src/call-member-content.h b/src/call-member-content.h
index 98034096e..0f47d61ab 100644
--- a/src/call-member-content.h
+++ b/src/call-member-content.h
@@ -22,10 +22,9 @@
#define __CALL_MEMBER_CONTENT_H__
#include <glib-object.h>
+#include <wocky/wocky.h>
#include "types.h"
-#include "jingle-content.h"
-#include "jingle-media-rtp.h"
G_BEGIN_DECLS
@@ -61,20 +60,20 @@ GType gabble_call_member_content_get_type (void);
GabbleCallMemberContentClass))
GabbleCallMemberContent *gabble_call_member_content_new (const gchar *name,
- JingleMediaType type,
+ WockyJingleMediaType type,
GabbleCallMember *member);
GabbleCallMemberContent *gabble_call_member_content_from_jingle_content (
- GabbleJingleContent *jingle_content,
+ WockyJingleContent *jingle_content,
GabbleCallMember *member);
-JingleMediaType gabble_call_member_content_get_media_type (
+WockyJingleMediaType gabble_call_member_content_get_media_type (
GabbleCallMemberContent *self);
const gchar *gabble_call_member_content_get_name (
GabbleCallMemberContent *self);
-GabbleJingleContent *gabble_call_member_content_get_jingle_content (
+WockyJingleContent *gabble_call_member_content_get_jingle_content (
GabbleCallMemberContent *self);
gboolean gabble_call_member_content_has_jingle_content (
@@ -95,7 +94,7 @@ GabbleCallMember *gabble_call_member_content_get_member (
void gabble_call_member_content_set_jingle_content (
GabbleCallMemberContent *self,
- GabbleJingleContent *content);
+ WockyJingleContent *content);
void gabble_call_member_content_add_to_session (
GabbleCallMemberContent *self);
diff --git a/src/call-member.c b/src/call-member.c
index aba19013b..935dfaf71 100644
--- a/src/call-member.c
+++ b/src/call-member.c
@@ -60,7 +60,7 @@ struct _GabbleCallMemberPrivate
GabbleBaseCallChannel *call;
TpCallMemberFlags flags;
- GabbleJingleSession *session;
+ WockyJingleSession *session;
GList *contents;
gchar *transport_ns;
@@ -126,7 +126,7 @@ gabble_call_member_set_property (GObject *object,
break;
case PROP_SESSION:
gabble_call_member_set_session (self,
- GABBLE_JINGLE_SESSION (g_value_get_object (value)));
+ WOCKY_JINGLE_SESSION (g_value_get_object (value)));
break;
case PROP_TARGET:
priv->target = g_value_get_uint (value);
@@ -165,7 +165,7 @@ gabble_call_member_class_init (
param_spec = g_param_spec_object ("session", "Session",
"The jingle session below this call",
- GABBLE_TYPE_JINGLE_SESSION,
+ WOCKY_TYPE_JINGLE_SESSION,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_SESSION, param_spec);
@@ -243,16 +243,16 @@ gabble_call_member_finalize (GObject *object)
}
static void
-remote_state_changed_cb (GabbleJingleSession *session, gpointer user_data)
+remote_state_changed_cb (WockyJingleSession *session, gpointer user_data)
{
GabbleCallMember *self = GABBLE_CALL_MEMBER (user_data);
GabbleCallMemberPrivate *priv = self->priv;
TpCallMemberFlags newflags = 0;
- if (gabble_jingle_session_get_remote_ringing (session))
+ if (wocky_jingle_session_get_remote_ringing (session))
newflags |= TP_CALL_MEMBER_FLAG_RINGING;
- if (gabble_jingle_session_get_remote_hold (session))
+ if (wocky_jingle_session_get_remote_hold (session))
newflags |= TP_CALL_MEMBER_FLAG_HELD;
if (priv->flags == newflags)
@@ -293,14 +293,14 @@ gabble_call_member_add_member_content (GabbleCallMember *self,
/* This function handles additional contents added by the remote side */
static void
-new_content_cb (GabbleJingleSession *session,
- GabbleJingleContent *c,
+new_content_cb (WockyJingleSession *session,
+ WockyJingleContent *c,
gpointer user_data)
{
GabbleCallMember *self = GABBLE_CALL_MEMBER (user_data);
GabbleCallMemberContent *content = NULL;
- if (gabble_jingle_content_is_created_by_us (c))
+ if (wocky_jingle_content_is_created_by_us (c))
return;
content = gabble_call_member_content_from_jingle_content (c, self);
@@ -310,7 +310,7 @@ new_content_cb (GabbleJingleSession *session,
static gboolean
call_member_update_existing_content (GabbleCallMember *self,
- GabbleJingleContent *content)
+ WockyJingleContent *content)
{
GList *l;
@@ -322,7 +322,7 @@ call_member_update_existing_content (GabbleCallMember *self,
continue;
if (!tp_strdiff (gabble_call_member_content_get_name (mcontent),
- gabble_jingle_content_get_name (content)))
+ wocky_jingle_content_get_name (content)))
{
gabble_call_member_content_set_jingle_content (mcontent, content);
return TRUE;
@@ -334,7 +334,7 @@ call_member_update_existing_content (GabbleCallMember *self,
void
gabble_call_member_set_session (GabbleCallMember *self,
- GabbleJingleSession *session)
+ WockyJingleSession *session)
{
GabbleCallMemberPrivate *priv = self->priv;
GList *c, *contents;
@@ -345,10 +345,10 @@ gabble_call_member_set_session (GabbleCallMember *self,
DEBUG ("Setting session: %p -> %p\n", self, session);
priv->session = g_object_ref (session);
- contents = gabble_jingle_session_get_contents (session);
+ contents = wocky_jingle_session_get_contents (session);
for (c = contents ; c != NULL; c = g_list_next (c))
{
- GabbleJingleContent *content = GABBLE_JINGLE_CONTENT (c->data);
+ WockyJingleContent *content = WOCKY_JINGLE_CONTENT (c->data);
if (priv->transport_ns == NULL)
{
@@ -380,7 +380,7 @@ gabble_call_member_set_session (GabbleCallMember *self,
g_list_free (contents);
}
-GabbleJingleSession *
+WockyJingleSession *
gabble_call_member_get_session (GabbleCallMember *self)
{
return self->priv->session;
@@ -409,7 +409,7 @@ gabble_call_member_get_contents (GabbleCallMember *self)
GabbleCallMemberContent *
gabble_call_member_ensure_content (GabbleCallMember *self,
const gchar *name,
- JingleMediaType mtype)
+ WockyJingleMediaType mtype)
{
GabbleCallMemberPrivate *priv = self->priv;
GList *l;
@@ -439,19 +439,19 @@ gabble_call_member_ensure_content (GabbleCallMember *self,
GabbleCallMemberContent *
gabble_call_member_create_content (GabbleCallMember *self,
const gchar *name,
- JingleMediaType mtype,
- JingleContentSenders senders,
+ WockyJingleMediaType mtype,
+ WockyJingleContentSenders senders,
GError **error)
{
GabbleCallMemberPrivate *priv = self->priv;
const gchar *content_ns;
- GabbleJingleContent *c;
+ WockyJingleContent *c;
GabbleCallMemberContent *content;
const gchar *peer_resource;
g_assert (priv->session != NULL);
- peer_resource = gabble_jingle_session_get_peer_resource (priv->session);
+ peer_resource = wocky_jingle_session_get_peer_resource (priv->session);
DEBUG ("Creating new content %s, type %d", name, mtype);
@@ -466,7 +466,7 @@ gabble_call_member_create_content (GabbleCallMember *self,
if (content_ns == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Content type %d not available for this resource", mtype);
return NULL;
}
@@ -474,7 +474,7 @@ gabble_call_member_create_content (GabbleCallMember *self,
DEBUG ("Creating new jingle content with ns %s : %s",
content_ns, priv->transport_ns);
- c = gabble_jingle_session_add_content (priv->session,
+ c = wocky_jingle_session_add_content (priv->session,
mtype, senders, name, content_ns, priv->transport_ns);
g_assert (c != NULL);
@@ -492,7 +492,7 @@ gabble_call_member_accept (GabbleCallMember *self)
self->priv->accepted = TRUE;
if (self->priv->session != NULL)
- gabble_jingle_session_accept (self->priv->session);
+ wocky_jingle_session_accept (self->priv->session);
}
/**
@@ -506,8 +506,8 @@ gabble_call_member_open_session (GabbleCallMember *self,
{
GabbleCallMemberPrivate *priv = self->priv;
GabbleConnection *conn = gabble_call_member_get_connection (self);
- GabbleJingleFactory *jf;
- GabbleJingleSession *session;
+ WockyJingleFactory *jf;
+ WockyJingleSession *session;
gchar *jid;
jid = gabble_peer_to_jid (conn, priv->target, NULL);
@@ -515,7 +515,7 @@ gabble_call_member_open_session (GabbleCallMember *self,
jf = gabble_jingle_mint_get_factory (conn->jingle_mint);
g_return_val_if_fail (jf != NULL, FALSE);
- session = gabble_jingle_factory_create_session (jf, jid, JINGLE_DIALECT_V032,
+ session = wocky_jingle_factory_create_session (jf, jid, WOCKY_JINGLE_DIALECT_V032,
FALSE);
DEBUG ("Created a jingle session: %p", session);
@@ -538,11 +538,11 @@ gabble_call_member_start_session (GabbleCallMember *self,
TpBaseChannel *base_channel = TP_BASE_CHANNEL (priv->call);
TpHandle target = tp_base_channel_get_target_handle (base_channel);
const gchar *resource;
- JingleDialect dialect;
+ WockyJingleDialect dialect;
gchar *jid;
const gchar *transport;
- GabbleJingleFactory *jf;
- GabbleJingleSession *session;
+ WockyJingleFactory *jf;
+ WockyJingleSession *session;
/* FIXME might need to wait on capabilities, also don't need transport
* and dialect already */
@@ -550,7 +550,7 @@ gabble_call_member_start_session (GabbleCallMember *self,
target, audio_name != NULL, video_name != NULL,
&transport, &dialect, &resource))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_CAPABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE,
"member does not have the desired audio/video capabilities");
return FALSE;
}
@@ -561,7 +561,7 @@ gabble_call_member_start_session (GabbleCallMember *self,
gabble_call_member_get_connection (self)->jingle_mint);
g_return_val_if_fail (jf != NULL, FALSE);
- session = gabble_jingle_factory_create_session (jf, jid, dialect, FALSE);
+ session = wocky_jingle_factory_create_session (jf, jid, dialect, FALSE);
g_free (jid);
gabble_call_member_set_session (self, session);
@@ -570,11 +570,11 @@ gabble_call_member_start_session (GabbleCallMember *self,
if (audio_name != NULL)
gabble_call_member_create_content (self, audio_name,
- JINGLE_MEDIA_TYPE_AUDIO, JINGLE_CONTENT_SENDERS_BOTH, NULL);
+ WOCKY_JINGLE_MEDIA_TYPE_AUDIO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, NULL);
if (video_name != NULL)
gabble_call_member_create_content (self, video_name,
- JINGLE_MEDIA_TYPE_VIDEO, JINGLE_CONTENT_SENDERS_BOTH, NULL);
+ WOCKY_JINGLE_MEDIA_TYPE_VIDEO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, NULL);
return TRUE;
}
@@ -600,8 +600,8 @@ gabble_call_member_shutdown (GabbleCallMember *self)
if (priv->session != NULL)
{
- gabble_jingle_session_terminate (priv->session,
- JINGLE_REASON_UNKNOWN, NULL, NULL);
+ wocky_jingle_session_terminate (priv->session,
+ WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL);
}
/* removing the content will remove it from our list */
diff --git a/src/call-member.h b/src/call-member.h
index 5554a9ec0..bc8afe027 100644
--- a/src/call-member.h
+++ b/src/call-member.h
@@ -23,10 +23,10 @@
#include <glib-object.h>
-#include <telepathy-glib/handle.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <wocky/wocky.h>
#include "types.h"
-#include "jingle-session.h"
#include "call-member-content.h"
G_BEGIN_DECLS
@@ -63,12 +63,12 @@ GType gabble_call_member_get_type (void);
GabbleCallMemberClass))
void gabble_call_member_set_session (GabbleCallMember *member,
- GabbleJingleSession *session);
+ WockyJingleSession *session);
TpHandle gabble_call_member_get_handle (
GabbleCallMember *self);
-GabbleJingleSession *gabble_call_member_get_session (
+WockyJingleSession *gabble_call_member_get_session (
GabbleCallMember *self);
TpCallMemberFlags gabble_call_member_get_flags (
@@ -79,13 +79,13 @@ GList *gabble_call_member_get_contents (GabbleCallMember *self);
GabbleCallMemberContent * gabble_call_member_ensure_content (
GabbleCallMember *self,
const gchar *name,
- JingleMediaType mtype);
+ WockyJingleMediaType mtype);
GabbleCallMemberContent * gabble_call_member_create_content (
GabbleCallMember *self,
const gchar *name,
- JingleMediaType mtype,
- JingleContentSenders senders,
+ WockyJingleMediaType mtype,
+ WockyJingleContentSenders senders,
GError **error);
gboolean gabble_call_member_start_session (GabbleCallMember *self,
diff --git a/src/call-muc-channel.c b/src/call-muc-channel.c
index 62d40c695..1dbf3b23c 100644
--- a/src/call-muc-channel.c
+++ b/src/call-muc-channel.c
@@ -23,11 +23,9 @@
#include <stdio.h>
#include <stdlib.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
-#include <wocky/wocky.h>
#include "call-content.h"
#include "muc-channel.h"
@@ -418,7 +416,7 @@ call_muc_channel_member_content_added_cb (GabbleCallMember *member,
{
GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (user_data);
const gchar *name;
- JingleMediaType mtype;
+ WockyJingleMediaType mtype;
GList *l;
GabbleCallContent *ccontent;
@@ -433,7 +431,7 @@ call_muc_channel_member_content_added_cb (GabbleCallMember *member,
TP_BASE_CALL_CHANNEL (self)); l != NULL; l = g_list_next (l))
{
const char *cname;
- JingleMediaType cmtype;
+ WockyJingleMediaType cmtype;
ccontent = GABBLE_CALL_CONTENT (l->data);
cname = tp_base_call_content_get_name (
@@ -470,7 +468,7 @@ call_muc_channel_parse_codecs (GabbleCallMucChannel *self,
guint id;
guint clockrate = 0;
guint channels = 0;
- JingleCodec *codec;
+ WockyJingleCodec *codec;
WockyNodeIter param_iter;
WockyNode *parameter;
@@ -542,13 +540,13 @@ call_muc_channel_send_new_state (GabbleCallMucChannel *self)
GHashTable *tp_md;
GPtrArray *codecs;
guint i;
- JingleMediaType mtype = gabble_call_content_get_media_type (content);
+ WockyJingleMediaType mtype = gabble_call_content_get_media_type (content);
wocky_node_add_build (m,
'(', "content", '@', "name", name,
'(', "description", ':', NS_JINGLE_RTP, '*', &description,
- '@', "media", mtype == JINGLE_MEDIA_TYPE_AUDIO ? "audio" : "video",
+ '@', "media", mtype == WOCKY_JINGLE_MEDIA_TYPE_AUDIO ? "audio" : "video",
')',
')',
NULL);
@@ -626,7 +624,7 @@ call_muc_channel_parse_participant (GabbleCallMucChannel *self,
{
GabbleCallMemberContent *member_content;
WockyNode *description;
- JingleMediaType mtype;
+ WockyJingleMediaType mtype;
const gchar *name;
const gchar *mattr;
GList *codecs;
@@ -656,11 +654,11 @@ call_muc_channel_parse_participant (GabbleCallMucChannel *self,
if (!tp_strdiff (mattr, "video"))
{
- mtype = JINGLE_MEDIA_TYPE_VIDEO;
+ mtype = WOCKY_JINGLE_MEDIA_TYPE_VIDEO;
}
else if (!tp_strdiff (mattr, "audio"))
{
- mtype = JINGLE_MEDIA_TYPE_AUDIO;
+ mtype = WOCKY_JINGLE_MEDIA_TYPE_AUDIO;
}
else
{
@@ -679,7 +677,7 @@ call_muc_channel_parse_participant (GabbleCallMucChannel *self,
if (!priv->initialized)
{
- if (mtype == JINGLE_MEDIA_TYPE_AUDIO)
+ if (mtype == WOCKY_JINGLE_MEDIA_TYPE_AUDIO)
g_object_set (self, "initial-audio", TRUE, NULL);
else
g_object_set (self, "initial-video", TRUE, NULL);
@@ -998,7 +996,7 @@ call_muc_channel_init_async (GAsyncInitable *initable,
{
content = gabble_base_call_channel_add_content (
GABBLE_BASE_CALL_CHANNEL (base),
- initial_audio_name, JINGLE_MEDIA_TYPE_AUDIO,
+ initial_audio_name, WOCKY_JINGLE_MEDIA_TYPE_AUDIO,
TP_CALL_CONTENT_DISPOSITION_INITIAL);
call_muc_channel_setup_content (self, content);
}
@@ -1007,7 +1005,7 @@ call_muc_channel_init_async (GAsyncInitable *initable,
{
content = gabble_base_call_channel_add_content (
GABBLE_BASE_CALL_CHANNEL (base),
- initial_video_name, JINGLE_MEDIA_TYPE_VIDEO,
+ initial_video_name, WOCKY_JINGLE_MEDIA_TYPE_VIDEO,
TP_CALL_CONTENT_DISPOSITION_INITIAL);
call_muc_channel_setup_content (self, content);
}
@@ -1110,13 +1108,13 @@ gabble_call_muc_channel_new_finish (GObject *source,
void
gabble_call_muc_channel_incoming_session (GabbleCallMucChannel *self,
- GabbleJingleSession *session)
+ WockyJingleSession *session)
{
GabbleCallMember *member;
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
tp_base_channel_get_connection (TP_BASE_CHANNEL (self)),
TP_HANDLE_TYPE_CONTACT);
- const gchar *jid = gabble_jingle_session_get_peer_jid (session);
+ const gchar *jid = wocky_jingle_session_get_peer_jid (session);
TpHandle peer = tp_handle_ensure (contact_repo, jid, NULL, NULL);
DEBUG ("New incoming session from %s", jid);
@@ -1125,8 +1123,8 @@ gabble_call_muc_channel_incoming_session (GabbleCallMucChannel *self,
if (member == NULL || gabble_call_member_get_session (member) != NULL)
{
- gabble_jingle_session_terminate (session,
- JINGLE_REASON_UNKNOWN,
+ wocky_jingle_session_terminate (session,
+ WOCKY_JINGLE_REASON_UNKNOWN,
"Muji jingle session initiated while there already was one",
NULL);
}
@@ -1163,14 +1161,14 @@ call_muc_channel_add_content (TpBaseCallChannel *base,
if (initial_direction == TP_MEDIA_STREAM_DIRECTION_NONE)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Jingle can not do contents with direction = NONE");
return NULL;
}
if (initial_direction != TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Adding un-directional contents is not supported"
" in MUC channels");
return NULL;
@@ -1178,7 +1176,7 @@ call_muc_channel_add_content (TpBaseCallChannel *base,
content = gabble_base_call_channel_add_content (
GABBLE_BASE_CALL_CHANNEL (base),
- name, jingle_media_type_from_tp (type),
+ name, wocky_jingle_media_type_from_tp (type),
TP_CALL_CONTENT_DISPOSITION_NONE);
call_muc_channel_setup_content (self, content);
diff --git a/src/call-muc-channel.h b/src/call-muc-channel.h
index aa51700e1..e3df68235 100644
--- a/src/call-muc-channel.h
+++ b/src/call-muc-channel.h
@@ -22,9 +22,9 @@
#define __GABBLE_CALL_MUC_CHANNEL_H__
#include <glib-object.h>
+#include <wocky/wocky.h>
#include "base-call-channel.h"
-#include "jingle-session.h"
G_BEGIN_DECLS
@@ -75,7 +75,7 @@ GabbleCallMucChannel * gabble_call_muc_channel_new_finish (GObject *source,
GError **error);
void gabble_call_muc_channel_incoming_session (GabbleCallMucChannel *self,
- GabbleJingleSession *session);
+ WockyJingleSession *session);
G_END_DECLS
diff --git a/src/call-stream.c b/src/call-stream.c
index a25365db9..89af93ce1 100644
--- a/src/call-stream.c
+++ b/src/call-stream.c
@@ -23,16 +23,11 @@
#include <stdio.h>
#include <stdlib.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/svc-properties-interface.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/util.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "call-stream.h"
#include "connection.h"
-#include "jingle-session.h"
-#include "jingle-content.h"
#include "jingle-tp-util.h"
#include "util.h"
@@ -84,7 +79,7 @@ struct _GabbleCallStreamPrivate
{
gboolean dispose_has_run;
- GabbleJingleContent *content;
+ WockyJingleContent *content;
};
static void
@@ -103,25 +98,25 @@ static GPtrArray *
get_stun_servers (GabbleCallStream *self)
{
GPtrArray *arr;
- GabbleJingleFactory *jf;
- gchar *stun_server;
- guint stun_port;
+ WockyJingleFactory *jf;
+ GList *stun_servers;
arr = g_ptr_array_new_with_free_func ((GDestroyNotify) g_value_array_free);
- jf = gabble_jingle_session_get_factory (self->priv->content->session);
+ jf = wocky_jingle_session_get_factory (self->priv->content->session);
+ stun_servers = wocky_jingle_info_get_stun_servers (
+ wocky_jingle_factory_get_jingle_info (jf));
- /* maybe one day we'll support multiple STUN servers */
- if (gabble_jingle_info_get_stun_server (
- gabble_jingle_factory_get_jingle_info (jf),
- &stun_server, &stun_port))
+ while (stun_servers != NULL)
{
+ WockyStunServer *stun_server = stun_servers->data;
GValueArray *va = tp_value_array_build (2,
- G_TYPE_STRING, stun_server,
- G_TYPE_UINT, stun_port,
+ G_TYPE_STRING, stun_server->address,
+ G_TYPE_UINT, (guint) stun_server->port,
G_TYPE_INVALID);
- g_free (stun_server);
g_ptr_array_add (arr, va);
+
+ stun_servers = g_list_delete_link (stun_servers, stun_servers);
}
return arr;
@@ -143,9 +138,9 @@ gabble_call_stream_get_property (GObject *object,
break;
case PROP_CAN_REQUEST_RECEIVING:
{
- JingleDialect dialect =
- gabble_jingle_session_get_dialect (priv->content->session);
- g_value_set_boolean (value, !JINGLE_IS_GOOGLE_DIALECT (dialect));
+ WockyJingleDialect dialect =
+ wocky_jingle_session_get_dialect (priv->content->session);
+ g_value_set_boolean (value, !WOCKY_JINGLE_DIALECT_IS_GOOGLE (dialect));
}
break;
default:
@@ -195,7 +190,7 @@ google_relay_session_cb (GPtrArray *relays,
}
static void
-content_state_changed_cb (GabbleJingleContent *content,
+content_state_changed_cb (WockyJingleContent *content,
GParamSpec *spec,
gpointer user_data)
{
@@ -205,7 +200,7 @@ content_state_changed_cb (GabbleJingleContent *content,
}
static void
-content_remote_members_changed_cb (GabbleJingleContent *content,
+content_remote_members_changed_cb (WockyJingleContent *content,
GParamSpec *spec,
gpointer user_data)
{
@@ -216,7 +211,7 @@ content_remote_members_changed_cb (GabbleJingleContent *content,
static void
jingle_info_stun_server_changed_cb (
- GabbleJingleInfo *jingle_info,
+ WockyJingleInfo *jingle_info,
const gchar *stun_server,
guint stun_port,
GabbleCallStream *self)
@@ -231,7 +226,7 @@ jingle_info_stun_server_changed_cb (
static void
_new_candidates_cb (
- GabbleJingleContent *content,
+ WockyJingleContent *content,
GList *candidates,
TpCallStreamEndpoint *endpoint)
{
@@ -241,7 +236,7 @@ _new_candidates_cb (
if (candidates == NULL)
return;
- if (gabble_jingle_content_get_credentials (content, &ufrag, &pwd))
+ if (wocky_jingle_content_get_credentials (content, &ufrag, &pwd))
tp_call_stream_endpoint_set_remote_credentials (endpoint, ufrag, pwd);
tp_candidates = gabble_call_candidates_to_array (candidates);
@@ -253,19 +248,19 @@ static void
_endpoint_state_changed_cb (
TpCallStreamEndpoint *endpoint,
GParamSpec *spec,
- GabbleJingleContent *content)
+ WockyJingleContent *content)
{
TpMediaStreamState state;
/* We only care about connecting RTP, RTCP is optional */
state = tp_call_stream_endpoint_get_state (endpoint, 1);
- gabble_jingle_content_set_transport_state (content, state);
+ wocky_jingle_content_set_transport_state (content, state);
}
static TpCallStreamEndpoint *
_hook_up_endpoint (GabbleCallStream *self,
const gchar *path,
- GabbleJingleContent *content)
+ WockyJingleContent *content)
{
TpBaseCallStream *base = (TpBaseCallStream *) self;
TpBaseConnection *conn = tp_base_call_stream_get_connection (base);
@@ -276,7 +271,7 @@ _hook_up_endpoint (GabbleCallStream *self,
GList *candidates;
gchar *ufrag, *pwd;
- switch (gabble_jingle_content_get_transport_type (content))
+ switch (wocky_jingle_content_get_transport_type (content))
{
case JINGLE_TRANSPORT_GOOGLE_P2P:
type = TP_STREAM_TRANSPORT_TYPE_GTALK_P2P;
@@ -295,9 +290,9 @@ _hook_up_endpoint (GabbleCallStream *self,
/* FIXME: ice??? */
endpoint = tp_call_stream_endpoint_new (bus, path, type, FALSE);
- if (gabble_jingle_content_get_credentials (content, &ufrag, &pwd))
+ if (wocky_jingle_content_get_credentials (content, &ufrag, &pwd))
tp_call_stream_endpoint_set_remote_credentials (endpoint, ufrag, pwd);
- candidates = gabble_jingle_content_get_remote_candidates (content);
+ candidates = wocky_jingle_content_get_remote_candidates (content);
tp_candidates = gabble_call_candidates_to_array (candidates);
tp_call_stream_endpoint_add_new_candidates (endpoint, tp_candidates);
g_boxed_free (TP_ARRAY_TYPE_CANDIDATE_LIST, tp_candidates);
@@ -321,7 +316,7 @@ gabble_call_stream_constructed (GObject *obj)
GabbleConnection *conn;
TpCallStreamEndpoint *endpoint;
gchar *path;
- JingleTransportType transport;
+ WockyJingleTransportType transport;
GPtrArray *stun_servers;
gboolean locally_created;
@@ -333,7 +328,7 @@ gabble_call_stream_constructed (GObject *obj)
g_object_get (priv->content, "locally-created", &locally_created, NULL);
if (locally_created &&
- gabble_jingle_content_sending (priv->content))
+ wocky_jingle_content_sending (priv->content))
tp_base_media_call_stream_set_local_sending (
TP_BASE_MEDIA_CALL_STREAM (self), TRUE);
@@ -346,7 +341,7 @@ gabble_call_stream_constructed (GObject *obj)
g_object_unref (endpoint);
g_free (path);
- transport = gabble_jingle_content_get_transport_type (priv->content);
+ transport = wocky_jingle_content_get_transport_type (priv->content);
if (transport == JINGLE_TRANSPORT_GOOGLE_P2P)
{
@@ -355,7 +350,7 @@ gabble_call_stream_constructed (GObject *obj)
/* See if our server is Google, and if it is, ask them for a relay.
* We ask for enough relays for 2 components (RTP and RTCP) since we
* don't yet know whether there will be RTCP. */
- gabble_jingle_info_create_google_relay_session (
+ wocky_jingle_info_create_google_relay_session (
gabble_jingle_mint_get_info (conn->jingle_mint),
2, google_relay_session_cb, tp_weak_ref_new (self, NULL, NULL));
}
@@ -388,7 +383,7 @@ gabble_call_stream_update_member_states (GabbleCallStream *self)
TpBaseCallStream *base = TP_BASE_CALL_STREAM (self);
TpBaseMediaCallStream *bmcs = TP_BASE_MEDIA_CALL_STREAM (self);
GabbleCallStreamPrivate *priv = self->priv;
- JingleContentState state;
+ WockyJingleContentState state;
TpSendingState local_state;
TpSendingState remote_state;
TpBaseConnection *conn = tp_base_call_stream_get_connection (base);
@@ -398,13 +393,13 @@ gabble_call_stream_update_member_states (GabbleCallStream *self)
g_object_get (priv->content, "state", &state, NULL);
- if (state == JINGLE_CONTENT_STATE_REMOVING)
+ if (state == WOCKY_JINGLE_CONTENT_STATE_REMOVING)
return;
local_state = tp_base_call_stream_get_local_sending_state (base);
remote_state = tp_base_call_stream_get_remote_sending_state (base, 0);
- if (gabble_jingle_content_sending (priv->content))
+ if (wocky_jingle_content_sending (priv->content))
{
if (tp_base_media_call_stream_get_local_sending (bmcs))
local_state = TP_SENDING_STATE_SENDING;
@@ -419,7 +414,7 @@ gabble_call_stream_update_member_states (GabbleCallStream *self)
local_state = TP_SENDING_STATE_NONE;
}
- if (gabble_jingle_content_receiving (priv->content))
+ if (wocky_jingle_content_receiving (priv->content))
{
remote_state = TP_SENDING_STATE_SENDING;
}
@@ -433,7 +428,7 @@ gabble_call_stream_update_member_states (GabbleCallStream *self)
tp_base_call_stream_update_local_sending_state (base, local_state,
0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", "");
peer = tp_handle_ensure (contact_repo,
- gabble_jingle_session_get_peer_jid (priv->content->session),
+ wocky_jingle_session_get_peer_jid (priv->content->session),
NULL,
NULL);
tp_base_call_stream_update_remote_sending_state (base,
@@ -462,7 +457,7 @@ gabble_call_stream_class_init (GabbleCallStreamClass *gabble_call_stream_class)
param_spec = g_param_spec_object ("jingle-content", "Jingle Content",
"The Jingle Content related to this content object",
- GABBLE_TYPE_JINGLE_CONTENT,
+ WOCKY_TYPE_JINGLE_CONTENT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_JINGLE_CONTENT,
param_spec);
@@ -512,10 +507,10 @@ gabble_call_stream_add_candidates (TpBaseMediaCallStream *stream,
for (i = 0; i < candidates->len ; i++)
{
GValueArray *va;
- JingleCandidate *c;
+ WockyJingleCandidate *c;
GHashTable *info;
guint tptype;
- JingleCandidateType type;
+ WockyJingleCandidateType type;
/* borrowed strings, owned by other people. */
const gchar *username;
const gchar *password;
@@ -531,13 +526,13 @@ gabble_call_stream_add_candidates (TpBaseMediaCallStream *stream,
default:
/* Anything else is local */
case TP_CALL_STREAM_CANDIDATE_TYPE_HOST:
- type = JINGLE_CANDIDATE_TYPE_LOCAL;
+ type = WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL;
break;
case TP_CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE:
- type = JINGLE_CANDIDATE_TYPE_STUN;
+ type = WOCKY_JINGLE_CANDIDATE_TYPE_STUN;
break;
case TP_CALL_STREAM_CANDIDATE_TYPE_RELAY:
- type = JINGLE_CANDIDATE_TYPE_RELAY;
+ type = WOCKY_JINGLE_CANDIDATE_TYPE_RELAY;
break;
}
@@ -553,7 +548,7 @@ gabble_call_stream_add_candidates (TpBaseMediaCallStream *stream,
if (foundation == NULL)
foundation = "1";
- c = jingle_candidate_new (
+ c = wocky_jingle_candidate_new (
/* transport protocol */
tp_asv_get_uint32 (info, "protocol", NULL),
/* Candidate type */
@@ -580,11 +575,11 @@ gabble_call_stream_add_candidates (TpBaseMediaCallStream *stream,
g_ptr_array_add (accepted_candidates, va);
}
- gabble_jingle_content_add_candidates (priv->content, l);
+ wocky_jingle_content_add_candidates (priv->content, l);
if (accepted_candidates->len == 0 && candidates->len != 0)
{
- g_set_error_literal (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error_literal (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"All candidates had the wrong Type");
tp_clear_pointer (&accepted_candidates, g_ptr_array_unref);
}
@@ -602,7 +597,7 @@ gabble_call_stream_set_sending (TpBaseMediaCallStream *stream,
if (sending)
tp_base_media_call_stream_set_local_sending (stream, TRUE);
- gabble_jingle_content_set_sending (self->priv->content, sending);
+ wocky_jingle_content_set_sending (self->priv->content, sending);
return TRUE;
}
@@ -612,10 +607,10 @@ static void gabble_call_stream_request_receiving (TpBaseMediaCallStream *stream,
{
GabbleCallStream *self = GABBLE_CALL_STREAM (stream);
- gabble_jingle_content_request_receiving (self->priv->content, receive);
+ wocky_jingle_content_request_receiving (self->priv->content, receive);
}
-GabbleJingleContent *
+WockyJingleContent *
gabble_call_stream_get_jingle_content (GabbleCallStream *stream)
{
return stream->priv->content;
diff --git a/src/call-stream.h b/src/call-stream.h
index ed8bb767f..e83a50c7a 100644
--- a/src/call-stream.h
+++ b/src/call-stream.h
@@ -23,9 +23,8 @@
#include <glib-object.h>
-#include <telepathy-glib/base-media-call-stream.h>
-
-#include "jingle-types.h"
+#include <telepathy-glib/telepathy-glib.h>
+#include <wocky/wocky.h>
G_BEGIN_DECLS
@@ -61,7 +60,7 @@ GType gabble_call_stream_get_type (void);
(G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CALL_STREAM, \
GabbleCallStreamClass))
-GabbleJingleContent *gabble_call_stream_get_jingle_content (
+WockyJingleContent *gabble_call_stream_get_jingle_content (
GabbleCallStream *stream);
void gabble_call_stream_update_member_states (GabbleCallStream *self);
diff --git a/src/capabilities.c b/src/capabilities.c
index d2b25f57f..1c4801fd8 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -24,11 +24,8 @@
#include <stdlib.h>
#include <string.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/handle-repo.h>
-#include <telepathy-glib/handle-repo-dynamic.h>
-#include <telepathy-glib/util.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
#include "debug.h"
@@ -64,6 +61,8 @@ static const Feature self_advertised_features[] =
{ FEATURE_FIXED, NS_TUBES },
{ FEATURE_FIXED, NS_BYTESTREAMS },
{ FEATURE_FIXED, NS_VERSION },
+ { FEATURE_FIXED, NS_LAST },
+ { FEATURE_FIXED, NS_RECEIPTS },
#ifdef ENABLE_FILE_TRANSFER
{ FEATURE_OPTIONAL, NS_FILE_TRANSFER },
@@ -453,7 +452,7 @@ void
gabble_capability_set_update (GabbleCapabilitySet *target,
const GabbleCapabilitySet *source)
{
- TpIntSet *ret;
+ TpIntset *ret;
g_return_if_fail (target != NULL);
g_return_if_fail (source != NULL);
@@ -539,9 +538,7 @@ gabble_capability_set_add (GabbleCapabilitySet *caps,
g_return_if_fail (cap != NULL);
handle = tp_handle_ensure (feature_handles, cap, NULL, NULL);
-
tp_handle_set_add (caps->handles, handle);
- tp_handle_unref (feature_handles, handle);
}
gboolean
@@ -613,16 +610,17 @@ gboolean
gabble_capability_set_has_one (const GabbleCapabilitySet *caps,
const GabbleCapabilitySet *alternatives)
{
- TpIntSetIter iter;
+ TpIntsetFastIter iter;
+ guint element;
g_return_val_if_fail (caps != NULL, FALSE);
g_return_val_if_fail (alternatives != NULL, FALSE);
- tp_intset_iter_init (&iter, tp_handle_set_peek (alternatives->handles));
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (alternatives->handles));
- while (tp_intset_iter_next (&iter))
+ while (tp_intset_fast_iter_next (&iter, &element))
{
- if (tp_handle_set_is_member (caps->handles, iter.element))
+ if (tp_handle_set_is_member (caps->handles, element))
{
return TRUE;
}
@@ -636,16 +634,17 @@ gboolean
gabble_capability_set_at_least (const GabbleCapabilitySet *caps,
const GabbleCapabilitySet *query)
{
- TpIntSetIter iter;
+ TpIntsetFastIter iter;
+ guint element;
g_return_val_if_fail (caps != NULL, FALSE);
g_return_val_if_fail (query != NULL, FALSE);
- tp_intset_iter_init (&iter, tp_handle_set_peek (query->handles));
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (query->handles));
- while (tp_intset_iter_next (&iter))
+ while (tp_intset_fast_iter_next (&iter, &element))
{
- if (!tp_handle_set_is_member (caps->handles, iter.element))
+ if (!tp_handle_set_is_member (caps->handles, element))
{
return FALSE;
}
@@ -670,16 +669,17 @@ void
gabble_capability_set_foreach (const GabbleCapabilitySet *caps,
GFunc func, gpointer user_data)
{
- TpIntSetIter iter;
+ TpIntsetFastIter iter;
+ guint element;
g_return_if_fail (caps != NULL);
g_return_if_fail (func != NULL);
- tp_intset_iter_init (&iter, tp_handle_set_peek (caps->handles));
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (caps->handles));
- while (tp_intset_iter_next (&iter))
+ while (tp_intset_fast_iter_next (&iter, &element))
{
- const gchar *var = tp_handle_inspect (feature_handles, iter.element);
+ const gchar *var = tp_handle_inspect (feature_handles, element);
g_return_if_fail (var != NULL);
@@ -690,10 +690,10 @@ gabble_capability_set_foreach (const GabbleCapabilitySet *caps,
static void
append_intset (GString *ret,
- const TpIntSet *cap_ints,
+ const TpIntset *cap_ints,
const gchar *indent)
{
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
guint element;
tp_intset_fast_iter_init (&iter, cap_ints);
@@ -739,7 +739,7 @@ gabble_capability_set_dump_diff (const GabbleCapabilitySet *old_caps,
const GabbleCapabilitySet *new_caps,
const gchar *indent)
{
- TpIntSet *old_ints, *new_ints, *rem, *add;
+ TpIntset *old_ints, *new_ints, *rem, *add;
GString *ret;
g_return_val_if_fail (old_caps != NULL, NULL);
diff --git a/src/caps-channel-manager.c b/src/caps-channel-manager.c
index 135427aa0..ec18975e4 100644
--- a/src/caps-channel-manager.c
+++ b/src/caps-channel-manager.c
@@ -23,9 +23,7 @@
#include "config.h"
#include "gabble/caps-channel-manager.h"
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/channel-manager.h>
-
+#include <telepathy-glib/telepathy-glib.h>
#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
#include "debug.h"
diff --git a/src/caps-hash.c b/src/caps-hash.c
index 12d302ec3..ec2efc918 100644
--- a/src/caps-hash.c
+++ b/src/caps-hash.c
@@ -33,7 +33,6 @@
#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
-#include "base64.h"
#include "gabble/capabilities.h"
#include "debug.h"
#include "namespaces.h"
diff --git a/src/conn-addressing.c b/src/conn-addressing.c
index c02910e10..7fff35455 100644
--- a/src/conn-addressing.c
+++ b/src/conn-addressing.c
@@ -23,8 +23,8 @@
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "extensions/extensions.h"
@@ -104,7 +104,6 @@ conn_addressing_get_contacts_by_uri (GabbleSvcConnectionInterfaceAddressing *ifa
gabble_svc_connection_interface_addressing_return_from_get_contacts_by_uri (
context, requested, attributes);
- tp_handles_unref (contact_repo, handles);
g_array_unref (handles);
g_hash_table_unref (requested);
g_hash_table_unref (attributes);
@@ -145,7 +144,6 @@ conn_addressing_get_contacts_by_vcard_field (GabbleSvcConnectionInterfaceAddress
gabble_svc_connection_interface_addressing_return_from_get_contacts_by_vcard_field (
context, requested, attributes);
- tp_handles_unref (contact_repo, handles);
g_array_unref (handles);
g_hash_table_unref (requested);
g_hash_table_unref (attributes);
diff --git a/src/conn-aliasing.c b/src/conn-aliasing.c
index f48758eaf..26637039e 100644
--- a/src/conn-aliasing.c
+++ b/src/conn-aliasing.c
@@ -22,10 +22,9 @@
#include "conn-aliasing.h"
#include <wocky/wocky.h>
-#include <telepathy-glib/contacts-mixin.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-connection.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION
@@ -103,7 +102,6 @@ aliases_request_new (GabbleConnection *conn,
const GArray *contacts)
{
AliasesRequest *request;
- TpHandleRepoIface *contact_handles;
request = g_slice_new0 (AliasesRequest);
request->conn = conn;
@@ -116,10 +114,6 @@ aliases_request_new (GabbleConnection *conn,
g_new0 (GabbleRequestPipelineItem *, contacts->len);
request->aliases = g_new0 (gchar *, contacts->len + 1);
- contact_handles = tp_base_connection_get_handles ((TpBaseConnection *) conn,
- TP_HANDLE_TYPE_CONTACT);
- tp_handles_ref (contact_handles, contacts);
-
return request;
}
@@ -128,7 +122,6 @@ static void
aliases_request_free (AliasesRequest *request)
{
guint i;
- TpHandleRepoIface *contact_handles;
for (i = 0; i < request->contacts->len; i++)
{
@@ -138,10 +131,6 @@ aliases_request_free (AliasesRequest *request)
request->vcard_requests[i]);
}
- contact_handles = tp_base_connection_get_handles (
- (TpBaseConnection *) request->conn, TP_HANDLE_TYPE_CONTACT);
- tp_handles_unref (contact_handles, request->contacts);
-
g_array_unref (request->contacts);
g_free (request->vcard_requests);
g_free (request->pep_requests);
@@ -262,7 +251,7 @@ aliases_request_basic_pep_cb (GabbleConnection *self,
source = _gabble_connection_get_cached_alias (self, handle, NULL);
if (source < GABBLE_CONNECTION_ALIAS_FROM_VCARD &&
- base->status == TP_CONNECTION_STATUS_CONNECTED &&
+ tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED &&
!gabble_vcard_manager_has_cached_alias (self->vcard_manager, handle))
{
/* no alias in PEP, get the vcard */
@@ -303,7 +292,8 @@ aliases_request_pep_cb (GabbleConnection *self,
{
aliases_request->aliases[index] = alias;
}
- else if (base->status != TP_CONNECTION_STATUS_CONNECTED)
+ else if (tp_base_connection_get_status (base) !=
+ TP_CONNECTION_STATUS_CONNECTED)
{
DEBUG ("no longer connected, not chaining up to vCard");
g_free (alias);
@@ -341,7 +331,6 @@ pep_request_cb (
pep_request_ctx *ctx = user_data;
ctx->callback (conn, msg, ctx->user_data, error);
- tp_handle_unref (ctx->contact_handles, ctx->handle);
g_slice_free (pep_request_ctx, ctx);
}
@@ -362,7 +351,8 @@ gabble_do_pep_request (GabbleConnection *self,
pep_request_ctx *ctx;
/* callers must check this... */
- g_assert (base->status == TP_CONNECTION_STATUS_CONNECTED);
+ g_assert (tp_base_connection_get_status (base) ==
+ TP_CONNECTION_STATUS_CONNECTED);
/* ... which implies this */
g_assert (self->req_pipeline != NULL);
@@ -372,7 +362,6 @@ gabble_do_pep_request (GabbleConnection *self,
ctx->contact_handles = contact_handles;
ctx->handle = handle;
- tp_handle_ref (contact_handles, handle);
to = tp_handle_inspect (contact_handles, handle);
msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET,
NULL, to,
@@ -512,7 +501,8 @@ set_one_alias (
TP_HANDLE_TYPE_CONTACT);
gboolean ret = TRUE;
- g_assert (base->status == TP_CONNECTION_STATUS_CONNECTED);
+ g_assert (tp_base_connection_get_status (base) ==
+ TP_CONNECTION_STATUS_CONNECTED);
if (tp_str_empty (alias))
alias = NULL;
@@ -521,7 +511,7 @@ set_one_alias (
{
ret = FALSE;
}
- else if (base->self_handle == handle)
+ else if (tp_base_connection_get_self_handle (base) == handle)
{
/* only alter the roster if we're already there, e.g. because someone
* added us with another client
@@ -555,7 +545,7 @@ set_one_alias (
maybe_request_vcard (conn, handle, source);
}
- if (base->self_handle == handle)
+ if (tp_base_connection_get_self_handle (base) == handle)
{
GabbleVCardManagerEditInfo *edit;
GQueue edits = G_QUEUE_INIT;
@@ -936,7 +926,7 @@ get_cached_remote_alias (
/* 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)
+ if (handle == tp_base_connection_get_self_handle (base))
{
gchar *cm_alias;
@@ -1081,7 +1071,7 @@ maybe_request_vcard (GabbleConnection *self, TpHandle handle,
/* If the source wasn't good enough then do a request */
if (source < GABBLE_CONNECTION_ALIAS_FROM_VCARD &&
- base->status == TP_CONNECTION_STATUS_CONNECTED &&
+ tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED &&
!gabble_vcard_manager_has_cached_alias (self->vcard_manager, handle))
{
if (self->features & GABBLE_CONNECTION_FEATURES_PEP)
diff --git a/src/conn-avatars.c b/src/conn-avatars.c
index 3a12ce290..a90555113 100644
--- a/src/conn-avatars.c
+++ b/src/conn-avatars.c
@@ -24,11 +24,9 @@
#include <string.h>
-#include <telepathy-glib/svc-connection.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/contacts-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
-#include "base64.h"
#include "presence.h"
#include "presence-cache.h"
#include "conn-presence.h"
@@ -57,7 +55,7 @@ update_own_avatar_sha1 (GabbleConnection *conn,
return TRUE;
tp_svc_connection_interface_avatars_emit_avatar_updated (conn,
- base->self_handle, sha1);
+ tp_base_connection_get_self_handle (base), sha1);
g_free (conn->self_presence->avatar_sha1);
conn->self_presence->avatar_sha1 = g_strdup (sha1);
@@ -88,7 +86,7 @@ connection_avatar_update_cb (GabblePresenceCache *cache,
/* sha1 can be "" if we know there is no avatar, but must not be NULL here */
g_assert (sha1 != NULL);
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
update_own_avatar_sha1 (conn, sha1, NULL);
else
tp_svc_connection_interface_avatars_emit_avatar_updated (conn,
@@ -228,7 +226,7 @@ gabble_connection_get_avatar_tokens (TpSvcConnectionInterfaceAvatars *iface,
handle = g_array_index (contacts, TpHandle, i);
- if (base->self_handle == handle)
+ if (tp_base_connection_get_self_handle (base) == handle)
{
if (have_self_avatar)
{
@@ -294,9 +292,10 @@ _got_self_avatar_for_get_known_avatar_tokens (GObject *obj,
g_signal_handler_disconnect (obj, context->signal_conn);
- g_assert (base->self_handle != 0);
+ g_assert (tp_base_connection_get_self_handle (base) != 0);
- g_hash_table_insert (context->ret, GUINT_TO_POINTER (base->self_handle),
+ g_hash_table_insert (context->ret,
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)),
g_strdup (sha1));
tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens (
@@ -357,7 +356,7 @@ gabble_connection_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *ifac
handle = g_array_index (contacts, TpHandle, i);
- if (base->self_handle == handle)
+ if (tp_base_connection_get_self_handle (base) == handle)
{
if (have_self_avatar)
{
@@ -416,12 +415,14 @@ parse_avatar (WockyNode *vcard,
WockyNode *type_node;
WockyNode *binval_node;
const gchar *binval_value;
+ guchar *st;
+ gsize outlen;
photo_node = wocky_node_get_child (vcard, "PHOTO");
if (NULL == photo_node)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"contact vCard has no photo");
return FALSE;
}
@@ -441,7 +442,7 @@ parse_avatar (WockyNode *vcard,
if (NULL == binval_node)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"contact avatar is missing binval node");
return FALSE;
}
@@ -450,16 +451,18 @@ parse_avatar (WockyNode *vcard,
if (NULL == binval_value)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"contact avatar is missing binval content");
return FALSE;
}
- *avatar = base64_decode (binval_value);
+ st = g_base64_decode (binval_value, &outlen);
+ *avatar = g_string_new_len ((gchar *) st, outlen);
+ g_free (st);
if (NULL == *avatar)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"failed to decode avatar from base64");
return FALSE;
}
@@ -489,7 +492,7 @@ _request_avatar_cb (GabbleVCardManager *self,
if (NULL == vcard)
{
- GError tp_error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError tp_error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
vcard_error->message };
if (vcard_error->domain == WOCKY_XMPP_ERROR)
@@ -518,7 +521,7 @@ _request_avatar_cb (GabbleVCardManager *self,
goto out;
}
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
presence = conn->self_presence;
else
presence = gabble_presence_cache_get (conn->presence_cache, handle);
@@ -537,13 +540,13 @@ _request_avatar_cb (GabbleVCardManager *self,
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,
+ g_set_error (&error, TP_ERROR, 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)
+ if (handle == tp_base_connection_get_self_handle (base))
{
update_own_avatar_sha1 (conn, sha1, NULL);
g_free (sha1);
@@ -755,7 +758,7 @@ _set_avatar_cb2 (GabbleVCardManager *manager,
if (NULL == vcard)
{
- GError tp_error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError tp_error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
vcard_error->message };
/* Google Talk has been observed to return bad-request when the avatar is
@@ -790,7 +793,8 @@ _set_avatar_cb2 (GabbleVCardManager *manager,
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);
+ ctx->conn, tp_base_connection_get_self_handle (base),
+ presence->avatar_sha1);
}
else
{
@@ -833,15 +837,25 @@ gabble_connection_set_avatar (TpSvcConnectionInterfaceAvatars *iface,
if (avatar != NULL && avatar->len > 0)
{
+ gint state = 0, save = 0, outlen;
+ /* See the documentation for g_base64_encode_step(). */
+ guint base64_data_size = (avatar->len / 3 + 1) * 4 + 4;
+ guint base64_line_wrapped_data_size =
+ base64_data_size + (base64_data_size / 72) + 1;
+
ctx->avatar = g_string_new_len (avatar->data, avatar->len);
- base64 = base64_encode (avatar->len, avatar->data, TRUE);
+ base64 = g_malloc (base64_line_wrapped_data_size);
+ outlen = g_base64_encode_step ((const guchar *) avatar->data,
+ avatar->len, TRUE, base64, &state, &save);
+ outlen += g_base64_encode_close (TRUE, base64 + outlen, &state, &save);
+ base64[outlen] = '\0';
DEBUG ("Replacing avatar");
edit_info = gabble_vcard_manager_edit_info_new ("PHOTO",
NULL, GABBLE_VCARD_EDIT_REPLACE,
- "TYPE", mime_type,
- "BINVAL", base64,
+ '(', "TYPE", '$', mime_type, ')',
+ '(', "BINVAL", '$', base64, ')',
NULL);
g_free (base64);
@@ -890,7 +904,7 @@ conn_avatars_fill_contact_attributes (GObject *obj,
TpHandle handle = g_array_index (contacts, guint, i);
GabblePresence *presence = NULL;
- if (base->self_handle == handle)
+ if (tp_base_connection_get_self_handle (base) == handle)
presence = self->self_presence;
else
presence = gabble_presence_cache_get (self->presence_cache, handle);
diff --git a/src/conn-client-types.c b/src/conn-client-types.c
index 012749c19..1a5ff1e8f 100644
--- a/src/conn-client-types.c
+++ b/src/conn-client-types.c
@@ -22,7 +22,8 @@
#include <string.h>
#include <stdlib.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <extensions/extensions.h>
diff --git a/src/conn-contact-info.c b/src/conn-contact-info.c
index a78f172e4..599197b9b 100644
--- a/src/conn-contact-info.c
+++ b/src/conn-contact-info.c
@@ -24,9 +24,8 @@
#include <string.h>
-#include <telepathy-glib/svc-connection.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "vcard-manager.h"
@@ -484,7 +483,7 @@ _return_from_request_contact_info (WockyNode *vcard_node,
if (NULL == vcard_node)
{
- GError tp_error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError tp_error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
vcard_error->message };
if (vcard_error->domain == WOCKY_XMPP_ERROR)
@@ -650,7 +649,7 @@ conn_contact_info_new_edit (const VCardField *field,
if (field->types[0] == NULL && field_params[0] != NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%s vCard field expects no type-parameters", field->xmpp_name);
gabble_vcard_manager_edit_info_free (edit_info);
return NULL;
@@ -681,7 +680,7 @@ conn_contact_info_new_edit (const VCardField *field,
if (!used)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%s vCard field does not support type-parameter %s",
field->xmpp_name, *p);
gabble_vcard_manager_edit_info_free (edit_info);
@@ -703,7 +702,7 @@ _set_contact_info_cb (GabbleVCardManager *vcard_manager,
if (vcard_node == NULL)
{
- GError tp_error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError tp_error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
vcard_error->message };
if (vcard_error->domain == WOCKY_XMPP_ERROR)
@@ -763,7 +762,7 @@ gabble_connection_set_contact_info (TpSvcConnectionInterfaceContactInfo *iface,
if (field == NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"unknown vCard field from D-Bus: %s", field_name);
goto finally;
}
@@ -771,7 +770,7 @@ gabble_connection_set_contact_info (TpSvcConnectionInterfaceContactInfo *iface,
if (!gabble_vcard_manager_can_use_vcard_field (self->vcard_manager,
field->xmpp_name))
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%s vCard field is not supported by this server",
field->xmpp_name);
goto finally;
@@ -784,7 +783,7 @@ gabble_connection_set_contact_info (TpSvcConnectionInterfaceContactInfo *iface,
{
if (n_field_values != 1)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%s vCard field expects one value but got %u",
field->xmpp_name, n_field_values);
goto finally;
@@ -808,7 +807,7 @@ gabble_connection_set_contact_info (TpSvcConnectionInterfaceContactInfo *iface,
if (n_field_values != n_elements)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%s vCard field expects %u values but got %u",
field->xmpp_name, n_elements, n_field_values);
goto finally;
@@ -834,7 +833,7 @@ gabble_connection_set_contact_info (TpSvcConnectionInterfaceContactInfo *iface,
if (n_field_values == 0)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"ORG vCard field expects at least one value but got 0");
goto finally;
}
@@ -865,7 +864,7 @@ gabble_connection_set_contact_info (TpSvcConnectionInterfaceContactInfo *iface,
if (n_field_values != 1)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%s vCard field expects one value but got %u",
field->xmpp_name, n_field_values);
goto finally;
diff --git a/src/conn-location.c b/src/conn-location.c
index b9ac05474..ae78d68be 100644
--- a/src/conn-location.c
+++ b/src/conn-location.c
@@ -8,8 +8,8 @@
#define DEBUG_FLAG GABBLE_DEBUG_LOCATION
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
#include <gabble/gabble.h>
@@ -263,7 +263,7 @@ add_to_geoloc_node (const gchar *tp_name,
{
if (G_VALUE_TYPE (value) != G_TYPE_STRING)
{
- g_set_error (err, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (err, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"expecting string for language value, but got %s",
G_VALUE_TYPE_NAME (value));
return FALSE;
@@ -286,7 +286,7 @@ add_to_geoloc_node (const gchar *tp_name,
if (G_VALUE_TYPE (value) != mapping->type)
{
- g_set_error (err, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (err, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"'%s' is supposed to be of type %s but is %s",
(const char *) tp_name, g_type_name (mapping->type),
G_VALUE_TYPE_NAME (value));
@@ -364,7 +364,7 @@ location_set_location (TpSvcConnectionInterfaceLocation *iface,
if (!(conn->features & GABBLE_CONNECTION_FEATURES_PEP))
{
- GError error = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ GError error = { TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Server does not support PEP, cannot publish geolocation" };
dbus_g_method_return_error (context, &error);
@@ -395,7 +395,7 @@ location_set_location (TpSvcConnectionInterfaceLocation *iface,
if (!_gabble_connection_send_with_reply (conn, msg, set_location_sent_cb,
G_OBJECT (conn), context, NULL))
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send msg" };
dbus_g_method_return_error (context, &error);
@@ -511,7 +511,7 @@ conn_location_properties_setter (GObject *object,
if (access_control_type !=
TP_RICH_PRESENCE_ACCESS_CONTROL_TYPE_PUBLISH_LIST)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Access control type not implemented");
return FALSE;
}
@@ -642,14 +642,11 @@ location_pep_node_changed (WockyPepService *pep,
return;
}
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
/* Ignore echoed pubsub notifications */
- goto out;
+ return;
update_location_from_item (conn, handle, item_node);
-
-out:
- tp_handle_unref (contact_repo, handle);
}
static void
diff --git a/src/conn-mail-notif.c b/src/conn-mail-notif.c
index 2fe12e41e..0bc7169f8 100644
--- a/src/conn-mail-notif.c
+++ b/src/conn-mail-notif.c
@@ -33,11 +33,9 @@
#include <string.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/svc-connection.h>
-#include <telepathy-glib/util.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
@@ -90,12 +88,12 @@ return_from_request_inbox_url (GabbleConnection *conn)
if (priv->inbox_url != NULL && priv->inbox_url[0] == '\0')
{
- error = g_error_new (TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ error = g_error_new (TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Server did not provide base URL.");
}
else if (priv->inbox_url == NULL)
{
- error = g_error_new (TP_ERRORS, TP_ERROR_DISCONNECTED,
+ error = g_error_new (TP_ERROR, TP_ERROR_DISCONNECTED,
"Connection was disconnected during request.");
}
else
@@ -141,9 +139,11 @@ static inline gboolean
check_supported_or_dbus_return (GabbleConnection *conn,
DBusGMethodInvocation *context)
{
- if (TP_BASE_CONNECTION (conn)->status != TP_CONNECTION_STATUS_CONNECTED)
+ TpBaseConnection *base = TP_BASE_CONNECTION (conn);
+
+ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
{
- GError e = { TP_ERRORS, TP_ERROR_DISCONNECTED, "Not connected" };
+ GError e = { TP_ERROR, TP_ERROR_DISCONNECTED, "Not connected" };
dbus_g_method_return_error (context, &e);
return TRUE;
}
@@ -220,7 +220,7 @@ gabble_mail_notification_request_mail_url (
}
else
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to retrieve URL from server."};
dbus_g_method_return_error (context, &error);
}
@@ -521,11 +521,11 @@ query_unread_mails_cb (GObject *source_object,
static void
update_unread_mails (GabbleConnection *conn)
{
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn);
+ TpBaseConnection *base = TP_BASE_CONNECTION (conn);
WockyStanza *query;
WockyPorter *porter = wocky_session_get_porter (conn->session);
- if (base_conn->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
return;
if (!(conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY))
@@ -606,14 +606,14 @@ new_mail_handler (WockyPorter *porter,
static void
ensure_google_settings (GabbleConnection *self)
{
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (self);
+ TpBaseConnection *base = TP_BASE_CONNECTION (self);
WockyStanza *query;
WockyPorter *porter;
if (!self->mail_priv->should_set_google_settings)
return;
- if (base_conn->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
return;
porter = wocky_session_get_porter (self->session);
diff --git a/src/conn-olpc.c b/src/conn-olpc.c
index 243d2dff0..46fef4b0d 100644
--- a/src/conn-olpc.c
+++ b/src/conn-olpc.c
@@ -23,8 +23,7 @@
#include <string.h>
#include <stdlib.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/util.h>
+#include <telepathy-glib/telepathy-glib.h>
#define DEBUG_FLAG GABBLE_DEBUG_OLPC
@@ -97,13 +96,12 @@ activity_info_contribute_properties (GabbleOlpcActivity *activity,
if (only_public && !gabble_olpc_activity_is_visible (activity))
return FALSE;
- props_node = wocky_node_add_child_with_content (parent,
- "properties", "");
+ props_node = wocky_node_add_child_ns (parent,
+ "properties", NS_OLPC_ACTIVITY_PROPS);
wocky_node_set_attributes (props_node,
"room", gabble_olpc_activity_get_room (activity),
"activity", activity->id,
NULL);
- props_node->ns = g_quark_from_string (NS_OLPC_ACTIVITY_PROPS);
lm_message_node_add_children_from_properties (props_node,
activity->properties, "property");
@@ -129,7 +127,7 @@ check_pep (GabbleConnection *conn,
{
if (!(conn->features & GABBLE_CONNECTION_FEATURES_PEP))
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Server does not support PEP" };
DEBUG ("%s", error.message);
@@ -277,7 +275,7 @@ get_properties_reply_cb (GObject *source,
NULL, &error);
if (reply_msg == NULL)
{
- GError err = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError err = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property request to server" };
DEBUG ("Query failed: %s", error->message);
@@ -379,7 +377,7 @@ transmit_properties (GabbleConnection *conn,
if (!_gabble_connection_send_with_reply (conn, msg,
set_properties_reply_cb, NULL, context, NULL))
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property change request to server" };
DEBUG ("%s", error.message);
@@ -433,10 +431,10 @@ olpc_buddy_info_set_properties (GabbleSvcOLPCBuddyInfo *iface,
DBusGMethodInvocation *context)
{
GabbleConnection *conn = GABBLE_CONNECTION (iface);
- TpBaseConnection *base_conn = (TpBaseConnection *) conn;
+ TpBaseConnection *base = (TpBaseConnection *) conn;
DEBUG ("called");
- if (base_conn->status == TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED)
{
transmit_properties (conn, properties, context);
}
@@ -493,9 +491,9 @@ olpc_buddy_props_pep_node_changed (WockyPepService *pep,
return;
}
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
/* Ignore echoed pubsub notifications */
- goto out;
+ return;
node = search_for_child (
wocky_stanza_get_top_node (stanza), "properties", NULL);
@@ -503,8 +501,6 @@ olpc_buddy_props_pep_node_changed (WockyPepService *pep,
gabble_svc_olpc_buddy_info_emit_properties_changed (conn, handle,
properties);
g_hash_table_unref (properties);
-out:
- tp_handle_unref (contact_repo, handle);
}
static void
@@ -575,7 +571,7 @@ static GPtrArray *
get_buddy_activities (GabbleConnection *conn,
TpHandle buddy)
{
- TpIntSet *all;
+ TpIntset *all;
gboolean free_all = FALSE;
GPtrArray *activities = g_ptr_array_new ();
TpHandleSet *invited_activities, *pep_activities;
@@ -612,18 +608,21 @@ get_buddy_activities (GabbleConnection *conn,
if (all != NULL)
{
- TpIntSetIter iter = TP_INTSET_ITER_INIT (all);
+ TpIntsetFastIter iter;
+ guint element;
+
+ tp_intset_fast_iter_init (&iter, all);
- while (tp_intset_iter_next (&iter))
+ while (tp_intset_fast_iter_next (&iter, &element))
{
GabbleOlpcActivity *activity = g_hash_table_lookup (
- conn->olpc_activities_info, GUINT_TO_POINTER (iter.element));
+ conn->olpc_activities_info, GUINT_TO_POINTER (element));
GValue gvalue = { 0 };
g_assert (activity != NULL);
if (activity->id == NULL)
{
- DEBUG ("... activity #%u has no ID, skipping", iter.element);
+ DEBUG ("... activity #%u has no ID, skipping", element);
continue;
}
@@ -707,7 +706,6 @@ extract_activities (GabbleConnection *conn,
if (tp_handle_set_is_member (activities_set, room_handle))
{
NODE_DEBUG (node, "Room advertised twice, skipping");
- tp_handle_unref (room_repo, room_handle);
continue;
}
@@ -719,7 +717,6 @@ extract_activities (GabbleConnection *conn,
}
/* pass ownership to the activities_set */
tp_handle_set_add (activities_set, room_handle);
- tp_handle_unref (room_repo, room_handle);
if (tp_strdiff (activity->id, act_id))
{
@@ -824,7 +821,7 @@ get_activities_reply_cb (GObject *source,
NULL, &err);
if (reply_msg == NULL)
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property request to server" };
DEBUG ("Query failed: %s", err->message);
@@ -838,7 +835,7 @@ get_activities_reply_cb (GObject *source,
wocky_stanza_get_top_node (reply_msg), "from");
if (from == NULL)
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Error in pubsub reply: no sender" };
dbus_g_method_return_error (ctx->context, &error);
@@ -848,7 +845,7 @@ get_activities_reply_cb (GObject *source,
from_handle = tp_handle_lookup (contact_repo, from, NULL, NULL);
if (from_handle == 0)
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Error in pubsub reply: unknown sender" };
dbus_g_method_return_error (ctx->context, &error);
@@ -926,8 +923,8 @@ upload_activities_pep (GabbleConnection *conn,
TpBaseConnection *base = (TpBaseConnection *) conn;
WockyNode *item, *activities;
WockyStanza *msg;
- TpHandleSet *my_activities = g_hash_table_lookup
- (conn->olpc_pep_activities, GUINT_TO_POINTER (base->self_handle));
+ TpHandleSet *my_activities = g_hash_table_lookup (conn->olpc_pep_activities,
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
GError *e = NULL;
gboolean ret;
@@ -938,13 +935,15 @@ upload_activities_pep (GabbleConnection *conn,
if (my_activities != NULL)
{
- TpIntSetIter iter = TP_INTSET_ITER_INIT (tp_handle_set_peek
- (my_activities));
+ TpIntsetFastIter iter;
+ guint element;
- while (tp_intset_iter_next (&iter))
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (my_activities));
+
+ while (tp_intset_fast_iter_next (&iter, &element))
{
GabbleOlpcActivity *activity = g_hash_table_lookup (
- conn->olpc_activities_info, GUINT_TO_POINTER (iter.element));
+ conn->olpc_activities_info, GUINT_TO_POINTER (element));
WockyNode *activity_node;
g_assert (activity != NULL);
@@ -965,7 +964,7 @@ upload_activities_pep (GabbleConnection *conn,
if (!ret)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property change request to server: %s", e->message);
g_error_free (e);
}
@@ -1001,7 +1000,7 @@ add_activity (GabbleConnection *self,
TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
base, TP_HANDLE_TYPE_ROOM);
TpHandleSet *old_activities = g_hash_table_lookup (self->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
GabbleOlpcActivity *activity;
if (!tp_handle_is_valid (room_repo, channel, error))
@@ -1012,7 +1011,7 @@ add_activity (GabbleConnection *self,
if (old_activities != NULL && tp_handle_set_is_member (old_activities, channel))
{
- *error = g_error_new (TP_ERRORS,
+ *error = g_error_new (TP_ERROR,
TP_ERROR_INVALID_ARGUMENT,
"Can't set twice the same activity: %s", id);
@@ -1109,7 +1108,7 @@ olpc_buddy_info_set_activities (GabbleSvcOLPCBuddyInfo *iface,
{
if (tp_handle_set_is_member (activities_set, channel))
{
- error = g_error_new (TP_ERRORS,
+ error = g_error_new (TP_ERROR,
TP_ERROR_INVALID_ARGUMENT,
"Can't set twice the same activity: %s", room);
@@ -1145,7 +1144,7 @@ olpc_buddy_info_set_activities (GabbleSvcOLPCBuddyInfo *iface,
}
old_activities = g_hash_table_lookup (conn->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
if (old_activities != NULL)
{
@@ -1157,11 +1156,12 @@ olpc_buddy_info_set_activities (GabbleSvcOLPCBuddyInfo *iface,
/* Update the list of activities associated with our own contact. */
g_hash_table_insert (conn->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle), activities_set);
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)),
+ activities_set);
if (!upload_activities_pep (conn, set_activities_reply_cb, context, NULL))
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property request to server" };
dbus_g_method_return_error (context, &error);
@@ -1195,7 +1195,7 @@ olpc_activities_pep_node_changed (WockyPepService *pep,
return;
}
- if (handle != base->self_handle)
+ if (handle != tp_base_connection_get_self_handle (base))
extract_activities (conn, stanza, handle);
activities = get_buddy_activities (conn, handle);
@@ -1302,8 +1302,6 @@ extract_current_activity (GabbleConnection *conn,
conn->olpc_pep_activities);
}
- tp_handle_unref (room_repo, room_handle);
-
/* update current-activity cache */
if (activity != NULL)
{
@@ -1336,7 +1334,7 @@ get_current_activity_reply_cb (GObject *source,
NULL, &error);
if (reply_msg == NULL)
{
- GError err = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError err = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property request to server" };
DEBUG ("Query failed: %s", error->message);
@@ -1463,7 +1461,7 @@ activity_in_own_set (GabbleConnection *conn,
return FALSE;
activities_set = g_hash_table_lookup (conn->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
if (activities_set == NULL ||
!tp_handle_set_is_member (activities_set, room_handle))
@@ -1501,7 +1499,7 @@ olpc_buddy_info_set_current_activity (GabbleSvcOLPCBuddyInfo *iface,
if (!activity_in_own_set (conn, room))
{
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Can't set an activity as current if you're not announcing it" };
dbus_g_method_return_error (context, &error);
@@ -1522,7 +1520,7 @@ olpc_buddy_info_set_current_activity (GabbleSvcOLPCBuddyInfo *iface,
if (!_gabble_connection_send_with_reply (conn, msg,
set_current_activity_reply_cb, NULL, context, NULL))
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property change request to server" };
dbus_g_method_return_error (context, &error);
@@ -1554,9 +1552,9 @@ olpc_current_act_pep_node_changed (WockyPepService *pep,
return;
}
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
/* Ignore echoed pubsub notifications */
- goto out;
+ return;
node = search_for_child (wocky_stanza_get_top_node (stanza),
"activity", NULL);
@@ -1576,9 +1574,6 @@ olpc_current_act_pep_node_changed (WockyPepService *pep,
gabble_svc_olpc_buddy_info_emit_current_activity_changed (conn, handle,
"", 0);
}
-
-out:
- tp_handle_unref (contact_repo, handle);
}
static void
@@ -1607,7 +1602,7 @@ olpc_buddy_info_add_activity (GabbleSvcOLPCBuddyInfo *iface,
GabbleConnection *self = GABBLE_CONNECTION (iface);
TpBaseConnection *base = (TpBaseConnection *) self;
TpHandleSet *activities_set = g_hash_table_lookup (self->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
TpHandleRepoIface *room_repo = tp_base_connection_get_handles (base,
TP_HANDLE_TYPE_ROOM);
GError *error = NULL;
@@ -1627,14 +1622,15 @@ olpc_buddy_info_add_activity (GabbleSvcOLPCBuddyInfo *iface,
if (activities_set == NULL) {
activities_set = tp_handle_set_new (room_repo);
g_hash_table_insert (self->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle), activities_set);
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)),
+ activities_set);
}
tp_handle_set_add (activities_set, channel);
if (!upload_activities_pep (self, add_activity_reply_cb, context, NULL))
{
- error = g_error_new (TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ error = g_error_new (TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property request to server");
dbus_g_method_return_error (context, error);
@@ -1672,7 +1668,7 @@ upload_activity_properties_pep (GabbleConnection *conn,
GError *e = NULL;
gboolean ret;
TpHandleSet *my_activities = g_hash_table_lookup (conn->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_act_props, &item);
publish = wocky_node_add_child_ns (item, "activities",
@@ -1680,13 +1676,15 @@ upload_activity_properties_pep (GabbleConnection *conn,
if (my_activities != NULL)
{
- TpIntSetIter iter = TP_INTSET_ITER_INIT (tp_handle_set_peek
- (my_activities));
+ TpIntsetFastIter iter;
+ guint element;
+
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (my_activities));
- while (tp_intset_iter_next (&iter))
+ while (tp_intset_fast_iter_next (&iter, &element))
{
GabbleOlpcActivity *activity = g_hash_table_lookup (
- conn->olpc_activities_info, GUINT_TO_POINTER (iter.element));
+ conn->olpc_activities_info, GUINT_TO_POINTER (element));
activity_info_contribute_properties (activity, publish, TRUE);
}
@@ -1697,7 +1695,7 @@ upload_activity_properties_pep (GabbleConnection *conn,
if (!ret)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property change request to server: %s", e->message);
g_error_free (e);
}
@@ -1793,12 +1791,14 @@ refresh_invitations (GabbleConnection *conn,
if (invitees != NULL && tp_handle_set_size (invitees) > 0)
{
- TpIntSetIter iter = TP_INTSET_ITER_INIT (tp_handle_set_peek
- (invitees));
+ TpIntsetFastIter iter;
+ guint element;
+
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (invitees));
- while (tp_intset_iter_next (&iter))
+ while (tp_intset_fast_iter_next (&iter, &element))
{
- const gchar *to = tp_handle_inspect (contact_repo, iter.element);
+ const gchar *to = tp_handle_inspect (contact_repo, element);
WockyStanza *msg = wocky_stanza_build (
WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
NULL, to, NULL);
@@ -1853,7 +1853,7 @@ olpc_activity_properties_set_properties (GabbleSvcOLPCActivityProperties *iface,
if (!activity_in_own_set (conn, jid))
{
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Can't set properties on an activity if you're not announcing it" };
dbus_g_method_return_error (context, &error);
@@ -1870,7 +1870,7 @@ olpc_activity_properties_set_properties (GabbleSvcOLPCActivityProperties *iface,
}
if (muc_channel == NULL || state != MUC_STATE_JOINED)
{
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Can't set properties on an activity if you're not in it" };
dbus_g_method_return_error (context, &error);
@@ -1898,7 +1898,7 @@ olpc_activity_properties_set_properties (GabbleSvcOLPCActivityProperties *iface,
wocky_stanza_get_top_node (msg), FALSE);
if (!_gabble_connection_send (conn, msg, NULL))
{
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR,
"Failed to send property change notification to chatroom" };
g_object_unref (msg);
@@ -2093,8 +2093,6 @@ update_activity_properties (GabbleConnection *conn,
}
}
- tp_handle_unref (room_repo, room_handle);
-
if (activity == NULL)
return;
@@ -2175,13 +2173,11 @@ olpc_act_props_pep_node_changed (WockyPepService *pep,
return;
}
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
/* Ignore echoed pubsub notifications */
- goto out;
+ return;
update_activities_properties (conn, jid, stanza);
-out:
- tp_handle_unref (contact_repo, handle);
}
static void
@@ -2364,7 +2360,6 @@ conn_olpc_process_activity_properties_message (GabbleConnection *conn,
g_object_ref (activity);
tp_handle_set_add (their_invites, room_handle);
}
- tp_handle_unref (room_repo, room_handle);
}
else
{
@@ -2432,7 +2427,7 @@ conn_olpc_process_activity_properties_message (GabbleConnection *conn,
if (pep_properties_changed)
{
our_activities = g_hash_table_lookup (conn->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
if (our_activities != NULL &&
tp_handle_set_is_member (our_activities, room_handle))
{
@@ -2448,7 +2443,7 @@ conn_olpc_process_activity_properties_message (GabbleConnection *conn,
if (is_visible != was_visible)
{
our_activities = g_hash_table_lookup (conn->olpc_pep_activities,
- GUINT_TO_POINTER (base->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
if (our_activities != NULL &&
tp_handle_set_is_member (our_activities, room_handle))
{
@@ -2496,13 +2491,15 @@ revoke_invitations (GabbleConnection *conn,
if (invitees != NULL && tp_handle_set_size (invitees) > 0)
{
- TpIntSetIter iter = TP_INTSET_ITER_INIT (tp_handle_set_peek
- (invitees));
+ TpIntsetFastIter iter;
+ guint element;
+
+ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (invitees));
DEBUG ("revoke invitations for activity %s", activity->id);
- while (tp_intset_iter_next (&iter))
+ while (tp_intset_fast_iter_next (&iter, &element))
{
- const gchar *to = tp_handle_inspect (contact_repo, iter.element);
+ const gchar *to = tp_handle_inspect (contact_repo, element);
WockyStanza *msg = wocky_stanza_build (
WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
NULL, to,
@@ -2628,10 +2625,16 @@ muc_channel_closed_cb (GabbleMucChannel *chan,
GabbleOlpcActivity *activity)
{
GabbleConnection *conn;
+ TpBaseConnection *base;
TpHandleSet *my_activities;
gboolean was_in_our_pep = FALSE;
+ /* is the muc channel /actually/ disappearing */
+ if (!tp_base_channel_is_destroyed (TP_BASE_CHANNEL (chan)))
+ return;
+
g_object_get (activity, "connection", &conn, NULL);
+ base = TP_BASE_CONNECTION (conn);
/* Revoke invitations we sent for this activity */
revoke_invitations (conn, chan, activity, NULL);
@@ -2639,7 +2642,7 @@ muc_channel_closed_cb (GabbleMucChannel *chan,
/* remove it from our advertised activities list, unreffing it in the
* process if it was in fact advertised */
my_activities = g_hash_table_lookup (conn->olpc_pep_activities,
- GUINT_TO_POINTER (TP_BASE_CONNECTION (conn)->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)));
if (my_activities != NULL)
{
if (tp_handle_set_remove (my_activities, activity->room))
@@ -2723,7 +2726,6 @@ muc_channel_pre_invite_cb (GabbleMucChannel *chan,
}
tp_handle_set_add (invitees, handle);
- tp_handle_unref (contact_repo, handle);
g_object_unref (conn);
}
@@ -2784,10 +2786,12 @@ muc_channel_contact_join_cb (GabbleMucChannel *chan,
GabbleOlpcActivity *activity)
{
GabbleConnection *conn;
+ TpBaseConnection *base;
g_object_get (activity, "connection", &conn, NULL);
+ base = TP_BASE_CONNECTION (conn);
- if (contact == TP_BASE_CONNECTION (conn)->self_handle)
+ if (contact == tp_base_connection_get_self_handle (base))
{
/* We join the channel, forget about all invites we received about
* this activity */
@@ -3046,7 +3050,7 @@ olpc_activity_properties_get_activity (GabbleSvcOLPCActivityProperties *iface,
activity = find_activity_by_id (self, activity_id);
if (activity == NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Activity unknown: %s", activity_id);
goto error;
}
diff --git a/src/conn-presence.c b/src/conn-presence.c
index cc197643f..e06062f56 100644
--- a/src/conn-presence.c
+++ b/src/conn-presence.c
@@ -24,11 +24,8 @@
#include <string.h>
#include <stdlib.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/presence-mixin.h>
-#include <telepathy-glib/svc-connection.h>
-#include <telepathy-glib/util.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
@@ -122,13 +119,15 @@ static TpPresenceStatusSpec *gabble_statuses = NULL;
/* prototypes */
-static void set_xep0186_invisible_cb (GabbleConnection *conn,
- WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *obj,
+static void set_xep0186_invisible_cb (
+ GObject *source,
+ GAsyncResult *set_result,
gpointer user_data);
static void activate_current_privacy_list_cb (
- GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg,
- GObject *obj, gpointer user_data);
+ GObject *source,
+ GAsyncResult *activate_result,
+ gpointer user_data);
static void setup_invisible_privacy_list_async (GabbleConnection *self,
GAsyncReadyCallback callback, gpointer user_data);
@@ -139,8 +138,9 @@ static gboolean iq_privacy_list_push_cb (
gpointer user_data);
static void verify_invisible_privacy_list_cb (
- GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg,
- GObject *obj, gpointer user_data);
+ GObject *source,
+ GAsyncResult *verify_result,
+ gpointer user_data);
static void toggle_presence_visibility_async (GabbleConnection *self,
GAsyncReadyCallback callback,
@@ -196,7 +196,7 @@ construct_contact_statuses_cb (GObject *obj,
{
handle = g_array_index (contact_handles, TpHandle, i);
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
presence = self->self_presence;
else
presence = gabble_presence_cache_get (self->presence_cache, handle);
@@ -271,8 +271,10 @@ emit_presences_changed_for_self (GabbleConnection *self)
{
TpBaseConnection *base = TP_BASE_CONNECTION (self);
GArray *handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1);
+ TpHandle self_handle;
- g_array_insert_val (handles, 0, base->self_handle);
+ self_handle = tp_base_connection_get_self_handle (base);
+ g_array_insert_val (handles, 0, self_handle);
conn_presence_emit_presence_update (self, handles);
g_array_unref (handles);
}
@@ -490,15 +492,11 @@ set_xep0186_invisible (GabbleConnection *self,
TpBaseConnection *base = (TpBaseConnection *) self;
GabbleConnectionPresencePrivate *priv = self->presence_priv;
GError *error = NULL;
- const gchar *element = invisible ? "invisible" : "visible";
- WockyStanza *iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
- WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL,
- '(', element, ':', NS_INVISIBLE, ')',
- NULL);
g_object_ref (result);
- if (!invisible && base->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (!invisible &&
+ tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
{
if (priv->privacy_statuses != NULL)
{
@@ -513,30 +511,31 @@ set_xep0186_invisible (GabbleConnection *self,
g_object_unref (result);
}
}
- else if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
- set_xep0186_invisible_cb, NULL, result, &error))
+ else
{
- g_simple_async_result_set_from_error (result, error);
- g_simple_async_result_complete_in_idle (result);
+ const gchar *element = invisible ? "invisible" : "visible";
+ WockyStanza *iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
+ WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL,
+ '(', element, ':', NS_INVISIBLE, ')',
+ NULL);
- g_object_unref (result);
- g_error_free (error);
- }
+ conn_util_send_iq_async (self, iq, NULL, set_xep0186_invisible_cb, result);
- g_object_unref (iq);
+ g_object_unref (iq);
+ }
}
static void
-set_xep0186_invisible_cb (GabbleConnection *conn,
- WockyStanza *sent_msg,
- WockyStanza *reply_msg,
- GObject *obj,
+set_xep0186_invisible_cb (
+ GObject *source,
+ GAsyncResult *set_result,
gpointer user_data)
{
+ GabbleConnection *conn = GABBLE_CONNECTION (source);
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
GError *error = NULL;
- if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
+ if (!conn_util_send_iq_finish (conn, set_result, NULL, &error))
{
g_simple_async_result_set_error (result,
CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_INVISIBLE,
@@ -590,21 +589,10 @@ activate_current_privacy_list (GabbleConnection *self,
gabble_statuses[presence->status].name,
list_name ? list_name : "(no list)");
- iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
- WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL,
- '(', "query", ':', NS_PRIVACY,
- '(', "active",
- '*', &active_node,
- ')',
- ')',
- NULL);
-
- if (list_name != NULL)
- wocky_node_set_attribute (active_node, "name", list_name);
-
g_object_ref (result);
- if (base->status == TP_CONNECTION_STATUS_CONNECTED && invisible)
+ if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED &&
+ invisible)
{
if (!gabble_connection_send_presence (self,
WOCKY_STANZA_SUB_TYPE_UNAVAILABLE, NULL, NULL, &error))
@@ -614,7 +602,7 @@ activate_current_privacy_list (GabbleConnection *self,
* need to bother with removing the active list; just shortcut to
* signalling our presence. */
else if (list_name == NULL &&
- base->status != TP_CONNECTION_STATUS_CONNECTED)
+ tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
{
if (!conn_presence_signal_own_presence (self, NULL, &error))
goto ERROR;
@@ -622,11 +610,25 @@ activate_current_privacy_list (GabbleConnection *self,
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
- goto OUT;
+ return;
}
- _gabble_connection_send_with_reply (self, (WockyStanza *) iq,
- activate_current_privacy_list_cb, NULL, result, &error);
+ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
+ WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL,
+ '(', "query", ':', NS_PRIVACY,
+ '(', "active",
+ '*', &active_node,
+ ')',
+ ')',
+ NULL);
+
+ if (list_name != NULL)
+ wocky_node_set_attribute (active_node, "name", list_name);
+
+ conn_util_send_iq_async (self, iq, NULL,
+ activate_current_privacy_list_cb, result);
+ g_object_unref (iq);
+ return;
ERROR:
if (error != NULL)
@@ -636,22 +638,19 @@ activate_current_privacy_list (GabbleConnection *self,
g_error_free (error);
g_object_unref (result);
}
-
- OUT:
- g_object_unref (iq);
}
static void
-activate_current_privacy_list_cb (GabbleConnection *conn,
- WockyStanza *sent_msg,
- WockyStanza *reply_msg,
- GObject *obj,
+activate_current_privacy_list_cb (
+ GObject *source,
+ GAsyncResult *activate_result,
gpointer user_data)
{
+ GabbleConnection *conn = GABBLE_CONNECTION (source);
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
GError *error = NULL;
- if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
+ if (!conn_util_send_iq_finish (conn, activate_result, NULL, &error))
{
g_simple_async_result_set_error (result,
CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_PRIVACY_LIST,
@@ -696,20 +695,19 @@ disable_invisible_privacy_list (GabbleConnection *self)
}
static void
-create_invisible_privacy_list_reply_cb (GabbleConnection *conn,
- WockyStanza *sent_msg,
- WockyStanza *reply_msg,
- GObject *obj,
+create_invisible_privacy_list_reply_cb (
+ GObject *source,
+ GAsyncResult *create_result,
gpointer user_data)
{
+ GabbleConnection *conn = GABBLE_CONNECTION (source);
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
GError *error = NULL;
- if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
+ if (!conn_util_send_iq_finish (conn, create_result, NULL, &error))
g_simple_async_result_take_error (result, error);
- g_simple_async_result_complete_in_idle (result);
-
+ g_simple_async_result_complete (result);
g_object_unref (result);
}
@@ -718,7 +716,6 @@ create_invisible_privacy_list_async (GabbleConnection *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GError *error = NULL;
GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self),
callback, user_data, create_invisible_privacy_list_async);
WockyStanza *iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
@@ -738,16 +735,8 @@ create_invisible_privacy_list_async (GabbleConnection *self,
DEBUG ("Creating '%s'", self->presence_priv->invisible_list_name);
- if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
- create_invisible_privacy_list_reply_cb, NULL, result, &error))
- {
- g_simple_async_result_set_from_error (result, error);
- g_simple_async_result_complete_in_idle (result);
-
- g_object_unref (result);
- g_error_free (error);
- }
-
+ conn_util_send_iq_async (self, iq, NULL,
+ create_invisible_privacy_list_reply_cb, result);
g_object_unref (iq);
}
@@ -885,7 +874,7 @@ store_shared_statuses (GabbleConnection *self,
presence_id = GABBLE_PRESENCE_AVAILABLE;
}
- if (base->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
{
/* Not connected, override with the local status. */
rv = TRUE;
@@ -1076,28 +1065,32 @@ get_shared_status_finish (GabbleConnection *self,
}
static void
-get_existing_privacy_lists_cb (GabbleConnection *conn,
- WockyStanza *sent_msg,
- WockyStanza *reply_msg,
- GObject *obj,
+get_existing_privacy_lists_cb (
+ GObject *source,
+ GAsyncResult *get_result,
gpointer user_data)
{
+ GabbleConnection *conn = GABBLE_CONNECTION (source);
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
- WockyNode *query_node = wocky_node_get_child_ns (
- wocky_stanza_get_top_node (reply_msg), "query", NS_PRIVACY);
+ WockyStanza *reply_msg = NULL;
+ WockyNode *query_node;
GError *error = NULL;
- if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
+ if (!conn_util_send_iq_finish (conn, get_result, &reply_msg, &error))
{
DEBUG ("Error getting privacy lists: %s", error->message);
g_simple_async_result_set_from_error (result, error);
g_error_free (error);
+ goto out;
}
- else if (query_node == NULL)
+
+ query_node = wocky_node_get_child_ns (
+ wocky_stanza_get_top_node (reply_msg), "query", NS_PRIVACY);
+ if (query_node == NULL)
{
g_simple_async_result_set_error (result,
- TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ TP_ERROR, TP_ERROR_NETWORK_ERROR,
"no <query/> node in 'list privacy lists' reply");
}
else
@@ -1136,8 +1129,10 @@ get_existing_privacy_lists_cb (GabbleConnection *conn,
}
}
- g_simple_async_result_complete_in_idle (result);
+out:
+ g_simple_async_result_complete (result);
g_object_unref (result);
+ g_clear_object (&reply_msg);
}
static void
@@ -1145,7 +1140,6 @@ get_existing_privacy_lists_async (GabbleConnection *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GError *error = NULL;
GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self),
callback, user_data, get_existing_privacy_lists_async);
WockyStanza *iq;
@@ -1157,16 +1151,8 @@ get_existing_privacy_lists_async (GabbleConnection *self,
')',
NULL);
- if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
- get_existing_privacy_lists_cb, NULL, result, &error))
- {
- g_simple_async_result_set_from_error (result, error);
- g_simple_async_result_complete_in_idle (result);
-
- g_object_unref (result);
- g_error_free (error);
- }
-
+ conn_util_send_iq_async (self, iq, NULL, get_existing_privacy_lists_cb,
+ result);
g_object_unref (iq);
}
@@ -1185,7 +1171,6 @@ setup_invisible_privacy_list_async (GabbleConnection *self,
gpointer user_data)
{
GabbleConnectionPresencePrivate *priv = self->presence_priv;
- GError *error = NULL;
GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self),
callback, user_data, setup_invisible_privacy_list_async);
WockyStanza *iq;
@@ -1203,16 +1188,8 @@ setup_invisible_privacy_list_async (GabbleConnection *self,
')',
NULL);
- if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
- verify_invisible_privacy_list_cb, NULL, result, &error))
- {
- g_simple_async_result_set_from_error (result, error);
- g_simple_async_result_complete_in_idle (result);
-
- g_object_unref (result);
- g_error_free (error);
- }
-
+ wocky_porter_send_iq_async (wocky_session_get_porter (self->session),
+ iq, NULL, verify_invisible_privacy_list_cb, result);
g_object_unref (iq);
}
@@ -1271,23 +1248,30 @@ is_valid_invisible_list (WockyNode *list_node)
}
static void
-verify_invisible_privacy_list_cb (GabbleConnection *conn,
- WockyStanza *sent_msg,
- WockyStanza *reply_msg,
- GObject *obj,
+verify_invisible_privacy_list_cb (
+ GObject *source,
+ GAsyncResult *verify_result,
gpointer user_data)
{
+ GabbleConnection *conn = GABBLE_CONNECTION (
+ g_async_result_get_source_object (G_ASYNC_RESULT (user_data)));
GabbleConnectionPresencePrivate *priv = conn->presence_priv;
- WockyNode *query_node, *list_node = NULL;
+ WockyStanza *reply_msg = NULL;
+ WockyNode *query_node = NULL, *list_node = NULL;
GError *error = NULL;
- query_node = wocky_node_get_child_ns (wocky_stanza_get_top_node (reply_msg),
- "query", NS_PRIVACY);
+ reply_msg = wocky_porter_send_iq_finish (WOCKY_PORTER (source),
+ verify_result, &error);
+
+ if (reply_msg != NULL)
+ query_node = wocky_node_get_child_ns (wocky_stanza_get_top_node (reply_msg),
+ "query", NS_PRIVACY);
if (query_node != NULL)
list_node = wocky_node_get_child (query_node, "list");
- if (!wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
+ if (reply_msg != NULL &&
+ !wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
{
if (list_node == NULL ||
!is_valid_invisible_list (list_node))
@@ -1309,7 +1293,8 @@ verify_invisible_privacy_list_cb (GabbleConnection *conn,
toggle_initial_presence_visibility_cb, user_data);
}
}
- else if (error->code == WOCKY_XMPP_ERROR_ITEM_NOT_FOUND)
+ else if (error->domain == WOCKY_XMPP_ERROR &&
+ error->code == WOCKY_XMPP_ERROR_ITEM_NOT_FOUND)
{
create_invisible_privacy_list_async (conn,
create_invisible_privacy_list_cb, user_data);
@@ -1324,6 +1309,9 @@ verify_invisible_privacy_list_cb (GabbleConnection *conn,
if (error != NULL)
g_error_free (error);
+
+ g_clear_object (&reply_msg);
+ g_clear_object (&conn);
}
static void
@@ -1588,7 +1576,8 @@ conn_presence_signal_own_presence (GabbleConnection *self,
* previously sent directed presence to? (Perhaps also GC them after a
* while?) */
- if (to == NULL && base->status == TP_CONNECTION_STATUS_CONNECTED)
+ if (to == NULL &&
+ tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED)
gabble_muc_factory_broadcast_presence (self->muc_factory);
return ret;
@@ -1761,7 +1750,7 @@ set_own_status_cb (GObject *obj,
* with the check enabled). Assumes PresenceId value ordering. */
if (i < GABBLE_PRESENCE_HIDDEN)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Status '%s' can not be requested in this connection",
gabble_statuses[i].name);
retval = FALSE;
@@ -1779,7 +1768,7 @@ set_own_status_cb (GObject *obj,
if (!G_VALUE_HOLDS_STRING (message))
{
DEBUG ("got a status message which was not a string");
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Status argument 'message' requires a string");
retval = FALSE;
goto OUT;
@@ -1792,7 +1781,7 @@ set_own_status_cb (GObject *obj,
if (!G_VALUE_HOLDS_INT (priority))
{
DEBUG ("got a priority value which was not a signed integer");
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Status argument 'priority' requires a signed integer");
retval = FALSE;
goto OUT;
@@ -1812,7 +1801,8 @@ set_own_status_cb (GObject *obj,
if (gabble_presence_update (conn->self_presence, resource, i,
message_str, prio, NULL, time (NULL)))
{
- if (base->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) !=
+ TP_CONNECTION_STATUS_CONNECTED)
{
retval = TRUE;
}
@@ -1881,7 +1871,7 @@ status_available_cb (GObject *obj, guint status)
TpConnectionPresenceType presence_type =
gabble_statuses[status].presence_type;
- if (base->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
{
/* we just don't know yet */
return TRUE;
diff --git a/src/conn-sidecars.c b/src/conn-sidecars.c
index eb47bad0a..d2dd57eca 100644
--- a/src/conn-sidecars.c
+++ b/src/conn-sidecars.c
@@ -22,7 +22,7 @@
#include "conn-sidecars.h"
-#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "extensions/extensions.h"
@@ -65,10 +65,12 @@ make_sidecar_path (
GabbleConnection *conn,
const gchar *sidecar_iface)
{
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn);
+ TpBaseConnection *base = TP_BASE_CONNECTION (conn);
return g_strdelimit (
- g_strdup_printf ("%s/Sidecar/%s", base_conn->object_path, sidecar_iface),
+ g_strdup_printf ("%s/Sidecar/%s",
+ tp_base_connection_get_object_path (base),
+ sidecar_iface),
".", '/');
}
@@ -157,7 +159,7 @@ create_sidecar_cb (
{
/* TODO: maybe this lives in the loader? It knows what the plugin is
* called. */
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"A buggy plugin created a %s sidecar when asked to create %s",
actual_iface, ctx->sidecar_iface);
}
@@ -203,14 +205,14 @@ gabble_connection_ensure_sidecar (
DBusGMethodInvocation *context)
{
GabbleConnection *conn = GABBLE_CONNECTION (iface);
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn);
+ TpBaseConnection *base = TP_BASE_CONNECTION (conn);
GabbleSidecar *sidecar;
gpointer key, value;
GError *error = NULL;
- if (base_conn->status == TP_CONNECTION_STATUS_DISCONNECTED)
+ if (tp_base_connection_is_destroyed (base))
{
- GError e = { TP_ERRORS, TP_ERROR_DISCONNECTED,
+ GError e = { TP_ERROR, TP_ERROR_DISCONNECTED,
"This connection has already disconnected" };
DEBUG ("already disconnected, declining request for %s", sidecar_iface);
@@ -220,7 +222,7 @@ gabble_connection_ensure_sidecar (
if (!tp_dbus_check_valid_interface_name (sidecar_iface, &error))
{
- error->domain = TP_ERRORS;
+ error->domain = TP_ERROR;
error->code = TP_ERROR_INVALID_ARGUMENT;
DEBUG ("%s is malformed: %s", sidecar_iface, error->message);
dbus_g_method_return_error (context, error);
@@ -262,7 +264,7 @@ gabble_connection_ensure_sidecar (
g_hash_table_insert (conn->pending_sidecars, g_strdup (sidecar_iface),
g_list_prepend (NULL, context));
- if (base_conn->status == TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED)
{
GabblePluginLoader *loader = gabble_plugin_loader_dup ();
@@ -305,7 +307,7 @@ sidecars_conn_status_changed_cb (
{
const gchar *sidecar_iface = key;
GList *contexts = value;
- GError *error = g_error_new (TP_ERRORS, TP_ERROR_CANCELLED,
+ GError *error = g_error_new (TP_ERROR, TP_ERROR_CANCELLED,
"Disconnected before %s could be created", sidecar_iface);
DEBUG ("failing all %u requests for %s", g_list_length (contexts),
diff --git a/src/connection-manager.c b/src/connection-manager.c
index b2a0edb15..349cdafff 100644
--- a/src/connection-manager.c
+++ b/src/connection-manager.c
@@ -25,8 +25,10 @@
#include <dbus/dbus-protocol.h>
#include <dbus/dbus-glib.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+
#include <wocky/wocky.h>
#include "connection.h"
@@ -80,9 +82,7 @@ gabble_connection_manager_class_init (GabbleConnectionManagerClass *klass)
TpBaseConnectionManagerClass *base_class =
(TpBaseConnectionManagerClass *) klass;
- base_class->new_connection = NULL;
base_class->cm_dbus_name = "gabble";
- base_class->protocol_params = NULL;
object_class->constructed = gabble_connection_manager_constructed;
object_class->finalize = gabble_connection_manager_finalize;
}
diff --git a/src/connection-manager.h b/src/connection-manager.h
index 775bba79b..fc269e8d8 100644
--- a/src/connection-manager.h
+++ b/src/connection-manager.h
@@ -22,7 +22,7 @@
#define __GABBLE_CONNECTION_MANAGER_H__
#include <glib-object.h>
-#include <telepathy-glib/base-connection-manager.h>
+#include <telepathy-glib/telepathy-glib.h>
G_BEGIN_DECLS
diff --git a/src/connection.c b/src/connection.c
index e53b3de1d..cc15a0adc 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -30,14 +30,8 @@
#include <dbus/dbus-glib-lowlevel.h>
#include <glib-object.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/handle-repo-dynamic.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-generic.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "extensions/extensions.h"
@@ -83,7 +77,6 @@
#ifdef ENABLE_VOIP
#include "media-channel.h"
-#include "jingle-factory.h"
#include "media-factory.h"
#endif
@@ -332,7 +325,7 @@ _gabble_connection_create_channel_managers (TpBaseConnection *conn)
{
GabbleConnection *self = GABBLE_CONNECTION (conn);
GabblePluginConnection *plugin_connection = GABBLE_PLUGIN_CONNECTION (self);
- GPtrArray *channel_managers = g_ptr_array_sized_new (5);
+ GPtrArray *channel_managers = g_ptr_array_sized_new (10);
GabblePluginLoader *loader;
GPtrArray *tmp;
@@ -934,6 +927,21 @@ gabble_connection_get_guaranteed_interfaces (void)
return interfaces_always_present;
}
+static GPtrArray *
+_gabble_connection_get_interfaces_always_present (TpBaseConnection *base)
+{
+ GPtrArray *interfaces;
+ const gchar **iter;
+
+ interfaces = TP_BASE_CONNECTION_CLASS (
+ gabble_connection_parent_class)->get_interfaces_always_present (base);
+
+ for (iter = interfaces_always_present; *iter != NULL; iter++)
+ g_ptr_array_add (interfaces, (gchar *) *iter);
+
+ return interfaces;
+}
+
static void
gabble_connection_class_init (GabbleConnectionClass *gabble_connection_class)
{
@@ -1012,7 +1020,8 @@ gabble_connection_class_init (GabbleConnectionClass *gabble_connection_class)
_gabble_connection_create_channel_managers;
parent_class->shut_down = connection_shut_down;
parent_class->start_connecting = _gabble_connection_connect;
- parent_class->interfaces_always_present = interfaces_always_present;
+ parent_class->get_interfaces_always_present =
+ _gabble_connection_get_interfaces_always_present;
g_type_class_add_private (gabble_connection_class,
sizeof (GabbleConnectionPrivate));
@@ -1267,8 +1276,10 @@ gabble_connection_dispose (GObject *object)
DEBUG ("called");
- g_assert ((base->status == TP_CONNECTION_STATUS_DISCONNECTED) ||
- (base->status == TP_INTERNAL_CONNECTION_STATUS_NEW));
+ g_assert ((tp_base_connection_get_status (base) ==
+ TP_CONNECTION_STATUS_DISCONNECTED) ||
+ (tp_base_connection_get_status (base) ==
+ TP_INTERNAL_CONNECTION_STATUS_NEW));
tp_clear_object (&self->bytestream_factory);
tp_clear_object (&self->disco);
@@ -1398,7 +1409,7 @@ _gabble_connection_set_properties_from_account (GabbleConnection *conn,
if (!wocky_decode_jid (account, &username, &server, &resource))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"unable to extract JID from account name");
result = FALSE;
goto OUT;
@@ -1484,7 +1495,7 @@ _gabble_connection_send (GabbleConnection *conn, WockyStanza *msg, GError **erro
if (conn->priv->porter == NULL)
{
- g_set_error_literal (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ g_set_error_literal (error, TP_ERROR, TP_ERROR_NETWORK_ERROR,
"connection is disconnected");
return FALSE;
}
@@ -1600,7 +1611,7 @@ _gabble_connection_send_with_reply (GabbleConnection *conn,
if (priv->porter == NULL)
{
- g_set_error_literal (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ g_set_error_literal (error, TP_ERROR, TP_ERROR_NETWORK_ERROR,
"connection is disconnected");
return FALSE;
}
@@ -1647,7 +1658,7 @@ gabble_connection_disconnect_with_tp_error (GabbleConnection *self,
"debug-message", G_TYPE_STRING, tp_error->message,
NULL);
- g_assert (tp_error->domain == TP_ERRORS);
+ g_assert (tp_error->domain == TP_ERROR);
tp_base_connection_disconnect_with_dbus_error (base,
tp_error_get_dbus_name (tp_error->code), details, reason);
g_hash_table_unref (details);
@@ -1658,10 +1669,10 @@ remote_closed_cb (WockyPorter *porter,
GabbleConnection *self)
{
TpBaseConnection *base = TP_BASE_CONNECTION (self);
- GError e = { TP_ERRORS, TP_ERROR_CONNECTION_LOST,
+ GError e = { TP_ERROR, TP_ERROR_CONNECTION_LOST,
"server closed its XMPP stream" };
- if (base->status == TP_CONNECTION_STATUS_DISCONNECTED)
+ if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_DISCONNECTED)
/* Ignore if we are already disconnecting/disconnected */
return;
@@ -1708,12 +1719,13 @@ remote_error_cb (WockyPorter *porter,
GError e = { domain, code, msg };
GError *error = NULL;
- if (base->status == TP_CONNECTION_STATUS_DISCONNECTED)
+ if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_DISCONNECTED)
/* Ignore if we are already disconnecting/disconnected */
return;
- gabble_set_tp_conn_error_from_wocky (&e, base->status, &reason, &error);
- g_assert (error->domain == TP_ERRORS);
+ gabble_set_tp_conn_error_from_wocky (&e, tp_base_connection_get_status (base),
+ &reason, &error);
+ g_assert (error->domain == TP_ERROR);
DEBUG ("Force closing of the connection %p", self);
priv->closing = TRUE;
@@ -1767,10 +1779,10 @@ connector_error_disconnect (GabbleConnection *self,
return;
}
- gabble_set_tp_conn_error_from_wocky (error, base->status, &reason,
- &tp_error);
+ gabble_set_tp_conn_error_from_wocky (error,
+ tp_base_connection_get_status (base), &reason, &tp_error);
DEBUG ("connection failed: %s", tp_error->message);
- g_assert (tp_error->domain == TP_ERRORS);
+ g_assert (tp_error->domain == TP_ERROR);
gabble_connection_disconnect_with_tp_error (self, tp_error, reason);
g_error_free (tp_error);
@@ -1956,15 +1968,16 @@ connector_connected (GabbleConnection *self,
* components (Roster, presence-manager, etc) for now */
wocky_porter_start (priv->porter);
- base->self_handle = tp_handle_ensure (contact_handles, jid, NULL, &error);
+ tp_base_connection_set_self_handle (base,
+ tp_handle_ensure (contact_handles, jid, NULL, &error));
- if (base->self_handle == 0)
+ if (tp_base_connection_get_self_handle (base) == 0)
{
DEBUG ("couldn't get our self handle: %s", error->message);
- if (error->domain != TP_ERRORS)
+ if (error->domain != TP_ERROR)
{
- error->domain = TP_ERRORS;
+ error->domain = TP_ERROR;
error->code = TP_ERROR_INVALID_HANDLE;
}
@@ -1980,9 +1993,9 @@ connector_connected (GabbleConnection *self,
{
DEBUG ("couldn't parse our own JID: %s", error->message);
- if (error->domain != TP_ERRORS)
+ if (error->domain != TP_ERROR)
{
- error->domain = TP_ERRORS;
+ error->domain = TP_ERROR;
error->code = TP_ERROR_INVALID_ARGUMENT;
}
@@ -1993,7 +2006,8 @@ connector_connected (GabbleConnection *self,
return;
}
- DEBUG ("Created self handle %d, our JID is %s", base->self_handle, jid);
+ DEBUG ("Created self handle %d, our JID is %s",
+ tp_base_connection_get_self_handle (base), jid);
/* set initial capabilities */
gabble_connection_refresh_capabilities (self, NULL);
@@ -2008,9 +2022,9 @@ connector_connected (GabbleConnection *self,
DEBUG ("sending disco request failed: %s",
error->message);
- if (error->domain != TP_ERRORS)
+ if (error->domain != TP_ERROR)
{
- error->domain = TP_ERRORS;
+ error->domain = TP_ERROR;
error->code = TP_ERROR_NETWORK_ERROR;
}
@@ -2027,9 +2041,9 @@ connector_connected (GabbleConnection *self,
DEBUG ("Sending disco request to our own bare jid failed: %s",
error->message);
- if (error->domain != TP_ERRORS)
+ if (error->domain != TP_ERROR)
{
- error->domain = TP_ERRORS;
+ error->domain = TP_ERROR;
error->code = TP_ERROR_NETWORK_ERROR;
}
@@ -2374,14 +2388,13 @@ gabble_connection_fill_in_caps (GabbleConnection *self,
/* XEP-0115 version 1.5 uses a verification string in the 'ver' attribute */
caps_hash = caps_hash_compute_from_self_presence (self);
- node = wocky_node_add_child_with_content (node, "c", NULL);
+ node = wocky_node_add_child_ns (node, "c", NS_CAPS);
wocky_node_set_attributes (
node,
"hash", "sha-1",
"node", NS_GABBLE_CAPS,
"ver", caps_hash,
NULL);
- node->ns = g_quark_from_string (NS_CAPS);
/* Ensure this set of capabilities is in the cache. */
gabble_presence_cache_add_own_caps (self->presence_cache, caps_hash,
@@ -2463,9 +2476,8 @@ gabble_connection_request_decloak (GabbleConnection *self,
gabble_connection_fill_in_caps (self, message);
- decloak = wocky_node_add_child_with_content (wocky_stanza_get_top_node (message),
- "temppres", NULL);
- decloak->ns = g_quark_from_string (NS_TEMPPRES);
+ decloak = wocky_node_add_child_ns (wocky_stanza_get_top_node (message),
+ "temppres", NS_TEMPPRES);
if (reason != NULL && *reason != '\0')
{
@@ -2538,7 +2550,7 @@ gabble_connection_refresh_capabilities (GabbleConnection *self,
}
/* don't signal presence unless we're already CONNECTED */
- if (base->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
{
gabble_capability_set_free (save_set);
g_ptr_array_unref (data_forms);
@@ -2780,7 +2792,7 @@ set_status_to_connected (GabbleConnection *conn)
{
TpBaseConnection *base = (TpBaseConnection *) conn;
- if (base->status == TP_CONNECTION_STATUS_DISCONNECTED)
+ if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_DISCONNECTED)
{
/* We already failed to connect, but at the time an async thing was
* still pending, and now it has finished. Do nothing special. */
@@ -2827,6 +2839,115 @@ decrement_waiting_connected (GabbleConnection *conn)
}
static void
+conn_wlm_jid_lookup_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GabbleConnection *conn = (GabbleConnection *) source;
+ GSimpleAsyncResult *my_result = user_data;
+ WockyStanza *iq = NULL;
+ WockyNode *node;
+ const gchar *jid = NULL;
+ GError *error = NULL;
+
+ if (!conn_util_send_iq_finish (conn, result, &iq, &error))
+ {
+ g_simple_async_result_take_error (my_result, error);
+ goto out;
+ }
+
+ node = wocky_node_get_child_ns (wocky_stanza_get_top_node (iq),
+ "getjid", NS_WLM_JID_LOOKUP);
+
+ if (node != NULL)
+ {
+ jid = wocky_node_get_content_from_child (node, "jid");
+ }
+
+ if (!tp_str_empty (jid))
+ {
+ g_simple_async_result_set_op_res_gpointer (my_result,
+ g_strdup (jid), g_free);
+ }
+ else
+ {
+ g_simple_async_result_set_error (my_result,
+ TP_ERROR, TP_ERROR_INVALID_HANDLE,
+ "jid not found in getjid reply");
+ }
+
+out:
+ g_simple_async_result_complete (my_result);
+ g_object_unref (my_result);
+}
+
+static void
+conn_wlm_jid_lookup_async (TpHandleRepoIface *repo,
+ TpBaseConnection *base,
+ const gchar *id,
+ gpointer context,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GabbleConnection *self = GABBLE_CONNECTION (base);
+ WockyStanza *iq;
+ GSimpleAsyncResult *result;
+ gchar *normal_id;
+ GError *error = NULL;
+
+ result = g_simple_async_result_new ((GObject *) repo, callback, user_data,
+ conn_wlm_jid_lookup_async);
+
+ /* First, do local normalization */
+ normal_id = gabble_normalize_contact (repo, id, context, &error);
+ if (normal_id == NULL)
+ {
+ g_simple_async_result_take_error (result, error);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ return;
+ }
+
+ /* If it is already a WLM jid, return it */
+ if (g_str_has_suffix (normal_id, "@messenger.live.com"))
+ {
+ g_simple_async_result_set_op_res_gpointer (result, normal_id, g_free);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ return;
+ }
+
+ /* Ask the server to give a WLM jid */
+ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET,
+ conn_util_get_bare_self_jid (self), normal_id,
+ '(', "getjid",
+ ':', NS_WLM_JID_LOOKUP,
+ ')',
+ NULL);
+
+ conn_util_send_iq_async (self, iq, NULL, conn_wlm_jid_lookup_cb, result);
+
+ g_object_unref (iq);
+ g_free (normal_id);
+}
+
+static gchar *
+conn_wlm_jid_lookup_finish (TpHandleRepoIface *repo,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = (GSimpleAsyncResult *) result;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result,
+ G_OBJECT (repo), conn_wlm_jid_lookup_async), NULL);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ return g_strdup (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+static void
connection_disco_cb (GabbleDisco *disco,
GabbleDiscoRequest *request,
const gchar *jid,
@@ -2838,9 +2959,10 @@ connection_disco_cb (GabbleDisco *disco,
GabbleConnection *conn = GABBLE_CONNECTION (user_data);
TpBaseConnection *base = (TpBaseConnection *) conn;
- if (base->status != TP_CONNECTION_STATUS_CONNECTING)
+ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTING)
{
- g_assert (base->status == TP_CONNECTION_STATUS_DISCONNECTED);
+ g_assert (tp_base_connection_get_status (base) ==
+ TP_CONNECTION_STATUS_DISCONNECTED);
return;
}
@@ -2903,12 +3025,25 @@ connection_disco_cb (GabbleDisco *disco,
conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_QUEUE;
else if (0 == strcmp (var, NS_GOOGLE_SETTING))
conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_SETTING;
+ else if (0 == strcmp (var, NS_WLM_JID_LOOKUP))
+ conn->features |= GABBLE_CONNECTION_FEATURES_WLM_JID_LOOKUP;
}
}
DEBUG ("set features flags to %d", conn->features);
}
+ if ((conn->features & GABBLE_CONNECTION_FEATURES_WLM_JID_LOOKUP) != 0)
+ {
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
+
+ tp_dynamic_handle_repo_set_normalize_async (
+ (TpDynamicHandleRepo *) contact_repo,
+ conn_wlm_jid_lookup_async,
+ conn_wlm_jid_lookup_finish);
+ }
+
conn_presence_set_initial_presence_async (conn,
connection_initial_presence_cb, NULL);
@@ -2943,7 +3078,8 @@ connection_initial_presence_cb (GObject *source_object,
{
DEBUG ("error setting up initial presence: %s", error->message);
- if (base->status != TP_CONNECTION_STATUS_DISCONNECTED)
+ if (tp_base_connection_get_status (base) !=
+ TP_CONNECTION_STATUS_DISCONNECTED)
tp_base_connection_change_status (base,
TP_CONNECTION_STATUS_DISCONNECTED,
TP_CONNECTION_STATUS_REASON_NETWORK_ERROR);
@@ -3099,11 +3235,11 @@ gabble_connection_get_handle_contact_capabilities (
GabbleConnection *self,
TpHandle handle)
{
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (self);
+ TpBaseConnection *base = TP_BASE_CONNECTION (self);
GabblePresence *p;
const GabbleCapabilitySet *caps;
- if (handle == base_conn->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
p = self->self_presence;
else
p = gabble_presence_cache_get (self->presence_cache, handle);
@@ -3211,8 +3347,8 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
if (gabble_connection_refresh_capabilities (self, &save_set))
{
- _emit_capabilities_changed (self, base->self_handle, save_set,
- priv->all_caps);
+ _emit_capabilities_changed (self,
+ tp_base_connection_get_self_handle (base), save_set, priv->all_caps);
gabble_capability_set_free (save_set);
}
@@ -3475,7 +3611,8 @@ gabble_connection_update_capabilities (
if (gabble_connection_refresh_capabilities (self, &old_caps))
{
- _emit_capabilities_changed (self, base->self_handle, old_caps,
+ _emit_capabilities_changed (self,
+ tp_base_connection_get_self_handle (base), old_caps,
self->priv->all_caps);
gabble_capability_set_free (old_caps);
}
@@ -3512,7 +3649,7 @@ gabble_connection_get_handle_capabilities (GabbleConnection *self,
return;
}
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
pres = self->self_presence;
else
pres = gabble_presence_cache_get (self->presence_cache, handle);
@@ -3842,6 +3979,7 @@ gabble_connection_update_sidecar_capabilities (GabbleConnection *self,
const GabbleCapabilitySet *add_set,
const GabbleCapabilitySet *remove_set)
{
+ TpBaseConnection *base = TP_BASE_CONNECTION (self);
GabbleConnectionPrivate *priv = self->priv;
GabbleCapabilitySet *save_set;
@@ -3874,8 +4012,8 @@ gabble_connection_update_sidecar_capabilities (GabbleConnection *self,
if (gabble_connection_refresh_capabilities (self, &save_set))
{
- _emit_capabilities_changed (self, TP_BASE_CONNECTION (self)->self_handle,
- save_set, priv->all_caps);
+ _emit_capabilities_changed (self,
+ tp_base_connection_get_self_handle (base), save_set, priv->all_caps);
gabble_capability_set_free (save_set);
}
}
diff --git a/src/connection.h b/src/connection.h
index 50734b777..c3e9138b0 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -25,11 +25,7 @@
#include <dbus/dbus-glib.h>
#include <glib-object.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/contacts-mixin.h>
-#include <telepathy-glib/presence-mixin.h>
-#include <telepathy-glib/dbus-properties-mixin.h>
-#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
@@ -43,9 +39,6 @@
#include "muc-factory.h"
#include "types.h"
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/base-contact-list.h>
-
#include <gabble/capabilities-set.h>
#include <gabble/types.h>
#include <gabble/plugin-connection.h>
@@ -143,6 +136,7 @@ typedef enum
GABBLE_CONNECTION_FEATURES_GOOGLE_SHARED_STATUS = 1 << 7,
GABBLE_CONNECTION_FEATURES_GOOGLE_QUEUE = 1 << 8,
GABBLE_CONNECTION_FEATURES_GOOGLE_SETTING = 1 << 9,
+ GABBLE_CONNECTION_FEATURES_WLM_JID_LOOKUP = 1 << 10,
} GabbleConnectionFeatures;
typedef struct _GabbleConnectionPrivate GabbleConnectionPrivate;
diff --git a/src/debug.c b/src/debug.c
index a7616f712..8e3dd0c50 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -16,8 +16,8 @@
#include <errno.h>
#include <glib/gstdio.h>
-#include <telepathy-glib/debug.h>
-#include <telepathy-glib/debug-sender.h>
+
+#include <telepathy-glib/telepathy-glib.h>
static GabbleDebugFlags flags = 0;
diff --git a/src/disco.c b/src/disco.c
index 6f142a4e1..20726dd31 100644
--- a/src/disco.c
+++ b/src/disco.c
@@ -28,7 +28,7 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/telepathy-glib.h>
#define DEBUG_FLAG GABBLE_DEBUG_DISCO
diff --git a/src/error.c b/src/error.c
index e79ddef32..ad3bf7b14 100644
--- a/src/error.c
+++ b/src/error.c
@@ -344,7 +344,7 @@ gabble_set_tp_conn_error_from_wocky (const GError *wocky_error,
klass = g_type_class_ref (WOCKY_TYPE_XMPP_ERROR);
name = get_error_prefix (klass, wocky_error->code,
"unknown WockyXmppError code");
- g_set_error (error, TP_ERRORS,
+ g_set_error (error, TP_ERROR,
map_wocky_xmpp_error (wocky_error, conn_reason),
"%s (#%d): %s", name, wocky_error->code, wocky_error->message);
g_type_class_unref (klass);
@@ -356,7 +356,7 @@ gabble_set_tp_conn_error_from_wocky (const GError *wocky_error,
"unknown GIOError code");
/* FIXME: is it safe to assume that every GIOError we encounter from
* Wocky is a NetworkError? */
- g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR,
"%s (#%d): %s", name, wocky_error->code, wocky_error->message);
g_type_class_unref (klass);
@@ -368,7 +368,7 @@ gabble_set_tp_conn_error_from_wocky (const GError *wocky_error,
klass = g_type_class_ref (WOCKY_TYPE_AUTH_ERROR);
name = get_error_prefix (klass, wocky_error->code,
"unknown WockyAuthError code");
- g_set_error (error, TP_ERRORS,
+ g_set_error (error, TP_ERROR,
map_wocky_auth_error (wocky_error, conn_reason),
"%s (#%d): %s", name, wocky_error->code, wocky_error->message);
g_type_class_unref (klass);
@@ -378,7 +378,7 @@ gabble_set_tp_conn_error_from_wocky (const GError *wocky_error,
klass = g_type_class_ref (WOCKY_TYPE_CONNECTOR_ERROR);
name = get_error_prefix (klass, wocky_error->code,
"unknown WockyConnectorError code");
- g_set_error (error, TP_ERRORS,
+ g_set_error (error, TP_ERROR,
map_wocky_connector_error (wocky_error, conn_reason),
"%s (#%d): %s", name, wocky_error->code, wocky_error->message);
g_type_class_unref (klass);
@@ -388,7 +388,7 @@ gabble_set_tp_conn_error_from_wocky (const GError *wocky_error,
klass = g_type_class_ref (WOCKY_TYPE_XMPP_STREAM_ERROR);
name = get_error_prefix (klass, wocky_error->code,
"unknown WockyXmppStreamError code");
- g_set_error (error, TP_ERRORS,
+ g_set_error (error, TP_ERROR,
map_wocky_stream_error (wocky_error, previous_status, conn_reason),
"%s (#%d): %s", name, wocky_error->code, wocky_error->message);
g_type_class_unref (klass);
@@ -398,7 +398,7 @@ gabble_set_tp_conn_error_from_wocky (const GError *wocky_error,
klass = g_type_class_ref (WOCKY_TYPE_TLS_CERT_STATUS);
name = get_error_prefix (klass, wocky_error->code,
"unknown WockyTLSCertStatus code");
- g_set_error (error, TP_ERRORS,
+ g_set_error (error, TP_ERROR,
map_wocky_tls_cert_error (wocky_error, conn_reason),
"%s (#%d): %s", name, wocky_error->code, wocky_error->message);
g_type_class_unref (klass);
@@ -406,14 +406,14 @@ gabble_set_tp_conn_error_from_wocky (const GError *wocky_error,
else if (wocky_error->domain == WOCKY_XMPP_CONNECTION_ERROR)
{
/* FIXME: there's no GEnum for WockyXmppConnectionError. */
- g_set_error_literal (error, TP_ERRORS,
+ g_set_error_literal (error, TP_ERROR,
map_connection_error (wocky_error),
wocky_error->message);
}
else
{
/* best we can do... */
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"%s (#%d): %s", g_quark_to_string (wocky_error->domain),
wocky_error->code, wocky_error->message);
}
diff --git a/src/ft-channel.c b/src/ft-channel.c
index 57b891205..fd82405c5 100644
--- a/src/ft-channel.c
+++ b/src/ft-channel.c
@@ -48,14 +48,8 @@
#include "presence-cache.h"
#include "util.h"
-#include <telepathy-glib/base-channel.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/svc-generic.h>
-#include <telepathy-glib/svc-channel.h>
-
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
static void file_transfer_iface_init (gpointer g_iface, gpointer iface_data);
static void transferred_chunk (GabbleFileTransferChannel *self, guint64 count);
@@ -79,8 +73,6 @@ G_DEFINE_TYPE_WITH_CODE (GabbleFileTransferChannel, gabble_file_transfer_channel
#define GABBLE_UNDEFINED_FILE_SIZE G_MAXUINT64
-static const char *gabble_file_transfer_channel_interfaces[] = { NULL };
-
/* properties */
enum
{
@@ -481,21 +473,21 @@ file_transfer_channel_properties_setter (GObject *object,
if (self->priv->uri != NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"URI has already be set");
return FALSE;
}
if (tp_base_channel_is_requested (base))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Channel is not an incoming transfer");
return FALSE;
}
if (self->priv->state != TP_FILE_TRANSFER_STATE_PENDING)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"State is not pending; cannot set URI");
return FALSE;
}
@@ -548,6 +540,20 @@ gabble_file_transfer_channel_get_object_path_suffix (TpBaseChannel *chan)
return g_strdup_printf ("FileTransferChannel/%p", chan);
}
+static GPtrArray *
+gabble_file_transfer_channel_get_interfaces (TpBaseChannel *base)
+{
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CHANNEL_CLASS (
+ gabble_file_transfer_channel_parent_class)->get_interfaces (base);
+
+ g_ptr_array_add (interfaces, GABBLE_IFACE_CHANNEL_TYPE_FILETRANSFER_FUTURE);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA);
+
+ return interfaces;
+}
+
static void
gabble_file_transfer_channel_class_init (
GabbleFileTransferChannelClass *gabble_file_transfer_channel_class)
@@ -614,8 +620,8 @@ gabble_file_transfer_channel_class_init (
object_class->set_property = gabble_file_transfer_channel_set_property;
base_class->channel_type = TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER;
- base_class->interfaces = gabble_file_transfer_channel_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
+ base_class->get_interfaces = gabble_file_transfer_channel_get_interfaces;
base_class->close = gabble_file_transfer_channel_close;
base_class->fill_immutable_properties =
gabble_file_transfer_channel_fill_immutable_properties;
@@ -931,7 +937,7 @@ check_address_and_access_control (GabbleFileTransferChannel *self,
GUINT_TO_POINTER (address_type));
if (access_arr == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"AddressType %u is not implemented", address_type);
return FALSE;
}
@@ -946,7 +952,7 @@ check_address_and_access_control (GabbleFileTransferChannel *self,
return TRUE;
}
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"AccesControl %u is not implemented with AddressType %u",
access_control, address_type);
@@ -1073,7 +1079,6 @@ set_gtalk_file_collection (
static void
bytestream_negotiate_cb (GabbleBytestreamIface *bytestream,
- const gchar *stream_id,
WockyStanza *msg,
GObject *object,
gpointer user_data)
@@ -1127,8 +1132,7 @@ add_metadata_forms (GabbleFileTransferChannel *self,
{
if (!tp_str_empty (self->priv->service_name))
{
- WockyStanza *tmp = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
- WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL,
+ wocky_node_add_build (file,
'(', "x",
':', NS_X_DATA,
'@', "type", "result",
@@ -1147,21 +1151,19 @@ add_metadata_forms (GabbleFileTransferChannel *self,
')',
')',
NULL);
- WockyNode *x = wocky_node_get_first_child (wocky_stanza_get_top_node (tmp));
- WockyNodeTree *tree = wocky_node_tree_new_from_node (x);
-
- wocky_node_add_node_tree (file, tree);
- g_object_unref (tree);
- g_object_unref (tmp);
}
if (self->priv->metadata != NULL
&& g_hash_table_size (self->priv->metadata) > 0)
{
- WockyStanza *tmp = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
- WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL,
+ WockyNode *x;
+ GHashTableIter iter;
+ gpointer key, val;
+
+ wocky_node_add_build (file,
'(', "x",
':', NS_X_DATA,
+ '*', &x,
'@', "type", "result",
'(', "field",
'@', "var", "FORM_TYPE",
@@ -1172,10 +1174,6 @@ add_metadata_forms (GabbleFileTransferChannel *self,
')',
')',
NULL);
- WockyNode *x = wocky_node_get_first_child (wocky_stanza_get_top_node (tmp));
- WockyNodeTree *tree;
- GHashTableIter iter;
- gpointer key, val;
g_hash_table_iter_init (&iter, self->priv->metadata);
while (g_hash_table_iter_next (&iter, &key, &val))
@@ -1190,21 +1188,15 @@ add_metadata_forms (GabbleFileTransferChannel *self,
wocky_node_add_child_with_content (field, "value", *values);
}
}
-
- tree = wocky_node_tree_new_from_node (x);
- wocky_node_add_node_tree (file, tree);
- g_object_unref (tree);
- g_object_unref (tmp);
}
}
-static gboolean
+static void
offer_bytestream (GabbleFileTransferChannel *self, const gchar *jid,
- const gchar *resource, GError **error)
+ const gchar *resource)
{
GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection (
TP_BASE_CHANNEL (self)));
- gboolean result;
WockyStanza *msg;
WockyNode *si_node, *file_node;
gchar *stream_id, *size_str, *full_jid;
@@ -1232,8 +1224,7 @@ offer_bytestream (GabbleFileTransferChannel *self, const gchar *jid,
size_str = g_strdup_printf ("%" G_GUINT64_FORMAT, self->priv->size);
- file_node = wocky_node_add_child_with_content (si_node, "file", NULL);
- file_node->ns = g_quark_from_string (NS_FILE_TRANSFER);
+ file_node = wocky_node_add_child_ns (si_node, "file", NS_FILE_TRANSFER);
wocky_node_set_attributes (file_node,
"name", self->priv->filename,
"size", size_str,
@@ -1266,18 +1257,16 @@ offer_bytestream (GabbleFileTransferChannel *self, const gchar *jid,
wocky_node_add_child_with_content (file_node, "desc", self->priv->description);
/* we support resume */
- wocky_node_add_child_with_content (file_node, "range", NULL);
+ wocky_node_add_child (file_node, "range");
- result = gabble_bytestream_factory_negotiate_stream (
+ gabble_bytestream_factory_negotiate_stream (
conn->bytestream_factory, msg, stream_id,
- bytestream_negotiate_cb, self, G_OBJECT (self), error);
+ bytestream_negotiate_cb, self, G_OBJECT (self));
g_object_unref (msg);
g_free (stream_id);
g_free (size_str);
g_free (full_jid);
-
- return result;
}
#ifdef ENABLE_JINGLE_FILE_TRANSFER
@@ -1349,7 +1338,7 @@ offer_gtalk_file_transfer (GabbleFileTransferChannel *self,
TpBaseChannel *base = TP_BASE_CHANNEL (self);
GabbleConnection *conn = GABBLE_CONNECTION (
tp_base_channel_get_connection (base));
- GabbleJingleFactory *jf;
+ WockyJingleFactory *jf;
GTalkFileCollection *gtalk_file_collection;
DEBUG ("Offering Gtalk file transfer to %s", full_jid);
@@ -1410,7 +1399,7 @@ gabble_file_transfer_channel_offer_file (GabbleFileTransferChannel *self,
if (presence == NULL)
{
DEBUG ("can't find contact's presence");
- g_set_error (error, TP_ERRORS, TP_ERROR_OFFLINE,
+ g_set_error (error, TP_ERROR, TP_ERROR_OFFLINE,
"can't find contact's presence");
return FALSE;
@@ -1422,7 +1411,7 @@ gabble_file_transfer_channel_offer_file (GabbleFileTransferChannel *self,
{
DEBUG ("trying to use Metadata properties on a contact "
"who doesn't support it");
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_CAPABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE,
"The specified contact does not support the "
"Metadata extension; you should ensure both ServiceName and "
"Metadata properties are not present in the channel "
@@ -1468,7 +1457,7 @@ gabble_file_transfer_channel_offer_file (GabbleFileTransferChannel *self,
#ifdef ENABLE_JINGLE_FILE_TRANSFER
use_si = si &&
(!jingle_share ||
- gabble_jingle_info_get_google_relay_token (
+ wocky_jingle_info_get_google_relay_token (
gabble_jingle_mint_get_info (conn->jingle_mint)) == NULL);
#else
use_si = si;
@@ -1476,7 +1465,8 @@ gabble_file_transfer_channel_offer_file (GabbleFileTransferChannel *self,
if (use_si)
{
- result = offer_bytestream (self, jid, si_resource, error);
+ offer_bytestream (self, jid, si_resource);
+ result = TRUE;
}
#ifdef ENABLE_JINGLE_FILE_TRANSFER
else if (jingle_share)
@@ -1490,7 +1480,7 @@ gabble_file_transfer_channel_offer_file (GabbleFileTransferChannel *self,
else
{
DEBUG ("contact doesn't have file transfer capabilities");
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_CAPABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE,
"contact doesn't have file transfer capabilities");
result = FALSE;
}
@@ -1658,15 +1648,14 @@ augment_si_reply (WockyNode *si,
GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (user_data);
WockyNode *file;
- file = wocky_node_add_child_with_content (si, "file", NULL);
- file->ns = g_quark_from_string (NS_FILE_TRANSFER);
+ file = wocky_node_add_child_ns (si, "file", NS_FILE_TRANSFER);
if (self->priv->initial_offset != 0)
{
WockyNode *range;
gchar *offset_str;
- range = wocky_node_add_child_with_content (file, "range", NULL);
+ range = wocky_node_add_child (file, "range");
offset_str = g_strdup_printf ("%" G_GUINT64_FORMAT,
self->priv->initial_offset);
wocky_node_set_attribute (range, "offset", offset_str);
@@ -1698,7 +1687,7 @@ gabble_file_transfer_channel_accept_file (TpSvcChannelTypeFileTransfer *iface,
if (tp_base_channel_is_requested (base))
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Channel is not an incoming transfer");
dbus_g_method_return_error (context, error);
g_error_free (error);
@@ -1707,7 +1696,7 @@ gabble_file_transfer_channel_accept_file (TpSvcChannelTypeFileTransfer *iface,
if (self->priv->state != TP_FILE_TRANSFER_STATE_PENDING)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"State is not pending; cannot accept file");
dbus_g_method_return_error (context, error);
g_error_free (error);
@@ -1726,7 +1715,7 @@ gabble_file_transfer_channel_accept_file (TpSvcChannelTypeFileTransfer *iface,
access_control_param))
{
DEBUG ("Could not set up local socket");
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Could not set up local socket");
dbus_g_method_return_error (context, error);
g_error_free (error);
@@ -1798,7 +1787,7 @@ gabble_file_transfer_channel_provide_file (
if (!tp_base_channel_is_requested (TP_BASE_CHANNEL (self)))
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Channel is not an outgoing transfer");
dbus_g_method_return_error (context, error);
g_error_free (error);
@@ -1808,7 +1797,7 @@ gabble_file_transfer_channel_provide_file (
if (self->priv->state != TP_FILE_TRANSFER_STATE_PENDING &&
self->priv->state != TP_FILE_TRANSFER_STATE_ACCEPTED)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"State is not pending or accepted; cannot provide file");
dbus_g_method_return_error (context, error);
g_error_free (error);
@@ -1817,7 +1806,7 @@ gabble_file_transfer_channel_provide_file (
if (self->priv->socket_address != NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"ProvideFile has already been called for this channel");
dbus_g_method_return_error (context, error);
g_error_free (error);
@@ -1836,7 +1825,7 @@ gabble_file_transfer_channel_provide_file (
access_control_param))
{
DEBUG ("Could not set up local socket");
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Could not set up local socket");
dbus_g_method_return_error (context, error);
g_error_free (error);
diff --git a/src/ft-channel.h b/src/ft-channel.h
index 323c1e651..87943646b 100644
--- a/src/ft-channel.h
+++ b/src/ft-channel.h
@@ -26,7 +26,7 @@
#include <glib-object.h>
#include <extensions/extensions.h>
-#include <telepathy-glib/base-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
typedef struct _GabbleFileTransferChannel GabbleFileTransferChannel;
diff --git a/src/ft-manager.c b/src/ft-manager.c
index a6bb13090..a4266b5a0 100644
--- a/src/ft-manager.c
+++ b/src/ft-manager.c
@@ -31,7 +31,6 @@
#include <glib/gstdio.h>
#ifdef ENABLE_JINGLE_FILE_TRANSFER
-#include "jingle-session.h"
#include "jingle-share.h"
#endif
#include "gabble/caps-channel-manager.h"
@@ -45,14 +44,8 @@
#include <wocky/wocky.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/base-channel.h>
-#include <telepathy-glib/channel-factory-iface.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/util.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_FT
#include "debug.h"
@@ -346,24 +339,24 @@ gabble_ft_manager_channel_created (GabbleFtManager *self,
#ifdef ENABLE_JINGLE_FILE_TRANSFER
static void
new_jingle_session_cb (GabbleJingleMint *jm,
- GabbleJingleSession *sess,
+ WockyJingleSession *sess,
gpointer data)
{
GabbleFtManager *self = GABBLE_FT_MANAGER (data);
GTalkFileCollection *gtalk_fc = NULL;
- GabbleJingleContent *content = NULL;
+ WockyJingleContent *content = NULL;
GabbleJingleShareManifest *manifest = NULL;
GList *channels = NULL;
GList *cs, *i;
- if (gabble_jingle_session_get_content_type (sess) ==
+ if (wocky_jingle_session_get_content_type (sess) ==
GABBLE_TYPE_JINGLE_SHARE)
{
- cs = gabble_jingle_session_get_contents (sess);
+ cs = wocky_jingle_session_get_contents (sess);
if (cs != NULL)
{
- content = GABBLE_JINGLE_CONTENT (cs->data);
+ content = WOCKY_JINGLE_CONTENT (cs->data);
g_list_free (cs);
}
@@ -393,7 +386,7 @@ new_jingle_session_cb (GabbleJingleMint *jm,
TP_BASE_CONNECTION (self->priv->connection),
TP_HANDLE_TYPE_CONTACT);
TpHandle peer = tp_handle_ensure (contacts,
- gabble_jingle_session_get_peer_jid (sess), NULL, NULL);
+ wocky_jingle_session_get_peer_jid (sess), NULL, NULL);
filename = g_strdup_printf ("%s%s",
entry->name, entry->folder? ".tar":"");
@@ -457,10 +450,9 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
{
GabbleFtManager *self = GABBLE_FT_MANAGER (manager);
GabbleFileTransferChannel *chan;
- TpBaseConnection *base_connection = TP_BASE_CONNECTION (
- self->priv->connection);
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->connection);
TpHandleRepoIface *contact_repo =
- tp_base_connection_get_handles (base_connection, TP_HANDLE_TYPE_CONTACT);
+ tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT);
TpHandle handle;
const gchar *content_type, *filename, *content_hash, *description;
const gchar *file_uri, *service_name;
@@ -491,9 +483,9 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
goto error;
/* Don't support opening a channel to our self handle */
- if (handle == base_connection->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base_conn))
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Can't open a file transfer channel to yourself");
goto error;
}
@@ -502,7 +494,7 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentType");
if (content_type == NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"ContentType property is mandatory");
goto error;
}
@@ -511,7 +503,7 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Filename");
if (filename == NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Filename property is mandatory");
goto error;
}
@@ -520,7 +512,7 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Size", NULL);
if (size == 0)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Size property is mandatory");
goto error;
}
@@ -536,7 +528,7 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
{
if (content_hash_type >= NUM_TP_FILE_HASH_TYPES)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%u is not a valid ContentHashType", content_hash_type);
goto error;
}
@@ -548,7 +540,7 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHash");
if (content_hash == NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"ContentHash property is mandatory if ContentHashType is "
"not None");
goto error;
@@ -580,7 +572,7 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
if (metadata != NULL && g_hash_table_lookup ((GHashTable *) metadata, "FORM_TYPE"))
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Metadata cannot contain an item with key 'FORM_TYPE'");
goto error;
}
@@ -589,7 +581,8 @@ gabble_ft_manager_handle_request (TpChannelManager *manager,
tp_handle_inspect (contact_repo, handle));
chan = gabble_file_transfer_channel_new (self->priv->connection,
- handle, base_connection->self_handle, TP_FILE_TRANSFER_STATE_PENDING,
+ handle, tp_base_connection_get_self_handle (base_conn),
+ TP_FILE_TRANSFER_STATE_PENDING,
content_type, filename, size, content_hash_type, content_hash,
description, date, initial_offset, TRUE, NULL, NULL, NULL, file_uri,
service_name, metadata);
diff --git a/src/gabble.c b/src/gabble.c
index 31ca34201..bd5056dfd 100644
--- a/src/gabble.c
+++ b/src/gabble.c
@@ -29,11 +29,8 @@
#include <glib/gstdio.h>
-#include <telepathy-glib/debug.h>
-#include <telepathy-glib/debug-sender.h>
-#include <telepathy-glib/run.h>
-#include <telepathy-glib/util.h>
-#include <wocky/wocky.h>
+#include <telepathy-glib/telepathy-glib.h>
+
#include <wocky/wocky.h>
#include "debug.h"
diff --git a/src/google-relay.c b/src/google-relay.c
deleted file mode 100644
index 472ef3781..000000000
--- a/src/google-relay.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * google-relay.c - Support for Google relays for Jingle
- *
- * Copyright (C) 2006-2008 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 "config.h"
-#include "google-relay.h"
-
-#include <string.h>
-
-#ifdef ENABLE_GOOGLE_RELAY
-#include <libsoup/soup.h>
-#endif
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#ifdef G_OS_WIN32
-#undef ERROR
-#endif
-
-#include "debug.h"
-
-#define RELAY_HTTP_TIMEOUT 5
-
-struct _GabbleGoogleRelayResolver {
-#ifdef ENABLE_GOOGLE_RELAY
- SoupSession *soup;
-#else
- GObject *soup;
-#endif
-};
-
-typedef struct
-{
- GPtrArray *relays;
- guint component;
- guint requests_to_do;
- GabbleJingleInfoRelaySessionCb callback;
- gpointer user_data;
-} RelaySessionData;
-
-static RelaySessionData *
-relay_session_data_new (guint requests_to_do,
- GabbleJingleInfoRelaySessionCb callback,
- gpointer user_data)
-{
- RelaySessionData *rsd = g_slice_new0 (RelaySessionData);
-
- rsd->relays = g_ptr_array_sized_new (requests_to_do);
- g_ptr_array_set_free_func (rsd->relays, (GDestroyNotify) gabble_jingle_relay_free);
- rsd->component = 1;
- rsd->requests_to_do = requests_to_do;
- rsd->callback = callback;
- rsd->user_data = user_data;
-
- return rsd;
-}
-
-/* This is a GSourceFunc */
-static gboolean
-relay_session_data_call (gpointer p)
-{
- RelaySessionData *rsd = p;
-
- g_assert (rsd->callback != NULL);
-
- rsd->callback (rsd->relays, rsd->user_data);
-
- return FALSE;
-}
-
-/* This is a GDestroyNotify */
-static void
-relay_session_data_destroy (gpointer p)
-{
- RelaySessionData *rsd = p;
-
- g_ptr_array_unref (rsd->relays);
-
- g_slice_free (RelaySessionData, rsd);
-}
-
-#ifdef ENABLE_GOOGLE_RELAY
-
-static void
-translate_relay_info (GPtrArray *relays,
- const gchar *relay_ip,
- const gchar *username,
- const gchar *password,
- GabbleJingleRelayType relay_type,
- const gchar *port_string,
- guint component)
-{
- guint64 portll;
- guint port;
-
- if (port_string == NULL)
- {
- DEBUG ("no relay port for %u found", relay_type);
- return;
- }
-
- portll = g_ascii_strtoull (port_string, NULL, 10);
-
- if (portll == 0 || portll > G_MAXUINT16)
- {
- DEBUG ("failed to parse relay port '%s' for %u", port_string,
- relay_type);
- return;
- }
- port = (guint) portll;
-
- DEBUG ("type=%u ip=%s port=%u username=%s password=%s component=%u",
- relay_type, relay_ip, port, username, password, component);
-
- g_ptr_array_add (relays,
- gabble_jingle_relay_new (relay_type, relay_ip, port, username, password,
- component));
-}
-
-static void
-on_http_response (SoupSession *soup,
- SoupMessage *msg,
- gpointer user_data)
-{
- RelaySessionData *rsd = user_data;
-
- if (msg->status_code != 200)
- {
- DEBUG ("Google session creation failed, relaying not used: %d %s",
- msg->status_code, msg->reason_phrase);
- }
- else
- {
- /* parse a=b lines into GHashTable
- * (key, value both borrowed from items of the strv 'lines') */
- GHashTable *map = g_hash_table_new (g_str_hash, g_str_equal);
- gchar **lines;
- guint i;
- const gchar *relay_ip;
- const gchar *relay_udp_port;
- const gchar *relay_tcp_port;
- const gchar *relay_ssltcp_port;
- const gchar *username;
- const gchar *password;
- gchar *escaped_str;
-
- escaped_str = g_strescape (msg->response_body->data, "\r\n");
- DEBUG ("Response from Google:\n====\n%s\n====", escaped_str);
- g_free (escaped_str);
-
- lines = g_strsplit (msg->response_body->data, "\n", 0);
-
- if (lines != NULL)
- {
- for (i = 0; lines[i] != NULL; i++)
- {
- gchar *delim = strchr (lines[i], '=');
- size_t len;
-
- if (delim == NULL || delim == lines[i])
- {
- /* ignore empty keys or lines without '=' */
- continue;
- }
-
- len = strlen (lines[i]);
-
- if (lines[i][len - 1] == '\r')
- {
- lines[i][len - 1] = '\0';
- }
-
- *delim = '\0';
- g_hash_table_insert (map, lines[i], delim + 1);
- }
- }
-
- relay_ip = g_hash_table_lookup (map, "relay.ip");
- relay_udp_port = g_hash_table_lookup (map, "relay.udp_port");
- relay_tcp_port = g_hash_table_lookup (map, "relay.tcp_port");
- relay_ssltcp_port = g_hash_table_lookup (map, "relay.ssltcp_port");
- username = g_hash_table_lookup (map, "username");
- password = g_hash_table_lookup (map, "password");
-
- if (relay_ip == NULL)
- {
- DEBUG ("No relay.ip found");
- }
- else if (username == NULL)
- {
- DEBUG ("No username found");
- }
- else if (password == NULL)
- {
- DEBUG ("No password found");
- }
- else
- {
- translate_relay_info (rsd->relays, relay_ip, username, password,
- GABBLE_JINGLE_RELAY_TYPE_UDP, relay_udp_port, rsd->component);
- translate_relay_info (rsd->relays, relay_ip, username, password,
- GABBLE_JINGLE_RELAY_TYPE_TCP, relay_tcp_port, rsd->component);
- translate_relay_info (rsd->relays, relay_ip, username, password,
- GABBLE_JINGLE_RELAY_TYPE_TLS, relay_ssltcp_port, rsd->component);
- }
-
- g_strfreev (lines);
- g_hash_table_unref (map);
- }
-
- rsd->component++;
-
- if ((--rsd->requests_to_do) == 0)
- {
- relay_session_data_call (rsd);
- relay_session_data_destroy (rsd);
- }
-}
-
-#endif /* ENABLE_GOOGLE_RELAY */
-
-GabbleGoogleRelayResolver *
-gabble_google_relay_resolver_new (void)
-{
- GabbleGoogleRelayResolver *resolver =
- g_slice_new0 (GabbleGoogleRelayResolver);
-
-#ifdef ENABLE_GOOGLE_RELAY
-
- resolver->soup = soup_session_async_new ();
-
- /* If we don't get answer in a few seconds, relay won't do
- * us much help anyways. */
- g_object_set (resolver->soup, "timeout", RELAY_HTTP_TIMEOUT, NULL);
-
-#endif
-
- return resolver;
-}
-
-void
-gabble_google_relay_resolver_destroy (GabbleGoogleRelayResolver *self)
-{
- g_clear_object (&self->soup);
-
- g_slice_free (GabbleGoogleRelayResolver, self);
-}
-
-void
-gabble_google_relay_resolver_resolve (GabbleGoogleRelayResolver *self,
- guint components,
- const gchar *server,
- guint16 port,
- const gchar *token,
- GabbleJingleInfoRelaySessionCb callback,
- gpointer user_data)
-{
- RelaySessionData *rsd =
- relay_session_data_new (components, callback, user_data);
-
-#ifdef ENABLE_GOOGLE_RELAY
-
- gchar *url;
- guint i;
-
- if (server == NULL)
- {
- DEBUG ("No relay server provided, not creating google relay session");
- g_idle_add_full (G_PRIORITY_DEFAULT, relay_session_data_call, rsd,
- relay_session_data_destroy);
- return;
- }
-
- if (token == NULL)
- {
- DEBUG ("No relay token provided, not creating google relay session");
- g_idle_add_full (G_PRIORITY_DEFAULT, relay_session_data_call, rsd,
- relay_session_data_destroy);
- return;
- }
-
- url = g_strdup_printf ("http://%s:%u/create_session", server, (guint) port);
-
- for (i = 0; i < components; i++)
- {
- SoupMessage *msg = soup_message_new ("GET", url);
-
- DEBUG ("Trying to create a new relay session on %s", url);
-
- /* libjingle sets both headers, so shall we */
- soup_message_headers_append (msg->request_headers,
- "X-Talk-Google-Relay-Auth", token);
- soup_message_headers_append (msg->request_headers,
- "X-Google-Relay-Auth", token);
-
- soup_session_queue_message (self->soup, msg, on_http_response, rsd);
- }
-
- g_free (url);
-
-#else /* !ENABLE_GOOGLE_RELAY */
-
- DEBUG ("Google relay service is not supported");
-
- g_idle_add_full (G_PRIORITY_DEFAULT, relay_session_data_call, rsd,
- relay_session_data_destroy);
-
-#endif
-}
diff --git a/src/google-relay.h b/src/google-relay.h
deleted file mode 100644
index fc737a7c6..000000000
--- a/src/google-relay.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * google-relay.h - Header for GabbleGoogleRelaySession
- *
- * Copyright (C) 2006-2008 Collabora Ltd.
- * Copyright (C) 2011 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_GOOGLE_RELAY_H__
-#define __GABBLE_GOOGLE_RELAY_H__
-
-#include <glib.h>
-
-#include "jingle-info.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleGoogleRelayResolver GabbleGoogleRelayResolver;
-
-GabbleGoogleRelayResolver * gabble_google_relay_resolver_new (void);
-void gabble_google_relay_resolver_destroy (GabbleGoogleRelayResolver *self);
-void gabble_google_relay_resolver_resolve (GabbleGoogleRelayResolver *self,
- guint requests_to_do,
- const gchar *server,
- guint16 port,
- const gchar *token,
- GabbleJingleInfoRelaySessionCb callback,
- gpointer user_data);
-
-G_END_DECLS
-
-#endif /* __GABBLE_GOOGLE_RELAY_H__ */
diff --git a/src/gtalk-file-collection.c b/src/gtalk-file-collection.c
index e13180fe0..6626fd0e3 100644
--- a/src/gtalk-file-collection.c
+++ b/src/gtalk-file-collection.c
@@ -29,8 +29,6 @@
#define DEBUG_FLAG GABBLE_DEBUG_SHARE
#include "debug.h"
-#include "jingle-factory.h"
-#include "jingle-session.h"
#include "jingle-share.h"
#include "namespaces.h"
#include "util.h"
@@ -66,7 +64,7 @@
* | \
* | \
* ref | \
- * GabbleJingleSession \
+ * WockyJingleSession \
* | \ (one at a time)
* | \
* ref | \
@@ -74,7 +72,7 @@
* | |
* | |
* ref | ref |
- * GabbleTransportGoogle ----------------*- JingleCandidate PseudoTCP
+ * GabbleTransportGoogle ----------------*- WockyJingleCandidate PseudoTCP
*
* The protocol works like this :
* Once you receive an invitation, the manifest will contain a number of files
@@ -183,8 +181,8 @@ struct _GTalkFileCollectionPrivate
/* the weakref to the channel here is held through the GList *channels */
GHashTable *channels_usable;
GabbleFileTransferChannel *current_channel;
- GabbleJingleFactory *jingle_factory;
- GabbleJingleSession *jingle;
+ WockyJingleFactory *jingle_factory;
+ WockyJingleSession *jingle;
/* ICE component id to jingle share channel association
GINT_TO_POINTER (candidate->component) => g_slice_new (ShareChannel) */
GHashTable *share_channels;
@@ -249,8 +247,8 @@ gtalk_file_collection_dispose (GObject *object)
self->priv->dispose_has_run = TRUE;
if (self->priv->jingle != NULL)
- gabble_jingle_session_terminate (self->priv->jingle,
- JINGLE_REASON_UNKNOWN, NULL, NULL);
+ wocky_jingle_session_terminate (self->priv->jingle,
+ WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL);
tp_clear_object (&self->priv->jingle);
@@ -412,11 +410,11 @@ del_channel (GTalkFileCollection * self, GabbleFileTransferChannel *channel)
}
static void
-jingle_session_state_changed_cb (GabbleJingleSession *session,
+jingle_session_state_changed_cb (WockyJingleSession *session,
GParamSpec *arg1,
GTalkFileCollection *self)
{
- JingleState state;
+ WockyJingleState state;
GList *i;
DEBUG ("called");
@@ -427,11 +425,11 @@ jingle_session_state_changed_cb (GabbleJingleSession *session,
switch (state)
{
- case JINGLE_STATE_INVALID:
- case JINGLE_STATE_PENDING_CREATED:
+ case WOCKY_JINGLE_STATE_INVALID:
+ case WOCKY_JINGLE_STATE_PENDING_CREATED:
break;
- case JINGLE_STATE_PENDING_INITIATE_SENT:
- case JINGLE_STATE_PENDING_INITIATED:
+ case WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT:
+ case WOCKY_JINGLE_STATE_PENDING_INITIATED:
for (i = self->priv->channels; i;)
{
GabbleFileTransferChannel *channel = i->data;
@@ -441,8 +439,8 @@ jingle_session_state_changed_cb (GabbleJingleSession *session,
channel, GTALK_FILE_COLLECTION_STATE_PENDING, FALSE);
}
break;
- case JINGLE_STATE_PENDING_ACCEPT_SENT:
- case JINGLE_STATE_ACTIVE:
+ case WOCKY_JINGLE_STATE_PENDING_ACCEPT_SENT:
+ case WOCKY_JINGLE_STATE_ACTIVE:
/* Do not set the channels to OPEN unless we're ready to send/receive
data from them */
if (self->priv->status == GTALK_FT_STATUS_INITIATED)
@@ -461,7 +459,7 @@ jingle_session_state_changed_cb (GabbleJingleSession *session,
channel, GTALK_FILE_COLLECTION_STATE_ACCEPTED, FALSE);
}
break;
- case JINGLE_STATE_ENDED:
+ case WOCKY_JINGLE_STATE_ENDED:
/* Do nothing, let the terminated signal set the correct state
depending on the termination reason */
default:
@@ -470,9 +468,9 @@ jingle_session_state_changed_cb (GabbleJingleSession *session,
}
static void
-jingle_session_terminated_cb (GabbleJingleSession *session,
+jingle_session_terminated_cb (WockyJingleSession *session,
gboolean local_terminator,
- JingleReason reason,
+ WockyJingleReason reason,
const gchar *text,
gpointer user_data)
{
@@ -494,7 +492,7 @@ jingle_session_terminated_cb (GabbleJingleSession *session,
}
static void
-content_new_remote_candidates_cb (GabbleJingleContent *content,
+content_new_remote_candidates_cb (WockyJingleContent *content,
GList *clist, gpointer user_data)
{
GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data);
@@ -504,12 +502,12 @@ content_new_remote_candidates_cb (GabbleJingleContent *content,
for (li = clist; li; li = li->next)
{
- JingleCandidate *candidate = li->data;
+ WockyJingleCandidate *candidate = li->data;
NiceCandidate *cand = NULL;
ShareChannel *share_channel = NULL;
GSList *candidates = NULL;
- if (candidate->protocol != JINGLE_TRANSPORT_PROTOCOL_UDP)
+ if (candidate->protocol != WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP)
{
DEBUG ("Ignoring candidate %s because of non-UDP protocol : %d",
candidate->username, candidate->protocol);
@@ -526,14 +524,14 @@ content_new_remote_candidates_cb (GabbleJingleContent *content,
}
cand = nice_candidate_new (
- candidate->type == JINGLE_CANDIDATE_TYPE_LOCAL?
+ candidate->type == WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL?
NICE_CANDIDATE_TYPE_HOST:
- candidate->type == JINGLE_CANDIDATE_TYPE_STUN?
+ candidate->type == WOCKY_JINGLE_CANDIDATE_TYPE_STUN?
NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
NICE_CANDIDATE_TYPE_RELAYED);
- cand->transport = JINGLE_TRANSPORT_PROTOCOL_UDP;
+ cand->transport = WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP;
nice_address_init (&cand->addr);
if (!nice_address_set_from_string (&cand->addr, candidate->address))
@@ -577,7 +575,7 @@ nice_candidate_gathering_done (NiceAgent *agent, guint stream_id,
{
GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data);
ShareChannel *share_channel = get_share_channel (self, agent);
- GabbleJingleContent *content = GABBLE_JINGLE_CONTENT (share_channel->content);
+ WockyJingleContent *content = WOCKY_JINGLE_CONTENT (share_channel->content);
GList *candidates = NULL;
GList *remote_candidates = NULL;
GSList *local_candidates;
@@ -586,7 +584,7 @@ nice_candidate_gathering_done (NiceAgent *agent, guint stream_id,
DEBUG ("libnice candidate gathering done!!!!");
/* Send remote candidates to libnice and listen to new signal */
- remote_candidates = gabble_jingle_content_get_remote_candidates (content);
+ remote_candidates = wocky_jingle_content_get_remote_candidates (content);
content_new_remote_candidates_cb (content, remote_candidates, self);
gabble_signal_connect_weak (content, "new-candidates",
@@ -599,22 +597,22 @@ nice_candidate_gathering_done (NiceAgent *agent, guint stream_id,
for (li = local_candidates; li; li = li->next)
{
NiceCandidate *cand = li->data;
- JingleCandidate *candidate;
+ WockyJingleCandidate *candidate;
gchar ip[NICE_ADDRESS_STRING_LEN];
nice_address_to_string (&cand->addr, ip);
- candidate = jingle_candidate_new (
+ candidate = wocky_jingle_candidate_new (
/* protocol */
cand->transport == NICE_CANDIDATE_TRANSPORT_UDP?
- JINGLE_TRANSPORT_PROTOCOL_UDP:
- JINGLE_TRANSPORT_PROTOCOL_TCP,
+ WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP:
+ WOCKY_JINGLE_TRANSPORT_PROTOCOL_TCP,
/* candidate type */
cand->type == NICE_CANDIDATE_TYPE_HOST?
- JINGLE_CANDIDATE_TYPE_LOCAL:
+ WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL:
cand->type == NICE_CANDIDATE_TYPE_RELAYED?
- JINGLE_CANDIDATE_TYPE_RELAY:
- JINGLE_CANDIDATE_TYPE_STUN,
+ WOCKY_JINGLE_CANDIDATE_TYPE_RELAY:
+ WOCKY_JINGLE_CANDIDATE_TYPE_STUN,
/* id */
cand->foundation,
/* component */
@@ -637,7 +635,7 @@ nice_candidate_gathering_done (NiceAgent *agent, guint stream_id,
candidates = g_list_prepend (candidates, candidate);
}
- gabble_jingle_content_add_candidates (content, candidates);
+ wocky_jingle_content_add_candidates (content, candidates);
}
static void
@@ -646,8 +644,8 @@ nice_component_state_changed (NiceAgent *agent, guint stream_id,
{
GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data);
ShareChannel *share_channel = get_share_channel (self, agent);
- GabbleJingleContent *content = GABBLE_JINGLE_CONTENT (share_channel->content);
- JingleTransportState ts = JINGLE_TRANSPORT_STATE_DISCONNECTED;
+ WockyJingleContent *content = WOCKY_JINGLE_CONTENT (share_channel->content);
+ WockyJingleTransportState ts = WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED;
DEBUG ("libnice component state changed %d!!!!", state);
@@ -655,14 +653,14 @@ nice_component_state_changed (NiceAgent *agent, guint stream_id,
{
case NICE_COMPONENT_STATE_DISCONNECTED:
case NICE_COMPONENT_STATE_GATHERING:
- ts = JINGLE_TRANSPORT_STATE_DISCONNECTED;
+ ts = WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED;
break;
case NICE_COMPONENT_STATE_CONNECTING:
- ts = JINGLE_TRANSPORT_STATE_CONNECTING;
+ ts = WOCKY_JINGLE_TRANSPORT_STATE_CONNECTING;
break;
case NICE_COMPONENT_STATE_CONNECTED:
case NICE_COMPONENT_STATE_READY:
- ts = JINGLE_TRANSPORT_STATE_CONNECTED;
+ ts = WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED;
break;
case NICE_COMPONENT_STATE_FAILED:
{
@@ -682,7 +680,7 @@ nice_component_state_changed (NiceAgent *agent, guint stream_id,
return;
}
}
- gabble_jingle_content_set_transport_state (content, ts);
+ wocky_jingle_content_set_transport_state (content, ts);
}
static void
@@ -700,11 +698,11 @@ get_next_manifest_entry (GTalkFileCollection *self,
{
if (g_list_length (self->priv->channels) == 1)
{
- GabbleJingleContent *content = \
- GABBLE_JINGLE_CONTENT (share_channel->content);
+ WockyJingleContent *content = \
+ WOCKY_JINGLE_CONTENT (share_channel->content);
DEBUG ("Received all the files. Transfer is complete");
- gabble_jingle_content_send_complete (content);
+ wocky_jingle_content_send_complete (content);
}
g_hash_table_replace (self->priv->channels_usable,
@@ -765,7 +763,7 @@ get_next_manifest_entry (GTalkFileCollection *self,
"User-Agent: %s\r\n\r\n",
(source_url != NULL ? source_url : ""),
separator, filename,
- gabble_jingle_session_get_initiator (self->priv->jingle),
+ wocky_jingle_session_get_initiator (self->priv->jingle),
PACKAGE_STRING);
g_free (filename);
@@ -852,19 +850,19 @@ typedef struct
} GoogleRelaySessionData;
static const NiceRelayType relay_type_map[] = {
- /* GABBLE_JINGLE_RELAY_TYPE_UDP */ NICE_RELAY_TYPE_TURN_UDP,
- /* GABBLE_JINGLE_RELAY_TYPE_TCP */ NICE_RELAY_TYPE_TURN_TCP,
- /* GABBLE_JINGLE_RELAY_TYPE_TLS */ NICE_RELAY_TYPE_TURN_TLS,
+ /* WOCKY_JINGLE_RELAY_TYPE_UDP */ NICE_RELAY_TYPE_TURN_UDP,
+ /* WOCKY_JINGLE_RELAY_TYPE_TCP */ NICE_RELAY_TYPE_TURN_TCP,
+ /* WOCKY_JINGLE_RELAY_TYPE_TLS */ NICE_RELAY_TYPE_TURN_TLS,
};
static void
set_relay_info (gpointer item, gpointer user_data)
{
GoogleRelaySessionData *data = user_data;
- GabbleJingleRelay *relay = item;
+ WockyJingleRelay *relay = item;
NiceRelayType type;
- g_return_if_fail (relay->type < GABBLE_N_JINGLE_RELAY_TYPES);
+ g_return_if_fail (relay->type < WOCKY_N_JINGLE_RELAY_TYPES);
type = relay_type_map[relay->type];
nice_agent_set_relay_info (data->share_channel->agent,
@@ -896,7 +894,7 @@ google_relay_session_cb (GPtrArray *relays, gpointer user_data)
static void
-content_new_share_channel_cb (GabbleJingleContent *content, const gchar *name,
+content_new_share_channel_cb (WockyJingleContent *content, const gchar *name,
guint share_channel_id, gpointer user_data)
{
GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data);
@@ -904,8 +902,7 @@ content_new_share_channel_cb (GabbleJingleContent *content, const gchar *name,
NiceAgent *agent = nice_agent_new_reliable (g_main_context_default (),
NICE_COMPATIBILITY_GOOGLE);
guint stream_id = nice_agent_add_stream (agent, 1);
- gchar *stun_server;
- guint stun_port;
+ GList *stun_servers;
GoogleRelaySessionData *relay_data = NULL;
DEBUG ("New Share channel %s was created and linked to id %d", name,
@@ -945,15 +942,18 @@ content_new_share_channel_cb (GabbleJingleContent *content, const gchar *name,
nice_agent_attach_recv (agent, stream_id, share_channel->component_id,
g_main_context_default (), nice_data_received_cb, self);
- if (gabble_jingle_info_get_stun_server (
- gabble_jingle_factory_get_jingle_info (self->priv->jingle_factory),
- &stun_server, &stun_port))
+ stun_servers = wocky_jingle_info_get_stun_servers (
+ wocky_jingle_factory_get_jingle_info (self->priv->jingle_factory));
+ if (stun_servers != NULL)
{
+ WockyStunServer *stun_server = stun_servers->data;
+
g_object_set (agent,
- "stun-server", stun_server,
- "stun-server-port", stun_port,
+ "stun-server", stun_server->address,
+ "stun-server-port", (guint) stun_server->port,
NULL);
- g_free (stun_server);
+
+ g_list_free (stun_servers);
}
relay_data = g_slice_new0 (GoogleRelaySessionData);
@@ -961,13 +961,13 @@ content_new_share_channel_cb (GabbleJingleContent *content, const gchar *name,
relay_data->share_channel = share_channel;
g_object_add_weak_pointer (G_OBJECT (relay_data->u.self),
&relay_data->u.ptr);
- gabble_jingle_info_create_google_relay_session (
- gabble_jingle_factory_get_jingle_info (self->priv->jingle_factory), 1,
+ wocky_jingle_info_create_google_relay_session (
+ wocky_jingle_factory_get_jingle_info (self->priv->jingle_factory), 1,
google_relay_session_cb, relay_data);
}
static void
-content_completed (GabbleJingleContent *content, gpointer user_data)
+content_completed (WockyJingleContent *content, gpointer user_data)
{
GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data);
GList *i;
@@ -1381,7 +1381,7 @@ nice_data_received_cb (NiceAgent *agent,
static void
set_session (GTalkFileCollection * self,
- GabbleJingleSession *session, GabbleJingleContent *content)
+ WockyJingleSession *session, WockyJingleContent *content)
{
self->priv->jingle = g_object_ref (session);
@@ -1400,19 +1400,19 @@ set_session (GTalkFileCollection * self,
GTalkFileCollection *
gtalk_file_collection_new (GabbleFileTransferChannel *channel,
- GabbleJingleFactory *jingle_factory, TpHandle handle, const gchar *jid)
+ WockyJingleFactory *jingle_factory, TpHandle handle, const gchar *jid)
{
GTalkFileCollection * self = g_object_new (GTALK_TYPE_FILE_COLLECTION, NULL);
- GabbleJingleSession *session = NULL;
- GabbleJingleContent *content = NULL;
+ WockyJingleSession *session = NULL;
+ WockyJingleContent *content = NULL;
gchar *filename;
guint64 size;
self->priv->jingle_factory = jingle_factory;
self->priv->requested = TRUE;
- session = gabble_jingle_factory_create_session (jingle_factory,
- jid, JINGLE_DIALECT_GTALK4, FALSE);
+ session = wocky_jingle_factory_create_session (jingle_factory,
+ jid, WOCKY_JINGLE_DIALECT_GTALK4, FALSE);
if (session == NULL)
{
@@ -1420,8 +1420,8 @@ gtalk_file_collection_new (GabbleFileTransferChannel *channel,
return NULL;
}
- content = gabble_jingle_session_add_content (session,
- JINGLE_MEDIA_TYPE_NONE, JINGLE_CONTENT_SENDERS_BOTH, "share",
+ content = wocky_jingle_session_add_content (session,
+ WOCKY_JINGLE_MEDIA_TYPE_NONE, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, "share",
NS_GOOGLE_SESSION_SHARE, NS_GOOGLE_TRANSPORT_P2P);
if (content == NULL)
@@ -1449,22 +1449,22 @@ gtalk_file_collection_new (GabbleFileTransferChannel *channel,
}
GTalkFileCollection *
-gtalk_file_collection_new_from_session (GabbleJingleFactory *jingle_factory,
- GabbleJingleSession *session)
+gtalk_file_collection_new_from_session (WockyJingleFactory *jingle_factory,
+ WockyJingleSession *session)
{
GTalkFileCollection * self = NULL;
- GabbleJingleContent *content = NULL;
+ WockyJingleContent *content = NULL;
GList *cs;
- if (gabble_jingle_session_get_content_type (session) !=
+ if (wocky_jingle_session_get_content_type (session) !=
GABBLE_TYPE_JINGLE_SHARE)
return NULL;
- cs = gabble_jingle_session_get_contents (session);
+ cs = wocky_jingle_session_get_contents (session);
if (cs != NULL)
{
- content = GABBLE_JINGLE_CONTENT (cs->data);
+ content = WOCKY_JINGLE_CONTENT (cs->data);
g_list_free (cs);
}
@@ -1502,7 +1502,7 @@ gtalk_file_collection_initiate (GTalkFileCollection *self,
if (self->priv->status == GTALK_FT_STATUS_PENDING)
{
- gabble_jingle_session_accept (self->priv->jingle);
+ wocky_jingle_session_accept (self->priv->jingle);
self->priv->status = GTALK_FT_STATUS_INITIATED;
}
else
@@ -1517,7 +1517,7 @@ void
gtalk_file_collection_accept (GTalkFileCollection *self,
GabbleFileTransferChannel * channel)
{
- GList *cs = gabble_jingle_session_get_contents (self->priv->jingle);
+ GList *cs = wocky_jingle_session_get_contents (self->priv->jingle);
DEBUG ("called");
@@ -1531,11 +1531,11 @@ gtalk_file_collection_accept (GTalkFileCollection *self,
{
if (cs != NULL)
{
- GabbleJingleContent *content = GABBLE_JINGLE_CONTENT (cs->data);
+ WockyJingleContent *content = WOCKY_JINGLE_CONTENT (cs->data);
guint initial_id = 0;
guint share_channel_id;
- gabble_jingle_session_accept (self->priv->jingle);
+ wocky_jingle_session_accept (self->priv->jingle);
self->priv->status = GTALK_FT_STATUS_ACCEPTED;
/* The new-share-channel signal will take care of the rest.. */
@@ -1544,7 +1544,7 @@ gtalk_file_collection_accept (GTalkFileCollection *self,
gchar *share_channel_name = NULL;
share_channel_name = g_strdup_printf ("gabble-%d", ++initial_id);
- share_channel_id = gabble_jingle_content_create_share_channel (
+ share_channel_id = wocky_jingle_content_create_share_channel (
content, share_channel_name);
g_free (share_channel_name);
} while (share_channel_id == 0 && initial_id < 10);
@@ -1683,8 +1683,8 @@ gtalk_file_collection_terminate (GTalkFileCollection *self,
terminate all channels which should unref us which will unref the
jingle session */
self->priv->status = GTALK_FT_STATUS_TERMINATED;
- gabble_jingle_session_terminate (self->priv->jingle,
- JINGLE_REASON_UNKNOWN, NULL, NULL);
+ wocky_jingle_session_terminate (self->priv->jingle,
+ WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL);
return;
}
return;
@@ -1695,7 +1695,7 @@ gtalk_file_collection_terminate (GTalkFileCollection *self,
/* If this was the last channel, it will cause it to unref us and
the dispose will be called, which will call
- gabble_jingle_session_terminate */
+ wocky_jingle_session_terminate */
gabble_file_transfer_channel_gtalk_file_collection_state_changed (channel,
GTALK_FILE_COLLECTION_STATE_TERMINATED, TRUE);
}
@@ -1724,8 +1724,8 @@ channel_disposed (gpointer data, GObject *object)
terminate all channels which should unref us which will unref the
jingle session */
self->priv->status = GTALK_FT_STATUS_TERMINATED;
- gabble_jingle_session_terminate (self->priv->jingle,
- JINGLE_REASON_UNKNOWN, NULL, NULL);
+ wocky_jingle_session_terminate (self->priv->jingle,
+ WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL);
return;
}
}
diff --git a/src/gtalk-file-collection.h b/src/gtalk-file-collection.h
index 895a77d43..b1e784fc2 100644
--- a/src/gtalk-file-collection.h
+++ b/src/gtalk-file-collection.h
@@ -21,7 +21,7 @@
#define __GTALK_FILE_COLLECTION_H__
#include <glib-object.h>
-#include "jingle-session.h"
+#include <wocky/wocky.h>
#include "connection.h"
typedef struct _GTalkFileCollection GTalkFileCollection;
@@ -73,11 +73,11 @@ struct _GTalkFileCollection {
};
GTalkFileCollection *gtalk_file_collection_new (
- GabbleFileTransferChannel *channel, GabbleJingleFactory *jingle_factory,
+ GabbleFileTransferChannel *channel, WockyJingleFactory *jingle_factory,
TpHandle handle, const gchar *jid);
GTalkFileCollection *gtalk_file_collection_new_from_session (
- GabbleJingleFactory *jingle_factory, GabbleJingleSession *session);
+ WockyJingleFactory *jingle_factory, WockyJingleSession *session);
void gtalk_file_collection_add_channel (GTalkFileCollection *self,
GabbleFileTransferChannel *channel);
diff --git a/src/im-channel.c b/src/im-channel.c
index d294c3a04..9cbdbfaab 100644
--- a/src/im-channel.c
+++ b/src/im-channel.c
@@ -24,14 +24,9 @@
#include <string.h>
#include <dbus/dbus-glib.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-generic.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_IM
#include "connection.h"
@@ -44,7 +39,6 @@
#include "roster.h"
#include "util.h"
-static void chat_state_iface_init (gpointer, gpointer);
static void destroyable_iface_init (gpointer, gpointer);
G_DEFINE_TYPE_WITH_CODE (GabbleIMChannel, gabble_im_channel,
@@ -54,20 +48,16 @@ G_DEFINE_TYPE_WITH_CODE (GabbleIMChannel, gabble_im_channel,
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MESSAGES,
tp_message_mixin_messages_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CHAT_STATE,
- chat_state_iface_init);
+ tp_message_mixin_chat_state_iface_init)
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DESTROYABLE,
destroyable_iface_init));
static void _gabble_im_channel_send_message (GObject *object,
TpMessage *message, TpMessageSendingFlags flags);
static void gabble_im_channel_close (TpBaseChannel *base_chan);
-
-static const gchar *gabble_im_channel_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE,
- TP_IFACE_CHANNEL_INTERFACE_MESSAGES,
- TP_IFACE_CHANNEL_INTERFACE_DESTROYABLE,
- NULL
-};
+static gboolean _gabble_im_channel_send_chat_state (GObject *object,
+ TpChannelChatState state,
+ GError **error);
/* private structure */
@@ -84,13 +74,6 @@ struct _GabbleIMChannelPrivate
gboolean send_nick;
ChatStateSupport chat_states_supported;
- /* FALSE unless at least one chat state notification has been sent; <gone/>
- * will only be sent when the channel closes if this is TRUE. This prevents
- * opening a channel and closing it immediately sending a spurious <gone/> to
- * the peer.
- */
- gboolean send_gone;
-
gboolean dispose_has_run;
};
@@ -98,8 +81,24 @@ typedef struct {
GabbleIMChannel *channel;
TpMessage *message;
gchar *token;
+ TpMessageSendingFlags flags;
} _GabbleIMSendMessageCtx;
+static GPtrArray *
+gabble_im_channel_get_interfaces (TpBaseChannel *base)
+{
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CHANNEL_CLASS (
+ gabble_im_channel_parent_class)->get_interfaces (base);
+
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_MESSAGES);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_DESTROYABLE);
+
+ return interfaces;
+}
+
static void
gabble_im_channel_init (GabbleIMChannel *self)
{
@@ -143,15 +142,21 @@ gabble_im_channel_constructed (GObject *obj)
else
priv->send_nick = TRUE;
- priv->chat_states_supported = CHAT_STATES_UNKNOWN;
-
tp_message_mixin_init (obj, G_STRUCT_OFFSET (GabbleIMChannel, message_mixin),
base_conn);
+ /* We deliberately do not include
+ * TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_SUCCESSES here, even though we
+ * support requesting receipts, because XEP-0184 provides no guarantees.
+ */
tp_message_mixin_implement_sending (obj, _gabble_im_channel_send_message,
G_N_ELEMENTS (types), types, 0,
TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES,
supported_content_types);
+
+ priv->chat_states_supported = CHAT_STATES_UNKNOWN;
+ tp_message_mixin_implement_send_chat_state (obj,
+ _gabble_im_channel_send_chat_state);
}
static void gabble_im_channel_dispose (GObject *object);
@@ -197,7 +202,7 @@ gabble_im_channel_class_init (GabbleIMChannelClass *gabble_im_channel_class)
object_class->finalize = gabble_im_channel_finalize;
base_class->channel_type = TP_IFACE_CHANNEL_TYPE_TEXT;
- base_class->interfaces = gabble_im_channel_interfaces;
+ base_class->get_interfaces = gabble_im_channel_get_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
base_class->close = gabble_im_channel_close;
base_class->fill_immutable_properties =
@@ -237,22 +242,26 @@ chat_states_supported (GabbleIMChannel *self,
}
}
-static void
-im_channel_send_gone (GabbleIMChannel *self)
+static gboolean
+receipts_conceivably_supported (
+ GabbleIMChannel *self)
{
- GabbleIMChannelPrivate *priv = self->priv;
TpBaseChannel *base = (TpBaseChannel *) self;
+ GabbleConnection *conn =
+ GABBLE_CONNECTION (tp_base_channel_get_connection (base));
+ GabblePresence *presence;
- if (priv->send_gone)
- {
- if (chat_states_supported (self, FALSE))
- gabble_message_util_send_chat_state (G_OBJECT (self),
- GABBLE_CONNECTION (tp_base_channel_get_connection (base)),
- WOCKY_STANZA_SUB_TYPE_CHAT, TP_CHANNEL_CHAT_STATE_GONE,
- priv->peer_jid, NULL);
+ presence = gabble_presence_cache_get (conn->presence_cache,
+ tp_base_channel_get_target_handle (base));
- priv->send_gone = FALSE;
- }
+ /* ...except it's never null because _parse_message_message() in
+ * presence-cache.c. I hate this exactly as much as I did when I wrote the
+ * FIXME on that function. */
+ if (presence != NULL)
+ return gabble_presence_has_cap (presence, NS_RECEIPTS);
+
+ /* Otherwise ... who knows. Why not ask for one? */
+ return TRUE;
}
static void
@@ -282,7 +291,7 @@ gabble_im_channel_dispose (GObject *object)
}
}
- im_channel_send_gone (self);
+ tp_message_mixin_maybe_send_gone (object);
if (G_OBJECT_CLASS (gabble_im_channel_parent_class)->dispose)
G_OBJECT_CLASS (gabble_im_channel_parent_class)->dispose (object);
@@ -318,7 +327,7 @@ _gabble_im_channel_message_sent_cb (GObject *source,
if (wocky_porter_send_finish (porter, res, &error))
{
- tp_message_mixin_sent ((GObject *) chan, message, 0,
+ tp_message_mixin_sent ((GObject *) chan, message, context->flags,
context->token, NULL);
}
else
@@ -340,9 +349,10 @@ _gabble_im_channel_send_message (GObject *object,
{
GabbleIMChannel *self = GABBLE_IM_CHANNEL (object);
TpBaseChannel *base = (TpBaseChannel *) self;
+ TpBaseConnection *base_conn;
GabbleConnection *gabble_conn;
GabbleIMChannelPrivate *priv;
- gint state = -1;
+ TpChannelChatState state = -1;
WockyStanza *stanza = NULL;
gchar *id = NULL;
GError *error = NULL;
@@ -352,29 +362,40 @@ _gabble_im_channel_send_message (GObject *object,
g_assert (GABBLE_IS_IM_CHANNEL (self));
priv = self->priv;
+ base_conn = tp_base_channel_get_connection (base);
+ gabble_conn = GABBLE_CONNECTION (base_conn);
+
if (chat_states_supported (self, TRUE))
{
state = TP_CHANNEL_CHAT_STATE_ACTIVE;
- priv->send_gone = TRUE;
+ tp_message_mixin_change_chat_state (object,
+ tp_base_connection_get_self_handle (base_conn), state);
}
- /* We don't support providing successful delivery reports. */
- flags = 0;
- gabble_conn =
- GABBLE_CONNECTION (tp_base_channel_get_connection (base));
-
stanza = gabble_message_util_build_stanza (message,
gabble_conn, 0, state, priv->peer_jid,
priv->send_nick, &id, &error);
-
if (stanza != NULL)
{
+ if ((flags & TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY) &&
+ receipts_conceivably_supported (self))
+ {
+ wocky_node_add_child_ns (wocky_stanza_get_top_node (stanza),
+ "request", NS_RECEIPTS);
+ flags = TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY;
+ }
+ else
+ {
+ flags = 0;
+ }
+
porter = gabble_connection_dup_porter (gabble_conn);
context = g_slice_new0 (_GabbleIMSendMessageCtx);
context->channel = g_object_ref (base);
context->message = g_object_ref (message);
context->token = id;
+ context->flags = flags;
wocky_porter_send_async (porter, stanza, NULL,
_gabble_im_channel_message_sent_cb, context);
g_object_unref (porter);
@@ -382,7 +403,7 @@ _gabble_im_channel_send_message (GObject *object,
}
else
{
- tp_message_mixin_sent (object, message, flags, NULL, error);
+ tp_message_mixin_sent (object, message, 0, NULL, error);
g_error_free (error);
}
@@ -415,29 +436,61 @@ build_message (
return msg;
}
+static void
+maybe_send_delivery_report (
+ GabbleIMChannel *self,
+ WockyStanza *message,
+ const gchar *jid,
+ const gchar *id)
+{
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpHandle target = tp_base_channel_get_target_handle (base);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ GabbleConnection *conn = GABBLE_CONNECTION (base_conn);
+ WockyStanza *report;
+
+ if (id == NULL)
+ return;
+
+ if (wocky_node_get_child_ns (wocky_stanza_get_top_node (message),
+ "request", NS_RECEIPTS) == NULL)
+ return;
+
+ if (conn->self_presence->status == GABBLE_PRESENCE_HIDDEN ||
+ !gabble_roster_handle_gets_presence_from_us (conn->roster, target))
+ return;
+
+ report = wocky_stanza_build (
+ WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
+ NULL, jid,
+ '(', "received", ':', NS_RECEIPTS,
+ '@', "id", id,
+ ')', NULL);
+
+ _gabble_connection_send (conn, report, NULL);
+ g_object_unref (report);
+}
+
/*
* _gabble_im_channel_receive:
* @chan: a channel
+ * @message: the <message> stanza, from which all the following arguments were
+ * extracted.
* @type: the message type
* @from: the full JID we received the message from
* @timestamp: the time at which the message was sent (not the time it was
* received)
* @id: the id='' attribute from the <message/> stanza, if any
* @text: the plaintext body of the message
- * @send_error: the reason why sending @text to @sender failed, or
- * GABBLE_TEXT_CHANNEL_SEND_NO_ERROR if this call is not to report
- * a failure to send.
- * @delivery_status: if @send_error is GABBLE_TEXT_CHANNEL_SEND_NO_ERROR,
- * ignored; else the delivery status to attach to the report.
* @state: a #TpChannelChatState, or -1 if there was no chat state in the
* message.
*
* Shoves an incoming message into @chan, possibly updating the chat state at
- * the same time; or maybe this is a delivery report? Who knows! It's a magical
- * adventure.
+ * the same time.
*/
void
_gabble_im_channel_receive (GabbleIMChannel *chan,
+ WockyStanza *message,
TpChannelTextMessageType type,
const char *from,
time_t timestamp,
@@ -475,6 +528,7 @@ _gabble_im_channel_receive (GabbleIMChannel *chan,
tp_message_set_string (msg, 0, "message-token", id);
tp_message_mixin_take_received (G_OBJECT (chan), msg);
+ maybe_send_delivery_report (chan, message, from, id);
}
void
@@ -491,7 +545,7 @@ _gabble_im_channel_report_delivery (
TpBaseChannel *base_chan = (TpBaseChannel *) self;
TpBaseConnection *base_conn;
TpHandle peer;
- TpMessage *msg, *delivery_report;
+ TpMessage *delivery_report;
gchar *tmp;
g_return_if_fail (GABBLE_IS_IM_CHANNEL (self));
@@ -510,7 +564,6 @@ _gabble_im_channel_report_delivery (
priv->chat_states_supported = CHAT_STATES_UNKNOWN;
}
- msg = build_message (self, type, timestamp, text);
delivery_report = tp_cm_message_new (base_conn, 1);
tp_message_set_uint32 (delivery_report, 0, "message-type",
TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT);
@@ -529,15 +582,20 @@ _gabble_im_channel_report_delivery (
if (id != NULL)
tp_message_set_string (delivery_report, 0, "delivery-token", id);
- /* This is a delivery report, so the original sender of the echoed message
- * must be us! */
- tp_cm_message_set_sender (msg, base_conn->self_handle);
+ if (text != NULL)
+ {
+ TpMessage *msg = build_message (self, type, timestamp, text);
+ /* This is a delivery report, so the original sender of the echoed message
+ * must be us! */
+ tp_cm_message_set_sender (msg, tp_base_connection_get_self_handle (base_conn));
- /* Since this is a delivery report, we can trust the id on the message. */
- if (id != NULL)
- tp_message_set_string (msg, 0, "message-token", id);
+ /* Since this is a delivery report, we can trust the id on the message. */
+ if (id != NULL)
+ tp_message_set_string (msg, 0, "message-token", id);
+
+ tp_cm_message_take_message (delivery_report, 0, "delivery-echo", msg);
+ }
- tp_cm_message_take_message (delivery_report, 0, "delivery-echo", msg);
tp_message_mixin_take_received (G_OBJECT (self), delivery_report);
}
@@ -555,24 +613,32 @@ _gabble_im_channel_state_receive (GabbleIMChannel *chan,
GabbleIMChannelPrivate *priv;
TpBaseChannel *base_chan;
- g_assert (state < NUM_TP_CHANNEL_CHAT_STATES);
g_assert (GABBLE_IS_IM_CHANNEL (chan));
base_chan = (TpBaseChannel *) chan;
priv = chan->priv;
priv->chat_states_supported = CHAT_STATES_SUPPORTED;
- tp_svc_channel_interface_chat_state_emit_chat_state_changed (
- (TpSvcChannelInterfaceChatState *) chan,
+ tp_message_mixin_change_chat_state ((GObject *) chan,
tp_base_channel_get_target_handle (base_chan), state);
}
+void
+gabble_im_channel_receive_receipt (
+ GabbleIMChannel *self,
+ const gchar *receipt_id)
+{
+ _gabble_im_channel_report_delivery (self,
+ TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, 0, receipt_id, NULL,
+ GABBLE_TEXT_CHANNEL_SEND_NO_ERROR, TP_DELIVERY_STATUS_DELIVERED);
+}
+
static void
gabble_im_channel_close (TpBaseChannel *base_chan)
{
GabbleIMChannel *self = GABBLE_IM_CHANNEL (base_chan);
- im_channel_send_gone (self);
+ tp_message_mixin_maybe_send_gone ((GObject *) self);
/* The IM factory will resurrect the channel if we have pending
* messages. When we're resurrected, we want the initiator
@@ -610,76 +676,24 @@ gabble_im_channel_destroy (TpSvcChannelInterfaceDestroyable *iface,
tp_svc_channel_interface_destroyable_return_from_destroy (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)
+static gboolean
+_gabble_im_channel_send_chat_state (GObject *object,
+ TpChannelChatState state,
+ GError **error)
{
- GabbleIMChannel *self = GABBLE_IM_CHANNEL (iface);
+ GabbleIMChannel *self = GABBLE_IM_CHANNEL (object);
+ GabbleIMChannelPrivate *priv = self->priv;
TpBaseChannel *base = (TpBaseChannel *) self;
- GabbleIMChannelPrivate *priv;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_IM_CHANNEL (self));
- priv = self->priv;
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
- if (state >= NUM_TP_CHANNEL_CHAT_STATES)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "invalid state: %u", state);
- }
- else if (state == TP_CHANNEL_CHAT_STATE_GONE)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "you may not explicitly set the Gone state");
- }
/* Only send anything to the peer if we actually know they support chat
- * states.
- */
- else if (chat_states_supported (self, FALSE))
- {
- TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
-
- if (gabble_message_util_send_chat_state (G_OBJECT (self),
- GABBLE_CONNECTION (base_conn),
- WOCKY_STANZA_SUB_TYPE_CHAT, state, priv->peer_jid, &error))
- {
- priv->send_gone = TRUE;
-
- /* Send the ChatStateChanged signal for the local user */
- tp_svc_channel_interface_chat_state_emit_chat_state_changed (iface,
- base_conn->self_handle, state);
- }
- }
-
- if (error != NULL)
- {
- DEBUG ("%s", error->message);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
- else
- {
- tp_svc_channel_interface_chat_state_return_from_set_chat_state (context);
- }
-}
+ * states. */
+ if (!chat_states_supported (self, FALSE))
+ return TRUE;
-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
+ return gabble_message_util_send_chat_state (G_OBJECT (self),
+ GABBLE_CONNECTION (base_conn),
+ WOCKY_STANZA_SUB_TYPE_CHAT, state, priv->peer_jid, error);
}
static void
diff --git a/src/im-channel.h b/src/im-channel.h
index fdbae19bf..c09408484 100644
--- a/src/im-channel.h
+++ b/src/im-channel.h
@@ -24,9 +24,8 @@
#include <glib-object.h>
#include <time.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/message-mixin.h>
-#include <telepathy-glib/base-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <wocky/wocky.h>
G_BEGIN_DECLS
@@ -65,6 +64,7 @@ GType gabble_im_channel_get_type (void);
GabbleIMChannelClass))
void _gabble_im_channel_receive (GabbleIMChannel *chan,
+ WockyStanza *message,
TpChannelTextMessageType type,
const char *from,
time_t timestamp,
@@ -73,6 +73,9 @@ void _gabble_im_channel_receive (GabbleIMChannel *chan,
gint state);
void _gabble_im_channel_state_receive (GabbleIMChannel *chan,
TpChannelChatState state);
+void gabble_im_channel_receive_receipt (
+ GabbleIMChannel *self,
+ const gchar *receipt_id);
void _gabble_im_channel_report_delivery (
GabbleIMChannel *self,
diff --git a/src/im-factory.c b/src/im-factory.c
index 0459c2dc0..4170d1012 100644
--- a/src/im-factory.c
+++ b/src/im-factory.c
@@ -24,10 +24,8 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
#define DEBUG_FLAG GABBLE_DEBUG_IM
@@ -62,6 +60,7 @@ struct _GabbleImFactoryPrivate
{
GabbleConnection *conn;
guint message_cb_id;
+ guint delivery_report_cb_id;
GHashTable *channels;
gulong status_changed_id;
@@ -258,7 +257,8 @@ im_factory_message_cb (
}
else if (body != NULL)
{
- _gabble_im_channel_receive (chan, msgtype, from, stamp, id, body, state);
+ _gabble_im_channel_receive (chan, message, msgtype, from, stamp, id,
+ body, state);
}
else if (state != -1)
{
@@ -268,6 +268,42 @@ im_factory_message_cb (
return TRUE;
}
+/* Signals incoming delivery receipts. http://xmpp.org/extensions/xep-0184.html
+ */
+static gboolean
+im_factory_receipt_cb (
+ WockyPorter *porter,
+ WockyStanza *message,
+ gpointer user_data)
+{
+ GabbleImFactory *self = GABBLE_IM_FACTORY (user_data);
+ WockyNode *received;
+ const gchar *from, *received_id;
+ GabbleIMChannel *channel;
+
+ received = wocky_node_get_child_ns (wocky_stanza_get_top_node (message),
+ "received", NS_RECEIPTS);
+ g_return_val_if_fail (received != NULL, FALSE);
+
+ received_id = wocky_node_get_attribute (received, "id");
+ if (received_id == NULL)
+ {
+ STANZA_DEBUG (message, "but *what* did you receive?!");
+ return TRUE;
+ }
+
+ from = wocky_stanza_get_from (message);
+ channel = get_channel_for_incoming_message (self, from, FALSE);
+ if (channel == NULL)
+ {
+ DEBUG ("no existing channel with '%s'; ignoring receipt", from);
+ return TRUE;
+ }
+
+ gabble_im_channel_receive_receipt (channel, received_id);
+ return TRUE;
+}
+
/**
* im_channel_closed_cb:
*
@@ -281,35 +317,39 @@ im_channel_closed_cb (GabbleIMChannel *chan, gpointer user_data)
{
GabbleImFactory *self = GABBLE_IM_FACTORY (user_data);
GabbleImFactoryPrivate *priv = self->priv;
- TpHandle contact_handle;
- gboolean really_destroyed;
+ TpBaseChannel *base = TP_BASE_CHANNEL (chan);
+ TpHandle contact_handle = tp_base_channel_get_target_handle (base);
DEBUG ("%p, channel %p", self, chan);
- tp_channel_manager_emit_channel_closed_for_object (self,
- (TpExportableChannel *) chan);
+ if (tp_base_channel_is_registered (base))
+ {
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ (TpExportableChannel *) chan);
+ }
if (priv->channels != NULL)
{
- g_object_get (chan,
- "handle", &contact_handle,
- "channel-destroyed", &really_destroyed,
- NULL);
-
- if (really_destroyed)
+ if (tp_base_channel_is_destroyed (base))
{
DEBUG ("removing channel with handle %u", contact_handle);
g_hash_table_remove (priv->channels,
GUINT_TO_POINTER (contact_handle));
}
- else
+ else if (tp_base_channel_is_respawning (base))
{
-
DEBUG ("reopening channel with handle %u due to pending messages",
contact_handle);
tp_channel_manager_emit_new_channel (self,
(TpExportableChannel *) chan, NULL);
}
+ else
+ {
+ /* this basically means tp_base_channel_disappear() must
+ * have been called; this doesn't have any meaning in this
+ * channel manager. */
+ g_assert_not_reached ();
+ }
}
}
@@ -339,7 +379,7 @@ new_im_channel (GabbleImFactory *fac,
g_return_val_if_fail (handle != 0, NULL);
if (request_token != NULL)
- initiator = conn->self_handle;
+ initiator = tp_base_connection_get_self_handle (conn);
else
initiator = handle;
@@ -431,6 +471,10 @@ gabble_im_factory_close_all (GabbleImFactory *self)
wocky_porter_unregister_handler (porter, self->priv->message_cb_id);
self->priv->message_cb_id = 0;
+
+ wocky_porter_unregister_handler (porter, self->priv->delivery_report_cb_id);
+ self->priv->delivery_report_cb_id = 0;
+
g_object_unref (porter);
}
}
@@ -517,6 +561,12 @@ porter_available_cb (
WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
WOCKY_PORTER_HANDLER_PRIORITY_MIN, im_factory_message_cb, self,
NULL);
+ self->priv->delivery_report_cb_id = wocky_porter_register_handler_from_anyone (porter,
+ WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
+ WOCKY_PORTER_HANDLER_PRIORITY_MIN, im_factory_receipt_cb, self,
+ '(',
+ "received", ':', NS_RECEIPTS,
+ ')', NULL);
g_object_get (conn, "stream-server", &stream_server, NULL);
@@ -704,7 +754,7 @@ gabble_im_factory_requestotron (GabbleImFactory *self,
if (require_new)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Already chatting with contact #%u in another channel", handle);
goto error;
}
diff --git a/src/jingle-content.c b/src/jingle-content.c
deleted file mode 100644
index 4989a3280..000000000
--- a/src/jingle-content.c
+++ /dev/null
@@ -1,1409 +0,0 @@
-/*
- * gabble-jingle-content.c - Source for GabbleJingleContent
- * Copyright (C) 2008 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 "config.h"
-#include "jingle-content.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "connection.h"
-#include "debug.h"
-#include "jingle-factory.h"
-#include "jingle-session.h"
-#include "jingle-transport-iface.h"
-#include "jingle-transport-google.h"
-#include "jingle-media-rtp.h"
-#include "namespaces.h"
-#include "gabble-signals-marshal.h"
-
-/* signal enum */
-enum
-{
- READY,
- NEW_CANDIDATES,
- REMOVED,
- NEW_SHARE_CHANNEL,
- COMPLETED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_SESSION = 1,
- PROP_CONTENT_NS,
- PROP_TRANSPORT_NS,
- PROP_NAME,
- PROP_SENDERS,
- PROP_STATE,
- PROP_DISPOSITION,
- PROP_LOCALLY_CREATED,
- LAST_PROPERTY
-};
-
-struct _GabbleJingleContentPrivate
-{
- gchar *name;
- gchar *creator;
- gboolean created_by_us;
- JingleContentState state;
- JingleContentSenders senders;
-
- gchar *content_ns;
- gchar *transport_ns;
- gchar *disposition;
-
- GabbleJingleTransportIface *transport;
-
- /* Whether we've got the codecs (intersection) ready. */
- gboolean media_ready;
-
- /* Whether we have at least one local candidate. */
- gboolean have_local_candidates;
-
- guint gtalk4_event_id;
- guint last_share_channel_component_id;
-
- gboolean dispose_has_run;
-};
-
-#define DEFAULT_CONTENT_TIMEOUT 60000
-
-/* lookup tables */
-
-G_DEFINE_TYPE(GabbleJingleContent, gabble_jingle_content, G_TYPE_OBJECT);
-
-static void new_transport_candidates_cb (GabbleJingleTransportIface *trans,
- GList *candidates, GabbleJingleContent *content);
-static void _maybe_ready (GabbleJingleContent *self);
-static void transport_created (GabbleJingleContent *c);
-
-static void
-gabble_jingle_content_init (GabbleJingleContent *obj)
-{
- GabbleJingleContentPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_JINGLE_CONTENT,
- GabbleJingleContentPrivate);
- obj->priv = priv;
-
- DEBUG ("%p", obj);
-
- priv->state = JINGLE_CONTENT_STATE_EMPTY;
- priv->created_by_us = TRUE;
- priv->media_ready = FALSE;
- priv->have_local_candidates = FALSE;
- priv->gtalk4_event_id = 0;
- priv->dispose_has_run = FALSE;
-
- obj->session = NULL;
-}
-
-static void
-gabble_jingle_content_dispose (GObject *object)
-{
- GabbleJingleContent *content = GABBLE_JINGLE_CONTENT (object);
- GabbleJingleContentPrivate *priv = content->priv;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("%p", object);
- priv->dispose_has_run = TRUE;
-
- if (priv->gtalk4_event_id != 0)
- {
- g_source_remove (priv->gtalk4_event_id);
- priv->gtalk4_event_id = 0;
- }
-
- g_free (priv->name);
- priv->name = NULL;
-
- g_free (priv->creator);
- priv->creator = NULL;
-
- g_free (priv->content_ns);
- priv->content_ns = NULL;
-
- g_free (priv->transport_ns);
- priv->transport_ns = NULL;
-
- g_free (priv->disposition);
- priv->disposition = NULL;
-
- if (G_OBJECT_CLASS (gabble_jingle_content_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_jingle_content_parent_class)->dispose (object);
-}
-
-static void
-gabble_jingle_content_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleContent *self = GABBLE_JINGLE_CONTENT (object);
- GabbleJingleContentPrivate *priv = self->priv;
-
- switch (property_id) {
- case PROP_SESSION:
- g_value_set_object (value, self->session);
- break;
- case PROP_NAME:
- g_value_set_string (value, priv->name);
- break;
- case PROP_SENDERS:
- g_value_set_uint (value, priv->senders);
- break;
- case PROP_STATE:
- g_value_set_uint (value, priv->state);
- break;
- case PROP_CONTENT_NS:
- g_value_set_string (value, priv->content_ns);
- break;
- case PROP_TRANSPORT_NS:
- g_value_set_string (value, priv->transport_ns);
- break;
- case PROP_DISPOSITION:
- g_value_set_string (value, priv->disposition);
- break;
- case PROP_LOCALLY_CREATED:
- g_value_set_boolean (value, priv->created_by_us);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_jingle_content_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleContent *self = GABBLE_JINGLE_CONTENT (object);
- GabbleJingleContentPrivate *priv = self->priv;
-
- switch (property_id) {
- case PROP_SESSION:
- self->session = g_value_get_object (value);
- break;
- case PROP_CONTENT_NS:
- g_free (priv->content_ns);
- priv->content_ns = g_value_dup_string (value);
- break;
- case PROP_TRANSPORT_NS:
- g_free (priv->transport_ns);
- priv->transport_ns = g_value_dup_string (value);
-
- /* We can't switch transports. */
- g_assert (priv->transport == NULL);
-
- if (priv->transport_ns != NULL)
- {
- GType transport_type = gabble_jingle_factory_lookup_transport (
- gabble_jingle_session_get_factory (self->session),
- priv->transport_ns);
-
- g_assert (transport_type != 0);
-
- priv->transport = gabble_jingle_transport_iface_new (transport_type,
- self, priv->transport_ns);
-
- g_signal_connect (priv->transport, "new-candidates",
- (GCallback) new_transport_candidates_cb, self);
-
- transport_created (self);
- }
- break;
- case PROP_NAME:
- /* can't rename */
- g_assert (priv->name == NULL);
-
- priv->name = g_value_dup_string (value);
- break;
- case PROP_SENDERS:
- priv->senders = g_value_get_uint (value);
- break;
- case PROP_STATE:
- priv->state = g_value_get_uint (value);
- break;
- case PROP_DISPOSITION:
- g_assert (priv->disposition == NULL);
- priv->disposition = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static JingleContentSenders
-get_default_senders_real (GabbleJingleContent *c)
-{
- return JINGLE_CONTENT_SENDERS_BOTH;
-}
-
-
-static void
-gabble_jingle_content_class_init (GabbleJingleContentClass *cls)
-{
- GParamSpec *param_spec;
- GObjectClass *object_class = G_OBJECT_CLASS (cls);
-
- g_type_class_add_private (cls, sizeof (GabbleJingleContentPrivate));
-
- object_class->get_property = gabble_jingle_content_get_property;
- object_class->set_property = gabble_jingle_content_set_property;
- object_class->dispose = gabble_jingle_content_dispose;
-
- cls->get_default_senders = get_default_senders_real;
-
- /* property definitions */
- param_spec = g_param_spec_object ("session", "GabbleJingleSession object",
- "Jingle session object that owns this content.",
- GABBLE_TYPE_JINGLE_SESSION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_SESSION, param_spec);
-
- param_spec = g_param_spec_string ("name", "Content name",
- "A unique content name in the session.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_NAME, param_spec);
-
- param_spec = g_param_spec_string ("content-ns", "Content namespace",
- "Namespace identifying the content type.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONTENT_NS, param_spec);
-
- param_spec = g_param_spec_string ("transport-ns", "Transport namespace",
- "Namespace identifying the transport type.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_TRANSPORT_NS, param_spec);
-
- param_spec = g_param_spec_uint ("senders", "Stream senders",
- "Valid senders for the stream.",
- 0, G_MAXUINT32, JINGLE_CONTENT_SENDERS_NONE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_SENDERS, param_spec);
-
- param_spec = g_param_spec_uint ("state", "Content state",
- "The current state that the content is in.",
- 0, G_MAXUINT32, JINGLE_CONTENT_STATE_EMPTY,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- param_spec = g_param_spec_string ("disposition", "Content disposition",
- "Distinguishes between 'session' and other contents.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_DISPOSITION, param_spec);
-
- param_spec = g_param_spec_boolean ("locally-created", "Locally created",
- "True if the content was created by the local client.",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_LOCALLY_CREATED, param_spec);
-
- /* signal definitions */
-
- signals[READY] = g_signal_new ("ready",
- G_OBJECT_CLASS_TYPE (cls),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[NEW_CANDIDATES] = g_signal_new (
- "new-candidates",
- G_TYPE_FROM_CLASS (cls),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
-
- signals[NEW_SHARE_CHANNEL] = g_signal_new (
- "new-share-channel",
- G_TYPE_FROM_CLASS (cls),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- gabble_marshal_VOID__STRING_UINT,
- G_TYPE_NONE,
- 2,
- G_TYPE_STRING, G_TYPE_UINT);
-
- signals[COMPLETED] = g_signal_new (
- "completed",
- G_TYPE_FROM_CLASS (cls),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- /* This signal serves as notification that the GabbleJingleContent is now
- * meaningless; everything holding a reference should drop it after receiving
- * 'removed'.
- */
- signals[REMOVED] = g_signal_new ("removed",
- G_OBJECT_CLASS_TYPE (cls),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-
-static JingleContentSenders
-get_default_senders (GabbleJingleContent *c)
-{
- JingleContentSenders (*virtual_method)(GabbleJingleContent *) = \
- GABBLE_JINGLE_CONTENT_GET_CLASS (c)->get_default_senders;
-
- g_assert (virtual_method != NULL);
- return virtual_method (c);
-}
-
-
-static JingleContentSenders
-parse_senders (const gchar *txt)
-{
- if (txt == NULL)
- return JINGLE_CONTENT_SENDERS_NONE;
-
- if (!wocky_strdiff (txt, "initiator"))
- return JINGLE_CONTENT_SENDERS_INITIATOR;
- else if (!wocky_strdiff (txt, "responder"))
- return JINGLE_CONTENT_SENDERS_RESPONDER;
- else if (!wocky_strdiff (txt, "both"))
- return JINGLE_CONTENT_SENDERS_BOTH;
-
- return JINGLE_CONTENT_SENDERS_NONE;
-}
-
-static const gchar *
-produce_senders (JingleContentSenders senders)
-{
- switch (senders) {
- case JINGLE_CONTENT_SENDERS_INITIATOR:
- return "initiator";
- case JINGLE_CONTENT_SENDERS_RESPONDER:
- return "responder";
- case JINGLE_CONTENT_SENDERS_BOTH:
- return "both";
- default:
- DEBUG ("invalid content senders %u", senders);
- g_assert_not_reached ();
- }
-
- /* to make gcc not complain */
- return NULL;
-}
-
-
-#define SET_BAD_REQ(txt) \
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, txt)
-
-static void
-new_transport_candidates_cb (GabbleJingleTransportIface *trans,
- GList *candidates, GabbleJingleContent *content)
-{
- /* just pass the signal on */
- g_signal_emit (content, signals[NEW_CANDIDATES], 0, candidates);
-}
-
-static void
-transport_created (GabbleJingleContent *c)
-{
- void (*virtual_method)(GabbleJingleContent *, GabbleJingleTransportIface *) = \
- GABBLE_JINGLE_CONTENT_GET_CLASS (c)->transport_created;
-
- if (virtual_method != NULL)
- virtual_method (c, c->priv->transport);
-}
-
-
-static void
-parse_description (GabbleJingleContent *c, WockyNode *desc_node,
- GError **error)
-{
- void (*virtual_method)(GabbleJingleContent *, WockyNode *,
- GError **) = GABBLE_JINGLE_CONTENT_GET_CLASS (c)->parse_description;
-
- g_assert (virtual_method != NULL);
- virtual_method (c, desc_node, error);
-}
-
-static gboolean
-send_gtalk4_transport_accept (gpointer user_data)
-{
- GabbleJingleContent *c = GABBLE_JINGLE_CONTENT (user_data);
- GabbleJingleContentPrivate *priv = c->priv;
- WockyNode *sess_node, *tnode;
- WockyStanza *msg = gabble_jingle_session_new_message (c->session,
- JINGLE_ACTION_TRANSPORT_ACCEPT, &sess_node);
-
- DEBUG ("Sending Gtalk4 'transport-accept' message to peer");
- tnode = wocky_node_add_child_with_content (sess_node, "transport", NULL);
- tnode->ns = g_quark_from_string (priv->transport_ns);
-
- gabble_jingle_session_send (c->session, msg);
-
- return FALSE;
-}
-
-void
-gabble_jingle_content_parse_add (GabbleJingleContent *c,
- WockyNode *content_node, gboolean google_mode, GError **error)
-{
- GabbleJingleContentPrivate *priv = c->priv;
- const gchar *name, *creator, *senders, *disposition;
- WockyNode *trans_node, *desc_node;
- GType transport_type = 0;
- GabbleJingleTransportIface *trans = NULL;
- JingleDialect dialect = gabble_jingle_session_get_dialect (c->session);
-
- priv->created_by_us = FALSE;
-
- desc_node = wocky_node_get_child (content_node, "description");
- trans_node = wocky_node_get_child (content_node, "transport");
- creator = wocky_node_get_attribute (content_node, "creator");
- name = wocky_node_get_attribute (content_node, "name");
- senders = wocky_node_get_attribute (content_node, "senders");
-
- g_assert (priv->transport_ns == NULL);
-
- if (google_mode)
- {
- if (creator == NULL)
- creator = "initiator";
-
- /* the google protocols don't give the contents names, so put in a dummy
- * value if none was set by the session*/
- if (priv->name == NULL)
- name = priv->name = g_strdup ("gtalk");
- else
- name = priv->name;
-
- if (trans_node == NULL)
- {
- /* gtalk lj0.3 assumes google-p2p transport */
- DEBUG ("detected GTalk3 dialect");
-
- dialect = JINGLE_DIALECT_GTALK3;
- g_object_set (c->session, "dialect", JINGLE_DIALECT_GTALK3, NULL);
- transport_type = gabble_jingle_factory_lookup_transport (
- gabble_jingle_session_get_factory (c->session),
- "");
-
- /* in practice we do support gtalk-p2p, so this can't happen */
- if (G_UNLIKELY (transport_type == 0))
- {
- SET_BAD_REQ ("gtalk-p2p transport unsupported");
- return;
- }
-
- priv->transport_ns = g_strdup ("");
- }
- }
- else
- {
- if (creator == NULL &&
- gabble_jingle_session_peer_has_cap (c->session,
- QUIRK_GOOGLE_WEBMAIL_CLIENT))
- {
- if (gabble_jingle_content_creator_is_initiator (c))
- creator = "initiator";
- else
- creator = "responder";
-
- DEBUG ("Working around GMail omitting creator=''; assuming '%s'",
- creator);
- }
-
- if ((trans_node == NULL) || (creator == NULL) || (name == NULL))
- {
- SET_BAD_REQ ("missing required content attributes or elements");
- return;
- }
-
- /* In proper protocols the name comes from the stanza */
- g_assert (priv->name == NULL);
- priv->name = g_strdup (name);
- }
-
- /* if we didn't set it to google-p2p implicitly already, detect it */
- if (transport_type == 0)
- {
- const gchar *ns = wocky_node_get_ns (trans_node);
-
- transport_type = gabble_jingle_factory_lookup_transport (
- gabble_jingle_session_get_factory (c->session), ns);
-
- if (transport_type == 0)
- {
- SET_BAD_REQ ("unsupported content transport");
- return;
- }
-
- priv->transport_ns = g_strdup (ns);
- }
-
- if (senders == NULL)
- priv->senders = get_default_senders (c);
- else
- priv->senders = parse_senders (senders);
-
- if (priv->senders == JINGLE_CONTENT_SENDERS_NONE)
- {
- SET_BAD_REQ ("invalid content senders");
- return;
- }
-
- parse_description (c, desc_node, error);
- if (*error != NULL)
- return;
-
- disposition = wocky_node_get_attribute (content_node, "disposition");
- if (disposition == NULL)
- disposition = "session";
-
- if (wocky_strdiff (disposition, priv->disposition))
- {
- g_free (priv->disposition);
- priv->disposition = g_strdup (disposition);
- }
-
- DEBUG ("content creating new transport type %s", g_type_name (transport_type));
-
- trans = gabble_jingle_transport_iface_new (transport_type,
- c, priv->transport_ns);
-
- g_signal_connect (trans, "new-candidates",
- (GCallback) new_transport_candidates_cb, c);
-
- /* Depending on transport, there may be initial candidates specified here */
- if (trans_node != NULL)
- {
- gabble_jingle_transport_iface_parse_candidates (trans, trans_node, error);
- if (*error)
- {
- g_object_unref (trans);
- return;
- }
- }
-
- g_assert (priv->transport == NULL);
- priv->transport = trans;
- transport_created (c);
-
- g_assert (priv->creator == NULL);
- priv->creator = g_strdup (creator);
-
- priv->state = JINGLE_CONTENT_STATE_NEW;
-
- /* GTalk4 seems to require "transport-accept" for acknowledging
- * the transport type. wjt confirms that this is apparently necessary for
- * incoming calls to work.
- */
- if (dialect == JINGLE_DIALECT_GTALK4)
- priv->gtalk4_event_id = g_idle_add (send_gtalk4_transport_accept, c);
-
- return;
-}
-
-static guint
-new_share_channel (GabbleJingleContent *c, const gchar *name)
-{
- GabbleJingleContentPrivate *priv = c->priv;
- GabbleJingleTransportGoogle *gtrans = NULL;
-
- if (priv->transport &&
- GABBLE_IS_JINGLE_TRANSPORT_GOOGLE (priv->transport))
- {
- guint id = priv->last_share_channel_component_id + 1;
-
- gtrans = GABBLE_JINGLE_TRANSPORT_GOOGLE (priv->transport);
-
- if (!jingle_transport_google_set_component_name (gtrans, name, id))
- return 0;
-
- priv->last_share_channel_component_id++;
-
- DEBUG ("New Share channel '%s' with id : %d", name, id);
-
- g_signal_emit (c, signals[NEW_SHARE_CHANNEL], 0, name, id);
-
- return priv->last_share_channel_component_id;
- }
- return 0;
-}
-
-guint
-gabble_jingle_content_create_share_channel (GabbleJingleContent *self,
- const gchar *name)
-{
- GabbleJingleContentPrivate *priv = self->priv;
- WockyNode *sess_node, *channel_node;
- WockyStanza *msg = NULL;
-
- /* Send the info action before creating the channel, in case candidates need
- to be sent on the signal emit. It doesn't matter if the channel already
- exists anyways... */
- msg = gabble_jingle_session_new_message (self->session,
- JINGLE_ACTION_INFO, &sess_node);
-
- DEBUG ("Sending 'info' message to peer : channel %s", name);
- channel_node = wocky_node_add_child_with_content (sess_node, "channel", NULL);
- channel_node->ns = g_quark_from_string (priv->content_ns);
- wocky_node_set_attribute (channel_node, "name", name);
-
- gabble_jingle_session_send (self->session, msg);
-
- return new_share_channel (self, name);
-}
-
-void
-gabble_jingle_content_send_complete (GabbleJingleContent *self)
-{
- GabbleJingleContentPrivate *priv = self->priv;
- WockyNode *sess_node, *complete_node;
- WockyStanza *msg = NULL;
-
- msg = gabble_jingle_session_new_message (self->session,
- JINGLE_ACTION_INFO, &sess_node);
-
- DEBUG ("Sending 'info' message to peer : complete");
- complete_node = wocky_node_add_child_with_content (sess_node, "complete", NULL);
- complete_node->ns = g_quark_from_string (priv->content_ns);
-
- gabble_jingle_session_send (self->session, msg);
-
-}
-
-void
-gabble_jingle_content_parse_info (GabbleJingleContent *c,
- WockyNode *content_node, GError **error)
-{
- WockyNode *channel_node;
- WockyNode *complete_node;
-
- channel_node = wocky_node_get_child (content_node, "channel");
- complete_node = wocky_node_get_child (content_node, "complete");
-
- DEBUG ("parsing info message : %p - %p", channel_node, complete_node);
- if (channel_node)
- {
- const gchar *name;
- name = wocky_node_get_attribute (channel_node, "name");
- if (name != NULL)
- new_share_channel (c, name);
- }
- else if (complete_node)
- {
- g_signal_emit (c, signals[COMPLETED], 0);
- }
-
-}
-
-void
-gabble_jingle_content_parse_accept (GabbleJingleContent *c,
- WockyNode *content_node, gboolean google_mode, GError **error)
-{
- GabbleJingleContentPrivate *priv = c->priv;
- const gchar *senders;
- WockyNode *trans_node, *desc_node;
- JingleDialect dialect = gabble_jingle_session_get_dialect (c->session);
- JingleContentSenders newsenders;
-
- desc_node = wocky_node_get_child (content_node, "description");
- trans_node = wocky_node_get_child (content_node, "transport");
- senders = wocky_node_get_attribute (content_node, "senders");
-
- if (GABBLE_IS_JINGLE_MEDIA_RTP (c) &&
- JINGLE_IS_GOOGLE_DIALECT (dialect) && trans_node == NULL)
- {
- DEBUG ("no transport node, assuming GTalk3 dialect");
- /* gtalk lj0.3 assumes google-p2p transport */
- g_object_set (c->session, "dialect", JINGLE_DIALECT_GTALK3, NULL);
- }
-
- if (senders == NULL)
- newsenders = get_default_senders (c);
- else
- newsenders = parse_senders (senders);
-
- if (newsenders == JINGLE_CONTENT_SENDERS_NONE)
- {
- SET_BAD_REQ ("invalid content senders");
- return;
- }
-
- if (newsenders != priv->senders)
- {
- DEBUG ("changing senders from %s to %s", produce_senders (priv->senders),
- produce_senders (newsenders));
- priv->senders = newsenders;
- g_object_notify ((GObject *) c, "senders");
- }
-
- parse_description (c, desc_node, error);
- if (*error != NULL)
- return;
-
- priv->state = JINGLE_CONTENT_STATE_ACKNOWLEDGED;
- g_object_notify ((GObject *) c, "state");
-
- if (trans_node != NULL)
- {
- gabble_jingle_transport_iface_parse_candidates (priv->transport,
- trans_node, NULL);
- }
-}
-
-void
-gabble_jingle_content_parse_description_info (GabbleJingleContent *c,
- WockyNode *content_node, GError **error)
-{
- GabbleJingleContentPrivate *priv = c->priv;
- WockyNode *desc_node;
- desc_node = wocky_node_get_child (content_node, "description");
- if (desc_node == NULL)
- {
- SET_BAD_REQ ("invalid description-info action");
- return;
- }
-
- if (priv->created_by_us && priv->state < JINGLE_CONTENT_STATE_ACKNOWLEDGED)
- {
- /* The stream was created by us and the other side didn't acknowledge it
- * yet, thus we don't have their codec information, thus the
- * description-info isn't meaningful and can be ignored */
- DEBUG ("Ignoring description-info as we didn't receive the codecs yet");
- return;
- }
-
- parse_description (c, desc_node, error);
-}
-
-
-void
-gabble_jingle_content_produce_node (GabbleJingleContent *c,
- WockyNode *parent,
- gboolean include_description,
- gboolean include_transport,
- WockyNode **trans_node_out)
-{
- GabbleJingleContentPrivate *priv = c->priv;
- WockyNode *content_node, *trans_node;
- JingleDialect dialect = gabble_jingle_session_get_dialect (c->session);
- void (*produce_desc)(GabbleJingleContent *, WockyNode *) =
- GABBLE_JINGLE_CONTENT_GET_CLASS (c)->produce_description;
-
- if ((dialect == JINGLE_DIALECT_GTALK3) ||
- (dialect == JINGLE_DIALECT_GTALK4))
- {
- content_node = parent;
- }
- else
- {
- content_node = wocky_node_add_child_with_content (parent, "content", NULL);
- wocky_node_set_attributes (content_node,
- "name", priv->name,
- "senders", produce_senders (priv->senders),
- NULL);
-
- if (gabble_jingle_content_creator_is_initiator (c))
- wocky_node_set_attribute (content_node, "creator", "initiator");
- else
- wocky_node_set_attribute (content_node, "creator", "responder");
- }
-
- if (include_description)
- produce_desc (c, content_node);
-
- if (include_transport)
- {
- if (dialect == JINGLE_DIALECT_GTALK3)
- {
- /* GTalk 03 doesn't use a transport, but assumes gtalk-p2p */
- trans_node = parent;
- }
- else
- {
- trans_node = wocky_node_add_child_with_content (content_node, "transport", NULL);
- trans_node->ns = g_quark_from_string (priv->transport_ns);
- }
-
- if (trans_node_out != NULL)
- *trans_node_out = trans_node;
- }
-}
-
-void
-gabble_jingle_content_update_senders (GabbleJingleContent *c,
- WockyNode *content_node, GError **error)
-{
- GabbleJingleContentPrivate *priv = c->priv;
- JingleContentSenders senders;
-
- senders = parse_senders (wocky_node_get_attribute (content_node, "senders"));
-
- if (senders == JINGLE_CONTENT_SENDERS_NONE)
- {
- SET_BAD_REQ ("invalid content senders in stream");
- return;
- }
-
- priv->senders = senders;
- g_object_notify ((GObject *) c, "senders");
-}
-
-void
-gabble_jingle_content_parse_transport_info (GabbleJingleContent *self,
- WockyNode *trans_node, GError **error)
-{
- GabbleJingleContentPrivate *priv = self->priv;
-
- gabble_jingle_transport_iface_parse_candidates (priv->transport, trans_node, error);
-}
-
-/* Takes in a list of slice-allocated JingleCandidate structs */
-void
-gabble_jingle_content_add_candidates (GabbleJingleContent *self, GList *li)
-{
- GabbleJingleContentPrivate *priv = self->priv;
-
- DEBUG ("called content: %s created_by_us: %d", priv->name,
- priv->created_by_us);
-
- if (li == NULL)
- return;
-
- gabble_jingle_transport_iface_new_local_candidates (priv->transport, li);
-
- if (!priv->have_local_candidates)
- {
- priv->have_local_candidates = TRUE;
- /* Maybe we were waiting for at least one candidate? */
- _maybe_ready (self);
- }
-
- /* If the content exists on the wire, let the transport send this candidate
- * if it wants to.
- */
- if (priv->state > JINGLE_CONTENT_STATE_EMPTY)
- gabble_jingle_transport_iface_send_candidates (priv->transport, FALSE);
-}
-
-/* Returns whether the content is ready to be signalled (initiated, for local
- * streams, or acknowledged, for remote streams. */
-gboolean
-gabble_jingle_content_is_ready (GabbleJingleContent *self)
-{
- GabbleJingleContentPrivate *priv = self->priv;
-
- if (priv->created_by_us)
- {
- /* If it's created by us, media ready, not signalled, and we have
- * at least one local candidate, it's ready to be added. */
- if (priv->media_ready && priv->state == JINGLE_CONTENT_STATE_EMPTY &&
- (!GABBLE_IS_JINGLE_MEDIA_RTP (self) || priv->have_local_candidates))
- return TRUE;
- }
- else
- {
- /* If it's created by peer, media and transports ready,
- * and not acknowledged yet, it's ready for acceptance. */
- if (priv->media_ready && priv->state == JINGLE_CONTENT_STATE_NEW &&
- (!GABBLE_IS_JINGLE_MEDIA_RTP (self) ||
- gabble_jingle_transport_iface_can_accept (priv->transport)))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-send_content_add_or_accept (GabbleJingleContent *self)
-{
- GabbleJingleContentPrivate *priv = self->priv;
- WockyStanza *msg;
- WockyNode *sess_node, *transport_node;
- JingleAction action;
- JingleContentState new_state = JINGLE_CONTENT_STATE_EMPTY;
-
- g_assert (gabble_jingle_content_is_ready (self));
-
- if (priv->created_by_us)
- {
- /* TODO: set a timer for acknowledgement */
- action = JINGLE_ACTION_CONTENT_ADD;
- new_state = JINGLE_CONTENT_STATE_SENT;
- }
- else
- {
- action = JINGLE_ACTION_CONTENT_ACCEPT;
- new_state = JINGLE_CONTENT_STATE_ACKNOWLEDGED;
- }
-
- msg = gabble_jingle_session_new_message (self->session,
- action, &sess_node);
- gabble_jingle_content_produce_node (self, sess_node, TRUE, TRUE,
- &transport_node);
- gabble_jingle_transport_iface_inject_candidates (priv->transport,
- transport_node);
- gabble_jingle_session_send (self->session, msg);
-
- priv->state = new_state;
- g_object_notify (G_OBJECT (self), "state");
-}
-
-static void
-_maybe_ready (GabbleJingleContent *self)
-{
- GabbleJingleContentPrivate *priv = self->priv;
- JingleState state;
-
- if (!gabble_jingle_content_is_ready (self))
- return;
-
- /* If content disposition is session and session
- * is not yet acknowledged/active, we signall
- * the readiness to the session and let it take
- * care of it. Otherwise, we can deal with it
- * ourselves. */
-
- g_object_get (self->session, "state", &state, NULL);
-
- if (!wocky_strdiff (priv->disposition, "session") &&
- (state < JINGLE_STATE_PENDING_ACCEPT_SENT))
- {
- /* Notify the session that we're ready for
- * session-initiate/session-accept */
- g_signal_emit (self, signals[READY], 0);
- }
- else
- {
- if (state >= JINGLE_STATE_PENDING_INITIATE_SENT)
- {
- send_content_add_or_accept (self);
-
- /* if neccessary, transmit the candidates */
- gabble_jingle_transport_iface_send_candidates (priv->transport,
- FALSE);
- }
- else
- {
- /* non session-disposition content ready without session
- * being initiated at all? */
- DEBUG ("session not initiated yet, ignoring non-session ready content");
- return;
- }
- }
-}
-
-void
-gabble_jingle_content_maybe_send_description (GabbleJingleContent *self)
-{
- GabbleJingleContentPrivate *priv = self->priv;
-
- /* If we didn't send the content yet there is no reason to send a
- * description-info to update it */
- if (priv->state < JINGLE_CONTENT_STATE_SENT)
- return;
-
- if (gabble_jingle_session_defines_action (self->session,
- JINGLE_ACTION_DESCRIPTION_INFO))
- {
- WockyNode *sess_node;
- WockyStanza *msg = gabble_jingle_session_new_message (self->session,
- JINGLE_ACTION_DESCRIPTION_INFO, &sess_node);
-
- gabble_jingle_content_produce_node (self, sess_node, TRUE, FALSE, NULL);
- gabble_jingle_session_send (self->session, msg);
- }
- else
- {
- DEBUG ("not sending description-info, speaking an old dialect");
- }
-}
-
-
-/* Used when session-initiate is sent (so all initial contents transmit their
- * candidates), and when we detect gtalk3 after we've transmitted some
- * candidates. */
-void
-gabble_jingle_content_retransmit_candidates (GabbleJingleContent *self,
- gboolean all)
-{
- gabble_jingle_transport_iface_send_candidates (self->priv->transport, all);
-}
-
-void
-gabble_jingle_content_inject_candidates (GabbleJingleContent *self,
- WockyNode *transport_node)
-{
- gabble_jingle_transport_iface_inject_candidates (self->priv->transport,
- transport_node);
-}
-
-
-/* Called by a subclass when the media is ready (e.g. we got local codecs) */
-void
-_gabble_jingle_content_set_media_ready (GabbleJingleContent *self)
-{
- GabbleJingleContentPrivate *priv = self->priv;
-
- DEBUG ("media ready on content: %s created_by_us: %d", priv->name,
- priv->created_by_us);
-
- priv->media_ready = TRUE;
-
- _maybe_ready (self);
-}
-
-void
-gabble_jingle_content_set_transport_state (GabbleJingleContent *self,
- JingleTransportState state)
-{
- GabbleJingleContentPrivate *priv = self->priv;
-
- g_object_set (priv->transport, "state", state, NULL);
-
- _maybe_ready (self);
-}
-
-GList *
-gabble_jingle_content_get_remote_candidates (GabbleJingleContent *c)
-{
- GabbleJingleContentPrivate *priv = c->priv;
-
- return gabble_jingle_transport_iface_get_remote_candidates (priv->transport);
-}
-
-GList *
-gabble_jingle_content_get_local_candidates (GabbleJingleContent *c)
-{
- GabbleJingleContentPrivate *priv = c->priv;
-
- return gabble_jingle_transport_iface_get_local_candidates (priv->transport);
-}
-
-gboolean
-gabble_jingle_content_get_credentials (GabbleJingleContent *c,
- gchar **ufrag, gchar **pwd)
-{
- GabbleJingleContentPrivate *priv = c->priv;
-
- return jingle_transport_get_credentials (priv->transport, ufrag, pwd);
-}
-
-gboolean
-gabble_jingle_content_change_direction (GabbleJingleContent *c,
- JingleContentSenders senders)
-{
- GabbleJingleContentPrivate *priv = c->priv;
- WockyStanza *msg;
- WockyNode *sess_node;
- JingleDialect dialect = gabble_jingle_session_get_dialect (c->session);
-
- if (senders == priv->senders)
- return TRUE;
-
- priv->senders = senders;
- g_object_notify (G_OBJECT (c), "senders");
-
- if (JINGLE_IS_GOOGLE_DIALECT (dialect))
- {
- DEBUG ("ignoring direction change request for GTalk stream");
- return FALSE;
- }
-
- if (priv->state >= JINGLE_CONTENT_STATE_SENT)
- {
- msg = gabble_jingle_session_new_message (c->session,
- JINGLE_ACTION_CONTENT_MODIFY, &sess_node);
- gabble_jingle_content_produce_node (c, sess_node, FALSE, FALSE, NULL);
- gabble_jingle_session_send (c->session, msg);
- }
-
- /* FIXME: actually check whether remote end accepts our content-modify */
- return TRUE;
-}
-
-static void
-_on_remove_reply (
- GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GabbleJingleContent *c = GABBLE_JINGLE_CONTENT (user_data);
- GabbleJingleContentPrivate *priv = c->priv;
-
- g_assert (priv->state == JINGLE_CONTENT_STATE_REMOVING);
-
- DEBUG ("%p", c);
-
- /* Everything holding a reference to a content should drop it after receiving
- * 'removed'.
- */
- g_signal_emit (c, signals[REMOVED], 0);
- g_object_unref (c);
-}
-
-static void
-_content_remove (GabbleJingleContent *c,
- gboolean signal_peer,
- JingleReason reason)
-{
- GabbleJingleContentPrivate *priv = c->priv;
- WockyStanza *msg;
- WockyNode *sess_node;
-
- DEBUG ("called for %p (%s)", c, priv->name);
-
- /* If we were already signalled and removal is not a side-effect of
- * something else (sesssion termination, or removal by peer),
- * we have to signal removal to the peer. */
- if (signal_peer && (priv->state != JINGLE_CONTENT_STATE_EMPTY))
- {
- if (priv->state == JINGLE_CONTENT_STATE_REMOVING)
- {
- DEBUG ("ignoring request to remove content which is already being removed");
- return;
- }
-
- priv->state = JINGLE_CONTENT_STATE_REMOVING;
- g_object_notify ((GObject *) c, "state");
-
- msg = gabble_jingle_session_new_message (c->session,
- reason == JINGLE_REASON_UNKNOWN ?
- JINGLE_ACTION_CONTENT_REMOVE : JINGLE_ACTION_CONTENT_REJECT,
- &sess_node);
-
- if (reason != JINGLE_REASON_UNKNOWN)
- {
- WockyNode *reason_node = wocky_node_add_child_with_content (sess_node,
- "reason", NULL);
- wocky_node_add_child_with_content (reason_node,
- gabble_jingle_session_get_reason_name (reason), NULL);
- }
-
- gabble_jingle_content_produce_node (c, sess_node, FALSE, FALSE, NULL);
- wocky_porter_send_iq_async (gabble_jingle_session_get_porter (c->session),
- msg, NULL, _on_remove_reply, g_object_ref (c));
- g_object_unref (msg);
- }
- else
- {
- DEBUG ("signalling removed with %u refs", G_OBJECT (c)->ref_count);
- /* Everything holding a reference to a content should drop it after receiving
- * 'removed'.
- */
- g_signal_emit (c, signals[REMOVED], 0);
- }
-}
-
-void
-gabble_jingle_content_remove (GabbleJingleContent *c,
- gboolean signal_peer)
-{
- _content_remove (c, signal_peer, JINGLE_REASON_UNKNOWN);
-}
-
-void
-gabble_jingle_content_reject (GabbleJingleContent *c,
- JingleReason reason)
-{
- _content_remove (c, TRUE, reason);
-}
-
-gboolean
-gabble_jingle_content_is_created_by_us (GabbleJingleContent *c)
-{
- return c->priv->created_by_us;
-}
-
-gboolean
-gabble_jingle_content_creator_is_initiator (GabbleJingleContent *c)
-{
- gboolean session_created_by_us;
-
- g_object_get (c->session, "local-initiator", &session_created_by_us, NULL);
-
- return (c->priv->created_by_us == session_created_by_us);
-}
-
-const gchar *
-gabble_jingle_content_get_name (GabbleJingleContent *self)
-{
- return self->priv->name;
-}
-
-const gchar *
-gabble_jingle_content_get_ns (GabbleJingleContent *self)
-{
- return self->priv->content_ns;
-}
-
-const gchar *
-gabble_jingle_content_get_transport_ns (GabbleJingleContent *self)
-{
- return self->priv->transport_ns;
-}
-
-const gchar *
-gabble_jingle_content_get_disposition (GabbleJingleContent *self)
-{
- return self->priv->disposition;
-}
-
-JingleTransportType
-gabble_jingle_content_get_transport_type (GabbleJingleContent *c)
-{
- return gabble_jingle_transport_iface_get_transport_type (c->priv->transport);
-}
-
-static gboolean
-jingle_content_has_direction (GabbleJingleContent *self,
- gboolean sending)
-{
- GabbleJingleContentPrivate *priv = self->priv;
- gboolean initiated_by_us;
-
- g_object_get (self->session, "local-initiator",
- &initiated_by_us, NULL);
-
- switch (priv->senders)
- {
- case JINGLE_CONTENT_SENDERS_BOTH:
- return TRUE;
- case JINGLE_CONTENT_SENDERS_NONE:
- return FALSE;
- case JINGLE_CONTENT_SENDERS_INITIATOR:
- return sending ? initiated_by_us : !initiated_by_us;
- case JINGLE_CONTENT_SENDERS_RESPONDER:
- return sending ? !initiated_by_us : initiated_by_us;
- }
-
- return FALSE;
-}
-
-gboolean
-gabble_jingle_content_sending (GabbleJingleContent *self)
-{
- return jingle_content_has_direction (self, TRUE);
-}
-
-gboolean
-gabble_jingle_content_receiving (GabbleJingleContent *self)
-{
- return jingle_content_has_direction (self, FALSE);
-}
-
-void
-gabble_jingle_content_set_sending (GabbleJingleContent *self,
- gboolean send)
-{
- GabbleJingleContentPrivate *priv = self->priv;
- JingleContentSenders senders;
- gboolean initiated_by_us;
-
- if (send == gabble_jingle_content_sending (self))
- return;
-
- g_object_get (self->session, "local-initiator",
- &initiated_by_us, NULL);
-
- if (send)
- {
- if (priv->senders == JINGLE_CONTENT_SENDERS_NONE)
- senders = (initiated_by_us ? JINGLE_CONTENT_SENDERS_INITIATOR :
- JINGLE_CONTENT_SENDERS_RESPONDER);
- else
- senders = JINGLE_CONTENT_SENDERS_BOTH;
- }
- else
- {
- if (priv->senders == JINGLE_CONTENT_SENDERS_BOTH)
- senders = (initiated_by_us ? JINGLE_CONTENT_SENDERS_RESPONDER :
- JINGLE_CONTENT_SENDERS_INITIATOR);
- else
- senders = JINGLE_CONTENT_SENDERS_NONE;
- }
-
- if (senders == JINGLE_CONTENT_SENDERS_NONE)
- gabble_jingle_content_remove (self, TRUE);
- else
- gabble_jingle_content_change_direction (self, senders);
-}
-
-
-void
-gabble_jingle_content_request_receiving (GabbleJingleContent *self,
- gboolean receive)
-{
- GabbleJingleContentPrivate *priv = self->priv;
- JingleContentSenders senders;
- gboolean initiated_by_us;
-
- if (receive == gabble_jingle_content_receiving (self))
- return;
-
- g_object_get (self->session, "local-initiator",
- &initiated_by_us, NULL);
-
- if (receive)
- {
- if (priv->senders == JINGLE_CONTENT_SENDERS_NONE)
- senders = (initiated_by_us ? JINGLE_CONTENT_SENDERS_RESPONDER :
- JINGLE_CONTENT_SENDERS_INITIATOR);
- else
- senders = JINGLE_CONTENT_SENDERS_BOTH;
- }
- else
- {
- if (priv->senders == JINGLE_CONTENT_SENDERS_BOTH)
- senders = (initiated_by_us ? JINGLE_CONTENT_SENDERS_INITIATOR :
- JINGLE_CONTENT_SENDERS_RESPONDER);
- else
- senders = JINGLE_CONTENT_SENDERS_NONE;
- }
-
-
- if (senders == JINGLE_CONTENT_SENDERS_NONE)
- gabble_jingle_content_remove (self, TRUE);
- else
- gabble_jingle_content_change_direction (self, senders);
-}
diff --git a/src/jingle-content.h b/src/jingle-content.h
deleted file mode 100644
index 1c337efb5..000000000
--- a/src/jingle-content.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * jingle-content.h - Header for GabbleJingleContent
- * Copyright (C) 2008 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 __JINGLE_CONTENT_H__
-#define __JINGLE_CONTENT_H__
-
-#include <glib-object.h>
-
-#include "jingle-factory.h"
-#include "jingle-transport-iface.h"
-#include "jingle-types.h"
-
-G_BEGIN_DECLS
-
-typedef enum {
- JINGLE_MEDIA_TYPE_NONE = 0,
- JINGLE_MEDIA_TYPE_AUDIO,
- JINGLE_MEDIA_TYPE_VIDEO,
-} JingleMediaType;
-
-typedef enum {
- JINGLE_CONTENT_STATE_EMPTY = 0,
- JINGLE_CONTENT_STATE_NEW,
- JINGLE_CONTENT_STATE_SENT,
- JINGLE_CONTENT_STATE_ACKNOWLEDGED,
- JINGLE_CONTENT_STATE_REMOVING
-} JingleContentState;
-
-struct _JingleCandidate {
- JingleTransportProtocol protocol;
- JingleCandidateType type;
-
- gchar *id;
- gchar *address;
- int port;
- int component;
- int generation;
-
- int preference;
- gchar *username;
- gchar *password;
- int network;
-};
-
-typedef struct _GabbleJingleContentClass GabbleJingleContentClass;
-
-GType gabble_jingle_content_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_CONTENT \
- (gabble_jingle_content_get_type ())
-#define GABBLE_JINGLE_CONTENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_CONTENT, \
- GabbleJingleContent))
-#define GABBLE_JINGLE_CONTENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_CONTENT, \
- GabbleJingleContentClass))
-#define GABBLE_IS_JINGLE_CONTENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_CONTENT))
-#define GABBLE_IS_JINGLE_CONTENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_CONTENT))
-#define GABBLE_JINGLE_CONTENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_CONTENT, \
- GabbleJingleContentClass))
-
-struct _GabbleJingleContentClass {
- GObjectClass parent_class;
-
- void (*parse_description) (GabbleJingleContent *, WockyNode *,
- GError **);
- void (*produce_description) (GabbleJingleContent *, WockyNode *);
- void (*transport_created) (GabbleJingleContent *,
- GabbleJingleTransportIface *);
- JingleContentSenders (*get_default_senders) (GabbleJingleContent *);
-};
-
-typedef struct _GabbleJingleContentPrivate GabbleJingleContentPrivate;
-
-struct _GabbleJingleContent {
- GObject parent;
- GabbleJingleContentPrivate *priv;
-
- GabbleJingleSession *session;
-};
-
-void gabble_jingle_content_parse_add (GabbleJingleContent *c,
- WockyNode *content_node, gboolean google_mode, GError **error);
-void gabble_jingle_content_update_senders (GabbleJingleContent *c,
- WockyNode *content_node, GError **error);
-void gabble_jingle_content_produce_node (GabbleJingleContent *c,
- WockyNode *parent,
- gboolean include_description,
- gboolean include_transport,
- WockyNode **trans_node_out);
-void gabble_jingle_content_parse_accept (GabbleJingleContent *c,
- WockyNode *content_node, gboolean google_mode, GError **error);
-
-void gabble_jingle_content_parse_info (GabbleJingleContent *c,
- WockyNode *content_node, GError **error);
-void gabble_jingle_content_parse_transport_info (GabbleJingleContent *self,
- WockyNode *trans_node, GError **error);
-void gabble_jingle_content_parse_description_info (GabbleJingleContent *self,
- WockyNode *trans_node, GError **error);
-guint gabble_jingle_content_create_share_channel (GabbleJingleContent *self,
- const gchar *name);
-void gabble_jingle_content_add_candidates (GabbleJingleContent *self, GList *li);
-void _gabble_jingle_content_set_media_ready (GabbleJingleContent *self);
-gboolean gabble_jingle_content_is_ready (GabbleJingleContent *self);
-void gabble_jingle_content_set_transport_state (GabbleJingleContent *content,
- JingleTransportState state);
-void gabble_jingle_content_remove (GabbleJingleContent *c, gboolean signal_peer);
-void gabble_jingle_content_reject (GabbleJingleContent *c,
- JingleReason reason);
-
-GList *gabble_jingle_content_get_remote_candidates (GabbleJingleContent *c);
-GList *gabble_jingle_content_get_local_candidates (GabbleJingleContent *c);
-gboolean gabble_jingle_content_get_credentials (GabbleJingleContent *c,
- gchar **ufrag, gchar **pwd);
-gboolean gabble_jingle_content_change_direction (GabbleJingleContent *c,
- JingleContentSenders senders);
-void gabble_jingle_content_retransmit_candidates (GabbleJingleContent *self,
- gboolean all);
-void gabble_jingle_content_inject_candidates (GabbleJingleContent *self,
- WockyNode *transport_node);
-gboolean gabble_jingle_content_is_created_by_us (GabbleJingleContent *c);
-gboolean gabble_jingle_content_creator_is_initiator (GabbleJingleContent *c);
-
-const gchar *gabble_jingle_content_get_name (GabbleJingleContent *self);
-const gchar *gabble_jingle_content_get_ns (GabbleJingleContent *self);
-const gchar *gabble_jingle_content_get_disposition (GabbleJingleContent *self);
-JingleTransportType gabble_jingle_content_get_transport_type (GabbleJingleContent *c);
-const gchar *gabble_jingle_content_get_transport_ns (GabbleJingleContent *self);
-
-void gabble_jingle_content_maybe_send_description (GabbleJingleContent *self);
-
-gboolean gabble_jingle_content_sending (GabbleJingleContent *self);
-gboolean gabble_jingle_content_receiving (GabbleJingleContent *self);
-
-void gabble_jingle_content_set_sending (GabbleJingleContent *self,
- gboolean send);
-void gabble_jingle_content_request_receiving (GabbleJingleContent *self,
- gboolean receive);
-
-void gabble_jingle_content_send_complete (GabbleJingleContent *self);
-
-#endif /* __JINGLE_CONTENT_H__ */
-
diff --git a/src/jingle-factory.c b/src/jingle-factory.c
deleted file mode 100644
index 0e9f6f73f..000000000
--- a/src/jingle-factory.c
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * jingle-factory.c - Support for XEP-0166 (Jingle)
- *
- * Copyright (C) 2006-2008 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 "config.h"
-#include "jingle-factory.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <glib.h>
-
-#include <wocky/wocky.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "debug.h"
-#include "gabble-signals-marshal.h"
-#include "jingle-share.h"
-#include "jingle-media-rtp.h"
-#include "jingle-session.h"
-#include "jingle-transport-google.h"
-#include "jingle-transport-rawudp.h"
-#include "jingle-transport-iceudp.h"
-#include "namespaces.h"
-
-#include "google-relay.h"
-
-G_DEFINE_TYPE(GabbleJingleFactory, gabble_jingle_factory, G_TYPE_OBJECT);
-
-/* signal enum */
-enum
-{
- NEW_SESSION,
- QUERY_CAP,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_SESSION = 1,
- LAST_PROPERTY
-};
-
-struct _GabbleJingleFactoryPrivate
-{
- WockySession *session;
- WockyPorter *porter;
- guint jingle_handler_id;
- GHashTable *content_types;
- GHashTable *transports;
-
- /* instances of SESSION_MAP_KEY_FORMAT => GabbleJingleSession. */
- GHashTable *sessions;
-
- GabbleJingleInfo *jingle_info;
-
- gboolean dispose_has_run;
-};
-
-static gboolean jingle_cb (
- WockyPorter *porter,
- WockyStanza *msg,
- gpointer user_data);
-static GabbleJingleSession *create_session (GabbleJingleFactory *fac,
- const gchar *sid,
- const gchar *jid,
- JingleDialect dialect,
- gboolean local_hold);
-
-static gboolean session_query_cap_cb (
- GabbleJingleSession *session,
- WockyContact *contact,
- const gchar *cap_or_quirk,
- gpointer user_data);
-static void session_terminated_cb (GabbleJingleSession *sess,
- gboolean local_terminator,
- JingleReason reason,
- const gchar *text,
- GabbleJingleFactory *fac);
-
-static void attach_to_wocky_session (GabbleJingleFactory *self);
-
-static void
-gabble_jingle_factory_init (GabbleJingleFactory *obj)
-{
- GabbleJingleFactoryPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_JINGLE_FACTORY,
- GabbleJingleFactoryPrivate);
- obj->priv = priv;
-
- priv->sessions = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
-
- priv->transports = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, NULL);
-
- priv->content_types = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, NULL);
-
- priv->dispose_has_run = FALSE;
-}
-
-static void
-gabble_jingle_factory_dispose (GObject *object)
-{
- GabbleJingleFactory *fac = GABBLE_JINGLE_FACTORY (object);
- GabbleJingleFactoryPrivate *priv = fac->priv;
- GHashTableIter iter;
- gpointer val;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- gabble_jingle_factory_stop (fac);
- g_clear_object (&priv->session);
- g_clear_object (&priv->porter);
-
- g_hash_table_iter_init (&iter, priv->sessions);
- while (g_hash_table_iter_next (&iter, NULL, &val))
- g_signal_handlers_disconnect_by_func (val, session_query_cap_cb, fac);
- g_hash_table_unref (priv->sessions);
- priv->sessions = NULL;
-
- g_hash_table_unref (priv->content_types);
- priv->content_types = NULL;
- g_hash_table_unref (priv->transports);
- priv->transports = NULL;
- g_clear_object (&priv->jingle_info);
-
- if (G_OBJECT_CLASS (gabble_jingle_factory_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_jingle_factory_parent_class)->dispose (object);
-}
-
-static void
-gabble_jingle_factory_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleFactory *chan = GABBLE_JINGLE_FACTORY (object);
- GabbleJingleFactoryPrivate *priv = chan->priv;
-
- switch (property_id) {
- case PROP_SESSION:
- g_value_set_object (value, priv->session);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_jingle_factory_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleFactory *chan = GABBLE_JINGLE_FACTORY (object);
- GabbleJingleFactoryPrivate *priv = chan->priv;
-
- switch (property_id) {
- case PROP_SESSION:
- priv->session = g_value_dup_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_jingle_factory_constructed (GObject *obj)
-{
- GabbleJingleFactory *self = GABBLE_JINGLE_FACTORY (obj);
- GObjectClass *parent = G_OBJECT_CLASS (gabble_jingle_factory_parent_class);
-
- if (parent->constructed != NULL)
- parent->constructed (obj);
-
- attach_to_wocky_session (self);
-
- jingle_share_register (self);
- jingle_media_rtp_register (self);
- jingle_transport_google_register (self);
- jingle_transport_rawudp_register (self);
- jingle_transport_iceudp_register (self);
-}
-
-static void
-gabble_jingle_factory_class_init (GabbleJingleFactoryClass *cls)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (cls);
- GParamSpec *param_spec;
-
- g_type_class_add_private (cls, sizeof (GabbleJingleFactoryPrivate));
-
- object_class->constructed = gabble_jingle_factory_constructed;
- object_class->get_property = gabble_jingle_factory_get_property;
- object_class->set_property = gabble_jingle_factory_set_property;
- object_class->dispose = gabble_jingle_factory_dispose;
-
- param_spec = g_param_spec_object ("session", "WockySession object",
- "WockySession to listen for Jingle sessions on",
- WOCKY_TYPE_SESSION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_SESSION, param_spec);
-
- /* signal definitions */
-
- /*
- * @session: a fresh new Jingle session for your listening pleasure
- * @initiated_locally: %TRUE if this is a new outgoing session; %FALSE if it
- * is a new incoming session
- */
- signals[NEW_SESSION] = g_signal_new ("new-session",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, gabble_marshal_VOID__OBJECT_BOOL,
- G_TYPE_NONE, 2, GABBLE_TYPE_JINGLE_SESSION, G_TYPE_BOOLEAN);
-
- /*
- * @contact: the peer in a call
- * @cap: the XEP-0115 feature string the session is interested in.
- *
- * Emitted when a Jingle session wants to check whether the peer has a
- * particular capability. The handler should return %TRUE if @contact has
- * @cap.
- */
- signals[QUERY_CAP] = g_signal_new ("query-cap",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, g_signal_accumulator_first_wins, NULL,
- gabble_marshal_BOOLEAN__OBJECT_STRING,
- G_TYPE_BOOLEAN, 2, WOCKY_TYPE_CONTACT, G_TYPE_STRING);
-}
-
-GabbleJingleFactory *
-gabble_jingle_factory_new (
- WockySession *session)
-{
- return g_object_new (GABBLE_TYPE_JINGLE_FACTORY,
- "session", session,
- NULL);
-}
-
-static void
-attach_to_wocky_session (GabbleJingleFactory *self)
-{
- GabbleJingleFactoryPrivate *priv = self->priv;
-
- g_assert (priv->session != NULL);
-
- g_assert (priv->porter == NULL);
- priv->porter = g_object_ref (wocky_session_get_porter (priv->session));
-
- /* TODO: we could match different dialects here maybe? */
- priv->jingle_handler_id = wocky_porter_register_handler_from_anyone (
- priv->porter,
- WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
- WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, jingle_cb, self,
- NULL);
-
- priv->jingle_info = gabble_jingle_info_new (priv->porter);
-}
-
-void
-gabble_jingle_factory_stop (GabbleJingleFactory *self)
-{
- GabbleJingleFactoryPrivate *priv = self->priv;
-
- if (priv->porter != NULL &&
- priv->jingle_handler_id != 0)
- {
- wocky_porter_unregister_handler (priv->porter, priv->jingle_handler_id);
- priv->jingle_handler_id = 0;
- }
-}
-
-/* The 'session' map is keyed by:
- * "<peer's jid>\n<session id>"
- */
-#define SESSION_MAP_KEY_FORMAT "%s\n%s"
-
-static gchar *
-make_session_map_key (
- const gchar *jid,
- const gchar *sid)
-{
- return g_strdup_printf (SESSION_MAP_KEY_FORMAT, jid, sid);
-}
-
-static gchar *
-get_unique_sid_for (GabbleJingleFactory *factory,
- const gchar *jid,
- gchar **key)
-{
- guint32 val;
- gchar *sid = NULL;
- gchar *key_ = NULL;
-
- do
- {
- val = g_random_int_range (1000000, G_MAXINT);
-
- g_free (sid);
- g_free (key_);
- sid = g_strdup_printf ("%u", val);
- key_ = make_session_map_key (jid, sid);
- }
- while (g_hash_table_lookup (factory->priv->sessions, key_) != NULL);
-
- *key = key_;
- return sid;
-}
-
-static GabbleJingleSession *
-ensure_session (GabbleJingleFactory *self,
- const gchar *sid,
- const gchar *from,
- JingleAction action,
- JingleDialect dialect,
- gboolean *new_session,
- GError **error)
-{
- GabbleJingleFactoryPrivate *priv = self->priv;
- gchar *key;
- GabbleJingleSession *sess;
-
- if (!wocky_decode_jid (from, NULL, NULL, NULL))
- {
- g_prefix_error (error, "Couldn't parse sender '%s': ", from);
- return NULL;
- }
-
- /* If we can ensure the handle, we can decode the jid */
- key = make_session_map_key (from, sid);
- sess = g_hash_table_lookup (priv->sessions, key);
- g_free (key);
-
- if (sess == NULL)
- {
- if (action == JINGLE_ACTION_SESSION_INITIATE)
- {
- sess = create_session (self, sid, from, dialect, FALSE);
- *new_session = TRUE;
- }
- else
- {
- g_set_error (error, WOCKY_XMPP_ERROR,
- WOCKY_JINGLE_ERROR_UNKNOWN_SESSION,
- "session %s is unknown", sid);
- return NULL;
- }
- }
- else
- {
- *new_session = FALSE;
- }
-
- return sess;
-}
-
-static gboolean
-jingle_cb (
- WockyPorter *porter,
- WockyStanza *msg,
- gpointer user_data)
-{
- GabbleJingleFactory *self = GABBLE_JINGLE_FACTORY (user_data);
- GError *error = NULL;
- const gchar *sid, *from;
- GabbleJingleSession *sess;
- gboolean new_session = FALSE;
- JingleAction action;
- JingleDialect dialect;
-
- /* see if it's a jingle message and detect dialect */
- sid = gabble_jingle_session_detect (msg, &action, &dialect);
- from = wocky_stanza_get_from (msg);
-
- if (sid == NULL || from == NULL)
- return FALSE;
-
- sess = ensure_session (self, sid, from, action, dialect, &new_session,
- &error);
-
- if (sess == NULL)
- goto REQUEST_ERROR;
-
- /* now act on the message */
- if (!gabble_jingle_session_parse (sess, action, msg, &error))
- goto REQUEST_ERROR;
-
- /* This has to be after the call to parse(), not inside create_session():
- * until the session has parsed the session-initiate stanza, it does not know
- * about its own contents, and we don't even know if the content types are
- * something we understand. So it's essentially half-alive and useless to
- * signal listeners.
- */
- if (new_session)
- g_signal_emit (self, signals[NEW_SESSION], 0, sess, FALSE);
-
- /* all went well, we can acknowledge the IQ */
- wocky_porter_acknowledge_iq (porter, msg, NULL);
-
- return TRUE;
-
-REQUEST_ERROR:
- g_assert (error != NULL);
- DEBUG ("NAKing with error: %s", error->message);
- wocky_porter_send_iq_gerror (porter, msg, error);
- g_error_free (error);
-
- if (sess != NULL && new_session)
- gabble_jingle_session_terminate (sess, JINGLE_REASON_UNKNOWN, NULL, NULL);
-
- return TRUE;
-}
-
-static gboolean
-session_query_cap_cb (
- GabbleJingleSession *session,
- WockyContact *contact,
- const gchar *cap_or_quirk,
- gpointer user_data)
-{
- GabbleJingleFactory *self = GABBLE_JINGLE_FACTORY (user_data);
- gboolean ret;
-
- /* Propagate the query out to the application. We can't depend on the
- * application connecting to ::query-cap on the session because caps queries
- * may happen while parsing the session-initiate stanza, which must happen
- * before the session is announced to the application.
- */
- g_signal_emit (self, signals[QUERY_CAP], 0, contact, cap_or_quirk, &ret);
- return ret;
-}
-
-/*
- * If sid is set to NULL a unique sid is generated and
- * the "local-initiator" property of the newly created
- * GabbleJingleSession is set to true.
- */
-static GabbleJingleSession *
-create_session (GabbleJingleFactory *fac,
- const gchar *sid,
- const gchar *jid,
- JingleDialect dialect,
- gboolean local_hold)
-{
- GabbleJingleFactoryPrivate *priv = fac->priv;
- GabbleJingleSession *sess;
- gboolean local_initiator;
- gchar *sid_, *key;
- gpointer contact;
- WockyContactFactory *factory;
-
- factory = wocky_session_get_contact_factory (priv->session);
- g_assert (jid != NULL);
-
- if (strchr (jid, '/') != NULL)
- contact = wocky_contact_factory_ensure_resource_contact (factory, jid);
- else
- contact = wocky_contact_factory_ensure_bare_contact (factory, jid);
-
- g_return_val_if_fail (contact != NULL, NULL);
- g_return_val_if_fail (WOCKY_IS_CONTACT (contact), NULL);
-
- if (sid != NULL)
- {
- key = make_session_map_key (jid, sid);
- sid_ = g_strdup (sid);
-
- local_initiator = FALSE;
- }
- else
- {
- sid_ = get_unique_sid_for (fac, jid, &key);
-
- local_initiator = TRUE;
- }
-
- /* Either we should have found the existing session when the IQ arrived, or
- * get_unique_sid_for should have ensured the key is fresh. */
- g_assert (NULL == g_hash_table_lookup (priv->sessions, key));
-
- sess = gabble_jingle_session_new (
- fac,
- priv->porter,
- sid_, local_initiator, contact, dialect, local_hold);
- g_signal_connect (sess, "terminated",
- (GCallback) session_terminated_cb, fac);
-
- /* Takes ownership of key */
- g_hash_table_insert (priv->sessions, key, sess);
-
- DEBUG ("new session (%s, %s) @ %p", jid, sid_, sess);
-
- g_free (sid_);
- g_object_unref (contact);
-
- g_signal_connect (sess, "query-cap",
- (GCallback) session_query_cap_cb, (GObject *) fac);
-
- return sess;
-}
-
-GabbleJingleSession *
-gabble_jingle_factory_create_session (GabbleJingleFactory *fac,
- const gchar *jid,
- JingleDialect dialect,
- gboolean local_hold)
-{
- GabbleJingleSession *session = create_session (fac, NULL, jid, dialect, local_hold);
-
- g_signal_emit (fac, signals[NEW_SESSION], 0, session, TRUE);
- return session;
-}
-
-void
-gabble_jingle_factory_register_transport (GabbleJingleFactory *self,
- gchar *xmlns,
- GType transport_type)
-{
- g_return_if_fail (g_type_is_a (transport_type,
- GABBLE_TYPE_JINGLE_TRANSPORT_IFACE));
-
- g_hash_table_insert (self->priv->transports, xmlns,
- GSIZE_TO_POINTER (transport_type));
-}
-
-GType
-gabble_jingle_factory_lookup_transport (GabbleJingleFactory *self,
- const gchar *xmlns)
-{
- return GPOINTER_TO_SIZE (g_hash_table_lookup (self->priv->transports,
- xmlns));
-}
-
-void
-gabble_jingle_factory_register_content_type (GabbleJingleFactory *self,
- gchar *xmlns,
- GType content_type)
-{
- g_return_if_fail (g_type_is_a (content_type, GABBLE_TYPE_JINGLE_CONTENT));
-
- g_hash_table_insert (self->priv->content_types, xmlns,
- GSIZE_TO_POINTER (content_type));
-}
-
-GType
-gabble_jingle_factory_lookup_content_type (GabbleJingleFactory *self,
- const gchar *xmlns)
-{
- return GPOINTER_TO_SIZE (g_hash_table_lookup (self->priv->content_types,
- xmlns));
-}
-
-static void
-session_terminated_cb (GabbleJingleSession *session,
- gboolean local_terminator G_GNUC_UNUSED,
- JingleReason reason G_GNUC_UNUSED,
- const gchar *text G_GNUC_UNUSED,
- GabbleJingleFactory *factory)
-{
- gchar *key = make_session_map_key (
- gabble_jingle_session_get_peer_jid (session),
- gabble_jingle_session_get_sid (session));
-
- DEBUG ("removing terminated session with key %s", key);
-
- g_signal_handlers_disconnect_by_func (session, session_query_cap_cb, factory);
- g_warn_if_fail (g_hash_table_remove (factory->priv->sessions, key));
-
- g_free (key);
-}
-
-GabbleJingleInfo *
-gabble_jingle_factory_get_jingle_info (
- GabbleJingleFactory *self)
-{
- return self->priv->jingle_info;
-}
diff --git a/src/jingle-factory.h b/src/jingle-factory.h
deleted file mode 100644
index d254dbf20..000000000
--- a/src/jingle-factory.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * jingle-factory.h - Header for GabbleJingleFactory
- * Copyright (C) 2008 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 __JINGLE_FACTORY_H__
-#define __JINGLE_FACTORY_H__
-
-#include <glib-object.h>
-
-#include "jingle-info.h"
-#include "jingle-types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleJingleFactoryClass GabbleJingleFactoryClass;
-
-GType gabble_jingle_factory_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_FACTORY \
- (gabble_jingle_factory_get_type ())
-#define GABBLE_JINGLE_FACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_FACTORY, \
- GabbleJingleFactory))
-#define GABBLE_JINGLE_FACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_FACTORY, \
- GabbleJingleFactoryClass))
-#define GABBLE_IS_JINGLE_FACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_FACTORY))
-#define GABBLE_IS_JINGLE_FACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_FACTORY))
-#define GABBLE_JINGLE_FACTORY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_FACTORY, \
- GabbleJingleFactoryClass))
-
-struct _GabbleJingleFactoryClass {
- GObjectClass parent_class;
-};
-
-typedef struct _GabbleJingleFactoryPrivate GabbleJingleFactoryPrivate;
-
-struct _GabbleJingleFactory {
- GObject parent;
-
- GabbleJingleFactoryPrivate *priv;
-};
-
-GabbleJingleFactory *gabble_jingle_factory_new (
- WockySession *session);
-
-void gabble_jingle_factory_stop (GabbleJingleFactory *self);
-
-void gabble_jingle_factory_register_content_type (GabbleJingleFactory *self,
- gchar *xmlns, GType content_type);
-GType gabble_jingle_factory_lookup_content_type (GabbleJingleFactory *self,
- const gchar *xmlns);
-
-void gabble_jingle_factory_register_transport (GabbleJingleFactory *self,
- gchar *xmlns, GType transport_type);
-GType gabble_jingle_factory_lookup_transport (GabbleJingleFactory *self,
- const gchar *xmlns);
-
-GabbleJingleSession *gabble_jingle_factory_create_session (
- GabbleJingleFactory *fac,
- const gchar *jid,
- JingleDialect dialect,
- gboolean local_hold);
-
-GabbleJingleInfo *gabble_jingle_factory_get_jingle_info (
- GabbleJingleFactory *fac);
-
-G_END_DECLS;
-
-#endif /* __JINGLE_FACTORY_H__ */
-
diff --git a/src/jingle-info.c b/src/jingle-info.c
deleted file mode 100644
index 4048fa3b3..000000000
--- a/src/jingle-info.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * jingle-info.c - exciting times with Google's jingleinfo extension
- * Copyright © 2008–2012 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 "config.h"
-#include "jingle-info.h"
-
-#include <stdlib.h>
-#include <telepathy-glib/util.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-#include "debug.h"
-#include "google-relay.h"
-#include "gabble-signals-marshal.h"
-#include "namespaces.h"
-
-static gboolean jingle_info_cb (
- WockyPorter *porter,
- WockyStanza *stanza,
- gpointer user_data);
-
-struct _GabbleJingleInfoPrivate {
- WockyPorter *porter;
- guint jingle_info_handler_id;
-
- GabbleGoogleRelayResolver *google_resolver;
-
- gchar *stun_server;
- guint16 stun_port;
- gchar *fallback_stun_server;
- guint16 fallback_stun_port;
- gchar *relay_token;
-
- /* TRUE if the user has not explicitly specified a STUN server, and hence
- * we should ask the XMPP server for one; FALSE if not.
- */
- gboolean get_stun_from_jingle;
-
- gchar *relay_server;
- guint16 relay_http_port;
- guint16 relay_udp;
- guint16 relay_tcp;
- guint16 relay_ssltcp;
-
-};
-
-enum {
- PROP_PORTER = 1,
-};
-
-enum {
- STUN_SERVER_CHANGED = 0,
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS];
-
-static gboolean test_mode = FALSE;
-
-void
-gabble_jingle_info_set_test_mode (void)
-{
- test_mode = TRUE;
-}
-
-G_DEFINE_TYPE (GabbleJingleInfo, gabble_jingle_info, G_TYPE_OBJECT)
-
-static void
-gabble_jingle_info_init (GabbleJingleInfo *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_JINGLE_INFO,
- GabbleJingleInfoPrivate);
-
- self->priv->relay_http_port = 80;
- self->priv->get_stun_from_jingle = TRUE;
-}
-
-static void
-gabble_jingle_info_get_property (
- GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleInfo *self = GABBLE_JINGLE_INFO (object);
- GabbleJingleInfoPrivate *priv = self->priv;
-
- switch (property_id)
- {
- case PROP_PORTER:
- g_value_set_object (value, priv->porter);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-gabble_jingle_info_set_property (
- GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleInfo *self = GABBLE_JINGLE_INFO (object);
- GabbleJingleInfoPrivate *priv = self->priv;
-
- switch (property_id)
- {
- case PROP_PORTER:
- g_assert (priv->porter == NULL);
- priv->porter = g_value_dup_object (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-gabble_jingle_info_constructed (GObject *object)
-{
- GabbleJingleInfo *self = GABBLE_JINGLE_INFO (object);
- GabbleJingleInfoPrivate *priv = self->priv;
- GObjectClass *parent_class = gabble_jingle_info_parent_class;
-
- if (parent_class->constructed != NULL)
- parent_class->constructed (object);
-
- g_assert (priv->porter != NULL);
- priv->jingle_info_handler_id = wocky_c2s_porter_register_handler_from_server (
- WOCKY_C2S_PORTER (priv->porter),
- WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
- WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, jingle_info_cb, self,
- '(', "query", ':', NS_GOOGLE_JINGLE_INFO, ')', NULL);
-}
-
-static void
-gabble_jingle_info_dispose (GObject *object)
-{
- GabbleJingleInfo *self = GABBLE_JINGLE_INFO (object);
- GabbleJingleInfoPrivate *priv = self->priv;
- GObjectClass *parent_class = gabble_jingle_info_parent_class;
-
- if (priv->porter != NULL)
- {
- g_assert (priv->jingle_info_handler_id != 0);
- wocky_porter_unregister_handler (priv->porter, priv->jingle_info_handler_id);
- g_clear_object (&priv->porter);
- }
-
- if (priv->google_resolver != NULL)
- {
- gabble_google_relay_resolver_destroy (priv->google_resolver);
- priv->google_resolver = NULL;
- }
-
- g_free (priv->stun_server);
- priv->stun_server = NULL;
- g_free (priv->fallback_stun_server);
- priv->fallback_stun_server = NULL;
- g_free (priv->relay_token);
- priv->relay_token = NULL;
- g_free (priv->relay_server);
- priv->relay_server = NULL;
-
- if (parent_class->dispose != NULL)
- parent_class->dispose (object);
-}
-
-static void
-gabble_jingle_info_class_init (GabbleJingleInfoClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GParamSpec *param_spec;
-
- object_class->get_property = gabble_jingle_info_get_property;
- object_class->set_property = gabble_jingle_info_set_property;
- object_class->constructed = gabble_jingle_info_constructed;
- object_class->dispose = gabble_jingle_info_dispose;
-
- g_type_class_add_private (klass, sizeof (GabbleJingleInfoPrivate));
-
- param_spec = g_param_spec_object ("porter", "WockyC2SPorter",
- "Porter for the current connection",
- WOCKY_TYPE_C2S_PORTER,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_PORTER, param_spec);
-
- signals[STUN_SERVER_CHANGED] = g_signal_new ("stun-server-changed",
- G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, gabble_marshal_VOID__STRING_UINT,
- G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT);
-}
-
-GabbleJingleInfo *
-gabble_jingle_info_new (
- WockyPorter *porter)
-{
- return g_object_new (GABBLE_TYPE_JINGLE_INFO,
- "porter", porter,
- NULL);
-}
-
-typedef struct {
- GabbleJingleInfo *factory;
- gchar *stun_server;
- guint16 stun_port;
- gboolean fallback;
- GCancellable *cancellable;
-} PendingStunServer;
-
-static void
-pending_stun_server_free (gpointer p)
-{
- PendingStunServer *data = p;
-
- if (data->factory != NULL)
- g_object_remove_weak_pointer (G_OBJECT (data->factory),
- (gpointer)&data->factory);
-
- g_object_unref (data->cancellable);
- g_free (data->stun_server);
- g_slice_free (PendingStunServer, p);
-}
-
-static void
-stun_server_resolved_cb (GObject *resolver,
- GAsyncResult *result,
- gpointer user_data)
-{
- PendingStunServer *data = user_data;
- GabbleJingleInfo *self = data->factory;
- GError *e = NULL;
- gchar *stun_server;
- GList *entries;
-
- if (self != NULL)
- g_object_weak_unref (G_OBJECT (self),
- (GWeakNotify)g_cancellable_cancel, data->cancellable);
-
- entries = g_resolver_lookup_by_name_finish (
- G_RESOLVER (resolver), result, &e);
-
- if (entries == NULL)
- {
- DEBUG ("Failed to resolve STUN server %s:%u: %s",
- data->stun_server, data->stun_port, e->message);
- g_error_free (e);
- goto out;
- }
-
- stun_server = g_inet_address_to_string (entries->data);
- g_resolver_free_addresses (entries);
-
- DEBUG ("Resolved STUN server %s:%u to %s:%u", data->stun_server,
- data->stun_port, stun_server, data->stun_port);
-
- if (self == NULL)
- {
- g_free (stun_server);
- goto out;
- }
-
- if (data->fallback)
- {
- g_free (self->priv->fallback_stun_server);
- self->priv->fallback_stun_server = stun_server;
- self->priv->fallback_stun_port = data->stun_port;
- }
- else
- {
- g_free (self->priv->stun_server);
- self->priv->stun_server = stun_server;
- self->priv->stun_port = data->stun_port;
-
- g_signal_emit (self, signals[STUN_SERVER_CHANGED], 0,
- stun_server, data->stun_port);
- }
-
-out:
- pending_stun_server_free (data);
- g_object_unref (resolver);
-}
-
-void
-gabble_jingle_info_take_stun_server (
- GabbleJingleInfo *self,
- gchar *stun_server,
- guint16 stun_port,
- gboolean is_fallback)
-{
- GResolver *resolver;
- PendingStunServer *data;
-
- if (stun_server == NULL)
- return;
-
- if (!is_fallback)
- self->priv->get_stun_from_jingle = FALSE;
-
- resolver = g_resolver_get_default ();
- data = g_slice_new0 (PendingStunServer);
-
- DEBUG ("Resolving %s STUN server %s:%u",
- is_fallback ? "fallback" : "primary", stun_server, stun_port);
- data->factory = self;
- g_object_add_weak_pointer (G_OBJECT (self), (gpointer *) &data->factory);
- data->stun_server = stun_server;
- data->stun_port = stun_port;
- data->fallback = is_fallback;
-
- data->cancellable = g_cancellable_new ();
- g_object_weak_ref (G_OBJECT (self), (GWeakNotify)g_cancellable_cancel,
- data->cancellable);
-
- g_resolver_lookup_by_name_async (resolver, stun_server,
- data->cancellable, stun_server_resolved_cb, data);
-}
-
-static void
-got_jingle_info_stanza (
- GabbleJingleInfo *self,
- WockyStanza *stanza)
-{
- WockyNode *node, *query_node;
-
- query_node = wocky_node_get_child_ns (
- wocky_stanza_get_top_node (stanza), "query", NS_GOOGLE_JINGLE_INFO);
-
- if (query_node == NULL)
- return;
-
- if (self->priv->get_stun_from_jingle)
- node = wocky_node_get_child (query_node, "stun");
- else
- node = NULL;
-
- if (node != NULL)
- {
- node = wocky_node_get_child (node, "server");
-
- if (node != NULL)
- {
- const gchar *server;
- const gchar *port_attr;
- guint port = 0;
-
- server = wocky_node_get_attribute (node, "host");
- port_attr = wocky_node_get_attribute (node, "udp");
-
- if (port_attr != NULL)
- port = atoi (port_attr);
-
- if (server != NULL &&
- port_attr != NULL && port > 0 && port <= G_MAXUINT16)
- {
- DEBUG ("jingle info: got stun server %s, port %u", server,
- port);
- gabble_jingle_info_take_stun_server (self,
- g_strdup (server), port, FALSE);
- }
- }
- }
-
-#ifdef ENABLE_GOOGLE_RELAY
- node = wocky_node_get_child (query_node, "relay");
-
- if (node != NULL)
- {
- WockyNode *subnode = wocky_node_get_child (node, "token");
-
- if (subnode != NULL)
- {
- const gchar *token = subnode->content;
-
- if (token != NULL)
- {
- DEBUG ("jingle info: got Google relay token %s", token);
- g_free (self->priv->relay_token);
- self->priv->relay_token = g_strdup (token);
- }
- }
-
- subnode = wocky_node_get_child (node, "server");
-
- if (subnode != NULL)
- {
- const gchar *server;
- const gchar *port;
-
- server = wocky_node_get_attribute (subnode, "host");
-
- if (server != NULL)
- {
- DEBUG ("jingle info: got relay server %s", server);
- g_free (self->priv->relay_server);
- self->priv->relay_server = g_strdup (server);
- }
-
- if (test_mode)
- {
- /* this is not part of the real protocol, but we can't listen on
- * port 80 in an unprivileged regression test */
- port = wocky_node_get_attribute (subnode,
- "gabble-test-http-port");
-
- if (port != NULL)
- {
- DEBUG ("jingle info: diverting 'Google' HTTP requests to "
- "port %s", port);
- self->priv->relay_http_port = atoi (port);
- }
- }
-
- /* FIXME: these are not really actually used anywhere at
- * the moment, because we get the same info when creating
- * relay session. */
- port = wocky_node_get_attribute (subnode, "udp");
-
- if (port != NULL)
- {
- DEBUG ("jingle info: got relay udp port %s", port);
- self->priv->relay_udp = atoi (port);
- }
-
- port = wocky_node_get_attribute (subnode, "tcp");
-
- if (port != NULL)
- {
- DEBUG ("jingle info: got relay tcp port %s", port);
- self->priv->relay_tcp = atoi (port);
- }
-
- port = wocky_node_get_attribute (subnode, "tcpssl");
-
- if (port != NULL)
- {
- DEBUG ("jingle info: got relay tcpssl port %s", port);
- self->priv->relay_ssltcp = atoi (port);
- }
-
- }
-
- }
-#endif /* ENABLE_GOOGLE_RELAY */
-}
-
-static gboolean
-jingle_info_cb (
- WockyPorter *porter,
- WockyStanza *stanza,
- gpointer user_data)
-{
- GabbleJingleInfo *self = GABBLE_JINGLE_INFO (user_data);
-
- got_jingle_info_stanza (self, stanza);
- wocky_porter_acknowledge_iq (porter, stanza, NULL);
-
- return TRUE;
-}
-
-static void
-jingle_info_reply_cb (
- GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- WockyPorter *porter = WOCKY_PORTER (source);
- GabbleJingleInfo *self = GABBLE_JINGLE_INFO (user_data);
- WockyStanza *reply = NULL;
- GError *error = NULL;
-
- reply = wocky_porter_send_iq_finish (porter, result, &error);
- if (reply != NULL &&
- !wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL))
- {
- got_jingle_info_stanza (self, reply);
- }
- else
- {
- DEBUG ("jingle info request failed: %s", error->message);
- g_clear_error (&error);
- }
-
- g_clear_object (&reply);
- g_object_unref (self);
-}
-
-void
-gabble_jingle_info_send_request (GabbleJingleInfo *self)
-{
- GabbleJingleInfoPrivate *priv = self->priv;
- WockyStanza *stanza = wocky_stanza_build (
- WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL,
- wocky_porter_get_bare_jid (priv->porter),
- '(', "query", ':', NS_GOOGLE_JINGLE_INFO, ')', NULL);
-
- wocky_porter_send_iq_async (priv->porter, stanza, NULL, jingle_info_reply_cb,
- g_object_ref (self));
- g_object_unref (stanza);
-}
-
-gboolean
-gabble_jingle_info_get_stun_server (
- GabbleJingleInfo *self,
- gchar **stun_server,
- guint *stun_port)
-{
- if (self->priv->stun_server == NULL || self->priv->stun_port == 0)
- {
- if (self->priv->fallback_stun_server == NULL ||
- self->priv->fallback_stun_port == 0)
- return FALSE;
-
- if (stun_server != NULL)
- *stun_server = g_strdup (self->priv->fallback_stun_server);
-
- if (stun_port != NULL)
- *stun_port = self->priv->fallback_stun_port;
-
- return TRUE;
- }
-
- if (stun_server != NULL)
- *stun_server = g_strdup (self->priv->stun_server);
-
- if (stun_port != NULL)
- *stun_port = self->priv->stun_port;
-
- return TRUE;
-}
-
-const gchar *
-gabble_jingle_info_get_google_relay_token (
- GabbleJingleInfo *self)
-{
- return self->priv->relay_token;
-}
-
-GabbleJingleRelay *
-gabble_jingle_relay_new (
- GabbleJingleRelayType type,
- const gchar *ip,
- guint port,
- const gchar *username,
- const gchar *password,
- guint component)
-{
- GabbleJingleRelay ret = { type, g_strdup (ip), port, g_strdup (username),
- g_strdup (password), component };
-
- return g_slice_dup (GabbleJingleRelay, &ret);
-}
-
-void
-gabble_jingle_relay_free (GabbleJingleRelay *relay)
-{
- g_free (relay->ip);
- g_free (relay->username);
- g_free (relay->password);
- g_slice_free (GabbleJingleRelay, relay);
-}
-
-void
-gabble_jingle_info_create_google_relay_session (
- GabbleJingleInfo *self,
- guint components,
- GabbleJingleInfoRelaySessionCb callback,
- gpointer user_data)
-{
- GabbleJingleInfoPrivate *priv = self->priv;
-
- g_return_if_fail (callback != NULL);
-
- if (priv->google_resolver == NULL)
- {
- priv->google_resolver = gabble_google_relay_resolver_new ();
- }
-
- gabble_google_relay_resolver_resolve (priv->google_resolver,
- components, priv->relay_server, priv->relay_http_port, priv->relay_token,
- callback, user_data);
-}
diff --git a/src/jingle-info.h b/src/jingle-info.h
deleted file mode 100644
index 2ce8111c6..000000000
--- a/src/jingle-info.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * jingle-info.h - exciting times with Google's jingleinfo extension
- * Copyright © 2008–2012 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 GABBLE_JINGLE_INFO_H
-#define GABBLE_JINGLE_INFO_H
-
-#include <glib-object.h>
-#include <wocky/wocky.h>
-
-typedef struct _GabbleJingleInfo GabbleJingleInfo;
-typedef struct _GabbleJingleInfoClass GabbleJingleInfoClass;
-typedef struct _GabbleJingleInfoPrivate GabbleJingleInfoPrivate;
-
-struct _GabbleJingleInfoClass {
- GObjectClass parent_class;
-};
-
-struct _GabbleJingleInfo {
- GObject parent;
-
- GabbleJingleInfoPrivate *priv;
-};
-
-GType gabble_jingle_info_get_type (void);
-
-GabbleJingleInfo *gabble_jingle_info_new (
- WockyPorter *porter);
-
-void gabble_jingle_info_take_stun_server (
- GabbleJingleInfo *self,
- gchar *stun_server,
- guint16 stun_port,
- gboolean is_fallback);
-void gabble_jingle_info_send_request (GabbleJingleInfo *self);
-
-gboolean gabble_jingle_info_get_stun_server (
- GabbleJingleInfo *self,
- gchar **stun_server,
- guint *stun_port);
-
-const gchar *gabble_jingle_info_get_google_relay_token (
- GabbleJingleInfo *self);
-
-typedef enum {
- GABBLE_JINGLE_RELAY_TYPE_UDP,
- GABBLE_JINGLE_RELAY_TYPE_TCP,
- GABBLE_JINGLE_RELAY_TYPE_TLS
-} GabbleJingleRelayType;
-#define GABBLE_N_JINGLE_RELAY_TYPES 3
-
-typedef struct {
- GabbleJingleRelayType type;
- gchar *ip;
- guint port;
- gchar *username;
- gchar *password;
- guint component;
-} GabbleJingleRelay;
-
-GabbleJingleRelay *gabble_jingle_relay_new (
- GabbleJingleRelayType type,
- const gchar *ip,
- guint port,
- const gchar *username,
- const gchar *password,
- guint component);
-void gabble_jingle_relay_free (GabbleJingleRelay *relay);
-
-/*
- * @relays: (element-type GabbleJingleRelay) (transfer none): a possibly-empty
- * array of GabbleJingleRelay structs.
- */
-typedef void (*GabbleJingleInfoRelaySessionCb) (
- GPtrArray *relays,
- gpointer user_data);
-void gabble_jingle_info_create_google_relay_session (
- GabbleJingleInfo *self,
- guint components,
- GabbleJingleInfoRelaySessionCb callback,
- gpointer user_data);
-
-void gabble_jingle_info_set_test_mode (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_INFO \
- (gabble_jingle_info_get_type ())
-#define GABBLE_JINGLE_INFO(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_INFO, GabbleJingleInfo))
-#define GABBLE_JINGLE_INFO_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_INFO,\
- GabbleJingleInfoClass))
-#define GABBLE_IS_JINGLE_INFO(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_INFO))
-#define GABBLE_IS_JINGLE_INFO_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_INFO))
-#define GABBLE_JINGLE_INFO_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_INFO, \
- GabbleJingleInfoClass))
-
-#endif /* GABBLE_JINGLE_INFO_H */
diff --git a/src/jingle-media-rtp.c b/src/jingle-media-rtp.c
deleted file mode 100644
index 45a14191a..000000000
--- a/src/jingle-media-rtp.c
+++ /dev/null
@@ -1,1516 +0,0 @@
-/*
- * jingle-media-rtp.c - Source for GabbleJingleMediaRtp
- *
- * Copyright (C) 2008 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
- */
-
-/* Media/RTP content type deals with audio/video content, ie. jingle calls. It
- * supports standard Jingle drafts (v0.15, v0.26) and Google's jingle variants
- * (libjingle 0.3/0.4). */
-
-#include "config.h"
-#include "jingle-media-rtp.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "connection.h"
-#include "debug.h"
-#include "jingle-content.h"
-#include "jingle-factory.h"
-#include "jingle-session.h"
-#include "namespaces.h"
-#include "presence-cache.h"
-#include "jingle-transport-google.h"
-
-G_DEFINE_TYPE (GabbleJingleMediaRtp,
- gabble_jingle_media_rtp, GABBLE_TYPE_JINGLE_CONTENT);
-
-/* signal enum */
-enum
-{
- REMOTE_MEDIA_DESCRIPTION,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_MEDIA_TYPE = 1,
- PROP_REMOTE_MUTE,
- LAST_PROPERTY
-};
-
-typedef enum {
- JINGLE_MEDIA_PROFILE_RTP_AVP,
-} JingleMediaProfile;
-
-struct _GabbleJingleMediaRtpPrivate
-{
- JingleMediaDescription *local_media_description;
-
- /* Holds (JingleCodec *)'s borrowed from local_media_description,
- * namely codecs which have changed from local_media_description's
- * previous value. Since the contents are borrowed, this must be
- * freed with g_list_free, not jingle_media_rtp_free_codecs().
- */
- GList *local_codec_updates;
-
- JingleMediaDescription *remote_media_description;
- JingleMediaType media_type;
- gboolean remote_mute;
-
- gboolean has_rtcp_fb;
- gboolean has_rtp_hdrext;
-
- gboolean dispose_has_run;
-};
-
-static void
-gabble_jingle_media_rtp_init (GabbleJingleMediaRtp *obj)
-{
- GabbleJingleMediaRtpPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_JINGLE_MEDIA_RTP,
- GabbleJingleMediaRtpPrivate);
- obj->priv = priv;
- priv->dispose_has_run = FALSE;
-}
-
-JingleCodec *
-jingle_media_rtp_codec_new (guint id, const gchar *name,
- guint clockrate, guint channels, GHashTable *params)
-{
- JingleCodec *p = g_slice_new0 (JingleCodec);
-
- p->id = id;
- p->name = g_strdup (name);
- p->clockrate = clockrate;
- p->channels = channels;
- p->trr_int = G_MAXUINT;
-
- if (params != NULL)
- {
- g_hash_table_ref (params);
- p->params = params;
- }
- else
- {
- p->params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
- g_free);
- }
-
- return p;
-}
-
-
-static GList *
-jingle_feedback_message_list_copy (GList *fbs)
-{
- GQueue new = G_QUEUE_INIT;
- GList *li;
-
- for (li = fbs; li; li = li->next)
- {
- JingleFeedbackMessage *fb = li->data;
-
- g_queue_push_tail (&new, jingle_feedback_message_new (fb->type,
- fb->subtype));
- }
-
- return new.head;
-}
-
-static void
-jingle_feedback_message_list_free (GList *fbs)
-{
- while (fbs != NULL)
- {
- jingle_feedback_message_free (fbs->data);
- fbs = g_list_delete_link (fbs, fbs);
- }
-}
-
-void
-jingle_media_rtp_codec_free (JingleCodec *p)
-{
- g_hash_table_unref (p->params);
- g_free (p->name);
- jingle_feedback_message_list_free (p->feedback_msgs);
- g_slice_free (JingleCodec, p);
-}
-
-static void
-add_codec_to_table (JingleCodec *codec,
- GHashTable *table)
-{
- g_hash_table_insert (table, GUINT_TO_POINTER ((guint) codec->id), codec);
-}
-
-static GHashTable *
-build_codec_table (GList *codecs)
-{
- GHashTable *table = g_hash_table_new (NULL, NULL);
-
- g_list_foreach (codecs, (GFunc) add_codec_to_table, table);
- return table;
-}
-
-GList *
-jingle_media_rtp_copy_codecs (GList *codecs)
-{
- GList *ret = NULL, *l;
-
- for (l = codecs; l != NULL; l = g_list_next (l))
- {
- JingleCodec *c = l->data;
- JingleCodec *newc = jingle_media_rtp_codec_new (c->id,
- c->name, c->clockrate, c->channels, c->params);
- newc->trr_int = c->trr_int;
- ret = g_list_append (ret, newc);
- }
-
- return ret;
-}
-
-void
-jingle_media_rtp_free_codecs (GList *codecs)
-{
- while (codecs != NULL)
- {
- jingle_media_rtp_codec_free (codecs->data);
- codecs = g_list_delete_link (codecs, codecs);
- }
-}
-
-static void
-gabble_jingle_media_rtp_dispose (GObject *object)
-{
- GabbleJingleMediaRtp *trans = GABBLE_JINGLE_MEDIA_RTP (object);
- GabbleJingleMediaRtpPrivate *priv = trans->priv;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- if (priv->remote_media_description != NULL)
- jingle_media_description_free (priv->remote_media_description);
- priv->remote_media_description = NULL;
-
- if (priv->local_media_description != NULL)
- jingle_media_description_free (priv->local_media_description);
- priv->local_media_description = NULL;
-
- if (priv->local_codec_updates != NULL)
- {
- DEBUG ("We have an unsent codec parameter update! Weird.");
-
- g_list_free (priv->local_codec_updates);
- priv->local_codec_updates = NULL;
- }
-
- if (G_OBJECT_CLASS (gabble_jingle_media_rtp_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_jingle_media_rtp_parent_class)->dispose (object);
-}
-
-static void
-gabble_jingle_media_rtp_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleMediaRtp *trans = GABBLE_JINGLE_MEDIA_RTP (object);
- GabbleJingleMediaRtpPrivate *priv = trans->priv;
-
- switch (property_id) {
- case PROP_MEDIA_TYPE:
- g_value_set_uint (value, priv->media_type);
- break;
- case PROP_REMOTE_MUTE:
- g_value_set_boolean (value, priv->remote_mute);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_jingle_media_rtp_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleMediaRtp *trans = GABBLE_JINGLE_MEDIA_RTP (object);
- GabbleJingleMediaRtpPrivate *priv = trans->priv;
-
- switch (property_id) {
- case PROP_MEDIA_TYPE:
- priv->media_type = g_value_get_uint (value);
- break;
- case PROP_REMOTE_MUTE:
- priv->remote_mute = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void parse_description (GabbleJingleContent *content,
- WockyNode *desc_node, GError **error);
-static void produce_description (GabbleJingleContent *obj,
- WockyNode *content_node);
-static void transport_created (GabbleJingleContent *obj,
- GabbleJingleTransportIface *transport);
-
-static void
-gabble_jingle_media_rtp_class_init (GabbleJingleMediaRtpClass *cls)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (cls);
- GabbleJingleContentClass *content_class = GABBLE_JINGLE_CONTENT_CLASS (cls);
- GParamSpec *param_spec;
-
- g_type_class_add_private (cls, sizeof (GabbleJingleMediaRtpPrivate));
-
- object_class->get_property = gabble_jingle_media_rtp_get_property;
- object_class->set_property = gabble_jingle_media_rtp_set_property;
- object_class->dispose = gabble_jingle_media_rtp_dispose;
-
- content_class->parse_description = parse_description;
- content_class->produce_description = produce_description;
- content_class->transport_created = transport_created;
-
- param_spec = g_param_spec_uint ("media-type", "RTP media type",
- "Media type.",
- JINGLE_MEDIA_TYPE_NONE, G_MAXUINT32, JINGLE_MEDIA_TYPE_NONE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MEDIA_TYPE, param_spec);
-
- param_spec = g_param_spec_boolean ("remote-mute", "Remote mute",
- "TRUE if the peer has muted this stream", FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_REMOTE_MUTE, param_spec);
-
- /* signal definitions */
-
- signals[REMOTE_MEDIA_DESCRIPTION] = g_signal_new ("remote-media-description",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-}
-
-static void transport_created (GabbleJingleContent *content,
- GabbleJingleTransportIface *transport)
-{
- GabbleJingleMediaRtp *self = GABBLE_JINGLE_MEDIA_RTP (content);
- GabbleJingleMediaRtpPrivate *priv = self->priv;
- GabbleJingleTransportGoogle *gtrans = NULL;
- JingleDialect dialect;
-
- if (GABBLE_IS_JINGLE_TRANSPORT_GOOGLE (transport))
- {
- gtrans = GABBLE_JINGLE_TRANSPORT_GOOGLE (transport);
- dialect = gabble_jingle_session_get_dialect (content->session);
-
- if (priv->media_type == JINGLE_MEDIA_TYPE_VIDEO &&
- (JINGLE_IS_GOOGLE_DIALECT (dialect) ||
- gabble_jingle_session_peer_has_cap (content->session,
- QUIRK_GOOGLE_WEBMAIL_CLIENT) ||
- gabble_jingle_session_peer_has_cap (content->session,
- QUIRK_ANDROID_GTALK_CLIENT)))
- {
- jingle_transport_google_set_component_name (gtrans, "video_rtp", 1);
- jingle_transport_google_set_component_name (gtrans, "video_rtcp", 2);
- }
- else
- {
- jingle_transport_google_set_component_name (gtrans, "rtp", 1);
- jingle_transport_google_set_component_name (gtrans, "rtcp", 2);
- }
- }
-}
-
-
-static JingleMediaType
-extract_media_type (WockyNode *desc_node,
- GError **error)
-{
- if (wocky_node_has_ns (desc_node, NS_JINGLE_RTP))
- {
- const gchar *type = wocky_node_get_attribute (desc_node, "media");
-
- if (type == NULL)
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "missing required media type attribute");
- return JINGLE_MEDIA_TYPE_NONE;
- }
-
- if (!wocky_strdiff (type, "audio"))
- return JINGLE_MEDIA_TYPE_AUDIO;
-
- if (!wocky_strdiff (type, "video"))
- return JINGLE_MEDIA_TYPE_VIDEO;
-
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "unknown media type %s", type);
- return JINGLE_MEDIA_TYPE_NONE;
- }
-
- if (wocky_node_has_ns (desc_node, NS_JINGLE_DESCRIPTION_AUDIO))
- return JINGLE_MEDIA_TYPE_AUDIO;
-
- if (wocky_node_has_ns (desc_node, NS_JINGLE_DESCRIPTION_VIDEO))
- return JINGLE_MEDIA_TYPE_VIDEO;
-
- if (wocky_node_has_ns (desc_node, NS_GOOGLE_SESSION_PHONE))
- return JINGLE_MEDIA_TYPE_AUDIO;
-
- if (wocky_node_has_ns (desc_node, NS_GOOGLE_SESSION_VIDEO))
- return JINGLE_MEDIA_TYPE_VIDEO;
-
- /* If we get here, namespace in use is not one of namespaces we signed up
- * with, so obviously a bug somewhere.
- */
- g_assert_not_reached ();
-}
-
-static JingleFeedbackMessage *
-parse_rtcp_fb (GabbleJingleContent *content, WockyNode *node)
-{
- const gchar *pt_ns = wocky_node_get_ns (node);
- const gchar *type;
- const gchar *subtype;
-
- if (wocky_strdiff (pt_ns, NS_JINGLE_RTCP_FB))
- return NULL;
-
- type = wocky_node_get_attribute (node, "type");
- if (type == NULL)
- return NULL;
-
- subtype = wocky_node_get_attribute (node, "subtype");
-
- /* This is optional, defaults to "" */
- if (subtype == NULL)
- subtype = "";
-
- return jingle_feedback_message_new (type, subtype);
-}
-
-
-/*
- * Returns G_MAXUINT on error
- */
-static guint
-parse_rtcp_fb_trr_int (GabbleJingleContent *content, WockyNode *node)
-{
- const gchar *pt_ns = wocky_node_get_ns (node);
- const gchar *txt;
- guint trr_int;
- gchar *endptr = NULL;
-
- if (wocky_strdiff (pt_ns, NS_JINGLE_RTCP_FB))
- return G_MAXUINT;
-
- txt = wocky_node_get_attribute (node, "value");
- if (txt == NULL)
- return G_MAXUINT;
-
- trr_int = strtol (txt, &endptr, 10);
- if (endptr == NULL || endptr == txt)
- return G_MAXUINT;
-
- return trr_int;
-}
-
-
-/**
- * parse_payload_type:
- * @node: a <payload-type> node.
- *
- * Returns: a newly-allocated JingleCodec if parsing succeeds, or %NULL
- * otherwise.
- */
-static JingleCodec *
-parse_payload_type (GabbleJingleContent *content,
- WockyNode *node)
-{
- GabbleJingleMediaRtp *self = GABBLE_JINGLE_MEDIA_RTP (content);
- GabbleJingleMediaRtpPrivate *priv = self->priv;
- JingleCodec *p;
- const char *txt;
- guint8 id;
- const gchar *name;
- guint clockrate = 0;
- guint channels = 0;
- WockyNode *param;
- WockyNodeIter i;
-
- txt = wocky_node_get_attribute (node, "id");
- if (txt == NULL)
- return NULL;
-
- id = atoi (txt);
-
- name = wocky_node_get_attribute (node, "name");
- if (name == NULL)
- name = "";
-
- /* xep-0167 v0.22, gtalk libjingle 0.3/0.4 use "clockrate" */
- txt = wocky_node_get_attribute (node, "clockrate");
- /* older jingle rtp used "rate" ? */
- if (txt == NULL)
- txt = wocky_node_get_attribute (node, "rate");
-
- if (txt != NULL)
- clockrate = atoi (txt);
-
- txt = wocky_node_get_attribute (node, "channels");
- if (txt != NULL)
- channels = atoi (txt);
-
- p = jingle_media_rtp_codec_new (id, name, clockrate, channels, NULL);
-
- wocky_node_iter_init (&i, node, NULL, NULL);
- while (wocky_node_iter_next (&i, &param))
- {
- if (!wocky_strdiff (param->name, "parameter"))
- {
- const gchar *param_name, *param_value;
-
- param_name = wocky_node_get_attribute (param, "name");
- param_value = wocky_node_get_attribute (param, "value");
-
- if (param_name == NULL || param_value == NULL)
- continue;
-
- g_hash_table_insert (p->params, g_strdup (param_name),
- g_strdup (param_value));
- }
- else if (!wocky_strdiff (param->name, "rtcp-fb"))
- {
- JingleFeedbackMessage *fb = parse_rtcp_fb (content, param);
-
- if (fb != NULL)
- {
- p->feedback_msgs = g_list_append (p->feedback_msgs, fb);
- priv->has_rtcp_fb = TRUE;
- }
- }
- else if (!wocky_strdiff (param->name,
- "rtcp-fb-trr-int"))
- {
- guint trr_int = parse_rtcp_fb_trr_int (content, param);
-
- if (trr_int != G_MAXUINT)
- {
- p->trr_int = trr_int;
- priv->has_rtcp_fb = TRUE;
- }
- }
- }
-
- DEBUG ("new remote codec: id = %u, name = %s, clockrate = %u, channels = %u",
- p->id, p->name, p->clockrate, p->channels);
-
- return p;
-}
-
-static JingleRtpHeaderExtension *
-parse_rtp_header_extension (WockyNode *node)
-{
- guint id;
- JingleContentSenders senders;
- const gchar *uri;
- const char *txt;
-
- txt = wocky_node_get_attribute (node, "id");
- if (txt == NULL)
- return NULL;
-
- id = atoi (txt);
-
- /* Only valid ranges are 1-256 and 4096-4351 */
- if ((id < 1 || id > 256) && (id < 4096 || id > 4351))
- return NULL;
-
- txt = wocky_node_get_attribute (node, "senders");
-
- if (txt == NULL || !g_ascii_strcasecmp (txt, "both"))
- senders = JINGLE_CONTENT_SENDERS_BOTH;
- else if (!g_ascii_strcasecmp (txt, "initiator"))
- senders = JINGLE_CONTENT_SENDERS_INITIATOR;
- else if (!g_ascii_strcasecmp (txt, "responder"))
- senders = JINGLE_CONTENT_SENDERS_RESPONDER;
- else
- return NULL;
-
- uri = wocky_node_get_attribute (node, "uri");
-
- if (uri == NULL)
- return NULL;
-
- return jingle_rtp_header_extension_new (id, senders, uri);
-}
-
-
-/**
- * codec_update_coherent:
- * @old_c: Gabble's old cache of the codec, or %NULL if it hasn't heard of it.
- * @new_c: the proposed update, whose id must equal that of @old_c if the
- * latter is non-NULL.
- * @domain: the error domain to set @e to if necessary
- * @code: the error code to set @e to if necessary
- * @e: location to hold an error
- *
- * Compares @old_c and @new_c, which are assumed to have the same id, to check
- * that the name, clockrate and number of channels hasn't changed. If they
- * have, returns %FALSE and sets @e.
- */
-static gboolean
-codec_update_coherent (const JingleCodec *old_c,
- const JingleCodec *new_c,
- GError **e)
-{
- const GQuark domain = WOCKY_XMPP_ERROR;
- const gint code = WOCKY_XMPP_ERROR_BAD_REQUEST;
-
- if (old_c == NULL)
- {
- g_set_error (e, domain, code, "Codec with id %u ('%s') unknown",
- new_c->id, new_c->name);
- return FALSE;
- }
-
- if (g_ascii_strcasecmp (new_c->name, old_c->name))
- {
- g_set_error (e, domain, code,
- "tried to change codec %u's name from %s to %s",
- new_c->id, old_c->name, new_c->name);
- return FALSE;
- }
-
- if (new_c->clockrate != old_c->clockrate)
- {
- g_set_error (e, domain, code,
- "tried to change codec %u (%s)'s clockrate from %u to %u",
- new_c->id, new_c->name, old_c->clockrate, new_c->clockrate);
- return FALSE;
- }
-
- if (old_c->channels != 0 &&
- new_c->channels != old_c->channels)
- {
- g_set_error (e, domain, code,
- "tried to change codec %u (%s)'s channels from %u to %u",
- new_c->id, new_c->name, new_c->channels, old_c->channels);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-update_remote_media_description (GabbleJingleMediaRtp *self,
- JingleMediaDescription *new_media_description,
- GError **error)
-{
- GabbleJingleMediaRtpPrivate *priv = self->priv;
- GHashTable *rc = NULL;
- JingleCodec *old_c, *new_c;
- GList *l;
- GError *e = NULL;
-
- if (priv->remote_media_description == NULL)
- {
- priv->remote_media_description = new_media_description;
- new_media_description = NULL;
- goto out;
- }
-
- rc = build_codec_table (priv->remote_media_description->codecs);
-
- /* We already know some remote codecs, so this is just the other end updating
- * some parameters.
- */
- for (l = new_media_description->codecs; l != NULL; l = l->next)
- {
- new_c = l->data;
- old_c = g_hash_table_lookup (rc, GUINT_TO_POINTER ((guint) new_c->id));
-
- if (!codec_update_coherent (old_c, new_c, &e))
- goto out;
- }
-
- /* Okay, all the updates are cool. Let's switch the parameters around. */
- for (l = new_media_description->codecs; l != NULL; l = l->next)
- {
- GHashTable *params;
-
- new_c = l->data;
- old_c = g_hash_table_lookup (rc, GUINT_TO_POINTER ((guint) new_c->id));
-
- params = old_c->params;
- old_c->params = new_c->params;
- new_c->params = params;
- }
-
-out:
- if (new_media_description != NULL)
- jingle_media_description_free (new_media_description);
-
- if (rc != NULL)
- g_hash_table_unref (rc);
-
- if (e != NULL)
- {
- DEBUG ("Rejecting codec update: %s", e->message);
- g_propagate_error (error, e);
- }
- else
- {
- DEBUG ("Emitting remote-media-description signal");
- g_signal_emit (self, signals[REMOTE_MEDIA_DESCRIPTION], 0,
- priv->remote_media_description);
- }
-}
-
-static void
-parse_description (GabbleJingleContent *content,
- WockyNode *desc_node, GError **error)
-{
- GabbleJingleMediaRtp *self = GABBLE_JINGLE_MEDIA_RTP (content);
- GabbleJingleMediaRtpPrivate *priv = self->priv;
- JingleMediaType mtype;
- JingleMediaDescription *md;
- JingleCodec *p;
- JingleDialect dialect = gabble_jingle_session_get_dialect (content->session);
- gboolean video_session = FALSE;
- WockyNodeIter i;
- WockyNode *node;
- gboolean description_error = FALSE;
- gboolean is_avpf = FALSE;
-
- DEBUG ("node: %s", desc_node->name);
-
- if (priv->media_type == JINGLE_MEDIA_TYPE_NONE)
- mtype = extract_media_type (desc_node, error);
- else
- mtype = priv->media_type;
-
- if (mtype == JINGLE_MEDIA_TYPE_NONE)
- return;
-
- DEBUG ("detected media type %u", mtype);
-
- if (dialect == JINGLE_DIALECT_GTALK3)
- {
- const gchar *desc_ns =
- wocky_node_get_ns (desc_node);
- video_session = !wocky_strdiff (desc_ns, NS_GOOGLE_SESSION_VIDEO);
- }
-
- md = jingle_media_description_new ();
-
- wocky_node_iter_init (&i, desc_node, NULL, NULL);
- while (wocky_node_iter_next (&i, &node) && !description_error)
- {
- if (!wocky_strdiff (node->name, "payload-type"))
- {
- if (dialect == JINGLE_DIALECT_GTALK3)
- {
- const gchar *pt_ns = wocky_node_get_ns (node);
-
- if (priv->media_type == JINGLE_MEDIA_TYPE_AUDIO)
- {
- if (video_session &&
- wocky_strdiff (pt_ns, NS_GOOGLE_SESSION_PHONE))
- continue;
- }
- else if (priv->media_type == JINGLE_MEDIA_TYPE_VIDEO)
- {
- if (!(video_session && pt_ns == NULL)
- && wocky_strdiff (pt_ns, NS_GOOGLE_SESSION_VIDEO))
- continue;
- }
- }
-
- p = parse_payload_type (content, node);
-
- if (p == NULL)
- {
- description_error = TRUE;
- }
- else
- {
- md->codecs = g_list_append (md->codecs, p);
- if (p->trr_int != G_MAXUINT || p->feedback_msgs)
- is_avpf = TRUE;
- }
- }
- else if (!wocky_strdiff (node->name, "rtp-hdrext"))
- {
- const gchar *pt_ns = wocky_node_get_ns (node);
- JingleRtpHeaderExtension *hdrext;
-
- if (wocky_strdiff (pt_ns, NS_JINGLE_RTP_HDREXT))
- continue;
-
- hdrext = parse_rtp_header_extension (node);
-
- if (hdrext == NULL)
- {
- description_error = TRUE;
- }
- else
- {
- md->hdrexts = g_list_append (md->hdrexts, hdrext);
- priv->has_rtp_hdrext = TRUE;
- }
-
- }
- else if (!wocky_strdiff (node->name, "rtcp-fb"))
- {
- JingleFeedbackMessage *fb = parse_rtcp_fb (content, node);
-
- if (fb == NULL)
- {
- description_error = TRUE;
- }
- else
- {
- md->feedback_msgs = g_list_append (md->feedback_msgs, fb);
- is_avpf = TRUE;
- priv->has_rtcp_fb = TRUE;
- }
- }
- else if (!wocky_strdiff (node->name, "rtcp-fb-trr-int"))
- {
- guint trr_int = parse_rtcp_fb_trr_int (content, node);
-
- if (trr_int == G_MAXUINT)
- {
- description_error = TRUE;
- }
- else
- {
- md->trr_int = trr_int;
- is_avpf = TRUE;
- priv->has_rtcp_fb = TRUE;
- }
- }
- }
-
- if (description_error)
- {
- /* rollback these */
- jingle_media_description_free (md);
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "invalid description");
- return;
- }
-
- /* If the profile is AVPF, the trr-int default to 0 */
- if (is_avpf && md->trr_int == G_MAXUINT)
- md->trr_int = 0;
-
- priv->media_type = mtype;
-
- update_remote_media_description (self, md, error);
-}
-
-/* The Google Talk desktop client is picky about the case of codec names, even
- * though SDP defines them to be case-insensitive. The particular case that was
- * causing problems was ILBC vs iLBC, but it seems safer to special-case the
- * lot. This list is taken from the initiate sent by the desktop client on
- * 2009-07-01.
- */
-static const gchar * const codec_cases[] = {
- "CN",
- "EG711A",
- "EG711U",
- "G723",
- "IPCMWB",
- "ISAC",
- "PCMA",
- "PCMU",
- "iLBC",
- "speex",
- "telephone-event",
- NULL
-};
-
-static const gchar *
-gtalk_case (const gchar *codec)
-{
- const gchar * const *ret = codec_cases;
-
- for (; *ret != NULL; ret++)
- if (g_ascii_strcasecmp (*ret, codec) == 0)
- return *ret;
-
- return codec;
-}
-
-static void
-_produce_extra_param (gpointer key, gpointer value, gpointer user_data)
-{
- WockyNode *pt_node = user_data;
- WockyNode *param;
- gchar *param_name = key;
- gchar *param_value = value;
-
- param = wocky_node_add_child_with_content (pt_node, "parameter", NULL);
- wocky_node_set_attribute (param, "name", param_name);
- wocky_node_set_attribute (param, "value", param_value);
-}
-
-static void
-produce_rtcp_fb_trr_int (WockyNode *node,
- guint trr_int)
-{
- WockyNode *trr_int_node;
- gchar tmp[10];
-
- if (trr_int == G_MAXUINT || trr_int == 0)
- return;
-
- trr_int_node = wocky_node_add_child_ns (node, "rtcp-fb-trr-int",
- NS_JINGLE_RTCP_FB);
- snprintf (tmp, 9, "%d", trr_int);
- wocky_node_set_attribute (trr_int_node, "value", tmp);
-}
-
-
-static void
-produce_rtcp_fb (JingleFeedbackMessage *fb, WockyNode *node)
-{
- WockyNode *fb_node;
-
- fb_node = wocky_node_add_child (node, "rtcp-fb");
-
- wocky_node_set_attribute (fb_node, "xmlns", NS_JINGLE_RTCP_FB);
- wocky_node_set_attribute (fb_node, "type", fb->type);
-
- if (fb->subtype != NULL && fb->subtype[0] != 0)
- wocky_node_set_attribute (fb_node, "subtype", fb->subtype);
-}
-
-static void
-produce_payload_type (GabbleJingleContent *content,
- WockyNode *desc_node,
- JingleMediaType type,
- JingleCodec *p,
- JingleDialect dialect)
-{
- GabbleJingleMediaRtp *self = GABBLE_JINGLE_MEDIA_RTP (content);
- GabbleJingleMediaRtpPrivate *priv = self->priv;
- WockyNode *pt_node;
- gchar buf[16];
-
- pt_node = wocky_node_add_child_with_content (desc_node, "payload-type", NULL);
-
- /* id: required */
- sprintf (buf, "%d", p->id);
- wocky_node_set_attribute (pt_node, "id", buf);
-
- if (dialect == JINGLE_DIALECT_GTALK3)
- {
- if (type == JINGLE_MEDIA_TYPE_AUDIO)
- {
- /* Gtalk 03 has either an audio or a video session, in case of a
- * video session the audio codecs need to set their namespace to
- * NS_GOOGLE_SESSION_PHONE. In the case of an audio session it
- * doesn't matter, so just always set the namespace on audio
- * payloads.
- */
- pt_node->ns = g_quark_from_static_string (
- NS_GOOGLE_SESSION_PHONE);
- }
- else
- {
- /* If width, height and framerate aren't set the google server ignore
- * our initiate.. These are a recv parameters, to it doesn't matter
- * for what we're sending, just for what we're getting.. 320x240
- * seems a sane enough default */
- wocky_node_set_attributes (pt_node,
- "width", "320",
- "height", "240",
- "framerate", "30",
- NULL);
- }
-
- }
-
- /* name: optional */
- if (*p->name != '\0')
- {
- if (JINGLE_IS_GOOGLE_DIALECT (dialect))
- wocky_node_set_attribute (pt_node, "name", gtalk_case (p->name));
- else
- wocky_node_set_attribute (pt_node, "name", p->name);
- }
-
- /* clock rate: optional */
- if (p->clockrate != 0)
- {
- const gchar *attname = "clockrate";
-
- if (dialect == JINGLE_DIALECT_V015)
- attname = "rate";
-
- sprintf (buf, "%u", p->clockrate);
- wocky_node_set_attribute (pt_node, attname, buf);
- }
-
- if (p->channels != 0)
- {
- sprintf (buf, "%u", p->channels);
- wocky_node_set_attribute (pt_node, "channels", buf);
- }
-
- if (p->params != NULL)
- g_hash_table_foreach (p->params, _produce_extra_param, pt_node);
-
-
- if (priv->has_rtcp_fb)
- {
- g_list_foreach (p->feedback_msgs, (GFunc) produce_rtcp_fb, pt_node);
- produce_rtcp_fb_trr_int (pt_node, p->trr_int);
- }
-}
-
-static WockyNode *
-produce_description_node (JingleDialect dialect, JingleMediaType media_type,
- WockyNode *content_node)
-{
- WockyNode *desc_node;
- const gchar *xmlns = NULL;
-
- if (dialect == JINGLE_DIALECT_GTALK3)
- return NULL;
-
- desc_node = wocky_node_add_child_with_content (content_node, "description", NULL);
-
- switch (dialect)
- {
- case JINGLE_DIALECT_GTALK4:
- g_assert (media_type == JINGLE_MEDIA_TYPE_AUDIO);
- xmlns = NS_GOOGLE_SESSION_PHONE;
- break;
- case JINGLE_DIALECT_V015:
- if (media_type == JINGLE_MEDIA_TYPE_AUDIO)
- xmlns = NS_JINGLE_DESCRIPTION_AUDIO;
- else if (media_type == JINGLE_MEDIA_TYPE_VIDEO)
- xmlns = NS_JINGLE_DESCRIPTION_VIDEO;
- else
- {
- DEBUG ("unknown media type %u", media_type);
- xmlns = "";
- }
- break;
- default:
- xmlns = NS_JINGLE_RTP;
- if (media_type == JINGLE_MEDIA_TYPE_AUDIO)
- wocky_node_set_attribute (desc_node, "media", "audio");
- else if (media_type == JINGLE_MEDIA_TYPE_VIDEO)
- wocky_node_set_attribute (desc_node, "media", "video");
- else
- g_assert_not_reached ();
- break;
- }
-
- desc_node->ns = g_quark_from_string (xmlns);
-
- return desc_node;
-}
-
-static void
-produce_hdrext (gpointer data, gpointer user_data)
-{
- JingleRtpHeaderExtension *hdrext = data;
- WockyNode *desc_node = user_data;
- WockyNode *hdrext_node;
- gchar buf[16];
-
- hdrext_node = wocky_node_add_child (desc_node, "rtp-hdrext");
-
- /* id: required */
- sprintf (buf, "%d", hdrext->id);
- wocky_node_set_attribute (hdrext_node, "id", buf);
- wocky_node_set_attribute (hdrext_node, "uri", hdrext->uri);
-
- if (hdrext->senders == JINGLE_CONTENT_SENDERS_INITIATOR)
- wocky_node_set_attribute (hdrext_node, "senders", "initiator");
- else if (hdrext->senders == JINGLE_CONTENT_SENDERS_RESPONDER)
- wocky_node_set_attribute (hdrext_node, "senders", "responder");
-
- wocky_node_set_attribute (hdrext_node, "xmlns", NS_JINGLE_RTP_HDREXT);
-}
-
-static void
-produce_description (GabbleJingleContent *content, WockyNode *content_node)
-{
- GabbleJingleMediaRtp *self = GABBLE_JINGLE_MEDIA_RTP (content);
- GabbleJingleMediaRtpPrivate *priv = self->priv;
- GList *li;
- JingleDialect dialect = gabble_jingle_session_get_dialect (content->session);
- WockyNode *desc_node;
-
- if (gabble_jingle_session_peer_has_cap (content->session, NS_JINGLE_RTCP_FB))
- priv->has_rtcp_fb = TRUE;
-
- if (gabble_jingle_session_peer_has_cap (content->session, NS_JINGLE_RTP_HDREXT))
- priv->has_rtp_hdrext = TRUE;
-
- desc_node = produce_description_node (dialect, priv->media_type,
- content_node);
-
- /* For GTalk3 the description is added by the session */
- if (desc_node == NULL)
- desc_node = content_node;
-
- /* If we're only updating our codec parameters, only generate payload-types
- * for those.
- */
- if (priv->local_codec_updates != NULL)
- li = priv->local_codec_updates;
- else
- li = priv->local_media_description->codecs;
-
- for (; li != NULL; li = li->next)
- produce_payload_type (content, desc_node, priv->media_type, li->data,
- dialect);
-
- if (priv->has_rtp_hdrext && priv->local_media_description->hdrexts)
- g_list_foreach (priv->local_media_description->hdrexts, produce_hdrext,
- desc_node);
-
- if (priv->has_rtcp_fb)
- {
- g_list_foreach (priv->local_media_description->feedback_msgs,
- (GFunc) produce_rtcp_fb, desc_node);
- produce_rtcp_fb_trr_int (desc_node,
- priv->local_media_description->trr_int);
- }
-}
-
-/**
- * string_string_maps_equal:
- *
- * Returns: TRUE iff @a and @b contain exactly the same keys and values when
- * compared as strings.
- */
-static gboolean
-string_string_maps_equal (GHashTable *a,
- GHashTable *b)
-{
- GHashTableIter iter;
- gpointer a_key, a_value, b_value;
-
- if (g_hash_table_size (a) != g_hash_table_size (b))
- return FALSE;
-
- g_hash_table_iter_init (&iter, a);
-
- while (g_hash_table_iter_next (&iter, &a_key, &a_value))
- {
- if (!g_hash_table_lookup_extended (b, a_key, NULL, &b_value))
- return FALSE;
-
- if (wocky_strdiff (a_value, b_value))
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * compare_codecs:
- * @old: previous local codecs
- * @new: new local codecs supplied by streaming implementation
- * @changed: location at which to store the changed codecs
- * @error: location at which to store an error if the update was invalid
- *
- * Returns: %TRUE if the update made sense, %FALSE with @error set otherwise
- */
-gboolean
-jingle_media_rtp_compare_codecs (GList *old,
- GList *new,
- GList **changed,
- GError **e)
-{
- gboolean ret = FALSE;
- GHashTable *old_table = build_codec_table (old);
- GList *l;
- JingleCodec *old_c, *new_c;
-
- g_assert (changed != NULL && *changed == NULL);
-
- for (l = new; l != NULL; l = l->next)
- {
- new_c = l->data;
- old_c = g_hash_table_lookup (old_table, GUINT_TO_POINTER (
- (guint) new_c->id));
-
- if (!codec_update_coherent (old_c, new_c, e))
- goto out;
-
- if (!string_string_maps_equal (old_c->params, new_c->params))
- *changed = g_list_prepend (*changed, new_c);
- }
-
- ret = TRUE;
-
-out:
- if (!ret)
- {
- g_list_free (*changed);
- *changed = NULL;
- }
-
- g_hash_table_unref (old_table);
- return ret;
-}
-
-/*
- * @self: a content in an RTP session
- * @md: (transfer full): new media description for this content
- * @ready: whether the codecs can regarded as ready to sent from now on
- * @error: used to return a %WOCKY_XMPP_ERROR if the codec update is illegal.
- *
- * Sets or updates the media description (codecs, feedback messages, etc) for
- * @self.
- *
- * Returns: %TRUE if no description was previously set, or if the update is
- * compatible with the existing description; %FALSE if the update is illegal
- * (due to adding previously-unknown codecs or renaming an existing codec, for
- * example)
- */
-gboolean
-jingle_media_rtp_set_local_media_description (GabbleJingleMediaRtp *self,
- JingleMediaDescription *md,
- gboolean ready,
- GError **error)
-{
- GabbleJingleMediaRtpPrivate *priv = self->priv;
-
- DEBUG ("setting new local media description");
-
- if (priv->local_media_description != NULL)
- {
- GList *changed = NULL;
- GError *err = NULL;
-
- g_assert (priv->local_codec_updates == NULL);
-
- if (!jingle_media_rtp_compare_codecs (
- priv->local_media_description->codecs,
- md->codecs, &changed, &err))
- {
- DEBUG ("codec update was illegal: %s", err->message);
- jingle_media_description_free (md);
- g_propagate_error (error, err);
- return FALSE;
- }
-
- if (changed == NULL)
- {
- DEBUG ("codec update changed nothing!");
- jingle_media_description_free (md);
- goto out;
- }
-
- DEBUG ("%u codecs changed", g_list_length (changed));
- priv->local_codec_updates = changed;
-
- jingle_media_description_free (priv->local_media_description);
- }
-
- priv->local_media_description = md;
-
- /* Codecs have changed, sending a fresh description might be necessary */
- gabble_jingle_content_maybe_send_description (GABBLE_JINGLE_CONTENT (self));
-
- /* Update done if any, free the changed codecs if any */
- g_list_free (priv->local_codec_updates);
- priv->local_codec_updates = NULL;
-
-out:
- if (ready)
- _gabble_jingle_content_set_media_ready (GABBLE_JINGLE_CONTENT (self));
-
- return TRUE;
-}
-
-void
-jingle_media_rtp_register (GabbleJingleFactory *factory)
-{
- /* Current (v0.25) Jingle draft URI */
- gabble_jingle_factory_register_content_type (factory,
- NS_JINGLE_RTP, GABBLE_TYPE_JINGLE_MEDIA_RTP);
-
- /* Old Jingle audio/video namespaces */
- gabble_jingle_factory_register_content_type (factory,
- NS_JINGLE_DESCRIPTION_AUDIO,
- GABBLE_TYPE_JINGLE_MEDIA_RTP);
-
- gabble_jingle_factory_register_content_type (factory,
- NS_JINGLE_DESCRIPTION_VIDEO,
- GABBLE_TYPE_JINGLE_MEDIA_RTP);
-
- /* GTalk audio call namespace */
- gabble_jingle_factory_register_content_type (factory,
- NS_GOOGLE_SESSION_PHONE,
- GABBLE_TYPE_JINGLE_MEDIA_RTP);
-
- /* GTalk video call namespace */
- gabble_jingle_factory_register_content_type (factory,
- NS_GOOGLE_SESSION_VIDEO,
- GABBLE_TYPE_JINGLE_MEDIA_RTP);
-}
-
-/* We can't get remote media description when they're signalled, because
- * the signal is emitted immediately upon JingleContent creation,
- * and parsing, which is before a corresponding MediaStream is
- * created. */
-JingleMediaDescription *
-gabble_jingle_media_rtp_get_remote_media_description (
- GabbleJingleMediaRtp *self)
-{
- GabbleJingleMediaRtpPrivate *priv = self->priv;
-
- return priv->remote_media_description;
-}
-
-JingleMediaDescription *
-jingle_media_description_new (void)
-{
- JingleMediaDescription *md = g_slice_new0 (JingleMediaDescription);
-
- md->trr_int = G_MAXUINT;
-
- return md;
-}
-
-void
-jingle_media_description_free (JingleMediaDescription *md)
-{
- jingle_media_rtp_free_codecs (md->codecs);
-
- while (md->hdrexts != NULL)
- {
- jingle_rtp_header_extension_free (md->hdrexts->data);
- md->hdrexts = g_list_delete_link (md->hdrexts, md->hdrexts);
- }
-
- g_slice_free (JingleMediaDescription, md);
-}
-
-JingleMediaDescription *
-jingle_media_description_copy (JingleMediaDescription *md)
-{
- JingleMediaDescription *newmd = g_slice_new0 (JingleMediaDescription);
- GList *li;
-
- newmd->codecs = jingle_media_rtp_copy_codecs (md->codecs);
- newmd->feedback_msgs = jingle_feedback_message_list_copy (md->feedback_msgs);
- newmd->trr_int = md->trr_int;
-
- for (li = md->hdrexts; li; li = li->next)
- {
- JingleRtpHeaderExtension *h = li->data;
-
- newmd->hdrexts = g_list_append (newmd->hdrexts,
- jingle_rtp_header_extension_new (h->id, h->senders, h->uri));
- }
-
- return newmd;
-}
-
-JingleRtpHeaderExtension *
-jingle_rtp_header_extension_new (guint id, JingleContentSenders senders,
- const gchar *uri)
-{
- JingleRtpHeaderExtension *hdrext = g_slice_new (JingleRtpHeaderExtension);
-
- hdrext->id = id;
- hdrext->senders = senders;
- hdrext->uri = g_strdup (uri);
-
- return hdrext;
-}
-
-void
-jingle_rtp_header_extension_free (JingleRtpHeaderExtension *hdrext)
-{
- g_free (hdrext->uri);
- g_slice_free (JingleRtpHeaderExtension, hdrext);
-}
-
-JingleFeedbackMessage *
-jingle_feedback_message_new (const gchar *type, const gchar *subtype)
-{
- JingleFeedbackMessage *fb = g_slice_new0 (JingleFeedbackMessage);
-
- fb->type = g_strdup (type);
- fb->subtype = g_strdup (subtype);
-
- return fb;
-}
-
-void
-jingle_feedback_message_free (JingleFeedbackMessage *fb)
-{
- g_free (fb->type);
- g_free (fb->subtype);
- g_slice_free (JingleFeedbackMessage, fb);
-}
-
-
-static gint
-jingle_feedback_message_compare (const JingleFeedbackMessage *fb1,
- const JingleFeedbackMessage *fb2)
-{
- if (!g_ascii_strcasecmp (fb1->type, fb2->type) &&
- !g_ascii_strcasecmp (fb1->subtype, fb2->subtype))
- return 0;
- else
- return 1;
-}
-
-/**
- * jingle_media_description_simplify:
- *
- * Removes duplicated Feedback message and put them in the global structure
- *
- * This function will iterate over every codec in a description and look for
- * feedback messages that are exactly the same in every codec and will instead
- * put the in the list in the description and remove them from the childs.
- * This limits the amount of duplication in the resulting XML.
- */
-
-void
-jingle_media_description_simplify (JingleMediaDescription *md)
-{
- GList *item;
- guint trr_int = 0;
- gboolean trr_int_all_same = TRUE;
- gboolean init = FALSE;
- GList *identical_fbs = NULL;
-
- for (item = md->codecs; item; item = item->next)
- {
- JingleCodec *c = item->data;
-
- if (!init)
- {
- /* For the first codec, it stores the trr_int and the list
- * of feedback messages */
- trr_int = c->trr_int;
- identical_fbs = g_list_copy (c->feedback_msgs);
- init = TRUE;
- }
- else
- {
- GList *item2;
-
- /* For every subsequent codec, we check if the trr_int is the same */
-
- if (trr_int != c->trr_int)
- trr_int_all_same = FALSE;
-
- /* We also intersect the remembered list of feedback messages with
- * the list for that codec and remove any feedback message that isn't
- * in both
- */
-
- for (item2 = identical_fbs; item2;)
- {
- JingleFeedbackMessage *fb = identical_fbs->data;
- GList *next = item2->next;
-
- if (!g_list_find_custom (c->feedback_msgs, fb,
- (GCompareFunc) jingle_feedback_message_compare))
- identical_fbs = g_list_delete_link (identical_fbs, item2);
-
- item2 = next;
- }
-
- /* If the trr_int is not the same everywhere and there are not common
- * feedback messages, then stop
- */
- if (!trr_int_all_same && identical_fbs == NULL)
- break;
- }
- }
-
- if (trr_int_all_same && trr_int == G_MAXUINT)
- trr_int_all_same = FALSE;
-
- /* if the trr_int is the same everywhere, lets set it globally */
- if (trr_int_all_same)
- md->trr_int = trr_int;
-
- /* If there are feedback messages that are in every codec, put a copy of them
- * in the global structure
- */
- if (identical_fbs)
- {
- md->feedback_msgs = jingle_feedback_message_list_copy (identical_fbs);
- g_list_free (identical_fbs);
- }
-
- if (trr_int_all_same || md->feedback_msgs != NULL)
- for (item = md->codecs; item; item = item->next)
- {
- JingleCodec *c = item->data;
- GList *item2;
-
- /* If the trr_int is the same everywhere, lets put the default on
- * each codec, we have it in the main structure
- */
- if (trr_int_all_same)
- c->trr_int = G_MAXUINT;
-
- /* Find the feedback messages that were put in the main structure and
- * remove them from each codec
- */
- for (item2 = md->feedback_msgs; item2; item2 = item2->next)
- {
- GList *duplicated;
- JingleFeedbackMessage *fb = item2->data;
-
- while ((duplicated = g_list_find_custom (c->feedback_msgs, fb,
- (GCompareFunc) jingle_feedback_message_compare)) != NULL)
- {
- jingle_feedback_message_free (duplicated->data);
- c->feedback_msgs = g_list_delete_link (c->feedback_msgs,
- duplicated);
- }
- }
- }
-}
diff --git a/src/jingle-media-rtp.h b/src/jingle-media-rtp.h
deleted file mode 100644
index d904c8c10..000000000
--- a/src/jingle-media-rtp.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * jingle-media-rtp.h - Header for GabbleJingleMediaRtp
- * Copyright (C) 2008 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 __JINGLE_MEDIA_RTP_H__
-#define __JINGLE_MEDIA_RTP_H__
-
-#include <glib-object.h>
-
-#include "jingle-content.h"
-#include "jingle-types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleJingleMediaRtpClass GabbleJingleMediaRtpClass;
-
-GType gabble_jingle_media_rtp_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_MEDIA_RTP \
- (gabble_jingle_media_rtp_get_type ())
-#define GABBLE_JINGLE_MEDIA_RTP(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_MEDIA_RTP, \
- GabbleJingleMediaRtp))
-#define GABBLE_JINGLE_MEDIA_RTP_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_MEDIA_RTP, \
- GabbleJingleMediaRtpClass))
-#define GABBLE_IS_JINGLE_MEDIA_RTP(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_MEDIA_RTP))
-#define GABBLE_IS_JINGLE_MEDIA_RTP_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_MEDIA_RTP))
-#define GABBLE_JINGLE_MEDIA_RTP_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_MEDIA_RTP, \
- GabbleJingleMediaRtpClass))
-
-struct _GabbleJingleMediaRtpClass {
- GabbleJingleContentClass parent_class;
-};
-
-typedef struct _GabbleJingleMediaRtpPrivate GabbleJingleMediaRtpPrivate;
-
-struct _GabbleJingleMediaRtp {
- GabbleJingleContent parent;
- GabbleJingleMediaRtpPrivate *priv;
-};
-
-typedef struct {
- guint id;
- gchar *name;
- guint clockrate;
- guint channels;
- GHashTable *params;
- guint trr_int;
- GList *feedback_msgs;
-} JingleCodec;
-
-typedef struct {
- gchar *type;
- gchar *subtype;
-} JingleFeedbackMessage;
-
-typedef struct {
- guint id;
- JingleContentSenders senders;
- gchar *uri;
-} JingleRtpHeaderExtension;
-
-typedef struct {
- GList *codecs;
- GList *hdrexts;
- guint trr_int;
- GList *feedback_msgs;
-} JingleMediaDescription;
-
-void jingle_media_rtp_register (GabbleJingleFactory *factory);
-gboolean jingle_media_rtp_set_local_media_description (
- GabbleJingleMediaRtp *self, JingleMediaDescription *md, gboolean ready,
- GError **error);
-JingleMediaDescription *gabble_jingle_media_rtp_get_remote_media_description (
- GabbleJingleMediaRtp *self);
-
-JingleCodec * jingle_media_rtp_codec_new (guint id, const gchar *name,
- guint clockrate, guint channels, GHashTable *params);
-void jingle_media_rtp_codec_free (JingleCodec *p);
-void jingle_media_rtp_free_codecs (GList *codecs);
-GList * jingle_media_rtp_copy_codecs (GList *codecs);
-
-gboolean jingle_media_rtp_compare_codecs (GList *old,
- GList *new,
- GList **changed,
- GError **e);
-
-JingleMediaDescription *jingle_media_description_new (void);
-void jingle_media_description_free (JingleMediaDescription *md);
-JingleMediaDescription *jingle_media_description_copy (
- JingleMediaDescription *md);
-
-JingleRtpHeaderExtension *jingle_rtp_header_extension_new (guint id,
- JingleContentSenders senders, const gchar *uri);
-void jingle_rtp_header_extension_free (JingleRtpHeaderExtension *hdrext);
-
-
-JingleFeedbackMessage *jingle_feedback_message_new (const gchar *type,
- const gchar *subtype);
-void jingle_feedback_message_free (JingleFeedbackMessage *fb);
-void jingle_media_description_simplify (JingleMediaDescription *md);
-
-#endif /* __JINGLE_MEDIA_RTP_H__ */
-
diff --git a/src/jingle-mint.c b/src/jingle-mint.c
index f575cfd39..f41a504ea 100644
--- a/src/jingle-mint.c
+++ b/src/jingle-mint.c
@@ -1,5 +1,5 @@
/*
- * jingle-mint.c - creates and configures a GabbleJingleFactory
+ * jingle-mint.c - creates and configures a WockyJingleFactory
* Copyright ©2012 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
@@ -32,14 +32,13 @@
#include "connection.h"
#include "conn-presence.h"
-#include "jingle-factory.h"
-#include "jingle-session.h"
+#include "jingle-share.h"
#include "presence-cache.h"
struct _GabbleJingleMintPrivate {
GabbleConnection *conn;
- GabbleJingleFactory *factory;
+ WockyJingleFactory *factory;
};
enum {
@@ -65,12 +64,12 @@ static void connection_porter_available_cb (
gpointer user_data);
static void factory_new_session_cb (
- GabbleJingleFactory *factory,
- GabbleJingleSession *session,
+ WockyJingleFactory *factory,
+ WockyJingleSession *session,
gboolean initiated_locally,
gpointer user_data);
static gboolean factory_query_cap_cb (
- GabbleJingleFactory *factory,
+ WockyJingleFactory *factory,
WockyContact *contact,
const gchar *cap_or_quirk,
gpointer user_data);
@@ -177,7 +176,7 @@ gabble_jingle_mint_class_init (GabbleJingleMintClass *klass)
signals[INCOMING_SESSION] = g_signal_new ("incoming-session",
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GABBLE_TYPE_JINGLE_SESSION);
+ G_TYPE_NONE, 1, WOCKY_TYPE_JINGLE_SESSION);
}
GabbleJingleMint *
@@ -207,7 +206,7 @@ connection_status_changed_cb (
case TP_CONNECTION_STATUS_CONNECTED:
{
- GabbleJingleInfo *info = gabble_jingle_mint_get_info (self);
+ WockyJingleInfo *info = gabble_jingle_mint_get_info (self);
gchar *stun_server = NULL;
guint stun_port = 0;
@@ -217,7 +216,7 @@ connection_status_changed_cb (
NULL);
if (stun_server != NULL)
- gabble_jingle_info_take_stun_server (info,
+ wocky_jingle_info_take_stun_server (info,
stun_server, stun_port, FALSE);
g_object_get (priv->conn,
@@ -226,20 +225,21 @@ connection_status_changed_cb (
NULL);
if (stun_server != NULL)
- gabble_jingle_info_take_stun_server (info,
+ wocky_jingle_info_take_stun_server (info,
stun_server, stun_port, TRUE);
- if (priv->conn->features &
- GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO)
- {
- gabble_jingle_info_send_request (info);
- }
+ wocky_jingle_info_send_request (info,
+ /* FIXME: one day Wocky will know about caps and then we won't
+ * have to pass in a flag here.
+ */
+ !!(priv->conn->features &
+ GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO));
}
break;
case TP_CONNECTION_STATUS_DISCONNECTED:
if (priv->factory != NULL)
- gabble_jingle_factory_stop (priv->factory);
+ wocky_jingle_factory_stop (priv->factory);
break;
}
}
@@ -257,7 +257,9 @@ connection_porter_available_cb (
g_assert (conn->session != NULL);
g_assert (priv->factory == NULL);
- priv->factory = gabble_jingle_factory_new (conn->session);
+ priv->factory = wocky_jingle_factory_new (conn->session);
+
+ jingle_share_register (priv->factory);
tp_g_signal_connect_object (priv->factory, "new-session",
(GCallback) factory_new_session_cb, self, 0);
@@ -267,12 +269,12 @@ connection_porter_available_cb (
static void
session_about_to_initiate_cb (
- GabbleJingleSession *session,
+ WockyJingleSession *session,
gpointer user_data)
{
GabbleJingleMint *self = GABBLE_JINGLE_MINT (user_data);
GabbleJingleMintPrivate *priv = self->priv;
- const gchar *peer_jid = gabble_jingle_session_get_peer_jid (session);
+ const gchar *peer_jid = wocky_jingle_session_get_peer_jid (session);
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
TpHandle peer = tp_handle_ensure (contact_repo, peer_jid, NULL, NULL);
@@ -285,8 +287,8 @@ session_about_to_initiate_cb (
static void
factory_new_session_cb (
- GabbleJingleFactory *factory,
- GabbleJingleSession *session,
+ WockyJingleFactory *factory,
+ WockyJingleSession *session,
gboolean initiated_locally,
gpointer user_data)
{
@@ -303,7 +305,7 @@ factory_new_session_cb (
static gboolean
factory_query_cap_cb (
- GabbleJingleFactory *factory,
+ WockyJingleFactory *factory,
WockyContact *contact,
const gchar *cap_or_quirk,
gpointer user_data)
@@ -330,16 +332,16 @@ factory_query_cap_cb (
}
}
-GabbleJingleFactory *
+WockyJingleFactory *
gabble_jingle_mint_get_factory (
GabbleJingleMint *self)
{
return self->priv->factory;
}
-GabbleJingleInfo *
+WockyJingleInfo *
gabble_jingle_mint_get_info (
GabbleJingleMint *self)
{
- return gabble_jingle_factory_get_jingle_info (self->priv->factory);
+ return wocky_jingle_factory_get_jingle_info (self->priv->factory);
}
diff --git a/src/jingle-mint.h b/src/jingle-mint.h
index 90b52270a..6f7685077 100644
--- a/src/jingle-mint.h
+++ b/src/jingle-mint.h
@@ -1,5 +1,5 @@
/*
- * jingle-mint.h - creates and configures a GabbleJingleFactory
+ * jingle-mint.h - creates and configures a WockyJingleFactory
* Copyright ©2012 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
@@ -23,8 +23,7 @@
#include <glib-object.h>
#include "types.h"
-#include "jingle-info.h"
-#include "jingle-types.h"
+#include <wocky/wocky.h>
typedef struct _GabbleJingleMint GabbleJingleMint;
typedef struct _GabbleJingleMintClass GabbleJingleMintClass;
@@ -45,9 +44,9 @@ GType gabble_jingle_mint_get_type (void);
GabbleJingleMint *gabble_jingle_mint_new (
GabbleConnection *connection);
-GabbleJingleFactory *gabble_jingle_mint_get_factory (
+WockyJingleFactory *gabble_jingle_mint_get_factory (
GabbleJingleMint *self);
-GabbleJingleInfo *gabble_jingle_mint_get_info (
+WockyJingleInfo *gabble_jingle_mint_get_info (
GabbleJingleMint *self);
/* TYPE MACROS */
diff --git a/src/jingle-session.c b/src/jingle-session.c
deleted file mode 100644
index 0e266b92d..000000000
--- a/src/jingle-session.c
+++ /dev/null
@@ -1,2457 +0,0 @@
-/*
- * gabble-jingle-session.c - Source for GabbleJingleSession
- * Copyright (C) 2008 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 "config.h"
-#include "jingle-session.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#include <wocky/wocky.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "gabble/capabilities.h"
-#include "debug.h"
-#include "gabble-signals-marshal.h"
-#include "gabble-enumtypes.h"
-#include "jingle-content.h"
-#include "jingle-factory.h"
-/* FIXME: the RTP-specific bits of this file should be separated from the
- * generic Jingle code.
- */
-#include "jingle-media-rtp.h"
-#include "namespaces.h"
-
-G_DEFINE_TYPE(GabbleJingleSession, gabble_jingle_session, G_TYPE_OBJECT);
-
-/* signal enum */
-enum
-{
- NEW_CONTENT,
- REMOTE_STATE_CHANGED,
- TERMINATED,
- CONTENT_REJECTED,
- QUERY_CAP,
- ABOUT_TO_INITIATE,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_JINGLE_FACTORY = 1,
- PROP_PORTER,
- PROP_SESSION_ID,
- PROP_PEER_CONTACT,
- PROP_LOCAL_INITIATOR,
- PROP_STATE,
- PROP_DIALECT,
- PROP_LOCAL_HOLD,
- PROP_REMOTE_HOLD,
- PROP_REMOTE_RINGING,
- LAST_PROPERTY
-};
-
-struct _GabbleJingleSessionPrivate
-{
- /* Borrowed; the factory owns us. */
- GabbleJingleFactory *jingle_factory;
- WockyPorter *porter;
-
- WockyContact *peer_contact;
- /* Borrowed from peer_contact if it's a WockyResourceContact. */
- const gchar *peer_resource;
- gchar *peer_jid;
- /* Either borrowed from 'porter' or equal to peer_jid. */
- const gchar *initiator;
- gboolean local_initiator;
-
- /* GabbleJingleContent objects keyed by content name.
- * Table owns references to these objects. */
- GHashTable *initiator_contents;
- GHashTable *responder_contents;
-
- JingleDialect dialect;
- JingleState state;
- gchar *sid;
-
- gboolean locally_accepted;
- gboolean locally_terminated;
-
- gboolean local_hold;
-
- gboolean remote_hold;
- gboolean remote_ringing;
-
- gboolean dispose_has_run;
-};
-
-typedef struct {
- JingleState state;
- JingleAction *actions;
-} JingleStateActions;
-
-/* gcc should be able to figure this out from the table below, but.. */
-#define MAX_ACTIONS_PER_STATE 12
-
-/* NB: JINGLE_ACTION_UNKNOWN is used as a terminator here. */
-static JingleAction allowed_actions[MAX_JINGLE_STATES][MAX_ACTIONS_PER_STATE] = {
- /* JINGLE_STATE_PENDING_CREATED */
- { JINGLE_ACTION_SESSION_INITIATE, JINGLE_ACTION_UNKNOWN },
- /* JINGLE_STATE_PENDING_INITIATE_SENT */
- { JINGLE_ACTION_SESSION_TERMINATE, JINGLE_ACTION_SESSION_ACCEPT,
- JINGLE_ACTION_TRANSPORT_ACCEPT, /* required for GTalk4 */
- JINGLE_ACTION_DESCRIPTION_INFO, JINGLE_ACTION_SESSION_INFO,
- JINGLE_ACTION_TRANSPORT_INFO, JINGLE_ACTION_INFO,
- JINGLE_ACTION_UNKNOWN },
- /* JINGLE_STATE_PENDING_INITIATED */
- { JINGLE_ACTION_SESSION_ACCEPT, JINGLE_ACTION_SESSION_TERMINATE,
- JINGLE_ACTION_TRANSPORT_INFO, JINGLE_ACTION_CONTENT_REJECT,
- JINGLE_ACTION_CONTENT_MODIFY, JINGLE_ACTION_CONTENT_ACCEPT,
- JINGLE_ACTION_CONTENT_REMOVE, JINGLE_ACTION_DESCRIPTION_INFO,
- JINGLE_ACTION_TRANSPORT_ACCEPT, JINGLE_ACTION_SESSION_INFO,
- JINGLE_ACTION_INFO,
- JINGLE_ACTION_UNKNOWN },
- /* JINGLE_STATE_PENDING_ACCEPT_SENT */
- { JINGLE_ACTION_TRANSPORT_INFO, JINGLE_ACTION_DESCRIPTION_INFO,
- JINGLE_ACTION_SESSION_TERMINATE, JINGLE_ACTION_SESSION_INFO,
- JINGLE_ACTION_INFO,
- JINGLE_ACTION_UNKNOWN },
- /* JINGLE_STATE_ACTIVE */
- { JINGLE_ACTION_CONTENT_MODIFY, JINGLE_ACTION_CONTENT_ADD,
- JINGLE_ACTION_CONTENT_REMOVE, JINGLE_ACTION_CONTENT_REPLACE,
- JINGLE_ACTION_CONTENT_ACCEPT, JINGLE_ACTION_CONTENT_REJECT,
- JINGLE_ACTION_SESSION_INFO, JINGLE_ACTION_TRANSPORT_INFO,
- JINGLE_ACTION_DESCRIPTION_INFO, JINGLE_ACTION_INFO,
- JINGLE_ACTION_SESSION_TERMINATE, JINGLE_ACTION_UNKNOWN },
- /* JINGLE_STATE_ENDED */
- { JINGLE_ACTION_UNKNOWN }
-};
-
-gboolean
-gabble_jingle_session_defines_action (GabbleJingleSession *sess,
- JingleAction a)
-{
- JingleDialect d = sess->priv->dialect;
-
- if (a == JINGLE_ACTION_UNKNOWN)
- return FALSE;
-
- switch (d)
- {
- case JINGLE_DIALECT_V032:
- return TRUE;
- case JINGLE_DIALECT_V015:
- return (a != JINGLE_ACTION_DESCRIPTION_INFO &&
- a != JINGLE_ACTION_SESSION_INFO);
- case JINGLE_DIALECT_GTALK4:
- if (a == JINGLE_ACTION_TRANSPORT_ACCEPT ||
- a == JINGLE_ACTION_INFO )
- return TRUE;
- case JINGLE_DIALECT_GTALK3:
- return (a == JINGLE_ACTION_SESSION_ACCEPT ||
- a == JINGLE_ACTION_SESSION_INITIATE ||
- a == JINGLE_ACTION_SESSION_TERMINATE ||
- a == JINGLE_ACTION_TRANSPORT_INFO ||
- a == JINGLE_ACTION_INFO);
- default:
- return FALSE;
- }
-}
-
-static void gabble_jingle_session_send_held (GabbleJingleSession *sess);
-static void content_ready_cb (GabbleJingleContent *c, gpointer user_data);
-static void content_removed_cb (GabbleJingleContent *c, gpointer user_data);
-
-static void
-gabble_jingle_session_init (GabbleJingleSession *obj)
-{
- GabbleJingleSessionPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_JINGLE_SESSION,
- GabbleJingleSessionPrivate);
- obj->priv = priv;
-
- DEBUG ("Initializing the jingle session %p", obj);
-
- priv->initiator_contents = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
- priv->responder_contents = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
-
- priv->state = JINGLE_STATE_PENDING_CREATED;
- priv->locally_accepted = FALSE;
- priv->locally_terminated = FALSE;
- priv->dispose_has_run = FALSE;
-}
-
-static void
-dispose_content_hash (
- GabbleJingleSession *sess,
- GHashTable **contents)
-{
- GHashTableIter iter;
- gpointer content;
-
- g_hash_table_iter_init (&iter, *contents);
- while (g_hash_table_iter_next (&iter, NULL, &content))
- {
- g_signal_handlers_disconnect_by_func (content, content_ready_cb, sess);
- g_signal_handlers_disconnect_by_func (content, content_removed_cb, sess);
- g_hash_table_iter_remove (&iter);
- }
-
- g_hash_table_unref (*contents);
- *contents = NULL;
-}
-
-static void
-gabble_jingle_session_dispose (GObject *object)
-{
- GabbleJingleSession *sess = GABBLE_JINGLE_SESSION (object);
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("called");
- priv->dispose_has_run = TRUE;
-
- g_assert ((priv->state == JINGLE_STATE_PENDING_CREATED) ||
- (priv->state == JINGLE_STATE_ENDED));
-
- dispose_content_hash (sess, &priv->initiator_contents);
- dispose_content_hash (sess, &priv->responder_contents);
-
- g_clear_object (&priv->peer_contact);
- g_clear_object (&priv->porter);
-
- g_free (priv->sid);
- priv->sid = NULL;
-
- g_free (priv->peer_jid);
- priv->peer_jid = NULL;
-
- if (G_OBJECT_CLASS (gabble_jingle_session_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_jingle_session_parent_class)->dispose (object);
-}
-
-static void
-gabble_jingle_session_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleSession *sess = GABBLE_JINGLE_SESSION (object);
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- switch (property_id) {
- case PROP_JINGLE_FACTORY:
- g_value_set_object (value, priv->jingle_factory);
- break;
- case PROP_PORTER:
- g_value_set_object (value, priv->porter);
- break;
- case PROP_SESSION_ID:
- g_value_set_string (value, priv->sid);
- break;
- case PROP_LOCAL_INITIATOR:
- g_value_set_boolean (value, priv->local_initiator);
- break;
- case PROP_PEER_CONTACT:
- g_value_set_object (value, priv->peer_contact);
- break;
- case PROP_STATE:
- g_value_set_uint (value, priv->state);
- break;
- case PROP_DIALECT:
- g_value_set_uint (value, priv->dialect);
- break;
- case PROP_LOCAL_HOLD:
- g_value_set_boolean (value, priv->local_hold);
- break;
- case PROP_REMOTE_HOLD:
- g_value_set_boolean (value, priv->remote_hold);
- break;
- case PROP_REMOTE_RINGING:
- g_value_set_boolean (value, priv->remote_ringing);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_jingle_session_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleSession *sess = GABBLE_JINGLE_SESSION (object);
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- switch (property_id) {
- case PROP_JINGLE_FACTORY:
- priv->jingle_factory = g_value_get_object (value);
- g_assert (priv->jingle_factory != NULL);
- break;
- case PROP_PORTER:
- priv->porter = g_value_dup_object (value);
- g_assert (priv->porter != NULL);
- break;
- case PROP_SESSION_ID:
- g_free (priv->sid);
- priv->sid = g_value_dup_string (value);
- break;
- case PROP_LOCAL_INITIATOR:
- priv->local_initiator = g_value_get_boolean (value);
- break;
- case PROP_DIALECT:
- priv->dialect = g_value_get_uint (value);
- break;
- case PROP_PEER_CONTACT:
- priv->peer_contact = g_value_dup_object (value);
- break;
- case PROP_LOCAL_HOLD:
- {
- gboolean local_hold = g_value_get_boolean (value);
-
- if (priv->local_hold != local_hold)
- {
- priv->local_hold = local_hold;
-
- if (priv->state >= JINGLE_STATE_PENDING_INITIATED &&
- priv->state < JINGLE_STATE_ENDED)
- gabble_jingle_session_send_held (sess);
-
- /* else, we'll send this in set_state when we move to PENDING_INITIATED or
- * better.
- */
- }
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- g_assert_not_reached ();
- break;
- }
-}
-
-static void
-gabble_jingle_session_constructed (GObject *object)
-{
- void (*chain_up) (GObject *) =
- G_OBJECT_CLASS (gabble_jingle_session_parent_class)->constructed;
- GabbleJingleSession *self = GABBLE_JINGLE_SESSION (object);
- GabbleJingleSessionPrivate *priv = self->priv;
-
- if (chain_up != NULL)
- chain_up (object);
-
- g_assert (priv->jingle_factory != NULL);
- g_assert (priv->porter != NULL);
- g_assert (priv->peer_contact != NULL);
- g_assert (priv->sid != NULL);
-
- priv->peer_jid = wocky_contact_dup_jid (priv->peer_contact);
-
- if (priv->local_initiator)
- priv->initiator = wocky_porter_get_full_jid (priv->porter);
- else
- priv->initiator = priv->peer_jid;
-
- if (WOCKY_IS_RESOURCE_CONTACT (priv->peer_contact))
- priv->peer_resource = wocky_resource_contact_get_resource (
- WOCKY_RESOURCE_CONTACT (priv->peer_contact));
-}
-
-GabbleJingleSession *
-gabble_jingle_session_new (
- GabbleJingleFactory *factory,
- WockyPorter *porter,
- const gchar *session_id,
- gboolean local_initiator,
- WockyContact *peer,
- JingleDialect dialect,
- gboolean local_hold)
-{
- return g_object_new (GABBLE_TYPE_JINGLE_SESSION,
- "session-id", session_id,
- "jingle-factory", factory,
- "porter", porter,
- "local-initiator", local_initiator,
- "peer-contact", peer,
- "dialect", dialect,
- "local-hold", local_hold,
- NULL);
-}
-
-static void
-gabble_jingle_session_class_init (GabbleJingleSessionClass *cls)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (cls);
- GParamSpec *param_spec;
-
- g_type_class_add_private (cls, sizeof (GabbleJingleSessionPrivate));
-
- object_class->constructed = gabble_jingle_session_constructed;
- object_class->get_property = gabble_jingle_session_get_property;
- object_class->set_property = gabble_jingle_session_set_property;
- object_class->dispose = gabble_jingle_session_dispose;
-
- /* property definitions */
- param_spec = g_param_spec_object ("jingle-factory",
- "GabbleJingleFactory object",
- "The Jingle factory which created this session",
- GABBLE_TYPE_JINGLE_FACTORY,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_JINGLE_FACTORY, param_spec);
-
- param_spec = g_param_spec_object ("porter", "WockyPorter",
- "The WockyPorter for the current connection",
- WOCKY_TYPE_PORTER,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_PORTER, 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_STRINGS);
- g_object_class_install_property (object_class, PROP_SESSION_ID, param_spec);
-
- param_spec = g_param_spec_boolean ("local-initiator", "Session initiator",
- "Specifies if local end initiated the session.",
- TRUE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_LOCAL_INITIATOR,
- param_spec);
-
- /**
- * GabbleJingleSession:peer-contact:
- *
- * The #WockyContact representing the other party in the session. Note that
- * if this is a #WockyBareContact (as opposed to a #WockyResourceContact) the
- * session is with the contact's bare JID.
- */
- param_spec = g_param_spec_object ("peer-contact", "Session peer",
- "The WockyContact representing the other party in the session.",
- WOCKY_TYPE_CONTACT,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_PEER_CONTACT, param_spec);
-
- param_spec = g_param_spec_uint ("state", "Session state",
- "The current state that the session is in.",
- 0, G_MAXUINT32, JINGLE_STATE_PENDING_CREATED,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- param_spec = g_param_spec_uint ("dialect", "Jingle dialect",
- "Jingle dialect used for this session.",
- 0, G_MAXUINT32, JINGLE_DIALECT_ERROR,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_DIALECT, param_spec);
-
- param_spec = g_param_spec_boolean ("local-hold", "Local hold",
- "TRUE if we've placed the peer on hold", FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_LOCAL_HOLD, param_spec);
-
- param_spec = g_param_spec_boolean ("remote-hold", "Remote hold",
- "TRUE if the peer has placed us on hold", FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_REMOTE_HOLD, param_spec);
-
- param_spec = g_param_spec_boolean ("remote-ringing", "Remote ringing",
- "TRUE if the peer's client is ringing", FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_REMOTE_RINGING,
- param_spec);
-
- /* signal definitions */
-
- signals[NEW_CONTENT] = g_signal_new ("new-content",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, G_TYPE_OBJECT);
-
- signals[TERMINATED] = g_signal_new ("terminated",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, gabble_marshal_VOID__BOOLEAN_UINT_STRING,
- G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING);
-
- signals[REMOTE_STATE_CHANGED] = g_signal_new ("remote-state-changed",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- signals[CONTENT_REJECTED] = g_signal_new ("content-rejected",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, gabble_marshal_VOID__OBJECT_UINT_STRING,
- G_TYPE_NONE, 3, G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_STRING);
-
- /*
- * @contact: this call's peer (the artist commonly known as
- * gabble_jingle_session_get_peer_contact())
- * @cap: the XEP-0115 feature string the session is interested in.
- *
- * Emitted when the session wants to check whether the peer has a particular
- * capability. The handler should return %TRUE if @contact has @cap.
- */
- signals[QUERY_CAP] = g_signal_new ("query-cap",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, g_signal_accumulator_first_wins, NULL,
- gabble_marshal_BOOLEAN__OBJECT_STRING,
- G_TYPE_BOOLEAN, 2, WOCKY_TYPE_CONTACT, G_TYPE_STRING);
-
- signals[ABOUT_TO_INITIATE] = g_signal_new ("about-to-initiate",
- G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-typedef void (*HandlerFunc)(GabbleJingleSession *sess,
- WockyNode *node, GError **error);
-typedef void (*ContentHandlerFunc)(GabbleJingleSession *sess,
- GabbleJingleContent *c, WockyNode *content_node, gpointer user_data,
- GError **error);
-
-static gboolean
-extract_reason (WockyNode *node, JingleReason *reason, gchar **message)
-{
- JingleReason _reason = JINGLE_REASON_UNKNOWN;
- WockyNode *child;
- WockyNodeIter iter;
-
- g_return_val_if_fail (node != NULL, FALSE);
-
- if (message != NULL)
- *message = g_strdup (wocky_node_get_content_from_child (node, "text"));
-
- wocky_node_iter_init (&iter, node, NULL, NULL);
-
- while (wocky_node_iter_next (&iter, &child))
- {
- if (wocky_enum_from_nick (
- jingle_reason_get_type (), child->name, (gint *) &_reason))
- {
- if (reason != NULL)
- *reason = _reason;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static JingleAction
-parse_action (const gchar *txt)
-{
- if (txt == NULL)
- return JINGLE_ACTION_UNKNOWN;
-
- /* synonyms, best deal with them right now */
- if (!wocky_strdiff (txt, "initiate") ||
- !wocky_strdiff (txt, "session-initiate"))
- return JINGLE_ACTION_SESSION_INITIATE;
- else if (!wocky_strdiff (txt, "terminate") ||
- !wocky_strdiff (txt, "session-terminate") ||
- !wocky_strdiff (txt, "reject"))
- return JINGLE_ACTION_SESSION_TERMINATE;
- else if (!wocky_strdiff (txt, "accept") ||
- !wocky_strdiff (txt, "session-accept"))
- return JINGLE_ACTION_SESSION_ACCEPT;
- else if (!wocky_strdiff (txt, "candidates") ||
- !wocky_strdiff (txt, "transport-info"))
- return JINGLE_ACTION_TRANSPORT_INFO;
- else if (!wocky_strdiff (txt, "content-accept"))
- return JINGLE_ACTION_CONTENT_ACCEPT;
- else if (!wocky_strdiff (txt, "content-add"))
- return JINGLE_ACTION_CONTENT_ADD;
- else if (!wocky_strdiff (txt, "content-modify"))
- return JINGLE_ACTION_CONTENT_MODIFY;
- else if (!wocky_strdiff (txt, "content-replace"))
- return JINGLE_ACTION_CONTENT_REPLACE;
- else if (!wocky_strdiff (txt, "content-reject"))
- return JINGLE_ACTION_CONTENT_REJECT;
- else if (!wocky_strdiff (txt, "content-remove"))
- return JINGLE_ACTION_CONTENT_REMOVE;
- else if (!wocky_strdiff (txt, "session-info"))
- return JINGLE_ACTION_SESSION_INFO;
- else if (!wocky_strdiff (txt, "transport-accept"))
- return JINGLE_ACTION_TRANSPORT_ACCEPT;
- else if (!wocky_strdiff (txt, "description-info"))
- return JINGLE_ACTION_DESCRIPTION_INFO;
- else if (!wocky_strdiff (txt, "info"))
- return JINGLE_ACTION_INFO;
-
- return JINGLE_ACTION_UNKNOWN;
-}
-
-static const gchar *
-produce_action (JingleAction action, JingleDialect dialect)
-{
- gboolean gmode = (dialect == JINGLE_DIALECT_GTALK3) ||
- (dialect == JINGLE_DIALECT_GTALK4);
-
- g_return_val_if_fail (action != JINGLE_ACTION_UNKNOWN, NULL);
-
- switch (action) {
- case JINGLE_ACTION_SESSION_INITIATE:
- return (gmode) ? "initiate" : "session-initiate";
- case JINGLE_ACTION_SESSION_TERMINATE:
- return (gmode) ? "terminate" : "session-terminate";
- case JINGLE_ACTION_SESSION_ACCEPT:
- return (gmode) ? "accept" : "session-accept";
- case JINGLE_ACTION_TRANSPORT_INFO:
- return (dialect == JINGLE_DIALECT_GTALK3) ?
- "candidates" : "transport-info";
- case JINGLE_ACTION_CONTENT_ACCEPT:
- return "content-accept";
- case JINGLE_ACTION_CONTENT_ADD:
- return "content-add";
- case JINGLE_ACTION_CONTENT_MODIFY:
- return "content-modify";
- case JINGLE_ACTION_CONTENT_REMOVE:
- return "content-remove";
- case JINGLE_ACTION_CONTENT_REPLACE:
- return "content-replace";
- case JINGLE_ACTION_CONTENT_REJECT:
- return "content-reject";
- case JINGLE_ACTION_SESSION_INFO:
- return "session-info";
- case JINGLE_ACTION_TRANSPORT_ACCEPT:
- return "transport-accept";
- case JINGLE_ACTION_DESCRIPTION_INFO:
- return "description-info";
- case JINGLE_ACTION_INFO:
- return "info";
- default:
- /* only reached if g_return_val_if_fail is disabled */
- DEBUG ("unknown action %u", action);
- return NULL;
- }
-}
-
-static gboolean
-action_is_allowed (JingleAction action, JingleState state)
-{
- guint i;
-
- for (i = 0; allowed_actions[state][i] != JINGLE_ACTION_UNKNOWN; i++)
- {
- if (allowed_actions[state][i] == action)
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void gabble_jingle_session_send_rtp_info (GabbleJingleSession *sess,
- const gchar *name);
-static void set_state (GabbleJingleSession *sess,
- JingleState state, JingleReason termination_reason, const gchar *text);
-static GabbleJingleContent *_get_any_content (GabbleJingleSession *session);
-
-gboolean
-gabble_jingle_session_peer_has_cap (
- GabbleJingleSession *self,
- const gchar *cap_or_quirk)
-{
- GabbleJingleSessionPrivate *priv = self->priv;
- gboolean ret;
-
- g_signal_emit (self, signals[QUERY_CAP], 0,
- priv->peer_contact, cap_or_quirk,
- &ret);
- return ret;
-}
-
-static gboolean
-lookup_content (GabbleJingleSession *sess,
- const gchar *name,
- const gchar *creator,
- gboolean fail_if_missing,
- GabbleJingleContent **c,
- GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- if (name == NULL)
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "'name' attribute unset");
- return FALSE;
- }
-
- if (JINGLE_IS_GOOGLE_DIALECT (priv->dialect))
- {
- /* Only the initiator can create contents on GTalk. */
- *c = g_hash_table_lookup (priv->initiator_contents, name);
- }
- else
- {
- /* Versions of Gabble between 0.7.16 and 0.7.28 (inclusive) omitted the
- * 'creator' attribute from transport-info (and possibly other) stanzas.
- * We try to detect contacts using such a version of Gabble from their
- * caps; if 'creator' is missing and the peer has that caps flag, we look
- * up the content in both hashes.
- *
- * While this doesn't deal with the case where the content is found in
- * both hashes, this isn't a problem in practice: the versions of Gabble
- * we're working around didn't allow this to happen (they'd either reject
- * the second stream, or let it replace the first, depending on the phase
- * of the moon, and get kind of confused in the process), and we try to
- * pick globally-unique content names.
- */
- if (creator == NULL &&
- gabble_jingle_session_peer_has_cap (sess,
- QUIRK_OMITS_CONTENT_CREATORS))
- {
- DEBUG ("working around missing 'creator' attribute");
-
- *c = g_hash_table_lookup (priv->initiator_contents, name);
-
- if (*c == NULL)
- *c = g_hash_table_lookup (priv->responder_contents, name);
- }
- else if (!wocky_strdiff (creator, "initiator"))
- {
- *c = g_hash_table_lookup (priv->initiator_contents, name);
- }
- else if (!wocky_strdiff (creator, "responder"))
- {
- *c = g_hash_table_lookup (priv->responder_contents, name);
- }
- else
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "'creator' attribute %s",
- (creator == NULL ? "missing" : "invalid"));
- return FALSE;
- }
- }
-
- if (fail_if_missing && *c == NULL)
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "Content '%s' (created by %s) does not exist", name, creator);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-_foreach_content (GabbleJingleSession *sess,
- WockyNode *node,
- gboolean fail_if_missing,
- ContentHandlerFunc func,
- gpointer user_data,
- GError **error)
-{
- GabbleJingleContent *c;
- WockyNode *content_node;
- WockyNodeIter iter;
-
- wocky_node_iter_init (&iter, node, "content", NULL);
- while (wocky_node_iter_next (&iter, &content_node))
- {
- if (!lookup_content (sess,
- wocky_node_get_attribute (content_node, "name"),
- wocky_node_get_attribute (content_node, "creator"),
- fail_if_missing, &c, error))
- return;
-
- func (sess, c, content_node, user_data, error);
- if (*error != NULL)
- return;
- }
-}
-
-struct idle_content_reject_ctx {
- GabbleJingleSession *session;
- gchar *creator;
- gchar *name;
-};
-
-static gboolean
-idle_content_reject (gpointer data)
-{
- WockyStanza *msg;
- WockyNode *sess_node, *node;
- struct idle_content_reject_ctx *ctx = data;
-
- msg = gabble_jingle_session_new_message (ctx->session,
- JINGLE_ACTION_CONTENT_REJECT, &sess_node);
-
- g_debug ("name = %s, intiiator = %s", ctx->name, ctx->creator);
-
- node = wocky_node_add_child_with_content (sess_node, "content", NULL);
- wocky_node_set_attributes (node,
- "name", ctx->name, "creator", ctx->creator, NULL);
-
- gabble_jingle_session_send (ctx->session, msg);
-
- g_object_unref (ctx->session);
- g_free (ctx->name);
- g_free (ctx->creator);
- g_free (ctx);
-
- return FALSE;
-}
-
-static void
-fire_idle_content_reject (GabbleJingleSession *sess, const gchar *name,
- const gchar *creator)
-{
- struct idle_content_reject_ctx *ctx = g_new0 (struct idle_content_reject_ctx, 1);
-
- if (creator == NULL)
- creator = "";
-
- ctx->session = g_object_ref (sess);
- ctx->name = g_strdup (name);
- ctx->creator = g_strdup (creator);
-
- /* FIXME: add API for ordering IQs rather than using g_idle_add. */
- g_idle_add (idle_content_reject, ctx);
-}
-
-static GabbleJingleContent *
-create_content (GabbleJingleSession *sess, GType content_type,
- JingleMediaType type, JingleContentSenders senders,
- const gchar *content_ns, const gchar *transport_ns,
- const gchar *name, WockyNode *content_node, GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- GabbleJingleContent *c;
- GHashTable *contents;
-
- DEBUG ("session creating new content name %s, type %d", name, type);
-
- /* FIXME: media-type is introduced by GabbleJingleMediaRTP, not by the
- * superclass, so this call is unsafe in the general case */
- c = g_object_new (content_type,
- "session", sess,
- "content-ns", content_ns,
- "transport-ns", transport_ns,
- "media-type", type,
- "name", name,
- "disposition", "session",
- "senders", senders,
- NULL);
-
- g_signal_connect (c, "ready",
- (GCallback) content_ready_cb, sess);
- g_signal_connect (c, "removed",
- (GCallback) content_removed_cb, sess);
-
- /* if we are called by parser, parse content add */
- if (content_node != NULL)
- {
- gabble_jingle_content_parse_add (c, content_node,
- JINGLE_IS_GOOGLE_DIALECT (priv->dialect), error);
-
- if (*error != NULL)
- {
- g_object_unref (c);
- return NULL;
- }
-
- /* gtalk streams don't have name, so use whatever Content came up with */
- if (name == NULL)
- name = gabble_jingle_content_get_name (c);
- }
-
- if (priv->local_initiator == gabble_jingle_content_is_created_by_us (c))
- {
- DEBUG ("inserting content %s into initiator_contents", name);
- contents = priv->initiator_contents;
- }
- else
- {
- DEBUG ("inserting content %s into responder_contents", name);
- contents = priv->responder_contents;
- }
-
- /* If the content already existed, either we shouldn't have picked the name
- * we did (if we're creating it) or _each_content_add should have already
- * said no.
- */
- g_assert (g_hash_table_lookup (contents, name) == NULL);
- g_hash_table_insert (contents, g_strdup (name), c);
- g_signal_emit (sess, signals[NEW_CONTENT], 0, c);
- return c;
-}
-
-
-static void
-_each_content_add (GabbleJingleSession *sess, GabbleJingleContent *c,
- WockyNode *content_node, gpointer user_data, GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- const gchar *name = wocky_node_get_attribute (content_node, "name");
- WockyNode *desc_node = wocky_node_get_child (content_node,
- "description");
- GType content_type = 0;
- const gchar *content_ns = NULL;
-
- if (desc_node != NULL)
- {
- content_ns = wocky_node_get_ns (desc_node);
- DEBUG ("namespace: %s", content_ns);
- content_type = gabble_jingle_factory_lookup_content_type (
- gabble_jingle_session_get_factory (sess),
- content_ns);
- }
-
- if (content_type == 0)
- {
- /* if this is session-initiate, we should return error, otherwise,
- * we should respond with content-reject */
- if (priv->state < JINGLE_STATE_PENDING_INITIATED)
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "unsupported content type with ns %s", content_ns);
- else
- fire_idle_content_reject (sess, name,
- wocky_node_get_attribute (content_node, "creator"));
-
- return;
- }
-
- if (c != NULL)
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "content '%s' already exists", name);
- return;
- }
-
- create_content (sess, content_type, JINGLE_MEDIA_TYPE_NONE,
- JINGLE_CONTENT_SENDERS_BOTH, content_ns, NULL, NULL, content_node,
- error);
-}
-
-static void
-_each_content_remove (GabbleJingleSession *sess, GabbleJingleContent *c,
- WockyNode *content_node, gpointer user_data, GError **error)
-{
- g_assert (c != NULL);
-
- gabble_jingle_content_remove (c, FALSE);
-}
-
-static void
-_each_content_rejected (GabbleJingleSession *sess, GabbleJingleContent *c,
- WockyNode *content_node, gpointer user_data, GError **error)
-{
- JingleReason reason = GPOINTER_TO_UINT (user_data);
- g_assert (c != NULL);
-
- g_signal_emit (sess, signals[CONTENT_REJECTED], 0, c, reason, "");
-
- gabble_jingle_content_remove (c, FALSE);
-}
-
-static void
-_each_content_modify (GabbleJingleSession *sess, GabbleJingleContent *c,
- WockyNode *content_node, gpointer user_data, GError **error)
-{
- g_assert (c != NULL);
-
- gabble_jingle_content_update_senders (c, content_node, error);
-
- if (*error != NULL)
- return;
-}
-
-static void
-_each_content_replace (GabbleJingleSession *sess, GabbleJingleContent *c,
- WockyNode *content_node, gpointer user_data, GError **error)
-{
- _each_content_remove (sess, c, content_node, NULL, error);
-
- if (*error != NULL)
- return;
-
- _each_content_add (sess, c, content_node, NULL, error);
-}
-
-static void
-_each_content_accept (GabbleJingleSession *sess, GabbleJingleContent *c,
- WockyNode *content_node, gpointer user_data, GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- JingleContentState state;
-
- g_assert (c != NULL);
-
- g_object_get (c, "state", &state, NULL);
- if (state != JINGLE_CONTENT_STATE_SENT)
- {
-#ifdef ENABLE_DEBUG
- const gchar *name = wocky_node_get_attribute (content_node, "name");
- DEBUG ("ignoring content \"%s\"s acceptance for content not in SENT state", name);
-#endif
- return;
- }
-
- gabble_jingle_content_parse_accept (c, content_node,
- JINGLE_IS_GOOGLE_DIALECT (priv->dialect), error);
-}
-
-static void
-_each_description_info (GabbleJingleSession *sess, GabbleJingleContent *c,
- WockyNode *content_node, gpointer user_data, GError **error)
-{
- gabble_jingle_content_parse_description_info (c, content_node, error);
-}
-
-static void
-on_session_initiate (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- /* we can't call ourselves at the moment */
- if (priv->local_initiator)
- {
- /* We ignore initiate from us, and terminate the session immediately
- * afterwards */
- gabble_jingle_session_terminate (sess, JINGLE_REASON_BUSY, NULL, NULL);
- return;
- }
-
- if ((priv->dialect == JINGLE_DIALECT_GTALK3))
- {
- const gchar *content_ns = NULL;
- WockyNode *desc_node =
- wocky_node_get_child (node, "description");
- content_ns = wocky_node_get_ns (desc_node);
-
- if (!wocky_strdiff (content_ns, NS_GOOGLE_SESSION_VIDEO))
- {
- GabbleJingleFactory *factory =
- gabble_jingle_session_get_factory (sess);
- GType content_type = 0;
-
- DEBUG ("GTalk v3 session with audio and video");
-
- /* audio and video content */
- content_type = gabble_jingle_factory_lookup_content_type (
- factory, content_ns);
- create_content (sess, content_type, JINGLE_MEDIA_TYPE_VIDEO,
- JINGLE_CONTENT_SENDERS_BOTH, NS_GOOGLE_SESSION_VIDEO, NULL,
- "video", node, error);
-
- content_type = gabble_jingle_factory_lookup_content_type (
- factory, NS_GOOGLE_SESSION_PHONE);
- create_content (sess, content_type, JINGLE_MEDIA_TYPE_AUDIO,
- JINGLE_CONTENT_SENDERS_BOTH, NS_GOOGLE_SESSION_PHONE, NULL,
- "audio", node, error);
- }
- else
- {
- _each_content_add (sess, NULL, node, NULL, error);
- }
- }
- else if (priv->dialect == JINGLE_DIALECT_GTALK4)
- {
- /* in this case we implicitly have just one content */
- _each_content_add (sess, NULL, node, NULL, error);
- }
- else
- {
- _foreach_content (sess, node, FALSE, _each_content_add, NULL, error);
- }
-
- if (*error == NULL)
- {
- /* FIXME: contents defined here should always have "session" content
- * disposition; resolve this as soon as the proper procedure is defined
- * in XEP-0166. */
-
- set_state (sess, JINGLE_STATE_PENDING_INITIATED, JINGLE_REASON_UNKNOWN,
- NULL);
-
- gabble_jingle_session_send_rtp_info (sess, "ringing");
- }
-}
-
-static void
-on_content_add (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- _foreach_content (sess, node, FALSE, _each_content_add, NULL, error);
-}
-
-static void
-on_content_modify (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- _foreach_content (sess, node, TRUE, _each_content_modify, NULL, error);
-}
-
-static void
-on_content_remove (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- _foreach_content (sess, node, TRUE, _each_content_remove, NULL, error);
-}
-
-static void
-on_content_replace (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- _foreach_content (sess, node, TRUE, _each_content_replace, NULL, error);
-}
-
-static void
-on_content_reject (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- WockyNode *n = wocky_node_get_child (node, "reason");
- JingleReason reason = JINGLE_REASON_UNKNOWN;
-
- DEBUG (" ");
-
- if (n != NULL)
- extract_reason (n, &reason, NULL);
-
- if (reason == JINGLE_REASON_UNKNOWN)
- reason = JINGLE_REASON_GENERAL_ERROR;
-
- _foreach_content (sess, node, TRUE, _each_content_rejected,
- GUINT_TO_POINTER (reason), error);
-}
-
-static void
-on_content_accept (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- _foreach_content (sess, node, TRUE, _each_content_accept, NULL, error);
-}
-
-static void
-on_session_accept (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- DEBUG ("called");
-
- if ((priv->dialect == JINGLE_DIALECT_GTALK3) ||
- (priv->dialect == JINGLE_DIALECT_GTALK4))
- {
- /* Google Talk calls don't have contents per se; they just have
- * <payload-type>s in different namespaces for audio and video, in the
- * same <description> stanza. So we need to feed the whole stanza to each
- * content in turn.
- */
- GList *cs = gabble_jingle_session_get_contents (sess);
- GList *l;
-
- for (l = cs; l != NULL; l = l->next)
- _each_content_accept (sess, l->data, node, NULL, error);
-
- g_list_free (cs);
- }
- else
- {
- _foreach_content (sess, node, TRUE, _each_content_accept, NULL, error);
- }
-
- if (*error != NULL)
- return;
-
- set_state (sess, JINGLE_STATE_ACTIVE, JINGLE_REASON_UNKNOWN, NULL);
-
- /* Make sure each content knows the session is active */
- g_list_foreach (gabble_jingle_session_get_contents (sess),
- (GFunc) g_object_notify, "state");
-
-
- if (priv->dialect != JINGLE_DIALECT_V032)
- {
- /* If this is a dialect that doesn't support <active/>, we treat
- * session-accept as the cue to remove the ringing flag.
- */
- priv->remote_ringing = FALSE;
- g_signal_emit (sess, signals[REMOTE_STATE_CHANGED], 0);
- }
-}
-
-static void
-mute_all_foreach (gpointer key,
- gpointer value,
- gpointer mute)
-{
- if (G_OBJECT_TYPE (value) == GABBLE_TYPE_JINGLE_MEDIA_RTP)
- g_object_set (value, "remote-mute", GPOINTER_TO_INT (mute), NULL);
-}
-
-static void
-mute_all (GabbleJingleSession *sess,
- gboolean mute)
-{
- g_hash_table_foreach (sess->priv->initiator_contents, mute_all_foreach,
- GINT_TO_POINTER (mute));
- g_hash_table_foreach (sess->priv->responder_contents, mute_all_foreach,
- GINT_TO_POINTER (mute));
-}
-
-static gboolean
-set_mute (GabbleJingleSession *sess,
- const gchar *name,
- const gchar *creator,
- gboolean mute,
- GError **error)
-{
- GabbleJingleContent *c;
-
- if (name == NULL)
- {
- mute_all (sess, mute);
- return TRUE;
- }
-
- if (!lookup_content (sess, name, creator, TRUE /* fail if missing */, &c,
- error))
- return FALSE;
-
- if (G_OBJECT_TYPE (c) != GABBLE_TYPE_JINGLE_MEDIA_RTP)
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "content '%s' isn't an RTP session", name);
- return FALSE;
- }
-
- g_object_set (c, "remote-mute", mute, NULL);
- return TRUE;
-}
-
-static void
-set_hold (GabbleJingleSession *sess,
- gboolean hold)
-{
- sess->priv->remote_hold = hold;
-}
-
-static void
-set_ringing (GabbleJingleSession *sess,
- gboolean ringing)
-{
- sess->priv->remote_ringing = ringing;
-}
-
-static gboolean
-handle_payload (GabbleJingleSession *sess,
- WockyNode *payload,
- gboolean *handled,
- GError **error)
-{
- const gchar *ns = wocky_node_get_ns (payload);
- const gchar *elt = payload->name;
- const gchar *name = wocky_node_get_attribute (payload, "name");
- const gchar *creator = wocky_node_get_attribute (payload, "creator");
-
- if (wocky_strdiff (ns, NS_JINGLE_RTP_INFO))
- {
- *handled = FALSE;
- return TRUE;
- }
-
- *handled = TRUE;
-
- if (!wocky_strdiff (elt, "active"))
- {
- /* Clear all states, we're active */
- mute_all (sess, FALSE);
- set_ringing (sess, FALSE);
- set_hold (sess, FALSE);
- }
- else if (!wocky_strdiff (elt, "ringing"))
- {
- set_ringing (sess, TRUE);
- }
- else if (!wocky_strdiff (elt, "hold"))
- {
- set_hold (sess, TRUE);
- }
- else if (!wocky_strdiff (elt, "unhold"))
- {
- set_hold (sess, FALSE);
- }
- /* XEP-0178 says that only <mute/> and <unmute/> can have a name=''
- * attribute.
- */
- else if (!wocky_strdiff (elt, "mute"))
- {
- return set_mute (sess, name, creator, TRUE, error);
- }
- else if (!wocky_strdiff (elt, "unmute"))
- {
- return set_mute (sess, name, creator, FALSE, error);
- }
- else
- {
- g_set_error (error, WOCKY_JINGLE_ERROR,
- WOCKY_JINGLE_ERROR_UNSUPPORTED_INFO,
- "<%s> is not known in namespace %s", elt, ns);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-on_session_info (GabbleJingleSession *sess,
- WockyNode *node,
- GError **error)
-{
- gboolean understood_a_payload = FALSE;
- gboolean hit_an_error = FALSE;
- WockyNodeIter i;
- WockyNode *n;
-
- /* if this is a ping, just ack it. */
- if (wocky_node_get_first_child (node) == NULL)
- return;
-
- wocky_node_iter_init (&i, node, NULL, NULL);
- while (wocky_node_iter_next (&i, &n))
- {
- gboolean handled;
- GError *e = NULL;
-
- if (handle_payload (sess, n, &handled, &e))
- {
- understood_a_payload = understood_a_payload || handled;
- }
- else if (hit_an_error)
- {
- DEBUG ("already got another error; ignoring %s", e->message);
- g_error_free (e);
- }
- else
- {
- DEBUG ("hit an error: %s", e->message);
- hit_an_error = TRUE;
- g_propagate_error (error, e);
- }
- }
-
- /* If we understood something, the remote state (may have) changed. Else,
- * return an error to the peer.
- */
- if (understood_a_payload)
- g_signal_emit (sess, signals[REMOTE_STATE_CHANGED], 0);
- else if (!hit_an_error)
- g_set_error (error, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_UNSUPPORTED_INFO,
- "no recognized session-info payloads");
-}
-
-static void
-on_session_terminate (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- gchar *text = NULL;
- WockyNode *n = wocky_node_get_child (node, "reason");
- JingleReason jingle_reason = JINGLE_REASON_UNKNOWN;
-
- if (n != NULL)
- extract_reason (n, &jingle_reason, &text);
-
- DEBUG ("remote end terminated the session with reason %s and text '%s'",
- gabble_jingle_session_get_reason_name (jingle_reason),
- (text != NULL ? text : "(none)"));
-
- set_state (sess, JINGLE_STATE_ENDED, jingle_reason, text);
-
- g_free (text);
-}
-
-static void
-on_transport_info (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- GabbleJingleContent *c = NULL;
-
- if (JINGLE_IS_GOOGLE_DIALECT (priv->dialect))
- {
- GHashTableIter iter;
- gpointer value;
-
- if (priv->dialect == JINGLE_DIALECT_GTALK4)
- {
- if (!wocky_strdiff (wocky_node_get_attribute (node, "type"),
- "candidates"))
- {
- GList *contents = gabble_jingle_session_get_contents (sess);
- GList *l;
-
- DEBUG ("switching to gtalk3 dialect and retransmiting our candidates");
- priv->dialect = JINGLE_DIALECT_GTALK3;
-
- for (l = contents; l != NULL; l = l->next)
- gabble_jingle_content_retransmit_candidates (l->data, TRUE);
-
- g_list_free (contents);
- }
- else
- {
- node = wocky_node_get_child (node, "transport");
-
- if (node == NULL)
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "transport-info stanza without a <transport/>");
- return;
- }
- }
- }
-
- g_hash_table_iter_init (&iter, priv->initiator_contents);
- while (g_hash_table_iter_next (&iter, NULL, &value))
- {
- c = value;
- gabble_jingle_content_parse_transport_info (c, node, error);
- if (error != NULL && *error != NULL)
- break;
- }
- }
- else
- {
- WockyNodeIter i;
- WockyNode *content_node;
- GError *e = NULL;
-
- wocky_node_iter_init (&i, node, "content", NULL);
-
- while (wocky_node_iter_next (&i, &content_node))
- {
- WockyNode *transport_node;
-
- if (lookup_content (sess,
- wocky_node_get_attribute (content_node, "name"),
- wocky_node_get_attribute (content_node, "creator"),
- TRUE /* fail_if_missing */, &c, &e))
- {
- /* we need transport child of content node */
- transport_node = wocky_node_get_child (
- content_node, "transport");
- gabble_jingle_content_parse_transport_info (c,
- transport_node, &e);
- }
-
- /* Save the first error we encounter, but go through all remaining
- * contents anyway to try and recover as much info as we can */
- if (e != NULL && error != NULL && *error == NULL)
- {
- *error = e;
- e = NULL;
- }
- g_clear_error (&e);
- }
- }
-
-}
-
-static void
-on_transport_accept (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- DEBUG ("Ignoring 'transport-accept' action from peer");
-}
-
-static void
-on_description_info (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- _foreach_content (sess, node, TRUE, _each_description_info, NULL, error);
-}
-
-static void
-on_info (GabbleJingleSession *sess, WockyNode *node,
- GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- GabbleJingleContent *c = NULL;
-
- DEBUG ("received info ");
- if (JINGLE_IS_GOOGLE_DIALECT (priv->dialect))
- {
- GHashTableIter iter;
- g_hash_table_iter_init (&iter, priv->initiator_contents);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &c))
- {
- gabble_jingle_content_parse_info (c, node, error);
- if (error != NULL && *error != NULL)
- break;
- }
- }
-}
-
-static HandlerFunc handlers[] = {
- NULL, /* for unknown action */
- on_content_accept,
- on_content_add,
- on_content_modify,
- on_content_remove,
- on_content_replace,
- on_content_reject,
- on_session_accept, /* jingle_on_session_accept */
- on_session_info,
- on_session_initiate,
- on_session_terminate, /* jingle_on_session_terminate */
- on_transport_info, /* jingle_on_transport_info */
- on_transport_accept,
- on_description_info,
- on_info
-};
-
-static void
-jingle_state_machine_dance (GabbleJingleSession *sess,
- JingleAction action,
- WockyNode *node,
- GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- /* parser should've checked this already */
- g_assert (action_is_allowed (action, priv->state));
- g_assert (handlers[action] != NULL);
-
- handlers[action] (sess, node, error);
-}
-
-static JingleDialect
-detect_google_dialect (WockyNode *session_node)
-{
- /* The GTALK3 dialect is the only one that supports video at this time */
- if (wocky_node_get_child_ns (session_node,
- "description", NS_GOOGLE_SESSION_VIDEO) != NULL)
- return JINGLE_DIALECT_GTALK3;
-
- /* GTalk4 has a transport item, GTalk3 doesn't */
- if (wocky_node_get_child_ns (session_node,
- "transport", NS_GOOGLE_TRANSPORT_P2P) == NULL)
- return JINGLE_DIALECT_GTALK3;
-
- return JINGLE_DIALECT_GTALK4;
-}
-
-const gchar *
-gabble_jingle_session_detect (
- WockyStanza *stanza,
- JingleAction *action,
- JingleDialect *dialect)
-{
- const gchar *actxt, *sid;
- WockyNode *iq_node, *session_node;
- WockyStanzaSubType sub_type;
- gboolean google_mode = FALSE;
-
- /* all jingle actions are sets */
- wocky_stanza_get_type_info (stanza, NULL, &sub_type);
- if (sub_type != WOCKY_STANZA_SUB_TYPE_SET)
- return NULL;
-
- iq_node = wocky_stanza_get_top_node (stanza);
-
- if ((NULL == wocky_stanza_get_from (stanza)) ||
- (NULL == wocky_stanza_get_to (stanza)))
- return NULL;
-
- /* first, we try standard jingle */
- session_node = wocky_node_get_child_ns (iq_node, "jingle", NS_JINGLE032);
-
- if (session_node != NULL)
- {
- *dialect = JINGLE_DIALECT_V032;
- }
- else
- {
- /* then, we try a bit older jingle version */
- session_node = wocky_node_get_child_ns (iq_node, "jingle", NS_JINGLE015);
-
- if (session_node != NULL)
- {
- *dialect = JINGLE_DIALECT_V015;
- }
- else
- {
- /* next, we try googletalk */
- session_node = wocky_node_get_child_ns (iq_node,
- "session", NS_GOOGLE_SESSION);
-
- if (session_node != NULL)
- {
- *dialect = detect_google_dialect (session_node);
- google_mode = TRUE;
- }
- else
- {
- return NULL;
- }
- }
- }
-
- if (google_mode)
- {
- actxt = wocky_node_get_attribute (session_node, "type");
- sid = wocky_node_get_attribute (session_node, "id");
- }
- else
- {
- actxt = wocky_node_get_attribute (session_node, "action");
- sid = wocky_node_get_attribute (session_node, "sid");
- }
-
- *action = parse_action (actxt);
-
- return sid;
-}
-
-gboolean
-gabble_jingle_session_parse (
- GabbleJingleSession *sess,
- JingleAction action,
- WockyStanza *stanza,
- GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- WockyNode *iq_node, *session_node;
- const gchar *from, *action_name;
-
- /* IQ from/to can come in handy */
- from = wocky_stanza_get_from (stanza);
- iq_node = wocky_stanza_get_top_node (stanza);
-
- if (action == JINGLE_ACTION_UNKNOWN)
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "unknown session action");
- return FALSE;
- }
-
- action_name = produce_action (action, priv->dialect);
-
- DEBUG ("jingle action '%s' from '%s' in session '%s' dialect %u state %u",
- action_name, from, priv->sid, priv->dialect, priv->state);
-
- switch (priv->dialect) {
- case JINGLE_DIALECT_V032:
- session_node = wocky_node_get_child_ns (iq_node,
- "jingle", NS_JINGLE032);
- break;
- case JINGLE_DIALECT_V015:
- session_node = wocky_node_get_child_ns (iq_node,
- "jingle", NS_JINGLE015);
- break;
- case JINGLE_DIALECT_GTALK3:
- case JINGLE_DIALECT_GTALK4:
- session_node = wocky_node_get_child_ns (iq_node,
- "session", NS_GOOGLE_SESSION);
- break;
- default:
- /* just to make gcc happy about dealing with default case */
- session_node = NULL;
- }
-
- if (session_node == NULL)
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "malformed jingle stanza");
- return FALSE;
- }
-
- if (!gabble_jingle_session_defines_action (sess, action))
- {
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "action '%s' unknown (using dialect %u)", action_name, priv->dialect);
- return FALSE;
- }
-
- if (!action_is_allowed (action, priv->state))
- {
- g_set_error (error, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_OUT_OF_ORDER,
- "action '%s' not allowed in current state", action_name);
- return FALSE;
- }
-
- jingle_state_machine_dance (sess, action, session_node, error);
-
- if (*error != NULL)
- return FALSE;
-
- return TRUE;
-}
-
-WockyStanza *
-gabble_jingle_session_new_message (GabbleJingleSession *sess,
- JingleAction action, WockyNode **sess_node)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- WockyStanza *stanza;
- WockyNode *session_node;
- gchar *el = NULL, *ns = NULL;
- gboolean gtalk_mode = FALSE;
-
- g_return_val_if_fail (action != JINGLE_ACTION_UNKNOWN, NULL);
-
- g_assert ((action == JINGLE_ACTION_SESSION_INITIATE) ||
- (priv->state > JINGLE_STATE_PENDING_CREATED));
- g_assert (GABBLE_IS_JINGLE_SESSION (sess));
-
- switch (priv->dialect)
- {
- case JINGLE_DIALECT_V032:
- el = "jingle";
- ns = NS_JINGLE032;
- break;
- case JINGLE_DIALECT_V015:
- el = "jingle";
- ns = NS_JINGLE015;
- break;
- case JINGLE_DIALECT_GTALK3:
- case JINGLE_DIALECT_GTALK4:
- el = "session";
- ns = NS_GOOGLE_SESSION;
- gtalk_mode = TRUE;
- break;
- case JINGLE_DIALECT_ERROR:
- g_assert_not_reached ();
- }
-
- stanza = wocky_stanza_build (
- WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
- NULL, priv->peer_jid,
- '(', el, ':', ns,
- '*', &session_node,
- ')', NULL);
-
- wocky_node_set_attributes (session_node,
- "initiator", priv->initiator,
- (gtalk_mode) ? "id" : "sid", priv->sid,
- (gtalk_mode) ? "type" : "action",
- produce_action (action, priv->dialect),
- NULL);
-
- if (sess_node != NULL)
- *sess_node = session_node;
-
- return stanza;
-}
-
-typedef void (*ContentMapperFunc) (GabbleJingleSession *sess,
- GabbleJingleContent *c, gpointer user_data);
-
-static void
-_map_initial_contents (GabbleJingleSession *sess, ContentMapperFunc mapper,
- gpointer user_data)
-{
- GList *li;
- GList *contents = gabble_jingle_session_get_contents (sess);
-
- for (li = contents; li; li = li->next)
- {
- GabbleJingleContent *c = GABBLE_JINGLE_CONTENT (li->data);
- const gchar *disposition = gabble_jingle_content_get_disposition (c);
-
- if (!wocky_strdiff (disposition, "session"))
- mapper (sess, c, user_data);
- }
-
- g_list_free (contents);
-}
-
-static void
-_check_content_ready (GabbleJingleSession *sess,
- GabbleJingleContent *c, gpointer user_data)
-{
- gboolean *ready = (gboolean *) user_data;
-
- if (!gabble_jingle_content_is_ready (c))
- {
- *ready = FALSE;
- }
-}
-
-static void
-_transmit_candidates (GabbleJingleSession *sess,
- GabbleJingleContent *c,
- gpointer user_data)
-{
- gabble_jingle_content_retransmit_candidates (c, FALSE);
-}
-
-static void
-_fill_content (GabbleJingleSession *sess,
- GabbleJingleContent *c, gpointer user_data)
-{
- WockyNode *sess_node = user_data;
- WockyNode *transport_node;
- JingleContentState state;
-
- gabble_jingle_content_produce_node (c, sess_node, TRUE, TRUE,
- &transport_node);
- gabble_jingle_content_inject_candidates (c, transport_node);
-
- g_object_get (c, "state", &state, NULL);
-
- if (state == JINGLE_CONTENT_STATE_EMPTY)
- {
- g_object_set (c, "state", JINGLE_CONTENT_STATE_SENT, NULL);
- }
- else if (state == JINGLE_CONTENT_STATE_NEW)
- {
- g_object_set (c, "state", JINGLE_CONTENT_STATE_ACKNOWLEDGED, NULL);
- }
- else
- {
- DEBUG ("content %p is in state %u", c, state);
- g_assert_not_reached ();
- }
-}
-
-/**
- * gabble_jingle_session_send:
- * @sess: a session
- * @stanza: (transfer full): a stanza, of which this function will take ownership
- *
- * A shorthand for sending a Jingle IQ without waiting for the reply.
- */
-void
-gabble_jingle_session_send (GabbleJingleSession *sess,
- WockyStanza *stanza)
-{
- wocky_porter_send_iq_async (sess->priv->porter,
- stanza, NULL, NULL, NULL);
- g_object_unref (stanza);
-}
-
-static void
-_on_initiate_reply (
- GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- WockyPorter *porter = WOCKY_PORTER (source);
- GabbleJingleSession *sess = GABBLE_JINGLE_SESSION (user_data);
- GabbleJingleSessionPrivate *priv = sess->priv;
- WockyStanza *reply;
-
- if (priv->state != JINGLE_STATE_PENDING_INITIATE_SENT)
- {
- DEBUG ("Ignoring session-initiate reply; session %p is in state %u.",
- sess, priv->state);
- g_object_unref (sess);
- return;
- }
-
- reply = wocky_porter_send_iq_finish (porter, result, NULL);
- if (reply != NULL &&
- !wocky_stanza_extract_errors (reply, NULL, NULL, NULL, NULL))
- {
- set_state (sess, JINGLE_STATE_PENDING_INITIATED, 0, NULL);
-
- if (priv->dialect != JINGLE_DIALECT_V032)
- {
- /* If this is a dialect that doesn't support <ringing/>, we treat the
- * session-initiate being acked as the cue to say we're ringing.
- */
- priv->remote_ringing = TRUE;
- g_signal_emit (sess, signals[REMOTE_STATE_CHANGED], 0);
- }
- }
- else
- {
- set_state (sess, JINGLE_STATE_ENDED, JINGLE_REASON_UNKNOWN,
- NULL);
- }
-
- g_clear_object (&reply);
- g_object_unref (sess);
-}
-
-static void
-_on_accept_reply (
- GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- WockyPorter *porter = WOCKY_PORTER (source);
- GabbleJingleSession *sess = GABBLE_JINGLE_SESSION (user_data);
- GabbleJingleSessionPrivate *priv = sess->priv;
- WockyStanza *reply;
-
- if (priv->state != JINGLE_STATE_PENDING_ACCEPT_SENT)
- {
- DEBUG ("Ignoring session-accept reply; session %p is in state %u.",
- sess, priv->state);
- g_object_unref (sess);
- return;
- }
-
- reply = wocky_porter_send_iq_finish (porter, result, NULL);
- if (reply != NULL &&
- !wocky_stanza_extract_errors (reply, NULL, NULL, NULL, NULL))
- {
- set_state (sess, JINGLE_STATE_ACTIVE, 0, NULL);
- gabble_jingle_session_send_rtp_info (sess, "active");
- }
- else
- {
- set_state (sess, JINGLE_STATE_ENDED, JINGLE_REASON_UNKNOWN,
- NULL);
- }
-
- g_clear_object (&reply);
- g_object_unref (sess);
-}
-
-static void
-try_session_initiate_or_accept (GabbleJingleSession *sess)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- WockyStanza *msg;
- WockyNode *sess_node;
- gboolean contents_ready = TRUE;
- JingleAction action;
- JingleState new_state;
- GAsyncReadyCallback handler;
-
- DEBUG ("Trying initiate or accept");
-
- /* If there are no contents yet, we shouldn't have been called at all. */
- g_assert (g_hash_table_size (priv->initiator_contents) +
- g_hash_table_size (priv->responder_contents) > 0);
-
- if (priv->local_initiator)
- {
- if (priv->state != JINGLE_STATE_PENDING_CREATED)
- {
- DEBUG ("session is in state %u, won't try to initiate", priv->state);
- return;
- }
-
- if (!priv->locally_accepted)
- {
- DEBUG ("session not locally accepted yet, not initiating");
- return;
- }
-
- g_signal_emit (sess, signals[ABOUT_TO_INITIATE], 0);
-
- action = JINGLE_ACTION_SESSION_INITIATE;
- new_state = JINGLE_STATE_PENDING_INITIATE_SENT;
- handler = _on_initiate_reply;
- }
- else
- {
- if (priv->state != JINGLE_STATE_PENDING_INITIATED)
- {
- DEBUG ("session is in state %u, won't try to accept", priv->state);
- return;
- }
-
- if (!priv->locally_accepted)
- {
- DEBUG ("session not locally accepted yet, not accepting");
- return;
- }
-
- action = JINGLE_ACTION_SESSION_ACCEPT;
- new_state = JINGLE_STATE_PENDING_ACCEPT_SENT;
- handler = _on_accept_reply;
- }
-
- _map_initial_contents (sess, _check_content_ready, &contents_ready);
-
- DEBUG ("Contents are ready: %s", contents_ready ? "yes" : "no");
-
- if (!contents_ready)
- {
- DEBUG ("Contents not yet ready, not initiating/accepting now..");
- return;
- }
-
- msg = gabble_jingle_session_new_message (sess, action, &sess_node);
-
- if (priv->dialect == JINGLE_DIALECT_GTALK3)
- {
- gboolean has_video = FALSE;
- gboolean has_audio = FALSE;
- GHashTableIter iter;
- gpointer value;
-
- g_hash_table_iter_init (&iter, priv->initiator_contents);
- while (g_hash_table_iter_next (&iter, NULL, &value))
- {
- JingleMediaType type;
-
- g_object_get (value, "media-type", &type, NULL);
-
- if (type == JINGLE_MEDIA_TYPE_VIDEO)
- {
- has_video = TRUE;
- }
- else if (type == JINGLE_MEDIA_TYPE_AUDIO)
- {
- has_audio = TRUE;
- }
- }
-
- if (has_video || has_audio)
- {
- sess_node = wocky_node_add_child_with_content (sess_node, "description",
- NULL);
-
- sess_node->ns = g_quark_from_static_string (
- has_video ? NS_GOOGLE_SESSION_VIDEO : NS_GOOGLE_SESSION_PHONE);
- }
- }
-
-
- _map_initial_contents (sess, _fill_content, sess_node);
- wocky_porter_send_iq_async (priv->porter,
- msg, NULL, handler, g_object_ref (sess));
- g_object_unref (msg);
- set_state (sess, new_state, 0, NULL);
-
- /* now all initial contents can transmit their candidates */
- _map_initial_contents (sess, _transmit_candidates, NULL);
-}
-
-/**
- * set_state:
- * @sess: a jingle session
- * @state: the new state for the session
- * @termination_reason: if @state is JINGLE_STATE_ENDED, the reason the session
- * ended. Otherwise, must be JINGLE_REASON_UNKNOWN.
- * @text: if @state is JINGLE_STATE_ENDED, the human-readable reason the session
- * ended.
- */
-static void
-set_state (GabbleJingleSession *sess,
- JingleState state,
- JingleReason termination_reason,
- const gchar *text)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- if (state <= priv->state)
- {
- DEBUG ("ignoring request to set state from %u back to %u", priv->state, state);
- return;
- }
-
- if (state != JINGLE_STATE_ENDED)
- g_assert (termination_reason == JINGLE_REASON_UNKNOWN);
-
- DEBUG ("Setting state of JingleSession: %p (priv = %p) from %u to %u", sess, priv, priv->state, state);
-
- priv->state = state;
- g_object_notify (G_OBJECT (sess), "state");
-
- /* If we have an outstanding "you're on hold notification", send it */
- if (priv->local_hold &&
- state >= JINGLE_STATE_PENDING_INITIATED &&
- state < JINGLE_STATE_ENDED)
- gabble_jingle_session_send_held (sess);
-
- if (state == JINGLE_STATE_ENDED)
- g_signal_emit (sess, signals[TERMINATED], 0, priv->locally_terminated,
- termination_reason, text);
-}
-
-void
-gabble_jingle_session_accept (GabbleJingleSession *sess)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- priv->locally_accepted = TRUE;
-
- try_session_initiate_or_accept (sess);
-}
-
-const gchar *
-gabble_jingle_session_get_reason_name (JingleReason reason)
-{
- GEnumClass *klass = g_type_class_ref (jingle_reason_get_type ());
- GEnumValue *enum_value = g_enum_get_value (klass, (gint) reason);
-
- g_return_val_if_fail (enum_value != NULL, NULL);
-
- return enum_value->value_nick;
-}
-
-gboolean
-gabble_jingle_session_terminate (GabbleJingleSession *sess,
- JingleReason reason,
- const gchar *text,
- GError **error)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- const gchar *reason_elt;
-
- if (priv->state == JINGLE_STATE_ENDED)
- {
- DEBUG ("session already terminated, ignoring terminate request");
- return TRUE;
- }
-
- if (reason == JINGLE_REASON_UNKNOWN)
- reason = (priv->state == JINGLE_STATE_ACTIVE) ?
- JINGLE_REASON_SUCCESS : JINGLE_REASON_CANCEL;
-
- reason_elt = gabble_jingle_session_get_reason_name (reason);
-
- if (priv->state != JINGLE_STATE_PENDING_CREATED)
- {
- WockyNode *session_node;
- WockyStanza *msg = gabble_jingle_session_new_message (sess,
- JINGLE_ACTION_SESSION_TERMINATE, &session_node);
-
- if (priv->dialect == JINGLE_DIALECT_V032 && reason_elt != NULL)
- {
- WockyNode *r = wocky_node_add_child_with_content (session_node, "reason",
- NULL);
-
- wocky_node_add_child_with_content (r, reason_elt, NULL);
-
- if (text != NULL && *text != '\0')
- wocky_node_add_child_with_content (r, "text", text);
- }
-
- gabble_jingle_session_send (sess, msg);
- }
-
- /* NOTE: on "terminated", jingle factory and media channel will unref
- * it, bringing refcount to 0, so dispose will be called, and it
- * takes care of cleanup */
-
- DEBUG ("we are terminating this session");
- priv->locally_terminated = TRUE;
- set_state (sess, JINGLE_STATE_ENDED, reason, text);
-
- return TRUE;
-}
-
-static void
-_foreach_count_active_contents (gpointer key, gpointer value, gpointer user_data)
-{
- GabbleJingleContent *c = value;
- guint *n_contents = user_data;
- JingleContentState state;
-
- g_object_get (c, "state", &state, NULL);
- if ((state >= JINGLE_CONTENT_STATE_NEW) &&
- (state < JINGLE_CONTENT_STATE_REMOVING))
- {
- *n_contents = *n_contents + 1;
- }
-}
-
-static gboolean
-count_active_contents (GabbleJingleSession *sess)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- guint n_contents = 0;
-
- g_hash_table_foreach (priv->initiator_contents, _foreach_count_active_contents,
- &n_contents);
- g_hash_table_foreach (priv->responder_contents, _foreach_count_active_contents,
- &n_contents);
-
- return n_contents;
-}
-
-static void
-content_removed_cb (GabbleJingleContent *c, gpointer user_data)
-{
- GabbleJingleSession *sess = GABBLE_JINGLE_SESSION (user_data);
- GabbleJingleSessionPrivate *priv = sess->priv;
- const gchar *name = gabble_jingle_content_get_name (c);
-
- if (gabble_jingle_content_creator_is_initiator (c))
- g_hash_table_remove (priv->initiator_contents, name);
- else
- g_hash_table_remove (priv->responder_contents, name);
-
- if (priv->state == JINGLE_STATE_ENDED)
- return;
-
- if (count_active_contents (sess) == 0)
- {
- gabble_jingle_session_terminate (sess,
- JINGLE_REASON_UNKNOWN, NULL, NULL);
- }
- else
- {
- /* It's possible the content now removed was
- * blocking us from creating or accepting the
- * session, so we might as well try now. */
- try_session_initiate_or_accept (sess);
- }
-}
-
-
-void
-gabble_jingle_session_remove_content (GabbleJingleSession *sess,
- GabbleJingleContent *c)
-{
- if (count_active_contents (sess) > 1)
- {
- gabble_jingle_content_remove (c, TRUE);
- }
- else
- {
- /* session will be terminated when the content gets marked as removed */
- DEBUG ("called for last active content, doing session-terminate instead");
- gabble_jingle_content_remove (c, FALSE);
- }
-}
-
-GabbleJingleContent *
-gabble_jingle_session_add_content (GabbleJingleSession *sess,
- JingleMediaType mtype,
- JingleContentSenders senders,
- const gchar *name,
- const gchar *content_ns,
- const gchar *transport_ns)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
- GabbleJingleContent *c;
- GType content_type;
- GHashTable *contents = priv->local_initiator ? priv->initiator_contents
- : priv->responder_contents;
- guint id = g_hash_table_size (contents) + 1;
- gchar *cname = NULL;
-
- if (name == NULL || *name == '\0')
- name = (mtype == JINGLE_MEDIA_TYPE_AUDIO ? "Audio" : "Video");
-
- cname = g_strdup (name);
-
- while (g_hash_table_lookup (priv->initiator_contents, cname) != NULL
- || g_hash_table_lookup (priv->responder_contents, cname) != NULL)
- {
- g_free (cname);
- cname = g_strdup_printf ("%s_%d", name, id++);
- }
-
- content_type = gabble_jingle_factory_lookup_content_type (
- gabble_jingle_session_get_factory (sess),
- content_ns);
-
- g_assert (content_type != 0);
-
- c = create_content (sess, content_type, mtype, senders,
- content_ns, transport_ns, cname, NULL, NULL);
-
- /* The new content better have ended up in the set we thought it would... */
- g_assert (g_hash_table_lookup (contents, cname) != NULL);
-
- g_free (cname);
-
- return c;
-}
-
-/* Get any content. Either we're in google mode (so we only have one content
- * anyways), or we just need any content type to figure out what use case
- * we're in (media, ft, etc). */
-static GabbleJingleContent *
-_get_any_content (GabbleJingleSession *session)
-{
- GabbleJingleContent *c;
-
- GList *li = gabble_jingle_session_get_contents (session);
-
- if (li == NULL)
- return NULL;
-
- c = li->data;
- g_list_free (li);
-
- return c;
-}
-
-/* Note: if there are multiple content types, not guaranteed which one will
- * be returned. Typically, the same GType will know how to handle related
- * contents found in a session (e.g. media-rtp for audio/video), so that
- * should not be a problem. Returns 0 if there are no contents yet. */
-GType
-gabble_jingle_session_get_content_type (GabbleJingleSession *sess)
-{
- GabbleJingleContent *c = _get_any_content (sess);
-
- if (c == NULL)
- return 0;
-
- return G_OBJECT_TYPE (c);
-}
-
-/* FIXME: probably should make this into a property */
-GList *
-gabble_jingle_session_get_contents (GabbleJingleSession *sess)
-{
- GabbleJingleSessionPrivate *priv = sess->priv;
-
- return g_list_concat (g_hash_table_get_values (priv->initiator_contents),
- g_hash_table_get_values (priv->responder_contents));
-}
-
-const gchar *
-gabble_jingle_session_get_peer_resource (GabbleJingleSession *sess)
-{
- return sess->priv->peer_resource;
-}
-
-const gchar *
-gabble_jingle_session_get_initiator (GabbleJingleSession *sess)
-{
- return sess->priv->initiator;
-}
-
-const gchar *
-gabble_jingle_session_get_sid (GabbleJingleSession *sess)
-{
- return sess->priv->sid;
-}
-
-static void
-content_ready_cb (GabbleJingleContent *c, gpointer user_data)
-{
- GabbleJingleSession *sess = GABBLE_JINGLE_SESSION (user_data);
- const gchar *disposition;
-
- DEBUG ("called");
-
- disposition = gabble_jingle_content_get_disposition (c);
- /* This assertion is actually safe, because 'ready' is only emitted by
- * contents with disposition "session". But this is crazy.
- */
- g_assert (!wocky_strdiff (disposition, "session"));
-
- try_session_initiate_or_accept (sess);
-}
-
-static void
-gabble_jingle_session_send_rtp_info (GabbleJingleSession *sess,
- const gchar *name)
-{
- WockyStanza *message;
- WockyNode *jingle, *notification;
-
- if (!gabble_jingle_session_defines_action (sess, JINGLE_ACTION_SESSION_INFO))
- {
- DEBUG ("Not sending <%s/>; not using modern Jingle", name);
- return;
- }
-
- message = gabble_jingle_session_new_message (sess,
- JINGLE_ACTION_SESSION_INFO, &jingle);
-
- notification = wocky_node_add_child_with_content (jingle, name, NULL);
- notification->ns = g_quark_from_static_string (NS_JINGLE_RTP_INFO);
-
- /* This is just informational, so ignoring the reply. */
- gabble_jingle_session_send (sess, message);
-}
-
-static void
-gabble_jingle_session_send_held (GabbleJingleSession *sess)
-{
- const gchar *s = (sess->priv->local_hold ? "hold" : "unhold");
-
- gabble_jingle_session_send_rtp_info (sess, s);
-}
-
-void
-gabble_jingle_session_set_local_hold (GabbleJingleSession *sess,
- gboolean held)
-{
- g_object_set (sess, "local-hold", held, NULL);
-}
-
-gboolean
-gabble_jingle_session_get_remote_hold (GabbleJingleSession *sess)
-{
- g_assert (GABBLE_IS_JINGLE_SESSION (sess));
-
- return sess->priv->remote_hold;
-}
-
-gboolean
-gabble_jingle_session_get_remote_ringing (GabbleJingleSession *sess)
-{
- g_assert (GABBLE_IS_JINGLE_SESSION (sess));
-
- return sess->priv->remote_ringing;
-}
-
-gboolean
-gabble_jingle_session_can_modify_contents (GabbleJingleSession *sess)
-{
- return !JINGLE_IS_GOOGLE_DIALECT (sess->priv->dialect) &&
- !gabble_jingle_session_peer_has_cap (sess, QUIRK_GOOGLE_WEBMAIL_CLIENT);
-}
-
-JingleDialect
-gabble_jingle_session_get_dialect (GabbleJingleSession *sess)
-{
- return sess->priv->dialect;
-}
-
-WockyContact *
-gabble_jingle_session_get_peer_contact (GabbleJingleSession *self)
-{
- return self->priv->peer_contact;
-}
-
-/*
- * gabble_jingle_session_get_peer_jid:
- * @sess: a jingle session
- *
- * Returns: the full JID of the remote contact.
- */
-const gchar *
-gabble_jingle_session_get_peer_jid (GabbleJingleSession *sess)
-{
- return sess->priv->peer_jid;
-}
-
-GabbleJingleFactory *
-gabble_jingle_session_get_factory (GabbleJingleSession *self)
-{
- return self->priv->jingle_factory;
-}
-
-WockyPorter *
-gabble_jingle_session_get_porter (GabbleJingleSession *self)
-{
- return self->priv->porter;
-}
diff --git a/src/jingle-session.h b/src/jingle-session.h
deleted file mode 100644
index 95bc23af1..000000000
--- a/src/jingle-session.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * jingle-session.h - Header for GabbleJingleSession
- * Copyright (C) 2008 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 __JINGLE_SESSION_H__
-#define __JINGLE_SESSION_H__
-
-#include <glib-object.h>
-#include <wocky/wocky.h>
-
-#include "jingle-content.h"
-#include "jingle-factory.h"
-#include "jingle-types.h"
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- MODE_GOOGLE,
- MODE_JINGLE
-} GabbleMediaSessionMode;
-
-typedef struct _GabbleJingleSessionClass GabbleJingleSessionClass;
-
-GType gabble_jingle_session_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_SESSION \
- (gabble_jingle_session_get_type ())
-#define GABBLE_JINGLE_SESSION(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_SESSION, \
- GabbleJingleSession))
-#define GABBLE_JINGLE_SESSION_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_SESSION, \
- GabbleJingleSessionClass))
-#define GABBLE_IS_JINGLE_SESSION(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_SESSION))
-#define GABBLE_IS_JINGLE_SESSION_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_SESSION))
-#define GABBLE_JINGLE_SESSION_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_SESSION, \
- GabbleJingleSessionClass))
-
-struct _GabbleJingleSessionClass {
- GObjectClass parent_class;
-};
-
-typedef struct _GabbleJingleSessionPrivate GabbleJingleSessionPrivate;
-
-struct _GabbleJingleSession {
- GObject parent;
- GabbleJingleSessionPrivate *priv;
-};
-
-GabbleJingleSession *gabble_jingle_session_new (
- GabbleJingleFactory *factory,
- WockyPorter *porter,
- const gchar *session_id,
- gboolean local_initiator,
- WockyContact *peer,
- JingleDialect dialect,
- gboolean local_hold);
-
-const gchar * gabble_jingle_session_detect (WockyStanza *stanza,
- JingleAction *action, JingleDialect *dialect);
-gboolean gabble_jingle_session_parse (GabbleJingleSession *sess,
- JingleAction action, WockyStanza *stanza, GError **error);
-WockyStanza *gabble_jingle_session_new_message (GabbleJingleSession *sess,
- JingleAction action, WockyNode **sess_node);
-
-void gabble_jingle_session_accept (GabbleJingleSession *sess);
-gboolean gabble_jingle_session_terminate (GabbleJingleSession *sess,
- JingleReason reason,
- const gchar *text,
- GError **error);
-void gabble_jingle_session_remove_content (GabbleJingleSession *sess,
- GabbleJingleContent *c);
-
-GabbleJingleContent *
-gabble_jingle_session_add_content (GabbleJingleSession *sess,
- JingleMediaType mtype,
- JingleContentSenders senders,
- const char *name,
- const gchar *content_ns,
- const gchar *transport_ns);
-
-GType gabble_jingle_session_get_content_type (GabbleJingleSession *);
-GList *gabble_jingle_session_get_contents (GabbleJingleSession *sess);
-const gchar *gabble_jingle_session_get_peer_resource (
- GabbleJingleSession *sess);
-const gchar *gabble_jingle_session_get_initiator (
- GabbleJingleSession *sess);
-const gchar *gabble_jingle_session_get_sid (GabbleJingleSession *sess);
-JingleDialect gabble_jingle_session_get_dialect (GabbleJingleSession *sess);
-
-gboolean gabble_jingle_session_can_modify_contents (GabbleJingleSession *sess);
-gboolean gabble_jingle_session_peer_has_cap (
- GabbleJingleSession *self,
- const gchar *cap_or_quirk);
-
-void gabble_jingle_session_send (
- GabbleJingleSession *sess,
- WockyStanza *stanza);
-
-void gabble_jingle_session_set_local_hold (GabbleJingleSession *sess,
- gboolean held);
-
-gboolean gabble_jingle_session_get_remote_hold (GabbleJingleSession *sess);
-
-gboolean gabble_jingle_session_get_remote_ringing (GabbleJingleSession *sess);
-
-gboolean gabble_jingle_session_defines_action (GabbleJingleSession *sess,
- JingleAction action);
-
-WockyContact *gabble_jingle_session_get_peer_contact (GabbleJingleSession *self);
-const gchar *gabble_jingle_session_get_peer_jid (GabbleJingleSession *sess);
-
-const gchar *gabble_jingle_session_get_reason_name (JingleReason reason);
-
-GabbleJingleFactory *gabble_jingle_session_get_factory (GabbleJingleSession *self);
-WockyPorter *gabble_jingle_session_get_porter (GabbleJingleSession *self);
-
-#endif /* __JINGLE_SESSION_H__ */
-
diff --git a/src/jingle-share.c b/src/jingle-share.c
index 838888c2d..a4909f2b0 100644
--- a/src/jingle-share.c
+++ b/src/jingle-share.c
@@ -34,9 +34,6 @@
#include "connection.h"
#include "debug.h"
-#include "jingle-content.h"
-#include "jingle-factory.h"
-#include "jingle-session.h"
#include "namespaces.h"
#include "util.h"
@@ -68,7 +65,7 @@
G_DEFINE_TYPE (GabbleJingleShare,
- gabble_jingle_share, GABBLE_TYPE_JINGLE_CONTENT);
+ gabble_jingle_share, WOCKY_TYPE_JINGLE_CONTENT);
/* properties */
enum
@@ -182,9 +179,9 @@ gabble_jingle_share_dispose (GObject *object)
}
-static void parse_description (GabbleJingleContent *content,
+static void parse_description (WockyJingleContent *content,
WockyNode *desc_node, GError **error);
-static void produce_description (GabbleJingleContent *obj,
+static void produce_description (WockyJingleContent *obj,
WockyNode *content_node);
@@ -200,7 +197,7 @@ gabble_jingle_share_get_property (GObject *object,
switch (property_id)
{
case PROP_MEDIA_TYPE:
- g_value_set_uint (value, JINGLE_MEDIA_TYPE_NONE);
+ g_value_set_uint (value, WOCKY_JINGLE_MEDIA_TYPE_NONE);
break;
case PROP_FILENAME:
g_value_set_string (value, priv->filename);
@@ -232,7 +229,7 @@ gabble_jingle_share_set_property (GObject *object,
priv->filename = g_value_dup_string (value);
free_manifest (self);
/* simulate a media_ready when we know our own filename */
- _gabble_jingle_content_set_media_ready (GABBLE_JINGLE_CONTENT (self));
+ _wocky_jingle_content_set_media_ready (WOCKY_JINGLE_CONTENT (self));
break;
case PROP_FILESIZE:
priv->filesize = g_value_get_uint64 (value);
@@ -244,17 +241,17 @@ gabble_jingle_share_set_property (GObject *object,
}
}
-static JingleContentSenders
-get_default_senders (GabbleJingleContent *c)
+static WockyJingleContentSenders
+get_default_senders (WockyJingleContent *c)
{
- return JINGLE_CONTENT_SENDERS_INITIATOR;
+ return WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR;
}
static void
gabble_jingle_share_class_init (GabbleJingleShareClass *cls)
{
GObjectClass *object_class = G_OBJECT_CLASS (cls);
- GabbleJingleContentClass *content_class = GABBLE_JINGLE_CONTENT_CLASS (cls);
+ WockyJingleContentClass *content_class = WOCKY_JINGLE_CONTENT_CLASS (cls);
g_type_class_add_private (cls, sizeof (GabbleJingleSharePrivate));
@@ -271,8 +268,8 @@ gabble_jingle_share_class_init (GabbleJingleShareClass *cls)
g_object_class_install_property (object_class, PROP_MEDIA_TYPE,
g_param_spec_uint ("media-type", "media type",
"irrelevant media type. Will always be NONE.",
- JINGLE_MEDIA_TYPE_NONE, JINGLE_MEDIA_TYPE_NONE,
- JINGLE_MEDIA_TYPE_NONE,
+ WOCKY_JINGLE_MEDIA_TYPE_NONE, WOCKY_JINGLE_MEDIA_TYPE_NONE,
+ WOCKY_JINGLE_MEDIA_TYPE_NONE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_FILENAME,
@@ -290,7 +287,7 @@ gabble_jingle_share_class_init (GabbleJingleShareClass *cls)
}
static void
-parse_description (GabbleJingleContent *content,
+parse_description (WockyJingleContent *content,
WockyNode *desc_node, GError **error)
{
GabbleJingleShare *self = GABBLE_JINGLE_SHARE (content);
@@ -438,11 +435,11 @@ parse_description (GabbleJingleContent *content,
g_free (temp);
}
}
- _gabble_jingle_content_set_media_ready (content);
+ _wocky_jingle_content_set_media_ready (content);
}
static void
-produce_description (GabbleJingleContent *content, WockyNode *content_node)
+produce_description (WockyJingleContent *content, WockyNode *content_node)
{
GabbleJingleShare *self = GABBLE_JINGLE_SHARE (content);
GabbleJingleSharePrivate *priv = self->priv;
@@ -458,11 +455,10 @@ produce_description (GabbleJingleContent *content, WockyNode *content_node)
ensure_manifest (self);
- desc_node = wocky_node_add_child_with_content (content_node, "description", NULL);
+ desc_node = wocky_node_add_child_ns (content_node, "description",
+ NS_GOOGLE_SESSION_SHARE);
- desc_node->ns = g_quark_from_string (NS_GOOGLE_SESSION_SHARE);
-
- manifest_node = wocky_node_add_child_with_content (desc_node, "manifest", NULL);
+ manifest_node = wocky_node_add_child (desc_node, "manifest");
for (i = priv->manifest->entries; i; i = i->next)
{
@@ -472,9 +468,9 @@ produce_description (GabbleJingleContent *content, WockyNode *content_node)
gchar *size_str, *width_str, *height_str;
if (m->folder)
- file_node = wocky_node_add_child_with_content (manifest_node, "folder", NULL);
+ file_node = wocky_node_add_child (manifest_node, "folder");
else
- file_node = wocky_node_add_child_with_content (manifest_node, "file", NULL);
+ file_node = wocky_node_add_child (manifest_node, "file");
if (m->size > 0)
{
@@ -487,7 +483,7 @@ produce_description (GabbleJingleContent *content, WockyNode *content_node)
if (m->image &&
(m->image_width > 0 || m->image_height > 0))
{
- image_node = wocky_node_add_child_with_content (file_node, "image", NULL);
+ image_node = wocky_node_add_child (file_node, "image");
if (m->image_width > 0)
{
width_str = g_strdup_printf ("%d", m->image_width);
@@ -504,8 +500,8 @@ produce_description (GabbleJingleContent *content, WockyNode *content_node)
}
}
- protocol_node = wocky_node_add_child_with_content (desc_node, "protocol", NULL);
- http_node = wocky_node_add_child_with_content (protocol_node, "http", NULL);
+ protocol_node = wocky_node_add_child (desc_node, "protocol");
+ http_node = wocky_node_add_child (protocol_node, "http");
url_node = wocky_node_add_child_with_content (http_node, "url",
priv->manifest->source_url);
wocky_node_set_attribute (url_node, "name", "source-path");
@@ -523,10 +519,10 @@ gabble_jingle_share_get_manifest (GabbleJingleShare *self)
}
void
-jingle_share_register (GabbleJingleFactory *factory)
+jingle_share_register (WockyJingleFactory *factory)
{
/* GTalk video call namespace */
- gabble_jingle_factory_register_content_type (factory,
+ wocky_jingle_factory_register_content_type (factory,
NS_GOOGLE_SESSION_SHARE,
GABBLE_TYPE_JINGLE_SHARE);
}
diff --git a/src/jingle-share.h b/src/jingle-share.h
index 27d1ecce8..06066c987 100644
--- a/src/jingle-share.h
+++ b/src/jingle-share.h
@@ -21,9 +21,7 @@
#define __JINGLE_SHARE_H__
#include <glib-object.h>
-
-#include "jingle-content.h"
-#include "jingle-types.h"
+#include <wocky/wocky.h>
G_BEGIN_DECLS
@@ -49,13 +47,14 @@ GType gabble_jingle_share_get_type (void);
GabbleJingleShareClass))
struct _GabbleJingleShareClass {
- GabbleJingleContentClass parent_class;
+ WockyJingleContentClass parent_class;
};
typedef struct _GabbleJingleSharePrivate GabbleJingleSharePrivate;
+typedef struct _GabbleJingleShare GabbleJingleShare;
struct _GabbleJingleShare {
- GabbleJingleContent parent;
+ WockyJingleContent parent;
GabbleJingleSharePrivate *priv;
};
@@ -75,7 +74,7 @@ typedef struct {
GList *entries;
} GabbleJingleShareManifest;
-void jingle_share_register (GabbleJingleFactory *factory);
+void jingle_share_register (WockyJingleFactory *factory);
gchar *gabble_jingle_share_get_source_url (GabbleJingleShare *content);
gchar *gabble_jingle_share_get_preview_url (GabbleJingleShare *content);
diff --git a/src/jingle-tp-util.c b/src/jingle-tp-util.c
index d6378f45c..212579f20 100644
--- a/src/jingle-tp-util.c
+++ b/src/jingle-tp-util.c
@@ -21,28 +21,28 @@
#include "jingle-tp-util.h"
-JingleMediaType
-jingle_media_type_from_tp (TpMediaStreamType type)
+WockyJingleMediaType
+wocky_jingle_media_type_from_tp (TpMediaStreamType type)
{
switch (type)
{
case TP_MEDIA_STREAM_TYPE_AUDIO:
- return JINGLE_MEDIA_TYPE_AUDIO;
+ return WOCKY_JINGLE_MEDIA_TYPE_AUDIO;
case TP_MEDIA_STREAM_TYPE_VIDEO:
- return JINGLE_MEDIA_TYPE_VIDEO;
+ return WOCKY_JINGLE_MEDIA_TYPE_VIDEO;
default:
- g_return_val_if_reached (JINGLE_MEDIA_TYPE_NONE);
+ g_return_val_if_reached (WOCKY_JINGLE_MEDIA_TYPE_NONE);
}
}
TpMediaStreamType
-jingle_media_type_to_tp (JingleMediaType type)
+wocky_jingle_media_type_to_tp (WockyJingleMediaType type)
{
switch (type)
{
- case JINGLE_MEDIA_TYPE_AUDIO:
+ case WOCKY_JINGLE_MEDIA_TYPE_AUDIO:
return TP_MEDIA_STREAM_TYPE_AUDIO;
- case JINGLE_MEDIA_TYPE_VIDEO:
+ case WOCKY_JINGLE_MEDIA_TYPE_VIDEO:
return TP_MEDIA_STREAM_TYPE_VIDEO;
default:
g_return_val_if_reached (TP_MEDIA_STREAM_TYPE_AUDIO);
@@ -50,9 +50,9 @@ jingle_media_type_to_tp (JingleMediaType type)
}
static const gchar * const relay_type_map[] = {
- /* GABBLE_JINGLE_RELAY_TYPE_UDP */ "udp",
- /* GABBLE_JINGLE_RELAY_TYPE_TCP */ "tcp",
- /* GABBLE_JINGLE_RELAY_TYPE_TLS */ "tls",
+ /* WOCKY_JINGLE_RELAY_TYPE_UDP */ "udp",
+ /* WOCKY_JINGLE_RELAY_TYPE_TCP */ "tcp",
+ /* WOCKY_JINGLE_RELAY_TYPE_TLS */ "tls",
};
GPtrArray *
@@ -65,9 +65,9 @@ gabble_build_tp_relay_info (GPtrArray *relays)
for (i = 0; i < relays->len; i++)
{
- GabbleJingleRelay *relay = g_ptr_array_index (relays, i);
+ WockyJingleRelay *relay = g_ptr_array_index (relays, i);
- g_return_val_if_fail (relay->type < GABBLE_N_JINGLE_RELAY_TYPES, tp_relays);
+ g_return_val_if_fail (relay->type < WOCKY_N_JINGLE_RELAY_TYPES, tp_relays);
g_ptr_array_add (tp_relays, tp_asv_new (
"type", G_TYPE_STRING, relay_type_map[relay->type],
diff --git a/src/jingle-tp-util.h b/src/jingle-tp-util.h
index f573c1132..47091c53a 100644
--- a/src/jingle-tp-util.h
+++ b/src/jingle-tp-util.h
@@ -21,10 +21,10 @@
#define GABBLE_JINGLE_TP_UTIL_H
#include <telepathy-glib/telepathy-glib.h>
-#include "jingle-content.h"
+#include <wocky/wocky.h>
-JingleMediaType jingle_media_type_from_tp (TpMediaStreamType type);
-TpMediaStreamType jingle_media_type_to_tp (JingleMediaType type);
+WockyJingleMediaType wocky_jingle_media_type_from_tp (TpMediaStreamType type);
+TpMediaStreamType wocky_jingle_media_type_to_tp (WockyJingleMediaType type);
GPtrArray *gabble_build_tp_relay_info (GPtrArray *relays);
diff --git a/src/jingle-transport-google.c b/src/jingle-transport-google.c
deleted file mode 100644
index 491036d48..000000000
--- a/src/jingle-transport-google.c
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- * jingle-transport-google.c - Source for GabbleJingleTransportGoogle
- *
- * Copyright (C) 2008 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 "config.h"
-#include "jingle-transport-google.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "debug.h"
-#include "jingle-content.h"
-#include "jingle-factory.h"
-#include "jingle-session.h"
-#include "namespaces.h"
-
-static void
-transport_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleJingleTransportGoogle,
- gabble_jingle_transport_google, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (GABBLE_TYPE_JINGLE_TRANSPORT_IFACE,
- transport_iface_init));
-
-/* signal enum */
-enum
-{
- NEW_CANDIDATES,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_CONTENT = 1,
- PROP_TRANSPORT_NS,
- PROP_STATE,
- LAST_PROPERTY
-};
-
-struct _GabbleJingleTransportGooglePrivate
-{
- GabbleJingleContent *content;
- JingleTransportState state;
- gchar *transport_ns;
-
- /* Component names or jingle-share transport 'channels'
- g_strdup'd component name => GINT_TO_POINTER (component id) */
- GHashTable *component_names;
-
- GList *local_candidates;
-
- /* A pointer into "local_candidates" list to mark the
- * candidates that are still not transmitted, or NULL
- * if all of them are transmitted. */
-
- GList *pending_candidates;
- GList *remote_candidates;
- gboolean dispose_has_run;
-};
-
-static void
-gabble_jingle_transport_google_init (GabbleJingleTransportGoogle *obj)
-{
- GabbleJingleTransportGooglePrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE,
- GabbleJingleTransportGooglePrivate);
- obj->priv = priv;
-
- priv->component_names = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
-
- priv->dispose_has_run = FALSE;
-}
-
-static void
-gabble_jingle_transport_google_dispose (GObject *object)
-{
- GabbleJingleTransportGoogle *trans = GABBLE_JINGLE_TRANSPORT_GOOGLE (object);
- GabbleJingleTransportGooglePrivate *priv = trans->priv;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- g_hash_table_unref (priv->component_names);
- priv->component_names = NULL;
-
- jingle_transport_free_candidates (priv->remote_candidates);
- priv->remote_candidates = NULL;
-
- jingle_transport_free_candidates (priv->local_candidates);
- priv->local_candidates = NULL;
-
- g_free (priv->transport_ns);
- priv->transport_ns = NULL;
-
- if (G_OBJECT_CLASS (gabble_jingle_transport_google_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_jingle_transport_google_parent_class)->dispose (object);
-}
-
-static void
-gabble_jingle_transport_google_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleTransportGoogle *trans = GABBLE_JINGLE_TRANSPORT_GOOGLE (object);
- GabbleJingleTransportGooglePrivate *priv = trans->priv;
-
- switch (property_id) {
- case PROP_CONTENT:
- g_value_set_object (value, priv->content);
- break;
- case PROP_TRANSPORT_NS:
- g_value_set_string (value, priv->transport_ns);
- 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
-gabble_jingle_transport_google_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleTransportGoogle *trans = GABBLE_JINGLE_TRANSPORT_GOOGLE (object);
- GabbleJingleTransportGooglePrivate *priv = trans->priv;
-
- switch (property_id) {
- case PROP_CONTENT:
- priv->content = g_value_get_object (value);
- break;
- case PROP_TRANSPORT_NS:
- g_free (priv->transport_ns);
- priv->transport_ns = g_value_dup_string (value);
- break;
- case PROP_STATE:
- priv->state = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_jingle_transport_google_class_init (GabbleJingleTransportGoogleClass *cls)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (cls);
- GParamSpec *param_spec;
-
- g_type_class_add_private (cls, sizeof (GabbleJingleTransportGooglePrivate));
-
- object_class->get_property = gabble_jingle_transport_google_get_property;
- object_class->set_property = gabble_jingle_transport_google_set_property;
- object_class->dispose = gabble_jingle_transport_google_dispose;
-
- /* property definitions */
- param_spec = g_param_spec_object ("content", "GabbleJingleContent object",
- "Jingle content object using this transport.",
- GABBLE_TYPE_JINGLE_CONTENT,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONTENT, param_spec);
-
- param_spec = g_param_spec_string ("transport-ns", "Transport namespace",
- "Namespace identifying the transport type.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_TRANSPORT_NS, param_spec);
-
- param_spec = g_param_spec_uint ("state",
- "Connection state for the transport.",
- "Enum specifying the connection state of the transport.",
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- JINGLE_TRANSPORT_STATE_CONNECTED,
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- /* signal definitions */
- signals[NEW_CANDIDATES] = g_signal_new (
- "new-candidates",
- G_TYPE_FROM_CLASS (cls),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-}
-
-static void
-parse_candidates (GabbleJingleTransportIface *obj,
- WockyNode *transport_node, GError **error)
-{
- GabbleJingleTransportGoogle *t = GABBLE_JINGLE_TRANSPORT_GOOGLE (obj);
- GabbleJingleTransportGooglePrivate *priv = t->priv;
- GList *candidates = NULL;
- WockyNodeIter i;
- WockyNode *node;
-
- wocky_node_iter_init (&i, transport_node, "candidate", NULL);
- while (wocky_node_iter_next (&i, &node))
- {
- const gchar *name, *address, *user, *pass, *str;
- guint port, net, gen, component;
- int pref;
- JingleTransportProtocol proto;
- JingleCandidateType ctype;
- JingleCandidate *c;
-
- name = wocky_node_get_attribute (node, "name");
- if (name == NULL)
- break;
-
- if (!g_hash_table_lookup_extended (priv->component_names, name,
- NULL, NULL))
- {
- DEBUG ("component name %s unknown to this transport", name);
- continue;
- }
-
- component = GPOINTER_TO_INT (g_hash_table_lookup (priv->component_names,
- name));
- address = wocky_node_get_attribute (node, "address");
- if (address == NULL)
- break;
-
- str = wocky_node_get_attribute (node, "port");
- if (str == NULL)
- break;
- port = atoi (str);
-
- str = wocky_node_get_attribute (node, "protocol");
- if (str == NULL)
- break;
-
- if (!wocky_strdiff (str, "udp"))
- {
- proto = JINGLE_TRANSPORT_PROTOCOL_UDP;
- }
- else if (!wocky_strdiff (str, "tcp"))
- {
- /* candiates on port 443 must be "ssltcp" */
- if (port == 443)
- break;
-
- proto = JINGLE_TRANSPORT_PROTOCOL_TCP;
- }
- else if (!wocky_strdiff (str, "ssltcp"))
- {
- /* "ssltcp" must use port 443 */
- if (port != 443)
- break;
-
- /* we really don't care about "ssltcp" otherwise */
- proto = JINGLE_TRANSPORT_PROTOCOL_TCP;
- }
- else
- {
- /* unknown protocol */
- DEBUG ("unknown protocol: %s", str);
- break;
- }
-
- str = wocky_node_get_attribute (node, "preference");
- if (str == NULL)
- break;
-
- pref = g_ascii_strtod (str, NULL) * 65536;
-
- str = wocky_node_get_attribute (node, "type");
- if (str == NULL)
- break;
-
- if (!wocky_strdiff (str, "local"))
- {
- ctype = JINGLE_CANDIDATE_TYPE_LOCAL;
- }
- else if (!wocky_strdiff (str, "stun"))
- {
- ctype = JINGLE_CANDIDATE_TYPE_STUN;
- }
- else if (!wocky_strdiff (str, "relay"))
- {
- ctype = JINGLE_CANDIDATE_TYPE_RELAY;
- }
- else
- {
- /* unknown candidate type */
- DEBUG ("unknown candidate type: %s", str);
- break;
- }
-
- user = wocky_node_get_attribute (node, "username");
- if (user == NULL)
- break;
-
- pass = wocky_node_get_attribute (node, "password");
- if (pass == NULL)
- break;
-
- str = wocky_node_get_attribute (node, "network");
- if (str == NULL)
- break;
- net = atoi (str);
-
- str = wocky_node_get_attribute (node, "generation");
- if (str == NULL)
- break;
- gen = atoi (str);
-
- str = wocky_node_get_attribute (node, "component");
- if (str != NULL)
- component = atoi (str);
-
- c = jingle_candidate_new (proto, ctype, NULL, component,
- address, port, gen, pref, user, pass, net);
-
- candidates = g_list_append (candidates, c);
- }
-
- if (wocky_node_iter_next (&i, NULL))
- {
- DEBUG ("not all nodes were processed, reporting error");
- /* rollback these */
- jingle_transport_free_candidates (candidates);
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "invalid candidate");
- return;
- }
-
- DEBUG ("emitting %d new remote candidates", g_list_length (candidates));
-
- g_signal_emit (obj, signals[NEW_CANDIDATES], 0, candidates);
-
- /* append them to the known remote candidates */
- priv->remote_candidates = g_list_concat (priv->remote_candidates, candidates);
-}
-
-static void
-transmit_candidates (GabbleJingleTransportGoogle *transport,
- const gchar *name,
- GList *candidates)
-{
- GabbleJingleTransportGooglePrivate *priv = transport->priv;
- GList *li;
- WockyStanza *msg;
- WockyNode *trans_node, *sess_node;
-
- if (candidates == NULL)
- return;
-
- msg = gabble_jingle_session_new_message (priv->content->session,
- JINGLE_ACTION_TRANSPORT_INFO, &sess_node);
-
- gabble_jingle_content_produce_node (priv->content, sess_node, FALSE, TRUE,
- &trans_node);
-
- for (li = candidates; li; li = li->next)
- {
- JingleCandidate *c = (JingleCandidate *) li->data;
- gchar port_str[16], pref_str[16], comp_str[16], *type_str, *proto_str;
- WockyNode *cnode;
-
- sprintf (port_str, "%d", c->port);
- sprintf (pref_str, "%lf", c->preference / 65536.0);
- sprintf (comp_str, "%d", c->component);
-
- switch (c->type) {
- case JINGLE_CANDIDATE_TYPE_LOCAL:
- type_str = "local";
- break;
- case JINGLE_CANDIDATE_TYPE_STUN:
- type_str = "stun";
- break;
- case JINGLE_CANDIDATE_TYPE_RELAY:
- type_str = "relay";
- break;
- default:
- g_assert_not_reached ();
- }
-
- switch (c->protocol) {
- case JINGLE_TRANSPORT_PROTOCOL_UDP:
- proto_str = "udp";
- break;
- case JINGLE_TRANSPORT_PROTOCOL_TCP:
- if ((c->port == 443) && (c->type == JINGLE_CANDIDATE_TYPE_RELAY))
- proto_str = "ssltcp";
- else
- proto_str = "tcp";
- break;
- default:
- g_assert_not_reached ();
- }
-
- cnode = wocky_node_add_child_with_content (trans_node, "candidate", NULL);
- wocky_node_set_attributes (cnode,
- "address", c->address,
- "port", port_str,
- "username", c->username,
- "password", c->password != NULL ? c->password : "",
- "preference", pref_str,
- "protocol", proto_str,
- "type", type_str,
- "component", comp_str,
- "network", "0",
- "generation", "0",
- NULL);
-
- wocky_node_set_attribute (cnode, "name", name);
- }
-
- wocky_porter_send_iq_async (
- gabble_jingle_session_get_porter (priv->content->session), msg,
- NULL, NULL, NULL);
- g_object_unref (msg);
-}
-
-/* Groups @candidates into rtp and rtcp and sends each group in its own
- * transport-info. This works around old Gabble, which rejected transport-info
- * stanzas containing non-rtp candidates.
- */
-static void
-group_and_transmit_candidates (GabbleJingleTransportGoogle *transport,
- GList *candidates)
-{
- GabbleJingleTransportGooglePrivate *priv = transport->priv;
- GList *all_candidates = NULL;
- JingleMediaType media;
- GList *li;
- GList *cands;
-
- for (li = candidates; li != NULL; li = g_list_next (li))
- {
- JingleCandidate *c = li->data;
-
- for (cands = all_candidates; cands != NULL; cands = g_list_next (cands))
- {
- JingleCandidate *c2 = ((GList *) cands->data)->data;
-
- if (c->component == c2->component)
- {
- break;
- }
- }
- if (cands == NULL)
- {
- all_candidates = g_list_prepend (all_candidates, NULL);
- cands = all_candidates;
- }
-
- cands->data = g_list_prepend (cands->data, c);
- }
-
- g_object_get (priv->content, "media-type", &media, NULL);
-
- for (cands = all_candidates; cands != NULL; cands = g_list_next (cands))
- {
- GHashTableIter iter;
- gpointer key, value;
- gchar *name = NULL;
- JingleCandidate *c = ((GList *) cands->data)->data;
-
- g_hash_table_iter_init (&iter, priv->component_names);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- if (GPOINTER_TO_INT (value) == c->component)
- {
- name = key;
- break;
- }
- }
- if (name)
- {
- transmit_candidates (transport, name, cands->data);
- }
- else
- {
- DEBUG ("Ignoring unknown component %d", c->component);
- }
- g_list_free (cands->data);
- }
-
- g_list_free (all_candidates);
-}
-
-/* Takes in a list of slice-allocated JingleCandidate structs */
-static void
-new_local_candidates (GabbleJingleTransportIface *obj, GList *new_candidates)
-{
- GabbleJingleTransportGoogle *transport =
- GABBLE_JINGLE_TRANSPORT_GOOGLE (obj);
- GabbleJingleTransportGooglePrivate *priv = transport->priv;
-
- priv->local_candidates = g_list_concat (priv->local_candidates,
- new_candidates);
-
- /* If all previous candidates have been signalled, set the new
- * ones as pending. If there are existing pending candidates,
- * the new ones will just be appended to that list. */
- if (priv->pending_candidates == NULL)
- priv->pending_candidates = new_candidates;
-}
-
-static void
-send_candidates (GabbleJingleTransportIface *obj, gboolean all)
-{
- GabbleJingleTransportGoogle *transport =
- GABBLE_JINGLE_TRANSPORT_GOOGLE (obj);
- GabbleJingleTransportGooglePrivate *priv = transport->priv;
-
- if (all)
- {
- /* for gtalk3, we might have to retransmit everything */
- group_and_transmit_candidates (transport, priv->local_candidates);
- priv->pending_candidates = NULL;
- }
- else
- {
- /* If the content became ready after we wanted to transmit
- * these originally, we are called to transmit when it them */
- if (priv->pending_candidates != NULL)
- {
- group_and_transmit_candidates (transport, priv->pending_candidates);
- priv->pending_candidates = NULL;
- }
- }
-}
-
-static GList *
-get_local_candidates (GabbleJingleTransportIface *iface)
-{
- GabbleJingleTransportGoogle *transport =
- GABBLE_JINGLE_TRANSPORT_GOOGLE (iface);
- GabbleJingleTransportGooglePrivate *priv = transport->priv;
-
- return priv->local_candidates;
-}
-
-static GList *
-get_remote_candidates (GabbleJingleTransportIface *iface)
-{
- GabbleJingleTransportGoogle *transport =
- GABBLE_JINGLE_TRANSPORT_GOOGLE (iface);
- GabbleJingleTransportGooglePrivate *priv = transport->priv;
-
- return priv->remote_candidates;
-}
-
-static JingleTransportType
-get_transport_type (void)
-{
- return JINGLE_TRANSPORT_GOOGLE_P2P;
-}
-
-static void
-transport_iface_init (gpointer g_iface, gpointer iface_data)
-{
- GabbleJingleTransportIfaceClass *klass = (GabbleJingleTransportIfaceClass *) g_iface;
-
- klass->parse_candidates = parse_candidates;
-
- klass->new_local_candidates = new_local_candidates;
- /* Not implementing inject_candidates: gtalk-p2p candidates are always sent
- * in transport-info or equivalent.
- */
- klass->send_candidates = send_candidates;
-
- klass->get_remote_candidates = get_remote_candidates;
- klass->get_local_candidates = get_local_candidates;
- klass->get_transport_type = get_transport_type;
-}
-
-/* Returns FALSE if the component name already exists */
-gboolean
-jingle_transport_google_set_component_name (
- GabbleJingleTransportGoogle *transport,
- const gchar *name, guint component_id)
-{
- GabbleJingleTransportGooglePrivate *priv = transport->priv;
-
- if (g_hash_table_lookup_extended (priv->component_names, name, NULL, NULL))
- return FALSE;
-
- g_hash_table_insert (priv->component_names, g_strdup (name),
- GINT_TO_POINTER (component_id));
-
- return TRUE;
-}
-
-void
-jingle_transport_google_register (GabbleJingleFactory *factory)
-{
- /* GTalk libjingle0.3 dialect */
- gabble_jingle_factory_register_transport (factory, "",
- GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE);
-
- /* GTalk libjingle0.4 dialect */
- gabble_jingle_factory_register_transport (factory,
- NS_GOOGLE_TRANSPORT_P2P,
- GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE);
-}
-
diff --git a/src/jingle-transport-google.h b/src/jingle-transport-google.h
deleted file mode 100644
index bfab8f0fb..000000000
--- a/src/jingle-transport-google.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * jingle-transport-google.h - Header for GabbleJingleTransportGoogle
- * Copyright (C) 2008 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 __JINGLE_TRANSPORT_GOOGLE_H__
-#define __JINGLE_TRANSPORT_GOOGLE_H__
-
-#include <glib-object.h>
-
-#include "jingle-types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleJingleTransportGoogleClass GabbleJingleTransportGoogleClass;
-
-GType gabble_jingle_transport_google_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE \
- (gabble_jingle_transport_google_get_type ())
-#define GABBLE_JINGLE_TRANSPORT_GOOGLE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE, \
- GabbleJingleTransportGoogle))
-#define GABBLE_JINGLE_TRANSPORT_GOOGLE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE, \
- GabbleJingleTransportGoogleClass))
-#define GABBLE_IS_JINGLE_TRANSPORT_GOOGLE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE))
-#define GABBLE_IS_JINGLE_TRANSPORT_GOOGLE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE))
-#define GABBLE_JINGLE_TRANSPORT_GOOGLE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_TRANSPORT_GOOGLE, \
- GabbleJingleTransportGoogleClass))
-
-struct _GabbleJingleTransportGoogleClass {
- GObjectClass parent_class;
-};
-
-typedef struct _GabbleJingleTransportGooglePrivate GabbleJingleTransportGooglePrivate;
-
-struct _GabbleJingleTransportGoogle {
- GObject parent;
- GabbleJingleTransportGooglePrivate *priv;
-};
-
-void jingle_transport_google_register (GabbleJingleFactory *factory);
-
-gboolean jingle_transport_google_set_component_name (
- GabbleJingleTransportGoogle *transport,
- const gchar *name, guint component_id);
-
-#endif /* __JINGLE_TRANSPORT_GOOGLE_H__ */
-
diff --git a/src/jingle-transport-iceudp.c b/src/jingle-transport-iceudp.c
deleted file mode 100644
index cd7f3a1e3..000000000
--- a/src/jingle-transport-iceudp.c
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * jingle-transport-iceudp.c - Source for GabbleJingleTransportIceUdp
- *
- * Copyright (C) 2008 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 "config.h"
-#include "jingle-transport-iceudp.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "debug.h"
-#include "jingle-content.h"
-#include "jingle-factory.h"
-#include "jingle-session.h"
-#include "namespaces.h"
-
-static void
-transport_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleJingleTransportIceUdp,
- gabble_jingle_transport_iceudp, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (GABBLE_TYPE_JINGLE_TRANSPORT_IFACE,
- transport_iface_init));
-
-/* signal enum */
-enum
-{
- NEW_CANDIDATES,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_CONTENT = 1,
- PROP_TRANSPORT_NS,
- PROP_STATE,
- LAST_PROPERTY
-};
-
-struct _GabbleJingleTransportIceUdpPrivate
-{
- GabbleJingleContent *content;
- JingleTransportState state;
- gchar *transport_ns;
-
- GList *local_candidates;
-
- /* A pointer into "local_candidates" list to mark the
- * candidates that are still not transmitted, or NULL
- * if all of them are transmitted. */
-
- GList *pending_candidates;
- GList *remote_candidates;
-
- gchar *ufrag;
- gchar *pwd;
-
- /* next ID to send with a candidate */
- int id_sequence;
-
- gboolean dispose_has_run;
-};
-
-static void
-gabble_jingle_transport_iceudp_init (GabbleJingleTransportIceUdp *obj)
-{
- GabbleJingleTransportIceUdpPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_JINGLE_TRANSPORT_ICEUDP,
- GabbleJingleTransportIceUdpPrivate);
- obj->priv = priv;
-
- priv->id_sequence = 1;
- priv->dispose_has_run = FALSE;
-}
-
-static void
-gabble_jingle_transport_iceudp_dispose (GObject *object)
-{
- GabbleJingleTransportIceUdp *trans = GABBLE_JINGLE_TRANSPORT_ICEUDP (object);
- GabbleJingleTransportIceUdpPrivate *priv = trans->priv;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- jingle_transport_free_candidates (priv->remote_candidates);
- priv->remote_candidates = NULL;
-
- jingle_transport_free_candidates (priv->local_candidates);
- priv->local_candidates = NULL;
-
- g_free (priv->transport_ns);
- priv->transport_ns = NULL;
-
- g_free (priv->ufrag);
- priv->ufrag = NULL;
-
- g_free (priv->pwd);
- priv->pwd = NULL;
-
- if (G_OBJECT_CLASS (gabble_jingle_transport_iceudp_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_jingle_transport_iceudp_parent_class)->dispose (object);
-}
-
-static void
-gabble_jingle_transport_iceudp_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleTransportIceUdp *trans = GABBLE_JINGLE_TRANSPORT_ICEUDP (object);
- GabbleJingleTransportIceUdpPrivate *priv = trans->priv;
-
- switch (property_id) {
- case PROP_CONTENT:
- g_value_set_object (value, priv->content);
- break;
- case PROP_TRANSPORT_NS:
- g_value_set_string (value, priv->transport_ns);
- 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
-gabble_jingle_transport_iceudp_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleTransportIceUdp *trans = GABBLE_JINGLE_TRANSPORT_ICEUDP (object);
- GabbleJingleTransportIceUdpPrivate *priv = trans->priv;
-
- switch (property_id) {
- case PROP_CONTENT:
- priv->content = g_value_get_object (value);
- break;
- case PROP_TRANSPORT_NS:
- g_free (priv->transport_ns);
- priv->transport_ns = g_value_dup_string (value);
- break;
- case PROP_STATE:
- priv->state = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_jingle_transport_iceudp_class_init (GabbleJingleTransportIceUdpClass *cls)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (cls);
- GParamSpec *param_spec;
-
- g_type_class_add_private (cls, sizeof (GabbleJingleTransportIceUdpPrivate));
-
- object_class->get_property = gabble_jingle_transport_iceudp_get_property;
- object_class->set_property = gabble_jingle_transport_iceudp_set_property;
- object_class->dispose = gabble_jingle_transport_iceudp_dispose;
-
- /* property definitions */
- param_spec = g_param_spec_object ("content", "GabbleJingleContent object",
- "Jingle content object using this transport.",
- GABBLE_TYPE_JINGLE_CONTENT,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONTENT, param_spec);
-
- param_spec = g_param_spec_string ("transport-ns", "Transport namespace",
- "Namespace identifying the transport type.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_TRANSPORT_NS, param_spec);
-
- param_spec = g_param_spec_uint ("state",
- "Connection state for the transport.",
- "Enum specifying the connection state of the transport.",
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- JINGLE_TRANSPORT_STATE_CONNECTED,
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- /* signal definitions */
- signals[NEW_CANDIDATES] = g_signal_new (
- "new-candidates",
- G_TYPE_FROM_CLASS (cls),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-}
-
-static void
-parse_candidates (GabbleJingleTransportIface *obj,
- WockyNode *transport_node, GError **error)
-{
- GabbleJingleTransportIceUdp *t = GABBLE_JINGLE_TRANSPORT_ICEUDP (obj);
- GabbleJingleTransportIceUdpPrivate *priv = t->priv;
- gboolean node_contains_a_candidate = FALSE;
- GList *candidates = NULL;
- WockyNodeIter i;
- WockyNode *node;
-
- DEBUG ("called");
-
- wocky_node_iter_init (&i, transport_node, "candidate", NULL);
- while (wocky_node_iter_next (&i, &node))
- {
- const gchar *id, *address, *user, *pass, *str;
- guint port, net, gen, component = 1;
- gdouble pref;
- JingleTransportProtocol proto;
- JingleCandidateType ctype;
- JingleCandidate *c;
-
- node_contains_a_candidate = TRUE;
-
- id = wocky_node_get_attribute (node, "foundation");
- if (id == NULL)
- {
- DEBUG ("candidate doesn't contain foundation");
- continue;
- }
-
- address = wocky_node_get_attribute (node, "ip");
- if (address == NULL)
- {
- DEBUG ("candidate doesn't contain ip");
- continue;
- }
-
- str = wocky_node_get_attribute (node, "port");
- if (str == NULL)
- {
- DEBUG ("candidate doesn't contain port");
- continue;
- }
- port = atoi (str);
-
- str = wocky_node_get_attribute (node, "protocol");
- if (str == NULL)
- {
- DEBUG ("candidate doesn't contain protocol");
- continue;
- }
-
- if (!wocky_strdiff (str, "udp"))
- {
- proto = JINGLE_TRANSPORT_PROTOCOL_UDP;
- }
- else
- {
- /* unknown protocol */
- DEBUG ("unknown protocol: %s", str);
- continue;
- }
-
- str = wocky_node_get_attribute (node, "priority");
- if (str == NULL)
- {
- DEBUG ("candidate doesn't contain priority");
- continue;
- }
- pref = g_ascii_strtod (str, NULL);
-
- str = wocky_node_get_attribute (node, "type");
- if (str == NULL)
- {
- DEBUG ("candidate doesn't contain type");
- continue;
- }
-
- if (!wocky_strdiff (str, "host"))
- {
- ctype = JINGLE_CANDIDATE_TYPE_LOCAL;
- }
- else if (!wocky_strdiff (str, "srflx") || !wocky_strdiff (str, "prflx"))
- {
- /* FIXME Strictly speaking a prflx candidate should be a different
- * type, but the TP spec has now way to distinguish and it doesn't
- * matter much anyway.. */
- ctype = JINGLE_CANDIDATE_TYPE_STUN;
- }
- else if (!wocky_strdiff (str, "relay"))
- {
- ctype = JINGLE_CANDIDATE_TYPE_RELAY;
- }
- else
- {
- /* unknown candidate type */
- DEBUG ("unknown candidate type: %s", str);
- continue;
- }
-
- user = wocky_node_get_attribute (transport_node, "ufrag");
- if (user == NULL)
- {
- DEBUG ("transport doesn't contain ufrag");
- continue;
- }
-
- pass = wocky_node_get_attribute (transport_node, "pwd");
- if (pass == NULL)
- {
- DEBUG ("transport doesn't contain pwd");
- continue;
- }
-
- str = wocky_node_get_attribute (node, "network");
- if (str == NULL)
- {
- DEBUG ("candidate doesn't contain network");
- continue;
- }
- net = atoi (str);
-
- str = wocky_node_get_attribute (node, "generation");
- if (str == NULL)
- {
- DEBUG ("candidate doesn't contain generation");
- continue;
- }
- gen = atoi (str);
-
- str = wocky_node_get_attribute (node, "component");
- if (str == NULL)
- {
- DEBUG ("candidate doesn't contain component");
- continue;
- }
- component = atoi (str);
-
- if (priv->ufrag == NULL || strcmp (priv->ufrag, user))
- {
- g_free (priv->ufrag);
- priv->ufrag = g_strdup (user);
- }
-
- if (priv->pwd == NULL || strcmp (priv->pwd, pass))
- {
- g_free (priv->pwd);
- priv->pwd = g_strdup (pass);
- }
-
- c = jingle_candidate_new (proto, ctype, id, component,
- address, port, gen, pref, user, pass, net);
-
- candidates = g_list_append (candidates, c);
- }
-
- if (candidates == NULL)
- {
- if (node_contains_a_candidate)
- {
- NODE_DEBUG (transport_node,
- "couldn't parse any of the given candidates");
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "could not parse any of the given candidates");
- }
- else
- {
- DEBUG ("no candidates in this stanza");
- }
- }
- else
- {
- DEBUG ("emitting %d new remote candidates", g_list_length (candidates));
-
- g_signal_emit (obj, signals[NEW_CANDIDATES], 0, candidates);
-
- priv->remote_candidates = g_list_concat (priv->remote_candidates,
- candidates);
- }
-}
-
-static void
-inject_candidates (GabbleJingleTransportIface *obj,
- WockyNode *transport_node)
-{
- GabbleJingleTransportIceUdp *self = GABBLE_JINGLE_TRANSPORT_ICEUDP (obj);
- GabbleJingleTransportIceUdpPrivate *priv = self->priv;
- const gchar *username = NULL;
-
- for (; priv->pending_candidates != NULL;
- priv->pending_candidates = priv->pending_candidates->next)
- {
- JingleCandidate *c = (JingleCandidate *) priv->pending_candidates->data;
- gchar port_str[16], pref_str[16], comp_str[16], id_str[16],
- *type_str, *proto_str;
- WockyNode *cnode;
-
- if (username == NULL)
- {
- username = c->username;
- }
- else if (wocky_strdiff (username, c->username))
- {
- DEBUG ("found a candidate with a different username (%s not %s); "
- "will send in a separate batch", c->username, username);
- break;
- }
-
- sprintf (pref_str, "%d", c->preference);
- sprintf (port_str, "%d", c->port);
- sprintf (comp_str, "%d", c->component);
- sprintf (id_str, "%d", priv->id_sequence++);
-
- switch (c->type) {
- case JINGLE_CANDIDATE_TYPE_LOCAL:
- type_str = "host";
- break;
- case JINGLE_CANDIDATE_TYPE_STUN:
- type_str = "srflx";
- break;
- case JINGLE_CANDIDATE_TYPE_RELAY:
- type_str = "relay";
- break;
- default:
- DEBUG ("skipping candidate with unknown type %u", c->type);
- continue;
- }
-
- switch (c->protocol) {
- case JINGLE_TRANSPORT_PROTOCOL_UDP:
- proto_str = "udp";
- break;
- case JINGLE_TRANSPORT_PROTOCOL_TCP:
- DEBUG ("ignoring TCP candidate");
- continue;
- default:
- DEBUG ("skipping candidate with unknown protocol %u", c->protocol);
- continue;
- }
-
- wocky_node_set_attributes (transport_node,
- "ufrag", c->username,
- "pwd", c->password,
- NULL);
-
- cnode = wocky_node_add_child_with_content (transport_node, "candidate", NULL);
- wocky_node_set_attributes (cnode,
- "ip", c->address,
- "port", port_str,
- "priority", pref_str,
- "protocol", proto_str,
- "type", type_str,
- "component", comp_str,
- "foundation", c->id,
- "id", id_str,
- "network", "0",
- "generation", "0",
- NULL);
- }
-}
-
-/* We never have to retransmit candidates we've already sent, so we ignore
- * @all.
- */
-static void
-send_candidates (GabbleJingleTransportIface *iface,
- gboolean all G_GNUC_UNUSED)
-{
- GabbleJingleTransportIceUdp *self = GABBLE_JINGLE_TRANSPORT_ICEUDP (iface);
- GabbleJingleTransportIceUdpPrivate *priv = self->priv;
-
- while (priv->pending_candidates != NULL)
- {
- WockyNode *trans_node, *sess_node;
- WockyStanza *msg;
-
- msg = gabble_jingle_session_new_message (priv->content->session,
- JINGLE_ACTION_TRANSPORT_INFO, &sess_node);
-
- gabble_jingle_content_produce_node (priv->content, sess_node, FALSE,
- TRUE, &trans_node);
- inject_candidates (iface, trans_node);
-
- wocky_porter_send_iq_async (
- gabble_jingle_session_get_porter (priv->content->session), msg,
- NULL, NULL, NULL);
- g_object_unref (msg);
- }
-
- DEBUG ("sent all pending candidates");
-}
-
-/* Takes in a list of slice-allocated JingleCandidate structs */
-static void
-new_local_candidates (GabbleJingleTransportIface *obj, GList *new_candidates)
-{
- GabbleJingleTransportIceUdp *transport =
- GABBLE_JINGLE_TRANSPORT_ICEUDP (obj);
- GabbleJingleTransportIceUdpPrivate *priv = transport->priv;
-
- priv->local_candidates = g_list_concat (priv->local_candidates,
- new_candidates);
-
- /* If all previous candidates have been signalled, set the new
- * ones as pending. If there are existing pending candidates,
- * the new ones will just be appended to that list. */
- if (priv->pending_candidates == NULL)
- priv->pending_candidates = new_candidates;
-}
-
-static GList *
-get_remote_candidates (GabbleJingleTransportIface *iface)
-{
- GabbleJingleTransportIceUdp *transport =
- GABBLE_JINGLE_TRANSPORT_ICEUDP (iface);
- GabbleJingleTransportIceUdpPrivate *priv = transport->priv;
-
- return priv->remote_candidates;
-}
-
-static GList *
-get_local_candidates (GabbleJingleTransportIface *iface)
-{
- GabbleJingleTransportIceUdp *transport =
- GABBLE_JINGLE_TRANSPORT_ICEUDP (iface);
- GabbleJingleTransportIceUdpPrivate *priv = transport->priv;
-
- return priv->local_candidates;
-}
-
-static JingleTransportType
-get_transport_type (void)
-{
- return JINGLE_TRANSPORT_ICE_UDP;
-}
-
-static gboolean
-get_credentials (GabbleJingleTransportIface *iface,
- gchar **ufrag, gchar **pwd)
-{
- GabbleJingleTransportIceUdp *transport =
- GABBLE_JINGLE_TRANSPORT_ICEUDP (iface);
- GabbleJingleTransportIceUdpPrivate *priv = transport->priv;
-
- if (!priv->ufrag || !priv->pwd)
- return FALSE;
-
- if (ufrag)
- *ufrag = priv->ufrag;
- if (pwd)
- *pwd = priv->pwd;
-
- return TRUE;
-}
-
-
-static void
-transport_iface_init (gpointer g_iface, gpointer iface_data)
-{
- GabbleJingleTransportIfaceClass *klass = (GabbleJingleTransportIfaceClass *) g_iface;
-
- klass->parse_candidates = parse_candidates;
-
- klass->new_local_candidates = new_local_candidates;
- klass->inject_candidates = inject_candidates;
- klass->send_candidates = send_candidates;
-
- klass->get_remote_candidates = get_remote_candidates;
- klass->get_local_candidates = get_local_candidates;
- klass->get_transport_type = get_transport_type;
- klass->get_credentials = get_credentials;
-}
-
-void
-jingle_transport_iceudp_register (GabbleJingleFactory *factory)
-{
- gabble_jingle_factory_register_transport (factory,
- NS_JINGLE_TRANSPORT_ICEUDP,
- GABBLE_TYPE_JINGLE_TRANSPORT_ICEUDP);
-}
-
diff --git a/src/jingle-transport-iceudp.h b/src/jingle-transport-iceudp.h
deleted file mode 100644
index 8f7324371..000000000
--- a/src/jingle-transport-iceudp.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * jingle-transport-iceudp.h - Header for GabbleJingleTransportIceUdp
- * Copyright (C) 2008 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 __JINGLE_TRANSPORT_ICEUDP_H__
-#define __JINGLE_TRANSPORT_ICEUDP_H__
-
-#include <glib-object.h>
-
-#include "jingle-types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleJingleTransportIceUdpClass GabbleJingleTransportIceUdpClass;
-
-GType gabble_jingle_transport_iceudp_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_TRANSPORT_ICEUDP \
- (gabble_jingle_transport_iceudp_get_type ())
-#define GABBLE_JINGLE_TRANSPORT_ICEUDP(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_TRANSPORT_ICEUDP, \
- GabbleJingleTransportIceUdp))
-#define GABBLE_JINGLE_TRANSPORT_ICEUDP_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_TRANSPORT_ICEUDP, \
- GabbleJingleTransportIceUdpClass))
-#define GABBLE_IS_JINGLE_TRANSPORT_ICEUDP(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_TRANSPORT_ICEUDP))
-#define GABBLE_IS_JINGLE_TRANSPORT_ICEUDP_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_TRANSPORT_ICEUDP))
-#define GABBLE_JINGLE_TRANSPORT_ICEUDP_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_TRANSPORT_ICEUDP, \
- GabbleJingleTransportIceUdpClass))
-
-struct _GabbleJingleTransportIceUdpClass {
- GObjectClass parent_class;
-};
-
-typedef struct _GabbleJingleTransportIceUdpPrivate GabbleJingleTransportIceUdpPrivate;
-
-struct _GabbleJingleTransportIceUdp {
- GObject parent;
- GabbleJingleTransportIceUdpPrivate *priv;
-};
-
-void jingle_transport_iceudp_register (GabbleJingleFactory *factory);
-
-#endif /* __JINGLE_TRANSPORT_ICEUDP_H__ */
-
diff --git a/src/jingle-transport-iface.c b/src/jingle-transport-iface.c
deleted file mode 100644
index 7a1ca9bf3..000000000
--- a/src/jingle-transport-iface.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * jingle-transport-iface.c - Source for GabbleJingleTransport interface
- * Copyright (C) 2007-2008 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 "config.h"
-#include "jingle-transport-iface.h"
-
-#include <glib.h>
-
-#include "connection.h"
-#include "jingle-content.h"
-#include "jingle-session.h"
-
-GabbleJingleTransportIface *
-gabble_jingle_transport_iface_new (GType type,
- GabbleJingleContent *content,
- const gchar *transport_ns)
-{
- g_return_val_if_fail (g_type_is_a (type, GABBLE_TYPE_JINGLE_TRANSPORT_IFACE),
- NULL);
-
- return g_object_new (type,
- "content", content,
- "transport-ns", transport_ns,
- NULL);
-}
-
-void
-gabble_jingle_transport_iface_parse_candidates (GabbleJingleTransportIface *self,
- WockyNode *node, GError **error)
-{
- void (*virtual_method)(GabbleJingleTransportIface *,
- WockyNode *, GError **) =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->parse_candidates;
-
- g_assert (virtual_method != NULL);
- return virtual_method (self, node, error);
-}
-
-/* Takes in a list of slice-allocated JingleCandidate structs */
-void
-gabble_jingle_transport_iface_new_local_candidates (GabbleJingleTransportIface *self,
- GList *candidates)
-{
- void (*virtual_method)(GabbleJingleTransportIface *,
- GList *) =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->new_local_candidates;
-
- g_assert (virtual_method != NULL);
- virtual_method (self, candidates);
-}
-
-/* Inserts candidates into the given <transport/> node, or equivalent, of a
- * session-initiate, session-accept, content-add or content-accept action.
- */
-void
-gabble_jingle_transport_iface_inject_candidates (
- GabbleJingleTransportIface *self,
- WockyNode *transport_node)
-{
- void (*virtual_method)(GabbleJingleTransportIface *, WockyNode *) =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->inject_candidates;
-
- if (virtual_method != NULL)
- virtual_method (self, transport_node);
-}
-
-/* Transmits outstanding or all candidates (if applicable and @all is set). */
-void
-gabble_jingle_transport_iface_send_candidates (
- GabbleJingleTransportIface *self,
- gboolean all)
-{
- void (*virtual_method) (GabbleJingleTransportIface *, gboolean) =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->send_candidates;
-
- if (virtual_method != NULL)
- virtual_method (self, all);
-}
-
-/* Returns TRUE if and only if @self has enough candidates to inject into a
- * {session,content}-accept, and is connected.
- */
-gboolean
-gabble_jingle_transport_iface_can_accept (GabbleJingleTransportIface *self)
-{
- JingleTransportState state;
- gboolean (*m) (GabbleJingleTransportIface *) =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->can_accept;
-
- g_object_get (self, "state", &state, NULL);
-
- if (state != JINGLE_TRANSPORT_STATE_CONNECTED)
- return FALSE;
-
- /* Only Raw UDP *needs* candidates in order to accept. */
- if (m != NULL)
- return m (self);
- else
- return TRUE;
-}
-
-GList *
-gabble_jingle_transport_iface_get_remote_candidates (
- GabbleJingleTransportIface *self)
-{
- GList * (*virtual_method)(GabbleJingleTransportIface *) =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->get_remote_candidates;
-
- g_assert (virtual_method != NULL);
- return virtual_method (self);
-}
-
-GList *
-gabble_jingle_transport_iface_get_local_candidates (
- GabbleJingleTransportIface *self)
-{
- GList * (*virtual_method)(GabbleJingleTransportIface *) =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->get_local_candidates;
-
- g_assert (virtual_method != NULL);
- return virtual_method (self);
-}
-
-gboolean
-jingle_transport_get_credentials (GabbleJingleTransportIface *self,
- gchar **ufrag, gchar **pwd)
-{
- GabbleJingleTransportIfaceClass *klass =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self);
-
- if (klass->get_credentials)
- return klass->get_credentials (self, ufrag, pwd);
- else
- return FALSE;
-}
-
-JingleTransportType
-gabble_jingle_transport_iface_get_transport_type (GabbleJingleTransportIface *self)
-{
- JingleTransportType (*virtual_method)(void) =
- GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->get_transport_type;
-
- g_assert (virtual_method != NULL);
- return virtual_method ();
-}
-
-static void
-gabble_jingle_transport_iface_base_init (gpointer klass)
-{
- static gboolean initialized = FALSE;
-
- if (!initialized)
- {
- GParamSpec *param_spec;
-
- param_spec = g_param_spec_object (
- "content",
- "GabbleJingleContent object",
- "Jingle content that's using this jingle transport object.",
- GABBLE_TYPE_JINGLE_CONTENT,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_interface_install_property (klass, param_spec);
-
- param_spec = g_param_spec_string (
- "transport-ns",
- "Transport namespace",
- "Namespace identifying the transport type.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_interface_install_property (klass, param_spec);
-
- param_spec = g_param_spec_uint (
- "state",
- "Connection state for the transport.",
- "Enum specifying the connection state of the transport.",
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- JINGLE_TRANSPORT_STATE_CONNECTED,
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
-
- g_object_interface_install_property (klass, param_spec);
-
- initialized = TRUE;
- }
-}
-
-GType
-gabble_jingle_transport_iface_get_type (void)
-{
- static GType type = 0;
-
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (GabbleJingleTransportIfaceClass),
- gabble_jingle_transport_iface_base_init, /* base_init */
- NULL, /* base_finalize */
- NULL, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- 0,
- 0, /* n_preallocs */
- NULL /* instance_init */
- };
-
- type = g_type_register_static (G_TYPE_INTERFACE, "GabbleJingleTransportIface",
- &info, 0);
- }
-
- return type;
-}
-
-JingleCandidate *
-jingle_candidate_new (JingleTransportProtocol protocol,
- JingleCandidateType type, const gchar *id, int component,
- const gchar *address, int port, int generation, int preference,
- const gchar *username, const gchar *password, int network)
-{
- JingleCandidate *c = g_slice_new0 (JingleCandidate);
-
- c->protocol = protocol;
- c->type = type;
- c->id = g_strdup (id);
- c->address = g_strdup (address);
- c->component = component;
- c->port = port;
- c->generation = generation;
- c->preference = preference;
- c->username = g_strdup (username);
- c->password = g_strdup (password);
- c->network = network;
-
- return c;
-}
-
-void
-jingle_candidate_free (JingleCandidate *c)
-{
- g_free (c->id);
- g_free (c->address);
- g_free (c->username);
- g_free (c->password);
-
- g_slice_free (JingleCandidate, c);
-}
-
-void
-jingle_transport_free_candidates (GList *candidates)
-{
- while (candidates != NULL)
- {
- JingleCandidate *c = (JingleCandidate *) candidates->data;
- jingle_candidate_free (c);
- candidates = g_list_remove (candidates, c);
- }
-}
-
diff --git a/src/jingle-transport-iface.h b/src/jingle-transport-iface.h
deleted file mode 100644
index dc59d5394..000000000
--- a/src/jingle-transport-iface.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * jingle_transport-iface.h - Header for GabbleJingleTransport interface
- * Copyright (C) 2007-2008 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 __GABBLE_JINGLE_TRANSPORT_IFACE_H__
-#define __GABBLE_JINGLE_TRANSPORT_IFACE_H__
-
-#include <glib-object.h>
-#include <wocky/wocky.h>
-
-#include "jingle-factory.h"
-#include "jingle-types.h"
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- JINGLE_TRANSPORT_STATE_CONNECTING,
- JINGLE_TRANSPORT_STATE_CONNECTED
-} JingleTransportState;
-
-typedef struct _GabbleJingleTransportIface GabbleJingleTransportIface;
-typedef struct _GabbleJingleTransportIfaceClass GabbleJingleTransportIfaceClass;
-
-struct _GabbleJingleTransportIfaceClass {
- GTypeInterface parent;
-
- void (*parse_candidates) (GabbleJingleTransportIface *,
- WockyNode *, GError **);
-
- void (*new_local_candidates) (GabbleJingleTransportIface *, GList *);
- void (*inject_candidates) (GabbleJingleTransportIface *,
- WockyNode *transport_node);
- void (*send_candidates) (GabbleJingleTransportIface *, gboolean all);
- gboolean (*can_accept) (GabbleJingleTransportIface *);
-
- GList * (*get_remote_candidates) (GabbleJingleTransportIface *);
- GList * (*get_local_candidates) (GabbleJingleTransportIface *);
- gboolean (*get_credentials) (GabbleJingleTransportIface *,
- gchar **ufrag, gchar **pwd);
-
- JingleTransportType (*get_transport_type) (void);
-};
-
-GType gabble_jingle_transport_iface_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_TRANSPORT_IFACE \
- (gabble_jingle_transport_iface_get_type ())
-#define GABBLE_JINGLE_TRANSPORT_IFACE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_TRANSPORT_IFACE, GabbleJingleTransportIface))
-#define GABBLE_IS_JINGLE_TRANSPORT_IFACE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_TRANSPORT_IFACE))
-#define GABBLE_JINGLE_TRANSPORT_IFACE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GABBLE_TYPE_JINGLE_TRANSPORT_IFACE,\
- GabbleJingleTransportIfaceClass))
-
-void gabble_jingle_transport_iface_parse_candidates (GabbleJingleTransportIface *,
- WockyNode *, GError **);
-
-void gabble_jingle_transport_iface_new_local_candidates (
- GabbleJingleTransportIface *self,
- GList *candidates);
-void gabble_jingle_transport_iface_inject_candidates (
- GabbleJingleTransportIface *self,
- WockyNode *transport_node);
-void gabble_jingle_transport_iface_send_candidates (
- GabbleJingleTransportIface *self,
- gboolean all);
-gboolean gabble_jingle_transport_iface_can_accept (
- GabbleJingleTransportIface *self);
-
-GList *gabble_jingle_transport_iface_get_remote_candidates (GabbleJingleTransportIface *);
-GList *gabble_jingle_transport_iface_get_local_candidates (GabbleJingleTransportIface *);
-JingleTransportType gabble_jingle_transport_iface_get_transport_type (GabbleJingleTransportIface *);
-gboolean jingle_transport_get_credentials (GabbleJingleTransportIface *,
- gchar **ufrag, gchar **pwd);
-
-GabbleJingleTransportIface *gabble_jingle_transport_iface_new (
- GType type, GabbleJingleContent *content, const gchar *transport_ns);
-
-JingleCandidate *jingle_candidate_new (JingleTransportProtocol protocol,
- JingleCandidateType type, const gchar *id, int component,
- const gchar *address, int port, int generation, int preference,
- const gchar *username, const gchar *password, int network);
-
-void jingle_candidate_free (JingleCandidate *c);
-void jingle_transport_free_candidates (GList *candidates);
-
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_JINGLE_TRANSPORT_IFACE_H__ */
diff --git a/src/jingle-transport-rawudp.c b/src/jingle-transport-rawudp.c
deleted file mode 100644
index 17b1b1f8f..000000000
--- a/src/jingle-transport-rawudp.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * jingle-transport-rawudp.c - Source for GabbleJingleTransportRawUdp
- *
- * Copyright (C) 2008 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 "config.h"
-#include "jingle-transport-rawudp.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
-
-#include "connection.h"
-#include "debug.h"
-#include "jingle-content.h"
-#include "jingle-factory.h"
-#include "jingle-session.h"
-#include "namespaces.h"
-
-static void
-transport_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleJingleTransportRawUdp,
- gabble_jingle_transport_rawudp, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (GABBLE_TYPE_JINGLE_TRANSPORT_IFACE,
- transport_iface_init));
-
-/* signal enum */
-enum
-{
- NEW_CANDIDATES,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_CONTENT = 1,
- PROP_TRANSPORT_NS,
- PROP_STATE,
- LAST_PROPERTY
-};
-
-struct _GabbleJingleTransportRawUdpPrivate
-{
- GabbleJingleContent *content;
- JingleTransportState state;
- gchar *transport_ns;
-
- GList *local_candidates;
- GList *remote_candidates;
- gboolean dispose_has_run;
-};
-
-static void
-gabble_jingle_transport_rawudp_init (GabbleJingleTransportRawUdp *obj)
-{
- GabbleJingleTransportRawUdpPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_JINGLE_TRANSPORT_RAWUDP,
- GabbleJingleTransportRawUdpPrivate);
- obj->priv = priv;
-
- priv->dispose_has_run = FALSE;
-}
-
-static void
-gabble_jingle_transport_rawudp_dispose (GObject *object)
-{
- GabbleJingleTransportRawUdp *trans = GABBLE_JINGLE_TRANSPORT_RAWUDP (object);
- GabbleJingleTransportRawUdpPrivate *priv = trans->priv;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- jingle_transport_free_candidates (priv->remote_candidates);
- priv->remote_candidates = NULL;
-
- jingle_transport_free_candidates (priv->local_candidates);
- priv->local_candidates = NULL;
-
- g_free (priv->transport_ns);
- priv->transport_ns = NULL;
-
- if (G_OBJECT_CLASS (gabble_jingle_transport_rawudp_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_jingle_transport_rawudp_parent_class)->dispose (object);
-}
-
-static void
-gabble_jingle_transport_rawudp_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleTransportRawUdp *trans = GABBLE_JINGLE_TRANSPORT_RAWUDP (object);
- GabbleJingleTransportRawUdpPrivate *priv = trans->priv;
-
- switch (property_id) {
- case PROP_CONTENT:
- g_value_set_object (value, priv->content);
- break;
- case PROP_TRANSPORT_NS:
- g_value_set_string (value, priv->transport_ns);
- 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
-gabble_jingle_transport_rawudp_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleJingleTransportRawUdp *trans = GABBLE_JINGLE_TRANSPORT_RAWUDP (object);
- GabbleJingleTransportRawUdpPrivate *priv = trans->priv;
-
- switch (property_id) {
- case PROP_CONTENT:
- priv->content = g_value_get_object (value);
- break;
- case PROP_TRANSPORT_NS:
- g_free (priv->transport_ns);
- priv->transport_ns = g_value_dup_string (value);
- break;
- case PROP_STATE:
- priv->state = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_jingle_transport_rawudp_class_init (GabbleJingleTransportRawUdpClass *cls)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (cls);
- GParamSpec *param_spec;
-
- g_type_class_add_private (cls, sizeof (GabbleJingleTransportRawUdpPrivate));
-
- object_class->get_property = gabble_jingle_transport_rawudp_get_property;
- object_class->set_property = gabble_jingle_transport_rawudp_set_property;
- object_class->dispose = gabble_jingle_transport_rawudp_dispose;
-
- /* property definitions */
- param_spec = g_param_spec_object ("content", "GabbleJingleContent object",
- "Jingle content object using this transport.",
- GABBLE_TYPE_JINGLE_CONTENT,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONTENT, param_spec);
-
- param_spec = g_param_spec_string ("transport-ns", "Transport namespace",
- "Namespace identifying the transport type.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_TRANSPORT_NS, param_spec);
-
- param_spec = g_param_spec_uint ("state",
- "Connection state for the transport.",
- "Enum specifying the connection state of the transport.",
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- JINGLE_TRANSPORT_STATE_CONNECTED,
- JINGLE_TRANSPORT_STATE_DISCONNECTED,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- /* signal definitions */
- signals[NEW_CANDIDATES] = g_signal_new (
- "new-candidates",
- G_TYPE_FROM_CLASS (cls),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-}
-
-static void
-parse_candidates (GabbleJingleTransportIface *obj,
- WockyNode *transport_node, GError **error)
-{
- GabbleJingleTransportRawUdp *t = GABBLE_JINGLE_TRANSPORT_RAWUDP (obj);
- GabbleJingleTransportRawUdpPrivate *priv = t->priv;
- GList *candidates = NULL;
- WockyNodeIter i;
- WockyNode *node;
-
- DEBUG ("called");
-
- if (priv->remote_candidates != NULL)
- {
- DEBUG ("already have raw udp candidates, ignoring extra ones");
- return;
- }
-
- wocky_node_iter_init (&i, transport_node, "candidate", NULL);
- while (wocky_node_iter_next (&i, &node))
- {
- const gchar *id, *ip, *str;
- guint port, gen, component = 1;
- JingleCandidate *c;
-
- str = wocky_node_get_attribute (node, "component");
- if (str != NULL)
- component = atoi (str);
-
- if ((component != 1) && (component != 2))
- {
- DEBUG ("Ignoring non-RTP/RTCP component %d", component);
- continue;
- }
-
- id = wocky_node_get_attribute (node, "id");
- if (id == NULL)
- break;
-
- ip = wocky_node_get_attribute (node, "ip");
- if (ip == NULL)
- break;
-
- str = wocky_node_get_attribute (node, "port");
- if (str == NULL)
- break;
- port = atoi (str);
-
- str = wocky_node_get_attribute (node, "generation");
- if (str == NULL)
- break;
- gen = atoi (str);
-
- c = jingle_candidate_new (JINGLE_TRANSPORT_PROTOCOL_UDP,
- JINGLE_CANDIDATE_TYPE_LOCAL, id, component, ip, port,
- gen, 1.0, NULL, NULL, 0);
-
- candidates = g_list_append (candidates, c);
- }
-
- if (wocky_node_iter_next (&i, NULL))
- {
- DEBUG ("not all nodes were processed, reporting error");
- /* rollback these */
- jingle_transport_free_candidates (candidates);
- g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "invalid candidate");
- return;
- }
-
- DEBUG ("emitting %d new remote candidates", g_list_length (candidates));
- g_signal_emit (obj, signals[NEW_CANDIDATES], 0, candidates);
- priv->remote_candidates = candidates;
-}
-
-static void
-inject_candidates (GabbleJingleTransportIface *obj,
- WockyNode *transport_node)
-{
- GabbleJingleTransportRawUdp *self = GABBLE_JINGLE_TRANSPORT_RAWUDP (obj);
- GabbleJingleTransportRawUdpPrivate *priv = self->priv;
- JingleCandidate *c;
- GList *li;
- gchar port_str[16], comp_str[16];
- WockyNode *cnode;
-
- /* If we don't have the local candidates yet, we should've waited with
- * the session initiation, or can_accept would have returned FALSE.
- */
- g_assert (priv->local_candidates != NULL);
-
- for (li = priv->local_candidates; li != NULL; li = li->next)
- {
- c = (JingleCandidate *) li->data;
- sprintf (port_str, "%d", c->port);
- sprintf (comp_str, "%d", c->component);
-
- cnode = wocky_node_add_child_with_content (transport_node, "candidate", NULL);
- wocky_node_set_attributes (cnode,
- "ip", c->address,
- "port", port_str,
- "generation", "0",
- "id", c->id,
- "component", comp_str,
- NULL);
- }
-}
-
-/* Takes in a list of slice-allocated JingleCandidate structs */
-static void
-new_local_candidates (GabbleJingleTransportIface *obj, GList *new_candidates)
-{
- GabbleJingleTransportRawUdp *transport =
- GABBLE_JINGLE_TRANSPORT_RAWUDP (obj);
- GabbleJingleTransportRawUdpPrivate *priv = transport->priv;
-
- if (priv->local_candidates != NULL)
- {
- DEBUG ("ignoring new local candidates for RAW UDP");
- jingle_transport_free_candidates (new_candidates);
- return;
- }
-
- priv->local_candidates = new_candidates;
-}
-
-static gboolean
-can_accept (GabbleJingleTransportIface *iface)
-{
- GabbleJingleTransportRawUdp *self = GABBLE_JINGLE_TRANSPORT_RAWUDP (iface);
-
- return (self->priv->local_candidates != NULL);
-}
-
-static GList *
-get_local_candidates (GabbleJingleTransportIface *iface)
-{
- GabbleJingleTransportRawUdp *transport =
- GABBLE_JINGLE_TRANSPORT_RAWUDP (iface);
- GabbleJingleTransportRawUdpPrivate *priv = transport->priv;
-
- return priv->local_candidates;
-}
-
-static GList *
-get_remote_candidates (GabbleJingleTransportIface *iface)
-{
- GabbleJingleTransportRawUdp *transport =
- GABBLE_JINGLE_TRANSPORT_RAWUDP (iface);
- GabbleJingleTransportRawUdpPrivate *priv = transport->priv;
-
- return priv->remote_candidates;
-}
-
-static JingleTransportType
-get_transport_type (void)
-{
- DEBUG ("called");
-
- return JINGLE_TRANSPORT_RAW_UDP;
-}
-
-static void
-transport_iface_init (gpointer g_iface, gpointer iface_data)
-{
- GabbleJingleTransportIfaceClass *klass = (GabbleJingleTransportIfaceClass *) g_iface;
-
- klass->parse_candidates = parse_candidates;
-
- klass->new_local_candidates = new_local_candidates;
- klass->inject_candidates = inject_candidates;
- /* Not implementing _send: XEP-0177 says that the candidates live in
- * content-{add,accept}, not in transport-info.
- */
- klass->can_accept = can_accept;
-
- klass->get_remote_candidates = get_remote_candidates;
- klass->get_local_candidates = get_local_candidates;
- klass->get_transport_type = get_transport_type;
-}
-
-void
-jingle_transport_rawudp_register (GabbleJingleFactory *factory)
-{
- gabble_jingle_factory_register_transport (factory,
- NS_JINGLE_TRANSPORT_RAWUDP,
- GABBLE_TYPE_JINGLE_TRANSPORT_RAWUDP);
-}
-
diff --git a/src/jingle-transport-rawudp.h b/src/jingle-transport-rawudp.h
deleted file mode 100644
index 060f854dc..000000000
--- a/src/jingle-transport-rawudp.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * jingle-transport-rawudp.h - Header for GabbleJingleTransportRawUdp
- * Copyright (C) 2008 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 __JINGLE_TRANSPORT_RAWUDP_H__
-#define __JINGLE_TRANSPORT_RAWUDP_H__
-
-#include <glib-object.h>
-
-#include "jingle-types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleJingleTransportRawUdpClass GabbleJingleTransportRawUdpClass;
-
-GType gabble_jingle_transport_rawudp_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_JINGLE_TRANSPORT_RAWUDP \
- (gabble_jingle_transport_rawudp_get_type ())
-#define GABBLE_JINGLE_TRANSPORT_RAWUDP(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_TRANSPORT_RAWUDP, \
- GabbleJingleTransportRawUdp))
-#define GABBLE_JINGLE_TRANSPORT_RAWUDP_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_TRANSPORT_RAWUDP, \
- GabbleJingleTransportRawUdpClass))
-#define GABBLE_IS_JINGLE_TRANSPORT_RAWUDP(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_TRANSPORT_RAWUDP))
-#define GABBLE_IS_JINGLE_TRANSPORT_RAWUDP_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_TRANSPORT_RAWUDP))
-#define GABBLE_JINGLE_TRANSPORT_RAWUDP_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_TRANSPORT_RAWUDP, \
- GabbleJingleTransportRawUdpClass))
-
-struct _GabbleJingleTransportRawUdpClass {
- GObjectClass parent_class;
-};
-
-typedef struct _GabbleJingleTransportRawUdpPrivate GabbleJingleTransportRawUdpPrivate;
-
-struct _GabbleJingleTransportRawUdp {
- GObject parent;
- GabbleJingleTransportRawUdpPrivate *priv;
-};
-
-void jingle_transport_rawudp_register (GabbleJingleFactory *factory);
-
-#endif /* __JINGLE_TRANSPORT_RAWUDP_H__ */
-
diff --git a/src/jingle-types.h b/src/jingle-types.h
deleted file mode 100644
index 14934aae6..000000000
--- a/src/jingle-types.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * jingle-types.h - Header for Jingle-related enums and typedefs
- * Copyright © 2008–2012 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 GABBLE_JINGLE_ENUMS_H
-#define GABBLE_JINGLE_ENUMS_H
-
-typedef struct _GabbleJingleFactory GabbleJingleFactory;
-typedef struct _GabbleJingleSession GabbleJingleSession;
-typedef struct _GabbleJingleContent GabbleJingleContent;
-typedef struct _GabbleJingleTransportGoogle GabbleJingleTransportGoogle;
-typedef struct _GabbleJingleTransportRawUdp GabbleJingleTransportRawUdp;
-typedef struct _GabbleJingleTransportIceUdp GabbleJingleTransportIceUdp;
-typedef struct _GabbleJingleMediaRtp GabbleJingleMediaRtp;
-typedef struct _GabbleJingleShare GabbleJingleShare;
-typedef struct _JingleCandidate JingleCandidate;
-
-typedef enum { /*< skip >*/
- /* not a jingle message */
- JINGLE_DIALECT_ERROR,
- /* old libjingle3 gtalk variant */
- JINGLE_DIALECT_GTALK3,
- /* new gtalk variant */
- JINGLE_DIALECT_GTALK4,
- /* jingle in the old 0.15 version days */
- JINGLE_DIALECT_V015,
- /* current jingle standard */
- JINGLE_DIALECT_V032
-} JingleDialect;
-
-#define JINGLE_IS_GOOGLE_DIALECT(d)\
- ((d == JINGLE_DIALECT_GTALK3) || (d == JINGLE_DIALECT_GTALK4))
-
-typedef enum { /*< skip >*/
- JINGLE_STATE_INVALID = -1,
- JINGLE_STATE_PENDING_CREATED = 0,
- JINGLE_STATE_PENDING_INITIATE_SENT,
- JINGLE_STATE_PENDING_INITIATED,
- JINGLE_STATE_PENDING_ACCEPT_SENT,
- JINGLE_STATE_ACTIVE,
- JINGLE_STATE_ENDED,
- MAX_JINGLE_STATES
-} JingleState;
-
-typedef enum { /*< skip >*/
- JINGLE_ACTION_UNKNOWN,
- JINGLE_ACTION_CONTENT_ACCEPT,
- JINGLE_ACTION_CONTENT_ADD,
- JINGLE_ACTION_CONTENT_MODIFY,
- JINGLE_ACTION_CONTENT_REMOVE,
- JINGLE_ACTION_CONTENT_REPLACE,
- JINGLE_ACTION_CONTENT_REJECT,
- JINGLE_ACTION_SESSION_ACCEPT,
- JINGLE_ACTION_SESSION_INFO,
- JINGLE_ACTION_SESSION_INITIATE,
- JINGLE_ACTION_SESSION_TERMINATE,
- JINGLE_ACTION_TRANSPORT_INFO,
- JINGLE_ACTION_TRANSPORT_ACCEPT,
- JINGLE_ACTION_DESCRIPTION_INFO,
- JINGLE_ACTION_INFO
-} JingleAction;
-
-typedef enum { /*< skip >*/
- JINGLE_CONTENT_SENDERS_NONE,
- JINGLE_CONTENT_SENDERS_INITIATOR,
- JINGLE_CONTENT_SENDERS_RESPONDER,
- JINGLE_CONTENT_SENDERS_BOTH
-} JingleContentSenders;
-
-typedef enum { /*< skip >*/
- JINGLE_TRANSPORT_UNKNOWN,
- JINGLE_TRANSPORT_GOOGLE_P2P,
- JINGLE_TRANSPORT_RAW_UDP,
- JINGLE_TRANSPORT_ICE_UDP,
-} JingleTransportType;
-
-typedef enum { /*< skip >*/
- JINGLE_TRANSPORT_PROTOCOL_UDP,
- JINGLE_TRANSPORT_PROTOCOL_TCP
-} JingleTransportProtocol;
-
-typedef enum { /*< skip >*/
- JINGLE_CANDIDATE_TYPE_LOCAL,
- JINGLE_CANDIDATE_TYPE_STUN,
- JINGLE_CANDIDATE_TYPE_RELAY
-} JingleCandidateType;
-
-typedef enum
-{
- JINGLE_REASON_UNKNOWN,
- JINGLE_REASON_ALTERNATIVE_SESSION,
- JINGLE_REASON_BUSY,
- JINGLE_REASON_CANCEL,
- JINGLE_REASON_CONNECTIVITY_ERROR,
- JINGLE_REASON_DECLINE,
- JINGLE_REASON_EXPIRED,
- JINGLE_REASON_FAILED_APPLICATION,
- JINGLE_REASON_FAILED_TRANSPORT,
- JINGLE_REASON_GENERAL_ERROR,
- JINGLE_REASON_GONE,
- JINGLE_REASON_INCOMPATIBLE_PARAMETERS,
- JINGLE_REASON_MEDIA_ERROR,
- JINGLE_REASON_SECURITY_ERROR,
- JINGLE_REASON_SUCCESS,
- JINGLE_REASON_TIMEOUT,
- JINGLE_REASON_UNSUPPORTED_APPLICATIONS,
- JINGLE_REASON_UNSUPPORTED_TRANSPORTS
-} JingleReason;
-
-
-#endif /* GABBLE_JINGLE_ENUMS_H */
diff --git a/src/legacy-caps.c b/src/legacy-caps.c
index 3f4ebde5c..827fc15ea 100644
--- a/src/legacy-caps.c
+++ b/src/legacy-caps.c
@@ -21,7 +21,7 @@
#include "config.h"
#include "legacy-caps.h"
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
#include "debug.h"
diff --git a/src/media-channel-hold.c b/src/media-channel-hold.c
index bb4cb576c..b4dc26c5a 100644
--- a/src/media-channel-hold.c
+++ b/src/media-channel-hold.c
@@ -19,10 +19,11 @@
*/
#include "config.h"
+
#include "media-channel.h"
#include "media-channel-internal.h"
-#include <telepathy-glib/channel-iface.h>
+#include <telepathy-glib/telepathy-glib.h>
#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
@@ -79,7 +80,7 @@ stream_hold_state_changed (GabbleMediaStream *stream G_GNUC_UNUSED,
priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
if (priv->session != NULL)
- gabble_jingle_session_set_local_hold (priv->session, FALSE);
+ wocky_jingle_session_set_local_hold (priv->session, FALSE);
break;
@@ -173,7 +174,7 @@ stream_hold_state_changed (GabbleMediaStream *stream G_GNUC_UNUSED,
/* Tell the peer what's happened. */
if (priv->session != NULL)
- gabble_jingle_session_set_local_hold (priv->session, FALSE);
+ wocky_jingle_session_set_local_hold (priv->session, FALSE);
}
tp_svc_channel_interface_hold_emit_hold_state_changed (self,
@@ -234,7 +235,7 @@ gabble_media_channel_request_hold (TpSvcChannelInterfaceHold *iface,
{
GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface);
GabbleMediaChannelPrivate *priv = self->priv;
- GabbleJingleSession *session = priv->session;
+ WockyJingleSession *session = priv->session;
guint i;
TpLocalHoldState old_state = priv->hold_state;
@@ -250,7 +251,7 @@ gabble_media_channel_request_hold (TpSvcChannelInterfaceHold *iface,
}
if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD && session != NULL)
- gabble_jingle_session_set_local_hold (session, TRUE);
+ wocky_jingle_session_set_local_hold (session, TRUE);
priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
}
@@ -327,16 +328,16 @@ gabble_media_channel_hold_iface_init (gpointer g_iface,
*/
static void
-remote_state_changed_cb (GabbleJingleSession *session,
+remote_state_changed_cb (WockyJingleSession *session,
GabbleMediaChannel *self)
{
GabbleMediaChannelPrivate *priv = self->priv;
TpChannelCallStateFlags call_state = 0;
- if (gabble_jingle_session_get_remote_hold (session))
+ if (wocky_jingle_session_get_remote_hold (session))
call_state |= TP_CHANNEL_CALL_STATE_HELD;
- if (gabble_jingle_session_get_remote_ringing (session))
+ if (wocky_jingle_session_get_remote_ringing (session))
call_state |= TP_CHANNEL_CALL_STATE_RINGING;
DEBUG ("Call state changed to %u (current state %u)", call_state,
@@ -393,7 +394,7 @@ gabble_media_channel_call_state_iface_init (gpointer g_iface,
void
gabble_media_channel_hold_new_stream (GabbleMediaChannel *chan,
GabbleMediaStream *stream,
- GabbleJingleMediaRtp *content)
+ WockyJingleMediaRtp *content)
{
GObject *chan_o = (GObject *) chan;
diff --git a/src/media-channel-internal.h b/src/media-channel-internal.h
index 9264eac8b..4459df726 100644
--- a/src/media-channel-internal.h
+++ b/src/media-channel-internal.h
@@ -26,11 +26,10 @@
#include <glib.h>
-#include <telepathy-glib/dtmf.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <wocky/wocky.h>
#include "media-stream.h"
-#include "jingle-session.h"
-#include "jingle-media-rtp.h"
G_BEGIN_DECLS
@@ -43,7 +42,7 @@ struct _GabbleMediaChannelPrivate
TpHandle peer;
gboolean peer_in_rp;
- GabbleJingleSession *session;
+ WockyJingleSession *session;
/* array of referenced GabbleMediaStream*. Always non-NULL. */
GPtrArray *streams;
@@ -79,7 +78,7 @@ void gabble_media_channel_hold_latch_to_session (GabbleMediaChannel *chan);
void gabble_media_channel_hold_new_stream (GabbleMediaChannel *chan,
GabbleMediaStream *stream,
- GabbleJingleMediaRtp *content);
+ WockyJingleMediaRtp *content);
void gabble_media_channel_hold_stream_closed (GabbleMediaChannel *chan,
GabbleMediaStream *stream);
diff --git a/src/media-channel.c b/src/media-channel.c
index 0721b2908..c4ab89e37 100644
--- a/src/media-channel.c
+++ b/src/media-channel.c
@@ -26,23 +26,15 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/exportable-channel.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 <telepathy-glib/svc-media-interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+
+#include <wocky/wocky.h>
#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
#include "connection.h"
#include "debug.h"
-#include "jingle-content.h"
-#include "jingle-factory.h"
-#include "jingle-media-rtp.h"
-#include "jingle-session.h"
#include "jingle-tp-util.h"
#include "media-factory.h"
#include "media-stream.h"
@@ -148,7 +140,7 @@ const TpPropertySignature channel_property_signatures[NUM_CHAN_PROPS] = {
typedef struct {
GabbleMediaChannel *self;
- GabbleJingleContent *content;
+ WockyJingleContent *content;
gulong removed_id;
gchar *name;
const gchar *nat_traversal;
@@ -208,20 +200,20 @@ gabble_media_channel_init (GabbleMediaChannel *self)
G_CONNECT_SWAPPED);
}
-static void session_state_changed_cb (GabbleJingleSession *session,
+static void session_state_changed_cb (WockyJingleSession *session,
GParamSpec *arg1, GabbleMediaChannel *channel);
-static void session_terminated_cb (GabbleJingleSession *session,
- gboolean local_terminator, JingleReason reason, const gchar *text,
+static void session_terminated_cb (WockyJingleSession *session,
+ gboolean local_terminator, WockyJingleReason reason, const gchar *text,
gpointer user_data);
-static void session_new_content_cb (GabbleJingleSession *session,
- GabbleJingleContent *c, gpointer user_data);
+static void session_new_content_cb (WockyJingleSession *session,
+ WockyJingleContent *c, gpointer user_data);
static void create_stream_from_content (GabbleMediaChannel *chan,
- GabbleJingleContent *c, gboolean initial);
+ WockyJingleContent *c, gboolean initial);
static gboolean contact_is_media_capable (GabbleMediaChannel *chan, TpHandle peer,
gboolean *wait, GError **error);
static void stream_creation_data_cancel (gpointer p, gpointer unused);
-static void session_content_rejected_cb (GabbleJingleSession *session,
- GabbleJingleContent *c, JingleReason reason, const gchar *message,
+static void session_content_rejected_cb (WockyJingleSession *session,
+ WockyJingleContent *c, WockyJingleReason reason, const gchar *message,
gpointer user_data);
static void
@@ -230,14 +222,14 @@ create_initial_streams (GabbleMediaChannel *chan)
GabbleMediaChannelPrivate *priv = chan->priv;
GList *contents, *li;
- contents = gabble_jingle_session_get_contents (priv->session);
+ contents = wocky_jingle_session_get_contents (priv->session);
for (li = contents; li; li = li->next)
{
- GabbleJingleContent *c = li->data;
+ WockyJingleContent *c = li->data;
/* I'm so sorry. */
- if (G_OBJECT_TYPE (c) == GABBLE_TYPE_JINGLE_MEDIA_RTP)
+ if (G_OBJECT_TYPE (c) == WOCKY_TYPE_JINGLE_MEDIA_RTP)
{
guint media_type;
@@ -245,10 +237,10 @@ create_initial_streams (GabbleMediaChannel *chan)
switch (media_type)
{
- case JINGLE_MEDIA_TYPE_AUDIO:
+ case WOCKY_JINGLE_MEDIA_TYPE_AUDIO:
priv->initial_audio = TRUE;
break;
- case JINGLE_MEDIA_TYPE_VIDEO:
+ case WOCKY_JINGLE_MEDIA_TYPE_VIDEO:
priv->initial_video = TRUE;
break;
default:
@@ -303,11 +295,11 @@ _latch_to_session (GabbleMediaChannel *chan)
static void
create_session (GabbleMediaChannel *chan,
const gchar *jid,
- JingleDialect dialect)
+ WockyJingleDialect dialect)
{
GabbleMediaChannelPrivate *priv = chan->priv;
gboolean local_hold = (priv->hold_state != TP_LOCAL_HOLD_STATE_UNHELD);
- GabbleJingleFactory *jf;
+ WockyJingleFactory *jf;
g_assert (priv->session == NULL);
@@ -316,7 +308,7 @@ create_session (GabbleMediaChannel *chan,
jf = gabble_jingle_mint_get_factory (priv->conn->jingle_mint);
g_return_if_fail (jf != NULL);
priv->session = g_object_ref (
- gabble_jingle_factory_create_session (jf, jid, dialect, local_hold));
+ wocky_jingle_factory_create_session (jf, jid, dialect, local_hold));
_latch_to_session (chan);
}
@@ -329,12 +321,11 @@ gabble_media_channel_constructor (GType type, guint n_props,
GabbleMediaChannelPrivate *priv;
TpBaseConnection *conn;
TpDBusDaemon *bus;
- TpIntSet *set;
+ TpIntset *set;
TpHandleRepoIface *contact_handles;
- GabbleJingleInfo *ji;
+ WockyJingleInfo *ji;
const gchar *relay_token;
- gchar *stun_server;
- guint stun_port;
+ GList *stun_servers;
obj = G_OBJECT_CLASS (gabble_media_channel_parent_class)->
constructor (type, n_props, props);
@@ -349,24 +340,23 @@ gabble_media_channel_constructor (GType type, guint n_props,
tp_dbus_daemon_register_object (bus, priv->object_path, obj);
tp_group_mixin_init (obj, G_STRUCT_OFFSET (GabbleMediaChannel, group),
- contact_handles, conn->self_handle);
+ contact_handles, tp_base_connection_get_self_handle (conn));
if (priv->session != NULL)
{
priv->peer = ensure_handle_from_contact (priv->conn,
- gabble_jingle_session_get_peer_contact (priv->session));
+ wocky_jingle_session_get_peer_contact (priv->session));
g_return_val_if_fail (priv->peer != 0, NULL);
priv->creator = priv->peer;
}
else
{
- priv->creator = conn->self_handle;
+ priv->creator = tp_base_connection_get_self_handle (conn);
}
/* automatically add creator to channel, but also ref them again (because
* priv->creator is the InitiatorHandle) */
g_assert (priv->creator != 0);
- tp_handle_ref (contact_handles, priv->creator);
set = tp_intset_new_containing (priv->creator);
tp_group_mixin_change_members (obj, "", set, NULL, NULL, NULL, 0,
@@ -385,18 +375,20 @@ gabble_media_channel_constructor (GType type, guint n_props,
/* Set up Google relay related properties */
ji = gabble_jingle_mint_get_info (priv->conn->jingle_mint);
-
- if (gabble_jingle_info_get_stun_server (ji, &stun_server,
- &stun_port))
+ stun_servers = wocky_jingle_info_get_stun_servers (ji);
+ if (stun_servers != NULL)
{
+ WockyStunServer *stun_server = stun_servers->data;
+
g_object_set (obj,
- "stun-server", stun_server,
- "stun-port", stun_port,
+ "stun-server", stun_server->address,
+ "stun-port", (guint) stun_server->port,
NULL);
- g_free (stun_server);
+
+ g_list_free (stun_servers);
}
- relay_token = gabble_jingle_info_get_google_relay_token (ji);
+ relay_token = wocky_jingle_info_get_google_relay_token (ji);
if (relay_token != NULL)
{
@@ -411,7 +403,7 @@ gabble_media_channel_constructor (GType type, guint n_props,
* group flags (all we can do is add or remove ourselves, which is always
* valid per the spec)
*/
- set = tp_intset_new_containing (conn->self_handle);
+ set = tp_intset_new_containing (tp_base_connection_get_self_handle (conn));
tp_group_mixin_change_members (obj, "", NULL, NULL, set, NULL,
priv->peer, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
tp_intset_destroy (set);
@@ -435,7 +427,8 @@ gabble_media_channel_constructor (GType type, guint n_props,
*/
set = tp_intset_new_containing (priv->initial_peer);
tp_group_mixin_change_members (obj, "", NULL, NULL, NULL, set,
- conn->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
+ tp_base_connection_get_self_handle (conn),
+ TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
tp_intset_destroy (set);
}
@@ -460,7 +453,7 @@ gabble_media_channel_constructor (GType type, guint n_props,
/* If this is a Google session, let's set ImmutableStreams */
if (priv->session != NULL)
{
- priv->immutable_streams = !gabble_jingle_session_can_modify_contents (priv->session);
+ priv->immutable_streams = !wocky_jingle_session_can_modify_contents (priv->session);
}
/* If there's no session yet, but we know who the peer will be, and we have
* presence for them, we can set ImmutableStreams using the same algorithm as
@@ -565,7 +558,8 @@ gabble_media_channel_get_property (GObject *object,
}
break;
case PROP_REQUESTED:
- g_value_set_boolean (value, (priv->creator == base_conn->self_handle));
+ g_value_set_boolean (value,
+ (priv->creator == tp_base_connection_get_self_handle (base_conn)));
break;
case PROP_INTERFACES:
g_value_set_boxed (value, gabble_media_channel_interfaces);
@@ -666,15 +660,6 @@ gabble_media_channel_set_property (GObject *object,
break;
case PROP_INITIAL_PEER:
priv->initial_peer = g_value_get_uint (value);
-
- if (priv->initial_peer != 0)
- {
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
- TpHandleRepoIface *repo = tp_base_connection_get_handles (base_conn,
- TP_HANDLE_TYPE_CONTACT);
- tp_handle_ref (repo, priv->initial_peer);
- }
-
break;
case PROP_PEER_IN_RP:
priv->peer_in_rp = g_value_get_boolean (value);
@@ -881,9 +866,9 @@ gabble_media_channel_class_init (GabbleMediaChannelClass *gabble_media_channel_c
g_object_class_install_property (object_class, PROP_GTALK_P2P_RELAY_TOKEN,
param_spec);
- param_spec = g_param_spec_object ("session", "GabbleJingleSession object",
+ param_spec = g_param_spec_object ("session", "WockyJingleSession object",
"Jingle session associated with this media channel object.",
- GABBLE_TYPE_JINGLE_SESSION,
+ WOCKY_TYPE_JINGLE_SESSION,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
g_object_class_install_property (object_class, PROP_SESSION, param_spec);
@@ -952,9 +937,6 @@ gabble_media_channel_dispose (GObject *object)
{
GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (object);
GabbleMediaChannelPrivate *priv = self->priv;
- TpBaseConnection *conn = (TpBaseConnection *) priv->conn;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (
- conn, TP_HANDLE_TYPE_CONTACT);
GList *l;
if (priv->dispose_has_run)
@@ -990,15 +972,6 @@ gabble_media_channel_dispose (GObject *object)
priv->delayed_request_streams = NULL;
}
- tp_handle_unref (contact_handles, priv->creator);
- priv->creator = 0;
-
- if (priv->initial_peer != 0)
- {
- tp_handle_unref (contact_handles, priv->initial_peer);
- priv->initial_peer = 0;
- }
-
/* All of the streams should have closed in response to the contents being
* removed when the call ended.
*/
@@ -1062,8 +1035,8 @@ gabble_media_channel_close (GabbleMediaChannel *self)
priv->closed = TRUE;
if (priv->session != NULL)
- gabble_jingle_session_terminate (priv->session,
- JINGLE_REASON_UNKNOWN, NULL, NULL);
+ wocky_jingle_session_terminate (priv->session,
+ WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL);
tp_svc_channel_emit_closed (self);
}
@@ -1279,14 +1252,14 @@ _find_stream_by_id (GabbleMediaChannel *chan,
return stream;
}
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"given stream id %u does not exist", stream_id);
return NULL;
}
static GabbleMediaStream *
_find_stream_by_content (GabbleMediaChannel *chan,
- GabbleJingleContent *content)
+ WockyJingleContent *content)
{
GabbleMediaChannelPrivate *priv;
guint i;
@@ -1298,7 +1271,7 @@ _find_stream_by_content (GabbleMediaChannel *chan,
for (i = 0; i < priv->streams->len; i++)
{
GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i);
- GabbleJingleContent *c = GABBLE_JINGLE_CONTENT (
+ WockyJingleContent *c = WOCKY_JINGLE_CONTENT (
gabble_media_stream_get_content (stream));
if (content == c)
@@ -1329,9 +1302,9 @@ gabble_media_channel_remove_streams (TpSvcChannelTypeStreamedMedia *iface,
priv = obj->priv;
- if (!gabble_jingle_session_can_modify_contents (priv->session))
+ if (!wocky_jingle_session_can_modify_contents (priv->session))
{
- GError e = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ GError e = { TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Streams can't be removed from Google Talk calls" };
dbus_g_method_return_error (context, &e);
return;
@@ -1374,7 +1347,7 @@ gabble_media_channel_remove_streams (TpSvcChannelTypeStreamedMedia *iface,
if (stream_objs->len > 0)
{
GabbleMediaStream *stream;
- GabbleJingleMediaRtp *c;
+ WockyJingleMediaRtp *c;
for (i = 0; i < stream_objs->len; i++)
{
@@ -1383,8 +1356,8 @@ gabble_media_channel_remove_streams (TpSvcChannelTypeStreamedMedia *iface,
/* FIXME: make sure session emits content-removed, on which we can
* delete it from the list */
- gabble_jingle_session_remove_content (priv->session,
- (GabbleJingleContent *) c);
+ wocky_jingle_session_remove_content (priv->session,
+ (WockyJingleContent *) c);
}
}
@@ -1426,7 +1399,7 @@ gabble_media_channel_request_stream_direction (TpSvcChannelTypeStreamedMedia *if
if (stream_direction > TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"given stream direction %u is not valid", stream_direction);
dbus_g_method_return_error (context, error);
g_error_free (error);
@@ -1449,22 +1422,22 @@ gabble_media_channel_request_stream_direction (TpSvcChannelTypeStreamedMedia *if
if (stream_direction == TP_MEDIA_STREAM_DIRECTION_NONE)
{
- if (gabble_jingle_session_can_modify_contents (priv->session))
+ if (wocky_jingle_session_can_modify_contents (priv->session))
{
- GabbleJingleMediaRtp *c;
+ WockyJingleMediaRtp *c;
DEBUG ("request for NONE direction; removing stream");
c = gabble_media_stream_get_content (stream);
- gabble_jingle_session_remove_content (priv->session,
- (GabbleJingleContent *) c);
+ wocky_jingle_session_remove_content (priv->session,
+ (WockyJingleContent *) c);
tp_svc_channel_type_streamed_media_return_from_request_stream_direction (
context);
}
else
{
- GError e = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ GError e = { TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Stream direction can't be set to None in Google Talk calls" };
DEBUG ("%s", e.message);
dbus_g_method_return_error (context, &e);
@@ -1489,7 +1462,7 @@ typedef struct {
/* number of streams requested == number of content objects */
guint len;
/* array of @len borrowed pointers */
- GabbleJingleContent **contents;
+ WockyJingleContent **contents;
/* accumulates borrowed pointers to streams. Initially @len NULL pointers;
* when the stream for contents[i] is created, it is stored at streams[i].
*/
@@ -1531,7 +1504,7 @@ pending_stream_request_new (GPtrArray *contents,
static gboolean
pending_stream_request_maybe_satisfy (PendingStreamRequest *p,
GabbleMediaChannel *channel,
- GabbleJingleContent *content,
+ WockyJingleContent *content,
GabbleMediaStream *stream)
{
guint i;
@@ -1562,7 +1535,7 @@ pending_stream_request_maybe_satisfy (PendingStreamRequest *p,
static gboolean
pending_stream_request_maybe_fail (PendingStreamRequest *p,
GabbleMediaChannel *channel,
- GabbleJingleContent *content)
+ WockyJingleContent *content)
{
guint i;
@@ -1570,7 +1543,7 @@ pending_stream_request_maybe_fail (PendingStreamRequest *p,
{
if (content == p->contents[i])
{
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"A stream was removed before it could be fully set up" };
/* return early */
@@ -1590,7 +1563,7 @@ pending_stream_request_free (gpointer data)
if (p->context != NULL)
{
- GError e = { TP_ERRORS, TP_ERROR_CANCELLED,
+ GError e = { TP_ERROR, TP_ERROR_CANCELLED,
"The session terminated before the requested streams could be added"
};
@@ -1612,7 +1585,7 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
{
GabbleMediaChannelPrivate *priv = chan->priv;
gboolean want_audio, want_video;
- JingleDialect dialect;
+ WockyJingleDialect dialect;
guint idx;
const gchar *peer_resource;
const gchar *transport_ns = NULL;
@@ -1635,7 +1608,7 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
}
else
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"given media type %u is invalid", media_type);
return FALSE;
}
@@ -1644,7 +1617,7 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
/* existing call; the recipient and the mode has already been decided */
if (priv->session != NULL)
{
- peer_resource = gabble_jingle_session_get_peer_resource (priv->session);
+ peer_resource = wocky_jingle_session_get_peer_resource (priv->session);
if (peer_resource[0] != '\0')
DEBUG ("existing call, using peer resource %s", peer_resource);
@@ -1652,9 +1625,9 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
DEBUG ("existing call, using bare JID");
/* is a google call... we have no other option */
- if (!gabble_jingle_session_can_modify_contents (priv->session))
+ if (!wocky_jingle_session_can_modify_contents (priv->session))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Streams can't be added to ongoing Google Talk calls");
return FALSE;
}
@@ -1663,9 +1636,9 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
* one channel type (video or audio) will be added later */
if (NULL == jingle_pick_best_content_type (priv->conn, peer,
peer_resource,
- want_audio ? JINGLE_MEDIA_TYPE_AUDIO : JINGLE_MEDIA_TYPE_VIDEO))
+ want_audio ? WOCKY_JINGLE_MEDIA_TYPE_AUDIO : WOCKY_JINGLE_MEDIA_TYPE_VIDEO))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"member does not have the desired audio/video capabilities");
return FALSE;
@@ -1674,8 +1647,8 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
/* We assume we already picked the best possible transport ns for the
* previous streams, so we just reuse that one */
{
- GList *contents = gabble_jingle_session_get_contents (priv->session);
- GabbleJingleContent *c;
+ GList *contents = wocky_jingle_session_get_contents (priv->session);
+ WockyJingleContent *c;
/* If we have a session, we must have at least one content. */
g_assert (contents != NULL);
@@ -1683,7 +1656,7 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
c = contents->data;
g_list_free (contents);
- transport_ns = gabble_jingle_content_get_transport_ns (c);
+ transport_ns = wocky_jingle_content_get_transport_ns (c);
}
}
/* no existing call; we should choose a recipient and a mode */
@@ -1699,7 +1672,7 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
if (!jingle_pick_best_resource (priv->conn, peer,
want_audio, want_video, &transport_ns, &dialect, &peer_resource))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_CAPABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE,
"member does not have the desired audio/video capabilities");
return FALSE;
}
@@ -1729,7 +1702,7 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
/* 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,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"I think that's quite enough streams already");
return FALSE;
}
@@ -1741,13 +1714,13 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
for (idx = 0; idx < media_types->len; idx++)
{
guint media_type = g_array_index (media_types, guint, idx);
- GabbleJingleContent *c;
+ WockyJingleContent *c;
const gchar *content_ns;
content_ns = jingle_pick_best_content_type (priv->conn, peer,
peer_resource,
media_type == TP_MEDIA_STREAM_TYPE_AUDIO ?
- JINGLE_MEDIA_TYPE_AUDIO : JINGLE_MEDIA_TYPE_VIDEO);
+ WOCKY_JINGLE_MEDIA_TYPE_AUDIO : WOCKY_JINGLE_MEDIA_TYPE_VIDEO);
/* if we got this far, resource should be capable enough, so we
* should not fail in choosing ns */
@@ -1756,10 +1729,10 @@ _gabble_media_channel_request_contents (GabbleMediaChannel *chan,
DEBUG ("Creating new jingle content with ns %s : %s", content_ns, transport_ns);
- c = gabble_jingle_session_add_content (priv->session,
+ c = wocky_jingle_session_add_content (priv->session,
media_type == TP_MEDIA_STREAM_TYPE_AUDIO ?
- JINGLE_MEDIA_TYPE_AUDIO : JINGLE_MEDIA_TYPE_VIDEO,
- JINGLE_CONTENT_SENDERS_BOTH, NULL, content_ns, transport_ns);
+ WOCKY_JINGLE_MEDIA_TYPE_AUDIO : WOCKY_JINGLE_MEDIA_TYPE_VIDEO,
+ WOCKY_JINGLE_CONTENT_SENDERS_BOTH, NULL, content_ns, transport_ns);
/* The stream is created in "new-content" callback, and appended to
* priv->streams. This is now guaranteed to happen asynchronously (adding
@@ -1790,7 +1763,7 @@ destroy_request (struct _delayed_request_streams_ctx *ctx,
if (ctx->context != NULL)
{
GError *error = NULL;
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"cannot add streams: peer has insufficient caps");
ctx->failed_cb (ctx->context, error);
g_error_free (error);
@@ -1917,7 +1890,7 @@ media_channel_request_streams (GabbleMediaChannel *self,
if (priv->peer != 0 && priv->peer != contact_handle)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"cannot add streams for %u: this channel's peer is %u",
contact_handle, priv->peer);
goto error;
@@ -1934,7 +1907,7 @@ media_channel_request_streams (GabbleMediaChannel *self,
g_ptr_array_unref (contents);
/* signal acceptance */
- gabble_jingle_session_accept (priv->session);
+ wocky_jingle_session_accept (priv->session);
return;
@@ -2001,9 +1974,10 @@ gabble_media_channel_request_initial_streams (GabbleMediaChannel *chan,
GabbleMediaChannelPrivate *priv = chan->priv;
GArray *types = g_array_sized_new (FALSE, FALSE, sizeof (guint), 2);
guint media_type;
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
/* This has to be an outgoing call... */
- g_assert (priv->creator == priv->conn->parent.self_handle);
+ g_assert (priv->creator == tp_base_connection_get_self_handle (base_conn));
/* ...which has just been constructed. */
g_assert (priv->session == NULL);
@@ -2080,11 +2054,11 @@ contact_is_media_capable (GabbleMediaChannel *chan,
*wait_ret = wait;
if (presence == NULL)
- g_set_error (error, TP_ERRORS, TP_ERROR_OFFLINE,
+ g_set_error (error, TP_ERROR, TP_ERROR_OFFLINE,
"contact %d (%s) has no presence available", peer,
tp_handle_inspect (contact_handles, peer));
else
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_CAPABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE,
"contact %d (%s) doesn't have sufficient media caps", peer,
tp_handle_inspect (contact_handles, peer));
@@ -2100,7 +2074,7 @@ gabble_media_channel_add_member (GObject *obj,
GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (obj);
GabbleMediaChannelPrivate *priv = chan->priv;
TpGroupMixin *mixin = TP_GROUP_MIXIN (obj);
- TpIntSet *set;
+ TpIntset *set;
/* did we create this channel? */
if (priv->creator == mixin->self_handle)
@@ -2113,7 +2087,7 @@ gabble_media_channel_add_member (GObject *obj,
*/
if (priv->peer != 0 && priv->peer != handle)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"handle %u cannot be added: this channel's peer is %u",
handle, priv->peer);
return FALSE;
@@ -2160,7 +2134,7 @@ gabble_media_channel_add_member (GObject *obj,
/* is the call on hold? */
if (priv->hold_state != TP_LOCAL_HOLD_STATE_UNHELD)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Can't answer a call while it's on hold");
return FALSE;
}
@@ -2176,13 +2150,13 @@ gabble_media_channel_add_member (GObject *obj,
(GFunc) gabble_media_stream_accept_pending_local_send, NULL);
/* signal acceptance */
- gabble_jingle_session_accept (priv->session);
+ wocky_jingle_session_accept (priv->session);
return TRUE;
}
}
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"handle %u cannot be added in the current state", handle);
return FALSE;
}
@@ -2213,33 +2187,33 @@ gabble_media_channel_remove_member (GObject *obj,
}
else
{
- JingleReason jingle_reason = JINGLE_REASON_UNKNOWN;
+ WockyJingleReason wocky_jingle_reason = WOCKY_JINGLE_REASON_UNKNOWN;
switch (reason)
{
case TP_CHANNEL_GROUP_CHANGE_REASON_NONE:
- jingle_reason = JINGLE_REASON_UNKNOWN;
+ wocky_jingle_reason = WOCKY_JINGLE_REASON_UNKNOWN;
break;
case TP_CHANNEL_GROUP_CHANGE_REASON_OFFLINE:
- jingle_reason = JINGLE_REASON_GONE;
+ wocky_jingle_reason = WOCKY_JINGLE_REASON_GONE;
break;
case TP_CHANNEL_GROUP_CHANGE_REASON_BUSY:
- jingle_reason = JINGLE_REASON_BUSY;
+ wocky_jingle_reason = WOCKY_JINGLE_REASON_BUSY;
break;
case TP_CHANNEL_GROUP_CHANGE_REASON_ERROR:
- jingle_reason = JINGLE_REASON_GENERAL_ERROR;
+ wocky_jingle_reason = WOCKY_JINGLE_REASON_GENERAL_ERROR;
break;
case TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER:
- jingle_reason = JINGLE_REASON_TIMEOUT;
+ wocky_jingle_reason = WOCKY_JINGLE_REASON_TIMEOUT;
break;
default:
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%u doesn't make sense as a reason to end a call", reason);
g_object_unref (chan);
return FALSE;
}
- gabble_jingle_session_terminate (priv->session, jingle_reason, message,
+ wocky_jingle_session_terminate (priv->session, wocky_jingle_reason, message,
error);
}
@@ -2269,24 +2243,24 @@ copy_stream_list (GabbleMediaChannel *channel)
/* return TRUE when the jingle reason is reason enough to raise a
* StreamError */
static gboolean
-extract_media_stream_error_from_jingle_reason (JingleReason jingle_reason,
+extract_media_stream_error_from_jingle_reason (WockyJingleReason wocky_jingle_reason,
TpMediaStreamError *stream_error)
{
TpMediaStreamError _stream_error;
/* TODO: Make a better mapping with more distinction of possible errors */
- switch (jingle_reason)
+ switch (wocky_jingle_reason)
{
- case JINGLE_REASON_CONNECTIVITY_ERROR:
+ case WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR:
_stream_error = TP_MEDIA_STREAM_ERROR_NETWORK_ERROR;
break;
- case JINGLE_REASON_MEDIA_ERROR:
+ case WOCKY_JINGLE_REASON_MEDIA_ERROR:
_stream_error = TP_MEDIA_STREAM_ERROR_MEDIA_ERROR;
break;
- case JINGLE_REASON_FAILED_APPLICATION:
+ case WOCKY_JINGLE_REASON_FAILED_APPLICATION:
_stream_error = TP_MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED;
break;
- case JINGLE_REASON_GENERAL_ERROR:
+ case WOCKY_JINGLE_REASON_GENERAL_ERROR:
_stream_error = TP_MEDIA_STREAM_ERROR_UNKNOWN;
break;
default:
@@ -2304,42 +2278,42 @@ extract_media_stream_error_from_jingle_reason (JingleReason jingle_reason,
return TRUE;
}
-static JingleReason
+static WockyJingleReason
media_stream_error_to_jingle_reason (TpMediaStreamError stream_error)
{
switch (stream_error)
{
case TP_MEDIA_STREAM_ERROR_NETWORK_ERROR:
- return JINGLE_REASON_CONNECTIVITY_ERROR;
+ return WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR;
case TP_MEDIA_STREAM_ERROR_MEDIA_ERROR:
- return JINGLE_REASON_MEDIA_ERROR;
+ return WOCKY_JINGLE_REASON_MEDIA_ERROR;
case TP_MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED:
- return JINGLE_REASON_FAILED_APPLICATION;
+ return WOCKY_JINGLE_REASON_FAILED_APPLICATION;
default:
- return JINGLE_REASON_GENERAL_ERROR;
+ return WOCKY_JINGLE_REASON_GENERAL_ERROR;
}
}
static TpChannelGroupChangeReason
-jingle_reason_to_group_change_reason (JingleReason jingle_reason)
+wocky_jingle_reason_to_group_change_reason (WockyJingleReason wocky_jingle_reason)
{
- switch (jingle_reason)
+ switch (wocky_jingle_reason)
{
- case JINGLE_REASON_BUSY:
+ case WOCKY_JINGLE_REASON_BUSY:
return TP_CHANNEL_GROUP_CHANGE_REASON_BUSY;
- case JINGLE_REASON_GONE:
+ case WOCKY_JINGLE_REASON_GONE:
return TP_CHANNEL_GROUP_CHANGE_REASON_OFFLINE;
- case JINGLE_REASON_TIMEOUT:
+ case WOCKY_JINGLE_REASON_TIMEOUT:
return TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER;
- case JINGLE_REASON_CONNECTIVITY_ERROR:
- case JINGLE_REASON_FAILED_APPLICATION:
- case JINGLE_REASON_FAILED_TRANSPORT:
- case JINGLE_REASON_GENERAL_ERROR:
- case JINGLE_REASON_MEDIA_ERROR:
- case JINGLE_REASON_SECURITY_ERROR:
- case JINGLE_REASON_INCOMPATIBLE_PARAMETERS:
- case JINGLE_REASON_UNSUPPORTED_APPLICATIONS:
- case JINGLE_REASON_UNSUPPORTED_TRANSPORTS:
+ case WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR:
+ case WOCKY_JINGLE_REASON_FAILED_APPLICATION:
+ case WOCKY_JINGLE_REASON_FAILED_TRANSPORT:
+ case WOCKY_JINGLE_REASON_GENERAL_ERROR:
+ case WOCKY_JINGLE_REASON_MEDIA_ERROR:
+ case WOCKY_JINGLE_REASON_SECURITY_ERROR:
+ case WOCKY_JINGLE_REASON_INCOMPATIBLE_PARAMETERS:
+ case WOCKY_JINGLE_REASON_UNSUPPORTED_APPLICATIONS:
+ case WOCKY_JINGLE_REASON_UNSUPPORTED_TRANSPORTS:
return TP_CHANNEL_GROUP_CHANGE_REASON_ERROR;
default:
return TP_CHANNEL_GROUP_CHANGE_REASON_NONE;
@@ -2347,9 +2321,9 @@ jingle_reason_to_group_change_reason (JingleReason jingle_reason)
}
static void
-session_terminated_cb (GabbleJingleSession *session,
+session_terminated_cb (WockyJingleSession *session,
gboolean local_terminator,
- JingleReason jingle_reason,
+ WockyJingleReason wocky_jingle_reason,
const gchar *text,
gpointer user_data)
{
@@ -2357,8 +2331,8 @@ session_terminated_cb (GabbleJingleSession *session,
GabbleMediaChannelPrivate *priv = channel->priv;
TpGroupMixin *mixin = TP_GROUP_MIXIN (channel);
guint terminator;
- JingleState state;
- TpIntSet *set;
+ WockyJingleState state;
+ TpIntset *set;
DEBUG ("called");
@@ -2379,7 +2353,7 @@ session_terminated_cb (GabbleJingleSession *session,
tp_group_mixin_change_members ((GObject *) channel,
text, NULL, set, NULL, NULL, terminator,
- jingle_reason_to_group_change_reason (jingle_reason));
+ wocky_jingle_reason_to_group_change_reason (wocky_jingle_reason));
tp_intset_destroy (set);
@@ -2398,7 +2372,7 @@ session_terminated_cb (GabbleJingleSession *session,
guint i;
TpMediaStreamError stream_error = TP_MEDIA_STREAM_ERROR_UNKNOWN;
gboolean is_error = extract_media_stream_error_from_jingle_reason (
- jingle_reason, &stream_error);
+ wocky_jingle_reason, &stream_error);
for (i = 0; i < tmp->len; i++)
{
@@ -2437,15 +2411,15 @@ session_terminated_cb (GabbleJingleSession *session,
static void
-session_state_changed_cb (GabbleJingleSession *session,
+session_state_changed_cb (WockyJingleSession *session,
GParamSpec *arg1,
GabbleMediaChannel *channel)
{
GObject *as_object = (GObject *) channel;
GabbleMediaChannelPrivate *priv = channel->priv;
TpGroupMixin *mixin = TP_GROUP_MIXIN (channel);
- JingleState state;
- TpIntSet *set;
+ WockyJingleState state;
+ TpIntset *set;
DEBUG ("called");
@@ -2455,8 +2429,8 @@ session_state_changed_cb (GabbleJingleSession *session,
set = tp_intset_new_containing (priv->peer);
- if (state >= JINGLE_STATE_PENDING_INITIATE_SENT &&
- state < JINGLE_STATE_ACTIVE &&
+ if (state >= WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT &&
+ state < WOCKY_JINGLE_STATE_ACTIVE &&
!tp_handle_set_is_member (mixin->members, priv->peer))
{
/* The first time we send anything to the other user, they materialise
@@ -2471,7 +2445,7 @@ session_state_changed_cb (GabbleJingleSession *session,
tp_group_mixin_change_flags (as_object, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD);
}
- if (state == JINGLE_STATE_ACTIVE &&
+ if (state == WOCKY_JINGLE_STATE_ACTIVE &&
priv->creator == mixin->self_handle)
{
@@ -2536,7 +2510,7 @@ stream_error_cb (GabbleMediaStream *stream,
GabbleMediaChannel *chan)
{
GabbleMediaChannelPrivate *priv = chan->priv;
- GabbleJingleMediaRtp *c;
+ WockyJingleMediaRtp *c;
GList *contents;
guint id;
@@ -2545,9 +2519,9 @@ stream_error_cb (GabbleMediaStream *stream,
tp_svc_channel_type_streamed_media_emit_stream_error (chan, id, errno,
message);
- contents = gabble_jingle_session_get_contents (priv->session);
+ contents = wocky_jingle_session_get_contents (priv->session);
- if (gabble_jingle_session_can_modify_contents (priv->session) &&
+ if (wocky_jingle_session_can_modify_contents (priv->session) &&
g_list_length (contents) > 1)
{
/* remove stream from session (removal will be signalled
@@ -2556,11 +2530,11 @@ stream_error_cb (GabbleMediaStream *stream,
c = gabble_media_stream_get_content (stream);
if (errno == TP_MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED)
- gabble_jingle_content_reject ((GabbleJingleContent *) c,
- JINGLE_REASON_FAILED_APPLICATION);
+ wocky_jingle_content_reject ((WockyJingleContent *) c,
+ WOCKY_JINGLE_REASON_FAILED_APPLICATION);
else
- gabble_jingle_session_remove_content (priv->session,
- (GabbleJingleContent *) c);
+ wocky_jingle_session_remove_content (priv->session,
+ (WockyJingleContent *) c);
}
else
{
@@ -2570,7 +2544,7 @@ stream_error_cb (GabbleMediaStream *stream,
* Talk-using peer.)
*/
DEBUG ("Terminating call in response to stream error");
- gabble_jingle_session_terminate (priv->session,
+ wocky_jingle_session_terminate (priv->session,
media_stream_error_to_jingle_reason (errno), message, NULL);
}
@@ -2620,7 +2594,7 @@ stream_direction_changed_cb (GabbleMediaStream *stream,
static void
construct_stream (GabbleMediaChannel *chan,
- GabbleJingleContent *c,
+ WockyJingleContent *c,
const gchar *name,
const gchar *nat_traversal,
const GPtrArray *relays,
@@ -2713,7 +2687,7 @@ construct_stream (GabbleMediaChannel *chan,
stream_direction_changed_cb (stream, NULL, chan);
gabble_media_channel_hold_new_stream (chan, stream,
- GABBLE_JINGLE_MEDIA_RTP (c));
+ WOCKY_JINGLE_MEDIA_RTP (c));
if (priv->ready)
{
@@ -2789,7 +2763,7 @@ google_relay_session_cb (GPtrArray *relays,
}
static void
-content_removed_cb (GabbleJingleContent *content,
+content_removed_cb (WockyJingleContent *content,
StreamCreationData *d)
{
@@ -2829,7 +2803,7 @@ content_removed_cb (GabbleJingleContent *content,
static void
create_stream_from_content (GabbleMediaChannel *self,
- GabbleJingleContent *c,
+ WockyJingleContent *c,
gboolean initial)
{
gchar *name;
@@ -2839,7 +2813,7 @@ create_stream_from_content (GabbleMediaChannel *self,
"name", &name,
NULL);
- if (G_OBJECT_TYPE (c) != GABBLE_TYPE_JINGLE_MEDIA_RTP)
+ if (G_OBJECT_TYPE (c) != WOCKY_TYPE_JINGLE_MEDIA_RTP)
{
DEBUG ("ignoring non MediaRtp content '%s'", name);
g_free (name);
@@ -2864,7 +2838,7 @@ create_stream_from_content (GabbleMediaChannel *self,
self->priv->stream_creation_datas = g_list_prepend (
self->priv->stream_creation_datas, d);
- switch (gabble_jingle_content_get_transport_type (c))
+ switch (wocky_jingle_content_get_transport_type (c))
{
case JINGLE_TRANSPORT_GOOGLE_P2P:
/* See if our server is Google, and if it is, ask them for a relay.
@@ -2872,7 +2846,7 @@ create_stream_from_content (GabbleMediaChannel *self,
* don't yet know whether there will be RTCP. */
d->nat_traversal = "gtalk-p2p";
DEBUG ("Attempting to create Google relay session");
- gabble_jingle_info_create_google_relay_session (
+ wocky_jingle_info_create_google_relay_session (
gabble_jingle_mint_get_info (self->priv->conn->jingle_mint),
2, google_relay_session_cb, d);
return;
@@ -2892,8 +2866,8 @@ create_stream_from_content (GabbleMediaChannel *self,
}
static void
-session_content_rejected_cb (GabbleJingleSession *session,
- GabbleJingleContent *c, JingleReason reason, const gchar *message,
+session_content_rejected_cb (WockyJingleSession *session,
+ WockyJingleContent *c, WockyJingleReason reason, const gchar *message,
gpointer user_data)
{
GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (user_data);
@@ -2916,8 +2890,8 @@ session_content_rejected_cb (GabbleJingleSession *session,
}
static void
-session_new_content_cb (GabbleJingleSession *session,
- GabbleJingleContent *c, gpointer user_data)
+session_new_content_cb (WockyJingleSession *session,
+ WockyJingleContent *c, gpointer user_data)
{
GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (user_data);
@@ -2966,7 +2940,7 @@ gabble_media_channel_ready (TpSvcMediaSessionHandler *iface,
* error message describes the only legitimate situation in which this
* could arise.
*/
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE, "call has already ended" };
+ GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "call has already ended" };
DEBUG ("no session, returning an error.");
dbus_g_method_return_error (context, &e);
@@ -2998,7 +2972,7 @@ gabble_media_channel_error (TpSvcMediaSessionHandler *iface,
GabbleMediaChannelPrivate *priv;
GPtrArray *tmp;
guint i;
- JingleState state;
+ WockyJingleState state;
g_assert (GABBLE_IS_MEDIA_CHANNEL (self));
@@ -3013,7 +2987,7 @@ gabble_media_channel_error (TpSvcMediaSessionHandler *iface,
* error message describes the only legitimate situation in which this
* could arise.
*/
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE, "call has already ended" };
+ GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "call has already ended" };
DEBUG ("no session, returning an error.");
dbus_g_method_return_error (context, &e);
@@ -3025,16 +2999,16 @@ gabble_media_channel_error (TpSvcMediaSessionHandler *iface,
g_object_get (priv->session, "state", &state, NULL);
- if (state == JINGLE_STATE_ENDED)
+ if (state == WOCKY_JINGLE_STATE_ENDED)
{
tp_svc_media_session_handler_return_from_error (context);
return;
}
- else if (state == JINGLE_STATE_PENDING_CREATED)
+ else if (state == WOCKY_JINGLE_STATE_PENDING_CREATED)
{
/* shortcut to prevent sending remove actions if we haven't sent an
* initiate yet */
- g_object_set (self, "state", JINGLE_STATE_ENDED, NULL);
+ g_object_set (self, "state", WOCKY_JINGLE_STATE_ENDED, NULL);
tp_svc_media_session_handler_return_from_error (context);
return;
}
diff --git a/src/media-channel.h b/src/media-channel.h
index b10886ca2..cbe488af2 100644
--- a/src/media-channel.h
+++ b/src/media-channel.h
@@ -23,8 +23,7 @@
#include <glib-object.h>
-#include <telepathy-glib/dbus-properties-mixin.h>
-#include <telepathy-glib/group-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <telepathy-glib/properties-mixin.h>
#include "presence.h"
diff --git a/src/media-factory.c b/src/media-factory.c
index 8f3e39761..85e4a1c46 100644
--- a/src/media-factory.c
+++ b/src/media-factory.c
@@ -25,18 +25,17 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+
+#include <wocky/wocky.h>
#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
#include "gabble/caps-channel-manager.h"
#include "connection.h"
#include "debug.h"
-#include "jingle-factory.h"
-#include "jingle-media-rtp.h"
-#include "jingle-session.h"
#include "call-channel.h"
#include "media-channel.h"
@@ -261,7 +260,7 @@ media_channel_closed_cb (GabbleMediaChannel *chan, gpointer user_data)
*/
static GabbleMediaChannel *
new_media_channel (GabbleMediaFactory *fac,
- GabbleJingleSession *sess,
+ WockyJingleSession *sess,
TpHandle maybe_peer,
gboolean peer_in_rp,
gboolean initial_audio,
@@ -278,7 +277,7 @@ new_media_channel (GabbleMediaFactory *fac,
conn = (TpBaseConnection *) priv->conn;
object_path = g_strdup_printf ("%s/MediaChannel%u",
- conn->object_path, priv->channel_index);
+ tp_base_connection_get_object_path (conn), priv->channel_index);
priv->channel_index += 1;
chan = g_object_new (GABBLE_TYPE_MEDIA_CHANNEL,
@@ -360,7 +359,7 @@ call_channel_initialized (GObject *source,
*/
static void
new_call_channel (GabbleMediaFactory *self,
- GabbleJingleSession *sess,
+ WockyJingleSession *sess,
TpHandle peer,
gboolean initial_audio,
const gchar *initial_audio_name,
@@ -377,10 +376,10 @@ new_call_channel (GabbleMediaFactory *self,
if (sess != NULL)
initiator = peer;
else
- initiator = conn->self_handle;
+ initiator = tp_base_connection_get_self_handle (conn);
object_path = g_strdup_printf ("%s/CallChannel%u",
- conn->object_path, self->priv->channel_index);
+ tp_base_connection_get_object_path (conn), self->priv->channel_index);
self->priv->channel_index++;
channel = g_object_new (GABBLE_TYPE_CALL_CHANNEL,
@@ -442,7 +441,7 @@ gabble_media_factory_close_all (GabbleMediaFactory *fac)
static void
new_jingle_session_cb (GabbleJingleMint *jm,
- GabbleJingleSession *sess,
+ WockyJingleSession *sess,
gpointer data)
{
GabbleMediaFactory *self = GABBLE_MEDIA_FACTORY (data);
@@ -450,8 +449,8 @@ new_jingle_session_cb (GabbleJingleMint *jm,
TpHandleRepoIface *contacts;
TpHandle peer;
- if (gabble_jingle_session_get_content_type (sess) !=
- GABBLE_TYPE_JINGLE_MEDIA_RTP)
+ if (wocky_jingle_session_get_content_type (sess) !=
+ WOCKY_TYPE_JINGLE_MEDIA_RTP)
return;
if (gabble_muc_factory_handle_jingle_session (priv->conn->muc_factory, sess))
@@ -462,7 +461,7 @@ new_jingle_session_cb (GabbleJingleMint *jm,
contacts = tp_base_connection_get_handles (TP_BASE_CONNECTION (priv->conn),
TP_HANDLE_TYPE_CONTACT);
- peer = tp_handle_ensure (contacts, gabble_jingle_session_get_peer_jid (sess),
+ peer = tp_handle_ensure (contacts, wocky_jingle_session_get_peer_jid (sess),
NULL, NULL);
if (self->priv->use_call_channels)
@@ -481,11 +480,11 @@ new_jingle_session_cb (GabbleJingleMint *jm,
/* FIXME: we need this detection to properly adjust nat-traversal on
* the channel. We hope all contents will have the same transport... */
- cs = gabble_jingle_session_get_contents (sess);
+ cs = wocky_jingle_session_get_contents (sess);
if (cs != NULL)
{
- GabbleJingleContent *c = cs->data;
+ WockyJingleContent *c = cs->data;
gchar *ns;
g_object_get (c, "transport-ns", &ns, NULL);
@@ -776,7 +775,7 @@ gabble_media_factory_requestotron (TpChannelManager *manager,
if (require_target_handle)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"A valid Contact handle must be provided when requesting a media "
"channel");
goto error;
@@ -918,7 +917,7 @@ gabble_media_factory_create_call (TpChannelManager *manager,
if (!initial_audio && !initial_video)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Call channel must contain at least "
"one of InitialAudio or InitialVideo");
goto error;
diff --git a/src/media-stream.c b/src/media-stream.c
index 75c9ea38f..426aa8a20 100644
--- a/src/media-stream.c
+++ b/src/media-stream.c
@@ -27,23 +27,15 @@
#include <string.h>
#include <dbus/dbus-glib.h>
-#include <telepathy-glib/debug-ansi.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-media-interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
#include "connection.h"
#include "debug.h"
#include "gabble-signals-marshal.h"
-#include "jingle-content.h"
-#include "jingle-session.h"
-#include "jingle-media-rtp.h"
#include "media-channel.h"
#include "namespaces.h"
#include "util.h"
@@ -95,9 +87,8 @@ enum
struct _GabbleMediaStreamPrivate
{
- GabbleJingleContent *content;
+ WockyJingleContent *content;
- GabbleMediaSessionMode mode;
TpDBusDaemon *dbus_daemon;
gchar *object_path;
guint id;
@@ -145,26 +136,26 @@ static void push_remote_candidates (GabbleMediaStream *stream);
static void push_playing (GabbleMediaStream *stream);
static void push_sending (GabbleMediaStream *stream);
-static void new_remote_candidates_cb (GabbleJingleContent *content,
+static void new_remote_candidates_cb (WockyJingleContent *content,
GList *clist, GabbleMediaStream *stream);
-static void new_remote_media_description_cb (GabbleJingleContent *content,
- JingleMediaDescription *md, GabbleMediaStream *stream);
-static void content_state_changed_cb (GabbleJingleContent *c,
+static void new_remote_media_description_cb (WockyJingleContent *content,
+ WockyJingleMediaDescription *md, GabbleMediaStream *stream);
+static void content_state_changed_cb (WockyJingleContent *c,
GParamSpec *pspec, GabbleMediaStream *stream);
-static void content_senders_changed_cb (GabbleJingleContent *c,
+static void content_senders_changed_cb (WockyJingleContent *c,
GParamSpec *pspec, GabbleMediaStream *stream);
-static void remote_state_changed_cb (GabbleJingleSession *session,
+static void remote_state_changed_cb (WockyJingleSession *session,
GabbleMediaStream *stream);
-static void content_removed_cb (GabbleJingleContent *content,
+static void content_removed_cb (WockyJingleContent *content,
GabbleMediaStream *stream);
-static void update_direction (GabbleMediaStream *stream, GabbleJingleContent *c);
+static void update_direction (GabbleMediaStream *stream, WockyJingleContent *c);
static void update_sending (GabbleMediaStream *stream, gboolean start_sending);
GabbleMediaStream *
gabble_media_stream_new (
TpDBusDaemon *dbus_daemon,
const gchar *object_path,
- GabbleJingleContent *content,
+ WockyJingleContent *content,
const gchar *name,
guint id,
const gchar *nat_traversal,
@@ -174,7 +165,7 @@ gabble_media_stream_new (
GPtrArray *empty = NULL;
GabbleMediaStream *result;
- g_return_val_if_fail (GABBLE_IS_JINGLE_MEDIA_RTP (content), NULL);
+ g_return_val_if_fail (WOCKY_IS_JINGLE_MEDIA_RTP (content), NULL);
if (relay_info == NULL)
{
@@ -246,13 +237,13 @@ _get_initial_codecs_and_candidates (gpointer user_data)
{
GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (user_data);
GabbleMediaStreamPrivate *priv = stream->priv;
- JingleMediaDescription *md;
+ WockyJingleMediaDescription *md;
priv->initial_getter_id = 0;
/* we can immediately get the codecs if we're responder */
- md = gabble_jingle_media_rtp_get_remote_media_description (
- GABBLE_JINGLE_MEDIA_RTP (priv->content));
+ md = wocky_jingle_media_rtp_get_remote_media_description (
+ WOCKY_JINGLE_MEDIA_RTP (priv->content));
if (md != NULL)
new_remote_media_description_cb (priv->content, md, stream);
@@ -260,7 +251,7 @@ _get_initial_codecs_and_candidates (gpointer user_data)
* us (e.g. specified in session-initiate/content-add), we don't want to
* miss them */
new_remote_candidates_cb (priv->content,
- gabble_jingle_content_get_remote_candidates (priv->content), stream);
+ wocky_jingle_content_get_remote_candidates (priv->content), stream);
return FALSE;
}
@@ -272,9 +263,8 @@ gabble_media_stream_constructor (GType type, guint n_props,
GObject *obj;
GabbleMediaStream *stream;
GabbleMediaStreamPrivate *priv;
- GabbleJingleFactory *jf;
- gchar *stun_server;
- guint stun_port;
+ WockyJingleFactory *jf;
+ GList *stun_servers;
/* call base class constructor */
obj = G_OBJECT_CLASS (gabble_media_stream_parent_class)->
@@ -287,22 +277,20 @@ gabble_media_stream_constructor (GType type, guint n_props,
/* STUN servers are needed as soon as the stream appears, so there's little
* point in waiting for them - either they've already been resolved, or
* we're too late to use them for this stream */
- jf = gabble_jingle_session_get_factory (priv->content->session);
-
- /* maybe one day we'll support multiple STUN servers */
- if (gabble_jingle_info_get_stun_server (
- gabble_jingle_factory_get_jingle_info (jf),
- &stun_server, &stun_port))
+ jf = wocky_jingle_session_get_factory (priv->content->session);
+ stun_servers = wocky_jingle_info_get_stun_servers (
+ wocky_jingle_factory_get_jingle_info (jf));
+ while (stun_servers != NULL)
{
- GValueArray *va = g_value_array_new (2);
-
- g_value_array_append (va, NULL);
- g_value_array_append (va, NULL);
- g_value_init (va->values + 0, G_TYPE_STRING);
- g_value_init (va->values + 1, G_TYPE_UINT);
- g_value_take_string (va->values + 0, stun_server);
- g_value_set_uint (va->values + 1, stun_port);
+ WockyStunServer *stun_server = stun_servers->data;
+ GValueArray *va = tp_value_array_build (2,
+ G_TYPE_STRING, stun_server->address,
+ G_TYPE_UINT, (guint) stun_server->port,
+ G_TYPE_INVALID);
+
g_ptr_array_add (priv->stun_servers, va);
+
+ stun_servers = g_list_delete_link (stun_servers, stun_servers);
}
/* go for the bus */
@@ -311,7 +299,7 @@ gabble_media_stream_constructor (GType type, guint n_props,
update_direction (stream, priv->content);
- /* MediaStream is created as soon as GabbleJingleContent is
+ /* MediaStream is created as soon as WockyJingleContent is
* created, but we want to let it parse the initiation (if
* initiated by remote end) before we pick up initial
* codecs and candidates.
@@ -455,7 +443,7 @@ gabble_media_stream_set_property (GObject *object,
"locally-created", &locally_created,
NULL);
- if (jtype == JINGLE_MEDIA_TYPE_VIDEO)
+ if (jtype == WOCKY_JINGLE_MEDIA_TYPE_VIDEO)
priv->media_type = TP_MEDIA_STREAM_TYPE_VIDEO;
else
priv->media_type = TP_MEDIA_STREAM_TYPE_AUDIO;
@@ -630,9 +618,9 @@ gabble_media_stream_class_init (GabbleMediaStreamClass *gabble_media_stream_clas
G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK);
g_object_class_install_property (object_class, PROP_LOCAL_HOLD, param_spec);
- param_spec = g_param_spec_object ("content", "GabbleJingleContent object",
+ param_spec = g_param_spec_object ("content", "WockyJingleContent object",
"Jingle content signalling this media stream.",
- GABBLE_TYPE_JINGLE_CONTENT,
+ WOCKY_TYPE_JINGLE_CONTENT,
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE |
G_PARAM_STATIC_NICK |
@@ -910,7 +898,7 @@ gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
{
GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
GabbleMediaStreamPrivate *priv;
- JingleState state;
+ WockyJingleState state;
GList *li = NULL;
guint i;
@@ -922,9 +910,9 @@ gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
/* FIXME: maybe this should be an assertion in case the channel
* isn't closed early enough right now? */
- if (state > JINGLE_STATE_ACTIVE)
+ if (state > WOCKY_JINGLE_STATE_ACTIVE)
{
- DEBUG ("state > JINGLE_STATE_ACTIVE, doing nothing");
+ DEBUG ("state > WOCKY_JINGLE_STATE_ACTIVE, doing nothing");
tp_svc_media_stream_handler_return_from_new_native_candidate (context);
return;
}
@@ -934,7 +922,7 @@ gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
GValueArray *transport;
guint component;
const gchar *addr;
- JingleCandidate *c;
+ WockyJingleCandidate *c;
transport = g_ptr_array_index (transports, i);
component = g_value_get_uint (g_value_array_get_nth (transport, 0));
@@ -954,7 +942,7 @@ gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
continue;
}
- c = jingle_candidate_new (
+ c = wocky_jingle_candidate_new (
/* protocol */
g_value_get_uint (g_value_array_get_nth (transport, 3)),
/* candidate type, we're relying on 1:1 candidate type mapping */
@@ -982,7 +970,7 @@ gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
}
if (li != NULL)
- gabble_jingle_content_add_candidates (priv->content, li);
+ wocky_jingle_content_add_candidates (priv->content, li);
tp_svc_media_stream_handler_return_from_new_native_candidate (context);
}
@@ -1043,7 +1031,7 @@ pass_local_codecs (GabbleMediaStream *stream,
{
GabbleMediaStreamPrivate *priv = stream->priv;
guint i;
- JingleMediaDescription *md;
+ WockyJingleMediaDescription *md;
const GPtrArray *hdrexts;
GHashTable *fbs;
GError *wocky_error = NULL;
@@ -1051,7 +1039,7 @@ pass_local_codecs (GabbleMediaStream *stream,
DEBUG ("putting list of %d supported codecs from stream-engine into cache",
codecs->len);
- md = jingle_media_description_new ();
+ md = wocky_jingle_media_description_new ();
fbs = g_value_get_boxed (&priv->local_feedback_messages);
@@ -1063,7 +1051,7 @@ pass_local_codecs (GabbleMediaStream *stream,
guint id, clock_rate, channels;
gchar *name;
GHashTable *params;
- JingleCodec *c;
+ WockyJingleCodec *c;
GValueArray *fb_codec;
g_value_init (&codec, codec_struct_type);
@@ -1113,7 +1101,7 @@ pass_local_codecs (GabbleMediaStream *stream,
subtype = g_value_get_string (val);
c->feedback_msgs = g_list_append (c->feedback_msgs,
- jingle_feedback_message_new (type, subtype));
+ wocky_jingle_feedback_message_new (type, subtype));
}
}
}
@@ -1139,7 +1127,7 @@ pass_local_codecs (GabbleMediaStream *stream,
GValueArray *hdrext;
guint id;
guint direction;
- JingleContentSenders senders;
+ WockyJingleContentSenders senders;
gchar *uri;
gchar *params;
@@ -1168,37 +1156,37 @@ pass_local_codecs (GabbleMediaStream *stream,
switch (direction)
{
case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL:
- senders = JINGLE_CONTENT_SENDERS_BOTH;
+ senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH;
break;
case TP_MEDIA_STREAM_DIRECTION_NONE:
- senders = JINGLE_CONTENT_SENDERS_NONE;
+ senders = WOCKY_JINGLE_CONTENT_SENDERS_NONE;
break;
case TP_MEDIA_STREAM_DIRECTION_SEND:
- senders = initiated_by_us ? JINGLE_CONTENT_SENDERS_INITIATOR :
- JINGLE_CONTENT_SENDERS_RESPONDER;
+ senders = initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR :
+ WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER;
break;
case TP_MEDIA_STREAM_DIRECTION_RECEIVE:
- senders = initiated_by_us ? JINGLE_CONTENT_SENDERS_RESPONDER :
- JINGLE_CONTENT_SENDERS_INITIATOR;
+ senders = initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER :
+ WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR;
break;
default:
g_assert_not_reached ();
}
md->hdrexts = g_list_append (md->hdrexts,
- jingle_rtp_header_extension_new (id, senders, uri));
+ wocky_jingle_rtp_header_extension_new (id, senders, uri));
}
/* Can only be used once */
g_value_reset (&priv->local_rtp_hdrexts);
}
- jingle_media_description_simplify (md);
+ wocky_jingle_media_description_simplify (md);
if (jingle_media_rtp_set_local_media_description (
- GABBLE_JINGLE_MEDIA_RTP (priv->content), md, ready, &wocky_error))
+ WOCKY_JINGLE_MEDIA_RTP (priv->content), md, ready, &wocky_error))
return TRUE;
- g_set_error_literal (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error_literal (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
wocky_error->message);
g_clear_error (&wocky_error);
return FALSE;
@@ -1226,7 +1214,7 @@ gabble_media_stream_set_local_codecs (TpSvcMediaStreamHandler *iface,
priv->local_codecs_set = TRUE;
- if (gabble_jingle_content_is_created_by_us (self->priv->content))
+ if (wocky_jingle_content_is_created_by_us (self->priv->content))
{
if (!pass_local_codecs (self, codecs, self->priv->created_locally,
&error))
@@ -1260,17 +1248,17 @@ gabble_media_stream_stream_state (TpSvcMediaStreamHandler *iface,
{
GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface);
GabbleMediaStreamPrivate *priv = self->priv;
- JingleTransportState ts = JINGLE_TRANSPORT_STATE_DISCONNECTED;
+ WockyJingleTransportState ts = WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED;
switch (connection_state) {
case TP_MEDIA_STREAM_STATE_DISCONNECTED:
- ts = JINGLE_TRANSPORT_STATE_DISCONNECTED;
+ ts = WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED;
break;
case TP_MEDIA_STREAM_STATE_CONNECTING:
- ts = JINGLE_TRANSPORT_STATE_CONNECTING;
+ ts = WOCKY_JINGLE_TRANSPORT_STATE_CONNECTING;
break;
case TP_MEDIA_STREAM_STATE_CONNECTED:
- ts = JINGLE_TRANSPORT_STATE_CONNECTED;
+ ts = WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED;
break;
default:
DEBUG ("ignoring unknown connection state %u", connection_state);
@@ -1278,7 +1266,7 @@ gabble_media_stream_stream_state (TpSvcMediaStreamHandler *iface,
}
g_object_set (self, "connection-state", connection_state, NULL);
- gabble_jingle_content_set_transport_state (priv->content, ts);
+ wocky_jingle_content_set_transport_state (priv->content, ts);
OUT:
tp_svc_media_stream_handler_return_from_stream_state (context);
@@ -1304,7 +1292,7 @@ gabble_media_stream_supported_codecs (TpSvcMediaStreamHandler *iface,
if (codecs->len == 0)
{
- GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ GError e = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"SupportedCodecs must have a non-empty list of codecs" };
dbus_g_method_return_error (context, &e);
@@ -1357,7 +1345,7 @@ gabble_media_stream_codecs_updated (TpSvcMediaStreamHandler *iface,
if (!self->priv->local_codecs_set)
{
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"CodecsUpdated may only be called once an initial set of codecs "
"has been set" };
@@ -1440,7 +1428,7 @@ gabble_media_stream_close (GabbleMediaStream *stream)
}
static void
-insert_feedback_message (JingleFeedbackMessage *fb, GPtrArray *fb_msgs)
+insert_feedback_message (WockyJingleFeedbackMessage *fb, GPtrArray *fb_msgs)
{
GValueArray *msg;
@@ -1454,8 +1442,8 @@ insert_feedback_message (JingleFeedbackMessage *fb, GPtrArray *fb_msgs)
}
static void
-new_remote_media_description_cb (GabbleJingleContent *content,
- JingleMediaDescription *md, GabbleMediaStream *stream)
+new_remote_media_description_cb (WockyJingleContent *content,
+ WockyJingleMediaDescription *md, GabbleMediaStream *stream)
{
GabbleMediaStreamPrivate *priv;
GList *li;
@@ -1514,7 +1502,7 @@ new_remote_media_description_cb (GabbleJingleContent *content,
for (li = md->codecs; li; li = li->next)
{
GValue codec = { 0, };
- JingleCodec *c = li->data;
+ WockyJingleCodec *c = li->data;
g_value_init (&codec, codec_struct_type);
g_value_take_boxed (&codec,
@@ -1565,7 +1553,7 @@ new_remote_media_description_cb (GabbleJingleContent *content,
for (li = md->hdrexts; li; li = li->next)
{
- JingleRtpHeaderExtension *h = li->data;
+ WockyJingleRtpHeaderExtension *h = li->data;
TpMediaStreamDirection direction;
if (!have_initiator)
@@ -1577,17 +1565,17 @@ new_remote_media_description_cb (GabbleJingleContent *content,
switch (h->senders)
{
- case JINGLE_CONTENT_SENDERS_BOTH:
+ case WOCKY_JINGLE_CONTENT_SENDERS_BOTH:
direction = TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
break;
- case JINGLE_CONTENT_SENDERS_NONE:
+ case WOCKY_JINGLE_CONTENT_SENDERS_NONE:
direction = TP_MEDIA_STREAM_DIRECTION_NONE;
break;
- case JINGLE_CONTENT_SENDERS_INITIATOR:
+ case WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR:
direction = initiated_by_us ? TP_MEDIA_STREAM_DIRECTION_SEND :
TP_MEDIA_STREAM_DIRECTION_RECEIVE;
break;
- case JINGLE_CONTENT_SENDERS_RESPONDER:
+ case WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER:
direction = initiated_by_us ? TP_MEDIA_STREAM_DIRECTION_RECEIVE :
TP_MEDIA_STREAM_DIRECTION_SEND;
break;
@@ -1645,7 +1633,7 @@ push_remote_media_description (GabbleMediaStream *stream)
}
static void
-new_remote_candidates_cb (GabbleJingleContent *content,
+new_remote_candidates_cb (WockyJingleContent *content,
GList *clist, GabbleMediaStream *stream)
{
GabbleMediaStreamPrivate *priv = stream->priv;
@@ -1662,7 +1650,7 @@ new_remote_candidates_cb (GabbleJingleContent *content,
GValue candidate = { 0, };
GPtrArray *transports;
GValue transport = { 0, };
- JingleCandidate *c = li->data;
+ WockyJingleCandidate *c = li->data;
GType transport_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT;
GType candidate_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE;
@@ -1674,7 +1662,7 @@ new_remote_candidates_cb (GabbleJingleContent *content,
0, c->component,
1, c->address,
2, c->port,
- 3, c->protocol == JINGLE_TRANSPORT_PROTOCOL_UDP ? 0 : 1,
+ 3, c->protocol == WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP ? 0 : 1,
4, "RTP",
5, "AVP",
6, (gdouble) (c->preference / 65536.0),
@@ -1712,19 +1700,19 @@ new_remote_candidates_cb (GabbleJingleContent *content,
}
static void
-content_state_changed_cb (GabbleJingleContent *c,
+content_state_changed_cb (WockyJingleContent *c,
GParamSpec *pspec,
GabbleMediaStream *stream)
{
GabbleMediaStreamPrivate *priv = stream->priv;
- JingleContentState state;
+ WockyJingleContentState state;
g_object_get (c, "state", &state, NULL);
DEBUG ("called");
switch (state) {
- case JINGLE_CONTENT_STATE_ACKNOWLEDGED:
+ case WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED:
/* connected stream means we can play, but sending is determined
* by content senders (in update_senders) */
stream->playing = TRUE;
@@ -1732,7 +1720,7 @@ content_state_changed_cb (GabbleJingleContent *c,
push_playing (stream);
push_sending (stream);
break;
- case JINGLE_CONTENT_STATE_REMOVING:
+ case WOCKY_JINGLE_CONTENT_STATE_REMOVING:
stream->playing = FALSE;
priv->sending = FALSE;
push_playing (stream);
@@ -1824,12 +1812,12 @@ push_sending (GabbleMediaStream *stream)
}
static void
-update_direction (GabbleMediaStream *stream, GabbleJingleContent *c)
+update_direction (GabbleMediaStream *stream, WockyJingleContent *c)
{
CombinedStreamDirection new_combined_dir;
TpMediaStreamDirection requested_dir, current_dir;
TpMediaStreamPendingSend pending_send;
- JingleContentSenders senders;
+ WockyJingleContentSenders senders;
gboolean local_initiator;
DEBUG ("called");
@@ -1838,15 +1826,15 @@ update_direction (GabbleMediaStream *stream, GabbleJingleContent *c)
g_object_get (c->session, "local-initiator", &local_initiator, NULL);
switch (senders) {
- case JINGLE_CONTENT_SENDERS_INITIATOR:
+ case WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR:
requested_dir = local_initiator ?
TP_MEDIA_STREAM_DIRECTION_SEND : TP_MEDIA_STREAM_DIRECTION_RECEIVE;
break;
- case JINGLE_CONTENT_SENDERS_RESPONDER:
+ case WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER:
requested_dir = local_initiator ?
TP_MEDIA_STREAM_DIRECTION_RECEIVE : TP_MEDIA_STREAM_DIRECTION_SEND;
break;
- case JINGLE_CONTENT_SENDERS_BOTH:
+ case WOCKY_JINGLE_CONTENT_SENDERS_BOTH:
requested_dir = TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
break;
default:
@@ -1878,7 +1866,7 @@ update_direction (GabbleMediaStream *stream, GabbleJingleContent *c)
}
static void
-content_senders_changed_cb (GabbleJingleContent *c,
+content_senders_changed_cb (WockyJingleContent *c,
GParamSpec *pspec,
GabbleMediaStream *stream)
{
@@ -1886,20 +1874,20 @@ content_senders_changed_cb (GabbleJingleContent *c,
}
static void
-remote_state_changed_cb (GabbleJingleSession *session,
+remote_state_changed_cb (WockyJingleSession *session,
GabbleMediaStream *stream)
{
GabbleMediaStreamPrivate *priv = stream->priv;
gboolean old_hold = priv->on_hold;
- priv->on_hold = gabble_jingle_session_get_remote_hold (session);
+ priv->on_hold = wocky_jingle_session_get_remote_hold (session);
if (old_hold != priv->on_hold)
push_sending (stream);
}
static void
-content_removed_cb (GabbleJingleContent *content, GabbleMediaStream *stream)
+content_removed_cb (WockyJingleContent *content, GabbleMediaStream *stream)
{
gabble_media_stream_close (stream);
}
@@ -1913,7 +1901,7 @@ gabble_media_stream_change_direction (GabbleMediaStream *stream,
CombinedStreamDirection new_combined_dir;
TpMediaStreamDirection current_dir;
TpMediaStreamPendingSend pending_send;
- JingleContentSenders senders;
+ WockyJingleContentSenders senders;
gboolean local_initiator;
current_dir = COMBINED_DIRECTION_GET_DIRECTION (stream->combined_direction);
@@ -1935,7 +1923,7 @@ gabble_media_stream_change_direction (GabbleMediaStream *stream,
new_combined_dir = MAKE_COMBINED_DIRECTION (requested_dir, pending_send);
if (new_combined_dir != stream->combined_direction)
{
- JingleContentState state;
+ WockyJingleContentState state;
gboolean start_sending;
g_object_set (stream, "combined-direction", new_combined_dir, NULL);
@@ -1946,7 +1934,7 @@ gabble_media_stream_change_direction (GabbleMediaStream *stream,
* This appears to be the meaning of Acknowledged. :-)
*/
g_object_get (stream->priv->content, "state", &state, NULL);
- start_sending = (state == JINGLE_CONTENT_STATE_ACKNOWLEDGED);
+ start_sending = (state == WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED);
update_sending (stream, start_sending);
}
@@ -1963,25 +1951,25 @@ gabble_media_stream_change_direction (GabbleMediaStream *stream,
{
case TP_MEDIA_STREAM_DIRECTION_SEND:
senders = local_initiator ?
- JINGLE_CONTENT_SENDERS_INITIATOR : JINGLE_CONTENT_SENDERS_RESPONDER;
+ WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR : WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER;
break;
case TP_MEDIA_STREAM_DIRECTION_RECEIVE:
senders = local_initiator ?
- JINGLE_CONTENT_SENDERS_RESPONDER : JINGLE_CONTENT_SENDERS_INITIATOR;
+ WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER : WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR;
break;
case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL:
- senders = JINGLE_CONTENT_SENDERS_BOTH;
+ senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH;
break;
default:
g_assert_not_reached ();
}
- if (!gabble_jingle_content_change_direction (priv->content, senders))
+ if (!wocky_jingle_content_change_direction (priv->content, senders))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"stream direction invalid for the Jingle dialect in use");
return FALSE;
}
@@ -2056,13 +2044,13 @@ stream_handler_iface_init (gpointer g_iface, gpointer iface_data)
#undef IMPLEMENT
}
-GabbleJingleMediaRtp *
+WockyJingleMediaRtp *
gabble_media_stream_get_content (GabbleMediaStream *self)
{
/* FIXME: we should fix this whole class up. It relies throughout on
- * self->priv->content actually secretly being a GabbleJingleMediaRtp.
+ * self->priv->content actually secretly being a WockyJingleMediaRtp.
*/
- return GABBLE_JINGLE_MEDIA_RTP (self->priv->content);
+ return WOCKY_JINGLE_MEDIA_RTP (self->priv->content);
}
void
diff --git a/src/media-stream.h b/src/media-stream.h
index c8c50929a..2174f52df 100644
--- a/src/media-stream.h
+++ b/src/media-stream.h
@@ -22,12 +22,8 @@
#define __GABBLE_MEDIA_STREAM_H__
#include <glib-object.h>
-
-#include "jingle-types.h"
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/dtmf.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/dbus-properties-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <wocky/wocky.h>
G_BEGIN_DECLS
@@ -102,7 +98,7 @@ void gabble_media_stream_accept_pending_local_send (GabbleMediaStream *stream);
GabbleMediaStream *gabble_media_stream_new (
TpDBusDaemon *dbus_daemon,
const gchar *object_path,
- GabbleJingleContent *content,
+ WockyJingleContent *content,
const gchar *name,
guint id,
const gchar *nat_traversal,
@@ -113,7 +109,7 @@ TpMediaStreamType gabble_media_stream_get_media_type (GabbleMediaStream *self);
void gabble_media_stream_add_dtmf_player (GabbleMediaStream *self,
TpDTMFPlayer *dtmf_player);
-GabbleJingleMediaRtp *gabble_media_stream_get_content (GabbleMediaStream *self);
+WockyJingleMediaRtp *gabble_media_stream_get_content (GabbleMediaStream *self);
void gabble_media_stream_start_telephony_event (GabbleMediaStream *self, guchar event);
void gabble_media_stream_stop_telephony_event (GabbleMediaStream *self);
diff --git a/src/message-util.c b/src/message-util.c
index 5001be307..01bb71735 100644
--- a/src/message-util.c
+++ b/src/message-util.c
@@ -23,12 +23,13 @@
*/
#include "config.h"
+
#include "message-util.h"
#include <string.h>
#include <time.h>
-#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
#define DEBUG_FLAG GABBLE_DEBUG_IM
@@ -41,30 +42,31 @@ void
gabble_message_util_add_chat_state (WockyStanza *stanza,
TpChannelChatState state)
{
- WockyNode *node = NULL;
WockyNode *n = wocky_stanza_get_top_node (stanza);
+ const gchar *node_name = NULL;
switch (state)
{
case TP_CHANNEL_CHAT_STATE_GONE:
- node = wocky_node_add_child_with_content (n, "gone", NULL);
+ node_name = "gone";
break;
case TP_CHANNEL_CHAT_STATE_INACTIVE:
- node = wocky_node_add_child_with_content (n, "inactive", NULL);
+ node_name = "inactive";
break;
case TP_CHANNEL_CHAT_STATE_ACTIVE:
- node = wocky_node_add_child_with_content (n, "active", NULL);
+ node_name = "active";
break;
case TP_CHANNEL_CHAT_STATE_PAUSED:
- node = wocky_node_add_child_with_content (n, "paused", NULL);
+ node_name = "paused";
break;
case TP_CHANNEL_CHAT_STATE_COMPOSING:
- node = wocky_node_add_child_with_content (n, "composing", NULL);
+ node_name = "composing";
break;
}
- if (node != NULL)
- node->ns = g_quark_from_static_string (NS_CHAT_STATES);
+ if (node_name != NULL)
+ wocky_node_add_child_ns_q (n, node_name,
+ g_quark_from_static_string (NS_CHAT_STATES));
}
/**
@@ -103,7 +105,7 @@ gabble_message_util_build_stanza (TpMessage *message,
#define RETURN_INVALID_ARGUMENT(msg, ...) \
G_STMT_START { \
DEBUG (msg , ## __VA_ARGS__); \
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, \
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, \
msg , ## __VA_ARGS__); \
return NULL; \
} G_STMT_END
@@ -239,6 +241,7 @@ gabble_tp_send_error_from_wocky_xmpp_error (WockyXmppError err)
case WOCKY_XMPP_ERROR_FORBIDDEN:
case WOCKY_XMPP_ERROR_NOT_AUTHORIZED:
+ case WOCKY_XMPP_ERROR_POLICY_VIOLATION:
return TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED;
case WOCKY_XMPP_ERROR_RESOURCE_CONSTRAINT:
diff --git a/src/message-util.h b/src/message-util.h
index 80853c890..404d431bc 100644
--- a/src/message-util.h
+++ b/src/message-util.h
@@ -21,7 +21,7 @@
#ifndef __GABBLE_MESSAGE_UTIL_H__
#define __GABBLE_MESSAGE_UTIL_H__
-#include <telepathy-glib/message-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
#include <wocky/wocky.h>
diff --git a/src/muc-channel.c b/src/muc-channel.c
index 69fd30a6e..15c337b07 100644
--- a/src/muc-channel.c
+++ b/src/muc-channel.c
@@ -28,13 +28,8 @@
#include <wocky/wocky.h>
#include <dbus/dbus-glib.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/debug-ansi.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_MUC
#include "connection.h"
@@ -51,6 +46,10 @@
#include "presence-cache.h"
#include "gabble-signals-marshal.h"
#include "gabble-enumtypes.h"
+#include "tube-dbus.h"
+#include "tube-stream.h"
+#include "private-tubes-factory.h"
+#include "bytestream-factory.h"
#define DEFAULT_JOIN_TIMEOUT 180
#define DEFAULT_LEAVE_TIMEOUT 180
@@ -60,7 +59,6 @@
#define PROPS_POLL_INTERVAL_HIGH 60
static void password_iface_init (gpointer, gpointer);
-static void chat_state_iface_init (gpointer, gpointer);
static void subject_iface_init (gpointer, gpointer);
#ifdef ENABLE_VOIP
static void gabble_muc_channel_start_call_creation (GabbleMucChannel *gmuc,
@@ -81,7 +79,7 @@ G_DEFINE_TYPE_WITH_CODE (GabbleMucChannel, gabble_muc_channel,
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MESSAGES,
tp_message_mixin_messages_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CHAT_STATE,
- chat_state_iface_init);
+ tp_message_mixin_chat_state_iface_init)
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CONFERENCE, NULL);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_ROOM, NULL);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_ROOM_CONFIG,
@@ -92,20 +90,11 @@ G_DEFINE_TYPE_WITH_CODE (GabbleMucChannel, gabble_muc_channel,
static void gabble_muc_channel_send (GObject *obj, TpMessage *message,
TpMessageSendingFlags flags);
+static gboolean gabble_muc_channel_send_chat_state (GObject *object,
+ TpChannelChatState state,
+ GError **error);
static void gabble_muc_channel_close (TpBaseChannel *base);
-static const gchar *gabble_muc_channel_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- TP_IFACE_CHANNEL_INTERFACE_PASSWORD,
- TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE,
- TP_IFACE_CHANNEL_INTERFACE_MESSAGES,
- TP_IFACE_CHANNEL_INTERFACE_CONFERENCE,
- TP_IFACE_CHANNEL_INTERFACE_ROOM,
- TP_IFACE_CHANNEL_INTERFACE_ROOM_CONFIG,
- TP_IFACE_CHANNEL_INTERFACE_SUBJECT,
- NULL
-};
-
/* signal enum */
enum
{
@@ -129,11 +118,11 @@ static guint signals[LAST_SIGNAL] = {0};
enum
{
PROP_STATE = 1,
+ PROP_INITIALLY_REGISTER,
PROP_INVITED,
PROP_INVITATION_MESSAGE,
PROP_SELF_JID,
PROP_WOCKY_MUC,
- PROP_TUBE,
PROP_INITIAL_CHANNELS,
PROP_INITIAL_INVITEE_HANDLES,
PROP_INITIAL_INVITEE_IDS,
@@ -163,6 +152,8 @@ struct _GabbleMucChannelPrivate
{
GabbleMucState state;
gboolean closing;
+ gboolean autoclose;
+ gboolean initially_register;
guint join_timer_id;
guint poll_timer_id;
@@ -203,7 +194,9 @@ struct _GabbleMucChannelPrivate
gchar *invitation_message;
WockyMuc *wmuc;
- GabbleTubesChannel *tube;
+
+ /* tube ID => owned GabbleTubeIface */
+ GHashTable *tubes;
#ifdef ENABLE_VOIP
/* Current active call */
@@ -221,6 +214,8 @@ struct _GabbleMucChannelPrivate
GPtrArray *initial_channels;
GArray *initial_handles;
char **initial_ids;
+
+ gboolean have_received_error_type_wait;
};
typedef struct {
@@ -229,6 +224,26 @@ typedef struct {
gchar *token;
} _GabbleMUCSendMessageCtx;
+static GPtrArray *
+gabble_muc_channel_get_interfaces (TpBaseChannel *base)
+{
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CHANNEL_CLASS (
+ gabble_muc_channel_parent_class)->get_interfaces (base);
+
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_GROUP);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_PASSWORD);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_MESSAGES);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_CONFERENCE);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_ROOM);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_ROOM_CONFIG);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_SUBJECT);
+
+ return interfaces;
+}
+
static void
gabble_muc_channel_init (GabbleMucChannel *self)
{
@@ -238,6 +253,9 @@ gabble_muc_channel_init (GabbleMucChannel *self)
self->priv = priv;
priv->requests_cancellable = g_cancellable_new ();
+
+ priv->tubes = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_object_unref);
}
static TpHandle create_room_identity (GabbleMucChannel *)
@@ -256,8 +274,8 @@ static void handle_renamed (GObject *source,
static void handle_error (GObject *source,
WockyStanza *stanza,
- WockyXmppError errnum,
- const gchar *message,
+ WockyXmppErrorType errtype,
+ const GError *error,
gpointer data);
static void handle_join (WockyMuc *muc,
@@ -314,8 +332,8 @@ static void handle_errmsg (GObject *source,
GDateTime *datetime,
WockyMucMember *who,
const gchar *text,
- WockyXmppError error,
WockyXmppErrorType etype,
+ const GError *error,
gpointer data);
/* Signatures for some other stuff. */
@@ -323,11 +341,12 @@ static void handle_errmsg (GObject *source,
static void _gabble_muc_channel_handle_subject (GabbleMucChannel *chan,
TpHandleType handle_type,
TpHandle sender, GDateTime *datetime, const gchar *subject,
- WockyStanza *msg);
+ WockyStanza *msg, const GError *error);
static void _gabble_muc_channel_receive (GabbleMucChannel *chan,
TpChannelTextMessageType msg_type, TpHandleType handle_type,
TpHandle sender, GDateTime *datetime, const gchar *id, const gchar *text,
- WockyStanza *msg, TpChannelTextSendError send_error,
+ WockyStanza *msg,
+ const GError *send_error,
TpDeliveryStatus delivery_status);
static void
@@ -356,8 +375,6 @@ gabble_muc_channel_constructed (GObject *obj)
if (chain_up != NULL)
chain_up (obj);
- priv->tube = NULL;
-
room_handles = tp_base_connection_get_handles (base_conn,
TP_HANDLE_TYPE_ROOM);
contact_handles = tp_base_connection_get_handles (base_conn,
@@ -416,7 +433,8 @@ gabble_muc_channel_constructed (GObject *obj)
}
/* register object on the bus */
- tp_base_channel_register (base);
+ if (priv->initially_register)
+ tp_base_channel_register (base);
/* initialize group mixin */
tp_group_mixin_init (obj,
@@ -439,8 +457,11 @@ gabble_muc_channel_constructed (GObject *obj)
TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES |
TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_SUCCESSES,
supported_content_types);
+ tp_message_mixin_implement_send_chat_state (obj,
+ gabble_muc_channel_send_chat_state);
- tp_group_mixin_add_handle_owner (obj, self_handle, base_conn->self_handle);
+ tp_group_mixin_add_handle_owner (obj, self_handle,
+ tp_base_connection_get_self_handle (base_conn));
/* Room interface */
g_object_get (self,
@@ -493,8 +514,8 @@ gabble_muc_channel_constructed (GObject *obj)
if (priv->invited)
{
/* invited: add ourself to local pending and the inviter to members */
- TpIntSet *members = tp_intset_new_containing (initiator);
- TpIntSet *pending = tp_intset_new_containing (self_handle);
+ TpIntset *members = tp_intset_new_containing (initiator);
+ TpIntset *pending = tp_intset_new_containing (self_handle);
tp_group_mixin_change_members (obj, priv->invitation_message,
members, NULL, pending, NULL,
@@ -517,7 +538,7 @@ gabble_muc_channel_constructed (GObject *obj)
GError *error = NULL;
GArray *members = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1);
- g_assert (initiator == base_conn->self_handle);
+ g_assert (initiator == tp_base_connection_get_self_handle (base_conn));
g_assert (priv->invitation_message == NULL);
g_array_append_val (members, self_handle);
@@ -525,8 +546,6 @@ gabble_muc_channel_constructed (GObject *obj)
g_assert (error == NULL);
g_array_unref (members);
}
-
- tp_handle_unref (contact_handles, self_handle);
}
typedef struct {
@@ -741,7 +760,7 @@ create_room_identity (GabbleMucChannel *chan)
g_assert (priv->self_jid == NULL);
source = _gabble_connection_get_cached_alias (GABBLE_CONNECTION (conn),
- conn->self_handle, &alias);
+ tp_base_connection_get_self_handle (conn), &alias);
g_assert (alias != NULL);
if (source == GABBLE_CONNECTION_ALIAS_FROM_JID)
@@ -776,6 +795,49 @@ send_join_request (GabbleMucChannel *gmuc)
wocky_muc_join (priv->wmuc, NULL);
}
+static void
+tube_pre_presence (GabbleMucChannel *gmuc,
+ WockyStanza *stanza)
+{
+ GabbleMucChannelPrivate *priv = gmuc->priv;
+ TpBaseConnection *conn = tp_base_channel_get_connection (
+ TP_BASE_CHANNEL (gmuc));
+ WockyNode *tubes_node;
+ GHashTableIter iter;
+ gpointer value;
+
+ tubes_node = wocky_node_add_child_with_content_ns (
+ wocky_stanza_get_top_node (stanza), "tubes", NULL, NS_TUBES);
+
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ GabbleTubeIface *tube = value;
+ TpTubeChannelState state;
+ WockyNode *tube_node;
+ TpTubeType type;
+ TpHandle initiator;
+
+ g_object_get (tube,
+ "state", &state,
+ "type", &type,
+ "initiator-handle", &initiator,
+ NULL);
+
+ if (state != TP_TUBE_CHANNEL_STATE_OPEN)
+ continue;
+
+ if (type == TP_TUBE_TYPE_STREAM
+ && initiator != TP_GROUP_MIXIN (gmuc)->self_handle)
+ /* We only announce stream tubes we initiated */
+ continue;
+
+ tube_node = wocky_node_add_child_with_content (tubes_node,
+ "tube", NULL);
+ gabble_tube_iface_publish_in_node (tube, conn, tube_node);
+ }
+}
+
static gboolean
timeout_leave (gpointer data)
{
@@ -798,6 +860,8 @@ send_leave_message (GabbleMucChannel *gmuc,
WockyStanza *stanza = wocky_muc_create_presence (priv->wmuc,
WOCKY_STANZA_SUB_TYPE_UNAVAILABLE, reason);
+ tube_pre_presence (gmuc, stanza);
+
g_signal_emit (gmuc, signals[PRE_PRESENCE], 0, stanza);
_gabble_connection_send (
GABBLE_CONNECTION (tp_base_channel_get_connection (base)), stanza, NULL);
@@ -821,12 +885,12 @@ gabble_muc_channel_get_property (GObject *object,
case PROP_STATE:
g_value_set_uint (value, priv->state);
break;
+ case PROP_INITIALLY_REGISTER:
+ g_value_set_boolean (value, priv->initially_register);
+ break;
case PROP_SELF_JID:
g_value_set_string (value, priv->self_jid->str);
break;
- case PROP_TUBE:
- g_value_set_object (value, priv->tube);
- break;
case PROP_WOCKY_MUC:
g_value_set_object (value, priv->wmuc);
break;
@@ -896,6 +960,9 @@ gabble_muc_channel_set_property (GObject *object,
channel_state_changed (chan, prev_state, priv->state);
break;
+ case PROP_INITIALLY_REGISTER:
+ priv->initially_register = g_value_get_boolean (value);
+ break;
case PROP_INVITED:
priv->invited = g_value_get_boolean (value);
break;
@@ -1012,7 +1079,7 @@ gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class)
base_class->channel_type = TP_IFACE_CHANNEL_TYPE_TEXT;
base_class->target_handle_type = TP_HANDLE_TYPE_ROOM;
- base_class->interfaces = gabble_muc_channel_interfaces;
+ base_class->get_interfaces = gabble_muc_channel_get_interfaces;
base_class->fill_immutable_properties = gabble_muc_channel_fill_immutable_properties;
base_class->close = gabble_muc_channel_close;
@@ -1022,6 +1089,12 @@ gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_STATE, param_spec);
+ param_spec = g_param_spec_boolean ("initially-register", "Initially register",
+ "whether to register the channel on the bus on creation",
+ TRUE,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INITIALLY_REGISTER, param_spec);
+
param_spec = g_param_spec_boolean ("invited", "Invited?",
"Whether the user has been invited to the channel.", FALSE,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
@@ -1043,11 +1116,6 @@ gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class)
g_object_class_install_property (object_class, PROP_SELF_JID,
param_spec);
- param_spec = g_param_spec_object ("tube", "Tube Channel",
- "The GabbleTubesChannel associated with this MUC (if any)",
- GABBLE_TYPE_TUBES_CHANNEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_TUBE, param_spec);
-
param_spec = g_param_spec_object ("wocky-muc", "Wocky MUC Object",
"The backend (Wocky) MUC instance",
WOCKY_TYPE_MUC, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
@@ -1178,7 +1246,9 @@ gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class)
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GABBLE_TYPE_TUBES_CHANNEL);
+ /* this should be GABBLE_TYPE_TUBE_IFACE but GObject
+ * wants a value type, not an interface. */
+ G_TYPE_NONE, 1, TP_TYPE_BASE_CHANNEL);
#ifdef ENABLE_VOIP
signals[NEW_CALL] = g_signal_new ("new-call",
@@ -1232,6 +1302,8 @@ gabble_muc_channel_dispose (GObject *object)
tp_clear_object (&priv->requests_cancellable);
tp_clear_object (&priv->room_config);
+ tp_clear_pointer (&priv->tubes, g_hash_table_unref);
+
if (G_OBJECT_CLASS (gabble_muc_channel_parent_class)->dispose)
G_OBJECT_CLASS (gabble_muc_channel_parent_class)->dispose (object);
}
@@ -1472,19 +1544,42 @@ close_channel (GabbleMucChannel *chan, const gchar *reason,
GabbleMucChannelPrivate *priv = chan->priv;
GabbleConnection *conn = GABBLE_CONNECTION (
tp_base_channel_get_connection (base));
- TpIntSet *set;
+ TpIntset *set;
GArray *handles;
- GError error = { TP_ERRORS, TP_ERROR_CANCELLED,
+ GError error = { TP_ERROR, TP_ERROR_CANCELLED,
"Muc channel closed below us" };
- if (tp_base_channel_is_destroyed (base) || priv->closing)
+ if (tp_base_channel_is_destroyed (base))
return;
+ /* if priv->closing is TRUE, we're waiting for the MUC to echo our
+ * presence. however, if we're being asked to close again, but this
+ * time without letting the muc know, let's actually close. if we
+ * don't then the channel won't disappear from the bus properly. */
+ if (priv->closing && !inform_muc)
+ {
+ clear_leave_timer (chan);
+ tp_base_channel_destroyed (base);
+ return;
+ }
+
+ /* If inform_muc is TRUE it means that we're closing the channel
+ * gracefully and we don't mind if the channel doesn't actually
+ * close behind the scenes if a tube/call is still open. Every call
+ * to this function has inform_muc=FALSE, except for Channel.Close()
+ * and RemoveMembers(self_handle) */
+ if (inform_muc && !gabble_muc_channel_can_be_closed (chan))
+ {
+ priv->autoclose = TRUE;
+ tp_base_channel_disappear (base);
+ return;
+ }
+
DEBUG ("Closing");
/* Ensure we stay alive even while telling everyone else to abandon us. */
g_object_ref (chan);
- gabble_muc_channel_close_tube (chan);
+ g_hash_table_remove_all (priv->tubes);
#ifdef ENABLE_VOIP
muc_call_channel_finish_requests (chan, NULL, &error);
@@ -1543,6 +1638,35 @@ _gabble_muc_channel_is_ready (GabbleMucChannel *chan)
return priv->ready;
}
+/* returns TRUE if there are no tube or Call channels open in this MUC */
+gboolean
+gabble_muc_channel_can_be_closed (GabbleMucChannel *chan)
+{
+ GabbleMucChannelPrivate *priv = chan->priv;
+
+ if (g_hash_table_size (priv->tubes) > 0)
+ return FALSE;
+
+ if (priv->calls != NULL || priv->call_requests != NULL
+ || priv->call_initiating)
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gabble_muc_channel_get_autoclose (GabbleMucChannel *chan)
+{
+ return chan->priv->autoclose;
+}
+
+void
+gabble_muc_channel_set_autoclose (GabbleMucChannel *chan,
+ gboolean autoclose)
+{
+ chan->priv->autoclose = autoclose;
+}
+
static gboolean
handle_nick_conflict (GabbleMucChannel *chan,
WockyStanza *stanza,
@@ -1554,7 +1678,7 @@ handle_nick_conflict (GabbleMucChannel *chan,
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
tp_base_channel_get_connection (base), TP_HANDLE_TYPE_CONTACT);
TpHandle self_handle;
- TpIntSet *add_rp, *remove_rp;
+ TpIntset *add_rp, *remove_rp;
const gchar *from = wocky_stanza_get_from (stanza);
/* If this is a nick conflict message with a resource in the JID, and the
@@ -1578,7 +1702,7 @@ handle_nick_conflict (GabbleMucChannel *chan,
if (priv->nick_retry_count >= MAX_NICK_RETRIES)
{
- g_set_error (tp_error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (tp_error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"nickname already in use and retry count exceeded");
return FALSE;
}
@@ -1602,7 +1726,6 @@ handle_nick_conflict (GabbleMucChannel *chan,
tp_intset_destroy (add_rp);
tp_intset_destroy (remove_rp);
- tp_handle_unref (contact_repo, self_handle);
priv->nick_retry_count++;
send_join_request (chan);
@@ -1762,8 +1885,8 @@ update_permissions (GabbleMucChannel *chan)
static void
handle_error (GObject *source,
WockyStanza *stanza,
- WockyXmppError errnum,
- const gchar *message,
+ WockyXmppErrorType errtype,
+ const GError *error,
gpointer data)
{
GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data);
@@ -1778,7 +1901,7 @@ handle_error (GObject *source,
return;
}
- if (errnum == WOCKY_XMPP_ERROR_NOT_AUTHORIZED)
+ if (error->code == WOCKY_XMPP_ERROR_NOT_AUTHORIZED)
{
/* channel can sit requiring a password indefinitely */
clear_join_timer (gmuc);
@@ -1798,21 +1921,21 @@ handle_error (GObject *source,
{
GError *tp_error = NULL;
- switch (errnum)
+ switch (error->code)
{
case WOCKY_XMPP_ERROR_FORBIDDEN:
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_CHANNEL_BANNED,
+ tp_error = g_error_new (TP_ERROR, TP_ERROR_CHANNEL_BANNED,
"banned from room");
reason = TP_CHANNEL_GROUP_CHANGE_REASON_BANNED;
break;
case WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE:
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_CHANNEL_FULL,
+ tp_error = g_error_new (TP_ERROR, TP_ERROR_CHANNEL_FULL,
"room is full");
reason = TP_CHANNEL_GROUP_CHANGE_REASON_BUSY;
break;
case WOCKY_XMPP_ERROR_REGISTRATION_REQUIRED:
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_CHANNEL_INVITE_ONLY,
+ tp_error = g_error_new (TP_ERROR, TP_ERROR_CHANNEL_INVITE_ONLY,
"room is invite only");
break;
@@ -1822,8 +1945,8 @@ handle_error (GObject *source,
break;
default:
- tp_error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "%s", wocky_xmpp_error_description (errnum));
+ tp_error = g_error_new (TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "%s", wocky_xmpp_error_description (error->code));
break;
}
@@ -1835,90 +1958,386 @@ handle_error (GObject *source,
}
static void
-tube_closed_cb (GabbleTubesChannel *chan, gpointer user_data)
+tube_closed_cb (GabbleTubeIface *tube,
+ GabbleMucChannel *gmuc)
{
- GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (user_data);
GabbleMucChannelPrivate *priv = gmuc->priv;
- TpHandle room;
+ guint64 tube_id;
- if (priv->tube != NULL)
- {
- priv->tube = NULL;
- g_object_get (chan, "handle", &room, NULL);
- DEBUG ("removing MUC tubes channel with handle %d", room);
- g_object_unref (chan);
- }
+ g_object_get (tube, "id", &tube_id, NULL);
+
+ g_hash_table_remove (priv->tubes, GUINT_TO_POINTER (tube_id));
}
-static GabbleTubesChannel *
-new_tube (GabbleMucChannel *gmuc,
+static GabbleTubeIface *
+create_new_tube (GabbleMucChannel *gmuc,
+ TpTubeType type,
TpHandle initiator,
+ const gchar *service,
+ GHashTable *parameters,
+ const gchar *stream_id,
+ guint64 tube_id,
+ GabbleBytestreamIface *bytestream,
gboolean requested)
{
GabbleMucChannelPrivate *priv = gmuc->priv;
TpBaseChannel *base = TP_BASE_CHANNEL (gmuc);
- TpBaseConnection *conn = tp_base_channel_get_connection (base);
- char *object_path;
+ GabbleConnection *conn = GABBLE_CONNECTION (
+ tp_base_channel_get_connection (base));
+ TpHandle self_handle = TP_GROUP_MIXIN (gmuc)->self_handle;
+ TpHandle handle = tp_base_channel_get_target_handle (base);
+ GabbleTubeIface *tube;
- g_assert (priv->tube == NULL);
+ switch (type)
+ {
+ case TP_TUBE_TYPE_DBUS:
+ tube = GABBLE_TUBE_IFACE (gabble_tube_dbus_new (conn,
+ handle, TP_HANDLE_TYPE_ROOM, self_handle, initiator,
+ service, parameters, stream_id, tube_id, bytestream, gmuc,
+ requested));
+ break;
+ case TP_TUBE_TYPE_STREAM:
+ tube = GABBLE_TUBE_IFACE (gabble_tube_stream_new (conn,
+ handle, TP_HANDLE_TYPE_ROOM, self_handle, initiator,
+ service, parameters, tube_id, gmuc, requested));
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ }
- object_path = g_strdup_printf ("%s/MucTubesChannel%u",
- conn->object_path, tp_base_channel_get_target_handle (base));
+ tp_base_channel_register ((TpBaseChannel *) tube);
- DEBUG ("creating new tubes chan, object path %s", object_path);
+ DEBUG ("create tube %" G_GUINT64_FORMAT, tube_id);
+ g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube);
- priv->tube = g_object_new (GABBLE_TYPE_TUBES_CHANNEL,
- "connection", tp_base_channel_get_connection (base),
- "object-path", object_path,
- "handle", tp_base_channel_get_target_handle (base),
- "handle-type", TP_HANDLE_TYPE_ROOM,
- "muc", gmuc,
- "initiator-handle", initiator,
- "requested", requested,
- NULL);
+ g_signal_connect (tube, "closed", G_CALLBACK (tube_closed_cb), gmuc);
+
+ return tube;
+}
+
+static guint64
+generate_tube_id (GabbleMucChannel *self)
+{
+ GabbleMucChannelPrivate *priv = self->priv;
+ guint64 out;
+
+ /* probably totally overkill */
+ do
+ {
+ out = g_random_int_range (1, G_MAXINT32);
+ }
+ while (g_hash_table_lookup (priv->tubes,
+ GUINT_TO_POINTER (out)) != NULL);
+
+ return out;
+}
+
+GabbleTubeIface *
+gabble_muc_channel_tube_request (GabbleMucChannel *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new)
+{
+ GabbleTubeIface *tube;
+ const gchar *channel_type;
+ const gchar *service;
+ GHashTable *parameters = NULL;
+ guint64 tube_id;
+ gchar *stream_id;
+ TpTubeType type;
+
+ tube_id = generate_tube_id (self);
+
+ channel_type = tp_asv_get_string (request_properties,
+ TP_PROP_CHANNEL_CHANNEL_TYPE);
+
+ if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
+ {
+ type = TP_TUBE_TYPE_STREAM;
+ service = tp_asv_get_string (request_properties,
+ TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
+
+ }
+ else if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
+ {
+ type = TP_TUBE_TYPE_DBUS;
+ service = tp_asv_get_string (request_properties,
+ TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME);
+ }
+ else
+ /* This assertion is safe: this function's caller only calls it in one of
+ * the above cases.
+ * FIXME: but it would be better to pass an enum member or something maybe.
+ */
+ g_assert_not_reached ();
+
+ /* requested tubes have an empty parameters dict */
+ parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) tp_g_value_slice_free);
+
+ /* if the service property is missing, the requestotron rejects the request
+ */
+ g_assert (service != NULL);
+
+ DEBUG ("Request a tube channel with type='%s' and service='%s'",
+ channel_type, service);
+
+ stream_id = gabble_bytestream_factory_generate_stream_id ();
+ tube = create_new_tube (self, type, TP_GROUP_MIXIN (self)->self_handle,
+ service, parameters, stream_id, tube_id, NULL, TRUE);
+ g_free (stream_id);
+ g_hash_table_unref (parameters);
+
+ return tube;
+}
+
+void
+gabble_muc_channel_foreach_tubes (GabbleMucChannel *gmuc,
+ TpExportableChannelFunc foreach,
+ gpointer user_data)
+{
+ GabbleMucChannelPrivate *priv = gmuc->priv;
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ foreach (TP_EXPORTABLE_CHANNEL (value), user_data);
+ }
+}
+
+void
+gabble_muc_channel_handle_si_stream_request (GabbleMucChannel *self,
+ GabbleBytestreamIface *bytestream,
+ const gchar *stream_id,
+ WockyStanza *msg)
+{
+ GabbleMucChannelPrivate *priv = self->priv;
+ WockyNode *si_node, *stream_node;
+ const gchar *tmp;
+ guint64 tube_id;
+ GabbleTubeIface *tube;
+
+ si_node = wocky_node_get_child_ns (
+ wocky_stanza_get_top_node (msg), "si", NS_SI);
+ g_return_if_fail (si_node != NULL);
+
+ stream_node = wocky_node_get_child_ns (si_node,
+ "muc-stream", NS_TUBES);
+ g_return_if_fail (stream_node != NULL);
+
+ tmp = wocky_node_get_attribute (stream_node, "tube");
+ if (tmp == NULL)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<muc-stream> has no tube attribute" };
+
+ NODE_DEBUG (stream_node, e.message);
+ gabble_bytestream_iface_close (bytestream, &e);
+ return;
+ }
+ tube_id = g_ascii_strtoull (tmp, NULL, 10);
+ if (tube_id == 0 || tube_id > G_MAXUINT32)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<muc-stream> tube ID attribute non-numeric or out of range" };
- g_signal_connect (priv->tube, "closed", (GCallback) tube_closed_cb, gmuc);
+ DEBUG ("tube id is non-numeric or out of range: %s", tmp);
+ gabble_bytestream_iface_close (bytestream, &e);
+ return;
+ }
+
+ tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+ if (tube == NULL)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<muc-stream> tube attribute points to a nonexistent "
+ "tube" };
- g_signal_emit (gmuc, signals[NEW_TUBE], 0 , priv->tube);
+ DEBUG ("tube %" G_GUINT64_FORMAT " doesn't exist", tube_id);
+ gabble_bytestream_iface_close (bytestream, &e);
+ return;
+ }
- g_free (object_path);
+ DEBUG ("received new bytestream request for existing tube: %" G_GUINT64_FORMAT,
+ tube_id);
- return priv->tube;
+ gabble_tube_iface_add_bytestream (tube, bytestream);
+}
+
+static void
+tubes_presence_update (GabbleMucChannel *gmuc,
+ TpHandle contact,
+ WockyNode *pnode)
+{
+ GabbleMucChannelPrivate *priv = gmuc->priv;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ tp_base_channel_get_connection (TP_BASE_CHANNEL (gmuc)),
+ TP_HANDLE_TYPE_CONTACT);
+ const gchar *presence_type;
+ WockyNode *tubes_node;
+ GHashTable *old_dbus_tubes;
+ GHashTableIter iter;
+ gpointer key, value;
+ WockyNodeIter i;
+ WockyNode *tube_node;
+
+ if (contact == TP_GROUP_MIXIN (gmuc)->self_handle)
+ /* We don't need to inspect our own presence */
+ return;
+
+ presence_type = wocky_node_get_attribute (pnode, "type");
+ if (!tp_strdiff (presence_type, "unavailable"))
+ {
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ GabbleTubeDBus *tube = value;
+
+ if (!GABBLE_IS_TUBE_DBUS (value))
+ continue;
+
+ gabble_tube_dbus_remove_name (tube, contact);
+ }
+ }
+
+ tubes_node = wocky_node_get_child_ns (pnode, "tubes", NS_TUBES);
+
+ if (tubes_node == NULL)
+ return;
+
+ /* Fill old_dbus_tubes with D-BUS tubes previously announced by
+ * the contact */
+ old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ if (!GABBLE_IS_TUBE_DBUS (value))
+ continue;
+
+ if (gabble_tube_dbus_handle_in_names (GABBLE_TUBE_DBUS (value),
+ contact))
+ {
+ g_hash_table_insert (old_dbus_tubes,
+ key, value);
+ }
+ }
+
+ wocky_node_iter_init (&i, tubes_node, NULL, NULL);
+ while (wocky_node_iter_next (&i, &tube_node))
+ {
+ const gchar *stream_id;
+ GabbleTubeIface *tube;
+ guint64 tube_id;
+ TpTubeType type;
+
+ stream_id = wocky_node_get_attribute (tube_node, "stream-id");
+
+ if (!gabble_private_tubes_factory_extract_tube_information (
+ contact_repo, tube_node, NULL, NULL, NULL, NULL, &tube_id))
+ {
+ DEBUG ("Bad tube ID, skipping to next child of <tubes>");
+ continue;
+ }
+
+ tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+
+ if (tube == NULL)
+ {
+ /* We don't know yet this tube */
+ const gchar *service;
+ TpHandle initiator_handle;
+ GHashTable *parameters;
+
+ if (gabble_private_tubes_factory_extract_tube_information (
+ contact_repo, tube_node, &type, &initiator_handle,
+ &service, &parameters, NULL))
+ {
+ if (type == TP_TUBE_TYPE_DBUS && initiator_handle == 0)
+ {
+ DEBUG ("D-Bus tube initiator missing");
+ /* skip to the next child of <tubes> */
+ continue;
+ }
+ else if (type == TP_TUBE_TYPE_STREAM)
+ {
+ initiator_handle = contact;
+ }
+
+ tube = create_new_tube (gmuc, type, initiator_handle,
+ service, parameters, stream_id, tube_id, NULL, FALSE);
+
+ g_signal_emit (gmuc, signals[NEW_TUBE], 0, tube);
+
+ g_hash_table_unref (parameters);
+ }
+ }
+ else
+ {
+ /* The contact is in the tube.
+ * Remove it from old_dbus_tubes if needed */
+ g_hash_table_remove (old_dbus_tubes, GUINT_TO_POINTER (tube_id));
+ }
+
+ if (tube == NULL)
+ /* skip to the next child of <tubes> */
+ continue;
+
+ g_object_get (tube, "type", &type, NULL);
+
+ if (type == TP_TUBE_TYPE_DBUS)
+ {
+ /* Update mapping of handle -> D-Bus name. */
+ if (!gabble_tube_dbus_handle_in_names (GABBLE_TUBE_DBUS (tube),
+ contact))
+ {
+ /* Contact just joined the tube */
+ const gchar *new_name;
+
+ new_name = wocky_node_get_attribute (tube_node,
+ "dbus-name");
+
+ if (!new_name)
+ {
+ DEBUG ("Contact %u isn't announcing their D-Bus name",
+ contact);
+ /* skip to the next child of <tubes> */
+ continue;
+ }
+
+ gabble_tube_dbus_add_name (GABBLE_TUBE_DBUS (tube),
+ contact, new_name);
+ }
+ }
+ }
+
+ /* Tubes remaining in old_dbus_tubes was left by the contact */
+ g_hash_table_iter_init (&iter, old_dbus_tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ gabble_tube_dbus_remove_name (GABBLE_TUBE_DBUS (value), contact);
+ }
+
+ g_hash_table_unref (old_dbus_tubes);
}
/* ************************************************************************* */
/* presence related signal handlers */
-/* not actually a signal handler, but used by them: *
- * creates a tube if none exists, and then prods the presence handler *
- * in the gabble tubes implementation to do whatever else needs to be done */
+/* not actually a signal handler, but used by them. */
static void
handle_tube_presence (GabbleMucChannel *gmuc,
TpHandle from,
WockyStanza *stanza)
{
- GabbleMucChannelPrivate *priv = gmuc->priv;
WockyNode *node = wocky_stanza_get_top_node (stanza);
if (from == 0)
return;
- if (priv->tube == NULL)
- {
- WockyNode *tubes;
- tubes = wocky_node_get_child_ns (node, "tubes", NS_TUBES);
-
- /* presence doesn't contain tubes information, no need
- * to create a tubes channel */
- if (tubes == NULL)
- return;
-
- /* MUC Tubes channels (as opposed to the individual tubes) don't
- * have a well-defined initiator (they're a consensus) so use 0 */
- priv->tube = new_tube (gmuc, 0, FALSE);
- }
-
- gabble_tubes_channel_presence_updated (priv->tube, from, node);
+ tubes_presence_update (gmuc, from, node);
}
static TpChannelGroupChangeReason
@@ -1955,7 +2374,7 @@ handle_parted (GObject *source,
TpHandleRepoIface *contact_repo =
tp_base_connection_get_handles (tp_base_channel_get_connection (base),
TP_HANDLE_TYPE_CONTACT);
- TpIntSet *handles = NULL;
+ TpIntset *handles = NULL;
TpHandle member = 0;
TpHandle actor = 0;
const char *jid = wocky_muc_jid (wmuc);
@@ -1999,16 +2418,11 @@ handle_parted (GObject *source,
reason = muc_status_codes_to_change_reason (codes);
/* handle_tube_presence creates tubes if need be, so bypass it here: */
- if (priv->tube != NULL)
- gabble_tubes_channel_presence_updated (priv->tube, member,
- wocky_stanza_get_top_node (stanza));
+ tubes_presence_update (gmuc, member, wocky_stanza_get_top_node (stanza));
close_channel (gmuc, why, FALSE, actor, reason);
- if (actor != 0)
- tp_handle_unref (contact_repo, actor);
tp_intset_destroy (handles);
- tp_handle_unref (contact_repo, member);
}
@@ -2026,12 +2440,11 @@ handle_left (GObject *source,
{
GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data);
TpBaseChannel *base = TP_BASE_CHANNEL (gmuc);
- GabbleMucChannelPrivate *priv = gmuc->priv;
TpChannelGroupChangeReason reason = TP_CHANNEL_GROUP_CHANGE_REASON_NONE;
TpHandleRepoIface *contact_repo =
tp_base_connection_get_handles (tp_base_channel_get_connection (base),
TP_HANDLE_TYPE_CONTACT);
- TpIntSet *handles = NULL;
+ TpIntset *handles = NULL;
TpHandle member = 0;
TpHandle actor = 0;
@@ -2056,17 +2469,14 @@ handle_left (GObject *source,
reason = muc_status_codes_to_change_reason (codes);
/* handle_tube_presence creates tubes if need be, so bypass it here: */
- if (priv->tube != NULL)
- gabble_tubes_channel_presence_updated (priv->tube, member,
- wocky_stanza_get_top_node (stanza));
+ tubes_presence_update (gmuc, member, wocky_stanza_get_top_node (stanza));
tp_group_mixin_change_members (data, why, NULL, handles, NULL, NULL,
actor, reason);
+ tp_message_mixin_change_chat_state (data, member,
+ TP_CHANNEL_CHAT_STATE_GONE);
- if (actor != 0)
- tp_handle_unref (contact_repo, actor);
tp_intset_destroy (handles);
- tp_handle_unref (contact_repo, member);
}
/* connect to wocky-muc:SIG_PERM_CHANGE, which we will receive when the *
@@ -2124,6 +2534,8 @@ handle_fill_presence (WockyMuc *muc,
conn->self_presence->status_message,
0);
+ tube_pre_presence (self, stanza);
+
g_signal_emit (self, signals[PRE_PRESENCE], 0, (WockyStanza *) stanza);
}
@@ -2141,7 +2553,7 @@ handle_renamed (GObject *source,
TpHandleRepoIface *contact_repo =
tp_base_connection_get_handles (tp_base_channel_get_connection (base),
TP_HANDLE_TYPE_CONTACT);
- TpIntSet *old_self = tp_intset_new ();
+ TpIntset *old_self = tp_intset_new ();
const gchar *me = wocky_muc_jid (wmuc);
const gchar *me2 = wocky_muc_user (wmuc);
TpHandle myself = tp_handle_ensure (contact_repo, me,
@@ -2157,8 +2569,6 @@ handle_renamed (GObject *source,
handle_tube_presence (gmuc, myself, stanza);
tp_intset_destroy (old_self);
- tp_handle_unref (contact_repo, userid);
- tp_handle_unref (contact_repo, myself);
}
static void
@@ -2194,7 +2604,6 @@ update_roster_presence (GabbleMucChannel *gmuc,
GUINT_TO_POINTER (handle),
GUINT_TO_POINTER (owner));
- tp_handle_unref (contact_repo, handle);
/* make a note of the fact that owner JIDs are visible to us */
/* notify whomever that an identifiable contact joined the MUC */
if (owner != 0)
@@ -2202,7 +2611,6 @@ update_roster_presence (GabbleMucChannel *gmuc,
tp_group_mixin_change_flags (G_OBJECT (gmuc), 0,
TP_CHANNEL_GROUP_FLAG_HANDLE_OWNERS_NOT_AVAILABLE);
g_signal_emit (gmuc, signals[CONTACT_JOIN], 0, owner);
- tp_handle_unref (contact_repo, owner);
}
handle_tube_presence (gmuc, handle, member->presence_stanza);
@@ -2240,7 +2648,7 @@ handle_join (WockyMuc *muc,
g_hash_table_insert (omap,
GUINT_TO_POINTER (myself),
- GUINT_TO_POINTER (base_conn->self_handle));
+ GUINT_TO_POINTER (tp_base_connection_get_self_handle (base_conn)));
tp_handle_set_add (members, myself);
tp_group_mixin_add_handle_owners (G_OBJECT (gmuc), omap);
@@ -2266,7 +2674,6 @@ handle_join (WockyMuc *muc,
g_object_set (gmuc, "state", MUC_STATE_JOINED, NULL);
- tp_handle_unref (contact_repo, myself);
tp_handle_set_destroy (members);
tp_handle_set_destroy (owners);
g_hash_table_unref (omap);
@@ -2341,10 +2748,6 @@ handle_presence (GObject *source,
}
#endif
- /* zap the handle refs we created */
- tp_handle_unref (contact_repo, handle);
- if (owner != 0)
- tp_handle_unref (contact_repo, owner);
tp_handle_set_destroy (handles);
}
@@ -2391,7 +2794,6 @@ handle_message (GObject *source,
handle_type = TP_HANDLE_TYPE_ROOM;
repo = tp_base_connection_get_handles (conn, handle_type);
from = tp_base_channel_get_target_handle (base);
- tp_handle_ref (repo, from);
}
switch (type)
@@ -2409,11 +2811,12 @@ handle_message (GObject *source,
if (text != NULL)
_gabble_muc_channel_receive (gmuc,
msg_type, handle_type, from, datetime, xmpp_id, text, stanza,
- GABBLE_TEXT_CHANNEL_SEND_NO_ERROR, TP_DELIVERY_STATUS_DELIVERED);
+ NULL,
+ TP_DELIVERY_STATUS_DELIVERED);
if (from_member && state != WOCKY_MUC_MSG_STATE_NONE)
{
- gint tp_msg_state;
+ TpChannelChatState tp_msg_state;
switch (state)
{
case WOCKY_MUC_MSG_STATE_ACTIVE:
@@ -2432,15 +2835,12 @@ handle_message (GObject *source,
tp_msg_state = TP_CHANNEL_CHAT_STATE_ACTIVE;
}
- tp_svc_channel_interface_chat_state_emit_chat_state_changed (gmuc,
- from, tp_msg_state);
+ tp_message_mixin_change_chat_state ((GObject *) gmuc, from, tp_msg_state);
}
if (subject != NULL)
_gabble_muc_channel_handle_subject (gmuc, handle_type, from,
- datetime, subject, stanza);
-
- tp_handle_unref (repo, from);
+ datetime, subject, stanza, NULL);
}
static void
@@ -2451,8 +2851,8 @@ handle_errmsg (GObject *source,
GDateTime *datetime,
WockyMucMember *who,
const gchar *text,
- WockyXmppError error,
WockyXmppErrorType etype,
+ const GError *error,
gpointer data)
{
GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data);
@@ -2460,7 +2860,6 @@ handle_errmsg (GObject *source,
TpBaseChannel *base = TP_BASE_CHANNEL (gmuc);
TpBaseConnection *conn = tp_base_channel_get_connection (base);
gboolean from_member = (who != NULL);
- TpChannelTextSendError tp_err = TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN;
TpDeliveryStatus ds = TP_DELIVERY_STATUS_DELIVERED;
TpHandleRepoIface *repo = NULL;
TpHandleType handle_type;
@@ -2485,19 +2884,32 @@ handle_errmsg (GObject *source,
handle_type = TP_HANDLE_TYPE_ROOM;
repo = tp_base_connection_get_handles (conn, handle_type);
from = tp_base_channel_get_target_handle (base);
- tp_handle_ref (repo, from);
}
- tp_err = gabble_tp_send_error_from_wocky_xmpp_error (error);
-
if (etype == WOCKY_XMPP_ERROR_TYPE_WAIT)
- ds = TP_DELIVERY_STATUS_TEMPORARILY_FAILED;
+ {
+ ds = TP_DELIVERY_STATUS_TEMPORARILY_FAILED;
+ /* Some MUCs have very strict rate limiting like "at most one stanza per
+ * second". Since chat state notifications count towards this, if the
+ * user types a message very quickly then the typing notification is
+ * accepted but then the stanza containing the actual message is
+ * rejected.
+ *
+ * So: if we ever get rate-limited, let's just stop sending chat states.
+ *
+ * https://bugs.freedesktop.org/show_bug.cgi?id=43166
+ */
+ DEBUG ("got <error type='wait'>, disabling chat state notifications");
+ priv->have_received_error_type_wait = TRUE;
+ }
else
- ds = TP_DELIVERY_STATUS_PERMANENTLY_FAILED;
+ {
+ ds = TP_DELIVERY_STATUS_PERMANENTLY_FAILED;
+ }
if (text != NULL)
_gabble_muc_channel_receive (gmuc, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE,
- handle_type, from, datetime, xmpp_id, text, stanza, tp_err, ds);
+ handle_type, from, datetime, xmpp_id, text, stanza, error, ds);
/* FIXME: this is stupid. WockyMuc gives us the subject for non-errors, but
* doesn't bother for errors.
@@ -2513,9 +2925,7 @@ handle_errmsg (GObject *source,
(priv->set_subject_stanza_id != NULL &&
!tp_strdiff (xmpp_id, priv->set_subject_stanza_id)))
_gabble_muc_channel_handle_subject (gmuc,
- handle_type, from, datetime, subject, stanza);
-
- tp_handle_unref (repo, from);
+ handle_type, from, datetime, subject, stanza, error);
}
/* ************************************************************************* */
@@ -2528,11 +2938,11 @@ _gabble_muc_channel_handle_subject (GabbleMucChannel *chan,
TpHandle sender,
GDateTime *datetime,
const gchar *subject,
- WockyStanza *msg)
+ WockyStanza *msg,
+ const GError *error)
{
GabbleMucChannelPrivate *priv;
const gchar *actor;
- GError *error = NULL;
gint64 timestamp = datetime != NULL ?
g_date_time_to_unix (datetime) : G_MAXINT64;
@@ -2540,7 +2950,7 @@ _gabble_muc_channel_handle_subject (GabbleMucChannel *chan,
priv = chan->priv;
- if (wocky_stanza_extract_errors (msg, NULL, &error, NULL, NULL))
+ if (error != NULL)
{
if (priv->set_subject_context != NULL)
{
@@ -2557,7 +2967,6 @@ _gabble_muc_channel_handle_subject (GabbleMucChannel *chan,
room_properties_update (chan);
}
- g_clear_error (&error);
return;
}
@@ -2595,7 +3004,7 @@ _gabble_muc_channel_handle_subject (GabbleMucChannel *chan,
/**
* _gabble_muc_channel_receive: receive MUC messages
*/
-void
+static void
_gabble_muc_channel_receive (GabbleMucChannel *chan,
TpChannelTextMessageType msg_type,
TpHandleType sender_handle_type,
@@ -2604,7 +3013,7 @@ _gabble_muc_channel_receive (GabbleMucChannel *chan,
const gchar *id,
const gchar *text,
WockyStanza *msg,
- TpChannelTextSendError send_error,
+ const GError *send_error,
TpDeliveryStatus error_status)
{
TpBaseChannel *base;
@@ -2623,7 +3032,7 @@ _gabble_muc_channel_receive (GabbleMucChannel *chan,
muc_self_handle = chan->group.self_handle;
/* Is this an error report? */
- is_error = (send_error != GABBLE_TEXT_CHANNEL_SEND_NO_ERROR);
+ is_error = (send_error != NULL);
if (is_error && sender == muc_self_handle)
{
@@ -2655,6 +3064,16 @@ _gabble_muc_channel_receive (GabbleMucChannel *chan,
return;
}
+ /* are we actually hidden? */
+ if (!tp_base_channel_is_registered (base))
+ {
+ DEBUG ("making MUC channel reappear!");
+ tp_base_channel_reopened_with_requested (base, FALSE, sender);
+ }
+
+ /* let's not autoclose now */
+ chan->priv->autoclose = FALSE;
+
message = tp_cm_message_new (base_conn, 2);
/* Header common to normal message and delivery-echo */
@@ -2689,9 +3108,21 @@ _gabble_muc_channel_receive (GabbleMucChannel *chan,
if (id != NULL)
tp_message_set_string (delivery_report, 0, "delivery-token", id);
- if (is_error)
- tp_message_set_uint32 (delivery_report, 0, "delivery-error",
- send_error);
+ if (send_error != NULL)
+ {
+ tp_message_set_uint32 (delivery_report, 0, "delivery-error",
+ gabble_tp_send_error_from_wocky_xmpp_error (send_error->code));
+
+ if (!tp_str_empty (send_error->message))
+ {
+ guint body_part_number = tp_message_append_part (delivery_report);
+
+ tp_message_set_string (delivery_report, body_part_number,
+ "content-type", "text/plain");
+ tp_message_set_string (delivery_report, body_part_number,
+ "content", send_error->message);
+ }
+ }
/* We do not set a message-sender on the report: the intended recipient
* of the original message was the MUC, so the spec says we should omit
@@ -2783,7 +3214,7 @@ gabble_muc_channel_provide_password (TpSvcChannelInterfacePassword *iface,
if (!priv->must_provide_password ||
priv->password_ctx != NULL)
{
- GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"password cannot be provided in the current state" };
dbus_g_method_return_error (context, &error);
}
@@ -2839,14 +3270,21 @@ gabble_muc_channel_send (GObject *obj,
GabbleMucChannel *self = GABBLE_MUC_CHANNEL (obj);
TpBaseChannel *base = TP_BASE_CHANNEL (self);
GabbleMucChannelPrivate *priv = self->priv;
- GabbleConnection *gabble_conn =
- GABBLE_CONNECTION (tp_base_channel_get_connection (base));
+ TpBaseConnection *base_conn;
+ GabbleConnection *gabble_conn;
_GabbleMUCSendMessageCtx *context = NULL;
WockyStanza *stanza = NULL;
WockyPorter *porter = NULL;
GError *error = NULL;
gchar *id = NULL;
+ base_conn = tp_base_channel_get_connection (base);
+ gabble_conn = GABBLE_CONNECTION (base_conn);
+
+ tp_message_mixin_change_chat_state (obj,
+ tp_base_channel_get_self_handle (base),
+ TP_CHANNEL_CHAT_STATE_ACTIVE);
+
stanza = gabble_message_util_build_stanza (message, gabble_conn,
WOCKY_STANZA_SUB_TYPE_GROUPCHAT, TP_CHANNEL_CHAT_STATE_ACTIVE,
priv->jid, FALSE, &id, &error);
@@ -2902,7 +3340,7 @@ gabble_muc_channel_send_invite (GabbleMucChannel *self,
if (continue_)
{
- wocky_node_add_child_with_content (invite_node, "continue", NULL);
+ wocky_node_add_child (invite_node, "continue");
}
DEBUG ("sending MUC invitation for room %s to contact %s with reason "
@@ -2932,14 +3370,14 @@ gabble_muc_channel_add_member (GObject *obj,
if (handle == mixin->self_handle)
{
TpBaseConnection *conn = tp_base_channel_get_connection (base);
- TpIntSet *set_remove_members, *set_remote_pending;
+ TpIntset *set_remove_members, *set_remote_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,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"already a member or in remote pending");
return FALSE;
@@ -2961,7 +3399,7 @@ gabble_muc_channel_add_member (GObject *obj,
tp_intset_add (set_remote_pending, handle);
tp_group_mixin_add_handle_owner (obj, mixin->self_handle,
- conn->self_handle);
+ tp_base_connection_get_self_handle (conn));
tp_group_mixin_change_members (obj, "", NULL, set_remove_members,
NULL, set_remote_pending, 0,
priv->invited
@@ -2983,7 +3421,7 @@ gabble_muc_channel_add_member (GObject *obj,
/* 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,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"channel membership is required for inviting others");
return FALSE;
@@ -3250,7 +3688,7 @@ request_config_form_reply_cb (
* platforms, so fail at compile time if this is no longer the case
*/
#if TP_NUM_BASE_ROOM_CONFIG_PROPERTIES > 32
-#error GabbleMUCChannel request_config_form_reply_cb needs porting to TpIntSet
+#error GabbleMUCChannel request_config_form_reply_cb needs porting to TpIntset
#endif
props_left = 0;
@@ -3324,8 +3762,7 @@ request_config_form_reply_cb (
{
GString *unsubstituted = g_string_new ("");
- printf (TP_ANSI_BOLD_ON TP_ANSI_FG_WHITE TP_ANSI_BG_RED
- "\n%s: the following properties were not substituted:\n",
+ printf ("\n%s: the following properties were not substituted:\n",
G_STRFUNC);
for (i = 0; i < TP_NUM_BASE_ROOM_CONFIG_PROPERTIES; i++)
@@ -3345,10 +3782,10 @@ request_config_form_reply_cb (
printf ("\nthis is a MUC server compatibility bug in gabble, please "
"report it with a full debug log attached (running gabble "
- "with WOCKY_DEBUG=xmpp)" TP_ANSI_RESET "\n\n");
+ "with WOCKY_DEBUG=xmpp)\n\n");
fflush (stdout);
- error = g_error_new (TP_ERRORS, TP_ERROR_SERVICE_CONFUSED,
+ error = g_error_new (TP_ERROR, TP_ERROR_SERVICE_CONFUSED,
"Couldn't find fields corresponding to %s in the muc#owner form. "
"This is a MUC server compatibility bug in Gabble.",
unsubstituted->str);
@@ -3403,55 +3840,21 @@ request_config_form_submit_reply_cb (
g_object_unref (update_result);
}
-/**
- * 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)
+static gboolean
+gabble_muc_channel_send_chat_state (GObject *object,
+ TpChannelChatState state,
+ GError **error)
{
- GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface);
+ GabbleMucChannel *self = GABBLE_MUC_CHANNEL (object);
+ GabbleMucChannelPrivate *priv = self->priv;
TpBaseChannel *base = TP_BASE_CHANNEL (self);
- GabbleMucChannelPrivate *priv;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_MUC_CHANNEL (self));
-
- priv = self->priv;
-
- 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_message_util_send_chat_state (G_OBJECT (self),
- GABBLE_CONNECTION (tp_base_channel_get_connection (base)),
- WOCKY_STANZA_SUB_TYPE_GROUPCHAT, state, priv->jid, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- return;
- }
+ if (priv->have_received_error_type_wait)
+ return TRUE;
- tp_svc_channel_interface_chat_state_return_from_set_chat_state (context);
+ return gabble_message_util_send_chat_state (G_OBJECT (self),
+ GABBLE_CONNECTION (tp_base_channel_get_connection (base)),
+ WOCKY_STANZA_SUB_TYPE_GROUPCHAT, state, priv->jid, error);
}
void
@@ -3473,40 +3876,6 @@ gabble_muc_channel_send_presence (GabbleMucChannel *self)
g_object_unref (stanza);
}
-GabbleTubesChannel *
-gabble_muc_channel_open_tube (GabbleMucChannel *gmuc,
- TpHandle initiator,
- gboolean requested)
-{
- GabbleMucChannelPrivate *priv = gmuc->priv;
-
- if (priv->tube == NULL)
- priv->tube = new_tube (gmuc, initiator, requested);
-
- if (priv->tube != NULL)
- return g_object_ref (priv->tube);
-
- return NULL;
-}
-
-void
-gabble_muc_channel_close_tube (GabbleMucChannel *gmuc)
-{
- GabbleMucChannelPrivate *priv = gmuc->priv;
-
- if (priv->tube != NULL)
- {
- TpHandle room;
- GabbleTubesChannel *tube = priv->tube;
-
- priv->tube = NULL;
- g_object_get (tube, "handle", &room, NULL);
- DEBUG ("removing MUC tubes channel with handle %d", room);
- gabble_tubes_channel_close (tube);
- g_object_unref (tube);
- }
-}
-
#ifdef ENABLE_VOIP
GabbleCallMucChannel *
gabble_muc_channel_get_call (GabbleMucChannel *gmuc)
@@ -3654,7 +4023,7 @@ gabble_muc_channel_start_call_creation (GabbleMucChannel *gmuc,
* address; and finally TpBaseChannel pastes the connection path back on. :)
*/
prefix = tp_base_channel_get_object_path (base) +
- strlen (base_conn->object_path) + 1 /* for the slash */;
+ strlen (tp_base_connection_get_object_path (base_conn)) + 1 /* for the slash */;
/* Keep ourselves reffed while call channels are created */
g_object_ref (gmuc);
@@ -3689,7 +4058,7 @@ gabble_muc_channel_request_call (GabbleMucChannel *gmuc,
{
g_simple_async_report_error_in_idle (G_OBJECT (gmuc),
callback, user_data,
- TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"A request for a call is already in progress");
return;
}
@@ -3721,7 +4090,7 @@ gabble_muc_channel_request_call_finish (GabbleMucChannel *gmuc,
gboolean
gabble_muc_channel_handle_jingle_session (GabbleMucChannel *self,
- GabbleJingleSession *session)
+ WockyJingleSession *session)
{
GabbleMucChannelPrivate *priv = self->priv;
@@ -3785,21 +4154,21 @@ gabble_muc_channel_set_subject (TpSvcChannelInterfaceSubject *iface,
if (priv->state < MUC_STATE_JOINED)
{
- GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Steady on. You're not in the room yet" };
dbus_g_method_return_error (context, &error);
}
else if (priv->state > MUC_STATE_JOINED || priv->closing)
{
- GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Already left/leaving the room" };
dbus_g_method_return_error (context, &error);
}
else if (priv->set_subject_context != NULL)
{
- GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Hey! Stop changing the subject! (Your last request is still in "
"flight.)" };
@@ -3845,18 +4214,6 @@ password_iface_init (gpointer g_iface, gpointer iface_data)
}
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
-}
-
-static void
subject_iface_init (gpointer g_iface, gpointer iface_data)
{
TpSvcChannelInterfaceSubjectClass *klass =
diff --git a/src/muc-channel.h b/src/muc-channel.h
index f28b7a07e..0db129ed3 100644
--- a/src/muc-channel.h
+++ b/src/muc-channel.h
@@ -27,16 +27,13 @@
#include <glib-object.h>
#include <gio/gio.h>
-#include <telepathy-glib/base-channel.h>
-#include <telepathy-glib/dbus-properties-mixin.h>
-#include <telepathy-glib/group-mixin.h>
-#include <telepathy-glib/message-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "types.h"
-#include "tubes-channel.h"
#ifdef ENABLE_VOIP
#include "call-muc-channel.h"
#endif
+#include "tube-iface.h"
G_BEGIN_DECLS
@@ -88,15 +85,29 @@ GType gabble_muc_channel_get_type (void);
gboolean _gabble_muc_channel_is_ready (GabbleMucChannel *chan);
+void gabble_muc_channel_set_autoclose (GabbleMucChannel *chan,
+ gboolean autoclose);
+
+gboolean gabble_muc_channel_get_autoclose (GabbleMucChannel *chan);
+
+gboolean gabble_muc_channel_can_be_closed (GabbleMucChannel *chan);
+
void gabble_muc_channel_send_presence (GabbleMucChannel *chan);
gboolean gabble_muc_channel_send_invite (GabbleMucChannel *self,
const gchar *jid, const gchar *message, gboolean continue_, GError **error);
-GabbleTubesChannel *
-gabble_muc_channel_open_tube (GabbleMucChannel *gmuc,
- TpHandle initiator,
- gboolean requested);
+GabbleTubeIface * gabble_muc_channel_tube_request (GabbleMucChannel *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new);
+
+void gabble_muc_channel_foreach_tubes (GabbleMucChannel *gmuc,
+ TpExportableChannelFunc foreach, gpointer user_data);
+
+void gabble_muc_channel_handle_si_stream_request (GabbleMucChannel *self,
+ GabbleBytestreamIface *bytestream, const gchar *stream_id,
+ WockyStanza *msg);
#ifdef ENABLE_VOIP
GabbleCallMucChannel * gabble_muc_channel_get_call (GabbleMucChannel *gmuc);
@@ -114,7 +125,7 @@ gboolean gabble_muc_channel_request_call_finish (GabbleMucChannel *gmuc,
GError **error);
gboolean gabble_muc_channel_handle_jingle_session (GabbleMucChannel *channel,
- GabbleJingleSession *session);
+ WockyJingleSession *session);
#endif
void gabble_muc_channel_update_configuration_async (
@@ -128,7 +139,6 @@ gboolean gabble_muc_channel_update_configuration_finish (
GError **error);
void gabble_muc_channel_teardown (GabbleMucChannel *gmuc);
-void gabble_muc_channel_close_tube (GabbleMucChannel *gmuc);
G_END_DECLS
diff --git a/src/muc-factory.c b/src/muc-factory.c
index f734c13cc..0f1dbcb07 100644
--- a/src/muc-factory.c
+++ b/src/muc-factory.c
@@ -25,11 +25,9 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/util.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_MUC
@@ -46,7 +44,6 @@
#include "muc-channel.h"
#include "namespaces.h"
#include "presence-cache.h"
-#include "tubes-channel.h"
#include "tube-dbus.h"
#include "tube-stream.h"
#include "util.h"
@@ -81,14 +78,10 @@ struct _GabbleMucFactoryPrivate
guint message_cb_id;
/* GUINT_TO_POINTER(room_handle) => (GabbleMucChannel *) */
GHashTable *text_channels;
- /* Tubes channels which will be considered ready when the corresponding
- * text channel is created.
- * Borrowed GabbleMucChannel => borrowed GabbleTubesChannel */
- GHashTable *text_needed_for_tubes;
/* Tube channels which will be considered ready when the corresponding
- * tubes channel is created.
- * Borrowed GabbleTubesChannel => GSlist of borrowed GabbleTubeIface */
- GHashTable *tubes_needed_for_tube;
+ * text channel is created.
+ * Borrowed GabbleMucChannel => owned GQueue of borrowed GabbleTubeIface */
+ GHashTable *text_needed_for_tube;
/* GabbleDiscoRequest * => NULL (used as a set) */
GHashTable *disco_requests;
@@ -103,6 +96,9 @@ struct _GabbleMucFactoryPrivate
static GObject *gabble_muc_factory_constructor (GType type, guint n_props,
GObjectConstructParam *props);
+static void gabble_muc_factory_associate_tube (GabbleMucFactory *self,
+ GabbleMucChannel *gmuc, GabbleTubeIface *tube);
+
static void
gabble_muc_factory_init (GabbleMucFactory *fac)
{
@@ -113,13 +109,11 @@ gabble_muc_factory_init (GabbleMucFactory *fac)
priv->text_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, g_object_unref);
- priv->text_needed_for_tubes = g_hash_table_new_full (g_direct_hash,
- g_direct_equal, NULL, NULL);
- priv->tubes_needed_for_tube = g_hash_table_new_full (g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) g_slist_free);
+ priv->text_needed_for_tube = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, NULL, (GDestroyNotify) g_queue_free);
priv->disco_requests = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
+ NULL, NULL);
priv->queued_requests = g_hash_table_new_full (g_direct_hash,
g_direct_equal, NULL, NULL);
@@ -156,8 +150,7 @@ gabble_muc_factory_dispose (GObject *object)
gabble_muc_factory_close_all (fac);
g_assert (priv->text_channels == NULL);
- g_assert (priv->text_needed_for_tubes == NULL);
- g_assert (priv->tubes_needed_for_tube == NULL);
+ g_assert (priv->text_needed_for_tube == NULL);
g_assert (priv->queued_requests == NULL);
g_hash_table_foreach (priv->disco_requests, cancel_disco_request,
@@ -239,19 +232,30 @@ muc_channel_closed_cb (GabbleMucChannel *chan, gpointer user_data)
{
GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data);
GabbleMucFactoryPrivate *priv = fac->priv;
+ TpBaseChannel *base = TP_BASE_CHANNEL (chan);
TpHandle room_handle;
- tp_channel_manager_emit_channel_closed_for_object (fac,
- TP_EXPORTABLE_CHANNEL (chan));
+ /* channel is actually reappearing, announce it */
+ if (tp_base_channel_is_respawning (base))
+ {
+ tp_channel_manager_emit_new_channel (fac,
+ TP_EXPORTABLE_CHANNEL (chan), NULL);
+ return;
+ }
- if (priv->text_channels != NULL)
+ if (tp_base_channel_is_registered (base))
+ {
+ tp_channel_manager_emit_channel_closed_for_object (fac,
+ TP_EXPORTABLE_CHANNEL (chan));
+ }
+
+ if (tp_base_channel_is_destroyed (base)
+ && priv->text_channels != NULL)
{
g_object_get (chan, "handle", &room_handle, NULL);
DEBUG ("removing MUC channel with handle %d", room_handle);
- gabble_muc_channel_close_tube (chan);
-
g_hash_table_remove (priv->text_channels, GUINT_TO_POINTER (room_handle));
}
}
@@ -262,86 +266,56 @@ muc_ready_cb (GabbleMucChannel *text_chan,
{
GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data);
GabbleMucFactoryPrivate *priv = fac->priv;
- GabbleTubesChannel *tubes_chan;
- GSList *requests_satisfied_text, *requests_satisfied_tubes = NULL;
- gboolean text_requested;
- GSList *tube_channels, *l;
+ GHashTable *channels;
+ TpBaseChannel *base = TP_BASE_CHANNEL (text_chan);
+
+ GSList *requests_satisfied_text = NULL;
+ GQueue *tube_channels;
DEBUG ("text chan=%p", text_chan);
- g_object_get (text_chan, "requested", &text_requested, NULL);
+ channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_slist_free);
requests_satisfied_text = g_hash_table_lookup (
priv->queued_requests, text_chan);
g_hash_table_steal (priv->queued_requests, text_chan);
requests_satisfied_text = g_slist_reverse (requests_satisfied_text);
- tubes_chan = g_hash_table_lookup (priv->text_needed_for_tubes, text_chan);
- g_hash_table_remove (priv->text_needed_for_tubes, text_chan);
-
- if (tubes_chan != NULL)
- {
- requests_satisfied_tubes = g_hash_table_lookup (
- priv->queued_requests, tubes_chan);
- g_hash_table_steal (priv->queued_requests, tubes_chan);
- }
-
/* Announce tube channels now */
- /* FIXME: we should probably aggregate tube announcement with tubes and text
- * ones in some cases. */
- tube_channels = g_hash_table_lookup (priv->tubes_needed_for_tube,
- tubes_chan);
-
- tube_channels = g_slist_reverse (tube_channels);
- for (l = tube_channels; l != NULL; l = g_slist_next (l))
+ tube_channels = g_hash_table_lookup (priv->text_needed_for_tube, text_chan);
+ if (tube_channels != NULL)
{
- GabbleTubeIface *tube_chan = GABBLE_TUBE_IFACE (l->data);
- GSList *requests_satisfied_tube;
+ GList *l;
- requests_satisfied_tube = g_hash_table_lookup (priv->queued_requests,
- tube_chan);
- g_hash_table_steal (priv->queued_requests, tube_chan);
- requests_satisfied_tube = g_slist_reverse (requests_satisfied_tube);
+ for (l = tube_channels->head; l != NULL; l = l->next)
+ {
+ GabbleTubeIface *tube_chan = GABBLE_TUBE_IFACE (l->data);
+ GSList *requests_satisfied_tube;
- tp_channel_manager_emit_new_channel (fac,
- TP_EXPORTABLE_CHANNEL (tube_chan), requests_satisfied_tube);
+ requests_satisfied_tube = g_hash_table_lookup (
+ priv->queued_requests, tube_chan);
+ g_hash_table_steal (priv->queued_requests, tube_chan);
+ requests_satisfied_tube = g_slist_reverse (requests_satisfied_tube);
- g_slist_free (requests_satisfied_tube);
+ g_hash_table_insert (channels, tube_chan, requests_satisfied_tube);
+ }
+
+ g_hash_table_remove (priv->text_needed_for_tube, text_chan);
}
- if (tubes_chan == NULL || text_requested)
+ /* only announce channels which are on the bus (requested or
+ * requested with an invite, not channels only around because they
+ * have to be) */
+ if (tp_base_channel_is_registered (base))
{
- /* There is no tubes channel or the text channel has been explicitely
- * requested. In both cases, the text channel has to be announced
- * separately. */
-
- /* announce text channel */
tp_channel_manager_emit_new_channel (fac,
TP_EXPORTABLE_CHANNEL (text_chan), requests_satisfied_text);
-
- if (tubes_chan != NULL)
- {
- tp_channel_manager_emit_new_channel (fac,
- TP_EXPORTABLE_CHANNEL (tubes_chan), requests_satisfied_tubes);
- }
}
- else
- {
- /* Announce text and tubes text_chan together */
- GHashTable *channels;
- channels = g_hash_table_new (g_direct_hash, g_direct_equal);
- g_hash_table_insert (channels, text_chan, requests_satisfied_text);
- g_hash_table_insert (channels, tubes_chan, requests_satisfied_tubes);
+ tp_channel_manager_emit_new_channels (fac, channels);
- tp_channel_manager_emit_new_channels (fac, channels);
-
- g_hash_table_unref (channels);
- }
-
- g_hash_table_remove (priv->tubes_needed_for_tube, tubes_chan);
- g_slist_free (requests_satisfied_text);
- g_slist_free (requests_satisfied_tubes);
+ g_hash_table_unref (channels);
}
static void
@@ -351,7 +325,7 @@ muc_join_error_cb (GabbleMucChannel *chan,
{
GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data);
GabbleMucFactoryPrivate *priv = fac->priv;
- GabbleTubesChannel *tubes_chan;
+ GQueue *tube_channels;
GSList *requests_satisfied;
GSList *iter;
@@ -369,23 +343,32 @@ muc_join_error_cb (GabbleMucChannel *chan,
g_slist_free (requests_satisfied);
- tubes_chan = g_hash_table_lookup (priv->text_needed_for_tubes, chan);
+ /* tube channels */
+ tube_channels = g_hash_table_lookup (priv->text_needed_for_tube, chan);
- if (tubes_chan != NULL)
+ if (tube_channels != NULL)
{
- g_hash_table_remove (priv->text_needed_for_tubes, chan);
+ GList *l;
- requests_satisfied = g_slist_reverse (g_hash_table_lookup (
- priv->queued_requests, tubes_chan));
- g_hash_table_steal (priv->queued_requests, tubes_chan);
-
- for (iter = requests_satisfied; iter != NULL; iter = iter->next)
+ for (l = tube_channels->head; l != NULL; l = l->next)
{
- tp_channel_manager_emit_request_failed (fac, iter->data,
- error->domain, error->code, error->message);
+ GabbleTubeIface *tube_chan = GABBLE_TUBE_IFACE (l->data);
+
+ requests_satisfied = g_hash_table_lookup (
+ priv->queued_requests, tube_chan);
+ g_hash_table_steal (priv->queued_requests, tube_chan);
+ requests_satisfied = g_slist_reverse (requests_satisfied);
+
+ for (iter = requests_satisfied; iter != NULL; iter = iter->next)
+ {
+ tp_channel_manager_emit_request_failed (fac, iter->data,
+ error->domain, error->code, error->message);
+ }
+
+ g_slist_free (requests_satisfied);
}
- g_slist_free (requests_satisfied);
+ g_hash_table_remove (priv->text_needed_for_tube, chan);
}
}
@@ -394,9 +377,23 @@ muc_sub_channel_closed_cb (TpSvcChannel *chan,
gpointer user_data)
{
GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data);
+ GabbleMucChannel *muc;
tp_channel_manager_emit_channel_closed_for_object (fac,
TP_EXPORTABLE_CHANNEL (chan));
+
+ /* GabbleTubeDBus, GabbleTubeStream, and GabbleMucCallChannel all
+ * have "muc" properties. */
+ g_object_get (chan,
+ "muc", &muc,
+ NULL);
+
+ if (muc == NULL)
+ return;
+
+ if (gabble_muc_channel_can_be_closed (muc)
+ && gabble_muc_channel_get_autoclose (muc))
+ tp_base_channel_close (TP_BASE_CHANNEL (muc));
}
#ifdef ENABLE_VOIP
@@ -420,19 +417,18 @@ muc_channel_new_call (GabbleMucChannel *muc,
static void
muc_channel_new_tube (GabbleMucChannel *channel,
- GabbleTubesChannel *tube,
+ GabbleTubeIface *tube,
gpointer user_data)
{
GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data);
- GabbleMucFactoryPrivate *priv = fac->priv;
- /* If the muc channel is ready announce the tubes channel right away
+ /* If the muc channel is ready announce the tube channel right away
* otherwise wait for the text channel to be ready */
if (_gabble_muc_channel_is_ready (channel))
tp_channel_manager_emit_new_channel (fac,
- TP_EXPORTABLE_CHANNEL (tube), NULL);
+ TP_EXPORTABLE_CHANNEL (tube), NULL);
else
- g_hash_table_insert (priv->text_needed_for_tubes, channel, tube);
+ gabble_muc_factory_associate_tube (fac, channel, tube);
g_signal_connect (tube, "closed",
G_CALLBACK (muc_sub_channel_closed_cb), fac);
@@ -448,6 +444,7 @@ new_muc_channel (GabbleMucFactory *fac,
TpHandle inviter,
const gchar *message,
gboolean requested,
+ gboolean initially_register,
GHashTable *initial_channels,
GArray *initial_handles,
char **initial_ids,
@@ -459,11 +456,10 @@ new_muc_channel (GabbleMucFactory *fac,
char *object_path;
GPtrArray *initial_channels_array = NULL;
- g_assert (g_hash_table_lookup (priv->text_channels,
- GUINT_TO_POINTER (handle)) == NULL);
+ g_assert (gabble_muc_factory_find_text_channel (fac, handle) == NULL);
object_path = g_strdup_printf ("%s/MucChannel%u",
- conn->object_path, handle);
+ tp_base_connection_get_object_path (conn), handle);
initial_channels_array = g_ptr_array_new ();
if (initial_channels != NULL)
@@ -490,13 +486,15 @@ new_muc_channel (GabbleMucFactory *fac,
"object-path", object_path,
"handle", handle,
"invited", invited,
- "initiator-handle", invited ? inviter : conn->self_handle,
+ "initiator-handle",
+ invited ? inviter : tp_base_connection_get_self_handle (conn),
"invitation-message", message,
"requested", requested,
"initial-channels", initial_channels_array,
"initial-invitee-handles", initial_handles,
"initial-invitee-ids", initial_ids,
"room-name", room_name,
+ "initially-register", initially_register,
NULL);
g_signal_connect (chan, "closed", (GCallback) muc_channel_closed_cb, fac);
@@ -523,8 +521,6 @@ new_muc_channel (GabbleMucFactory *fac,
return chan;
}
-// tubes_channel_closed_cb
-
static void
do_invite (GabbleMucFactory *fac,
const gchar *room,
@@ -545,18 +541,15 @@ do_invite (GabbleMucFactory *fac,
return;
}
- if (g_hash_table_lookup (priv->text_channels,
- GUINT_TO_POINTER (room_handle)) == NULL)
+ if (gabble_muc_factory_find_text_channel (fac, room_handle) == NULL)
{
- new_muc_channel (fac, room_handle, TRUE, inviter_handle, reason, FALSE,
- NULL, NULL, NULL, NULL);
+ new_muc_channel (fac, room_handle, TRUE, inviter_handle, reason,
+ FALSE, TRUE, NULL, NULL, NULL, NULL);
}
else
{
DEBUG ("ignoring invite to room \"%s\"; we're already there", room);
}
-
- tp_handle_unref (room_repo, room_handle);
}
struct DiscoInviteData {
@@ -584,8 +577,6 @@ obsolete_invite_disco_cb (GabbleDisco *self,
GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data->factory);
GabbleMucFactoryPrivate *priv = fac->priv;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
WockyNode *identity;
const char *category = NULL, *type = NULL;
@@ -617,7 +608,6 @@ obsolete_invite_disco_cb (GabbleDisco *self,
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);
}
@@ -690,8 +680,6 @@ process_muc_invite (GabbleMucFactory *fac,
do_invite (fac, room, inviter_handle, reason);
g_free (room);
- tp_handle_unref (contact_repo, inviter_handle);
-
return TRUE;
}
@@ -769,7 +757,6 @@ process_obsolete_invite (GabbleMucFactory *fac,
{
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);
}
@@ -843,6 +830,25 @@ gabble_muc_factory_broadcast_presence (GabbleMucFactory *self)
}
static void
+gabble_muc_factory_associate_tube (GabbleMucFactory *self,
+ GabbleMucChannel *gmuc,
+ GabbleTubeIface *tube)
+{
+ GabbleMucFactoryPrivate *priv = self->priv;
+ GQueue *queue;
+
+ queue = g_hash_table_lookup (priv->text_needed_for_tube, gmuc);
+
+ if (queue == NULL)
+ {
+ queue = g_queue_new ();
+ g_hash_table_insert (priv->text_needed_for_tube, gmuc, queue);
+ }
+
+ g_queue_push_tail (queue, tube);
+}
+
+static void
gabble_muc_factory_associate_request (GabbleMucFactory *self,
gpointer channel,
gpointer request)
@@ -858,13 +864,11 @@ gabble_muc_factory_associate_request (GabbleMucFactory *self,
}
-static gboolean
-cancel_queued_requests (gpointer k,
- gpointer v,
- gpointer d)
+static void
+cancel_queued_requests (
+ GabbleMucFactory *self,
+ GSList *requests_satisfied)
{
- GabbleMucFactory *self = GABBLE_MUC_FACTORY (d);
- GSList *requests_satisfied = v;
GSList *iter;
requests_satisfied = g_slist_reverse (requests_satisfied);
@@ -872,13 +876,11 @@ cancel_queued_requests (gpointer k,
for (iter = requests_satisfied; iter != NULL; iter = iter->next)
{
tp_channel_manager_emit_request_failed (self,
- iter->data, TP_ERRORS, TP_ERROR_DISCONNECTED,
+ iter->data, TP_ERROR, TP_ERROR_DISCONNECTED,
"Unable to complete this channel request, we're disconnecting!");
}
g_slist_free (requests_satisfied);
-
- return TRUE;
}
@@ -897,16 +899,24 @@ gabble_muc_factory_close_all (GabbleMucFactory *self)
}
if (priv->queued_requests != NULL)
- g_hash_table_foreach_steal (priv->queued_requests,
- cancel_queued_requests, self);
+ {
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, priv->queued_requests);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ cancel_queued_requests (self, value);
+ g_hash_table_iter_steal (&iter);
+ }
+ }
tp_clear_pointer (&priv->queued_requests, g_hash_table_unref);
- tp_clear_pointer (&priv->text_needed_for_tubes, g_hash_table_unref);
- tp_clear_pointer (&priv->tubes_needed_for_tube, g_hash_table_unref);
+ tp_clear_pointer (&priv->text_needed_for_tube, g_hash_table_unref);
/* Use a temporary variable because we don't want
- * muc_channel_closed_cb or tubes_channel_closed_cb to remove the channel
- * from the hash table a second time */
+ * muc_channel_closed_cb remove the channel from the hash table a
+ * second time */
if (priv->text_channels != NULL)
{
GHashTable *tmp = priv->text_channels;
@@ -979,39 +989,6 @@ gabble_muc_factory_constructor (GType type, guint n_props,
return obj;
}
-
-struct _ForeachData
-{
- TpExportableChannelFunc foreach;
- gpointer user_data;
-};
-
-static void
-_foreach_slave (gpointer key, gpointer value, gpointer user_data)
-{
- struct _ForeachData *data = (struct _ForeachData *) user_data;
- TpExportableChannel *channel = TP_EXPORTABLE_CHANNEL (value);
- GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (value);
- GabbleTubesChannel *tube = NULL;
-
- data->foreach (channel, data->user_data);
-
- g_object_get (gmuc, "tube", &tube, NULL);
-
- if (tube != NULL)
- {
- channel = TP_EXPORTABLE_CHANNEL (tube);
- data->foreach (channel, data->user_data);
- gabble_tubes_channel_foreach (tube, data->foreach, data->user_data);
- g_object_unref (tube);
- }
-
-#ifdef ENABLE_VOIP
- g_list_foreach (gabble_muc_channel_get_call_channels (gmuc),
- (GFunc) data->foreach, data->user_data);
-#endif
-}
-
static void
gabble_muc_factory_foreach_channel (TpChannelManager *manager,
TpExportableChannelFunc foreach,
@@ -1019,14 +996,24 @@ gabble_muc_factory_foreach_channel (TpChannelManager *manager,
{
GabbleMucFactory *fac = GABBLE_MUC_FACTORY (manager);
GabbleMucFactoryPrivate *priv = fac->priv;
- struct _ForeachData data;
+ GHashTableIter iter;
+ gpointer value;
- data.user_data = user_data;
- data.foreach = foreach;
+ g_hash_table_iter_init (&iter, priv->text_channels);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (value);
- g_hash_table_foreach (priv->text_channels, _foreach_slave, &data);
-}
+ foreach (TP_EXPORTABLE_CHANNEL (gmuc), user_data);
+
+ gabble_muc_channel_foreach_tubes (gmuc, foreach, user_data);
+#ifdef ENABLE_VOIP
+ g_list_foreach (gabble_muc_channel_get_call_channels (gmuc),
+ (GFunc) foreach, user_data);
+#endif
+ }
+}
/**
* ensure_muc_channel:
@@ -1042,6 +1029,7 @@ ensure_muc_channel (GabbleMucFactory *fac,
TpHandle handle,
GabbleMucChannel **ret,
gboolean requested,
+ gboolean export_text,
GHashTable *initial_channels,
GArray *initial_handles,
char **initial_ids,
@@ -1049,13 +1037,21 @@ ensure_muc_channel (GabbleMucFactory *fac,
{
TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
- *ret = g_hash_table_lookup (priv->text_channels, GUINT_TO_POINTER (handle));
+ *ret = gabble_muc_factory_find_text_channel (fac, handle);
if (*ret == NULL)
{
- *ret = new_muc_channel (fac, handle, FALSE, base_conn->self_handle, NULL,
- requested, initial_channels, initial_handles, initial_ids, room_name);
- return FALSE;
+ *ret = new_muc_channel (fac, handle, FALSE,
+ tp_base_connection_get_self_handle (base_conn),
+ NULL, requested, export_text, initial_channels,
+ initial_handles, initial_ids, room_name);
+
+ gabble_muc_channel_set_autoclose (*ret, !export_text);
+ }
+ else
+ {
+ if (export_text)
+ gabble_muc_channel_set_autoclose (*ret, FALSE);
}
if (_gabble_muc_channel_is_ready (*ret))
@@ -1076,26 +1072,29 @@ gabble_muc_factory_handle_si_stream_request (GabbleMucFactory *self,
TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM);
GabbleMucChannel *gmuc = NULL;
- GabbleTubesChannel *tube = NULL;
+ WockyStanzaType stanza_type;
+ WockyStanzaSubType sub_type;
g_return_if_fail (tp_handle_is_valid (room_repo, room_handle, NULL));
- gmuc = g_hash_table_lookup (priv->text_channels,
- GUINT_TO_POINTER (room_handle));
- g_object_get (gmuc, "tube", &tube, NULL);
+ wocky_stanza_get_type_info (msg, &stanza_type, &sub_type);
+ g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_IQ);
+ g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET);
- if (tube == NULL)
+ gmuc = gabble_muc_factory_find_text_channel (self, room_handle);
+
+ if (gmuc == NULL)
{
GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "No tubes channel available for this MUC" };
+ "No MUC channel available" };
- DEBUG ("tubes channel doesn't exist for muc %d", room_handle);
+ DEBUG ("MUC channel doesn't exist handle %d", room_handle);
gabble_bytestream_iface_close (bytestream, &e);
return;
}
- gabble_tubes_channel_bytestream_offered (tube, bytestream, msg);
- g_object_unref (tube);
+ gabble_muc_channel_handle_si_stream_request (
+ gmuc, bytestream, stream_id, msg);
}
GabbleMucChannel *
@@ -1129,12 +1128,6 @@ static const gchar * const muc_channel_allowed_properties[] = {
NULL
};
-static const gchar * const muc_tubes_channel_allowed_properties[] = {
- TP_PROP_CHANNEL_TARGET_HANDLE,
- TP_PROP_CHANNEL_TARGET_ID,
- NULL
-};
-
static void
gabble_muc_factory_type_foreach_channel_class (GType type,
TpChannelManagerTypeChannelClassFunc func,
@@ -1159,11 +1152,6 @@ gabble_muc_factory_type_foreach_channel_class (GType type,
func (type, table, muc_channel_allowed_properties,
user_data);
- /* Channel.Type.Tubes */
- g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_TUBES);
- func (type, table, muc_tubes_channel_allowed_properties,
- user_data);
-
/* Muc Channel.Type.StreamTube */
g_value_set_static_string (channel_type_value,
TP_IFACE_CHANNEL_TYPE_STREAM_TUBE);
@@ -1188,31 +1176,6 @@ gabble_muc_factory_type_foreach_channel_class (GType type,
g_hash_table_unref (table);
}
-/* return TRUE if the text_channel associated is ready */
-static gboolean
-ensure_tubes_channel (GabbleMucFactory *self,
- TpHandle handle,
- GabbleTubesChannel **tubes_chan,
- gboolean requested)
-{
- GabbleMucFactoryPrivate *priv = self->priv;
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
- GabbleMucChannel *text_chan;
- TpHandle initiator = base_conn->self_handle;
- gboolean result;
-
- result = ensure_muc_channel (self, priv, handle, &text_chan, FALSE,
- NULL, NULL, NULL, NULL);
-
- /* this refs the tube channel object */
- *tubes_chan = gabble_muc_channel_open_tube (text_chan, initiator, requested);
-
- if (!result)
- g_hash_table_insert (priv->text_needed_for_tubes, text_chan, *tubes_chan);
-
- return result;
-}
-
static gboolean
handle_text_channel_request (GabbleMucFactory *self,
gpointer request_token,
@@ -1225,7 +1188,7 @@ handle_text_channel_request (GabbleMucFactory *self,
TpBaseConnection *conn = TP_BASE_CONNECTION (priv->conn);
GabbleMucChannel *text_chan;
TpHandleSet *handles;
- TpIntSet *continue_handles;
+ TpIntset *continue_handles;
guint i;
gboolean ret = TRUE;
@@ -1279,7 +1242,7 @@ handle_text_channel_request (GabbleMucFactory *self,
const char *object_path = g_ptr_array_index (initial_channels, i);
GObject *object;
TpHandle handle;
- GabbleConnection *connection;
+ TpBaseConnection *connection;
object = dbus_g_connection_lookup_g_object (bus, object_path);
@@ -1290,19 +1253,19 @@ handle_text_channel_request (GabbleMucFactory *self,
continue;
}
- g_object_get (object,
- "connection", &connection,
- "handle", &handle,
- NULL);
- g_object_unref (connection); /* drop the ref immediately */
+ connection = tp_base_channel_get_connection (
+ TP_BASE_CHANNEL (object));
- if (connection != priv->conn)
+ if ((GabbleConnection *) connection != priv->conn)
{
DEBUG ("Channel %s is from a different Connection, ignoring",
object_path);
continue;
}
+ handle = tp_base_channel_get_target_handle (
+ TP_BASE_CHANNEL (object));
+
tp_handle_set_add (handles, handle);
tp_intset_add (continue_handles, handle);
g_hash_table_insert (final_channels, (char *) object_path, NULL);
@@ -1343,7 +1306,6 @@ handle_text_channel_request (GabbleMucFactory *self,
}
tp_handle_set_add (handles, handle);
- tp_handle_unref (contact_handles, handle);
}
}
@@ -1418,11 +1380,6 @@ handle_text_channel_request (GabbleMucFactory *self,
goto out;
}
}
- else
- {
- /* ref room here so we can unref it again, below */
- tp_handle_ref (room_handles, room);
- }
/* Make sure TargetID and RoomName don't conflict. */
if (room_name != NULL && room_name[0] != '\0')
@@ -1439,7 +1396,7 @@ handle_text_channel_request (GabbleMucFactory *self,
if (!ok)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"TargetID's node part (%s) doesn't match RoomName (%s)",
target_room, room_name);
ret = FALSE;
@@ -1469,7 +1426,7 @@ handle_text_channel_request (GabbleMucFactory *self,
if (!ok)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"TargetID's domain part (%s) doesn't match Server (%s)",
target_server, server_prop);
ret = FALSE;
@@ -1482,14 +1439,15 @@ handle_text_channel_request (GabbleMucFactory *self,
}
- if (ensure_muc_channel (self, priv, room, &text_chan, TRUE,
+ if (ensure_muc_channel (self, priv, room, &text_chan, TRUE, TRUE,
final_channels, final_handles, final_ids, room_name))
{
/* channel exists */
- if (require_new)
+ if (require_new
+ && tp_base_channel_is_registered (TP_BASE_CHANNEL (text_chan)))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"That channel has already been created (or requested)");
ret = FALSE;
}
@@ -1499,15 +1457,30 @@ handle_text_channel_request (GabbleMucFactory *self,
initial_handles != NULL ||
initial_ids != NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Cannot set InitialChannels, InitialInviteeHandles or "
"InitialInviteIDs for existing channel");
ret = FALSE;
}
else
{
- tp_channel_manager_emit_request_already_satisfied (self,
- request_token, TP_EXPORTABLE_CHANNEL (text_chan));
+ if (tp_base_channel_is_registered (TP_BASE_CHANNEL (text_chan)))
+ {
+ tp_channel_manager_emit_request_already_satisfied (self,
+ request_token, TP_EXPORTABLE_CHANNEL (text_chan));
+ }
+ else
+ {
+ GSList *tokens;
+
+ tp_base_channel_register (TP_BASE_CHANNEL (text_chan));
+
+ tokens = g_slist_append (NULL, request_token);
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (text_chan), tokens);
+ g_slist_free (tokens);
+ }
+
ret = TRUE;
}
}
@@ -1546,9 +1519,6 @@ handle_text_channel_request (GabbleMucFactory *self,
}
out:
- if (room != 0)
- tp_handle_unref (room_handles, room);
-
g_hash_table_unref (final_channels);
g_array_unref (final_handles);
g_free (final_ids);
@@ -1560,62 +1530,6 @@ out:
}
static gboolean
-handle_tubes_channel_request (GabbleMucFactory *self,
- gpointer request_token,
- GHashTable *request_properties,
- gboolean require_new,
- TpHandle handle,
- GError **error)
-{
- GabbleMucFactoryPrivate *priv = self->priv;
- GabbleTubesChannel *tube = NULL;
- GabbleMucChannel *gmuc = NULL;
-
- if (tp_channel_manager_asv_has_unknown_properties (request_properties,
- muc_tubes_channel_fixed_properties,
- muc_tubes_channel_allowed_properties,
- error))
- return FALSE;
-
- gmuc = g_hash_table_lookup (priv->text_channels, GUINT_TO_POINTER (handle));
-
- if (gmuc != NULL)
- g_object_get (gmuc, "tube", &tube, NULL);
-
- if (tube != NULL)
- {
- if (require_new)
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "That channel has already been created (or requested)");
- return FALSE;
- }
- else
- {
- tp_channel_manager_emit_request_already_satisfied (self,
- request_token, TP_EXPORTABLE_CHANNEL (tube));
- }
- }
- else if (ensure_tubes_channel (self, handle, &tube, TRUE))
- {
- GSList *list = NULL;
-
- list = g_slist_prepend (list, request_token);
- tp_channel_manager_emit_new_channel (self,
- TP_EXPORTABLE_CHANNEL (tube), list);
- g_slist_free (list);
- }
- else
- {
- gabble_muc_factory_associate_request (self, tube, request_token);
- }
-
- g_object_unref (tube);
-
- return TRUE;
-}
-
-static gboolean
handle_tube_channel_request (GabbleMucFactory *self,
gpointer request_token,
GHashTable *request_properties,
@@ -1625,63 +1539,38 @@ handle_tube_channel_request (GabbleMucFactory *self,
{
GabbleMucFactoryPrivate *priv = self->priv;
- gboolean can_announce_now = TRUE;
- gboolean tubes_channel_created = FALSE;
- GabbleTubesChannel *tube = NULL;
+ gboolean can_announce_now;
GabbleMucChannel * gmuc;
GabbleTubeIface *new_channel;
- gmuc = g_hash_table_lookup (priv->text_channels, GUINT_TO_POINTER (handle));
+ gmuc = gabble_muc_factory_find_text_channel (self, handle);
- if (gmuc != NULL)
- g_object_get (gmuc, "tube", &tube, NULL);
+ if (gmuc == NULL)
+ ensure_muc_channel (self, priv, handle, &gmuc, FALSE, FALSE,
+ NULL, NULL, NULL, NULL);
- if (tube == NULL)
- {
- /* Need to create a tubes channel */
- if (!ensure_tubes_channel (self, handle, &tube, FALSE))
- {
- /* We have to wait the tubes channel before announcing */
- can_announce_now = FALSE;
- }
-
- tubes_channel_created = TRUE;
- }
+ can_announce_now = _gabble_muc_channel_is_ready (gmuc);
- g_assert (tube != NULL);
+ new_channel = gabble_muc_channel_tube_request (gmuc, request_token,
+ request_properties, TRUE);
- new_channel = gabble_tubes_channel_tube_request (tube,
- request_token, request_properties, TRUE);
- g_assert (new_channel != NULL);
+ g_signal_connect (new_channel, "closed",
+ G_CALLBACK (muc_sub_channel_closed_cb), self);
if (can_announce_now)
{
- GHashTable *channels;
GSList *request_tokens;
- channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
-
- if (tubes_channel_created)
- g_hash_table_insert (channels, tube, NULL);
-
request_tokens = g_slist_prepend (NULL, request_token);
- g_hash_table_insert (channels, new_channel, request_tokens);
- tp_channel_manager_emit_new_channels (self, channels);
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (new_channel), request_tokens);
- g_hash_table_unref (channels);
g_slist_free (request_tokens);
}
else
{
- GSList *l;
-
- l = g_hash_table_lookup (priv->tubes_needed_for_tube, tube);
- g_hash_table_steal (priv->tubes_needed_for_tube, tube);
-
- l = g_slist_prepend (l, new_channel);
- g_hash_table_insert (priv->tubes_needed_for_tube, tube, l);
+ gabble_muc_factory_associate_tube (self, gmuc, new_channel);
/* And now finally associate the new stream or dbus tube channel with
* the request token so that when the muc channel is ready, the request
@@ -1689,8 +1578,6 @@ handle_tube_channel_request (GabbleMucFactory *self,
gabble_muc_factory_associate_request (self, new_channel, request_token);
}
- g_object_unref (tube);
-
return TRUE;
}
@@ -1715,7 +1602,7 @@ handle_stream_tube_channel_request (GabbleMucFactory *self,
TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
if (service == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Request does not contain the mandatory property '%s'",
TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
return FALSE;
@@ -1746,7 +1633,7 @@ handle_dbus_tube_channel_request (GabbleMucFactory *self,
TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME);
if (service == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Request does not contain the mandatory property '%s'",
TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME);
return FALSE;
@@ -1810,12 +1697,12 @@ handle_call_channel_request (GabbleMucFactory *self,
if (!initial_audio && !initial_video)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Request didn't set either InitialAudio or InitialVideo");
return FALSE;
}
- ensure_muc_channel (self, priv, handle, &muc, FALSE, NULL, NULL, NULL, NULL);
+ ensure_muc_channel (self, priv, handle, &muc, FALSE, FALSE, NULL, NULL, NULL, NULL);
call = gabble_muc_channel_get_call (muc);
@@ -1823,7 +1710,7 @@ handle_call_channel_request (GabbleMucFactory *self,
{
if (require_new)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"There is already a call in this muc");
goto error;
}
@@ -1870,7 +1757,6 @@ typedef struct {
static ChannelTypeHandler channel_type_handlers[] = {
{ TP_IFACE_CHANNEL_TYPE_TEXT, handle_text_channel_request },
- { TP_IFACE_CHANNEL_TYPE_TUBES, handle_tubes_channel_request },
{ TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, handle_stream_tube_channel_request },
{ TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, handle_dbus_tube_channel_request },
#ifdef ENABLE_VOIP
@@ -1980,7 +1866,7 @@ gabble_muc_factory_ensure_channel (TpChannelManager *manager,
#ifdef ENABLE_VOIP
gboolean
gabble_muc_factory_handle_jingle_session (GabbleMucFactory *self,
- GabbleJingleSession *session)
+ WockyJingleSession *session)
{
GabbleMucFactoryPrivate *priv = self->priv;
TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
@@ -1988,14 +1874,13 @@ gabble_muc_factory_handle_jingle_session (GabbleMucFactory *self,
TpHandle room;
room = gabble_get_room_handle_from_jid (room_repo,
- gabble_jingle_session_get_peer_jid (session));
+ wocky_jingle_session_get_peer_jid (session));
if (room != 0)
{
GabbleMucChannel *channel;
- channel = g_hash_table_lookup (priv->text_channels,
- GUINT_TO_POINTER (room));
+ channel = gabble_muc_factory_find_text_channel (self, room);
g_assert (GABBLE_IS_MUC_CHANNEL (channel));
if (channel != NULL)
diff --git a/src/muc-factory.h b/src/muc-factory.h
index 23c635458..507ae5298 100644
--- a/src/muc-factory.h
+++ b/src/muc-factory.h
@@ -26,9 +26,6 @@
#include <wocky/wocky.h>
#include "bytestream-iface.h"
-#ifdef ENABLE_VOIP
-#include "jingle-types.h"
-#endif
#include "types.h"
G_BEGIN_DECLS
@@ -76,7 +73,7 @@ void gabble_muc_factory_broadcast_presence (GabbleMucFactory *self);
#ifdef ENABLE_VOIP
gboolean gabble_muc_factory_handle_jingle_session (GabbleMucFactory *self,
- GabbleJingleSession *session);
+ WockyJingleSession *session);
#endif
G_END_DECLS
diff --git a/src/muc-tube-dbus.c b/src/muc-tube-dbus.c
index 2aa61fc82..6ba1d827f 100644
--- a/src/muc-tube-dbus.c
+++ b/src/muc-tube-dbus.c
@@ -18,16 +18,24 @@
*/
#include "config.h"
+
#include "muc-tube-dbus.h"
G_DEFINE_TYPE (GabbleMucTubeDBus, gabble_muc_tube_dbus,
GABBLE_TYPE_TUBE_DBUS)
-static const gchar *gabble_muc_tube_dbus_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- TP_IFACE_CHANNEL_INTERFACE_TUBE,
- NULL
-};
+static GPtrArray *
+gabble_muc_tube_dbus_get_interfaces (TpBaseChannel *base)
+{
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CHANNEL_CLASS (
+ gabble_muc_tube_dbus_parent_class)->get_interfaces (base);
+
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_GROUP);
+
+ return interfaces;
+}
static void
gabble_muc_tube_dbus_init (GabbleMucTubeDBus *self)
@@ -41,6 +49,6 @@ gabble_muc_tube_dbus_class_init (
TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (
gabble_muc_tube_dbus_class);
- base_class->interfaces = gabble_muc_tube_dbus_interfaces;
+ base_class->get_interfaces = gabble_muc_tube_dbus_get_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_ROOM;
}
diff --git a/src/muc-tube-stream.c b/src/muc-tube-stream.c
index 3700c46f6..96448ab2b 100644
--- a/src/muc-tube-stream.c
+++ b/src/muc-tube-stream.c
@@ -18,16 +18,24 @@
*/
#include "config.h"
+
#include "muc-tube-stream.h"
G_DEFINE_TYPE (GabbleMucTubeStream, gabble_muc_tube_stream,
GABBLE_TYPE_TUBE_STREAM)
-static const gchar *gabble_muc_tube_stream_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- TP_IFACE_CHANNEL_INTERFACE_TUBE,
- NULL
-};
+static GPtrArray *
+gabble_muc_tube_stream_get_interfaces (TpBaseChannel *base)
+{
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CHANNEL_CLASS (
+ gabble_muc_tube_stream_parent_class)->get_interfaces (base);
+
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_GROUP);
+
+ return interfaces;
+}
static void
gabble_muc_tube_stream_init (GabbleMucTubeStream *self)
@@ -41,6 +49,6 @@ gabble_muc_tube_stream_class_init (
TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (
gabble_muc_tube_stream_class);
- base_class->interfaces = gabble_muc_tube_stream_interfaces;
+ base_class->get_interfaces = gabble_muc_tube_stream_get_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_ROOM;
}
diff --git a/src/namespaces.h b/src/namespaces.h
index 13ae5dbb6..2a2d8f91b 100644
--- a/src/namespaces.h
+++ b/src/namespaces.h
@@ -103,6 +103,7 @@
#define NS_PRESENCE_INVISIBLE "presence-invisible"
#define NS_PRIVACY "jabber:iq:privacy"
#define NS_INVISIBLE "urn:xmpp:invisible:0"
+#define NS_RECEIPTS "urn:xmpp:receipts"
#define NS_REGISTER "jabber:iq:register"
#define NS_ROSTER "jabber:iq:roster"
#define NS_SEARCH "jabber:iq:search"
@@ -135,4 +136,8 @@
#define NS_TP_FT_METADATA_SERVICE "http://telepathy.freedesktop.org/xmpp/file-transfer-service"
#define NS_TP_FT_METADATA "http://telepathy.freedesktop.org/xmpp/file-transfer-metadata"
+/* This is used by WLM to convert Windows Live ID to XMPP jid.
+ * See http://msdn.microsoft.com/en-us/library/live/hh550849.aspx */
+#define NS_WLM_JID_LOOKUP "http://messenger.live.com/xmpp/jidlookup"
+
#endif /* __GABBLE_NAMESPACES__H__ */
diff --git a/src/olpc-activity.c b/src/olpc-activity.c
index 1c5f7d3af..a5f34a581 100644
--- a/src/olpc-activity.c
+++ b/src/olpc-activity.c
@@ -18,6 +18,7 @@
*/
#include "config.h"
+
#include "olpc-activity.h"
#include <stdlib.h>
@@ -64,26 +65,6 @@ gabble_olpc_activity_init (GabbleOlpcActivity *self)
}
static void
-gabble_olpc_activity_dispose (GObject *object)
-{
- GabbleOlpcActivity *self = GABBLE_OLPC_ACTIVITY (object);
- GabbleOlpcActivityPrivate *priv = self->priv;
- TpHandleRepoIface *room_repo;
-
- if (priv->dispose_has_run)
- return;
-
- room_repo = tp_base_connection_get_handles ((TpBaseConnection *) priv->conn,
- TP_HANDLE_TYPE_ROOM);
- tp_handle_unref (room_repo, self->room);
-
- priv->dispose_has_run = TRUE;
-
- if (G_OBJECT_CLASS (gabble_olpc_activity_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_olpc_activity_parent_class)->dispose (object);
-}
-
-static void
gabble_olpc_activity_finalize (GObject *object)
{
GabbleOlpcActivity *self = GABBLE_OLPC_ACTIVITY (object);
@@ -172,23 +153,14 @@ gabble_olpc_activity_constructor (GType type,
{
GObject *obj;
GabbleOlpcActivity *self;
- GabbleOlpcActivityPrivate *priv;
- TpHandleRepoIface *room_repo;
obj = G_OBJECT_CLASS (gabble_olpc_activity_parent_class)->
constructor (type, n_props, props);
self = GABBLE_OLPC_ACTIVITY (obj);
- priv = self->priv;
-
- room_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn,
- TP_HANDLE_TYPE_ROOM);
g_assert (self->room != 0);
- tp_handle_ref (room_repo, self->room);
-
DEBUG ("new activity %s (%d)", gabble_olpc_activity_get_room (self),
self->room);
@@ -209,7 +181,6 @@ gabble_olpc_activity_class_init (
g_type_class_add_private (gabble_olpc_activity_class,
sizeof (GabbleOlpcActivityPrivate));
- object_class->dispose = gabble_olpc_activity_dispose;
object_class->finalize = gabble_olpc_activity_finalize;
param_spec = g_param_spec_object (
diff --git a/src/olpc-activity.h b/src/olpc-activity.h
index 47101bd66..4c08df6cf 100644
--- a/src/olpc-activity.h
+++ b/src/olpc-activity.h
@@ -22,8 +22,7 @@
#include <glib-object.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/handle-repo.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "connection.h"
diff --git a/src/plugin-connection.c b/src/plugin-connection.c
index 0d0d95e9f..dcbb74bc6 100644
--- a/src/plugin-connection.c
+++ b/src/plugin-connection.c
@@ -23,7 +23,7 @@
#include <glib-object.h>
#include <gabble/types.h>
-#include <telepathy-glib/errors.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <debug.h>
diff --git a/src/plugin-loader.c b/src/plugin-loader.c
index dedc724ad..d308437ee 100644
--- a/src/plugin-loader.c
+++ b/src/plugin-loader.c
@@ -28,8 +28,7 @@
# include <gmodule.h>
#endif
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/presence-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
#define DEBUG_FLAG GABBLE_DEBUG_PLUGINS
#include "debug.h"
@@ -301,7 +300,7 @@ gabble_plugin_loader_create_sidecar (
}
g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data,
- TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "No plugin implements sidecar '%s'",
+ TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "No plugin implements sidecar '%s'",
sidecar_interface);
}
diff --git a/src/plugin-loader.h b/src/plugin-loader.h
index 15bce505e..985cccbc5 100644
--- a/src/plugin-loader.h
+++ b/src/plugin-loader.h
@@ -23,8 +23,7 @@
#include <glib-object.h>
#include <gio/gio.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/presence-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
#include "gabble/sidecar.h"
diff --git a/src/plugin.c b/src/plugin.c
index 2003d3e87..2ddd23ea6 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -22,9 +22,7 @@
#include "gabble/plugin.h"
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/presence-mixin.h>
-#include <telepathy-glib/util.h>
+#include <telepathy-glib/telepathy-glib.h>
#define DEBUG_FLAG GABBLE_DEBUG_PLUGINS
#include "debug.h"
@@ -110,17 +108,17 @@ gabble_plugin_create_sidecar_async (
if (!gabble_plugin_implements_sidecar (plugin, sidecar_interface))
g_simple_async_report_error_in_idle (G_OBJECT (plugin), callback,
- user_data, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Gabble is buggy: '%s' doesn't implement sidecar %s",
iface->name, sidecar_interface);
else if (iface->create_sidecar_async == NULL)
g_simple_async_report_error_in_idle (G_OBJECT (plugin), callback,
- user_data, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"'%s' is buggy: it claims to implement %s, but does not implement "
"create_sidecar_async", iface->name, sidecar_interface);
else if (iface->create_sidecar_finish == NULL)
g_simple_async_report_error_in_idle (G_OBJECT (plugin), callback,
- user_data, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"'%s' is buggy: does not imlement create_sidecar_finish",
iface->name);
else
diff --git a/src/presence-cache.c b/src/presence-cache.c
index 72901a057..f7d02eecf 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -35,8 +35,7 @@
#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
#include <dbus/dbus-glib.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/intset.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
@@ -147,7 +146,6 @@ disco_waiter_new (TpHandleRepoIface *repo,
DiscoWaiter *waiter;
g_assert (repo);
- tp_handle_ref (repo, handle);
waiter = g_slice_new0 (DiscoWaiter);
waiter->repo = repo;
@@ -171,8 +169,6 @@ disco_waiter_free (DiscoWaiter *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_free (waiter->hash);
g_free (waiter->ver);
@@ -501,49 +497,9 @@ static void gabble_presence_cache_add_bundle_caps (GabblePresenceCache *cache,
static void
gabble_presence_cache_add_bundles (GabblePresenceCache *cache)
{
-#define GOOGLE_BUNDLE(cap, features) \
- gabble_presence_cache_add_bundle_caps (cache, \
- "http://www.google.com/xmpp/client/caps#" cap, features); \
- gabble_presence_cache_add_bundle_caps (cache, \
- "http://talk.google.com/xmpp/client/caps#" cap, features); \
- gabble_presence_cache_add_bundle_caps (cache, \
- "http://www.android.com/gtalk/client/caps#" cap, features); \
- gabble_presence_cache_add_bundle_caps (cache, \
- "http://www.android.com/gtalk/client/caps2#" cap, features); \
- gabble_presence_cache_add_bundle_caps (cache, \
- "http://talk.google.com/xmpp/bot/caps#" cap, features);
-
- /* Cache various bundle from the Google Talk clients as trusted. Some old
- * versions of Google Talk do not reply correctly to discovery requests.
- * Plus, we know what Google's bundles mean, so it's a waste of time to disco
- * them, particularly the ones for features we don't support. The desktop
- * client doesn't currently have all of these, but it doesn't hurt to cache
- * them anyway.
- */
- GOOGLE_BUNDLE ("voice-v1", NS_GOOGLE_FEAT_VOICE);
- GOOGLE_BUNDLE ("video-v1", NS_GOOGLE_FEAT_VIDEO);
- GOOGLE_BUNDLE ("camera-v1", NS_GOOGLE_FEAT_CAMERA);
-
- /* File transfer support */
- GOOGLE_BUNDLE ("share-v1", NS_GOOGLE_FEAT_SHARE);
-
- /* Not really sure what this ones is. */
- GOOGLE_BUNDLE ("sms-v1", NULL);
-
- /* TODO: remove this when we fix fd.o#22768. */
- GOOGLE_BUNDLE ("pmuc-v1", NULL);
-
- /* The camera-v1 bundle seems to mean "I have a camera plugged in". Not
- * having it doesn't seem to affect anything, and we have no way of exposing
- * that information anyway.
- */
- GOOGLE_BUNDLE ("camera-v1", NULL);
-
-#undef GOOGLE_BUNDLE
-
- /* We should also cache the ext='' bundles Gabble advertises: older Gabbles
- * advertise these and don't support hashed caps, and we shouldn't need to
- * disco them.
+ /* We cache the ext='' bundles Gabble advertises: older Gabbles
+ * advertise these and don't support hashed caps, and we shouldn't
+ * need to disco them.
*/
gabble_presence_cache_add_bundle_caps (cache,
NS_GABBLE_CAPS "#" BUNDLE_VOICE_V1, NS_GOOGLE_FEAT_VOICE);
@@ -839,7 +795,7 @@ self_avatar_resolve_conflict (GabblePresenceCache *cache)
GabblePresence *presence = priv->conn->self_presence;
GError *error = NULL;
- if (base_conn->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base_conn) != TP_CONNECTION_STATUS_CONNECTED)
{
DEBUG ("no longer connected");
return;
@@ -885,9 +841,10 @@ self_avatar_resolve_conflict (GabblePresenceCache *cache)
}
gabble_vcard_manager_invalidate_cache (priv->conn->vcard_manager,
- base_conn->self_handle);
+ tp_base_connection_get_self_handle (base_conn));
gabble_vcard_manager_request (priv->conn->vcard_manager,
- base_conn->self_handle, 0, self_vcard_request_cb, cache,
+ tp_base_connection_get_self_handle (base_conn), 0,
+ self_vcard_request_cb, cache,
NULL);
}
@@ -903,7 +860,7 @@ _grab_avatar_sha1 (GabblePresenceCache *cache,
WockyNode *x_node, *photo_node;
GabblePresence *presence;
- if (handle == base_conn->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base_conn))
presence = priv->conn->self_presence;
else
presence = gabble_presence_cache_get (cache, handle);
@@ -949,14 +906,14 @@ _grab_avatar_sha1 (GabblePresenceCache *cache,
if (tp_strdiff (presence->avatar_sha1, sha1))
{
- if (handle == base_conn->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base_conn))
{
DEBUG ("Avatar conflict! Received hash '%s' and our cache is '%s'",
sha1, presence->avatar_sha1 == NULL ?
"<NULL>" : presence->avatar_sha1);
self_avatar_resolve_conflict (cache);
}
- else if (base_conn->status == TP_CONNECTION_STATUS_CONNECTED)
+ else if (tp_base_connection_get_status (base_conn) == TP_CONNECTION_STATUS_CONNECTED)
{
g_free (presence->avatar_sha1);
presence->avatar_sha1 = g_strdup (sha1);
@@ -970,9 +927,10 @@ static GSList *
_parse_cap_bundles (
WockyNode *lm_node,
const gchar **hash,
- const gchar **ver)
+ const gchar **ver,
+ const gchar **node)
{
- const gchar *node, *ext;
+ const gchar *ext;
GSList *uris = NULL;
WockyNode *cap_node;
@@ -986,15 +944,15 @@ _parse_cap_bundles (
*hash = wocky_node_get_attribute (cap_node, "hash");
- node = wocky_node_get_attribute (cap_node, "node");
+ *node = wocky_node_get_attribute (cap_node, "node");
- if (NULL == node)
+ if (NULL == *node)
return NULL;
*ver = wocky_node_get_attribute (cap_node, "ver");
if (NULL != *ver)
- uris = g_slist_prepend (uris, g_strdup_printf ("%s#%s", node, *ver));
+ uris = g_slist_prepend (uris, g_strdup (*ver));
/* If there is a hash, the remote contact uses XEP-0115 v1.5 and the 'ext'
* attribute MUST be ignored. */
@@ -1010,7 +968,7 @@ _parse_cap_bundles (
exts = g_strsplit (ext, " ", 0);
for (i = exts; NULL != *i; i++)
- uris = g_slist_prepend (uris, g_strdup_printf ("%s#%s", node, *i));
+ uris = g_slist_prepend (uris, g_strdup (*i));
g_strfreev (exts);
}
@@ -1365,7 +1323,7 @@ _caps_disco_cb (GabbleDisco *disco,
if (NULL == waiter_self)
{
DEBUG ("Ignoring non requested disco reply from %s", jid);
- goto OUT;
+ return;
}
/* Now onto caps */
@@ -1507,16 +1465,51 @@ _caps_disco_cb (GabbleDisco *disco,
gabble_capability_set_free (cap_set);
g_ptr_array_unref (data_forms);
+}
+
+static gboolean
+get_google_cap (const gchar *fragment,
+ const gchar **ns)
+{
+ if (!tp_strdiff (fragment, "voice-v1"))
+ {
+ *ns = NS_GOOGLE_FEAT_VOICE;
+ return TRUE;
+ }
+ else if (!tp_strdiff (fragment, "video-v1"))
+ {
+ *ns = NS_GOOGLE_FEAT_VIDEO;
+ return TRUE;
+ }
+ else if (!tp_strdiff (fragment, "share-v1"))
+ {
+ *ns = NS_GOOGLE_FEAT_SHARE;
+ return TRUE;
+ }
+ else if (!tp_strdiff (fragment, "sms-v1"))
+ {
+ *ns = NULL;
+ return TRUE;
+ }
+ else if (!tp_strdiff (fragment, "pmuc-v1"))
+ {
+ *ns = NULL;
+ return TRUE;
+ }
+ else if (!tp_strdiff (fragment, "camera-v1"))
+ {
+ *ns = NULL;
+ return TRUE;
+ }
-OUT:
- if (handle)
- tp_handle_unref (contact_repo, handle);
+ return FALSE;
}
static void
_process_caps_uri (GabblePresenceCache *cache,
const gchar *from,
- const gchar *uri,
+ const gchar *node,
+ const gchar *fragment,
const gchar *hash,
const gchar *ver,
TpHandle handle,
@@ -1529,6 +1522,8 @@ _process_caps_uri (GabblePresenceCache *cache,
GabblePresenceCachePrivate *priv;
TpHandleRepoIface *contact_repo;
WockyCapsCache *caps_cache;
+ gchar *uri = g_strdup_printf ("%s#%s", node, fragment);
+ const gchar *ns = NULL;
priv = cache->priv;
contact_repo = tp_base_connection_get_handles (
@@ -1596,6 +1591,34 @@ _process_caps_uri (GabblePresenceCache *cache,
if (cached_caps != NULL)
gabble_capability_set_free (cached_caps);
}
+ else if (hash == NULL && get_google_cap (fragment, &ns))
+ {
+ /* if the hash is NULL then are looking at the ext='...' values,
+ * so this is starting to smell like Google */
+ GabblePresence *presence = gabble_presence_cache_get (cache, handle);
+
+ /* we already know about this fragment; apply the known value to
+ * the (handle, resource) */
+ DEBUG ("we know about fragment %s, setting caps for %u (%s)", fragment, handle,
+ from);
+
+ if (presence != NULL)
+ {
+ GabbleCapabilitySet *cap_set = gabble_capability_set_new ();
+
+ if (ns != NULL)
+ gabble_capability_set_add (cap_set, ns);
+
+ gabble_presence_set_capabilities (
+ presence, resource, cap_set, NULL, serial);
+
+ gabble_capability_set_free (cap_set);
+ }
+ else
+ {
+ DEBUG ("presence not found");
+ }
+ }
else
{
GSList *waiters;
@@ -1661,6 +1684,8 @@ _process_caps_uri (GabblePresenceCache *cache,
out:
if (cached_query_reply != NULL)
g_object_unref (cached_query_reply);
+
+ g_free (uri);
}
static void
@@ -1672,10 +1697,11 @@ _process_caps (GabblePresenceCache *cache,
{
const gchar *resource;
GSList *uris, *i;
+
GabblePresenceCachePrivate *priv;
GabbleCapabilitySet *old_cap_set = NULL;
guint serial;
- const gchar *hash, *ver;
+ const gchar *hash, *ver, *node;
priv = cache->priv;
serial = priv->caps_serial++;
@@ -1684,7 +1710,7 @@ _process_caps (GabblePresenceCache *cache,
if (resource != NULL)
resource++;
- uris = _parse_cap_bundles (lm_node, &hash, &ver);
+ uris = _parse_cap_bundles (lm_node, &hash, &ver, &node);
if (presence)
{
@@ -1706,7 +1732,7 @@ _process_caps (GabblePresenceCache *cache,
*/
for (i = uris; NULL != i; i = i->next)
{
- _process_caps_uri (cache, from, (gchar *) i->data, hash, ver, handle,
+ _process_caps_uri (cache, from, node, (gchar *) i->data, hash, ver, handle,
resource, serial);
g_free (i->data);
@@ -2217,6 +2243,7 @@ gabble_presence_cache_add_own_caps (
{
gchar *uri = g_strdup_printf ("%s#%s", NS_GABBLE_CAPS, ver);
GabbleCapabilityInfo *info = capability_info_get (cache, uri);
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (cache->priv->conn);
if (info->complete)
goto out;
@@ -2246,7 +2273,7 @@ gabble_presence_cache_add_own_caps (
info->complete = TRUE;
info->trust = CAPABILITY_BUNDLE_ENOUGH_TRUST;
- tp_intset_add (info->guys, cache->priv->conn->parent.self_handle);
+ tp_intset_add (info->guys, tp_base_connection_get_self_handle (base_conn));
replace_data_forms (info, data_forms);
@@ -2440,7 +2467,7 @@ gabble_presence_cache_is_unsure (GabblePresenceCache *cache,
* Presences with keep_unavailable are the result of caching someone's
* nick from <message> stanzas, so they don't count as real presence - if
* someone sends us a <message>, their presence might still follow. */
- if (base_conn->status != TP_CONNECTION_STATUS_CONNECTED ||
+ if (tp_base_connection_get_status (base_conn) != TP_CONNECTION_STATUS_CONNECTED ||
priv->unsure_id != 0)
{
GabblePresence *presence = gabble_presence_cache_get (cache, handle);
diff --git a/src/presence-cache.h b/src/presence-cache.h
index 8c765517f..55023447f 100644
--- a/src/presence-cache.h
+++ b/src/presence-cache.h
@@ -68,7 +68,7 @@ struct _GabbleCapabilityInfo
/* array of WockyDataForm or NULL */
GPtrArray *data_forms;
- TpIntSet *guys;
+ TpIntset *guys;
guint trust;
/* bitfield of GabbleClientType flags */
diff --git a/src/presence.c b/src/presence.c
index 704834ca2..db9830c6e 100644
--- a/src/presence.c
+++ b/src/presence.c
@@ -22,7 +22,7 @@
#include "presence.h"
#include <string.h>
-#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
#include "gabble/capabilities.h"
diff --git a/src/private-tubes-factory.c b/src/private-tubes-factory.c
index ea418f262..48b421165 100644
--- a/src/private-tubes-factory.c
+++ b/src/private-tubes-factory.c
@@ -25,17 +25,15 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/util.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "extensions/extensions.h"
#define DEBUG_FLAG GABBLE_DEBUG_TUBES
+#include "bytestream-factory.h"
#include "gabble/caps-channel-manager.h"
#include "connection.h"
#include "debug.h"
@@ -43,18 +41,18 @@
#include "muc-factory.h"
#include "namespaces.h"
#include "presence-cache.h"
-#include "tubes-channel.h"
#include "tube-dbus.h"
#include "tube-stream.h"
#include "util.h"
-static GabbleTubesChannel *new_tubes_channel (GabblePrivateTubesFactory *fac,
- TpHandle handle, TpHandle initiator, gpointer request_token,
- gboolean send_new_channel_signal);
+static GabbleTubeIface * new_channel_from_stanza (GabblePrivateTubesFactory *self,
+ WockyStanza *stanza, WockyNode *tube_node, guint64 tube_id,
+ GabbleBytestreamIface *bytestream);
-static void tubes_channel_closed_cb (GabbleTubesChannel *chan,
+static gboolean private_tubes_factory_tube_close_cb (
+ WockyPorter *porter,
+ WockyStanza *msg,
gpointer user_data);
-
static gboolean private_tubes_factory_msg_tube_cb (
WockyPorter *porter,
WockyStanza *msg,
@@ -85,7 +83,8 @@ struct _GabblePrivateTubesFactoryPrivate
guint msg_tube_cb;
guint msg_close_cb;
- GHashTable *tubes_channels;
+ /* guint tube ID => (owned) (GabbleTubeIface *) */
+ GHashTable *tubes;
gboolean dispose_has_run;
};
@@ -104,6 +103,97 @@ static const gchar * const old_tubes_channel_allowed_properties[] = {
NULL
};
+gboolean
+gabble_private_tubes_factory_extract_tube_information (
+ TpHandleRepoIface *contact_repo,
+ WockyNode *tube_node,
+ TpTubeType *type,
+ TpHandle *initiator_handle,
+ const gchar **service,
+ GHashTable **parameters,
+ guint64 *tube_id)
+{
+ if (type != NULL)
+ {
+ const gchar *_type;
+
+ _type = wocky_node_get_attribute (tube_node, "type");
+
+ if (!tp_strdiff (_type, "stream"))
+ {
+ *type = TP_TUBE_TYPE_STREAM;
+ }
+ else if (!tp_strdiff (_type, "dbus"))
+ {
+ *type = TP_TUBE_TYPE_DBUS;
+ }
+ else
+ {
+ DEBUG ("Unknown tube type: %s", _type);
+ return FALSE;
+ }
+ }
+
+ if (initiator_handle != NULL)
+ {
+ const gchar *initiator;
+
+ initiator = wocky_node_get_attribute (tube_node, "initiator");
+
+ if (initiator != NULL)
+ {
+ *initiator_handle = tp_handle_ensure (contact_repo, initiator,
+ GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL);
+
+ if (*initiator_handle == 0)
+ {
+ DEBUG ("invalid initiator JID %s", initiator);
+ return FALSE;
+ }
+ }
+ else
+ {
+ *initiator_handle = 0;
+ }
+ }
+
+ if (service != NULL)
+ {
+ *service = wocky_node_get_attribute (tube_node, "service");
+ }
+
+ if (parameters != NULL)
+ {
+ WockyNode *node;
+
+ node = wocky_node_get_child (tube_node, "parameters");
+ *parameters = lm_message_node_extract_properties (node, "parameter");
+ }
+
+ if (tube_id != NULL)
+ {
+ const gchar *str;
+ guint64 tmp;
+
+ str = wocky_node_get_attribute (tube_node, "id");
+ if (str == NULL)
+ {
+ DEBUG ("no tube id in SI request");
+ return FALSE;
+ }
+
+ tmp = g_ascii_strtoull (str, NULL, 10);
+ if (tmp == 0 || tmp > G_MAXUINT32)
+ {
+ DEBUG ("tube id is non-numeric or out of range: %s", str);
+ return FALSE;
+ }
+ *tube_id = tmp;
+ }
+
+ return TRUE;
+}
+
static void
gabble_private_tubes_factory_init (GabblePrivateTubesFactory *self)
{
@@ -112,8 +202,8 @@ gabble_private_tubes_factory_init (GabblePrivateTubesFactory *self)
self->priv = priv;
- priv->tubes_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
+ priv->tubes = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_object_unref);
priv->conn = NULL;
priv->dispose_has_run = FALSE;
@@ -141,7 +231,7 @@ porter_available_cb (
priv->msg_close_cb = wocky_porter_register_handler_from_anyone (porter,
WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
WOCKY_PORTER_HANDLER_PRIORITY_MAX,
- private_tubes_factory_msg_tube_cb, self,
+ private_tubes_factory_tube_close_cb, self,
'(', "close", ':', NS_TUBES,
')', NULL);
}
@@ -199,7 +289,7 @@ gabble_private_tubes_factory_dispose (GObject *object)
priv->dispose_has_run = TRUE;
gabble_private_tubes_factory_close_all (fac);
- g_assert (priv->tubes_channels == NULL);
+ g_assert (priv->tubes == NULL);
if (G_OBJECT_CLASS (gabble_private_tubes_factory_parent_class)->dispose)
G_OBJECT_CLASS (gabble_private_tubes_factory_parent_class)->dispose (
@@ -275,99 +365,6 @@ gabble_private_tubes_factory_class_init (
}
-
-/**
- * tubes_channel_closed_cb:
- *
- * Signal callback for when an Tubes channel is closed. Removes the references
- * that PrivateTubesFactory holds to them.
- */
-static void
-tubes_channel_closed_cb (GabbleTubesChannel *chan,
- gpointer user_data)
-{
- GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (user_data);
- GabblePrivateTubesFactoryPrivate *priv =
- GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
- TpHandle contact_handle;
-
- if (priv->tubes_channels == NULL)
- return;
-
- g_object_get (chan, "handle", &contact_handle, NULL);
-
- tp_channel_manager_emit_channel_closed_for_object (self,
- TP_EXPORTABLE_CHANNEL (chan));
-
- DEBUG ("removing tubes channel with handle %d", contact_handle);
-
- g_hash_table_remove (priv->tubes_channels, GUINT_TO_POINTER (contact_handle));
-}
-
-/**
- * new_tubes_channel
- *
- * Creates the GabbleTubes object associated with the given parameters
- */
-static GabbleTubesChannel *
-new_tubes_channel (GabblePrivateTubesFactory *fac,
- TpHandle handle,
- TpHandle initiator,
- gpointer request_token,
- gboolean send_new_channel_signal)
-{
- GabblePrivateTubesFactoryPrivate *priv;
- TpBaseConnection *conn;
- GabbleTubesChannel *chan;
- char *object_path;
- gboolean requested;
-
- g_assert (GABBLE_IS_PRIVATE_TUBES_FACTORY (fac));
- g_assert (handle != 0);
- g_assert (initiator != 0);
-
- priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (fac);
- conn = (TpBaseConnection *) priv->conn;
-
- object_path = g_strdup_printf ("%s/SITubesChannel%u", conn->object_path,
- handle);
-
- requested = (request_token != NULL);
-
- chan = g_object_new (GABBLE_TYPE_TUBES_CHANNEL,
- "connection", priv->conn,
- "object-path", object_path,
- "handle", handle,
- "handle-type", TP_HANDLE_TYPE_CONTACT,
- "initiator-handle", initiator,
- "requested", requested,
- NULL);
-
- DEBUG ("object path %s", object_path);
-
- g_signal_connect (chan, "closed", G_CALLBACK (tubes_channel_closed_cb), fac);
-
- g_hash_table_insert (priv->tubes_channels, GUINT_TO_POINTER (handle), chan);
-
- g_free (object_path);
-
- if (send_new_channel_signal)
- {
- GSList *request_tokens;
- if (request_token != NULL)
- request_tokens = g_slist_prepend (NULL, request_token);
- else
- request_tokens = NULL;
-
- tp_channel_manager_emit_new_channel (fac,
- TP_EXPORTABLE_CHANNEL (chan), request_tokens);
-
- g_slist_free (request_tokens);
- }
-
- return chan;
-}
-
static void
gabble_private_tubes_factory_close_all (GabblePrivateTubesFactory *fac)
{
@@ -393,10 +390,7 @@ gabble_private_tubes_factory_close_all (GabblePrivateTubesFactory *fac)
priv->msg_close_cb = 0;
}
- /* Use a temporary variable (the macro does this) because we don't want
- * tubes_channel_closed_cb to remove the channel from the hash table a
- * second time */
- tp_clear_pointer (&priv->tubes_channels, g_hash_table_unref);
+ tp_clear_pointer (&priv->tubes, g_hash_table_unref);
}
static void
@@ -567,9 +561,11 @@ gabble_private_tubes_factory_get_contact_caps (
{
GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (manager);
GetContactCapsClosure closure = { FALSE, arr, handle };
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn);
/* Always claim that we support tubes. */
- closure.supports_tubes = (handle == self->priv->conn->parent.self_handle);
+ closure.supports_tubes = (handle ==
+ tp_base_connection_get_self_handle (base_conn));
gabble_capability_set_foreach (caps, get_contact_caps_foreach, &closure);
@@ -658,16 +654,10 @@ _foreach_slave (gpointer key,
gpointer value,
gpointer user_data)
{
- struct _ForeachData *data = (struct _ForeachData *) user_data;
+ struct _ForeachData *data = user_data;
TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value);
- /* Add channels of type Channel.Type.Tubes */
data->foreach (chan, data->user_data);
-
- /* Add channels of type Channel.Type.{Stream|DBus}Tube which live in the
- * GabbleTubesChannel object */
- gabble_tubes_channel_foreach (GABBLE_TUBES_CHANNEL (chan), data->foreach,
- data->user_data);
}
static void
@@ -683,7 +673,7 @@ gabble_private_tubes_factory_foreach_channel (TpChannelManager *manager,
data.user_data = user_data;
data.foreach = foreach;
- g_hash_table_foreach (priv->tubes_channels, _foreach_slave, &data);
+ g_hash_table_foreach (priv->tubes, _foreach_slave, &data);
}
void
@@ -694,25 +684,54 @@ gabble_private_tubes_factory_handle_si_tube_request (
const gchar *stream_id,
WockyStanza *msg)
{
- GabblePrivateTubesFactoryPrivate *priv =
- GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ GabblePrivateTubesFactoryPrivate *priv = self->priv;
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleTubesChannel *chan;
+ WockyNode *si_node, *tube_node;
+ WockyStanzaType stanza_type;
+ WockyStanzaSubType sub_type;
+ guint64 tube_id;
+ GabbleTubeIface *tube;
DEBUG ("contact#%u stream %s", handle, stream_id);
g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL));
- chan = g_hash_table_lookup (priv->tubes_channels, GUINT_TO_POINTER (handle));
- if (chan == NULL)
+ wocky_stanza_get_type_info (msg, &stanza_type, &sub_type);
+ g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_IQ);
+ g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET);
+ si_node = wocky_node_get_child_ns (
+ wocky_stanza_get_top_node (msg), "si", NS_SI);
+ g_return_if_fail (si_node != NULL);
+ tube_node = wocky_node_get_child_ns (si_node, "tube",
+ NS_TUBES);
+ g_return_if_fail (tube_node != NULL);
+
+ if (!gabble_private_tubes_factory_extract_tube_information (
+ contact_repo, tube_node, NULL, NULL,
+ NULL, NULL, &tube_id))
{
- chan = new_tubes_channel (self, handle, handle, NULL, TRUE);
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<tube> has no id attribute" };
- /* FIXME: Should we close the channel if the request is not properly
- * handled by the newly created channel ? */
+ NODE_DEBUG (tube_node, e.message);
+ gabble_bytestream_iface_close (bytestream, &e);
+ return;
}
- gabble_tubes_channel_tube_si_offered (chan, bytestream, msg);
+ tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+ if (tube != NULL)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "tube ID already in use" };
+
+ NODE_DEBUG (tube_node, e.message);
+ gabble_bytestream_iface_close (bytestream, &e);
+ return;
+ }
+
+ /* New tube */
+ tube = new_channel_from_stanza (self, msg, tube_node,
+ tube_id, bytestream);
}
void
@@ -726,48 +745,82 @@ gabble_private_tubes_factory_handle_si_stream_request (
GabblePrivateTubesFactoryPrivate *priv =
GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- GabbleTubesChannel *chan;
+ (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+ const gchar *tmp;
+ guint64 tube_id;
+ WockyNode *si_node, *stream_node;
+ GabbleTubeIface *tube;
+ WockyStanzaType stanza_type;
+ WockyStanzaSubType sub_type;
DEBUG ("contact#%u stream %s", handle, stream_id);
g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL));
- chan = g_hash_table_lookup (priv->tubes_channels, GUINT_TO_POINTER (handle));
- if (chan == NULL)
+ wocky_stanza_get_type_info (msg, &stanza_type, &sub_type);
+ g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_IQ);
+ g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET);
+
+ si_node = wocky_node_get_child_ns (
+ wocky_stanza_get_top_node (msg), "si", NS_SI);
+ g_return_if_fail (si_node != NULL);
+
+ stream_node = wocky_node_get_child_ns (si_node,
+ "stream", NS_TUBES);
+ g_return_if_fail (stream_node != NULL);
+
+ tmp = wocky_node_get_attribute (stream_node, "tube");
+ if (tmp == NULL)
{
GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "No tubes channel available for this contact" };
+ "<stream> has no tube attribute" };
- DEBUG ("tubes channel with contact %d doesn't exist", handle);
+ NODE_DEBUG (stream_node, e.message);
gabble_bytestream_iface_close (bytestream, &e);
return;
}
+ tube_id = g_ascii_strtoull (tmp, NULL, 10);
+ if (tube_id == 0 || tube_id > G_MAXUINT32)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<stream> tube ID attribute non-numeric or out of range" };
- gabble_tubes_channel_bytestream_offered (chan, bytestream, msg);
+ DEBUG ("tube id is non-numeric or out of range: %s", tmp);
+ gabble_bytestream_iface_close (bytestream, &e);
+ return;
+ }
+
+ tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+ if (tube == NULL)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<stream> tube attribute points to a nonexistent "
+ "tube" };
+
+ DEBUG ("tube %" G_GUINT64_FORMAT " doesn't exist", tube_id);
+ gabble_bytestream_iface_close (bytestream, &e);
+ return;
+ }
+
+ DEBUG ("received new bytestream request for existing tube: %" G_GUINT64_FORMAT,
+ tube_id);
+
+ gabble_tube_iface_add_bytestream (tube, bytestream);
}
static gboolean
-private_tubes_factory_msg_tube_cb (
- WockyPorter *porter,
+tube_msg_checks (GabblePrivateTubesFactory *self,
WockyStanza *msg,
- gpointer user_data)
+ WockyNode *node,
+ TpHandle *out_handle,
+ guint64 *out_tube_id)
{
- GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (user_data);
GabblePrivateTubesFactoryPrivate *priv =
GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- WockyNode *tube_node, *close_node;
- GabbleTubesChannel *chan;
- const gchar *from;
+ const gchar *from, *tmp;
TpHandle handle;
-
- tube_node = wocky_node_get_child_ns (
- wocky_stanza_get_top_node (msg), "tube", NS_TUBES);
- close_node = wocky_node_get_child_ns (
- wocky_stanza_get_top_node (msg), "close", NS_TUBES);
-
- g_return_val_if_fail (tube_node != NULL || close_node != NULL, FALSE);
+ guint64 tube_id;
from = wocky_node_get_attribute (
wocky_stanza_get_top_node (msg), "from");
@@ -784,30 +837,396 @@ private_tubes_factory_msg_tube_cb (
return FALSE;
}
- /* Tube offer */
- chan = g_hash_table_lookup (priv->tubes_channels, GUINT_TO_POINTER (handle));
+ tmp = wocky_node_get_attribute (node, "id");
+ if (tmp == NULL)
+ {
+ DEBUG ("failed to get the tube ID");
+ return FALSE;
+ }
- if (chan == NULL)
+ tube_id = g_ascii_strtoull (tmp, NULL, 10);
+ if (tube_id == 0 || tube_id > G_MAXUINT32)
{
- if (tube_node != NULL)
- {
- /* We create the tubes channel only if the message is a new tube
- * offer */
- chan = new_tubes_channel (self, handle, handle, NULL, TRUE);
- }
- else
- {
- DEBUG ("Ignore tube close message as there is no tubes channel"
- " to handle it");
- return TRUE;
- }
+ DEBUG ("tube ID is non-numeric or out of range: %s", tmp);
+ return FALSE;
}
- gabble_tubes_channel_tube_msg (chan, msg);
+ if (out_tube_id != NULL)
+ *out_tube_id = tube_id;
+
+ if (out_handle != NULL)
+ *out_handle = handle;
return TRUE;
}
+static gboolean
+private_tubes_factory_msg_tube_cb (
+ WockyPorter *porter,
+ WockyStanza *msg,
+ gpointer user_data)
+{
+ GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (user_data);
+ GabblePrivateTubesFactoryPrivate *priv =
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ WockyNode *node;
+ guint64 tube_id;
+ GabbleTubeIface *channel;
+ TpHandle handle;
+
+ node = wocky_node_get_child_ns (
+ wocky_stanza_get_top_node (msg), "tube", NS_TUBES);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (!tube_msg_checks (self, msg, node, &handle, &tube_id))
+ return FALSE;
+
+ channel = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+
+ if (channel != NULL)
+ {
+ TpHandle tube_handle = 0;
+
+ g_object_get (channel,
+ "handle", &tube_handle,
+ NULL);
+
+ DEBUG ("tube ID already in use; do not open the offered tube and close "
+ "the existing tube if it's to the same contact");
+
+ /* only close the existing channel if it's the same contact
+ * otherwise contacts could force close unrelated tubes. */
+ if (handle == tube_handle)
+ gabble_tube_iface_close (channel, FALSE);
+
+ return TRUE;
+ }
+
+ channel = new_channel_from_stanza (self, msg, node, tube_id, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+private_tubes_factory_tube_close_cb (
+ WockyPorter *porter,
+ WockyStanza *msg,
+ gpointer user_data)
+{
+ GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (user_data);
+ GabblePrivateTubesFactoryPrivate *priv =
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ WockyNode *node;
+ guint64 tube_id;
+ GabbleTubeIface *channel;
+ TpTubeType type;
+
+ node = wocky_node_get_child_ns (
+ wocky_stanza_get_top_node (msg), "close", NS_TUBES);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (!tube_msg_checks (self, msg, node, NULL, &tube_id))
+ return FALSE;
+
+ channel = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+
+ if (channel == NULL)
+ {
+ DEBUG ("<close> tube attribute points to a nonexistent tube");
+ return TRUE;
+ }
+
+ g_object_get (channel, "type", &type, NULL);
+ if (type != TP_TUBE_TYPE_STREAM)
+ {
+ DEBUG ("Only stream tubes can be closed using a close message");
+ return TRUE;
+ }
+
+ DEBUG ("tube %" G_GUINT64_FORMAT " was closed by remote peer", tube_id);
+ gabble_tube_iface_close (channel, TRUE);
+
+ return TRUE;
+}
+
+static GabbleTubeIface *
+gabble_private_tubes_factory_lookup (GabblePrivateTubesFactory *self,
+ const gchar *type,
+ TpHandle handle,
+ const gchar *service)
+{
+ GabblePrivateTubesFactoryPrivate *priv =
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ GabbleTubeIface *tube = value;
+ gboolean match = FALSE;
+
+ gchar *channel_type, *channel_service;
+ TpHandle channel_handle;
+
+ g_object_get (tube,
+ "channel-type", &channel_type,
+ "handle", &channel_handle,
+ "service", &channel_service,
+ NULL);
+
+ if (!tp_strdiff (type, channel_type)
+ && handle == channel_handle
+ && !tp_strdiff (service, channel_service))
+ match = TRUE;
+
+ g_free (channel_type);
+ g_free (channel_service);
+
+ if (match)
+ return tube;
+ }
+
+ return NULL;
+}
+
+static void
+channel_closed_cb (GabbleTubeIface *tube,
+ GabblePrivateTubesFactory *self)
+{
+ GabblePrivateTubesFactoryPrivate *priv =
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ guint id;
+
+ g_object_get (tube,
+ "id", &id,
+ NULL);
+
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ TP_EXPORTABLE_CHANNEL (tube));
+
+ if (priv->tubes != NULL)
+ g_hash_table_remove (priv->tubes, GUINT_TO_POINTER (id));
+}
+
+static guint64
+generate_tube_id (GabblePrivateTubesFactory *self)
+{
+ GabblePrivateTubesFactoryPrivate *priv =
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ guint out;
+
+ /* probably totally overkill */
+ do
+ {
+ out = g_random_int_range (1, G_MAXINT32);
+ }
+ while (g_hash_table_lookup (priv->tubes,
+ GUINT_TO_POINTER (out)) != NULL);
+
+ return out;
+}
+
+/* Returns: (transfer none): new tube channel. the channel manager holds
+ * the ref to this channel, so don't unref it! */
+static GabbleTubeIface *
+new_channel_from_request (GabblePrivateTubesFactory *self,
+ GHashTable *request)
+{
+ GabblePrivateTubesFactoryPrivate *priv =
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ GabbleTubeIface *tube;
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
+
+ gchar *stream_id;
+
+ TpHandle handle;
+ const gchar *ctype, *service;
+ TpHandleType handle_type;
+ GHashTable *parameters;
+ guint64 tube_id;
+
+ ctype = tp_asv_get_string (request, TP_PROP_CHANNEL_CHANNEL_TYPE);
+ handle = tp_asv_get_uint32 (request, TP_PROP_CHANNEL_TARGET_HANDLE,
+ NULL);
+ handle_type = tp_asv_get_uint32 (request,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL);
+
+ tube_id = generate_tube_id (self);
+
+ /* requested tubes have an empty parameters dict */
+ parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) tp_g_value_slice_free);
+
+ if (!tp_strdiff (ctype, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
+ {
+ service = tp_asv_get_string (request,
+ TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
+
+ tube = GABBLE_TUBE_IFACE (gabble_tube_stream_new (priv->conn,
+ handle, handle_type,
+ tp_base_connection_get_self_handle (base_conn),
+ tp_base_connection_get_self_handle (base_conn),
+ service, parameters, tube_id, NULL, TRUE));
+ }
+ else if (!tp_strdiff (ctype, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
+ {
+ service = tp_asv_get_string (request,
+ TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME);
+
+ stream_id = gabble_bytestream_factory_generate_stream_id ();
+
+ tube = GABBLE_TUBE_IFACE (gabble_tube_dbus_new (priv->conn,
+ handle, handle_type,
+ tp_base_connection_get_self_handle (base_conn),
+ tp_base_connection_get_self_handle (base_conn),
+ service, parameters, stream_id, tube_id, NULL, NULL, TRUE));
+
+ g_free (stream_id);
+ }
+ else
+ {
+ g_return_val_if_reached (NULL);
+ }
+
+ tp_base_channel_register ((TpBaseChannel *) tube);
+
+ g_signal_connect (tube, "closed",
+ G_CALLBACK (channel_closed_cb), self);
+
+ g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id),
+ tube);
+
+ g_hash_table_unref (parameters);
+
+ return tube;
+}
+
+static void
+send_tube_close_msg (GabblePrivateTubesFactory *self,
+ const gchar *jid,
+ guint64 tube_id)
+{
+ GabblePrivateTubesFactoryPrivate *priv =
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ WockyPorter *porter;
+ WockyStanza *msg;
+ gchar *id_str;
+
+ id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, tube_id);
+
+ porter = gabble_connection_dup_porter (priv->conn);
+
+ /* Send the close message */
+ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
+ NULL, jid,
+ '(', "close",
+ ':', NS_TUBES,
+ '@', "tube", id_str,
+ ')',
+ GABBLE_AMP_DO_NOT_STORE_SPEC,
+ NULL);
+ g_free (id_str);
+
+ wocky_porter_send (porter, msg);
+
+ g_object_unref (porter);
+ g_object_unref (msg);
+}
+
+/* Returns: (transfer none): new tube channel. the channel manager holds
+ * the ref to this channel, so don't unref it! */
+static GabbleTubeIface *
+new_channel_from_stanza (GabblePrivateTubesFactory *self,
+ WockyStanza *stanza,
+ WockyNode *tube_node,
+ guint64 tube_id,
+ GabbleBytestreamIface *bytestream)
+{
+ GabblePrivateTubesFactoryPrivate *priv =
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
+ GabbleTubeIface *tube;
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+
+ TpTubeType type;
+ TpHandle handle;
+ const gchar *service;
+ GHashTable *parameters;
+
+ /* the validity of this has already been checked by wocky */
+ handle = tp_handle_ensure (contact_repo,
+ wocky_stanza_get_from (stanza), NULL, NULL);
+ g_return_val_if_fail (handle != 0, NULL);
+
+ if (!gabble_private_tubes_factory_extract_tube_information (
+ contact_repo, tube_node, &type, NULL,
+ &service, &parameters, NULL))
+ {
+ DEBUG ("can't extract <tube> information from message");
+ send_tube_close_msg (self, wocky_stanza_get_from (stanza), tube_id);
+ return NULL;
+ }
+
+ if (bytestream == NULL && type != TP_TUBE_TYPE_STREAM)
+ {
+ DEBUG ("Only stream tubes are allowed to be created using messages");
+ send_tube_close_msg (self, wocky_stanza_get_from (stanza), tube_id);
+ return NULL;
+ }
+ else if (bytestream != NULL && type != TP_TUBE_TYPE_DBUS)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FORBIDDEN,
+ "Only D-Bus tubes are allowed to be created using SI" };
+
+ DEBUG ("%s", e.message);
+ gabble_bytestream_iface_close (bytestream, &e);
+ return NULL;
+ }
+
+ if (type == TP_TUBE_TYPE_STREAM)
+ {
+ tube = GABBLE_TUBE_IFACE (gabble_tube_stream_new (priv->conn,
+ handle, TP_HANDLE_TYPE_CONTACT,
+ tp_base_connection_get_self_handle (base_conn),
+ handle, service, parameters, tube_id, NULL, FALSE));
+ }
+ else
+ {
+ WockyNode *si_node;
+ const gchar *stream_id;
+
+ si_node = wocky_node_get_child_ns (
+ wocky_stanza_get_top_node (stanza), "si", NS_SI);
+ g_return_val_if_fail (si_node != NULL, NULL);
+
+ stream_id = wocky_node_get_attribute (si_node, "id");
+ g_return_val_if_fail (stream_id != NULL, NULL);
+
+ tube = GABBLE_TUBE_IFACE (gabble_tube_dbus_new (priv->conn,
+ handle, TP_HANDLE_TYPE_CONTACT,
+ tp_base_connection_get_self_handle (base_conn),
+ handle, service, parameters,
+ stream_id, tube_id, bytestream, NULL, FALSE));
+ }
+
+ tp_base_channel_register ((TpBaseChannel *) tube);
+
+ g_signal_connect (tube, "closed",
+ G_CALLBACK (channel_closed_cb), self);
+
+ g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id),
+ tube);
+
+ g_hash_table_unref (parameters);
+
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (tube), NULL);
+
+ return tube;
+}
+
GabblePrivateTubesFactory *
gabble_private_tubes_factory_new (GabbleConnection *conn)
{
@@ -827,24 +1246,6 @@ gabble_private_tubes_factory_type_foreach_channel_class (GType type,
GHashTable *table;
GValue *value;
- /* 1-1 Channel.Type.Tubes */
- table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) tp_g_value_slice_free);
-
- value = tp_g_value_slice_new (G_TYPE_STRING);
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TUBES);
- g_hash_table_insert (table, TP_PROP_CHANNEL_CHANNEL_TYPE,
- value);
-
- value = tp_g_value_slice_new (G_TYPE_UINT);
- g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
- g_hash_table_insert (table, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
- value);
-
- func (type, table, old_tubes_channel_allowed_properties, user_data);
-
- g_hash_table_unref (table);
-
/* 1-1 Channel.Type.StreamTube */
table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
(GDestroyNotify) tp_g_value_slice_free);
@@ -895,7 +1296,8 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
TpHandle handle;
GError *error = NULL;
const gchar *channel_type;
- GabbleTubesChannel *channel;
+ GabbleTubeIface *channel;
+ const gchar *service = NULL;
if (tp_asv_get_uint32 (request_properties,
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != TP_HANDLE_TYPE_CONTACT)
@@ -904,25 +1306,14 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
channel_type = tp_asv_get_string (request_properties,
TP_PROP_CHANNEL_CHANNEL_TYPE);
- if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES) &&
- tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) &&
+ if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) &&
tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
return FALSE;
- if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES))
+ if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
{
if (tp_channel_manager_asv_has_unknown_properties (request_properties,
tubes_channel_fixed_properties,
- old_tubes_channel_allowed_properties,
- &error))
- goto error;
- }
- else if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
- {
- const gchar *service;
-
- if (tp_channel_manager_asv_has_unknown_properties (request_properties,
- tubes_channel_fixed_properties,
gabble_tube_stream_channel_get_allowed_properties (),
&error))
goto error;
@@ -932,7 +1323,7 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
if (service == NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Request does not contain the mandatory property '%s'",
TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
goto error;
@@ -940,7 +1331,6 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
}
else if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
{
- const gchar *service;
GError *err = NULL;
if (tp_channel_manager_asv_has_unknown_properties (request_properties,
@@ -954,7 +1344,7 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME);
if (service == NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Request does not contain the mandatory property '%s'",
TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME);
goto error;
@@ -963,7 +1353,7 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
if (!tp_dbus_check_valid_bus_name (service, TP_DBUS_NAME_TYPE_WELL_KNOWN,
&err))
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Invalid ServiceName: %s", err->message);
g_error_free (err);
goto error;
@@ -976,83 +1366,45 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
g_assert (handle != 0);
/* Don't support opening a channel to our self handle */
- if (handle == base_conn->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base_conn))
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Can't open a channel to your self handle");
goto error;
}
- channel = g_hash_table_lookup (self->priv->tubes_channels,
- GUINT_TO_POINTER (handle));
+ channel = gabble_private_tubes_factory_lookup (self, channel_type,
+ handle, service);
- if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES))
+ if (channel == NULL)
{
- if (channel == NULL)
- {
- new_tubes_channel (self, handle, base_conn->self_handle,
- request_token, TRUE);
- return TRUE;
- }
+ GSList *request_tokens = NULL;
+
+ channel = new_channel_from_request (self, request_properties);
+ if (request_token != NULL)
+ request_tokens = g_slist_prepend (NULL, request_token);
+
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (channel), request_tokens);
+
+ g_slist_free (request_tokens);
+ }
+ else
+ {
if (require_new)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Tubes channel with contact #%u already exists", handle);
- DEBUG ("Tubes channel with contact #%u already exists",
- handle);
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "A channel to #%u (service: %s) is already open",
+ handle, service);
goto error;
}
tp_channel_manager_emit_request_already_satisfied (self,
request_token, TP_EXPORTABLE_CHANNEL (channel));
- return TRUE;
}
- else
- {
- gboolean tubes_channel_already_existed = (channel != NULL);
- GabbleTubeIface *new_channel;
-
- if (channel == NULL)
- {
- /* Don't give the request_token to new_tubes_channel() because we
- * must emit NewChannels with 2 channels together */
- channel = new_tubes_channel (self, handle, base_conn->self_handle,
- NULL, FALSE);
- }
- g_assert (channel != NULL);
-
- new_channel = gabble_tubes_channel_tube_request (channel, request_token,
- request_properties, require_new);
- if (new_channel != NULL)
- {
- GHashTable *channels;
- GSList *request_tokens;
- channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
- if (!tubes_channel_already_existed)
- g_hash_table_insert (channels, channel, NULL);
-
- if (request_token != NULL)
- request_tokens = g_slist_prepend (NULL, request_token);
- else
- request_tokens = NULL;
-
- g_hash_table_insert (channels, new_channel, request_tokens);
- tp_channel_manager_emit_new_channels (self, channels);
-
- g_hash_table_unref (channels);
- g_slist_free (request_tokens);
- }
- else
- {
- tp_channel_manager_emit_request_already_satisfied (self,
- request_token, TP_EXPORTABLE_CHANNEL (channel));
- }
-
- return TRUE;
- }
+ return TRUE;
error:
tp_channel_manager_emit_request_failed (self, request_token,
diff --git a/src/private-tubes-factory.h b/src/private-tubes-factory.h
index d9895199d..d9e01f17a 100644
--- a/src/private-tubes-factory.h
+++ b/src/private-tubes-factory.h
@@ -22,10 +22,10 @@
#include <glib-object.h>
-#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
+
#include "connection.h"
#include "bytestream-iface.h"
-#include "tubes-channel.h"
G_BEGIN_DECLS
@@ -75,6 +75,12 @@ void gabble_private_tubes_factory_handle_si_stream_request (
GabblePrivateTubesFactory *fac, GabbleBytestreamIface *bytestream,
TpHandle handle, const gchar *stream_id, WockyStanza *msg);
+gboolean gabble_private_tubes_factory_extract_tube_information (
+ TpHandleRepoIface *contact_repo, WockyNode *tube_node,
+ TpTubeType *type, TpHandle *initiator_handle,
+ const gchar **service, GHashTable **parameters,
+ guint64 *tube_id);
+
G_END_DECLS
#endif /* #ifndef __PRIVATE_TUBES_FACTORY_H__ */
diff --git a/src/protocol.c b/src/protocol.c
index a8bceb2ff..deeaa8d9e 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -18,11 +18,13 @@
*/
#include "config.h"
+
#include "protocol.h"
#include <string.h>
-#include <telepathy-glib/base-connection-manager.h>
-#include <telepathy-glib/interfaces.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <dbus/dbus-protocol.h>
#include <dbus/dbus-glib.h>
@@ -318,15 +320,18 @@ identify_account (TpBaseProtocol *self G_GNUC_UNUSED,
return g_strdup (account);
}
-static GStrv
-get_interfaces (TpBaseProtocol *self)
+static GPtrArray *
+get_interfaces_array (TpBaseProtocol *self)
{
- const gchar * const interfaces[] = {
- TP_IFACE_PROTOCOL_INTERFACE_PRESENCE,
- TP_IFACE_PROTOCOL_INTERFACE_ADDRESSING,
- NULL };
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_PROTOCOL_CLASS (
+ gabble_jabber_protocol_parent_class)->get_interfaces_array (self);
+
+ g_ptr_array_add (interfaces, TP_IFACE_PROTOCOL_INTERFACE_PRESENCE);
+ g_ptr_array_add (interfaces, TP_IFACE_PROTOCOL_INTERFACE_ADDRESSING);
- return g_strdupv ((GStrv) interfaces);
+ return interfaces;
}
static const TpPresenceStatusSpec *
@@ -458,7 +463,7 @@ gabble_jabber_protocol_class_init (GabbleJabberProtocolClass *klass)
base_class->new_connection = new_connection;
base_class->normalize_contact = normalize_contact;
base_class->identify_account = identify_account;
- base_class->get_interfaces = get_interfaces;
+ base_class->get_interfaces_array = get_interfaces_array;
base_class->get_connection_details = get_connection_details;
base_class->get_statuses = get_presence_statuses;
base_class->dup_authentication_types = dup_authentication_types;
diff --git a/src/protocol.h b/src/protocol.h
index 30809df47..c013d9913 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -21,7 +21,7 @@
#define JABBER_PROTOCOL_H
#include <glib-object.h>
-#include <telepathy-glib/base-protocol.h>
+#include <telepathy-glib/telepathy-glib.h>
G_BEGIN_DECLS
diff --git a/src/request-pipeline.c b/src/request-pipeline.c
index 1bbfe4aa4..7b4eb5cc0 100644
--- a/src/request-pipeline.c
+++ b/src/request-pipeline.c
@@ -21,7 +21,7 @@
#include "config.h"
#include "request-pipeline.h"
-#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/telepathy-glib.h>
#define DEBUG_FLAG GABBLE_DEBUG_PIPELINE
@@ -245,7 +245,7 @@ gabble_request_pipeline_flush (GabbleRequestPipeline *self,
GSList **list)
{
GabbleRequestPipelineItem *item;
- GError disconnected = { TP_ERRORS, TP_ERROR_DISCONNECTED,
+ GError disconnected = { TP_ERROR, TP_ERROR_DISCONNECTED,
"Request failed because connection became disconnected" };
while (*list != NULL)
diff --git a/src/room-config.c b/src/room-config.c
index 47489058f..199545ad5 100644
--- a/src/room-config.c
+++ b/src/room-config.c
@@ -18,6 +18,7 @@
*/
#include "config.h"
+
#include "room-config.h"
#include "muc-channel.h"
diff --git a/src/room-config.h b/src/room-config.h
index a2981c186..ce5247201 100644
--- a/src/room-config.h
+++ b/src/room-config.h
@@ -21,7 +21,7 @@
#define GABBLE_ROOM_CONFIG_H
#include <glib-object.h>
-#include <telepathy-glib/base-room-config.h>
+#include <telepathy-glib/telepathy-glib.h>
typedef struct _GabbleRoomConfig GabbleRoomConfig;
typedef struct _GabbleRoomConfigClass GabbleRoomConfigClass;
diff --git a/src/roomlist-channel.c b/src/roomlist-channel.c
index 642c983d1..070cf5ee3 100644
--- a/src/roomlist-channel.c
+++ b/src/roomlist-channel.c
@@ -24,14 +24,9 @@
#include <string.h>
#include <dbus/dbus-glib.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-generic.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_ROOMLIST
@@ -49,10 +44,6 @@ G_DEFINE_TYPE_WITH_CODE (GabbleRoomlistChannel, gabble_roomlist_channel,
roomlist_iface_init);
);
-static const gchar *gabble_roomlist_channel_interfaces[] = {
- NULL
-};
-
/* properties */
enum
{
@@ -192,7 +183,6 @@ gabble_roomlist_channel_class_init (GabbleRoomlistChannelClass *klass)
object_class->finalize = gabble_roomlist_channel_finalize;
base_class->channel_type = TP_IFACE_CHANNEL_TYPE_ROOM_LIST;
- base_class->interfaces = gabble_roomlist_channel_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_NONE;
base_class->get_object_path_suffix =
gabble_roomlist_channel_get_object_path_suffix;
@@ -415,7 +405,6 @@ room_info_cb (gpointer pipeline, GabbleDiscoItem *item, gpointer user_data)
/* 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, room_info_type);
g_value_take_boxed (&room,
diff --git a/src/roomlist-channel.h b/src/roomlist-channel.h
index e86d6b028..5c74f3485 100644
--- a/src/roomlist-channel.h
+++ b/src/roomlist-channel.h
@@ -23,7 +23,7 @@
#include <glib-object.h>
-#include <telepathy-glib/base-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "connection.h"
diff --git a/src/roomlist-manager.c b/src/roomlist-manager.c
index 6f8d499ea..ff2f37fef 100644
--- a/src/roomlist-manager.c
+++ b/src/roomlist-manager.c
@@ -25,10 +25,9 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/util.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_MUC
@@ -329,7 +328,7 @@ gabble_roomlist_manager_handle_request (TpChannelManager *manager,
if (tp_asv_get_uint32 (request_properties,
TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"RoomList channels can't have a target handle");
goto error;
}
@@ -349,7 +348,7 @@ gabble_roomlist_manager_handle_request (TpChannelManager *manager,
if (server == NULL)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Unable to choose a default conference server");
goto error;
}
diff --git a/src/roster.c b/src/roster.c
index 7bd6758f4..d2cc4dae8 100644
--- a/src/roster.c
+++ b/src/roster.c
@@ -25,9 +25,8 @@
#include <string.h>
#include <dbus/dbus-glib.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
#define DEBUG_FLAG GABBLE_DEBUG_ROSTER
@@ -214,17 +213,6 @@ gabble_roster_dispose (GObject *object)
}
static void
-item_handle_unref_foreach (gpointer key, gpointer data, gpointer user_data)
-{
- TpHandle handle = GPOINTER_TO_UINT (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);
-}
-
-static void
gabble_roster_finalize (GObject *object)
{
GabbleRoster *self = GABBLE_ROSTER (object);
@@ -232,7 +220,6 @@ gabble_roster_finalize (GObject *object)
DEBUG ("called with %p", object);
- g_hash_table_foreach (priv->items, item_handle_unref_foreach, priv);
g_hash_table_unref (priv->items);
G_OBJECT_CLASS (gabble_roster_parent_class)->finalize (object);
@@ -323,7 +310,6 @@ _parse_item_groups (WockyNode *item_node, TpBaseConnection *conn)
if (!handle)
continue;
tp_handle_set_add (groups, handle);
- tp_handle_unref (group_repo, handle);
}
return groups;
@@ -459,7 +445,6 @@ _gabble_roster_item_ensure (GabbleRoster *roster,
item->publish = TP_SUBSCRIPTION_STATE_NO;
item->name = alias;
item->groups = tp_handle_set_new (group_repo);
- tp_handle_ref (contact_repo, handle);
g_hash_table_insert (priv->items, GUINT_TO_POINTER (handle), item);
}
@@ -512,7 +497,6 @@ _gabble_roster_item_maybe_remove (GabbleRoster *roster,
DEBUG ("removing contact#%u", handle);
item = NULL;
g_hash_table_remove (priv->items, GUINT_TO_POINTER (handle));
- tp_handle_unref (contact_repo, handle);
return TRUE;
}
@@ -526,7 +510,7 @@ _gabble_roster_item_update (GabbleRoster *roster,
GabbleRosterPrivate *priv = roster->priv;
GabbleRosterItem *item;
const gchar *ask, *name;
- TpIntSet *new_groups, *added_to, *removed_from, *removed_from2;
+ TpIntset *new_groups, *added_to, *removed_from, *removed_from2;
TpHandleSet *new_groups_handle_set, *old_groups;
TpBaseContactList *base = (TpBaseContactList *) roster;
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
@@ -588,7 +572,7 @@ _gabble_roster_item_update (GabbleRoster *roster,
if (roster->priv->groups != NULL)
{
- TpIntSet *created_groups = tp_handle_set_update (roster->priv->groups,
+ TpIntset *created_groups = tp_handle_set_update (roster->priv->groups,
new_groups);
/* we don't need to do this work if TpBaseContactList will just be
@@ -599,7 +583,7 @@ _gabble_roster_item_update (GabbleRoster *roster,
{
GPtrArray *strv = g_ptr_array_sized_new (tp_intset_size (
created_groups));
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle group;
tp_intset_fast_iter_init (&iter, created_groups);
@@ -636,7 +620,7 @@ _gabble_roster_item_update (GabbleRoster *roster,
GPtrArray *removed_names = g_ptr_array_sized_new (
tp_intset_size (removed_from));
TpHandleSet *the_contact = tp_handle_set_new (contact_repo);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle group;
tp_handle_set_add (the_contact, contact_handle);
@@ -1113,7 +1097,6 @@ process_roster (
/* 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,
google_roster, &nickname_updated);
@@ -1547,12 +1530,11 @@ gabble_roster_presence_cb (WockyPorter *porter,
return FALSE;
}
- if (handle == conn->self_handle)
+ if (handle == tp_base_connection_get_self_handle (conn))
{
NODE_DEBUG (pres_node, "ignoring presence from ourselves on another "
"resource");
- ret = FALSE;
- goto OUT;
+ return FALSE;
}
g_assert (handle != 0);
@@ -1679,8 +1661,6 @@ gabble_roster_presence_cb (WockyPorter *porter,
ret = FALSE;
}
-OUT:
- tp_handle_unref (contact_repo, handle);
return ret;
}
@@ -1880,7 +1860,6 @@ item_edit_new (TpHandleRepoIface *contact_repo,
{
GabbleRosterItemEdit *self = g_slice_new0 (GabbleRosterItemEdit);
- tp_handle_ref (contact_repo, handle);
self->contact_repo = g_object_ref (contact_repo);
self->handle = handle;
self->new_subscription = GABBLE_ROSTER_SUBSCRIPTION_INVALID;
@@ -1906,7 +1885,6 @@ item_edit_free (GabbleRosterItemEdit *edits)
g_slist_free (edits->results);
- tp_handle_unref (edits->contact_repo, edits->handle);
g_object_unref (edits->contact_repo);
tp_clear_pointer (&edits->add_to_groups, tp_handle_set_destroy);
tp_clear_pointer (&edits->remove_from_groups, tp_handle_set_destroy);
@@ -1969,7 +1947,7 @@ roster_item_apply_edits (GabbleRoster *roster,
{
gboolean altered = FALSE;
GabbleRosterItem edited_item;
- TpIntSet *intset;
+ TpIntset *intset;
GabbleRosterPrivate *priv = roster->priv;
TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_GROUP);
@@ -2658,7 +2636,7 @@ gabble_roster_request_subscription_added_cb (GObject *source,
(TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT);
SubscribeContext *context = user_data;
GError *error = NULL;
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
/* Now that we've added all the contacts, send off all the subscription
@@ -2712,7 +2690,7 @@ gabble_roster_request_subscription_async (TpBaseContactList *base,
GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self,
gabble_roster_request_subscription_added_cb, context,
gabble_roster_request_subscription_async, 1);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
/* Before subscribing, add items to the roster
@@ -2740,7 +2718,7 @@ gabble_roster_authorize_publication_async (TpBaseContactList *base,
gpointer user_data)
{
GabbleRoster *self = GABBLE_ROSTER (base);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
GError *error = NULL;
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
@@ -2793,7 +2771,7 @@ gabble_roster_store_contacts_async (TpBaseContactList *base,
gpointer user_data)
{
GabbleRoster *self = GABBLE_ROSTER (base);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self,
callback, user_data, gabble_roster_store_contacts_async, 1);
@@ -2814,7 +2792,7 @@ gabble_roster_remove_contacts_async (TpBaseContactList *base,
gpointer user_data)
{
GabbleRoster *self = GABBLE_ROSTER (base);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self,
callback, user_data, gabble_roster_request_subscription_async, 1);
@@ -2839,7 +2817,7 @@ gabble_roster_unsubscribe_async (TpBaseContactList *base,
(TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT);
TpHandleSet *changed = tp_handle_set_new (contact_repo);
TpHandleSet *removed = tp_handle_set_new (contact_repo);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
GError *error = NULL;
@@ -2900,7 +2878,7 @@ gabble_roster_unpublish_async (TpBaseContactList *base,
(TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT);
TpHandleSet *changed = tp_handle_set_new (contact_repo);
TpHandleSet *removed = tp_handle_set_new (contact_repo);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
GError *error = NULL;
@@ -3041,7 +3019,7 @@ gabble_roster_block_contacts_async (TpBaseContactList *base,
gpointer user_data)
{
GabbleRoster *self = GABBLE_ROSTER (base);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self,
callback, user_data, gabble_roster_request_subscription_async, 1);
@@ -3062,7 +3040,7 @@ gabble_roster_unblock_contacts_async (TpBaseContactList *base,
gpointer user_data)
{
GabbleRoster *self = GABBLE_ROSTER (base);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self,
callback, user_data, gabble_roster_request_subscription_async, 1);
@@ -3086,7 +3064,7 @@ gabble_roster_dup_groups (TpBaseContactList *base)
if (self->priv->groups != NULL)
{
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle group;
ret = g_ptr_array_sized_new (
@@ -3122,7 +3100,7 @@ gabble_roster_dup_contact_groups (TpBaseContactList *base,
{
TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
(TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle group;
ret = g_ptr_array_sized_new (tp_handle_set_size (item->groups) + 1);
@@ -3218,7 +3196,6 @@ gabble_roster_set_contact_groups_async (TpBaseContactList *base,
g_ptr_array_add (groups_created, (gchar *) groups[i]);
}
- tp_handle_unref (group_repo, group_handle);
}
if (groups_created->len > 0)
@@ -3273,7 +3250,7 @@ gabble_roster_set_group_members_async (TpBaseContactList *base,
/* You can't add people to an invalid group. */
if (G_UNLIKELY (group_handle == 0))
{
- g_simple_async_result_set_error (result, TP_ERRORS,
+ g_simple_async_result_set_error (result, TP_ERROR,
TP_ERROR_INVALID_ARGUMENT, "Invalid group name: %s", group);
goto finally;
}
@@ -3300,8 +3277,6 @@ gabble_roster_set_group_members_async (TpBaseContactList *base,
result);
}
- tp_handle_unref (group_repo, group_handle);
-
finally:
gabble_simple_async_countdown_dec (result);
g_object_unref (result);
@@ -3315,7 +3290,7 @@ gabble_roster_add_to_group_async (TpBaseContactList *base,
gpointer user_data)
{
GabbleRoster *self = GABBLE_ROSTER (base);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
(TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP);
@@ -3327,7 +3302,7 @@ gabble_roster_add_to_group_async (TpBaseContactList *base,
/* You can't add people to an invalid group. */
if (G_UNLIKELY (group_handle == 0))
{
- g_simple_async_result_set_error (result, TP_ERRORS,
+ g_simple_async_result_set_error (result, TP_ERROR,
TP_ERROR_INVALID_ARGUMENT, "Invalid group name: %s", group);
goto finally;
}
@@ -3348,8 +3323,6 @@ gabble_roster_add_to_group_async (TpBaseContactList *base,
gabble_roster_handle_add_to_group (self, contact, group_handle, result);
}
- tp_handle_unref (group_repo, group_handle);
-
finally:
gabble_simple_async_countdown_dec (result);
g_object_unref (result);
@@ -3363,7 +3336,7 @@ gabble_roster_remove_from_group_async (TpBaseContactList *base,
gpointer user_data)
{
GabbleRoster *self = GABBLE_ROSTER (base);
- TpIntSetFastIter iter;
+ TpIntsetFastIter iter;
TpHandle contact;
TpHandleRepoIface *group_repo = tp_base_connection_get_handles (
(TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP);
@@ -3464,8 +3437,6 @@ gabble_roster_remove_group_removed_cb (GObject *source,
DEBUG ("contact #%u is still a member of group '%s', not removing",
remaining_member, group);
}
-
- tp_handle_unref (group_repo, context->group_handle);
}
context->callback (source, result, context->user_data);
@@ -3495,9 +3466,6 @@ gabble_roster_remove_group_async (TpBaseContactList *base,
context->user_data = user_data;
context->contacts = tp_handle_set_new (contact_repo);
- if (context->group_handle != 0)
- tp_handle_ref (group_repo, context->group_handle);
-
result = gabble_simple_async_countdown_new (self,
gabble_roster_remove_group_removed_cb,
context, gabble_roster_remove_group_async, 1);
@@ -3633,6 +3601,9 @@ gabble_roster_handle_gets_presence_from_us (GabbleRoster *self,
if (item == NULL)
return FALSE;
+ if (item->blocked)
+ return FALSE;
+
return (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_FROM ||
item->subscription == GABBLE_ROSTER_SUBSCRIPTION_BOTH);
}
diff --git a/src/roster.h b/src/roster.h
index 185dde514..4cc2b0dcf 100644
--- a/src/roster.h
+++ b/src/roster.h
@@ -24,7 +24,7 @@
#include <glib-object.h>
-#include <telepathy-glib/base-contact-list.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "types.h"
diff --git a/src/search-channel.c b/src/search-channel.c
index afbb098ee..0c253ba92 100644
--- a/src/search-channel.c
+++ b/src/search-channel.c
@@ -23,11 +23,8 @@
#include <string.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/util.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
@@ -39,10 +36,6 @@
#include "namespaces.h"
#include "util.h"
-static const gchar *gabble_search_channel_interfaces[] = {
- NULL
-};
-
/* properties */
enum
{
@@ -234,7 +227,7 @@ parse_unextended_field_response (
}
else
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"server is broken: %s is not a field defined in XEP 0055",
field->name);
g_ptr_array_unref (search_keys);
@@ -272,7 +265,7 @@ parse_data_form (
if (tp_strdiff (wocky_node_get_attribute (x_node, "type"), "form"))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"server is broken: <x> not type='form'");
goto fail;
}
@@ -308,7 +301,7 @@ parse_data_form (
if (tp_strdiff (form_type, NS_SEARCH))
{
DEBUG ("<x> form does not have FORM_TYPE %s", NS_SEARCH);
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"server is broken: form lacking FORM_TYPE %s", NS_SEARCH);
goto fail;
}
@@ -416,7 +409,7 @@ query_reply_cb (GabbleConnection *conn,
}
else if (NULL == query_node)
{
- err = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ err = g_error_new (TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"%s is broken: it replied to our <query> with an empty IQ",
chan->priv->server);
}
@@ -461,7 +454,7 @@ request_search_fields (GabbleSearchChannel *chan)
* change_search_state:
* @chan: a search channel
* @state: the new state for the channel
- * @reason: an error in the TP_ERRORS domain if the search has failed; NULL
+ * @reason: an error in the TP_ERROR domain if the search has failed; NULL
* otherwise.
*/
static void
@@ -493,7 +486,7 @@ change_search_state (GabbleSearchChannel *chan,
if (state == TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED)
{
g_assert (reason != NULL);
- g_assert (reason->domain == TP_ERRORS);
+ g_assert (reason->domain == TP_ERROR);
error_name = tp_error_get_dbus_name (reason->code);
g_value_init (&v, G_TYPE_STRING);
@@ -737,7 +730,7 @@ parse_extended_search_results (GabbleSearchChannel *chan,
x = wocky_node_get_child_ns (query_node, "x", NS_X_DATA);
if (x == NULL)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"reply doens't contain a <x> node");
return FALSE;
}
@@ -802,7 +795,7 @@ search_reply_cb (GabbleConnection *conn,
}
else if (NULL == query_node)
{
- err = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ err = g_error_new (TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"%s is broken: its iq reply didn't contain a <query/>",
chan->priv->server);
}
@@ -848,7 +841,7 @@ validate_terms (GabbleSearchChannel *chan,
if (!tp_strv_contains (asks, field))
{
DEBUG ("%s is not in AvailableSearchKeys", field);
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%s is not in AvailableSearchKeys", field);
return FALSE;
}
@@ -887,12 +880,12 @@ build_extended_query (GabbleSearchChannel *self,
GHashTableIter iter;
gpointer key, value;
- x = wocky_node_add_child_with_content (query, "x", "");
- x->ns = g_quark_from_static_string (NS_X_DATA);
+ x = wocky_node_add_child_ns_q (query, "x",
+ g_quark_from_static_string (NS_X_DATA));
wocky_node_set_attribute (x, "type", "submit");
/* add FORM_TYPE */
- field = wocky_node_add_child_with_content (x, "field", "");
+ field = wocky_node_add_child (x, "field");
wocky_node_set_attributes (field,
"type", "hidden",
"var", "FORM_TYPE",
@@ -909,7 +902,7 @@ build_extended_query (GabbleSearchChannel *self,
g_assert (xmpp_field != NULL);
- field = wocky_node_add_child_with_content (x, "field", "");
+ field = wocky_node_add_child (x, "field");
wocky_node_set_attribute (field, "var", xmpp_field);
wocky_node_add_child_with_content (field, "value", value);
@@ -922,7 +915,7 @@ build_extended_query (GabbleSearchChannel *self,
{
xmpp_field = g_ptr_array_index (self->priv->boolean_keys, i);
- field = wocky_node_add_child_with_content (x, "field", "");
+ field = wocky_node_add_child (x, "field");
wocky_node_set_attributes (field,
"var", xmpp_field,
"type", "boolean",
@@ -1159,7 +1152,6 @@ gabble_search_channel_class_init (GabbleSearchChannelClass *klass)
object_class->set_property = gabble_search_channel_set_property;
base_class->channel_type = TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH;
- base_class->interfaces = gabble_search_channel_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_NONE;
base_class->fill_immutable_properties =
gabble_search_channel_fill_immutable_properties;
@@ -1204,7 +1196,7 @@ gabble_search_channel_class_init (GabbleSearchChannelClass *klass)
* server gave us a set of search keys, and they were sane, all components
* will be 0 or %NULL, indicating that this channel can be announced and
* used; if the server doesn't actually speak XEP 0055 or is full of bees,
- * they'll be an error in either the GABBLE_XMPP_ERROR or the TP_ERRORS
+ * they'll be an error in either the GABBLE_XMPP_ERROR or the TP_ERROR
* domain.
*/
signals[READY_OR_NOT] =
@@ -1235,7 +1227,7 @@ gabble_search_channel_search (TpSvcChannelTypeContactSearch *self,
if (priv->state != TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED)
{
- error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ error = g_error_new (TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"SearchState is %s", states[priv->state]);
goto err;
}
@@ -1262,7 +1254,7 @@ gabble_search_channel_stop (TpSvcChannelTypeContactSearch *self,
{
case TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS:
{
- GError e = { TP_ERRORS, TP_ERROR_CANCELLED, "Stop() called" };
+ GError e = { TP_ERROR, TP_ERROR_CANCELLED, "Stop() called" };
change_search_state (chan,
TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED, &e);
@@ -1274,7 +1266,7 @@ gabble_search_channel_stop (TpSvcChannelTypeContactSearch *self,
break;
case TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED:
{
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Search() hasn't been called yet" };
dbus_g_method_return_error (context, &e);
diff --git a/src/search-channel.h b/src/search-channel.h
index 9b6c748ab..066fd8535 100644
--- a/src/search-channel.h
+++ b/src/search-channel.h
@@ -23,7 +23,7 @@
#include <glib-object.h>
-#include <telepathy-glib/base-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
G_BEGIN_DECLS
diff --git a/src/search-manager.c b/src/search-manager.c
index c78598fb1..e0af6eb4a 100644
--- a/src/search-manager.c
+++ b/src/search-manager.c
@@ -21,9 +21,8 @@
#include "config.h"
#include "search-manager.h"
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
@@ -149,7 +148,7 @@ disco_done_cb (GabbleDisco *disco,
else
{
tp_channel_manager_emit_request_failed (self, request_token,
- TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"No Server has been specified and no server has been "
"discovered on the connection");
}
@@ -408,7 +407,7 @@ search_channel_ready_or_not_cb (GabbleSearchChannel *chan,
{
if (domain == WOCKY_XMPP_ERROR)
{
- domain = TP_ERRORS;
+ domain = TP_ERROR;
switch (code)
{
@@ -424,7 +423,7 @@ search_channel_ready_or_not_cb (GabbleSearchChannel *chan,
}
else
{
- g_assert (domain == TP_ERRORS);
+ g_assert (domain == TP_ERROR);
}
tp_channel_manager_emit_request_failed (ctx->self,
@@ -442,13 +441,14 @@ new_search_channel (GabbleSearchManager *self,
{
GabbleSearchManagerPrivate *priv = self->priv;
GabbleSearchChannel *chan;
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
g_assert (server != NULL);
chan = g_object_new (GABBLE_TYPE_SEARCH_CHANNEL,
"connection", priv->conn,
"server", server,
- "initiator-handle", priv->conn->parent.self_handle,
+ "initiator-handle", tp_base_connection_get_self_handle (base_conn),
NULL);
g_hash_table_insert (priv->channels, chan, priv->channels);
g_signal_connect (chan, "closed", (GCallback) search_channel_closed_cb, self);
@@ -490,7 +490,7 @@ gabble_search_manager_create_channel (TpChannelManager *manager,
else if (!wocky_decode_jid (server, NULL, NULL, NULL))
{
/* On the other hand, if the JID's invalid, blow up. */
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Specified server '%s' is not a valid JID", server);
goto error;
}
@@ -501,7 +501,7 @@ gabble_search_manager_create_channel (TpChannelManager *manager,
{
if (self->priv->disco_done)
{
- error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ error = g_error_new (TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"No Server has been specified and no server has been "
"discovered on the connection");
goto error;
diff --git a/src/server-sasl-channel.c b/src/server-sasl-channel.c
index 961d6d491..3eb4f66f2 100644
--- a/src/server-sasl-channel.c
+++ b/src/server-sasl-channel.c
@@ -36,15 +36,8 @@
#include <dbus/dbus-glib.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-generic.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_AUTH
@@ -66,12 +59,6 @@ G_DEFINE_TYPE_WITH_CODE (GabbleServerSaslChannel, gabble_server_sasl_channel,
TP_TYPE_SVC_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
sasl_auth_iface_init));
-static const gchar *gabble_server_sasl_channel_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
- TP_IFACE_CHANNEL_INTERFACE_SECURABLE,
- NULL
-};
-
enum
{
/* server authentication channel */
@@ -106,10 +93,25 @@ struct _GabbleServerSaslChannelPrivate
GHashTable *sasl_error_details;
/* Given to the Connection on request */
TpConnectionStatusReason disconnect_reason;
+ GError *wocky_auth_error /* = NULL */;
GSimpleAsyncResult *result;
};
+static GPtrArray *
+gabble_server_sasl_channel_get_interfaces (TpBaseChannel *base)
+{
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CHANNEL_CLASS (
+ gabble_server_sasl_channel_parent_class)->get_interfaces (base);
+
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION);
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_SECURABLE);
+
+ return interfaces;
+}
+
static void
gabble_server_sasl_channel_init (GabbleServerSaslChannel *self)
{
@@ -274,6 +276,7 @@ gabble_server_sasl_channel_finalize (GObject *object)
g_free (priv->sasl_error);
g_hash_table_unref (priv->sasl_error_details);
+ g_clear_error (&priv->wocky_auth_error);
if (G_OBJECT_CLASS (gabble_server_sasl_channel_parent_class)->finalize)
G_OBJECT_CLASS (gabble_server_sasl_channel_parent_class)->finalize (object);
@@ -337,7 +340,7 @@ gabble_server_sasl_channel_class_init (GabbleServerSaslChannelClass *klass)
channel_class->channel_type =
TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION;
- channel_class->interfaces = gabble_server_sasl_channel_interfaces;
+ channel_class->get_interfaces = gabble_server_sasl_channel_get_interfaces;
channel_class->target_handle_type = TP_HANDLE_TYPE_NONE;
channel_class->fill_immutable_properties =
gabble_server_sasl_channel_fill_immutable_properties;
@@ -431,13 +434,12 @@ gabble_server_sasl_channel_class_init (GabbleServerSaslChannelClass *klass)
}
static void
-change_current_state (GabbleServerSaslChannel *self,
- TpSASLStatus status,
+set_errors (
+ GabbleServerSaslChannel *self,
const gchar *dbus_error,
- const gchar *debug_message)
+ const gchar *debug_message,
+ const GError *error)
{
- self->priv->sasl_status = status;
-
g_free (self->priv->sasl_error);
self->priv->sasl_error = g_strdup (dbus_error);
@@ -446,12 +448,41 @@ change_current_state (GabbleServerSaslChannel *self,
tp_asv_set_string (self->priv->sasl_error_details, "debug-message",
debug_message);
+ g_clear_error (&self->priv->wocky_auth_error);
+ self->priv->wocky_auth_error = g_error_copy (error);
+}
+
+static void
+change_current_state (GabbleServerSaslChannel *self,
+ TpSASLStatus status)
+{
+ self->priv->sasl_status = status;
+
tp_svc_channel_interface_sasl_authentication_emit_sasl_status_changed (
self, self->priv->sasl_status,
self->priv->sasl_error,
self->priv->sasl_error_details);
}
+static void
+complete_operation (
+ GabbleServerSaslChannel *self,
+ gboolean in_idle)
+{
+ GabbleServerSaslChannelPrivate *priv = self->priv;
+ GSimpleAsyncResult *r = priv->result;
+
+ g_return_if_fail (priv->result != NULL);
+ priv->result = NULL;
+
+ if (in_idle)
+ g_simple_async_result_complete_in_idle (r);
+ else
+ g_simple_async_result_complete (r);
+
+ g_object_unref (r);
+}
+
/**
* SASL Authentication Channel Interface
*/
@@ -470,7 +501,7 @@ gabble_server_sasl_channel_raise (DBusGMethodInvocation *context,
GError *error = NULL;
va_start (ap, message);
- error = g_error_new_valist (TP_ERRORS, code, message, ap);
+ error = g_error_new_valist (TP_ERROR, code, message, ap);
va_end (ap);
dbus_g_method_return_error (context, error);
@@ -489,7 +520,6 @@ gabble_server_sasl_channel_start_mechanism_with_data (
GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (iface);
GabbleServerSaslChannelPrivate *priv = self->priv;
WockyAuthRegistryStartData *start_data;
- GSimpleAsyncResult *r = priv->result;
GString *initial_data = NULL;
if (self->priv->sasl_status != TP_SASL_STATUS_NOT_STARTED)
@@ -503,15 +533,13 @@ gabble_server_sasl_channel_start_mechanism_with_data (
/* NotStarted state is entered by creating the channel: the caller must
* call start_auth_async immediately */
- g_assert (r != NULL);
- g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (r),
+ g_assert (priv->result != NULL);
+ g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (priv->result),
G_OBJECT (self), gabble_server_sasl_channel_start_auth_async));
if (tp_strv_contains ((const gchar * const *) priv->available_mechanisms,
in_Mechanism))
{
- priv->result = NULL;
-
if (in_InitialData != NULL)
{
/* The initial data might be secret (for PLAIN etc.), and also might
@@ -527,16 +555,15 @@ gabble_server_sasl_channel_start_mechanism_with_data (
in_Mechanism);
}
- change_current_state (self, TP_SASL_STATUS_IN_PROGRESS, NULL, NULL);
+ change_current_state (self, TP_SASL_STATUS_IN_PROGRESS);
dbus_g_method_return (context);
start_data =
wocky_auth_registry_start_data_new (in_Mechanism, initial_data);
- g_simple_async_result_set_op_res_gpointer (r,
+ g_simple_async_result_set_op_res_gpointer (priv->result,
start_data, (GDestroyNotify) wocky_auth_registry_start_data_free);
- g_simple_async_result_complete_in_idle (r);
- g_object_unref (r);
+ complete_operation (self, TRUE);
if (initial_data != NULL)
g_string_free (initial_data, TRUE);
@@ -567,8 +594,8 @@ gabble_server_sasl_channel_respond (
{
GabbleServerSaslChannel *self =
GABBLE_SERVER_SASL_CHANNEL (channel);
+ GabbleServerSaslChannelPrivate *priv = self->priv;
GString *response_data;
- GSimpleAsyncResult *r = self->priv->result;
if (self->priv->sasl_status != TP_SASL_STATUS_IN_PROGRESS)
{
@@ -580,7 +607,7 @@ gabble_server_sasl_channel_respond (
return;
}
- if (r == NULL)
+ if (priv->result == NULL)
{
gabble_server_sasl_channel_raise (context, TP_ERROR_NOT_AVAILABLE,
"You already responded to the most recent challenge");
@@ -588,26 +615,22 @@ gabble_server_sasl_channel_respond (
return;
}
- g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (r),
+ g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (priv->result),
G_OBJECT (self), gabble_server_sasl_channel_challenge_async));
/* The response might be secret (for PLAIN etc.), and also might
* not be UTF-8 or even text, so we just output the length */
DEBUG ("responding with %u bytes", in_Response_Data->len);
- self->priv->result = NULL;
-
if (in_Response_Data->len > 0)
response_data = g_string_new_len (in_Response_Data->data,
in_Response_Data->len);
else
response_data = NULL;
- g_simple_async_result_set_op_res_gpointer (r, response_data,
+ g_simple_async_result_set_op_res_gpointer (priv->result, response_data,
(GDestroyNotify) wocky_g_string_free);
-
- g_simple_async_result_complete_in_idle (r);
- g_object_unref (r);
+ complete_operation (self, TRUE);
tp_svc_channel_interface_sasl_authentication_return_from_respond (
context);
@@ -619,10 +642,9 @@ gabble_server_sasl_channel_accept_sasl (
DBusGMethodInvocation *context)
{
GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel);
- GSimpleAsyncResult *r = self->priv->result;
+ GabbleServerSaslChannelPrivate *priv = self->priv;
const gchar *message = NULL;
-
switch (self->priv->sasl_status)
{
case TP_SASL_STATUS_NOT_STARTED:
@@ -633,7 +655,7 @@ gabble_server_sasl_channel_accept_sasl (
/* In this state, the only valid time to call this method is in response
* to a challenge, to indicate that, actually, that challenge was
* additional data for a successful authentication. */
- if (r == NULL)
+ if (priv->result == NULL)
{
message = "In_Progress, but you already responded to the last "
"challenge";
@@ -642,10 +664,9 @@ gabble_server_sasl_channel_accept_sasl (
{
DEBUG ("client says the last challenge was actually final data "
"and has accepted it");
- g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (r),
+ g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (priv->result),
G_OBJECT (self), gabble_server_sasl_channel_challenge_async));
- change_current_state (self, TP_SASL_STATUS_CLIENT_ACCEPTED, NULL,
- NULL);
+ change_current_state (self, TP_SASL_STATUS_CLIENT_ACCEPTED);
}
break;
@@ -654,9 +675,9 @@ gabble_server_sasl_channel_accept_sasl (
* success_async(), i.e. waiting for the UI to check whether it's
* happy too. AcceptSASL means that it is. */
DEBUG ("client has accepted server's success");
- g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (r),
+ g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (priv->result),
G_OBJECT (self), gabble_server_sasl_channel_success_async));
- change_current_state (self, TP_SASL_STATUS_SUCCEEDED, NULL, NULL);
+ change_current_state (self, TP_SASL_STATUS_SUCCEEDED);
break;
case TP_SASL_STATUS_CLIENT_ACCEPTED:
@@ -687,20 +708,18 @@ gabble_server_sasl_channel_accept_sasl (
return;
}
- if (r != NULL)
+ if (priv->result != NULL)
{
/* This is a bit weird - this code is run for two different async
* results. In the In_Progress case, this code results in
* success with the GSimpleAsyncResult's op_res left as NULL, which
* is what Wocky wants for an empty response. In the Server_Succeeded
* response, the async result is just success or error - we succeed. */
- self->priv->result = NULL;
/* We want want to complete not in an idle because if we do we
* will hit fd.o#32278. This is safe because we're being called
* from dbus-glib in the main loop. */
- g_simple_async_result_complete (r);
- g_object_unref (r);
+ complete_operation (self, FALSE);
}
tp_svc_channel_interface_sasl_authentication_return_from_accept_sasl (
@@ -715,8 +734,7 @@ gabble_server_sasl_channel_abort_sasl (
DBusGMethodInvocation *context)
{
GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel);
- GSimpleAsyncResult *r = self->priv->result;
- guint code;
+ GabbleServerSaslChannelPrivate *priv = self->priv;
const gchar *dbus_error;
switch (self->priv->sasl_status)
@@ -736,49 +754,53 @@ gabble_server_sasl_channel_abort_sasl (
case TP_SASL_STATUS_NOT_STARTED:
case TP_SASL_STATUS_IN_PROGRESS:
case TP_SASL_STATUS_SERVER_SUCCEEDED:
+ {
+ GError *error = NULL;
+
switch (in_Reason)
{
case TP_SASL_ABORT_REASON_INVALID_CHALLENGE:
- DEBUG ("invalid challenge (%s)", in_Debug_Message);
- code = WOCKY_AUTH_ERROR_INVALID_REPLY;
+ g_set_error (&error, WOCKY_AUTH_ERROR,
+ WOCKY_AUTH_ERROR_INVALID_REPLY,
+ "invalid challenge (%s)", in_Debug_Message);
dbus_error = TP_ERROR_STR_SERVICE_CONFUSED;
break;
case TP_SASL_ABORT_REASON_USER_ABORT:
- DEBUG ("user aborted auth (%s)", in_Debug_Message);
- code = WOCKY_AUTH_ERROR_FAILURE;
+ g_set_error (&error, WOCKY_AUTH_ERROR,
+ WOCKY_AUTH_ERROR_FAILURE,
+ "user aborted auth (%s)", in_Debug_Message);
dbus_error = TP_ERROR_STR_CANCELLED;
break;
default:
- DEBUG ("unknown reason code %u, treating as User_Abort (%s)",
+ g_set_error (&error, WOCKY_AUTH_ERROR,
+ WOCKY_AUTH_ERROR_FAILURE,
+ "unknown reason code %u, treating as User_Abort (%s)",
in_Reason, in_Debug_Message);
- code = WOCKY_AUTH_ERROR_FAILURE;
dbus_error = TP_ERROR_STR_CANCELLED;
break;
}
- if (r != NULL)
- {
- self->priv->result = NULL;
+ DEBUG ("%s", error->message);
+ set_errors (self, dbus_error, in_Debug_Message, error);
+ change_current_state (self, TP_SASL_STATUS_CLIENT_FAILED);
+
+ if (priv->result != NULL)
+ {
/* If Not_Started, we're returning failure from start_auth_async.
* If In_Progress, we might be returning failure from
* challenge_async, if one is outstanding.
* If Server_Succeeded, we're returning failure from success_async.
*/
-
- g_simple_async_result_set_error (r, WOCKY_AUTH_ERROR, code,
- "Authentication aborted: %s", in_Debug_Message);
-
- g_simple_async_result_complete_in_idle (r);
- g_object_unref (r);
+ g_simple_async_result_set_from_error (priv->result, error);
+ complete_operation (self, TRUE);
}
- change_current_state (self, TP_SASL_STATUS_CLIENT_FAILED,
- dbus_error, in_Debug_Message);
+ g_error_free (error);
break;
-
+ }
default:
g_assert_not_reached ();
}
@@ -840,7 +862,7 @@ gabble_server_sasl_channel_challenge_async (GabbleServerSaslChannel *self,
g_assert (!tp_base_channel_is_destroyed ((TpBaseChannel *) self));
g_assert (priv->result == NULL);
- g_assert (priv->sasl_status == TP_SASL_STATUS_IN_PROGRESS);
+
/* it might be sensitive, and also might not be UTF-8 text, so just print
* the length */
DEBUG ("New challenge, %" G_GSIZE_FORMAT " bytes", challenge_data->len);
@@ -848,13 +870,26 @@ gabble_server_sasl_channel_challenge_async (GabbleServerSaslChannel *self,
priv->result = g_simple_async_result_new (G_OBJECT (self), callback,
user_data, gabble_server_sasl_channel_challenge_async);
- challenge_ay = g_array_sized_new (FALSE, FALSE, sizeof (gchar),
- challenge_data->len);
- g_array_append_vals (challenge_ay, challenge_data->str,
- challenge_data->len);
+ switch (priv->sasl_status)
+ {
+ case TP_SASL_STATUS_IN_PROGRESS:
+ challenge_ay = g_array_sized_new (FALSE, FALSE, sizeof (gchar),
+ challenge_data->len);
+ g_array_append_vals (challenge_ay, challenge_data->str,
+ challenge_data->len);
- tp_svc_channel_interface_sasl_authentication_emit_new_challenge (
- self, challenge_ay);
+ tp_svc_channel_interface_sasl_authentication_emit_new_challenge (
+ self, challenge_ay);
+ break;
+ case TP_SASL_STATUS_CLIENT_FAILED:
+ g_return_if_fail (priv->wocky_auth_error != NULL);
+ g_simple_async_result_set_from_error (priv->result,
+ priv->wocky_auth_error);
+ complete_operation (self, TRUE);
+ return;
+ default:
+ g_assert_not_reached ();
+ }
}
gboolean
@@ -874,12 +909,11 @@ gabble_server_sasl_channel_success_async (GabbleServerSaslChannel *self,
gpointer user_data)
{
GabbleServerSaslChannelPrivate *priv = self->priv;
- GSimpleAsyncResult *r;
g_assert (!tp_base_channel_is_destroyed ((TpBaseChannel *) self));
g_assert (priv->result == NULL);
- r = g_simple_async_result_new (G_OBJECT (self),
+ priv->result = g_simple_async_result_new (G_OBJECT (self),
callback, user_data,
gabble_server_sasl_channel_success_async);
@@ -887,16 +921,12 @@ gabble_server_sasl_channel_success_async (GabbleServerSaslChannel *self,
if (self->priv->sasl_status != TP_SASL_STATUS_CLIENT_ACCEPTED)
{
- priv->result = r;
- change_current_state (self, TP_SASL_STATUS_SERVER_SUCCEEDED,
- NULL, NULL);
+ change_current_state (self, TP_SASL_STATUS_SERVER_SUCCEEDED);
}
else
{
- change_current_state (self, TP_SASL_STATUS_SUCCEEDED, NULL,
- NULL);
- g_simple_async_result_complete_in_idle (r);
- g_object_unref (r);
+ change_current_state (self, TP_SASL_STATUS_SUCCEEDED);
+ complete_operation (self, TRUE);
}
}
@@ -924,11 +954,12 @@ gabble_server_sasl_channel_fail (GabbleServerSaslChannel *self,
gabble_set_tp_conn_error_from_wocky (error, TP_CONNECTION_STATUS_CONNECTING,
&conn_reason, &tp_error);
- g_assert (tp_error->domain == TP_ERRORS);
+ g_assert (tp_error->domain == TP_ERROR);
DEBUG ("auth failed: %s", tp_error->message);
- change_current_state (self, TP_SASL_STATUS_SERVER_FAILED,
- tp_error_get_dbus_name (tp_error->code), tp_error->message);
+ set_errors (self,
+ tp_error_get_dbus_name (tp_error->code), tp_error->message, error);
+ change_current_state (self, TP_SASL_STATUS_SERVER_FAILED);
self->priv->disconnect_reason = conn_reason;
}
@@ -961,21 +992,37 @@ gabble_server_sasl_channel_close (TpBaseChannel *channel)
{
GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel);
GabbleServerSaslChannelPrivate *priv = self->priv;
+ GError error = { WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE,
+ "Client aborted authentication." };
DEBUG ("called on %p", self);
- if (priv->result != NULL)
+ switch (priv->sasl_status)
{
- GSimpleAsyncResult *r = priv->result;
+ case TP_SASL_STATUS_NOT_STARTED:
+ case TP_SASL_STATUS_IN_PROGRESS:
+ case TP_SASL_STATUS_SERVER_SUCCEEDED:
+ set_errors (self, TP_ERROR_STR_AUTHENTICATION_FAILED, "Close() called",
+ &error);
+ break;
+
+ case TP_SASL_STATUS_CLIENT_ACCEPTED:
+ case TP_SASL_STATUS_SUCCEEDED:
+ /* Hooray! */
+ break;
+ case TP_SASL_STATUS_SERVER_FAILED:
+ case TP_SASL_STATUS_CLIENT_FAILED:
+ g_warn_if_fail (priv->sasl_error != NULL);
+ break;
+ }
+
+ if (priv->result != NULL)
+ {
DEBUG ("closed channel");
- priv->result = NULL;
- g_simple_async_result_set_error (r, WOCKY_AUTH_ERROR,
- WOCKY_AUTH_ERROR_FAILURE,
- "%s", "Client aborted authentication.");
- g_simple_async_result_complete_in_idle (r);
- g_object_unref (r);
+ g_simple_async_result_set_from_error (priv->result, &error);
+ complete_operation (self, TRUE);
}
tp_base_channel_destroyed (channel);
@@ -986,6 +1033,8 @@ gabble_server_sasl_channel_close (TpBaseChannel *channel)
* @details: (out) (transfer full) (element-type utf8 GObject.Value): the
* error details
* @reason: (out): the reason with which to disconnect
+ * @error: (out): an error in a domain Wocky understands describing what went
+ * wrong
*
* Returns: %TRUE if an error was copied; %FALSE leaving the 'out' parameters
* untouched if there is no error
@@ -994,7 +1043,8 @@ gboolean
gabble_server_sasl_channel_get_failure_details (GabbleServerSaslChannel *self,
gchar **dbus_error,
GHashTable **details,
- TpConnectionStatusReason *reason)
+ TpConnectionStatusReason *reason,
+ GError **error)
{
if (self->priv->sasl_error != NULL)
{
@@ -1007,6 +1057,9 @@ gabble_server_sasl_channel_get_failure_details (GabbleServerSaslChannel *self,
if (reason != NULL)
*reason = self->priv->disconnect_reason;
+ if (error != NULL)
+ *error = g_error_copy (self->priv->wocky_auth_error);
+
return TRUE;
}
else
diff --git a/src/server-sasl-channel.h b/src/server-sasl-channel.h
index 69b469974..83e41bd56 100644
--- a/src/server-sasl-channel.h
+++ b/src/server-sasl-channel.h
@@ -22,7 +22,7 @@
#include <glib-object.h>
-#include <telepathy-glib/base-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
#include "types.h"
@@ -94,7 +94,8 @@ void gabble_server_sasl_channel_fail (GabbleServerSaslChannel *self,
gboolean gabble_server_sasl_channel_get_failure_details (
GabbleServerSaslChannel *self, gchar **dbus_error, GHashTable **details,
- TpConnectionStatusReason *reason);
+ TpConnectionStatusReason *reason,
+ GError **error);
G_END_DECLS
diff --git a/src/server-tls-channel.c b/src/server-tls-channel.c
index a82842d77..aae0aadc8 100644
--- a/src/server-tls-channel.c
+++ b/src/server-tls-channel.c
@@ -22,10 +22,8 @@
#include "server-tls-channel.h"
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-generic.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include <wocky/wocky.h>
@@ -41,10 +39,6 @@ G_DEFINE_TYPE_WITH_CODE (GabbleServerTLSChannel, gabble_server_tls_channel,
static void gabble_server_tls_channel_close (TpBaseChannel *base);
-static const gchar *gabble_server_tls_channel_interfaces[] = {
- NULL
-};
-
enum {
/* server TLS channel iface */
PROP_SERVER_CERTIFICATE = 1,
@@ -262,7 +256,6 @@ gabble_server_tls_channel_class_init (GabbleServerTLSChannelClass *klass)
oclass->constructed = gabble_server_tls_channel_constructed;
base_class->channel_type = TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION;
- base_class->interfaces = gabble_server_tls_channel_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_NONE;
base_class->fill_immutable_properties =
gabble_server_tls_channel_fill_immutable_properties;
diff --git a/src/server-tls-channel.h b/src/server-tls-channel.h
index 45afbf2a3..a21f1e358 100644
--- a/src/server-tls-channel.h
+++ b/src/server-tls-channel.h
@@ -23,7 +23,7 @@
#include <glib-object.h>
-#include <telepathy-glib/base-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <extensions/extensions.h>
diff --git a/src/server-tls-manager.c b/src/server-tls-manager.c
index c28d2d4d2..4e961cdde 100644
--- a/src/server-tls-manager.c
+++ b/src/server-tls-manager.c
@@ -21,7 +21,8 @@
#include "config.h"
#include "server-tls-manager.h"
-#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_TLS
#include "debug.h"
@@ -345,7 +346,7 @@ gabble_server_tls_manager_verify_async (WockyTLSHandler *handler,
if (self->priv->connection == NULL)
{
DEBUG ("connection already went away; failing immediately");
- g_simple_async_result_set_error (result, TP_ERRORS, TP_ERROR_CANCELLED,
+ g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_CANCELLED,
"The Telepathy connection has already been disconnected");
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
diff --git a/src/server-tls-manager.h b/src/server-tls-manager.h
index e8f10af1b..816866b5e 100644
--- a/src/server-tls-manager.h
+++ b/src/server-tls-manager.h
@@ -23,8 +23,7 @@
#include <glib-object.h>
#include <wocky/wocky.h>
-
-#include <telepathy-glib/enums.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "extensions/extensions.h"
diff --git a/src/tls-certificate.c b/src/tls-certificate.c
index 6d5748568..303b70644 100644
--- a/src/tls-certificate.c
+++ b/src/tls-certificate.c
@@ -22,7 +22,7 @@
#include "tls-certificate.h"
#include <telepathy-glib/telepathy-glib.h>
-#include <telepathy-glib/svc-tls.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_TLS
#include "debug.h"
@@ -266,7 +266,7 @@ gabble_tls_certificate_accept (TpSvcAuthenticationTLSCertificate *cert,
if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING)
{
GError error =
- { TP_ERRORS,
+ { TP_ERROR,
TP_ERROR_INVALID_ARGUMENT,
"Calling Accept() on a certificate with state != PENDING "
"doesn't make sense."
@@ -295,7 +295,7 @@ gabble_tls_certificate_reject (TpSvcAuthenticationTLSCertificate *cert,
if (rejections->len < 1)
{
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Calling Reject() with a zero-length rejection list." };
dbus_g_method_return_error (context, &error);
@@ -305,7 +305,7 @@ gabble_tls_certificate_reject (TpSvcAuthenticationTLSCertificate *cert,
if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING)
{
GError error =
- { TP_ERRORS,
+ { TP_ERROR,
TP_ERROR_INVALID_ARGUMENT,
"Calling Reject() on a certificate with state != PENDING "
"doesn't make sense."
diff --git a/src/tls-certificate.h b/src/tls-certificate.h
index e71245d1c..271ce09d7 100644
--- a/src/tls-certificate.h
+++ b/src/tls-certificate.h
@@ -23,7 +23,7 @@
#include <glib-object.h>
-#include <telepathy-glib/dbus-properties-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
G_BEGIN_DECLS
diff --git a/src/tube-dbus.c b/src/tube-dbus.c
index 424bf3dc5..d982e7902 100644
--- a/src/tube-dbus.c
+++ b/src/tube-dbus.c
@@ -27,18 +27,13 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/group-mixin.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-generic.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "extensions/extensions.h"
#define DEBUG_FLAG GABBLE_DEBUG_TUBES
-#include "base64.h"
#include "bytestream-factory.h"
#include "bytestream-ibb.h"
#include "bytestream-iface.h"
@@ -75,11 +70,6 @@ G_DEFINE_TYPE_WITH_CODE (GabbleTubeDBus, gabble_tube_dbus,
tp_external_group_mixin_iface_init);
);
-static const gchar *gabble_tube_dbus_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_TUBE,
- NULL
-};
-
static const gchar * const gabble_tube_dbus_channel_allowed_properties[] = {
TP_IFACE_CHANNEL ".TargetHandle",
TP_IFACE_CHANNEL ".TargetID",
@@ -120,7 +110,7 @@ enum
struct _GabbleTubeDBusPrivate
{
TpHandle self_handle;
- guint id;
+ guint64 id;
GabbleBytestreamIface *bytestream;
gchar *stream_id;
gchar *service;
@@ -165,6 +155,19 @@ struct _GabbleTubeDBusPrivate
#define GABBLE_TUBE_DBUS_GET_PRIVATE(obj) ((obj)->priv)
+static GPtrArray *
+gabble_tube_dbus_get_interfaces (TpBaseChannel *base)
+{
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CHANNEL_CLASS (
+ gabble_tube_dbus_parent_class)->get_interfaces (base);
+
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_TUBE);
+
+ return interfaces;
+}
+
static void data_received_cb (GabbleBytestreamIface *stream, TpHandle sender,
GString *data, gpointer user_data);
@@ -394,7 +397,7 @@ create_dbus_server (GabbleTubeDBus *self,
g_free (priv->socket_path);
priv->socket_path = NULL;
- g_set_error (err, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (err, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Can't create D-Bus server");
return FALSE;
}
@@ -411,6 +414,8 @@ static void
tube_dbus_open (GabbleTubeDBus *self)
{
GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
g_signal_connect (priv->bytestream, "data-received",
G_CALLBACK (data_received_cb), self);
@@ -424,6 +429,15 @@ tube_dbus_open (GabbleTubeDBus *self)
{
dbus_server_setup_with_g_main (priv->dbus_srv, NULL);
}
+
+ if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
+ {
+ /* add yourself in dbus names */
+ gabble_tube_dbus_add_name (self, priv->self_handle,
+ priv->dbus_local_name);
+
+ gabble_muc_channel_send_presence (priv->muc);
+ }
}
static void
@@ -435,17 +449,6 @@ gabble_tube_dbus_init (GabbleTubeDBus *self)
self->priv = priv;
}
-static void
-unref_handle_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- TpHandle handle = GPOINTER_TO_UINT (key);
- TpHandleRepoIface *contact_repo = (TpHandleRepoIface *) user_data;
-
- tp_handle_unref (contact_repo, handle);
-}
-
static TpTubeChannelState
get_tube_state (GabbleTubeDBus *self)
{
@@ -485,11 +488,16 @@ bytestream_state_changed_cb (GabbleBytestreamIface *bytestream,
{
GabbleTubeDBus *self = GABBLE_TUBE_DBUS (user_data);
GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
if (state == GABBLE_BYTESTREAM_STATE_CLOSED)
{
tp_clear_object (&priv->bytestream);
g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
+
+ if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
+ gabble_muc_channel_send_presence (priv->muc);
}
else if (state == GABBLE_BYTESTREAM_STATE_OPEN)
{
@@ -507,10 +515,6 @@ gabble_tube_dbus_dispose (GObject *object)
{
GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object);
GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
- TpBaseConnection *base_conn = tp_base_channel_get_connection (
- TP_BASE_CHANNEL (self));
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
DEBUG ("called");
@@ -556,13 +560,6 @@ gabble_tube_dbus_dispose (GObject *object)
tp_clear_pointer (&priv->dbus_srv_addr, g_free);
tp_clear_pointer (&priv->socket_path, g_free);
tp_clear_pointer (&priv->dbus_local_name, g_free);
-
- if (priv->dbus_names != NULL)
- {
- g_hash_table_foreach (priv->dbus_names, unref_handle_foreach,
- contact_repo);
- }
-
tp_clear_pointer (&priv->dbus_names, g_hash_table_unref);
tp_clear_pointer (&priv->dbus_name_to_handle, g_hash_table_unref);
@@ -605,7 +602,7 @@ gabble_tube_dbus_get_property (GObject *object,
g_value_set_uint (value, priv->self_handle);
break;
case PROP_ID:
- g_value_set_uint (value, priv->id);
+ g_value_set_uint64 (value, priv->id);
break;
case PROP_BYTESTREAM:
g_value_set_object (value, priv->bytestream);
@@ -661,7 +658,7 @@ gabble_tube_dbus_set_property (GObject *object,
priv->self_handle = g_value_get_uint (value);
break;
case PROP_ID:
- priv->id = g_value_get_uint (value);
+ priv->id = g_value_get_uint64 (value);
break;
case PROP_BYTESTREAM:
if (priv->bytestream == NULL)
@@ -839,7 +836,7 @@ gabble_tube_dbus_get_object_path_suffix (TpBaseChannel *base)
{
GabbleTubeDBus *self = GABBLE_TUBE_DBUS (base);
- return g_strdup_printf ("DBusTubeChannel/%u/%u",
+ return g_strdup_printf ("DBusTubeChannel/%u/%" G_GUINT64_FORMAT,
tp_base_channel_get_target_handle (base),
self->priv->id);
}
@@ -882,7 +879,7 @@ gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class)
object_class->finalize = gabble_tube_dbus_finalize;
base_class->channel_type = TP_IFACE_CHANNEL_TYPE_DBUS_TUBE;
- base_class->interfaces = gabble_tube_dbus_interfaces;
+ base_class->get_interfaces = gabble_tube_dbus_get_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
base_class->close = gabble_tube_dbus_close;
base_class->fill_immutable_properties =
@@ -1003,7 +1000,6 @@ gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class)
static void
bytestream_negotiate_cb (GabbleBytestreamIface *bytestream,
- const gchar *stream_id,
WockyStanza *msg,
GObject *object,
gpointer user_data)
@@ -1038,7 +1034,7 @@ gabble_tube_dbus_offer (GabbleTubeDBus *tube,
if (priv->offered)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Tube has already been offered");
return FALSE;
}
@@ -1052,7 +1048,6 @@ gabble_tube_dbus_offer (GabbleTubeDBus *tube,
GabblePresence *presence;
WockyNode *tube_node, *si_node;
WockyStanza *msg;
- gboolean result;
jid = tp_handle_inspect (contact_repo,
tp_base_channel_get_target_handle (base));
@@ -1062,7 +1057,7 @@ gabble_tube_dbus_offer (GabbleTubeDBus *tube,
if (presence == NULL)
{
DEBUG ("can't find contact %s's presence", jid);
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"can't find contact %s's presence", jid);
return FALSE;
}
@@ -1073,7 +1068,7 @@ gabble_tube_dbus_offer (GabbleTubeDBus *tube,
if (resource == NULL)
{
DEBUG ("contact %s doesn't have tubes capabilities", jid);
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"contact %s doesn't have tubes capabilities", jid);
return FALSE;
}
@@ -1085,28 +1080,22 @@ gabble_tube_dbus_offer (GabbleTubeDBus *tube,
wocky_stanza_get_top_node (msg), "si", NS_SI);
g_assert (si_node != NULL);
- tube_node = wocky_node_add_child_with_content (si_node, "tube", NULL);
- tube_node->ns = g_quark_from_string (NS_TUBES);
+ tube_node = wocky_node_add_child_ns (si_node, "tube", NS_TUBES);
gabble_tube_iface_publish_in_node (GABBLE_TUBE_IFACE (tube),
base_conn, tube_node);
tube->priv->offered = TRUE;
- result = gabble_bytestream_factory_negotiate_stream (
+ gabble_bytestream_factory_negotiate_stream (
conn->bytestream_factory, msg, priv->stream_id,
- bytestream_negotiate_cb, tube, G_OBJECT (tube), error);
+ bytestream_negotiate_cb, tube, G_OBJECT (tube));
/* We don't create the bytestream of private D-Bus tube yet.
* It will be when we'll receive the answer of the SI request */
-
g_object_unref (msg);
g_free (full_jid);
- if (!result)
- return FALSE;
-
tp_svc_channel_interface_tube_emit_tube_channel_state_changed (tube,
TP_TUBE_CHANNEL_STATE_REMOTE_PENDING);
-
}
else
{
@@ -1114,6 +1103,8 @@ gabble_tube_dbus_offer (GabbleTubeDBus *tube,
g_object_set (priv->bytestream,
"state", GABBLE_BYTESTREAM_STATE_OPEN,
NULL);
+
+ gabble_muc_channel_send_presence (priv->muc);
}
if (!create_dbus_server (tube, error))
@@ -1348,7 +1339,7 @@ gabble_tube_dbus_new (GabbleConnection *conn,
const gchar *service,
GHashTable *parameters,
const gchar *stream_id,
- guint id,
+ guint64 id,
GabbleBytestreamIface *bytestream,
GabbleMucChannel *muc,
gboolean requested)
@@ -1382,10 +1373,7 @@ static void
augment_si_accept_iq (WockyNode *si,
gpointer user_data)
{
- WockyNode *tube_node;
-
- tube_node = wocky_node_add_child_with_content (si, "tube", "");
- tube_node->ns = g_quark_from_string (NS_TUBES);
+ wocky_node_add_child_ns (si, "tube", NS_TUBES);
}
/*
@@ -1518,7 +1506,6 @@ gabble_tube_dbus_add_name (GabbleTubeDBus *self,
name_copy = g_strdup (name);
g_hash_table_insert (priv->dbus_names, GUINT_TO_POINTER (handle),
name_copy);
- tp_handle_ref (contact_repo, handle);
g_hash_table_insert (priv->dbus_name_to_handle, name_copy,
GUINT_TO_POINTER (handle));
@@ -1545,9 +1532,6 @@ gabble_tube_dbus_remove_name (GabbleTubeDBus *self,
GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
TpBaseChannel *base = TP_BASE_CHANNEL (self);
TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
- TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
const gchar *name;
GHashTable *added;
GArray *removed;
@@ -1575,7 +1559,6 @@ gabble_tube_dbus_remove_name (GabbleTubeDBus *self,
g_hash_table_unref (added);
g_array_unref (removed);
- tp_handle_unref (contact_repo, handle);
return TRUE;
}
@@ -1603,7 +1586,7 @@ _gabble_generate_dbus_unique_name (const gchar *nick)
if (len <= 186)
{
- encoded = base64_encode (len, nick, FALSE);
+ encoded = g_base64_encode ((const guchar *) nick, len);
}
else
{
@@ -1616,7 +1599,7 @@ _gabble_generate_dbus_unique_name (const gchar *nick)
g_string_append_len (tmp, nick, 169);
g_string_append_len (tmp, (const gchar *) sha1, 20);
- encoded = base64_encode (tmp->len, tmp->str, FALSE);
+ encoded = g_base64_encode ((const guchar *) tmp->str, tmp->len);
g_string_free (tmp, TRUE);
}
@@ -1661,7 +1644,7 @@ gabble_tube_dbus_check_access_control (GabbleTubeDBus *self,
break;
default:
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%u socket access control is not supported", access_control);
return FALSE;
}
diff --git a/src/tube-dbus.h b/src/tube-dbus.h
index 35073ce3f..b3020a9f4 100644
--- a/src/tube-dbus.h
+++ b/src/tube-dbus.h
@@ -22,10 +22,8 @@
#include <glib-object.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/group-mixin.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/base-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "connection.h"
#include "bytestream-iface.h"
@@ -73,7 +71,7 @@ GType gabble_tube_dbus_get_type (void);
GabbleTubeDBus *gabble_tube_dbus_new (GabbleConnection *conn, TpHandle handle,
TpHandleType handle_type, TpHandle self_handle, TpHandle initiator,
const gchar *service, GHashTable *parameters, const gchar *stream_id,
- guint id, GabbleBytestreamIface *bytestream, GabbleMucChannel *muc,
+ guint64 id, GabbleBytestreamIface *bytestream, GabbleMucChannel *muc,
gboolean requested);
gboolean gabble_tube_dbus_add_name (GabbleTubeDBus *tube, TpHandle handle,
diff --git a/src/tube-iface.c b/src/tube-iface.c
index 62585eb33..7faf514ea 100644
--- a/src/tube-iface.c
+++ b/src/tube-iface.c
@@ -20,7 +20,8 @@
#include "config.h"
#include "tube-iface.h"
-#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "connection.h"
#include "util.h"
@@ -72,7 +73,7 @@ gabble_tube_iface_base_init (gpointer klass)
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_interface_install_property (klass, param_spec);
- param_spec = g_param_spec_uint (
+ param_spec = g_param_spec_uint64 (
"id",
"id",
"The unique identifier of this tube",
@@ -151,7 +152,7 @@ gabble_tube_iface_publish_in_node (GabbleTubeIface *tube,
GHashTable *parameters;
TpTubeType type;
gchar *service, *id_str;
- guint tube_id;
+ guint64 tube_id;
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
conn, TP_HANDLE_TYPE_CONTACT);
TpHandle initiator_handle;
@@ -164,7 +165,7 @@ gabble_tube_iface_publish_in_node (GabbleTubeIface *tube,
"id", &tube_id,
NULL);
- id_str = g_strdup_printf ("%u", tube_id);
+ id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, tube_id);
wocky_node_set_attributes (node,
"service", service,
diff --git a/src/tube-iface.h b/src/tube-iface.h
index 311bf65bc..b727f391d 100644
--- a/src/tube-iface.h
+++ b/src/tube-iface.h
@@ -21,7 +21,7 @@
#define __GABBLE_TUBE_IFACE_H__
#include <glib-object.h>
-#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "bytestream-iface.h"
diff --git a/src/tube-stream.c b/src/tube-stream.c
index a505ef1a1..e1d2289de 100644
--- a/src/tube-stream.c
+++ b/src/tube-stream.c
@@ -31,12 +31,8 @@
#endif
#include <glib/gstdio.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/group-mixin.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-generic.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "extensions/extensions.h"
@@ -86,11 +82,6 @@ static const gchar * const gabble_tube_stream_channel_allowed_properties[] = {
NULL
};
-static const gchar *gabble_tube_stream_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_TUBE,
- NULL
-};
-
/* Linux glibc bits/socket.h suggests that struct sockaddr_storage is
* not guaranteed to be big enough for AF_UNIX addresses */
typedef union
@@ -136,7 +127,7 @@ enum
struct _GabbleTubeStreamPrivate
{
TpHandle self_handle;
- guint id;
+ guint64 id;
/* Bytestreams for tubes. One tube can have several bytestreams. The
* mapping between the tube bytestream and the transport to the local
@@ -179,6 +170,19 @@ struct _GabbleTubeStreamPrivate
gboolean dispose_has_run;
};
+static GPtrArray *
+gabble_tube_stream_get_interfaces (TpBaseChannel *base)
+{
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CHANNEL_CLASS (
+ gabble_tube_stream_parent_class)->get_interfaces (base);
+
+ g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_TUBE);
+
+ return interfaces;
+}
+
typedef struct
{
GabbleTubeStream *self;
@@ -402,7 +406,6 @@ extra_bytestream_state_changed_cb (GabbleBytestreamIface *bytestream,
static void
extra_bytestream_negotiate_cb (GabbleBytestreamIface *bytestream,
- const gchar *stream_id,
WockyStanza *msg,
GObject *object,
gpointer user_data)
@@ -453,7 +456,6 @@ start_stream_initiation (GabbleTubeStream *self,
TpHandleRepoIface *contact_repo;
const gchar *jid;
gchar *full_jid, *stream_id, *id_str;
- gboolean result;
contact_repo = tp_base_connection_get_handles (
base_conn, TP_HANDLE_TYPE_CONTACT);
@@ -471,7 +473,7 @@ start_stream_initiation (GabbleTubeStream *self,
if (presence == NULL)
{
DEBUG ("can't find initiator's presence");
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"can't find initiator's presence");
return FALSE;
}
@@ -481,7 +483,7 @@ start_stream_initiation (GabbleTubeStream *self,
if (resource == NULL)
{
DEBUG ("initiator doesn't have tubes capabilities");
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"initiator doesn't have tubes capabilities");
return FALSE;
}
@@ -503,37 +505,31 @@ start_stream_initiation (GabbleTubeStream *self,
wocky_stanza_get_top_node (msg), "si", NS_SI);
g_assert (si_node != NULL);
- id_str = g_strdup_printf ("%u", priv->id);
+ id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->id);
if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
- node = wocky_node_add_child_with_content (si_node, "stream", NULL);
+ node = wocky_node_add_child_ns (si_node, "stream", NS_TUBES);
}
else
{
- node = wocky_node_add_child_with_content (si_node, "muc-stream", NULL);
+ node = wocky_node_add_child_ns (si_node, "muc-stream", NS_TUBES);
}
- node->ns = g_quark_from_static_string (NS_TUBES);
wocky_node_set_attribute (node, "tube", id_str);
- result = gabble_bytestream_factory_negotiate_stream (
+ gabble_bytestream_factory_negotiate_stream (
conn->bytestream_factory, msg, stream_id,
- extra_bytestream_negotiate_cb, g_object_ref (transport), G_OBJECT (self),
- error);
+ extra_bytestream_negotiate_cb, g_object_ref (transport), G_OBJECT (self));
/* FIXME: data and one ref on data->transport are leaked if the tube is
* closed before we got the SI reply. */
-
- if (!result)
- g_object_unref (transport);
-
g_object_unref (msg);
g_free (stream_id);
g_free (full_jid);
g_free (id_str);
- return result;
+ return TRUE;
}
static guint
@@ -1235,7 +1231,7 @@ gabble_tube_stream_get_property (GObject *object,
g_value_set_uint (value, priv->self_handle);
break;
case PROP_ID:
- g_value_set_uint (value, priv->id);
+ g_value_set_uint64 (value, priv->id);
break;
case PROP_TYPE:
g_value_set_uint (value, TP_TUBE_TYPE_STREAM);
@@ -1289,7 +1285,7 @@ gabble_tube_stream_set_property (GObject *object,
priv->self_handle = g_value_get_uint (value);
break;
case PROP_ID:
- priv->id = g_value_get_uint (value);
+ priv->id = g_value_get_uint64 (value);
break;
case PROP_SERVICE:
g_free (priv->service);
@@ -1401,7 +1397,7 @@ gabble_tube_stream_get_object_path_suffix (TpBaseChannel *base)
{
GabbleTubeStream *self = GABBLE_TUBE_STREAM (base);
- return g_strdup_printf ("StreamTubeChannel/%u/%u",
+ return g_strdup_printf ("StreamTubeChannel/%u/%" G_GUINT64_FORMAT,
tp_base_channel_get_target_handle (base),
self->priv->id);
}
@@ -1449,7 +1445,7 @@ gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class)
object_class->finalize = gabble_tube_stream_finalize;
base_class->channel_type = TP_IFACE_CHANNEL_TYPE_STREAM_TUBE;
- base_class->interfaces = gabble_tube_stream_interfaces;
+ base_class->get_interfaces = gabble_tube_stream_get_interfaces;
base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
base_class->close = gabble_tube_stream_close;
base_class->fill_immutable_properties =
@@ -1620,7 +1616,7 @@ gabble_tube_stream_new (GabbleConnection *conn,
TpHandle initiator,
const gchar *service,
GHashTable *parameters,
- guint id,
+ guint64 id,
GabbleMucChannel *muc,
gboolean requested)
{
@@ -1665,7 +1661,7 @@ gabble_tube_stream_accept (GabbleTubeIface *tube,
if (priv->state != TP_TUBE_CHANNEL_STATE_LOCAL_PENDING)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Tube is not in the local pending state");
goto fail;
}
@@ -1725,7 +1721,7 @@ gabble_tube_iface_stream_close (GabbleTubeIface *tube,
jid = tp_handle_inspect (contact_repo,
tp_base_channel_get_target_handle (base));
- id_str = g_strdup_printf ("%u", priv->id);
+ id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->id);
/* Send the close message */
msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE,
@@ -1750,6 +1746,9 @@ gabble_tube_iface_stream_close (GabbleTubeIface *tube,
* disappear when we finally remove the Tubes channel type.. */
g_object_ref (self);
+ if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
+ gabble_muc_channel_send_presence (priv->muc);
+
g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
tp_base_channel_destroyed (base);
@@ -1761,10 +1760,7 @@ static void
augment_si_accept_iq (WockyNode *si,
gpointer user_data)
{
- WockyNode *tube_node;
-
- tube_node = wocky_node_add_child_with_content (si, "tube", "");
- tube_node->ns = g_quark_from_string (NS_TUBES);
+ wocky_node_add_child_ns (si, "tube", NS_TUBES);
}
/**
@@ -1861,7 +1857,7 @@ check_unix_params (TpSocketAddressType address_type,
{
if (G_VALUE_TYPE (address) != DBUS_TYPE_G_UCHAR_ARRAY)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Unix socket address is supposed to be ay");
return FALSE;
}
@@ -1870,7 +1866,7 @@ check_unix_params (TpSocketAddressType address_type,
if (array->len > sizeof (dummy.sun_path) - 1)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Unix socket path is too long (max length allowed: %"
G_GSIZE_FORMAT ")",
sizeof (dummy.sun_path) - 1);
@@ -1881,7 +1877,7 @@ check_unix_params (TpSocketAddressType address_type,
{
if (g_array_index (array, gchar , i) == '\0')
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Unix socket path can't contain zero bytes");
return FALSE;
}
@@ -1893,7 +1889,7 @@ check_unix_params (TpSocketAddressType address_type,
{
DEBUG ("Error calling stat on socket: %s", g_strerror (errno));
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "%s: %s",
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s: %s",
socket_address->str, g_strerror (errno));
g_string_free (socket_address, TRUE);
return FALSE;
@@ -1903,7 +1899,7 @@ check_unix_params (TpSocketAddressType address_type,
{
DEBUG ("%s is not a socket", socket_address->str);
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%s is not a socket", socket_address->str);
g_string_free (socket_address, TRUE);
return FALSE;
@@ -1919,7 +1915,7 @@ check_unix_params (TpSocketAddressType address_type,
return TRUE;
}
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%u socket access control is not supported", access_control);
return FALSE;
}
@@ -1944,7 +1940,7 @@ check_ip_params (TpSocketAddressType address_type,
{
if (G_VALUE_TYPE (address) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"IPv4 socket address is supposed to be sq");
return FALSE;
}
@@ -1953,7 +1949,7 @@ check_ip_params (TpSocketAddressType address_type,
{
if (G_VALUE_TYPE (address) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV6)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"IPv6 socket address is supposed to be sq");
return FALSE;
}
@@ -1981,7 +1977,7 @@ check_ip_params (TpSocketAddressType address_type,
ret = getaddrinfo (ip, NULL, &req, &result);
if (ret != 0)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Invalid address: %s", gai_strerror (ret));
g_free (ip);
return FALSE;
@@ -2002,7 +1998,7 @@ check_ip_params (TpSocketAddressType address_type,
if (G_VALUE_TYPE (access_control_param) !=
TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Port access param is supposed to be sq");
return FALSE;
}
@@ -2010,7 +2006,7 @@ check_ip_params (TpSocketAddressType address_type,
return TRUE;
}
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"%u socket access control is not supported", access_control);
return FALSE;
}
@@ -2040,7 +2036,7 @@ gabble_tube_stream_check_params (TpSocketAddressType address_type,
access_control_param, error);
default:
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
"Address type %d not implemented", address_type);
return FALSE;
}
@@ -2077,7 +2073,7 @@ send_tube_offer (GabbleTubeStream *self,
if (presence == NULL)
{
DEBUG ("can't find tube recipient's presence");
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"can't find tube recipient's presence");
return FALSE;
}
@@ -2087,7 +2083,7 @@ send_tube_offer (GabbleTubeStream *self,
if (resource == NULL)
{
DEBUG ("tube recipient doesn't have tubes capabilities");
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"tube recipient doesn't have tubes capabilities");
return FALSE;
}
@@ -2141,6 +2137,8 @@ gabble_tube_stream_offer (GabbleTubeStream *self,
/* muc tube is open as soon it's offered */
priv->state = TP_TUBE_CHANNEL_STATE_OPEN;
g_signal_emit (G_OBJECT (self), signals[OPENED], 0);
+
+ gabble_muc_channel_send_presence (priv->muc);
}
g_signal_emit (G_OBJECT (self), signals[OFFERED], 0);
@@ -2239,7 +2237,7 @@ gabble_tube_stream_offer_async (TpSvcChannelTypeStreamTube *iface,
if (priv->state != TP_TUBE_CHANNEL_STATE_NOT_OFFERED)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Tube is not in the not offered state");
dbus_g_method_return_error (context, error);
g_error_free (error);
diff --git a/src/tube-stream.h b/src/tube-stream.h
index 991116238..5b26fcced 100644
--- a/src/tube-stream.h
+++ b/src/tube-stream.h
@@ -22,9 +22,8 @@
#include <glib-object.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/base-channel.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "connection.h"
#include "extensions/extensions.h"
@@ -69,7 +68,7 @@ GType gabble_tube_stream_get_type (void);
GabbleTubeStream *gabble_tube_stream_new (GabbleConnection *conn,
TpHandle handle, TpHandleType handle_type, TpHandle self_handle,
TpHandle initiator, const gchar *service, GHashTable *parameters,
- guint id, GabbleMucChannel *muc, gboolean requested);
+ guint64 id, GabbleMucChannel *muc, gboolean requested);
gboolean gabble_tube_stream_check_params (TpSocketAddressType address_type,
const GValue *address, TpSocketAccessControl access_control,
diff --git a/src/tubes-channel.c b/src/tubes-channel.c
deleted file mode 100644
index 7d7cab984..000000000
--- a/src/tubes-channel.c
+++ /dev/null
@@ -1,2398 +0,0 @@
-/*
- * tubes-channel.c - Source for GabbleTubesChannel
- * Copyright (C) 2007 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 "config.h"
-#include "tubes-channel.h"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include <glib/gstdio.h>
-#include <dbus/dbus-glib.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/group-mixin.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-generic.h>
-
-#define DEBUG_FLAG GABBLE_DEBUG_TUBES
-
-#include "bytestream-factory.h"
-#include "connection.h"
-#include "debug.h"
-#include "namespaces.h"
-#include "presence-cache.h"
-#include "presence.h"
-#include "private-tubes-factory.h"
-#include "tube-iface.h"
-#include "tube-dbus.h"
-#include "tube-stream.h"
-#include "tube-dbus.h"
-#include "util.h"
-
-static void channel_iface_init (gpointer, gpointer);
-static void tubes_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (GabbleTubesChannel, gabble_tubes_channel,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TUBES, tubes_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
- tp_external_group_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL));
-
-static const gchar *gabble_tubes_channel_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- /* If more interfaces are added, either keep Group as the first, or change
- * the implementations of gabble_tubes_channel_get_interfaces () and
- * gabble_tubes_channel_get_property () too */
- NULL
-};
-
-
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_HANDLE_TYPE,
- PROP_HANDLE,
- PROP_TARGET_ID,
- PROP_REQUESTED,
- PROP_CONNECTION,
- PROP_INTERFACES,
- PROP_MUC,
- PROP_INITIATOR_HANDLE,
- PROP_INITIATOR_ID,
- PROP_CHANNEL_DESTROYED,
- PROP_CHANNEL_PROPERTIES,
- LAST_PROPERTY,
-};
-
-/* private structure */
-
-struct _GabbleTubesChannelPrivate
-{
- GabbleConnection *conn;
- char *object_path;
- TpHandle handle;
- TpHandleType handle_type;
- TpHandle self_handle;
- TpHandle initiator;
- gboolean requested;
-
- GHashTable *tubes;
-
- gulong pre_presence_signal;
- gboolean closed;
- gboolean dispose_has_run;
-};
-
-static void update_tubes_presence (GabbleTubesChannel *self);
-
-static void pre_presence_cb (GabbleMucChannel *muc, WockyStanza *msg,
- GabbleTubesChannel *self);
-
-static void
-gabble_tubes_channel_init (GabbleTubesChannel *self)
-{
- GabbleTubesChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_TUBES_CHANNEL, GabbleTubesChannelPrivate);
-
- self->priv = priv;
-
- priv->tubes = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) g_object_unref);
-}
-
-static GObject *
-gabble_tubes_channel_constructor (GType type,
- guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleTubesChannel *self;
- GabbleTubesChannelPrivate *priv;
- TpDBusDaemon *bus;
- TpHandleRepoIface *handle_repo, *contact_repo;
-
- DEBUG ("Called");
-
- obj = G_OBJECT_CLASS (gabble_tubes_channel_parent_class)->
- constructor (type, n_props, props);
-
- self = GABBLE_TUBES_CHANNEL (obj);
- priv = self->priv;
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- handle_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, priv->handle_type);
-
- tp_handle_ref (handle_repo, priv->handle);
-
- if (priv->initiator != 0)
- tp_handle_ref (contact_repo, priv->initiator);
-
- switch (priv->handle_type)
- {
- case TP_HANDLE_TYPE_CONTACT:
- g_assert (self->muc == NULL);
- g_assert (priv->initiator != 0);
- priv->self_handle = ((TpBaseConnection *) (priv->conn))->self_handle;
- break;
- case TP_HANDLE_TYPE_ROOM:
- g_assert (self->muc != NULL);
-
- priv->pre_presence_signal = g_signal_connect (self->muc, "pre-presence",
- G_CALLBACK (pre_presence_cb), self);
-
- priv->self_handle = self->muc->group.self_handle;
- tp_external_group_mixin_init (obj, (GObject *) self->muc);
- break;
- default:
- g_return_val_if_reached (NULL);
- }
-
- bus = tp_base_connection_get_dbus_daemon ((TpBaseConnection *) priv->conn);
- tp_dbus_daemon_register_object (bus, priv->object_path, obj);
-
- DEBUG ("Registering at '%s'", priv->object_path);
-
- return obj;
-}
-
-static void
-gabble_tubes_channel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleTubesChannel *chan = GABBLE_TUBES_CHANNEL (object);
- GabbleTubesChannelPrivate *priv = chan->priv;
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
-
- 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_TUBES);
- 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_TARGET_ID:
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- base_conn, priv->handle_type);
-
- g_value_set_string (value,
- tp_handle_inspect (repo, priv->handle));
- }
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_INTERFACES:
- if (chan->muc)
- {
- /* MUC tubes */
- g_value_set_boxed (value, gabble_tubes_channel_interfaces);
- }
- else
- {
- /* 1-1 tubes - omit the Group interface */
- g_value_set_boxed (value, gabble_tubes_channel_interfaces + 1);
- }
- break;
- case PROP_MUC:
- g_value_set_object (value, chan->muc);
- break;
- case PROP_INITIATOR_HANDLE:
- g_value_set_uint (value, priv->initiator);
- break;
- case PROP_INITIATOR_ID:
- if (priv->initiator == 0)
- {
- g_value_set_static_string (value, "");
- }
- else
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
-
- g_value_set_string (value,
- tp_handle_inspect (repo, priv->initiator));
- }
- break;
- case PROP_REQUESTED:
- g_value_set_boolean (value, priv->requested);
- break;
- case PROP_CHANNEL_DESTROYED:
- g_value_set_boolean (value, priv->closed);
- break;
- case PROP_CHANNEL_PROPERTIES:
- g_value_take_boxed (value,
- tp_dbus_properties_mixin_make_properties_hash (object,
- TP_IFACE_CHANNEL, "TargetHandle",
- TP_IFACE_CHANNEL, "TargetHandleType",
- TP_IFACE_CHANNEL, "ChannelType",
- TP_IFACE_CHANNEL, "TargetID",
- TP_IFACE_CHANNEL, "InitiatorHandle",
- TP_IFACE_CHANNEL, "InitiatorID",
- TP_IFACE_CHANNEL, "Requested",
- TP_IFACE_CHANNEL, "Interfaces",
- NULL));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_tubes_channel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleTubesChannel *chan = GABBLE_TUBES_CHANNEL (object);
- GabbleTubesChannelPrivate *priv = chan->priv;
-
- switch (property_id)
- {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- DEBUG ("Setting object_path: %s", priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- /* this property is writable in the interface, but not actually
- * meaningfully changeable on this channel, so we do nothing */
- break;
- case PROP_HANDLE:
- priv->handle = g_value_get_uint (value);
- break;
- case PROP_HANDLE_TYPE:
- priv->handle_type = g_value_get_uint (value);
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_MUC:
- chan->muc = g_value_get_object (value);
- break;
- case PROP_INITIATOR_HANDLE:
- priv->initiator = g_value_get_uint (value);
- break;
- case PROP_REQUESTED:
- priv->requested = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-d_bus_names_changed_added (GabbleTubesChannel *self,
- guint tube_id,
- TpHandle contact,
- const gchar *new_name)
-{
- GPtrArray *added = g_ptr_array_sized_new (1);
- GArray *removed = g_array_new (FALSE, FALSE, sizeof (guint));
- GValue tmp = {0,};
- guint i;
-
- g_value_init (&tmp, TP_STRUCT_TYPE_DBUS_TUBE_MEMBER);
- g_value_take_boxed (&tmp,
- dbus_g_type_specialized_construct (TP_STRUCT_TYPE_DBUS_TUBE_MEMBER));
- dbus_g_type_struct_set (&tmp,
- 0, contact,
- 1, new_name,
- G_MAXUINT);
- g_ptr_array_add (added, g_value_get_boxed (&tmp));
-
- tp_svc_channel_type_tubes_emit_d_bus_names_changed (self,
- tube_id, added, removed);
-
- for (i = 0; i < added->len; i++)
- g_boxed_free (TP_STRUCT_TYPE_DBUS_TUBE_MEMBER, added->pdata[i]);
- g_ptr_array_unref (added);
- g_array_unref (removed);
-}
-
-static void
-d_bus_names_changed_removed (GabbleTubesChannel *self,
- guint tube_id,
- TpHandle contact)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- GPtrArray *added;
- GArray *removed;
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- return;
-
- added = g_ptr_array_new ();
- removed = g_array_new (FALSE, FALSE, sizeof (guint));
-
- g_array_append_val (removed, contact);
-
- tp_svc_channel_type_tubes_emit_d_bus_names_changed (self,
- tube_id, added, removed);
-
- g_ptr_array_unref (added);
- g_array_unref (removed);
-}
-
-static void
-add_name_in_dbus_names (GabbleTubesChannel *self,
- guint tube_id,
- TpHandle handle,
- const gchar *dbus_name)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- GabbleTubeDBus *tube;
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- return;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube == NULL)
- return;
-
- if (gabble_tube_dbus_add_name (tube, handle, dbus_name))
- {
- /* Emit the DBusNamesChanged signal */
- d_bus_names_changed_added (self, tube_id, handle, dbus_name);
- }
-}
-
-static void
-add_yourself_in_dbus_names (GabbleTubesChannel *self,
- guint tube_id)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- GabbleTubeDBus *tube;
- gchar *dbus_name;
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- return;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube == NULL)
- return;
-
- g_object_get (tube,
- "dbus-name", &dbus_name,
- NULL);
-
- add_name_in_dbus_names (self, tube_id, priv->self_handle, dbus_name);
-
- g_free (dbus_name);
-}
-
-static void
-tube_closed_cb (GabbleTubeIface *tube,
- gpointer user_data)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (user_data);
- GabbleTubesChannelPrivate *priv = self->priv;
- guint tube_id;
-
- if (priv->closed)
- return;
-
- g_object_get (tube, "id", &tube_id, NULL);
- if (!g_hash_table_remove (priv->tubes, GUINT_TO_POINTER (tube_id)))
- {
- DEBUG ("Can't find tube having this id: %d", tube_id);
- }
- DEBUG ("tube %d removed", tube_id);
-
- /* Emit the DBusNamesChanged signal if muc tube */
- d_bus_names_changed_removed (self, tube_id, priv->self_handle);
-
- update_tubes_presence (self);
-
- tp_svc_channel_type_tubes_emit_tube_closed (self, tube_id);
-
- /* Ideally, this should be done in the factory directly but the private
- * tubes factory and the muc factory are not aware of tube channels.
- * This design is a legacy of the old tube API and we can't really change it
- * without big refactoring. */
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- {
- tp_channel_manager_emit_channel_closed_for_object (
- priv->conn->private_tubes_factory, TP_EXPORTABLE_CHANNEL (tube));
- }
- else
- {
- tp_channel_manager_emit_channel_closed_for_object (
- priv->conn->muc_factory, TP_EXPORTABLE_CHANNEL (tube));
- }
-
-}
-
-static void
-tube_opened_cb (GabbleTubeIface *tube,
- gpointer user_data)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (user_data);
- guint tube_id;
- TpTubeType type;
-
- g_object_get (tube,
- "id", &tube_id,
- "type", &type,
- NULL);
-
- if (type == TP_TUBE_TYPE_DBUS)
- {
- add_yourself_in_dbus_names (self, tube_id);
- }
-
- update_tubes_presence (self);
-
- tp_svc_channel_type_tubes_emit_tube_state_changed (self, tube_id,
- TP_TUBE_CHANNEL_STATE_OPEN);
-}
-
-static void
-tube_offered_cb (GabbleTubeIface *tube,
- gpointer user_data)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (user_data);
- guint tube_id;
- TpHandle initiator;
- TpTubeType type;
- gchar *service;
- GHashTable *parameters;
- TpTubeChannelState state;
-
- g_object_get (tube,
- "id", &tube_id,
- "initiator-handle", &initiator,
- "type", &type,
- "service", &service,
- "parameters", &parameters,
- "state", &state,
- NULL);
-
- /* tube has been offered and so can be announced using the old API;
- * TpTubeState and TpTubeChannelState are numerically equal for
- * values other than NOT_OFFERED */
- g_assert (state < NUM_TP_TUBE_STATES);
- tp_svc_channel_type_tubes_emit_new_tube (self,
- tube_id,
- initiator,
- type,
- service,
- parameters,
- state);
-
- update_tubes_presence (self);
-
- g_free (service);
- g_hash_table_unref (parameters);
-}
-
-static GabbleTubeIface *
-create_new_tube (GabbleTubesChannel *self,
- TpTubeType type,
- TpHandle initiator,
- const gchar *service,
- GHashTable *parameters,
- const gchar *stream_id,
- guint tube_id,
- GabbleBytestreamIface *bytestream,
- gboolean requested)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- GabbleTubeIface *tube;
- TpTubeChannelState state;
-
- switch (type)
- {
- case TP_TUBE_TYPE_DBUS:
- tube = GABBLE_TUBE_IFACE (gabble_tube_dbus_new (priv->conn,
- priv->handle, priv->handle_type, priv->self_handle, initiator,
- service, parameters, stream_id, tube_id, bytestream, self->muc,
- requested));
- break;
- case TP_TUBE_TYPE_STREAM:
- tube = GABBLE_TUBE_IFACE (gabble_tube_stream_new (priv->conn,
- priv->handle, priv->handle_type, priv->self_handle, initiator,
- service, parameters, tube_id, self->muc, requested));
- break;
- default:
- g_return_val_if_reached (NULL);
- }
-
- tp_base_channel_register ((TpBaseChannel *) tube);
-
- DEBUG ("create tube %u", tube_id);
- g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube);
-
- g_object_get (tube, "state", &state, NULL);
-
- /* The old API doesn't know the "not offered" state, so we have to wait that
- * the tube is offered before announcing it.
- * TpTubeState and TpTubeChannelState are numerically equal for
- * values other than NOT_OFFERED */
- if (state != TP_TUBE_CHANNEL_STATE_NOT_OFFERED)
- {
- tp_svc_channel_type_tubes_emit_new_tube (self,
- tube_id,
- initiator,
- type,
- service,
- parameters,
- state);
- }
-
- g_signal_connect (tube, "tube-opened", G_CALLBACK (tube_opened_cb), self);
- g_signal_connect (tube, "tube-closed", G_CALLBACK (tube_closed_cb), self);
- g_signal_connect (tube, "tube-offered", G_CALLBACK (tube_offered_cb), self);
-
- return tube;
-}
-
-static gboolean
-extract_tube_information (GabbleTubesChannel *self,
- WockyNode *tube_node,
- TpTubeType *type,
- TpHandle *initiator_handle,
- const gchar **service,
- GHashTable **parameters,
- guint *tube_id)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- if (type != NULL)
- {
- const gchar *_type;
-
- _type = wocky_node_get_attribute (tube_node, "type");
-
- if (!tp_strdiff (_type, "stream"))
- {
- *type = TP_TUBE_TYPE_STREAM;
- }
- else if (!tp_strdiff (_type, "dbus"))
- {
- *type = TP_TUBE_TYPE_DBUS;
- }
- else
- {
- DEBUG ("Unknown tube type: %s", _type);
- return FALSE;
- }
- }
-
- if (initiator_handle != NULL)
- {
- const gchar *initiator;
-
- initiator = wocky_node_get_attribute (tube_node, "initiator");
-
- if (initiator != NULL)
- {
- *initiator_handle = tp_handle_ensure (contact_repo, initiator,
- GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL);
-
- if (*initiator_handle == 0)
- {
- DEBUG ("invalid initiator JID %s", initiator);
- return FALSE;
- }
- }
- else
- {
- *initiator_handle = 0;
- }
- }
-
- if (service != NULL)
- {
- *service = wocky_node_get_attribute (tube_node, "service");
- }
-
- if (parameters != NULL)
- {
- WockyNode *node;
-
- node = wocky_node_get_child (tube_node, "parameters");
- *parameters = lm_message_node_extract_properties (node, "parameter");
- }
-
- if (tube_id != NULL)
- {
- const gchar *str;
- gchar *endptr;
- unsigned long tmp;
-
- str = wocky_node_get_attribute (tube_node, "id");
- if (str == NULL)
- {
- DEBUG ("no tube id in SI request");
- return FALSE;
- }
-
- tmp = strtoul (str, &endptr, 10);
- if (!endptr || *endptr || tmp > G_MAXUINT32)
- {
- DEBUG ("tube id is not numeric or > 2**32: %s", str);
- return FALSE;
- }
- *tube_id = (guint) tmp;
- }
-
- return TRUE;
-}
-
-struct _add_in_old_dbus_tubes_data
-{
- GHashTable *old_dbus_tubes;
- TpHandle contact;
-};
-
-static void
-add_in_old_dbus_tubes (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint tube_id = GPOINTER_TO_UINT (key);
- GabbleTubeIface *tube = GABBLE_TUBE_IFACE (value);
- struct _add_in_old_dbus_tubes_data *data =
- (struct _add_in_old_dbus_tubes_data *) user_data;
- TpTubeType type;
-
- g_object_get (tube, "type", &type, NULL);
-
- if (type != TP_TUBE_TYPE_DBUS)
- return;
-
- if (gabble_tube_dbus_handle_in_names (GABBLE_TUBE_DBUS (tube),
- data->contact))
- {
- /* contact was in this tube */
- g_hash_table_insert (data->old_dbus_tubes, GUINT_TO_POINTER (tube_id),
- tube);
- }
-}
-
-struct
-_emit_d_bus_names_changed_foreach_data
-{
- GabbleTubesChannel *self;
- TpHandle contact;
-};
-
-struct _ForeachData
-{
- TpExportableChannelFunc foreach;
- gpointer user_data;
-};
-
-static void
-foreach_slave (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- GabbleTubeIface *tube = GABBLE_TUBE_IFACE (value);
- struct _ForeachData *data = (struct _ForeachData *) user_data;
- TpTubeType type;
-
- g_object_get (tube, "type", &type, NULL);
- data->foreach (TP_EXPORTABLE_CHANNEL (tube), data->user_data);
-}
-
-void gabble_tubes_channel_foreach (GabbleTubesChannel *self,
- TpExportableChannelFunc foreach, gpointer user_data)
-{
- struct _ForeachData data;
- GabbleTubesChannelPrivate *priv = self->priv;
-
- data.user_data = user_data;
- data.foreach = foreach;
-
- g_hash_table_foreach (priv->tubes, foreach_slave, &data);
-}
-
-static void
-emit_d_bus_names_changed_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint tube_id = GPOINTER_TO_UINT (key);
- GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (value);
- struct _emit_d_bus_names_changed_foreach_data *data =
- (struct _emit_d_bus_names_changed_foreach_data *) user_data;
-
- /* Remove from the D-Bus names mapping */
- if (gabble_tube_dbus_remove_name (tube, data->contact))
- {
- /* Emit the DBusNamesChanged signal */
- d_bus_names_changed_removed (data->self, tube_id, data->contact);
- }
-}
-
-static void
-contact_left_muc (GabbleTubesChannel *self,
- TpHandle contact)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- GHashTable *old_dbus_tubes;
- struct _add_in_old_dbus_tubes_data add_data;
- struct _emit_d_bus_names_changed_foreach_data emit_data;
-
- DEBUG ("%s left muc and so left all its tube", tp_handle_inspect (
- contact_repo, contact));
-
- /* Fill old_dbus_tubes with D-BUS tubes previoulsy announced by
- * the contact */
- old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
- add_data.old_dbus_tubes = old_dbus_tubes;
- add_data.contact = contact;
- g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
-
- /* contact left the muc so he left all its tubes */
- emit_data.contact = contact;
- emit_data.self = self;
- g_hash_table_foreach (old_dbus_tubes, emit_d_bus_names_changed_foreach,
- &emit_data);
-
- g_hash_table_unref (old_dbus_tubes);
-}
-
-/* Called when we receive a presence from a contact who is
- * in the muc associated with this tubes channel */
-void
-gabble_tubes_channel_presence_updated (GabbleTubesChannel *self,
- TpHandle contact,
- WockyNode *pnode)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- WockyNode *tubes_node;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- WockyNodeIter i;
- WockyNode *tube_node;
- const gchar *presence_type;
- GHashTable *old_dbus_tubes;
- struct _add_in_old_dbus_tubes_data add_data;
- struct _emit_d_bus_names_changed_foreach_data emit_data;
-
- if (contact == priv->self_handle)
- /* We don't need to inspect our own presence */
- return;
-
- /* We are interested by this presence only if it contains tube information
- * or indicates someone left the muc */
- presence_type = wocky_node_get_attribute (pnode, "type");
- if (!tp_strdiff (presence_type, "unavailable"))
- {
- contact_left_muc (self, contact);
- return;
- }
-
- tubes_node = wocky_node_get_child_ns (pnode, "tubes", NS_TUBES);
-
- if (tubes_node == NULL)
- return;
-
- /* Fill old_dbus_tubes with D-BUS tubes previoulsy announced by
- * the contact */
- old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
- add_data.old_dbus_tubes = old_dbus_tubes;
- add_data.contact = contact;
- g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
-
- wocky_node_iter_init (&i, tubes_node, NULL, NULL);
- while (wocky_node_iter_next (&i, &tube_node))
- {
- const gchar *stream_id;
- GabbleTubeIface *tube;
- guint tube_id;
- TpTubeType type;
-
- stream_id = wocky_node_get_attribute (tube_node, "stream-id");
-
- if (!extract_tube_information (self, tube_node, NULL,
- NULL, NULL, NULL, &tube_id))
- {
- DEBUG ("Bad tube ID, skipping to next child of <tubes>");
- continue;
- }
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
-
- if (tube == NULL)
- {
- /* We don't know yet this tube */
- const gchar *service;
- TpHandle initiator_handle;
- GHashTable *parameters;
-
- if (extract_tube_information (self, tube_node, &type,
- &initiator_handle, &service, &parameters, NULL))
- {
- switch (type)
- {
- case TP_TUBE_TYPE_DBUS:
- {
- if (initiator_handle == 0)
- {
- DEBUG ("D-Bus tube initiator missing");
- /* skip to the next child of <tubes> */
- continue;
- }
- }
- break;
- case TP_TUBE_TYPE_STREAM:
- {
- if (initiator_handle != 0)
- /* ignore it */
- tp_handle_unref (contact_repo, initiator_handle);
-
- initiator_handle = contact;
- tp_handle_ref (contact_repo, initiator_handle);
- }
- break;
- default:
- {
- g_return_if_reached ();
- }
- }
-
- tube = create_new_tube (self, type, initiator_handle,
- service, parameters, stream_id, tube_id, NULL, FALSE);
-
- tp_channel_manager_emit_new_channel (priv->conn->muc_factory,
- TP_EXPORTABLE_CHANNEL (tube), NULL);
-
- /* the tube has reffed its initiator, no need to keep a ref */
- tp_handle_unref (contact_repo, initiator_handle);
- g_hash_table_unref (parameters);
- }
- }
- else
- {
- /* The contact is in the tube.
- * Remove it from old_dbus_tubes if needed */
- g_hash_table_remove (old_dbus_tubes, GUINT_TO_POINTER (tube_id));
- }
-
- if (tube == NULL)
- /* skip to the next child of <tubes> */
- continue;
-
- g_object_get (tube, "type", &type, NULL);
-
- if (type == TP_TUBE_TYPE_DBUS)
- {
- /* Update mapping of handle -> D-Bus name. */
- if (!gabble_tube_dbus_handle_in_names (GABBLE_TUBE_DBUS (tube),
- contact))
- {
- /* Contact just joined the tube */
- const gchar *new_name;
-
- new_name = wocky_node_get_attribute (tube_node,
- "dbus-name");
-
- if (!new_name)
- {
- DEBUG ("Contact %u isn't announcing their D-Bus name",
- contact);
- /* skip to the next child of <tubes> */
- continue;
- }
-
- add_name_in_dbus_names (self, tube_id, contact, new_name);
- }
- }
- }
-
- /* Tubes remaining in old_dbus_tubes was left by the contact */
- emit_data.contact = contact;
- emit_data.self = self;
- g_hash_table_foreach (old_dbus_tubes, emit_d_bus_names_changed_foreach,
- &emit_data);
-
- g_hash_table_unref (old_dbus_tubes);
-}
-
-static void
-copy_tube_in_ptr_array (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- GabbleTubeIface *tube = (GabbleTubeIface *) value;
- guint tube_id = GPOINTER_TO_UINT (key);
- TpHandle initiator;
- gchar *service;
- GHashTable *parameters;
- TpTubeChannelState state;
- TpTubeType type;
- GPtrArray *array = (GPtrArray *) user_data;
- GValue entry = {0,};
-
- g_object_get (tube,
- "state", &state,
- NULL);
-
- /* The old interface has no way to represent unoffered tubes, so they
- * shouldn't appear in the result of ListTubes()
- */
- if (state == TP_TUBE_CHANNEL_STATE_NOT_OFFERED)
- return;
-
- g_object_get (tube,
- "type", &type,
- "initiator-handle", &initiator,
- "service", &service,
- "parameters", &parameters,
- NULL);
-
- g_value_init (&entry, TP_STRUCT_TYPE_TUBE_INFO);
- g_value_take_boxed (&entry,
- dbus_g_type_specialized_construct (TP_STRUCT_TYPE_TUBE_INFO));
- dbus_g_type_struct_set (&entry,
- 0, tube_id,
- 1, initiator,
- 2, type,
- 3, service,
- 4, parameters,
- 5, state,
- G_MAXUINT);
-
- g_ptr_array_add (array, g_value_get_boxed (&entry));
- g_free (service);
- g_hash_table_unref (parameters);
-}
-
-static GPtrArray *
-make_tubes_ptr_array (GabbleTubesChannel *self,
- GHashTable *tubes)
-{
- GPtrArray *ret;
-
- ret = g_ptr_array_sized_new (g_hash_table_size (tubes));
-
- g_hash_table_foreach (tubes, copy_tube_in_ptr_array, ret);
-
- return ret;
-}
-
-/**
- * gabble_tubes_channel_get_available_tube_types
- *
- * Implements D-Bus method GetAvailableTubeTypes
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_get_available_tube_types (TpSvcChannelTypeTubes *iface,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GArray *ret;
- TpTubeType type;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- ret = g_array_sized_new (FALSE, FALSE, sizeof (TpTubeType), 1);
- type = TP_TUBE_TYPE_DBUS;
- g_array_append_val (ret, type);
- type = TP_TUBE_TYPE_STREAM;
- g_array_append_val (ret, type);
-
- tp_svc_channel_type_tubes_return_from_get_available_tube_types (context,
- ret);
-
- g_array_unref (ret);
-}
-
-/**
- * gabble_tubes_channel_list_tubes
- *
- * Implements D-Bus method ListTubes
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_list_tubes (TpSvcChannelTypeTubes *iface,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv;
- GPtrArray *ret;
- guint i;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- priv = self->priv;
-
- ret = make_tubes_ptr_array (self, priv->tubes);
- tp_svc_channel_type_tubes_return_from_list_tubes (context, ret);
-
- for (i = 0; i < ret->len; i++)
- g_boxed_free (TP_STRUCT_TYPE_TUBE_INFO, ret->pdata[i]);
-
- g_ptr_array_unref (ret);
-}
-
-struct _i_hate_g_hash_table_foreach
-{
- GabbleTubesChannel *self;
- WockyNode *tubes_node;
-};
-
-static void
-publish_tubes_in_node (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- GabbleTubeIface *tube = (GabbleTubeIface *) value;
- struct _i_hate_g_hash_table_foreach *data =
- (struct _i_hate_g_hash_table_foreach *) user_data;
- GabbleTubesChannelPrivate *priv = data->self->priv;
- TpTubeChannelState state;
- WockyNode *tube_node;
- TpTubeType type;
- TpHandle initiator;
-
- if (tube == NULL)
- return;
-
- g_object_get (tube,
- "state", &state,
- "type", &type,
- "initiator-handle", &initiator,
- NULL);
-
- if (state != TP_TUBE_CHANNEL_STATE_OPEN)
- return;
-
- if (type == TP_TUBE_TYPE_STREAM && initiator != priv->self_handle)
- /* We only announce stream tubes we initiated */
- return;
-
- tube_node = wocky_node_add_child_with_content (data->tubes_node, "tube", NULL);
- gabble_tube_iface_publish_in_node (tube, (TpBaseConnection *) priv->conn,
- tube_node);
-}
-
-static void
-pre_presence_cb (GabbleMucChannel *muc,
- WockyStanza *msg,
- GabbleTubesChannel *self)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- struct _i_hate_g_hash_table_foreach data;
- WockyNode *node;
-
- /* Augment the muc presence with tubes information */
- node = wocky_node_add_child_with_content (
- wocky_stanza_get_top_node (msg), "tubes", NULL);
- node->ns = g_quark_from_string (NS_TUBES);
- data.self = self;
- data.tubes_node = node;
-
- g_hash_table_foreach (priv->tubes, publish_tubes_in_node, &data);
-}
-
-static void
-update_tubes_presence (GabbleTubesChannel *self)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
-
- if (priv->handle_type != TP_HANDLE_TYPE_ROOM)
- return;
-
- gabble_muc_channel_send_presence (self->muc);
-}
-
-/* Called when we receive a SI request,
- * via gabble_tubes_factory_handle_si_tube_request
- */
-void
-gabble_tubes_channel_tube_si_offered (GabbleTubesChannel *self,
- GabbleBytestreamIface *bytestream,
- WockyStanza *msg)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- const gchar *service, *stream_id;
- GHashTable *parameters;
- TpTubeType type;
- WockyNode *si_node, *tube_node;
- guint tube_id;
- GabbleTubeIface *tube;
- WockyStanzaType stanza_type;
- WockyStanzaSubType sub_type;
-
- /* Caller is expected to have checked that we have a SI node with
- * a stream ID, the TUBES profile and a <tube> element
- */
- wocky_stanza_get_type_info (msg, &stanza_type, &sub_type);
- g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_IQ);
- g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET);
- si_node = wocky_node_get_child_ns (
- wocky_stanza_get_top_node (msg), "si", NS_SI);
- g_return_if_fail (si_node != NULL);
- stream_id = wocky_node_get_attribute (si_node, "id");
- g_return_if_fail (stream_id != NULL);
- tube_node = wocky_node_get_child_ns (si_node, "tube",
- NS_TUBES);
- g_return_if_fail (tube_node != NULL);
-
- if (!extract_tube_information (self, tube_node, NULL, NULL,
- NULL, NULL, &tube_id))
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "<tube> has no id attribute" };
-
- NODE_DEBUG (tube_node, e.message);
- gabble_bytestream_iface_close (bytestream, &e);
- return;
- }
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube != NULL)
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "tube ID already in use" };
-
- NODE_DEBUG (tube_node, e.message);
- gabble_bytestream_iface_close (bytestream, &e);
- return;
- }
-
- /* New tube */
- if (!extract_tube_information (self, tube_node, &type, NULL,
- &service, &parameters, NULL))
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "can't extract <tube> information from SI request" };
-
- NODE_DEBUG (tube_node, e.message);
- gabble_bytestream_iface_close (bytestream, &e);
- g_hash_table_unref (parameters);
- return;
- }
-
- if (type != TP_TUBE_TYPE_DBUS)
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FORBIDDEN,
- "Only D-Bus tubes are allowed to be created using SI" };
-
- DEBUG ("%s", e.message);
- gabble_bytestream_iface_close (bytestream, &e);
- return;
- }
-
- tube = create_new_tube (self, type, priv->handle, service,
- parameters, stream_id, tube_id, (GabbleBytestreamIface *) bytestream,
- FALSE);
-
- tp_channel_manager_emit_new_channel (priv->conn->private_tubes_factory,
- TP_EXPORTABLE_CHANNEL (tube), NULL);
-
- g_hash_table_unref (parameters);
-}
-
-/* Called when we receive a SI request,
- * via either gabble_muc_factory_handle_si_stream_request or
- * gabble_tubes_factory_handle_si_stream_request
- */
-void
-gabble_tubes_channel_bytestream_offered (GabbleTubesChannel *self,
- GabbleBytestreamIface *bytestream,
- WockyStanza *msg)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- const gchar *stream_id, *tmp;
- gchar *endptr;
- WockyNode *si_node, *stream_node;
- guint tube_id;
- unsigned long tube_id_tmp;
- GabbleTubeIface *tube;
- WockyStanzaType stanza_type;
- WockyStanzaSubType sub_type;
-
- /* Caller is expected to have checked that we have a stream or muc-stream
- * node with a stream ID and the TUBES profile
- */
- wocky_stanza_get_type_info (msg, &stanza_type, &sub_type);
- g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_IQ);
- g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET);
-
- si_node = wocky_node_get_child_ns (
- wocky_stanza_get_top_node (msg), "si", NS_SI);
- g_return_if_fail (si_node != NULL);
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- stream_node = wocky_node_get_child_ns (si_node,
- "stream", NS_TUBES);
- else
- stream_node = wocky_node_get_child_ns (si_node,
- "muc-stream", NS_TUBES);
- g_return_if_fail (stream_node != NULL);
-
- stream_id = wocky_node_get_attribute (si_node, "id");
- g_return_if_fail (stream_id != NULL);
-
- tmp = wocky_node_get_attribute (stream_node, "tube");
- if (tmp == NULL)
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "<stream> or <muc-stream> has no tube attribute" };
-
- NODE_DEBUG (stream_node, e.message);
- gabble_bytestream_iface_close (bytestream, &e);
- return;
- }
- tube_id_tmp = strtoul (tmp, &endptr, 10);
- if (!endptr || *endptr || tube_id_tmp > G_MAXUINT32)
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "<stream> or <muc-stream> tube attribute not numeric or > 2**32" };
-
- DEBUG ("tube id is not numeric or > 2**32: %s", tmp);
- gabble_bytestream_iface_close (bytestream, &e);
- return;
- }
- tube_id = (guint) tube_id_tmp;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube == NULL)
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "<stream> or <muc-stream> tube attribute points to a nonexistent "
- "tube" };
-
- DEBUG ("tube %u doesn't exist", tube_id);
- gabble_bytestream_iface_close (bytestream, &e);
- return;
- }
-
- DEBUG ("received new bytestream request for existing tube: %u", tube_id);
-
- gabble_tube_iface_add_bytestream (tube, bytestream);
-}
-
-
-static void
-send_tube_close_msg (GabbleTubesChannel *self,
- guint tube_id)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- WockyStanza *msg;
- const gchar *jid;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- gchar *id_str;
-
- jid = tp_handle_inspect (contact_repo, priv->handle);
- id_str = g_strdup_printf ("%u", tube_id);
-
- /* Send the close message */
- msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
- NULL, jid,
- '(', "close",
- ':', NS_TUBES,
- '@', "tube", id_str,
- ')',
- GABBLE_AMP_DO_NOT_STORE_SPEC,
- NULL);
- g_free (id_str);
-
- _gabble_connection_send (priv->conn, msg, NULL);
-
- g_object_unref (msg);
-}
-
-static void
-tube_msg_offered (GabbleTubesChannel *self,
- WockyStanza *msg,
- WockyNode *tube_node)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- const gchar *service;
- GHashTable *parameters;
- TpTubeType type;
- guint tube_id;
- GabbleTubeIface *tube;
- WockyStanzaType stanza_type;
-
- wocky_stanza_get_type_info (msg, &stanza_type, NULL);
- g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_MESSAGE);
-
- if (!extract_tube_information (self, tube_node, NULL, NULL,
- NULL, NULL, &tube_id))
- {
- DEBUG ("<tube> has no id attribute");
- /* We can't send a close message as reply so just ignore it */
- return;
- }
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube != NULL)
- {
- DEBUG ("tube ID already in use. Do not open the offered tube and close "
- "the existing tube id %u", tube_id);
- gabble_tube_iface_close (tube, FALSE);
- return;
- }
-
- /* New tube */
- if (!extract_tube_information (self, tube_node, &type, NULL,
- &service, &parameters, NULL))
- {
- DEBUG ("can't extract <tube> information from message");
- send_tube_close_msg (self, tube_id);
- return;
- }
-
- if (type != TP_TUBE_TYPE_STREAM)
- {
- DEBUG ("Only stream tubes are allowed to be created using messages");
- send_tube_close_msg (self, tube_id);
- return;
- }
-
- tube = create_new_tube (self, type, priv->handle, service,
- parameters, NULL, tube_id, NULL, FALSE);
-
- tp_channel_manager_emit_new_channel (priv->conn->private_tubes_factory,
- TP_EXPORTABLE_CHANNEL (tube), NULL);
-
- g_hash_table_unref (parameters);
-}
-
-static void
-tube_msg_close (GabbleTubesChannel *self,
- WockyStanza *msg,
- WockyNode *close_node)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- guint tube_id;
- const gchar *tmp;
- gchar *endptr;
- GabbleTubeIface *tube;
- TpTubeType type;
-
- tmp = wocky_node_get_attribute (close_node, "tube");
- if (tmp == NULL)
- {
- DEBUG ("no tube id in close message");
- return;
- }
-
- tube_id = (guint) strtoul (tmp, &endptr, 10);
- if (!endptr || *endptr || tube_id > G_MAXUINT32)
- {
- DEBUG ("tube id is not numeric or > 2**32: %s", tmp);
- return;
- }
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube == NULL)
- {
- DEBUG ("<close> tube attribute points to a nonexistent tube");
- return;
- }
-
- g_object_get (tube, "type", &type, NULL);
- if (type != TP_TUBE_TYPE_STREAM)
- {
- DEBUG ("Only stream tubes can be closed using a close message");
- return;
- }
-
- DEBUG ("tube %u was closed by remote peer", tube_id);
- gabble_tube_iface_close (tube, TRUE);
-}
-
-void
-gabble_tubes_channel_tube_msg (GabbleTubesChannel *self,
- WockyStanza *msg)
-{
- WockyNode *node;
-
- node = wocky_node_get_child_ns (
- wocky_stanza_get_top_node (msg), "tube", NS_TUBES);
- if (node != NULL)
- {
- tube_msg_offered (self, msg, node);
- return;
- }
-
- node = wocky_node_get_child_ns (
- wocky_stanza_get_top_node (msg), "close", NS_TUBES);
- if (node != NULL)
- {
- tube_msg_close (self, msg, node);
- return;
- }
-}
-
-static guint
-generate_tube_id (void)
-{
- /* We don't generate IDs in the top half of the range, to be nice to
- * older Gabble versions. */
- return g_random_int_range (0, G_MAXINT);
-}
-
-GabbleTubeIface *gabble_tubes_channel_tube_request (GabbleTubesChannel *self,
- gpointer request_token, GHashTable *request_properties,
- gboolean require_new)
-{
- GabbleTubesChannelPrivate *priv = self->priv;
- GabbleTubeIface *tube;
- const gchar *channel_type;
- const gchar *service;
- GHashTable *parameters = NULL;
- guint tube_id;
- gchar *stream_id;
- TpTubeType type;
-
- tube_id = generate_tube_id ();
-
- channel_type = tp_asv_get_string (request_properties,
- TP_IFACE_CHANNEL ".ChannelType");
-
- if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
- {
- type = TP_TUBE_TYPE_STREAM;
- service = tp_asv_get_string (request_properties,
- TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service");
-
- }
- else if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
- {
- type = TP_TUBE_TYPE_DBUS;
- service = tp_asv_get_string (request_properties,
- TP_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName");
- }
- else
- /* This assertion is safe: this function's caller only calls it in one of
- * the above cases.
- * FIXME: but it would be better to pass an enum member or something maybe.
- */
- g_assert_not_reached ();
-
- /* requested tubes have an empty parameters dict */
- parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
- (GDestroyNotify) tp_g_value_slice_free);
-
- /* if the service property is missing, the requestotron rejects the request
- */
- g_assert (service != NULL);
-
- DEBUG ("Request a tube channel with type='%s' and service='%s'",
- channel_type, service);
-
- stream_id = gabble_bytestream_factory_generate_stream_id ();
- tube = create_new_tube (self, type, priv->self_handle, service,
- parameters, stream_id, tube_id, NULL, TRUE);
- g_free (stream_id);
- g_hash_table_unref (parameters);
-
- return tube;
-}
-
-/**
- * gabble_tubes_channel_offer_d_bus_tube
- *
- * Implements D-Bus method OfferDBusTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_offer_d_bus_tube (TpSvcChannelTypeTubes *iface,
- const gchar *service,
- GHashTable *parameters,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv;
- guint tube_id;
- GabbleTubeIface *tube;
- gchar *stream_id;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- priv = self->priv;
-
- stream_id = gabble_bytestream_factory_generate_stream_id ();
- tube_id = generate_tube_id ();
-
- tube = create_new_tube (self, TP_TUBE_TYPE_DBUS, priv->self_handle,
- service, parameters, (const gchar *) stream_id, tube_id, NULL, TRUE);
-
- if (!gabble_tube_dbus_offer (GABBLE_TUBE_DBUS (tube), &error))
- {
- gabble_tube_iface_close (tube, TRUE);
- dbus_g_method_return_error (context, error);
-
- g_error_free (error);
- g_free (stream_id);
- return;
- }
-
- tp_svc_channel_type_tubes_return_from_offer_d_bus_tube (context, tube_id);
-
- g_free (stream_id);
-}
-
-static void
-stream_unix_tube_new_connection_cb (GabbleTubeIface *tube,
- guint contact,
- gpointer user_data)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (user_data);
- guint tube_id;
- TpTubeType type;
-
- g_object_get (tube,
- "id", &tube_id,
- "type", &type,
- NULL);
-
- g_assert (type == TP_TUBE_TYPE_STREAM);
-
- tp_svc_channel_type_tubes_emit_stream_tube_new_connection (self,
- tube_id, contact);
-}
-
-/**
- * gabble_tubes_channel_offer_stream_tube
- *
- * Implements D-Bus method OfferStreamTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_offer_stream_tube (TpSvcChannelTypeTubes *iface,
- const gchar *service,
- GHashTable *parameters,
- guint address_type,
- const GValue *address,
- guint access_control,
- const GValue *access_control_param,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv;
- guint tube_id;
- GabbleTubeIface *tube;
- gchar *stream_id;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- priv = self->priv;
-
- if (!gabble_tube_stream_check_params (address_type, address,
- access_control, access_control_param, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- stream_id = gabble_bytestream_factory_generate_stream_id ();
- tube_id = generate_tube_id ();
-
- tube = create_new_tube (self, TP_TUBE_TYPE_STREAM, priv->self_handle,
- service, parameters, (const gchar *) stream_id, tube_id, NULL, TRUE);
-
- g_object_set (tube,
- "address-type", address_type,
- "address", address,
- "access-control", access_control,
- "access-control-param", access_control_param,
- NULL);
-
- /* Tube was created using the old API so is already offered */
- if (!gabble_tube_stream_offer (GABBLE_TUBE_STREAM (tube), &error))
- {
- gabble_tube_iface_close (tube, TRUE);
-
- dbus_g_method_return_error (context, error);
-
- g_error_free (error);
- g_free (stream_id);
- return;
- }
-
- g_signal_connect (tube, "tube-new-connection",
- G_CALLBACK (stream_unix_tube_new_connection_cb), self);
-
- /* announce the new tube channel we just created (new tube API) */
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- {
- tp_channel_manager_emit_new_channel (priv->conn->private_tubes_factory,
- TP_EXPORTABLE_CHANNEL (tube), NULL);
- }
- else
- {
- tp_channel_manager_emit_new_channel (priv->conn->muc_factory,
- TP_EXPORTABLE_CHANNEL (tube), NULL);
- }
-
- tp_svc_channel_type_tubes_return_from_offer_stream_tube (context,
- tube_id);
-
- g_free (stream_id);
-}
-
-/**
- * gabble_tubes_channel_accept_d_bus_tube
- *
- * Implements D-Bus method AcceptDBusTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_accept_d_bus_tube (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv;
- GabbleTubeIface *tube;
- TpTubeChannelState state;
- TpTubeType type;
- gchar *addr;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- priv = self->priv;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
- if (tube == NULL)
- {
- GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &e);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_DBUS)
- {
- GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a D-Bus tube" };
-
- dbus_g_method_return_error (context, &e);
- return;
- }
-
- if (state != TP_TUBE_CHANNEL_STATE_LOCAL_PENDING)
- {
- GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not in the local pending state" };
-
- dbus_g_method_return_error (context, &e);
- return;
- }
-
- if (!gabble_tube_iface_accept (tube, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- g_object_get (tube, "dbus-address", &addr, NULL);
- tp_svc_channel_type_tubes_return_from_accept_d_bus_tube (context, addr);
- g_free (addr);
-}
-
-/**
- * gabble_tubes_channel_accept_stream_tube
- *
- * Implements D-Bus method AcceptStreamTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_accept_stream_tube (TpSvcChannelTypeTubes *iface,
- guint id,
- guint address_type,
- guint access_control,
- const GValue *access_control_param,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv;
- GabbleTubeIface *tube;
- TpTubeChannelState state;
- TpTubeType type;
- GValue *address;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- priv = self->priv;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
- if (tube == NULL)
- {
- GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &e);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_STREAM)
- {
- GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a stream tube" };
-
- dbus_g_method_return_error (context, &e);
- return;
- }
-
- /* most parameters sanity checks are done in gabble_tube_stream_accept,
- * but at least check that they fit the properties requirements */
- if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX &&
- address_type != TP_SOCKET_ADDRESS_TYPE_IPV4 &&
- address_type != TP_SOCKET_ADDRESS_TYPE_IPV6)
- {
- GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Address type not implemented" };
-
- dbus_g_method_return_error (context, &e);
- return;
- }
- g_object_set (tube,
- "address-type", address_type,
- "access-control", access_control,
- "access-control-param", access_control_param,
- NULL);
-
- if (!gabble_tube_iface_accept (tube, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- update_tubes_presence (self);
-
- g_object_get (tube, "address", &address, NULL);
-
- tp_svc_channel_type_tubes_return_from_accept_stream_tube (context,
- address);
-}
-
-/**
- * gabble_tubes_channel_close_tube
- *
- * Implements D-Bus method CloseTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_close_tube (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv;
- GabbleTubeIface *tube;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- priv = self->priv;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
-
- if (tube == NULL)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- gabble_tube_iface_close (tube, FALSE);
-
- tp_svc_channel_type_tubes_return_from_close_tube (context);
-}
-
-/**
- * gabble_tubes_channel_get_d_bus_tube_address
- *
- * Implements D-Bus method GetDBusTubeAddress
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_get_d_bus_tube_address (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv;
- GabbleTubeIface *tube;
- gchar *addr;
- TpTubeType type;
- TpTubeChannelState state;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- priv = self->priv;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
-
- if (tube == NULL)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_DBUS)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a D-Bus tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube, "dbus-address", &addr, NULL);
- tp_svc_channel_type_tubes_return_from_get_d_bus_tube_address (context,
- addr);
- g_free (addr);
-}
-
-static void
-get_d_bus_names_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- GPtrArray *ret = user_data;
- GValue tmp = {0,};
-
- g_value_init (&tmp, TP_STRUCT_TYPE_DBUS_TUBE_MEMBER);
- g_value_take_boxed (&tmp,
- dbus_g_type_specialized_construct (TP_STRUCT_TYPE_DBUS_TUBE_MEMBER));
- dbus_g_type_struct_set (&tmp,
- 0, key,
- 1, value,
- G_MAXUINT);
- g_ptr_array_add (ret, g_value_get_boxed (&tmp));
-}
-
-/**
- * gabble_tubes_channel_get_d_bus_names
- *
- * Implements D-Bus method GetDBusNames
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_get_d_bus_names (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv = self->priv;
- GabbleTubeIface *tube;
- GHashTable *names;
- GPtrArray *ret;
- TpTubeType type;
- TpTubeChannelState state;
- guint i;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
-
- if (tube == NULL)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_DBUS ||
- priv->handle_type != TP_HANDLE_TYPE_ROOM)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a Muc D-Bus tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- if (state != TP_TUBE_CHANNEL_STATE_OPEN)
- {
- GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Tube is not open" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube, "dbus-names", &names, NULL);
- g_assert (names);
-
- ret = g_ptr_array_sized_new (g_hash_table_size (names));
- g_hash_table_foreach (names, get_d_bus_names_foreach, ret);
-
- tp_svc_channel_type_tubes_return_from_get_d_bus_names (context, ret);
-
- for (i = 0; i < ret->len; i++)
- g_boxed_free (TP_STRUCT_TYPE_DBUS_TUBE_MEMBER, ret->pdata[i]);
- g_hash_table_unref (names);
- g_ptr_array_unref (ret);
-}
-
-/**
- * gabble_tubes_channel_get_stream_tube_socket_address
- *
- * Implements D-Bus method GetStreamTubeSocketAddress
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_get_stream_tube_socket_address (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv = self->priv;
- GabbleTubeIface *tube;
- TpTubeType type;
- TpTubeChannelState state;
- TpSocketAddressType address_type;
- GValue *address;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
- if (tube == NULL)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_STREAM)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a Stream tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- if (state != TP_TUBE_CHANNEL_STATE_OPEN)
- {
- GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Tube is not open" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube,
- "address-type", &address_type,
- "address", &address,
- NULL);
-
- tp_svc_channel_type_tubes_return_from_get_stream_tube_socket_address (
- context, address_type, address);
-}
-
-/**
- * gabble_tubes_channel_get_available_stream_tube_types
- *
- * Implements D-Bus method GetAvailableStreamTubeTypes
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-gabble_tubes_channel_get_available_stream_tube_types (TpSvcChannelTypeTubes *iface,
- DBusGMethodInvocation *context)
-{
- GHashTable *ret;
-
- ret = gabble_tube_stream_get_supported_socket_types ();
-
- tp_svc_channel_type_tubes_return_from_get_available_stream_tube_types (
- context, ret);
-
- g_hash_table_unref (ret);
-}
-
-static void
-emit_tube_closed_signal (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint id = GPOINTER_TO_UINT (key);
- GabbleTubesChannel *self = (GabbleTubesChannel *) user_data;
-
- tp_svc_channel_type_tubes_emit_tube_closed (self, id);
-}
-
-void
-gabble_tubes_channel_close (GabbleTubesChannel *self)
-{
- GabbleTubesChannelPrivate *priv;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- DEBUG ("called on %p", self);
-
- priv = self->priv;
-
- if (priv->closed)
- {
- return;
- }
-
- priv->closed = TRUE;
-
- g_hash_table_foreach (priv->tubes, emit_tube_closed_signal, self);
- g_hash_table_unref (priv->tubes);
-
- priv->tubes = NULL;
-
- tp_svc_channel_emit_closed (self);
-}
-
-/**
- * gabble_tubes_channel_close_async:
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_tubes_channel_close_async (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
-
- gabble_tubes_channel_close (self);
- tp_svc_channel_return_from_close (context);
-}
-
-/**
- * gabble_tubes_channel_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_tubes_channel_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_TUBES);
-}
-
-/**
- * gabble_tubes_channel_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_tubes_channel_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
- GabbleTubesChannelPrivate *priv;
-
- g_assert (GABBLE_IS_TUBES_CHANNEL (self));
- priv = self->priv;
-
- tp_svc_channel_return_from_get_handle (context, priv->handle_type,
- priv->handle);
-}
-
-/**
- * gabble_tubes_channel_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_tubes_channel_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (iface);
-
- if (self->muc)
- {
- tp_svc_channel_return_from_get_interfaces (context,
- gabble_tubes_channel_interfaces);
- }
- else
- {
- /* omit the Group interface */
- tp_svc_channel_return_from_get_interfaces (context,
- gabble_tubes_channel_interfaces + 1);
- }
-}
-
-static void gabble_tubes_channel_dispose (GObject *object);
-static void gabble_tubes_channel_finalize (GObject *object);
-
-static void
-gabble_tubes_channel_class_init (
- GabbleTubesChannelClass *gabble_tubes_channel_class)
-{
- static TpDBusPropertiesMixinPropImpl channel_props[] = {
- { "TargetHandleType", "handle-type", NULL },
- { "TargetHandle", "handle", NULL },
- { "TargetID", "target-id", NULL },
- { "ChannelType", "channel-type", NULL },
- { "Interfaces", "interfaces", NULL },
- { "Requested", "requested", NULL },
- { "InitiatorHandle", "initiator-handle", NULL },
- { "InitiatorID", "initiator-id", NULL },
- { NULL }
- };
- static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { TP_IFACE_CHANNEL,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- channel_props,
- },
- { NULL }
- };
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_tubes_channel_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (gabble_tubes_channel_class,
- sizeof (GabbleTubesChannelPrivate));
-
- object_class->constructor = gabble_tubes_channel_constructor;
-
- object_class->get_property = gabble_tubes_channel_get_property;
- object_class->set_property = gabble_tubes_channel_set_property;
-
- object_class->dispose = gabble_tubes_channel_dispose;
- object_class->finalize = gabble_tubes_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");
-
- g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
- "channel-destroyed");
- g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
- "channel-properties");
-
- param_spec = g_param_spec_object (
- "connection",
- "GabbleConnection object",
- "Gabble connection object that owns this Tubes channel object.",
- GABBLE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
- "Additional Channel.Interface.* interfaces",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
- param_spec = g_param_spec_object (
- "muc",
- "GabbleMucChannel object",
- "Gabble text MUC channel corresponding to this Tubes channel object, "
- "if the handle type is ROOM.",
- GABBLE_TYPE_MUC_CHANNEL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MUC, param_spec);
-
- param_spec = g_param_spec_string ("target-id", "Target JID",
- "The string obtained by inspecting the target handle",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
-
- param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle",
- "The contact who initiated the channel",
- 0, G_MAXUINT32, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE,
- param_spec);
-
- param_spec = g_param_spec_string ("initiator-id", "Initiator's bare JID",
- "The string obtained by inspecting the initiator-handle",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIATOR_ID,
- param_spec);
-
- param_spec = g_param_spec_boolean ("requested", "Requested?",
- "True if this channel was requested by the local user",
- FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
-
- gabble_tubes_channel_class->dbus_props_class.interfaces = prop_interfaces;
- tp_dbus_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleTubesChannelClass, dbus_props_class));
-
- tp_external_group_mixin_init_dbus_properties (object_class);
-}
-
-void
-gabble_tubes_channel_dispose (GObject *object)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (object);
- GabbleTubesChannelPrivate *priv = self->priv;
- TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, priv->handle_type);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- tp_handle_unref (handle_repo, priv->handle);
-
- if (self->muc != NULL)
- {
- g_signal_handler_disconnect (self->muc, priv->pre_presence_signal);
-
- tp_external_group_mixin_finalize (object);
- }
- gabble_tubes_channel_close (self);
-
- g_assert (priv->closed);
- g_assert (priv->tubes == NULL);
-
- if (G_OBJECT_CLASS (gabble_tubes_channel_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_tubes_channel_parent_class)->dispose (object);
-}
-
-void
-gabble_tubes_channel_finalize (GObject *object)
-{
- GabbleTubesChannel *self = GABBLE_TUBES_CHANNEL (object);
- GabbleTubesChannelPrivate *priv = self->priv;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- g_free (priv->object_path);
-
- if (priv->initiator != 0)
- tp_handle_unref (contact_handles, priv->initiator);
-
- G_OBJECT_CLASS (gabble_tubes_channel_parent_class)->finalize (object);
-}
-
-static void
-tubes_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpSvcChannelTypeTubesClass *klass = (TpSvcChannelTypeTubesClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_type_tubes_implement_##x (\
- klass, gabble_tubes_channel_##x)
- IMPLEMENT(get_available_tube_types);
- IMPLEMENT(list_tubes);
- IMPLEMENT(close_tube);
- IMPLEMENT(offer_d_bus_tube);
- IMPLEMENT(accept_d_bus_tube);
- IMPLEMENT(get_d_bus_tube_address);
- IMPLEMENT(get_d_bus_names);
- IMPLEMENT(offer_stream_tube);
- IMPLEMENT(accept_stream_tube);
- IMPLEMENT(get_stream_tube_socket_address);
- IMPLEMENT(get_available_stream_tube_types);
-#undef IMPLEMENT
-}
-
-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_tubes_channel_##x##suffix)
- IMPLEMENT(close,_async);
- IMPLEMENT(get_channel_type,);
- IMPLEMENT(get_handle,);
- IMPLEMENT(get_interfaces,);
-#undef IMPLEMENT
-}
diff --git a/src/tubes-channel.h b/src/tubes-channel.h
deleted file mode 100644
index dbf7d5fd4..000000000
--- a/src/tubes-channel.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * tubes-channel.h - Header for GabbleTubesChannel
- * Copyright (C) 2007 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 __GABBLE_TUBES_CHANNEL_H__
-#define __GABBLE_TUBES_CHANNEL_H__
-
-#include <glib-object.h>
-#include <wocky/wocky.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/exportable-channel.h>
-
-#include "bytestream-iface.h"
-#include "muc-channel.h"
-#include "tube-iface.h"
-#include "types.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleTubesChannelPrivate GabbleTubesChannelPrivate;
-typedef struct _GabbleTubesChannelClass GabbleTubesChannelClass;
-
-struct _GabbleTubesChannelClass {
- GObjectClass parent_class;
-
- TpDBusPropertiesMixinClass dbus_props_class;
-};
-
-struct _GabbleTubesChannel {
- GObject parent;
-
- GabbleMucChannel *muc;
-
- GabbleTubesChannelPrivate *priv;
-};
-
-GType gabble_tubes_channel_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_TUBES_CHANNEL \
- (gabble_tubes_channel_get_type ())
-#define GABBLE_TUBES_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_TUBES_CHANNEL,\
- GabbleTubesChannel))
-#define GABBLE_TUBES_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_TUBES_CHANNEL,\
- GabbleTubesChannelClass))
-#define GABBLE_IS_TUBES_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_TUBES_CHANNEL))
-#define GABBLE_IS_TUBES_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_TUBES_CHANNEL))
-#define GABBLE_TUBES_CHANNEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_TUBES_CHANNEL,\
- GabbleTubesChannelClass))
-
-void gabble_tubes_channel_foreach (GabbleTubesChannel *self,
- TpExportableChannelFunc foreach, gpointer user_data);
-
-GabbleTubeIface *gabble_tubes_channel_tube_request (GabbleTubesChannel *self,
- gpointer request_token, GHashTable *request_properties,
- gboolean require_new);
-
-void gabble_tubes_channel_presence_updated (GabbleTubesChannel *chan,
- TpHandle contact, WockyNode *presence);
-
-void gabble_tubes_channel_tube_si_offered (GabbleTubesChannel *chan,
- GabbleBytestreamIface *bytestream, WockyStanza *msg);
-
-void gabble_tubes_channel_bytestream_offered (GabbleTubesChannel *chan,
- GabbleBytestreamIface *bytestream, WockyStanza *msg);
-
-void gabble_tubes_channel_tube_msg (GabbleTubesChannel *chan, WockyStanza *msg);
-
-void gabble_tubes_channel_close (GabbleTubesChannel *self);
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_TUBES_CHANNEL_H__*/
diff --git a/src/types.h b/src/types.h
index 1c9de3f1a..977ff3fb7 100644
--- a/src/types.h
+++ b/src/types.h
@@ -24,7 +24,7 @@
#include "config.h"
-#include <telepathy-glib/handle.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "gabble/types.h"
diff --git a/src/util.c b/src/util.c
index 4102f2194..b36f5745a 100644
--- a/src/util.c
+++ b/src/util.c
@@ -31,13 +31,11 @@
#include <gobject/gvaluecollector.h>
#include <wocky/wocky.h>
-#include <telepathy-glib/handle-repo-dynamic.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG GABBLE_DEBUG_JID
-#include "base64.h"
#include "conn-aliasing.h"
#include "connection.h"
#include "debug.h"
@@ -134,16 +132,6 @@ gabble_generate_id (void)
return str;
}
-
-static void
-lm_message_node_add_nick (WockyNode *node, const gchar *nick)
-{
- WockyNode *nick_node;
-
- nick_node = wocky_node_add_child_with_content (node, "nick", nick);
- nick_node->ns = g_quark_from_string (NS_NICK);
-}
-
void
lm_message_node_add_own_nick (WockyNode *node,
GabbleConnection *connection)
@@ -153,10 +141,11 @@ lm_message_node_add_own_nick (WockyNode *node,
TpBaseConnection *base = (TpBaseConnection *) connection;
source = _gabble_connection_get_cached_alias (connection,
- base->self_handle, &nick);
+ tp_base_connection_get_self_handle (base), &nick);
if (source > GABBLE_CONNECTION_ALIAS_FROM_JID)
- lm_message_node_add_nick (node, nick);
+ wocky_node_add_child_with_content_ns_q (node, "nick", nick,
+ g_quark_from_static_string (NS_NICK));
g_free (nick);
}
@@ -193,7 +182,7 @@ gabble_get_room_handle_from_jid (TpHandleRepoIface *room_repo,
#define INVALID_HANDLE(e, f, ...) \
G_STMT_START { \
DEBUG (f, ##__VA_ARGS__); \
- g_set_error (e, TP_ERRORS, TP_ERROR_INVALID_HANDLE, f, ##__VA_ARGS__);\
+ g_set_error (e, TP_ERROR, TP_ERROR_INVALID_HANDLE, f, ##__VA_ARGS__);\
} G_STMT_END
gchar *
@@ -404,19 +393,20 @@ lm_message_node_extract_properties (WockyNode *node,
if (0 == strcmp (type, "bytes"))
{
GArray *arr;
- GString *decoded;
+ guchar *st;
+ gsize outlen;
- decoded = base64_decode (value);
- if (!decoded)
+ st = g_base64_decode (value, &outlen);
+ if (!st)
continue;
arr = g_array_new (FALSE, FALSE, sizeof (guchar));
- g_array_append_vals (arr, decoded->str, decoded->len);
+ g_array_append_vals (arr, st, outlen);
gvalue = g_slice_new0 (GValue);
g_value_init (gvalue, DBUS_TYPE_G_UCHAR_ARRAY);
g_value_take_boxed (gvalue, arr);
g_hash_table_insert (properties, g_strdup (name), gvalue);
- g_string_free (decoded, TRUE);
+ g_free (st);
}
else if (0 == strcmp (type, "str"))
{
@@ -512,7 +502,7 @@ set_child_from_property (gpointer key,
return;
}
- child = wocky_node_add_child_with_content (data->node, data->prop, "");
+ child = wocky_node_add_child (data->node, data->prop);
if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING)
{
@@ -526,7 +516,7 @@ set_child_from_property (gpointer key,
type = "bytes";
arr = g_value_get_boxed (gvalue);
- str = base64_encode (arr->len, arr->data, FALSE);
+ str = g_base64_encode ((guchar *) arr->data, arr->len);
wocky_node_set_content (child, str);
g_free (str);
@@ -824,7 +814,7 @@ jingle_pick_best_resource (GabbleConnection *conn,
gboolean want_audio,
gboolean want_video,
const char **transport_ns,
- JingleDialect *dialect,
+ WockyJingleDialect *dialect,
const gchar **resource_out)
{
/* We prefer gtalk-p2p to ice, because it can use tcp and https relays (if
@@ -848,7 +838,7 @@ jingle_pick_best_resource (GabbleConnection *conn,
return FALSE;
}
- *dialect = JINGLE_DIALECT_ERROR;
+ *dialect = WOCKY_JINGLE_DIALECT_ERROR;
*transport_ns = NULL;
g_return_val_if_fail (want_audio || want_video, FALSE);
@@ -866,7 +856,7 @@ jingle_pick_best_resource (GabbleConnection *conn,
if (jingle_pick_resource_or_bare_jid (presence, caps, &resource))
{
- *dialect = JINGLE_DIALECT_V032;
+ *dialect = WOCKY_JINGLE_DIALECT_V032;
goto CHOOSE_TRANSPORT;
}
@@ -880,7 +870,7 @@ jingle_pick_best_resource (GabbleConnection *conn,
if (jingle_pick_resource_or_bare_jid (presence, caps, &resource))
{
- *dialect = JINGLE_DIALECT_V015;
+ *dialect = WOCKY_JINGLE_DIALECT_V015;
goto CHOOSE_TRANSPORT;
}
@@ -900,7 +890,7 @@ jingle_pick_best_resource (GabbleConnection *conn,
if (jingle_pick_resource_or_bare_jid (presence, caps, &resource))
{
- *dialect = JINGLE_DIALECT_GTALK3;
+ *dialect = WOCKY_JINGLE_DIALECT_GTALK3;
goto CHOOSE_TRANSPORT;
}
@@ -917,7 +907,7 @@ jingle_pick_best_resource (GabbleConnection *conn,
if (jingle_pick_resource_or_bare_jid (presence, caps, &resource))
{
- *dialect = JINGLE_DIALECT_GTALK4;
+ *dialect = WOCKY_JINGLE_DIALECT_GTALK4;
goto CHOOSE_TRANSPORT;
}
@@ -931,7 +921,7 @@ CHOOSE_TRANSPORT:
success = TRUE;
- if (*dialect == JINGLE_DIALECT_GTALK4 || *dialect == JINGLE_DIALECT_GTALK3)
+ if (*dialect == WOCKY_JINGLE_DIALECT_GTALK4 || *dialect == WOCKY_JINGLE_DIALECT_GTALK3)
{
/* the GTalk dialects only support google p2p as transport protocol. */
*transport_ns = NS_GOOGLE_TRANSPORT_P2P;
@@ -959,20 +949,20 @@ const gchar *
jingle_pick_best_content_type (GabbleConnection *conn,
TpHandle peer,
const gchar *resource,
- JingleMediaType type)
+ WockyJingleMediaType type)
{
GabblePresence *presence;
const GabbleFeatureFallback content_types[] = {
/* if $thing is supported, then use it */
{ TRUE, TWICE (NS_JINGLE_RTP) },
- { type == JINGLE_MEDIA_TYPE_VIDEO,
+ { type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO,
TWICE (NS_JINGLE_DESCRIPTION_VIDEO) },
- { type == JINGLE_MEDIA_TYPE_AUDIO,
+ { type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO,
TWICE (NS_JINGLE_DESCRIPTION_AUDIO) },
/* odd Google ones: if $thing is supported, use $other_thing */
- { type == JINGLE_MEDIA_TYPE_AUDIO,
+ { type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO,
NS_GOOGLE_FEAT_VOICE, NS_GOOGLE_SESSION_PHONE },
- { type == JINGLE_MEDIA_TYPE_VIDEO,
+ { type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO,
NS_GOOGLE_FEAT_VIDEO, NS_GOOGLE_SESSION_VIDEO },
{ FALSE, NULL, NULL }
};
@@ -998,23 +988,23 @@ jingle_pick_best_content_type (GabbleConnection *conn,
}
static TpCallStreamCandidateType
-tp_candidate_type_from_jingle (JingleCandidateType type)
+tp_candidate_type_from_jingle (WockyJingleCandidateType type)
{
switch (type)
{
default:
/* Consider UNKNOWN as LOCAL/HOST */
- case JINGLE_CANDIDATE_TYPE_LOCAL:
+ case WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL:
return TP_CALL_STREAM_CANDIDATE_TYPE_HOST;
- case JINGLE_CANDIDATE_TYPE_STUN:
+ case WOCKY_JINGLE_CANDIDATE_TYPE_STUN:
return TP_CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE;
- case JINGLE_CANDIDATE_TYPE_RELAY:
+ case WOCKY_JINGLE_CANDIDATE_TYPE_RELAY:
return TP_CALL_STREAM_CANDIDATE_TYPE_RELAY;
}
}
/**
- * @candidates: (element-type JingleCandidate): candidates
+ * @candidates: (element-type WockyJingleCandidate): candidates
*
* Returns: (transfer full): a GABBLE_ARRAY_TYPE_CANDIDATE_LIST, i.e.
* a(usqa{sv})
@@ -1029,7 +1019,7 @@ gabble_call_candidates_to_array (GList *candidates)
for (c = candidates; c != NULL; c = g_list_next (c))
{
- JingleCandidate *cand = (JingleCandidate *) c->data;
+ WockyJingleCandidate *cand = (WockyJingleCandidate *) c->data;
GValueArray *a;
GHashTable *info;
diff --git a/src/util.h b/src/util.h
index 10b2b6eec..e01ff7e50 100644
--- a/src/util.h
+++ b/src/util.h
@@ -25,15 +25,9 @@
#include <config.h>
#include <glib.h>
-#include <telepathy-glib/handle-repo.h>
-#include <telepathy-glib/util.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <wocky/wocky.h>
-#ifdef ENABLE_VOIP
-#include "jingle-factory.h"
-#include "jingle-content.h"
-#endif
-
#include "types.h"
/* Guarantees that the resulting hash is in lower-case */
@@ -84,13 +78,13 @@ gboolean jingle_pick_best_resource (GabbleConnection *conn,
gboolean want_audio,
gboolean want_video,
const char **transport_ns,
- JingleDialect *dialect,
+ WockyJingleDialect *dialect,
const gchar **resource_out);
const gchar *jingle_pick_best_content_type (GabbleConnection *conn,
TpHandle peer,
const gchar *resource,
- JingleMediaType type);
+ WockyJingleMediaType type);
GPtrArray *gabble_call_candidates_to_array (GList *candidates);
#endif
diff --git a/src/vcard-manager.c b/src/vcard-manager.c
index 67466be01..74e933e9c 100644
--- a/src/vcard-manager.c
+++ b/src/vcard-manager.c
@@ -24,13 +24,12 @@
#include <string.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/heap.h>
+#include <telepathy-glib/telepathy-glib.h>
+
#include <wocky/wocky.h>
#define DEBUG_FLAG GABBLE_DEBUG_VCARD
-#include "base64.h"
#include "conn-aliasing.h"
#include "conn-contact-info.h"
#include "connection.h"
@@ -49,53 +48,29 @@ static guint request_wait_delay = 5 * 60;
static const gchar *NO_ALIAS = "none";
-typedef struct {
- gchar *key;
- gchar *value;
-} GabbleVCardChild;
-
-static GabbleVCardChild *
-gabble_vcard_child_new (const gchar *key,
- const gchar *value)
-{
- GabbleVCardChild *child = g_slice_new (GabbleVCardChild);
-
- child->key = g_strdup (key);
- child->value = g_strdup (value);
- return child;
-}
-
-static void
-gabble_vcard_child_free (GabbleVCardChild *child)
-{
- g_free (child->key);
- g_free (child->value);
- g_slice_free (GabbleVCardChild, child);
-}
-
struct _GabbleVCardManagerEditInfo {
/* name of element to edit */
gchar *element_name;
- /* value of element to edit or NULL if no value should be used */
- gchar *element_value;
-
- /* list of GabbleVCardChild */
- GList *children;
-
/* If REPLACE, the first element with this name (if any) will be updated;
* if APPEND, an element with this name will be added;
* if DELETE, all elements with this name will be removed;
* if CLEAR, everything except PHOTO and NICKNAME will be deleted, in
* preparation for a SetContactInfo operation
- * if SET_ALIAS and element_value is NULL, set the best alias we have
+ * if SET_ALIAS and new_alias is NULL, set the best alias we have
* as the NICKNAME or FN (as appropriate) if that field doesn't already
* have a value
- * if SET_ALIAS and element_value is non-NULL, set that
+ * if SET_ALIAS and new_alias is non-NULL, set that
* as the NICKNAME or FN (as appropriate), overriding anything already
* there
*/
GabbleVCardEditType edit_type;
+
+ /* the element to fill in, if edit_type is REPLACE or APPEND. */
+ WockyNodeTree *element;
+
+ /* only meaningful if edit_type is SET_ALIAS; see above. */
+ gchar *new_alias;
};
/* signal enum */
@@ -155,7 +130,7 @@ struct _GabbleVCardManagerPrivate
/* Patched vCard that we sent to the server to update, but haven't
* got confirmation yet. We don't want to store it in cache (visible
* to others) before we're sure the server accepts it. */
- WockyNode *patched_vcard;
+ WockyNodeTree *patched_vcard;
};
struct _GabbleVCardManagerRequest
@@ -209,7 +184,7 @@ struct _GabbleVCardCacheEntry
guint suspended_timer_id;
/* VCard node for this entry (owned reference), or NULL if there's no node */
- WockyNode *vcard_node;
+ WockyNodeTree *vcard_node;
/* If @vcard_node is not NULL, the time the message will expire */
time_t expires;
@@ -351,42 +326,6 @@ gabble_vcard_manager_set_property (GObject *object,
}
}
-static gboolean
-copy_attribute (const gchar *key,
- const gchar *value,
- const gchar *prefix,
- const gchar *ns,
- gpointer user_data)
-{
- WockyNode *copy = (WockyNode *) user_data;
-
- wocky_node_set_attribute_ns (copy, key, value, ns);
- return TRUE;
-}
-
-static WockyNode *
-copy_node (WockyNode *node)
-{
- WockyNode *copy;
- GSList *l;
-
- copy = wocky_node_new (node->name, wocky_node_get_ns (node));
- wocky_node_set_content (copy, node->content);
- wocky_node_set_language (copy, wocky_node_get_language (node));
-
- wocky_node_each_attribute (node, copy_attribute, copy);
-
- for (l = node->children; l != NULL; l = g_slist_next (l))
- {
- WockyNode *child = l->data;
-
- copy->children = g_slist_prepend (copy->children, copy_node (child));
- }
- copy->children = g_slist_reverse (copy->children);
-
- return copy;
-}
-
static void delete_request (GabbleVCardManagerRequest *request);
static void cancel_request (GabbleVCardManagerRequest *request);
static void cancel_all_edit_requests (GabbleVCardManager *manager);
@@ -403,9 +342,6 @@ static void
cache_entry_free (gpointer data)
{
GabbleVCardCacheEntry *entry = data;
- GabbleVCardManagerPrivate *priv = entry->manager->priv;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
- ((TpBaseConnection *) priv->connection, TP_HANDLE_TYPE_CONTACT);
g_assert (entry != NULL);
@@ -419,9 +355,7 @@ cache_entry_free (gpointer data)
gabble_request_pipeline_item_cancel (entry->pipeline_item);
}
- tp_clear_pointer (&entry->vcard_node, wocky_node_free);
-
- tp_handle_unref (contact_repo, entry->handle);
+ g_clear_object (&entry->vcard_node);
g_slice_free (GabbleVCardCacheEntry, entry);
}
@@ -430,8 +364,6 @@ static GabbleVCardCacheEntry *
cache_entry_get (GabbleVCardManager *manager, TpHandle handle)
{
GabbleVCardManagerPrivate *priv = manager->priv;
- 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));
@@ -442,7 +374,6 @@ cache_entry_get (GabbleVCardManager *manager, TpHandle handle)
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;
@@ -511,7 +442,7 @@ cache_entry_attempt_to_free (GabbleVCardCacheEntry *entry)
*/
g_assert (entry->suspended_timer_id == 0);
- if (entry->handle == base->self_handle)
+ if (entry->handle == tp_base_connection_get_self_handle (base))
{
/* if we do have some pending edits, we should also have
* some pipeline items or pending requests */
@@ -540,7 +471,7 @@ gabble_vcard_manager_invalidate_cache (GabbleVCardManager *manager,
tp_heap_remove (priv->timed_cache, entry);
- tp_clear_pointer (&entry->vcard_node, wocky_node_free);
+ g_clear_object (&entry->vcard_node);
cache_entry_attempt_to_free (entry);
}
@@ -552,14 +483,18 @@ static void
cache_entry_complete_requests (GabbleVCardCacheEntry *entry, GError *error)
{
GSList *cur, *tmp;
+ WockyNode *vcard_node = NULL;
tmp = g_slist_copy (entry->pending_requests);
+ if (entry->vcard_node != NULL)
+ vcard_node = wocky_node_tree_get_top_node (entry->vcard_node);
+
for (cur = tmp; cur != NULL; cur = cur->next)
{
GabbleVCardManagerRequest *request = cur->data;
- complete_one_request (request, error ? NULL : entry->vcard_node, error);
+ complete_one_request (request, error ? NULL : vcard_node, error);
}
g_slist_free (tmp);
@@ -582,7 +517,7 @@ complete_one_request (GabbleVCardManagerRequest *request,
static void
disconnect_entry_foreach (gpointer handle, gpointer value, gpointer unused)
{
- GError err = { TP_ERRORS, TP_ERROR_DISCONNECTED, "Connection closed" };
+ GError err = { TP_ERROR, TP_ERROR_DISCONNECTED, "Connection closed" };
GabbleVCardCacheEntry *entry = value;
if (entry->suspended_timer_id)
@@ -650,7 +585,8 @@ vcard_get_avatar_sha1 (WockyNode *vcard)
{
gchar *sha1;
const gchar *binval_value;
- GString *avatar;
+ guchar *avatar;
+ gsize outlen;
WockyNode *node;
WockyNode *binval;
@@ -670,12 +606,12 @@ vcard_get_avatar_sha1 (WockyNode *vcard)
if (!binval_value)
return g_strdup ("");
- avatar = base64_decode (binval_value);
+ avatar = g_base64_decode (binval_value, &outlen);
if (avatar)
{
- sha1 = sha1_hex (avatar->str, avatar->len);
- g_string_free (avatar, TRUE);
+ sha1 = sha1_hex ((gchar *) avatar, outlen);
+ g_free (avatar);
DEBUG ("Successfully decoded PHOTO.BINVAL, SHA-1 %s", sha1);
}
else
@@ -738,8 +674,7 @@ status_changed_cb (GObject *object,
/* 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);
+ tp_base_connection_get_self_handle (base), &alias);
if (alias_src >= GABBLE_CONNECTION_ALIAS_FROM_VCARD)
{
@@ -751,7 +686,8 @@ status_changed_cb (GObject *object,
g_free (alias);
/* FIXME: we happen to know that synchronous errors can't happen */
- gabble_vcard_manager_request (self, base->self_handle, 0,
+ gabble_vcard_manager_request (self,
+ tp_base_connection_get_self_handle (base), 0,
initial_request_cb, NULL, (GObject *) self);
}
}
@@ -948,25 +884,28 @@ replace_reply_cb (GabbleConnection *conn,
if (error)
{
/* We won't need our patched vcard after all */
- tp_clear_pointer (&priv->patched_vcard, wocky_node_free);
+ g_clear_object (&priv->patched_vcard);
}
else
{
- GabbleVCardCacheEntry *entry = cache_entry_get (self, base->self_handle);
+ GabbleVCardCacheEntry *entry = cache_entry_get (self,
+ tp_base_connection_get_self_handle (base));
/* We must have patched vcard by now */
g_assert (priv->patched_vcard != NULL);
/* Finally we may put the new vcard in the cache. */
- tp_clear_pointer (&entry->vcard_node, wocky_node_free);
+ g_clear_object (&entry->vcard_node);
entry->vcard_node = priv->patched_vcard;
priv->patched_vcard = NULL;
+ node = wocky_node_tree_get_top_node (entry->vcard_node);
+
/* observe it so we pick up alias updates */
- observe_vcard (conn, self, base->self_handle, entry->vcard_node);
+ observe_vcard (conn, self, tp_base_connection_get_self_handle (base),
+ node);
- node = entry->vcard_node;
}
/* Scan all edit requests, call and remove ones whose data made it
@@ -1015,66 +954,27 @@ gabble_vcard_manager_replace_is_significant (GabbleVCardManagerEditInfo *info,
{
gboolean seen = FALSE;
WockyNodeIter i;
- WockyNode *node;
+ WockyNode *node, *replacement_node;
+
+ g_return_val_if_fail (info->element != NULL, FALSE);
+ replacement_node = wocky_node_tree_get_top_node (info->element);
/* Find the first node matching the one we want to edit */
wocky_node_iter_init (&i, old_vcard, info->element_name, NULL);
while (wocky_node_iter_next (&i, &node))
{
- const gchar *value;
- const gchar *new_value;
-
/* if there are >= 2 copies of this field, we're going to reduce that
* to 1 */
if (seen)
return TRUE;
- /* consider NULL and "" to be different representations for the
- * same thing */
- value = node->content;
- new_value = info->element_value;
-
- if (value == NULL)
- value = "";
+ seen = TRUE;
- if (new_value == NULL)
- new_value = "";
-
- if (tp_strdiff (value, new_value))
+ /* This depends on PHOTO's children being TYPE, BINVAL in the correct
+ * order—which is required by the vcard-temp schema, soooo...
+ */
+ if (!wocky_node_equal (node, replacement_node))
return TRUE;
-
- /* we assume that a change to child nodes is always significant,
- * unless it's the <PHOTO/> */
- if (!tp_strdiff (node->name, "PHOTO"))
- {
- /* For the special case of PHOTO, we know that the child nodes
- * are only meant to appear once, so we can be more aggressive
- * about avoiding unnecessary edits: assume that the PHOTO on
- * the server doesn't have extra children, and that one matching
- * child is enough. */
- GList *child_iter;
-
- for (child_iter = info->children;
- child_iter != NULL;
- child_iter = child_iter->next)
- {
- GabbleVCardChild *child = child_iter->data;
- WockyNode *child_node = wocky_node_get_child (node,
- child->key);
-
- if (child_node == NULL ||
- tp_strdiff (child_node->content,
- child->value))
- {
- return TRUE;
- }
- }
- }
- else
- {
- if (info->children != NULL)
- return TRUE;
- }
}
/* if there are no copies of this field, we're going to add one; otherwise,
@@ -1083,76 +983,38 @@ gabble_vcard_manager_replace_is_significant (GabbleVCardManagerEditInfo *info,
return !seen;
}
-static WockyNode *vcard_copy (WockyNode *parent, WockyNode *src,
- const gchar *exclude, gboolean *exclude_mattered);
-
-static WockyStanza *
-gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info,
- WockyNode *old_vcard,
- GabbleVCardManager *vcard_manager)
+static gboolean
+remove_all_children_named (
+ WockyNode *node,
+ const gchar *name)
{
- WockyStanza *msg;
- WockyNode *vcard_node;
- WockyNode *node;
- GList *iter;
- gboolean maybe_changed = FALSE;
- GabbleConnection *conn = vcard_manager->priv->connection;
- TpBaseConnection *base = (TpBaseConnection *) conn;
+ WockyNodeIter iter;
+ gboolean changed = FALSE;
- if (info->edit_type == GABBLE_VCARD_EDIT_SET_ALIAS)
+ wocky_node_iter_init (&iter, node, name, NULL);
+ while (wocky_node_iter_next (&iter, NULL))
{
- /* SET_ALIAS is shorthand for a REPLACE operation or nothing */
-
- g_assert (info->element_name == NULL);
-
- if (gabble_vcard_manager_can_use_vcard_field (vcard_manager, "NICKNAME"))
- {
- info->element_name = g_strdup ("NICKNAME");
- }
- else
- {
- /* Google Talk servers won't let us set a NICKNAME; recover by
- * setting the FN */
- info->element_name = g_strdup ("FN");
- }
-
- if (info->element_value == NULL)
- {
- /* We're just trying to fix a possibly-incomplete SetContactInfo() -
- * */
- gchar *alias;
-
- node = wocky_node_get_child (old_vcard, info->element_name);
-
- /* If the user has set this field explicitly via SetContactInfo(),
- * that takes precedence */
- if (node != NULL)
- return NULL;
-
- if (_gabble_connection_get_cached_alias (conn, base->self_handle,
- &alias) < GABBLE_CONNECTION_ALIAS_FROM_VCARD)
- {
- /* not good enough to want to put it in the vCard */
- g_free (alias);
- return NULL;
- }
+ wocky_node_iter_remove (&iter);
+ changed = TRUE;
+ }
- info->element_value = alias;
- }
+ return changed;
+}
- info->edit_type = GABBLE_VCARD_EDIT_REPLACE;
- }
+static gboolean
+gabble_vcard_manager_edit_info_apply_replace (
+ GabbleVCardManagerEditInfo *info,
+ WockyNode *vcard_node,
+ GabbleVCardManager *vcard_manager)
+{
+ g_return_val_if_fail (info->edit_type == GABBLE_VCARD_EDIT_REPLACE, FALSE);
- if (info->edit_type == GABBLE_VCARD_EDIT_APPEND ||
- info->edit_type == GABBLE_VCARD_EDIT_REPLACE)
+ if (!gabble_vcard_manager_can_use_vcard_field (vcard_manager,
+ info->element_name))
{
- if (!gabble_vcard_manager_can_use_vcard_field (vcard_manager,
- info->element_name))
- {
- DEBUG ("ignoring vcard node %s because this server doesn't "
- "support it", info->element_name);
- return NULL;
- }
+ DEBUG ("ignoring vcard node %s because this server doesn't "
+ "support it", info->element_name);
+ return FALSE;
}
/* A special case for replacing one field with another: we detect no-op
@@ -1160,156 +1022,177 @@ gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info,
* frequently (on every login), and as well as wasting bandwidth, setting
* the vCard too often can cause a memory leak in OpenFire (see fd.o#25341).
*/
- if (info->edit_type == GABBLE_VCARD_EDIT_REPLACE &&
- ! gabble_vcard_manager_replace_is_significant (info, old_vcard))
+ if (! gabble_vcard_manager_replace_is_significant (info, vcard_node))
{
DEBUG ("ignoring no-op vCard %s replacement", info->element_name);
- return NULL;
+ return FALSE;
}
- msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
- NULL, NULL, NULL);
+ remove_all_children_named (vcard_node, info->element_name);
+ wocky_node_add_node_tree (vcard_node, info->element);
+
+ return TRUE;
+}
- if (info->edit_type == GABBLE_VCARD_EDIT_CLEAR)
+static gboolean
+gabble_vcard_manager_edit_info_apply_append (
+ GabbleVCardManagerEditInfo *info,
+ WockyNode *vcard_node,
+ GabbleVCardManager *vcard_manager)
+{
+ if (!gabble_vcard_manager_can_use_vcard_field (vcard_manager,
+ info->element_name))
{
- /* start from a clean slate... */
- vcard_node = wocky_node_add_child_with_content (
- wocky_stanza_get_top_node (msg), "vCard", "");
- vcard_node->ns = g_quark_from_string ("vcard-temp");
+ DEBUG ("ignoring vcard node %s because this server doesn't "
+ "support it", info->element_name);
+ return FALSE;
+ }
- /* ... but as a special case, the photo gets copied in from the old
- * vCard, because SetContactInfo doesn't touch photos */
- node = wocky_node_get_child (old_vcard, "PHOTO");
+ wocky_node_add_node_tree (vcard_node, info->element);
- if (node != NULL)
- vcard_copy (vcard_node, node, NULL, NULL);
+ return TRUE;
+}
+
+static gboolean
+gabble_vcard_manager_edit_info_apply_delete (
+ GabbleVCardManagerEditInfo *info,
+ WockyNode *vcard_node,
+ GabbleVCardManager *vcard_manager)
+{
+ return remove_all_children_named (vcard_node, info->element_name);
+}
+
+static gboolean
+gabble_vcard_manager_edit_info_apply_clear (
+ GabbleVCardManagerEditInfo *info,
+ WockyNode *vcard_node,
+ GabbleVCardManager *vcard_manager)
+{
+ /* Blow almost everything away! As a special case, the photo gets left in
+ * place from the old vCard, because SetContactInfo doesn't touch
+ * photos, and CLEAR is only used by SetContactInfo */
+ WockyNodeIter iter;
+ WockyNode *node;
+ gboolean changed = FALSE;
- /* Yes, we can do this: "WockyNode" is really a WockyNode */
- if (wocky_node_equal (old_vcard, vcard_node))
+ wocky_node_iter_init (&iter, vcard_node, NULL, NULL);
+ while (wocky_node_iter_next (&iter, &node))
+ {
+ if (tp_strdiff (node->name, "PHOTO"))
{
- /* nothing actually happened, forget it */
- g_object_unref (msg);
- return NULL;
+ wocky_node_iter_remove (&iter);
+ changed = TRUE;
}
-
- return msg;
}
- if (info->edit_type == GABBLE_VCARD_EDIT_APPEND)
+ return changed;
+}
+
+/* SET_ALIAS is shorthand for a REPLACE operation or nothing */
+static gboolean
+gabble_vcard_manager_edit_info_apply_set_alias (
+ GabbleVCardManagerEditInfo *info,
+ WockyNode *old_vcard,
+ GabbleVCardManager *vcard_manager)
+{
+ GabbleConnection *conn = vcard_manager->priv->connection;
+ TpBaseConnection *base = (TpBaseConnection *) conn;
+
+ g_assert (info->element_name == NULL);
+
+ if (gabble_vcard_manager_can_use_vcard_field (vcard_manager, "NICKNAME"))
{
- /* appending: keep all child nodes */
- vcard_node = vcard_copy (
- wocky_stanza_get_top_node (msg), old_vcard, NULL, NULL);
+ info->element_name = g_strdup ("NICKNAME");
}
else
{
- /* replacing or deleting: exclude all matching child nodes from
- * copying */
- vcard_node = vcard_copy (
- wocky_stanza_get_top_node (msg), old_vcard, info->element_name,
- &maybe_changed);
+ /* Google Talk servers won't let us set a NICKNAME; recover by
+ * setting the FN */
+ info->element_name = g_strdup ("FN");
}
- if (info->edit_type != GABBLE_VCARD_EDIT_DELETE)
+ if (info->new_alias == NULL)
{
- maybe_changed = TRUE;
+ /* We're just trying to fix a possibly-incomplete SetContactInfo() */
+ WockyNode *node = wocky_node_get_child (old_vcard, info->element_name);
+ gchar *alias;
- node = wocky_node_add_child_with_content (vcard_node,
- info->element_name, info->element_value);
+ /* If the user has set this field explicitly via SetContactInfo(),
+ * that takes precedence */
+ if (node != NULL)
+ return FALSE;
- for (iter = info->children; iter != NULL; iter = iter->next)
+ if (_gabble_connection_get_cached_alias (conn,
+ tp_base_connection_get_self_handle (base),
+ &alias) < GABBLE_CONNECTION_ALIAS_FROM_VCARD)
{
- GabbleVCardChild *child = iter->data;
-
- wocky_node_add_child_with_content (node, child->key, child->value);
+ /* not good enough to want to put it in the vCard */
+ g_free (alias);
+ return FALSE;
}
- }
- if ((!maybe_changed) || wocky_node_equal (old_vcard, vcard_node))
- {
- /* nothing actually happened, forget it */
- g_object_unref (msg);
- return NULL;
+ info->new_alias = alias;
}
- return msg;
+ info->element = wocky_node_tree_new (info->element_name, NS_VCARD_TEMP,
+ '$', info->new_alias, NULL);
+ info->edit_type = GABBLE_VCARD_EDIT_REPLACE;
+ return gabble_vcard_manager_edit_info_apply_replace (info, old_vcard,
+ vcard_manager);
}
-/* Loudmouth hates me. The feelings are mutual.
- *
- * Note that this function doesn't copy any attributes other than
- * xmlns, because LM provides no way to iterate over attributes. Thanks, LM. */
-static WockyNode *
-vcard_copy (WockyNode *parent,
- WockyNode *src,
- const gchar *exclude,
- gboolean *exclude_mattered)
-{
- WockyNode *new = wocky_node_add_child_with_content (parent, src->name,
- src->content);
- const gchar *xmlns;
- WockyNodeIter i;
- WockyNode *child;
-
- xmlns = wocky_node_get_ns (src);
- if (xmlns != NULL)
- new->ns = g_quark_from_string (xmlns);
-
- wocky_node_iter_init (&i, src, NULL, NULL);
- while (wocky_node_iter_next (&i, &child))
- {
-
- if (tp_strdiff (child->name, exclude))
- {
- vcard_copy (new, child, NULL, NULL);
- }
- else
- {
- if (exclude_mattered != NULL)
- *exclude_mattered = TRUE;
- }
- }
+typedef gboolean (*EditFunction) (
+ GabbleVCardManagerEditInfo *info,
+ WockyNode *vcard_node,
+ GabbleVCardManager *vcard_manager);
+
+static const EditFunction edit_functions[] = {
+ gabble_vcard_manager_edit_info_apply_replace,
+ gabble_vcard_manager_edit_info_apply_append,
+ gabble_vcard_manager_edit_info_apply_delete,
+ gabble_vcard_manager_edit_info_apply_clear,
+ gabble_vcard_manager_edit_info_apply_set_alias,
+};
- return new;
+static gboolean
+gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info,
+ WockyNode *vcard_node,
+ GabbleVCardManager *vcard_manager)
+{
+ return edit_functions[info->edit_type] (info, vcard_node, vcard_manager);
}
static void
manager_patch_vcard (GabbleVCardManager *self,
- WockyNode *vcard_node)
+ WockyNode *old_vcard_node)
{
GabbleVCardManagerPrivate *priv = self->priv;
- WockyStanza *msg = NULL;
+ WockyNodeTree *vcard_node_tree;
+ WockyNode *vcard_node;
+ WockyStanza *msg;
GList *li;
+ gboolean changed = FALSE;
/* Bail out if we don't have outstanding edits to make, or if we already
* have a set request in progress.
*/
if (priv->edits == NULL || priv->edit_pipeline_item != NULL)
- return;
+ return;
+
+ vcard_node_tree = wocky_node_tree_new_from_node (old_vcard_node);
+ vcard_node = wocky_node_tree_get_top_node (vcard_node_tree);
/* Apply any unsent edits to the patched vCard */
for (li = priv->edits; li != NULL; li = li->next)
{
- WockyStanza *new_msg = gabble_vcard_manager_edit_info_apply (
- li->data, vcard_node, self);
-
- /* edit_info_apply returns NULL if nothing happened */
- if (new_msg == NULL)
- continue;
-
- tp_clear_pointer (&msg, g_object_unref);
-
- msg = new_msg;
- /* gabble_vcard_manager_edit_info_apply always returns an IQ message
- * with one vCard child */
- vcard_node = wocky_node_get_child (
- wocky_stanza_get_top_node (msg), "vCard");
- g_assert (vcard_node != NULL);
+ if (gabble_vcard_manager_edit_info_apply (li->data, vcard_node, self))
+ changed = TRUE;
}
- if (msg == NULL)
+ if (!changed)
{
DEBUG ("nothing really changed, not updating vCard");
+ g_clear_object (&vcard_node_tree);
goto out;
}
@@ -1318,7 +1201,11 @@ manager_patch_vcard (GabbleVCardManager *self,
/* We'll save the patched vcard, and if the server says
* we're ok, put it into the cache. But we want to leave the
* original vcard in the cache until that happens. */
- priv->patched_vcard = copy_node (vcard_node);
+ priv->patched_vcard = vcard_node_tree;
+
+ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
+ NULL, NULL, NULL);
+ wocky_node_add_node_tree (wocky_stanza_get_top_node (msg), vcard_node_tree);
priv->edit_pipeline_item = gabble_request_pipeline_enqueue (
priv->connection->req_pipeline, msg, default_request_timeout,
@@ -1425,7 +1312,8 @@ pipeline_reply_cb (GabbleConnection *conn,
/* If request for our own vCard failed, and we do have
* pending edits to make, cancel those and return error
* to the user */
- if (entry->handle == base->self_handle && priv->edits != NULL)
+ if (entry->handle == tp_base_connection_get_self_handle (base) &&
+ priv->edits != NULL)
{
/* We won't have a chance to apply those, might as well forget them */
g_list_foreach (priv->edits,
@@ -1452,14 +1340,13 @@ pipeline_reply_cb (GabbleConnection *conn,
DEBUG ("successful lookup response contained no <vCard> node, "
"creating an empty one");
- vcard_node = wocky_node_add_child_with_content (
+ vcard_node = wocky_node_add_child_ns (
wocky_stanza_get_top_node (reply_msg), "vCard",
- NULL);
- vcard_node->ns = g_quark_from_string (NS_VCARD_TEMP);
+ NS_VCARD_TEMP);
}
/* Put the message in the cache */
- entry->vcard_node = copy_node (vcard_node);
+ entry->vcard_node = wocky_node_tree_new_from_node (vcard_node);
entry->expires = time (NULL) + VCARD_CACHE_ENTRY_TTL;
tp_heap_add (priv->timed_cache, entry);
@@ -1475,7 +1362,7 @@ pipeline_reply_cb (GabbleConnection *conn,
/* We have freshly updated cache for our vCard, edit it if
* there are any pending edits and no outstanding set request.
*/
- if (entry->handle == base->self_handle)
+ if (entry->handle == tp_base_connection_get_self_handle (base))
{
manager_patch_vcard (self, vcard_node);
}
@@ -1523,7 +1410,7 @@ request_send (GabbleVCardManagerRequest *request, guint timeout)
request->timer_id =
g_timeout_add_seconds (request->timeout, timeout_request, request);
- if (entry->handle == base->self_handle)
+ if (entry->handle == tp_base_connection_get_self_handle (base))
{
DEBUG ("Cache entry %p is my own, not setting @to", entry);
jid = NULL;
@@ -1576,14 +1463,14 @@ gabble_vcard_manager_request (GabbleVCardManager *self,
GObject *object)
{
GabbleVCardManagerPrivate *priv = self->priv;
- TpBaseConnection *connection = (TpBaseConnection *) priv->connection;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- connection, TP_HANDLE_TYPE_CONTACT);
+ TpBaseConnection *base = (TpBaseConnection *) priv->connection;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base,
+ TP_HANDLE_TYPE_CONTACT);
GabbleVCardManagerRequest *request;
GabbleVCardCacheEntry *entry = cache_entry_get (self, handle);
- g_return_val_if_fail (connection->status == TP_CONNECTION_STATUS_CONNECTED,
- NULL);
+ g_return_val_if_fail (tp_base_connection_get_status (base) ==
+ TP_CONNECTION_STATUS_CONNECTED, NULL);
g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), NULL);
g_assert (entry->vcard_node == NULL);
@@ -1630,20 +1517,22 @@ gabble_vcard_manager_edit (GabbleVCardManager *self,
GabbleVCardManagerEditRequest *req;
GabbleVCardCacheEntry *entry;
- g_return_val_if_fail (base->status == TP_CONNECTION_STATUS_CONNECTED, NULL);
+ g_return_val_if_fail (tp_base_connection_get_status (base) ==
+ TP_CONNECTION_STATUS_CONNECTED, NULL);
/* Invalidate our current vCard and ensure that we're going to get
* it in the near future */
DEBUG ("called; invalidating cache");
- gabble_vcard_manager_invalidate_cache (self, base->self_handle);
+ gabble_vcard_manager_invalidate_cache (self,
+ tp_base_connection_get_self_handle (base));
DEBUG ("checking if we have pending requests already");
- entry = cache_entry_get (self, base->self_handle);
+ entry = cache_entry_get (self, tp_base_connection_get_self_handle (base));
if (!priv->edit_pipeline_item && !entry->pending_requests)
{
DEBUG ("we don't, create one");
/* create dummy GET request if neccessary */
- gabble_vcard_manager_request (self, base->self_handle, 0, NULL,
- NULL, NULL);
+ gabble_vcard_manager_request (self,
+ tp_base_connection_get_self_handle (base), 0, NULL, NULL, NULL);
}
priv->edits = g_list_concat (priv->edits, edits);
@@ -1745,7 +1634,7 @@ gabble_vcard_manager_get_cached (GabbleVCardManager *self,
return FALSE;
if (node != NULL)
- *node = entry->vcard_node;
+ *node = wocky_node_tree_get_top_node (entry->vcard_node);
return TRUE;
}
@@ -1826,36 +1715,49 @@ gabble_vcard_manager_edit_info_new (const gchar *element_name,
{
GabbleVCardManagerEditInfo *info;
va_list ap;
- const gchar *key;
- const gchar *value;
-
- if (edit_type == GABBLE_VCARD_EDIT_DELETE)
- {
- const gchar *first_edit = NULL;
- g_return_val_if_fail (element_value == NULL, NULL);
-
- va_start (ap, edit_type);
- first_edit = va_arg (ap, const gchar *);
- va_end (ap);
- g_return_val_if_fail (first_edit == NULL, NULL);
- }
-
- info = g_slice_new (GabbleVCardManagerEditInfo);
+ info = g_slice_new0 (GabbleVCardManagerEditInfo);
info->element_name = g_strdup (element_name);
- info->element_value = g_strdup (element_value);
info->edit_type = edit_type;
- info->children = NULL;
va_start (ap, edit_type);
- while ((key = va_arg (ap, const gchar *)))
+ switch (edit_type)
{
- value = va_arg (ap, const gchar *);
- gabble_vcard_manager_edit_info_add_child (info, key, value);
- }
+ case GABBLE_VCARD_EDIT_REPLACE:
+ case GABBLE_VCARD_EDIT_APPEND:
+ g_return_val_if_fail (element_name != NULL, NULL);
+
+ info->element = wocky_node_tree_new_va (element_name, NS_VCARD_TEMP,
+ ap);
+ va_end (ap);
- va_end (ap);
+ if (element_value != NULL)
+ wocky_node_set_content (wocky_node_tree_get_top_node (info->element),
+ element_value);
+
+ break;
+
+ case GABBLE_VCARD_EDIT_SET_ALIAS:
+ g_return_val_if_fail (element_name == NULL, NULL);
+
+ info->new_alias = g_strdup (element_value);
+ element_value = NULL;
+
+ /* deliberate fall-through to check the varargs... */
+ case GABBLE_VCARD_EDIT_DELETE:
+ case GABBLE_VCARD_EDIT_CLEAR:
+ {
+ const gchar *first_edit = NULL;
+
+ g_return_val_if_fail (element_value == NULL, NULL);
+
+ first_edit = va_arg (ap, const gchar *);
+ va_end (ap);
+ g_return_val_if_fail (first_edit == NULL, NULL);
+ break;
+ }
+ }
return info;
}
@@ -1866,17 +1768,19 @@ gabble_vcard_manager_edit_info_add_child (
const gchar *key,
const gchar *value)
{
- edit_info->children = g_list_append (edit_info->children,
- gabble_vcard_child_new (key, value));
+ g_return_if_fail (edit_info->element != NULL);
+
+ wocky_node_add_child_with_content (
+ wocky_node_tree_get_top_node (edit_info->element),
+ key, value);
}
void
gabble_vcard_manager_edit_info_free (GabbleVCardManagerEditInfo *info)
{
g_free (info->element_name);
- g_free (info->element_value);
- g_list_foreach (info->children, (GFunc) gabble_vcard_child_free, NULL);
- g_list_free (info->children);
+ g_free (info->new_alias);
+ g_clear_object (&info->element);
g_slice_free (GabbleVCardManagerEditInfo, info);
}
@@ -1897,10 +1801,11 @@ gabble_vcard_manager_can_use_vcard_field (GabbleVCardManager *self,
if (self->priv->connection->features &
GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER)
{
- /* Google's server only allows N, FN and PHOTO */
+ /* Google's server only allows N, FN, PHOTO and URL */
if (tp_strdiff (field_name, "N") &&
tp_strdiff (field_name, "FN") &&
- tp_strdiff (field_name, "PHOTO"))
+ tp_strdiff (field_name, "PHOTO") &&
+ tp_strdiff (field_name, "URL"))
{
return FALSE;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2d2860e08..c97e5d114 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,7 +1,6 @@
SUBDIRS = twisted suppressions
tests_list = \
- test-base64 \
test-dtube-unique-names \
test-gabble-idle-weak \
test-handles \
@@ -53,7 +52,6 @@ check-valgrind: $(TESTS)
check_c_sources = \
$(dbus_test_sources) \
- test-base64.c \
test-dtube-unique-names.c \
test-presence.c \
test-jid-decode.c \
diff --git a/tests/README b/tests/README
index 6f96f0b23..7cbb7277a 100644
--- a/tests/README
+++ b/tests/README
@@ -77,6 +77,11 @@ To debug an individual test you can set one of the following env variable:
bus daemon. The logs are saved to tools/*bustle-logs.
export GABBLE_TEST_BUSTLE=1
+ * GABBLE_NODELAY : to run any Gabble test with TCP_NODELAY set on
+ both Wocky and Twisted's socket. This can speed up tests
+ significantly.
+ export GABBLE_NODELAY=1
+
== Jingle tests ==
Various jingle tests run the same tests with different dialects. To only test
diff --git a/tests/test-base64.c b/tests/test-base64.c
deleted file mode 100644
index 49ebbf37d..000000000
--- a/tests/test-base64.c
+++ /dev/null
@@ -1,106 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include <glib-object.h>
-
-#include "src/base64.h"
-
-struct test {
- gchar *str;
- size_t len;
- gchar *encoded;
-};
-
-struct test tests[] = {
- { "c", 0, "Yw==" },
- { "ca", 0, "Y2E=" },
- { "car", 0, "Y2Fy" },
- { "carnal pleasure.", 0, "Y2FybmFsIHBsZWFzdXJlLg==" },
- { "carnal pleasure", 0, "Y2FybmFsIHBsZWFzdXJl" },
- { "carnal pleasur", 0, "Y2FybmFsIHBsZWFzdXI=" },
- { "carnal pleasu", 0, "Y2FybmFsIHBsZWFzdQ==" },
- /* test long (> 76 / 4 * 3) string */
- {
- "1234567890"
- "1234567890"
- "1234567890"
- "1234567890"
- "1234567890"
- "1234567890",
- 0,
- "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM"
- "0NTY3\nODkw" },
- /* regression test: formerly we assumed that there was a NUL immediately
- * after the data */
- { "hello", 5, "aGVsbG8=" },
- { "hello\xff\xff", 5, "aGVsbG8=" },
-
- { NULL, 0, NULL }
-};
-
-int
-main (void)
-{
- gchar *s;
- GString *tmp1, *tmp2;
- struct test *t;
-
- g_type_init ();
-
- for (t = tests; t->str != NULL; t++)
- {
- if (t->len == 0)
- t->len = strlen (t->str);
- s = base64_encode (t->len, t->str, TRUE);
- g_assert (0 == strcmp (s, t->encoded));
- g_free (s);
- }
-
- /* 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 (tmp1);
- 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_len (t->str, t->len);
- g_assert (g_string_equal (tmp1, tmp2));
- g_string_free (tmp1, TRUE);
- g_string_free (tmp2, TRUE);
- }
-
- return 0;
-}
-
diff --git a/tests/test-handles.c b/tests/test-handles.c
index 7439a6882..a0d60be49 100644
--- a/tests/test-handles.c
+++ b/tests/test-handles.c
@@ -4,9 +4,8 @@
#include <string.h>
#include <glib.h>
#include <glib-object.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/errors.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#include "src/connection.h"
@@ -65,9 +64,6 @@ test_handles (guint handle_type)
return_jid = tp_handle_inspect (tp_repo, handle);
g_assert (!strcmp (return_jid, jid));
- /* Now unref it */
- tp_handle_unref (tp_repo, handle);
-
for (i = 0; i < NUM_TP_HANDLE_TYPES; i++)
{
if (repos[i])
diff --git a/tests/tp-error-from-wocky.c b/tests/tp-error-from-wocky.c
index 207ec5952..729af31a4 100644
--- a/tests/tp-error-from-wocky.c
+++ b/tests/tp-error-from-wocky.c
@@ -19,7 +19,7 @@ test_remap (GQuark domain,
&conn_reason, &error);
g_assert (error != NULL);
g_assert_cmpstr (g_quark_to_string (error->domain), ==,
- g_quark_to_string (TP_ERRORS));
+ g_quark_to_string (TP_ERROR));
g_assert_cmpint (error->code, ==, exp_code);
g_assert_cmpint (conn_reason, ==, exp_reason);
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index ae24bd110..fdc6d612a 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -113,6 +113,7 @@ TWISTED_TESTS = \
text/facebook-own-message.py \
text/initiate.py \
text/initiate-requestotron.py \
+ text/receipts.py \
text/respawn.py \
text/send-error.py \
text/send-to-correct-resource.py \
@@ -132,10 +133,8 @@ TWISTED_TUBE_TESTS = \
tubes/accept-private-stream-tube.py \
tubes/check-create-tube-return.py \
tubes/close-muc-with-closed-tube.py \
- tubes/crash-on-list-channels.py \
tubes/create-invalid-tube-channels.py \
tubes/ensure-si-tube.py \
- tubes/muc-presence.py \
tubes/offer-muc-dbus-tube.py \
tubes/offer-muc-stream-tube.py \
tubes/offer-no-caps.py \
@@ -147,12 +146,14 @@ TWISTED_TUBE_TESTS = \
$(NULL)
TWISTED_VCARD_TESTS = \
+ vcard/clear-avatar.py \
vcard/disconnect-during-pep.py \
vcard/get-contact-info.py \
vcard/item-not-found.py \
vcard/overlapping-sets.py \
vcard/redundant-set.py \
vcard/refresh-contact-info.py \
+ vcard/set-avatar.py \
vcard/set-contact-info.py \
vcard/set-set-disconnect.py \
vcard/supported-fields.py \
@@ -217,6 +218,7 @@ TWISTED_JINGLE_TESTS = \
jingle/test-wait-for-caps-incomplete.py \
jingle/test-wait-for-caps.py \
jingle/transport-info-parsing.py \
+ jingle/unknown-session.py \
$(NULL)
TWISTED_FT_TESTS = \
@@ -263,12 +265,12 @@ TWISTED_OTHER_FILES = \
jingle/callutils.py \
jingle/__init__.py \
jingle/jingletest2.py \
- jingle/jingletest.py \
jingle-share/file_transfer_helper.py \
jingle-share/jingleshareutils.py \
mucutil.py \
ns.py \
olpc/util.py \
+ presence/__init__.py \
presence/invisible_helper.py \
rostertest.py \
sasl/saslutil.py \
@@ -276,7 +278,6 @@ TWISTED_OTHER_FILES = \
test-helper.py \
tls-cert.pem \
tls-key.pem \
- tubes/muctubeutil.py \
tubes/tubetestutil.py \
$(NULL)
diff --git a/tests/twisted/caps/advertise-contact-caps.py b/tests/twisted/caps/advertise-contact-caps.py
index 9200e1626..ab40277fd 100644
--- a/tests/twisted/caps/advertise-contact-caps.py
+++ b/tests/twisted/caps/advertise-contact-caps.py
@@ -2,6 +2,7 @@
Test UpdateCapabilities.
"""
+from functools import partial
import dbus
from twisted.words.xish import xpath, domish
@@ -247,14 +248,20 @@ def run_mixed_test (q, bus, conn, stream):
check_caps(namespaces, JINGLE_CAPS)
if __name__ == '__main__':
- exec_test(lambda q, b, c, s:
- run_test (q, b, c, s,
- cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.CHANNEL_IFACE_MEDIA_SIGNALLING,
- cs.INITIAL_AUDIO, cs.INITIAL_VIDEO), do_connect=False)
+ exec_test(
+ partial(run_test,
+ media_channel_type=cs.CHANNEL_TYPE_STREAMED_MEDIA,
+ media_interface=cs.CHANNEL_IFACE_MEDIA_SIGNALLING,
+ initial_audio=cs.INITIAL_AUDIO,
+ initial_video=cs.INITIAL_VIDEO),
+ do_connect=False)
- exec_test(lambda q, b, c, s:
- run_test (q, b, c, s,
- cs.CHANNEL_TYPE_CALL, cs.CHANNEL_TYPE_CALL,
- cs.CALL_INITIAL_AUDIO, cs.CALL_INITIAL_VIDEO), do_connect=False)
+ exec_test(
+ partial(run_test,
+ media_channel_type=cs.CHANNEL_TYPE_CALL,
+ media_interface=cs.CHANNEL_TYPE_CALL,
+ initial_audio=cs.CALL_INITIAL_AUDIO,
+ initial_video=cs.CALL_INITIAL_VIDEO),
+ do_connect=False)
exec_test(run_mixed_test, do_connect=False)
diff --git a/tests/twisted/caps/jingle-caps.py b/tests/twisted/caps/jingle-caps.py
index 0ab26c6f6..42f69cf1d 100644
--- a/tests/twisted/caps/jingle-caps.py
+++ b/tests/twisted/caps/jingle-caps.py
@@ -4,14 +4,16 @@ and/or video capable
"""
from functools import partial
+from itertools import permutations
from gabbletest import exec_test, make_presence, sync_stream
from servicetest import (
- assertContains, assertEquals, EventPattern, make_channel_proxy
+ assertContains, assertDoesNotContain, assertEquals, EventPattern,
+ make_channel_proxy
)
import constants as cs
import ns
-from caps_helper import presence_and_disco, compute_caps_hash
+from caps_helper import presence_and_disco, compute_caps_hash, send_presence
from jingle.jingletest2 import JingleTest2, JingleProtocol031
from config import VOIP_ENABLED
@@ -197,6 +199,49 @@ def test_prefer_phones(q, bus, conn, stream, expect_disco):
# ...then calls should go there, even though the laptop is more available.
make_call(expected_recipient=phone_jid)
+def test_google_caps(q, bus, conn, stream):
+ i = 1
+
+ # we want to make sure all permutations of voice-v1 and video-v1
+ # result in the correct caps, so let's do exactly that.
+ for j in (1, 2):
+ for ext_set in permutations(['voice-v1', 'video-v1'], j):
+ jid = 'larry%s@page/mountainview' % i
+ i += 1
+
+ # order of these ext values shouldn't matter
+ gcaps = { 'node': 'blahblahthiskeepsonchanging',
+ 'ver': '1.1',
+ 'ext': ' '.join(ext_set) }
+
+ handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0]
+
+ send_presence(q, conn, stream, jid, gcaps, initial=True)
+
+ e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged',
+ predicate=lambda e: handle in e.args[0])
+
+ assertEquals(1, len(e.args[0]))
+ rccs = e.args[0][handle]
+
+ found = False
+ for fixed, allowed in rccs:
+ if fixed[cs.CHANNEL_TYPE] != cs.CHANNEL_TYPE_CALL:
+ continue
+
+ # we should only have InitialAudio or InitialVideo if
+ # voice-v1 or video-v1 is present respectively
+ for a, b in [('voice-v1' in ext_set, cs.CALL_INITIAL_AUDIO),
+ ('video-v1' in ext_set, cs.CALL_INITIAL_VIDEO)]:
+ if a:
+ assertContains(b, allowed)
+ else:
+ assertDoesNotContain(b, allowed)
+
+ found = True
+
+ assert found
+
if __name__ == '__main__':
exec_test(test)
@@ -204,3 +249,5 @@ if __name__ == '__main__':
# And again, this time pulling the caps from the cache. This tests that the
# quirk is cached!
exec_test(partial(test_prefer_phones, expect_disco=False))
+
+ exec_test(test_google_caps)
diff --git a/tests/twisted/cm/protocol.py b/tests/twisted/cm/protocol.py
index 3320bfb22..e9c0b1c3b 100644
--- a/tests/twisted/cm/protocol.py
+++ b/tests/twisted/cm/protocol.py
@@ -53,7 +53,10 @@ def test(q, bus, conn, stream):
'hidden' : (cs.PRESENCE_HIDDEN, True, True)}
presences = proto_prop_iface.Get(cs.PROTOCOL_IFACE_PRESENCES, 'Statuses');
- assertEquals(expected_status, unwrap(presences))
+ # Plugins could add additional statuses, so we check if expected_status is
+ # included in presences rather than equality.
+ for k, v in expected_status.iteritems():
+ assertEquals(expected_status[k], unwrap(presences[k]))
# (Only) 'account' is mandatory for IdentifyAccount()
call_async(q, proto_iface, 'IdentifyAccount', {})
diff --git a/tests/twisted/console.py b/tests/twisted/console.py
index f6a6336c9..95c76a30e 100644
--- a/tests/twisted/console.py
+++ b/tests/twisted/console.py
@@ -9,6 +9,7 @@ from servicetest import (
from gabbletest import exec_test, acknowledge_iq, elem, elem_iq
from config import PLUGINS_ENABLED
from twisted.words.xish import domish
+import ns
CONSOLE_PLUGIN_IFACE = "org.freedesktop.Telepathy.Gabble.Plugin.Console"
STACY = 'stacy@pilgrim.lit'
@@ -77,10 +78,15 @@ def test(q, bus, conn, stream):
</message>''' % { 'stacy': STACY })
e = q.expect('stream-message', to=STACY, message_type='headline')
- # Wocky fills in xmlns='' for us if we don't specify a namespace... great.
- # So this means <message/> gets sent as <message xmlns=''/> and the server
- # kicks us off.
- assertNotEquals('', e.stanza.uri)
+
+ # Make sure that Wocky has filled in the jabber:client namespace we
+ # carelessly omitted.
+ message = e.stanza
+ assertEquals('message', message.name)
+ assertEquals(ns.CLIENT, message.uri)
+ body = message.firstChildElement()
+ assertEquals('body', body.name)
+ assertEquals(ns.CLIENT, body.uri)
if __name__ == '__main__':
exec_test(test)
diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py
index 0ea9d5b7f..d541c75fe 100644
--- a/tests/twisted/constants.py
+++ b/tests/twisted/constants.py
@@ -463,6 +463,20 @@ MT_NOTICE = 2
MT_AUTO_REPLY = 3
MT_DELIVERY_REPORT = 4
+class MessageFlag(object):
+ TRUNCATED = 1
+ NON_TEXT_CONTENT = 2
+ SCROLLBACK = 4
+ RESCUED = 8
+
+class SendError(object):
+ UNKNOWN = 0
+ OFFLINE = 1
+ INVALID_CONTACT = 2
+ PERMISSION_DENIED = 3
+ TOO_LONG = 4
+ NOT_IMPLEMENTED = 5
+
PROTOCOL = 'org.freedesktop.Telepathy.Protocol'
PROTOCOL_IFACE_PRESENCES = PROTOCOL + '.Interface.Presence'
PROTOCOL_IFACE_ADDRESSING = PROTOCOL + '.Interface.Addressing'
diff --git a/tests/twisted/file-transfer/file_transfer_helper.py b/tests/twisted/file-transfer/file_transfer_helper.py
index 4b72379da..79b3acf92 100644
--- a/tests/twisted/file-transfer/file_transfer_helper.py
+++ b/tests/twisted/file-transfer/file_transfer_helper.py
@@ -5,7 +5,7 @@ import time
import datetime
import os
-from servicetest import EventPattern, assertEquals, call_async
+from servicetest import EventPattern, assertEquals, assertSameSets, call_async
from gabbletest import exec_test, sync_stream, make_result_iq
import ns
from bytestream import create_from_si_offer, announce_socks5_proxy
@@ -218,7 +218,10 @@ class ReceiveFileTest(FileTransferTest):
# check channel properties
# org.freedesktop.Telepathy.Channel D-Bus properties
assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER
- assert props[cs.INTERFACES] == []
+ assertSameSets(
+ [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA,
+ cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE',
+ ], props[cs.INTERFACES])
assert props[cs.TARGET_HANDLE] == self.handle
assert props[cs.TARGET_ID] == self.contact_name
assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT
@@ -408,7 +411,10 @@ class SendFileTest(FileTransferTest):
# org.freedesktop.Telepathy.Channel D-Bus properties
assertEquals(cs.CHANNEL_TYPE_FILE_TRANSFER, props[cs.CHANNEL_TYPE])
- assertEquals([], props[cs.INTERFACES])
+ assertSameSets(
+ [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA,
+ cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE',
+ ], props[cs.INTERFACES])
assertEquals(self.handle, props[cs.TARGET_HANDLE])
assertEquals(self.contact_name, props[cs.TARGET_ID])
assertEquals(cs.HT_CONTACT, props[cs.TARGET_HANDLE_TYPE])
diff --git a/tests/twisted/gabbletest.py b/tests/twisted/gabbletest.py
index aa63c6ddf..0985cd422 100644
--- a/tests/twisted/gabbletest.py
+++ b/tests/twisted/gabbletest.py
@@ -130,6 +130,7 @@ class JabberAuthenticator(GabbleAuthenticator):
def streamStarted(self, root=None):
if root:
self.xmlstream.sid = '%x' % random.randint(1, sys.maxint)
+ self.xmlstream.domain = root.getAttribute('to')
self.xmlstream.sendHeader()
self.xmlstream.addOnetimeObserver(
@@ -175,7 +176,7 @@ class JabberAuthenticator(GabbleAuthenticator):
if self.resource is not None:
assertEquals(self.resource, str(resource[0]))
- self.bare_jid = '%s@localhost' % self.username
+ self.bare_jid = '%s@%s' % (self.username, self.xmlstream.domain)
self.full_jid = '%s/%s' % (self.bare_jid, resource)
result = IQ(self.xmlstream, "result")
@@ -188,9 +189,12 @@ class XmppAuthenticator(GabbleAuthenticator):
GabbleAuthenticator.__init__(self, username, password, resource)
self.authenticated = False
+ self._mechanisms = ['PLAIN']
+
def streamInitialize(self, root):
if root:
self.xmlstream.sid = root.getAttribute('id')
+ self.xmlstream.domain = root.getAttribute('to')
if self.xmlstream.sid is None:
self.xmlstream.sid = '%x' % random.randint(1, sys.maxint)
@@ -212,7 +216,8 @@ class XmppAuthenticator(GabbleAuthenticator):
def streamSASL(self):
features = domish.Element((xmlstream.NS_STREAMS, 'features'))
mechanisms = features.addElement((ns.NS_XMPP_SASL, 'mechanisms'))
- mechanism = mechanisms.addElement('mechanism', content='PLAIN')
+ for mechanism in self._mechanisms:
+ mechanisms.addElement('mechanism', content=mechanism)
self.xmlstream.send(features)
self.xmlstream.addOnetimeObserver("/auth", self.auth)
@@ -245,7 +250,7 @@ class XmppAuthenticator(GabbleAuthenticator):
result = IQ(self.xmlstream, "result")
result["id"] = iq["id"]
bind = result.addElement((ns.NS_XMPP_BIND, 'bind'))
- self.bare_jid = '%s@localhost' % self.username
+ self.bare_jid = '%s@%s' % (self.username, self.xmlstream.domain)
self.full_jid = '%s/%s' % (self.bare_jid, resource)
jid = bind.addElement('jid', content=self.full_jid)
self.xmlstream.send(result)
@@ -397,6 +402,12 @@ class BaseXmlStream(xmlstream.XmlStream):
self.addObserver("/iq/query[@xmlns='%s']" % ns.PRIVACY,
self._cb_priv_list)
+ def connectionMade(self):
+ xmlstream.XmlStream.connectionMade(self)
+
+ if 'GABBLE_NODELAY' in os.environ:
+ self.transport.setTcpNoDelay(True)
+
def _cb_priv_list(self, iq):
send_error_reply(self, iq)
@@ -406,7 +417,7 @@ class BaseXmlStream(xmlstream.XmlStream):
assert self.authenticator.bare_jid is not None
self.addObserver(
- "/iq[@to='localhost']/query[@xmlns='http://jabber.org/protocol/disco#info']",
+ "/iq[@to='%s']/query[@xmlns='http://jabber.org/protocol/disco#info']" % self.domain,
self._cb_disco_iq)
self.addObserver(
"/iq[@to='%s']/query[@xmlns='http://jabber.org/protocol/disco#info']"
@@ -446,6 +457,10 @@ class BaseXmlStream(xmlstream.XmlStream):
# disconnect the TCP connection making tests as
# connect/disconnect-timeout.py not working
+ def connectionLost(self, reason):
+ self.event_func(servicetest.Event('stream-connection-lost'))
+ xmlstream.XmlStream.connectionLost(self, reason)
+
def send_stream_error(self, error='system-shutdown'):
# Yes, there are meant to be two different STREAMS namespaces.
go_away = \
@@ -540,17 +555,29 @@ def disconnect_conn(q, conn, stream, expected_before=[], expected_after=[]):
return before_events[:-2], after_events[:-1]
+def element_repr(element):
+ """__repr__ cannot safely return non-ASCII: see
+ <http://bugs.python.org/issue5876>. So we print non-ASCII characters as
+ \uXXXX escapes in debug output
+
+ """
+ return element.toXml().encode('unicode-escape')
+
def exec_test_deferred(fun, params, protocol=None, timeout=None,
authenticator=None, num_instances=1,
do_connect=True):
# hack to ease debugging
- domish.Element.__repr__ = domish.Element.toXml
+ domish.Element.__repr__ = element_repr
colourer = None
if sys.stdout.isatty() or 'CHECK_FORCE_COLOR' in os.environ:
colourer = servicetest.install_colourer()
- bus = dbus.SessionBus()
+ try:
+ bus = dbus.SessionBus()
+ except dbus.exceptions.DBusException as e:
+ print e
+ os._exit(1)
queue = servicetest.IteratingEventQueue(timeout)
queue.verbose = (
diff --git a/tests/twisted/jingle-share/file_transfer_helper.py b/tests/twisted/jingle-share/file_transfer_helper.py
index 2fe008795..19a45ca57 100644
--- a/tests/twisted/jingle-share/file_transfer_helper.py
+++ b/tests/twisted/jingle-share/file_transfer_helper.py
@@ -4,7 +4,7 @@ import hashlib
import time
import datetime
-from servicetest import EventPattern, TimeoutError, assertEquals, assertLength
+from servicetest import EventPattern, assertEquals, assertLength, assertSameSets
from gabbletest import exec_test, sync_stream, make_result_iq, elem_iq, elem
import ns
@@ -273,7 +273,10 @@ class ReceiveFileTest(FileTransferTest):
# check channel properties
# org.freedesktop.Telepathy.Channel D-Bus properties
assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER, props
- assert props[cs.INTERFACES] == [], props
+ assertSameSets(
+ [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA,
+ cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE',
+ ], props[cs.INTERFACES])
assert props[cs.TARGET_HANDLE] == self.handle, props
assert props[cs.TARGET_ID] == self.target, props
assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT, props
@@ -425,7 +428,10 @@ class SendFileTest(FileTransferTest):
# org.freedesktop.Telepathy.Channel D-Bus properties
assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER
- assert props[cs.INTERFACES] == []
+ assertSameSets(
+ [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA,
+ cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE',
+ ], props[cs.INTERFACES])
assert props[cs.TARGET_HANDLE] == self.handle
assert props[cs.TARGET_ID] == self.target
assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT
diff --git a/tests/twisted/jingle-share/jingleshareutils.py b/tests/twisted/jingle-share/jingleshareutils.py
index 16c75fbda..6ade4f50d 100644
--- a/tests/twisted/jingle-share/jingleshareutils.py
+++ b/tests/twisted/jingle-share/jingleshareutils.py
@@ -64,19 +64,18 @@ def test_ft_caps_from_contact(q, bus, conn, stream, contact, contact_handle, cli
c = presence.addElement((ns.CAPS, 'c'))
c['node'] = client
c['ext'] = "share-v1"
- c['ver'] = compute_caps_hash([], [], {})
+ c['ver'] = '1.1'
stream.send(presence)
# Gabble looks up our capabilities
event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO)
query_node = xpath.queryForNodes('/iq/query', event.stanza)[0]
- assert query_node.attributes['node'] == \
- client + '#' + c['ext']
+ assertEquals(client + '#' + c['ver'], query_node.attributes['node'])
# send good reply
result = make_result_iq(stream, event.stanza)
query = result.firstChildElement()
- query['node'] = client + '#' + c['ext']
+ query['node'] = client + '#' + c['ver']
feature = query.addElement('feature')
feature['var'] = ns.GOOGLE_FEAT_SHARE
stream.send(result)
diff --git a/tests/twisted/jingle-share/test-multift.py b/tests/twisted/jingle-share/test-multift.py
index 7916281e6..d318e427d 100644
--- a/tests/twisted/jingle-share/test-multift.py
+++ b/tests/twisted/jingle-share/test-multift.py
@@ -1,22 +1,13 @@
import dbus
-from twisted.words.xish import xpath
from twisted.words.protocols.jabber.client import IQ
-from servicetest import (assertEquals, EventPattern, TimeoutError)
-from gabbletest import exec_test, make_result_iq, sync_stream, make_presence
+from servicetest import assertEquals, assertSameSets, EventPattern
+from gabbletest import exec_test, sync_stream
import constants as cs
-from caps_helper import compute_caps_hash, \
- text_fixed_properties, text_allowed_properties, \
- stream_tube_fixed_properties, stream_tube_allowed_properties, \
- dbus_tube_fixed_properties, dbus_tube_allowed_properties, \
- ft_fixed_properties, ft_allowed_properties
-
from jingleshareutils import test_ft_caps_from_contact
-import ns
-
from config import JINGLE_FILE_TRANSFER_ENABLED
if not JINGLE_FILE_TRANSFER_ENABLED:
@@ -102,7 +93,10 @@ def test(q, bus, conn, stream):
assert props[cs.FT_SIZE] == size, props
assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER, props
- assert props[cs.INTERFACES] == [], props
+ assertSameSets(
+ [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA,
+ cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE',
+ ], props[cs.INTERFACES])
assert props[cs.TARGET_HANDLE] == 2L, props
assert props[cs.TARGET_ID] == contact.replace("/Resource", ""), props
assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT, props
@@ -128,34 +122,34 @@ def test(q, bus, conn, stream):
event = q.expect('stream-iq', to=contact,
iq_type='set', query_name='session')
- stanza = event.stanza
- session_node = xpath.queryForNodes('/iq/session', event.stanza)[0]
+ session_node = event.query
assert session_node.attributes['type'] == 'transport-accept'
- # Lower the timeout because we will do a q.expect where we expect it to
- # timeout since we check for the *not* reception of the terminate
- q.timeout = 2
+ # Close all but one of the channels, and make sure Gabble doesn't cancel
+ # the multi-FT yet.
+ terminate_pattern = EventPattern('stream-iq', to=contact, iq_type='set',
+ query_name='session',
+ predicate=lambda event: event.query['type'] == 'terminate')
- # Cancel all the channels and make sure gabble cancels the multiFT only
- # once the last channel has been closed
- last_path, props = channels[-1]
- for i in range(len(channels)):
- path, props = channels[i]
+ q.forbid_events([terminate_pattern])
+
+ for path, props in channels[:-1]:
ft_chan = bus.get_object(conn.object.bus_name, path)
channel = dbus.Interface(ft_chan, cs.CHANNEL)
channel.Close()
- try:
- event = q.expect('stream-iq', to=contact,
- iq_type='set', query_name='session')
- # If the iq is received, it must be for the last channel closed
- assert path == last_path, event
- # Make sure it's a terminate message
- stanza = event.stanza
- session_node = xpath.queryForNodes('/iq/session', event.stanza)[0]
- assert session_node.attributes['type'] == 'terminate'
- except TimeoutError, e:
- # Timeout only for the non last channel getting closed
- assert path != last_path
+ q.expect('dbus-signal', signal='Closed', path=path)
+
+ sync_stream(q, stream)
+ q.unforbid_all()
+
+ # Now close the final channel, and make sure Gabble terminates the session.
+ last_path, props = channels[-1]
+
+ ft_chan = bus.get_object(conn.object.bus_name, last_path)
+ channel = dbus.Interface(ft_chan, cs.CHANNEL)
+ channel.Close()
+
+ q.expect_many(terminate_pattern)
if __name__ == '__main__':
exec_test(test)
diff --git a/tests/twisted/jingle/call-muc-cancel.py b/tests/twisted/jingle/call-muc-cancel.py
index 62fa006c3..36fb23891 100644
--- a/tests/twisted/jingle/call-muc-cancel.py
+++ b/tests/twisted/jingle/call-muc-cancel.py
@@ -2,7 +2,7 @@
Test closing the muc channel while a muji request is in flight
"""
-from gabbletest import exec_test
+from gabbletest import exec_test, disconnect_conn
from servicetest import call_async
import constants as cs
@@ -25,7 +25,7 @@ def run_cancel_test(q, bus, conn, stream):
q.expect('stream-presence', to = muc + "/test")
- conn.Disconnect()
+ disconnect_conn(q, conn, stream)
if __name__ == '__main__':
exec_test (run_cancel_test)
diff --git a/tests/twisted/jingle/call-muc-re-re-request.py b/tests/twisted/jingle/call-muc-re-re-request.py
index 087c63f2c..1f72db4c8 100644
--- a/tests/twisted/jingle/call-muc-re-re-request.py
+++ b/tests/twisted/jingle/call-muc-re-re-request.py
@@ -36,16 +36,20 @@ def run_cancel_test(q, bus, conn, stream):
# Accept the channel
channel.Accept()
- e = q.expect('stream-presence', to = muc + "/test")
- mujinode = xpath.queryForNodes("/presence/muji/preparing", e.stanza)
- assertNotEquals(None, mujinode)
+ def preparing(e):
+ node = xpath.queryForNodes("/presence/muji/preparing", e.stanza)
+ return node is not None
+
+ q.expect('stream-presence', to = muc + "/test", predicate=preparing)
channel.Hangup(0, "", "",
dbus_interface=cs.CHANNEL_TYPE_CALL)
- e = q.expect('stream-presence', to = muc + "/test")
- mujinode = xpath.queryForNodes("/presence/muji/preparing", e.stanza)
- assertEquals(None, mujinode)
+ def notpreparing(e):
+ node = xpath.queryForNodes("/presence/muji/preparing", e.stanza)
+ return node is None
+
+ q.expect('stream-presence', to = muc + "/test", predicate=notpreparing)
if x % 2 == 0:
channel.Close()
diff --git a/tests/twisted/jingle/decloak-peer.py b/tests/twisted/jingle/decloak-peer.py
index d7c50b254..fa8f1ee50 100644
--- a/tests/twisted/jingle/decloak-peer.py
+++ b/tests/twisted/jingle/decloak-peer.py
@@ -6,10 +6,9 @@ should ask them to "de-cloak".
from gabbletest import exec_test
from servicetest import (make_channel_proxy, call_async, sync_dbus,
assertEquals, assertLength)
-import jingletest
+from jingletest2 import JingleProtocol031, JingleTest2
import dbus
-from twisted.words.xish import xpath
import constants as cs
import ns
@@ -21,8 +20,10 @@ if not VOIP_ENABLED:
raise SystemExit(77)
def test(q, bus, conn, stream):
- jt = jingletest.JingleTest(stream, 'test@localhost', 'foo@bar.com/Foo')
- jt2 = jingletest.JingleTest(stream, 'test@localhost', 'foo2@bar.com/Foo')
+ jp = JingleProtocol031()
+ jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo')
+ jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost',
+ 'foo2@bar.com/Foo')
# Make gabble think this is a different client
jt2.remote_caps['node'] = 'http://example.com/fake-client1'
@@ -37,7 +38,7 @@ def run_test(q, bus, conn, stream, jt, decloak_allowed):
request = dbus.Dictionary({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA,
cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
- cs.TARGET_ID: jt.remote_jid
+ cs.TARGET_ID: jt.peer,
}, signature='sv')
path, props = conn.CreateChannel(request, dbus_interface=cs.CONN_IFACE_REQUESTS)
media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia')
@@ -47,18 +48,13 @@ def run_test(q, bus, conn, stream, jt, decloak_allowed):
[cs.MEDIA_STREAM_TYPE_AUDIO])
e = q.expect('stream-presence',
- to=jt.remote_bare_jid, presence_type=None)
- nodes = xpath.queryForNodes('/presence/temppres[@xmlns="%s"]'
- % ns.TEMPPRES, e.stanza)
+ to=jt.peer_bare_jid, presence_type=None)
+ nodes = [ node for node in e.stanza.elements(uri=ns.TEMPPRES, name='temppres') ]
assertLength(1, nodes)
assertEquals('media', nodes[0].getAttribute('reason'))
if decloak_allowed:
- jt.send_remote_presence()
- info_event = q.expect('stream-iq', query_ns=ns.DISCO_INFO,
- to=jt.remote_jid)
-
- jt.send_remote_disco_reply(info_event.stanza)
+ jt.send_presence_and_caps()
# RequestStreams should now happily complete
q.expect('dbus-return', method='RequestStreams')
diff --git a/tests/twisted/jingle/google-relay.py b/tests/twisted/jingle/google-relay.py
index 2ac72a2dd..18940fa16 100644
--- a/tests/twisted/jingle/google-relay.py
+++ b/tests/twisted/jingle/google-relay.py
@@ -14,7 +14,7 @@ from gabbletest import exec_test, make_result_iq, sync_stream, \
GoogleXmlStream, disconnect_conn
from servicetest import make_channel_proxy, \
EventPattern, call_async, sync_dbus, assertEquals, assertLength
-import jingletest
+import jingletest2
import gabbletest
import constants as cs
import dbus
@@ -85,7 +85,9 @@ TOO_SLOW_DISCONNECT = 3
TOO_SLOW_DISCONNECT_IMMEDIATELY = 4
def test(q, bus, conn, stream, incoming=True, too_slow=None, use_call=False):
- jt = jingletest.JingleTest(stream, 'test@localhost', 'foo@bar.com/Foo')
+ jp = jingletest2.JingleProtocol031()
+ jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost',
+ 'foo@bar.com/Foo')
if use_call:
# wjt only updated just about enough of this test for Call to check for
@@ -108,7 +110,7 @@ def test(q, bus, conn, stream, incoming=True, too_slow=None, use_call=False):
])
# See: http://code.google.com/apis/talk/jep_extensions/jingleinfo.html
- ji_event = q.expect('stream-iq', query_ns='google:jingleinfo',
+ ji_event = q.expect('stream-iq', query_ns=ns.GOOGLE_JINGLE_INFO,
to='test@localhost')
# Regression test for a bug where Gabble would crash if it disconnected
@@ -181,17 +183,7 @@ def test(q, bus, conn, stream, incoming=True, too_slow=None, use_call=False):
stream.send(iq)
- # We need remote end's presence for capabilities
- jt.send_remote_presence()
-
- # Gabble doesn't trust it, so makes a disco
- event = q.expect('stream-iq', query_ns='http://jabber.org/protocol/disco#info',
- to='foo@bar.com/Foo')
-
- jt.send_remote_disco_reply(event.stanza)
-
- # Force Gabble to process the capabilities
- sync_stream(q, stream)
+ jt.send_presence_and_caps()
remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["foo@bar.com/Foo"])[0]
self_handle = conn.GetSelfHandle()
diff --git a/tests/twisted/jingle/incoming-gmail-modern-jingle.py b/tests/twisted/jingle/incoming-gmail-modern-jingle.py
index 34691306d..033a9975d 100644
--- a/tests/twisted/jingle/incoming-gmail-modern-jingle.py
+++ b/tests/twisted/jingle/incoming-gmail-modern-jingle.py
@@ -31,7 +31,8 @@ def test(q, bus, conn, stream):
jt.prepare(send_roster=False)
sid = 'c1025763497'
- si = elem_iq(stream, 'set', from_=peer, to=self)(
+ iq_id = 'session_init_iq'
+ si = elem_iq(stream, 'set', from_=peer, to=self, id=iq_id)(
elem(ns.JINGLE, 'jingle', action='session-initiate', sid=sid, initiator=peer)(
elem('content', name='video')(
elem(ns.JINGLE_RTP, 'description', media='video')(
@@ -73,7 +74,11 @@ def test(q, bus, conn, stream):
)
stream.send(si)
- nc, nsh = q.expect_many(
+ ok, nc, nsh = q.expect_many(
+ # fd.o #65131: we have to tell Google which dialect we're speaking
+ EventPattern('stream-iq', iq_type='result',
+ query_name='jingle', query_ns=ns.JINGLE,
+ iq_id=iq_id),
EventPattern('dbus-signal', signal='NewChannels'),
EventPattern('dbus-signal', signal='NewSessionHandler'),
)
diff --git a/tests/twisted/jingle/jingletest.py b/tests/twisted/jingle/jingletest.py
deleted file mode 100644
index 104805032..000000000
--- a/tests/twisted/jingle/jingletest.py
+++ /dev/null
@@ -1,227 +0,0 @@
-"""
-Jingle (XEP-0166) testing support.
-"""
-
-import random
-from gabbletest import make_presence
-from twisted.words.xish import domish
-from twisted.words.protocols.jabber.client import IQ
-import dbus
-from caps_helper import send_disco_reply
-
-class JingleTest:
-
- def __init__(self, stream, local_jid, remote_jid):
- self.stream = stream
- self.local_jid = local_jid
- self.remote_jid = remote_jid
- self.remote_bare_jid = remote_jid.split('/', 1)[0]
- self.session_id = 'sess' + str(int(random.random() * 10000))
- self.google_mode = False
-
- # Default caps for the remote end
- self.remote_caps = { 'ext': '', 'ver': '0.0.0',
- 'node': 'http://example.com/fake-client0' }
-
- # Default feats for remote end
- self.remote_feats = [ 'http://www.google.com/xmpp/protocol/session',
- 'http://www.google.com/transport/p2p',
- 'http://jabber.org/protocol/jingle',
- # was previously in bundles:
- 'http://jabber.org/protocol/jingle/description/audio',
- 'http://jabber.org/protocol/jingle/description/video',
- 'http://www.google.com/xmpp/protocol/voice/v1']
-
- # Default audio codecs for the remote end
- self.audio_codecs = [ ('GSM', 3, 8000), ('PCMA', 8, 8000), ('PCMU', 0, 8000) ]
-
- # Default video codecs for the remote end. I have no idea what's
- # a suitable value here...
- self.video_codecs = [ ('WTF', 42, 80000) ]
-
- # Default candidates for the remote end
- self.remote_transports = [
- ( "192.168.0.1", # host
- 666, # port
- 0, # protocol = TP_MEDIA_STREAM_BASE_PROTO_UDP
- "RTP", # protocol subtype
- "AVP", # profile
- 1.0, # preference
- 0, # transport type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL,
- "username",
- "password" ) ]
-
-
- def get_video_codecs_dbus(self):
- return dbus.Array([ (id, name, 0, rate, 0, {} ) for (name, id, rate) in self.video_codecs ],
- signature='(usuuua{ss})')
-
-
- def get_audio_codecs_dbus(self):
- return dbus.Array([ (id, name, 0, rate, 0, {} ) for (name, id, rate) in self.audio_codecs ],
- signature='(usuuua{ss})')
-
-
- def get_remote_transports_dbus(self):
- return dbus.Array([
- (dbus.UInt32(1 + i), host, port, proto, subtype,
- profile, pref, transtype, user, pwd)
- for i, (host, port, proto, subtype, profile,
- pref, transtype, user, pwd)
- in enumerate(self.remote_transports) ],
- signature='(usuussduss)')
-
-
- def _jingle_stanza(self, action):
- iq = IQ(self.stream, 'set')
- iq['from'] = self.remote_jid
- iq['to'] = self.local_jid
- jingle = domish.Element(("http://jabber.org/protocol/jingle", 'jingle'))
- if self.direction == 'incoming':
- jingle['initiator'] = self.remote_jid
- elif self.direction == 'outgoing':
- jingle['initiator'] = self.local_jid
-
- jingle['action'] = action
- jingle['sid'] = self.session_id
- iq.addChild(jingle)
- return (iq, jingle)
-
- def _gtalk_stanza(self, action):
- iq = IQ(self.stream, 'set')
- iq['from'] = self.remote_jid
- iq['to'] = self.local_jid
- sess = domish.Element(("http://www.google.com/session", 'session'))
- if self.direction == 'incoming':
- sess['initiator'] = self.remote_jid
- elif self.direction == 'outgoing':
- sess['initiator'] = self.local_jid
-
- sess['type'] = action
- sess['id'] = self.session_id
- iq.addChild(sess)
- return (iq, sess)
-
-
- def send_remote_presence(self):
- presence = make_presence(self.remote_jid, self.local_jid,
- caps=self.remote_caps)
- self.stream.send(presence.toXml())
-
-
- def send_remote_disco_reply(self, stanza):
- send_disco_reply(self.stream, stanza, [], self.remote_feats)
-
- def incoming_call(self, codec_parameters=None):
- self.direction = 'incoming'
-
- if self.google_mode:
- iq, sess = self._gtalk_stanza('initiate')
- desc_ns = 'http://www.google.com/session/phone'
- else:
- iq, jingle = self._jingle_stanza('session-initiate')
- desc_ns = 'http://jabber.org/protocol/jingle/description/audio'
-
- content = domish.Element((None, 'content'))
- content['creator'] = 'initiator'
- content['name'] = 'audio1'
- content['senders'] = 'both'
-
- desc = domish.Element((desc_ns, 'description'))
- for codec, id, rate in self.audio_codecs:
- p = domish.Element((None, 'payload-type'))
- p['name'] = codec
- p['id'] = str(id)
-
- if self.google_mode:
- p['clockrate'] = p['bitrate'] = str(rate)
- else:
- p['rate'] = str(rate)
-
- if codec_parameters is not None:
- for name, value in codec_parameters.iteritems():
- param = domish.Element((None, 'parameter'))
- param['name'] = name
- param['value'] = value
- p.addChild(param)
-
- desc.addChild(p)
-
- xport = domish.Element(("http://www.google.com/transport/p2p", 'transport'))
-
- if self.google_mode:
- sess.addChild(desc)
- sess.addChild(xport)
- else:
- jingle.addChild(content)
- content.addChild(desc)
- content.addChild(xport)
-
- self.stream.send(iq.toXml())
-
- def create_content_node(self, name, type, codecs):
- content = domish.Element((None, 'content'))
- content['creator'] = 'initiator'
- content['name'] = name
- content['senders'] = 'both'
-
- desc = domish.Element(("http://jabber.org/protocol/jingle/description/" + type, 'description'))
- for codec, id, rate in codecs:
- p = domish.Element((None, 'payload-type'))
- p['name'] = codec
- p['id'] = str(id)
- p['rate'] = str(rate)
- desc.addChild(p)
- content.addChild(desc)
-
- xport = domish.Element(("http://www.google.com/transport/p2p", 'transport'))
- content.addChild(xport)
- return content
-
- def outgoing_call_reply(self, session_id, accept, with_video=False):
- self.session_id = session_id
- self.direction = 'outgoing'
-
- if not accept:
- self.remote_terminate()
- return
-
- iq, jingle = self._jingle_stanza('session-accept')
-
- jingle.addChild(self.create_content_node('Audio', 'audio',
- self.audio_codecs))
-
- if with_video:
- jingle.addChild(self.create_content_node('Video', 'video',
- self.video_codecs))
-
- self.stream.send(iq.toXml())
-
-
- def remote_terminate(self):
- if self.google_mode:
- iq, _ = self._gtalk_stanza('terminate')
- else:
- iq, _ = self._jingle_stanza('session-terminate')
- self.stream.send(iq.toXml())
-
-
- def send_remote_candidates(self):
-
- iq, el = self._gtalk_stanza('candidates')
- for t in self.remote_transports:
- c = domish.Element((None, 'candidate'))
- c['generation'] = '0'
- c['network'] = '0'
- c['type'] = 'local'
- c['protocol'] = 'udp'
- c['preference'] = str(t[5])
- c['password'] = t[8]
- c['username'] = t[7]
- c['port'] = str(t[1])
- c['address'] = t[0]
- c['name'] = t[3].lower()
- el.addChild(c)
-
- self.stream.send(iq.toXml())
-
diff --git a/tests/twisted/jingle/jingletest2.py b/tests/twisted/jingle/jingletest2.py
index 5ca91d428..64eaa40e8 100644
--- a/tests/twisted/jingle/jingletest2.py
+++ b/tests/twisted/jingle/jingletest2.py
@@ -3,9 +3,6 @@
# unreadable), but to make the expressions denser and more concise.
# Helper classes support different dialects so the test can
# be invoked for different (possibly all) dialects.
-#
-# This can be used in parallel with the old API, but should
-# obsolete it in time.
from functools import partial
from twisted.words.xish import domish, xpath
@@ -17,7 +14,7 @@ import ns
import os
import constants as cs
-class JingleProtocol:
+class JingleProtocol(object):
"""
Defines a simple DSL for constructing Jingle messages.
"""
@@ -496,7 +493,7 @@ class JingleProtocol031(JingleProtocol):
return (self._extract_session_id(query), audio, video)
-class JingleTest2:
+class JingleTest2(object):
# Default caps for the remote end
remote_caps = { 'ext': '', 'ver': '0.0.0',
'node': 'http://example.com/fake-client0' }
@@ -621,19 +618,23 @@ class JingleTest2:
if send_presence:
self.send_presence_and_caps()
- def send_presence_and_caps(self):
+ def send_presence(self):
# We need remote end's presence for capabilities
self.stream.send(self.jp.xml(
self.jp.Presence(self.peer, self.jid, self.remote_caps)))
# Gabble doesn't trust it, so makes a disco
- event = self.q.expect('stream-iq', query_ns=ns.DISCO_INFO, to=self.peer)
+ return self.q.expect('stream-iq', query_ns=ns.DISCO_INFO, to=self.peer)
- # jt.send_remote_disco_reply(event.stanza)
- self.stream.send(self.jp.xml(self.jp.ResultIq(self.jid, event.stanza,
+ def send_remote_disco_reply(self, query_stanza):
+ self.stream.send(self.jp.xml(self.jp.ResultIq(self.jid, query_stanza,
[ self.jp.Query(None, ns.DISCO_INFO,
[ self.jp.Feature(x) for x in self.jp.features ]) ]) ))
+ def send_presence_and_caps(self):
+ event = self.send_presence()
+ self.send_remote_disco_reply(event.stanza)
+
# Force Gabble to process the caps before doing any more Jingling
sync_stream(self.q, self.stream)
@@ -850,11 +851,11 @@ class JingleTest2:
signature='(usqa{sv})')
-def test_dialects(f, dialects):
+def test_dialects(f, dialects, params=None, protocol=None):
for dialect in dialects:
- exec_test(partial(f, dialect()))
+ exec_test(partial(f, dialect()), params=params, protocol=protocol)
-def test_all_dialects(f):
+def test_all_dialects(f, params=None, protocol=None):
dialectmap = { "jingle015": JingleProtocol015,
"jingle031": JingleProtocol031,
"gtalk03": GtalkProtocol03,
@@ -868,4 +869,4 @@ def test_all_dialects(f):
else:
for d in jd.split (','):
dialects.append(dialectmap[d])
- test_dialects(f, dialects)
+ test_dialects(f, dialects, params=params, protocol=protocol)
diff --git a/tests/twisted/jingle/outgoing-ensure.py b/tests/twisted/jingle/outgoing-ensure.py
index f2f1d5560..a5bab23c7 100644
--- a/tests/twisted/jingle/outgoing-ensure.py
+++ b/tests/twisted/jingle/outgoing-ensure.py
@@ -6,6 +6,7 @@ This also exercises calls to a contact on a SIP gateway, who has no resource,
only a bare JID.
"""
+from functools import partial
from gabbletest import exec_test
from servicetest import (
wrap_channel,
@@ -212,7 +213,5 @@ def test(q, bus, conn, stream, channel_type):
chan.Close()
if __name__ == '__main__':
- exec_test(lambda q, bus, conn, stream:
- test(q, bus, conn, stream, cs.CHANNEL_TYPE_STREAMED_MEDIA))
- exec_test(lambda q, bus, conn, stream:
- test(q, bus, conn, stream, cs.CHANNEL_TYPE_CALL))
+ exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_STREAMED_MEDIA))
+ exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_CALL))
diff --git a/tests/twisted/jingle/outgoing-many-streams.py b/tests/twisted/jingle/outgoing-many-streams.py
index ecdcf1182..b93ce616c 100644
--- a/tests/twisted/jingle/outgoing-many-streams.py
+++ b/tests/twisted/jingle/outgoing-many-streams.py
@@ -9,7 +9,7 @@ import dbus
from gabbletest import exec_test, sync_stream
from servicetest import (
make_channel_proxy, call_async, EventPattern)
-import jingletest
+import jingletest2
import gabbletest
import constants as cs
@@ -25,23 +25,13 @@ def test(q, bus, conn, stream):
worker(q, bus, conn, stream, 'foo@sip.bar.com')
def worker(q, bus, conn, stream, peer):
- jt = jingletest.JingleTest(stream, 'test@localhost', peer)
+ jp = jingletest2.JingleProtocol031()
+ jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost', peer)
self_handle = conn.GetSelfHandle()
+ jt.send_presence_and_caps()
- # We need remote end's presence for capabilities
- jt.send_remote_presence()
-
- # Gabble doesn't trust it, so makes a disco
- event = q.expect('stream-iq', query_ns='http://jabber.org/protocol/disco#info',
- to=jt.remote_jid)
-
- jt.send_remote_disco_reply(event.stanza)
-
- # Force Gabble to process the caps before calling RequestChannel
- sync_stream(q, stream)
-
- handle = conn.RequestHandles(cs.HT_CONTACT, [jt.remote_jid])[0]
+ handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0]
call_async(q, conn.Requests, 'CreateChannel',
{ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA,
@@ -77,7 +67,7 @@ def worker(q, bus, conn, stream, peer):
assert emitted_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAMED_MEDIA
assert emitted_props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT
assert emitted_props[cs.TARGET_HANDLE] == handle
- assert emitted_props[cs.TARGET_ID] == jt.remote_bare_jid, emitted_props
+ assert emitted_props[cs.TARGET_ID] == jt.peer_bare_jid, emitted_props
assert emitted_props[cs.REQUESTED] == True
assert emitted_props[cs.INITIATOR_HANDLE] == self_handle
assert emitted_props[cs.INITIATOR_ID] == 'test@localhost'
@@ -103,7 +93,7 @@ def worker(q, bus, conn, stream, peer):
cs.TP_AWKWARD_PROPERTIES, cs.CHANNEL_IFACE_HOLD]:
assert i in interfaces, (i, interfaces)
- assert channel_props['TargetID'] == jt.remote_bare_jid, channel_props
+ assert channel_props['TargetID'] == jt.peer_bare_jid, channel_props
assert channel_props['Requested'] == True
assert channel_props['InitiatorID'] == 'test@localhost'
assert channel_props['InitiatorHandle'] == self_handle
@@ -205,8 +195,9 @@ def worker(q, bus, conn, stream, peer):
assert e.query.name == 'jingle'
assert e.query['action'] == 'session-initiate'
stream.send(gabbletest.make_result_iq(stream, e.stanza))
+ jt.parse_session_initiate(e.query)
- jt.outgoing_call_reply(e.query['sid'], True)
+ jt.accept()
q.expect('stream-iq', iq_type='result')
diff --git a/tests/twisted/jingle/payload-types.py b/tests/twisted/jingle/payload-types.py
index 10cb837da..64a300ff1 100644
--- a/tests/twisted/jingle/payload-types.py
+++ b/tests/twisted/jingle/payload-types.py
@@ -4,13 +4,11 @@ Regression test for https://bugs.freedesktop.org/show_bug.cgi?id=18918
import dbus
-from gabbletest import exec_test, sync_stream
-from servicetest import make_channel_proxy
-import jingletest
+from gabbletest import exec_test
+from servicetest import wrap_channel, make_channel_proxy
+import jingletest2
import constants as cs
-from twisted.words.xish import domish
-
from config import VOIP_ENABLED
if not VOIP_ENABLED:
@@ -18,46 +16,24 @@ if not VOIP_ENABLED:
raise SystemExit(77)
def test(q, bus, conn, stream):
- jt = jingletest.JingleTest(stream, 'test@localhost', 'foo@bar.com/Foo')
+ jp = jingletest2.JingleProtocol031()
+ jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost',
+ 'foo@bar.com/Foo')
self_handle = conn.GetSelfHandle()
- # We need remote end's presence for capabilities
- jt.send_remote_presence()
-
- # Gabble doesn't trust it, so makes a disco
- event = q.expect('stream-iq', query_ns='http://jabber.org/protocol/disco#info',
- to='foo@bar.com/Foo')
-
- jt.send_remote_disco_reply(event.stanza)
+ jt.send_presence_and_caps()
- # Force Gabble to process the caps before calling RequestChannel
- sync_stream(q, stream)
-
- handle = conn.RequestHandles(cs.HT_CONTACT, [jt.remote_jid])[0]
+ handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0]
path = conn.RequestChannel(
cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True)
- channel = bus.get_object(conn.bus_name, path)
- signalling_iface = make_channel_proxy(conn, path, 'Channel.Interface.MediaSignalling')
- media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia')
- group_iface = make_channel_proxy(conn, path, 'Channel.Interface.Group')
-
- # FIXME: Hack to make sure the disco info has been processed - we need to
- # send Gabble some XML that will cause an event when processed, and
- # wait for that event (until
- # https://bugs.freedesktop.org/show_bug.cgi?id=15769 is fixed)
- el = domish.Element(('jabber:client', 'presence'))
- el['from'] = 'bob@example.com/Bar'
- stream.send(el.toXml())
- q.expect('dbus-signal', signal='PresencesChanged')
- # OK, now we can continue. End of hack
-
+ channel = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia')
# Test that codec parameters are correctly sent in <parameter> children of
# <payload-type> rather than as attributes of the latter.
- media_iface.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO])
+ channel.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO])
# S-E gets notified about new session handler, and calls Ready on it
e = q.expect('dbus-signal', signal='NewSessionHandler')
@@ -107,7 +83,8 @@ def test(q, bus, conn, stream):
# Test that codec parameters are correctly extracted from <parameter>
# children of <payload-type> rather than from attributes of the latter.
- jt.incoming_call({'misc': 'other'})
+ jt.audio_codecs = [ ('GSM', 3, 8000, {'misc': 'other'}) ]
+ jt.incoming_call()
e = q.expect('dbus-signal', signal='NewSessionHandler')
assert e.args[1] == 'rtp'
diff --git a/tests/twisted/jingle/stream-handler-error.py b/tests/twisted/jingle/stream-handler-error.py
index 8c3943b2b..5b05f6d15 100644
--- a/tests/twisted/jingle/stream-handler-error.py
+++ b/tests/twisted/jingle/stream-handler-error.py
@@ -8,7 +8,7 @@ from functools import partial
from gabbletest import exec_test
from servicetest import make_channel_proxy
-import jingletest
+import jingletest2
import constants as cs
@@ -19,9 +19,11 @@ if not VOIP_ENABLED:
raise SystemExit(77)
def test(q, bus, conn, stream, call_error_on):
- jt = jingletest.JingleTest(stream, 'test@localhost', 'foo@bar.com/Foo')
+ jp = jingletest2.JingleProtocol031()
+ jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost',
+ 'foo@bar.com/Foo')
- remote_handle = conn.RequestHandles(1, ["foo@bar.com/Foo"])[0]
+ remote_handle = conn.RequestHandles(1, [jt.peer])[0]
# Remote end calls us
jt.incoming_call()
diff --git a/tests/twisted/jingle/stun-server.py b/tests/twisted/jingle/stun-server.py
index 6b69ea3a6..0676993d4 100644
--- a/tests/twisted/jingle/stun-server.py
+++ b/tests/twisted/jingle/stun-server.py
@@ -2,16 +2,18 @@
Test getting STUN server from Google jingleinfo
"""
+from functools import partial
import dbus
import socket
-from gabbletest import exec_test, make_result_iq, sync_stream, GoogleXmlStream
+from gabbletest import make_result_iq, GoogleXmlStream, elem_iq, elem
from servicetest import (
make_channel_proxy, EventPattern,
assertEquals, assertLength, assertNotEquals, assertEquals
)
-import jingletest
+from jingletest2 import test_all_dialects, JingleTest2
import constants as cs
+import ns
from config import CHANNEL_TYPE_CALL_ENABLED, GOOGLE_RELAY_ENABLED, VOIP_ENABLED
@@ -19,70 +21,71 @@ if not VOIP_ENABLED:
print "NOTE: built with --disable-voip"
raise SystemExit(77)
-def test_stun_server(stun_server_prop,
- expected_stun_server=None, expected_stun_port=None):
- if expected_stun_server == None:
- # If there is no stun server set then gabble should fallback on the
- # default fallback stunserver (stun.collabora.co.uk)
+def test_stun_server(stun_server_prop, expected_stun_servers=None):
+ if expected_stun_servers is None:
+ # If there is no stun server set, and it can't discover some from the
+ # network, then gabble should fallback on the default fallback stun
+ # server (stun.telepathy.im)
+ #
# This test uses the test-resolver which is set to
- # have 'stun.collabora.co.uk' resolve to '6.7.8.9'
- expected_stun_server = '6.7.8.9'
- expected_stun_port = 3478
-
- assertEquals ([(expected_stun_server, expected_stun_port)],
- stun_server_prop)
-
-def init_test(q, conn, stream, google=False):
- jt = jingletest.JingleTest(stream, 'test@localhost', 'foo@bar.com/Foo')
+ # have 'stun.telepathy.im' resolve to '6.7.8.9'
+ expected_stun_servers=[('6.7.8.9', 3478)]
+
+ assertEquals(expected_stun_servers, stun_server_prop)
+
+def add_jingle_info(jingleinfo, stun_server, stun_port):
+ stun = jingleinfo.firstChildElement().addElement('stun')
+ server = stun.addElement('server')
+ server['host'] = stun_server
+ server['udp'] = stun_port
+ relay = jingleinfo.firstChildElement().addElement('relay')
+ relay.addElement('token', content='jingle all the way')
+
+def handle_jingle_info_query(q, stream, stun_server, stun_port):
+ # See: http://code.google.com/apis/talk/jep_extensions/jingleinfo.html
+ event = q.expect('stream-iq', query_ns=ns.GOOGLE_JINGLE_INFO,
+ to=stream.authenticator.bare_jid)
+ jingleinfo = make_result_iq(stream, event.stanza)
+ add_jingle_info(jingleinfo, stun_server, stun_port)
+ stream.send(jingleinfo)
+
+def push_jingle_info(q, stream, stun_server, stun_port):
+ iq = elem_iq(stream, 'set')(elem(ns.GOOGLE_JINGLE_INFO, 'query'))
+ add_jingle_info(iq, stun_server, stun_port)
+ stream.send(iq)
+ q.expect('stream-iq', iq_type='result', iq_id=iq['id'])
+
+def init_test(jp, q, conn, stream, google=False, google_push_replacements=None):
+ jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo')
# If we need to override remote caps, feats, codecs or caps,
# this is a good time to do it
- # Connecting
- conn.Connect()
-
- expected = [EventPattern('dbus-signal', signal='StatusChanged',
- args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])]
-
if google:
- # See: http://code.google.com/apis/talk/jep_extensions/jingleinfo.html
- expected.append(EventPattern('stream-iq', query_ns='google:jingleinfo',
- to='test@localhost'))
-
- events = q.expect_many(*expected)
-
- if google:
- event = events[-1]
- jingleinfo = make_result_iq(stream, event.stanza)
- stun = jingleinfo.firstChildElement().addElement('stun')
- server = stun.addElement('server')
- server['host'] = 'resolves-to-1.2.3.4'
- server['udp'] = '12345'
- relay = jingleinfo.firstChildElement().addElement('relay')
- relay.addElement('token', content='jingle all the way')
- stream.send(jingleinfo)
-
- # We need remote end's presence for capabilities
- jt.send_remote_presence()
+ handle_jingle_info_query(q, stream, 'resolves-to-1.2.3.4', '12345')
- # Gabble doesn't trust it, so makes a disco
- event = q.expect('stream-iq', query_ns='http://jabber.org/protocol/disco#info',
- to='foo@bar.com/Foo')
-
- jt.send_remote_disco_reply(event.stanza)
+ if google_push_replacements is not None:
+ # oh no! the server changed its mind!
+ server, port = google_push_replacements
+ push_jingle_info(q, stream, server, port)
+ else:
+ # We shouldn't be sending google:jingleinfo queries if the server
+ # doesn't support it.
+ q.forbid_events([
+ EventPattern('stream-iq', query_ns=ns.GOOGLE_JINGLE_INFO),
+ ])
- # Force Gabble to process the caps before calling RequestChannel
- sync_stream(q, stream)
+ jt.send_presence_and_caps()
remote_handle = conn.RequestHandles(1, ["foo@bar.com/Foo"])[0]
return jt, remote_handle
-def test_streamed_media(q, bus, conn, stream,
- expected_stun_server=None, expected_stun_port=None, google=False,
+def test_streamed_media(jp, q, bus, conn, stream,
+ expected_stun_servers=None, google=False, google_push_replacements=None,
expected_relays=[]):
# Initialize the test values
- jt, remote_handle = init_test(q, conn, stream, google)
+ jt, remote_handle = init_test(jp, q, conn, stream, google, google_push_replacements)
# Remote end calls us
jt.incoming_call()
@@ -127,21 +130,7 @@ def test_streamed_media(q, bus, conn, stream,
assert sh_props['NATTraversal'] == 'gtalk-p2p'
assert sh_props['CreatedLocally'] == False
- if expected_stun_server == None:
- # If there is no stun server set then gabble should fallback on the
- # default fallback stunserver (stun.telepathy.im)
- # This test uses the test-resolver which is set to
- # have 'stun.telepathy.im' resolve to '6.7.8.9'
- expected_stun_server = '6.7.8.9'
- expected_stun_port = 3478
-
- if expected_stun_server is None:
- assert sh_props['STUNServers'] == [], sh_props['STUNServers']
- else:
- assert sh_props['STUNServers'] == \
- [(expected_stun_server, expected_stun_port)], \
- sh_props['STUNServers']
-
+ test_stun_server(sh_props['STUNServers'], expected_stun_servers)
assert sh_props['RelayInfo'] == expected_relays
# consistency check, since we currently reimplement Get separately
@@ -187,10 +176,9 @@ def test_streamed_media(q, bus, conn, stream,
assert tp_props['nat-traversal']['value'] == 'gtalk-p2p'
- if expected_stun_server is not None:
+ if expected_stun_servers is not None:
+ expected_stun_server, expected_stun_port = expected_stun_servers[0]
assert tp_props['stun-server']['value'] == expected_stun_server
-
- if expected_stun_port is not None:
assert tp_props['stun-port']['value'] == expected_stun_port
if google:
@@ -200,17 +188,15 @@ def test_streamed_media(q, bus, conn, stream,
q.expect_many(
EventPattern('stream-iq',
- predicate=lambda e: e.query is not None and
- e.query.name == 'jingle' and
- e.query['action'] == 'session-terminate'),
+ predicate=jp.action_predicate('session-terminate')),
EventPattern('dbus-signal', signal='Closed'),
)
-def test_call(q, bus, conn, stream,
- expected_stun_server=None, expected_stun_port=None, google=False,
+def test_call(jp, q, bus, conn, stream,
+ expected_stun_servers=None, google=False, google_push_replacements=None,
expected_relays=[]):
# Initialize the test values
- jt, remote_handle = init_test(q, conn, stream, google)
+ jt, remote_handle = init_test(jp, q, conn, stream, google, google_push_replacements)
# Advertise that we can do new style calls
conn.ContactCapabilities.UpdateCapabilities([
@@ -272,67 +258,76 @@ def test_call(q, bus, conn, stream,
dbus_interface=dbus.PROPERTIES_IFACE)
assertEquals(cs.CALL_STREAM_TRANSPORT_GTALK_P2P, stream_props['Transport'])
- test_stun_server(stream_props['STUNServers'],
- expected_stun_server, expected_stun_port)
+ test_stun_server(stream_props['STUNServers'], expected_stun_servers)
assertEquals(expected_relays, stream_props['RelayInfo'])
assertEquals(True, stream_props['HasServerInfo'])
if __name__ == '__main__':
# StreamedMedia tests
- exec_test(lambda q, b, c, s: test_streamed_media(q, b, c, s,
- google=False), do_connect=False)
- exec_test(lambda q, b, c, s: test_streamed_media(q, b, c, s,
- google=False, expected_stun_server='5.4.3.2', expected_stun_port=54321),
+ test_all_dialects(partial(test_streamed_media,
+ google=False))
+ test_all_dialects(partial(test_streamed_media,
+ google=False, expected_stun_servers=[('5.4.3.2', 54321)]),
params={'fallback-stun-server': 'resolves-to-5.4.3.2',
- 'fallback-stun-port': dbus.UInt16(54321)}, do_connect=False)
+ 'fallback-stun-port': dbus.UInt16(54321)})
+ test_all_dialects(partial(test_streamed_media, google=False,
+ expected_stun_servers=[('5.4.3.2', 1)]),
+ params={'account': 'test@stunning.localhost'})
if GOOGLE_RELAY_ENABLED:
- exec_test(lambda q, b, c, s: test_streamed_media(q, b, c, s,
- google=True, expected_stun_server='1.2.3.4', expected_stun_port=12345),
- protocol=GoogleXmlStream, do_connect=False)
- exec_test(lambda q, b, c, s: test_streamed_media(q, b, c, s,
- google=True, expected_stun_server='5.4.3.2', expected_stun_port=54321),
+ test_all_dialects(partial(test_streamed_media,
+ google=True, expected_stun_servers=[('1.2.3.4', 12345)]),
+ protocol=GoogleXmlStream)
+ test_all_dialects(partial(test_streamed_media,
+ google=True, expected_stun_servers=[('5.4.3.2', 54321)]),
protocol=GoogleXmlStream,
params={'stun-server': 'resolves-to-5.4.3.2',
- 'stun-port': dbus.UInt16(54321)}, do_connect=False)
- exec_test(lambda q, b, c, s: test_streamed_media(q, b, c, s,
- google=True, expected_stun_server='1.2.3.4', expected_stun_port=12345),
+ 'stun-port': dbus.UInt16(54321)})
+ test_all_dialects(partial(test_streamed_media,
+ google=True, expected_stun_servers=[('1.2.3.4', 12345)]),
protocol=GoogleXmlStream,
params={'fallback-stun-server': 'resolves-to-5.4.3.2',
- 'fallback-stun-port': dbus.UInt16(54321)}, do_connect=False)
+ 'fallback-stun-port': dbus.UInt16(54321)})
+ test_all_dialects(partial(test_streamed_media,
+ google=True, google_push_replacements=('resolves-to-5.4.3.2', '3838'),
+ expected_stun_servers=[('5.4.3.2', 3838)]),
+ protocol=GoogleXmlStream)
else:
print "NOTE: built with --disable-google-relay; omitting StreamedMedia tests with Google relay"
# Call tests
if CHANNEL_TYPE_CALL_ENABLED:
- exec_test(lambda q, b, c, s: test_call(q, b, c, s,
- google=False), do_connect=False)
- exec_test(lambda q, b, c, s: test_call(q, b, c, s,
- google=False, expected_stun_server='5.4.3.2',
- expected_stun_port=54321),
+ test_all_dialects(partial(test_call,
+ google=False))
+ test_all_dialects(partial(test_call,
+ google=False, expected_stun_servers=[('5.4.3.2', 54321)]),
params={'fallback-stun-server': 'resolves-to-5.4.3.2',
- 'fallback-stun-port': dbus.UInt16(54321)}, do_connect=False)
+ 'fallback-stun-port': dbus.UInt16(54321)})
+ test_all_dialects(partial(test_call,
+ google=False, expected_stun_servers=[('5.4.3.2', 1)]),
+ params={'account': 'test@stunning.localhost'})
else:
print "NOTE: built with --disable-channel-type-call; omitting Call tests"
if CHANNEL_TYPE_CALL_ENABLED and GOOGLE_RELAY_ENABLED:
- exec_test(lambda q, b, c, s: test_call(q, b, c, s,
- google=True, expected_stun_server='1.2.3.4',
- expected_stun_port=12345),
- protocol=GoogleXmlStream, do_connect=False)
- exec_test(lambda q, b, c, s: test_call(q, b, c, s,
- google=True, expected_stun_server='5.4.3.2',
- expected_stun_port=54321),
+ test_all_dialects(partial(test_call,
+ google=True, expected_stun_servers=[('1.2.3.4', 12345)]),
+ protocol=GoogleXmlStream)
+ test_all_dialects(partial(test_call,
+ google=True, expected_stun_servers=[('5.4.3.2', 54321)]),
protocol=GoogleXmlStream,
params={'stun-server': 'resolves-to-5.4.3.2',
- 'stun-port': dbus.UInt16(54321)}, do_connect=False)
- exec_test(lambda q, b, c, s: test_call(q, b, c, s,
- google=True, expected_stun_server='1.2.3.4',
- expected_stun_port=12345),
+ 'stun-port': dbus.UInt16(54321)})
+ test_all_dialects(partial(test_call,
+ google=True, expected_stun_servers=[('1.2.3.4', 12345)]),
protocol=GoogleXmlStream,
params={'fallback-stun-server': 'resolves-to-5.4.3.2',
- 'fallback-stun-port': dbus.UInt16(54321)}, do_connect=False)
+ 'fallback-stun-port': dbus.UInt16(54321)})
+ test_all_dialects(partial(test_call,
+ google=True, google_push_replacements=('resolves-to-5.4.3.2', '3838'),
+ expected_stun_servers=[('5.4.3.2', 3838)]),
+ protocol=GoogleXmlStream)
else:
print "NOTE: built with --disable-channel-type-call or with --disable-google-relay; omitting Call tests with Google relay"
diff --git a/tests/twisted/jingle/test-wait-for-caps-incomplete.py b/tests/twisted/jingle/test-wait-for-caps-incomplete.py
index 353c33482..e6e97c226 100644
--- a/tests/twisted/jingle/test-wait-for-caps-incomplete.py
+++ b/tests/twisted/jingle/test-wait-for-caps-incomplete.py
@@ -4,9 +4,9 @@ and returns an error when Disconnect is called and there are
incomplete requests.
"""
+from functools import partial
from gabbletest import exec_test, disconnect_conn
from servicetest import make_channel_proxy, call_async, sync_dbus, EventPattern
-import jingletest
import constants as cs
@@ -17,13 +17,12 @@ if not VOIP_ENABLED:
raise SystemExit(77)
def test(q, bus, conn, stream, channel_type):
- jt = jingletest.JingleTest(stream, 'test@localhost', 'foo@bar.com/Foo')
-
+ peer = 'foo@bar.com/Foo'
# We intentionally DON'T set remote presence yet. Since Gabble is still
# unsure whether to treat contact as offline for this purpose, it
# will tentatively allow channel creation and contact handle addition
- handle = conn.RequestHandles(cs.HT_CONTACT, [jt.remote_jid])[0]
+ handle = conn.RequestHandles(cs.HT_CONTACT, [peer])[0]
if channel_type == cs.CHANNEL_TYPE_STREAMED_MEDIA:
path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA,
@@ -54,7 +53,7 @@ def test(q, bus, conn, stream, channel_type):
call_async(q, conn.Requests, 'CreateChannel',
{ cs.CHANNEL_TYPE: channel_type,
cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
- cs.TARGET_ID: jt.remote_jid,
+ cs.TARGET_ID: peer,
cs.CALL_INITIAL_AUDIO: True
})
@@ -66,10 +65,7 @@ def test(q, bus, conn, stream, channel_type):
before_events[0].error
if __name__ == '__main__':
- exec_test(lambda q, bus, conn, stream:
- test(q, bus, conn, stream, cs.CHANNEL_TYPE_STREAMED_MEDIA), timeout=10)
- print "FIXME: leaks connection, everyone dies"
- raise SystemExit(77)
- exec_test(lambda q, bus, conn, stream:
- test(q, bus, conn, stream, cs.CHANNEL_TYPE_CALL), timeout=10)
-
+ exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_STREAMED_MEDIA),
+ timeout=10)
+ exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_CALL),
+ timeout=10)
diff --git a/tests/twisted/jingle/test-wait-for-caps.py b/tests/twisted/jingle/test-wait-for-caps.py
index f7eaa96a3..98221ef8e 100644
--- a/tests/twisted/jingle/test-wait-for-caps.py
+++ b/tests/twisted/jingle/test-wait-for-caps.py
@@ -4,14 +4,14 @@ attempts to call a contact. Gabble should delay the RequestStreams
call until caps have arrived.
"""
+from functools import partial
from gabbletest import exec_test
from servicetest import make_channel_proxy, call_async, sync_dbus
-import jingletest
+import jingletest2
import dbus
import constants as cs
-import ns
from config import VOIP_ENABLED
@@ -20,8 +20,11 @@ if not VOIP_ENABLED:
raise SystemExit(77)
def test(q, bus, conn, stream, channel_type):
- jt = jingletest.JingleTest(stream, 'test@localhost', 'foo@bar.com/Foo')
- jt2 = jingletest.JingleTest(stream, 'test@localhost', 'foo2@bar.com/Foo')
+ jp = jingletest2.JingleProtocol031()
+ jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost',
+ 'foo@bar.com/Foo')
+ jt2 = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost',
+ 'foo2@bar.com/Foo')
# Make gabble think this is a different client
jt2.remote_caps['node'] = 'http://example.com/fake-client1'
@@ -30,7 +33,7 @@ def test(q, bus, conn, stream, channel_type):
def run_test(q, bus, conn, stream, jt, request_before_presence, channel_type):
"""
- Requests streams on a media channel to jt.remote_jid, either before their
+ Requests streams on a media channel to jt.peer, either before their
presence is received (if request_before_presence is True) or after their
presence is received but before we've got a disco response for their
capabilities (otherwise).
@@ -41,7 +44,7 @@ def run_test(q, bus, conn, stream, jt, request_before_presence, channel_type):
# will tentatively allow channel creation and contact handle addition
request = dbus.Dictionary({ cs.CHANNEL_TYPE: channel_type,
cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
- cs.TARGET_ID: jt.remote_jid
+ cs.TARGET_ID: jt.peer,
}, signature='sv')
if channel_type == cs.CHANNEL_TYPE_CALL:
@@ -64,10 +67,6 @@ def run_test(q, bus, conn, stream, jt, request_before_presence, channel_type):
else:
call_async(q, conn.Requests, 'CreateChannel', request)
- def send_presence():
- jt.send_remote_presence()
- return q.expect('stream-iq', query_ns=ns.DISCO_INFO, to=jt.remote_jid)
-
if request_before_presence:
# Request streams before either <presence> or caps have arrived. Gabble
# should wait for both to arrive before returning from RequestStreams.
@@ -77,9 +76,9 @@ def run_test(q, bus, conn, stream, jt, request_before_presence, channel_type):
sync_dbus(bus, q, conn)
# Now send the presence.
- info_event = send_presence()
+ info_event = jt.send_presence()
else:
- info_event = send_presence()
+ info_event = jt.send_presence()
# Now call RequestStreams; it should wait for the disco reply.
call_request_streams()
@@ -93,8 +92,8 @@ def run_test(q, bus, conn, stream, jt, request_before_presence, channel_type):
q.expect('dbus-return', method='CreateChannel')
if __name__ == '__main__':
- exec_test(lambda q, bus, conn, stream:
- test(q, bus, conn, stream, cs.CHANNEL_TYPE_STREAMED_MEDIA), timeout=10)
- exec_test(lambda q, bus, conn, stream:
- test(q, bus, conn, stream, cs.CHANNEL_TYPE_CALL), timeout=10)
+ exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_STREAMED_MEDIA),
+ timeout=10)
+ exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_CALL),
+ timeout=10)
diff --git a/tests/twisted/jingle/unknown-session.py b/tests/twisted/jingle/unknown-session.py
new file mode 100644
index 000000000..68c97c662
--- /dev/null
+++ b/tests/twisted/jingle/unknown-session.py
@@ -0,0 +1,38 @@
+"""
+Tests that Gabble doesn't explode if it gets Jingle stanzas for unknown
+sessions.
+"""
+
+from gabbletest import exec_test
+from servicetest import assertEquals
+from jingletest2 import JingleProtocol031
+import ns
+
+def assertHasChild(node, uri, name):
+ try:
+ node.elements(uri=uri, name=name).next()
+ except StopIteration:
+ raise AssertionError(
+ "Expected <%s xmlns='%s'> to be a child of\n %s" % (
+ name, uri, node.toXml()))
+
+def test_send_action_for_unknown_session(q, bus, conn, stream):
+ jp = JingleProtocol031()
+ peer = 'guybrush@threepwo.od'
+
+ iq = jp.SetIq(peer, 'test@localhost',
+ [ jp.Jingle('fine-leather-jackets', peer, 'session-info', [])
+ ])
+ stream.send(jp.xml(iq))
+
+ e = q.expect('stream-iq', iq_type='error', iq_id=iq[2]['id'])
+ stanza = e.stanza
+ error_node = stanza.children[-1]
+ assertEquals('error', error_node.name)
+
+ # http://xmpp.org/extensions/xep-0166.html#example-29
+ assertHasChild(error_node, ns.STANZA, 'item-not-found')
+ assertHasChild(error_node, ns.JINGLE_ERRORS, 'unknown-session')
+
+if __name__ == '__main__':
+ exec_test(test_send_action_for_unknown_session)
diff --git a/tests/twisted/main-debug.c b/tests/twisted/main-debug.c
index 2e860c17f..8bc16ff90 100644
--- a/tests/twisted/main-debug.c
+++ b/tests/twisted/main-debug.c
@@ -21,13 +21,16 @@
#include <stdlib.h>
+#include <glib.h>
+
+#ifdef G_OS_UNIX
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#endif
+
#include "gabble.h"
#include "connection.h"
#include "vcard-manager.h"
-#ifdef ENABLE_VOIP
-#include "jingle-factory.h"
-#include "jingle-session.h"
-#endif
#ifdef ENABLE_JINGLE_FILE_TRANSFER
#include "gtalk-file-collection.h"
#endif
@@ -36,12 +39,43 @@
#include <dbus/dbus.h>
+#ifdef G_OS_UNIX
+static gboolean
+connection_established_cb (GSignalInvocationHint *ihint,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer user_data)
+{
+ GSocketConnection *conn;
+ GSocket *sock;
+ gint flag, ret, fd;
+
+ conn = g_value_get_object (param_values + 1);
+ sock = g_socket_connection_get_socket (conn);
+
+ flag = 1;
+
+ fd = g_socket_get_fd (sock);
+ ret = setsockopt (fd, IPPROTO_TCP, TCP_NODELAY,
+ (const char *) &flag, sizeof (flag));
+
+ if (ret == -1)
+ /* not the worst thing ever. */
+ g_print ("Couldn't setsockopt(TCP_NODELAY) on the connection; ain't so bad.\n");
+
+ return TRUE;
+}
+#endif
+
int
main (int argc,
char **argv)
{
int ret = 1;
GResolver *kludged;
+#ifdef G_OS_UNIX
+ gpointer cls;
+#endif
gabble_init ();
@@ -66,20 +100,40 @@ main (int argc,
test_resolver_add_A (TEST_RESOLVER (kludged),
"stun.telepathy.im", "6.7.8.9");
+ test_resolver_add_SRV (TEST_RESOLVER (kludged),
+ "stun", "udp", "stunning.localhost", "resolves-to-5.4.3.2", 1);
+
#ifdef ENABLE_VOIP
- gabble_jingle_info_set_test_mode ();
+ wocky_jingle_info_set_test_mode ();
#endif
#ifdef ENABLE_JINGLE_FILE_TRANSFER
gtalk_file_collection_set_test_mode ();
#endif
+#ifdef G_OS_UNIX
+ /* We want to set TCP_NODELAY on the socket as soon as possible in
+ * the connector so let's use ::connection-established. We need to
+ * ref the class type as it's not loaded yet. */
+ cls = g_type_class_ref (WOCKY_TYPE_CONNECTOR);
+ if (g_getenv ("GABBLE_NODELAY") != NULL)
+ {
+ g_signal_add_emission_hook (
+ g_signal_lookup ("connection-established", WOCKY_TYPE_CONNECTOR),
+ 0, connection_established_cb, NULL, NULL);
+ }
+#endif
+
ret = gabble_main (argc, argv);
/* Hack, remove the ref g_resolver has on this object, atm there is no way to
* unset a custom resolver */
g_object_unref (kludged);
+#ifdef G_OS_UNIX
+ g_type_class_unref (cls);
+#endif
+
dbus_shutdown ();
return ret;
diff --git a/tests/twisted/muc/chat-states.py b/tests/twisted/muc/chat-states.py
index edcbb3277..4be5f50b2 100644
--- a/tests/twisted/muc/chat-states.py
+++ b/tests/twisted/muc/chat-states.py
@@ -1,10 +1,10 @@
"""
Regression test for <https://bugs.freedesktop.org/show_bug.cgi?id=32952>,
-wherein chat states in MUCs were misparsed.
+wherein chat states in MUCs were misparsed, and MUC chat states in general.
"""
-from servicetest import assertEquals
-from gabbletest import exec_test, elem
+from servicetest import assertEquals, assertLength, EventPattern
+from gabbletest import exec_test, elem, make_muc_presence, sync_stream
from mucutil import join_muc_and_check
import ns
import constants as cs
@@ -12,10 +12,34 @@ import constants as cs
MUC = 'ohai@groupchat.google.com'
BOB = MUC + '/bob'
+def get_state_notification(stanza):
+ for x in stanza.elements():
+ if x.uri == ns.CHAT_STATES:
+ return x
+
+ return None
+
+def check_state_notification(elem, name, allow_body=False):
+ assertEquals('message', elem.name)
+ assertEquals('groupchat', elem['type'])
+
+ notification = get_state_notification(elem)
+ assert notification is not None, elem.toXml()
+ assert notification.name == name, notification.toXml()
+
+ if not allow_body:
+ assert len(elem.children) == 1, elem.toXml()
+
def test(q, bus, conn, stream):
(muc_handle, chan, user, bob) = join_muc_and_check(q, bus, conn, stream,
MUC)
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(user, cs.CHAT_STATE_INACTIVE))
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(bob, cs.CHAT_STATE_INACTIVE))
+
stream.send(
elem('message', from_=BOB, to='test@localhost/Resource',
type='groupchat', jid='bob@bob.bob')(
@@ -29,6 +53,12 @@ def test(q, bus, conn, stream):
assertEquals(bob, contact)
assertEquals(cs.CHAT_STATE_COMPOSING, state)
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(user, cs.CHAT_STATE_INACTIVE))
+ assertEquals(cs.CHAT_STATE_COMPOSING,
+ states.get(bob, cs.CHAT_STATE_INACTIVE))
+
stream.send(
elem('message', from_=BOB, to='test@localhost/Resource',
type='groupchat', jid='bob@bob.bob')(
@@ -42,5 +72,77 @@ def test(q, bus, conn, stream):
assertEquals(bob, contact)
assertEquals(cs.CHAT_STATE_PAUSED, state)
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(user, cs.CHAT_STATE_INACTIVE))
+ assertEquals(cs.CHAT_STATE_PAUSED,
+ states.get(bob, cs.CHAT_STATE_INACTIVE))
+
+ # Bob leaves
+ presence = make_muc_presence('owner', 'none', MUC, 'bob')
+ presence['type'] = 'unavailable'
+ stream.send(presence)
+
+ e = q.expect('dbus-signal', signal='ChatStateChanged')
+ contact, state = e.args
+ assertEquals(bob, contact)
+ assertEquals(cs.CHAT_STATE_GONE, state)
+
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(user, cs.CHAT_STATE_INACTIVE))
+ # Bob no longer has any chat state at all
+ assertEquals(None, states.get(bob, None))
+
+ # Sending chat states:
+
+ # Composing...
+ chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING)
+
+ stream_message = q.expect('stream-message')
+ check_state_notification(stream_message.stanza, 'composing')
+
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_COMPOSING,
+ states.get(user, cs.CHAT_STATE_INACTIVE))
+
+ # XEP 0085:
+ # every content message SHOULD contain an <active/> notification.
+ chan.Text.Send(0, 'hi.')
+
+ stream_message = q.expect('stream-message')
+ stanza = stream_message.stanza
+ check_state_notification(stanza, 'active', allow_body=True)
+
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_ACTIVE,
+ states.get(user, cs.CHAT_STATE_INACTIVE))
+
+ bodies = list(stanza.elements(uri=ns.CLIENT, name='body'))
+ assertLength(1, bodies)
+ assertEquals(u'hi.', bodies[0].children[0])
+
+ # If we get an error with type='wait', stop sending chat states.
+ stanza['type'] = 'error'
+ stanza['from'] = MUC
+ stanza['to'] = 'test@localhost/Resource'
+
+ error = stanza.addElement('error')
+ error['type'] = 'wait'
+ error.addElement((ns.STANZA, 'resource-constraint'))
+ stream.send(stanza)
+
+ q.expect('dbus-signal', signal='MessageReceived',
+ predicate=lambda e: e.args[0][0]['message-type'] == cs.MT_DELIVERY_REPORT)
+
+ q.forbid_events([
+ EventPattern('stream-message', to=MUC,
+ predicate=lambda e: get_state_notification(e.stanza) is not None)
+ ])
+
+ # User starts typing again but nothing should be seen or heard on the stream.
+ chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING)
+ sync_stream(q, stream)
+
if __name__ == '__main__':
exec_test(test)
diff --git a/tests/twisted/muc/only-text-when-needed.py b/tests/twisted/muc/only-text-when-needed.py
new file mode 100644
index 000000000..260d26c8a
--- /dev/null
+++ b/tests/twisted/muc/only-text-when-needed.py
@@ -0,0 +1,416 @@
+"""
+Test support for creating MUC text channels when necessary, not all
+the time.
+"""
+
+import dbus
+
+from servicetest import call_async, EventPattern, assertEquals, \
+ sync_dbus, wrap_channel
+from gabbletest import exec_test, acknowledge_iq, make_muc_presence, \
+ sync_stream, elem
+import constants as cs
+import ns
+
+from mucutil import echo_muc_presence
+
+def request_stream_tube(q, bus, conn, method, jid):
+ call_async(q, conn.Requests, method,
+ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
+ cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
+ cs.TARGET_ID: jid,
+ cs.STREAM_TUBE_SERVICE: 'the.service',
+ })
+
+def stream_tube(q, bus, conn, stream, method, jid, presence=True):
+ request_stream_tube(q, bus, conn, method, jid)
+ if presence:
+ send_muc_presence(q, stream, jid)
+ e, _ = q.expect_many(EventPattern('dbus-return', method=method),
+ EventPattern('dbus-signal', signal='NewChannels'))
+
+ # sigh
+ if method == 'EnsureChannel':
+ path = e.value[1]
+ else:
+ path = e.value[0]
+
+ tube_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamTube')
+
+ return (tube_chan,) + e.value
+
+def request_text_channel(q, bus, conn, method, jid):
+ call_async(q, conn.Requests, method,
+ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
+ cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
+ cs.TARGET_ID: jid,
+ })
+
+def text_channel(q, bus, conn, stream, method, jid, presence=True):
+ request_text_channel(q, bus, conn, method, jid)
+ if presence:
+ send_muc_presence(q, stream, jid)
+ e, _ = q.expect_many(EventPattern('dbus-return', method=method),
+ EventPattern('dbus-signal', signal='NewChannels'))
+
+ # sigh
+ if method == 'EnsureChannel':
+ path = e.value[1]
+ else:
+ path = e.value[0]
+
+ text_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text')
+
+ return (text_chan,) + e.value
+
+def send_muc_presence(q, stream, jid):
+ q.expect('stream-presence', to='%s/test' % jid)
+
+ stream.send(make_muc_presence('owner', 'moderator', jid, 'bob'))
+ stream.send(make_muc_presence('none', 'participant', jid, 'test'))
+
+def expect_close(q, path, stream=None, jid=None):
+ forbid_unavailable = [EventPattern('stream-presence',
+ presence_type='unavailable',
+ to='%s/test' % jid)]
+
+ if jid is not None:
+ e = q.expect_many(*forbid_unavailable)[0]
+ echo_muc_presence(q, stream, e.stanza, 'none', 'participant')
+ else:
+ q.forbid_events(forbid_unavailable)
+
+ q.expect_many(EventPattern('dbus-signal', signal='ChannelClosed',
+ args=[path]),
+ EventPattern('dbus-signal', signal='Closed',
+ path=path))
+
+ if jid is not None:
+ q.unforbid_events(forbid_unavailable)
+
+def assert_on_bus(q, chan):
+ call_async(q, chan.Properties, 'GetAll', cs.CHANNEL)
+ e = q.expect('dbus-return', method='GetAll')
+ props = e.value[0]
+ assert 'ChannelType' in props
+
+def assert_not_on_bus(q, chan):
+ call_async(q, chan.Properties, 'GetAll', cs.CHANNEL)
+ q.expect('dbus-error', method='GetAll',
+ name='org.freedesktop.DBus.Error.UnknownMethod')
+
+# tests start here
+
+def tube_no_text(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ # create a stream tube.
+ # this will need a MUC channel to be opened, but we want to make
+ # sure it doesn't get signalled.
+ request_stream_tube(q, bus, conn, 'CreateChannel', jid)
+
+ send_muc_presence(q, stream, jid)
+
+ ret, new_sig = q.expect_many(
+ EventPattern('dbus-return', method='CreateChannel'),
+ EventPattern('dbus-signal', signal='NewChannels'))
+
+ q.forbid_events([EventPattern('dbus-signal', signal='NewChannels')])
+
+ tube_path, tube_props = ret.value
+ assertEquals(cs.CHANNEL_TYPE_STREAM_TUBE, tube_props[cs.CHANNEL_TYPE])
+
+ channels = new_sig.args[0]
+ assertEquals(1, len(channels))
+ path, props = channels[0]
+
+ assertEquals(tube_path, path)
+ assertEquals(tube_props, props)
+
+ sync_dbus(bus, q, conn)
+
+ q.unforbid_all()
+
+def tube_then_text(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ # first let's get a stream tube
+ stream_tube(q, bus, conn, stream, 'CreateChannel', jid)
+
+ # now let's try and ensure the text channel which should happen
+ # immediately
+ request_text_channel(q, bus, conn, 'EnsureChannel', jid)
+
+ ret = q.expect('dbus-return', method='EnsureChannel')
+
+ yours, text_path, text_props = ret.value
+ assertEquals(True, yours)
+ assertEquals(cs.CHANNEL_TYPE_TEXT, text_props[cs.CHANNEL_TYPE])
+
+ new_sig = q.expect('dbus-signal', signal='NewChannels')
+
+ channels = new_sig.args[0]
+ assertEquals(1, len(channels))
+ path, props = channels[0]
+
+ assertEquals(text_path, path)
+ assertEquals(text_props, props)
+
+def tube_remains_text_closes(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ text_chan, text_path, _ = text_channel(q, bus, conn, stream, 'CreateChannel', jid)
+ tube_chan, tube_path, _ = stream_tube(q, bus, conn, stream, 'CreateChannel', jid,
+ presence=False)
+
+ # now let's try and close the text channel
+ # this should happen sucessfully but the tube channel
+ # should stick around
+ q.forbid_events([EventPattern('dbus-signal', signal='ChannelClosed',
+ args=[tube_path])])
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ sync_dbus(bus, q, conn)
+
+ assert_on_bus(q, tube_chan)
+ assert_not_on_bus(q, text_chan)
+
+ q.unforbid_all()
+
+def normally_close_text(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ text_chan, text_path, _ = text_channel(q, bus, conn, stream, 'CreateChannel', jid)
+
+ sync_stream(q, stream)
+
+ text_chan.Close()
+ expect_close(q, text_path, stream, jid)
+
+ assert_not_on_bus(q, text_chan)
+
+def text_can_automatically_close(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ tube_chan, tube_path, _ = stream_tube(q, bus, conn, stream, 'CreateChannel', jid)
+
+ sync_dbus(bus, q, conn)
+
+ tube_chan.Close()
+ expect_close(q, tube_path, stream, jid)
+
+ assert_not_on_bus(q, tube_chan)
+
+def text_remains_after_tube(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ tube_chan, tube_path, _ = stream_tube(q, bus, conn, stream, 'CreateChannel', jid)
+ text_chan, text_path, _ = text_channel(q, bus, conn, stream, 'CreateChannel', jid,
+ presence=False)
+
+ sync_dbus(bus, q, conn)
+
+ tube_chan.Close()
+ expect_close(q, tube_path)
+
+ assert_not_on_bus(q, tube_chan)
+ assert_on_bus(q, text_chan)
+
+ call_async(q, text_chan.Properties, 'GetAll', cs.CHANNEL_TYPE_TEXT)
+ q.expect('dbus-return', method='GetAll')
+
+ text_chan.Close()
+ expect_close(q, text_path, stream, jid)
+
+ assert_not_on_bus(q, tube_chan)
+ assert_not_on_bus(q, text_chan)
+
+def recreate_text(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ tube_chan, _, _ = stream_tube(q, bus, conn, stream, 'CreateChannel', jid)
+ text_chan, text_path, text_props = text_channel(q, bus, conn, stream,
+ 'CreateChannel', jid, presence=False)
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ assert_on_bus(q, tube_chan)
+ assert_not_on_bus(q, text_chan)
+
+ # now let's try and create the same text channel and hope we get
+ # back the same channel
+ q.forbid_events([EventPattern('stream-presence', to='%s/test' % jid)])
+
+ request_text_channel(q, bus, conn, 'CreateChannel', jid)
+
+ ret = q.expect('dbus-return', method='CreateChannel')
+
+ path, props = ret.value
+ assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE])
+
+ new_sig = q.expect('dbus-signal', signal='NewChannels')
+
+ channels = new_sig.args[0]
+ assertEquals(1, len(channels))
+
+ assertEquals(path, channels[0][0])
+ assertEquals(props, channels[0][1])
+
+ # the channel should be identical given it's the same MucChannel
+ assertEquals(text_path, path)
+ assertEquals(text_props, props)
+
+ assert_on_bus(q, tube_chan)
+ assert_on_bus(q, text_chan)
+
+ q.unforbid_all()
+
+def test_channels(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ tube_chan, _, _ = stream_tube(q, bus, conn, stream, 'CreateChannel', jid)
+ text_chan, text_path, _ = text_channel(q, bus, conn, stream,'CreateChannel',
+ jid, presence=False)
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ # the following are basically the same as assert_[not_]on_bus()
+ # but they look pretty.
+
+ # methods on the text channel should fail
+ call_async(q, text_chan.Properties, 'GetAll', cs.CHANNEL_TYPE_TEXT)
+ q.expect('dbus-error', method='GetAll')
+
+ # but methods on the tube should pass
+ call_async(q, tube_chan.Properties, 'GetAll', cs.CHANNEL_TYPE_STREAM_TUBE)
+ q.expect('dbus-return', method='GetAll')
+
+def test_message(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ tube_chan, tube_path, _ = stream_tube(q, bus, conn, stream, 'CreateChannel', jid)
+
+ bob_jid = '%s/bob' % jid
+ bob_handle = conn.RequestHandles(cs.HT_CONTACT, [bob_jid])[0]
+
+ # now let's send a message
+ stream.send(
+ elem('message', from_=bob_jid, type='groupchat')(
+ elem('body')(
+ u'oh hey i didnt see you there'
+ ),
+ )
+ )
+
+ # the text channel appears!
+ e = q.expect('dbus-signal', signal='NewChannels')
+ channels = e.args[0]
+ assertEquals(1, len(channels))
+ path, props = channels[0]
+ assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE])
+ # make sure we didn't request it
+ assertEquals(False, props[cs.REQUESTED])
+ assertEquals(bob_handle, props[cs.INITIATOR_HANDLE])
+
+ # and the message is then signalled
+ e = q.expect('dbus-signal', signal='MessageReceived', path=path)
+ parts = e.args[0]
+
+ header = parts[0]
+ assertEquals(bob_handle, header['message-sender'])
+ assertEquals(bob_jid, header['message-sender-id'])
+
+ body = parts[1]
+ assertEquals('oh hey i didnt see you there', body['content'])
+
+def test_requested_message(q, bus, conn, stream):
+ jid = 'test@conf.localhost'
+
+ self_handle = conn.Properties.Get(cs.CONN, 'SelfHandle')
+
+ text_chan, text_path, _ = text_channel(q, bus, conn, stream,'CreateChannel', jid)
+ tube_chan, tube_path, _ = stream_tube(q, bus, conn, stream, 'CreateChannel', jid,
+ presence=False)
+
+ bob_jid = '%s/bob' % jid
+ bob_handle = conn.RequestHandles(cs.HT_CONTACT, [bob_jid])[0]
+
+ # make sure it says we requested it
+ props = text_chan.Properties.GetAll(cs.CHANNEL)
+ assertEquals(True, props['Requested'])
+ assertEquals(self_handle, props['InitiatorHandle'])
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ assert_on_bus(q, tube_chan)
+ assert_not_on_bus(q, text_chan)
+
+ # now let's send a message
+ stream.send(
+ elem('message', from_=bob_jid, type='groupchat')(
+ elem('body')(
+ u'hello again'
+ ),
+ )
+ )
+
+ e = q.expect('dbus-signal', signal='NewChannels')
+ channels = e.args[0]
+ assertEquals(1, len(channels))
+ path, props = channels[0]
+ assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE])
+ # now make sure we didn't request it
+ assertEquals(False, props[cs.REQUESTED])
+ assertEquals(bob_handle, props[cs.INITIATOR_HANDLE])
+
+ e = q.expect('dbus-signal', signal='MessageReceived', path=path)
+ parts = e.args[0]
+
+ header = parts[0]
+ assertEquals(bob_handle, header['message-sender'])
+ assertEquals(bob_jid, header['message-sender-id'])
+
+ body = parts[1]
+ assertEquals('hello again', body['content'])
+
+ assert_on_bus(q, tube_chan)
+ assert_on_bus(q, text_chan)
+
+if __name__ == '__main__':
+ # request tube, assert no text appears
+ exec_test(tube_no_text)
+
+ # request tube, request text (no presence), assert both appear
+ exec_test(tube_then_text)
+
+ # request tube & text, close text, assert tube doesn't close
+ exec_test(tube_remains_text_closes)
+
+ # request text, close text, assert unavailable presence
+ exec_test(normally_close_text)
+
+ # request tube, close tube, assert unavailable presence
+ exec_test(text_can_automatically_close)
+
+ # request tube & text, close tube, assert text doesn't close
+ exec_test(text_remains_after_tube)
+
+ # request tube & text, close text, request text (no presence),
+ # assert appears as normal
+ exec_test(recreate_text)
+
+ # request tube & text, close text, assert GetAll on text fails but
+ # works on tube
+ exec_test(test_channels)
+
+ # request tube, incoming message, assert text channel appears
+ exec_test(test_message)
+
+ # request text & tube, close text, incoming message, assert text
+ # reappears with correct props
+ exec_test(test_requested_message)
diff --git a/tests/twisted/muc/send-error.py b/tests/twisted/muc/send-error.py
index 545d64285..33f376bf5 100644
--- a/tests/twisted/muc/send-error.py
+++ b/tests/twisted/muc/send-error.py
@@ -2,10 +2,11 @@
Test incoming error messages in MUC channels.
"""
+import warnings
import dbus
from gabbletest import exec_test
-from servicetest import EventPattern
+from servicetest import EventPattern, assertEquals, assertLength, assertContains
import constants as cs
import ns
@@ -18,7 +19,47 @@ def test(q, bus, conn, stream):
# Suppose we don't have permission to speak in this MUC. Send a message to
# the channel, and have the MUC reject it as unauthorized.
- content = u"hi r ther ne warez n this chanel?"
+ send_message_and_expect_error(q, stream,
+ text_chan, test_handle, bob_handle,
+ u"hi r ther ne warez n this chanel?",
+ '401', 'auth', 'not-authorized',
+ delivery_status=cs.DELIVERY_STATUS_PERMANENTLY_FAILED,
+ send_error_value=cs.SendError.PERMISSION_DENIED)
+
+ # This time, we get rate-limited.
+ # <https://bugs.freedesktop.org/show_bug.cgi?id=43166>
+ send_message_and_expect_error(q, stream,
+ text_chan, test_handle, bob_handle,
+ "faster faster",
+ '500', 'wait', 'resource-constraint',
+ delivery_status=cs.DELIVERY_STATUS_TEMPORARILY_FAILED,
+ # Yuck this isn't a very good name is it?
+ send_error_value=cs.SendError.TOO_LONG)
+
+ # How about an error message in the reply? This is from Prosody. See
+ # https://bugs.freedesktop.org/show_bug.cgi?id=43166#c9
+ send_message_and_expect_error(q, stream,
+ text_chan, test_handle, bob_handle,
+ content=u"fair enough",
+ code=None,
+ type_='wait',
+ element='policy-violation',
+ error_message='The room is currently overactive, please try again later',
+ delivery_status=cs.DELIVERY_STATUS_TEMPORARILY_FAILED,
+ # Maybe we should expand the SendError codes some day, because this one
+ # is l-a-m-e.
+ send_error_value=cs.SendError.PERMISSION_DENIED)
+
+
+def send_message_and_expect_error(q, stream,
+ text_chan, test_handle, bob_handle,
+ content,
+ code=None,
+ type_=None,
+ element=None,
+ error_message=None,
+ delivery_status=None,
+ send_error_value=None):
greeting = [
dbus.Dictionary({ }, signature='sv'),
{ 'content-type': 'text/plain',
@@ -26,8 +67,7 @@ def test(q, bus, conn, stream):
}
]
- sent_token = dbus.Interface(text_chan, cs.CHANNEL_IFACE_MESSAGES) \
- .SendMessage(greeting, dbus.UInt32(0))
+ sent_token = text_chan.Messages.SendMessage(greeting, dbus.UInt32(0))
stream_message, _, _ = q.expect_many(
EventPattern('stream-message'),
@@ -41,9 +81,14 @@ def test(q, bus, conn, stream):
elem['to'] = 'chat@conf.localhost/test'
elem['type'] = 'error'
error = elem.addElement('error')
- error['code'] = '401'
- error['type'] = 'auth'
- error.addElement((ns.STANZA, 'not-authorized'))
+ if code is not None:
+ error['code'] = code
+ if type_ is not None:
+ error['type'] = type_
+ if element is not None:
+ error.addElement((ns.STANZA, element))
+ if error_message is not None:
+ error.addElement((ns.STANZA, 'text')).addContent(error_message)
stream.send(elem)
@@ -54,48 +99,69 @@ def test(q, bus, conn, stream):
EventPattern('dbus-signal', signal='MessageReceived'),
)
- PERMISSION_DENIED = 3
-
err, timestamp, type, text = send_error.args
- assert err == PERMISSION_DENIED, send_error.args
+ assertEquals(send_error_value, err)
# there's no way to tell when the original message was sent from the error stanza
- assert timestamp == 0, send_error.args
+ assertEquals(0, timestamp)
# Gabble can't determine the type of the original message; see muc/test-muc.py
# assert type == 0, send_error.args
- assert text == content, send_error.args
+ assertEquals(content, text)
# The Text.Received signal should be a "you're not tall enough" stub
id, timestamp, sender, type, flags, text = received.args
- assert sender == 0, received.args
- assert type == 4, received.args # Message_Type_Delivery_Report
- assert flags == 2, received.args # Non_Text_Content
- assert text == '', received.args
+
+ assertEquals(0, sender)
+ assertEquals(type, cs.MT_DELIVERY_REPORT)
+
+ if flags == 0:
+ warnings.warn("ignoring tp-glib bug #61254")
+ else:
+ assertEquals(cs.MessageFlag.NON_TEXT_CONTENT, flags)
+
+ if error_message is None:
+ assertEquals('', text)
+ else:
+ assertEquals(error_message, text)
# Check that the Messages.MessageReceived signal was a failed delivery report
- assert len(message_received.args) == 1, message_received.args
+ assertLength(1, message_received.args)
parts = message_received.args[0]
- # The delivery report should just be a header, no body.
- assert len(parts) == 1, parts
+
+ if error_message is None:
+ # The delivery report should just be a header, no body.
+ assertLength(1, parts)
+ else:
+ assertLength(2, parts)
+
part = parts[0]
# The intended recipient was the MUC, so there's no contact handle
# suitable for being 'message-sender'.
- assert 'message-sender' not in part or part['message-sender'] == 0, part
- assert part['message-type'] == 4, part # Message_Type_Delivery_Report
- assert part['delivery-status'] == 3, part # Delivery_Status_Permanently_Failed
- assert part['delivery-error'] == PERMISSION_DENIED, part
- assert part['delivery-token'] == sent_token, part
+ assertEquals(0, part.get('message-sender', 0))
+ assertEquals(cs.MT_DELIVERY_REPORT, part['message-type'])
+ assertEquals(delivery_status, part['delivery-status'])
+ assertEquals(send_error_value, part['delivery-error'])
+ assertEquals(sent_token, part['delivery-token'])
# Check that the included echo is from us, and matches all the keys in the
# message we sent.
- assert 'delivery-echo' in part, part
+ assertContains('delivery-echo', part)
echo = part['delivery-echo']
- assert len(echo) == len(greeting), (echo, greeting)
- assert echo[0]['message-sender'] == test_handle, echo[0]
- assert echo[0]['message-token'] == sent_token, echo[0]
+ assertLength(len(greeting), echo)
+ echo_header = echo[0]
+ assertEquals(test_handle, echo_header['message-sender'])
+ assertEquals(sent_token, echo_header['message-token'])
+
for i in range(0, len(echo)):
for key in greeting[i]:
assert key in echo[i], (i, key, echo)
assert echo[i][key] == greeting[i][key], (i, key, echo, greeting)
+ if error_message is not None:
+ body = parts[1]
+
+ assertEquals('text/plain', body['content-type'])
+ assertEquals(error_message, body['content'])
+
+
if __name__ == '__main__':
exec_test(test)
diff --git a/tests/twisted/mucutil.py b/tests/twisted/mucutil.py
index a7a0671d4..103b68b79 100644
--- a/tests/twisted/mucutil.py
+++ b/tests/twisted/mucutil.py
@@ -74,7 +74,7 @@ def join_muc(q, bus, conn, stream, muc, request=None,
*also_capture)
path, props = captured[0].value
chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text',
- ['Messages', 'Subject.DRAFT', 'RoomConfig1'])
+ ['Messages', 'Subject.DRAFT', 'RoomConfig1', 'ChatState'])
return (muc_handle, chan, path, props) + tuple(captured[1:])
diff --git a/tests/twisted/ns.py b/tests/twisted/ns.py
index e1e6db977..30f9a8114 100644
--- a/tests/twisted/ns.py
+++ b/tests/twisted/ns.py
@@ -2,6 +2,7 @@ AMP = "http://jabber.org/protocol/amp"
BYTESTREAMS = 'http://jabber.org/protocol/bytestreams'
CHAT_STATES = 'http://jabber.org/protocol/chatstates'
CAPS = "http://jabber.org/protocol/caps"
+CLIENT = "jabber:client"
DISCO_INFO = "http://jabber.org/protocol/disco#info"
DISCO_ITEMS = "http://jabber.org/protocol/disco#items"
FEATURE_NEG = 'http://jabber.org/protocol/feature-neg'
@@ -25,6 +26,7 @@ JINGLE_015 = "http://jabber.org/protocol/jingle"
JINGLE_015_AUDIO = "http://jabber.org/protocol/jingle/description/audio"
JINGLE_015_VIDEO = "http://jabber.org/protocol/jingle/description/video"
JINGLE = "urn:xmpp:jingle:1"
+JINGLE_ERRORS = "urn:xmpp:jingle:errors:1"
JINGLE_RTP = "urn:xmpp:jingle:apps:rtp:1"
JINGLE_RTP_AUDIO = "urn:xmpp:jingle:apps:rtp:audio"
JINGLE_RTP_VIDEO = "urn:xmpp:jingle:apps:rtp:video"
@@ -55,6 +57,7 @@ OLPC_CURRENT_ACTIVITY = "http://laptop.org/xmpp/current-activity"
OLPC_CURRENT_ACTIVITY_NOTIFY = "%s+notify" % OLPC_CURRENT_ACTIVITY
PUBSUB = "http://jabber.org/protocol/pubsub"
PUBSUB_EVENT = "%s#event" % PUBSUB
+RECEIPTS = "urn:xmpp:receipts"
REGISTER = "jabber:iq:register"
ROSTER = "jabber:iq:roster"
SEARCH = 'jabber:iq:search'
diff --git a/tests/twisted/presence/__init__.py b/tests/twisted/presence/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/twisted/presence/__init__.py
diff --git a/tests/twisted/presence/invisible_xep_0126.py b/tests/twisted/presence/invisible_xep_0126.py
index a22fe46c3..7dbfb36b7 100644
--- a/tests/twisted/presence/invisible_xep_0126.py
+++ b/tests/twisted/presence/invisible_xep_0126.py
@@ -8,8 +8,7 @@ XEP-0016 or XEP-0126. Some servers silently support it, like certain
version of Ejabberd and all released versions of Prosody (as of 7.0).
"""
from gabbletest import (
- exec_test, XmppXmlStream, acknowledge_iq, send_error_reply,
- disconnect_conn, elem, elem_iq
+ exec_test, acknowledge_iq, send_error_reply, elem, elem_iq
)
from servicetest import (
EventPattern, assertEquals, assertNotEquals, assertContains,
@@ -19,6 +18,7 @@ import ns
import constants as cs
from twisted.words.xish import xpath, domish
from invisible_helper import ManualPrivacyListStream
+from functools import partial
def test_create_invisible_list(q, bus, conn, stream):
conn.SimplePresence.SetPresence("away", "")
@@ -49,6 +49,35 @@ def test_create_invisible_list(q, bus, conn, stream):
assertContains("hidden",
conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses"))
+def test_create_invisible_list_failed(q, bus, conn, stream):
+ conn.SimplePresence.SetPresence("away", "")
+
+ conn.Connect()
+
+ stream.handle_get_all_privacy_lists(q, bus, conn)
+
+ get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get')
+ list_node = xpath.queryForNodes('//list', get_list.query)[0]
+ assertEquals('invisible', list_node['name'])
+
+ error = domish.Element((None, 'error'))
+ error['type'] = 'cancel'
+ error.addElement((ns.STANZA, 'item-not-found'))
+ send_error_reply (stream, get_list.stanza, error)
+
+ create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
+ list_node = xpath.queryForNodes('//list', create_list.query)[0]
+ assertEquals('invisible', list_node['name'])
+ assertNotEquals([],
+ xpath.queryForNodes('/query/list/item/presence-out', create_list.query))
+ send_error_reply(stream, create_list.stanza)
+
+ q.expect('dbus-signal', signal='StatusChanged',
+ args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
+
+ assertDoesNotContain("hidden",
+ conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses"))
+
def test_invisible_on_connect_fail_no_list(q, bus, conn, stream):
props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE)
assertNotEquals({}, props['Statuses'])
@@ -83,7 +112,8 @@ def test_invisible_on_connect_fail_no_list(q, bus, conn, stream):
assertDoesNotContain("hidden",
conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses"))
-def test_invisible_on_connect_fail_invalid_list(q, bus, conn, stream):
+def test_invisible_on_connect_fail_invalid_list(q, bus, conn, stream,
+ really_invalid=False):
props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE)
assertNotEquals({}, props['Statuses'])
@@ -101,10 +131,15 @@ def test_invisible_on_connect_fail_invalid_list(q, bus, conn, stream):
list_node = xpath.queryForNodes('//list', get_list.query)[0]
assertEquals('invisible', list_node['name'])
- stream.send_privacy_list(get_list.stanza,
- [elem('item', type='jid', value='tybalt@example.com', action='allow',
- order='1')(elem('presence-out')),
- elem('item', action='deny', order='2')(elem('presence-out'))])
+ if really_invalid:
+ # At one point Gabble would crash if the reply was of type 'result' but
+ # wasn't well-formed.
+ acknowledge_iq(stream, get_list.stanza)
+ else:
+ stream.send_privacy_list(get_list.stanza,
+ [elem('item', type='jid', value='tybalt@example.com', action='allow',
+ order='1')(elem('presence-out')),
+ elem('item', action='deny', order='2')(elem('presence-out'))])
create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
created = xpath.queryForNodes('//list', create_list.stanza)[0]
@@ -267,8 +302,7 @@ def test_privacy_list_push_conflict(q, bus, conn, stream):
set_id = stream.send_privacy_list_push_iq("invisible")
_, req_list = q.expect_many(
- EventPattern('stream-iq', iq_type='result', predicate=lambda event: \
- event.stanza['id'] == set_id),
+ EventPattern('stream-iq', iq_type='result', iq_id=set_id),
EventPattern('stream-iq', query_ns=ns.PRIVACY, iq_type="get"))
stream.send_privacy_list(req_list.stanza,
@@ -293,8 +327,7 @@ def test_privacy_list_push_valid(q, bus, conn, stream):
set_id = stream.send_privacy_list_push_iq("invisible")
_, req_list = q.expect_many(
- EventPattern('stream-iq', iq_type='result', predicate=lambda event: \
- event.stanza['id'] == set_id),
+ EventPattern('stream-iq', iq_type='result', iq_id=set_id),
EventPattern('stream-iq', query_ns=ns.PRIVACY, iq_type="get"))
stream.send_privacy_list(req_list.stanza,
@@ -316,10 +349,15 @@ if __name__ == '__main__':
do_connect=False)
exec_test(test_create_invisible_list, protocol=ManualPrivacyListStream,
do_connect=False)
+ exec_test(test_create_invisible_list_failed, protocol=ManualPrivacyListStream,
+ do_connect=False)
exec_test(test_invisible_on_connect_fail_no_list,
protocol=ManualPrivacyListStream, do_connect=False)
exec_test(test_invisible_on_connect_fail_invalid_list,
protocol=ManualPrivacyListStream, do_connect=False)
+ exec_test(partial(test_invisible_on_connect_fail_invalid_list,
+ really_invalid=True),
+ protocol=ManualPrivacyListStream, do_connect=False)
exec_test(test_privacy_list_push_valid, protocol=ManualPrivacyListStream,
do_connect=False)
exec_test(test_privacy_list_push_conflict, protocol=ManualPrivacyListStream,
diff --git a/tests/twisted/run-test.sh.in b/tests/twisted/run-test.sh.in
index 311a89d15..e6638553c 100644
--- a/tests/twisted/run-test.sh.in
+++ b/tests/twisted/run-test.sh.in
@@ -18,11 +18,26 @@ else
list=$(cat @gabbletestsdir@/twisted/gabble-twisted-tests.list)
fi
-for i in $list ; do
- echo "Testing $i"
+any_failed=0
+for i in $list ; do
+ echo "Testing $i ..."
sh @gabbletestsdir@/twisted/tools/with-session-bus.sh \
--config-file=@gabbletestsdir@/twisted/tools/servicedir/tmp-session-bus.conf \
-- \
@PYTHON@ @gabbletestsdir@/twisted/$i
+ e=$?
+ case "$e" in
+ (0)
+ echo "PASS: $i"
+ ;;
+ (77)
+ echo "SKIP: $i"
+ ;;
+ (*)
+ any_failed=1
+ echo "FAIL: $i ($e)"
+ ;;
+ esac
done
+exit $any_failed
diff --git a/tests/twisted/sasl/abort.py b/tests/twisted/sasl/abort.py
index 2c906f631..1cb03f311 100644
--- a/tests/twisted/sasl/abort.py
+++ b/tests/twisted/sasl/abort.py
@@ -21,17 +21,20 @@ def test_abort_early(q, bus, conn, stream):
chan, props = connect_and_get_sasl_channel(q, bus, conn)
abort_auth(q, chan, 31337, "maybe if I use an undefined code you'll crash")
-def test_abort_mid(q, bus, conn, stream):
+def start_mechanism(q, bus, conn,
+ mechanism="ABORT-TEST", initial_response=EXCHANGE[0][1]):
chan, props = connect_and_get_sasl_channel(q, bus, conn)
-
- chan.SASLAuthentication.StartMechanismWithData("ABORT-TEST", EXCHANGE[0][1])
+ chan.SASLAuthentication.StartMechanismWithData(mechanism, initial_response)
q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
args=[cs.SASL_STATUS_IN_PROGRESS, '', {}])
- e = q.expect('sasl-auth', initial_response=EXCHANGE[0][1])
- authenticator = e.authenticator
+ e = q.expect('sasl-auth', initial_response=initial_response)
+ return chan, e.authenticator
+
+def test_abort_mid(q, bus, conn, stream):
+ chan, authenticator = start_mechanism(q, bus, conn)
authenticator.challenge(EXCHANGE[1][0])
q.expect('dbus-signal', signal='NewChallenge',
@@ -42,16 +45,7 @@ def test_abort_mid(q, bus, conn, stream):
"wrong data from server")
def test_disconnect_mid(q, bus, conn, stream):
- chan, props = connect_and_get_sasl_channel(q, bus, conn)
-
- chan.SASLAuthentication.StartMechanismWithData("ABORT-TEST", EXCHANGE[0][1])
-
- q.expect('dbus-signal', signal='SASLStatusChanged',
- interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_IN_PROGRESS, '', {}])
-
- e = q.expect('sasl-auth', initial_response=EXCHANGE[0][1])
- authenticator = e.authenticator
+ chan, authenticator = start_mechanism(q, bus, conn)
authenticator.challenge(EXCHANGE[1][0])
q.expect('dbus-signal', signal='NewChallenge',
@@ -65,17 +59,10 @@ def test_disconnect_mid(q, bus, conn, stream):
EventPattern('dbus-return', method='Disconnect'))
def test_abort_connected(q, bus, conn, stream):
- chan, props = connect_and_get_sasl_channel(q, bus, conn)
-
- chan.SASLAuthentication.StartMechanismWithData('PLAIN',
- '\0' + JID.split('@')[0] + '\0' + PASSWORD)
- e, _ = q.expect_many(
- EventPattern('sasl-auth'),
- EventPattern('dbus-signal', signal='SASLStatusChanged',
- interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]),
- )
- authenticator = e.authenticator
+ initial_response = '\0' + JID.split('@')[0] + '\0' + PASSWORD
+ chan, authenticator = start_mechanism(q, bus, conn,
+ mechanism='PLAIN',
+ initial_response=initial_response)
authenticator.success(None)
q.expect('dbus-signal', signal='SASLStatusChanged',
@@ -86,31 +73,124 @@ def test_abort_connected(q, bus, conn, stream):
q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
args=[cs.SASL_STATUS_SUCCEEDED, '', {}])
-
- e = q.expect('dbus-signal', signal='StatusChanged',
- args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
+ q.expect('dbus-signal', signal='StatusChanged',
+ args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
call_async(q, chan.SASLAuthentication, 'AbortSASL',
cs.SASL_ABORT_REASON_USER_ABORT, "aborting too late")
q.expect('dbus-error', method='AbortSASL', name=cs.NOT_AVAILABLE)
chan.Close()
+def test_give_up_while_waiting(q, bus, conn, stream,
+ channel_method,
+ authenticator_method):
+ """Regression test for https://bugs.freedesktop.org/show_bug.cgi?id=52146
+ where closing the auth channel while waiting for a challenge from the
+ server would not abort the SASL exchange, and the challenge subsequently
+ arriving would make Gabble assert.
+
+ """
+ chan, authenticator = start_mechanism(q, bus, conn)
+
+ # While Gabble is waiting for waiting for the server to make the next move,
+ # a Telepathy client does something to try to end the authentication
+ # process.
+ channel_method(chan)
+
+ # And then we hear something back from the server.
+ authenticator_method(authenticator)
+
+ # FIXME: Gabble should probably send <abort/> and wait for the server to
+ # say <failure><aborted/> rather than unceremoniously closing the
+ # connection.
+ #
+ # In the bug we're testing for, the stream connection would indeed be lost,
+ # but Gabble would also crash and leave a core dump behind. So this test
+ # would appear to pass, but 'make check' would fail as we want.
+ q.expect_many(
+ EventPattern('stream-connection-lost'),
+ EventPattern('dbus-signal', signal='ConnectionError'),
+ EventPattern(
+ 'dbus-signal', signal="StatusChanged",
+ args=[cs.CONN_STATUS_DISCONNECTED,
+ cs.CSR_AUTHENTICATION_FAILED]),
+ )
+
+def test_close_then_challenge(q, bus, conn, stream):
+ """This is the specific scenario for which 52146 was reported. The channel
+ was being closed because its handler crashed.
+
+ """
+ test_give_up_while_waiting(q, bus, conn, stream,
+ lambda chan: chan.Close(),
+ lambda authenticator: authenticator.challenge(EXCHANGE[1][0]))
+
+def test_close_then_success(q, bus, conn, stream):
+ test_give_up_while_waiting(q, bus, conn, stream,
+ lambda chan: chan.Close(),
+ lambda authenticator: authenticator.success())
+
+def test_close_then_failure(q, bus, conn, stream):
+ test_give_up_while_waiting(q, bus, conn, stream,
+ lambda chan: chan.Close(),
+ lambda authenticator: authenticator.not_authorized())
+
+def test_abort_then_challenge(q, bus, conn, stream):
+ test_give_up_while_waiting(q, bus, conn, stream,
+ lambda chan: chan.SASLAuthentication.AbortSASL(
+ cs.SASL_ABORT_REASON_USER_ABORT, "bored now"),
+ lambda authenticator: authenticator.challenge(EXCHANGE[1][0]))
+
+def test_abort_then_success(q, bus, conn, stream):
+ """FIXME: this test fails because the channel changes its state from
+ TP_SASL_STATUS_CLIENT_FAILED to TP_SASL_STATUS_SERVER_SUCCEEDED and waits
+ for the client to ack it when <success> arrives, which is dumb.
+
+ """
+ test_give_up_while_waiting(q, bus, conn, stream,
+ lambda chan: chan.SASLAuthentication.AbortSASL(
+ cs.SASL_ABORT_REASON_USER_ABORT, "bored now"),
+ lambda authenticator: authenticator.success())
+
+def test_abort_then_failure(q, bus, conn, stream):
+ test_give_up_while_waiting(q, bus, conn, stream,
+ lambda chan: chan.SASLAuthentication.AbortSASL(
+ cs.SASL_ABORT_REASON_USER_ABORT, "bored now"),
+ lambda authenticator: authenticator.not_authorized())
+
+def abort_and_close(chan):
+ chan.SASLAuthentication.AbortSASL(
+ cs.SASL_ABORT_REASON_USER_ABORT, "bored now")
+ chan.Close()
+
+def test_abort_and_close_then_challenge(q, bus, conn, stream):
+ test_give_up_while_waiting(q, bus, conn, stream,
+ abort_and_close,
+ lambda authenticator: authenticator.challenge(EXCHANGE[1][0]))
+
+def test_abort_and_close_then_failure(q, bus, conn, stream):
+ test_give_up_while_waiting(q, bus, conn, stream,
+ abort_and_close,
+ lambda authenticator: authenticator.not_authorized())
+
+def exec_test_(func):
+ # Can't use functools.partial, because the authenticator is stateful.
+ authenticator = SaslEventAuthenticator(JID.split('@')[0], MECHANISMS)
+ exec_test(func, do_connect=False, authenticator=authenticator,
+ params={'password': None,
+ 'account' : JID,
+ })
+
if __name__ == '__main__':
- exec_test(test_abort_early,
- {'password': None,'account' : JID}, do_connect=False)
-
- exec_test(test_abort_mid,
- {'password': None,'account' : JID},
- authenticator=SaslEventAuthenticator(JID.split('@')[0],
- MECHANISMS),
- do_connect=False)
- exec_test(test_disconnect_mid,
- {'password': None,'account' : JID},
- authenticator=SaslEventAuthenticator(JID.split('@')[0],
- MECHANISMS),
- do_connect=False)
-
- exec_test(
- test_abort_connected, {'password': None,'account' : JID},
- authenticator=SaslEventAuthenticator(JID.split('@')[0], ['PLAIN']),
- do_connect=False)
+ exec_test_(test_abort_early)
+ exec_test_(test_abort_mid)
+ exec_test_(test_disconnect_mid)
+ exec_test_(test_abort_connected)
+ exec_test_(test_close_then_challenge)
+ exec_test_(test_close_then_success)
+ exec_test_(test_close_then_failure)
+ exec_test_(test_abort_then_challenge)
+ # exec_test_(test_abort_then_success)
+ exec_test_(test_abort_then_failure)
+ exec_test_(test_abort_and_close_then_challenge)
+ exec_test_(test_abort_and_close_then_failure)
diff --git a/tests/twisted/sasl/saslutil.py b/tests/twisted/sasl/saslutil.py
index 5ad78727c..7d146146c 100644
--- a/tests/twisted/sasl/saslutil.py
+++ b/tests/twisted/sasl/saslutil.py
@@ -1,5 +1,4 @@
# hey, Python: encoding: utf-8
-from twisted.words.protocols.jabber.xmlstream import NS_STREAMS
from gabbletest import XmppAuthenticator
from base64 import b64decode, b64encode
from twisted.words.xish import domish
@@ -19,31 +18,11 @@ class SaslEventAuthenticator(XmppAuthenticator):
XmppAuthenticator.__init__(self, jid, '')
self._mechanisms = mechanisms
- def streamStarted(self, root=None):
- if root:
- self.xmlstream.sid = root.getAttribute('id')
+ def streamSASL(self):
+ XmppAuthenticator.streamSASL(self)
- self.xmlstream.sendHeader()
-
- if self.authenticated:
- # Initiator authenticated itself, and has started a new stream.
-
- features = domish.Element((NS_STREAMS, 'features'))
- bind = features.addElement((ns.NS_XMPP_BIND, 'bind'))
- self.xmlstream.send(features)
-
- self.xmlstream.addOnetimeObserver(
- "/iq/bind[@xmlns='%s']" % ns.NS_XMPP_BIND, self.bindIq)
- else:
- features = domish.Element((NS_STREAMS, 'features'))
- mechanisms = features.addElement((ns.NS_XMPP_SASL, 'mechanisms'))
- for mechanism in self._mechanisms:
- mechanisms.addElement('mechanism', content=mechanism)
- self.xmlstream.send(features)
-
- self.xmlstream.addOnetimeObserver("/auth", self._auth)
- self.xmlstream.addObserver("/response", self._response)
- self.xmlstream.addObserver("/abort", self._abort)
+ self.xmlstream.addObserver("/response", self._response)
+ self.xmlstream.addObserver("/abort", self._abort)
def failure(self, fail_str):
reply = domish.Element((ns.NS_XMPP_SASL, 'failure'))
@@ -72,7 +51,7 @@ class SaslEventAuthenticator(XmppAuthenticator):
reply.addContent(b64encode(data))
self.xmlstream.send(reply)
- def _auth(self, auth):
+ def auth(self, auth):
# Special case in XMPP: '=' means a zero-byte blob, whereas an empty
# or self-terminating XML element means no initial response.
# (RFC 3920 §6.2 (3))
diff --git a/tests/twisted/servicetest.py b/tests/twisted/servicetest.py
index 28ed03f5b..31c00f476 100644
--- a/tests/twisted/servicetest.py
+++ b/tests/twisted/servicetest.py
@@ -8,6 +8,7 @@ from twisted.internet.protocol import Protocol, Factory, ClientFactory
glib2reactor.install()
import sys
import time
+import os
import pprint
import unittest
@@ -154,6 +155,12 @@ class BaseEventQueue:
"""
self.forbidden_events.difference_update(set(patterns))
+ def unforbid_all(self):
+ """
+ Remove all patterns from the set of forbidden events.
+ """
+ self.forbidden_events.clear()
+
def _check_forbidden(self, event):
for e in self.forbidden_events:
if e.match(event):
@@ -647,6 +654,16 @@ def install_colourer():
sys.stdout = Colourer(sys.stdout, patterns)
return sys.stdout
-if __name__ == '__main__':
- unittest.main()
+# this is just to shut up unittest.
+class DummyStream(object):
+ def write(self, s):
+ if 'CHECK_TWISTED_VERBOSE' in os.environ:
+ print s,
+
+ def flush(self):
+ pass
+if __name__ == '__main__':
+ stream = DummyStream()
+ runner = unittest.TextTestRunner(stream=stream)
+ unittest.main(testRunner=runner)
diff --git a/tests/twisted/test-resolver.h b/tests/twisted/test-resolver.h
index 3948fdca7..7863135f3 100644
--- a/tests/twisted/test-resolver.h
+++ b/tests/twisted/test-resolver.h
@@ -42,7 +42,6 @@ GType test_resolver_get_type (void);
typedef struct {
GResolver parent_instance;
- GResolver *real_resolver;
GList *fake_A;
GList *fake_SRV;
} TestResolver;
diff --git a/tests/twisted/text/receipts.py b/tests/twisted/text/receipts.py
new file mode 100644
index 000000000..45c7d9f89
--- /dev/null
+++ b/tests/twisted/text/receipts.py
@@ -0,0 +1,197 @@
+# coding=utf-8
+"""
+Test XEP-0184 receipts.
+"""
+
+from servicetest import (
+ EventPattern, assertEquals, assertLength, sync_dbus, wrap_channel,
+)
+from gabbletest import exec_test, elem, sync_stream, acknowledge_iq
+import constants as cs
+import ns
+
+import caps_helper
+import rostertest
+from presence.invisible_helper import Xep0186Stream
+
+GUYBRUSH = 'guybrush@mi.lit'
+GUYBRUSH_FULL_JID = GUYBRUSH + '/Sea Cucumber'
+
+def send_received_report(stream, jid, received_id):
+ stream.send(
+ elem('message', from_=jid)(
+ elem(ns.RECEIPTS, 'received', id=received_id)
+ ))
+
+def report_received_on_open_channel(q, bus, conn, stream, chan):
+ received_id = 'fine-leather-jackets'
+
+ send_received_report(stream, GUYBRUSH, received_id)
+ e = q.expect('dbus-signal', signal='MessageReceived', path=chan.object_path)
+ message, = e.args
+ header, = message
+
+ assertEquals(cs.MT_DELIVERY_REPORT, header['message-type'])
+ assertEquals(cs.DELIVERY_STATUS_DELIVERED, header['delivery-status'])
+ assertEquals(received_id, header['delivery-token'])
+
+def report_ignored_without_channel(q, bus, conn, stream):
+ q.forbid_events([EventPattern('dbus-signal', signal='MessageReceived')])
+ send_received_report(stream, 'marley@mi.gov', 'only-one-candidate')
+ sync_dbus(bus, q, conn)
+ q.unforbid_all()
+
+def not_sending_request_to_contact(q, bus, conn, stream, chan):
+ message = [
+ { 'message-type': cs.MT_NORMAL,
+ },
+ { 'content-type': 'text/plain',
+ 'content': 'Mancomb Seepgood?',
+ }]
+ chan.Messages.SendMessage(message, 0)
+
+ e = q.expect('stream-message', to=GUYBRUSH)
+ assertLength(0, list(e.stanza.elements(uri=ns.RECEIPTS, name='request')))
+
+def sending_request_to_presenceless_contact(q, bus, conn, stream, chan):
+ """
+ Initially we know nothing of Guybrush's presence, so should just try our
+ level best if asked to.
+ """
+ message = [
+ { 'message-type': cs.MT_NORMAL,
+ },
+ { 'content-type': 'text/plain',
+ 'content': 'Thriftweed?',
+ }]
+ chan.Messages.SendMessage(message, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY)
+
+ e = q.expect('stream-message', to=GUYBRUSH)
+ assertLength(1, list(e.stanza.elements(uri=ns.RECEIPTS, name='request')))
+
+def sending_request_to_cappy_contact(q, bus, conn, stream, chan):
+ """
+ Test that Gabble requests a receipt from a contact whom we know supports
+ this extension, but only if asked.
+ """
+
+ # Convince Gabble that Guybrush supports this extension
+ caps = { 'node': 'http://whatever',
+ 'ver': caps_helper.compute_caps_hash([], [ns.RECEIPTS], {}),
+ 'hash': 'sha-1',
+ }
+ caps_helper.presence_and_disco(q, conn, stream, GUYBRUSH_FULL_JID,
+ disco=True,
+ client=caps['node'],
+ caps=caps,
+ features=[ns.RECEIPTS])
+ sync_stream(q, stream)
+
+ # Don't ask, don't tell — even if we know Guybrush does support this.
+ not_sending_request_to_contact(q, bus, conn, stream, chan)
+
+ # Ask, tell.
+ message = [
+ { 'message-type': cs.MT_NORMAL,
+ },
+ { 'content-type': 'text/plain',
+ 'content': 'Ulysses?',
+ }]
+ chan.Messages.SendMessage(message, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY)
+
+ e = q.expect('stream-message', to=GUYBRUSH)
+ assertLength(1, list(e.stanza.elements(uri=ns.RECEIPTS, name='request')))
+
+def replying_to_requests(q, bus, conn, stream):
+ jid = 'lechuck@lucasarts.lit'
+
+ # We shouldn't send receipts to people who aren't on our roster.
+ q.forbid_events([EventPattern('stream-message', to=jid)])
+ stream.send(
+ elem('message', from_=jid, type='chat', id='alpha')(
+ elem('body')(
+ u"You didn't kill me, you moron!"
+ ),
+ elem(ns.RECEIPTS, 'request')
+ ))
+
+ q.expect('dbus-signal', signal='MessageReceived')
+ sync_stream(q, stream)
+ q.unforbid_all()
+
+ # We should send receipts to people on our roster, seeing as we're not
+ # invisible.
+ rostertest.send_roster_push(stream, jid, subscription='from')
+
+ stream.send(
+ elem('message', from_=jid, type='chat', id='beta')(
+ elem('body')(
+ u"You've just destroyed my spiritual essences."
+ ),
+ elem(ns.RECEIPTS, 'request')
+ ))
+ q.expect('dbus-signal', signal='MessageReceived')
+ e = q.expect('stream-message', to=jid)
+ receipt = e.stanza.elements(uri=ns.RECEIPTS, name='received').next()
+ assertEquals('beta', receipt['id'])
+
+ # We would like requests in messages without id=''s not to crash Gabble,
+ # and also for it not to send a reply.
+ q.forbid_events([EventPattern('stream-message', to=jid)])
+ stream.send(
+ elem('message', from_=jid, type='chat')( # NB. no id='' attribute
+ elem('body')(
+ u"A favor that I shall now return!"
+ ),
+ elem(ns.RECEIPTS, 'request')
+ ))
+ q.expect('dbus-signal', signal='MessageReceived')
+ sync_stream(q, stream)
+ q.unforbid_all()
+
+ # If we're invisible, LeChuck shouldn't get receipts.
+ conn.SimplePresence.SetPresence("hidden", "")
+ event = q.expect('stream-iq', query_name='invisible')
+ acknowledge_iq(stream, event.stanza)
+
+ q.forbid_events([EventPattern('stream-message', to=jid)])
+ stream.send(
+ elem('message', from_=jid, type='chat', id='epsilon')(
+ elem('body')(
+ u"… but where am I going to find a duck wearing burlap chaps?"
+ ),
+ elem(ns.RECEIPTS, 'request')
+ ))
+ q.expect('dbus-signal', signal='MessageReceived')
+ sync_stream(q, stream)
+ q.unforbid_all()
+
+def test(q, bus, conn, stream):
+ path = conn.Requests.CreateChannel(
+ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
+ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
+ cs.TARGET_ID: GUYBRUSH,
+ })[0]
+ chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text',
+ ['Messages'])
+
+ # Let's start out with an empty roster, eh?
+ e = q.expect('stream-iq', iq_type='get', query_ns=ns.ROSTER)
+ e.stanza['type'] = 'result'
+ stream.send(e.stanza)
+
+ report_received_on_open_channel(q, bus, conn, stream, chan)
+ report_ignored_without_channel(q, bus, conn, stream)
+ not_sending_request_to_contact(q, bus, conn, stream, chan)
+
+ # FIXME: This test is disabled because of stupidity in the presence cache.
+ # See the comment in receipts_conceivably_supported().
+ #sending_request_to_presenceless_contact(q, bus, conn, stream, chan)
+
+ sending_request_to_cappy_contact(q, bus, conn, stream, chan)
+
+ replying_to_requests(q, bus, conn, stream)
+
+
+if __name__ == '__main__':
+ exec_test(test, protocol=Xep0186Stream)
diff --git a/tests/twisted/text/test-chat-state.py b/tests/twisted/text/test-chat-state.py
index f161fd61d..c129fb7a3 100644
--- a/tests/twisted/text/test-chat-state.py
+++ b/tests/twisted/text/test-chat-state.py
@@ -6,8 +6,9 @@ channels.
from twisted.words.xish import domish
-from servicetest import assertEquals, assertNotEquals, \
- assertLength, wrap_channel, EventPattern
+from servicetest import (assertEquals, assertNotEquals,
+ assertLength, wrap_channel, EventPattern, call_async,
+ sync_dbus)
from gabbletest import exec_test, make_result_iq, sync_stream, make_presence
import constants as cs
import ns
@@ -70,24 +71,62 @@ def test(q, bus, conn, stream):
sync_stream(q, stream)
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(self_handle, cs.CHAT_STATE_INACTIVE))
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(foo_handle, cs.CHAT_STATE_INACTIVE))
+
# Receiving chat states:
# Composing...
stream.send(make_message(full_jid, state='composing'))
- changed = q.expect('dbus-signal', signal='ChatStateChanged')
+ changed = q.expect('dbus-signal', signal='ChatStateChanged',
+ path=chan.object_path)
handle, state = changed.args
assertEquals(foo_handle, handle)
assertEquals(cs.CHAT_STATE_COMPOSING, state)
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(self_handle, cs.CHAT_STATE_INACTIVE))
+ assertEquals(cs.CHAT_STATE_COMPOSING,
+ states.get(foo_handle, cs.CHAT_STATE_INACTIVE))
+
# Message!
stream.send(make_message(full_jid, body='hello', state='active'))
- changed = q.expect('dbus-signal', signal='ChatStateChanged')
+ changed = q.expect('dbus-signal', signal='ChatStateChanged',
+ path=chan.object_path)
handle, state = changed.args
assertEquals(foo_handle, handle)
assertEquals(cs.CHAT_STATE_ACTIVE, state)
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_INACTIVE,
+ states.get(self_handle, cs.CHAT_STATE_INACTIVE))
+ assertEquals(cs.CHAT_STATE_ACTIVE,
+ states.get(foo_handle, cs.CHAT_STATE_INACTIVE))
+
+ # Assert that a redundant chat-state change doesn't emit a signal
+
+ forbidden = [EventPattern('dbus-signal', signal='ChatStateChanged',
+ args=[foo_handle, cs.CHAT_STATE_ACTIVE])]
+ q.forbid_events(forbidden)
+
+ m = domish.Element((None, 'message'))
+ m['from'] = 'foo@bar.com/Foo'
+ m['type'] = 'chat'
+ m.addElement((ns.CHAT_STATES, 'active'))
+ m.addElement('body', content='hello')
+ stream.send(m)
+
+ sync_dbus(bus, q, conn)
+ sync_stream(q, stream)
+
+ q.unforbid_events(forbidden)
+
# Sending chat states:
# Composing...
@@ -96,6 +135,12 @@ def test(q, bus, conn, stream):
stream_message = q.expect('stream-message')
check_state_notification(stream_message.stanza, 'composing')
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_COMPOSING,
+ states.get(self_handle, cs.CHAT_STATE_INACTIVE))
+ assertEquals(cs.CHAT_STATE_ACTIVE,
+ states.get(foo_handle, cs.CHAT_STATE_INACTIVE))
+
# XEP 0085:
# every content message SHOULD contain an <active/> notification.
chan.Text.Send(0, 'hi.')
@@ -106,6 +151,12 @@ def test(q, bus, conn, stream):
check_state_notification(elem, 'active', allow_body=True)
+ states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates')
+ assertEquals(cs.CHAT_STATE_ACTIVE,
+ states.get(self_handle, cs.CHAT_STATE_INACTIVE))
+ assertEquals(cs.CHAT_STATE_ACTIVE,
+ states.get(foo_handle, cs.CHAT_STATE_INACTIVE))
+
def is_body(e):
if e.name == 'body':
assert e.children[0] == u'hi.', e.toXml()
@@ -172,7 +223,8 @@ def test(q, bus, conn, stream):
stream.send(make_message(full_jid, body='i am invisible', state='active'))
- changed = q.expect('dbus-signal', signal='ChatStateChanged')
+ changed = q.expect('dbus-signal', signal='ChatStateChanged',
+ path=chan.object_path)
assertEquals(cs.CHAT_STATE_ACTIVE, changed.args[1])
# We've seen them send a chat state notification, so we should send them
@@ -181,7 +233,8 @@ def test(q, bus, conn, stream):
stream_message = q.expect('stream-message', to=full_jid)
check_state_notification(stream_message.stanza, 'composing')
- changed = q.expect('dbus-signal', signal='ChatStateChanged')
+ changed = q.expect('dbus-signal', signal='ChatStateChanged',
+ path=chan.object_path)
handle, state = changed.args
assertEquals(cs.CHAT_STATE_COMPOSING, state)
assertEquals(self_handle, handle)
@@ -204,11 +257,18 @@ def test(q, bus, conn, stream):
['ChatState'])
# We shouldn't send any notifications until we actually send a message.
+ # But ChatStateChanged is still emitted locally
e = EventPattern('stream-message', to=jid)
q.forbid_events([e])
- for i in [cs.CHAT_STATE_COMPOSING, cs.CHAT_STATE_INACTIVE,
- cs.CHAT_STATE_PAUSED, cs.CHAT_STATE_ACTIVE]:
+ for i in [cs.CHAT_STATE_ACTIVE, cs.CHAT_STATE_COMPOSING,
+ cs.CHAT_STATE_PAUSED, cs.CHAT_STATE_INACTIVE ]:
chan.ChatState.SetChatState(i)
+ changed = q.expect('dbus-signal', signal='ChatStateChanged',
+ path=chan.object_path)
+ handle, state = changed.args
+ assertEquals(i, state)
+ assertEquals(self_handle, handle)
+
sync_stream(q, stream)
q.unforbid_events([e])
@@ -217,15 +277,23 @@ def test(q, bus, conn, stream):
stream_message = q.expect('stream-message', to=jid)
check_state_notification(stream_message.stanza, 'active', allow_body=True)
+ # The D-Bus property changes, too
+ changed = q.expect('dbus-signal', signal='ChatStateChanged',
+ path=chan.object_path)
+ handle, state = changed.args
+ assertEquals(cs.CHAT_STATE_ACTIVE, state)
+ assertEquals(self_handle, handle)
+
# We get a notification back from our contact.
stream.send(make_message(full_jid, state='composing'))
# Wait until gabble tells us the chat-state of the remote party has
# changed so we know gabble knows chat state notification are supported
- changed = q.expect('dbus-signal', signal='ChatStateChanged')
+ changed = q.expect('dbus-signal', signal='ChatStateChanged',
+ path=chan.object_path)
handle, state = changed.args
assertEquals(cs.CHAT_STATE_COMPOSING, state)
- assertNotEquals(self_handle, handle)
+ assertNotEquals(foo_handle, handle)
# So now we know they support notification, so should send notifications.
chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING)
@@ -244,6 +312,13 @@ def test(q, bus, conn, stream):
stream_message = q.expect('stream-message')
check_state_notification(stream_message.stanza, 'composing')
+ # The D-Bus property changes, too
+ changed = q.expect('dbus-signal', signal='ChatStateChanged',
+ path=chan.object_path)
+ handle, state = changed.args
+ assertEquals(cs.CHAT_STATE_COMPOSING, state)
+ assertEquals(self_handle, handle)
+
# But! Now they start messaging us from a different client, which *doesn't*
# support notifications.
other_jid = jid + '/Library'
diff --git a/tests/twisted/tls/server-tls-channel.py b/tests/twisted/tls/server-tls-channel.py
index 7823eacc5..6528e696d 100644
--- a/tests/twisted/tls/server-tls-channel.py
+++ b/tests/twisted/tls/server-tls-channel.py
@@ -47,8 +47,6 @@ class TlsAuthenticator(XmppAuthenticator):
starttls = features.addElement((ns.NS_XMPP_TLS, 'starttls'))
starttls.addElement('required')
- mechanisms = features.addElement((ns.NS_XMPP_SASL, 'mechanisms'))
- mechanism = mechanisms.addElement('mechanism', content='PLAIN')
self.xmlstream.send(features)
self.xmlstream.addOnetimeObserver("/starttls", self.tlsAuth)
@@ -64,19 +62,13 @@ class TlsAuthenticator(XmppAuthenticator):
self.streamTLS()
def tlsAuth(self, auth):
- try:
- file = open(CA_KEY, 'rb')
- pem_key = file.read()
+ with open(CA_KEY, 'rb') as f:
+ pem_key = f.read()
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, pem_key, "")
- finally:
- file.close()
- try:
- file = open(CA_CERT, 'rb')
- pem_cert = file.read()
+ with open(CA_CERT, 'rb') as f:
+ pem_cert = f.read()
cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem_cert)
- finally:
- file.close()
tls_ctx = ssl.CertificateOptions(privateKey=pkey, certificate=cert)
diff --git a/tests/twisted/tools/exec-with-log.sh.in b/tests/twisted/tools/exec-with-log.sh.in
index 11302e6f6..9210eecc5 100644
--- a/tests/twisted/tools/exec-with-log.sh.in
+++ b/tests/twisted/tools/exec-with-log.sh.in
@@ -14,6 +14,8 @@ WOCKY_CAPS_CACHE=:memory:
export WOCKY_CAPS_CACHE
WOCKY_CAPS_CACHE_SIZE=50
export WOCKY_CAPS_CACHE_SIZE
+G_MESSAGES_DEBUG=all
+export G_MESSAGES_DEBUG
ulimit -c unlimited
exec >> gabble-testing.log 2>&1
diff --git a/tests/twisted/tubes/accept-muc-dbus-tube.py b/tests/twisted/tubes/accept-muc-dbus-tube.py
index fb841c3ca..df5b81ed0 100644
--- a/tests/twisted/tubes/accept-muc-dbus-tube.py
+++ b/tests/twisted/tubes/accept-muc-dbus-tube.py
@@ -1,6 +1,9 @@
import dbus
-from servicetest import assertEquals, assertNotEquals, call_async, EventPattern
+from servicetest import (
+ assertEquals, assertNotEquals, assertSameSets,
+ call_async, EventPattern,
+)
from gabbletest import exec_test, acknowledge_iq, make_muc_presence
import constants as cs
@@ -37,20 +40,20 @@ def test(q, bus, conn, stream, access_control):
parameter.addContent('bar')
stream.send(presence)
- # tubes channel is created
- event = q.expect('dbus-signal', signal='NewChannels')
- channels = event.args[0]
- path, props = channels[0]
-
# tube channel is created
- event = q.expect('dbus-signal', signal='NewChannels')
+ def new_chan_predicate(e):
+ path, props = e.args[0][0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
+
+ event = q.expect('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate)
channels = event.args[0]
path, props = channels[0]
assertEquals(cs.CHANNEL_TYPE_DBUS_TUBE, props[cs.CHANNEL_TYPE])
assertEquals('chat@conf.localhost/bob', props[cs.INITIATOR_ID])
bob_handle = props[cs.INITIATOR_HANDLE]
- assertEquals([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE],
+ assertSameSets([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE],
props[cs.INTERFACES])
assertEquals(False, props[cs.REQUESTED])
assertEquals('chat@conf.localhost', props[cs.TARGET_ID])
diff --git a/tests/twisted/tubes/accept-muc-stream-tube.py b/tests/twisted/tubes/accept-muc-stream-tube.py
index 01e65fdb2..7fc4aa0a6 100644
--- a/tests/twisted/tubes/accept-muc-stream-tube.py
+++ b/tests/twisted/tubes/accept-muc-stream-tube.py
@@ -4,15 +4,14 @@ import sys
import dbus
-from servicetest import call_async, EventPattern, EventProtocolClientFactory, unwrap, assertEquals
-from gabbletest import make_result_iq, acknowledge_iq, make_muc_presence, send_error_reply, disconnect_conn
+from servicetest import call_async, EventPattern, assertEquals, assertSameSets
+from gabbletest import acknowledge_iq, make_muc_presence, send_error_reply, disconnect_conn
import constants as cs
import ns
import tubetestutil as t
from bytestream import create_from_si_offer, announce_socks5_proxy, BytestreamS5BRelay, BytestreamS5BRelayBugged
from twisted.words.xish import xpath
-from twisted.internet import reactor
sample_parameters = dbus.Dictionary({
's': 'hello',
@@ -49,8 +48,10 @@ def test(q, bus, conn, stream, bytestream_cls,
room_handle = handles[0]
# join the muc
- call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM,
- room_handle, True)
+ call_async(q, conn.Requests, 'CreateChannel', {
+ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
+ cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
+ cs.TARGET_HANDLE: room_handle})
_, stream_event = q.expect_many(
EventPattern('dbus-signal', signal='MembersChanged',
@@ -70,7 +71,7 @@ def test(q, bus, conn, stream, bytestream_cls,
assert conn.InspectHandles(1, [3]) == ['chat@conf.localhost/bob']
bob_handle = 3
- event = q.expect('dbus-return', method='RequestChannel')
+ event = q.expect('dbus-return', method='CreateChannel')
# Bob offers a stream tube
stream_tube_id = 666
@@ -112,51 +113,13 @@ def test(q, bus, conn, stream, bytestream_cls,
path, props = channels[0]
assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT
- # tubes channel is automatically created
- event, new_event = q.expect_many(
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'))
-
- assert event.args[1] == cs.CHANNEL_TYPE_TUBES, event.args
- assert event.args[2] == cs.HT_ROOM
- assert event.args[3] == room_handle
-
- tubes_chan = bus.get_object(conn.bus_name, event.args[0])
- tubes_iface = dbus.Interface(tubes_chan, event.args[1])
-
- channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE)
- assert channel_props['TargetID'] == 'chat@conf.localhost', channel_props
- assert channel_props['Requested'] == False
- assert channel_props['InitiatorID'] == ''
- assert channel_props['InitiatorHandle'] == 0
-
- channels = new_event.args[0]
- assert len(channels) == 1
- path, props = channels[0]
- assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES
-
- tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)
-
- q.expect('dbus-signal', signal='NewTube',
- args=[stream_tube_id, bob_handle, 1, 'echo', sample_parameters, 0])
-
- expected_tube = (stream_tube_id, bob_handle, cs.TUBE_TYPE_STREAM, 'echo',
- sample_parameters, cs.TUBE_STATE_LOCAL_PENDING)
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert tubes == [(
- stream_tube_id,
- bob_handle,
- 1, # Stream
- 'echo',
- sample_parameters,
- cs.TUBE_CHANNEL_STATE_LOCAL_PENDING
- )]
-
- assert len(tubes) == 1, unwrap(tubes)
- t.check_tube_in_tubes(expected_tube, tubes)
+ def new_chan_predicate(e):
+ path, props = e.args[0][0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
- # tube channel is also announced (new API)
- new_event = q.expect('dbus-signal', signal='NewChannels')
+ # tube channel is announced
+ new_event = q.expect('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate)
channels = new_event.args[0]
assert len(channels) == 1
@@ -164,7 +127,8 @@ def test(q, bus, conn, stream, bytestream_cls,
assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
assert props[cs.INITIATOR_HANDLE] == bob_handle
assert props[cs.INITIATOR_ID] == 'chat@conf.localhost/bob'
- assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE]
+ assertSameSets([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE],
+ props[cs.INTERFACES])
assert props[cs.REQUESTED] == False
assert props[cs.TARGET_HANDLE] == room_handle
assert props[cs.TARGET_ID] == 'chat@conf.localhost'
@@ -176,17 +140,18 @@ def test(q, bus, conn, stream, bytestream_cls,
tube_chan = bus.get_object(conn.bus_name, path)
tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE,
byte_arrays=True)
+ tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
assert tube_props['Parameters'] == sample_parameters
assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING
# Accept the tube
- call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id,
+ call_async(q, tube_iface, 'Accept',
address_type, access_control, access_control_param, byte_arrays=True)
accept_return_event, _ = q.expect_many(
- EventPattern('dbus-return', method='AcceptStreamTube'),
- EventPattern('dbus-signal', signal='TubeStateChanged',
- args=[stream_tube_id, 2]))
+ EventPattern('dbus-return', method='Accept'),
+ EventPattern('dbus-signal', signal='TubeChannelStateChanged',
+ args=[2]))
address = accept_return_event.value[0]
@@ -260,8 +225,7 @@ def test(q, bus, conn, stream, bytestream_cls,
assertEquals(cs.CANCELLED, e.args[1])
# OK, we're done
- disconnect_conn(q, conn, stream,
- [EventPattern('dbus-signal', signal='TubeClosed', args=[stream_tube_id])])
+ disconnect_conn(q, conn, stream)
if __name__ == '__main__':
t.exec_stream_tube_test(test)
diff --git a/tests/twisted/tubes/accept-private-dbus-tube.py b/tests/twisted/tubes/accept-private-dbus-tube.py
index 82e81118c..dbbeb3bed 100644
--- a/tests/twisted/tubes/accept-private-dbus-tube.py
+++ b/tests/twisted/tubes/accept-private-dbus-tube.py
@@ -81,66 +81,21 @@ def test(q, bus, conn, stream, bytestream_cls, access_control):
# RequestChannel are the ones we wanted.
sync_dbus(bus, q, conn)
- # let's try to accept a D-Bus tube using the old API
- bytestream = bytestream_cls(stream, q, 'beta', bob_full_jid,
- 'test@localhost/Reource', True)
-
- last_tube_id += 1
- contact_offer_dbus_tube(bytestream, last_tube_id)
-
- # tubes channel is created
- event = q.expect('dbus-signal', signal='NewChannel')
-
bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@localhost'])[0]
- t.check_NewChannel_signal(event.args, cs.CHANNEL_TYPE_TUBES, None,
- bob_handle, False)
-
- tubes_chan = bus.get_object(conn.bus_name, event.args[0])
- tubes_iface = dbus.Interface(tubes_chan, cs.CHANNEL_TYPE_TUBES)
-
- event = q.expect('dbus-signal', signal='NewTube')
- id = event.args[0]
- initiator = event.args[1]
- type = event.args[2]
- service = event.args[3]
- parameters = event.args[4]
- state = event.args[5]
-
- assertEquals (last_tube_id, id)
- initiator_jid = conn.InspectHandles(1, [initiator])[0]
- assert initiator_jid == 'bob@localhost'
- assert type == cs.TUBE_TYPE_DBUS
- assert service == 'com.example.TestCase2'
- assert parameters == {'login': 'TEST'}
- assert state == cs.TUBE_STATE_LOCAL_PENDING
-
- # accept the tube (old API)
- call_async(q, tubes_iface, 'AcceptDBusTube', id)
-
- event = q.expect('stream-iq', iq_type='result')
- bytestream.check_si_reply(event.stanza)
- tube = xpath.queryForNodes('/iq/si/tube[@xmlns="%s"]' % ns.TUBES,
- event.stanza)
- assert len(tube) == 1
-
- # Init the bytestream
- events, _ = bytestream.open_bytestream([EventPattern('dbus-return', method='AcceptDBusTube')],
- [EventPattern('dbus-signal', signal='TubeStateChanged',
- args=[last_tube_id, 2])])
-
- return_event = events[0]
- address = return_event.value[0]
- assert len(address) > 0
-
- # OK, now let's try to accept a D-Bus tube using the new API
+ # let's try to accept a D-Bus tube using the new API
bytestream = bytestream_cls(stream, q, 'gamma', bob_full_jid,
self_full_jid, True)
last_tube_id += 1
contact_offer_dbus_tube(bytestream, last_tube_id)
- e = q.expect('dbus-signal', signal='NewChannels')
+ def new_chan_predicate(e):
+ path, props = e.args[0][0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
+
+ e = q.expect('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate)
channels = e.args[0]
assert len(channels) == 1
path, props = channels[0]
diff --git a/tests/twisted/tubes/accept-private-stream-tube.py b/tests/twisted/tubes/accept-private-stream-tube.py
index 58f3558ae..37ed1693d 100644
--- a/tests/twisted/tubes/accept-private-stream-tube.py
+++ b/tests/twisted/tubes/accept-private-stream-tube.py
@@ -24,54 +24,37 @@ bob_jid = 'bob@localhost/Bob'
stream_tube_id = 49
def receive_tube_offer(q, bus, conn, stream):
+ global stream_tube_id
message = domish.Element(('jabber:client', 'message'))
message['to'] = 'test@localhost/Resource'
message['from'] = bob_jid
tube_node = message.addElement((ns.TUBES, 'tube'))
tube_node['type'] = 'stream'
tube_node['service'] = 'http'
+ stream_tube_id += 1
tube_node['id'] = str(stream_tube_id)
stream.send(message)
- old_sig, new_sig = q.expect_many(
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
- )
- chan_path = old_sig.args[0]
- assert old_sig.args[1] == cs.CHANNEL_TYPE_TUBES, old_sig.args[1]
- assert old_sig.args[2] == cs.HT_CONTACT
- bob_handle = old_sig.args[3]
- assert old_sig.args[2] == 1, old_sig.args[2] # Suppress_Handler
- assert len(new_sig.args) == 1
- assert len(new_sig.args[0]) == 1
- assert new_sig.args[0][0][0] == chan_path, new_sig.args[0][0]
- assert new_sig.args[0][0][1] is not None
-
- event = q.expect('dbus-signal', signal='NewTube')
-
- old_sig, new_sig = q.expect_many(
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
- )
- new_chan_path = old_sig.args[0]
- assert new_chan_path != chan_path
- assert old_sig.args[1] == cs.CHANNEL_TYPE_STREAM_TUBE, old_sig.args[1]
- assert old_sig.args[2] == cs.HT_CONTACT
- bob_handle = old_sig.args[3]
- assert old_sig.args[2] == 1, old_sig.args[2] # Suppress_Handler
+ def new_chan_predicate(e):
+ path, props = e.args[0][0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
+
+ new_sig = q.expect('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate)
+
assert len(new_sig.args) == 1
assert len(new_sig.args[0]) == 1
- assert new_sig.args[0][0][0] == new_chan_path, new_sig.args[0][0]
- assert new_sig.args[0][0][1] is not None
- # create channel proxies
- tubes_chan = bus.get_object(conn.bus_name, chan_path)
- tubes_iface = dbus.Interface(tubes_chan, cs.CHANNEL_TYPE_TUBES)
+ path, props = new_sig.args[0][0]
+ assertEquals(cs.CHANNEL_TYPE_STREAM_TUBE, props[cs.CHANNEL_TYPE])
+ assertEquals(cs.HT_CONTACT, props[cs.TARGET_HANDLE_TYPE])
+ assertEquals(False, props[cs.REQUESTED])
- new_tube_chan = bus.get_object(conn.bus_name, new_chan_path)
+ # create channel proxies
+ new_tube_chan = bus.get_object(conn.bus_name, path)
new_tube_iface = dbus.Interface(new_tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
- return (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface)
+ return (new_tube_chan, new_tube_iface)
def expect_tube_activity(q, bus, conn, stream, bytestream_cls, address_type,
address, access_control, access_control_param):
@@ -157,20 +140,9 @@ def test(q, bus, conn, stream, bytestream_cls,
sync_dbus(bus, q, conn)
# Receive a tube offer from Bob
- (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
+ (new_tube_chan, new_tube_iface) = \
receive_tube_offer(q, bus, conn, stream)
- # Try bad parameters on the old iface
- call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id+1, 2, 0, '',
- byte_arrays=True)
- q.expect('dbus-error', method='AcceptStreamTube')
- call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 2, 1, '',
- byte_arrays=True)
- q.expect('dbus-error', method='AcceptStreamTube')
- call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 20, 0, '',
- byte_arrays=True)
- q.expect('dbus-error', method='AcceptStreamTube')
-
# Try bad parameters on the new iface
call_async(q, new_tube_iface, 'Accept', 20, 0, '',
byte_arrays=True)
@@ -179,69 +151,8 @@ def test(q, bus, conn, stream, bytestream_cls,
byte_arrays=True)
q.expect('dbus-error', method='Accept')
- # Accept the tube with old iface
- call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, address_type,
- access_control, access_control_param, byte_arrays=True)
-
- accept_return_event, _ = q.expect_many(
- EventPattern('dbus-return', method='AcceptStreamTube'),
- EventPattern('dbus-signal', signal='TubeStateChanged',
- args=[stream_tube_id, 2]))
-
- socket_address = accept_return_event.value[0]
-
- bytestream, conn_id = expect_tube_activity(q, bus, conn, stream, bytestream_cls,
- address_type, socket_address, access_control, access_control_param)
-
- tubes_chan.Close()
- bytestream.wait_bytestream_closed()
-
- # Receive a tube offer from Bob
- (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
- receive_tube_offer(q, bus, conn, stream)
-
- # Accept the tube with old iface, and use UNIX sockets
- call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id,
- address_type, access_control, access_control_param, byte_arrays=True)
-
- accept_return_event, _ = q.expect_many(
- EventPattern('dbus-return', method='AcceptStreamTube'),
- EventPattern('dbus-signal', signal='TubeStateChanged',
- args=[stream_tube_id, 2]))
-
- socket_address = accept_return_event.value[0]
-
- bytestream, conn_id = expect_tube_activity(q, bus, conn, stream, bytestream_cls,
- address_type, socket_address, access_control, access_control_param)
- tubes_chan.Close()
- bytestream.wait_bytestream_closed()
-
- # Receive a tube offer from Bob
- (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
- receive_tube_offer(q, bus, conn, stream)
-
- # Accept the tube with new iface, and use IPv4
- call_async(q, new_tube_iface, 'Accept', address_type,
- access_control, access_control_param, byte_arrays=True)
-
- accept_return_event, _ = q.expect_many(
- EventPattern('dbus-return', method='Accept'),
- EventPattern('dbus-signal', signal='TubeStateChanged',
- args=[stream_tube_id, 2]))
-
- socket_address = accept_return_event.value[0]
-
- bytestream, conn_id = expect_tube_activity(q, bus, conn, stream, bytestream_cls,
- address_type, socket_address, access_control, access_control_param)
- tubes_chan.Close()
- e, _ = bytestream.wait_bytestream_closed([
- EventPattern('dbus-signal', signal='ConnectionClosed'),
- EventPattern('socket-disconnected')])
- assertEquals(conn_id, e.args[0])
- assertEquals(cs.CANCELLED, e.args[1])
-
# Receive a tube offer from Bob
- (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
+ (new_tube_chan, new_tube_iface) = \
receive_tube_offer(q, bus, conn, stream)
# Accept the tube with new iface, and use UNIX sockets
@@ -250,8 +161,8 @@ def test(q, bus, conn, stream, bytestream_cls,
accept_return_event, _ = q.expect_many(
EventPattern('dbus-return', method='Accept'),
- EventPattern('dbus-signal', signal='TubeStateChanged',
- args=[stream_tube_id, 2]))
+ EventPattern('dbus-signal', signal='TubeChannelStateChanged',
+ args=[2]))
socket_address = accept_return_event.value[0]
@@ -274,16 +185,10 @@ def test(q, bus, conn, stream, bytestream_cls,
assertEquals(conn_id, e.args[0])
assertEquals(cs.CONNECTION_REFUSED, e.args[1])
- tubes_chan.Close()
-
- # Receive a tube offer from Bob
- (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
- receive_tube_offer(q, bus, conn, stream)
- # Just close the tube
- tubes_chan.Close()
+ new_tube_chan.Close()
# Receive a tube offer from Bob
- (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
+ (new_tube_chan, new_tube_iface) = \
receive_tube_offer(q, bus, conn, stream)
# Just close the tube
new_tube_chan.Close()
diff --git a/tests/twisted/tubes/check-create-tube-return.py b/tests/twisted/tubes/check-create-tube-return.py
index 2a3a6304b..46db340c4 100644
--- a/tests/twisted/tubes/check-create-tube-return.py
+++ b/tests/twisted/tubes/check-create-tube-return.py
@@ -74,29 +74,5 @@ def test(q, bus, conn, stream):
assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM)
assertEquals(props[cs.TARGET_ID], muc)
- # Now make sure we can get our Tubes channel if we request it.
- muc = 'chat3@conf.localhost'
-
- call_async(q, conn.Requests, 'CreateChannel',
- { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TUBES,
- cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
- cs.TARGET_ID: muc})
-
- q.expect('stream-presence', to='%s/test' % muc)
- stream.send(make_muc_presence('owner', 'moderator', muc, 'bob'))
- stream.send(make_muc_presence('none', 'participant', muc, 'test'))
-
- ret, _, _ = q.expect_many(
- EventPattern('dbus-return', method='CreateChannel'),
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
- )
-
- _, props = ret.value
-
- assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_TUBES)
- assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM)
- assertEquals(props[cs.TARGET_ID], muc)
-
if __name__ == '__main__':
exec_test(test)
diff --git a/tests/twisted/tubes/close-muc-with-closed-tube.py b/tests/twisted/tubes/close-muc-with-closed-tube.py
index bcebe77f1..ed08add64 100644
--- a/tests/twisted/tubes/close-muc-with-closed-tube.py
+++ b/tests/twisted/tubes/close-muc-with-closed-tube.py
@@ -2,7 +2,7 @@
import dbus
-from servicetest import call_async, EventPattern, unwrap
+from servicetest import call_async, EventPattern, unwrap, assertEquals
from gabbletest import exec_test, make_result_iq, acknowledge_iq, make_muc_presence
import constants as cs
import ns
@@ -84,43 +84,28 @@ def test(q, bus, conn, stream):
stream.send(presence)
- # tubes channel is automatically created
- event = q.expect('dbus-signal', signal='NewChannel')
+ def new_chan_predicate(e):
+ path, props = e.args[0][0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
- if event.args[1] == cs.CHANNEL_TYPE_TEXT:
- # skip this one, try the next one
- event = q.expect('dbus-signal', signal='NewChannel')
+ # tube channel is automatically created
+ event = q.expect('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate)
- assert event.args[1] == cs.CHANNEL_TYPE_TUBES, event.args
- assert event.args[2] == cs.HT_ROOM
- assert event.args[3] == room_handle
+ path, props = event.args[0][0]
- tubes_chan = bus.get_object(conn.bus_name, event.args[0])
- tubes_iface = dbus.Interface(tubes_chan, event.args[1])
+ assertEquals(cs.CHANNEL_TYPE_DBUS_TUBE, props[cs.CHANNEL_TYPE])
+ assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE])
+ assertEquals(room_handle, props[cs.TARGET_HANDLE])
+ assertEquals('chat@conf.localhost', props[cs.TARGET_ID])
+ assertEquals(False, props[cs.REQUESTED])
- channel_props = tubes_chan.GetAll(
- cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE)
- assert channel_props['TargetID'] == 'chat@conf.localhost', channel_props
- assert channel_props['Requested'] == False
- assert channel_props['InitiatorID'] == ''
- assert channel_props['InitiatorHandle'] == 0
-
- tubes_self_handle = tubes_chan.GetSelfHandle(
- dbus_interface=cs.CHANNEL_IFACE_GROUP)
-
- q.expect('dbus-signal', signal='NewTube',
- args=[tube_id, bob_handle, 0, 'org.telepathy.freedesktop.test', sample_parameters, 0])
-
- expected_tube = (tube_id, bob_handle, cs.TUBE_TYPE_DBUS,
- 'org.telepathy.freedesktop.test', sample_parameters,
- cs.TUBE_STATE_LOCAL_PENDING)
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert len(tubes) == 1, unwrap(tubes)
- t.check_tube_in_tubes(expected_tube, tubes)
+ tube_chan = bus.get_object(conn.bus_name, path)
+ tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE)
# reject the tube
- tubes_iface.CloseTube(tube_id)
- q.expect('dbus-signal', signal='TubeClosed', args=[tube_id])
+ tube_iface.Close(dbus_interface=cs.CHANNEL)
+ q.expect('dbus-signal', signal='ChannelClosed')
# close the text channel
text_chan.Close()
diff --git a/tests/twisted/tubes/crash-on-list-channels.py b/tests/twisted/tubes/crash-on-list-channels.py
deleted file mode 100644
index b2532e515..000000000
--- a/tests/twisted/tubes/crash-on-list-channels.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""
-Regression test for a bug where calling ListChannels with an open old-skool
-DBus tube asserted.
-"""
-
-import dbus
-
-from servicetest import call_async, EventPattern
-from gabbletest import exec_test, sync_stream, make_result_iq
-
-import ns
-import constants as cs
-
-from twisted.words.xish import domish
-
-jid = 'explosions@in.the.sky'
-
-def test(q, bus, conn, stream):
- roster_event = q.expect('stream-iq', query_ns=ns.ROSTER)
-
- roster = roster_event.stanza
- roster['type'] = 'result'
- item = roster_event.query.addElement('item')
- item['jid'] = jid
- item['subscription'] = 'both'
- stream.send(roster)
-
- presence = domish.Element(('jabber:client', 'presence'))
- presence['from'] = '%s/Bob' % jid
- presence['to'] = 'test@localhost/Resource'
- c = presence.addElement('c')
- c['xmlns'] = ns.CAPS
- c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy'
- c['ver'] = '1.2.3'
- stream.send(presence)
-
- event = q.expect('stream-iq', iq_type='get',
- query_ns=ns.DISCO_INFO,
- to=('%s/Bob' % jid))
- assert event.query['node'] == \
- 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3'
- result = make_result_iq(stream, event.stanza)
- query = result.firstChildElement()
- feature = query.addElement('feature')
- feature['var'] = ns.TUBES
- stream.send(result)
-
- sync_stream(q, stream)
-
- h = conn.RequestHandles(cs.HT_CONTACT, [jid])[0]
- tubes_path = conn.RequestChannel(
- cs.CHANNEL_TYPE_TUBES, cs.HT_CONTACT, h, True)
-
- tubes_chan = bus.get_object(conn.bus_name, tubes_path)
- tubes_iface = dbus.Interface(tubes_chan, cs.CHANNEL_TYPE_TUBES)
-
- tubes_iface.OfferDBusTube('bong.hits', dbus.Dictionary({}, signature='sv'))
-
- conn.ListChannels()
-
-if __name__ == '__main__':
- exec_test(test)
diff --git a/tests/twisted/tubes/ensure-si-tube.py b/tests/twisted/tubes/ensure-si-tube.py
index 9330fa7c8..dccb337cc 100644
--- a/tests/twisted/tubes/ensure-si-tube.py
+++ b/tests/twisted/tubes/ensure-si-tube.py
@@ -4,7 +4,7 @@ Test support for creating and retrieving 1-1 tubes with EnsureChannel
import dbus
-from servicetest import call_async, EventPattern, tp_name_prefix
+from servicetest import call_async, EventPattern, tp_name_prefix, unwrap
from gabbletest import exec_test, acknowledge_iq
import constants as cs
import ns
@@ -27,12 +27,12 @@ def test(q, bus, conn, stream):
properties = conn.GetAll(
cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE)
assert properties.get('Channels') == [], properties['Channels']
- assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TUBES,
+ assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
},
- [cs.TARGET_HANDLE, cs.TARGET_ID]
+ [cs.TARGET_HANDLE, cs.TARGET_ID, cs.STREAM_TUBE_SERVICE]
) in properties.get('RequestableChannelClasses'),\
- properties['RequestableChannelClasses']
+ unwrap(properties['RequestableChannelClasses'])
_, vcard_event, roster_event = q.expect_many(
EventPattern('dbus-signal', signal='StatusChanged',
@@ -72,48 +72,58 @@ def test(q, bus, conn, stream):
bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0]
- call_async(q, conn, 'RequestChannel',
- cs.CHANNEL_TYPE_TUBES, cs.HT_CONTACT, bob_handle, True);
+ def new_chan_predicate(e):
+ types = []
+ for _, props in e.args[0]:
+ types.append(props[cs.CHANNEL_TYPE])
- ret, old_sig, new_sig = q.expect_many(
- EventPattern('dbus-return', method='RequestChannel'),
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
- )
+ return cs.CHANNEL_TYPE_STREAM_TUBE in types
+ call_async(q, conn.Requests, 'CreateChannel',
+ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
+ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
+ cs.TARGET_HANDLE: bob_handle,
+ cs.STREAM_TUBE_SERVICE: 'the.service',
+ })
+
+ ret, _ = q.expect_many(
+ EventPattern('dbus-return', method='CreateChannel'),
+ EventPattern('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate),
+ )
- assert len(ret.value) == 1
- chan_path = ret.value[0]
+ chan_path, props = ret.value
# Ensure a tube to the same person; check it's the same one.
- call_async(q, conn.Requests, 'EnsureChannel',
- { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TUBES,
- cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
- cs.TARGET_HANDLE: bob_handle
- })
+# call_async(q, conn.Requests, 'EnsureChannel',
+# { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
+# cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
+# cs.TARGET_HANDLE: bob_handle,
+# cs.STREAM_TUBE_SERVICE: 'the.service',
+# })
- ret = q.expect('dbus-return', method='EnsureChannel')
- yours, ensured_path, _ = ret.value
+# ret = q.expect('dbus-return', method='EnsureChannel')
+# yours, ensured_path, _ = ret.value
- assert ensured_path == chan_path, (ensured_path, chan_path)
- assert not yours
+# assert ensured_path == chan_path, (ensured_path, chan_path)
+# assert not yours
chan = bus.get_object(conn.bus_name, chan_path)
chan.Close()
-
# Now let's try ensuring a new tube.
call_async(q, conn.Requests, 'EnsureChannel',
- { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TUBES,
+ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
- cs.TARGET_HANDLE: bob_handle
+ cs.TARGET_HANDLE: bob_handle,
+ cs.STREAM_TUBE_SERVICE: 'the.service',
})
- ret, old_sig, new_sig = q.expect_many(
+ ret, new_sig = q.expect_many(
EventPattern('dbus-return', method='EnsureChannel'),
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
+ EventPattern('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate),
)
yours, path, props = ret.value
diff --git a/tests/twisted/tubes/muc-presence.py b/tests/twisted/tubes/muc-presence.py
deleted file mode 100644
index 8efcb8780..000000000
--- a/tests/twisted/tubes/muc-presence.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""
-Regression test for a bug where, if you had any MUC Tubes channels open and
-changed your presence, a GabbleMucChannel method was called on a
-GabbleTubesChannel, crashing Gabble.
-"""
-
-from gabbletest import exec_test
-import constants as cs
-
-from muctubeutil import get_muc_tubes_channel
-
-def test(q, bus, conn, stream):
- handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn,
- stream, 'chat@conf.localhost')
-
- conn.SimplePresence.SetPresence('away', 'Christmas lunch!')
-
-if __name__ == '__main__':
- exec_test(test)
diff --git a/tests/twisted/tubes/muctubeutil.py b/tests/twisted/tubes/muctubeutil.py
deleted file mode 100644
index 61fa41f88..000000000
--- a/tests/twisted/tubes/muctubeutil.py
+++ /dev/null
@@ -1,89 +0,0 @@
-import dbus
-
-from servicetest import call_async, EventPattern, tp_name_prefix
-from gabbletest import make_result_iq, make_muc_presence
-import constants as cs
-
-def get_muc_tubes_channel(q, bus, conn, stream, muc_jid, anonymous=True):
- """
- Returns a singleton list containing the MUC's handle, a proxy for the Tubes
- channel, and a proxy for the Tubes iface on that channel.
- """
- muc_server = muc_jid.split('@')[1]
- test_jid = muc_jid + "/test"
- bob_jid = muc_jid + "/bob"
-
- self_handle = conn.GetSelfHandle()
- self_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0]
-
- call_async(q, conn, 'RequestHandles', cs.HT_ROOM, [muc_jid])
-
- event = q.expect('dbus-return', method='RequestHandles')
- handles = event.value[0]
- room_handle = handles[0]
-
- # request tubes channel
- call_async(q, conn, 'RequestChannel',
- tp_name_prefix + '.Channel.Type.Tubes', cs.HT_ROOM, room_handle, True)
-
- _, stream_event = q.expect_many(
- EventPattern('dbus-signal', signal='MembersChanged',
- args=[u'', [], [], [], [2], 0, 0]),
- EventPattern('stream-presence', to=test_jid))
-
- # Send presence for other member of room.
- if not anonymous:
- real_jid = 'bob@localhost'
- else:
- real_jid = None
-
- stream.send(make_muc_presence('owner', 'moderator', muc_jid, 'bob', real_jid))
-
- # Send presence for own membership of room.
- stream.send(make_muc_presence('none', 'participant', muc_jid, 'test'))
-
- q.expect('dbus-signal', signal='MembersChanged',
- args=[u'', [2, 3], [], [], [], 0, 0])
-
- assert conn.InspectHandles(cs.HT_CONTACT, [2]) == [test_jid]
- assert conn.InspectHandles(cs.HT_CONTACT, [3]) == [bob_jid]
-
- # text and tubes channels are created
- # FIXME: We can't check NewChannel signals (old API) because two of them
- # would be fired and we can't catch twice the same signals without specifying
- # all their arguments.
- new_sig, returned = q.expect_many(
- EventPattern('dbus-signal', signal='NewChannels'),
- EventPattern('dbus-return', method='RequestChannel'))
-
- channels = new_sig.args[0]
- assert len(channels) == 2
-
- for channel in channels:
- path, props = channel
- type = props[cs.CHANNEL_TYPE]
-
- if type == cs.CHANNEL_TYPE_TEXT:
- # check text channel properties
- assert props[cs.TARGET_HANDLE] == room_handle
- assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
- assert props[cs.TARGET_ID] == 'chat@conf.localhost'
- assert props[cs.REQUESTED] == False
- assert props[cs.INITIATOR_HANDLE] == self_handle
- assert props[cs.INITIATOR_ID] == self_name
- elif type == cs.CHANNEL_TYPE_TUBES:
- # check tubes channel properties
- assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
- assert props[cs.TARGET_HANDLE] == room_handle
- assert props[cs.TARGET_ID] == 'chat@conf.localhost'
- assert props[cs.REQUESTED] == True
- assert props[cs.INITIATOR_HANDLE] == self_handle
- assert props[cs.INITIATOR_ID] == self_name
- else:
- assert True
-
- tubes_chan = bus.get_object(conn.bus_name, returned.value[0])
- tubes_iface = dbus.Interface(tubes_chan,
- tp_name_prefix + '.Channel.Type.Tubes')
-
- return (room_handle, tubes_chan, tubes_iface)
diff --git a/tests/twisted/tubes/offer-muc-dbus-tube.py b/tests/twisted/tubes/offer-muc-dbus-tube.py
index 199fa3d6b..06ccc2804 100644
--- a/tests/twisted/tubes/offer-muc-dbus-tube.py
+++ b/tests/twisted/tubes/offer-muc-dbus-tube.py
@@ -15,7 +15,6 @@ import tubetestutil as t
from twisted.words.xish import xpath
from mucutil import join_muc, echo_muc_presence
-from muctubeutil import get_muc_tubes_channel
sample_parameters = dbus.Dictionary({
's': 'hello',
@@ -24,7 +23,7 @@ sample_parameters = dbus.Dictionary({
'i': dbus.Int32(-123),
}, signature='sv')
-def check_tube_in_presence(presence, dbus_tube_id, initiator):
+def check_tube_in_presence(presence, initiator):
tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]'
% ns.TUBES, presence)
assert tubes_nodes is not None
@@ -39,7 +38,7 @@ def check_tube_in_presence(presence, dbus_tube_id, initiator):
assert tube['service'] == 'com.example.TestCase'
dbus_stream_id = tube['stream-id']
my_bus_name = tube['dbus-name']
- assert tube['id'] == str(dbus_tube_id)
+ dbus_tube_id = tube['id']
params = {}
parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
@@ -52,7 +51,7 @@ def check_tube_in_presence(presence, dbus_tube_id, initiator):
'u': ('uint', '123'),
}
- return dbus_stream_id, my_bus_name
+ return dbus_stream_id, my_bus_name, dbus_tube_id
def fire_signal_on_tube(q, tube, chatroom, dbus_stream_id, my_bus_name):
@@ -118,85 +117,6 @@ def test(q, bus, conn, stream, access_control):
self_handle = conn.GetSelfHandle()
self_name = conn.InspectHandles(1, [self_handle])[0]
- handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn,
- stream, 'chat@conf.localhost')
-
- # Exercise basic Channel Properties from spec 0.17.7
- channel_props = tubes_chan.GetAll(cs.CHANNEL,
- dbus_interface=dbus.PROPERTIES_IFACE)
- assert channel_props.get('TargetHandle') == handle,\
- (channel_props.get('TargetHandle'), handle)
- assert channel_props.get('TargetHandleType') == 2,\
- channel_props.get('TargetHandleType')
- assert channel_props.get('ChannelType') == cs.CHANNEL_TYPE_TUBES,\
- channel_props.get('ChannelType')
- assert 'Interfaces' in channel_props, channel_props
- assert cs.CHANNEL_IFACE_GROUP in channel_props['Interfaces'], \
- channel_props['Interfaces']
- assert channel_props['TargetID'] == 'chat@conf.localhost', channel_props
- assert channel_props['Requested'] == True
- assert channel_props['InitiatorID'] == 'test@localhost'
- assert channel_props['InitiatorHandle'] == conn.GetSelfHandle()
-
- # Exercise Group Properties from spec 0.17.6 (in a basic way)
- group_props = tubes_chan.GetAll(cs.CHANNEL_IFACE_GROUP,
- dbus_interface=dbus.PROPERTIES_IFACE)
- assert 'SelfHandle' in group_props, group_props
- assert 'HandleOwners' in group_props, group_props
- assert 'Members' in group_props, group_props
- assert 'LocalPendingMembers' in group_props, group_props
- assert 'RemotePendingMembers' in group_props, group_props
- assert 'GroupFlags' in group_props, group_props
-
- tubes_self_handle = tubes_chan.GetSelfHandle(
- dbus_interface=cs.CHANNEL_IFACE_GROUP)
- assert group_props['SelfHandle'] == tubes_self_handle
-
- # Offer a D-Bus tube (old API)
- call_async(q, tubes_iface, 'OfferDBusTube',
- 'com.example.TestCase', sample_parameters)
-
- new_tube_event, presence_event, offer_return_event, dbus_changed_event = \
- q.expect_many(
- EventPattern('dbus-signal', signal='NewTube'),
- EventPattern('stream-presence', to='chat@conf.localhost/test'),
- EventPattern('dbus-return', method='OfferDBusTube'),
- EventPattern('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_TUBES))
-
- # handle new_tube_event
- dbus_tube_id = new_tube_event.args[0]
- assert new_tube_event.args[1] == tubes_self_handle
- assert new_tube_event.args[2] == cs.TUBE_TYPE_DBUS
- assert new_tube_event.args[3] == 'com.example.TestCase'
- assert new_tube_event.args[4] == sample_parameters
- assert new_tube_event.args[5] == cs.TUBE_STATE_OPEN
-
- # handle offer_return_event
- assert offer_return_event.value[0] == dbus_tube_id
-
- # handle presence_event
- # We announce our newly created tube in our muc presence
- presence = presence_event.stanza
- dbus_stream_id, my_bus_name = check_tube_in_presence(presence, dbus_tube_id, 'chat@conf.localhost/test')
-
- # handle dbus_changed_event
- assert dbus_changed_event.args[0] == dbus_tube_id
- assert dbus_changed_event.args[1][0][0] == tubes_self_handle
- assert dbus_changed_event.args[1][0][1] == my_bus_name
-
- # handle offer_return_event
- assert dbus_tube_id == offer_return_event.value[0]
-
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert len(tubes) == 1
- expected_tube = (dbus_tube_id, tubes_self_handle, cs.TUBE_TYPE_DBUS,
- 'com.example.TestCase', sample_parameters, cs.TUBE_STATE_OPEN)
- t.check_tube_in_tubes(expected_tube, tubes)
-
- dbus_tube_adr = tubes_iface.GetDBusTubeAddress(dbus_tube_id)
- tube = Connection(dbus_tube_adr)
- fire_signal_on_tube(q, tube, 'chat@conf.localhost', dbus_stream_id, my_bus_name)
-
# offer a D-Bus tube to another room using new API
muc = 'chat2@conf.localhost'
request = {
@@ -207,72 +127,19 @@ def test(q, bus, conn, stream, access_control):
}
join_muc(q, bus, conn, stream, muc, request=request)
- # The order in which the NewChannels signals are fired is
- # undefined -- it could be the (tubes, text) channels first, or it
- # could be the tube channel first; so let's accept either order
- # here.
-
- first, second = q.expect_many(
- EventPattern('dbus-signal', signal='NewChannels'),
- EventPattern('dbus-signal', signal='NewChannels'))
-
- # NewChannels signal with the text and tubes channels together.
- def nc_textandtubes(event):
- channels = event.args[0]
- assert len(channels) == 2
- path1, prop1 = channels[0]
- path2, prop2 = channels[1]
- assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == \
- [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES]
-
- got_text, got_tubes = False, False
- for path, props in channels:
- if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT:
- got_text = True
-
- text_chan = dbus.Interface(bus.get_object(conn.bus_name, path),
- cs.CHANNEL)
- elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
- got_tubes = True
-
- tubes_iface = dbus.Interface(bus.get_object(conn.bus_name, path),
- cs.CHANNEL_TYPE_TUBES)
- else:
- assert False
-
- assert props[cs.INITIATOR_HANDLE] == self_handle
- assert props[cs.INITIATOR_ID] == self_name
- assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES]
- assert props[cs.TARGET_ID] == 'chat2@conf.localhost'
- assert props[cs.REQUESTED] == False
-
- assert (got_text, got_tubes) == (True, True)
-
- return text_chan
-
- # NewChannels signal with the tube channel.
- def nc_tube(event):
- # FIXME: in this case, all channels should probably be announced together
- channels = event.args[0]
- assert len(channels) == 1
- path, prop = channels[0]
- assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
- assert prop[cs.INITIATOR_ID] == 'chat2@conf.localhost/test'
- assert prop[cs.REQUESTED] == True
- assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
- assert prop[cs.TARGET_ID] == 'chat2@conf.localhost'
- assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
- assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [cs.SOCKET_ACCESS_CONTROL_CREDENTIALS,
- cs.SOCKET_ACCESS_CONTROL_LOCALHOST]
-
- return path, prop
+ e = q.expect('dbus-signal', signal='NewChannels')
- if len(first.args[0]) == 1:
- path, prop = nc_tube(first)
- text_chan = nc_textandtubes(second)
- else:
- text_chan = nc_textandtubes(first)
- path, prop = nc_tube(second)
+ channels = e.args[0]
+ assert len(channels) == 1
+ path, prop = channels[0]
+ assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
+ assert prop[cs.INITIATOR_ID] == 'chat2@conf.localhost/test'
+ assert prop[cs.REQUESTED] == True
+ assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
+ assert prop[cs.TARGET_ID] == 'chat2@conf.localhost'
+ assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
+ assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [cs.SOCKET_ACCESS_CONTROL_CREDENTIALS,
+ cs.SOCKET_ACCESS_CONTROL_LOCALHOST]
# check that the tube channel is in the channels list
all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels',
@@ -298,8 +165,7 @@ def test(q, bus, conn, stream, access_control):
# offer the tube
call_async(q, dbus_tube_iface, 'Offer', sample_parameters, access_control)
- new_tube_event, presence_event, return_event, status_event, dbus_changed_event = q.expect_many(
- EventPattern('dbus-signal', signal='NewTube'),
+ presence_event, return_event, status_event, dbus_changed_event = q.expect_many(
EventPattern('stream-presence', to='chat2@conf.localhost/test'),
EventPattern('dbus-return', method='Offer'),
EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN]),
@@ -308,17 +174,11 @@ def test(q, bus, conn, stream, access_control):
tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)
assert tube_self_handle != 0
- # handle new_tube_event
- dbus_tube_id = new_tube_event.args[0]
- assert new_tube_event.args[2] == cs.TUBE_TYPE_DBUS
- assert new_tube_event.args[3] == 'com.example.TestCase'
- assert new_tube_event.args[4] == sample_parameters
- assert new_tube_event.args[5] == cs.TUBE_STATE_OPEN
-
# handle presence_event
# We announce our newly created tube in our muc presence
presence = presence_event.stanza
- dbus_stream_id, my_bus_name = check_tube_in_presence(presence, dbus_tube_id, 'chat2@conf.localhost/test')
+ dbus_stream_id, my_bus_name, dbus_tube_id = check_tube_in_presence(presence,
+ 'chat2@conf.localhost/test')
# handle dbus_changed_event
added, removed = dbus_changed_event.args
@@ -330,9 +190,6 @@ def test(q, bus, conn, stream, access_control):
bob_bus_name = ':2.Ym9i'
bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['chat2@conf.localhost/bob'])[0]
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assertEquals(1, len(tubes))
-
def bob_in_tube():
presence = elem('presence', from_='chat2@conf.localhost/bob', to='chat2@conf.localhost')(
elem('x', xmlns=ns.MUC_USER),
@@ -386,26 +243,18 @@ def test(q, bus, conn, stream, access_control):
assert names == {tube_self_handle: my_bus_name}
chan_iface.Close()
- q.expect_many(
+ _, _, event = q.expect_many(
EventPattern('dbus-signal', signal='Closed'),
- EventPattern('dbus-signal', signal='ChannelClosed'))
-
- # leave the room
- text_chan.Close()
+ EventPattern('dbus-signal', signal='ChannelClosed'),
+ EventPattern('stream-presence', to='chat2@conf.localhost/test',
+ presence_type='unavailable'))
# we must echo the MUC presence so the room will actually close
# and we should wait to make sure gabble has actually parsed our
# echo before trying to rejoin
- event = q.expect('stream-presence', to='chat2@conf.localhost/test',
- presence_type='unavailable')
echo_muc_presence(q, stream, event.stanza, 'none', 'participant')
sync_stream(q, stream)
- q.expect_many(
- EventPattern('dbus-signal', signal='Closed'),
- EventPattern('dbus-signal', signal='ChannelClosed'),
- )
-
# rejoin the room
call_async(q, conn.Requests, 'CreateChannel',
{ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
@@ -420,41 +269,38 @@ def test(q, bus, conn, stream, access_control):
# Send presence for own membership of room.
stream.send(make_muc_presence('none', 'participant', muc, 'test'))
+ def new_tube(e):
+ path, props = e.args[0][0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
- # tube is created as well
- e = q.expect('dbus-signal', signal='NewChannels')
- tube_path, props = e.args[0][0]
+ def new_text(e):
+ path, props = e.args[0][0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT
+
+ # tube and text is created
+ text_event, tube_event = q.expect_many(EventPattern('dbus-signal', signal='NewChannels',
+ predicate=new_text),
+ EventPattern('dbus-signal', signal='NewChannels',
+ predicate=new_tube))
+
+ channels = e.args[0]
+ tube_path, props = tube_event.args[0][0]
assertEquals(cs.CHANNEL_TYPE_DBUS_TUBE, props[cs.CHANNEL_TYPE])
assertEquals('chat2@conf.localhost/test', props[cs.INITIATOR_ID])
assertEquals(False, props[cs.REQUESTED])
assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE])
assertEquals('com.example.TestCase', props[cs.DBUS_TUBE_SERVICE_NAME])
- # text channel is created
- e = q.expect('dbus-signal', signal='NewChannels')
- path, props = e.args[0][0]
+ _, props = text_event.args[0][0]
assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE])
assertEquals(True, props[cs.REQUESTED])
- # tubes channel is created
- e = q.expect('dbus-signal', signal='NewChannels')
- path, props = e.args[0][0]
- assertEquals(cs.CHANNEL_TYPE_TUBES, props[cs.CHANNEL_TYPE])
- assertEquals(False, props[cs.REQUESTED])
-
- tubes_iface = dbus.Interface(bus.get_object(conn.bus_name, path),
- cs.CHANNEL_TYPE_TUBES)
-
# tube is local-pending
tube_chan = bus.get_object(conn.bus_name, tube_path)
state = tube_chan.Get(cs.CHANNEL_IFACE_TUBE, 'State',
dbus_interface=dbus.PROPERTIES_IFACE)
assertEquals(cs.TUBE_STATE_LOCAL_PENDING, state)
- # tube is listed on the old interface
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assertEquals(1, len(tubes))
-
if __name__ == '__main__':
# We can't use t.exec_dbus_tube_test() as we can use only the muc bytestream
exec_test(lambda q, bus, conn, stream:
diff --git a/tests/twisted/tubes/offer-muc-stream-tube.py b/tests/twisted/tubes/offer-muc-stream-tube.py
index 433d79c82..2188e82a9 100644
--- a/tests/twisted/tubes/offer-muc-stream-tube.py
+++ b/tests/twisted/tubes/offer-muc-stream-tube.py
@@ -11,7 +11,6 @@ import constants as cs
import ns
import tubetestutil as t
from mucutil import join_muc
-from muctubeutil import get_muc_tubes_channel
from bytestream import BytestreamS5BRelay, BytestreamS5BRelayBugged
from twisted.words.xish import xpath
@@ -73,127 +72,25 @@ def test(q, bus, conn, stream, bytestream_cls,
acknowledge_iq(stream, iq_event.stanza)
- self_handle = conn.GetSelfHandle()
- self_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0]
-
t.check_conn_properties(q, conn)
- room_handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn,
- stream, 'chat@conf.localhost')
-
- tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)
-
bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['chat@conf.localhost/bob'])[0]
address = t.create_server(q, address_type)
- # offer stream tube (old API) using an Unix socket
- call_async(q, tubes_iface, 'OfferStreamTube',
- 'echo', sample_parameters, address_type, address,
- access_control, access_control_param)
+ def new_chan_predicate(e):
+ types = []
+ for _, props in e.args[0]:
+ types.append(props[cs.CHANNEL_TYPE])
- new_tube_event, stream_event, _, new_channels_event = q.expect_many(
- EventPattern('dbus-signal', signal='NewTube'),
- EventPattern('stream-presence', to='chat@conf.localhost/test'),
- EventPattern('dbus-return', method='OfferStreamTube'),
- EventPattern('dbus-signal', signal='NewChannels'))
-
- # handle new_tube_event
- stream_tube_id = new_tube_event.args[0]
- assert new_tube_event.args[1] == tubes_self_handle
- assert new_tube_event.args[2] == 1 # Stream
- assert new_tube_event.args[3] == 'echo'
- assert new_tube_event.args[4] == sample_parameters
- assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN
-
- # handle stream_event
- # We announce our newly created tube in our muc presence
- presence = stream_event.stanza
- tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]'
- % ns.TUBES, presence)
- assert tubes_nodes is not None
- assert len(tubes_nodes) == 1
+ return cs.CHANNEL_TYPE_STREAM_TUBE in types
- tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0])
- assert tube_nodes is not None
- assert len(tube_nodes) == 1
- for tube in tube_nodes:
- assert tube['type'] == 'stream'
- assert not tube.hasAttribute('initiator')
- assert tube['service'] == 'echo'
- assert not tube.hasAttribute('stream-id')
- assert not tube.hasAttribute('dbus-name')
- assert tube['id'] == str(stream_tube_id)
-
- params = {}
- parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
- for node in parameter_nodes:
- assert node['name'] not in params
- params[node['name']] = (node['type'], str(node))
- assert params == {'ay': ('bytes', 'aGVsbG8='),
- 's': ('str', 'hello'),
- 'i': ('int', '-123'),
- 'u': ('uint', '123'),
- }
-
- # tube is also announced using new API
- channels = new_channels_event.args[0]
- assert len(channels) == 1
- path, props = channels[0]
- assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
- assert props[cs.INITIATOR_HANDLE] == tubes_self_handle
- assert props[cs.INITIATOR_ID] == 'chat@conf.localhost/test'
- assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE]
- assert props[cs.REQUESTED] == True
- assert props[cs.TARGET_HANDLE] == room_handle
- assert props[cs.TARGET_ID] == 'chat@conf.localhost'
- assert props[cs.STREAM_TUBE_SERVICE] == 'echo'
-
- tube_chan = bus.get_object(conn.bus_name, path)
- tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE,
- byte_arrays=True)
- assert tube_props['Parameters'] == sample_parameters
- assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_OPEN
-
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert tubes == [(
- stream_tube_id,
- tubes_self_handle,
- 1, # Stream
- 'echo',
- sample_parameters,
- cs.TUBE_CHANNEL_STATE_OPEN
- )]
-
- assert len(tubes) == 1, unwrap(tubes)
- expected_tube = (stream_tube_id, tubes_self_handle, cs.TUBE_TYPE_STREAM,
- 'echo', sample_parameters, cs.TUBE_STATE_OPEN)
- t.check_tube_in_tubes(expected_tube, tubes)
-
- # FIXME: if we use an unknown JID here, everything fails
- # (the code uses lookup where it should use ensure)
-
- bytestream = connect_to_tube(stream, q, bytestream_cls, 'chat@conf.localhost', stream_tube_id)
-
- iq_event, socket_event, _, conn_event = q.expect_many(
- EventPattern('stream-iq', iq_type='result'),
- EventPattern('socket-connected'),
- EventPattern('dbus-signal', signal='StreamTubeNewConnection',
- args=[stream_tube_id, bob_handle], interface=cs.CHANNEL_TYPE_TUBES),
- EventPattern('dbus-signal', signal='NewRemoteConnection',
- interface=cs.CHANNEL_TYPE_STREAM_TUBE))
-
- protocol = socket_event.protocol
-
- # handle iq_event
- bytestream.check_si_reply(iq_event.stanza)
- tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza)
- assert len(tube) == 1
-
- handle, access, conn_id = conn_event.args
- assert handle == bob_handle
+ def find_stream_tube(channels):
+ for path, props in channels:
+ if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE:
+ return path, props
- use_tube(q, bytestream, protocol, conn_id)
+ return None, None
# offer a stream tube to another room (new API)
address = t.create_server(q, address_type, block_reading=True)
@@ -201,68 +98,22 @@ def test(q, bus, conn, stream, bytestream_cls,
request = {
cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
- cs.TARGET_ID: 'chat2@conf.localhost',
+ cs.TARGET_ID: 'chat@conf.localhost',
cs.STREAM_TUBE_SERVICE: 'newecho',
}
_, _, new_tube_path, new_tube_props = \
- join_muc(q, bus, conn, stream, 'chat2@conf.localhost', request)
-
- # The order in which the NewChannels signals are fired is
- # undefined -- it could be the (tubes, text) channels first, or it
- # could be the tube channel first; so let's accept either order
- # here.
-
- first, second = q.expect_many(
- EventPattern('dbus-signal', signal='NewChannels'),
- EventPattern('dbus-signal', signal='NewChannels'))
-
- # NewChannels signal with the text and tubes channels together.
- def nc_textandtubes(event):
- channels = event.args[0]
- assert len(channels) == 2
- path1, prop1 = channels[0]
- path2, prop2 = channels[1]
- assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == \
- [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES]
-
- got_text, got_tubes = False, False
- for path, props in channels:
- if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT:
- got_text = True
- elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
- got_tubes = True
- else:
- assert False
-
- assert props[cs.INITIATOR_HANDLE] == self_handle
- assert props[cs.INITIATOR_ID] == self_name
- assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES]
- assert props[cs.TARGET_ID] == 'chat2@conf.localhost'
- assert props[cs.REQUESTED] == False
-
- assert (got_text, got_tubes) == (True, True)
-
- # NewChannels signal with the tube channel.
- def nc_tube(event):
- # FIXME: in this case, all channels should probably be announced together
- channels = event.args[0]
- assert len(channels) == 1
- path, prop = channels[0]
- assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
- assert prop[cs.INITIATOR_ID] == 'chat2@conf.localhost/test'
- assert prop[cs.REQUESTED] == True
- assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
- assert prop[cs.TARGET_ID] == 'chat2@conf.localhost'
- assert prop[cs.STREAM_TUBE_SERVICE] == 'newecho'
-
- return path, prop
-
- if len(first.args[0]) == 1:
- path, prop = nc_tube(first)
- nc_textandtubes(second)
- else:
- nc_textandtubes(first)
- path, prop = nc_tube(second)
+ join_muc(q, bus, conn, stream, 'chat@conf.localhost', request)
+
+ e = q.expect('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate)
+
+ path, prop = find_stream_tube(e.args[0])
+ assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
+ assert prop[cs.INITIATOR_ID] == 'chat@conf.localhost/test'
+ assert prop[cs.REQUESTED] == True
+ assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
+ assert prop[cs.TARGET_ID] == 'chat@conf.localhost'
+ assert prop[cs.STREAM_TUBE_SERVICE] == 'newecho'
# check that the tube channel is in the channels list
all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels',
@@ -279,21 +130,13 @@ def test(q, bus, conn, stream, bytestream_cls,
# offer the tube
call_async(q, stream_tube_iface, 'Offer', address_type, address, access_control, {'foo': 'bar'})
- new_tube_event, stream_event, _, status_event = q.expect_many(
- EventPattern('dbus-signal', signal='NewTube'),
- EventPattern('stream-presence', to='chat2@conf.localhost/test'),
+ stream_event, _, status_event = q.expect_many(
+ EventPattern('stream-presence', to='chat@conf.localhost/test'),
EventPattern('dbus-return', method='Offer'),
EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN]))
tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)
- assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ['chat2@conf.localhost/test']
-
- # handle new_tube_event
- stream_tube_id = new_tube_event.args[0]
- assert new_tube_event.args[2] == 1 # Stream
- assert new_tube_event.args[3] == 'newecho'
- assert new_tube_event.args[4] == {'foo': 'bar'}
- assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN
+ assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ['chat@conf.localhost/test']
presence = stream_event.stanza
tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]'
@@ -301,6 +144,8 @@ def test(q, bus, conn, stream, bytestream_cls,
assert tubes_nodes is not None
assert len(tubes_nodes) == 1
+ stream_tube_id = 666
+
tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0])
assert tube_nodes is not None
assert len(tube_nodes) == 1
@@ -310,7 +155,8 @@ def test(q, bus, conn, stream, bytestream_cls,
assert tube['service'] == 'newecho'
assert not tube.hasAttribute('stream-id')
assert not tube.hasAttribute('dbus-name')
- assert tube['id'] == str(stream_tube_id)
+
+ stream_tube_id = int(tube['id'])
params = {}
parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
@@ -319,9 +165,9 @@ def test(q, bus, conn, stream, bytestream_cls,
params[node['name']] = (node['type'], str(node))
assert params == {'foo': ('str', 'bar')}
- bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['chat2@conf.localhost/bob'])[0]
+ bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['chat@conf.localhost/bob'])[0]
- bytestream = connect_to_tube(stream, q, bytestream_cls, 'chat2@conf.localhost', stream_tube_id)
+ bytestream = connect_to_tube(stream, q, bytestream_cls, 'chat@conf.localhost', stream_tube_id)
iq_event, socket_event, conn_event = q.expect_many(
EventPattern('stream-iq', iq_type='result'),
diff --git a/tests/twisted/tubes/offer-no-caps.py b/tests/twisted/tubes/offer-no-caps.py
index 09532736a..6aa9f4071 100644
--- a/tests/twisted/tubes/offer-no-caps.py
+++ b/tests/twisted/tubes/offer-no-caps.py
@@ -65,30 +65,12 @@ def test(q, bus, conn, stream):
# caps to appear, just like the StreamedMedia channel does.
sync_stream(q, stream)
- requests = dbus.Interface(conn, cs.CONN_IFACE_REQUESTS)
-
- # First, we make an old-style Tubes channel, which should work; calling
- # OfferStreamTube or OfferDBusTube on it, however, should fail with
- # NotAvailable
- path, _ = requests.CreateChannel(props(cs.CHANNEL_TYPE_TUBES))
- tubes = make_channel_proxy(conn, path, 'Channel.Type.Tubes')
-
- call_async(q, tubes, 'OfferDBusTube', 'com.example.monkeys', {})
- e = q.expect('dbus-error', method='OfferDBusTube').error
- assert e.get_dbus_name() == cs.NOT_AVAILABLE, e.get_dbus_name()
-
address = t.create_server(q, cs.SOCKET_ADDRESS_TYPE_IPV4)
- call_async(q, tubes, 'OfferStreamTube', 'echo', {},
- cs.SOCKET_ADDRESS_TYPE_IPV4, address,
- cs.SOCKET_ACCESS_CONTROL_LOCALHOST, "")
- e = q.expect('dbus-error', method='OfferStreamTube').error
- assert e.get_dbus_name() == cs.NOT_AVAILABLE, e.get_dbus_name()
-
# Now we try making new-style DBusTube and StreamTube channels, and calling
# the relevant Offer method on them; this should fail with NotAvailable.
# FIXME: I think this should be NotCapable
- st_path, _ = requests.CreateChannel(props(cs.CHANNEL_TYPE_STREAM_TUBE,
+ st_path, _ = conn.Requests.CreateChannel(props(cs.CHANNEL_TYPE_STREAM_TUBE,
{cs.STREAM_TUBE_SERVICE: "newecho"}))
st_chan = bus.get_object(conn.bus_name, st_path)
st = dbus.Interface(st_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
@@ -97,7 +79,7 @@ def test(q, bus, conn, stream):
e = q.expect('dbus-error', method='Offer').error
assert e.get_dbus_name() == cs.NOT_AVAILABLE, e.get_dbus_name()
- dt_path, _ = requests.CreateChannel(props(cs.CHANNEL_TYPE_DBUS_TUBE,
+ dt_path, _ = conn.Requests.CreateChannel(props(cs.CHANNEL_TYPE_DBUS_TUBE,
{ cs.DBUS_TUBE_SERVICE_NAME: "com.newecho" }))
dt_chan = bus.get_object(conn.bus_name, dt_path)
dt = dbus.Interface(dt_chan, cs.CHANNEL_TYPE_DBUS_TUBE)
diff --git a/tests/twisted/tubes/offer-private-dbus-tube.py b/tests/twisted/tubes/offer-private-dbus-tube.py
index 181311da7..bb61eb21c 100644
--- a/tests/twisted/tubes/offer-private-dbus-tube.py
+++ b/tests/twisted/tubes/offer-private-dbus-tube.py
@@ -5,7 +5,7 @@ from dbus.connection import Connection
from dbus.lowlevel import SignalMessage
from servicetest import call_async, EventPattern, unwrap, watch_tube_signals,\
- assertContains
+ assertContains, assertEquals
from gabbletest import sync_stream, make_presence
import constants as cs
import tubetestutil as t
@@ -57,8 +57,8 @@ def alice_accepts_tube(q, stream, iq_event, dbus_tube_id, bytestream_cls):
bytestream.wait_bytestream_open()
- q.expect('dbus-signal', signal='TubeStateChanged',
- args=[dbus_tube_id, cs.TUBE_STATE_OPEN])
+ q.expect('dbus-signal', signal='TubeChannelStateChanged',
+ args=[cs.TUBE_STATE_OPEN])
return bytestream
@@ -98,74 +98,24 @@ def send_dbus_message_to_alice(q, stream, dbus_tube_adr, bytestream):
q.expect('tube-signal', signal='baz', args=[42], tube=tube)
q.expect('tube-signal', signal='baz', args=[42], tube=tube)
-def offer_old_dbus_tube(q, bus, conn, stream, self_handle, alice_handle, bytestream_cls):
- # request tubes channel (old API)
- tubes_path = conn.RequestChannel(cs.CHANNEL_TYPE_TUBES, cs.HT_CONTACT,
- alice_handle, True)
- tubes_chan = bus.get_object(conn.bus_name, tubes_path)
- tubes_iface = dbus.Interface(tubes_chan, cs.CHANNEL_TYPE_TUBES)
- tubes_chan_iface = dbus.Interface(tubes_chan, cs.CHANNEL)
-
- # Exercise basic Channel Properties from spec 0.17.7
- channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE)
- assert channel_props.get('TargetHandle') == alice_handle,\
- (channel_props.get('TargetHandle'), alice_handle)
- assert channel_props.get('TargetHandleType') == cs.HT_CONTACT,\
- channel_props.get('TargetHandleType')
- assert channel_props.get('ChannelType') == cs.CHANNEL_TYPE_TUBES,\
- channel_props.get('ChannelType')
- assert 'Interfaces' in channel_props, channel_props
- assert channel_props['Interfaces'] == [], channel_props['Interfaces']
- assert channel_props['TargetID'] == 'alice@localhost', channel_props['TargetID']
- assert channel_props['Requested'] == True
- assert channel_props['InitiatorID'] == 'test@localhost'
- assert channel_props['InitiatorHandle'] == conn.GetSelfHandle()
-
- # Offer a D-Bus tube using old API
- call_async(q, tubes_iface, 'OfferDBusTube',
- 'com.example.TestCase', sample_parameters)
-
- new_tube_event, iq_event, offer_return_event = \
- q.expect_many(
- EventPattern('dbus-signal', signal='NewTube'),
- EventPattern('stream-iq', to='alice@localhost/Test'),
- EventPattern('dbus-return', method='OfferDBusTube'))
-
- # handle new_tube_event
- dbus_tube_id = new_tube_event.args[0]
- assert new_tube_event.args[1] == self_handle
- assert new_tube_event.args[2] == cs.TUBE_TYPE_DBUS
- assert new_tube_event.args[3] == 'com.example.TestCase'
- assert new_tube_event.args[4] == sample_parameters
- assert new_tube_event.args[5] == cs.TUBE_STATE_REMOTE_PENDING
-
- # handle offer_return_event
- assert offer_return_event.value[0] == dbus_tube_id
-
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert len(tubes) == 1
- expected_tube = (dbus_tube_id, self_handle, cs.TUBE_TYPE_DBUS,
- 'com.example.TestCase', sample_parameters, cs.TUBE_STATE_REMOTE_PENDING)
- t.check_tube_in_tubes(expected_tube, tubes)
-
- bytestream = alice_accepts_tube(q, stream, iq_event, dbus_tube_id, bytestream_cls)
-
- dbus_tube_adr = tubes_iface.GetDBusTubeAddress(dbus_tube_id)
- send_dbus_message_to_alice(q, stream, dbus_tube_adr, bytestream)
+def offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle,
+ bytestream_cls, access_control):
- # close the tube
- tubes_iface.CloseTube(dbus_tube_id)
- q.expect('dbus-signal', signal='TubeClosed', args=[dbus_tube_id])
+ # Offer a tube to Alice (new API)
- # and close the tubes channel
- tubes_chan_iface.Close()
- q.expect('dbus-signal', signal='Closed')
+ def new_chan_predicate(e):
+ types = []
+ for _, props in e.args[0]:
+ types.append(props[cs.CHANNEL_TYPE])
+ return cs.CHANNEL_TYPE_DBUS_TUBE in types
-def offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle,
- bytestream_cls, access_control):
+ def find_dbus_tube(channels):
+ for path, props in channels:
+ if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE:
+ return path, props
- # Offer a tube to Alice (new API)
+ return None, None
call_async(q, conn.Requests, 'CreateChannel',
{cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
@@ -175,10 +125,11 @@ def offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle,
}, byte_arrays=True)
cc_ret, nc = q.expect_many(
EventPattern('dbus-return', method='CreateChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
+ EventPattern('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate),
)
tube_path, tube_props = cc_ret.value
- new_channel_details = nc.args[0]
+ _, new_channel_props = find_dbus_tube(nc.args[0])
# check tube channel properties
assert tube_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
@@ -200,34 +151,10 @@ def offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle,
all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels',
dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)
- for path, props in new_channel_details:
+ for path, props in nc.args[0]:
assertContains((path, props), all_channels)
- # Under the current implementation, creating a new-style Tube channel
- # ensures that an old-style Tubes channel exists, even though Tube channels
- # aren't visible on the Tubes channel until they're offered. Another
- # correct implementation would have the Tubes channel spring up only when
- # the Tube is offered.
- #
- # Anyway. Given the current implementation, they should be announced together.
- assert len(new_channel_details) == 2, unwrap(new_channel_details)
- found_tubes = False
- found_tube = False
- for path, details in new_channel_details:
- if details[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
- found_tubes = True
- tubes_chan = bus.get_object(conn.bus_name, path)
- tubes_iface = dbus.Interface(tubes_chan, cs.CHANNEL_TYPE_TUBES)
- elif details[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE:
- found_tube = True
- assert tube_path == path, (tube_path, path)
- else:
- assert False, (path, details)
- assert found_tube and found_tubes, unwrap(new_channel_details)
-
- # The tube's not offered, so it shouldn't be shown on the old interface.
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert len(tubes) == 0, tubes
+ assertEquals(tube_props, new_channel_props)
tube_chan = bus.get_object(conn.bus_name, tube_path)
tube_chan_iface = dbus.Interface(tube_chan, cs.CHANNEL)
@@ -248,10 +175,9 @@ def offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle,
# arrived if it had been sent.
sync_stream(q, stream)
call_async(q, dbus_tube_iface, 'Offer', sample_parameters, access_control)
- offer_return_event, iq_event, new_tube_event, state_event = q.expect_many(
+ offer_return_event, iq_event, state_event = q.expect_many(
EventPattern('dbus-return', method='Offer'),
EventPattern('stream-iq', to='alice@localhost/Test'),
- EventPattern('dbus-signal', signal='NewTube'),
EventPattern('dbus-signal', signal='TubeChannelStateChanged'),
)
@@ -260,13 +186,6 @@ def offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle,
assert state_event.args[0] == cs.TUBE_CHANNEL_STATE_REMOTE_PENDING
- # Now the tube's been offered, it should be shown on the old interface
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert len(tubes) == 1
- expected_tube = (None, self_handle, cs.TUBE_TYPE_DBUS, 'com.example.TestCase',
- sample_parameters, cs.TUBE_STATE_REMOTE_PENDING)
- t.check_tube_in_tubes(expected_tube, tubes)
-
status = tube_chan.Get(cs.CHANNEL_IFACE_TUBE, 'State', dbus_interface=cs.PROPERTIES_IFACE)
assert status == cs.TUBE_STATE_REMOTE_PENDING
@@ -304,7 +223,6 @@ def test(q, bus, conn, stream, bytestream_cls, access_control):
sync_stream(q, stream)
- offer_old_dbus_tube(q, bus, conn, stream, self_handle, alice_handle, bytestream_cls)
offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle, bytestream_cls, access_control)
if __name__ == '__main__':
diff --git a/tests/twisted/tubes/offer-private-stream-tube.py b/tests/twisted/tubes/offer-private-stream-tube.py
index 71f59be19..de37041c2 100644
--- a/tests/twisted/tubes/offer-private-stream-tube.py
+++ b/tests/twisted/tubes/offer-private-stream-tube.py
@@ -98,27 +98,6 @@ def test(q, bus, conn, stream, bytestream_cls,
# Test tubes with Bob. Bob has tube capabilities.
bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0]
- # old tubes API
- call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TUBES, cs.HT_CONTACT,
- bob_handle, True)
-
- ret, old_sig, new_sig = q.expect_many(
- EventPattern('dbus-return', method='RequestChannel'),
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
- )
-
- assert len(ret.value) == 1
- chan_path = ret.value[0]
-
- t.check_NewChannel_signal(old_sig.args, cs.CHANNEL_TYPE_TUBES, chan_path,
- bob_handle, True)
- t.check_NewChannels_signal(conn, new_sig.args, cs.CHANNEL_TYPE_TUBES, chan_path,
- bob_handle, 'bob@localhost', self_handle)
- old_tubes_channel_properties = new_sig.args[0][0]
-
- t.check_conn_properties(q, conn, [old_tubes_channel_properties])
-
# Try CreateChannel with correct properties
# Gabble must succeed
call_async(q, conn.Requests, 'CreateChannel',
@@ -128,15 +107,23 @@ def test(q, bus, conn, stream, bytestream_cls,
cs.STREAM_TUBE_SERVICE: "newecho",
})
- # the NewTube signal (old API) is not fired now as the tube wasn't offered
- # yet
- ret, old_sig, new_sig = q.expect_many(
+ def find_stream_tube(channels):
+ for path, props in channels:
+ if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE:
+ return path, props
+
+ return None, None
+
+ def new_chan_predicate(e):
+ path, _ = find_stream_tube(e.args[0])
+ return path is not None
+
+ ret, new_sig = q.expect_many(
EventPattern('dbus-return', method='CreateChannel'),
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
+ EventPattern('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate),
)
- assert len(ret.value) == 2 # CreateChannel returns 2 values: o, a{sv}
new_chan_path = ret.value[0]
new_chan_prop_asv = ret.value[1]
# State and Parameters are mutables so not announced
@@ -144,9 +131,6 @@ def test(q, bus, conn, stream, bytestream_cls,
assert cs.TUBE_PARAMETERS not in new_chan_prop_asv
assert new_chan_path.find("StreamTube") != -1, new_chan_path
assert new_chan_path.find("SITubesChannel") == -1, new_chan_path
- # The path of the Channel.Type.Tubes object MUST be different to the path
- # of the Channel.Type.StreamTube object !
- assert chan_path != new_chan_path
new_tube_chan = bus.get_object(conn.bus_name, new_chan_path)
new_tube_iface = dbus.Interface(new_tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
@@ -158,110 +142,15 @@ def test(q, bus, conn, stream, bytestream_cls,
# the tube created using the new API is in the "not offered" state
assert new_tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED
- t.check_NewChannel_signal(old_sig.args, cs.CHANNEL_TYPE_STREAM_TUBE,
- new_chan_path, bob_handle, True)
- t.check_NewChannels_signal(conn, new_sig.args, cs.CHANNEL_TYPE_STREAM_TUBE,
- new_chan_path, bob_handle, 'bob@localhost', self_handle)
- stream_tube_channel_properties = new_sig.args[0][0]
+ _, stream_tube_channel_properties = find_stream_tube(new_sig.args[0])
assert cs.TUBE_STATE not in stream_tube_channel_properties
assert cs.TUBE_PARAMETERS not in stream_tube_channel_properties
- t.check_conn_properties(q, conn,
- [old_tubes_channel_properties, stream_tube_channel_properties])
-
- tubes_chan = bus.get_object(conn.bus_name, chan_path)
- tubes_iface = dbus.Interface(tubes_chan, cs.CHANNEL_TYPE_TUBES)
-
- t.check_channel_properties(q, bus, conn, tubes_chan, cs.CHANNEL_TYPE_TUBES,
- bob_handle, "bob@localhost")
-
- # Create another tube using old API
- call_async(q, tubes_iface, 'OfferStreamTube',
- 'echo', sample_parameters, address_type, address1,
- access_control, access_control_param)
-
- event, return_event, new_chan, new_chans = q.expect_many(
- EventPattern('stream-message'),
- EventPattern('dbus-return', method='OfferStreamTube'),
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'))
-
- message = event.stanza
- assert message['to'] == bob_full_jid
- tube_nodes = xpath.queryForNodes('/message/tube[@xmlns="%s"]' % ns.TUBES,
- message)
- assert tube_nodes is not None
- assert len(tube_nodes) == 1
- tube = tube_nodes[0]
-
- assert tube['service'] == 'echo'
- assert tube['type'] == 'stream'
- assert not tube.hasAttribute('initiator')
- stream_tube_id = long(tube['id'])
-
- params = {}
- parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
- for node in parameter_nodes:
- assert node['name'] not in params
- params[node['name']] = (node['type'], str(node))
- assert params == {'ay': ('bytes', 'aGVsbG8='),
- 's': ('str', 'hello'),
- 'i': ('int', '-123'),
- 'u': ('uint', '123'),
- }
-
-
- # the tube channel (new API) is announced
- t.check_NewChannel_signal(new_chan.args, cs.CHANNEL_TYPE_STREAM_TUBE,
- None, bob_handle, False)
- t.check_NewChannels_signal(conn, new_chans.args, cs.CHANNEL_TYPE_STREAM_TUBE,
- new_chan.args[0], bob_handle, "bob@localhost", self_handle)
-
- props = new_chans.args[0][0][1]
- assert cs.TUBE_STATE not in props
- assert cs.TUBE_PARAMETERS not in props
-
- # We offered a tube using the old tube API and created one with the new
- # API, so there are 2 tubes. Check the new tube API works
- assert len(filter(lambda x:
- x[1] == cs.CHANNEL_TYPE_TUBES,
- conn.ListChannels())) == 1
- channels = filter(lambda x:
- x[1] == cs.CHANNEL_TYPE_STREAM_TUBE and
- x[0] == new_chan_path,
- conn.ListChannels())
- assert len(channels) == 1
- assert new_chan_path == channels[0][0]
-
- old_tube_chan = bus.get_object(conn.bus_name, new_chan.args[0])
-
- tube_basic_props = old_tube_chan.GetAll(cs.CHANNEL,
- dbus_interface=cs.PROPERTIES_IFACE)
- assert tube_basic_props.get("InitiatorHandle") == self_handle
-
- stream_tube_props = old_tube_chan.GetAll(cs.CHANNEL_TYPE_STREAM_TUBE,
- dbus_interface=cs.PROPERTIES_IFACE)
- assert stream_tube_props.get("Service") == "echo", stream_tube_props
-
- old_tube_props = old_tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE,
- dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)
- assert old_tube_props.get("Parameters") == dbus.Dictionary(sample_parameters)
-
- # Tube have been created using the old API and so is already offered
- assert old_tube_props['State'] == cs.TUBE_CHANNEL_STATE_REMOTE_PENDING
-
- t.check_channel_properties(q, bus, conn, tubes_chan, cs.CHANNEL_TYPE_TUBES,
- bob_handle, "bob@localhost")
- t.check_channel_properties(q, bus, conn, old_tube_chan,
- cs.CHANNEL_TYPE_STREAM_TUBE, bob_handle, "bob@localhost",
- cs.TUBE_CHANNEL_STATE_REMOTE_PENDING)
-
- # Offer the first tube created (new API)
+ # Offer the first tube created
call_async(q, new_tube_iface, 'Offer', address_type, address2, access_control, new_sample_parameters)
- msg_event, new_tube_sig, state_event = q.expect_many(
+ msg_event, state_event = q.expect_many(
EventPattern('stream-message'),
- EventPattern('dbus-signal', signal='NewTube'),
EventPattern('dbus-signal', signal='TubeChannelStateChanged'))
assert state_event.args[0] == cs.TUBE_CHANNEL_STATE_REMOTE_PENDING
@@ -277,7 +166,7 @@ def test(q, bus, conn, stream, bytestream_cls,
assert tube['service'] == 'newecho'
assert tube['type'] == 'stream'
assert not tube.hasAttribute('initiator')
- new_stream_tube_id = long(tube['id'])
+ stream_tube_id = long(tube['id'])
params = {}
parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
@@ -290,17 +179,9 @@ def test(q, bus, conn, stream, bytestream_cls,
'u': ('uint', '123'),
}
- # check NewTube signal (old API)
- id, initiator_handle, type, service, params, state = new_tube_sig.args
- assert initiator_handle == self_handle
- assert type == 1 # stream
- assert service == 'newecho'
- assert params == new_sample_parameters
- assert state == 1 # remote pending
-
# The new tube has been offered, the parameters cannot be changed anymore
# We need to use call_async to check the error
- tube_prop_iface = dbus.Interface(old_tube_chan, cs.PROPERTIES_IFACE)
+ tube_prop_iface = dbus.Interface(new_tube_chan, cs.PROPERTIES_IFACE)
call_async(q, tube_prop_iface, 'Set', cs.CHANNEL_IFACE_TUBE,
'Parameters', dbus.Dictionary(
{dbus.String(u'foo2'): dbus.String(u'bar2')},
@@ -323,12 +204,10 @@ def test(q, bus, conn, stream, bytestream_cls,
stream_node['tube'] = str(stream_tube_id)
stream.send(iq)
- si_reply_event, _, _, new_conn_event, socket_event = q.expect_many(
+ si_reply_event, _, new_conn_event, socket_event = q.expect_many(
EventPattern('stream-iq', iq_type='result'),
- EventPattern('dbus-signal', signal='TubeStateChanged',
- args=[stream_tube_id, cs.TUBE_STATE_OPEN]),
- EventPattern('dbus-signal', signal='StreamTubeNewConnection',
- args=[stream_tube_id, bob_handle]),
+ EventPattern('dbus-signal', signal='TubeChannelStateChanged',
+ args=[cs.TUBE_STATE_OPEN]),
EventPattern('dbus-signal', signal='NewRemoteConnection'),
EventPattern('socket-connected'))
@@ -348,11 +227,6 @@ def test(q, bus, conn, stream, bytestream_cls,
t.check_new_connection_access(q, access_control, access, protocol)
protocol.echoed = True
- expected_tube = (stream_tube_id, self_handle, cs.TUBE_TYPE_STREAM, 'echo',
- sample_parameters, cs.TUBE_STATE_OPEN)
- tubes = tubes_iface.ListTubes(byte_arrays=True)
- t.check_tube_in_tubes(expected_tube, tubes)
-
# The CM is the server, so fake a client wanting to talk to it
# New API tube
bytestream2 = bytestream_cls(stream, q, 'beta', bob_full_jid,
@@ -360,13 +234,11 @@ def test(q, bus, conn, stream, bytestream_cls,
iq, si = bytestream2.create_si_offer(ns.TUBES)
stream_node = si.addElement((ns.TUBES, 'stream'))
- stream_node['tube'] = str(new_stream_tube_id)
+ stream_node['tube'] = str(stream_tube_id)
stream.send(iq)
- si_reply_event, _, new_conn_event, socket_event = q.expect_many(
+ si_reply_event, new_conn_event, socket_event = q.expect_many(
EventPattern('stream-iq', iq_type='result'),
- EventPattern('dbus-signal', signal='TubeChannelStateChanged',
- args=[cs.TUBE_STATE_OPEN]),
EventPattern('dbus-signal', signal='NewRemoteConnection'),
EventPattern('socket-connected'))
@@ -386,10 +258,6 @@ def test(q, bus, conn, stream, bytestream_cls,
t.check_new_connection_access(q, access_control, access, protocol)
protocol.echoed = True
- expected_tube = (new_stream_tube_id, self_handle, cs.TUBE_TYPE_STREAM,
- 'newecho', new_sample_parameters, cs.TUBE_STATE_OPEN)
- t.check_tube_in_tubes (expected_tube, tubes_iface.ListTubes(byte_arrays=True))
-
# have the fake client open the stream
bytestream1.open_bytestream()
diff --git a/tests/twisted/tubes/test-get-available-tubes.py b/tests/twisted/tubes/test-get-available-tubes.py
index 1020c0250..7b860ebfd 100644
--- a/tests/twisted/tubes/test-get-available-tubes.py
+++ b/tests/twisted/tubes/test-get-available-tubes.py
@@ -24,19 +24,14 @@ def test(q, bus, conn, stream):
acknowledge_iq(stream, iq_event.stanza)
- call_async(q, conn, 'RequestHandles', cs.HT_ROOM, ['chat@conf.localhost'])
-
- event = q.expect('dbus-return', method='RequestHandles')
- handles = event.value[0]
+ # muc stream tube
+ call_async(q, conn.Requests, 'CreateChannel', {
+ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
+ cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
+ cs.TARGET_ID: 'chat@conf.localhost',
+ cs.STREAM_TUBE_SERVICE: 'test'})
- # request tubes channel (old API)
- call_async(q, conn, 'RequestChannel',
- tp_name_prefix + '.Channel.Type.Tubes', cs.HT_ROOM, handles[0], True)
-
- _, stream_event = q.expect_many(
- EventPattern('dbus-signal', signal='MembersChanged',
- args=[u'', [], [], [], [2], 0, 0]),
- EventPattern('stream-presence', to='chat@conf.localhost/test'))
+ q.expect('stream-presence', to='chat@conf.localhost/test')
# Send presence for other member of room.
stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob'))
@@ -44,34 +39,17 @@ def test(q, bus, conn, stream):
# Send presence for own membership of room.
stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'test'))
- new_chans, members, event = q.expect_many(
- EventPattern('dbus-signal', signal='NewChannels'),
+ members, event = q.expect_many(
EventPattern('dbus-signal', signal='MembersChanged',
args=[u'', [2, 3], [], [], [], 0, 0]),
- EventPattern('dbus-return', method='RequestChannel'))
-
- channels = new_chans.args[0]
- assertLength(2, channels)
-
- assertEquals(conn.InspectHandles(cs.HT_CONTACT, [2]), ['chat@conf.localhost/test'])
- assertEquals(conn.InspectHandles(cs.HT_CONTACT, [3]), ['chat@conf.localhost/bob'])
- bob_handle = 3
-
- tubes_chan = bus.get_object(conn.bus_name, event.value[0])
- tubes_iface_muc = dbus.Interface(tubes_chan,
- tp_name_prefix + '.Channel.Type.Tubes')
-
- # FIXME: these using a "1-1" tubes channel too
+ EventPattern('dbus-return', method='CreateChannel'))
- # test GetAvailableTubeTypes (old API)
- tube_types = tubes_iface_muc.GetAvailableTubeTypes()
+ path = event.value[0]
+ props = event.value[1]
- assertLength(2, tube_types)
- assertContains(cs.TUBE_TYPE_DBUS, tube_types)
- assertContains(cs.TUBE_TYPE_STREAM, tube_types)
-
- # test GetAvailableStreamTubeTypes (old API)
- stream_tubes_types = tubes_iface_muc.GetAvailableStreamTubeTypes()
+ tube = bus.get_object(conn.bus_name, path)
+ stream_tubes_types = tube.Get(cs.CHANNEL_TYPE_STREAM_TUBE, 'SupportedSocketTypes',
+ dbus_interface=cs.PROPERTIES_IFACE)
if os.name == 'posix':
assert cs.SOCKET_ACCESS_CONTROL_LOCALHOST in \
@@ -88,17 +66,5 @@ def test(q, bus, conn, stream):
assertEquals([cs.SOCKET_ACCESS_CONTROL_LOCALHOST, cs.SOCKET_ACCESS_CONTROL_PORT],
stream_tubes_types[cs.SOCKET_ADDRESS_TYPE_IPV6])
- # muc stream tube (new API)
- path, props = conn.Requests.CreateChannel({
- cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
- cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
- cs.TARGET_ID: 'chat@conf.localhost',
- cs.STREAM_TUBE_SERVICE: 'test'})
-
- tube = bus.get_object(conn.bus_name, path)
- sockets = tube.Get(cs.CHANNEL_TYPE_STREAM_TUBE, 'SupportedSocketTypes',
- dbus_interface=cs.PROPERTIES_IFACE)
- assertEquals(sockets, stream_tubes_types)
-
if __name__ == '__main__':
exec_test(test)
diff --git a/tests/twisted/tubes/test-socks5-muc.py b/tests/twisted/tubes/test-socks5-muc.py
index 5f498a59e..4153801f8 100644
--- a/tests/twisted/tubes/test-socks5-muc.py
+++ b/tests/twisted/tubes/test-socks5-muc.py
@@ -6,11 +6,13 @@ if os.name != 'posix':
# skipped on non-Unix for now, because it uses a Unix socket
raise SystemExit(77)
+import dbus
+
from servicetest import call_async, EventPattern, EventProtocolClientFactory
from gabbletest import acknowledge_iq, make_muc_presence, exec_test
import constants as cs
import ns
-from muctubeutil import get_muc_tubes_channel
+from mucutil import join_muc
from bytestream import BytestreamS5BRelay, create_from_si_offer, announce_socks5_proxy
from twisted.internet import reactor
@@ -25,8 +27,7 @@ def test(q, bus, conn, stream):
announce_socks5_proxy(q, stream, disco_event.stanza)
- room_handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn,
- stream, 'chat@conf.localhost')
+ text_chan = join_muc(q, bus, conn, stream, 'chat@conf.localhost')
# bob offers a stream tube
stream_tube_id = 1
@@ -40,20 +41,27 @@ def test(q, bus, conn, stream):
parameters = tube.addElement((None, 'parameters'))
stream.send(presence)
- e = q.expect('dbus-signal', signal='NewChannels')
+ def new_chan_predicate(e):
+ path, props = e.args[0][0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
+
+ e = q.expect('dbus-signal', signal='NewChannels',
+ predicate=new_chan_predicate)
channels = e.args[0]
assert len(channels) == 1
path, props = channels[0]
assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
tube_chan = bus.get_object(conn.bus_name, path)
- call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 0, 0, '',
+ tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
+
+ call_async(q, tube_iface, 'Accept', 0, 0, '',
byte_arrays=True)
accept_return_event, _ = q.expect_many(
- EventPattern('dbus-return', method='AcceptStreamTube'),
- EventPattern('dbus-signal', signal='TubeStateChanged',
- args=[stream_tube_id, cs.TUBE_CHANNEL_STATE_OPEN]))
+ EventPattern('dbus-return', method='Accept'),
+ EventPattern('dbus-signal', signal='TubeChannelStateChanged',
+ args=[cs.TUBE_CHANNEL_STATE_OPEN]))
unix_socket_adr = accept_return_event.value[0]
diff --git a/tests/twisted/tubes/tubetestutil.py b/tests/twisted/tubes/tubetestutil.py
index 9aeb89ed6..3eb86d9d5 100644
--- a/tests/twisted/tubes/tubetestutil.py
+++ b/tests/twisted/tubes/tubetestutil.py
@@ -81,24 +81,6 @@ def check_conn_properties(q, conn, channel_list=None):
assert i in properties['Channels'], \
(i, properties['Channels'])
- # 1-1 tubes channel (old API)
- assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TUBES,
- cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
- },
- [cs.TARGET_HANDLE, cs.TARGET_ID
- ]
- ) in properties.get('RequestableChannelClasses'),\
- properties['RequestableChannelClasses']
-
- # muc tubes channel (old API)
- assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TUBES,
- cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
- },
- [cs.TARGET_HANDLE, cs.TARGET_ID
- ]
- ) in properties.get('RequestableChannelClasses'),\
- properties['RequestableChannelClasses']
-
# 1-1 StreamTube channel
assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT
diff --git a/tests/twisted/vcard/clear-avatar.py b/tests/twisted/vcard/clear-avatar.py
new file mode 100644
index 000000000..333c5e8e7
--- /dev/null
+++ b/tests/twisted/vcard/clear-avatar.py
@@ -0,0 +1,27 @@
+"""
+Tests the very simple case of "clearing your own avatar".
+"""
+
+from servicetest import call_async
+from gabbletest import (
+ exec_test, expect_and_handle_get_vcard, expect_and_handle_set_vcard, current_vcard
+ )
+
+def test(q, bus, conn, stream):
+ photo = current_vcard.addElement((None, 'PHOTO'))
+ photo.addElement((None, 'TYPE')).addContent('image/fake')
+ photo.addElement((None, 'BINVAL')).addContent('NYANYANYANYANYAN')
+
+ call_async(q, conn.Avatars, 'ClearAvatar')
+
+ expect_and_handle_get_vcard(q, stream)
+
+ def check(vcard):
+ assert len(vcard.children) == 0, vcard.toXml()
+
+ expect_and_handle_set_vcard(q, stream, check=check)
+
+ q.expect('dbus-return', method='ClearAvatar')
+
+if __name__ == '__main__':
+ exec_test(test)
diff --git a/tests/twisted/vcard/overlapping-sets.py b/tests/twisted/vcard/overlapping-sets.py
index d7fe563c5..a57ca9cc4 100644
--- a/tests/twisted/vcard/overlapping-sets.py
+++ b/tests/twisted/vcard/overlapping-sets.py
@@ -8,7 +8,7 @@ from servicetest import (EventPattern, call_async, sync_dbus, assertEquals,
assertLength)
from gabbletest import (
acknowledge_iq, exec_test, expect_and_handle_get_vcard, make_result_iq,
- sync_stream)
+ sync_stream, disconnect_conn)
import ns
def test(q, bus, conn, stream):
@@ -51,8 +51,9 @@ def test(q, bus, conn, stream):
vcard_set_event.stanza))
assertEquals('image/png', xpath.queryForString('/iq/vCard/PHOTO/TYPE',
vcard_set_event.stanza))
- assertEquals(hello_binval, xpath.queryForString('/iq/vCard/PHOTO/BINVAL',
- vcard_set_event.stanza))
+ binval = xpath.queryForString('/iq/vCard/PHOTO/BINVAL',
+ vcard_set_event.stanza)
+ assertEquals(hello_binval, binval.strip())
assertEquals(None, xpath.queryForNodes('/iq/vCard/FN',
vcard_set_event.stanza))
assertEquals(None, xpath.queryForNodes('/iq/vCard/N',
@@ -80,8 +81,9 @@ def test(q, bus, conn, stream):
vcard_set_event.stanza))
assertEquals('image/png', xpath.queryForString('/iq/vCard/PHOTO/TYPE',
vcard_set_event.stanza))
- assertEquals(hello_binval, xpath.queryForString('/iq/vCard/PHOTO/BINVAL',
- vcard_set_event.stanza))
+ binval = xpath.queryForString('/iq/vCard/PHOTO/BINVAL',
+ vcard_set_event.stanza)
+ assertEquals(hello_binval, binval.strip())
assertLength(1, xpath.queryForNodes('/iq/vCard/N',
vcard_set_event.stanza))
assertEquals('Robert', xpath.queryForString('/iq/vCard/N/GIVEN',
@@ -127,8 +129,7 @@ def test(q, bus, conn, stream):
# Now Gabble gets disconnected.
sync_stream(q, stream)
- conn.Disconnect()
- q.expect('dbus-signal', signal='StatusChanged', args=[2, 1])
+ disconnect_conn(q, conn, stream)
if __name__ == '__main__':
exec_test(test)
diff --git a/tests/twisted/vcard/set-avatar.py b/tests/twisted/vcard/set-avatar.py
new file mode 100644
index 000000000..6ce38a5c1
--- /dev/null
+++ b/tests/twisted/vcard/set-avatar.py
@@ -0,0 +1,55 @@
+"""
+Tests the very simple case of "setting your own avatar".
+"""
+
+from twisted.words.xish import xpath
+from servicetest import call_async, assertEquals
+from gabbletest import (
+ exec_test, expect_and_handle_get_vcard, expect_and_handle_set_vcard,
+ )
+import base64
+import functools
+
+def test(q, bus, conn, stream, image_data, mime_type):
+ call_async(q, conn.Avatars, 'SetAvatar', image_data, mime_type)
+
+ expect_and_handle_get_vcard(q, stream)
+
+ def check(vcard):
+ assertEquals(mime_type,
+ xpath.queryForString('/vCard/PHOTO/TYPE', vcard))
+
+ binval = xpath.queryForString('/vCard/PHOTO/BINVAL', vcard)
+
+ # <http://xmpp.org/extensions/xep-0153.html#bizrules-image> says:
+ #
+ # 5. The image data MUST conform to the base64Binary datatype and thus
+ # be encoded in accordance with Section 6.8 of RFC 2045, which
+ # recommends that base64 data should have lines limited to at most
+ # 76 characters in length.
+ lines = binval.split('\n')
+ for line in lines:
+ assert len(line) <= 76, line
+
+ assertEquals(image_data, base64.decodestring(binval))
+
+ expect_and_handle_set_vcard(q, stream, check=check)
+
+ q.expect('dbus-return', method='SetAvatar')
+
+def test_little_avatar(q, bus, conn, stream):
+ test(q, bus, conn, stream, image_data='Guy.brush',
+ mime_type='image/x-mighty-pirate')
+
+def test_massive_avatar(q, bus, conn, stream):
+ """Regression test for
+ <https://bugs.freedesktop.org/show_bug.cgi?id=57080>, where a too-small
+ buffer was allocated if the base64-encoded avatar spanned multiple lines.
+
+ """
+ avatar = '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xec\x00\x00\x00\x94\x04\x03\x00\x00\x00b\x8c\xd8\x8b\x00\x00\x00\x18PLTEap\x00\xff\x99\x99\xff\xff\xff\xff3\x99\xff\xcc\x99\x99\x99\x99\xff\x99\xff\x00\x00\x00\xcdt\xca\x11\x00\x00\x00\x01tRNS\x00@\xe6\xd8f\x00\x00\x00\x01bKGD\x00\x88\x05\x1dH\x00\x00\x00\tpHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x0b\x0e\x0f"%\xd9\xcd\xe5\x8c\x00\x00\x01\x88IDATx\xda\xed\xdb=n\xc20\x14\xc0\xf1l\xcc\x0c\\ K\x0f\x10\t.P\x95\xb9\x95\x10\x07\xa0jW\x96\xe0\xeb\x97\x90 ?\xdb\x0f;\x1f.i\xa3\xff\x9bBb\xfb\x17$\xec\xbc\xd8\xa6(ba\xa6E12`aa\xc7\xb2\xd7z\xaf\xd3\xe2\xda\xc2\x19\x16vN\xd68\xe6\xdb\xd7\xb0\xf8\xb4U\xf7\x83\xfa\x11,,l\x1eVm\xf8TU\xd5\xd6\x1eo\xc3\x12\xb0\xb0\xb03\xb1\n2$`aa\xe7c\xe3\xf1\xdd\xbeU^\xc2[\x14\xec\xaa-t\x86\x85\xfd\x93lC\xd6\x87[\x1c-\xedu \xe3\x16\x82\x85\x85\x9d\xca\xea\xb3\x93QVd\xa8\x82\xedZ\xbd\x84\xec\xc1)\x00\x0b\x0b\x9b\x83\x15\xa7\xee\xf2\x88\xe1\xc2k\xc5\x1d&`a\x9f\xc0\x1a\xf1#\x175\\\xb6ID\xfb\xb0\xf1\x80\x85\x85\xcd\xc1Z\xb9\xf6\xe4\xd8p\xd1\xdc\xc4n )\xbf\x19,\xecrX\x99@\x8aK\x1d\xfbp\xbe\xd1\xeb\xb3\x1feY\xbe\xa87R\xb6W`aa\x97\xc1\xda\xb9W\xd3g\x94\xd2_2\xfd|\xbc\xfb\xa8d\x12\xb0\xb0\xbf\xc7\xfa}Ie\xc5\n\xc4\x9d}_\xdfb\x93z\xce\xae\xbb\x80\x85\x85\xcd\xcf\x86\x9b[\xf4Er\x85=\xba\xd9\xb68\xacaaa\x9f\xc8F7\x93\xea\x8fz%\x06\xadh\xc2\xc2\xe6`\xdd\x9c5\x1d\xfb\x9e\x136\x89\xcd-\xb0\xb0\xb0cYwM\xdb\xe4\x8c\xc4n4X\xd8e\xb1\xb6\xf4\xca}`\x86\x9dO)\xe0e\x8e\xe9\xed\x9c\xb0\xb0\xb0\x13\xd8\xb0\x87\x8b\xb9\xd7\xc7\xd5\x95B\xfd\xffP\x0e\x0b\xfb?\xd9\x1f\xd9\xb2to\xf9Q\xd6\xee\x00\x00\x00\x00IEND\xaeB`\x82'
+ test(q, bus, conn, stream, image_data=avatar, mime_type='image/png')
+
+if __name__ == '__main__':
+ exec_test(test_little_avatar)
+ exec_test(test_massive_avatar)
diff --git a/tests/twisted/vcard/set-set-disconnect.py b/tests/twisted/vcard/set-set-disconnect.py
index b7b73151d..e35ee9744 100644
--- a/tests/twisted/vcard/set-set-disconnect.py
+++ b/tests/twisted/vcard/set-set-disconnect.py
@@ -4,7 +4,7 @@ Regression test for crash when disconnecting in the middle of a set.
"""
from servicetest import EventPattern, call_async, sync_dbus
-from gabbletest import exec_test, acknowledge_iq, expect_and_handle_get_vcard, sync_stream
+from gabbletest import exec_test, acknowledge_iq, expect_and_handle_get_vcard, sync_stream, disconnect_conn
import constants as cs
def test(q, bus, conn, stream):
@@ -18,9 +18,9 @@ def test(q, bus, conn, stream):
'stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard')
call_async(
q, conn.Avatars, 'SetAvatar', 'LeChuck.brush', 'image/x-ghost-pirate')
- conn.Disconnect()
- q.expect('dbus-signal', signal='StatusChanged',
- args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]),
+
+ disconnect_conn(q, conn, stream)
+
q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
sync_dbus(bus, q, conn)
diff --git a/tests/twisted/vcard/supported-fields.py b/tests/twisted/vcard/supported-fields.py
index 074d2331c..7a7860ce1 100644
--- a/tests/twisted/vcard/supported-fields.py
+++ b/tests/twisted/vcard/supported-fields.py
@@ -41,6 +41,7 @@ def check_google_props(props):
assertEquals([
('fn', [], PARAMS_EXACT | OVERWRITTEN_BY_NICKNAME, 1),
('n', [], PARAMS_EXACT, 1),
+ ('url', [], PARAMS_EXACT, UNLIMITED),
], sf)
def check_normal_props(props):
diff --git a/tests/twisted/vcard/test-vcard-race.py b/tests/twisted/vcard/test-vcard-race.py
index 291a0df57..5ecd978e1 100644
--- a/tests/twisted/vcard/test-vcard-race.py
+++ b/tests/twisted/vcard/test-vcard-race.py
@@ -13,7 +13,7 @@ import base64
from twisted.words.xish import xpath
-from servicetest import call_async, sync_dbus
+from servicetest import call_async, sync_dbus, assertEquals
from gabbletest import (
exec_test, expect_and_handle_get_vcard, expect_and_handle_set_vcard,
make_result_iq, sync_stream)
@@ -64,9 +64,9 @@ def test(q, bus, conn, stream):
assert types is not None and len(types) == 1, repr(types)
assert binvals is not None and len(binvals) == 1, repr(binvals)
assert str(types[0]) == 'image/png'
- got = str(binvals[0])
+ got = str(binvals[0]).strip()
exp = base64.b64encode('hello')
- assert got == exp, (got, exp)
+ assertEquals(exp, got)
# Now Gabble should set a new vCard with both of the above changes.
expect_and_handle_set_vcard(q, stream, has_nickname_and_photo)
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 3cfcfe923..5b78d699c 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,3 +1,21 @@
+abs_top_builddir = @abs_top_builddir@
+
+noinst_SCRIPTS = telepathy-glib-env
+
+telepathy-glib-env: telepathy-glib-env.in Makefile
+ sed -e 's![@]abs_top_builddir[@]!$(abs_top_builddir)!' $< > $@
+ chmod +x $@
+
+if ENABLE_INSTALLED_TESTS
+toolsdir = @tpglibtestsdir@/tools
+tools_SCRIPTS = \
+ with-session-bus.sh \
+ test-wrapper.sh \
+ libglibcodegen.py \
+ libtpcodegen.py \
+ $(NULL)
+endif
+
EXTRA_DIST = \
c-constants-gen.py \
check-coding-style.mk \
@@ -5,29 +23,50 @@ EXTRA_DIST = \
check-misc.sh \
check-whitespace.sh \
doc-generator.xsl \
+ flymake.mk \
+ git-which-branch.sh \
+ glib-client-gen.py \
+ glib-client-marshaller-gen.py \
+ glib-errors-check-gen.py \
+ glib-errors-str-gen.py \
glib-ginterface-gen.py \
glib-gtypes-generator.py \
glib-interfaces-gen.py \
- glib-signals-marshal-gen.py \
+ gobject-foo.py \
lcov.am \
- libglibcodegen.py \
libtpcodegen.py \
+ libglibcodegen.py \
make-release-mail.py \
+ make-version-script.py \
+ manager-file.py \
+ shave.mk \
telepathy.am \
+ telepathy-glib.supp \
+ telepathy-glib-env.in \
+ test-wrapper.sh \
+ with-session-bus.sh \
xincludator.py
-CLEANFILES = *.pyc *.pyo
+CLEANFILES = libtpcodegen.pyc libtpcodegen.pyo libglibcodegen.pyc libglibcodegen.pyo $(noinst_SCRIPTS)
all: $(EXTRA_DIST)
libglibcodegen.py: libtpcodegen.py
- test -e $<
- $(AM_V_GEN)touch $@
-
-glib-ginterface-gen.py glib-gtypes-generator.py glib-interfaces-gen.py \
-glib-signals-marshal-gen.py c-constants-gen.py: %: libglibcodegen.py
- test -e $<
- $(AM_V_GEN)touch $@
+ $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
+c-constants-gen.py: libglibcodegen.py
+ $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
+glib-client-marshaller-gen.py: libglibcodegen.py
+ $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
+glib-errors-enum-body-gen.py: libglibcodegen.py
+ $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
+glib-errors-enum-header-gen.py: libglibcodegen.py
+ $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
+glib-ginterface-gen.py: libglibcodegen.py
+ $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
+glib-gtypes-generator.py: libglibcodegen.py
+ $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
+glib-interfaces-gen.py: libglibcodegen.py
+ $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
TELEPATHY_GLIB_SRCDIR = $(top_srcdir)/../telepathy-glib
maintainer-update-from-telepathy-glib:
diff --git a/tools/c-constants-gen.py b/tools/c-constants-gen.py
index ff2a24d47..c7a93d371 100644
--- a/tools/c-constants-gen.py
+++ b/tools/c-constants-gen.py
@@ -3,6 +3,7 @@
from sys import argv, stdout, stderr
import xml.dom.minidom
+from libtpcodegen import file_set_contents
from libglibcodegen import NS_TP, get_docstring, \
get_descendant_text, get_by_path
@@ -11,19 +12,23 @@ class Generator(object):
self.prefix = prefix + '_'
self.spec = get_by_path(dom, "spec")[0]
- self.__header = open(output_base + '.h', 'w')
- self.__docs = open(output_base + '-gtk-doc.h', 'w')
+ self.output_base = output_base
+ self.__header = []
+ self.__docs = []
def __call__(self):
self.do_header()
self.do_body()
self.do_footer()
+ file_set_contents(self.output_base + '.h', ''.join(self.__header))
+ file_set_contents(self.output_base + '-gtk-doc.h', ''.join(self.__docs))
+
def write(self, code):
- self.__header.write(code.encode('utf-8'))
+ self.__header.append(code.encode('utf-8'))
def d(self, code):
- self.__docs.write(code.encode('utf-8'))
+ self.__docs.append(code.encode('utf-8'))
# Header
def do_header(self):
@@ -62,8 +67,7 @@ extern "C" {
flags.getAttribute('name')
self.d("""\
/**
- *
-%s:
+ * %s:
""" % (self.prefix + name).replace('_', ''))
for flag in get_by_path(flags, 'flag'):
self.do_gtkdoc(flag, value_prefix)
@@ -97,8 +101,7 @@ extern "C" {
enum.getAttribute('name') + 's'
self.d("""\
/**
- *
-%s:
+ * %s:
""" % (self.prefix + name).replace('_', ''))
vals = get_by_path(enum, 'enumvalue')
for val in vals:
@@ -123,19 +126,29 @@ extern "C" {
self.d("""\
/**
- * NUM_%(upper-plural)s: (skip)
+ * %(upper-prefix)sNUM_%(upper-plural)s:
+ *
+ * 1 higher than the highest valid value of #%(mixed-name)s.
+ */
+
+/**
+ * NUM_%(upper-prefix)s%(upper-plural)s: (skip)
*
* 1 higher than the highest valid value of #%(mixed-name)s.
+ * In new code, use %(upper-prefix)sNUM_%(upper-plural)s instead.
*/
""" % {'mixed-name' : (self.prefix + name).replace('_', ''),
- 'upper-plural' : (self.prefix + name_plural).upper(),
+ 'upper-prefix' : self.prefix.upper(),
+ 'upper-plural' : name_plural.upper(),
'last-val' : vals[-1].getAttribute('value')})
self.write("""\
-#define NUM_%(upper-plural)s (%(last-val)s+1)
+#define %(upper-prefix)sNUM_%(upper-plural)s (%(last-val)s+1)
+#define NUM_%(upper-prefix)s%(upper-plural)s %(upper-prefix)sNUM_%(upper-plural)s
""" % {'mixed-name' : (self.prefix + name).replace('_', ''),
- 'upper-plural' : (self.prefix + name_plural).upper(),
+ 'upper-prefix' : self.prefix.upper(),
+ 'upper-plural' : name_plural.upper(),
'last-val' : vals[-1].getAttribute('value')})
def do_val(self, val, value_prefix):
diff --git a/tools/check-c-style.sh b/tools/check-c-style.sh
index 4330b1479..55834207a 100644
--- a/tools/check-c-style.sh
+++ b/tools/check-c-style.sh
@@ -3,13 +3,6 @@ fail=0
( . "${tools_dir}"/check-misc.sh ) || fail=$?
-if grep -n '^ *GError *\*[[:alpha:]_][[:alnum:]_]* *;' "$@"
-then
- echo "^^^ The above files contain uninitialized GError*s - they should be"
- echo " initialized to NULL"
- fail=1
-fi
-
# The first regex finds function calls like foo() (as opposed to foo ()).
# It attempts to ignore string constants (may cause false negatives).
# The second and third ignore block comments (gtkdoc uses foo() as markup).
diff --git a/tools/flymake.mk b/tools/flymake.mk
new file mode 100644
index 000000000..020a7bfbf
--- /dev/null
+++ b/tools/flymake.mk
@@ -0,0 +1,4 @@
+check-syntax:
+ $(CC) $(AM_CPPFLAGS) $(AM_CFLAGS) -fsyntax-only $(CHK_SOURCES)
+
+.PHONY: check-syntax
diff --git a/tools/git-which-branch.sh b/tools/git-which-branch.sh
new file mode 100644
index 000000000..b96b5d5e2
--- /dev/null
+++ b/tools/git-which-branch.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# git-which-branch.sh - output the name of the current git branch
+#
+# The canonical location of this program is the telepathy-spec tools/
+# directory, please synchronize any changes with that copy.
+#
+# Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+default="$1"
+if { ref="`git symbolic-ref HEAD 2>/dev/null`"; }; then
+ echo ${ref#refs/heads/}
+ exit 0
+fi
+
+if test -n "$default"; then
+ echo "$default" >/dev/null
+ exit 0
+fi
+
+echo "no git branch found" >&2
+exit 1
diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py
new file mode 100644
index 000000000..f8465a62b
--- /dev/null
+++ b/tools/glib-client-gen.py
@@ -0,0 +1,1269 @@
+#!/usr/bin/python
+
+# glib-client-gen.py: "I Can't Believe It's Not dbus-binding-tool"
+#
+# Generate GLib client wrappers from the Telepathy specification.
+# The master copy of this program is in the telepathy-glib repository -
+# please make any changes there.
+#
+# Copyright (C) 2006-2008 Collabora Ltd. <http://www.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
+
+import sys
+import os.path
+import xml.dom.minidom
+from getopt import gnu_getopt
+
+from libtpcodegen import file_set_contents
+from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \
+ get_docstring, xml_escape, get_deprecated
+
+
+NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
+
+class Generator(object):
+
+ def __init__(self, dom, prefix, basename, opts):
+ self.dom = dom
+ self.__header = []
+ self.__body = []
+ self.__docs = []
+
+ self.prefix_lc = prefix.lower()
+ self.prefix_uc = prefix.upper()
+ self.prefix_mc = prefix.replace('_', '')
+ self.basename = basename
+ self.group = opts.get('--group', None)
+ self.iface_quark_prefix = opts.get('--iface-quark-prefix', None)
+ self.tp_proxy_api = tuple(map(int,
+ opts.get('--tp-proxy-api', '0').split('.')))
+ self.proxy_cls = opts.get('--subclass', 'TpProxy') + ' *'
+ self.proxy_arg = opts.get('--subclass', 'void') + ' *'
+ self.proxy_assert = opts.get('--subclass-assert', 'TP_IS_PROXY')
+ self.proxy_doc = ('A #%s or subclass'
+ % opts.get('--subclass', 'TpProxy'))
+ if self.proxy_arg == 'void *':
+ self.proxy_arg = 'gpointer '
+
+ self.reentrant_symbols = set()
+ try:
+ filename = opts['--generate-reentrant']
+ with open(filename, 'r') as f:
+ for line in f.readlines():
+ self.reentrant_symbols.add(line.strip())
+ except KeyError:
+ pass
+
+ self.deprecate_reentrant = opts.get('--deprecate-reentrant', None)
+ self.deprecation_attribute = opts.get('--deprecation-attribute',
+ 'G_GNUC_DEPRECATED')
+
+ self.guard = opts.get('--guard', None)
+
+ def h(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
+ self.__header.append(s)
+
+ def b(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
+ self.__body.append(s)
+
+ def d(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
+ self.__docs.append(s)
+
+ def get_iface_quark(self):
+ assert self.iface_dbus is not None
+ assert self.iface_uc is not None
+ if self.iface_quark_prefix is None:
+ return 'g_quark_from_static_string (\"%s\")' % self.iface_dbus
+ else:
+ return '%s_%s' % (self.iface_quark_prefix, self.iface_uc)
+
+ def do_signal(self, iface, signal):
+ iface_lc = iface.lower()
+
+ member = signal.getAttribute('name')
+ member_lc = signal.getAttribute('tp:name-for-bindings')
+ if member != member_lc.replace('_', ''):
+ raise AssertionError('Signal %s tp:name-for-bindings (%s) does '
+ 'not match' % (member, member_lc))
+ member_lc = member_lc.lower()
+ member_uc = member_lc.upper()
+
+ arg_count = 0
+ args = []
+ out_args = []
+
+ for arg in signal.getElementsByTagName('arg'):
+ name = arg.getAttribute('name')
+ type = arg.getAttribute('type')
+ tp_type = arg.getAttribute('tp:type')
+
+ if not name:
+ name = 'arg%u' % arg_count
+ arg_count += 1
+ else:
+ name = 'arg_%s' % name
+
+ info = type_to_gtype(type)
+ args.append((name, info, tp_type, arg))
+
+ callback_name = ('%s_%s_signal_callback_%s'
+ % (self.prefix_lc, iface_lc, member_lc))
+ collect_name = ('_%s_%s_collect_args_of_%s'
+ % (self.prefix_lc, iface_lc, member_lc))
+ invoke_name = ('_%s_%s_invoke_callback_for_%s'
+ % (self.prefix_lc, iface_lc, member_lc))
+
+ # Example:
+ #
+ # typedef void (*tp_cli_connection_signal_callback_new_channel)
+ # (TpConnection *proxy, const gchar *arg_object_path,
+ # const gchar *arg_channel_type, guint arg_handle_type,
+ # guint arg_handle, gboolean arg_suppress_handler,
+ # gpointer user_data, GObject *weak_object);
+
+ self.d('/**')
+ self.d(' * %s:' % callback_name)
+ self.d(' * @proxy: The proxy on which %s_%s_connect_to_%s ()'
+ % (self.prefix_lc, iface_lc, member_lc))
+ self.d(' * was called')
+
+ for arg in args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ docs = get_docstring(elt) or '(Undocumented)'
+
+ if ctype == 'guint ' and tp_type != '':
+ docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
+
+ self.d(' * @%s: %s' % (name, xml_escape(docs)))
+
+ self.d(' * @user_data: User-supplied data')
+ self.d(' * @weak_object: User-supplied weakly referenced object')
+ self.d(' *')
+ self.d(' * Represents the signature of a callback for the signal %s.'
+ % member)
+ self.d(' */')
+ self.d('')
+
+ self.h('typedef void (*%s) (%sproxy,'
+ % (callback_name, self.proxy_cls))
+
+ for arg in args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ const = pointer and 'const ' or ''
+
+ self.h(' %s%s%s,' % (const, ctype, name))
+
+ self.h(' gpointer user_data, GObject *weak_object);')
+
+ if args:
+ self.b('static void')
+ self.b('%s (DBusGProxy *proxy G_GNUC_UNUSED,' % collect_name)
+
+ for arg in args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ const = pointer and 'const ' or ''
+
+ self.b(' %s%s%s,' % (const, ctype, name))
+
+ self.b(' TpProxySignalConnection *sc)')
+ self.b('{')
+ self.b(' GValueArray *args = g_value_array_new (%d);' % len(args))
+ self.b(' GValue blank = { 0 };')
+ self.b(' guint i;')
+ self.b('')
+ self.b(' g_value_init (&blank, G_TYPE_INT);')
+ self.b('')
+ self.b(' for (i = 0; i < %d; i++)' % len(args))
+ self.b(' g_value_array_append (args, &blank);')
+ self.b('')
+
+ for i, arg in enumerate(args):
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ self.b(' g_value_unset (args->values + %d);' % i)
+ self.b(' g_value_init (args->values + %d, %s);' % (i, gtype))
+
+ if gtype == 'G_TYPE_STRING':
+ self.b(' g_value_set_string (args->values + %d, %s);'
+ % (i, name))
+ elif marshaller == 'BOXED':
+ self.b(' g_value_set_boxed (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_UCHAR':
+ self.b(' g_value_set_uchar (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_BOOLEAN':
+ self.b(' g_value_set_boolean (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_INT':
+ self.b(' g_value_set_int (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_UINT':
+ self.b(' g_value_set_uint (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_INT64':
+ self.b(' g_value_set_int (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_UINT64':
+ self.b(' g_value_set_uint64 (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_DOUBLE':
+ self.b(' g_value_set_double (args->values + %d, %s);'
+ % (i, name))
+ else:
+ assert False, ("Don't know how to put %s in a GValue"
+ % gtype)
+ self.b('')
+
+ self.b(' tp_proxy_signal_connection_v0_take_results (sc, args);')
+ self.b('}')
+
+ self.b('static void')
+ self.b('%s (TpProxy *tpproxy,' % invoke_name)
+ self.b(' GError *error G_GNUC_UNUSED,')
+ self.b(' GValueArray *args,')
+ self.b(' GCallback generic_callback,')
+ self.b(' gpointer user_data,')
+ self.b(' GObject *weak_object)')
+ self.b('{')
+ self.b(' %s callback =' % callback_name)
+ self.b(' (%s) generic_callback;' % callback_name)
+ self.b('')
+ self.b(' if (callback != NULL)')
+ self.b(' callback (g_object_ref (tpproxy),')
+
+ # FIXME: factor out into a function
+ for i, arg in enumerate(args):
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ if marshaller == 'BOXED':
+ self.b(' g_value_get_boxed (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_STRING':
+ self.b(' g_value_get_string (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_UCHAR':
+ self.b(' g_value_get_uchar (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_BOOLEAN':
+ self.b(' g_value_get_boolean (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_UINT':
+ self.b(' g_value_get_uint (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_INT':
+ self.b(' g_value_get_int (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_UINT64':
+ self.b(' g_value_get_uint64 (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_INT64':
+ self.b(' g_value_get_int64 (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_DOUBLE':
+ self.b(' g_value_get_double (args->values + %d),' % i)
+ else:
+ assert False, "Don't know how to get %s from a GValue" % gtype
+
+ self.b(' user_data,')
+ self.b(' weak_object);')
+ self.b('')
+
+ if len(args) > 0:
+ self.b(' g_value_array_free (args);')
+ else:
+ self.b(' if (args != NULL)')
+ self.b(' g_value_array_free (args);')
+ self.b('')
+
+ self.b(' g_object_unref (tpproxy);')
+ self.b('}')
+
+ # Example:
+ #
+ # TpProxySignalConnection *
+ # tp_cli_connection_connect_to_new_channel
+ # (TpConnection *proxy,
+ # tp_cli_connection_signal_callback_new_channel callback,
+ # gpointer user_data,
+ # GDestroyNotify destroy);
+ #
+ # destroy is invoked when the signal becomes disconnected. This
+ # is either because the signal has been disconnected explicitly
+ # by the user, because the TpProxy has become invalid and
+ # emitted the 'invalidated' signal, or because the weakly referenced
+ # object has gone away.
+
+ self.d('/**')
+ self.d(' * %s_%s_connect_to_%s:'
+ % (self.prefix_lc, iface_lc, member_lc))
+ self.d(' * @proxy: %s' % self.proxy_doc)
+ self.d(' * @callback: Callback to be called when the signal is')
+ self.d(' * received')
+ self.d(' * @user_data: User-supplied data for the callback')
+ self.d(' * @destroy: Destructor for the user-supplied data, which')
+ self.d(' * will be called when this signal is disconnected, or')
+ self.d(' * before this function returns %NULL')
+ self.d(' * @weak_object: A #GObject which will be weakly referenced; ')
+ self.d(' * if it is destroyed, this callback will automatically be')
+ self.d(' * disconnected')
+ self.d(' * @error: If not %NULL, used to raise an error if %NULL is')
+ self.d(' * returned')
+ self.d(' *')
+ self.d(' * Connect a handler to the signal %s.' % member)
+ self.d(' *')
+ self.d(' * %s' % xml_escape(get_docstring(signal) or '(Undocumented)'))
+ self.d(' *')
+ self.d(' * Returns: a #TpProxySignalConnection containing all of the')
+ self.d(' * above, which can be used to disconnect the signal; or')
+ self.d(' * %NULL if the proxy does not have the desired interface')
+ self.d(' * or has become invalid.')
+ self.d(' */')
+ self.d('')
+
+ self.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,'
+ % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
+ self.h(' %s callback,' % callback_name)
+ self.h(' gpointer user_data,')
+ self.h(' GDestroyNotify destroy,')
+ self.h(' GObject *weak_object,')
+ self.h(' GError **error);')
+ self.h('')
+
+ self.b('TpProxySignalConnection *')
+ self.b('%s_%s_connect_to_%s (%sproxy,'
+ % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
+ self.b(' %s callback,' % callback_name)
+ self.b(' gpointer user_data,')
+ self.b(' GDestroyNotify destroy,')
+ self.b(' GObject *weak_object,')
+ self.b(' GError **error)')
+ self.b('{')
+ self.b(' GType expected_types[%d] = {' % (len(args) + 1))
+
+ for arg in args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ self.b(' %s,' % gtype)
+
+ self.b(' G_TYPE_INVALID };')
+ self.b('')
+ self.b(' g_return_val_if_fail (%s (proxy), NULL);'
+ % self.proxy_assert)
+ self.b(' g_return_val_if_fail (callback != NULL, NULL);')
+ self.b('')
+ self.b(' return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,')
+ self.b(' %s, \"%s\",' % (self.get_iface_quark(), member))
+ self.b(' expected_types,')
+
+ if args:
+ self.b(' G_CALLBACK (%s),' % collect_name)
+ else:
+ self.b(' NULL, /* no args => no collector function */')
+
+ self.b(' %s,' % invoke_name)
+ self.b(' G_CALLBACK (callback), user_data, destroy,')
+ self.b(' weak_object, error);')
+ self.b('}')
+ self.b('')
+
+ def do_method(self, iface, method):
+ iface_lc = iface.lower()
+
+ member = method.getAttribute('name')
+ member_lc = method.getAttribute('tp:name-for-bindings')
+ if member != member_lc.replace('_', ''):
+ raise AssertionError('Method %s tp:name-for-bindings (%s) does '
+ 'not match' % (member, member_lc))
+ member_lc = member_lc.lower()
+ member_uc = member_lc.upper()
+
+ in_count = 0
+ ret_count = 0
+ in_args = []
+ out_args = []
+
+ for arg in method.getElementsByTagName('arg'):
+ name = arg.getAttribute('name')
+ direction = arg.getAttribute('direction')
+ type = arg.getAttribute('type')
+ tp_type = arg.getAttribute('tp:type')
+
+ if direction != 'out':
+ if not name:
+ name = 'in%u' % in_count
+ in_count += 1
+ else:
+ name = 'in_%s' % name
+ else:
+ if not name:
+ name = 'out%u' % ret_count
+ ret_count += 1
+ else:
+ name = 'out_%s' % name
+
+ info = type_to_gtype(type)
+ if direction != 'out':
+ in_args.append((name, info, tp_type, arg))
+ else:
+ out_args.append((name, info, tp_type, arg))
+
+ # Async reply callback type
+
+ # Example:
+ # void (*tp_cli_properties_interface_callback_for_get_properties)
+ # (TpProxy *proxy,
+ # const GPtrArray *out0,
+ # const GError *error,
+ # gpointer user_data,
+ # GObject *weak_object);
+
+ self.d('/**')
+ self.d(' * %s_%s_callback_for_%s:'
+ % (self.prefix_lc, iface_lc, member_lc))
+ self.d(' * @proxy: the proxy on which the call was made')
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ docs = xml_escape(get_docstring(elt) or '(Undocumented)')
+
+ if ctype == 'guint ' and tp_type != '':
+ docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
+
+ self.d(' * @%s: Used to return an \'out\' argument if @error is '
+ '%%NULL: %s'
+ % (name, docs))
+
+ self.d(' * @error: %NULL on success, or an error on failure')
+ self.d(' * @user_data: user-supplied data')
+ self.d(' * @weak_object: user-supplied object')
+ self.d(' *')
+ self.d(' * Signature of the callback called when a %s method call'
+ % member)
+ self.d(' * succeeds or fails.')
+
+ deprecated = method.getElementsByTagName('tp:deprecated')
+ if deprecated:
+ d = deprecated[0]
+ self.d(' *')
+ self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
+
+ self.d(' */')
+ self.d('')
+
+ callback_name = '%s_%s_callback_for_%s' % (self.prefix_lc, iface_lc,
+ member_lc)
+
+ self.h('typedef void (*%s) (%sproxy,'
+ % (callback_name, self.proxy_cls))
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+ const = pointer and 'const ' or ''
+
+ self.h(' %s%s%s,' % (const, ctype, name))
+
+ self.h(' const GError *error, gpointer user_data,')
+ self.h(' GObject *weak_object);')
+ self.h('')
+
+ # Async callback implementation
+
+ invoke_callback = '_%s_%s_invoke_callback_%s' % (self.prefix_lc,
+ iface_lc,
+ member_lc)
+
+ collect_callback = '_%s_%s_collect_callback_%s' % (self.prefix_lc,
+ iface_lc,
+ member_lc)
+
+ # The callback called by dbus-glib; this ends the call and collects
+ # the results into a GValueArray.
+ self.b('static void')
+ self.b('%s (DBusGProxy *proxy,' % collect_callback)
+ self.b(' DBusGProxyCall *call,')
+ self.b(' gpointer user_data)')
+ self.b('{')
+ self.b(' GError *error = NULL;')
+
+ if len(out_args) > 0:
+ self.b(' GValueArray *args;')
+ self.b(' GValue blank = { 0 };')
+ self.b(' guint i;')
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ # "We handle variants specially; the caller is expected to
+ # have already allocated storage for them". Thanks,
+ # dbus-glib...
+ if gtype == 'G_TYPE_VALUE':
+ self.b(' GValue *%s = g_new0 (GValue, 1);' % name)
+ else:
+ self.b(' %s%s;' % (ctype, name))
+
+ self.b('')
+ self.b(' dbus_g_proxy_end_call (proxy, call, &error,')
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ if gtype == 'G_TYPE_VALUE':
+ self.b(' %s, %s,' % (gtype, name))
+ else:
+ self.b(' %s, &%s,' % (gtype, name))
+
+ self.b(' G_TYPE_INVALID);')
+
+ if len(out_args) == 0:
+ self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,'
+ 'NULL);')
+ else:
+ self.b('')
+ self.b(' if (error != NULL)')
+ self.b(' {')
+ self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,')
+ self.b(' NULL);')
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+ if gtype == 'G_TYPE_VALUE':
+ self.b(' g_free (%s);' % name)
+
+ self.b(' return;')
+ self.b(' }')
+ self.b('')
+ self.b(' args = g_value_array_new (%d);' % len(out_args))
+ self.b(' g_value_init (&blank, G_TYPE_INT);')
+ self.b('')
+ self.b(' for (i = 0; i < %d; i++)' % len(out_args))
+ self.b(' g_value_array_append (args, &blank);')
+
+ for i, arg in enumerate(out_args):
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ self.b('')
+ self.b(' g_value_unset (args->values + %d);' % i)
+ self.b(' g_value_init (args->values + %d, %s);' % (i, gtype))
+
+ if gtype == 'G_TYPE_STRING':
+ self.b(' g_value_take_string (args->values + %d, %s);'
+ % (i, name))
+ elif marshaller == 'BOXED':
+ self.b(' g_value_take_boxed (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_UCHAR':
+ self.b(' g_value_set_uchar (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_BOOLEAN':
+ self.b(' g_value_set_boolean (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_INT':
+ self.b(' g_value_set_int (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_UINT':
+ self.b(' g_value_set_uint (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_INT64':
+ self.b(' g_value_set_int (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_UINT64':
+ self.b(' g_value_set_uint (args->values + %d, %s);'
+ % (i, name))
+ elif gtype == 'G_TYPE_DOUBLE':
+ self.b(' g_value_set_double (args->values + %d, %s);'
+ % (i, name))
+ else:
+ assert False, ("Don't know how to put %s in a GValue"
+ % gtype)
+
+ self.b(' tp_proxy_pending_call_v0_take_results (user_data, '
+ 'NULL, args);')
+
+ self.b('}')
+
+ self.b('static void')
+ self.b('%s (TpProxy *self,' % invoke_callback)
+ self.b(' GError *error,')
+ self.b(' GValueArray *args,')
+ self.b(' GCallback generic_callback,')
+ self.b(' gpointer user_data,')
+ self.b(' GObject *weak_object)')
+ self.b('{')
+ self.b(' %s callback = (%s) generic_callback;'
+ % (callback_name, callback_name))
+ self.b('')
+ self.b(' if (error != NULL)')
+ self.b(' {')
+ self.b(' callback ((%s) self,' % self.proxy_cls)
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ if marshaller == 'BOXED' or pointer:
+ self.b(' NULL,')
+ elif gtype == 'G_TYPE_DOUBLE':
+ self.b(' 0.0,')
+ else:
+ self.b(' 0,')
+
+ self.b(' error, user_data, weak_object);')
+ self.b(' g_error_free (error);')
+ self.b(' return;')
+ self.b(' }')
+
+ self.b(' callback ((%s) self,' % self.proxy_cls)
+
+ # FIXME: factor out into a function
+ for i, arg in enumerate(out_args):
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ if marshaller == 'BOXED':
+ self.b(' g_value_get_boxed (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_STRING':
+ self.b(' g_value_get_string (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_UCHAR':
+ self.b(' g_value_get_uchar (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_BOOLEAN':
+ self.b(' g_value_get_boolean (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_UINT':
+ self.b(' g_value_get_uint (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_INT':
+ self.b(' g_value_get_int (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_UINT64':
+ self.b(' g_value_get_uint64 (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_INT64':
+ self.b(' g_value_get_int64 (args->values + %d),' % i)
+ elif gtype == 'G_TYPE_DOUBLE':
+ self.b(' g_value_get_double (args->values + %d),' % i)
+ else:
+ assert False, "Don't know how to get %s from a GValue" % gtype
+
+ self.b(' error, user_data, weak_object);')
+ self.b('')
+
+ if len(out_args) > 0:
+ self.b(' g_value_array_free (args);')
+ else:
+ self.b(' if (args != NULL)')
+ self.b(' g_value_array_free (args);')
+
+ self.b('}')
+ self.b('')
+
+ # Async stub
+
+ # Example:
+ # TpProxyPendingCall *
+ # tp_cli_properties_interface_call_get_properties
+ # (gpointer proxy,
+ # gint timeout_ms,
+ # const GArray *in_properties,
+ # tp_cli_properties_interface_callback_for_get_properties callback,
+ # gpointer user_data,
+ # GDestroyNotify *destructor);
+
+ self.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,'
+ % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
+ self.h(' gint timeout_ms,')
+
+ self.d('/**')
+ self.d(' * %s_%s_call_%s:'
+ % (self.prefix_lc, iface_lc, member_lc))
+ self.d(' * @proxy: the #TpProxy')
+ self.d(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
+ self.d(' * default')
+
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ docs = xml_escape(get_docstring(elt) or '(Undocumented)')
+
+ if ctype == 'guint ' and tp_type != '':
+ docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
+
+ self.d(' * @%s: Used to pass an \'in\' argument: %s'
+ % (name, docs))
+
+ self.d(' * @callback: called when the method call succeeds or fails;')
+ self.d(' * may be %NULL to make a "fire and forget" call with no ')
+ self.d(' * reply tracking')
+ self.d(' * @user_data: user-supplied data passed to the callback;')
+ self.d(' * must be %NULL if @callback is %NULL')
+ self.d(' * @destroy: called with the user_data as argument, after the')
+ self.d(' * call has succeeded, failed or been cancelled;')
+ self.d(' * must be %NULL if @callback is %NULL')
+ self.d(' * @weak_object: If not %NULL, a #GObject which will be ')
+ self.d(' * weakly referenced; if it is destroyed, this call ')
+ self.d(' * will automatically be cancelled. Must be %NULL if ')
+ self.d(' * @callback is %NULL')
+ self.d(' *')
+ self.d(' * Start a %s method call.' % member)
+ self.d(' *')
+ self.d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
+ self.d(' *')
+ self.d(' * Returns: a #TpProxyPendingCall representing the call in')
+ self.d(' * progress. It is borrowed from the object, and will become')
+ self.d(' * invalid when the callback is called, the call is')
+ self.d(' * cancelled or the #TpProxy becomes invalid.')
+
+ deprecated = method.getElementsByTagName('tp:deprecated')
+ if deprecated:
+ d = deprecated[0]
+ self.d(' *')
+ self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
+
+ self.d(' */')
+ self.d('')
+
+ self.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,'
+ % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
+ self.b(' gint timeout_ms,')
+
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ const = pointer and 'const ' or ''
+
+ self.h(' %s%s%s,' % (const, ctype, name))
+ self.b(' %s%s%s,' % (const, ctype, name))
+
+ self.h(' %s callback,' % callback_name)
+ self.h(' gpointer user_data,')
+ self.h(' GDestroyNotify destroy,')
+ self.h(' GObject *weak_object);')
+ self.h('')
+
+ self.b(' %s callback,' % callback_name)
+ self.b(' gpointer user_data,')
+ self.b(' GDestroyNotify destroy,')
+ self.b(' GObject *weak_object)')
+ self.b('{')
+ self.b(' GError *error = NULL;')
+ self.b(' GQuark interface = %s;' % self.get_iface_quark())
+ self.b(' DBusGProxy *iface;')
+ self.b('')
+ self.b(' g_return_val_if_fail (%s (proxy), NULL);'
+ % self.proxy_assert)
+ self.b(' g_return_val_if_fail (callback != NULL || '
+ 'user_data == NULL, NULL);')
+ self.b(' g_return_val_if_fail (callback != NULL || '
+ 'destroy == NULL, NULL);')
+ self.b(' g_return_val_if_fail (callback != NULL || '
+ 'weak_object == NULL, NULL);')
+ self.b('')
+ self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
+ self.b(' iface = tp_proxy_borrow_interface_by_id (')
+ self.b(' (TpProxy *) proxy,')
+ self.b(' interface, &error);')
+ self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
+ self.b('')
+ self.b(' if (iface == NULL)')
+ self.b(' {')
+ self.b(' if (callback != NULL)')
+ self.b(' callback (proxy,')
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ if pointer:
+ self.b(' NULL,')
+ else:
+ self.b(' 0,')
+
+ self.b(' error, user_data, weak_object);')
+ self.b('')
+ self.b(' if (destroy != NULL)')
+ self.b(' destroy (user_data);')
+ self.b('')
+ self.b(' g_error_free (error);')
+ self.b(' return NULL;')
+ self.b(' }')
+ self.b('')
+ self.b(' if (callback == NULL)')
+ self.b(' {')
+ self.b(' dbus_g_proxy_call_no_reply (iface, "%s",' % member)
+
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ const = pointer and 'const ' or ''
+
+ self.b(' %s, %s,' % (gtype, name))
+
+ self.b(' G_TYPE_INVALID);')
+ self.b(' return NULL;')
+ self.b(' }')
+ self.b(' else')
+ self.b(' {')
+ self.b(' TpProxyPendingCall *data;')
+ self.b('')
+ self.b(' data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
+ self.b(' interface, "%s", iface,' % member)
+ self.b(' %s,' % invoke_callback)
+ self.b(' G_CALLBACK (callback), user_data, destroy,')
+ self.b(' weak_object, FALSE);')
+ self.b(' tp_proxy_pending_call_v0_take_pending_call (data,')
+ self.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
+ self.b(' "%s",' % member)
+ self.b(' %s,' % collect_callback)
+ self.b(' data,')
+ self.b(' tp_proxy_pending_call_v0_completed,')
+ self.b(' timeout_ms,')
+
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ const = pointer and 'const ' or ''
+
+ self.b(' %s, %s,' % (gtype, name))
+
+ self.b(' G_TYPE_INVALID));')
+ self.b('')
+ self.b(' return data;')
+ self.b(' }')
+ self.b('}')
+ self.b('')
+
+ self.do_method_reentrant(method, iface_lc, member, member_lc,
+ in_args, out_args, collect_callback)
+
+ # leave a gap for the end of the method
+ self.d('')
+ self.b('')
+ self.h('')
+
+ def do_method_reentrant(self, method, iface_lc, member, member_lc, in_args,
+ out_args, collect_callback):
+ # Reentrant blocking calls
+ # Example:
+ # gboolean tp_cli_properties_interface_run_get_properties
+ # (gpointer proxy,
+ # gint timeout_ms,
+ # const GArray *in_properties,
+ # GPtrArray **out0,
+ # GError **error,
+ # GMainLoop **loop);
+
+ run_method_name = '%s_%s_run_%s' % (self.prefix_lc, iface_lc, member_lc)
+ if run_method_name not in self.reentrant_symbols:
+ return
+
+ self.b('typedef struct {')
+ self.b(' GMainLoop *loop;')
+ self.b(' GError **error;')
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ self.b(' %s*%s;' % (ctype, name))
+
+ self.b(' unsigned success:1;')
+ self.b(' unsigned completed:1;')
+ self.b('} _%s_%s_run_state_%s;'
+ % (self.prefix_lc, iface_lc, member_lc))
+
+ reentrant_invoke = '_%s_%s_finish_running_%s' % (self.prefix_lc,
+ iface_lc,
+ member_lc)
+
+ self.b('static void')
+ self.b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke)
+ self.b(' GError *error,')
+ self.b(' GValueArray *args,')
+ self.b(' GCallback unused G_GNUC_UNUSED,')
+ self.b(' gpointer user_data G_GNUC_UNUSED,')
+ self.b(' GObject *unused2 G_GNUC_UNUSED)')
+ self.b('{')
+ self.b(' _%s_%s_run_state_%s *state = user_data;'
+ % (self.prefix_lc, iface_lc, member_lc))
+ self.b('')
+ self.b(' state->success = (error == NULL);')
+ self.b(' state->completed = TRUE;')
+ self.b(' g_main_loop_quit (state->loop);')
+ self.b('')
+ self.b(' if (error != NULL)')
+ self.b(' {')
+ self.b(' if (state->error != NULL)')
+ self.b(' *state->error = error;')
+ self.b(' else')
+ self.b(' g_error_free (error);')
+ self.b('')
+ self.b(' return;')
+ self.b(' }')
+ self.b('')
+
+ for i, arg in enumerate(out_args):
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ self.b(' if (state->%s != NULL)' % name)
+ if marshaller == 'BOXED':
+ self.b(' *state->%s = g_value_dup_boxed ('
+ 'args->values + %d);' % (name, i))
+ elif marshaller == 'STRING':
+ self.b(' *state->%s = g_value_dup_string '
+ '(args->values + %d);' % (name, i))
+ elif marshaller in ('UCHAR', 'BOOLEAN', 'INT', 'UINT',
+ 'INT64', 'UINT64', 'DOUBLE'):
+ self.b(' *state->%s = g_value_get_%s (args->values + %d);'
+ % (name, marshaller.lower(), i))
+ else:
+ assert False, "Don't know how to copy %s" % gtype
+
+ self.b('')
+
+ if len(out_args) > 0:
+ self.b(' g_value_array_free (args);')
+ else:
+ self.b(' if (args != NULL)')
+ self.b(' g_value_array_free (args);')
+
+ self.b('}')
+ self.b('')
+
+ if self.deprecate_reentrant:
+ self.h('#ifndef %s' % self.deprecate_reentrant)
+
+ self.h('gboolean %s (%sproxy,'
+ % (run_method_name, self.proxy_arg))
+ self.h(' gint timeout_ms,')
+
+ self.d('/**')
+ self.d(' * %s:' % run_method_name)
+ self.d(' * @proxy: %s' % self.proxy_doc)
+ self.d(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
+
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ docs = xml_escape(get_docstring(elt) or '(Undocumented)')
+
+ if ctype == 'guint ' and tp_type != '':
+ docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
+
+ self.d(' * @%s: Used to pass an \'in\' argument: %s'
+ % (name, docs))
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ self.d(' * @%s: Used to return an \'out\' argument if %%TRUE is '
+ 'returned: %s'
+ % (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
+
+ self.d(' * @error: If not %NULL, used to return errors if %FALSE ')
+ self.d(' * is returned')
+ self.d(' * @loop: If not %NULL, set before re-entering ')
+ self.d(' * the main loop, to point to a #GMainLoop ')
+ self.d(' * which can be used to cancel this call with ')
+ self.d(' * g_main_loop_quit(), causing a return of ')
+ self.d(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED')
+ self.d(' *')
+ self.d(' * Call the method %s and run the main loop' % member)
+ self.d(' * until it returns. Before calling this method, you must')
+ self.d(' * add a reference to any borrowed objects you need to keep,')
+ self.d(' * and generally ensure that everything is in a consistent')
+ self.d(' * state.')
+ self.d(' *')
+ self.d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
+ self.d(' *')
+ self.d(' * Returns: TRUE on success, FALSE and sets @error on error')
+
+ deprecated = method.getElementsByTagName('tp:deprecated')
+ if deprecated:
+ d = deprecated[0]
+ self.d(' *')
+ self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
+
+ self.d(' */')
+ self.d('')
+
+ self.b('gboolean\n%s (%sproxy,'
+ % (run_method_name, self.proxy_arg))
+ self.b(' gint timeout_ms,')
+
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ const = pointer and 'const ' or ''
+
+ self.h(' %s%s%s,' % (const, ctype, name))
+ self.b(' %s%s%s,' % (const, ctype, name))
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ self.h(' %s*%s,' % (ctype, name))
+ self.b(' %s*%s,' % (ctype, name))
+
+ self.h(' GError **error,')
+
+ if self.deprecate_reentrant:
+ self.h(' GMainLoop **loop) %s;' % self.deprecation_attribute)
+ self.h('#endif /* not %s */' % self.deprecate_reentrant)
+ else:
+ self.h(' GMainLoop **loop);')
+
+ self.h('')
+
+ self.b(' GError **error,')
+ self.b(' GMainLoop **loop)')
+ self.b('{')
+ self.b(' DBusGProxy *iface;')
+ self.b(' GQuark interface = %s;' % self.get_iface_quark())
+ self.b(' TpProxyPendingCall *pc;')
+ self.b(' _%s_%s_run_state_%s state = {'
+ % (self.prefix_lc, iface_lc, member_lc))
+ self.b(' NULL /* loop */, error,')
+
+ for arg in out_args:
+ name, info, tp_type, elt = arg
+
+ self.b(' %s,' % name)
+
+ self.b(' FALSE /* completed */, FALSE /* success */ };')
+ self.b('')
+ self.b(' g_return_val_if_fail (%s (proxy), FALSE);'
+ % self.proxy_assert)
+ self.b('')
+ self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
+ self.b(' iface = tp_proxy_borrow_interface_by_id')
+ self.b(' ((TpProxy *) proxy, interface, error);')
+ self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
+ self.b('')
+ self.b(' if (iface == NULL)')
+ self.b(' return FALSE;')
+ self.b('')
+ self.b(' state.loop = g_main_loop_new (NULL, FALSE);')
+ self.b('')
+ self.b(' pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
+ self.b(' interface, "%s", iface,' % member)
+ self.b(' %s,' % reentrant_invoke)
+ self.b(' NULL, &state, NULL, NULL, TRUE);')
+ self.b('')
+ self.b(' if (loop != NULL)')
+ self.b(' *loop = state.loop;')
+ self.b('')
+ self.b(' tp_proxy_pending_call_v0_take_pending_call (pc,')
+ self.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
+ self.b(' "%s",' % member)
+ self.b(' %s,' % collect_callback)
+ self.b(' pc,')
+ self.b(' tp_proxy_pending_call_v0_completed,')
+ self.b(' timeout_ms,')
+
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+
+ const = pointer and 'const ' or ''
+
+ self.b(' %s, %s,' % (gtype, name))
+
+ self.b(' G_TYPE_INVALID));')
+ self.b('')
+ self.b(' if (!state.completed)')
+ self.b(' g_main_loop_run (state.loop);')
+ self.b('')
+ self.b(' if (!state.completed)')
+ self.b(' tp_proxy_pending_call_cancel (pc);')
+ self.b('')
+ self.b(' if (loop != NULL)')
+ self.b(' *loop = NULL;')
+ self.b('')
+ self.b(' g_main_loop_unref (state.loop);')
+ self.b('')
+ self.b(' return state.success;')
+ self.b('}')
+ self.b('')
+
+ def do_signal_add(self, signal):
+ marshaller_items = []
+ gtypes = []
+
+ for i in signal.getElementsByTagName('arg'):
+ name = i.getAttribute('name')
+ type = i.getAttribute('type')
+ info = type_to_gtype(type)
+ # type, GType, STRING, is a pointer
+ gtypes.append(info[1])
+
+ self.b(' dbus_g_proxy_add_signal (proxy, "%s",'
+ % signal.getAttribute('name'))
+ for gtype in gtypes:
+ self.b(' %s,' % gtype)
+ self.b(' G_TYPE_INVALID);')
+
+ def do_interface(self, node):
+ ifaces = node.getElementsByTagName('interface')
+ assert len(ifaces) == 1
+ iface = ifaces[0]
+ name = node.getAttribute('name').replace('/', '')
+
+ self.iface = name
+ self.iface_lc = name.lower()
+ self.iface_uc = name.upper()
+ self.iface_mc = name.replace('_', '')
+ self.iface_dbus = iface.getAttribute('name')
+
+ signals = node.getElementsByTagName('signal')
+ methods = node.getElementsByTagName('method')
+
+ if signals:
+ self.b('static inline void')
+ self.b('%s_add_signals_for_%s (DBusGProxy *proxy)'
+ % (self.prefix_lc, name.lower()))
+ self.b('{')
+
+ if self.tp_proxy_api >= (0, 7, 6):
+ self.b(' if (!tp_proxy_dbus_g_proxy_claim_for_signal_adding '
+ '(proxy))')
+ self.b(' return;')
+
+ for signal in signals:
+ self.do_signal_add(signal)
+
+ self.b('}')
+ self.b('')
+ self.b('')
+
+ for signal in signals:
+ self.do_signal(name, signal)
+
+ for method in methods:
+ self.do_method(name, method)
+
+ self.iface_dbus = None
+
+ def __call__(self):
+
+ if self.guard is not None:
+ self.h('#ifndef %s' % self.guard)
+ self.h('#define %s' % self.guard)
+ self.h('')
+
+ self.h('G_BEGIN_DECLS')
+ self.h('')
+
+ self.b('/* We don\'t want gtkdoc scanning this file, it\'ll get')
+ self.b(' * confused by seeing function definitions, so mark it as: */')
+ self.b('/*<private_header>*/')
+ self.b('')
+
+ nodes = self.dom.getElementsByTagName('node')
+ nodes.sort(cmp_by_name)
+
+ for node in nodes:
+ self.do_interface(node)
+
+ if self.group is not None:
+
+ self.b('/*')
+ self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group))
+ self.b(' * @self: the #TpProxy')
+ self.b(' * @quark: a quark whose string value is the interface')
+ self.b(' * name whose signals should be added')
+ self.b(' * @proxy: the D-Bus proxy to which to add the signals')
+ self.b(' * @unused: not used for anything')
+ self.b(' *')
+ self.b(' * Tell dbus-glib that @proxy has the signatures of all')
+ self.b(' * signals on the given interface, if it\'s one we')
+ self.b(' * support.')
+ self.b(' *')
+ self.b(' * This function should be used as a signal handler for')
+ self.b(' * #TpProxy::interface-added.')
+ self.b(' */')
+ self.b('static void')
+ self.b('%s_%s_add_signals (TpProxy *self G_GNUC_UNUSED,'
+ % (self.prefix_lc, self.group))
+ self.b(' guint quark,')
+ self.b(' DBusGProxy *proxy,')
+ self.b(' gpointer unused G_GNUC_UNUSED)')
+
+ self.b('{')
+
+ for node in nodes:
+ iface = node.getElementsByTagName('interface')[0]
+ self.iface_dbus = iface.getAttribute('name')
+ signals = node.getElementsByTagName('signal')
+ if not signals:
+ continue
+ name = node.getAttribute('name').replace('/', '').lower()
+ self.iface_uc = name.upper()
+ self.b(' if (quark == %s)' % self.get_iface_quark())
+ self.b(' %s_add_signals_for_%s (proxy);'
+ % (self.prefix_lc, name))
+
+ self.b('}')
+ self.b('')
+
+ self.h('G_END_DECLS')
+ self.h('')
+
+ if self.guard is not None:
+ self.h('#endif /* defined (%s) */' % self.guard)
+ self.h('')
+
+ file_set_contents(self.basename + '.h', '\n'.join(self.__header))
+ file_set_contents(self.basename + '-body.h', '\n'.join(self.__body))
+ file_set_contents(self.basename + '-gtk-doc.h', '\n'.join(self.__docs))
+
+def types_to_gtypes(types):
+ return [type_to_gtype(t)[1] for t in types]
+
+
+if __name__ == '__main__':
+ options, argv = gnu_getopt(sys.argv[1:], '',
+ ['group=', 'subclass=', 'subclass-assert=',
+ 'iface-quark-prefix=', 'tp-proxy-api=',
+ 'generate-reentrant=', 'deprecate-reentrant=',
+ 'deprecation-attribute=', 'guard='])
+
+ opts = {}
+
+ for option, value in options:
+ opts[option] = value
+
+ dom = xml.dom.minidom.parse(argv[0])
+
+ Generator(dom, argv[1], argv[2], opts)()
diff --git a/tools/glib-client-marshaller-gen.py b/tools/glib-client-marshaller-gen.py
new file mode 100644
index 000000000..cb27d638a
--- /dev/null
+++ b/tools/glib-client-marshaller-gen.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+
+import sys
+import xml.dom.minidom
+from string import ascii_letters, digits
+
+
+from libglibcodegen import signal_to_marshal_name
+
+
+NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
+
+class Generator(object):
+
+ def __init__(self, dom, prefix):
+ self.dom = dom
+ self.marshallers = {}
+ self.prefix = prefix
+
+ def do_signal(self, signal):
+ marshaller = signal_to_marshal_name(signal, self.prefix)
+
+ assert '__' in marshaller
+ rhs = marshaller.split('__', 1)[1].split('_')
+
+ self.marshallers[marshaller] = rhs
+
+ def __call__(self):
+ signals = self.dom.getElementsByTagName('signal')
+
+ for signal in signals:
+ self.do_signal(signal)
+
+ print 'void'
+ print '%s_register_dbus_glib_marshallers (void)' % self.prefix
+ print '{'
+
+ all = self.marshallers.keys()
+ all.sort()
+ for marshaller in all:
+ rhs = self.marshallers[marshaller]
+
+ print ' dbus_g_object_register_marshaller ('
+ print ' g_cclosure_marshal_generic,'
+ print ' G_TYPE_NONE, /* return */'
+ for type in rhs:
+ print ' G_TYPE_%s,' % type.replace('VOID', 'NONE')
+ print ' G_TYPE_INVALID);'
+
+ print '}'
+
+
+def types_to_gtypes(types):
+ return [type_to_gtype(t)[1] for t in types]
+
+if __name__ == '__main__':
+ argv = sys.argv[1:]
+ dom = xml.dom.minidom.parse(argv[0])
+
+ Generator(dom, argv[1])()
diff --git a/tools/glib-errors-check-gen.py b/tools/glib-errors-check-gen.py
new file mode 100644
index 000000000..553fc9caf
--- /dev/null
+++ b/tools/glib-errors-check-gen.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+
+import sys
+import xml.dom.minidom
+
+from libglibcodegen import NS_TP, get_docstring, get_descendant_text
+
+class Generator(object):
+ def __init__(self, dom):
+ self.dom = dom
+ self.errors = self.dom.getElementsByTagNameNS(NS_TP, 'errors')[0]
+
+ def __call__(self):
+
+ print '{'
+ print ' GEnumClass *klass;'
+ print ' GEnumValue *value_by_name;'
+ print ' GEnumValue *value_by_nick;'
+ print ''
+ print ' g_type_init ();'
+ print ' klass = g_type_class_ref (TP_TYPE_ERROR);'
+
+ for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'):
+ ns = error.parentNode.getAttribute('namespace')
+ nick = error.getAttribute('name').replace(' ', '')
+ enum = ('TP_ERROR_' +
+ error.getAttribute('name').replace(' ', '_').replace('.', '_').upper())
+ s = ('TP_ERROR_STR_' +
+ error.getAttribute('name').replace(' ', '_').replace('.', '_').upper())
+
+ print ''
+ print ' /* %s.%s */' % (ns, nick)
+ print (' value_by_name = g_enum_get_value_by_name (klass, "%s");'
+ % enum)
+ print (' value_by_nick = g_enum_get_value_by_nick (klass, "%s");'
+ % nick)
+ print (' g_assert (value_by_name != NULL);')
+ print (' g_assert (value_by_nick != NULL);')
+ print (' g_assert_cmpint (value_by_name->value, ==, %s);'
+ % enum)
+ print (' g_assert_cmpint (value_by_nick->value, ==, %s);'
+ % enum)
+ print (' g_assert_cmpstr (value_by_name->value_name, ==, "%s");'
+ % enum)
+ print (' g_assert_cmpstr (value_by_nick->value_name, ==, "%s");'
+ % enum)
+ print (' g_assert_cmpstr (value_by_name->value_nick, ==, "%s");'
+ % nick)
+ print (' g_assert_cmpstr (value_by_nick->value_nick, ==, "%s");'
+ % nick)
+ print (' g_assert_cmpstr (%s, ==, TP_ERROR_PREFIX ".%s");'
+ % (s, nick))
+
+ print '}'
+
+if __name__ == '__main__':
+ argv = sys.argv[1:]
+ Generator(xml.dom.minidom.parse(argv[0]))()
diff --git a/tools/glib-errors-str-gen.py b/tools/glib-errors-str-gen.py
new file mode 100644
index 000000000..b2cf520bd
--- /dev/null
+++ b/tools/glib-errors-str-gen.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+
+import sys
+import xml.dom.minidom
+
+from libtpcodegen import file_set_contents
+from libglibcodegen import NS_TP, get_docstring, xml_escape
+
+class Generator(object):
+ def __init__(self, dom, basename):
+ self.dom = dom
+ self.errors = self.dom.getElementsByTagNameNS(NS_TP, 'errors')[0]
+ self.basename = basename
+
+ self.__header = []
+ self.__body = []
+ self.__docs = []
+
+ def h(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
+ self.__header.append(s)
+
+ def b(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
+ self.__body.append(s)
+
+ def d(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
+ self.__docs.append(s)
+
+ def __call__(self):
+ errors = self.errors.getElementsByTagNameNS(NS_TP, 'error')
+
+ self.b('#include <telepathy-glib/errors.h>')
+ self.b('')
+ self.b('const gchar *')
+ self.b('tp_error_get_dbus_name (TpError error)')
+ self.b('{')
+ self.b(' switch (error)')
+ self.b(' {')
+
+ for error in errors:
+ ns = error.parentNode.getAttribute('namespace')
+ nick = error.getAttribute('name').replace(' ', '')
+ uc_nick = error.getAttribute('name').replace(' ', '_').replace('.', '_').upper()
+ name = 'TP_ERROR_STR_' + uc_nick
+ error_name = '%s.%s' % (ns, nick)
+
+ self.d('/**')
+ self.d(' * %s:' % name)
+ self.d(' *')
+ self.d(' * The D-Bus error name %s' % error_name)
+ self.d(' *')
+ self.d(' * %s' % xml_escape(get_docstring(error)))
+ self.d(' */')
+ self.d('')
+
+ self.h('#define %s "%s"' % (name, error_name))
+
+ self.b(' case TP_ERROR_%s:' % uc_nick)
+ self.b(' return %s;' % name)
+
+ self.b(' default:')
+ self.b(' g_return_val_if_reached (NULL);')
+ self.b(' }')
+ self.b('}')
+
+ # make both files end with a newline
+ self.h('')
+ self.b('')
+
+ file_set_contents(self.basename + '.h', '\n'.join(self.__header))
+ file_set_contents(self.basename + '.c', '\n'.join(self.__body))
+ file_set_contents(self.basename + '-gtk-doc.h', '\n'.join(self.__docs))
+
+if __name__ == '__main__':
+ argv = sys.argv[1:]
+ basename = argv[0]
+
+ Generator(xml.dom.minidom.parse(argv[1]), basename)()
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
index e277b91f4..6fec0d3c4 100644
--- a/tools/glib-ginterface-gen.py
+++ b/tools/glib-ginterface-gen.py
@@ -26,9 +26,9 @@ import sys
import os.path
import xml.dom.minidom
+from libtpcodegen import file_set_contents
from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \
- NS_TP, dbus_gutils_wincaps_to_uscore, \
- signal_to_marshal_name, method_to_glue_marshal_name
+ NS_TP, dbus_gutils_wincaps_to_uscore
NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
@@ -421,8 +421,7 @@ class Generator(object):
'not match' % (method.getAttribute('name'), lc_name))
lc_name = lc_name.lower()
- marshaller = method_to_glue_marshal_name(method,
- self.signal_marshal_prefix)
+ marshaller = 'g_cclosure_marshal_generic'
wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name
self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset))
@@ -717,8 +716,7 @@ class Generator(object):
in_base_init.append(' G_SIGNAL_RUN_LAST|G_SIGNAL_DETAILED,')
in_base_init.append(' 0,')
in_base_init.append(' NULL, NULL,')
- in_base_init.append(' %s,'
- % signal_to_marshal_name(signal, self.signal_marshal_prefix))
+ in_base_init.append(' g_cclosure_marshal_generic,')
in_base_init.append(' G_TYPE_NONE,')
tmp = ['%d' % len(args)] + [gtype for (ctype, name, gtype) in args]
in_base_init.append(' %s);' % ',\n '.join(tmp))
@@ -740,8 +738,9 @@ class Generator(object):
self.h('#include <glib-object.h>')
self.h('#include <dbus/dbus-glib.h>')
- if self.have_properties(nodes):
- self.h('#include <telepathy-glib/dbus-properties-mixin.h>')
+ for header in self.headers:
+ self.h('#include %s' % header)
+ self.h('')
self.h('')
self.h('G_BEGIN_DECLS')
@@ -749,9 +748,6 @@ class Generator(object):
self.b('#include "%s.h"' % self.basename)
self.b('')
- for header in self.headers:
- self.b('#include %s' % header)
- self.b('')
for node in nodes:
self.do_node(node)
@@ -765,10 +761,9 @@ class Generator(object):
self.h('')
self.b('')
- open(self.basename + '.h', 'w').write('\n'.join(self.__header))
- open(self.basename + '.c', 'w').write('\n'.join(self.__body))
- open(self.basename + '-gtk-doc.h', 'w').write('\n'.join(self.__docs))
-
+ file_set_contents(self.basename + '.h', '\n'.join(self.__header))
+ file_set_contents(self.basename + '.c', '\n'.join(self.__body))
+ file_set_contents(self.basename + '-gtk-doc.h', '\n'.join(self.__docs))
def cmdline_error():
print """\
diff --git a/tools/glib-gtypes-generator.py b/tools/glib-gtypes-generator.py
index a49c36e7f..21dfc6aa7 100644
--- a/tools/glib-gtypes-generator.py
+++ b/tools/glib-gtypes-generator.py
@@ -23,6 +23,7 @@
import sys
import xml.dom.minidom
+from libtpcodegen import file_set_contents
from libglibcodegen import escape_as_identifier, \
get_docstring, \
NS_TP, \
@@ -42,15 +43,16 @@ class GTypesGenerator(object):
self.PREFIX_ = self.Prefix.upper() + '_'
self.prefix_ = self.Prefix.lower() + '_'
- self.header = open(output + '.h', 'w')
- self.body = open(output + '-body.h', 'w')
- self.docs = open(output + '-gtk-doc.h', 'w')
+ self.header = []
+ self.body = []
+ self.docs = []
+ self.output = output
for f in (self.header, self.body, self.docs):
- f.write('/* Auto-generated, do not edit.\n *\n'
- ' * This file may be distributed under the same terms\n'
- ' * as the specification from which it was generated.\n'
- ' */\n\n')
+ f.append('/* Auto-generated, do not edit.\n *\n'
+ ' * This file may be distributed under the same terms\n'
+ ' * as the specification from which it was generated.\n'
+ ' */\n\n')
# keys are e.g. 'sv', values are the key escaped
self.need_mappings = {}
@@ -66,13 +68,13 @@ class GTypesGenerator(object):
self.need_other_arrays = {}
def h(self, code):
- self.header.write(code.encode("utf-8"))
+ self.header.append(code.encode("utf-8"))
def c(self, code):
- self.body.write(code.encode("utf-8"))
+ self.body.append(code.encode("utf-8"))
def d(self, code):
- self.docs.write(code.encode('utf-8'))
+ self.docs.append(code.encode('utf-8'))
def do_mapping_header(self, mapping):
members = mapping.getElementsByTagNameNS(NS_TP, 'member')
@@ -89,7 +91,7 @@ class GTypesGenerator(object):
docstring = get_docstring(mapping) or '(Undocumented)'
- self.d('/**\n * %s:\n *\n' % name)
+ self.d('/**\n * %s:\n *\n' % name.strip())
self.d(' * %s\n' % xml_escape(docstring))
self.d(' *\n')
self.d(' * This macro expands to a call to a function\n')
@@ -290,6 +292,10 @@ class GTypesGenerator(object):
self.c(' return t;\n')
self.c('}\n\n')
+ file_set_contents(self.output + '.h', ''.join(self.header))
+ file_set_contents(self.output + '-body.h', ''.join(self.body))
+ file_set_contents(self.output + '-gtk-doc.h', ''.join(self.docs))
+
if __name__ == '__main__':
argv = sys.argv[1:]
diff --git a/tools/glib-interfaces-gen.py b/tools/glib-interfaces-gen.py
index 69c721be3..410762cde 100644
--- a/tools/glib-interfaces-gen.py
+++ b/tools/glib-interfaces-gen.py
@@ -3,6 +3,7 @@
from sys import argv, stdout, stderr
import xml.dom.minidom
+from libtpcodegen import file_set_contents
from libglibcodegen import NS_TP, get_docstring, \
get_descendant_text, get_by_path
@@ -13,25 +14,33 @@ class Generator(object):
assert declfile.endswith('.h')
docfile = declfile[:-2] + '-gtk-doc.h'
- self.impls = open(implfile, 'w')
- self.decls = open(declfile, 'w')
- self.docs = open(docfile, 'w')
+ self.implfile = implfile
+ self.declfile = declfile
+ self.docfile = docfile
+
+ self.impls = []
+ self.decls = []
+ self.docs = []
self.spec = get_by_path(dom, "spec")[0]
def h(self, code):
- self.decls.write(code.encode('utf-8'))
+ self.decls.append(code.encode('utf-8'))
def c(self, code):
- self.impls.write(code.encode('utf-8'))
+ self.impls.append(code.encode('utf-8'))
def d(self, code):
- self.docs.write(code.encode('utf-8'))
+ self.docs.append(code.encode('utf-8'))
def __call__(self):
for f in self.h, self.c:
self.do_header(f)
self.do_body()
+ file_set_contents(self.implfile, ''.join(self.impls))
+ file_set_contents(self.declfile, ''.join(self.decls))
+ file_set_contents(self.docfile, ''.join(self.docs))
+
# Header
def do_header(self, f):
f('/* Generated from: ')
@@ -49,6 +58,7 @@ class Generator(object):
f("""
*/
+#include <glib.h>
""")
# Body
diff --git a/tools/glib-signals-marshal-gen.py b/tools/glib-signals-marshal-gen.py
deleted file mode 100644
index 0d02c1341..000000000
--- a/tools/glib-signals-marshal-gen.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import xml.dom.minidom
-from string import ascii_letters, digits
-
-
-from libglibcodegen import signal_to_marshal_name, method_to_glue_marshal_name
-
-
-class Generator(object):
-
- def __init__(self, dom):
- self.dom = dom
- self.marshallers = {}
-
- def do_method(self, method):
- marshaller = method_to_glue_marshal_name(method, 'PREFIX')
-
- assert '__' in marshaller
- rhs = marshaller.split('__', 1)[1].split('_')
-
- self.marshallers[marshaller] = rhs
-
- def do_signal(self, signal):
- marshaller = signal_to_marshal_name(signal, 'PREFIX')
-
- assert '__' in marshaller
- rhs = marshaller.split('__', 1)[1].split('_')
-
- self.marshallers[marshaller] = rhs
-
- def __call__(self):
- methods = self.dom.getElementsByTagName('method')
-
- for method in methods:
- self.do_method(method)
-
- signals = self.dom.getElementsByTagName('signal')
-
- for signal in signals:
- self.do_signal(signal)
-
- all = self.marshallers.keys()
- all.sort()
- for marshaller in all:
- rhs = self.marshallers[marshaller]
- if not marshaller.startswith('g_cclosure'):
- print 'VOID:' + ','.join(rhs)
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
- dom = xml.dom.minidom.parse(argv[0])
-
- Generator(dom)()
diff --git a/tools/gobject-foo.py b/tools/gobject-foo.py
new file mode 100644
index 000000000..002a290ba
--- /dev/null
+++ b/tools/gobject-foo.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+
+# gobject-foo.py: generate standard GObject type macros etc.
+#
+# The master copy of this program is in the telepathy-glib repository -
+# please make any changes there.
+#
+# Copyright (C) 2007-2010 Collabora Ltd. <http://www.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
+
+def gobject_header(head, tail, as_interface=False):
+ out = []
+ o = out.append
+
+ name = head + '_' + tail
+ MixedCase = name.replace('_', '')
+ lower_case = name.lower()
+ UPPER_CASE = name.upper()
+
+ gtype = head.upper() + '_TYPE_' + tail.upper()
+
+ o("typedef struct _%s %s;" % (MixedCase, MixedCase))
+
+ if as_interface:
+ o("typedef struct _%sInterface %sInterface;" % (MixedCase, MixedCase))
+ else:
+ o("typedef struct _%sClass %sClass;" % (MixedCase, MixedCase))
+ o("typedef struct _%sPrivate %sPrivate;" % (MixedCase, MixedCase))
+
+ o("")
+ o("GType %s_get_type (void);" % lower_case)
+ o("")
+
+ o("#define %s \\" % gtype)
+ o(" (%s_get_type ())" % lower_case)
+
+ o("#define %s(obj) \\" % UPPER_CASE)
+ o(" (G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, \\" % gtype)
+ o(" %s))" % MixedCase)
+
+ if not as_interface:
+ o("#define %s_CLASS(klass) \\" % UPPER_CASE)
+ o(" (G_TYPE_CHECK_CLASS_CAST ((klass), %s, \\" % gtype)
+ o(" %sClass))" % MixedCase)
+
+ o("#define %s_IS_%s(obj) \\" % (head.upper(), tail.upper()))
+ o(" (G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))" % gtype)
+
+ if as_interface:
+ o("#define %s_GET_IFACE(obj) \\" % UPPER_CASE)
+ o(" (G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, \\" % gtype)
+ o(" %sInterface))" % MixedCase)
+ else:
+ o("#define %s_IS_%s_CLASS(klass) \\" % (head.upper(), tail.upper()))
+ o(" (G_TYPE_CHECK_CLASS_TYPE ((klass), %s))" % gtype)
+
+ o("#define %s_GET_CLASS(obj) \\" % UPPER_CASE)
+ o(" (G_TYPE_INSTANCE_GET_CLASS ((obj), %s, \\" % gtype)
+ o(" %sClass))" % MixedCase)
+
+ return out
+
+if __name__ == '__main__':
+ import sys
+ from getopt import gnu_getopt
+
+ options, argv = gnu_getopt(sys.argv[1:], '', ['interface'])
+
+ as_interface = False
+
+ for opt, val in options:
+ if opt == '--interface':
+ as_interface = True
+
+ head, tail = argv
+
+ print '\n'.join(gobject_header(head, tail, as_interface=as_interface))
diff --git a/tools/lcov.am b/tools/lcov.am
index 7384f1b99..80023cb78 100644
--- a/tools/lcov.am
+++ b/tools/lcov.am
@@ -8,6 +8,7 @@ lcov-report:
--remove @top_builddir@/lcov.info.tmp telepathy-glib-scan.c
rm @top_builddir@/lcov.info.tmp
$(mkdir_p) @top_builddir@/lcov.html
+ echo "Coming soon!" > @top_builddir@/lcov.html/index.html
git_commit=`GIT_DIR=@top_srcdir@/.git git log -1 --pretty=format:%h 2>/dev/null`;\
genhtml --title "@PACKAGE_STRING@ $$git_commit" \
--output-directory @top_builddir@/lcov.html lcov.info
diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py
index 837ff2f74..7e9eb9a50 100644
--- a/tools/libtpcodegen.py
+++ b/tools/libtpcodegen.py
@@ -20,7 +20,7 @@ please make any changes there.
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
+import os
from string import ascii_letters, digits
@@ -28,6 +28,18 @@ NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
_ASCII_ALNUM = ascii_letters + digits
+def file_set_contents(filename, contents):
+ try:
+ os.remove(filename)
+ except OSError:
+ pass
+ try:
+ os.remove(filename + '.tmp')
+ except OSError:
+ pass
+
+ open(filename + '.tmp', 'w').write(contents)
+ os.rename(filename + '.tmp', filename)
def cmp_by_name(node1, node2):
return cmp(node1.getAttributeNode("name").nodeValue,
diff --git a/tools/make-version-script.py b/tools/make-version-script.py
new file mode 100644
index 000000000..0d30aa323
--- /dev/null
+++ b/tools/make-version-script.py
@@ -0,0 +1,208 @@
+#!/usr/bin/python
+
+"""Construct a GNU ld or Debian dpkg version-script from a set of
+RFC822-style symbol lists.
+
+Usage:
+ make-version-script.py [--symbols SYMBOLS] [--unreleased-version VER]
+ [--dpkg "LIBRARY.so.0 LIBRARY0 #MINVER#"]
+ [--dpkg-build-depends-package LIBRARY-dev]
+ [FILES...]
+
+Each FILE starts with RFC822-style headers "Version:" (the name of the
+symbol version, e.g. FOO_1.2.3) and "Extends:" (either the previous
+version, or "-" if this is the first version). Next there is a blank
+line, then a list of C symbols one per line.
+
+Comments (lines starting with whitespace + "#") are allowed and ignored.
+
+If --symbols is given, SYMBOLS lists the symbols actually exported by
+the library (one per line). If --unreleased-version is given, any symbols
+in SYMBOLS but not in FILES are assigned to that version; otherwise, any
+such symbols cause an error.
+
+If --dpkg is given, produce a Debian dpkg-gensymbols file instead of a
+GNU ld version-script. The argument to --dpkg is the first line of the
+resulting symbols file, and --dpkg-build-depends-package can optionally
+be used to set the Build-Depends-Package field.
+
+This script originates in telepathy-glib <http://telepathy.freedesktop.org/> -
+please send us any changes that are needed.
+"""
+
+# Copyright (C) 2008-2010 Collabora Ltd. <http://www.collabora.co.uk/>
+# Copyright (C) 2008 Nokia Corporation
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+import sys
+from getopt import gnu_getopt
+
+
+def e(format, *args):
+ sys.stderr.write((format + '\n') % args)
+
+
+def main(abifiles, symbols=None, unreleased_version=None,
+ dpkg=False, dpkg_first_line=None, dpkg_build_depends_package=None):
+
+ gnuld = not dpkg
+ symbol_set = None
+
+ if symbols is not None:
+ symbol_set = open(symbols, 'r').readlines()
+ symbol_set = map(str.strip, symbol_set)
+ symbol_set = set(symbol_set)
+
+ versioned_symbols = set()
+
+ dpkg_symbols = []
+ dpkg_versions = []
+
+ if dpkg:
+ assert dpkg_first_line is not None
+ print dpkg_first_line
+ if dpkg_build_depends_package is not None:
+ print "* Build-Depends-Package: %s" % dpkg_build_depends_package
+
+ for filename in abifiles:
+ lines = open(filename, 'r').readlines()
+
+ version = None
+ extends = None
+ release = None
+
+ for i, line in enumerate(lines):
+ line = line.strip()
+
+ if line.startswith('#'):
+ continue
+ elif not line:
+ # the transition betwen headers and symbols
+ cut = i + 1
+ break
+ elif line.lower().startswith('version:'):
+ line = line[8:].strip()
+ version = line
+ continue
+ elif line.lower().startswith('extends:'):
+ line = line[8:].strip()
+ extends = line
+ continue
+ elif line.lower().startswith('release:'):
+ release = line[8:].strip()
+ continue
+ else:
+ e('Could not understand line in %s header: %s', filename, line)
+ raise SystemExit(1)
+
+ else:
+ e('No symbols in %s', filename)
+ raise SystemExit(1)
+
+ if version is None:
+ e('No Versions: header in %s', filename)
+ raise SystemExit(1)
+
+ if extends is None:
+ e('No Extends: header in %s', filename)
+ raise SystemExit(1)
+
+ if release is None and dpkg:
+ e('No Release: header in %s', filename)
+ raise SystemExit(1)
+
+ if dpkg:
+ dpkg_versions.append('%s@%s %s' % (version, version, release))
+
+ lines = lines[cut:]
+
+ if gnuld:
+ print "%s {" % version
+ print " global:"
+
+ for symbol in lines:
+ symbol = symbol.strip()
+
+ if symbol.startswith('#'):
+ continue
+
+ if gnuld:
+ print " %s;" % symbol
+ elif dpkg:
+ dpkg_symbols.append('%s@%s %s' % (symbol, version, release))
+
+ if symbol in versioned_symbols:
+ raise AssertionError('Symbol %s is in version %s and an '
+ 'earlier version' % (symbol, version))
+
+ versioned_symbols.add(symbol)
+
+ if gnuld:
+ if extends == '-':
+ print " local:"
+ print " *;"
+ print "};"
+ else:
+ print "} %s;" % extends
+ print
+
+ if dpkg:
+ dpkg_symbols.sort()
+ dpkg_versions.sort()
+
+ for x in dpkg_versions:
+ print " %s" % x
+
+ for x in dpkg_symbols:
+ print " %s" % x
+
+ if symbol_set is not None:
+ missing = versioned_symbols - symbol_set
+
+ if missing:
+ e('These symbols have disappeared:')
+
+ for symbol in missing:
+ e(' %s', symbol)
+
+ raise SystemExit(1)
+
+ unreleased = symbol_set - versioned_symbols
+
+ if unreleased:
+ if unreleased_version is None:
+ e('Unversioned symbols are not allowed in releases:')
+
+ for symbol in unreleased:
+ e(' %s', symbol)
+
+ raise SystemExit(1)
+
+ if gnuld:
+ print "%s {" % unreleased_version
+ print " global:"
+
+ for symbol in unreleased:
+ print " %s;" % symbol
+
+ print "} %s;" % version
+
+
+if __name__ == '__main__':
+ options, argv = gnu_getopt (sys.argv[1:], '',
+ ['symbols=', 'unreleased-version=',
+ 'dpkg=', 'dpkg-build-depends-package='])
+
+ opts = {'dpkg': False}
+
+ for option, value in options:
+ if option == '--dpkg':
+ opts['dpkg'] = True
+ opts['dpkg_first_line'] = value
+ else:
+ opts[option.lstrip('-').replace('-', '_')] = value
+
+ main(argv, **opts)
diff --git a/tools/manager-file.py b/tools/manager-file.py
new file mode 100644
index 000000000..e1b51a616
--- /dev/null
+++ b/tools/manager-file.py
@@ -0,0 +1,187 @@
+#!/usr/bin/python
+
+# manager-file.py: generate .manager files and TpCMParamSpec arrays from the
+# same data (should be suitable for all connection managers that don't have
+# plugins)
+#
+# The master copy of this program is in the telepathy-glib repository -
+# please make any changes there.
+#
+# Copyright (c) Collabora Ltd. <http://www.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
+
+import re
+import sys
+
+_NOT_C_STR = re.compile(r'[^A-Za-z0-9_-]')
+
+def c_string(x):
+ # whitelist-based brute force and ignorance - escape nearly all punctuation
+ return '"' + _NOT_C_STR.sub(lambda c: r'\x%02x' % ord(c), x) + '"'
+
+def desktop_string(x):
+ return x.replace(' ', r'\s').replace('\n', r'\n').replace('\r', r'\r').replace('\t', r'\t')
+
+supported = list('sbuiqn')
+
+fdefaultencoders = {
+ 's': desktop_string,
+ 'b': (lambda b: b and '1' or '0'),
+ 'u': (lambda n: '%u' % n),
+ 'i': (lambda n: '%d' % n),
+ 'q': (lambda n: '%u' % n),
+ 'n': (lambda n: '%d' % n),
+ }
+for x in supported: assert x in fdefaultencoders
+
+gtypes = {
+ 's': 'G_TYPE_STRING',
+ 'b': 'G_TYPE_BOOLEAN',
+ 'u': 'G_TYPE_UINT',
+ 'i': 'G_TYPE_INT',
+ 'q': 'G_TYPE_UINT',
+ 'n': 'G_TYPE_INT',
+}
+for x in supported: assert x in gtypes
+
+gdefaultencoders = {
+ 's': c_string,
+ 'b': (lambda b: b and 'GINT_TO_POINTER (TRUE)' or 'GINT_TO_POINTER (FALSE)'),
+ 'u': (lambda n: 'GUINT_TO_POINTER (%u)' % n),
+ 'i': (lambda n: 'GINT_TO_POINTER (%d)' % n),
+ 'q': (lambda n: 'GUINT_TO_POINTER (%u)' % n),
+ 'n': (lambda n: 'GINT_TO_POINTER (%d)' % n),
+ }
+for x in supported: assert x in gdefaultencoders
+
+gdefaultdefaults = {
+ 's': 'NULL',
+ 'b': 'GINT_TO_POINTER (FALSE)',
+ 'u': 'GUINT_TO_POINTER (0)',
+ 'i': 'GINT_TO_POINTER (0)',
+ 'q': 'GUINT_TO_POINTER (0)',
+ 'n': 'GINT_TO_POINTER (0)',
+ }
+for x in supported: assert x in gdefaultdefaults
+
+gflags = {
+ 'has-default': 'TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT',
+ 'register': 'TP_CONN_MGR_PARAM_FLAG_REGISTER',
+ 'required': 'TP_CONN_MGR_PARAM_FLAG_REQUIRED',
+ 'secret': 'TP_CONN_MGR_PARAM_FLAG_SECRET',
+ 'dbus-property': 'TP_CONN_MGR_PARAM_FLAG_DBUS_PROPERTY',
+}
+
+def write_manager(f, manager, protos):
+ # pointless backwards compat section
+ print >> f, '[ConnectionManager]'
+ print >> f, 'BusName=org.freedesktop.Telepathy.ConnectionManager.' + manager
+ print >> f, 'ObjectPath=/org/freedesktop/Telepathy/ConnectionManager/' + manager
+
+ # protocols
+ for proto, params in protos.iteritems():
+ print >> f
+ print >> f, '[Protocol %s]' % proto
+
+ defaults = {}
+
+ for param, info in params.iteritems():
+ dtype = info['dtype']
+ flags = info.get('flags', '').split()
+ struct_field = info.get('struct_field', param.replace('-', '_'))
+ filter = info.get('filter', 'NULL')
+ filter_data = info.get('filter_data', 'NULL')
+ setter_data = 'NULL'
+
+ if 'default' in info:
+ default = fdefaultencoders[dtype](info['default'])
+ defaults[param] = default
+
+ if flags:
+ flags = ' ' + ' '.join(flags)
+ else:
+ flags = ''
+
+ print >> f, 'param-%s=%s%s' % (param, desktop_string(dtype), flags)
+
+ for param, default in defaults.iteritems():
+ print >> f, 'default-%s=%s' % (param, default)
+
+def write_c_params(f, manager, proto, struct, params):
+ print >> f, "static const TpCMParamSpec %s_%s_params[] = {" % (manager, proto)
+
+ for param, info in params.iteritems():
+ dtype = info['dtype']
+ flags = info.get('flags', '').split()
+ struct_field = info.get('struct_field', param.replace('-', '_'))
+ filter = info.get('filter', 'NULL')
+ filter_data = info.get('filter_data', 'NULL')
+ setter_data = 'NULL'
+
+ if 'default' in info:
+ default = gdefaultencoders[dtype](info['default'])
+ else:
+ default = gdefaultdefaults[dtype]
+
+ if flags:
+ flags = ' | '.join([gflags[flag] for flag in flags])
+ else:
+ flags = '0'
+
+ if struct is None or struct_field is None:
+ struct_offset = '0'
+ else:
+ struct_offset = 'G_STRUCT_OFFSET (%s, %s)' % (struct, struct_field)
+
+ print >> f, (''' { %s, %s, %s,
+ %s,
+ %s, /* default */
+ %s, /* struct offset */
+ %s, /* filter */
+ %s, /* filter data */
+ %s /* setter data */ },''' %
+ (c_string(param), c_string(dtype), gtypes[dtype], flags,
+ default, struct_offset, filter, filter_data, setter_data))
+
+ print >> f, " { NULL }"
+ print >> f, "};"
+
+if __name__ == '__main__':
+ environment = {}
+ execfile(sys.argv[1], environment)
+
+ filename = '%s/%s.manager' % (sys.argv[2], environment['MANAGER'])
+ try:
+ os.remove(filename)
+ except OSError:
+ pass
+ f = open(filename + '.tmp', 'w')
+ write_manager(f, environment['MANAGER'], environment['PARAMS'])
+ f.close()
+ os.rename(filename + '.tmp', filename)
+
+ filename = '%s/param-spec-struct.h' % sys.argv[2]
+ try:
+ os.remove(filename)
+ except OSError:
+ pass
+ f = open(filename + '.tmp', 'w')
+ for protocol in environment['PARAMS']:
+ write_c_params(f, environment['MANAGER'], protocol,
+ environment['STRUCTS'][protocol],
+ environment['PARAMS'][protocol])
+ f.close()
+ os.rename(filename + '.tmp', filename)
diff --git a/tools/shave.mk b/tools/shave.mk
new file mode 100644
index 000000000..53cb3bf5e
--- /dev/null
+++ b/tools/shave.mk
@@ -0,0 +1 @@
+QUIET_GEN = $(Q:@=@echo ' GEN '$@;)
diff --git a/tools/telepathy-glib-env.in b/tools/telepathy-glib-env.in
new file mode 100644
index 000000000..ddc47bfd8
--- /dev/null
+++ b/tools/telepathy-glib-env.in
@@ -0,0 +1,9 @@
+#!/bin/sh
+abs_top_builddir="@abs_top_builddir@"
+export abs_top_builddir
+LD_LIBRARY_PATH="${abs_top_builddir}/telepathy-glib/.libs${LD_LIBRARY_PATH:+":${LD_LIBRARY_PATH}"}"
+export LD_LIBRARY_PATH
+G_DEBUG="fatal_criticals,fatal_warnings${G_DEBUG:+",${G_DEBUG}"}"
+export G_DEBUG
+
+exec "$@"
diff --git a/tools/telepathy-glib.supp b/tools/telepathy-glib.supp
new file mode 100644
index 000000000..28bd5a06a
--- /dev/null
+++ b/tools/telepathy-glib.supp
@@ -0,0 +1,390 @@
+# Valgrind error suppression file
+
+# ============================= libc ==================================
+
+{
+ ld.so initialization + selinux
+ Memcheck:Leak
+ ...
+ fun:_dl_init
+ obj:/lib/ld-*.so
+}
+
+{
+ dlopen initialization, triggered by handle-leak-debug code
+ Memcheck:Leak
+ ...
+ fun:__libc_dlopen_mode
+ fun:init
+ fun:backtrace
+ fun:handle_leak_debug_bt
+ fun:dynamic_ensure_handle
+ fun:tp_handle_ensure
+}
+
+# default.supp has these for 2.10, but they're too specific
+{
+ Debian libc6 (2.10.x, 2.11.x) stripped dynamic linker
+ Memcheck:Cond
+ fun:index
+ fun:expand_dynamic_string_token
+ fun:_dl_map_object
+ fun:map_doit
+ fun:_dl_catch_error
+ fun:do_preload
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:/lib/ld-*.so
+}
+{
+ Debian libc6 (2.9.x - 2.11.x) stripped dynamic linker
+ Memcheck:Cond
+ fun:_dl_relocate_object
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:/lib/ld-*.so
+}
+
+{
+ ld.so initialization on glibc 2.9
+ Memcheck:Cond
+ fun:strlen
+ fun:_dl_init_paths
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:/lib/ld-2.9.so
+}
+
+# ======================= libselinux on Debian amd64 =====================
+
+{
+ I have no idea what SELinux is doing but it's not my problem
+ Memcheck:Cond
+ ...
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+}
+
+{
+ I have no idea what SELinux is doing but it's not my problem
+ Memcheck:Value8
+ ...
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+}
+
+{
+ I have no idea what SELinux is doing but it's not my problem
+ Memcheck:Leak
+ ...
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+}
+
+# ============================= GLib ==================================
+
+{
+ g_set_prgname copies its argument
+ Memcheck:Leak
+ ...
+ fun:g_set_prgname
+}
+
+{
+ one g_get_charset per child^Wprocess
+ Memcheck:Leak
+ ...
+ fun:g_get_charset
+}
+
+{
+ one g_get_home_dir per process
+ Memcheck:Leak
+ ...
+ fun:g_get_home_dir
+}
+
+{
+ GQuarks can't be freed
+ Memcheck:Leak
+ ...
+ fun:g_quark_from_static_string
+}
+
+{
+ GQuarks can't be freed
+ Memcheck:Leak
+ ...
+ fun:g_quark_from_string
+}
+
+{
+ interned strings can't be freed
+ Memcheck:Leak
+ ...
+ fun:g_intern_string
+}
+
+{
+ interned strings can't be freed
+ Memcheck:Leak
+ ...
+ fun:g_intern_static_string
+}
+
+{
+ shared global default g_main_context
+ Memcheck:Leak
+ ...
+ fun:g_main_context_new
+ fun:g_main_context_default
+}
+
+{
+ GTest initialization
+ Memcheck:Leak
+ ...
+ fun:g_test_init
+ fun:main
+}
+
+{
+ GTest admin
+ Memcheck:Leak
+ ...
+ fun:g_test_add_vtable
+}
+
+{
+ GTest pseudorandomness
+ Memcheck:Leak
+ ...
+ fun:g_rand_new_with_seed_array
+ fun:test_run_seed
+ ...
+ fun:g_test_run
+}
+
+{
+ GSLice initialization
+ Memcheck:Leak
+ ...
+ fun:g_malloc0
+ fun:g_slice_init_nomessage
+ fun:g_slice_alloc
+}
+
+# ============================= GObject ===============================
+
+{
+ g_type_init
+ Memcheck:Leak
+ ...
+ fun:g_type_init
+}
+
+{
+ g_type_init_with_debug_flags
+ Memcheck:Leak
+ ...
+ fun:g_type_init_with_debug_flags
+}
+
+{
+ g_type_register_static
+ Memcheck:Leak
+ ...
+ fun:g_type_register_static
+}
+
+{
+ g_type_add_interface_static
+ Memcheck:Leak
+ ...
+ fun:g_type_add_interface_static
+}
+
+{
+ initialization of interfaces
+ Memcheck:Leak
+ ...
+ fun:type_iface_vtable_base_init_Wm
+ fun:g_type_class_ref
+}
+
+# ============================= GIO ===================================
+
+{
+ GIO init
+ Memcheck:Leak
+ ...
+ fun:g_inet_address_class_intern_init
+}
+
+{
+ g_simple_async_result class
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_simple_async_result_new
+}
+
+# ============================= dbus-glib =============================
+
+{
+ registering marshallers is permanent
+ Memcheck:Leak
+ ...
+ fun:dbus_g_object_register_marshaller_array
+ fun:dbus_g_object_register_marshaller
+}
+
+{
+ dbus-glib specialized GTypes are permanent
+ Memcheck:Leak
+ ...
+ fun:dbus_g_type_specialized_init
+}
+
+{
+ libdbus shared connection
+ Memcheck:Leak
+ ...
+ fun:dbus_g_bus_get
+}
+
+{
+ dbus-gobject registrations aren't freed unless we fall off the bus
+ Memcheck:Leak
+ ...
+ fun:g_slist_append
+ fun:dbus_g_connection_register_g_object
+}
+
+{
+ DBusGProxy slots aren't freed unless we fall off the bus
+ Memcheck:Leak
+ ...
+ fun:dbus_connection_allocate_data_slot
+ ...
+ fun:dbus_g_proxy_constructor
+}
+
+{
+ error registrations are for life, not just for Christmas
+ Memcheck:Leak
+ ...
+ fun:dbus_g_error_domain_register
+}
+
+{
+ DBusGProxy class init
+ Memcheck:Leak
+ ...
+ fun:dbus_g_proxy_class_init
+}
+
+# ============================= telepathy-glib ========================
+
+{
+ tp_dbus_daemon_constructor @daemons once per DBusConnection
+ Memcheck:Leak
+ ...
+ fun:g_slice_alloc
+ fun:tp_dbus_daemon_constructor
+}
+
+{
+ tp_proxy_subclass_add_error_mapping refs the enum
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ fun:tp_proxy_subclass_add_error_mapping
+}
+
+{
+ tp_proxy_or_subclass_hook_on_interface_add never frees its list
+ Memcheck:Leak
+ ...
+ fun:tp_proxy_or_subclass_hook_on_interface_add
+}
+
+{
+ tp_dbus_daemon_constructor filter not freed til we fall off the bus
+ Memcheck:Leak
+ ...
+ fun:dbus_connection_add_filter
+ fun:tp_dbus_daemon_constructor
+}
+
+{
+ tp_g_socket_address_from_variant reffing GNIO types
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:tp_g_socket_address_from_variant
+}
+
+{
+ creating classes for DBusGProxy
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_object_new
+ ...
+ fun:tp_proxy_borrow_interface_by_id
+}
+
+{
+ creating classes for tp_dbus_daemon_new
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_object_new
+ ...
+ fun:tp_dbus_daemon_new
+}
+
+{
+ creating classes for TpCHannel
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_object_new
+ ...
+ fun:tp_channel_new
+}
+
+{
+ creating a boxed type to use in TpCapabilities
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_param_spec_boxed
+ fun:tp_capabilities_class_intern_init
+}
+
+# ============================= questionable ==========================
+
+{
+ creating classes for instances (this is a pretty big hammer)
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_type_create_instance
+ ...
+ fun:g_param_spec_string
+}
diff --git a/tools/test-wrapper.sh b/tools/test-wrapper.sh
new file mode 100755
index 000000000..94900674a
--- /dev/null
+++ b/tools/test-wrapper.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# Make tests shut up. On success, if stdout is a tty, we only output messages
+# about skipped tests; on failure, or if stdout is a file or pipe, we output
+# the lot.
+#
+# Usage: test-wrapper.sh PROGRAM [ARGS...]
+
+set -e
+
+if test -t 1 && test "z$CHECK_VERBOSE" = z; then
+ : # continue with the output-suppressed code path, below
+else
+ "$@" || e=$?
+ exit $e
+fi
+
+e=0
+"$@" > capture-$$.log 2>&1 || e=$?
+if test z$e = z0; then
+ grep -i skipped capture-$$.log || true
+ rm -f capture-$$.log
+else
+ cat capture-$$.log
+ exit $e
+fi
+
+# Copyright © 2010 Collabora Ltd. <http://www.collabora.co.uk/>
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. There is no warranty.
diff --git a/tools/valgrind.mk b/tools/valgrind.mk
new file mode 100644
index 000000000..25a3488cd
--- /dev/null
+++ b/tools/valgrind.mk
@@ -0,0 +1,13 @@
+VALGRIND = valgrind --tool=memcheck \
+ --verbose \
+ --leak-check=full \
+ --leak-resolution=high \
+ --suppressions=$(top_srcdir)/tools/telepathy-glib.supp \
+ --child-silent-after-fork=yes \
+ --num-callers=20 \
+ --gen-suppressions=all
+
+# other potentially interesting options:
+# --show-reachable=yes reachable objects (many!)
+# --read-var-info=yes better diagnostics from DWARF3 info
+# --track-origins=yes better diagnostics for uninit values (slow)
diff --git a/tools/with-session-bus.sh b/tools/with-session-bus.sh
new file mode 100755
index 000000000..b3038cd9e
--- /dev/null
+++ b/tools/with-session-bus.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+# with-session-bus.sh - run a program with a temporary D-Bus session daemon
+#
+# The canonical location of this program is the telepathy-glib tools/
+# directory, please synchronize any changes with that copy.
+#
+# Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+set -e
+
+me=with-session-bus
+
+dbus_daemon_args="--print-address=5 --print-pid=6 --fork"
+sleep=0
+
+usage ()
+{
+ echo "usage: $me [options] -- program [program_options]" >&2
+ echo "Requires write access to the current directory." >&2
+ echo "" >&2
+ echo "If \$WITH_SESSION_BUS_FORK_DBUS_MONITOR is set, fork dbus-monitor" >&2
+ echo "with the arguments in \$WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT." >&2
+ echo "The output of dbus-monitor is saved in $me-<pid>.dbus-monitor-logs" >&2
+ exit 2
+}
+
+while test "z$1" != "z--"; do
+ case "$1" in
+ --sleep=*)
+ sleep="$1"
+ sleep="${sleep#--sleep=}"
+ shift
+ ;;
+ --session)
+ dbus_daemon_args="$dbus_daemon_args --session"
+ shift
+ ;;
+ --config-file=*)
+ # FIXME: assumes config file doesn't contain any special characters
+ dbus_daemon_args="$dbus_daemon_args $1"
+ shift
+ ;;
+ *)
+ usage
+ ;;
+ esac
+done
+shift
+if test "z$1" = "z"; then usage; fi
+
+exec 5> $me-$$.address
+exec 6> $me-$$.pid
+
+cleanup ()
+{
+ pid=`head -n1 $me-$$.pid`
+ if test -n "$pid" ; then
+ if [ -n "$VERBOSE_TESTS" ]; then
+ echo "Killing temporary bus daemon: $pid" >&2
+ fi
+ kill -INT "$pid"
+ fi
+ rm -f $me-$$.address
+ rm -f $me-$$.pid
+}
+
+trap cleanup INT HUP TERM
+dbus-daemon $dbus_daemon_args
+
+if [ -n "$VERBOSE_TESTS" ]; then
+ { echo -n "Temporary bus daemon is "; cat $me-$$.address; } >&2
+ { echo -n "Temporary bus daemon PID is "; head -n1 $me-$$.pid; } >&2
+fi
+
+e=0
+DBUS_SESSION_BUS_ADDRESS="`cat $me-$$.address`"
+export DBUS_SESSION_BUS_ADDRESS
+DBUS_SESSION_BUS_PID="`cat $me-$$.pid`"
+export DBUS_SESSION_BUS_PID
+
+if [ -n "$WITH_SESSION_BUS_FORK_DBUS_MONITOR" ] ; then
+ echo -n "Forking dbus-monitor $WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT" >&2
+ dbus-monitor $WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT \
+ > $me-$$.dbus-monitor-logs 2>&1 &
+fi
+
+"$@" || e=$?
+
+if test $sleep != 0; then
+ sleep $sleep
+fi
+
+trap - INT HUP TERM
+cleanup
+
+exit $e