#include #include #include #include #include #include #include #include "pipe_transfer.h" namespace // anonymous namespace (for "private" globals) { static Glib::RefPtr introspection_data; static Glib::ustring introspection_xml = "" " " " " " " " " ""; guint registered_id = 0; int fildes[2] = {0,0}; //fildes[0] is read end, fildes[1] is write end } static void on_method_call( const Glib::RefPtr& connection_ , const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */, const Glib::ustring& /* interface_name */, const Glib::ustring& method_name, const Glib::VariantContainerBase& parameters, const Glib::RefPtr& invocation) { Glib::RefPtr connection = connection_; //std::cerr << "server: on_method_call " << method_name << std::endl; if (method_name == "RemoteFunction") { Glib::RefPtr message = invocation->get_message(); GUnixFDList *fd_list = g_dbus_message_get_unix_fd_list(message->gobj()); int fd_index = 0; gint fd0 = -1, fd1 = -1; fd0 = g_unix_fd_list_get(fd_list, fd_index++, 0); fd1 = g_unix_fd_list_get(fd_list, fd_index++, 0); std::vector< guint32 > input_a; std::vector< guint32 > input_b; std::vector< guint32 > output; read_vector_from_pipe(fd0, input_a); read_vector_from_pipe(fd0, input_b); try { // the ouput vector will be the concatenation of both input vectors std::copy(input_a.begin(), input_a.end(), std::back_inserter >(output)); std::copy(input_b.begin(), input_b.end(), std::back_inserter >(output)); connection.reset(); } catch (...) { connection.reset(); throw; } std::vector response_vector; Glib::RefPtr out_fd_list = Gio::UnixFDList::create(); invocation->return_value(Glib::VariantContainerBase::create_tuple(response_vector), out_fd_list); write_vector_to_pipe(fd1, output); close(fd0); close(fd1); } else { std::cerr << "server: unknown method name" << std::endl; // Non-existent method on the interface. Gio::DBus::Error error(Gio::DBus::Error::UNKNOWN_METHOD, "Method does not exist."); invocation->return_error(error); } } // This must be a global instance. See the InterfaceVTable documentation. // TODO: Make that unnecessary. const Gio::DBus::InterfaceVTable interface_vtable(sigc::ptr_fun(&on_method_call)); void on_bus_acquired( const Glib::RefPtr& connection, const Glib::ustring& /* name */) { // Export an object to the bus: // See https://bugzilla.gnome.org/show_bug.cgi?id=646417 about avoiding // the repetition of the interface name: try { registered_id = connection->register_object( "/org/glibmm/DBus/TestObject", introspection_data->lookup_interface(), interface_vtable); } catch (const Glib::Error& ex) { std::cerr << "Registration of object failed." << std::endl; } return; } void on_name_acquired( const Glib::RefPtr& /* connection */, const Glib::ustring& /* name */) { // TODO: What is this good for? See https://bugzilla.gnome.org/show_bug.cgi?id=646427 } void on_name_lost(const Glib::RefPtr& connection, const Glib::ustring& /* name */) { std::cerr << "name lost" << std::endl; connection->unregister_object(registered_id); } int main(int, char**) { std::locale::global(std::locale("")); Gio::init(); int status = pipe(fildes); if (status==-1) { std::cerr << "Cannot create pipe" << std::endl; return 1; } try { introspection_data = Gio::DBus::NodeInfo::create_for_xml(introspection_xml); } catch (const Glib::Error& ex) { std::cerr << "Unable to create introspection data: " << ex.what() << "." << std::endl; return 1; } const auto id = Gio::DBus::own_name(Gio::DBus::BUS_TYPE_SESSION, "org.glibmm.DBusExample", sigc::ptr_fun(&on_bus_acquired), sigc::ptr_fun(&on_name_acquired), sigc::ptr_fun(&on_name_lost)); // Keep the service running until the process is killed: auto loop = Glib::MainLoop::create(); loop->run(); Gio::DBus::unown_name(id); return EXIT_SUCCESS; }