summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorJosé Alburquerque <jaalburqu@svn.gnome.org>2011-01-10 02:27:31 -0500
committerJosé Alburquerque <jaalburqu@svn.gnome.org>2011-01-10 02:27:31 -0500
commitd36542c993bf2abaeef926f31b5736856c413f79 (patch)
tree3975da8b82bef81d822d1dace1e7b97d8a3d675f /examples
parentf23cecd5a7a242688abf36b433ae8c4c099f06c5 (diff)
downloadglibmm-d36542c993bf2abaeef926f31b5736856c413f79.tar.gz
DBus: Add a peer example to test the DBusServer class.
* gio/src/dbusconnection.{ccg,hg}: Reorder the VariantBase 'parameters' parameter in the call*() methods to come after the method_name parameter. * gio/src/dbusintrospection.hg: Use refreturn for methods where the C API does not automatically reference the return. * gio/src/dbusserver.{ccg,hg}: Add non-observable constructors and create() methods. * glib/src/variant.{ccg,hg} (create_tuple): Renamed from create(). Write this method to be more specific for tuples (it's probably the only case where this method might be used). Dealing with tuples still feels awkward with the method. Maybe there's a better way. * examples/Makefile.am: * examples/dbus/peer.cc: * examples/dbus/userbus.cc: * examples/dbus/well-known-address-client.cc: Add the new server/client peer example (named peer). The example crashes because the C API seems to not deal with empty strings "" well, but at least there is now an example. Making sure it runs well is necessary. Also rename the previous example to userbus.cc.
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile.am9
-rw-r--r--examples/dbus/peer.cc258
-rw-r--r--examples/dbus/userbus.cc (renamed from examples/dbus/well-known-address-client.cc)2
3 files changed, 265 insertions, 4 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am
index d8733af9..e65dbfb9 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -20,7 +20,8 @@ AUTOMAKE_OPTIONS = subdir-objects
check_PROGRAMS = \
child_watch/child_watch \
compose/example \
- dbus/well-known-address-client \
+ dbus/peer \
+ dbus/userbus \
iochannel_stream/example \
keyfile/example \
markup/parser \
@@ -74,8 +75,10 @@ thread_threadpool_SOURCES = thread/threadpool.cc
thread_threadpool_LDADD = $(thread_ldadd)
# giomm examples
-dbus_well_known_address_client_SOURCES = dbus/well-known-address-client.cc
-dbus_well_known_address_client_LDADD = $(giomm_ldadd)
+dbus_peer_SOURCES = dbus/peer.cc
+dbus_peer_LDADD = $(giomm_ldadd)
+dbus_userbus_SOURCES = dbus/userbus.cc
+dbus_userbus_LDADD = $(giomm_ldadd)
network_resolver_SOURCES = network/resolver.cc
network_resolver_LDADD = $(giomm_ldadd)
diff --git a/examples/dbus/peer.cc b/examples/dbus/peer.cc
new file mode 100644
index 00000000..ea04b2ab
--- /dev/null
+++ b/examples/dbus/peer.cc
@@ -0,0 +1,258 @@
+/* Copyright (C) 2011 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* For some usage examples see the C API's GDBusServer's example from which
+ * this example was adapted.
+ */
+
+#include <giomm.h>
+#include <glibmm.h>
+#include <iostream>
+
+static Glib::RefPtr<Gio::DBusNodeInfo> introspection_data;
+
+static Glib::ustring introspection_xml =
+ "<node>"
+ " <interface name='org.glibmm.GDBus.TestPeerInterface'>"
+ " <method name='HelloWorld'>"
+ " <arg type='s' name='greeting' direction='in'/>"
+ " <arg type='s' name='response' direction='out'/>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+// This variable is used to keep an incoming connection active.
+Glib::RefPtr<Gio::DBusConnection> keep_connection;
+
+static void on_method_call(const Glib::RefPtr<Gio::DBusConnection>&,
+ const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */,
+ const Glib::ustring& /* interface_name */, const Glib::ustring& method_name,
+ // Since the parameters are generally tuples, get them from the invocation.
+ const Glib::VariantBase& /* parameters */,
+ const Glib::RefPtr<Gio::DBusMethodInvocation>& invocation)
+{
+ if(method_name == "HelloWorld")
+ {
+ // Get parameters.
+ Glib::VariantContainerBase parameters;
+ invocation->get_parameters(parameters);
+
+ // Get (expected) single string in tupple.
+ Glib::Variant<Glib::ustring> param;
+ parameters.get(param);
+
+ Glib::ustring response = "You said: '" + param.get() + "'.";
+
+ Glib::Variant<Glib::ustring> answer =
+ Glib::Variant<Glib::ustring>::create(response);
+
+ invocation->return_value(answer);
+
+ std::cout << "Client said '" << param.get() << "'." << std::endl;
+ }
+}
+
+// Create the interface VTable.
+static const Gio::DBusInterfaceVTable
+ interface_vtable(sigc::ptr_fun(&on_method_call));
+
+bool on_new_connection(const Glib::RefPtr<Gio::DBusConnection>& connection)
+{
+ Glib::RefPtr<Gio::Credentials> credentials =
+ connection->get_peer_credentials();
+
+ std::string credentials_str;
+
+ if(!credentials)
+ credentials_str = "(no credentials received)";
+ else
+ credentials_str = credentials->to_string();
+
+ std::cout <<
+ "Client connected." << std::endl <<
+ "Peer credentials: " << credentials_str << std::endl <<
+ "Negotiated capabilities: unix-fd-passing=" << (connection->get_capabilities() & Gio::DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING) << std::endl;
+
+ // In order for the connection to stay active the reference to the
+ // connection must be kept so store the connection in a global variable.
+ keep_connection = connection;
+
+ guint reg_id = connection->register_object("/org/glibmm/GDBus/TestObject",
+ introspection_data->lookup_interface("org.glibmm.GDBus.TestPeerInterface"),
+ &interface_vtable);
+
+ if(reg_id == 0)
+ {
+ std::cerr << "Registration of object for incoming connection not "
+ "possible." << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+void run_as_server(Glib::ustring address, bool allow_anonymous)
+{
+ Glib::ustring guid = Gio::DBus::generate_guid();
+ Gio::DBusServerFlags flags = Gio::DBUS_SERVER_FLAGS_NONE;
+
+ if(allow_anonymous)
+ flags |= Gio::DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
+
+ Glib::RefPtr<Gio::DBusServer> server;
+
+ try
+ {
+ server = Gio::DBusServer::create_sync(address, guid, flags);
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << "Error creating server at address: " << address <<
+ ": " << ex.what() << "." << std::endl;
+ }
+
+ server->start();
+
+ std::cout << "Server is listening at: " << server->get_client_address() <<
+ "." << std::endl;
+
+ server->signal_new_connection().connect(sigc::ptr_fun(&on_new_connection));
+
+ Glib::RefPtr<Glib::MainLoop> loop = Glib::MainLoop::create();
+ loop->run();
+}
+
+void run_as_client(Glib::ustring address)
+{
+ Glib::RefPtr<Gio::DBusConnection> connection;
+
+ try
+ {
+ connection = Gio::DBusConnection::create_for_address_sync(address,
+ Gio::DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT);
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << "Error connecting to D-Bus address " << address << ": " <<
+ ex.what() << "." << std::endl;
+ }
+
+ std::cout << "Connected. " << std::endl <<
+ "Negotiated capabilities: unix-fd-passing=" <<
+ static_cast<bool>(connection->get_capabilities() & Gio::DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING) << "." << std::endl;
+
+ // Get the current time to send as a greeting when calling a server's method.
+ Glib::TimeVal time;
+ time.assign_current_time();
+
+ // Create the single string tuple parameter for the method call.
+
+ Glib::ustring greeting("Hello, it's: " + time.as_iso8601() + '.');
+
+ Glib::Variant<Glib::ustring> param =
+ Glib::Variant<Glib::ustring>::create(greeting);
+
+ std::vector<Glib::VariantBase> variants;
+ variants.push_back(param);
+
+ Glib::VariantContainerBase parameters =
+ Glib::VariantContainerBase::create_tuple(variants);
+
+ try
+ {
+ Glib::VariantContainerBase result;
+ connection->call_sync(result, "/org/glibmm/GDBus/TestObject",
+ "org.glibmm.GDBus.TestPeerInterface",
+ "HelloWorld", parameters);
+
+ Glib::Variant<Glib::ustring> child;
+ result.get(child);
+
+ std::cout << "The server said: " << child.get() << "." << std::endl;
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << "Error calling the server's method: " << ex.what() << "." <<
+ std::endl;
+ }
+}
+
+int main(int argc, char** argv)
+{
+ std::locale::global(std::locale(""));
+ Gio::init();
+
+ bool opt_server = false;
+ char* opt_address = 0;
+ bool opt_allow_anonymous = false;
+
+ static const GOptionEntry opt_entries[] =
+ {
+ { "server", 's', 0, G_OPTION_ARG_NONE, &opt_server, "Start a server instead of a client", NULL },
+ { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_address, "D-Bus address to use", NULL },
+ { "allow-anonymous", 'n', 0, G_OPTION_ARG_NONE, &opt_allow_anonymous, "Allow anonymous authentication", NULL },
+ { 0, '\0', 0, G_OPTION_ARG_NONE, 0, 0, 0 }
+ };
+
+ Glib::OptionContext opt_context("DBus peer-to-peer example");
+ g_option_context_add_main_entries(opt_context.gobj(), opt_entries, 0);
+
+ try
+ {
+ if(!opt_context.parse(argc, argv))
+ {
+ std::cerr << "Error parsing options and initializing. Sorry." <<
+ std::endl;
+ return 1;
+ }
+ }
+ catch(const Glib::OptionError& ex)
+ {
+ std::cerr << "Error parsing options: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ if(!opt_address)
+ {
+ std::cerr << "Incorrect usage, try the --help options." << std::endl;
+ return 1;
+ }
+
+ if(!opt_server && opt_allow_anonymous)
+ {
+ std::cerr << "The --allow-anonymous option is only valid with the "
+ "--server option." << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ introspection_data = Gio::DBusNodeInfo::create_for_xml(introspection_xml);
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << "Unable to create introspection data: " << ex.what() <<
+ "." << std::endl;
+ }
+
+ if(opt_server)
+ run_as_server(opt_address, opt_allow_anonymous);
+ else
+ run_as_client(opt_address);
+
+ return 0;
+}
diff --git a/examples/dbus/well-known-address-client.cc b/examples/dbus/userbus.cc
index b8358ffb..63698540 100644
--- a/examples/dbus/well-known-address-client.cc
+++ b/examples/dbus/userbus.cc
@@ -64,7 +64,7 @@ void dbus_proxy_available(Glib::RefPtr<Gio::AsyncResult>& result)
for(unsigned i = 0; i < names.size(); i++)
std::cout << names[i] << "." << std::endl;
}
- catch (const Glib::Error& error)
+ catch(const Glib::Error& error)
{
std::cerr << "Got an error: '" << error.what() << "'." << std::endl;
}