├── .gitignore ├── AUTHORS ├── CODE-OF-CONDUCT.md ├── COPYING ├── ChangeLog ├── Makefile.am ├── NEWS ├── README ├── autogen.sh ├── configure.ac ├── dbus-sharp-2.0.pc.in ├── dbus-sharp.sln ├── dbus-sharp.snk ├── examples ├── Makefile.am ├── Notifications.cs ├── Test.cs ├── TestExceptions.cs ├── TestExport.cs ├── TestExportInterface.cs ├── TestNotifications.cs ├── TestObjects.cs ├── TestRental.cs ├── TestSample.cs ├── TestServer.cs ├── TestServerNative.cs ├── TestServerTcp.cs ├── UnixFDClient.cs ├── UnixFDInterface.cs └── UnixFDService.cs ├── src ├── Address.cs ├── AddressEntry.cs ├── ArgDirection.cs ├── AssemblyInfo.cs ├── AssemblyInfo.cs.in ├── Authentication.cs ├── Bus.cs ├── BusException.cs ├── BusObject.cs ├── Connection.cs ├── DBus.cs ├── DProxy.cs ├── Daemon.cs ├── DisposableList.cs ├── ExportObject.cs ├── Introspection.cs ├── Makefile.am ├── Mapper.cs ├── OSHelpers.cs ├── ObjectPath.cs ├── Protocol │ ├── DBusStruct.cs │ ├── DType.cs │ ├── DValue.cs │ ├── EndianFlag.cs │ ├── FieldCode.cs │ ├── Header.cs │ ├── HeaderFlag.cs │ ├── MatchRule.cs │ ├── Message.cs │ ├── MessageContainer.cs │ ├── MessageDumper.cs │ ├── MessageFilter.cs │ ├── MessageReader.cs │ ├── MessageType.cs │ ├── MessageWriter.cs │ ├── PendingCall.cs │ ├── ProtocolInformation.cs │ ├── Signature.cs │ ├── SocketTransport.cs │ ├── Transport.cs │ └── UnixFDArray.cs ├── Server.cs ├── ServerBus.cs ├── Transports │ ├── UnixNativeTransport.cs │ ├── UnixSendmsgTransport.cs │ └── UnixTransport.cs ├── TypeImplementer.cs ├── Unix │ ├── UnixError.cs │ ├── UnixMonoStream.cs │ ├── UnixSocket.cs │ └── UnixStream.cs ├── UnixFD.cs ├── daemon.mk ├── dbus-daemon.csproj ├── dbus-sharp.csproj ├── dbus-sharp.dll.config └── gencssources ├── tests ├── AddressTest.cs ├── AuthenticationTest.cs ├── BusTests.cs ├── ExportInterfaceTest.cs ├── IntrospectorTest.cs ├── Makefile.am ├── MatchRuleTest.cs ├── MessageReaderTest.cs ├── MessageWriterTest.cs ├── ObjectPathTest.cs ├── RenamedInterfaceTest.cs ├── SignatureTest.cs └── dbus-sharp-tests.csproj └── tools ├── Introspect.cs ├── Makefile.am ├── Monitor.cs ├── UuidGen.cs ├── dbus-monitor.csproj └── tools.mk /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.dll 3 | *.mdb 4 | *.suo 5 | *.pdb 6 | *.pidb 7 | *.user 8 | *.userprefs 9 | bin/ 10 | obj/ 11 | dbus-sharp-2.0.pc 12 | Makefile 13 | Makefile.in 14 | aclocal.m4 15 | autom4te.cache/ 16 | configure 17 | config.log 18 | config.status 19 | INSTALL 20 | install-sh 21 | missing 22 | tests/%temp%/ 23 | tests/TestResult.xml 24 | tests/dbus-sharp.dll.config 25 | xdb.il 26 | xdb.s 27 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Alp Toker 2 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the code of conduct defined by the Contributor Covenant 4 | to clarify expected behavior in our community. 5 | 6 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). 7 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright 2006 Alp Toker 2 | Copyright 2010 Other Contributors 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/dbus-sharp/dcef8fb3629974566a3962aa25f3f8185ea98174/ChangeLog -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src tools examples tests 2 | 3 | test: 4 | if ENABLE_TESTS 5 | $(MAKE) -C tests setup run 6 | else 7 | @echo "Test are disabled, run ./configure with --enable-tests" 8 | endif 9 | 10 | pkgconfigdir = $(libdir)/pkgconfig 11 | pkgconfig_DATA = dbus-sharp-2.0.pc 12 | 13 | EXTRA_DIST = \ 14 | dbus-sharp-2.0.pc.in \ 15 | dbus-sharp.snk \ 16 | dbus-sharp.sln 17 | 18 | DISTCLEANFILES = \ 19 | dbus-sharp-2.0.pc 20 | 21 | MAINTAINERCLEANFILES = \ 22 | INSTALL \ 23 | Makefile.in \ 24 | aclocal.m4 \ 25 | config.guess \ 26 | config.sub \ 27 | configure \ 28 | install-sh \ 29 | missing 30 | 31 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/dbus-sharp/dcef8fb3629974566a3962aa25f3f8185ea98174/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | D-Bus for .NET 2 | ============== 3 | 4 | This is a fork of ndesk-dbus, which is a C# implementation of D-Bus. It's 5 | often referred to as "managed D-Bus" to avoid confusion with existing 6 | bindings (which wrap libdbus). 7 | 8 | See http://mono.github.com/dbus-sharp/ for our fork 9 | - Tarball download: http://github.com/mono/dbus-sharp/downloads 10 | - GitHub repository: http://www.github.com/mono/dbus-sharp 11 | - Reporting bugs: http://github.com/mono/dbus-sharp/issues 12 | 13 | See http://www.ndesk.org/DBusSharp for Alp Toker's original project 14 | 15 | D-Bus is an inter-process communication framework that lets applications 16 | interface with the system event bus as well as allowing them to talk to 17 | one another in a peer-to-peer configuration. 18 | 19 | See http://www.freedesktop.org/wiki/Software/dbus for general 20 | information on the D-Bus IPC mechanism. 21 | 22 | This software is under active development but is already used by a wide 23 | range of applications for tasks as simple as maintaining a single 24 | instance of the GUI to whole instant messaging frameworks and hardware 25 | detection APIs. 26 | 27 | It provides a tested, high-performance bridge to and from all systems 28 | that are exposed via D-Bus, regardless of programming language, UI 29 | toolkit or license. The source code is MIT X11 licensed (Free 30 | Software/Open Source), allowing integration into other projects with 31 | very few restrictions. 32 | 33 | The code was written by Alp Toker and others, and is 34 | maintained by the dbus-sharp team. 35 | 36 | It is a clean-room implementation based on the D-Bus Specification 37 | Version 0.11 and study of the wire protocol of existing tools. 38 | 39 | It aims for compatibility with Mono and Microsoft .NET frameworks 40 | supporting the 2.0 profile. Backward compatibility with 1.0 will not be 41 | a consideration. 42 | 43 | -- 44 | Alp Toker and others 45 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Very simple autogen.sh script. 4 | # Added by popular demand. 5 | 6 | srcdir=${srcdir:-.} 7 | 8 | autoreconf -i 9 | 10 | conf_flags="--enable-maintainer-mode" 11 | $srcdir/configure $conf_flags "$@" 12 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | m4_define([api_version], [2.0]) 2 | m4_define([lib_version], [0.9]) 3 | 4 | AC_PREREQ(2.13) 5 | 6 | AC_INIT([dbus-sharp], lib_version) 7 | AC_CONFIG_SRCDIR([src/DBus.cs]) 8 | AM_INIT_AUTOMAKE 9 | 10 | AM_MAINTAINER_MODE 11 | 12 | AC_SUBST([API_VERSION], [api_version]) 13 | AC_SUBST([VERSION], [lib_version]) 14 | 15 | AC_PROG_INSTALL 16 | 17 | AC_PATH_PROG(PKG_CONFIG, pkg-config, no) 18 | if test "x$PKG_CONFIG" = "xno"; then 19 | AC_MSG_ERROR([You need to install pkg-config]) 20 | fi 21 | AC_SUBST(PKG_CONFIG) 22 | 23 | MONO_REQ_VERSION=1.1.13 24 | PKG_CHECK_MODULES(MONO, mono >= $MONO_REQ_VERSION) 25 | 26 | AC_PATH_PROG(MCS, mcs, no) 27 | if test "x$MCS" = "xno"; then 28 | AC_MSG_ERROR([You need to install mcs]) 29 | fi 30 | AC_SUBST(MCS) 31 | 32 | AC_PATH_PROG(GACUTIL, gacutil, no) 33 | if test "x$GACUTIL" = "xno"; then 34 | AC_MSG_ERROR([You need to install gacutil]) 35 | fi 36 | AC_SUBST(GACUTIL) 37 | 38 | AC_PATH_PROG(XBUILD, xbuild, no) 39 | if test "x$GACUTIL" = "xno"; then 40 | AC_MSG_ERROR([You need to install xbuild]) 41 | fi 42 | AC_SUBST(XBUILD) 43 | 44 | required_assemblies="Mono.Posix" 45 | 46 | for asm in $required_assemblies; do 47 | AC_MSG_CHECKING([for $asm.dll]) 48 | if test -n "`$GACUTIL /l $asm.dll | grep ^$asm.dll`"; then 49 | AC_MSG_RESULT([not found]) 50 | AC_MSG_ERROR([missing required assembly in the GAC: $asm.dll]) 51 | else 52 | AC_MSG_RESULT([found]) 53 | fi 54 | done 55 | 56 | NUNIT_REQUIRED=2.4.7 57 | 58 | AC_ARG_ENABLE(tests, AC_HELP_STRING([--enable-tests], [Enable NUnit tests]), 59 | enable_tests=$enableval, enable_tests="no") 60 | 61 | if test "x$enable_tests" = "xno"; then 62 | do_tests=no 63 | AM_CONDITIONAL(ENABLE_TESTS, false) 64 | else 65 | PKG_CHECK_MODULES(NUNIT, nunit >= $NUNIT_REQUIRED, 66 | do_tests="yes", do_tests="no") 67 | 68 | AC_SUBST(NUNIT_LIBS) 69 | AM_CONDITIONAL(ENABLE_TESTS, test "x$do_tests" = "xyes") 70 | 71 | if test "x$do_tests" = "xno"; then 72 | PKG_CHECK_MODULES(NUNIT, mono-nunit >= 2.4, 73 | do_tests="yes", do_tests="no") 74 | 75 | AC_SUBST(NUNIT_LIBS) 76 | AM_CONDITIONAL(ENABLE_TESTS, test "x$do_tests" = "xyes") 77 | 78 | if test "x$do_tests" = "xno"; then 79 | AC_MSG_WARN([Could not find nunit: tests will not be available]) 80 | fi 81 | fi 82 | fi 83 | 84 | AC_OUTPUT([ 85 | Makefile 86 | dbus-sharp-2.0.pc 87 | src/AssemblyInfo.cs 88 | src/Makefile 89 | tools/Makefile 90 | examples/Makefile 91 | tests/Makefile 92 | ]) 93 | 94 | -------------------------------------------------------------------------------- /dbus-sharp-2.0.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | datadir=${prefix}/share 3 | exec_prefix=${prefix} 4 | libdir=@libdir@ 5 | session_bus_services_dir=${datadir}/dbus-1/services 6 | 7 | Name: Managed DBus 8 | Description: Managed D-Bus IPC protocol library and CLR binding 9 | Version: @VERSION@ 10 | URL: http://mono.github.com/dbus-sharp/ 11 | Libs: -r:${libdir}/mono/@PACKAGE@-@API_VERSION@/dbus-sharp.dll 12 | -------------------------------------------------------------------------------- /dbus-sharp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dbus-sharp", "src\dbus-sharp.csproj", "{09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dbus-monitor", "tools\dbus-monitor.csproj", "{736160C3-844E-43D9-8106-E492D74D92CD}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dbus-daemon", "src\dbus-daemon.csproj", "{41918B94-6DAD-4C05-9FDF-17D51EC85AF0}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dbus-sharp-tests", "tests\dbus-sharp-tests.csproj", "{40AB91F9-BA2F-4C02-99F5-1F299CDBE86D}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {40AB91F9-BA2F-4C02-99F5-1F299CDBE86D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {40AB91F9-BA2F-4C02-99F5-1F299CDBE86D}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {40AB91F9-BA2F-4C02-99F5-1F299CDBE86D}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {40AB91F9-BA2F-4C02-99F5-1F299CDBE86D}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {41918B94-6DAD-4C05-9FDF-17D51EC85AF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {41918B94-6DAD-4C05-9FDF-17D51EC85AF0}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {736160C3-844E-43D9-8106-E492D74D92CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {736160C3-844E-43D9-8106-E492D74D92CD}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(MonoDevelopProperties) = preSolution 32 | StartupItem = src\dbus-sharp.csproj 33 | EndGlobalSection 34 | GlobalSection(SolutionProperties) = preSolution 35 | HideSolutionNode = FALSE 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /dbus-sharp.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/dbus-sharp/dcef8fb3629974566a3962aa25f3f8185ea98174/dbus-sharp.snk -------------------------------------------------------------------------------- /examples/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = \ 2 | Test.cs \ 3 | TestExportInterface.cs \ 4 | Notifications.cs \ 5 | TestNotifications.cs \ 6 | TestSample.cs 7 | -------------------------------------------------------------------------------- /examples/Notifications.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | using DBus; 9 | using org.freedesktop.DBus; 10 | 11 | // Hand-written interfaces for bootstrapping 12 | 13 | namespace org.freedesktop 14 | { 15 | public struct ServerInformation 16 | { 17 | public string Name; 18 | public string Vendor; 19 | public string Version; 20 | public string SpecVersion; 21 | } 22 | 23 | [Interface ("org.freedesktop.Notifications")] 24 | public interface Notifications : Introspectable, Properties 25 | { 26 | ServerInformation GetServerInformation (); 27 | string[] GetCapabilities (); 28 | void CloseNotification (uint id); 29 | uint Notify (string app_name, uint id, string icon, string summary, string body, string[] actions, IDictionary hints, int timeout); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/Test.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using DBus; 7 | using org.freedesktop.DBus; 8 | 9 | public class ManagedDBusTest 10 | { 11 | public static void Main (string[] args) 12 | { 13 | Connection conn; 14 | 15 | if (args.Length == 0) 16 | conn = Bus.Session; 17 | else { 18 | if (args[0] == "--session") 19 | conn = Bus.Session; 20 | else if (args[0] == "--system") 21 | conn = Bus.System; 22 | else 23 | conn = Connection.Open (args[0]); 24 | } 25 | 26 | ObjectPath opath = new ObjectPath ("/org/freedesktop/DBus"); 27 | string name = "org.freedesktop.DBus"; 28 | 29 | IBus bus = conn.GetObject (name, opath); 30 | 31 | bus.NameAcquired += delegate (string acquired_name) { 32 | Console.WriteLine ("NameAcquired: " + acquired_name); 33 | }; 34 | 35 | Console.WriteLine (); 36 | string xmlData = bus.Introspect (); 37 | Console.WriteLine ("xmlData: " + xmlData); 38 | 39 | Console.WriteLine (); 40 | foreach (string n in bus.ListNames ()) 41 | Console.WriteLine (n); 42 | 43 | Console.WriteLine (); 44 | foreach (string n in bus.ListNames ()) 45 | Console.WriteLine ("Name " + n + " has owner: " + bus.NameHasOwner (n)); 46 | 47 | Console.WriteLine (); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/TestExceptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using DBus; 8 | using org.freedesktop.DBus; 9 | 10 | public class ManagedDBusTestExceptions 11 | { 12 | public static void Main () 13 | { 14 | Bus bus = Bus.Session; 15 | 16 | string bus_name = "org.ndesk.testexceptions"; 17 | ObjectPath path = new ObjectPath ("/org/ndesk/testexceptions"); 18 | 19 | DemoObject demo; 20 | 21 | if (bus.RequestName (bus_name) == RequestNameReply.PrimaryOwner) { 22 | //create a new instance of the object to be exported 23 | demo = new DemoObject (); 24 | bus.Register (path, demo); 25 | 26 | //run the main loop 27 | while (true) 28 | bus.Iterate (); 29 | } else { 30 | //import a remote to a local proxy 31 | demo = bus.GetObject (bus_name, path); 32 | } 33 | 34 | Console.WriteLine (); 35 | //org.freedesktop.DBus.Error.InvalidArgs: Requested bus name "" is not valid 36 | try { 37 | bus.RequestName (""); 38 | } catch (Exception e) { 39 | Console.WriteLine (e); 40 | } 41 | 42 | //TODO: make this work as expected (what is expected?) 43 | Console.WriteLine (); 44 | try { 45 | demo.ThrowSomeException (); 46 | } catch (Exception e) { 47 | Console.WriteLine (e); 48 | } 49 | 50 | Console.WriteLine (); 51 | try { 52 | demo.ThrowSomeExceptionNoRet (); 53 | } catch (Exception e) { 54 | Console.WriteLine (e); 55 | } 56 | //handle the thrown exception 57 | //conn.Iterate (); 58 | 59 | Console.WriteLine (); 60 | try { 61 | demo.HandleVariant (null); 62 | } catch (Exception e) { 63 | Console.WriteLine (e); 64 | } 65 | 66 | Console.WriteLine (); 67 | try { 68 | demo.HandleString (null); 69 | } catch (Exception e) { 70 | Console.WriteLine (e); 71 | } 72 | 73 | Console.WriteLine (); 74 | try { 75 | demo.HandleArray (null); 76 | } catch (Exception e) { 77 | Console.WriteLine (e); 78 | } 79 | } 80 | } 81 | 82 | [Interface ("org.ndesk.testexceptions")] 83 | public class DemoObject : MarshalByRefObject 84 | { 85 | public int ThrowSomeException () 86 | { 87 | Console.WriteLine ("Asked to throw some Exception"); 88 | 89 | throw new Exception ("Some Exception"); 90 | } 91 | 92 | public void ThrowSomeExceptionNoRet () 93 | { 94 | Console.WriteLine ("Asked to throw some Exception NoRet"); 95 | 96 | throw new Exception ("Some Exception NoRet"); 97 | } 98 | 99 | public void HandleVariant (object o) 100 | { 101 | Console.WriteLine (o); 102 | } 103 | 104 | public void HandleString (string str) 105 | { 106 | Console.WriteLine (str); 107 | } 108 | 109 | public void HandleArray (byte[] arr) 110 | { 111 | Console.WriteLine (arr); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /examples/TestExportInterface.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2007 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using DBus; 8 | using org.freedesktop.DBus; 9 | 10 | public class ManagedDBusTestExport 11 | { 12 | public static void Main () 13 | { 14 | Bus bus = Bus.Session; 15 | 16 | string bus_name = "org.ndesk.test"; 17 | ObjectPath path = new ObjectPath ("/org/ndesk/test"); 18 | 19 | IDemoOne demo; 20 | 21 | if (bus.RequestName (bus_name) == RequestNameReply.PrimaryOwner) { 22 | //create a new instance of the object to be exported 23 | demo = new Demo (); 24 | bus.Register (path, demo); 25 | 26 | //run the main loop 27 | while (true) 28 | bus.Iterate (); 29 | } else { 30 | //import a remote to a local proxy 31 | demo = bus.GetObject (bus_name, path); 32 | //demo = bus.GetObject (bus_name, path); 33 | } 34 | 35 | Console.WriteLine (); 36 | demo.SomeEvent += HandleSomeEventA; 37 | demo.FireOffSomeEvent (); 38 | 39 | Console.WriteLine (); 40 | demo.SomeEvent -= HandleSomeEventA; 41 | demo.FireOffSomeEvent (); 42 | 43 | Console.WriteLine (); 44 | demo.SomeEvent += delegate (string arg1, object arg2, double arg3, MyTuple mt) {Console.WriteLine ("SomeEvent handler: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B);}; 45 | demo.SomeEvent += delegate (string arg1, object arg2, double arg3, MyTuple mt) {Console.WriteLine ("SomeEvent handler two: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B);}; 46 | demo.FireOffSomeEvent (); 47 | 48 | Console.WriteLine (); 49 | 50 | Console.WriteLine (demo.GetSomeVariant ()); 51 | 52 | Console.WriteLine (); 53 | 54 | demo.Say2 ("demo.Say2"); 55 | ((IDemoTwo)demo).Say2 ("((IDemoTwo)demo).Say2"); 56 | 57 | demo.SayEnum (DemoEnum.Bar, DemoEnum.Foo); 58 | 59 | uint n; 60 | string ostr; 61 | demo.WithOutParameters (out n, "21", out ostr); 62 | Console.WriteLine ("n: " + n); 63 | Console.WriteLine ("ostr: " + ostr); 64 | 65 | uint[] a1, a2, a3; 66 | demo.WithOutParameters2 (out a1, out a2, out a3); 67 | Console.WriteLine ("oparam2: " + a2[1]); 68 | 69 | uint[] @contacts = new uint[] { 2 }; 70 | IDictionary presence; 71 | demo.GetPresences (contacts, out presence); 72 | Console.WriteLine ("pres: " + presence[2].Status); 73 | 74 | MyTuple2 cpx = new MyTuple2 (); 75 | cpx.A = "a"; 76 | cpx.B = "b"; 77 | cpx.C = new Dictionary (); 78 | cpx.C[3] = new MyTuple("foo", "bar"); 79 | object cpxRet = demo.ComplexAsVariant (cpx, 12); 80 | MyTuple2 mt2ret = (MyTuple2)Convert.ChangeType (cpxRet, typeof (MyTuple2)); 81 | Console.WriteLine ("mt2ret.C[3].B " + mt2ret.C[3].B); 82 | 83 | /* 84 | IDemoOne[] objs = demo.GetObjArr (); 85 | foreach (IDemoOne obj in objs) 86 | obj.Say ("Some obj"); 87 | */ 88 | 89 | Console.WriteLine("SomeProp: " + demo.SomeProp); 90 | demo.SomeProp = 321; 91 | 92 | DemoProx demoProx = demo as DemoProx; 93 | if (demoProx != null) 94 | demoProx.SayRepeatedly(5, "Repetition"); 95 | 96 | demo.ThrowSomeException (); 97 | } 98 | 99 | public static void HandleSomeEventA (string arg1, object arg2, double arg3, MyTuple mt) 100 | { 101 | Console.WriteLine ("SomeEvent handler A: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B); 102 | } 103 | 104 | public static void HandleSomeEventB (string arg1, object arg2, double arg3, MyTuple mt) 105 | { 106 | Console.WriteLine ("SomeEvent handler B: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B); 107 | } 108 | } 109 | 110 | [Interface ("org.ndesk.test")] 111 | public interface IDemoOne 112 | { 113 | event SomeEventHandler SomeEvent; 114 | void FireOffSomeEvent (); 115 | void Say (object var); 116 | void SayEnum (DemoEnum a, DemoEnum b); 117 | void Say2 (string str); 118 | object GetSomeVariant (); 119 | void ThrowSomeException (); 120 | void WithOutParameters (out uint n, string str, out string ostr); 121 | void WithOutParameters2 (out uint[] a1, out uint[] a2, out uint[] a3); 122 | void GetPresences (uint[] @contacts, out IDictionary @presence); 123 | object ComplexAsVariant (object v, int num); 124 | 125 | IDemoOne[] GetEmptyObjArr (); 126 | IDemoOne[] GetObjArr (); 127 | int SomeProp { get; set; } 128 | } 129 | 130 | [Interface ("org.ndesk.test2")] 131 | public interface IDemoTwo 132 | { 133 | int Say (string str); 134 | void Say2 (string str); 135 | } 136 | 137 | public interface IDemo : IDemoOne, IDemoTwo 138 | { 139 | } 140 | 141 | public abstract class DemoProx : DemoBase 142 | { 143 | public virtual void SayRepeatedly (int count, string str) 144 | { 145 | for (int i = 0 ; i != count ; i++) 146 | Say2(str); 147 | } 148 | } 149 | 150 | public class Demo : DemoBase 151 | { 152 | public override void Say2 (string str) 153 | { 154 | Console.WriteLine ("Subclassed IDemoOne.Say2: " + str); 155 | } 156 | } 157 | 158 | public class DemoBase : IDemo 159 | { 160 | public event SomeEventHandler SomeEvent; 161 | 162 | public void Say (object var) 163 | { 164 | Console.WriteLine ("variant: " + var); 165 | } 166 | 167 | public int Say (string str) 168 | { 169 | Console.WriteLine ("string: " + str); 170 | return str.Length; 171 | } 172 | 173 | public void SayEnum (DemoEnum a, DemoEnum b) 174 | { 175 | Console.WriteLine ("SayEnum: " + a + ", " + b); 176 | } 177 | 178 | public virtual void Say2 (string str) 179 | { 180 | Console.WriteLine ("IDemoOne.Say2: " + str); 181 | } 182 | 183 | void IDemoTwo.Say2 (string str) 184 | { 185 | Console.WriteLine ("IDemoTwo.Say2: " + str); 186 | } 187 | 188 | public void FireOffSomeEvent () 189 | { 190 | Console.WriteLine ("Asked to fire off SomeEvent"); 191 | 192 | MyTuple mt; 193 | mt.A = "a"; 194 | mt.B = "b"; 195 | 196 | if (SomeEvent != null) { 197 | SomeEvent ("some string", 21, 19.84, mt); 198 | Console.WriteLine ("Fired off SomeEvent"); 199 | } 200 | } 201 | 202 | public object GetSomeVariant () 203 | { 204 | Console.WriteLine ("GetSomeVariant()"); 205 | 206 | return new byte[0]; 207 | } 208 | 209 | public void ThrowSomeException () 210 | { 211 | throw new Exception ("Some exception"); 212 | } 213 | 214 | public void WithOutParameters (out uint n, string str, out string ostr) 215 | { 216 | n = UInt32.Parse (str); 217 | ostr = "." + str + "."; 218 | } 219 | 220 | public void WithOutParameters2 (out uint[] a1, out uint[] a2, out uint[] a3) 221 | { 222 | a1 = new uint[] { }; 223 | a2 = new uint[] { 21, 23, 16 }; 224 | a3 = new uint[] { 21, 23 }; 225 | } 226 | 227 | public void GetPresences (uint[] @contacts, out IDictionary @presence) 228 | { 229 | Dictionary presences = new Dictionary(); 230 | presences[2] = new SimplePresence { Type = ConnectionPresenceType.Offline, Status = "offline", StatusMessage = "" }; 231 | presence = presences; 232 | } 233 | 234 | public object ComplexAsVariant (object v, int num) 235 | { 236 | Console.WriteLine ("v: " + v); 237 | Console.WriteLine ("v null? " + (v == null)); 238 | 239 | MyTuple2 mt2 = (MyTuple2)Convert.ChangeType (v, typeof (MyTuple2)); 240 | Console.WriteLine ("mt2.C[3].B " + mt2.C[3].B); 241 | Console.WriteLine ("num: " + num); 242 | 243 | return v; 244 | } 245 | 246 | public IDemoOne[] GetEmptyObjArr () 247 | { 248 | return new Demo[] {}; 249 | } 250 | 251 | public IDemoOne[] GetObjArr () 252 | { 253 | return new IDemoOne[] {this}; 254 | } 255 | 256 | public int SomeProp 257 | { 258 | get { 259 | return 123; 260 | } set { 261 | Console.WriteLine ("Set SomeProp: " + value); 262 | } 263 | } 264 | } 265 | 266 | public enum DemoEnum : byte 267 | { 268 | Foo, 269 | Bar, 270 | } 271 | 272 | 273 | public struct MyTuple 274 | { 275 | public MyTuple (string a, string b) 276 | { 277 | A = a; 278 | B = b; 279 | } 280 | 281 | public string A; 282 | public string B; 283 | } 284 | 285 | public struct MyTuple2 286 | { 287 | public string A; 288 | public string B; 289 | public IDictionary C; 290 | } 291 | 292 | public delegate void SomeEventHandler (string arg1, object arg2, double arg3, MyTuple mt); 293 | 294 | public enum ConnectionPresenceType : uint 295 | { 296 | Unset = 0, Offline = 1, Available = 2, Away = 3, ExtendedAway = 4, Hidden = 5, Busy = 6, Unknown = 7, Error = 8, 297 | } 298 | 299 | public struct SimplePresence 300 | { 301 | public ConnectionPresenceType Type; 302 | public string Status; 303 | public string StatusMessage; 304 | } 305 | 306 | -------------------------------------------------------------------------------- /examples/TestNotifications.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | using DBus; 9 | using org.freedesktop; 10 | using org.freedesktop.DBus; 11 | 12 | // Just for fun. A more complete implementation would cover the API at: 13 | // http://www.galago-project.org/docs/api/libnotify/notification_8h.html 14 | public class ManagedDBusTestNotifications 15 | { 16 | public static void Main () 17 | { 18 | Bus bus = Bus.Session; 19 | 20 | Notifications nf = bus.GetObject ("org.freedesktop.Notifications", new ObjectPath ("/org/freedesktop/Notifications")); 21 | 22 | Console.WriteLine (); 23 | Console.WriteLine ("Capabilities:"); 24 | foreach (string cap in nf.GetCapabilities ()) 25 | Console.WriteLine ("\t" + cap); 26 | 27 | ServerInformation si = nf.GetServerInformation (); 28 | 29 | //TODO: ability to pass null 30 | Dictionary hints = new Dictionary (); 31 | 32 | string message = String.Format ("Brought to you using {0} {1} (implementing spec version {2}) from {3}.", si.Name, si.Version, si.SpecVersion, si.Vendor); 33 | 34 | uint handle = nf.Notify ("D-Bus# Notifications Demo", 0, "warning", "Managed D-Bus# says 'Hello'!", message, new string[0], hints, 0); 35 | 36 | Console.WriteLine (); 37 | Console.WriteLine ("Got handle " + handle); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/TestObjects.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using DBus; 8 | using org.freedesktop.DBus; 9 | 10 | public class ManagedDBusTestObjects 11 | { 12 | public static void Main () 13 | { 14 | Bus bus = Bus.Session; 15 | 16 | ObjectPath myPath = new ObjectPath ("/org/ndesk/test"); 17 | string myName = "org.ndesk.test"; 18 | 19 | //TODO: write the rest of this demo and implement 20 | } 21 | } 22 | 23 | public class Device : IDevice 24 | { 25 | public string Name 26 | { 27 | get { 28 | return "Some device"; 29 | } 30 | } 31 | } 32 | 33 | public class DeviceManager : IDeviceManager 34 | { 35 | public IDevice CurrentDevice 36 | { 37 | get { 38 | return new Device (); 39 | } 40 | } 41 | } 42 | 43 | public interface IDevice 44 | { 45 | string Name { get; } 46 | } 47 | 48 | public interface IDeviceManager 49 | { 50 | IDevice CurrentDevice { get; } 51 | } 52 | 53 | public interface IUglyDeviceManager 54 | { 55 | ObjectPath CurrentDevice { get; } 56 | } 57 | -------------------------------------------------------------------------------- /examples/TestSample.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using DBus; 8 | using org.freedesktop.DBus; 9 | 10 | public class ManagedDBusTestSample 11 | { 12 | public static void Main () 13 | { 14 | Bus bus = Bus.Session; 15 | 16 | SampleInterface sample = bus.GetObject ("com.example.SampleService", new ObjectPath ("/SomeObject")); 17 | 18 | Console.WriteLine (); 19 | string xmlData = sample.Introspect (); 20 | Console.WriteLine ("xmlData: " + xmlData); 21 | 22 | //object obj = sample.HelloWorld ("Hello from example-client.py!"); 23 | string[] vals = sample.HelloWorld ("Hello from example-client.py!"); 24 | foreach (string val in vals) 25 | Console.WriteLine (val); 26 | 27 | Console.WriteLine (); 28 | MyTuple tup = sample.GetTuple (); 29 | Console.WriteLine (tup.A); 30 | Console.WriteLine (tup.B); 31 | 32 | Console.WriteLine (); 33 | IDictionary dict = sample.GetDict (); 34 | foreach (KeyValuePair pair in dict) 35 | Console.WriteLine (pair.Key + ": " + pair.Value); 36 | } 37 | } 38 | 39 | [Interface ("com.example.SampleInterface")] 40 | public interface SampleInterface : Introspectable 41 | { 42 | //void HelloWorld (object hello_message); 43 | //object HelloWorld (object hello_message); 44 | string[] HelloWorld (object hello_message); 45 | MyTuple GetTuple (); 46 | IDictionary GetDict (); 47 | } 48 | 49 | //(ss) 50 | public struct MyTuple 51 | { 52 | public string A; 53 | public string B; 54 | } 55 | -------------------------------------------------------------------------------- /examples/TestServer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using DBus; 7 | using org.freedesktop.DBus; 8 | 9 | using System.IO; 10 | using System.Net; 11 | using System.Net.Sockets; 12 | using Mono.Unix; 13 | 14 | using System.Threading; 15 | 16 | public class TestServer 17 | { 18 | //TODO: complete this test daemon/server example, and a client 19 | //TODO: maybe generalise it and integrate it into the core 20 | public static void Main (string[] args) 21 | { 22 | bool isServer; 23 | 24 | if (args.Length == 1 && args[0] == "server") 25 | isServer = true; 26 | else if (args.Length == 1 && args[0] == "client") 27 | isServer = false; 28 | else { 29 | Console.Error.WriteLine ("Usage: test-server [server|client]"); 30 | return; 31 | } 32 | 33 | string addr = "unix:abstract=/tmp/dbus-ABCDEFGHIJ"; 34 | 35 | Connection conn; 36 | 37 | ObjectPath myOpath = new ObjectPath ("/org/ndesk/test"); 38 | string myNameReq = "org.ndesk.test"; 39 | 40 | if (!isServer) { 41 | conn = new Connection (addr); 42 | DemoObject demo = conn.GetObject (myNameReq, myOpath); 43 | demo.GiveNoReply (); 44 | //float ret = demo.Hello ("hi from test client", 21); 45 | float ret = 200; 46 | while (ret > 5) { 47 | ret = demo.Hello ("hi from test client", (int)ret); 48 | Console.WriteLine ("Returned float: " + ret); 49 | System.Threading.Thread.Sleep (1000); 50 | } 51 | } else { 52 | string path; 53 | bool abstr; 54 | 55 | Address.Parse (addr, out path, out abstr); 56 | 57 | AbstractUnixEndPoint ep = new AbstractUnixEndPoint (path); 58 | Socket server = new Socket (AddressFamily.Unix, SocketType.Stream, 0); 59 | 60 | server.Bind (ep); 61 | //server.Listen (1); 62 | server.Listen (5); 63 | 64 | while (true) { 65 | Console.WriteLine ("Waiting for client on " + addr); 66 | Socket client = server.Accept (); 67 | Console.WriteLine ("Client accepted"); 68 | client.Blocking = true; 69 | 70 | PeerCred pc = new PeerCred (client); 71 | Console.WriteLine ("PeerCred: pid={0}, uid={1}, gid={2}", pc.ProcessID, pc.UserID, pc.GroupID); 72 | 73 | conn = new Connection (null); 74 | conn.ns = new NetworkStream (client); 75 | conn.SocketHandle = (long)client.Handle; 76 | 77 | //ConnectionHandler.Handle (conn); 78 | 79 | //in reality a thread per connection is of course too expensive 80 | ConnectionHandler hnd = new ConnectionHandler (conn); 81 | new Thread (new ThreadStart (hnd.Handle)).Start (); 82 | 83 | Console.WriteLine (); 84 | } 85 | } 86 | } 87 | } 88 | 89 | public class ConnectionHandler 90 | { 91 | protected Connection conn; 92 | 93 | public ConnectionHandler (Connection conn) 94 | { 95 | this.conn = conn; 96 | } 97 | 98 | public void Handle () 99 | { 100 | ConnectionHandler.Handle (conn); 101 | } 102 | 103 | public static void Handle (Connection conn) 104 | { 105 | string myNameReq = "org.ndesk.test"; 106 | ObjectPath myOpath = new ObjectPath ("/org/ndesk/test"); 107 | 108 | DemoObject demo = new DemoObject (); 109 | conn.Register (myNameReq, myOpath, demo); 110 | 111 | //TODO: handle lost connections etc. properly instead of stupido try/catch 112 | try { 113 | while (true) 114 | conn.Iterate (); 115 | } catch (Exception e) { 116 | //Console.Error.WriteLine (e); 117 | } 118 | 119 | conn.Unregister (myNameReq, myOpath); 120 | } 121 | } 122 | 123 | [Interface ("org.ndesk.test")] 124 | public class DemoObject : MarshalByRefObject 125 | { 126 | public float Hello (string arg0, int arg1) 127 | { 128 | Console.WriteLine ("Got a Hello(" + arg0 + ", " + arg1 +")"); 129 | 130 | return (float)arg1/2; 131 | } 132 | 133 | public void GiveNoReply () 134 | { 135 | Console.WriteLine ("Asked to give no reply"); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /examples/TestServerNative.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using DBus; 7 | using org.freedesktop.DBus; 8 | 9 | using System.IO; 10 | using Mono.Unix; 11 | 12 | using System.Threading; 13 | 14 | using System.Text; 15 | using DBus.Transports; 16 | 17 | public class TestServerNative 18 | { 19 | //TODO: complete this test daemon/server example, and a client 20 | //TODO: maybe generalise it and integrate it into the core 21 | public static void Main (string[] args) 22 | { 23 | bool isServer; 24 | 25 | if (args.Length == 1 && args[0] == "server") 26 | isServer = true; 27 | else if (args.Length == 1 && args[0] == "client") 28 | isServer = false; 29 | else { 30 | Console.Error.WriteLine ("Usage: test-server [server|client]"); 31 | return; 32 | } 33 | 34 | //string addr = "unix:abstract=/tmp/dbus-ABCDEFGHIJ"; 35 | string addr = "unix:path=/tmp/dbus-ABCDEFGHIJ"; 36 | 37 | Connection conn; 38 | 39 | ObjectPath myOpath = new ObjectPath ("/org/ndesk/test"); 40 | string myNameReq = "org.ndesk.test"; 41 | 42 | if (!isServer) { 43 | conn = new Connection (Transport.Create (AddressEntry.Parse (addr))); 44 | DemoObject demo = conn.GetObject (myNameReq, myOpath); 45 | demo.GiveNoReply (); 46 | //float ret = demo.Hello ("hi from test client", 21); 47 | float ret = 200; 48 | while (ret > 5) { 49 | ret = demo.Hello ("hi from test client", (int)ret); 50 | Console.WriteLine ("Returned float: " + ret); 51 | System.Threading.Thread.Sleep (1000); 52 | } 53 | } else { 54 | string path; 55 | bool abstr; 56 | 57 | AddressEntry entry = AddressEntry.Parse (addr); 58 | path = entry.Properties["path"]; 59 | 60 | UnixSocket server = new UnixSocket (); 61 | 62 | 63 | byte[] p = Encoding.Default.GetBytes (path); 64 | 65 | byte[] sa = new byte[2 + p.Length + 1]; 66 | 67 | //we use BitConverter to stay endian-safe 68 | byte[] afData = BitConverter.GetBytes (UnixSocket.AF_UNIX); 69 | sa[0] = afData[0]; 70 | sa[1] = afData[1]; 71 | 72 | for (int i = 0 ; i != p.Length ; i++) 73 | sa[2 + i] = p[i]; 74 | sa[2 + p.Length] = 0; //null suffix for domain socket addresses, see unix(7) 75 | 76 | 77 | server.Bind (sa); 78 | //server.Listen (1); 79 | server.Listen (5); 80 | 81 | while (true) { 82 | Console.WriteLine ("Waiting for client on " + addr); 83 | UnixSocket client = server.Accept (); 84 | Console.WriteLine ("Client accepted"); 85 | //client.Blocking = true; 86 | 87 | //PeerCred pc = new PeerCred (client); 88 | //Console.WriteLine ("PeerCred: pid={0}, uid={1}, gid={2}", pc.ProcessID, pc.UserID, pc.GroupID); 89 | 90 | UnixNativeTransport transport = new UnixNativeTransport (); 91 | transport.Stream = new UnixStream (client.Handle); 92 | conn = new Connection (transport); 93 | 94 | //ConnectionHandler.Handle (conn); 95 | 96 | //in reality a thread per connection is of course too expensive 97 | ConnectionHandler hnd = new ConnectionHandler (conn); 98 | new Thread (new ThreadStart (hnd.Handle)).Start (); 99 | 100 | Console.WriteLine (); 101 | } 102 | } 103 | } 104 | } 105 | 106 | public class ConnectionHandler 107 | { 108 | protected Connection conn; 109 | 110 | public ConnectionHandler (Connection conn) 111 | { 112 | this.conn = conn; 113 | } 114 | 115 | public void Handle () 116 | { 117 | ConnectionHandler.Handle (conn); 118 | } 119 | 120 | public static void Handle (Connection conn) 121 | { 122 | string myNameReq = "org.ndesk.test"; 123 | ObjectPath myOpath = new ObjectPath ("/org/ndesk/test"); 124 | 125 | DemoObject demo = new DemoObject (); 126 | conn.Register (myNameReq, myOpath, demo); 127 | 128 | //TODO: handle lost connections etc. properly instead of stupido try/catch 129 | try { 130 | while (true) 131 | conn.Iterate (); 132 | } catch (Exception e) { 133 | //Console.Error.WriteLine (e); 134 | } 135 | 136 | conn.Unregister (myNameReq, myOpath); 137 | } 138 | } 139 | 140 | [Interface ("org.ndesk.test")] 141 | public class DemoObject : MarshalByRefObject 142 | { 143 | public float Hello (string arg0, int arg1) 144 | { 145 | Console.WriteLine ("Got a Hello(" + arg0 + ", " + arg1 +")"); 146 | 147 | return (float)arg1/2; 148 | } 149 | 150 | public void GiveNoReply () 151 | { 152 | Console.WriteLine ("Asked to give no reply"); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /examples/TestServerTcp.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using DBus; 7 | using DBus.Transports; 8 | using org.freedesktop.DBus; 9 | 10 | using System.IO; 11 | using System.Net; 12 | using System.Net.Sockets; 13 | 14 | using System.Threading; 15 | 16 | public class TestServerTcp 17 | { 18 | public static void Main (string[] args) 19 | { 20 | bool isServer; 21 | 22 | int port; 23 | string hostname = "127.0.0.1"; 24 | //IPAddress ipaddr = IPAddress.Parse ("127.0.0.1"); 25 | 26 | if (args.Length == 2 && args[0] == "server") { 27 | isServer = true; 28 | port = Int32.Parse (args[1]); 29 | } else if (args.Length == 3 && args[0] == "client") { 30 | isServer = false; 31 | hostname = args[1]; 32 | port = Int32.Parse (args[2]); 33 | } else { 34 | Console.Error.WriteLine ("Usage: test-server-tcp [server PORT|client HOSTNAME PORT]"); 35 | return; 36 | } 37 | 38 | Connection conn; 39 | 40 | ObjectPath myOpath = new ObjectPath ("/org/ndesk/test"); 41 | string myNameReq = "org.ndesk.test"; 42 | 43 | if (!isServer) { 44 | SocketTransport transport = new SocketTransport (); 45 | transport.Open (hostname, port); 46 | conn = new Connection (transport); 47 | 48 | DemoObject demo = conn.GetObject (myNameReq, myOpath); 49 | demo.GiveNoReply (); 50 | //float ret = demo.Hello ("hi from test client", 21); 51 | float ret = 200; 52 | while (ret > 5) { 53 | ret = demo.Hello ("hi from test client", (int)ret); 54 | Console.WriteLine ("Returned float: " + ret); 55 | System.Threading.Thread.Sleep (1000); 56 | } 57 | } else { 58 | TcpListener server = new TcpListener (IPAddress.Any, port); 59 | 60 | server.Start (); 61 | 62 | while (true) { 63 | Console.WriteLine ("Waiting for client on " + port); 64 | TcpClient client = server.AcceptTcpClient (); 65 | Console.WriteLine ("Client accepted"); 66 | 67 | //TODO: use the right abstraction here, probably using the Server class 68 | SocketTransport transport = new SocketTransport (); 69 | transport.Stream = client.GetStream (); 70 | conn = new Connection (transport); 71 | 72 | //conn.SocketHandle = (long)clientSocket.Handle; 73 | 74 | //ConnectionHandler.Handle (conn); 75 | 76 | //in reality a thread per connection is of course too expensive 77 | ConnectionHandler hnd = new ConnectionHandler (conn); 78 | new Thread (new ThreadStart (hnd.Handle)).Start (); 79 | 80 | Console.WriteLine (); 81 | } 82 | } 83 | } 84 | } 85 | 86 | public class ConnectionHandler 87 | { 88 | protected Connection conn; 89 | 90 | public ConnectionHandler (Connection conn) 91 | { 92 | this.conn = conn; 93 | } 94 | 95 | public void Handle () 96 | { 97 | ConnectionHandler.Handle (conn); 98 | } 99 | 100 | public static void Handle (Connection conn) 101 | { 102 | string myNameReq = "org.ndesk.test"; 103 | ObjectPath myOpath = new ObjectPath ("/org/ndesk/test"); 104 | 105 | DemoObject demo = new DemoObject (); 106 | conn.Register (myNameReq, myOpath, demo); 107 | 108 | //TODO: handle lost connections etc. properly instead of stupido try/catch 109 | try { 110 | while (true) 111 | conn.Iterate (); 112 | } catch (Exception e) { 113 | //Console.Error.WriteLine (e); 114 | } 115 | 116 | conn.Unregister (myNameReq, myOpath); 117 | } 118 | } 119 | 120 | [Interface ("org.ndesk.test")] 121 | public class DemoObject : MarshalByRefObject 122 | { 123 | public float Hello (string arg0, int arg1) 124 | { 125 | Console.WriteLine ("Got a Hello(" + arg0 + ", " + arg1 +")"); 126 | 127 | return (float)arg1/2; 128 | } 129 | 130 | public void GiveNoReply () 131 | { 132 | Console.WriteLine ("Asked to give no reply"); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /examples/UnixFDClient.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Steffen Kiess 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | 7 | using DBus; 8 | using org.freedesktop.DBus; 9 | 10 | using Mono.Unix; 11 | using Mono.Unix.Native; 12 | 13 | class SignalsImpl : Signals { 14 | public event Action GotFD; 15 | 16 | public void CallGotFD (UnixFD fd) { 17 | var handler = GotFD; 18 | if (handler != null) 19 | handler (fd); 20 | } 21 | } 22 | 23 | public class ManagedDBusTest 24 | { 25 | public static void Main (string[] args) 26 | { 27 | Bus conn; 28 | 29 | if (args.Length == 0) 30 | conn = Bus.Session; 31 | else { 32 | if (args[0] == "--session") 33 | conn = Bus.Session; 34 | else if (args[0] == "--system") 35 | conn = Bus.System; 36 | else 37 | conn = Bus.Open (args[0]); 38 | } 39 | 40 | IBus bus = conn.GetObject ("org.freedesktop.DBus", new ObjectPath ("/org/freedesktop/DBus")); 41 | Console.WriteLine (bus.ListNames ().Length); 42 | 43 | var obj = conn.GetObject (Constants.BusName, Constants.ObjectPath); 44 | var obj2 = conn.GetObject (Constants.BusName, Constants.ObjectPath); 45 | var objIntr = conn.GetObject (Constants.BusName, Constants.ObjectPath); 46 | obj.Ping (); 47 | Console.WriteLine (obj.GetBytes (3).Length); 48 | 49 | Console.WriteLine ("conn.UnixFDSupported = " + conn.UnixFDSupported); 50 | if (!conn.UnixFDSupported) 51 | return; 52 | 53 | using (var disposableList = new DisposableList ()) { 54 | var res = obj.GetFD (disposableList, false); 55 | Console.WriteLine ("Got FD:"); 56 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + res.Handle); 57 | } 58 | using (var disposableList = new DisposableList ()) { 59 | var res = obj.GetFDList (disposableList, false); 60 | Console.WriteLine ("Got FDs:"); 61 | foreach (var fd in res) 62 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle); 63 | } 64 | using (var disposableList = new DisposableList ()) { 65 | var res = (UnixFD[]) obj.GetFDListVariant (disposableList, false); 66 | Console.WriteLine ("Got FDs as variant:"); 67 | foreach (var fd in res) 68 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle); 69 | } 70 | 71 | using (var disposableList = new DisposableList ()) { 72 | try { 73 | obj.GetFD (disposableList, true); 74 | throw new Exception ("Expected an exception"); 75 | } catch (Exception e) { 76 | if (!e.Message.Contains ("Throwing an exception after creating a UnixFD object")) 77 | throw; 78 | } 79 | } 80 | using (var disposableList = new DisposableList ()) { 81 | try { 82 | obj.GetFDList (disposableList, true); 83 | throw new Exception ("Expected an exception"); 84 | } catch (Exception e) { 85 | if (!e.Message.Contains ("Throwing an exception after creating a UnixFD object")) 86 | throw; 87 | } 88 | } 89 | using (var disposableList = new DisposableList ()) { 90 | try { 91 | obj.GetFDListVariant (disposableList, true); 92 | throw new Exception ("Expected an exception"); 93 | } catch (Exception e) { 94 | if (!e.Message.Contains ("Throwing an exception after creating a UnixFD object")) 95 | throw; 96 | } 97 | } 98 | 99 | // Check whether this leaks an FD 100 | obj.GetFD (null, false); 101 | obj.GetFDList (null, false); 102 | obj.GetFDListVariant (null, false); 103 | try { obj.GetFD (null, true); } catch {} 104 | try { obj.GetFDList (null, true); } catch {} 105 | try { obj.GetFDListVariant (null, true); } catch {} 106 | obj2.GetFD (false); 107 | obj2.GetFDList (false); 108 | obj2.GetFDListVariant (false); 109 | try { obj2.GetFD (true); } catch {} 110 | try { obj2.GetFDList (true); } catch {} 111 | try { obj2.GetFDListVariant (true); } catch {} 112 | 113 | var fd_ = Syscall.open ("/dev/null", OpenFlags.O_RDWR, 0); 114 | if (fd_ < 0) 115 | UnixMarshal.ThrowExceptionForLastError (); 116 | using (var fd = new UnixFD (fd_)) { 117 | obj.SendFD (fd); 118 | obj.SendFD (fd); 119 | obj.SendFDList (new UnixFD[] { fd, fd }); 120 | obj.SendFDListVariant (new UnixFD[] { fd, fd }); 121 | 122 | var impl = new SignalsImpl (); 123 | var spath = new ObjectPath ("/mono_dbus_sharp_test/Signals"); 124 | conn.Register (spath, impl); 125 | obj.RegisterSignalInterface (conn.UniqueName, spath); 126 | impl.CallGotFD (fd); 127 | } 128 | 129 | Console.WriteLine (objIntr.Introspect ().Length); 130 | 131 | obj.ListOpenFDs (); 132 | Console.WriteLine ("Open FDs:"); 133 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/"); 134 | } 135 | } 136 | 137 | -------------------------------------------------------------------------------- /examples/UnixFDInterface.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Steffen Kiess 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using DBus; 7 | 8 | public static class Constants { 9 | public const string BusName = "mono_dbus_sharp_test.UnixFDService"; 10 | public static readonly ObjectPath ObjectPath = new ObjectPath ("/mono_dbus_sharp_test/UnixFDService"); 11 | } 12 | 13 | [DBus.Interface ("mono_dbus_sharp_test.UnixFDService")] 14 | public interface Interface { 15 | void Ping (); 16 | 17 | void ListOpenFDs (); 18 | 19 | byte[] GetBytes (int len); 20 | 21 | UnixFD GetFD (DisposableList disposableList, bool throwError); 22 | UnixFD[] GetFDList (DisposableList disposableList, bool throwError); 23 | object GetFDListVariant (DisposableList disposableList, bool throwError); 24 | 25 | void SendFD (UnixFD fd); 26 | void SendFDList (UnixFD[] fds); 27 | void SendFDListVariant (object fds); 28 | 29 | void RegisterSignalInterface (string busName, ObjectPath path); 30 | } 31 | 32 | [DBus.Interface ("mono_dbus_sharp_test.UnixFDService")] 33 | public interface Interface2 { 34 | void Ping (); 35 | 36 | void ListOpenFDs (); 37 | 38 | byte[] GetBytes (int len); 39 | 40 | UnixFD GetFD (bool throwError); 41 | UnixFD[] GetFDList (bool throwError); 42 | object GetFDListVariant (bool throwError); 43 | 44 | void SendFD (UnixFD fd); 45 | void SendFDList (UnixFD[] fds); 46 | void SendFDListVariant (object fds); 47 | 48 | void RegisterSignalInterface (string busName, ObjectPath path); 49 | } 50 | 51 | [DBus.Interface ("mono_dbus_sharp_test.UnixFDSignals")] 52 | public interface Signals { 53 | event Action GotFD; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/UnixFDService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Steffen Kiess 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | /* 6 | PATH="$HOME/mono-master/bin:$PATH" ./autogen.sh && make -j8 7 | make && ( cd examples && mcs -g UnixFDService.cs UnixFDInterface.cs -r ../src/dbus-sharp.dll -r Mono.Posix ) && MONO_PATH=src $HOME/mono-master/bin/mono --debug examples/UnixFDService.exe 8 | make && ( cd examples && mcs -g UnixFDClient.cs UnixFDInterface.cs -r ../src/dbus-sharp.dll -r Mono.Posix ) && MONO_PATH=src $HOME/mono-master/bin/mono --debug examples/UnixFDClient.exe 9 | 10 | python3 11 | import dbus; dbus.SessionBus().get_object('mono_dbus_sharp_test.UnixFDService', '/mono_dbus_sharp_test/UnixFDService').GetBytes(3) 12 | import dbus; f = dbus.SessionBus().get_object('mono_dbus_sharp_test.UnixFDService', '/mono_dbus_sharp_test/UnixFDService').GetFD () 13 | */ 14 | 15 | using System; 16 | 17 | using Mono.Unix; 18 | using Mono.Unix.Native; 19 | 20 | using DBus; 21 | using org.freedesktop.DBus; 22 | 23 | public class Impl : Interface { 24 | Connection conn; 25 | 26 | public Impl (Connection conn) 27 | { 28 | this.conn = conn; 29 | } 30 | 31 | public void Ping () 32 | { 33 | } 34 | 35 | public void ListOpenFDs () 36 | { 37 | Console.WriteLine ("Open FDs:"); 38 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/"); 39 | } 40 | 41 | public UnixFD GetFD (DisposableList disposableList, bool throwError) 42 | { 43 | var fd_ = Syscall.open ("/dev/null", OpenFlags.O_RDWR, 0); 44 | if (fd_ < 0) 45 | UnixMarshal.ThrowExceptionForLastError (); 46 | var fd = new UnixFD (fd_); 47 | disposableList.Add (fd); 48 | 49 | if (throwError) 50 | throw new Exception ("Throwing an exception after creating a UnixFD object"); 51 | 52 | return fd; 53 | } 54 | 55 | public UnixFD[] GetFDList (DisposableList disposableList, bool throwError) 56 | { 57 | return new UnixFD[] { 58 | GetFD (disposableList, false), GetFD (disposableList, throwError), GetFD (disposableList, false) 59 | }; 60 | } 61 | 62 | public object GetFDListVariant (DisposableList disposableList, bool throwError) 63 | { 64 | return GetFDList (disposableList, throwError); 65 | } 66 | 67 | public byte[] GetBytes (int len) 68 | { 69 | return new byte[len]; 70 | } 71 | 72 | public void SendFD (UnixFD fd) 73 | { 74 | Console.WriteLine ("Got FD as parameter:"); 75 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle); 76 | } 77 | 78 | public void SendFDList (UnixFD[] fds) 79 | { 80 | Console.WriteLine ("Got FDs as parameter:"); 81 | foreach (var fd in fds) 82 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle); 83 | } 84 | 85 | public void SendFDListVariant (object fds) 86 | { 87 | Console.WriteLine ("Got FDs as variant parameter:"); 88 | foreach (var fd in (UnixFD[]) fds) 89 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle); 90 | } 91 | 92 | public void RegisterSignalInterface (string busName, ObjectPath path) 93 | { 94 | Console.WriteLine ("Register for GotFD event at {0} / {1}", busName, path); 95 | conn.GetObject (busName, path).GotFD += fd => { 96 | Console.WriteLine ("Got FD from signal:"); 97 | Mono.Unix.Native.Stdlib.system ("ls -l /proc/$PPID/fd/" + fd.Handle); 98 | }; 99 | } 100 | } 101 | 102 | public class UnixFDService 103 | { 104 | public static void Main (string[] args) 105 | { 106 | Bus conn; 107 | 108 | if (args.Length == 0) 109 | conn = Bus.Session; 110 | else { 111 | if (args[0] == "--session") 112 | conn = Bus.Session; 113 | else if (args[0] == "--system") 114 | conn = Bus.System; 115 | else 116 | conn = Bus.Open (args[0]); 117 | } 118 | 119 | conn.Register (Constants.ObjectPath, new Impl (conn)); 120 | 121 | if (conn.RequestName (Constants.BusName) != org.freedesktop.DBus.RequestNameReply.PrimaryOwner) 122 | throw new Exception ("Could not request name"); 123 | 124 | Console.WriteLine ("Waiting for requests..."); 125 | 126 | while (conn.IsConnected) { 127 | conn.Iterate (); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Address.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Text; 7 | using System.Collections.Generic; 8 | 9 | namespace DBus 10 | { 11 | // Subclass obsolete BadAddressException to avoid ABI break 12 | #pragma warning disable 0618 13 | //public class InvalidAddressException : Exception 14 | public class InvalidAddressException : BadAddressException 15 | { 16 | public InvalidAddressException (string reason) : base (reason) {} 17 | } 18 | #pragma warning restore 0618 19 | 20 | [Obsolete ("Use InvalidAddressException")] 21 | public class BadAddressException : Exception 22 | { 23 | public BadAddressException (string reason) : base (reason) {} 24 | } 25 | 26 | static class Address 27 | { 28 | // (unix:(path|abstract)=.*,guid=.*|tcp:host=.*(,port=.*)?);? ... 29 | // or 30 | // autolaunch: 31 | public static AddressEntry[] Parse (string addresses) 32 | { 33 | if (addresses == null) 34 | throw new ArgumentNullException (addresses); 35 | 36 | List entries = new List (); 37 | 38 | foreach (string entryStr in addresses.Split (';')) 39 | entries.Add (AddressEntry.Parse (entryStr)); 40 | 41 | return entries.ToArray (); 42 | } 43 | 44 | public static string System 45 | { 46 | get { 47 | string addr = Environment.GetEnvironmentVariable ("DBUS_SYSTEM_BUS_ADDRESS"); 48 | if (String.IsNullOrEmpty (addr) && OSHelpers.PlatformIsUnixoid) 49 | addr = "unix:path=/var/run/dbus/system_bus_socket"; 50 | return addr; 51 | } 52 | } 53 | 54 | public static string GetSessionBusAddressFromSharedMemory () 55 | { 56 | string result = OSHelpers.ReadSharedMemoryString ("DBusDaemonAddressInfo", 255); 57 | if (String.IsNullOrEmpty(result)) 58 | result = OSHelpers.ReadSharedMemoryString ("DBusDaemonAddressInfoDebug", 255); // a DEBUG build of the daemon uses this different address... 59 | return result; 60 | } 61 | 62 | public static string Session { 63 | get { 64 | // example: "tcp:host=localhost,port=21955,family=ipv4,guid=b2d47df3207abc3630ee6a71533effb6" 65 | // note that also "tcp:host=localhost,port=21955,family=ipv4" is sufficient 66 | 67 | // the predominant source for the address is the standard environment variable DBUS_SESSION_BUS_ADDRESS: 68 | string result = Environment.GetEnvironmentVariable ("DBUS_SESSION_BUS_ADDRESS"); 69 | 70 | // On Windows systems, the dbus-daemon additionally uses shared memory to publish the daemon's address. 71 | // See function _dbus_daemon_publish_session_bus_address() inside the daemon. 72 | if (string.IsNullOrEmpty (result) && !OSHelpers.PlatformIsUnixoid) { 73 | result = GetSessionBusAddressFromSharedMemory (); 74 | if (string.IsNullOrEmpty (result)) 75 | result = "autolaunch:"; 76 | } 77 | 78 | return result; 79 | } 80 | } 81 | 82 | public static string Starter { 83 | get { 84 | return Environment.GetEnvironmentVariable ("DBUS_STARTER_ADDRESS"); 85 | } 86 | } 87 | 88 | public static string StarterBusType { 89 | get { 90 | return Environment.GetEnvironmentVariable ("DBUS_STARTER_BUS_TYPE"); 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/AddressEntry.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | using System.Text; 8 | using System.Collections.Generic; 9 | 10 | namespace DBus 11 | { 12 | class AddressEntry 13 | { 14 | public string Method; 15 | public readonly IDictionary Properties = new Dictionary (); 16 | public UUID GUID = UUID.Zero; 17 | 18 | public override string ToString () 19 | { 20 | StringBuilder sb = new StringBuilder (); 21 | sb.Append (Method); 22 | sb.Append (':'); 23 | 24 | bool first = true; 25 | foreach (KeyValuePair prop in Properties) { 26 | if (first) 27 | first = false; 28 | else 29 | sb.Append (','); 30 | 31 | sb.Append (prop.Key); 32 | sb.Append ('='); 33 | sb.Append (Escape (prop.Value)); 34 | } 35 | 36 | if (GUID != UUID.Zero) { 37 | if (Properties.Count != 0) 38 | sb.Append (','); 39 | sb.Append ("guid"); 40 | sb.Append ('='); 41 | sb.Append (GUID.ToString ()); 42 | } 43 | 44 | return sb.ToString (); 45 | } 46 | 47 | static string Escape (string str) 48 | { 49 | if (str == null) 50 | return String.Empty; 51 | 52 | StringBuilder sb = new StringBuilder (); 53 | int len = str.Length; 54 | 55 | for (int i = 0 ; i != len ; i++) { 56 | char c = str[i]; 57 | 58 | //everything other than the optionally escaped chars _must_ be escaped 59 | if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') 60 | || c == '-' || c == '_' || c == '/' || c == '\\' || c == '.') 61 | sb.Append (c); 62 | else 63 | sb.Append (Uri.HexEscape (c)); 64 | } 65 | 66 | return sb.ToString (); 67 | } 68 | 69 | static string Unescape (string str) 70 | { 71 | if (str == null) 72 | return String.Empty; 73 | 74 | StringBuilder sb = new StringBuilder (); 75 | int len = str.Length; 76 | int i = 0; 77 | while (i != len) { 78 | if (Uri.IsHexEncoding (str, i)) 79 | sb.Append (Uri.HexUnescape (str, ref i)); 80 | else 81 | sb.Append (str[i++]); 82 | } 83 | 84 | return sb.ToString (); 85 | } 86 | 87 | 88 | public static AddressEntry Parse (string s) 89 | { 90 | AddressEntry entry = new AddressEntry (); 91 | 92 | string[] parts = s.Split (':'); 93 | 94 | if (parts.Length < 2) 95 | throw new InvalidAddressException ("No colon found"); 96 | if (parts.Length > 2) 97 | throw new InvalidAddressException ("Too many colons found"); 98 | 99 | entry.Method = parts[0]; 100 | 101 | if (parts[1].Length > 0) { 102 | foreach (string propStr in parts[1].Split (',')) { 103 | parts = propStr.Split ('='); 104 | 105 | if (parts.Length < 2) 106 | throw new InvalidAddressException ("No equals sign found"); 107 | if (parts.Length > 2) 108 | throw new InvalidAddressException ("Too many equals signs found"); 109 | 110 | if (parts[0] == "guid") { 111 | try { 112 | entry.GUID = UUID.Parse (parts[1]); 113 | } catch { 114 | throw new InvalidAddressException ("Invalid guid specified"); 115 | } 116 | continue; 117 | } 118 | 119 | entry.Properties[parts[0]] = Unescape (parts[1]); 120 | } 121 | } 122 | 123 | return entry; 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/ArgDirection.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern s 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | 8 | namespace DBus 9 | { 10 | enum ArgDirection 11 | { 12 | In, 13 | Out, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System.Reflection; 6 | using System.Runtime.CompilerServices; 7 | 8 | [assembly: AssemblyFileVersion("0.9")] 9 | [assembly: AssemblyInformationalVersion("0.9")] 10 | [assembly: AssemblyVersion("2.0")] 11 | [assembly: AssemblyTitle ("dbus-sharp")] 12 | [assembly: AssemblyDescription ("D-Bus IPC protocol library and CLR binding")] 13 | [assembly: AssemblyCopyright ("Copyright (C) Alp Toker and others")] 14 | 15 | #if STRONG_NAME 16 | [assembly: InternalsVisibleTo ("dbus-sharp-tests, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 17 | [assembly: InternalsVisibleTo ("dbus-monitor, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 18 | [assembly: InternalsVisibleTo ("dbus-daemon, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 19 | [assembly: InternalsVisibleTo ("dbus-sharp-glib, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 20 | [assembly: InternalsVisibleTo ("dbus-sharp-proxies, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 21 | #else 22 | [assembly: InternalsVisibleTo ("dbus-sharp-tests")] 23 | [assembly: InternalsVisibleTo ("dbus-monitor")] 24 | [assembly: InternalsVisibleTo ("dbus-daemon")] 25 | [assembly: InternalsVisibleTo ("dbus-sharp-glib")] 26 | [assembly: InternalsVisibleTo ("dbus-sharp-proxies")] 27 | #endif 28 | -------------------------------------------------------------------------------- /src/AssemblyInfo.cs.in: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System.Reflection; 6 | using System.Runtime.CompilerServices; 7 | 8 | [assembly: AssemblyFileVersion("@VERSION@")] 9 | [assembly: AssemblyInformationalVersion("@VERSION@")] 10 | [assembly: AssemblyVersion("@API_VERSION@")] 11 | [assembly: AssemblyTitle ("dbus-sharp")] 12 | [assembly: AssemblyDescription ("D-Bus IPC protocol library and CLR binding")] 13 | [assembly: AssemblyCopyright ("Copyright (C) Alp Toker and others")] 14 | 15 | #if STRONG_NAME 16 | [assembly: InternalsVisibleTo ("dbus-sharp-tests, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 17 | [assembly: InternalsVisibleTo ("dbus-monitor, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 18 | [assembly: InternalsVisibleTo ("dbus-daemon, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 19 | [assembly: InternalsVisibleTo ("dbus-sharp-glib, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 20 | [assembly: InternalsVisibleTo ("dbus-sharp-proxies, PublicKey=0024000004800000940000000602000000240000525341310004000011000000931ae68c635866ff1dcc22547815bbfd67e3d6e80dbfdc9afe7d079670243b9af245eb9797e0766f8adf6afb5eae1d6716fb46ef25d82c37ac7303fe1d13b90780886e0f7a8208167f16dd4678682d4d793a56ccaf0a233411b7604128ae128e306c959fcd2a8038003b2830a326fda3cbbade2f285a9477f6ff8d194e20a2a5")] 21 | #else 22 | [assembly: InternalsVisibleTo ("dbus-sharp-tests")] 23 | [assembly: InternalsVisibleTo ("dbus-monitor")] 24 | [assembly: InternalsVisibleTo ("dbus-daemon")] 25 | [assembly: InternalsVisibleTo ("dbus-sharp-glib")] 26 | [assembly: InternalsVisibleTo ("dbus-sharp-proxies")] 27 | #endif 28 | -------------------------------------------------------------------------------- /src/Bus.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using org.freedesktop.DBus; 8 | 9 | namespace DBus 10 | { 11 | public sealed class Bus : Connection 12 | { 13 | static readonly string DBusName = "org.freedesktop.DBus"; 14 | static readonly ObjectPath DBusPath = new ObjectPath ("/org/freedesktop/DBus"); 15 | 16 | static Dictionary buses = new Dictionary (); 17 | 18 | static Bus starterBus = null; 19 | 20 | static Bus systemBus = Address.StarterBusType=="system" ? Starter : (Address.System !=null ? Bus.Open (Address.System ) : null); 21 | static Bus sessionBus = Address.StarterBusType=="session" ? Starter : (Address.Session != null ? Bus.Open (Address.Session) : null); 22 | 23 | IBus bus; 24 | string address; 25 | string uniqueName; 26 | 27 | public static Bus System 28 | { 29 | get { 30 | return systemBus; 31 | } 32 | } 33 | 34 | public static Bus Session 35 | { 36 | get { 37 | return sessionBus; 38 | } 39 | } 40 | 41 | public static Bus Starter 42 | { 43 | get { 44 | if (starterBus == null) { 45 | try { 46 | starterBus = Bus.Open (Address.Starter); 47 | } catch (Exception e) { 48 | throw new Exception ("Unable to open the starter message bus.", e); 49 | } 50 | } 51 | 52 | return starterBus; 53 | } 54 | } 55 | 56 | public static new Bus Open (string address) 57 | { 58 | if (address == null) 59 | throw new ArgumentNullException ("address"); 60 | 61 | Bus bus; 62 | if (buses.TryGetValue (address, out bus)) 63 | return bus; 64 | 65 | bus = new Bus (address); 66 | buses[address] = bus; 67 | 68 | return bus; 69 | } 70 | 71 | public Bus (string address) : base (address) 72 | { 73 | this.bus = GetObject (DBusName, DBusPath); 74 | this.address = address; 75 | Register (); 76 | } 77 | 78 | //should this be public? 79 | //as long as Bus subclasses Connection, having a Register with a completely different meaning is bad 80 | void Register () 81 | { 82 | if (uniqueName != null) 83 | throw new Exception ("Bus already has a unique name"); 84 | 85 | uniqueName = bus.Hello (); 86 | } 87 | 88 | protected override void CloseInternal () 89 | { 90 | /* In case the bus was opened with static method 91 | * Open, clear it from buses dictionary 92 | */ 93 | if (buses.ContainsKey (address)) 94 | buses.Remove (address); 95 | } 96 | 97 | protected override bool CheckBusNameExists (string busName) 98 | { 99 | if (busName == DBusName) 100 | return true; 101 | return NameHasOwner (busName); 102 | } 103 | 104 | public ulong GetUnixUser (string name) 105 | { 106 | return bus.GetConnectionUnixUser (name); 107 | } 108 | 109 | public RequestNameReply RequestName (string name) 110 | { 111 | return RequestName (name, NameFlag.None); 112 | } 113 | 114 | public RequestNameReply RequestName (string name, NameFlag flags) 115 | { 116 | return bus.RequestName (name, flags); 117 | } 118 | 119 | public ReleaseNameReply ReleaseName (string name) 120 | { 121 | return bus.ReleaseName (name); 122 | } 123 | 124 | public bool NameHasOwner (string name) 125 | { 126 | return bus.NameHasOwner (name); 127 | } 128 | 129 | public StartReply StartServiceByName (string name) 130 | { 131 | return StartServiceByName (name, 0); 132 | } 133 | 134 | public StartReply StartServiceByName (string name, uint flags) 135 | { 136 | return bus.StartServiceByName (name, flags); 137 | } 138 | 139 | internal protected override void AddMatch (string rule) 140 | { 141 | bus.AddMatch (rule); 142 | } 143 | 144 | internal protected override void RemoveMatch (string rule) 145 | { 146 | bus.RemoveMatch (rule); 147 | } 148 | 149 | public string GetId () 150 | { 151 | return bus.GetId (); 152 | } 153 | 154 | public string UniqueName 155 | { 156 | get { 157 | return uniqueName; 158 | } set { 159 | if (uniqueName != null) 160 | throw new Exception ("Unique name can only be set once"); 161 | uniqueName = value; 162 | } 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/BusException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | 8 | namespace DBus 9 | { 10 | class BusException : Exception 11 | { 12 | public BusException (string errorName, string errorMessage) 13 | { 14 | this.ErrorName = errorName; 15 | this.ErrorMessage = errorMessage; 16 | } 17 | 18 | public BusException (string errorName, string format, params object[] args) 19 | { 20 | this.ErrorName = errorName; 21 | this.ErrorMessage = String.Format (format, args); 22 | } 23 | 24 | public override string Message 25 | { 26 | get 27 | { 28 | return ErrorName + ": " + ErrorMessage; 29 | } 30 | } 31 | 32 | public readonly string ErrorName; 33 | 34 | public readonly string ErrorMessage; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/BusObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Reflection; 7 | using System.Reflection.Emit; 8 | using System.Collections.Generic; 9 | 10 | namespace DBus 11 | { 12 | using Protocol; 13 | 14 | public class BusObject 15 | { 16 | static Dictionary boCache = new Dictionary(); 17 | 18 | protected Connection conn; 19 | string bus_name; 20 | ObjectPath object_path; 21 | 22 | public BusObject () 23 | { 24 | } 25 | 26 | public BusObject (Connection conn, string bus_name, ObjectPath object_path) 27 | { 28 | this.conn = conn; 29 | this.bus_name = bus_name; 30 | this.object_path = object_path; 31 | } 32 | 33 | public Connection Connection 34 | { 35 | get { 36 | return conn; 37 | } 38 | } 39 | 40 | public string BusName 41 | { 42 | get { 43 | return bus_name; 44 | } 45 | } 46 | 47 | public ObjectPath Path 48 | { 49 | get { 50 | return object_path; 51 | } 52 | } 53 | 54 | public void ToggleSignal (string iface, string member, Delegate dlg, bool adding) 55 | { 56 | MatchRule rule = new MatchRule (); 57 | rule.MessageType = MessageType.Signal; 58 | rule.Fields.Add (FieldCode.Interface, new MatchTest (iface)); 59 | rule.Fields.Add (FieldCode.Member, new MatchTest (member)); 60 | rule.Fields.Add (FieldCode.Path, new MatchTest (object_path)); 61 | // FIXME: Cause a regression compared to 0.6 as name wasn't matched before 62 | // the problem arises because busname is not used by DBus daemon and 63 | // instead it uses the canonical name of the sender (i.e. similar to ':1.13') 64 | // rule.Fields.Add (FieldCode.Sender, new MatchTest (bus_name)); 65 | 66 | if (adding) { 67 | if (conn.Handlers.ContainsKey (rule)) 68 | conn.Handlers[rule] = Delegate.Combine (conn.Handlers[rule], dlg); 69 | else { 70 | conn.Handlers[rule] = dlg; 71 | conn.AddMatch (rule.ToString ()); 72 | } 73 | } else if (conn.Handlers.ContainsKey (rule)) { 74 | conn.Handlers[rule] = Delegate.Remove (conn.Handlers[rule], dlg); 75 | if (conn.Handlers[rule] == null) { 76 | conn.RemoveMatch (rule.ToString ()); 77 | conn.Handlers.Remove (rule); 78 | } 79 | } 80 | } 81 | 82 | public void SendSignal (string iface, string member, string inSigStr, MessageWriter writer, Type retType, out Exception exception) 83 | { 84 | SendSignal (iface, member, inSigStr, writer, retType, null, out exception); 85 | } 86 | internal void SendSignal (string iface, string member, string inSigStr, MessageWriter writer, Type retType, DisposableList disposableList, out Exception exception) 87 | { 88 | exception = null; 89 | 90 | Signature outSig = String.IsNullOrEmpty (inSigStr) ? Signature.Empty : new Signature (inSigStr); 91 | 92 | MessageContainer signal = new MessageContainer { 93 | Type = MessageType.Signal, 94 | Path = object_path, 95 | Interface = iface, 96 | Member = member, 97 | Signature = outSig, 98 | }; 99 | 100 | Message signalMsg = signal.Message; 101 | signalMsg.AttachBodyTo (writer); 102 | 103 | conn.Send (signalMsg); 104 | } 105 | 106 | public MessageReader SendMethodCall (string iface, string member, string inSigStr, MessageWriter writer, Type retType, out Exception exception) 107 | { 108 | return SendMethodCall (iface, member, inSigStr, writer, retType, null, out exception); 109 | } 110 | public MessageReader SendMethodCall (string iface, string member, string inSigStr, MessageWriter writer, Type retType, DisposableList disposableList, out Exception exception) 111 | { 112 | if (string.IsNullOrEmpty (bus_name)) 113 | throw new ArgumentNullException ("bus_name"); 114 | if (object_path == null) 115 | throw new ArgumentNullException ("object_path"); 116 | 117 | exception = null; 118 | Signature inSig = String.IsNullOrEmpty (inSigStr) ? Signature.Empty : new Signature (inSigStr); 119 | 120 | MessageContainer method_call = new MessageContainer { 121 | Path = object_path, 122 | Interface = iface, 123 | Member = member, 124 | Destination = bus_name, 125 | Signature = inSig 126 | }; 127 | 128 | Message callMsg = method_call.Message; 129 | callMsg.AttachBodyTo (writer); 130 | 131 | bool needsReply = true; 132 | 133 | callMsg.ReplyExpected = needsReply; 134 | callMsg.Signature = inSig; 135 | 136 | if (!needsReply) { 137 | conn.Send (callMsg); 138 | return null; 139 | } 140 | 141 | #if PROTO_REPLY_SIGNATURE 142 | if (needsReply) { 143 | Signature outSig = Signature.GetSig (retType); 144 | callMsg.Header[FieldCode.ReplySignature] = outSig; 145 | } 146 | #endif 147 | 148 | Message retMsg = conn.SendWithReplyAndBlock (callMsg, disposableList != null); 149 | if (disposableList != null && retMsg.UnixFDArray != null) 150 | foreach (var fd in retMsg.UnixFDArray.FDs) 151 | disposableList.Add (fd); 152 | 153 | MessageReader retVal = null; 154 | 155 | //handle the reply message 156 | switch (retMsg.Header.MessageType) { 157 | case MessageType.MethodReturn: 158 | retVal = new MessageReader (retMsg); 159 | break; 160 | case MessageType.Error: 161 | MessageContainer error = MessageContainer.FromMessage (retMsg); 162 | string errMsg = String.Empty; 163 | if (retMsg.Signature.Value.StartsWith ("s")) { 164 | MessageReader reader = new MessageReader (retMsg); 165 | errMsg = reader.ReadString (); 166 | } 167 | exception = new Exception (error.ErrorName + ": " + errMsg); 168 | break; 169 | default: 170 | throw new Exception ("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error"); 171 | } 172 | 173 | return retVal; 174 | } 175 | 176 | public void Invoke (MethodBase methodBase, string methodName, object[] inArgs, out object[] outArgs, out object retVal, out Exception exception) 177 | { 178 | Invoke (methodBase, methodName, inArgs, null, out outArgs, out retVal, out exception); 179 | } 180 | public void Invoke (MethodBase methodBase, string methodName, object[] inArgs, DisposableList disposableList, out object[] outArgs, out object retVal, out Exception exception) 181 | { 182 | outArgs = new object[0]; 183 | retVal = null; 184 | exception = null; 185 | 186 | MethodInfo mi = methodBase as MethodInfo; 187 | 188 | if (mi != null && mi.IsSpecialName && (methodName.StartsWith ("add_") || methodName.StartsWith ("remove_"))) { 189 | string[] parts = methodName.Split (new char[]{'_'}, 2); 190 | string ename = parts[1]; 191 | Delegate dlg = (Delegate)inArgs[0]; 192 | 193 | ToggleSignal (Mapper.GetInterfaceName (mi), ename, dlg, parts[0] == "add"); 194 | 195 | return; 196 | } 197 | 198 | Type[] inTypes = Mapper.GetTypes (ArgDirection.In, mi.GetParameters ()); 199 | Signature inSig = Signature.GetSig (inTypes); 200 | 201 | string iface = null; 202 | if (mi != null) 203 | iface = Mapper.GetInterfaceName (mi); 204 | 205 | if (mi != null && mi.IsSpecialName) { 206 | methodName = methodName.Replace ("get_", "Get"); 207 | methodName = methodName.Replace ("set_", "Set"); 208 | } 209 | 210 | MessageWriter writer = new MessageWriter (conn); 211 | 212 | if (inArgs != null && inArgs.Length != 0) { 213 | for (int i = 0 ; i != inTypes.Length ; i++) 214 | writer.Write (inTypes[i], inArgs[i]); 215 | } 216 | 217 | MessageReader reader = SendMethodCall (iface, methodName, inSig.Value, writer, mi.ReturnType, out exception); 218 | if (reader == null) 219 | return; 220 | 221 | retVal = reader.ReadValue (mi.ReturnType); 222 | } 223 | 224 | public static object GetObject (Connection conn, string bus_name, ObjectPath object_path, Type declType) 225 | { 226 | Type proxyType = TypeImplementer.Root.GetImplementation (declType); 227 | 228 | object instObj = Activator.CreateInstance (proxyType); 229 | BusObject inst = GetBusObject (instObj); 230 | inst.conn = conn; 231 | inst.bus_name = bus_name; 232 | inst.object_path = object_path; 233 | 234 | return instObj; 235 | } 236 | 237 | public static BusObject GetBusObject (object instObj) 238 | { 239 | if (instObj is BusObject) 240 | return (BusObject)instObj; 241 | 242 | BusObject inst; 243 | if (boCache.TryGetValue (instObj, out inst)) 244 | return inst; 245 | 246 | inst = new BusObject (); 247 | boCache[instObj] = inst; 248 | 249 | return inst; 250 | } 251 | 252 | public Delegate GetHookupDelegate (EventInfo ei) 253 | { 254 | DynamicMethod hookupMethod = TypeImplementer.GetHookupMethod (ei); 255 | Delegate d = hookupMethod.CreateDelegate (ei.EventHandlerType, this); 256 | return d; 257 | } 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/DBus.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using DBus; 8 | 9 | namespace org.freedesktop.DBus 10 | { 11 | [Flags] 12 | public enum NameFlag : uint 13 | { 14 | None = 0, 15 | AllowReplacement = 0x1, 16 | ReplaceExisting = 0x2, 17 | DoNotQueue = 0x4, 18 | } 19 | 20 | public enum RequestNameReply : uint 21 | { 22 | PrimaryOwner = 1, 23 | InQueue, 24 | Exists, 25 | AlreadyOwner, 26 | } 27 | 28 | public enum ReleaseNameReply : uint 29 | { 30 | Released = 1, 31 | NonExistent, 32 | NotOwner, 33 | } 34 | 35 | public enum StartReply : uint 36 | { 37 | // The service was successfully started. 38 | Success = 1, 39 | // A connection already owns the given name. 40 | AlreadyRunning, 41 | } 42 | 43 | public delegate void NameOwnerChangedHandler (string name, string old_owner, string new_owner); 44 | public delegate void NameAcquiredHandler (string name); 45 | public delegate void NameLostHandler (string name); 46 | 47 | [Interface ("org.freedesktop.DBus.Peer")] 48 | public interface Peer 49 | { 50 | void Ping (); 51 | [return: Argument ("machine_uuid")] 52 | string GetMachineId (); 53 | } 54 | 55 | [Interface ("org.freedesktop.DBus.Introspectable")] 56 | public interface Introspectable 57 | { 58 | [return: Argument ("data")] 59 | string Introspect (); 60 | } 61 | 62 | [Interface ("org.freedesktop.DBus.Properties")] 63 | public interface Properties 64 | { 65 | [return: Argument ("value")] 66 | object Get (string @interface, string propname); 67 | void Set (string @interface, string propname, object value); 68 | [return: Argument ("props")] 69 | IDictionary GetAll (string @interface); 70 | } 71 | 72 | [Interface ("org.freedesktop.DBus")] 73 | public interface IBus 74 | { 75 | RequestNameReply RequestName (string name, NameFlag flags); 76 | ReleaseNameReply ReleaseName (string name); 77 | string Hello (); 78 | string[] ListNames (); 79 | string[] ListActivatableNames (); 80 | bool NameHasOwner (string name); 81 | event NameOwnerChangedHandler NameOwnerChanged; 82 | event NameLostHandler NameLost; 83 | event NameAcquiredHandler NameAcquired; 84 | StartReply StartServiceByName (string name, uint flags); 85 | void UpdateActivationEnvironment (IDictionary environment); 86 | string GetNameOwner (string name); 87 | uint GetConnectionUnixUser (string connection_name); 88 | void AddMatch (string rule); 89 | void RemoveMatch (string rule); 90 | string GetId (); 91 | 92 | //undocumented in spec 93 | string[] ListQueuedOwners (string name); 94 | uint GetConnectionUnixProcessID (string connection_name); 95 | byte[] GetConnectionSELinuxSecurityContext (string connection_name); 96 | void ReloadConfig (); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/DProxy.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Reflection; 7 | using System.Runtime.Remoting.Proxies; 8 | using System.Runtime.Remoting.Messaging; 9 | 10 | namespace DBus 11 | { 12 | using Protocol; 13 | 14 | //marked internal because this is really an implementation detail and needs to be replaced 15 | internal class DProxy : RealProxy 16 | { 17 | protected BusObject busObject; 18 | 19 | public DProxy (BusObject busObject, Type type) : base(type) 20 | { 21 | this.busObject = busObject; 22 | } 23 | 24 | static MethodInfo mi_GetHashCode = typeof (object).GetMethod ("GetHashCode"); 25 | static MethodInfo mi_Equals = typeof (object).GetMethod ("Equals", BindingFlags.Instance); 26 | static MethodInfo mi_ToString = typeof (object).GetMethod ("ToString"); 27 | static MethodInfo mi_GetLifetimeService = typeof (MarshalByRefObject).GetMethod ("GetLifetimeService"); 28 | 29 | object GetDefaultReturn (MethodBase mi, object[] inArgs) 30 | { 31 | if (mi == mi_GetHashCode) 32 | return busObject.Path.Value.GetHashCode (); 33 | if (mi == mi_Equals) 34 | return busObject.Path.Value == ((BusObject)((MarshalByRefObject)inArgs[0]).GetLifetimeService ()).Path.Value; 35 | if (mi == mi_ToString) 36 | return busObject.Path.Value; 37 | if (mi == mi_GetLifetimeService) 38 | return busObject; 39 | 40 | return null; 41 | } 42 | 43 | public override IMessage Invoke (IMessage message) 44 | { 45 | IMethodCallMessage callMessage = (IMethodCallMessage) message; 46 | 47 | object defaultRetVal = GetDefaultReturn (callMessage.MethodBase, callMessage.InArgs); 48 | if (defaultRetVal != null) { 49 | MethodReturnMessageWrapper defaultReturnMessage = new MethodReturnMessageWrapper ((IMethodReturnMessage) message); 50 | defaultReturnMessage.ReturnValue = defaultRetVal; 51 | 52 | return defaultReturnMessage; 53 | } 54 | 55 | object[] outArgs; 56 | object retVal; 57 | Exception exception; 58 | busObject.Invoke (callMessage.MethodBase, callMessage.MethodName, callMessage.InArgs, out outArgs, out retVal, out exception); 59 | 60 | MethodReturnMessageWrapper returnMessage = new MethodReturnMessageWrapper ((IMethodReturnMessage) message); 61 | returnMessage.Exception = exception; 62 | returnMessage.ReturnValue = retVal; 63 | 64 | return returnMessage; 65 | } 66 | 67 | ~DProxy () 68 | { 69 | //FIXME: remove handlers/match rules here 70 | if (ProtocolInformation.Verbose) 71 | Console.Error.WriteLine ("Warning: Finalization of " + busObject.Path + " not yet supported"); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Daemon.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | //#define USE_GLIB 6 | 7 | using System; 8 | using System.IO; 9 | using System.Text; 10 | 11 | using DBus; 12 | using DBus.Unix; 13 | 14 | public class DBusDaemon 15 | { 16 | public static void Main (string[] args) 17 | { 18 | string addr = "tcp:host=localhost,port=12345"; 19 | //string addr = "win:path=dbus-session"; 20 | 21 | bool shouldFork = false; 22 | 23 | for (int i = 0; i != args.Length; i++) { 24 | string arg = args[i]; 25 | //Console.Error.WriteLine ("arg: " + arg); 26 | 27 | /* 28 | if (!arg.StartsWith ("--")) { 29 | addr = arg; 30 | continue; 31 | } 32 | */ 33 | 34 | if (arg.StartsWith ("--print-")) { 35 | string[] parts = arg.Split('='); 36 | int fd = 1; 37 | if (parts.Length > 1) 38 | fd = Int32.Parse (parts[1]); 39 | else if (args.Length > i + 1) { 40 | string poss = args[i + 1]; 41 | if (Int32.TryParse (poss, out fd)) 42 | i++; 43 | } 44 | 45 | TextWriter tw; 46 | if (fd == 1) { 47 | tw = Console.Out; 48 | } else if (fd == 2) { 49 | tw = Console.Error; 50 | } else { 51 | Stream fs = new UnixStream (fd); 52 | tw = new StreamWriter (fs, Encoding.ASCII); 53 | tw.NewLine = "\n"; 54 | } 55 | 56 | if (parts[0] == "--print-address") 57 | tw.WriteLine (addr); 58 | //else if (parts[0] == "--print-pid") { 59 | // int pid = System.Diagnostics.Process.GetCurrentProcess ().Id; ; 60 | // tw.WriteLine (pid); 61 | //} 62 | else 63 | continue; 64 | //throw new Exception (); 65 | 66 | tw.Flush (); 67 | continue; 68 | } 69 | 70 | switch (arg) { 71 | case "--version": 72 | //Console.WriteLine ("D-Bus Message Bus Daemon " + Introspector.GetProductDescription ()); 73 | Console.WriteLine ("D-Bus Message Bus Daemon " + "0.1"); 74 | return; 75 | case "--system": 76 | break; 77 | case "--session": 78 | break; 79 | case "--fork": 80 | shouldFork = true; 81 | break; 82 | case "--introspect": 83 | { 84 | Introspector intro = new Introspector (); 85 | intro.root_path = ObjectPath.Root; 86 | intro.WriteStart (); 87 | intro.WriteType (typeof (org.freedesktop.DBus.IBus)); 88 | intro.WriteEnd (); 89 | 90 | Console.WriteLine (intro.xml); 91 | } 92 | return; 93 | default: 94 | break; 95 | } 96 | } 97 | 98 | /* 99 | if (args.Length >= 1) { 100 | addr = args[0]; 101 | } 102 | */ 103 | 104 | int childPid; 105 | if (shouldFork) { 106 | childPid = (int)UnixSocket.fork (); 107 | //if (childPid != 0) 108 | // return; 109 | } else 110 | childPid = System.Diagnostics.Process.GetCurrentProcess ().Id; 111 | 112 | if (childPid != 0) { 113 | for (int i = 0; i != args.Length; i++) { 114 | string arg = args[i]; 115 | //Console.Error.WriteLine ("arg: " + arg); 116 | 117 | /* 118 | if (!arg.StartsWith ("--")) { 119 | addr = arg; 120 | continue; 121 | } 122 | */ 123 | 124 | if (arg.StartsWith ("--print-")) { 125 | string[] parts = arg.Split ('='); 126 | int fd = 1; 127 | if (parts.Length > 1) 128 | fd = Int32.Parse (parts[1]); 129 | else if (args.Length > i + 1) { 130 | string poss = args[i + 1]; 131 | if (Int32.TryParse (poss, out fd)) 132 | i++; 133 | } 134 | 135 | TextWriter tw; 136 | if (fd == 1) { 137 | tw = Console.Out; 138 | } else if (fd == 2) { 139 | tw = Console.Error; 140 | } else { 141 | Stream fs = new UnixStream (fd); 142 | tw = new StreamWriter (fs, Encoding.ASCII); 143 | tw.NewLine = "\n"; 144 | } 145 | 146 | //if (parts[0] == "--print-address") 147 | // tw.WriteLine (addr); 148 | if (parts[0] == "--print-pid") { 149 | int pid = childPid; 150 | tw.WriteLine (pid); 151 | } 152 | 153 | tw.Flush (); 154 | continue; 155 | } 156 | } 157 | 158 | } 159 | 160 | if (shouldFork && childPid != 0) { 161 | return; 162 | //Environment.Exit (1); 163 | } 164 | 165 | 166 | //if (shouldFork && childPid == 0) { 167 | if (shouldFork) { 168 | 169 | /* 170 | Console.In.Dispose (); 171 | Console.Out.Dispose (); 172 | Console.Error.Dispose (); 173 | */ 174 | 175 | 176 | int O_RDWR = 2; 177 | int devnull = UnixSocket.open ("/dev/null", O_RDWR); 178 | 179 | UnixSocket.dup2 (devnull, 0); 180 | UnixSocket.dup2 (devnull, 1); 181 | UnixSocket.dup2 (devnull, 2); 182 | 183 | //UnixSocket.close (0); 184 | //UnixSocket.close (1); 185 | //UnixSocket.close (2); 186 | 187 | if (UnixSocket.setsid () == (IntPtr) (-1)) 188 | throw new Exception (); 189 | } 190 | 191 | RunServer (addr); 192 | 193 | 194 | //Console.Error.WriteLine ("Usage: dbus-daemon [address]"); 195 | } 196 | 197 | static void RunServer (string addr) 198 | { 199 | Server serv = Server.ListenAt (addr); 200 | 201 | ServerBus sbus = new ServerBus (); 202 | 203 | string activationEnv = Environment.GetEnvironmentVariable ("DBUS_ACTIVATION"); 204 | if (activationEnv == "1") { 205 | sbus.ScanServices (); 206 | sbus.allowActivation = true; 207 | } 208 | 209 | sbus.server = serv; 210 | serv.SBus = sbus; 211 | serv.NewConnection += sbus.AddConnection; 212 | 213 | #if USE_GLIB 214 | new Thread (new ThreadStart (serv.Listen)).Start (); 215 | //GLib.Idle.Add (delegate { serv.Listen (); return false; }); 216 | GLib.MainLoop main = new GLib.MainLoop (); 217 | main.Run (); 218 | #else 219 | serv.Listen (); 220 | #endif 221 | } 222 | } -------------------------------------------------------------------------------- /src/DisposableList.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Steffen Kiess 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | namespace DBus 10 | { 11 | public class DisposableList : IDisposable 12 | { 13 | List list = new List (); 14 | 15 | public void Dispose () 16 | { 17 | lock (list) { 18 | foreach (var obj in list) 19 | obj.Dispose (); 20 | } 21 | } 22 | 23 | public void Add (IDisposable obj) 24 | { 25 | if (obj == null) 26 | throw new ArgumentNullException ("obj"); 27 | 28 | list.Add (obj); 29 | } 30 | } 31 | } 32 | 33 | // Local Variables: 34 | // tab-width: 4 35 | // c-basic-offset: 4 36 | // indent-tabs-mode: t 37 | // End: 38 | -------------------------------------------------------------------------------- /src/ExportObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Linq; 7 | using System.Collections.Generic; 8 | using System.Reflection; 9 | using System.Reflection.Emit; 10 | 11 | using org.freedesktop.DBus; 12 | 13 | namespace DBus 14 | { 15 | using Protocol; 16 | 17 | //TODO: perhaps ExportObject should not derive from BusObject 18 | internal class ExportObject : BusObject, IDisposable 19 | { 20 | //maybe add checks to make sure this is not called more than once 21 | //it's a bit silly as a property 22 | bool isRegistered = false; 23 | Dictionary methodInfoCache = new Dictionary (); 24 | 25 | static readonly Dictionary mCallers = new Dictionary (); 26 | 27 | public ExportObject (Connection conn, ObjectPath object_path, object obj) : base (conn, null, object_path) 28 | { 29 | Object = obj; 30 | } 31 | 32 | public virtual bool Registered 33 | { 34 | get { 35 | return isRegistered; 36 | } 37 | set { 38 | if (value == isRegistered) 39 | return; 40 | 41 | Type type = Object.GetType (); 42 | 43 | foreach (var memberForType in Mapper.GetPublicMembers (type)) { 44 | MemberInfo mi = memberForType.Value; 45 | EventInfo ei = mi as EventInfo; 46 | 47 | if (ei == null) 48 | continue; 49 | 50 | Delegate dlg = GetHookupDelegate (ei); 51 | 52 | if (value) 53 | ei.AddEventHandler (Object, dlg); 54 | else 55 | ei.RemoveEventHandler (Object, dlg); 56 | } 57 | 58 | isRegistered = value; 59 | } 60 | } 61 | 62 | internal virtual void WriteIntrospect (Introspector intro) 63 | { 64 | intro.WriteType (Object.GetType ()); 65 | } 66 | 67 | internal static MethodCaller GetMCaller (MethodInfo mi) 68 | { 69 | MethodCaller mCaller; 70 | if (!mCallers.TryGetValue (mi, out mCaller)) { 71 | mCaller = TypeImplementer.GenCaller (mi); 72 | mCallers[mi] = mCaller; 73 | } 74 | return mCaller; 75 | } 76 | 77 | public static ExportObject CreateExportObject (Connection conn, ObjectPath object_path, object obj) 78 | { 79 | return new ExportObject (conn, object_path, obj); 80 | } 81 | 82 | public virtual void HandleMethodCall (MessageContainer method_call) 83 | { 84 | MethodInfo mi; 85 | if (!methodInfoCache.TryGetValue (method_call.Member, out mi)) 86 | methodInfoCache[method_call.Member] = mi = Mapper.GetMethod (Object.GetType (), method_call); 87 | 88 | if (mi == null) { 89 | conn.MaybeSendUnknownMethodError (method_call); 90 | return; 91 | } 92 | 93 | MethodCaller mCaller; 94 | if (!mCallers.TryGetValue (mi, out mCaller)) { 95 | mCaller = TypeImplementer.GenCaller (mi); 96 | mCallers[mi] = mCaller; 97 | } 98 | 99 | Signature inSig, outSig; 100 | bool hasDisposableList; 101 | TypeImplementer.SigsForMethod (mi, out inSig, out outSig, out hasDisposableList); 102 | 103 | Message msg = method_call.Message; 104 | MessageReader msgReader = new MessageReader (msg); 105 | MessageWriter retWriter = new MessageWriter (); 106 | 107 | using (var disposableList = new DisposableList ()) { 108 | 109 | Exception raisedException = null; 110 | try { 111 | mCaller (Object, msgReader, msg, retWriter, disposableList); 112 | } catch (Exception e) { 113 | raisedException = e; 114 | } 115 | 116 | if (!msg.ReplyExpected) 117 | return; 118 | 119 | Message replyMsg; 120 | 121 | if (raisedException == null) { 122 | MessageContainer method_return = new MessageContainer { 123 | Type = MessageType.MethodReturn, 124 | ReplySerial = msg.Header.Serial 125 | }; 126 | replyMsg = method_return.Message; 127 | replyMsg.AttachBodyTo (retWriter); 128 | replyMsg.Signature = outSig; 129 | } else { 130 | // BusException allows precisely formatted Error messages. 131 | BusException busException = raisedException as BusException; 132 | if (busException != null) 133 | replyMsg = method_call.CreateError (busException.ErrorName, busException.ErrorMessage); 134 | else if (raisedException is ArgumentException && raisedException.TargetSite.Name == mi.Name) { 135 | // Name match trick above is a hack since we don't have the resolved MethodInfo. 136 | ArgumentException argException = (ArgumentException)raisedException; 137 | using (System.IO.StringReader sr = new System.IO.StringReader (argException.Message)) { 138 | replyMsg = method_call.CreateError ("org.freedesktop.DBus.Error.InvalidArgs", sr.ReadLine ()); 139 | } 140 | } else 141 | replyMsg = method_call.CreateError (Mapper.GetInterfaceName (raisedException.GetType ()), raisedException.Message); 142 | } 143 | 144 | if (method_call.Sender != null) 145 | replyMsg.Header[FieldCode.Destination] = method_call.Sender; 146 | 147 | conn.Send (replyMsg); 148 | } 149 | } 150 | 151 | public object Object { 152 | get; 153 | private set; 154 | } 155 | 156 | public void Dispose () 157 | { 158 | Dispose (true); 159 | GC.SuppressFinalize (this); 160 | } 161 | 162 | ~ExportObject () 163 | { 164 | Dispose (false); 165 | } 166 | 167 | protected virtual void Dispose (bool disposing) 168 | { 169 | if (disposing) { 170 | if (Object != null) { 171 | Registered = false; 172 | Object = null; 173 | } 174 | } 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | ASSEMBLY = dbus-sharp 2 | TARGET = $(ASSEMBLY).dll 3 | XBUILD_Q = $(XBUILD) /nologo /verbosity:quiet 4 | 5 | # Use the gencssources script to generate this list 6 | CSFILES = Address.cs \ 7 | Authentication.cs \ 8 | Bus.cs \ 9 | BusObject.cs \ 10 | Connection.cs \ 11 | DBus.cs \ 12 | DisposableList.cs \ 13 | DProxy.cs \ 14 | ExportObject.cs \ 15 | Introspection.cs \ 16 | Mapper.cs \ 17 | TypeImplementer.cs \ 18 | ArgDirection.cs \ 19 | ObjectPath.cs \ 20 | OSHelpers.cs \ 21 | BusException.cs \ 22 | AddressEntry.cs \ 23 | UnixFD.cs \ 24 | Protocol/DBusStruct.cs \ 25 | Protocol/DType.cs \ 26 | Protocol/DValue.cs \ 27 | Protocol/EndianFlag.cs \ 28 | Protocol/FieldCode.cs \ 29 | Protocol/Header.cs \ 30 | Protocol/HeaderFlag.cs \ 31 | Protocol/MatchRule.cs \ 32 | Protocol/Message.cs \ 33 | Protocol/MessageContainer.cs \ 34 | Protocol/MessageDumper.cs \ 35 | Protocol/MessageFilter.cs \ 36 | Protocol/MessageReader.cs \ 37 | Protocol/MessageType.cs \ 38 | Protocol/MessageWriter.cs \ 39 | Protocol/PendingCall.cs \ 40 | Protocol/ProtocolInformation.cs \ 41 | Protocol/Signature.cs \ 42 | Protocol/SocketTransport.cs \ 43 | Protocol/Transport.cs \ 44 | Protocol/UnixFDArray.cs \ 45 | Transports/UnixNativeTransport.cs \ 46 | Transports/UnixSendmsgTransport.cs \ 47 | Transports/UnixTransport.cs \ 48 | Unix/UnixStream.cs \ 49 | Unix/UnixMonoStream.cs \ 50 | Unix/UnixError.cs \ 51 | Unix/UnixSocket.cs \ 52 | AssemblyInfo.cs 53 | 54 | all: $(TARGET) 55 | 56 | $(TARGET): $(CSFILES) AssemblyInfo.cs 57 | $(XBUILD_Q) dbus-sharp.csproj 58 | 59 | install-data-local: $(TARGET) 60 | @if test -n '$(TARGET)'; then \ 61 | echo "$(GACUTIL) /i $(TARGET) /package $(PACKAGE)-$(API_VERSION) /f /gacdir $(libdir) /root $(DESTDIR)$(libdir)"; \ 62 | $(GACUTIL) /i $(TARGET) /package $(PACKAGE)-$(API_VERSION) /f /gacdir $(libdir) /root $(DESTDIR)$(libdir) || exit 1; \ 63 | fi 64 | 65 | uninstall-local: 66 | @if test -n '$(TARGET)'; then \ 67 | echo "$(GACUTIL) /u $(ASSEMBLY) /package $(PACKAGE)-$(API_VERSION) /gacdir $(libdir) /root $(DESTDIR)$(libdir)"; \ 68 | $(GACUTIL) /u $(ASSEMBLY) /package $(PACKAGE)-$(API_VERSION) /gacdir $(libdir) /root $(DESTDIR)$(libdir) || exit 1; \ 69 | fi 70 | 71 | .PHONY: $(TARGET) 72 | 73 | EXTRA_DIST = \ 74 | $(CSFILES) \ 75 | $(srcdir)/dbus-sharp.dll.config \ 76 | $(srcdir)/AssemblyInfo.cs.in \ 77 | $(srcdir)/dbus-sharp.csproj 78 | 79 | CLEANFILES = \ 80 | $(TARGET) \ 81 | $(TARGET).mdb 82 | 83 | DISTCLEANFILES = \ 84 | AssemblyInfo.cs 85 | 86 | MAINTAINERCLEANFILES = \ 87 | Makefile.in 88 | -------------------------------------------------------------------------------- /src/OSHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | #if !NET35 4 | using System.IO.MemoryMappedFiles; 5 | #endif 6 | 7 | namespace DBus 8 | { 9 | internal class OSHelpers 10 | { 11 | 12 | static PlatformID platformid = Environment.OSVersion.Platform; 13 | 14 | public static bool PlatformIsUnixoid 15 | { 16 | get { 17 | switch (platformid) { 18 | case PlatformID.Win32S: return false; 19 | case PlatformID.Win32Windows: return false; 20 | case PlatformID.Win32NT: return false; 21 | case PlatformID.WinCE: return false; 22 | case PlatformID.Unix: return true; 23 | case PlatformID.Xbox: return false; 24 | case PlatformID.MacOSX: return true; 25 | default: return false; 26 | } 27 | } 28 | } 29 | 30 | // Reads a string from shared memory with the ID "id". 31 | // Optionally, a maximum length can be specified. A negative number means "no limit". 32 | public static string ReadSharedMemoryString (string id, long maxlen = -1) 33 | { 34 | #if !NET35 35 | MemoryMappedFile shmem; 36 | try { 37 | shmem = MemoryMappedFile.OpenExisting (id); 38 | } catch { 39 | shmem = null; 40 | } 41 | if (shmem == null) 42 | return null; 43 | MemoryMappedViewStream s = shmem.CreateViewStream (); 44 | long len = s.Length; 45 | if (maxlen >= 0 && len > maxlen) 46 | len = maxlen; 47 | if (len == 0) 48 | return string.Empty; 49 | if (len > Int32.MaxValue) 50 | len = Int32.MaxValue; 51 | byte[] bytes = new byte[len]; 52 | int count = s.Read (bytes, 0, (int)len); 53 | if (count <= 0) 54 | return string.Empty; 55 | 56 | count = 0; 57 | while (count < len && bytes[count] != 0) 58 | count++; 59 | 60 | return System.Text.Encoding.UTF8.GetString (bytes, 0, count); 61 | #else 62 | return null; 63 | #endif 64 | } 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/ObjectPath.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | 9 | namespace DBus 10 | { 11 | public sealed class ObjectPath : IComparable, IComparable, IEquatable 12 | { 13 | public static readonly ObjectPath Root = new ObjectPath ("/"); 14 | 15 | internal readonly string Value; 16 | 17 | public ObjectPath (string value) 18 | { 19 | if (value == null) 20 | throw new ArgumentNullException ("value"); 21 | 22 | Validate (value); 23 | 24 | this.Value = value; 25 | } 26 | 27 | static void Validate (string value) 28 | { 29 | if (!value.StartsWith ("/")) 30 | throw new ArgumentException ("value"); 31 | if (value.EndsWith ("/") && value.Length > 1) 32 | throw new ArgumentException ("ObjectPath cannot end in '/'"); 33 | 34 | bool multipleSlash = false; 35 | 36 | foreach (char c in value) { 37 | bool valid = (c >= 'a' && c <='z') 38 | || (c >= 'A' && c <= 'Z') 39 | || (c >= '0' && c <= '9') 40 | || c == '_' 41 | || (!multipleSlash && c == '/'); 42 | 43 | if (!valid) { 44 | var message = string.Format ("'{0}' is not a valid character in an ObjectPath", c); 45 | throw new ArgumentException (message, "value"); 46 | } 47 | 48 | multipleSlash = c == '/'; 49 | } 50 | 51 | } 52 | 53 | public int CompareTo (ObjectPath other) 54 | { 55 | if (other == null) 56 | return 1; 57 | 58 | return Value.CompareTo (other.Value); 59 | } 60 | 61 | public int CompareTo (object otherObject) 62 | { 63 | ObjectPath other = otherObject as ObjectPath; 64 | 65 | if (other == null) 66 | return 1; 67 | 68 | return Value.CompareTo (other.Value); 69 | } 70 | 71 | public bool Equals (ObjectPath other) 72 | { 73 | if (other == null) 74 | return false; 75 | 76 | return Value == other.Value; 77 | } 78 | 79 | public override bool Equals (object o) 80 | { 81 | ObjectPath b = o as ObjectPath; 82 | 83 | if (b == null) 84 | return false; 85 | 86 | return Value.Equals (b.Value); 87 | } 88 | 89 | public static bool operator == (ObjectPath a, ObjectPath b) 90 | { 91 | object aa = a, bb = b; 92 | if (aa == null && bb == null) 93 | return true; 94 | 95 | if (aa == null || bb == null) 96 | return false; 97 | 98 | return a.Value == b.Value; 99 | } 100 | 101 | public static bool operator != (ObjectPath a, ObjectPath b) 102 | { 103 | return !(a == b); 104 | } 105 | 106 | public override int GetHashCode () 107 | { 108 | return Value.GetHashCode (); 109 | } 110 | 111 | public override string ToString () 112 | { 113 | return Value; 114 | } 115 | 116 | //this may or may not prove useful 117 | internal string[] Decomposed 118 | { 119 | get { 120 | return Value.Split (new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries); 121 | /* 122 | } set { 123 | Value = String.Join ("/", value); 124 | */ 125 | } 126 | } 127 | 128 | internal ObjectPath Parent 129 | { 130 | get { 131 | if (Value == Root.Value) 132 | return null; 133 | 134 | string par = Value.Substring (0, Value.LastIndexOf ('/')); 135 | if (par == String.Empty) 136 | par = "/"; 137 | 138 | return new ObjectPath (par); 139 | } 140 | } 141 | 142 | /* 143 | public int CompareTo (object value) 144 | { 145 | return 1; 146 | } 147 | 148 | public int CompareTo (ObjectPath value) 149 | { 150 | return 1; 151 | } 152 | 153 | public bool Equals (ObjectPath value) 154 | { 155 | return false; 156 | } 157 | */ 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/Protocol/DBusStruct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace DBus.Protocol 5 | { 6 | /* We use these structs when we receive a struct from D-Bus without 7 | * knowing which .NET type they are supposed to map to 8 | * The case arises basically when a struct is inside a variant object 9 | */ 10 | public static class DBusStruct 11 | { 12 | public static Type FromInnerTypes (Type[] innerTypes) 13 | { 14 | // We only support up to 7 inner types 15 | if (innerTypes == null || innerTypes.Length == 0 || innerTypes.Length > 7) 16 | throw new NotSupportedException ("Can't create a valid type for the provided signature"); 17 | 18 | Type structType = null; 19 | switch (innerTypes.Length) { 20 | case 1: 21 | structType = typeof (DBusStruct<>); 22 | break; 23 | case 2: 24 | structType = typeof (DBusStruct<,>); 25 | break; 26 | case 3: 27 | structType = typeof (DBusStruct<,,>); 28 | break; 29 | case 4: 30 | structType = typeof (DBusStruct<,,,>); 31 | break; 32 | case 5: 33 | structType = typeof (DBusStruct<,,,,>); 34 | break; 35 | case 6: 36 | structType = typeof (DBusStruct<,,,,,>); 37 | break; 38 | case 7: 39 | structType = typeof (DBusStruct<,,,,,,>); 40 | break; 41 | } 42 | return structType.MakeGenericType (innerTypes); 43 | } 44 | } 45 | 46 | public struct DBusStruct 47 | { 48 | public T1 Item1; 49 | } 50 | 51 | public struct DBusStruct 52 | { 53 | public T1 Item1; 54 | public T2 Item2; 55 | } 56 | 57 | public struct DBusStruct 58 | { 59 | public T1 Item1; 60 | public T2 Item2; 61 | public T3 Item3; 62 | } 63 | 64 | public struct DBusStruct 65 | { 66 | public T1 Item1; 67 | public T2 Item2; 68 | public T3 Item3; 69 | public T4 Item4; 70 | } 71 | 72 | public struct DBusStruct 73 | { 74 | public T1 Item1; 75 | public T2 Item2; 76 | public T3 Item3; 77 | public T4 Item4; 78 | public T5 Item5; 79 | } 80 | 81 | public struct DBusStruct 82 | { 83 | public T1 Item1; 84 | public T2 Item2; 85 | public T3 Item3; 86 | public T4 Item4; 87 | public T5 Item5; 88 | public T6 Item6; 89 | } 90 | 91 | public struct DBusStruct 92 | { 93 | public T1 Item1; 94 | public T2 Item2; 95 | public T3 Item3; 96 | public T4 Item4; 97 | public T5 Item5; 98 | public T6 Item6; 99 | public T7 Item7; 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /src/Protocol/DType.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern s 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | 8 | namespace DBus.Protocol 9 | { 10 | public enum DType : byte 11 | { 12 | Invalid = (byte)'\0', 13 | 14 | Byte = (byte)'y', 15 | Boolean = (byte)'b', 16 | Int16 = (byte)'n', 17 | UInt16 = (byte)'q', 18 | Int32 = (byte)'i', 19 | UInt32 = (byte)'u', 20 | Int64 = (byte)'x', 21 | UInt64 = (byte)'t', 22 | Single = (byte)'f', //This is not yet supported! 23 | Double = (byte)'d', 24 | String = (byte)'s', 25 | ObjectPath = (byte)'o', 26 | Signature = (byte)'g', 27 | UnixFD = (byte)'h', 28 | 29 | Array = (byte)'a', 30 | Variant = (byte)'v', 31 | 32 | StructBegin = (byte)'(', 33 | StructEnd = (byte)')', 34 | DictEntryBegin = (byte)'{', 35 | DictEntryEnd = (byte)'}', 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Protocol/DValue.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | namespace DBus.Protocol 10 | { 11 | // Allows conversion of complex variants via System.Convert 12 | class DValue : IConvertible 13 | { 14 | // TODO: Note that we currently drop the originating Connection/Message details 15 | // They may be useful later in conversion! 16 | 17 | internal EndianFlag endianness; 18 | internal Signature signature; 19 | internal byte[] data; 20 | 21 | public DValue (EndianFlag endianness, byte[] data) 22 | { 23 | this.endianness = endianness; 24 | this.data = data; 25 | } 26 | 27 | public bool CanConvertTo (Type conversionType) 28 | { 29 | Signature typeSig = Signature.GetSig (conversionType); 30 | return signature == typeSig; 31 | } 32 | 33 | public TypeCode GetTypeCode () 34 | { 35 | return TypeCode.Object; 36 | } 37 | 38 | public object ToType (Type conversionType) 39 | { 40 | return ToType (conversionType, null); 41 | } 42 | 43 | public object ToType (Type conversionType, IFormatProvider provider) 44 | { 45 | Signature typeSig = Signature.GetSig (conversionType); 46 | if (typeSig != signature) 47 | throw new InvalidCastException (); 48 | 49 | MessageReader reader = new MessageReader (endianness, data); 50 | return reader.ReadValue (conversionType); 51 | } 52 | 53 | public override string ToString () 54 | { 55 | // Seems a reasonable way of providing the signature to the API layer 56 | return signature.ToString (); 57 | } 58 | 59 | // IConvertible implementation: 60 | 61 | /* 62 | public TypeCode GetTypeCode () 63 | { 64 | throw new NotSupportedException (); 65 | } 66 | */ 67 | 68 | public bool ToBoolean (IFormatProvider provider) 69 | { 70 | throw new NotSupportedException (); 71 | } 72 | 73 | public byte ToByte (IFormatProvider provider) 74 | { 75 | throw new NotSupportedException (); 76 | } 77 | 78 | public char ToChar (IFormatProvider provider) 79 | { 80 | throw new NotSupportedException (); 81 | } 82 | 83 | public DateTime ToDateTime (IFormatProvider provider) 84 | { 85 | throw new NotSupportedException (); 86 | } 87 | 88 | public decimal ToDecimal (IFormatProvider provider) 89 | { 90 | throw new NotSupportedException (); 91 | } 92 | 93 | public double ToDouble (IFormatProvider provider) 94 | { 95 | throw new NotSupportedException (); 96 | } 97 | 98 | public short ToInt16 (IFormatProvider provider) 99 | { 100 | throw new NotSupportedException (); 101 | } 102 | 103 | public int ToInt32 (IFormatProvider provider) 104 | { 105 | throw new NotSupportedException (); 106 | } 107 | 108 | public long ToInt64 (IFormatProvider provider) 109 | { 110 | throw new NotSupportedException (); 111 | } 112 | 113 | public sbyte ToSByte (IFormatProvider provider) 114 | { 115 | throw new NotSupportedException (); 116 | } 117 | 118 | public float ToSingle (IFormatProvider provider) 119 | { 120 | throw new NotSupportedException (); 121 | } 122 | 123 | public string ToString (IFormatProvider provider) 124 | { 125 | throw new NotSupportedException (); 126 | } 127 | 128 | public ushort ToUInt16 (IFormatProvider provider) 129 | { 130 | throw new NotSupportedException (); 131 | } 132 | 133 | public uint ToUInt32 (IFormatProvider provider) 134 | { 135 | throw new NotSupportedException (); 136 | } 137 | 138 | public ulong ToUInt64 (IFormatProvider provider) 139 | { 140 | throw new NotSupportedException (); 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /src/Protocol/EndianFlag.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | 8 | namespace DBus.Protocol 9 | { 10 | public enum EndianFlag : byte 11 | { 12 | Little = (byte)'l', 13 | Big = (byte)'B', 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Protocol/FieldCode.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | 8 | namespace DBus.Protocol 9 | { 10 | public enum FieldCode : byte 11 | { 12 | Invalid, 13 | Path, 14 | Interface, 15 | Member, 16 | ErrorName, 17 | ReplySerial, 18 | Destination, 19 | Sender, 20 | Signature, 21 | UnixFDs, 22 | #if PROTO_REPLY_SIGNATURE 23 | ReplySignature, //note: not supported in dbus 24 | #endif 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Protocol/Header.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | using System.IO; 8 | using System.Collections.Generic; 9 | 10 | namespace DBus.Protocol 11 | { 12 | public class Header 13 | { 14 | public EndianFlag Endianness; 15 | public MessageType MessageType; 16 | public HeaderFlag Flags; 17 | public byte MajorVersion; 18 | public uint Length; 19 | public uint Serial; 20 | 21 | Dictionary fields = new Dictionary (); 22 | 23 | public object this[FieldCode key] 24 | { 25 | get { 26 | object value = null; 27 | fields.TryGetValue ((byte)key, out value); 28 | return value; 29 | } 30 | set { 31 | if (value == null) 32 | fields.Remove((byte)key); 33 | else 34 | fields[(byte)key] = value; 35 | } 36 | } 37 | 38 | public bool TryGetField (FieldCode code, out object value) 39 | { 40 | return fields.TryGetValue ((byte)code, out value); 41 | } 42 | 43 | public int FieldsCount { 44 | get { 45 | return fields.Count; 46 | } 47 | } 48 | 49 | public static Header FromBytes (byte[] data) 50 | { 51 | Header header = new Header (); 52 | EndianFlag endianness = (EndianFlag)data[0]; 53 | 54 | header.Endianness = endianness; 55 | header.MessageType = (MessageType)data[1]; 56 | header.Flags = (HeaderFlag)data[2]; 57 | header.MajorVersion = data[3]; 58 | 59 | var reader = new MessageReader (endianness, data); 60 | reader.Seek (4); 61 | header.Length = reader.ReadUInt32 (); 62 | header.Serial = reader.ReadUInt32 (); 63 | 64 | FieldCodeEntry[] fields = reader.ReadArray (); 65 | foreach (var f in fields) { 66 | header[(FieldCode)f.Code] = f.Value; 67 | } 68 | 69 | return header; 70 | } 71 | 72 | public void GetHeaderDataToStream (Stream stream) 73 | { 74 | MessageWriter writer = new MessageWriter (Endianness); 75 | WriteHeaderToMessage (writer); 76 | writer.ToStream (stream); 77 | } 78 | 79 | internal void WriteHeaderToMessage (MessageWriter writer) 80 | { 81 | writer.Write ((byte)Endianness); 82 | writer.Write ((byte)MessageType); 83 | writer.Write ((byte)Flags); 84 | writer.Write (MajorVersion); 85 | writer.Write (Length); 86 | writer.Write (Serial); 87 | writer.WriteHeaderFields (fields); 88 | 89 | writer.CloseWrite (); 90 | } 91 | 92 | struct FieldCodeEntry 93 | { 94 | public byte Code; 95 | public object Value; 96 | } 97 | 98 | /* 99 | public static DType TypeForField (FieldCode f) 100 | { 101 | switch (f) { 102 | case FieldCode.Invalid: 103 | return DType.Invalid; 104 | case FieldCode.Path: 105 | return DType.ObjectPath; 106 | case FieldCode.Interface: 107 | return DType.String; 108 | case FieldCode.Member: 109 | return DType.String; 110 | case FieldCode.ErrorName: 111 | return DType.String; 112 | case FieldCode.ReplySerial: 113 | return DType.UInt32; 114 | case FieldCode.Destination: 115 | return DType.String; 116 | case FieldCode.Sender: 117 | return DType.String; 118 | case FieldCode.Signature: 119 | return DType.Signature; 120 | #if PROTO_REPLY_SIGNATURE 121 | case FieldCode.ReplySignature: //note: not supported in dbus 122 | return DType.Signature; 123 | #endif 124 | default: 125 | return DType.Invalid; 126 | } 127 | } 128 | */ 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Protocol/HeaderFlag.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | 8 | namespace DBus.Protocol 9 | { 10 | [Flags] 11 | public enum HeaderFlag : byte 12 | { 13 | None = 0, 14 | NoReplyExpected = 0x1, 15 | NoAutoStart = 0x2, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Protocol/Message.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | namespace DBus.Protocol 10 | { 11 | public class Message : IDisposable 12 | { 13 | Header header = new Header (); 14 | Connection connection; 15 | byte[] body; 16 | UnixFDArray fdArray; 17 | 18 | public Message () 19 | { 20 | header.Endianness = Connection.NativeEndianness; 21 | header.MessageType = MessageType.MethodCall; 22 | header.Flags = HeaderFlag.NoReplyExpected; //TODO: is this the right place to do this? 23 | header.MajorVersion = ProtocolInformation.Version; 24 | } 25 | 26 | public static Message FromReceivedBytes (Connection connection, byte[] header, byte[] body) 27 | { 28 | return FromReceivedBytes (connection, header, body, null); 29 | } 30 | 31 | public static Message FromReceivedBytes (Connection connection, byte[] header, byte[] body, UnixFDArray fdArray) 32 | { 33 | Message message = new Message (); 34 | message.connection = connection; 35 | message.body = body; 36 | message.fdArray = fdArray; 37 | message.SetHeaderData (header); 38 | 39 | return message; 40 | } 41 | 42 | public byte[] Body { 43 | get { 44 | return body; 45 | } 46 | } 47 | 48 | public UnixFDArray UnixFDArray { 49 | get { 50 | return fdArray; 51 | } 52 | } 53 | 54 | public Header Header { 55 | get { 56 | return header; 57 | } 58 | } 59 | 60 | public Connection Connection { 61 | get { 62 | return connection; 63 | } 64 | } 65 | 66 | public Signature Signature { 67 | get { 68 | object o = Header[FieldCode.Signature]; 69 | if (o == null) 70 | return Signature.Empty; 71 | else 72 | return (Signature)o; 73 | } 74 | set { 75 | if (value == Signature.Empty) 76 | Header[FieldCode.Signature] = null; 77 | else 78 | Header[FieldCode.Signature] = value; 79 | } 80 | } 81 | 82 | public bool ReplyExpected { 83 | get { 84 | return (Header.Flags & HeaderFlag.NoReplyExpected) == HeaderFlag.None; 85 | } 86 | set { 87 | if (value) 88 | Header.Flags &= ~HeaderFlag.NoReplyExpected; //flag off 89 | else 90 | Header.Flags |= HeaderFlag.NoReplyExpected; //flag on 91 | } 92 | } 93 | 94 | public void AttachBodyTo (MessageWriter writer) 95 | { 96 | body = writer.ToArray (); 97 | header.Length = (uint)body.Length; 98 | if (writer.fdArray.FDs.Count != 0) { 99 | header[FieldCode.UnixFDs] = (uint) writer.fdArray.FDs.Count; 100 | if (fdArray == null) 101 | fdArray = new UnixFDArray (); 102 | foreach (var fd in writer.fdArray.FDs) 103 | fdArray.FDs.Add (fd); 104 | } 105 | } 106 | 107 | public void HandleHeader (Header headerIn) 108 | { 109 | header = headerIn; 110 | } 111 | 112 | public void SetHeaderData (byte[] data) 113 | { 114 | header = Header.FromBytes (data); 115 | } 116 | 117 | public byte[] GetHeaderData () 118 | { 119 | MessageWriter writer = new MessageWriter (header.Endianness); 120 | header.WriteHeaderToMessage (writer); 121 | return writer.ToArray (); 122 | } 123 | 124 | public void Dispose () 125 | { 126 | if (UnixFDArray != null) 127 | UnixFDArray.Dispose (); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Protocol/MessageContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | namespace DBus.Protocol 10 | { 11 | public class MessageContainer 12 | { 13 | Message resultMessage; 14 | 15 | public MessageContainer () 16 | { 17 | Type = MessageType.MethodCall; 18 | } 19 | 20 | MessageContainer (Message originalMessage) 21 | { 22 | this.resultMessage = originalMessage; 23 | } 24 | 25 | public Message Message { 26 | get { 27 | if (resultMessage != null) 28 | return resultMessage; 29 | return resultMessage = ExportToMessage (); 30 | } 31 | } 32 | 33 | public Message CreateError (string errorName, string errorMessage) 34 | { 35 | var message = Message; 36 | MessageContainer error = new MessageContainer { 37 | Type = MessageType.Error, 38 | ErrorName = errorName, 39 | ReplySerial = message.Header.Serial, 40 | Signature = Signature.StringSig, 41 | Destination = Sender 42 | }; 43 | 44 | MessageWriter writer = new MessageWriter (message.Header.Endianness); 45 | writer.Write (errorMessage); 46 | message = error.Message; 47 | message.AttachBodyTo (writer); 48 | 49 | return message; 50 | } 51 | 52 | public static MessageContainer FromMessage (Message message) 53 | { 54 | MessageContainer container = new MessageContainer (message) { 55 | Path = (ObjectPath)message.Header[FieldCode.Path], 56 | Interface = (string)message.Header[FieldCode.Interface], 57 | Member = (string)message.Header[FieldCode.Member], 58 | Destination = (string)message.Header[FieldCode.Destination], 59 | //TODO: filled by the bus so reliable, but not the case for p2p 60 | //so we make it optional here, but this needs some more thought 61 | //if (message.Header.Fields.ContainsKey (FieldCode.Sender)) 62 | Sender = (string)message.Header[FieldCode.Sender], 63 | ErrorName = (string)message.Header[FieldCode.ErrorName], 64 | ReplySerial = (uint?)message.Header[FieldCode.ReplySerial], 65 | Signature = message.Signature, 66 | Serial = message.Header.Serial, 67 | Type = message.Header.MessageType, 68 | }; 69 | #if PROTO_REPLY_SIGNATURE 70 | //TODO: note that an empty ReplySignature should really be treated differently to the field not existing! 71 | if (message.Header.Fields.ContainsKey (FieldCode.ReplySignature)) 72 | container.ReplySignature = (Signature)message.Header[FieldCode.ReplySignature]; 73 | else 74 | container.ReplySignature = Signature.Empty; 75 | #endif 76 | 77 | return container; 78 | } 79 | 80 | Message ExportToMessage () { 81 | var message = new Message (); 82 | message.Header.MessageType = Type; 83 | if (Type == MessageType.MethodCall) 84 | message.ReplyExpected = true; 85 | else 86 | message.Header.Flags = HeaderFlag.NoReplyExpected | HeaderFlag.NoAutoStart; 87 | message.Header[FieldCode.Path] = Path; 88 | message.Header[FieldCode.Interface] = Interface; 89 | message.Header[FieldCode.Member] = Member; 90 | message.Header[FieldCode.Destination] = Destination; 91 | message.Header[FieldCode.ErrorName] = ErrorName; 92 | #if PROTO_REPLY_SIGNATURE 93 | //TODO 94 | #endif 95 | message.Signature = Signature; 96 | if (ReplySerial != null) 97 | message.Header[FieldCode.ReplySerial] = (uint)ReplySerial; 98 | if (Serial != null) 99 | message.Header.Serial = (uint)Serial; 100 | 101 | return message; 102 | } 103 | 104 | public MessageType Type { 105 | get; 106 | set; 107 | } 108 | 109 | public ObjectPath Path { 110 | get; 111 | set; 112 | } 113 | 114 | public string Interface { 115 | get; 116 | set; 117 | } 118 | 119 | public string Member { 120 | get; 121 | set; 122 | } 123 | 124 | public string Destination { 125 | get; 126 | set; 127 | } 128 | 129 | public string Sender { 130 | get; 131 | set; 132 | } 133 | 134 | #if PROTO_REPLY_SIGNATURE 135 | public Signature ReplySignature { 136 | get; 137 | set; 138 | } 139 | #endif 140 | 141 | public uint? ReplySerial { 142 | get; 143 | set; 144 | } 145 | 146 | public uint? Serial { 147 | get; 148 | set; 149 | } 150 | 151 | public Signature Signature { 152 | get; 153 | set; 154 | } 155 | 156 | public string ErrorName { 157 | get; 158 | set; 159 | } 160 | 161 | /*public override bool Equals (object other) 162 | { 163 | MessageContainer otherMethodCall = other as MessageContainer; 164 | return otherMethodCall == null ? false : Equals (otherMethodCall); 165 | } 166 | 167 | public bool Equals (MessageContainer other) 168 | { 169 | return (Path == other.Path || Path.Equals (other.Path)) 170 | && Interface == other.Interface 171 | && Member == other.Member 172 | && Destination == other.Destination 173 | && Sender == other.Destination 174 | && ErrorName == other.ErrorName 175 | && Signature.Equals (other.Signature) 176 | && ReplySerial.Equals (other.ReplySerial); 177 | } 178 | 179 | public override int GetHashCode () 180 | { 181 | return (Path == null ? 0 : Path.GetHashCode ()) 182 | ^ (Interface == null ? 0 : Interface.GetHashCode ()) 183 | ^ (Member == null ? 0 : Member.GetHashCode ()) 184 | ^ (Destination == null ? 0 : Destination.GetHashCode ()) 185 | ^ (Sender == null ? 0 : Sender.GetHashCode ()) 186 | ^ (ErrorName == null ? 0 : ErrorName.GetHashCode ()) 187 | ^ Signature.GetHashCode (); 188 | }*/ 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/Protocol/MessageDumper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | namespace DBus.Protocol 10 | { 11 | public class MessageDumper 12 | { 13 | public static byte[] ReadBlock (TextReader r) 14 | { 15 | //if (Body == null) 16 | // return; 17 | 18 | MemoryStream ms = new MemoryStream (); 19 | 20 | while (true) { 21 | string ln = r.ReadLine (); 22 | if (ln == null) 23 | break; 24 | if (!ReadFromHex (ms, ln)) 25 | break; 26 | } 27 | 28 | if (ms.Length == 0) 29 | return null; 30 | 31 | return ms.ToArray (); 32 | } 33 | 34 | public static void WriteComment (string comment, TextWriter w) 35 | { 36 | w.WriteLine ("# " + comment); 37 | } 38 | 39 | public static void WriteBlock (byte[] Body, TextWriter w) 40 | { 41 | //if (Body == null) 42 | // return; 43 | if (Body != null) 44 | for (int i = 0 ; i != Body.Length ; i++) { 45 | if (i == 0) {} 46 | else if (i % 32 == 0) 47 | w.WriteLine (); 48 | else if (i % 4 == 0) 49 | w.Write (' '); 50 | 51 | w.Write (Body[i].ToString ("x2", System.Globalization.CultureInfo.InvariantCulture)); 52 | } 53 | 54 | w.Write ('.'); 55 | w.WriteLine (); 56 | w.Flush (); 57 | } 58 | 59 | public static void WriteMessage (Message msg, TextWriter w) 60 | { 61 | w.WriteLine ("# Message"); 62 | w.WriteLine ("# Header"); 63 | MessageDumper.WriteBlock (msg.GetHeaderData (), w); 64 | w.WriteLine ("# Body"); 65 | MessageDumper.WriteBlock (msg.Body, w); 66 | w.WriteLine (); 67 | w.Flush (); 68 | } 69 | 70 | public static Message ReadMessage (TextReader r) 71 | { 72 | byte[] header = MessageDumper.ReadBlock (r); 73 | 74 | if (header == null) 75 | return null; 76 | 77 | byte[] body = MessageDumper.ReadBlock (r); 78 | 79 | return Message.FromReceivedBytes (null, header, body); 80 | } 81 | 82 | static byte FromHexChar (char c) 83 | { 84 | if ((c >= 'a') && (c <= 'f')) 85 | return (byte) (c - 'a' + 10); 86 | if ((c >= 'A') && (c <= 'F')) 87 | return (byte) (c - 'A' + 10); 88 | if ((c >= '0') && (c <= '9')) 89 | return (byte) (c - '0'); 90 | throw new ArgumentException ("Invalid hex char"); 91 | } 92 | 93 | static bool ReadFromHex (Stream ms, string hex) 94 | { 95 | if (hex.StartsWith ("#")) 96 | return true; 97 | 98 | int i = 0; 99 | while (i < hex.Length) { 100 | if (char.IsWhiteSpace (hex [i])) { 101 | i++; 102 | continue; 103 | } 104 | 105 | if (hex [i] == '.') { 106 | ms.Flush (); 107 | return false; 108 | } 109 | 110 | byte res = (byte) (FromHexChar (hex [i++]) << 4); 111 | res += FromHexChar (hex [i++]); 112 | ms.WriteByte (res); 113 | } 114 | 115 | ms.Flush (); 116 | return true; 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /src/Protocol/MessageFilter.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | 7 | namespace DBus.Protocol 8 | { 9 | public class MessageFilter 10 | { 11 | //this should probably be made to use HeaderField or similar 12 | //this class is not generalized yet 13 | 14 | public static string MessageTypeToString (MessageType mtype) 15 | { 16 | switch (mtype) 17 | { 18 | case MessageType.MethodCall: 19 | return "method_call"; 20 | case MessageType.MethodReturn: 21 | return "method_return"; 22 | case MessageType.Error: 23 | return "error"; 24 | case MessageType.Signal: 25 | return "signal"; 26 | case MessageType.Invalid: 27 | return "invalid"; 28 | default: 29 | throw new Exception ("Bad MessageType: " + mtype); 30 | } 31 | } 32 | 33 | public static MessageType StringToMessageType (string text) 34 | { 35 | switch (text) 36 | { 37 | case "method_call": 38 | return MessageType.MethodCall; 39 | case "method_return": 40 | return MessageType.MethodReturn; 41 | case "error": 42 | return MessageType.Error; 43 | case "signal": 44 | return MessageType.Signal; 45 | case "invalid": 46 | return MessageType.Invalid; 47 | default: 48 | throw new Exception ("Bad MessageType: " + text); 49 | } 50 | } 51 | 52 | //TODO: remove this -- left here for the benefit of the monitor tool for now 53 | public static string CreateMatchRule (MessageType mtype) 54 | { 55 | return "type='" + MessageTypeToString (mtype) + "'"; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Protocol/MessageType.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | 8 | namespace DBus.Protocol 9 | { 10 | public enum MessageType : byte 11 | { 12 | //This is an invalid type. 13 | Invalid, 14 | //Method call. 15 | MethodCall, 16 | //Method reply with returned data. 17 | MethodReturn, 18 | //Error reply. If the first argument exists and is a string, it is an error message. 19 | Error, 20 | //Signal emission. 21 | Signal, 22 | All 23 | // Correspond to all types 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Protocol/PendingCall.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2007 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Threading; 7 | 8 | namespace DBus.Protocol 9 | { 10 | public class PendingCall : IAsyncResult 11 | { 12 | Connection conn; 13 | Message reply; 14 | ManualResetEvent waitHandle; 15 | bool completedSync; 16 | bool keepFDs; 17 | 18 | public event Action Completed; 19 | 20 | public PendingCall (Connection conn) : this (conn, false) {} 21 | public PendingCall (Connection conn, bool keepFDs) 22 | { 23 | this.conn = conn; 24 | this.keepFDs = keepFDs; 25 | } 26 | 27 | internal bool KeepFDs 28 | { 29 | get { 30 | return keepFDs; 31 | } 32 | } 33 | 34 | public Message Reply { 35 | get { 36 | if (reply != null) 37 | return reply; 38 | 39 | if (Thread.CurrentThread == conn.mainThread) { 40 | while (reply == null) 41 | conn.HandleMessage (conn.Transport.ReadMessage ()); 42 | 43 | completedSync = true; 44 | 45 | conn.DispatchSignals (); 46 | } else { 47 | if (waitHandle == null) 48 | Interlocked.CompareExchange (ref waitHandle, new ManualResetEvent (false), null); 49 | 50 | while (reply == null) 51 | waitHandle.WaitOne (); 52 | 53 | completedSync = false; 54 | } 55 | 56 | return reply; 57 | } 58 | set { 59 | if (reply != null) 60 | throw new Exception ("Cannot handle reply more than once"); 61 | 62 | reply = value; 63 | 64 | if (waitHandle != null) 65 | waitHandle.Set (); 66 | 67 | if (Completed != null) 68 | Completed (reply); 69 | } 70 | } 71 | 72 | public void Cancel () 73 | { 74 | throw new NotImplementedException (); 75 | } 76 | 77 | #region IAsyncResult Members 78 | 79 | object IAsyncResult.AsyncState { 80 | get { 81 | return conn; 82 | } 83 | } 84 | 85 | WaitHandle IAsyncResult.AsyncWaitHandle { 86 | get { 87 | if (waitHandle == null) 88 | waitHandle = new ManualResetEvent (false); 89 | 90 | return waitHandle; 91 | } 92 | } 93 | 94 | bool IAsyncResult.CompletedSynchronously { 95 | get { 96 | return reply != null && completedSync; 97 | } 98 | } 99 | 100 | bool IAsyncResult.IsCompleted { 101 | get { 102 | return reply != null; 103 | } 104 | } 105 | 106 | #endregion 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Protocol/ProtocolInformation.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace DBus.Protocol 9 | { 10 | static class ProtocolInformation 11 | { 12 | //protocol versions that we support 13 | public const byte MinVersion = 0; 14 | public const byte Version = 1; 15 | public const byte MaxVersion = Version + 1; 16 | 17 | public const uint MaxMessageLength = 134217728; //2 to the 27th power 18 | public const uint MaxArrayLength = 67108864; //2 to the 26th power 19 | public const uint MaxSignatureLength = 255; 20 | public const uint MaxArrayDepth = 32; 21 | public const uint MaxStructDepth = 32; 22 | 23 | //this is not strictly related to Protocol since names are passed around as strings 24 | internal const uint MaxNameLength = 255; 25 | internal const uint MaxMatchRuleLength = 1024; 26 | internal const uint MaxMatchRuleArgs = 64; 27 | 28 | public static int PadNeeded (int pos, int alignment) 29 | { 30 | int pad = pos % alignment; 31 | return pad == 0 ? 0 : alignment - pad; 32 | } 33 | 34 | public static int Padded (int pos, int alignment) 35 | { 36 | int pad = pos % alignment; 37 | if (pad != 0) 38 | pos += alignment - pad; 39 | 40 | return pos; 41 | } 42 | 43 | public static int GetAlignment (DType dtype) 44 | { 45 | switch (dtype) { 46 | case DType.Byte: 47 | return 1; 48 | case DType.Boolean: 49 | return 4; 50 | case DType.Int16: 51 | case DType.UInt16: 52 | return 2; 53 | case DType.Int32: 54 | case DType.UInt32: 55 | return 4; 56 | case DType.Int64: 57 | case DType.UInt64: 58 | return 8; 59 | #if !DISABLE_SINGLE 60 | case DType.Single: //Not yet supported! 61 | return 4; 62 | #endif 63 | case DType.Double: 64 | return 8; 65 | case DType.String: 66 | return 4; 67 | case DType.UnixFD: 68 | return 4; 69 | case DType.ObjectPath: 70 | return 4; 71 | case DType.Signature: 72 | return 1; 73 | case DType.Array: 74 | return 4; 75 | case DType.StructBegin: 76 | return 8; 77 | case DType.Variant: 78 | return 1; 79 | case DType.DictEntryBegin: 80 | return 8; 81 | case DType.Invalid: 82 | default: 83 | throw new Exception ("Cannot determine alignment of " + dtype); 84 | } 85 | } 86 | 87 | //this class may not be the best place for Verbose 88 | public readonly static bool Verbose = !String.IsNullOrEmpty (Environment.GetEnvironmentVariable ("DBUS_VERBOSE")); 89 | } 90 | 91 | #if UNDOCUMENTED_IN_SPEC 92 | /* 93 | "org.freedesktop.DBus.Error.Failed" 94 | "org.freedesktop.DBus.Error.NoMemory" 95 | "org.freedesktop.DBus.Error.ServiceUnknown" 96 | "org.freedesktop.DBus.Error.NameHasNoOwner" 97 | "org.freedesktop.DBus.Error.NoReply" 98 | "org.freedesktop.DBus.Error.IOError" 99 | "org.freedesktop.DBus.Error.BadAddress" 100 | "org.freedesktop.DBus.Error.NotSupported" 101 | "org.freedesktop.DBus.Error.LimitsExceeded" 102 | "org.freedesktop.DBus.Error.AccessDenied" 103 | "org.freedesktop.DBus.Error.AuthFailed" 104 | "org.freedesktop.DBus.Error.NoServer" 105 | "org.freedesktop.DBus.Error.Timeout" 106 | "org.freedesktop.DBus.Error.NoNetwork" 107 | "org.freedesktop.DBus.Error.AddressInUse" 108 | "org.freedesktop.DBus.Error.Disconnected" 109 | "org.freedesktop.DBus.Error.InvalidArgs" 110 | "org.freedesktop.DBus.Error.FileNotFound" 111 | "org.freedesktop.DBus.Error.UnknownMethod" 112 | "org.freedesktop.DBus.Error.TimedOut" 113 | "org.freedesktop.DBus.Error.MatchRuleNotFound" 114 | "org.freedesktop.DBus.Error.MatchRuleInvalid" 115 | "org.freedesktop.DBus.Error.Spawn.ExecFailed" 116 | "org.freedesktop.DBus.Error.Spawn.ForkFailed" 117 | "org.freedesktop.DBus.Error.Spawn.ChildExited" 118 | "org.freedesktop.DBus.Error.Spawn.ChildSignaled" 119 | "org.freedesktop.DBus.Error.Spawn.Failed" 120 | "org.freedesktop.DBus.Error.UnixProcessIdUnknown" 121 | "org.freedesktop.DBus.Error.InvalidSignature" 122 | "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown" 123 | */ 124 | #endif 125 | } 126 | -------------------------------------------------------------------------------- /src/Protocol/SocketTransport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.IO; 7 | using System.Net; 8 | using System.Net.Sockets; 9 | 10 | namespace DBus.Transports 11 | { 12 | class SocketTransport : Transport 13 | { 14 | internal Socket socket; 15 | 16 | public override void Open (AddressEntry entry) 17 | { 18 | string host, portStr, family; 19 | int port; 20 | 21 | if (!entry.Properties.TryGetValue ("host", out host)) 22 | host = "localhost"; 23 | 24 | if (!entry.Properties.TryGetValue ("port", out portStr)) 25 | throw new Exception ("No port specified"); 26 | 27 | if (!Int32.TryParse (portStr, out port)) 28 | throw new Exception ("Invalid port: \"" + port + "\""); 29 | 30 | if (!entry.Properties.TryGetValue ("family", out family)) 31 | family = null; 32 | 33 | Open (host, port, family); 34 | } 35 | 36 | public void Open (string host, int port, string family) 37 | { 38 | //TODO: use Socket directly 39 | TcpClient client = new TcpClient (host, port); 40 | /* 41 | client.NoDelay = true; 42 | client.ReceiveBufferSize = (int)Protocol.MaxMessageLength; 43 | client.SendBufferSize = (int)Protocol.MaxMessageLength; 44 | */ 45 | this.socket = client.Client; 46 | SocketHandle = (long)client.Client.Handle; 47 | Stream = client.GetStream (); 48 | } 49 | 50 | public void Open (Socket socket) 51 | { 52 | this.socket = socket; 53 | 54 | socket.Blocking = true; 55 | SocketHandle = (long)socket.Handle; 56 | //Stream = new UnixStream ((int)socket.Handle); 57 | Stream = new NetworkStream (socket); 58 | } 59 | 60 | public override void WriteCred () 61 | { 62 | Stream.WriteByte (0); 63 | } 64 | 65 | public override string AuthString () 66 | { 67 | return OSHelpers.PlatformIsUnixoid ? 68 | Mono.Unix.Native.Syscall.geteuid ().ToString () // Unix User ID 69 | : System.Security.Principal.WindowsIdentity.GetCurrent ().User.Value; // Windows User ID 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Protocol/UnixFDArray.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Steffen Kiess 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | namespace DBus.Protocol 10 | { 11 | public class UnixFDArray : IDisposable 12 | { 13 | public static readonly int MaxFDs = 16; 14 | 15 | List fds = new List (); 16 | 17 | public IList FDs 18 | { 19 | get { 20 | return fds; 21 | } 22 | } 23 | 24 | public void Dispose () 25 | { 26 | for (int i = 0; i < fds.Count; i++) { 27 | fds[i].Dispose (); 28 | } 29 | } 30 | 31 | internal UnixFDArray Clone () { 32 | var res = new UnixFDArray (); 33 | foreach (var fd in FDs) 34 | res.FDs.Add (fd.Clone ()); 35 | return res; 36 | } 37 | } 38 | } 39 | 40 | // Local Variables: 41 | // tab-width: 4 42 | // c-basic-offset: 4 43 | // indent-tabs-mode: t 44 | // End: 45 | -------------------------------------------------------------------------------- /src/Transports/UnixNativeTransport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.IO; 7 | using System.Text; 8 | using System.Runtime.InteropServices; 9 | 10 | using DBus.Unix; 11 | using DBus.Protocol; 12 | 13 | namespace DBus.Transports 14 | { 15 | class UnixNativeTransport : UnixTransport 16 | { 17 | internal UnixSocket socket; 18 | 19 | public override string AuthString () 20 | { 21 | long uid = Mono.Unix.Native.Syscall.geteuid (); 22 | return uid.ToString (); 23 | } 24 | 25 | public override void Open (string path, bool @abstract) 26 | { 27 | if (String.IsNullOrEmpty (path)) 28 | throw new ArgumentException ("path"); 29 | 30 | if (@abstract) 31 | socket = OpenAbstractUnix (path); 32 | else 33 | socket = OpenUnix (path); 34 | 35 | //socket.Blocking = true; 36 | SocketHandle = (long)socket.Handle; 37 | //Stream = new UnixStream ((int)socket.Handle); 38 | Stream = new UnixStream (socket); 39 | } 40 | 41 | public static byte[] GetSockAddr (string path) 42 | { 43 | byte[] p = Encoding.Default.GetBytes (path); 44 | 45 | byte[] sa = new byte[2 + p.Length + 1]; 46 | 47 | //we use BitConverter to stay endian-safe 48 | byte[] afData = BitConverter.GetBytes (UnixSocket.AF_UNIX); 49 | sa[0] = afData[0]; 50 | sa[1] = afData[1]; 51 | 52 | for (int i = 0 ; i != p.Length ; i++) 53 | sa[2 + i] = p[i]; 54 | sa[2 + p.Length] = 0; //null suffix for domain socket addresses, see unix(7) 55 | 56 | return sa; 57 | } 58 | 59 | public static byte[] GetSockAddrAbstract (string path) 60 | { 61 | byte[] p = Encoding.Default.GetBytes (path); 62 | 63 | byte[] sa = new byte[2 + 1 + p.Length]; 64 | 65 | //we use BitConverter to stay endian-safe 66 | byte[] afData = BitConverter.GetBytes (UnixSocket.AF_UNIX); 67 | sa[0] = afData[0]; 68 | sa[1] = afData[1]; 69 | 70 | sa[2] = 0; //null prefix for abstract domain socket addresses, see unix(7) 71 | for (int i = 0 ; i != p.Length ; i++) 72 | sa[3 + i] = p[i]; 73 | 74 | return sa; 75 | } 76 | 77 | internal UnixSocket OpenUnix (string path) 78 | { 79 | byte[] sa = GetSockAddr (path); 80 | UnixSocket client = new UnixSocket (); 81 | client.Connect (sa); 82 | return client; 83 | } 84 | 85 | internal UnixSocket OpenAbstractUnix (string path) 86 | { 87 | byte[] sa = GetSockAddrAbstract (path); 88 | UnixSocket client = new UnixSocket (); 89 | client.Connect (sa); 90 | return client; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Transports/UnixSendmsgTransport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Steffen Kiess 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.IO; 7 | using System.Text; 8 | using System.Runtime.InteropServices; 9 | 10 | using DBus.Protocol; 11 | 12 | using Mono.Unix; 13 | using Mono.Unix.Native; 14 | 15 | namespace DBus.Transports 16 | { 17 | class UnixSendmsgTransport : UnixTransport 18 | { 19 | static bool CheckAvailable () 20 | { 21 | var msghdr = new Msghdr { 22 | msg_iov = new Iovec[] {}, 23 | msg_iovlen = 0, 24 | }; 25 | // sendmsg() should return EBADFD because fd == -1 26 | // If sendmsg() is not available (e.g. because Mono.Posix is too 27 | // old or this is on a system without sendmsg()), Syscall.sendmsg() 28 | // will throw an exception 29 | Syscall.sendmsg (-1, msghdr, 0); 30 | return true; 31 | } 32 | 33 | public static bool Available () 34 | { 35 | try { 36 | return CheckAvailable (); 37 | } catch { 38 | return false; 39 | } 40 | } 41 | 42 | public UnixSendmsgTransport () 43 | { 44 | SocketHandle = -1; 45 | } 46 | 47 | internal override bool TransportSupportsUnixFD { get { return true; } } 48 | 49 | public override string AuthString () 50 | { 51 | long uid = Mono.Unix.Native.Syscall.geteuid (); 52 | return uid.ToString (); 53 | } 54 | 55 | public override void Open (string path, bool @abstract) 56 | { 57 | if (String.IsNullOrEmpty (path)) 58 | throw new ArgumentException ("path"); 59 | 60 | var addr = new SockaddrUn (path, linuxAbstractNamespace:@abstract); 61 | 62 | SocketHandle = Syscall.socket (UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0); 63 | if (SocketHandle == -1) 64 | UnixMarshal.ThrowExceptionForLastError (); 65 | bool success = false; 66 | try { 67 | if (Syscall.connect ((int) SocketHandle, addr) < 0) 68 | UnixMarshal.ThrowExceptionForLastError (); 69 | Stream = new DBus.Unix.UnixMonoStream ((int) SocketHandle); 70 | success = true; 71 | } finally { 72 | if (!success) { 73 | int ret = Syscall.close ((int) SocketHandle); 74 | SocketHandle = -1; 75 | if (ret == -1) 76 | UnixMarshal.ThrowExceptionForLastError (); 77 | } 78 | } 79 | } 80 | 81 | readonly object writeLock = new object (); 82 | 83 | byte[] cmsgBuffer = new byte[Syscall.CMSG_LEN ((ulong)(sizeof (int) * UnixFDArray.MaxFDs))]; 84 | // Might return short reads 85 | unsafe int ReadShort (byte[] buffer, int offset, int length, UnixFDArray fdArray) 86 | { 87 | if (length < 0 || offset < 0 || length + offset < length || length + offset > buffer.Length) 88 | throw new ArgumentException (); 89 | 90 | fixed (byte* ptr = buffer, cmsgPtr = cmsgBuffer) { 91 | var iovecs = new Iovec[] { 92 | new Iovec { 93 | iov_base = (IntPtr) (ptr + offset), 94 | iov_len = (ulong) length, 95 | }, 96 | }; 97 | 98 | var msghdr = new Msghdr { 99 | msg_iov = iovecs, 100 | msg_iovlen = 1, 101 | msg_control = cmsgBuffer, 102 | msg_controllen = cmsgBuffer.Length, 103 | }; 104 | 105 | long r; 106 | do { 107 | r = Syscall.recvmsg ((int) SocketHandle, msghdr, 0); 108 | } while (UnixMarshal.ShouldRetrySyscall ((int) r)); 109 | 110 | for (long cOffset = Syscall.CMSG_FIRSTHDR (msghdr); cOffset != -1; cOffset = Syscall.CMSG_NXTHDR (msghdr, cOffset)) { 111 | var recvHdr = Cmsghdr.ReadFromBuffer (msghdr, cOffset); 112 | if (recvHdr.cmsg_level != UnixSocketProtocol.SOL_SOCKET) 113 | continue; 114 | if (recvHdr.cmsg_type != UnixSocketControlMessage.SCM_RIGHTS) 115 | continue; 116 | var recvDataOffset = Syscall.CMSG_DATA (msghdr, cOffset); 117 | var bytes = recvHdr.cmsg_len - (recvDataOffset - cOffset); 118 | var fdCount = bytes / sizeof (int); 119 | for (int i = 0; i < fdCount; i++) 120 | fdArray.FDs.Add (new UnixFD (((int*) (cmsgPtr + recvDataOffset))[i])); 121 | } 122 | 123 | if ((msghdr.msg_flags & MessageFlags.MSG_CTRUNC) != 0) 124 | throw new Exception ("Control message truncated (probably file descriptors lost)"); 125 | 126 | return (int) r; 127 | } 128 | } 129 | 130 | internal override int Read (byte[] buffer, int offset, int length, UnixFDArray fdArray) 131 | { 132 | if (!Connection.UnixFDSupported || fdArray == null) 133 | return base.Read (buffer, offset, length, fdArray); 134 | 135 | int read = 0; 136 | while (read < length) { 137 | int nread = ReadShort (buffer, offset + read, length - read, fdArray); 138 | if (nread == 0) 139 | break; 140 | read += nread; 141 | } 142 | 143 | if (read > length) 144 | throw new Exception (); 145 | 146 | return read; 147 | } 148 | 149 | internal override unsafe void WriteMessage (Message msg) 150 | { 151 | if (msg.UnixFDArray == null || msg.UnixFDArray.FDs.Count == 0) { 152 | base.WriteMessage (msg); 153 | return; 154 | } 155 | if (!Connection.UnixFDSupported) 156 | throw new Exception ("Attempting to write Unix FDs to a connection which does not support them"); 157 | 158 | lock (writeLock) { 159 | var ms = new MemoryStream (); 160 | msg.Header.GetHeaderDataToStream (ms); 161 | var header = ms.ToArray (); 162 | ((DBus.Unix.UnixMonoStream) Stream).Sendmsg (header, 0, header.Length, msg.Body, 0, msg.Body == null ? 0 : msg.Body.Length, msg.UnixFDArray); 163 | } 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/Transports/UnixTransport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | //We send BSD-style credentials on all platforms 6 | //Doesn't seem to break Linux (but is redundant there) 7 | //This may turn out to be a bad idea 8 | #define HAVE_CMSGCRED 9 | 10 | using System; 11 | using System.IO; 12 | 13 | using DBus.Protocol; 14 | using DBus.Unix; 15 | 16 | namespace DBus.Transports 17 | { 18 | abstract class UnixTransport : Transport 19 | { 20 | public override void Open (AddressEntry entry) 21 | { 22 | string path; 23 | bool abstr; 24 | 25 | if (entry.Properties.TryGetValue ("path", out path)) 26 | abstr = false; 27 | else if (entry.Properties.TryGetValue ("abstract", out path)) 28 | abstr = true; 29 | else 30 | throw new ArgumentException ("No path specified for UNIX transport"); 31 | 32 | Open (path, abstr); 33 | } 34 | 35 | public abstract void Open (string path, bool @abstract); 36 | 37 | //send peer credentials null byte 38 | //different platforms do this in different ways 39 | #if HAVE_CMSGCRED 40 | unsafe void WriteBsdCred () 41 | { 42 | //null credentials byte 43 | byte buf = 0; 44 | 45 | IOVector iov = new IOVector (); 46 | //iov.Base = (IntPtr)(&buf); 47 | iov.Base = &buf; 48 | iov.Length = 1; 49 | 50 | msghdr msg = new msghdr (); 51 | msg.msg_iov = &iov; 52 | msg.msg_iovlen = 1; 53 | 54 | cmsg cm = new cmsg (); 55 | msg.msg_control = (IntPtr)(&cm); 56 | msg.msg_controllen = (uint)sizeof (cmsg); 57 | cm.hdr.cmsg_len = (uint)sizeof (cmsg); 58 | cm.hdr.cmsg_level = 0xffff; //SOL_SOCKET 59 | cm.hdr.cmsg_type = 0x03; //SCM_CREDS 60 | 61 | int written = new UnixSocket ((int) SocketHandle, false).SendMsg (&msg, 0); 62 | if (written != 1) 63 | throw new Exception ("Failed to write credentials"); 64 | } 65 | #endif 66 | 67 | public override void WriteCred () 68 | { 69 | #if HAVE_CMSGCRED 70 | try { 71 | WriteBsdCred (); 72 | return; 73 | } catch { 74 | if (ProtocolInformation.Verbose) 75 | Console.Error.WriteLine ("Warning: WriteBsdCred() failed; falling back to ordinary WriteCred()"); 76 | } 77 | #endif 78 | //null credentials byte 79 | byte buf = 0; 80 | Stream.WriteByte (buf); 81 | } 82 | } 83 | 84 | #if HAVE_CMSGCRED 85 | unsafe struct msghdr 86 | { 87 | public IntPtr msg_name; //optional address 88 | public uint msg_namelen; //size of address 89 | public IOVector *msg_iov; //scatter/gather array 90 | public int msg_iovlen; //# elements in msg_iov 91 | public IntPtr msg_control; //ancillary data, see below 92 | public uint msg_controllen; //ancillary data buffer len 93 | public int msg_flags; //flags on received message 94 | } 95 | 96 | struct cmsghdr 97 | { 98 | public uint cmsg_len; //data byte count, including header 99 | public int cmsg_level; //originating protocol 100 | public int cmsg_type; //protocol-specific type 101 | } 102 | 103 | unsafe struct cmsgcred 104 | { 105 | const int CMGROUP_MAX = 16; 106 | 107 | public int cmcred_pid; //PID of sending process 108 | public uint cmcred_uid; //real UID of sending process 109 | public uint cmcred_euid; //effective UID of sending process 110 | public uint cmcred_gid; //real GID of sending process 111 | public short cmcred_ngroups; //number or groups 112 | public fixed uint cmcred_groups[CMGROUP_MAX]; //groups 113 | } 114 | 115 | struct cmsg 116 | { 117 | public cmsghdr hdr; 118 | public cmsgcred cred; 119 | } 120 | #endif 121 | } 122 | -------------------------------------------------------------------------------- /src/Unix/UnixError.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.IO; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace DBus 10 | { 11 | static class UnixError 12 | { 13 | internal const string LIBC = "libc"; 14 | 15 | [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=false)] 16 | static extern IntPtr strerror (int errnum); 17 | 18 | static string GetErrorString (int errnum) 19 | { 20 | IntPtr strPtr = strerror (errnum); 21 | 22 | if (strPtr == IntPtr.Zero) 23 | return "Unknown Unix error"; 24 | 25 | return Marshal.PtrToStringAnsi (strPtr); 26 | } 27 | 28 | // FIXME: Don't hard-code this. 29 | const int EINTR = 4; 30 | 31 | public static bool ShouldRetry 32 | { 33 | get { 34 | int errno = System.Runtime.InteropServices.Marshal.GetLastWin32Error (); 35 | return errno == EINTR; 36 | } 37 | } 38 | 39 | public static Exception GetLastUnixException () 40 | { 41 | int errno = System.Runtime.InteropServices.Marshal.GetLastWin32Error (); 42 | return new Exception (String.Format ("Error {0}: {1}", errno, GetErrorString (errno))); 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/Unix/UnixMonoStream.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Steffen Kiess 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.IO; 7 | using System.Runtime.InteropServices; 8 | 9 | using Mono.Unix; 10 | using Mono.Unix.Native; 11 | 12 | namespace DBus.Unix 13 | { 14 | sealed class UnixMonoStream : Stream 15 | { 16 | int fd; 17 | 18 | public UnixMonoStream (int fd) 19 | { 20 | this.fd = fd; 21 | } 22 | 23 | public override bool CanRead 24 | { 25 | get { 26 | return true; 27 | } 28 | } 29 | 30 | public override bool CanSeek 31 | { 32 | get { 33 | return false; 34 | } 35 | } 36 | 37 | public override bool CanWrite 38 | { 39 | get { 40 | return true; 41 | } 42 | } 43 | 44 | public override long Length 45 | { 46 | get { 47 | throw new NotImplementedException ("Seeking is not implemented"); 48 | } 49 | } 50 | 51 | public override long Position 52 | { 53 | get { 54 | throw new NotImplementedException ("Seeking is not implemented"); 55 | } set { 56 | throw new NotImplementedException ("Seeking is not implemented"); 57 | } 58 | } 59 | 60 | public override long Seek (long offset, SeekOrigin origin) 61 | { 62 | throw new NotImplementedException ("Seeking is not implemented"); 63 | } 64 | 65 | public override void SetLength (long value) 66 | { 67 | throw new NotImplementedException ("Not implemented"); 68 | } 69 | 70 | public override void Flush () 71 | { 72 | } 73 | 74 | private void AssertValidBuffer (byte[] buffer, long offset, long length) 75 | { 76 | if (buffer == null) 77 | throw new ArgumentNullException ("buffer"); 78 | if (offset < 0) 79 | throw new ArgumentOutOfRangeException ("offset", "< 0"); 80 | if (length < 0) 81 | throw new ArgumentOutOfRangeException ("length", "< 0"); 82 | if (offset > buffer.LongLength) 83 | throw new ArgumentException ("destination offset is beyond array size"); 84 | if (offset > (buffer.LongLength - length)) 85 | throw new ArgumentException ("would overrun buffer"); 86 | } 87 | 88 | public override unsafe int Read (byte[] buffer, int offset, int length) 89 | { 90 | AssertValidBuffer (buffer, offset, length); 91 | 92 | long r = 0; 93 | fixed (byte* buf = buffer) { 94 | do { 95 | r = Syscall.read (fd, buf + offset, (ulong) length); 96 | } while (UnixMarshal.ShouldRetrySyscall ((int) r)); 97 | if (r < 0) 98 | UnixMarshal.ThrowExceptionForLastError (); 99 | return (int) r; 100 | } 101 | } 102 | 103 | public override unsafe void Write (byte[] buffer, int offset, int length) 104 | { 105 | AssertValidBuffer (buffer, offset, length); 106 | 107 | int pos = 0; 108 | long r = 0; 109 | fixed (byte* buf = buffer) { 110 | while (pos < length) { 111 | do { 112 | r = Syscall.write (fd, buf + offset + pos, (ulong) length); 113 | } while (UnixMarshal.ShouldRetrySyscall ((int) r)); 114 | if (r < 0) 115 | UnixMarshal.ThrowExceptionForLastError (); 116 | pos += (int) r; 117 | } 118 | } 119 | } 120 | 121 | public override void Close () 122 | { 123 | if (fd != -1) { 124 | int ret = Syscall.close (fd); 125 | fd = -1; 126 | if (ret == -1) 127 | UnixMarshal.ThrowExceptionForLastError (); 128 | } 129 | base.Close (); 130 | } 131 | 132 | // Send the two buffers and the FDs using sendmsg(), don't handle short writes 133 | // length1 + length2 must not be 0 134 | public unsafe long SendmsgShort (byte[] buffer1, long offset1, long length1, 135 | byte[] buffer2, long offset2, long length2, 136 | DBus.Protocol.UnixFDArray fds) 137 | { 138 | //Console.WriteLine ("SendmsgShort (X, {0}, {1}, {2}, {3}, {4}, {5})", offset1, length1, buffer2 == null ? "-" : "Y", offset2, length2, fds == null ? "-" : "" + fds.FDs.Count); 139 | AssertValidBuffer (buffer1, offset1, length1); 140 | if (buffer2 == null) { 141 | if (length2 != 0) 142 | throw new ArgumentOutOfRangeException ("length2", "!= 0 while buffer2 == null"); 143 | offset2 = 0; 144 | } else { 145 | AssertValidBuffer (buffer2, offset2, length2); 146 | } 147 | 148 | fixed (byte* ptr1 = buffer1, ptr2 = buffer2) { 149 | var iovecs = new Iovec[] { 150 | new Iovec { 151 | iov_base = (IntPtr) (ptr1 + offset1), 152 | iov_len = (ulong) length1, 153 | }, 154 | new Iovec { 155 | iov_base = (IntPtr) (ptr2 + offset2), 156 | iov_len = (ulong) length2, 157 | }, 158 | }; 159 | /* Simulate short writes 160 | if (iovecs[0].iov_len == 0) { 161 | iovecs[1].iov_len = Math.Min (iovecs[1].iov_len, 5); 162 | } else { 163 | iovecs[0].iov_len = Math.Min (iovecs[0].iov_len, 5); 164 | iovecs[1].iov_len = 0; 165 | } 166 | */ 167 | byte[] cmsg = null; 168 | 169 | // Create copy of FDs to prevent the user from Dispose()ing the 170 | // FDs in another thread between writing the FDs into the cmsg 171 | // buffer and calling sendmsg() 172 | using (var fds2 = fds == null ? null : fds.Clone ()) { 173 | int fdCount = fds2 == null ? 0 : fds2.FDs.Count; 174 | if (fdCount != 0) { 175 | // Create one SCM_RIGHTS control message 176 | cmsg = new byte[Syscall.CMSG_SPACE ((uint) fdCount * sizeof (int))]; 177 | } 178 | var msghdr = new Msghdr { 179 | msg_iov = iovecs, 180 | msg_iovlen = length2 == 0 ? 1 : 2, 181 | msg_control = cmsg, 182 | msg_controllen = cmsg == null ? 0 : cmsg.Length, 183 | }; 184 | if (fdCount != 0) { 185 | var hdr = new Cmsghdr { 186 | cmsg_len = (long) Syscall.CMSG_LEN ((uint) fdCount * sizeof (int)), 187 | cmsg_level = UnixSocketProtocol.SOL_SOCKET, 188 | cmsg_type = UnixSocketControlMessage.SCM_RIGHTS, 189 | }; 190 | hdr.WriteToBuffer (msghdr, 0); 191 | var dataOffset = Syscall.CMSG_DATA (msghdr, 0); 192 | fixed (byte* ptr = cmsg) { 193 | for (int i = 0; i < fdCount; i++) 194 | ((int*) (ptr + dataOffset))[i] = fds2.FDs[i].Handle; 195 | } 196 | } 197 | long r; 198 | do { 199 | r = Syscall.sendmsg (fd, msghdr, MessageFlags.MSG_NOSIGNAL); 200 | } while (UnixMarshal.ShouldRetrySyscall ((int) r)); 201 | if (r < 0) 202 | UnixMarshal.ThrowExceptionForLastError (); 203 | if (r == 0) 204 | throw new Exception ("sendmsg() returned 0"); 205 | return r; 206 | } 207 | } 208 | } 209 | 210 | // Send the two buffers and the FDs using sendmsg(), handle short writes 211 | public unsafe void Sendmsg (byte[] buffer1, long offset1, long length1, 212 | byte[] buffer2, long offset2, long length2, 213 | DBus.Protocol.UnixFDArray fds) 214 | { 215 | //SendmsgShort (buffer1, offset1, length1, buffer2, offset2, length2, fds); return; 216 | long bytes_overall = (long) length1 + length2; 217 | long written = 0; 218 | while (written < bytes_overall) { 219 | if (written >= length1) { 220 | long written2 = written - length1; 221 | written += SendmsgShort (buffer2, offset2 + written2, length2 - written2, null, 0, 0, written == 0 ? fds : null); 222 | } else { 223 | written += SendmsgShort (buffer1, offset1 + written, length1 - written, buffer2, offset2, length2, written == 0 ? fds : null); 224 | } 225 | } 226 | if (written != bytes_overall) 227 | throw new Exception ("written != bytes_overall"); 228 | } 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /src/Unix/UnixStream.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.IO; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace DBus.Unix 10 | { 11 | // size_t 12 | using SizeT = System.UIntPtr; 13 | // ssize_t 14 | using SSizeT = System.IntPtr; 15 | // socklen_t: assumed to be 4 bytes 16 | // uid_t: assumed to be 4 bytes 17 | 18 | sealed class UnixStream : Stream //, IDisposable 19 | { 20 | public readonly UnixSocket usock; 21 | 22 | public UnixStream (int fd) 23 | { 24 | this.usock = new UnixSocket (fd); 25 | } 26 | 27 | public UnixStream (UnixSocket usock) 28 | { 29 | this.usock = usock; 30 | } 31 | 32 | public override bool CanRead 33 | { 34 | get { 35 | return true; 36 | } 37 | } 38 | 39 | public override bool CanSeek 40 | { 41 | get { 42 | return false; 43 | } 44 | } 45 | 46 | public override bool CanWrite 47 | { 48 | get { 49 | return true; 50 | } 51 | } 52 | 53 | public override long Length 54 | { 55 | get { 56 | throw new NotImplementedException ("Seeking is not implemented"); 57 | } 58 | } 59 | 60 | public override long Position 61 | { 62 | get { 63 | throw new NotImplementedException ("Seeking is not implemented"); 64 | } set { 65 | throw new NotImplementedException ("Seeking is not implemented"); 66 | } 67 | } 68 | 69 | public override long Seek (long offset, SeekOrigin origin) 70 | { 71 | throw new NotImplementedException ("Seeking is not implemented"); 72 | } 73 | 74 | public override void SetLength (long value) 75 | { 76 | throw new NotImplementedException ("Not implemented"); 77 | } 78 | 79 | public override void Flush () 80 | { 81 | } 82 | 83 | public override int Read ([In, Out] byte[] buffer, int offset, int count) 84 | { 85 | return usock.Read (buffer, offset, count); 86 | } 87 | 88 | public override void Write (byte[] buffer, int offset, int count) 89 | { 90 | usock.Write (buffer, offset, count); 91 | } 92 | 93 | unsafe public override int ReadByte () 94 | { 95 | byte value; 96 | usock.Read (&value, 1); 97 | return value; 98 | } 99 | 100 | unsafe public override void WriteByte (byte value) 101 | { 102 | usock.Write (&value, 1); 103 | } 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /src/UnixFD.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Steffen Kiess 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | using Mono.Unix; 10 | using Mono.Unix.Native; 11 | 12 | namespace DBus 13 | { 14 | public class UnixFD : IDisposable 15 | { 16 | object lck = new object (); 17 | int fd = -1; 18 | 19 | public UnixFD (int fd) 20 | { 21 | this.fd = fd; 22 | } 23 | 24 | public void Dispose () 25 | { 26 | lock (lck) { 27 | if (fd != -1) { 28 | int r; 29 | // Don't retry close() on EINTR, on a lot of systems (e.g. Linux) the FD will be already closed when EINTR is returned, see https://lwn.net/Articles/576478/ 30 | r = DBus.Unix.UnixSocket.close (fd); 31 | fd = -1; 32 | 33 | if (r < 0) 34 | UnixMarshal.ThrowExceptionForLastError (); 35 | } 36 | } 37 | } 38 | 39 | public override string ToString () 40 | { 41 | lock (lck) { 42 | if (fd == -1) 43 | return "UnixFD (disposed)"; 44 | return "UnixFD (" + fd + ")"; 45 | } 46 | } 47 | 48 | // The caller has to make sure that the FD does not get closed between 49 | // calling UnixFD.Handle and using the handle 50 | public int Handle { 51 | get { 52 | lock (lck) { 53 | if (fd == -1) 54 | throw new ObjectDisposedException (GetType ().FullName); 55 | return fd; 56 | } 57 | } 58 | } 59 | 60 | // Return a new UnixFD instance which will be usable after this UnixFD 61 | // has been closed 62 | public UnixFD Clone () { 63 | lock (lck) { 64 | if (fd == -1) 65 | throw new ObjectDisposedException (GetType ().FullName); 66 | int newFd = Syscall.dup (fd); 67 | if (newFd < 0) 68 | UnixMarshal.ThrowExceptionForLastError (); 69 | return new UnixFD (newFd); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/daemon.mk: -------------------------------------------------------------------------------- 1 | CSC=mcs 2 | 3 | SRCS=Daemon.cs Server.cs ServerBus.cs 4 | 5 | ifdef USE_GLIB 6 | GLIB_FLAGS=-d:USE_GLIB -pkg:dbus-sharp-glib-1.0 -pkg:glib-sharp-2.0 7 | endif 8 | 9 | dbus-daemon.exe: $(SRCS) 10 | $(CSC) -debug -t:exe -out:$@ -r:NDesk.DBus.dll $(GLIB_FLAGS) -keyfile:../dbus-sharp.snk $(SRCS) 11 | 12 | -------------------------------------------------------------------------------- /src/dbus-daemon.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {41918B94-6DAD-4C05-9FDF-17D51EC85AF0} 7 | 9.0.30729 8 | 2.0 9 | Exe 10 | false 11 | dbus-daemon 12 | 512 13 | DBus 14 | v3.5 15 | 16 | 17 | True 18 | full 19 | False 20 | . 21 | TRACE;DEBUG 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | True 28 | . 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C} 40 | dbus-sharp 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/dbus-sharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C} 7 | 9.0.30729 8 | 2.0 9 | Library 10 | false 11 | dbus-sharp 12 | 512 13 | DBus 14 | true 15 | ..\dbus-sharp.snk 16 | v4.5 17 | 18 | 19 | True 20 | full 21 | False 22 | . 23 | DEBUG;TRACE;STRONG_NAME;NET35 24 | none 25 | 4 26 | True 27 | 28 | 29 | pdbonly 30 | True 31 | . 32 | TRACE;STRONG_NAME;NET35 33 | none 34 | 4 35 | True 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | PreserveNewest 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /src/dbus-sharp.dll.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/gencssources: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env csharp 2 | LoadAssembly ("System.Xml.Linq.dll"); 3 | using System.Xml.Linq; 4 | 5 | try { 6 | var doc = XDocument.Load ("dbus-sharp.csproj"); 7 | var ns = (XNamespace)"http://schemas.microsoft.com/developer/msbuild/2003"; 8 | var sources = doc.Root.Elements (ns + "ItemGroup").Elements (ns + "Compile").Attributes ("Include"); 9 | Console.WriteLine (string.Join (" \\" + Environment.NewLine, sources.Select (a => a.Value.Replace ('\\', '/')))); 10 | } catch { 11 | Environment.Exit (1); 12 | } 13 | -------------------------------------------------------------------------------- /tests/AddressTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using NUnit.Framework; 7 | using DBus; 8 | using System.Collections.Generic; 9 | 10 | namespace DBus.Tests 11 | { 12 | [TestFixture] 13 | public class AddressTest 14 | { 15 | [Test] 16 | [ExpectedException (typeof (InvalidAddressException))] 17 | public void ParseBad () 18 | { 19 | Address.Parse ("lala"); 20 | } 21 | 22 | [Test] 23 | public void ParseUnix () 24 | { 25 | string addressText = @"unix:path=/var/run/dbus/system_bus_socket"; 26 | 27 | AddressEntry[] addrs = Address.Parse (addressText); 28 | Assert.AreEqual (1, addrs.Length); 29 | 30 | AddressEntry entry = addrs[0]; 31 | Assert.AreEqual (addressText, entry.ToString ()); 32 | 33 | Assert.AreEqual ("unix", entry.Method); 34 | Assert.AreEqual (1, entry.Properties.Count); 35 | Assert.AreEqual ("/var/run/dbus/system_bus_socket", entry.Properties["path"]); 36 | Assert.AreEqual (UUID.Zero, entry.GUID); 37 | } 38 | 39 | [Test] 40 | public void ParseMany () 41 | { 42 | string addressText = @"unix:path=/var/run/dbus/system_bus_socket;unix:path=/var/run/dbus/system_bus_socket"; 43 | 44 | AddressEntry[] addrs = Address.Parse (addressText); 45 | Assert.AreEqual (2, addrs.Length); 46 | // TODO: Improve this test. 47 | } 48 | 49 | [Test] 50 | public void ParseGuid () 51 | { 52 | string addressText = @"unix:abstract=/tmp/dbus-A4EzCUcGvg,guid=50ab33155e2cdd289e58c42a497ded1e"; 53 | 54 | AddressEntry[] addrs = Address.Parse (addressText); 55 | Assert.AreEqual (1, addrs.Length); 56 | 57 | AddressEntry entry = addrs[0]; 58 | Assert.AreEqual (addressText, entry.ToString ()); 59 | 60 | Assert.AreEqual ("unix", entry.Method); 61 | Assert.AreEqual (1, entry.Properties.Count); 62 | 63 | UUID expectedId = UUID.Parse ("50ab33155e2cdd289e58c42a497ded1e"); 64 | uint expectedTimestamp = 1232989470; 65 | Assert.AreEqual (expectedTimestamp, expectedId.UnixTimestamp); 66 | Assert.AreEqual (expectedId, entry.GUID); 67 | } 68 | 69 | [Test] 70 | public void UUIDEntropy () 71 | { 72 | int n = 10000; 73 | DateTime dt = DateTime.MinValue; 74 | 75 | HashSet hs = new HashSet (); 76 | for (int i = 0 ; i != n ; i++) 77 | Assert.IsTrue (hs.Add (UUID.Generate (dt).GetHashCode ())); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests/AuthenticationTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using NUnit.Framework; 8 | using DBus; 9 | using DBus.Authentication; 10 | 11 | namespace DBus.Tests 12 | { 13 | [TestFixture] 14 | public class AuthenticationTest 15 | { 16 | [Test] 17 | public void AuthSelf () 18 | { 19 | SaslServer server = new SaslServer (); 20 | SaslClient client = new SaslClient (); 21 | 22 | server.Peer = client; 23 | client.Peer = server; 24 | 25 | client.Identity = "1000"; 26 | server.Guid = UUID.Generate (); 27 | 28 | Assert.IsTrue (client.AuthenticateSelf ()); 29 | Assert.AreEqual (server.Guid, client.ActualId); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/BusTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using DBus; 4 | 5 | namespace DBus.Tests 6 | { 7 | [TestFixture] 8 | public class BusTests 9 | { 10 | /// 11 | /// Tests that re-opening a bus with the same address works (in other words that closing a connection works) 12 | /// 13 | [Test] 14 | public void ReopenedBusIsConnected() 15 | { 16 | var address = Environment.GetEnvironmentVariable ("DBUS_SESSION_BUS_ADDRESS"); 17 | var bus = Bus.Open (address); 18 | Assert.IsTrue (bus.IsConnected); 19 | bus.Close (); 20 | bus = Bus.Open (address); 21 | Assert.IsTrue (bus.IsConnected); 22 | } 23 | 24 | [Test] 25 | public void GetIdFromBusTest () 26 | { 27 | var sessionID = Bus.Session.GetId (); 28 | var systemID = Bus.System.GetId (); 29 | Assert.IsNotNull (sessionID); 30 | Assert.IsNotNull (systemID); 31 | Assert.AreNotEqual (systemID, sessionID); 32 | } 33 | 34 | [Test] 35 | public void DefaultBusesHaveUniqueName () 36 | { 37 | var name = Bus.Session.UniqueName; 38 | Assert.IsNotNull (name); 39 | Assert.IsNotEmpty (name); 40 | name = Bus.System.UniqueName; 41 | Assert.IsNotNull (name); 42 | Assert.IsNotEmpty (name); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/IntrospectorTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Xml.Linq; 4 | using System.Collections.Generic; 5 | 6 | using DBus; 7 | using DBus.Protocol; 8 | 9 | using NUnit; 10 | using NUnit.Framework; 11 | 12 | using org.freedesktop.DBus; 13 | 14 | namespace DBus.Tests 15 | { 16 | [TestFixture] 17 | public class IntrospectorTest 18 | { 19 | Introspector intro; 20 | 21 | [SetUp] 22 | public void Setup () 23 | { 24 | intro = new Introspector (); 25 | } 26 | 27 | [Interface ("org.dbussharp.IntrospectableTest")] 28 | interface IObjectIntrospected 29 | { 30 | string Method1 (int foo); 31 | [Obsolete] 32 | void Method2 (out long value); 33 | Dictionary Dict { get; } 34 | } 35 | 36 | public class ObjectIntrospectedImpl : IObjectIntrospected 37 | { 38 | public string Method1 (int foo) 39 | { 40 | return string.Empty; 41 | } 42 | 43 | public void Method2 (out long value) 44 | { 45 | value = 0; 46 | } 47 | 48 | public Dictionary Dict { 49 | get { return null; } 50 | } 51 | } 52 | 53 | const string expectedOutputSimpleInterface = @" 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | "; 73 | 74 | [Test] 75 | public void SimpleInterfaceTest () 76 | { 77 | intro.WriteStart (); 78 | intro.WriteType (typeof (ObjectIntrospectedImpl)); 79 | intro.WriteEnd (); 80 | Assert.IsTrue (XNode.DeepEquals (XDocument.Parse (expectedOutputSimpleInterface), 81 | XDocument.Parse (intro.Xml))); 82 | } 83 | 84 | [Test] 85 | public void InterfaceThroughWireTest () 86 | { 87 | ObjectIntrospectedImpl impl = new ObjectIntrospectedImpl (); 88 | ObjectPath path = new ObjectPath ("/org/dbussharp/test"); 89 | Bus.Session.Register (path, impl); 90 | 91 | const string ServiceName = "org.dbussharp.testservice"; 92 | Bus.Session.RequestName (ServiceName); 93 | var iface = Bus.Session.GetObject ("org.dbussharp.testservice", path); 94 | 95 | Assert.IsTrue (XNode.DeepEquals (XDocument.Parse (expectedOutputSimpleInterface), 96 | XDocument.Parse (iface.Introspect ()))); 97 | } 98 | 99 | [Test] 100 | public void TestIntrospectable () 101 | { 102 | var introspectable = Bus.Session.GetObject ("org.freedesktop.DBus", ObjectPath.Root); 103 | var xml = introspectable.Introspect (); 104 | Assert.IsNotNull (xml); 105 | Assert.IsNotEmpty (xml); 106 | 107 | var doc = XDocument.Parse (xml); 108 | Assert.AreEqual ((XName)"node", doc.Root.Name); 109 | // the main dbus object has two interfaces, the dbus interface and the introspectable one 110 | Assert.AreEqual (2, doc.Root.Elements ("interface").Count ()); 111 | var iface = doc.Root.Elements ("interface") 112 | .FirstOrDefault (e => ((string)e.Attribute ("name")) == "org.freedesktop.DBus.Introspectable"); 113 | Assert.IsNotNull (iface); 114 | Assert.AreEqual (1, iface.Elements ("method").Count ()); 115 | Assert.AreEqual ("Introspect", iface.Element ("method").Attribute ("name").Value); 116 | Assert.AreEqual (1, iface.Element ("method").Elements ("arg").Count ()); 117 | } 118 | } 119 | } 120 | 121 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | ASSEMBLY = dbus-sharp-tests 2 | TARGET = $(ASSEMBLY).dll 3 | XBUILD_Q = $(XBUILD) /nologo /verbosity:quiet 4 | 5 | NUNIT_CONSOLE = $$(echo $$(which nunit-console2 || which nunit-console)) 6 | RUNNER = $(NUNIT_CONSOLE) -nologo 7 | 8 | CSFILES = AddressTest.cs \ 9 | AuthenticationTest.cs \ 10 | MatchRuleTest.cs \ 11 | ObjectPathTest.cs \ 12 | SignatureTest.cs \ 13 | BusTests.cs \ 14 | ExportInterfaceTest.cs \ 15 | RenamedInterfaceTest.cs \ 16 | MessageReaderTest.cs \ 17 | MessageWriterTest.cs \ 18 | IntrospectorTest.cs 19 | 20 | if ENABLE_TESTS 21 | 22 | all: $(TARGET) 23 | 24 | $(TARGET): 25 | $(XBUILD_Q) dbus-sharp-tests.csproj 26 | 27 | test: $(TARGET) 28 | if test -z "$$DBUS_SESSION_BUS_ADDRESS" ; then \ 29 | eval `dbus-launch --sh-syntax` ; \ 30 | echo "D-Bus per-session daemon address is: $$DBUS_SESSION_BUS_ADDRESS" ; \ 31 | fi; $(RUNNER) $$TEST_HARNESS_FLAGS $(TARGET); 32 | 33 | check: test 34 | 35 | # This is not needed on that branch 36 | # it's for compat with wrench 37 | setup: ; 38 | run: check 39 | 40 | .PHONY: $(TARGET) 41 | 42 | endif 43 | 44 | EXTRA_DIST = \ 45 | $(CSFILES) \ 46 | dbus-sharp-tests.csproj 47 | 48 | CLEANFILES = \ 49 | $(TARGET) \ 50 | $(TARGET).mdb 51 | 52 | MAINTAINERCLEANFILES = \ 53 | Makefile.in 54 | -------------------------------------------------------------------------------- /tests/MatchRuleTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using NUnit.Framework; 7 | using DBus; 8 | using DBus.Protocol; 9 | 10 | namespace DBus.Tests 11 | { 12 | [TestFixture] 13 | public class MatchRuleTest 14 | { 15 | [Test] 16 | public void Parse () 17 | { 18 | string ruleText = @"member='Lala'"; 19 | MatchRule rule = MatchRule.Parse (ruleText); 20 | 21 | Assert.AreEqual (MessageType.All, rule.MessageType); 22 | Assert.AreEqual (0, rule.Args.Count); 23 | Assert.AreEqual (ruleText, rule.ToString ()); 24 | } 25 | 26 | [Test] 27 | public void ParsePathArgs () 28 | { 29 | string ruleText = @"arg0='La',arg1path='/Foo'"; 30 | MatchRule rule = MatchRule.Parse (ruleText); 31 | Assert.AreEqual (ruleText, rule.ToString ()); 32 | } 33 | 34 | [Test] 35 | public void CanonicalOrdering () 36 | { 37 | string ruleText = @"arg0='La',arg5path='/bar',arg2='Fa',destination='org.ndesk.Recipient',interface='org.ndesk.ITest',arg1path='/foo'"; 38 | string sortedRuleText = @"interface='org.ndesk.ITest',destination='org.ndesk.Recipient',arg0='La',arg1path='/foo',arg2='Fa',arg5path='/bar'"; 39 | MatchRule rule = MatchRule.Parse (ruleText); 40 | Assert.AreEqual (4, rule.Args.Count); 41 | Assert.AreEqual (sortedRuleText, rule.ToString ()); 42 | } 43 | 44 | // TODO: Should fail 45 | /* 46 | [Test] 47 | public void ParseArgsPartiallyBad () 48 | { 49 | string ruleText = @"arg0='A',arg4='Foo\'"; 50 | MatchRule.Parse (ruleText); 51 | } 52 | */ 53 | 54 | // TODO: Should fail 55 | /* 56 | [Test] 57 | [ExpectedException] 58 | public void ParseRepeated () 59 | { 60 | string ruleText = @"interface='org.ndesk.ITest',interface='org.ndesk.ITest2'"; 61 | MatchRule.Parse (ruleText); 62 | } 63 | */ 64 | 65 | // TODO: Should fail 66 | /* 67 | [Test] 68 | //[ExpectedException] 69 | public void ParseArgsRepeated () 70 | { 71 | string ruleText = @"arg0='A',arg0='A'"; 72 | MatchRule.Parse (ruleText); 73 | } 74 | */ 75 | 76 | [Test] 77 | public void ParseArgsMaxAllowed () 78 | { 79 | string ruleText = @"arg63='Foo'"; 80 | MatchRule.Parse (ruleText); 81 | } 82 | 83 | [Test] 84 | [ExpectedException] 85 | public void ParseArgsMoreThanAllowed () 86 | { 87 | string ruleText = @"arg64='Foo'"; 88 | MatchRule.Parse (ruleText); 89 | } 90 | 91 | [Test] 92 | public void ParseArgs () 93 | { 94 | string ruleText = @"arg5='F,o\'o\\\'\\',arg8=''"; 95 | MatchRule rule = MatchRule.Parse (ruleText); 96 | 97 | Assert.AreEqual (MessageType.All, rule.MessageType); 98 | Assert.AreEqual (2, rule.Args.Count); 99 | 100 | //Assert.AreEqual (@"F,o'o\'\", rule.Args[5].Value); 101 | //Assert.AreEqual (@"", rule.Args[8].Value); 102 | 103 | Assert.AreEqual (ruleText, rule.ToString ()); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/MessageReaderTest.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Runtime.InteropServices; 4 | using NUnit.Framework; 5 | using DBus; 6 | using DBus.Protocol; 7 | 8 | namespace DBus.Tests 9 | { 10 | [TestFixture] 11 | public class MessageReaderTest 12 | { 13 | [Test] 14 | public void ReadIntLittleEndian () 15 | { 16 | MessageReader reader = new MessageReader (EndianFlag.Little, new byte[] { 8, 8, 0, 0}); 17 | Assert.AreEqual (0x808, reader.ReadInt32 ()); 18 | Assert.IsFalse (reader.DataAvailable); 19 | } 20 | 21 | [Test] 22 | public void ReadIntBigEndian () 23 | { 24 | MessageReader reader = new MessageReader (EndianFlag.Big, new byte[] { 0, 0, 8, 8}); 25 | Assert.AreEqual (0x808, reader.ReadInt32 ()); 26 | Assert.IsFalse (reader.DataAvailable); 27 | } 28 | 29 | [Test] 30 | public void ReadIntArrayLittleEndian () 31 | { 32 | byte[] data = new byte[] { 16, 0, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0 }; 33 | MessageReader reader = new MessageReader (EndianFlag.Little, data); 34 | 35 | int[] array = (int[])reader.ReadArray (typeof (int)); 36 | Assert.IsNotNull (array); 37 | Assert.AreEqual (4, array.Length, "length"); 38 | CollectionAssert.AreEqual (new int[] { 0x808, 0x808, 0x808, 0x808}, array, "elements"); 39 | Assert.IsFalse (reader.DataAvailable); 40 | } 41 | 42 | [Test] 43 | public void ReadIntArrayBigEndian () 44 | { 45 | byte[] data = new byte[] { 0, 0, 0, 16, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8 }; 46 | MessageReader reader = new MessageReader (EndianFlag.Big, data); 47 | 48 | int[] array = (int[])reader.ReadArray (typeof (int)); 49 | Assert.IsNotNull (array); 50 | Assert.AreEqual (4, array.Length, "length"); 51 | CollectionAssert.AreEqual (new int[] { 0x808, 0x808, 0x808, 0x808}, array, "elements"); 52 | Assert.IsFalse (reader.DataAvailable); 53 | } 54 | 55 | [Test] 56 | public void ReadBooleanArrayLittleEndian () 57 | { 58 | byte[] data = new byte[] { 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 }; 59 | MessageReader reader = new MessageReader (EndianFlag.Little, data); 60 | 61 | bool[] array = (bool[])reader.ReadArray (typeof (bool)); 62 | Assert.IsNotNull (array); 63 | Assert.AreEqual (4, array.Length, "length"); 64 | CollectionAssert.AreEqual (new bool[] { true, false, true, true}, array, "elements"); 65 | Assert.IsFalse (reader.DataAvailable); 66 | } 67 | 68 | [Test] 69 | public void ReadBooleanArrayBigEndian () 70 | { 71 | byte[] data = new byte[] { 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 }; 72 | MessageReader reader = new MessageReader (EndianFlag.Big, data); 73 | 74 | bool[] array = (bool[])reader.ReadArray (typeof (bool)); 75 | Assert.IsNotNull (array); 76 | Assert.AreEqual (4, array.Length, "length"); 77 | CollectionAssert.AreEqual (new bool[] { true, false, true, true}, array, "elements"); 78 | Assert.IsFalse (reader.DataAvailable); 79 | } 80 | 81 | [StructLayout (LayoutKind.Sequential)] 82 | struct TestStruct { 83 | public int Item1; 84 | public long Item2; 85 | public int Item3; 86 | } 87 | 88 | [Test] 89 | public void ReadIntLongIntStructLittleEndian () 90 | { 91 | // (ixi) and (1, 2, 3) 92 | byte[] data = new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }; 93 | MessageReader reader = new MessageReader (EndianFlag.Little, data); 94 | 95 | TestStruct stct = (TestStruct)reader.ReadStruct (typeof (TestStruct)); 96 | Assert.AreEqual (1, stct.Item1); 97 | Assert.AreEqual (2, stct.Item2); 98 | Assert.AreEqual (3, stct.Item3); 99 | } 100 | 101 | [Test, ExpectedException (typeof (MessageReader.PaddingException))] 102 | public void ReadIntLongIntStructNonAlignedLittleEndian () 103 | { 104 | // (ixi) and (1, 2, 3) 105 | byte[] data = new byte[] { 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }; 106 | MessageReader reader = new MessageReader (EndianFlag.Little, data); 107 | 108 | TestStruct stct = (TestStruct)reader.ReadStruct (typeof (TestStruct)); 109 | } 110 | 111 | [StructLayout (LayoutKind.Sequential)] 112 | struct TestStruct2 { 113 | public int Item1; 114 | public int Item2; 115 | public int Item3; 116 | } 117 | 118 | [Test] 119 | public void ReadIntIntIntStructLittleEndian () 120 | { 121 | // Will test the fast path 122 | byte[] data = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 }; 123 | MessageReader reader = new MessageReader (EndianFlag.Little, data); 124 | 125 | TestStruct2 stct = (TestStruct2)reader.ReadStruct (typeof (TestStruct2)); 126 | Assert.AreEqual (1, stct.Item1); 127 | Assert.AreEqual (2, stct.Item2); 128 | Assert.AreEqual (3, stct.Item3); 129 | } 130 | 131 | [Test] 132 | public void ReadIntIntIntStructLittleEndianGeneric () 133 | { 134 | // Will test the fast path 135 | byte[] data = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 }; 136 | MessageReader reader = new MessageReader (EndianFlag.Little, data); 137 | 138 | TestStruct2 stct = reader.ReadStruct (); 139 | Assert.AreEqual (1, stct.Item1); 140 | Assert.AreEqual (2, stct.Item2); 141 | Assert.AreEqual (3, stct.Item3); 142 | } 143 | 144 | [StructLayout (LayoutKind.Sequential)] 145 | struct TestStruct3 { 146 | public long Item1; 147 | public ulong Item2; 148 | public double Item3; 149 | } 150 | 151 | [Test] 152 | public void ReadSameAlignementStructNativeEndian () 153 | { 154 | // Will test the fast path with mixed types but same alignement 155 | byte[] data = new byte[8 * 3]; 156 | Array.Copy (BitConverter.GetBytes ((long)1), 0, data, 0, 8); 157 | Array.Copy (BitConverter.GetBytes (ulong.MaxValue), 0, data, 8, 8); 158 | Array.Copy (BitConverter.GetBytes ((double)3.3), 0, data, 16, 8); 159 | 160 | MessageReader reader = new MessageReader (BitConverter.IsLittleEndian ? EndianFlag.Little : EndianFlag.Big, data); 161 | 162 | TestStruct3 stct = (TestStruct3)reader.ReadStruct (typeof (TestStruct3)); 163 | Assert.AreEqual (1, stct.Item1); 164 | Assert.AreEqual (ulong.MaxValue, stct.Item2); 165 | Assert.AreEqual (3.3, stct.Item3); 166 | } 167 | 168 | [Test] 169 | public void ReadSameAlignementStructNonNativeEndian () 170 | { 171 | // Will test the fast path with mixed types but same alignement 172 | byte[] data = new byte[8 * 3]; 173 | Array.Copy (BitConverter.GetBytes ((long)1), 0, data, 0, 8); 174 | Array.Copy (BitConverter.GetBytes (ulong.MaxValue), 0, data, 8, 8); 175 | Array.Copy (BitConverter.GetBytes ((double)3.3), 0, data, 16, 8); 176 | // Swap value to simulate other endianness 177 | for (int i = 0; i < data.Length; i += 8) { 178 | for (int j = 0; j < 4; j++) { 179 | data[i + j] = (byte)(data[i + j] ^ data[i + 7 - j]); 180 | data[i + 7 - j] = (byte)(data[i + j] ^ data[i + 7 - j]); 181 | data[i + j] = (byte)(data[i + j] ^ data[i + 7 - j]); 182 | } 183 | } 184 | 185 | MessageReader reader = new MessageReader (!BitConverter.IsLittleEndian ? EndianFlag.Little : EndianFlag.Big, data); 186 | 187 | TestStruct3 stct = (TestStruct3)reader.ReadStruct (typeof (TestStruct3)); 188 | Assert.AreEqual (1, stct.Item1); 189 | Assert.AreEqual (ulong.MaxValue, stct.Item2); 190 | Assert.AreEqual (3.3, stct.Item3); 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /tests/MessageWriterTest.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Runtime.InteropServices; 4 | using NUnit.Framework; 5 | using DBus; 6 | using DBus.Protocol; 7 | 8 | namespace DBus.Tests 9 | { 10 | [TestFixture] 11 | public class MessageWriterTest 12 | { 13 | DBus.Protocol.MessageWriter writer; 14 | 15 | [SetUp] 16 | public void Setup () 17 | { 18 | writer = new DBus.Protocol.MessageWriter (); 19 | } 20 | 21 | [Test] 22 | public void WriteIntArrayTest () 23 | { 24 | var initial = new int[] { 1, 2, 3, 4 }; 25 | writer.WriteArray (initial); 26 | byte[] result = writer.ToArray (); 27 | 28 | Assert.AreEqual (4 + initial.Length * 4, result.Length); 29 | uint length = BitConverter.ToUInt32 (result, 0); 30 | Assert.AreEqual (initial.Length * 4, length); 31 | for (int i = 0; i < initial.Length; i++) 32 | Assert.AreEqual (i + 1, BitConverter.ToInt32 (result, 4 + 4 * i), "#" + i); 33 | } 34 | 35 | struct TestStruct 36 | { 37 | public int bleh; 38 | public uint bloup; 39 | public float blop; 40 | } 41 | 42 | [Test] 43 | public void WriteStructTest () 44 | { 45 | TestStruct stct = new TestStruct (); 46 | stct.bleh = 5; 47 | stct.bloup = 3; 48 | stct.blop = 5.5f; 49 | 50 | writer.WriteStructure (stct); 51 | byte[] result = writer.ToArray (); 52 | Assert.AreEqual (5, BitConverter.ToInt32 (result, 0)); 53 | Assert.AreEqual ((uint)3, BitConverter.ToUInt32 (result, 4)); 54 | Assert.AreEqual (5.5f, BitConverter.ToSingle (result, 8)); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /tests/ObjectPathTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Alp Toker 2 | // Copyright 2010 Alan McGovern 3 | // This software is made available under the MIT License 4 | // See COPYING for details 5 | 6 | using System; 7 | using NUnit.Framework; 8 | using DBus; 9 | 10 | namespace DBus.Tests 11 | { 12 | [TestFixture] 13 | public class ObjectPathTest 14 | { 15 | [Test] 16 | [ExpectedException (typeof (ArgumentException))] 17 | public void InvalidStartingCharacter () 18 | { 19 | // Paths must start with "/" 20 | new ObjectPath ("no_starting_slash"); 21 | } 22 | 23 | [Test] 24 | [ExpectedException (typeof (ArgumentException))] 25 | public void InvalidEndingCharacter () 26 | { 27 | // Paths must not end with "/" 28 | new ObjectPath ("/ends_with_slash/"); 29 | } 30 | 31 | [Test] 32 | [ExpectedException (typeof (ArgumentException))] 33 | public void MultipleConsecutiveSlash () 34 | { 35 | // Paths must not contains consecutive "/" 36 | new ObjectPath ("/foo//bar"); 37 | } 38 | 39 | [Test] 40 | [ExpectedException (typeof (ArgumentException))] 41 | public void InvalidCharacters () 42 | { 43 | // Paths must be in the range "[A-Z][a-z][0-9]_" 44 | new ObjectPath ("/?valid/path/invalid?/character.^"); 45 | } 46 | 47 | [Test] 48 | public void ConstructorTest () 49 | { 50 | var x = new ObjectPath ("/"); 51 | Assert.AreEqual (x.ToString (), "/", "#1"); 52 | Assert.AreEqual (x, ObjectPath.Root, "#2"); 53 | 54 | x = new ObjectPath ("/this/01234567890/__Test__"); 55 | Assert.AreEqual ("/this/01234567890/__Test__", x.ToString (), "#3"); 56 | } 57 | 58 | [Test] 59 | public void Equality () 60 | { 61 | string pathText = "/org/freedesktop/DBus"; 62 | 63 | ObjectPath a = new ObjectPath (pathText); 64 | ObjectPath b = new ObjectPath (pathText); 65 | 66 | Assert.IsTrue (a.Equals (b)); 67 | Assert.AreEqual (String.Empty.CompareTo (null), a.CompareTo (null)); 68 | Assert.IsTrue (a == b); 69 | Assert.IsFalse (a != b); 70 | 71 | ObjectPath c = new ObjectPath (pathText + "/foo"); 72 | Assert.IsFalse (a == c); 73 | } 74 | 75 | [Test] 76 | [ExpectedException (typeof (ArgumentNullException))] 77 | public void NullConstructor () 78 | { 79 | new ObjectPath (null); 80 | } 81 | 82 | [Test] 83 | [ExpectedException (typeof (ArgumentException))] 84 | public void EmptyStringConstructor () 85 | { 86 | new ObjectPath (""); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /tests/RenamedInterfaceTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Bertrand Lorentz 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using NUnit.Framework; 7 | using DBus; 8 | using org.freedesktop.DBus; 9 | 10 | namespace DBus.Tests 11 | { 12 | [TestFixture] 13 | public class RenamedInterfaceTest 14 | { 15 | string bus_name = "org.dbussharp.restaurant"; 16 | ObjectPath path = new ObjectPath ("/org/dbussharp/restaurant"); 17 | 18 | [Test] 19 | public void FirstInterface () 20 | { 21 | var restaurant = new StandingRestaurant (); 22 | Assert.AreEqual (Bus.Session.RequestName (bus_name), RequestNameReply.PrimaryOwner); 23 | Bus.Session.Register (path, restaurant); 24 | 25 | try { 26 | Assert.AreEqual ("cheese", GetFood (false)); 27 | } finally { 28 | Bus.Session.ReleaseName (bus_name); 29 | Bus.Session.Unregister (path); 30 | } 31 | } 32 | 33 | [Test] 34 | public void SecondInterface () 35 | { 36 | var restaurant = new SeatedRestaurant (); 37 | Bus.Session.Register (path, restaurant); 38 | Assert.AreEqual (Bus.Session.RequestName (bus_name), RequestNameReply.PrimaryOwner); 39 | 40 | try { 41 | Assert.AreEqual ("bacon", GetFood (true)); 42 | } finally { 43 | Bus.Session.ReleaseName (bus_name); 44 | Bus.Session.Unregister (path); 45 | } 46 | } 47 | 48 | string GetFood (bool second) 49 | { 50 | IRestaurantBase restaurant = null; 51 | if (second) 52 | restaurant = Bus.Session.GetObject (bus_name, path); 53 | else 54 | restaurant = Bus.Session.GetObject (bus_name, path); 55 | return restaurant.Food (); 56 | } 57 | } 58 | 59 | interface IRestaurantBase { string Food (); } 60 | [Interface ("org.dbussharp.restaurant")] interface IRestaurant : IRestaurantBase { } 61 | [Interface ("org.dbussharp.restaurant.table")] interface IRestaurantv2 : IRestaurantBase { } 62 | 63 | public class StandingRestaurant : IRestaurant 64 | { 65 | public string Food () 66 | { 67 | return "cheese"; 68 | } 69 | } 70 | 71 | public class SeatedRestaurant : IRestaurantv2 72 | { 73 | public string Food () 74 | { 75 | return "bacon"; 76 | } 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /tests/SignatureTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Linq; 7 | using System.Collections.Generic; 8 | 9 | using NUnit.Framework; 10 | using DBus; 11 | using DBus.Protocol; 12 | 13 | namespace DBus.Tests 14 | { 15 | [TestFixture] 16 | public class SignatureTest 17 | { 18 | [Test] 19 | [ExpectedException (typeof (ArgumentNullException))] 20 | public void Parse_NullString () 21 | { 22 | new Signature ((string) null); 23 | } 24 | 25 | [Test] 26 | [ExpectedException (typeof (ArgumentNullException))] 27 | public void Parse_NullArray () 28 | { 29 | new Signature ((DType []) null); 30 | } 31 | 32 | [Test] 33 | public void Parse_Empty () 34 | { 35 | var x = new Signature (""); 36 | Assert.AreEqual (Signature.Empty, x, "#1"); 37 | } 38 | 39 | [Test] 40 | public void ParseStruct () 41 | { 42 | var sig = new Signature ("(iu)"); 43 | Assert.IsTrue (sig.IsStruct, "#1"); 44 | 45 | var elements = sig.GetFieldSignatures ().ToArray (); 46 | Assert.AreEqual (2, elements.Length, "#2"); 47 | Assert.AreEqual (Signature.Int32Sig, elements [0], "#3"); 48 | Assert.AreEqual (Signature.UInt32Sig, elements [1], "#4"); 49 | } 50 | 51 | [Test] 52 | [ExpectedException (typeof (ArgumentException))] 53 | public void ParseInvalid_TypeCode () 54 | { 55 | // Use an invalid type code 56 | new Signature ("z"); 57 | } 58 | 59 | [Test] 60 | [ExpectedException (typeof (ArgumentException))] 61 | public void ParseInvalid_MissingClosingBrace () 62 | { 63 | // Use an invalid type code 64 | new Signature ("(i"); 65 | } 66 | 67 | [Test] 68 | [ExpectedException (typeof (ArgumentException))] 69 | public void ParseInvalid_MissingOpeningBrace () 70 | { 71 | // Use an invalid type code 72 | new Signature ("i)"); 73 | } 74 | 75 | [Test] 76 | public void Parse_ArrayOfString () 77 | { 78 | string sigText = "as"; 79 | Signature sig = new Signature (sigText); 80 | 81 | Assert.IsTrue (sig.IsArray); 82 | Assert.IsFalse (sig.IsDict); 83 | Assert.IsFalse (sig.IsPrimitive); 84 | } 85 | 86 | [Test] 87 | public void Equality () 88 | { 89 | string sigText = "as"; 90 | Signature a = new Signature (sigText); 91 | Signature b = new Signature (sigText); 92 | 93 | Assert.IsTrue (a == b); 94 | Assert.IsTrue (a.GetElementSignature () == Signature.StringSig); 95 | 96 | Assert.AreEqual (Signature.ArraySig + Signature.StringSig + Signature.Empty, new Signature ("as")); 97 | } 98 | 99 | [Test] 100 | public void FixedSize () 101 | { 102 | Signature sig; 103 | 104 | sig = new Signature ("s"); 105 | Assert.IsFalse (sig.IsFixedSize); 106 | 107 | sig = new Signature ("as"); 108 | Assert.IsFalse (sig.IsFixedSize); 109 | 110 | sig = new Signature ("u"); 111 | Assert.IsTrue (sig.IsFixedSize); 112 | 113 | sig = new Signature ("u(ub)"); 114 | Assert.IsTrue (sig.IsFixedSize); 115 | 116 | sig = new Signature ("u(uvb)"); 117 | Assert.IsFalse (sig.IsFixedSize); 118 | } 119 | 120 | [Test] 121 | public void CombineSignatures () 122 | { 123 | var x = Signature.ByteSig + Signature.StringSig; 124 | Assert.AreEqual ("ys", x.Value, "#1"); 125 | } 126 | 127 | [Test] 128 | public void MakeArray () 129 | { 130 | var x = Signature.MakeArray (Signature.Int32Sig); 131 | Assert.AreEqual ("ai", x.Value, "#1"); 132 | } 133 | 134 | [Test] 135 | public void MakeArrayOfStruct () 136 | { 137 | var type = Signature.MakeStruct (Signature.Int32Sig + Signature.Int32Sig); 138 | var x = Signature.MakeArray (type); 139 | Assert.AreEqual ("a(ii)", x.Value, "#1"); 140 | } 141 | 142 | [Test] 143 | public void MakeArrayOfArray () 144 | { 145 | var x = Signature.MakeArray (Signature.Int32Sig); 146 | x = Signature.MakeArray (x); 147 | Assert.AreEqual ("aai", x.Value, "#1"); 148 | } 149 | 150 | [Test] 151 | [ExpectedException (typeof (ArgumentException))] 152 | public void MakeArray_NotSingleCompleteType () 153 | { 154 | Signature.MakeArray (Signature.Int32Sig + Signature.UInt16Sig); 155 | } 156 | 157 | [Test] 158 | public void MakeStruct () 159 | { 160 | // 'r' isn't used, just brackets. 161 | var x = Signature.MakeStruct (Signature.ByteSig + Signature.StringSig); 162 | Assert.AreEqual ("(ys)", x.Value, "#1"); 163 | } 164 | 165 | [Test] 166 | [ExpectedException (typeof (ArgumentException))] 167 | public void MakeStruct_Empty () 168 | { 169 | Signature.MakeStruct (Signature.Empty); 170 | } 171 | 172 | [Test] 173 | public void MakeDictionaryEntry () 174 | { 175 | // Make a valid dictionary entry, should appear as an array of dict_entries 176 | var x = Signature.MakeDictEntry (Signature.StringSig, Signature.Int32Sig); 177 | Assert.AreEqual ("{si}", x.Value, "#1"); 178 | } 179 | 180 | [Test] 181 | public void MakeDictionary () 182 | { 183 | // 'r' isn't used, just brackets. 184 | var x = Signature.MakeDict (Signature.StringSig, Signature.Int32Sig); 185 | Assert.AreEqual ("a{si}", x.Value, "#1"); 186 | } 187 | 188 | [Test] 189 | [ExpectedException (typeof (ArgumentException))] 190 | public void MakeDictionary_TwoCompleteTypes_Key () 191 | { 192 | // They key is not a single complete type 193 | Signature.MakeDictEntry (Signature.StringSig + Signature.Int32Sig, Signature.Int32Sig); 194 | } 195 | 196 | [Test] 197 | [ExpectedException (typeof (ArgumentException))] 198 | public void MakeDictionary_TwoCompleteTypes_Value () 199 | { 200 | // They value is not a single complete type 201 | Signature.MakeDictEntry (Signature.StringSig, Signature.Int32Sig + Signature.Int32Sig); 202 | } 203 | 204 | [Test] 205 | public void ComplexSignatureIsSingleTypeTest () 206 | { 207 | string sig = "(ssa{i(ss)})"; 208 | Assert.IsTrue (new Signature (sig).IsSingleCompleteType); 209 | } 210 | 211 | [Test] 212 | public void AssertComplexTypeToTypeTest () 213 | { 214 | var sig = new Signature ("(ssa{i(ss)})"); 215 | Assert.AreEqual (typeof (DBusStruct>>), 216 | sig.ToType ()); 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /tests/dbus-sharp-tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {40AB91F9-BA2F-4C02-99F5-1F299CDBE86D} 9 | Library 10 | DBus.Tests 11 | dbus-sharp-tests 12 | v3.5 13 | true 14 | ..\dbus-sharp.snk 15 | 16 | 17 | True 18 | full 19 | False 20 | . 21 | DEBUG 22 | prompt 23 | 4 24 | False 25 | 0219 26 | 27 | 28 | none 29 | False 30 | . 31 | prompt 32 | 4 33 | False 34 | 0219 35 | 36 | 37 | 38 | 39 | 40 | False 41 | False 42 | 43 | 44 | False 45 | False 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | {09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C} 67 | dbus-sharp 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /tools/Introspect.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Xml; 9 | using System.Xml.Serialization; 10 | using DBus; 11 | using Schemas; 12 | 13 | public class test 14 | { 15 | public static void Main (string[] args) 16 | { 17 | string fname = args[0]; 18 | StreamReader sr = new StreamReader (fname); 19 | XmlSerializer sz = new XmlSerializer (typeof (Node)); 20 | Node node = (Node)sz.Deserialize (sr); 21 | 22 | Interface iface = node.Interfaces[1]; 23 | 24 | foreach (Method meth in iface.Methods) { 25 | Console.Write (meth.Name); 26 | Console.Write (" ("); 27 | 28 | if (meth.Arguments != null) 29 | foreach (Argument arg in meth.Arguments) 30 | Console.Write ("[" + arg.Direction + "] " + arg.Type + " " + arg.Name + ", "); 31 | Console.Write (");"); 32 | Console.WriteLine (); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tools/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = \ 2 | Introspect.cs \ 3 | Monitor.cs 4 | -------------------------------------------------------------------------------- /tools/Monitor.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | using System.Text; 7 | using System.IO; 8 | using System.Collections.Generic; 9 | using DBus; 10 | using org.freedesktop.DBus; 11 | 12 | class BusMonitor 13 | { 14 | static Connection bus = null; 15 | 16 | public static int Main (string[] args) 17 | { 18 | bus = null; 19 | bool readIn = false; 20 | bool readOut = false; 21 | List rules = new List (); 22 | 23 | for (int i = 0 ; i != args.Length ; i++) { 24 | string arg = args[i]; 25 | 26 | if (!arg.StartsWith ("--")) { 27 | rules.Add (arg); 28 | continue; 29 | } 30 | 31 | switch (arg) 32 | { 33 | case "--stdin": 34 | readIn = true; 35 | break; 36 | case "--stdout": 37 | readOut = true; 38 | break; 39 | case "--system": 40 | bus = Bus.System; 41 | break; 42 | case "--session": 43 | bus = Bus.Session; 44 | break; 45 | default: 46 | Console.Error.WriteLine ("Usage: monitor.exe [--stdin|--stdout|--system|--session] [watch expressions]"); 47 | Console.Error.WriteLine (" If no watch expressions are provided, defaults will be used."); 48 | return 1; 49 | } 50 | } 51 | 52 | if (bus == null) 53 | bus = Bus.Session; 54 | 55 | if (rules.Count != 0) { 56 | //install custom match rules only 57 | foreach (string rule in rules) 58 | bus.AddMatch (rule); 59 | } else { 60 | //no custom match rules, install the defaults 61 | bus.AddMatch (MessageFilter.CreateMatchRule (MessageType.Signal)); 62 | bus.AddMatch (MessageFilter.CreateMatchRule (MessageType.MethodReturn)); 63 | bus.AddMatch (MessageFilter.CreateMatchRule (MessageType.Error)); 64 | bus.AddMatch (MessageFilter.CreateMatchRule (MessageType.MethodCall)); 65 | } 66 | 67 | if (readIn) { 68 | ReadIn (); 69 | return 0; 70 | } 71 | 72 | if (readOut) { 73 | ReadOut (); 74 | return 0; 75 | } 76 | 77 | PrettyPrintOut (); 78 | return 0; 79 | } 80 | 81 | static void ReadIn () 82 | { 83 | TextReader r = Console.In; 84 | 85 | while (true) { 86 | Message msg = MessageDumper.ReadMessage (r); 87 | if (msg == null) 88 | break; 89 | PrintMessage (msg); 90 | Console.WriteLine (); 91 | 92 | /* 93 | byte[] header = MessageDumper.ReadBlock (r); 94 | if (header == null) 95 | break; 96 | PrintHeader (header); 97 | 98 | byte[] body = MessageDumper.ReadBlock (r); 99 | PrintBody (header); 100 | */ 101 | } 102 | } 103 | 104 | static void ReadOut () 105 | { 106 | TextWriter w = Console.Out; 107 | 108 | DumpConn (bus, w); 109 | 110 | while (true) { 111 | Message msg = bus.Transport.ReadMessage (); 112 | if (msg == null) 113 | break; 114 | DumpMessage (msg, w); 115 | } 116 | } 117 | 118 | static void PrettyPrintOut () 119 | { 120 | while (true) { 121 | Message msg = bus.Transport.ReadMessage (); 122 | if (msg == null) 123 | break; 124 | PrintMessage (msg); 125 | Console.WriteLine (); 126 | } 127 | } 128 | 129 | static void DumpConn (Connection conn, TextWriter w) 130 | { 131 | w.WriteLine ("# This is a managed D-Bus protocol dump"); 132 | w.WriteLine (); 133 | w.WriteLine ("# Machine: " + Connection.MachineId); 134 | w.WriteLine ("# Connection: " + conn.Id); 135 | w.WriteLine ("# Date: " + DateTime.Now.ToString ("F")); 136 | w.WriteLine (); 137 | } 138 | 139 | static DateTime startTime = DateTime.Now; 140 | static void DumpMessage (Message msg, TextWriter w) 141 | { 142 | w.WriteLine ("# Message: " + msg.Header.Serial); 143 | 144 | TimeSpan delta = DateTime.Now - startTime; 145 | startTime = DateTime.Now; 146 | w.WriteLine ("# Time delta: " + delta.Ticks); 147 | 148 | w.WriteLine ("# Header"); 149 | MessageDumper.WriteBlock (msg.GetHeaderData (), w); 150 | w.WriteLine ("# Body"); 151 | MessageDumper.WriteBlock (msg.Body, w); 152 | 153 | w.WriteLine (); 154 | w.Flush (); 155 | } 156 | 157 | const string indent = " "; 158 | 159 | static void PrintMessage (Message msg) 160 | { 161 | Console.WriteLine ("Message (" + msg.Header.Endianness + " endian, v" + msg.Header.MajorVersion + "):"); 162 | Console.WriteLine (indent + "Type: " + msg.Header.MessageType); 163 | Console.WriteLine (indent + "Flags: " + msg.Header.Flags); 164 | Console.WriteLine (indent + "Serial: " + msg.Header.Serial); 165 | 166 | //foreach (HeaderField hf in msg.HeaderFields) 167 | // Console.WriteLine (indent + hf.Code + ": " + hf.Value); 168 | Console.WriteLine (indent + "Header Fields:"); 169 | foreach (KeyValuePair field in msg.Header.Fields) 170 | Console.WriteLine (indent + indent + field.Key + ": " + field.Value); 171 | 172 | Console.WriteLine (indent + "Body (" + msg.Header.Length + " bytes):"); 173 | if (msg.Body != null) { 174 | MessageReader reader = new MessageReader (msg); 175 | 176 | int argNum = 0; 177 | foreach (Signature sig in msg.Signature.GetParts ()) { 178 | //Console.Write (indent + indent + "arg" + argNum + " " + sig + ": "); 179 | PrintValue (reader, sig, 1); 180 | /* 181 | if (sig.IsPrimitive) { 182 | object arg = reader.ReadValue (sig[0]); 183 | Console.WriteLine (arg); 184 | } else { 185 | if (sig.IsArray) { 186 | //foreach (Signature elemSig in writer.StepInto (sig)) 187 | } 188 | reader.StepOver (sig); 189 | Console.WriteLine ("?"); 190 | } 191 | */ 192 | argNum++; 193 | } 194 | } 195 | } 196 | 197 | static void PrintValue (MessageReader reader, Signature sig, int depth) 198 | { 199 | string indent = new String (' ', depth * 2); 200 | indent += " "; 201 | 202 | //Console.Write (indent + indent + "arg" + argNum + " " + sig + ": "); 203 | Console.Write (indent); 204 | if (sig == Signature.VariantSig) { 205 | foreach (Signature elemSig in reader.StepInto (sig)) { 206 | Console.WriteLine ("Variant '{0}' (", elemSig); 207 | PrintValue (reader, elemSig, depth + 1); 208 | Console.WriteLine (indent + ")"); 209 | } 210 | } else if (sig.IsPrimitive) { 211 | object arg = reader.ReadValue (sig[0]); 212 | Type argType = sig.ToType (); 213 | if (sig == Signature.StringSig || sig == Signature.ObjectPathSig) 214 | Console.WriteLine ("{0} \"{1}\"", argType.Name, arg); 215 | else if (sig == Signature.SignatureSig) 216 | Console.WriteLine ("{0} '{1}'", argType.Name, arg); 217 | else 218 | Console.WriteLine ("{0} {1}", argType.Name, arg); 219 | } else if (sig.IsArray) { 220 | Console.WriteLine ("Array ["); 221 | foreach (Signature elemSig in reader.StepInto (sig)) 222 | PrintValue (reader, elemSig, depth + 1); 223 | Console.WriteLine (indent + "]"); 224 | } else if (sig.IsDictEntry) { 225 | Console.WriteLine ("DictEntry {"); 226 | foreach (Signature elemSig in reader.StepInto (sig)) 227 | PrintValue (reader, elemSig, depth + 1); 228 | Console.WriteLine (indent + "}"); 229 | } else if (sig.IsStruct) { 230 | Console.WriteLine ("Struct {"); 231 | foreach (Signature elemSig in reader.StepInto (sig)) 232 | PrintValue (reader, elemSig, depth + 1); 233 | Console.WriteLine (indent + "}"); 234 | } else { 235 | reader.StepOver (sig); 236 | Console.WriteLine ("'{0}'?", sig); 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /tools/UuidGen.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Alp Toker 2 | // This software is made available under the MIT License 3 | // See COPYING for details 4 | 5 | using System; 6 | 7 | public class UuidGen 8 | { 9 | public static void Main (string[] args) 10 | { 11 | throw new NotImplementedException ("Not yet supprted"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tools/dbus-monitor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {736160C3-844E-43D9-8106-E492D74D92CD} 7 | 9.0.30729 8 | 2.0 9 | Exe 10 | false 11 | dbus-monitor 12 | 512 13 | DBus 14 | v3.5 15 | 16 | 17 | True 18 | full 19 | False 20 | . 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | True 28 | . 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {09A0200F-F3AF-4BD6-9EC4-E7D80D273E4C} 40 | dbus-sharp 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tools/tools.mk: -------------------------------------------------------------------------------- 1 | all: dbus-monitor.exe 2 | 3 | CSC=mcs 4 | CSFLAGS=-debug 5 | 6 | dbus-monitor.exe: Monitor.cs 7 | $(CSC) $(CSFLAGS) -keyfile:../dbus-sharp.snk -r:../src/dbus-sharp.dll -out:$@ $^ 8 | 9 | --------------------------------------------------------------------------------