static void ide_worker_manager_constructed (GObject *object) { IdeWorkerManager *self = (IdeWorkerManager *)object; g_autofree gchar *guid = NULL; g_autofree gchar *address = NULL; GError *error = NULL; g_assert (IDE_IS_WORKER_MANAGER (self)); G_OBJECT_CLASS (ide_worker_manager_parent_class)->constructed (object); if (g_unix_socket_address_abstract_names_supported ()) { address = g_strdup_printf ("unix:abstract=/tmp/gnome-builder-%u", (int)getpid ()); } else { g_autofree gchar *tmpdir = NULL; tmpdir = g_dir_make_tmp ("gnome-builder-worker-XXXXXX", NULL); if (tmpdir == NULL) { g_error ("Failed to determine temporary directory for DBus."); exit (EXIT_FAILURE); } address = g_strdup_printf ("unix:tmpdir=%s", tmpdir); } guid = g_dbus_generate_guid (); self->dbus_server = g_dbus_server_new_sync (address, G_DBUS_SERVER_FLAGS_NONE, guid, NULL, NULL, &error); if (error != NULL) { g_error ("%s", error->message); exit (EXIT_FAILURE); } g_signal_connect_object (self->dbus_server, "new-connection", G_CALLBACK (ide_worker_manager_new_connection_cb), self, G_CONNECT_SWAPPED); IDE_TRACE_MSG ("GDBusServer listening at %s", address); g_dbus_server_start (self->dbus_server); g_assert (g_dbus_server_is_active (self->dbus_server)); }
/* pass NULL to allow any mechanism */ static GDBusServer * server_new_for_mechanism (const gchar *allowed_mechanism) { gchar *addr; gchar *guid; GDBusServer *server; GDBusAuthObserver *auth_observer; GError *error; GDBusServerFlags flags; guid = g_dbus_generate_guid (); #ifdef G_OS_UNIX if (g_unix_socket_address_abstract_names_supported ()) { addr = g_strdup ("unix:tmpdir=/tmp/gdbus-test-"); } else { gchar *tmpdir; tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL); addr = g_strdup_printf ("unix:tmpdir=%s", tmpdir); g_free (tmpdir); } #else addr = g_strdup ("nonce-tcp:"); #endif auth_observer = g_dbus_auth_observer_new (); flags = G_DBUS_SERVER_FLAGS_NONE; if (g_strcmp0 (allowed_mechanism, "ANONYMOUS") == 0) flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; error = NULL; server = g_dbus_server_new_sync (addr, flags, guid, auth_observer, NULL, /* cancellable */ &error); g_assert_no_error (error); g_assert (server != NULL); g_signal_connect (auth_observer, "allow-mechanism", G_CALLBACK (server_on_allow_mechanism), (gpointer) allowed_mechanism); g_free (addr); g_free (guid); g_object_unref (auth_observer); return server; }
static gboolean initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { g_debug (G_STRLOC ": %s", G_STRFUNC); DasomServer *server = DASOM_SERVER (initable); GSocketAddress *address; GError *local_error = NULL; server->listener = G_SOCKET_LISTENER (g_socket_service_new ()); /* server->listener = G_SOCKET_LISTENER (g_threaded_socket_service_new (-1)); */ if (g_unix_socket_address_abstract_names_supported ()) address = g_unix_socket_address_new_with_type (server->address, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT); else { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Abstract UNIX domain socket names are not supported."); return FALSE; } g_socket_listener_add_address (server->listener, address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL, NULL, &local_error); g_object_unref (address); if (local_error) { g_propagate_error (error, local_error); return FALSE; } server->is_using_listener = TRUE; server->run_signal_handler_id = g_signal_connect (G_SOCKET_SERVICE (server->listener), "incoming", (GCallback) on_new_connection, server); /* server->run_signal_handler_id = g_signal_connect (G_SOCKET_SERVICE (server->listener), "run", G_CALLBACK (on_run), server); */ return TRUE; }
static gboolean g_unix_socket_address_to_native (GSocketAddress *address, gpointer dest, gsize destlen, GError **error) { GUnixSocketAddress *addr = G_UNIX_SOCKET_ADDRESS (address); struct sockaddr_un *sock; if (destlen < sizeof (*sock)) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, _("Not enough space for socket address")); return FALSE; } if (addr->priv->abstract && !g_unix_socket_address_abstract_names_supported ()) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Abstract unix domain socket addresses not supported on this system")); return FALSE; } sock = (struct sockaddr_un *) dest; sock->sun_family = AF_UNIX; memset (sock->sun_path, 0, sizeof (sock->sun_path)); if (addr->priv->abstract) { sock->sun_path[0] = 0; memcpy (sock->sun_path+1, addr->priv->path, addr->priv->path_len); } else strcpy (sock->sun_path, addr->priv->path); return TRUE; }
/* note that address_entry has already been validated => exactly one of path, tmpdir or abstract keys are set */ static gboolean try_unix (GDBusServer *server, const gchar *address_entry, GHashTable *key_value_pairs, GError **error) { gboolean ret; const gchar *path; const gchar *tmpdir; const gchar *abstract; GSocketAddress *address; ret = FALSE; address = NULL; path = g_hash_table_lookup (key_value_pairs, "path"); tmpdir = g_hash_table_lookup (key_value_pairs, "tmpdir"); abstract = g_hash_table_lookup (key_value_pairs, "abstract"); if (path != NULL) { address = g_unix_socket_address_new (path); } else if (tmpdir != NULL) { gint n; GString *s; GError *local_error; retry: s = g_string_new (tmpdir); g_string_append (s, "/dbus-"); for (n = 0; n < 8; n++) g_string_append_c (s, random_ascii ()); /* prefer abstract namespace if available */ if (g_unix_socket_address_abstract_names_supported ()) address = g_unix_socket_address_new_with_type (s->str, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT); else address = g_unix_socket_address_new (s->str); g_string_free (s, TRUE); local_error = NULL; if (!g_socket_listener_add_address (server->listener, address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL, /* source_object */ NULL, /* effective_address */ &local_error)) { if (local_error->domain == G_IO_ERROR && local_error->code == G_IO_ERROR_ADDRESS_IN_USE) { g_error_free (local_error); goto retry; } g_propagate_error (error, local_error); goto out; } ret = TRUE; goto out; } else if (abstract != NULL) { if (!g_unix_socket_address_abstract_names_supported ()) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Abstract name space not supported")); goto out; } address = g_unix_socket_address_new_with_type (abstract, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT); } else { g_assert_not_reached (); } if (!g_socket_listener_add_address (server->listener, address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL, /* source_object */ NULL, /* effective_address */ error)) goto out; ret = TRUE; out: if (address != NULL) { /* Fill out client_address if the connection attempt worked */ if (ret) { server->is_using_listener = TRUE; switch (g_unix_socket_address_get_address_type (G_UNIX_SOCKET_ADDRESS (address))) { case G_UNIX_SOCKET_ADDRESS_ABSTRACT: server->client_address = g_strdup_printf ("unix:abstract=%s", g_unix_socket_address_get_path (G_UNIX_SOCKET_ADDRESS (address))); break; case G_UNIX_SOCKET_ADDRESS_PATH: server->client_address = g_strdup_printf ("unix:path=%s", g_unix_socket_address_get_path (G_UNIX_SOCKET_ADDRESS (address))); break; default: g_assert_not_reached (); break; } } g_object_unref (address); } return ret; }
int main (int argc, char *argv[]) { GError *error = NULL; GOptionContext *context; GMainLoop *loop; GInetAddress *inet; GSocketAddress *address; GSocketService *listener; char *path, *basename; char *http_address = NULL; char *unixsocket_address = NULL; int http_port = 0; char *ssl_cert = NULL; char *ssl_key = NULL; char *display; int port = 0; const GOptionEntry entries[] = { { "port", 'p', 0, G_OPTION_ARG_INT, &http_port, "Httpd port", "PORT" }, { "address", 'a', 0, G_OPTION_ARG_STRING, &http_address, "Ip address to bind to ", "ADDRESS" }, #ifdef G_OS_UNIX { "unixsocket", 'u', 0, G_OPTION_ARG_STRING, &unixsocket_address, "Unix domain socket address", "ADDRESS" }, #endif { "cert", 'c', 0, G_OPTION_ARG_STRING, &ssl_cert, "SSL certificate path", "PATH" }, { "key", 'k', 0, G_OPTION_ARG_STRING, &ssl_key, "SSL key path", "PATH" }, { NULL } }; setlocale (LC_ALL, ""); context = g_option_context_new ("[:DISPLAY] - broadway display daemon"); g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("option parsing failed: %s\n", error->message); exit (1); } display = NULL; if (argc > 1) { if (*argv[1] != ':') { g_printerr ("Usage broadwayd [:DISPLAY]\n"); exit (1); } display = argv[1]; } if (display == NULL) { #ifdef G_OS_UNIX if (g_unix_socket_address_abstract_names_supported ()) display = ":0"; else #endif display = ":tcp"; } if (g_str_has_prefix (display, ":tcp")) { port = strtol (display + strlen (":tcp"), NULL, 10); inet = g_inet_address_new_from_string ("127.0.0.1"); g_print ("Listening on 127.0.0.1:%d\n", port + 9090); address = g_inet_socket_address_new (inet, port + 9090); g_object_unref (inet); } #ifdef G_OS_UNIX else if (display[0] == ':' && g_ascii_isdigit(display[1])) { port = strtol (display + strlen (":"), NULL, 10); basename = g_strdup_printf ("broadway%d.socket", port + 1); path = g_build_filename (g_get_user_runtime_dir (), basename, NULL); g_free (basename); g_print ("Listening on %s\n", path); address = g_unix_socket_address_new_with_type (path, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT); g_free (path); } #endif else { g_printerr ("Failed to parse display %s\n", display); exit (1); } if (http_port == 0) http_port = 8080 + port; if (unixsocket_address != NULL) server = broadway_server_on_unix_socket_new (unixsocket_address, &error); else server = broadway_server_new (http_address, http_port, ssl_cert, ssl_key, &error); if (server == NULL) { g_printerr ("%s\n", error->message); return 1; } listener = g_socket_service_new (); if (!g_socket_listener_add_address (G_SOCKET_LISTENER (listener), address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, G_OBJECT (server), NULL, &error)) { g_printerr ("Can't listen: %s\n", error->message); return 1; } g_object_unref (address); g_signal_connect (listener, "incoming", G_CALLBACK (incoming_client), NULL); g_socket_service_start (G_SOCKET_SERVICE (listener)); loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); return 0; }
static VALUE unixsocketaddress_abstract_names_supported(G_GNUC_UNUSED VALUE self) { return CBOOL2RVAL(g_unix_socket_address_abstract_names_supported()); }