diff options
Diffstat (limited to 'recipes-core-ivi/dbus')
-rw-r--r-- | recipes-core-ivi/dbus/dbus/dbus_1.6-add-afbus-support.patch | 3201 | ||||
-rw-r--r-- | recipes-core-ivi/dbus/dbus_1.6.4.bbappend | 3 |
2 files changed, 3204 insertions, 0 deletions
diff --git a/recipes-core-ivi/dbus/dbus/dbus_1.6-add-afbus-support.patch b/recipes-core-ivi/dbus/dbus/dbus_1.6-add-afbus-support.patch new file mode 100644 index 0000000..2e91507 --- /dev/null +++ b/recipes-core-ivi/dbus/dbus/dbus_1.6-add-afbus-support.patch @@ -0,0 +1,3201 @@ +diff --git a/bus/Makefile.am b/bus/Makefile.am +index 6cbc09a..cf3a962 100644 +--- a/bus/Makefile.am ++++ b/bus/Makefile.am +@@ -63,6 +63,15 @@ endif + endif + endif + ++if HAVE_AFBUS ++AFBUS_SOURCE = \ ++ driver-afbus.c \ ++ driver-afbus.h \ ++ $(NULL) ++else ++AFBUS_SOURCE = ++endif ++ + BUS_SOURCES= \ + activation.c \ + activation.h \ +@@ -83,6 +92,7 @@ BUS_SOURCES= \ + dispatch.h \ + driver.c \ + driver.h \ ++ $(AFBUS_SOURCE) \ + expirelist.c \ + expirelist.h \ + policy.c \ +diff --git a/bus/bus.c b/bus/bus.c +index e80e708..5038958 100644 +--- a/bus/bus.c ++++ b/bus/bus.c +@@ -52,11 +52,20 @@ struct BusContext + char *type; + char *servicehelper; + char *address; ++ ++ /* if we are in AF_BUS compat mode, contains the AF_BUS address */ ++ char *main_address; ++ + char *pidfile; + char *user; + char *log_prefix; + DBusLoop *loop; + DBusList *servers; ++ ++ /* One of the servers may be a AF_BUS server. We can have at most only one ++ * AF_BUS server. */ ++ DBusServer *main_afbus_server; ++ + BusConnections *connections; + BusActivation *activation; + BusRegistry *registry; +@@ -207,6 +216,29 @@ free_server_data (void *data) + dbus_free (bd); + } + ++static void ++shutdown_server (BusContext *context, ++ DBusServer *server) ++{ ++ if (server == NULL || ++ !dbus_server_get_is_connected (server)) ++ return; ++ ++ if (!dbus_server_set_watch_functions (server, ++ NULL, NULL, NULL, ++ context, ++ NULL)) ++ _dbus_assert_not_reached ("setting watch functions to NULL failed"); ++ ++ if (!dbus_server_set_timeout_functions (server, ++ NULL, NULL, NULL, ++ context, ++ NULL)) ++ _dbus_assert_not_reached ("setting timeout functions to NULL failed"); ++ ++ dbus_server_disconnect (server); ++} ++ + static dbus_bool_t + setup_server (BusContext *context, + DBusServer *server, +@@ -275,6 +307,7 @@ process_config_first_time_only (BusContext *context, + DBusString log_prefix; + DBusList *link; + DBusList **addresses; ++ DBusList **addresses_if_possible; + const char *user, *pidfile; + char **auth_mechanisms; + DBusList **auth_mechanisms_list; +@@ -448,6 +481,7 @@ process_config_first_time_only (BusContext *context, + while (link != NULL) + { + DBusServer *server; ++ dbus_bool_t is_afbus; + + server = dbus_server_listen (link->data, error); + if (server == NULL) +@@ -455,17 +489,78 @@ process_config_first_time_only (BusContext *context, + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } +- else if (!setup_server (context, server, auth_mechanisms, error)) ++ is_afbus = dbus_server_is_afbus (server); ++ ++ /* Only accept one AF_BUS server */ ++ if (is_afbus && context->main_afbus_server != NULL) + { ++ dbus_server_disconnect (server); ++ dbus_server_unref (server); ++ dbus_set_error (error, ++ DBUS_ERROR_MULTIPLE_AFBUS, ++ "Cannot listen on multiple AF_BUS address"); ++ goto failed; ++ } ++ ++ if (!setup_server (context, server, auth_mechanisms, error)) ++ { ++ shutdown_server (context, server); ++ dbus_server_unref (server); + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } ++ if (is_afbus) ++ context->main_afbus_server = server; + + if (!_dbus_list_append (&context->servers, server)) + goto oom; + + link = _dbus_list_get_next_link (addresses, link); + } ++ ++ addresses_if_possible = ++ bus_config_parser_get_addresses_if_possible (parser); ++ ++ link = _dbus_list_get_first_link (addresses_if_possible); ++ while (link != NULL) ++ { ++ DBusServer *server; ++ dbus_bool_t is_afbus; ++ ++ server = dbus_server_listen (link->data, NULL); ++ if (server == NULL) ++ { ++ link = _dbus_list_get_next_link (addresses_if_possible, link); ++ continue; ++ } ++ is_afbus = dbus_server_is_afbus (server); ++ ++ /* Only accept one AF_BUS server */ ++ if (is_afbus && context->main_afbus_server != NULL) ++ { ++ dbus_server_disconnect (server); ++ dbus_server_unref (server); ++ ++ link = _dbus_list_get_next_link (addresses_if_possible, link); ++ continue; ++ } ++ ++ if (!setup_server (context, server, auth_mechanisms, NULL)) ++ { ++ shutdown_server (context, server); ++ dbus_server_unref (server); ++ ++ link = _dbus_list_get_next_link (addresses_if_possible, link); ++ continue; ++ } ++ if (is_afbus) ++ context->main_afbus_server = server; ++ ++ if (!_dbus_list_append (&context->servers, server)) ++ goto oom; ++ ++ link = _dbus_list_get_next_link (addresses_if_possible, link); ++ } + } + + context->fork = bus_config_parser_get_fork (parser); +@@ -499,6 +594,7 @@ process_config_every_time (BusContext *context, + DBusError *error) + { + DBusString full_address; ++ DBusString main_address; + DBusList *link; + DBusList **dirs; + char *addr; +@@ -518,6 +614,12 @@ process_config_every_time (BusContext *context, + return FALSE; + } + ++ if (!_dbus_string_init (&main_address)) ++ { ++ BUS_SET_OOM (error); ++ return FALSE; ++ } ++ + /* get our limits and timeout lengths */ + bus_config_parser_get_limits (parser, &context->limits); + +@@ -554,6 +656,18 @@ process_config_every_time (BusContext *context, + goto failed; + } + ++ if (dbus_server_is_afbus (link->data)) ++ { ++ /* There must be at most one AF_BUS server */ ++ _dbus_assert (_dbus_string_get_length (&main_address) == 0); ++ ++ if (!_dbus_string_append (&main_address, addr)) ++ { ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ } ++ + dbus_free (addr); + addr = NULL; + +@@ -561,7 +675,10 @@ process_config_every_time (BusContext *context, + } + + if (is_reload) +- dbus_free (context->address); ++ { ++ dbus_free (context->address); ++ dbus_free (context->main_address); ++ } + + if (!_dbus_string_copy_data (&full_address, &context->address)) + { +@@ -569,6 +686,12 @@ process_config_every_time (BusContext *context, + goto failed; + } + ++ if (!_dbus_string_copy_data (&main_address, &context->main_address)) ++ { ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ + /* get the service directories */ + dirs = bus_config_parser_get_service_dirs (parser); + +@@ -609,6 +732,7 @@ process_config_every_time (BusContext *context, + + failed: + _dbus_string_free (&full_address); ++ _dbus_string_free (&main_address); + + if (addr) + dbus_free (addr); +@@ -990,29 +1114,6 @@ bus_context_reload_config (BusContext *context, + return ret; + } + +-static void +-shutdown_server (BusContext *context, +- DBusServer *server) +-{ +- if (server == NULL || +- !dbus_server_get_is_connected (server)) +- return; +- +- if (!dbus_server_set_watch_functions (server, +- NULL, NULL, NULL, +- context, +- NULL)) +- _dbus_assert_not_reached ("setting watch functions to NULL failed"); +- +- if (!dbus_server_set_timeout_functions (server, +- NULL, NULL, NULL, +- context, +- NULL)) +- _dbus_assert_not_reached ("setting timeout functions to NULL failed"); +- +- dbus_server_disconnect (server); +-} +- + void + bus_context_shutdown (BusContext *context) + { +@@ -1099,6 +1200,7 @@ bus_context_unref (BusContext *context) + dbus_free (context->log_prefix); + dbus_free (context->type); + dbus_free (context->address); ++ dbus_free (context->main_address); + dbus_free (context->user); + dbus_free (context->servicehelper); + +@@ -1134,6 +1236,12 @@ bus_context_get_address (BusContext *context) + } + + const char* ++bus_context_get_main_address (BusContext *context) ++{ ++ return context->main_address; ++} ++ ++const char* + bus_context_get_servicehelper (BusContext *context) + { + return context->servicehelper; +diff --git a/bus/bus.h b/bus/bus.h +index 3597884..f2a55f2 100644 +--- a/bus/bus.h ++++ b/bus/bus.h +@@ -88,6 +88,7 @@ dbus_bool_t bus_context_get_id (BusContext + DBusString *uuid); + const char* bus_context_get_type (BusContext *context); + const char* bus_context_get_address (BusContext *context); ++const char* bus_context_get_main_address (BusContext *context); + const char* bus_context_get_servicehelper (BusContext *context); + dbus_bool_t bus_context_get_systemd_activation (BusContext *context); + BusRegistry* bus_context_get_registry (BusContext *context); +diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c +index c522ff4..8747835 100644 +--- a/bus/config-parser-common.c ++++ b/bus/config-parser-common.c +@@ -63,6 +63,10 @@ bus_config_parser_element_name_to_type (const char *name) + { + return ELEMENT_LISTEN; + } ++ else if (strcmp (name, "listen_if_possible") == 0) ++ { ++ return ELEMENT_LISTEN_IF_POSSIBLE; ++ } + else if (strcmp (name, "auth") == 0) + { + return ELEMENT_AUTH; +@@ -145,6 +149,8 @@ bus_config_parser_element_type_to_name (ElementType type) + return "user"; + case ELEMENT_LISTEN: + return "listen"; ++ case ELEMENT_LISTEN_IF_POSSIBLE: ++ return "listen_if_possible"; + case ELEMENT_AUTH: + return "auth"; + case ELEMENT_POLICY: +diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h +index 186bf4c..6ea509c 100644 +--- a/bus/config-parser-common.h ++++ b/bus/config-parser-common.h +@@ -31,6 +31,7 @@ typedef enum + ELEMENT_INCLUDE, + ELEMENT_USER, + ELEMENT_LISTEN, ++ ELEMENT_LISTEN_IF_POSSIBLE, + ELEMENT_AUTH, + ELEMENT_POLICY, + ELEMENT_LIMIT, +diff --git a/bus/config-parser.c b/bus/config-parser.c +index 07e8fbb..fffc0e1 100644 +--- a/bus/config-parser.c ++++ b/bus/config-parser.c +@@ -96,6 +96,8 @@ struct BusConfigParser + + DBusList *listen_on; /**< List of addresses to listen to */ + ++ DBusList *listen_on_if_possible; /**< List of addresses to listen to, but continue on failure */ ++ + DBusList *mechanisms; /**< Auth mechanisms */ + + DBusList *service_dirs; /**< Directories to look for session services in */ +@@ -327,6 +329,9 @@ merge_included (BusConfigParser *parser, + while ((link = _dbus_list_pop_first_link (&included->listen_on))) + _dbus_list_append_link (&parser->listen_on, link); + ++ while ((link = _dbus_list_pop_first_link (&included->listen_on_if_possible))) ++ _dbus_list_append_link (&parser->listen_on_if_possible, link); ++ + while ((link = _dbus_list_pop_first_link (&included->mechanisms))) + _dbus_list_append_link (&parser->mechanisms, link); + +@@ -497,6 +502,12 @@ bus_config_parser_unref (BusConfigParser *parser) + + _dbus_list_clear (&parser->listen_on); + ++ _dbus_list_foreach (&parser->listen_on_if_possible, ++ (DBusForeachFunction) dbus_free, ++ NULL); ++ ++ _dbus_list_clear (&parser->listen_on_if_possible); ++ + _dbus_list_foreach (&parser->service_dirs, + (DBusForeachFunction) dbus_free, + NULL); +@@ -774,6 +785,19 @@ start_busconfig_child (BusConfigParser *parser, + + return TRUE; + } ++ else if (element_type == ELEMENT_LISTEN_IF_POSSIBLE) ++ { ++ if (!check_no_attributes (parser, "listen_if_possible", attribute_names, attribute_values, error)) ++ return FALSE; ++ ++ if (push_element (parser, ELEMENT_LISTEN_IF_POSSIBLE) == NULL) ++ { ++ BUS_SET_OOM (error); ++ return FALSE; ++ } ++ ++ return TRUE; ++ } + else if (element_type == ELEMENT_AUTH) + { + if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error)) +@@ -2018,6 +2042,7 @@ bus_config_parser_end_element (BusConfigParser *parser, + case ELEMENT_USER: + case ELEMENT_CONFIGTYPE: + case ELEMENT_LISTEN: ++ case ELEMENT_LISTEN_IF_POSSIBLE: + case ELEMENT_PIDFILE: + case ELEMENT_AUTH: + case ELEMENT_SERVICEDIR: +@@ -2518,6 +2543,24 @@ bus_config_parser_content (BusConfigParser *parser, + } + break; + ++ case ELEMENT_LISTEN_IF_POSSIBLE: ++ { ++ char *s; ++ ++ e->had_content = TRUE; ++ ++ if (!_dbus_string_copy_data (content, &s)) ++ goto nomem; ++ ++ if (!_dbus_list_append (&parser->listen_on_if_possible, ++ s)) ++ { ++ dbus_free (s); ++ goto nomem; ++ } ++ } ++ break; ++ + case ELEMENT_AUTH: + { + char *s; +@@ -2646,6 +2689,12 @@ bus_config_parser_get_addresses (BusConfigParser *parser) + } + + DBusList** ++bus_config_parser_get_addresses_if_possible (BusConfigParser *parser) ++{ ++ return &parser->listen_on_if_possible; ++} ++ ++DBusList** + bus_config_parser_get_mechanisms (BusConfigParser *parser) + { + return &parser->mechanisms; +@@ -3123,6 +3172,9 @@ config_parsers_equal (const BusConfigParser *a, + if (!lists_of_c_strings_equal (a->listen_on, b->listen_on)) + return FALSE; + ++ if (!lists_of_c_strings_equal (a->listen_on_if_possible, b->listen_on_if_possible)) ++ return FALSE; ++ + if (!lists_of_c_strings_equal (a->mechanisms, b->mechanisms)) + return FALSE; + +diff --git a/bus/config-parser.h b/bus/config-parser.h +index ba5bf74..f8a3c07 100644 +--- a/bus/config-parser.h ++++ b/bus/config-parser.h +@@ -61,6 +61,7 @@ dbus_bool_t bus_config_parser_finished (BusConfigParser *parser, + const char* bus_config_parser_get_user (BusConfigParser *parser); + const char* bus_config_parser_get_type (BusConfigParser *parser); + DBusList** bus_config_parser_get_addresses (BusConfigParser *parser); ++DBusList** bus_config_parser_get_addresses_if_possible (BusConfigParser *parser); + DBusList** bus_config_parser_get_mechanisms (BusConfigParser *parser); + dbus_bool_t bus_config_parser_get_fork (BusConfigParser *parser); + dbus_bool_t bus_config_parser_get_allow_anonymous (BusConfigParser *parser); +diff --git a/bus/connection.c b/bus/connection.c +index d69758c..2d68c84 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -30,9 +30,16 @@ + #include "signals.h" + #include "expirelist.h" + #include "selinux.h" ++#include "driver-afbus.h" + #include <dbus/dbus-list.h> + #include <dbus/dbus-hash.h> + #include <dbus/dbus-timeout.h> ++#ifdef HAVE_AFBUS ++#include <dbus/dbus-transport-afbus.h> ++#endif ++ ++#include <sys/types.h> /* See NOTES */ ++#include <sys/socket.h> + + /* Trim executed commands to this length; we want to keep logs readable */ + #define MAX_LOG_COMMAND_LEN 50 +@@ -94,6 +101,13 @@ typedef struct + char *cached_loginfo_string; + BusSELinuxID *selinux_id; + ++ dbus_bool_t peer_address_set; ++ struct sockaddr_storage peer_address; ++ socklen_t peer_addrlen; ++ DBusConnection *proxy_connection; /**< If this is a compat connection, ++ proxy_connection is the proxy ++ connection to AF_BUS */ ++ + long connection_tv_sec; /**< Time when we connected (seconds component) */ + long connection_tv_usec; /**< Time when we connected (microsec component) */ + int stamp; /**< connections->stamp last time we were traversed */ +@@ -184,12 +198,33 @@ adjust_connections_for_uid (BusConnections *connections, + } + } + ++static DBusHandlerResult ++proxy_connection_message_filter (DBusConnection *connection, ++ DBusMessage *message, ++ void *user_data) ++{ ++ DBusConnection *source_connection = user_data; ++ ++ if (dbus_message_get_destination (message) == NULL && ++ dbus_message_is_signal (message, ++ DBUS_INTERFACE_LOCAL, ++ "Disconnected")) ++ { ++ dbus_connection_close (source_connection); ++ return DBUS_HANDLER_RESULT_HANDLED; ++ } ++ ++ dbus_connection_send (source_connection, message, NULL); ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ + void + bus_connection_disconnected (DBusConnection *connection) + { + BusConnectionData *d; + BusService *service; + BusMatchmaker *matchmaker; ++ DBusError error; + + d = BUS_CONNECTION_DATA (connection); + _dbus_assert (d != NULL); +@@ -197,6 +232,20 @@ bus_connection_disconnected (DBusConnection *connection) + _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n", + d->name ? d->name : "(inactive)"); + ++ if (d->proxy_connection) ++ { ++ dbus_connection_remove_filter (d->proxy_connection, ++ proxy_connection_message_filter, connection); ++ dbus_connection_close (d->proxy_connection); ++ dbus_connection_unref (d->proxy_connection); ++ d->proxy_connection = NULL; ++ } ++ ++ dbus_error_init (&error); ++ ++ if (!bus_driver_afbus_disconnected(connection, &error)) ++ dbus_error_free (&error); ++ + /* Delete our match rules */ + if (d->n_match_rules > 0) + { +@@ -309,6 +358,18 @@ bus_connection_disconnected (DBusConnection *connection) + dbus_connection_unref (connection); + } + ++DBusConnection * ++bus_connection_get_proxy_connection (DBusConnection *connection) ++{ ++ BusConnectionData *d; ++ ++ d = BUS_CONNECTION_DATA (connection); ++ ++ _dbus_assert (d != NULL); ++ ++ return d->proxy_connection; ++} ++ + static dbus_bool_t + add_connection_watch (DBusWatch *watch, + void *data) +@@ -588,6 +649,52 @@ oom: + return FALSE; + } + ++#ifdef HAVE_AFBUS ++static dbus_bool_t ++bus_connections_setup_proxy_connection (BusConnections *connections, ++ DBusConnection *connection, ++ const char *main_address) ++{ ++ BusConnectionData *d = BUS_CONNECTION_DATA (connection); ++ DBusError error; ++ dbus_bool_t retval = FALSE; ++ ++ dbus_error_init (&error); ++ ++ d->proxy_connection ++ = dbus_connection_open_private (main_address, &error); ++ if (dbus_error_is_set (&error)) ++ { ++ dbus_error_free (&error); ++ goto out; ++ } ++ ++ dbus_connection_set_route_peer_messages (d->proxy_connection, TRUE); ++ ++ dbus_connection_set_dispatch_status_function (d->proxy_connection, ++ dispatch_status_function, ++ bus_context_get_loop (connections->context), NULL); ++ ++ if (!dbus_connection_add_filter(d->proxy_connection, ++ proxy_connection_message_filter, connection, NULL)) ++ goto out; ++ ++ ++ if (!dbus_connection_set_watch_functions (d->proxy_connection, ++ add_connection_watch, ++ remove_connection_watch, ++ toggle_connection_watch, ++ connection, ++ NULL)) ++ goto out; ++ ++ return TRUE; ++ ++out: ++ return retval; ++} ++#endif ++ + dbus_bool_t + bus_connections_setup_connection (BusConnections *connections, + DBusConnection *connection) +@@ -596,7 +703,6 @@ bus_connections_setup_connection (BusConnections *connections, + BusConnectionData *d; + dbus_bool_t retval; + DBusError error; +- + + d = dbus_new0 (BusConnectionData, 1); + +@@ -622,8 +728,32 @@ bus_connections_setup_connection (BusConnections *connections, + dbus_connection_set_route_peer_messages (connection, TRUE); + + retval = FALSE; +- + dbus_error_init (&error); ++ ++#ifdef HAVE_AFBUS ++ d->peer_addrlen = sizeof(d->peer_address); ++ d->peer_address_set = dbus_connection_get_peer_address (connection, ++ &d->peer_address, (long int *)&d->peer_addrlen); ++ ++ /* If this connection is not AF_BUS, and we have a AF_BUS ++ * server, we are in compat mode and we need to setup a ++ * new connection */ ++ if (d->peer_address_set && ++ ((struct sockaddr *)&d->peer_address)->sa_family != AF_BUS) ++ { ++ const char *main_address; ++ main_address = bus_context_get_main_address (connections->context); ++ if (main_address && main_address[0] != '\0') ++ { ++ if (!bus_connections_setup_proxy_connection (connections, connection, ++ main_address)) ++ { ++ goto out; ++ } ++ } ++ } ++#endif ++ + d->selinux_id = bus_selinux_init_connection_id (connection, + &error); + if (dbus_error_is_set (&error)) +@@ -2383,3 +2513,21 @@ bus_connection_get_peak_bus_names (DBusConnection *connection) + return d->peak_bus_names; + } + #endif /* DBUS_ENABLE_STATS */ ++ ++int ++bus_connection_get_peer_address (DBusConnection *connection, ++ struct sockaddr **peer_address, ++ socklen_t *peer_addrlen) ++{ ++ BusConnectionData *d; ++ ++ d = BUS_CONNECTION_DATA (connection); ++ ++ if (!d->peer_address_set) ++ return FALSE; ++ ++ *peer_address = (struct sockaddr *) &d->peer_address; ++ *peer_addrlen = d->peer_addrlen; ++ ++ return TRUE; ++} +diff --git a/bus/connection.h b/bus/connection.h +index c936021..95856f3 100644 +--- a/bus/connection.h ++++ b/bus/connection.h +@@ -24,6 +24,8 @@ + #ifndef BUS_CONNECTION_H + #define BUS_CONNECTION_H + ++#include <sys/types.h> ++#include <sys/socket.h> + #include <dbus/dbus.h> + #include <dbus/dbus-list.h> + #include "bus.h" +@@ -103,8 +105,9 @@ dbus_bool_t bus_connection_complete (DBusConnection *connection, + const DBusString *name, + DBusError *error); + +-/* called by dispatch.c when the connection is dropped */ +-void bus_connection_disconnected (DBusConnection *connection); ++/* called by dispatch.c */ ++void bus_connection_disconnected (DBusConnection *connection); ++DBusConnection *bus_connection_get_proxy_connection (DBusConnection *connection); + + dbus_bool_t bus_connection_is_in_unix_group (DBusConnection *connection, + unsigned long gid); +@@ -151,4 +154,9 @@ int bus_connections_get_peak_bus_names_per_conn (BusConnections *connections); + int bus_connection_get_peak_match_rules (DBusConnection *connection); + int bus_connection_get_peak_bus_names (DBusConnection *connection); + ++/* called by driver-afbus.c */ ++int bus_connection_get_peer_address (DBusConnection *connection, ++ struct sockaddr **peer_address, ++ socklen_t *peer_addrlen); ++ + #endif /* BUS_CONNECTION_H */ +diff --git a/bus/dispatch.c b/bus/dispatch.c +index 7a96f9d..4feae05 100644 +--- a/bus/dispatch.c ++++ b/bus/dispatch.c +@@ -27,6 +27,7 @@ + #include "dispatch.h" + #include "connection.h" + #include "driver.h" ++#include "driver-afbus.h" + #include "services.h" + #include "activation.h" + #include "utils.h" +@@ -129,6 +130,18 @@ bus_dispatch_matches (BusTransaction *transaction, + BUS_SET_OOM (error); + return FALSE; + } ++ ++ /* If using AF_BUS and the message came to the daemon, the client sending ++ * the message doesn't yet know the address for this service, so notify ++ * it of the address associated with the service. */ ++ if (!bus_driver_afbus_emit_forwarded (transaction, ++ sender, ++ addressed_recipient, ++ dbus_message_get_destination (message))) ++ { ++ _dbus_verbose ("bus_driver_afbus_emit_forwarded() failed\n"); ++ return FALSE; ++ } + } + + /* Now dispatch to others who look interested in this message */ +@@ -180,6 +193,7 @@ bus_dispatch (DBusConnection *connection, + BusContext *context; + DBusHandlerResult result; + DBusConnection *addressed_recipient; ++ DBusConnection *proxy_connection; + + result = DBUS_HANDLER_RESULT_HANDLED; + +@@ -241,6 +255,15 @@ bus_dispatch (DBusConnection *connection, + } + } + ++ /* Directly send the message to the proxy without analysing it */ ++ proxy_connection = bus_connection_get_proxy_connection (connection); ++ if (proxy_connection) ++ { ++ if (!dbus_connection_send (proxy_connection, message, NULL)) ++ BUS_SET_OOM (&error); ++ goto out; ++ } ++ + /* Create our transaction */ + transaction = bus_transaction_new (context); + if (transaction == NULL) +diff --git a/bus/driver-afbus.c b/bus/driver-afbus.c +new file mode 100644 +index 0000000..70edafb +--- /dev/null ++++ b/bus/driver-afbus.c +@@ -0,0 +1,345 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* driver.c Bus client, AF_BUS bits (driver) ++ * ++ * Copyright (C) 2012 Collabora Ltd ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#include <config.h> ++ ++#include "driver-afbus.h" ++ ++#include <unistd.h> ++#include <sys/types.h> ++#include <sys/socket.h> ++#include <asm/types.h> ++#include <errno.h> ++#include <linux/netlink.h> ++#include <linux/rtnetlink.h> ++#include <linux/connector.h> ++#include <dbus/dbus-transport-afbus.h> ++ ++#define CN_IDX_NFDBUS 0xA /* netfilter D-Bus */ ++#define CN_VAL_NFDBUS 0x1 ++ ++#define NFDBUS_CMD_ADDMATCH 0x01 ++#define NFDBUS_CMD_REMOVEMATCH 0x02 ++#define NFDBUS_CMD_REMOVEALLMATCH 0x03 ++ ++struct nfdbus_nl_cfg_req { ++ __u32 cmd; ++ __u32 len; ++ struct sockaddr_bus addr; ++ __u64 pad; ++ unsigned char data[0]; ++}; ++ ++struct nfdbus_nl_cfg_reply { ++ __u32 ret_code; ++}; ++ ++static int ++ensure_nl_sock(DBusError *error) ++{ ++ static int nlsock = 0; ++ ++ struct sockaddr_nl l_local; ++ int fd; ++ int ret; ++ ++ if (nlsock > 0) ++ return nlsock; ++ ++ fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); ++ if (fd == -1) { ++ dbus_set_error (error, DBUS_ERROR_NETLINK, ++ "Couldn't use the netlink socket: %s", ++ strerror(errno)); ++ return -1; ++ } ++ ++ if (!_dbus_set_fd_nonblocking (fd, error)) ++ { ++ _dbus_close_socket (fd, NULL); ++ return -1; ++ } ++ ++ l_local.nl_family = AF_NETLINK; ++ l_local.nl_groups = 0; ++ l_local.nl_pid = 0; ++ ret = bind(fd, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)); ++ if (ret == -1) { ++ close(fd); ++ dbus_set_error (error, DBUS_ERROR_NETLINK, ++ "Couldn't bind the netlink socket: %s", ++ strerror(errno)); ++ return -1; ++ } ++ ++ nlsock = fd; ++ return nlsock; ++} ++ ++static int netlink_send(int nlsock, struct cn_msg *msg, int seq) ++{ ++ struct nlmsghdr *nlh; ++ unsigned int size; ++ char buf[4096]; ++ struct cn_msg *m; ++ ++ size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); ++ ++ nlh = (struct nlmsghdr *)buf; ++ nlh->nlmsg_seq = seq; ++ nlh->nlmsg_pid = getpid(); ++ nlh->nlmsg_type = NLMSG_DONE; ++ nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); ++ nlh->nlmsg_flags = 0; ++ ++ m = NLMSG_DATA(nlh); ++ memcpy(m, msg, sizeof(*m) + msg->len); ++ ++ return send(nlsock, nlh, size, 0); ++} ++ ++static dbus_bool_t ++bus_driver_afbus_upload_match_rule (DBusConnection *connection, ++ const char *rule, ++ int cmd, ++ DBusError *error) ++{ ++ static int seq; ++ ++ int nlsock; ++ int ret; ++ ++ char buf[sizeof(struct cn_msg) + sizeof(struct nfdbus_nl_cfg_req) + 1024]; ++ ++ struct cn_msg *data; ++ struct nlmsghdr *reply; ++ struct nfdbus_nl_cfg_req *req; ++ //struct nfdbus_nl_cfg_reply *req_reply; ++ ++ struct sockaddr_storage *address; ++ socklen_t addrlen = sizeof(address); ++ ++ if (!bus_connection_get_peer_address(connection, ++ (struct sockaddr **) &address, &addrlen)) ++ return TRUE; ++ ++ if (((struct sockaddr*)address)->sa_family != AF_BUS) ++ return TRUE; ++ ++ nlsock = ensure_nl_sock (error); ++ if (nlsock == -1) ++ return FALSE; ++ ++ memset(buf, 0, sizeof(buf)); ++ ++ data = (struct cn_msg *)buf; ++ ++ data->id.idx = CN_IDX_NFDBUS; ++ data->id.val = CN_VAL_NFDBUS; ++ data->seq = seq++; ++ data->ack = 0; ++ data->len = sizeof(struct nfdbus_nl_cfg_req) + strlen(rule) + 1; ++ req = (struct nfdbus_nl_cfg_req *) data->data; ++ ++ req->cmd = cmd; ++ req->len = strlen(rule) + 1; ++ req->addr = *(struct sockaddr_bus *)address; ++ strcpy((char *)req->data, rule); ++ ++ ret = netlink_send(nlsock, data, seq++); ++ if (ret <= 0) ++ { ++ } ++ ++ memset(buf, 0, sizeof(buf)); ++ ret = recv(nlsock, buf, sizeof(buf), 0); ++ if (ret <= 0) ++ { ++ } ++ ++ reply = (struct nlmsghdr *)buf; ++ if (reply->nlmsg_type != NLMSG_DONE) ++ { ++ } ++ ++ return TRUE; ++} ++ ++dbus_bool_t ++bus_driver_afbus_add_match_rule (DBusConnection *connection, ++ const char *rule, ++ DBusError *error) ++{ ++ if (bus_driver_afbus_upload_match_rule (connection, rule, NFDBUS_CMD_ADDMATCH, error)) ++ { ++ /* Check if the match rule is for eavesdropping, and set the socket ++ * to allow receiving all messages if so */ ++ if (strstr (rule, "eavesdrop=true")) ++ { ++ int fd; ++ ++ if (dbus_connection_get_socket (connection, &fd)) ++ { ++ if (setsockopt (fd, SOL_BUS, BUS_SET_EAVESDROP, NULL, 0) == 0) ++ return TRUE; ++ else ++ { ++ dbus_set_error (error, ++ _dbus_error_from_errno (errno), ++ "Failed to setsockopt on socket %d: %s", ++ fd, _dbus_strerror (errno)); ++ } ++ } ++ else ++ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); ++ } ++ else ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++dbus_bool_t ++bus_driver_afbus_remove_match_rule (DBusConnection *connection, ++ const char *rule, ++ DBusError *error) ++{ ++ return bus_driver_afbus_upload_match_rule (connection, rule, NFDBUS_CMD_REMOVEMATCH, error); ++} ++ ++dbus_bool_t ++bus_driver_afbus_append_unique_name (DBusConnection *connection, ++ DBusString *str) ++{ ++ struct sockaddr_bus address; ++ long len = sizeof(address); ++ ++ memset (&address, 0, sizeof (address)); ++ if (!dbus_connection_get_peer_address(connection, &address, &len) || ++ address.sbus_family != AF_BUS) ++ return FALSE; ++ ++ if (!_dbus_string_append (str, "AF-BUS.")) ++ return FALSE; ++ ++ if (!_dbus_string_append_uint (str, address.sbus_addr.s_addr)) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++dbus_bool_t ++bus_driver_afbus_emit_forwarded (BusTransaction *transaction, ++ DBusConnection *connection, ++ DBusConnection *addressed_recipient, ++ const char *service_name) ++{ ++ struct sockaddr_bus address; ++ long len = sizeof (address); ++ DBusMessage *message; ++ dbus_bool_t result = FALSE; ++ ++ memset (&address, 0, sizeof (address)); ++ if (!dbus_connection_get_peer_address (addressed_recipient, &address, &len) || ++ address.sbus_family != AF_BUS) ++ { ++ /* Don't return an error if it is not a AF_BUS socket */ ++ return TRUE; ++ } ++ ++ /* Prepare the message to be sent */ ++ message = dbus_message_new_signal (DBUS_PATH_AFBUS, ++ DBUS_INTERFACE_AFBUS, ++ "Forwarded"); ++ if (message == NULL) ++ { ++ _dbus_verbose ("Could not allocate AF_BUS.Forwarded signal message\n"); ++ return FALSE; ++ } ++ ++ if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) ++ { ++ _dbus_verbose ("Could not set sender for AF_BUS.Forwarded signal message\n"); ++ goto out; ++ } ++ ++ if (!dbus_message_append_args (message, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_UINT64, &address.sbus_addr.s_addr, ++ DBUS_TYPE_INVALID)) ++ { ++ _dbus_verbose ("Could not append arguments for AF_BUS.Forwarded signal message\n"); ++ goto out; ++ } ++ ++ if (bus_transaction_send (transaction, connection, message)) ++ result = TRUE; ++ else ++ _dbus_verbose ("Could not send AF_BUS.Forwarded signal message\n"); ++ ++ out: ++ dbus_message_unref (message); ++ ++ return result; ++} ++ ++dbus_bool_t ++bus_driver_afbus_assign_address (DBusConnection *connection) ++{ ++ struct sockaddr_bus address; ++ long len = sizeof (address); ++ int fd; ++ static dbus_uint64_t next_address = 0x1111000000000001ULL; ++ ++ memset (&address, 0, sizeof (address)); ++ if (!dbus_connection_get_peer_address (connection, &address, &len) || ++ ((struct sockaddr *) &address)->sa_family != AF_BUS) ++ { ++ /* Don't return an error if it is not a AF_BUS socket */ ++ return TRUE; ++ } ++ ++ if (!dbus_connection_get_unix_fd (connection, &fd)) ++ { ++ return FALSE; ++ } ++ ++ address.sbus_addr.s_addr = next_address; ++ if (setsockopt (fd, SOL_BUS, BUS_ADD_ADDR, &address, sizeof (address)) != 0) ++ { ++ return FALSE; ++ } ++ ++ next_address++; ++ ++ return TRUE; ++} ++ ++dbus_bool_t ++bus_driver_afbus_disconnected (DBusConnection *connection, ++ DBusError *error) ++{ ++ return bus_driver_afbus_upload_match_rule (connection, "", ++ NFDBUS_CMD_REMOVEALLMATCH, error); ++} +diff --git a/bus/driver-afbus.h b/bus/driver-afbus.h +new file mode 100644 +index 0000000..9c40111 +--- /dev/null ++++ b/bus/driver-afbus.h +@@ -0,0 +1,96 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* driver-afbus.h Bus client, AF_BUS bits (driver) ++ * ++ * Copyright (C) 2012 Collabora Ltd ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#ifndef BUS_DRIVER_AFBUS_H ++#define BUS_DRIVER_AFBUS_H ++ ++#include <config.h> ++#include <sys/socket.h> ++#include <dbus/dbus.h> ++#include "connection.h" ++ ++#if HAVE_AFBUS ++dbus_bool_t bus_driver_afbus_add_match_rule (DBusConnection *connection, ++ const char *rule, ++ DBusError *error); ++dbus_bool_t bus_driver_afbus_remove_match_rule (DBusConnection *connection, ++ const char *rule, ++ DBusError *error); ++dbus_bool_t bus_driver_afbus_append_unique_name (DBusConnection *connection, ++ DBusString *str); ++dbus_bool_t bus_driver_afbus_emit_forwarded (BusTransaction *transaction, ++ DBusConnection *connection, ++ DBusConnection *addressed_recipient, ++ const char *service_name); ++dbus_bool_t bus_driver_afbus_assign_address (DBusConnection *connection); ++dbus_bool_t bus_driver_afbus_disconnected (DBusConnection *connection, ++ DBusError *error); ++#else ++static inline ++dbus_bool_t bus_driver_afbus_add_match_rule (DBusConnection *connection, ++ const char *rule, ++ DBusError *error) ++{ ++ return TRUE; ++} ++ ++static inline ++dbus_bool_t bus_driver_afbus_remove_match_rule (DBusConnection *connection, ++ const char *rule, ++ DBusError *error) ++{ ++ return TRUE; ++} ++ ++static inline ++dbus_bool_t bus_driver_afbus_append_unique_name (DBusConnection *connection, ++ DBusString *str) ++{ ++ return TRUE; ++} ++ ++static inline ++dbus_bool_t bus_driver_afbus_emit_forwarded (BusTransaction *transaction, ++ DBusConnection *connection, ++ DBusConnection *addressed_recipient, ++ const char *service_name) ++{ ++ return TRUE; ++} ++ ++static inline ++dbus_bool_t bus_driver_afbus_assign_address (DBusConnection *connection) ++{ ++ return TRUE; ++} ++ ++static inline ++dbus_bool_t bus_driver_afbus_disconnected (DBusConnection *connection, ++ DBusError *error) ++{ ++ return TRUE; ++} ++ ++#endif ++ ++#endif /* BUS_DRIVER_AFBUS_H */ +diff --git a/bus/driver.c b/bus/driver.c +index 574e0f3..11767c8 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -26,6 +26,7 @@ + #include "activation.h" + #include "connection.h" + #include "driver.h" ++#include "driver-afbus.h" + #include "dispatch.h" + #include "services.h" + #include "selinux.h" +@@ -182,8 +183,9 @@ bus_driver_send_service_acquired (DBusConnection *connection, + } + + static dbus_bool_t +-create_unique_client_name (BusRegistry *registry, +- DBusString *str) ++create_unique_client_name (DBusConnection *connection, ++ BusRegistry *registry, ++ DBusString *str) + { + /* We never want to use the same unique client name twice, because + * we want to guarantee that if you send a message to a given unique +@@ -214,19 +216,23 @@ create_unique_client_name (BusRegistry *registry, + _dbus_assert (next_major_number > 0); + _dbus_assert (next_minor_number >= 0); + +- /* appname:MAJOR-MINOR */ ++ /* unique name: ++ * :[AF-BUS.BUS-ADDRESS.]MAJOR.MINOR */ + + if (!_dbus_string_append (str, ":")) + return FALSE; + +- if (!_dbus_string_append_int (str, next_major_number)) +- return FALSE; ++ if (!bus_driver_afbus_append_unique_name (connection, str)) ++ { ++ if (!_dbus_string_append_int (str, next_major_number)) ++ return FALSE; + +- if (!_dbus_string_append (str, ".")) +- return FALSE; ++ if (!_dbus_string_append (str, ".")) ++ return FALSE; + +- if (!_dbus_string_append_int (str, next_minor_number)) +- return FALSE; ++ if (!_dbus_string_append_int (str, next_minor_number)) ++ return FALSE; ++ } + + next_minor_number += 1; + +@@ -287,7 +293,7 @@ bus_driver_handle_hello (DBusConnection *connection, + + registry = bus_connection_get_registry (connection); + +- if (!create_unique_client_name (registry, &unique_name)) ++ if (!create_unique_client_name (connection, registry, &unique_name)) + { + BUS_SET_OOM (error); + goto out_0; +@@ -610,6 +616,13 @@ bus_driver_handle_acquire_service (DBusConnection *connection, + goto out; + } + ++ /* If using AF_BUS, assign an address to this peer */ ++ if (!bus_driver_afbus_assign_address (connection)) ++ { ++ BUS_SET_OOM (error); ++ goto out; ++ } ++ + retval = TRUE; + + out: +@@ -988,6 +1001,9 @@ bus_driver_handle_add_match (DBusConnection *connection, + if (rule == NULL) + goto failed; + ++ if (!bus_driver_afbus_add_match_rule (connection, text, error)) ++ goto failed; ++ + matchmaker = bus_connection_get_matchmaker (connection); + + if (!bus_matchmaker_add_rule (matchmaker, rule)) +@@ -1051,6 +1067,9 @@ bus_driver_handle_remove_match (DBusConnection *connection, + message, error)) + goto failed; + ++ if (!bus_driver_afbus_remove_match_rule (connection, text, error)) ++ goto failed; ++ + matchmaker = bus_connection_get_matchmaker (connection); + + if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error)) +@@ -1779,6 +1798,13 @@ static InterfaceHandler interface_handlers[] = { + { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL }, + #ifdef DBUS_ENABLE_STATS + { BUS_INTERFACE_STATS, stats_message_handlers, NULL }, ++#ifdef HAVE_AFBUS ++ { DBUS_INTERFACE_AFBUS, NULL, ++ " <signal name=\"AF_BUS.Forwarded\">\n" ++ " <arg type=\"s\"/>\n" ++ " <arg type=\"t\"/>\n" ++ " </signal>\n" }, ++#endif + #endif + { NULL, NULL, NULL } + }; +diff --git a/bus/session.conf.in b/bus/session.conf.in +index e121ff9..09a7ecf 100644 +--- a/bus/session.conf.in ++++ b/bus/session.conf.in +@@ -12,7 +12,8 @@ + the behavior of child processes. --> + <keep_umask/> + +- <listen>@DBUS_SESSION_BUS_DEFAULT_ADDRESS@</listen> ++ <listen_if_possible>afbus:tmpdir=/tmp</listen_if_possible> ++ <listen>unix:tmpdir=/tmp</listen> + + <standard_session_servicedirs /> + +diff --git a/bus/system.conf.in b/bus/system.conf.in +index 92f4cc4..515509f 100644 +--- a/bus/system.conf.in ++++ b/bus/system.conf.in +@@ -39,6 +39,7 @@ + means use abstract namespace, don't really create filesystem + file; only Linux supports this. Use path=/whatever on other + systems.) --> ++ <listen_if_possible>afbus:@DBUS_SYSTEM_SOCKET@.afbus</listen_if_possible> + <listen>@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@</listen> + + <policy context="default"> +diff --git a/configure.ac b/configure.ac +index 4f86e9d..51a48fd 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1509,6 +1509,20 @@ if test "x$with_systemdsystemunitdir" != xno; then + fi + AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ]) + ++## Check for AF_DBUS ++AC_MSG_CHECKING([for AF_BUS socket family]) ++AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include <sys/socket.h>]], ++ [[return socket (PF_BUS, SOCK_STREAM, 0);]])], ++ [have_afbus=yes], ++ [have_afbus=no]) ++AC_MSG_RESULT([$have_afbus]) ++if test "x$have_afbus" = "xyes"; then ++ AC_DEFINE(HAVE_AFBUS, 1, [Define if AF_BUS is available]) ++fi ++AM_CONDITIONAL(HAVE_AFBUS, test "x$have_afbus" = "xyes") ++ + ##### Set up location for system bus socket + if ! test -z "$with_system_socket"; then + DBUS_SYSTEM_SOCKET=$with_system_socket +@@ -1648,7 +1662,11 @@ AC_SUBST(TEST_SOCKET_DIR) + AC_DEFINE_UNQUOTED(DBUS_TEST_SOCKET_DIR, "$TEST_SOCKET_DIR", [Where to put test sockets]) + + if test "x$dbus_unix" = xyes; then +- TEST_LISTEN="unix:tmpdir=$TEST_SOCKET_DIR" ++ if test "x$have_afbus" = "xyes"; then ++ TEST_LISTEN="afbus:tmpdir=$TEST_SOCKET_DIR" ++ else ++ TEST_LISTEN="unix:tmpdir=$TEST_SOCKET_DIR" ++ fi + else + TEST_LISTEN="tcp:host=localhost" + fi +@@ -1668,6 +1686,8 @@ if test x$dbus_win = xyes; then + DBUS_SESSION_BUS_DEFAULT_ADDRESS="$with_dbus_session_bus_default_address" + elif test x$have_launchd = xyes; then + DBUS_SESSION_BUS_DEFAULT_ADDRESS="launchd:env=DBUS_LAUNCHD_SESSION_BUS_SOCKET" ++elif test x$have_afbus = xyes; then ++ DBUS_SESSION_BUS_DEFAULT_ADDRESS="afbus:tmpdir=$DBUS_SESSION_SOCKET_DIR" + else + DBUS_SESSION_BUS_DEFAULT_ADDRESS="unix:tmpdir=$DBUS_SESSION_SOCKET_DIR" + fi +diff --git a/dbus/Makefile.am b/dbus/Makefile.am +index bb5ccca..b925419 100644 +--- a/dbus/Makefile.am ++++ b/dbus/Makefile.am +@@ -87,6 +87,16 @@ else + launchd_source = + endif + ++if HAVE_AFBUS ++afbus_source = \ ++ dbus-server-afbus.c \ ++ dbus-server-afbus.h \ ++ dbus-transport-afbus.c \ ++ dbus-transport-afbus.h ++else ++afbus_source = ++endif ++ + DBUS_LIB_arch_sources = \ + dbus-uuidgen.c \ + dbus-uuidgen.h \ +@@ -95,6 +105,7 @@ DBUS_LIB_arch_sources = \ + + DBUS_SHARED_arch_sources = \ + $(launchd_source) \ ++ $(afbus_source) \ + dbus-file-unix.c \ + dbus-pipe-unix.c \ + dbus-sysdeps-unix.c \ +diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c +index ee33b6c..5f3a459 100644 +--- a/dbus/dbus-connection.c ++++ b/dbus/dbus-connection.c +@@ -45,6 +45,8 @@ + #include "dbus-bus.h" + #include "dbus-marshal-basic.h" + ++#include <sys/socket.h> ++ + #ifdef DBUS_DISABLE_CHECKS + #define TOOK_LOCK_CHECK(connection) + #define RELEASING_LOCK_CHECK(connection) +@@ -2054,9 +2056,15 @@ _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection, + dbus_uint32_t *client_serial) + { + DBusDispatchStatus status; ++ const char *sender; + + HAVE_LOCK_CHECK (connection); +- ++ ++ /* Set the sender field */ ++ sender = dbus_bus_get_unique_name (connection); ++ if (sender) ++ dbus_message_set_sender (message, sender); ++ + _dbus_connection_send_preallocated_unlocked_no_update (connection, + preallocated, + message, client_serial); +@@ -3359,6 +3367,7 @@ dbus_connection_send_with_reply (DBusConnection *connection, + DBusPendingCall *pending; + dbus_int32_t serial = -1; + DBusDispatchStatus status; ++ const char *sender; + + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (message != NULL, FALSE); +@@ -3401,6 +3410,11 @@ dbus_connection_send_with_reply (DBusConnection *connection, + return FALSE; + } + ++ /* Set the sender field */ ++ sender = dbus_bus_get_unique_name (connection); ++ if (sender) ++ dbus_message_set_sender (message, sender); ++ + /* Assign a serial to the message */ + serial = dbus_message_get_serial (message); + if (serial == 0) +@@ -5439,6 +5453,27 @@ dbus_connection_set_route_peer_messages (DBusConnection *connection, + CONNECTION_UNLOCK (connection); + } + ++dbus_bool_t ++dbus_connection_get_peer_address (DBusConnection *connection, ++ void *addr, ++ long *len) ++{ ++ dbus_bool_t res; ++ int fd; ++ socklen_t _len = *len; ++ ++ _dbus_return_val_if_fail (connection != NULL, FALSE); ++ ++ res = _dbus_transport_get_socket_fd (connection->transport, &fd); ++ if (!res) ++ return res; ++ ++ res = getpeername(fd, (struct sockaddr *) addr, &_len) == 0; ++ if (res) ++ *len = _len; ++ return res; ++} ++ + /** + * Adds a message filter. Filters are handlers that are run on all + * incoming messages, prior to the objects registered with +diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h +index fe4d04e..81fe9f1 100644 +--- a/dbus/dbus-connection.h ++++ b/dbus/dbus-connection.h +@@ -287,6 +287,10 @@ void dbus_connection_set_allow_anonymous (DBusConnection + DBUS_EXPORT + void dbus_connection_set_route_peer_messages (DBusConnection *connection, + dbus_bool_t value); ++DBUS_EXPORT ++dbus_bool_t dbus_connection_get_peer_address (DBusConnection *connection, ++ void *addr, ++ long *len); + + + /* Filters */ +diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h +index 60605ab..71c2870 100644 +--- a/dbus/dbus-protocol.h ++++ b/dbus/dbus-protocol.h +@@ -458,6 +458,12 @@ extern "C" { + /** XML document type declaration of the introspection format version 1.0 */ + #define DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\"" DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER "\">\n" + ++/* AF_BUS errors */ ++ ++/** Tried to use a netlink socket and it failed. */ ++#define DBUS_ERROR_NETLINK "org.freedesktop.DBus.Error.NetLink" ++#define DBUS_ERROR_MULTIPLE_AFBUS "org.freedesktop.DBus.Error.MultipleAFBUS" ++ + /** @} */ + + #ifdef __cplusplus +diff --git a/dbus/dbus-server-afbus.c b/dbus/dbus-server-afbus.c +new file mode 100644 +index 0000000..1d8e9bd +--- /dev/null ++++ b/dbus/dbus-server-afbus.c +@@ -0,0 +1,397 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* dbus-server-unix.c Server implementation for Unix network protocols. ++ * ++ * Copyright (C) 2012 Collabora Ltd ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#include <config.h> ++#include <errno.h> ++#include <sys/socket.h> ++#include "dbus-connection-internal.h" ++#include "dbus-server-afbus.h" ++#include "dbus-server-protected.h" ++#include "dbus-string.h" ++#include "dbus-sysdeps.h" ++#include "dbus-transport.h" ++#include "dbus-transport-afbus.h" ++ ++/** ++ * @defgroup DBusServerAfbus DBusServer implementation for AF_BUS sockets ++ * @ingroup DBusInternals ++ * @brief Implementation details of DBusServer for AF_BUS sockets ++ * ++ * @{ ++ */ ++/** ++ * Opaque object representing a AF_BUS-based server implementation. ++ */ ++typedef struct DBusServerAfbus DBusServerAfbus; ++ ++/** ++ * Implementation details of DBusServerAfbus. All members ++ * are private. ++ */ ++struct DBusServerAfbus ++{ ++ DBusServer base; /**< Parent class members. */ ++ int fd; /**< File descriptor. */ ++ DBusWatch *watch; /**< File descriptor watch. */ ++ DBusString address; /**< The server address */ ++}; ++ ++static void ++afbus_finalize (DBusServer *server) ++{ ++ DBusServerAfbus *afbus_server = (DBusServerAfbus *) server; ++ ++ _dbus_server_finalize_base (server); ++ ++ if (afbus_server->watch != NULL) ++ { ++ _dbus_watch_unref (afbus_server->watch); ++ afbus_server->watch = NULL; ++ } ++ ++ dbus_free (server); ++} ++ ++static void ++afbus_disconnect (DBusServer *server) ++{ ++ DBusServerAfbus *afbus_server = (DBusServerAfbus *) server; ++ ++ HAVE_LOCK_CHECK (server); ++ ++ if (afbus_server->watch) ++ { ++ _dbus_server_remove_watch (server, afbus_server->watch); ++ _dbus_watch_invalidate (afbus_server->watch); ++ _dbus_watch_unref (afbus_server->watch); ++ afbus_server->watch = NULL; ++ } ++ ++ _dbus_close_socket (afbus_server->fd, NULL); ++ afbus_server->fd = -1; ++ ++ HAVE_LOCK_CHECK (server); ++} ++ ++static const DBusServerVTable afbus_vtable = { ++ afbus_finalize, ++ afbus_disconnect ++}; ++ ++static dbus_bool_t ++handle_new_client (DBusServer *server, ++ int client_fd) ++{ ++ DBusTransport *transport; ++ DBusConnection *connection; ++ DBusNewConnectionFunction new_connection_function; ++ void *new_connection_data; ++ ++ _dbus_verbose ("Creating new client connection with fd %d\n", client_fd); ++ ++ if (!_dbus_set_fd_nonblocking (client_fd, NULL)) ++ { ++ SERVER_UNLOCK (server); ++ return TRUE; ++ } ++ ++ transport = _dbus_transport_new_for_afbus (client_fd, &server->guid_hex, NULL); ++ if (transport == NULL) ++ { ++ _dbus_close_socket (client_fd, NULL); ++ SERVER_UNLOCK (server); ++ return FALSE; ++ } ++ ++ if (!_dbus_transport_set_auth_mechanisms (transport, ++ (const char **) server->auth_mechanisms)) ++ { ++ _dbus_transport_unref (transport); ++ SERVER_UNLOCK (server); ++ return FALSE; ++ } ++ ++ /* note that client_fd is now owned by the transport, and will be ++ * closed on transport disconnection/finalization ++ */ ++ connection = _dbus_connection_new_for_transport (transport); ++ _dbus_transport_unref (transport); ++ transport = NULL; /* now under the connection lock */ ++ ++ if (connection == NULL) ++ { ++ SERVER_UNLOCK (server); ++ return FALSE; ++ } ++ ++ /* See if someone wants to handle this new connection, self-referencing ++ * for paranoia. ++ */ ++ new_connection_function = server->new_connection_function; ++ new_connection_data = server->new_connection_data; ++ ++ _dbus_server_ref_unlocked (server); ++ SERVER_UNLOCK (server); ++ ++ if (new_connection_function) ++ { ++ (* new_connection_function) (server, connection, ++ new_connection_data); ++ } ++ dbus_server_unref (server); ++ ++ /* If no one grabbed a reference, the connection will die. */ ++ _dbus_connection_close_if_only_one_ref (connection); ++ dbus_connection_unref (connection); ++ ++ return TRUE; ++} ++ ++static dbus_bool_t ++afbus_handle_watch (DBusWatch *watch, ++ unsigned int flags, ++ void *data) ++{ ++ DBusServerAfbus *afbus_server = (DBusServerAfbus *) data; ++ DBusServer *server = (DBusServer *) data; ++ ++ SERVER_LOCK (server); ++ ++#ifndef DBUS_DISABLE_ASSERT ++ _dbus_assert (afbus_server->watch == watch); ++#endif ++ ++ _dbus_verbose ("Handling client connection, flags 0x%x\n", flags); ++ ++ if (flags & DBUS_WATCH_READABLE) ++ { ++ int client_fd; ++ ++ client_fd = _dbus_accept (afbus_server->fd); ++ if (client_fd < 0) ++ { ++ /* EINTR handled for us */ ++ ++ if (_dbus_get_is_errno_eagain_or_ewouldblock ()) ++ _dbus_verbose ("No client available to accept after all\n"); ++ else ++ _dbus_verbose ("Failed to accept a client connection: %s\n", ++ _dbus_strerror_from_errno ()); ++ ++ SERVER_UNLOCK (server); ++ } ++ else ++ { ++ if (!handle_new_client (server, client_fd)) ++ _dbus_verbose ("Rejected client connection due to lack of memory\n"); ++ } ++ } ++ ++ if (flags & DBUS_WATCH_ERROR) ++ _dbus_verbose ("Error on server listening socket\n"); ++ ++ if (flags & DBUS_WATCH_HANGUP) ++ _dbus_verbose ("Hangup on server listening socket\n"); ++ ++ return TRUE; ++} ++ ++static DBusServer * ++_dbus_server_new_for_afbus (int fd, const char *path, DBusError *error) ++{ ++ DBusServerAfbus *afbus_server; ++ DBusServer *server; ++ struct sockaddr_bus sock_address; ++ ++ afbus_server = dbus_new0 (DBusServerAfbus, 1); ++ if (afbus_server == NULL) ++ return NULL; ++ ++ if (!_dbus_string_init (&afbus_server->address) || ++ !_dbus_string_append (&afbus_server->address, "afbus:path=") || ++ !_dbus_string_append (&afbus_server->address, path)) ++ { ++ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); ++ goto failed_1; ++ } ++ ++ afbus_server->fd = fd; ++ ++ sock_address.sbus_family = AF_BUS; ++ strcpy (sock_address.sbus_path, path); ++ if (bind (afbus_server->fd, (struct sockaddr *) &sock_address, sizeof (sock_address)) < 0) ++ { ++ dbus_set_error (error, _dbus_error_from_errno (errno), ++ "Failed to bind socket \"%s\": %s", ++ path, _dbus_strerror (errno)); ++ goto failed_1; ++ } ++ ++ if (listen (afbus_server->fd, 30 /* backlog */) < 0) ++ { ++ dbus_set_error (error, _dbus_error_from_errno (errno), ++ "Failed to listen on AF_BUS socket: %s", ++ _dbus_strerror (errno)); ++ goto failed_1; ++ } ++ ++ afbus_server->watch = _dbus_watch_new (fd, ++ DBUS_WATCH_READABLE, ++ TRUE, ++ afbus_handle_watch, afbus_server, ++ NULL); ++ if (afbus_server->watch == NULL) ++ goto failed_1; ++ ++ if (!_dbus_server_init_base (&afbus_server->base, ++ &afbus_vtable, &afbus_server->address)) ++ goto failed_2; ++ ++ server = (DBusServer *) afbus_server; ++ server->is_afbus = TRUE; ++ ++ ++ SERVER_LOCK (server); ++ ++ if (!_dbus_server_add_watch (&afbus_server->base, ++ afbus_server->watch)) ++ { ++ SERVER_UNLOCK (server); ++ _dbus_server_finalize_base (&afbus_server->base); ++ ++ goto failed_2; ++ } ++ ++ SERVER_UNLOCK (server); ++ ++ _dbus_server_trace_ref (&afbus_server->base, 0, 1, "new_for_afbus"); ++ return (DBusServer *) afbus_server; ++ ++ failed_2: ++ _dbus_watch_unref (afbus_server->watch); ++ ++ failed_1: ++ _dbus_close_socket (afbus_server->fd, NULL); ++ dbus_free (afbus_server); ++ ++ return NULL; ++} ++ ++/** ++ * Starts a DBusServer listening on AF_BUS socket. ++ * Sets error if the result is not OK. ++ * ++ * @param entry an address entry ++ * @param server_p location to store a new DBusServer, or #NULL on failure. ++ * @param error location to store rationale for failure on bad address ++ * @returns the outcome ++ * ++ */ ++DBusServerListenResult ++_dbus_server_listen_afbus (DBusAddressEntry *entry, ++ DBusServer **server_p, ++ DBusError *error) ++{ ++ const char *method, *path, *tmpdir; ++ int listen_fd; ++ ++ *server_p = NULL; ++ ++ method = dbus_address_entry_get_method (entry); ++ if (strcmp (method, "afbus") != 0) ++ { ++ /* If we don't handle the method, we return NULL with the ++ * error unset ++ */ ++ _DBUS_ASSERT_ERROR_IS_CLEAR(error); ++ return DBUS_SERVER_LISTEN_NOT_HANDLED; ++ } ++ ++ path = dbus_address_entry_get_value (entry, "path"); ++ tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); ++ ++ if (path == NULL && tmpdir == NULL) ++ { ++ _dbus_set_bad_address(error, "unix", ++ "path or tmpdir", ++ NULL); ++ return DBUS_SERVER_LISTEN_BAD_ADDRESS; ++ } ++ ++ if (path && tmpdir) ++ { ++ _dbus_set_bad_address(error, NULL, NULL, ++ "cannot specify both \"path\" and \"tmpdir\" at the same time"); ++ return DBUS_SERVER_LISTEN_BAD_ADDRESS; ++ } ++ ++ if (!_dbus_open_socket (&listen_fd, PF_BUS, SOCK_SEQPACKET, BUS_PROTO_DBUS, error)) ++ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; ++ ++ if (!_dbus_set_fd_nonblocking (listen_fd, error)) ++ goto failed_1; ++ ++ if (tmpdir != NULL) ++ { ++ DBusString full_path; ++ DBusString filename; ++ ++ if (!_dbus_string_init (&full_path)) ++ { ++ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); ++ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; ++ } ++ ++ if (!_dbus_string_init (&filename)) ++ { ++ _dbus_string_free (&full_path); ++ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); ++ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; ++ } ++ ++ if (!_dbus_string_append (&filename, ++ "dbus-") || ++ !_dbus_generate_random_ascii (&filename, 10) || ++ !_dbus_string_append (&full_path, tmpdir) || ++ !_dbus_concat_dir_and_file (&full_path, &filename)) ++ { ++ _dbus_string_free (&full_path); ++ _dbus_string_free (&filename); ++ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); ++ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; ++ } ++ ++ path = _dbus_string_get_const_data (&full_path); ++ } ++ ++ *server_p = _dbus_server_new_for_afbus (listen_fd, path, error); ++ if (*server_p == NULL) ++ goto failed_1; ++ ++ return DBUS_SERVER_LISTEN_OK; ++ ++ failed_1: ++ _dbus_close_socket (listen_fd, NULL); ++ ++ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; ++} +diff --git a/dbus/dbus-server-afbus.h b/dbus/dbus-server-afbus.h +new file mode 100644 +index 0000000..8e5ad31 +--- /dev/null ++++ b/dbus/dbus-server-afbus.h +@@ -0,0 +1,36 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* dbus-server-unix.h Server implementation for Unix network protocols. ++ * ++ * Copyright (C) 2012 Collabora Ltd ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++#ifndef DBUS_SERVER_AFBUS_H ++#define DBUS_SERVER_AFBUS_H ++ ++#include "dbus-server-protected.h" ++ ++DBUS_BEGIN_DECLS ++ ++DBusServerListenResult _dbus_server_listen_afbus (DBusAddressEntry *entry, ++ DBusServer **server_p, ++ DBusError *error); ++ ++DBUS_END_DECLS ++ ++#endif +diff --git a/dbus/dbus-server-protected.h b/dbus/dbus-server-protected.h +index dd5234b..b423cb9 100644 +--- a/dbus/dbus-server-protected.h ++++ b/dbus/dbus-server-protected.h +@@ -89,6 +89,9 @@ struct DBusServer + #ifndef DBUS_DISABLE_CHECKS + unsigned int have_server_lock : 1; /**< Does someone have the server mutex locked */ + #endif ++#ifdef HAVE_AFBUS ++ unsigned int is_afbus : 1; /**< TRUE if this server listen on a AF_BUS socket */ ++#endif + }; + + dbus_bool_t _dbus_server_init_base (DBusServer *server, +diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c +index b62c2b4..2a23252 100644 +--- a/dbus/dbus-server.c ++++ b/dbus/dbus-server.c +@@ -25,6 +25,9 @@ + #include "dbus-server.h" + #include "dbus-server-unix.h" + #include "dbus-server-socket.h" ++#ifdef HAVE_AFBUS ++#include "dbus-server-afbus.h" ++#endif + #include "dbus-string.h" + #ifdef DBUS_BUILD_TESTS + #include "dbus-server-debug-pipe.h" +@@ -529,6 +532,9 @@ static const struct { + } listen_funcs[] = { + { _dbus_server_listen_socket } + , { _dbus_server_listen_platform_specific } ++#ifdef HAVE_AFBUS ++ , { _dbus_server_listen_afbus } ++#endif + #ifdef DBUS_BUILD_TESTS + , { _dbus_server_listen_debug_pipe } + #endif +@@ -844,6 +850,30 @@ dbus_server_get_address (DBusServer *server) + } + + /** ++ * Returns TRUE if the server listens on an AF_BUS address ++ * ++ * @param server the server ++ * @returns TRUE if the server listens on an AF_BUS address ++ */ ++dbus_bool_t ++dbus_server_is_afbus (DBusServer *server) ++{ ++ dbus_bool_t retval; ++ ++ _dbus_return_val_if_fail (server != NULL, FALSE); ++ ++#ifdef HAVE_AFBUS ++ SERVER_LOCK (server); ++ retval = server->is_afbus; ++ SERVER_UNLOCK (server); ++#else ++ retval = FALSE; ++#endif ++ ++ return retval; ++} ++ ++/** + * Returns the unique ID of the server, as a newly-allocated + * string which must be freed by the caller. This ID is + * normally used by clients to tell when two #DBusConnection +diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h +index bdbefa0..49cb9cf 100644 +--- a/dbus/dbus-server.h ++++ b/dbus/dbus-server.h +@@ -62,6 +62,8 @@ dbus_bool_t dbus_server_get_is_connected (DBusServer *server); + DBUS_EXPORT + char* dbus_server_get_address (DBusServer *server); + DBUS_EXPORT ++dbus_bool_t dbus_server_is_afbus (DBusServer *server); ++DBUS_EXPORT + char* dbus_server_get_id (DBusServer *server); + DBUS_EXPORT + void dbus_server_set_new_connection_function (DBusServer *server, +diff --git a/dbus/dbus-shared.h b/dbus/dbus-shared.h +index 6a57670..b6b29b3 100644 +--- a/dbus/dbus-shared.h ++++ b/dbus/dbus-shared.h +@@ -80,6 +80,10 @@ typedef enum + #define DBUS_PATH_DBUS "/org/freedesktop/DBus" + /** The object path used in local/in-process-generated messages. */ + #define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local" ++#ifdef HAVE_AFBUS ++/** The object path used for AF_BUS sockets. */ ++#define DBUS_PATH_AFBUS "/org/freedesktop/DBus/AF_BUS" ++#endif + + /* Interfaces, these #define don't do much other than + * catch typos at compile time +@@ -92,6 +96,10 @@ typedef enum + #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties" + /** The interface supported by most dbus peers */ + #define DBUS_INTERFACE_PEER "org.freedesktop.DBus.Peer" ++#ifdef HAVE_AFBUS ++/** The interface supported by AF_BUS transport */ ++#define DBUS_INTERFACE_AFBUS "org.freedesktop.DBus.AF_BUS" ++#endif + + /** This is a special interface whose methods can only be invoked + * by the local implementation (messages from remote apps aren't +diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c +index cef8bd3..26e3d00 100644 +--- a/dbus/dbus-sysdeps-unix.c ++++ b/dbus/dbus-sysdeps-unix.c +@@ -122,7 +122,7 @@ + + #endif /* Solaris */ + +-static dbus_bool_t ++dbus_bool_t + _dbus_open_socket (int *fd_p, + int domain, + int type, +diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h +index 4052cda..a589486 100644 +--- a/dbus/dbus-sysdeps.h ++++ b/dbus/dbus-sysdeps.h +@@ -125,6 +125,11 @@ typedef unsigned long dbus_gid_t; + * + */ + ++dbus_bool_t _dbus_open_socket (int *fd_p, ++ int domain, ++ int type, ++ int protocol, ++ DBusError *error); + dbus_bool_t _dbus_close_socket (int fd, + DBusError *error); + int _dbus_read_socket (int fd, +diff --git a/dbus/dbus-transport-afbus.c b/dbus/dbus-transport-afbus.c +new file mode 100644 +index 0000000..9574bca +--- /dev/null ++++ b/dbus/dbus-transport-afbus.c +@@ -0,0 +1,394 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* dbus-transport-socket.h Socket subclasses of DBusTransport ++ * ++ * Copyright (C) 212 Collabora Ltd ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#include <config.h> ++#include <errno.h> ++#include <sys/socket.h> ++#include "dbus-connection-internal.h" ++#include "dbus-hash.h" ++#include "dbus-transport-afbus.h" ++#include "dbus-transport-socket.h" ++#include "dbus-watch.h" ++ ++static DBusHashTable *wkn_addresses_cache = NULL; ++ ++/** ++ * @defgroup DBusTransportAfbus AF_BUS-based DBusTransport implementation ++ * @ingroup DBusInternals ++ * @brief Implementation details of DBusTransport on AF_BUS sockets ++ * ++ * @{ ++ */ ++ ++/** ++ * Opaque object representing a AF_BUS-based transport. ++ */ ++typedef struct DBusTransportAfbus DBusTransportAfbus; ++ ++/** ++ * Implementation details of DBusTransportAfbus. All members are private. ++ */ ++struct DBusTransportAfbus ++{ ++ DBusTransportSocket base; /**< Parent instance */ ++}; ++ ++static dbus_bool_t ++get_write_destination (int fd, ++ DBusMessage *message, ++ struct sockaddr_bus *sock) ++{ ++ socklen_t addrlen; ++ const char *destination; ++ const char *sender; ++ ++ /* if the sender is the bus driver, don't set the sockaddr, just let the ++ * message be delivered to the peer socket ++ */ ++ sender = dbus_message_get_sender (message); ++ if (sender && strcmp (sender, DBUS_SERVICE_DBUS) == 0) ++ { ++ return FALSE; ++ } ++ ++ addrlen = sizeof(struct sockaddr_bus); ++ if (getsockname (fd, (struct sockaddr *) sock, &addrlen) != 0) ++ return FALSE; ++ if (addrlen != sizeof(struct sockaddr_bus)) ++ return FALSE; ++ if (sock->sbus_family != AF_BUS) ++ return FALSE; ++ ++ destination = dbus_message_get_destination (message); ++ if (destination && strcmp (destination, DBUS_SERVICE_DBUS) == 0) ++ { ++ /* a message for the bus driver */ ++ sock->sbus_addr.s_addr = 0; ++ return TRUE; ++ } ++ ++ if (destination != NULL && strlen (destination) > 0) ++ { ++ dbus_uint64_t peer = 0x0000000000000000ULL; ++ ++ /* If destination is a unique name, just retrieve the peer address from it */ ++ if (strncmp (destination, ":AF-BUS.", 8) == 0) ++ { ++ DBusString tmp; ++ ++ _dbus_string_init_const (&tmp, &destination[8]); ++ if (!_dbus_string_parse_uint (&tmp, 0, (unsigned long *) &peer, NULL)) ++ peer = 0x0000000000000000ULL; ++ _dbus_string_free (&tmp); ++ } ++ else ++ { ++ /* a message for a well known name */ ++ if (wkn_addresses_cache != NULL) ++ { ++ dbus_uint64_t *peer_pointer; ++ ++ peer_pointer = (dbus_uint64_t *) _dbus_hash_table_lookup_string (wkn_addresses_cache, destination); ++ if (peer_pointer != NULL) ++ peer = *peer_pointer; ++ } ++ } ++ ++ sock->sbus_addr.s_addr = peer; ++ ++ return TRUE; ++ } ++ else ++ { ++ /* a multicast message */ ++ sock->sbus_addr.s_addr = 0x0000ffffffffffffULL; ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++static int ++afbus_write_socket (DBusTransportSocket *socket_transport, ++ DBusMessage *message, ++ const DBusString *buffer, ++ int start, ++ int len) ++{ ++ int fd, bytes_written; ++ struct sockaddr_bus sock; ++ ++ if (!_dbus_transport_get_socket_fd ((DBusTransport *) socket_transport, &fd)) ++ { ++ _dbus_verbose ("Couldn't get socket's file descriptor\n"); ++ return -1; ++ } ++ ++ if (get_write_destination (fd, message, &sock)) ++ { ++ const char *data; ++ ++ /* Send the data to specific address */ ++ data = _dbus_string_get_const_data_len (buffer, start, len); ++ ++ bytes_written = sendto (fd, data, len, MSG_NOSIGNAL, ++ (struct sockaddr *) &sock, sizeof (struct sockaddr_bus)); ++ } ++ else ++ bytes_written = _dbus_write_socket (fd, buffer, start, len); ++ ++ return bytes_written; ++} ++ ++static int ++afbus_write_socket_two (DBusTransportSocket *socket_transport, ++ DBusMessage *message, ++ const DBusString *header, ++ int header_start, ++ int header_len, ++ const DBusString *body, ++ int body_start, ++ int body_len) ++{ ++ int fd, bytes_written; ++ struct sockaddr_bus sock; ++ ++ if (!_dbus_transport_get_socket_fd ((DBusTransport *) socket_transport, &fd)) ++ { ++ _dbus_verbose ("Couldn't get socket's file descriptor\n"); ++ return -1; ++ } ++ ++ if (get_write_destination (fd, message, &sock)) ++ { ++ struct iovec vectors[2]; ++ const char *data1, *data2; ++ struct msghdr m; ++ ++ data1 = _dbus_string_get_const_data_len (header, header_start, header_len); ++ if (body != NULL) ++ data2 = _dbus_string_get_const_data_len (body, body_start, body_len); ++ else ++ { ++ data2 = NULL; ++ body_start = body_len = 0; ++ } ++ ++ vectors[0].iov_base = (char *) data1; ++ vectors[0].iov_len = header_len; ++ vectors[1].iov_base = (char *) data2; ++ vectors[1].iov_len = body_len; ++ ++ _DBUS_ZERO(m); ++ m.msg_iov = vectors; ++ m.msg_iovlen = data2 ? 2 : 1; ++ m.msg_name = &sock; ++ m.msg_namelen = sizeof (sock); ++ ++ again: ++ bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL); ++ if (bytes_written < 0 && errno == EINTR) ++ goto again; ++ } ++ else ++ bytes_written = _dbus_write_socket_two (fd, header, header_start, header_len, body, body_start, body_len); ++ ++ return bytes_written; ++} ++ ++static void ++afbus_authenticated (DBusTransportSocket *socket_transport) ++{ ++ if (socket_transport->base.is_server) ++ { ++ /* Make the client join the bus when authenticated, so that it can send ++ * unicast messages to peers other than the daemon */ ++ if (setsockopt (socket_transport->fd, SOL_BUS, BUS_JOIN_BUS, NULL, 0) != 0) ++ { ++ _dbus_verbose ("Could not join client to the bus\n"); ++ } ++ } ++} ++ ++static void ++afbus_message_received (DBusTransportSocket *socket_transport, ++ DBusMessage *message) ++{ ++ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) ++ { ++ const char *path, *interface, *member; ++ ++ path = dbus_message_get_path (message); ++ interface = dbus_message_get_interface (message); ++ member = dbus_message_get_member (message); ++ ++ if (strcmp (path, DBUS_PATH_AFBUS) == 0 ++ && strcmp (interface, DBUS_INTERFACE_AFBUS) == 0 ++ && strcmp (member, "Forwarded") == 0) ++ { ++ char *wkn; ++ dbus_uint64_t peer; ++ dbus_uint64_t *peer_pointer; ++ ++ /* Update the cache */ ++ if (wkn_addresses_cache == NULL) ++ { ++ wkn_addresses_cache = _dbus_hash_table_new (DBUS_HASH_STRING, ++ dbus_free, ++ dbus_free); ++ if (wkn_addresses_cache == NULL) ++ return; ++ } ++ ++ dbus_message_get_args (message, NULL, ++ DBUS_TYPE_STRING, &wkn, ++ DBUS_TYPE_UINT64, &peer, ++ DBUS_TYPE_INVALID); ++ ++ peer_pointer = dbus_new (dbus_uint64_t, 1); ++ *peer_pointer = peer; ++ _dbus_hash_table_insert_string (wkn_addresses_cache, ++ _dbus_strdup (wkn), ++ (void *) peer_pointer); ++ } ++ } ++} ++ ++static const DBusTransportSocketVTable afbus_vtable = { ++ afbus_write_socket, ++ afbus_write_socket_two, ++ afbus_authenticated, ++ afbus_message_received ++}; ++ ++/** ++ * Creates a new AF_BUS-based transport for the given socket descriptor. ++ * ++ * @param fd the file descriptor. ++ * @param server_guid non-#NULL if this transport is on the server side of a connection ++ * @param address the transport's address ++ * @returns the new transport, or #NULL if no memory. ++ */ ++DBusTransport* ++_dbus_transport_new_for_afbus (int fd, ++ const DBusString *server_guid, ++ const DBusString *address) ++{ ++ DBusTransportAfbus *afbus_transport; ++ ++ afbus_transport = dbus_new0 (DBusTransportAfbus, 1); ++ if (afbus_transport == NULL) ++ return NULL; ++ ++ if (!_dbus_transport_socket_init_base (&afbus_transport->base, ++ fd, ++ &afbus_vtable, ++ server_guid, address)) ++ goto failed_1; ++ ++ return (DBusTransport *) afbus_transport; ++ ++ failed_1: ++ dbus_free (afbus_transport); ++ ++ return NULL; ++} ++ ++/** ++ * Opens a AF_BUS-based transport. ++ * ++ * @param entry the address entry to try opening as a tcp transport. ++ * @param transport_p return location for the opened transport ++ * @param error error to be set ++ * @returns result of the attempt ++ */ ++DBusTransportOpenResult ++_dbus_transport_open_afbus (DBusAddressEntry *entry, ++ DBusTransport **transport_p, ++ DBusError *error) ++{ ++ const char *method, *path; ++ DBusString address; ++ int fd; ++ struct sockaddr_bus sock_address; ++ ++ method = dbus_address_entry_get_method (entry); ++ if (strcmp (method, "afbus") != 0) ++ { ++ _DBUS_ASSERT_ERROR_IS_CLEAR (error); ++ return DBUS_TRANSPORT_OPEN_NOT_HANDLED; ++ } ++ ++ path = dbus_address_entry_get_value (entry, "path"); ++ if (path == NULL) ++ { ++ _dbus_set_bad_address (error, "afbus", ++ "path or tmpdir", ++ NULL); ++ return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; ++ } ++ ++ if (!_dbus_string_init (&address) || ++ !_dbus_string_append (&address, "afbus:path=") || ++ !_dbus_string_append (&address, path)) ++ { ++ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); ++ return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; ++ } ++ ++ if (!_dbus_open_socket (&fd, PF_BUS, SOCK_SEQPACKET, BUS_PROTO_DBUS, error)) ++ goto failed_1; ++ ++ if (!_dbus_set_fd_nonblocking (fd, error)) ++ goto failed_2; ++ ++ sock_address.sbus_family = AF_BUS; ++ strcpy (sock_address.sbus_path, path); ++ if (connect (fd, (struct sockaddr *) &sock_address, sizeof (sock_address)) < 0) ++ { ++ dbus_set_error (error, ++ _dbus_error_from_errno (errno), ++ "Failed to connect to socket %s: %s", ++ path, _dbus_strerror (errno)); ++ goto failed_2; ++ } ++ ++ *transport_p = _dbus_transport_new_for_afbus (fd, NULL, &address); ++ if (*transport_p == NULL) ++ { ++ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); ++ goto failed_2; ++ } ++ ++ _dbus_string_free (&address); ++ ++ return DBUS_TRANSPORT_OPEN_OK; ++ ++ failed_2: ++ _dbus_close_socket (fd, NULL); ++ ++ failed_1: ++ _dbus_string_free (&address); ++ ++ return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; ++} +diff --git a/dbus/dbus-transport-afbus.h b/dbus/dbus-transport-afbus.h +new file mode 100644 +index 0000000..c94e32d +--- /dev/null ++++ b/dbus/dbus-transport-afbus.h +@@ -0,0 +1,41 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* dbus-transport-socket.h Socket subclasses of DBusTransport ++ * ++ * Copyright (C) 212 Collabora Ltd ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++#ifndef DBUS_TRANSPORT_AFBUS_H ++#define DBUS_TRANSPORT_AFBUS_H ++ ++#include <sys/socket.h> ++#include <sys/bus.h> ++#include <dbus/dbus-transport-protected.h> ++ ++DBUS_BEGIN_DECLS ++ ++DBusTransport *_dbus_transport_new_for_afbus (int fd, ++ const DBusString *server_guid, ++ const DBusString *address); ++DBusTransportOpenResult _dbus_transport_open_afbus (DBusAddressEntry *entry, ++ DBusTransport **transport_p, ++ DBusError *error); ++ ++DBUS_END_DECLS ++ ++#endif +diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h +index 44b9d78..9becbdb 100644 +--- a/dbus/dbus-transport-protected.h ++++ b/dbus/dbus-transport-protected.h +@@ -69,6 +69,10 @@ struct DBusTransportVTable + dbus_bool_t (* get_socket_fd) (DBusTransport *transport, + int *fd_p); + /**< Get socket file descriptor */ ++ ++ void (* process_incoming_message) (DBusTransport *transport, ++ DBusMessage *message); ++ /**> Method to allow transport to filter messages */ + }; + + /** +diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c +index 544d00a..a3951ef 100644 +--- a/dbus/dbus-transport-socket.c ++++ b/dbus/dbus-transport-socket.c +@@ -22,6 +22,7 @@ + */ + + #include <config.h> ++#include <sys/ioctl.h> + #include "dbus-internals.h" + #include "dbus-connection-internal.h" + #include "dbus-nonce.h" +@@ -38,43 +39,13 @@ + * @{ + */ + +-/** +- * Opaque object representing a socket file descriptor transport. +- */ +-typedef struct DBusTransportSocket DBusTransportSocket; +- +-/** +- * Implementation details of DBusTransportSocket. All members are private. +- */ +-struct DBusTransportSocket +-{ +- DBusTransport base; /**< Parent instance */ +- int fd; /**< File descriptor. */ +- DBusWatch *read_watch; /**< Watch for readability. */ +- DBusWatch *write_watch; /**< Watch for writability. */ +- +- int max_bytes_read_per_iteration; /**< To avoid blocking too long. */ +- int max_bytes_written_per_iteration; /**< To avoid blocking too long. */ +- +- int message_bytes_written; /**< Number of bytes of current +- * outgoing message that have +- * been written. +- */ +- DBusString encoded_outgoing; /**< Encoded version of current +- * outgoing message. +- */ +- DBusString encoded_incoming; /**< Encoded version of current +- * incoming data. +- */ +-}; +- + static void + free_watches (DBusTransport *transport) + { + DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; + + _dbus_verbose ("start\n"); +- ++ + if (socket_transport->read_watch) + { + if (transport->connection) +@@ -104,7 +75,7 @@ socket_finalize (DBusTransport *transport) + DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; + + _dbus_verbose ("\n"); +- ++ + free_watches (transport); + + _dbus_string_free (&socket_transport->encoded_outgoing); +@@ -136,7 +107,16 @@ check_write_watch (DBusTransport *transport) + _dbus_transport_ref (transport); + + if (_dbus_transport_get_is_authenticated (transport)) +- needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection); ++ { ++ if (!socket_transport->auth_notified && ++ socket_transport->vtable->authenticated != NULL) ++ { ++ socket_transport->auth_notified = TRUE; ++ socket_transport->vtable->authenticated (socket_transport); ++ } ++ ++ needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection); ++ } + else + { + if (transport->send_credentials_pending) +@@ -146,7 +126,7 @@ check_write_watch (DBusTransport *transport) + DBusAuthState auth_state; + + auth_state = _dbus_auth_do_work (transport->auth); +- ++ + /* If we need memory we install the write watch just in case, + * if there's no need for it, it will get de-installed + * next time we try reading. +@@ -191,9 +171,18 @@ check_read_watch (DBusTransport *transport) + _dbus_transport_ref (transport); + + if (_dbus_transport_get_is_authenticated (transport)) +- need_read_watch = +- (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) && +- (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds); ++ { ++ if (!socket_transport->auth_notified && ++ socket_transport->vtable->authenticated != NULL) ++ { ++ socket_transport->auth_notified = TRUE; ++ socket_transport->vtable->authenticated (socket_transport); ++ } ++ ++ need_read_watch = ++ (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) && ++ (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds); ++ } + else + { + if (transport->receive_credentials_pending) +@@ -489,6 +478,59 @@ do_authentication (DBusTransport *transport, + return TRUE; + } + ++static int ++_write_socket (DBusTransportSocket *socket_transport, ++ DBusMessage *message, ++ const DBusString *buffer, ++ int start, ++ int len) ++{ ++ int bytes_written; ++ ++ if (socket_transport->vtable->write_socket != NULL) ++ { ++ bytes_written = socket_transport->vtable->write_socket (socket_transport, ++ message, ++ buffer, start, len); ++ } ++ else ++ { ++ bytes_written = _dbus_write_socket (socket_transport->fd, ++ buffer, ++ start, len); ++ } ++ ++ return bytes_written; ++} ++ ++static int ++_write_socket_two (DBusTransportSocket *socket_transport, ++ DBusMessage *message, ++ const DBusString *header, ++ int header_start, ++ int header_len, ++ const DBusString *body, ++ int body_start, ++ int body_len) ++{ ++ int bytes_written; ++ ++ if (socket_transport->vtable->write_socket_two != NULL) ++ { ++ bytes_written = socket_transport->vtable->write_socket_two (socket_transport, message, ++ header, header_start, header_len, ++ body, body_start, body_len); ++ } ++ else ++ { ++ bytes_written = _dbus_write_socket_two (socket_transport->fd, ++ header, header_start, header_len, ++ body, body_start, body_len); ++ } ++ ++ return bytes_written; ++} ++ + /* returns false on oom */ + static dbus_bool_t + do_writing (DBusTransport *transport) +@@ -579,12 +621,13 @@ do_writing (DBusTransport *transport) + _dbus_verbose ("encoded message is %d bytes\n", + total_bytes_to_write); + #endif +- ++ + bytes_written = +- _dbus_write_socket (socket_transport->fd, +- &socket_transport->encoded_outgoing, +- socket_transport->message_bytes_written, +- total_bytes_to_write - socket_transport->message_bytes_written); ++ _write_socket (socket_transport, ++ message, ++ &socket_transport->encoded_outgoing, ++ socket_transport->message_bytes_written, ++ total_bytes_to_write - socket_transport->message_bytes_written); + } + else + { +@@ -623,21 +666,23 @@ do_writing (DBusTransport *transport) + if (socket_transport->message_bytes_written < header_len) + { + bytes_written = +- _dbus_write_socket_two (socket_transport->fd, +- header, +- socket_transport->message_bytes_written, +- header_len - socket_transport->message_bytes_written, +- body, +- 0, body_len); ++ _write_socket_two (socket_transport, ++ message, ++ header, ++ socket_transport->message_bytes_written, ++ header_len - socket_transport->message_bytes_written, ++ body, ++ 0, body_len); + } + else + { + bytes_written = +- _dbus_write_socket (socket_transport->fd, +- body, +- (socket_transport->message_bytes_written - header_len), +- body_len - +- (socket_transport->message_bytes_written - header_len)); ++ _write_socket (socket_transport, ++ message, ++ body, ++ (socket_transport->message_bytes_written - header_len), ++ body_len - ++ (socket_transport->message_bytes_written - header_len)); + } + } + } +@@ -696,7 +741,7 @@ do_reading (DBusTransport *transport) + { + DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; + DBusString *buffer; +- int bytes_read; ++ int bytes_read, bytes_available; + int total; + dbus_bool_t oom; + +@@ -730,7 +775,12 @@ do_reading (DBusTransport *transport) + + if (!dbus_watch_get_enabled (socket_transport->read_watch)) + return TRUE; +- ++ ++ if (ioctl (socket_transport->fd, FIONREAD, &bytes_available) < 0) ++ bytes_available = socket_transport->max_bytes_read_per_iteration; ++ else if (bytes_available < socket_transport->max_bytes_read_per_iteration) ++ bytes_available = socket_transport->max_bytes_read_per_iteration; ++ + if (_dbus_auth_needs_decoding (transport->auth)) + { + /* Does fd passing even make sense with encoded data? */ +@@ -741,7 +791,7 @@ do_reading (DBusTransport *transport) + else + bytes_read = _dbus_read_socket (socket_transport->fd, + &socket_transport->encoded_incoming, +- socket_transport->max_bytes_read_per_iteration); ++ bytes_available); + + _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) == + bytes_read); +@@ -796,7 +846,7 @@ do_reading (DBusTransport *transport) + + bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd, + buffer, +- socket_transport->max_bytes_read_per_iteration, ++ bytes_available, + fds, &n_fds); + + if (bytes_read >= 0 && n_fds > 0) +@@ -808,7 +858,7 @@ do_reading (DBusTransport *transport) + #endif + { + bytes_read = _dbus_read_socket (socket_transport->fd, +- buffer, socket_transport->max_bytes_read_per_iteration); ++ buffer, bytes_available); + } + + _dbus_message_loader_return_buffer (transport->loader, +@@ -1207,6 +1257,19 @@ socket_get_socket_fd (DBusTransport *transport, + return TRUE; + } + ++static void ++socket_process_incoming_message (DBusTransport *transport, ++ DBusMessage *message) ++{ ++ DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; ++ ++ if (socket_transport->vtable->message_received != NULL) ++ { ++ (* socket_transport->vtable->message_received) (socket_transport, ++ message); ++ } ++} ++ + static const DBusTransportVTable socket_vtable = { + socket_finalize, + socket_handle_watch, +@@ -1214,37 +1277,40 @@ static const DBusTransportVTable socket_vtable = { + socket_connection_set, + socket_do_iteration, + socket_live_messages_changed, +- socket_get_socket_fd ++ socket_get_socket_fd, ++ socket_process_incoming_message + }; + + /** +- * Creates a new transport for the given socket file descriptor. The file +- * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to +- * make it so). This function is shared by various transports that +- * boil down to a full duplex file descriptor. ++ * Initializes the base class members of DBusTransportSocket. Chained up to ++ * by subclasses in their constructor. The server GUID is the ++ * globally unique ID for the server creating this connection ++ * and will be #NULL for the client side of a connection. The GUID ++ * is in hex format. + * +- * @param fd the file descriptor. ++ * @param socket_transport the transport being created. ++ * @param fd The socket for this transport ++ * @param vtable the subclass vtable. + * @param server_guid non-#NULL if this transport is on the server side of a connection +- * @param address the transport's address +- * @returns the new transport, or #NULL if no memory. ++ * @param address the address of the transport ++ * @returns #TRUE on success. + */ +-DBusTransport* +-_dbus_transport_new_for_socket (int fd, +- const DBusString *server_guid, +- const DBusString *address) ++dbus_bool_t ++_dbus_transport_socket_init_base (DBusTransportSocket *socket_transport, ++ int fd, ++ const DBusTransportSocketVTable *vtable, ++ const DBusString *server_guid, ++ const DBusString *address) + { +- DBusTransportSocket *socket_transport; +- +- socket_transport = dbus_new0 (DBusTransportSocket, 1); +- if (socket_transport == NULL) +- return NULL; +- + if (!_dbus_string_init (&socket_transport->encoded_outgoing)) + goto failed_0; + + if (!_dbus_string_init (&socket_transport->encoded_incoming)) + goto failed_1; +- ++ ++ socket_transport->auth_notified = FALSE; ++ socket_transport->vtable = vtable; ++ + socket_transport->write_watch = _dbus_watch_new (fd, + DBUS_WATCH_WRITABLE, + FALSE, +@@ -1275,7 +1341,7 @@ _dbus_transport_new_for_socket (int fd, + socket_transport->max_bytes_read_per_iteration = 2048; + socket_transport->max_bytes_written_per_iteration = 2048; + +- return (DBusTransport*) socket_transport; ++ return TRUE; + + failed_4: + _dbus_watch_invalidate (socket_transport->read_watch); +@@ -1288,8 +1354,46 @@ _dbus_transport_new_for_socket (int fd, + failed_1: + _dbus_string_free (&socket_transport->encoded_outgoing); + failed_0: +- dbus_free (socket_transport); +- return NULL; ++ ++ return FALSE; ++} ++ ++/** ++ * Creates a new transport for the given socket file descriptor. The file ++ * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to ++ * make it so). This function is shared by various transports that ++ * boil down to a full duplex file descriptor. ++ * ++ * @param fd the file descriptor. ++ * @param server_guid non-#NULL if this transport is on the server side of a connection ++ * @param address the transport's address ++ * @returns the new transport, or #NULL if no memory. ++ */ ++DBusTransport* ++_dbus_transport_new_for_socket (int fd, ++ const DBusString *server_guid, ++ const DBusString *address) ++{ ++ DBusTransportSocket *socket_transport; ++ static const DBusTransportSocketVTable vtable = { ++ NULL ++ }; ++ ++ socket_transport = dbus_new0 (DBusTransportSocket, 1); ++ if (socket_transport == NULL) ++ return NULL; ++ ++ if (!_dbus_transport_socket_init_base (socket_transport, ++ fd, ++ &vtable, ++ server_guid, ++ address)) ++ { ++ dbus_free (socket_transport); ++ return NULL; ++ } ++ ++ return (DBusTransport *) socket_transport; + } + + /** +diff --git a/dbus/dbus-transport-socket.h b/dbus/dbus-transport-socket.h +index 8aefae3..ed7fdcc 100644 +--- a/dbus/dbus-transport-socket.h ++++ b/dbus/dbus-transport-socket.h +@@ -27,6 +27,80 @@ + + DBUS_BEGIN_DECLS + ++/** ++ * Opaque object representing a socket file descriptor transport. ++ */ ++typedef struct DBusTransportSocket DBusTransportSocket; ++ ++/** ++ * The virtual table that must be implemented to ++ * create a socket-based transport. ++ */ ++typedef struct DBusTransportSocketVTable DBusTransportSocketVTable; ++ ++struct DBusTransportSocketVTable ++{ ++ int (* write_socket) (DBusTransportSocket *socket_transport, ++ DBusMessage *message, ++ const DBusString *buffer, ++ int start, ++ int len); ++ /**< Write part of a message to the transport */ ++ ++ int (* write_socket_two) (DBusTransportSocket *socket_transport, ++ DBusMessage *message, ++ const DBusString *header, ++ int header_start, ++ int header_len, ++ const DBusString *body, ++ int body_start, ++ int body_len); ++ /**< Write header and body to the transport */ ++ ++ void (* authenticated) (DBusTransportSocket *socket_transport); ++ /**< Notification of authentication successful */ ++ ++ void (* message_received) (DBusTransportSocket *socket_transport, ++ DBusMessage *message); ++ /**< Notification of a message received */ ++}; ++ ++/** ++ * Implementation details of DBusTransportSocket. All members are private. ++ */ ++struct DBusTransportSocket ++{ ++ DBusTransport base; /**< Parent instance */ ++ int fd; /**< File descriptor. */ ++ DBusWatch *read_watch; /**< Watch for readability. */ ++ DBusWatch *write_watch; /**< Watch for writability. */ ++ ++ int max_bytes_read_per_iteration; /**< To avoid blocking too long. */ ++ int max_bytes_written_per_iteration; /**< To avoid blocking too long. */ ++ ++ int message_bytes_written; /**< Number of bytes of current ++ * outgoing message that have ++ * been written. ++ */ ++ DBusString encoded_outgoing; /**< Encoded version of current ++ * outgoing message. ++ */ ++ DBusString encoded_incoming; /**< Encoded version of current ++ * incoming data. ++ */ ++ dbus_bool_t auth_notified; /**< Have we notified subclasses ++ * we are authenticated? ++ */ ++ const DBusTransportSocketVTable *vtable; /**< Virtual table of transport methods. */ ++}; ++ ++dbus_bool_t _dbus_transport_socket_init_base (DBusTransportSocket *socket_transport, ++ int fd, ++ const DBusTransportSocketVTable *vtable, ++ const DBusString *server_guid, ++ const DBusString *address); ++void _dbus_transport_socket_finalize_base (DBusTransportSocket *socket_transport); ++ + DBusTransport* _dbus_transport_new_for_socket (int fd, + const DBusString *server_guid, + const DBusString *address); +diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c +index 6b58fda..44923da 100644 +--- a/dbus/dbus-transport.c ++++ b/dbus/dbus-transport.c +@@ -25,6 +25,9 @@ + #include "dbus-transport-protected.h" + #include "dbus-transport-unix.h" + #include "dbus-transport-socket.h" ++#ifdef HAVE_AFBUS ++#include "dbus-transport-afbus.h" ++#endif + #include "dbus-connection-internal.h" + #include "dbus-watch.h" + #include "dbus-auth.h" +@@ -348,6 +351,9 @@ static const struct { + { _dbus_transport_open_socket }, + { _dbus_transport_open_platform_specific }, + { _dbus_transport_open_autolaunch } ++#ifdef HAVE_AFBUS ++ , { _dbus_transport_open_afbus } ++#endif + #ifdef DBUS_BUILD_TESTS + , { _dbus_transport_open_debug_pipe } + #endif +@@ -980,6 +986,28 @@ _dbus_transport_do_iteration (DBusTransport *transport, + _dbus_verbose ("end\n"); + } + ++/** ++ * Allows transports to process incoming messages ++ * ++ * @param transport the transport. ++ * @param message the message to be filtered ++ */ ++void ++_dbus_transport_process_incoming_message (DBusTransport *transport, ++ DBusMessage *message) ++{ ++ _dbus_verbose ("Transport message filtering\n"); ++ ++ if (transport->vtable->process_incoming_message != NULL) ++ { ++ _dbus_transport_ref (transport); ++ (* transport->vtable->process_incoming_message) (transport, message); ++ _dbus_transport_unref (transport); ++ } ++ ++ _dbus_verbose ("end\n"); ++} ++ + static dbus_bool_t + recover_unused_bytes (DBusTransport *transport) + { +@@ -1134,6 +1162,7 @@ _dbus_transport_queue_messages (DBusTransport *transport) + _dbus_assert (link != NULL); + + message = link->data; ++ _dbus_transport_process_incoming_message (transport, message); + + _dbus_verbose ("queueing received message %p\n", message); + +diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h +index 4b82151..194b2c6 100644 +--- a/dbus/dbus-transport.h ++++ b/dbus/dbus-transport.h +@@ -52,6 +52,8 @@ dbus_bool_t _dbus_transport_set_connection (DBusTransport + void _dbus_transport_do_iteration (DBusTransport *transport, + unsigned int flags, + int timeout_milliseconds); ++void _dbus_transport_process_incoming_message (DBusTransport *transport, ++ DBusMessage *message); + DBusDispatchStatus _dbus_transport_get_dispatch_status (DBusTransport *transport); + dbus_bool_t _dbus_transport_queue_messages (DBusTransport *transport); + +diff --git a/test/data/valid-config-files/basic.conf b/test/data/valid-config-files/basic.conf +index 5297097..af46d8b 100644 +--- a/test/data/valid-config-files/basic.conf ++++ b/test/data/valid-config-files/basic.conf +@@ -4,6 +4,8 @@ + <user>mybususer</user> + <listen>unix:path=/foo/bar</listen> + <listen>tcp:port=1234</listen> ++ <listen_if_possible>tcp:port=1235</listen_if_possible> ++ <listen_if_possible>pigeon:port=carrier,speed=110mph</listen_if_possible> + <includedir>basic.d</includedir> + <servicedir>/usr/share/foo</servicedir> + <include ignore_missing="yes">nonexistent.conf</include> diff --git a/recipes-core-ivi/dbus/dbus_1.6.4.bbappend b/recipes-core-ivi/dbus/dbus_1.6.4.bbappend index b4929f3..42bae26 100644 --- a/recipes-core-ivi/dbus/dbus_1.6.4.bbappend +++ b/recipes-core-ivi/dbus/dbus_1.6.4.bbappend @@ -1,5 +1,8 @@ +FILESEXTRAPATHS := "${THISDIR}/${PN}" PRINC = "1" +SRC_URI += "file://dbus_1.6-add-afbus-support.patch" + # Don't register init scripts INITSCRIPT_NAME = "" INITSCRIPT_PARAMS = "" |