Exemplo n.º 1
0
int
main (int argc, char *argv[])
{
	GDBusConnection *connection;
	GError *error = NULL;

	nm_g_type_init ();

	connection = g_dbus_connection_new_for_address_sync ("unix:path=" NMRUNDIR "/private-dhcp",
	                                                     G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
	                                                     NULL, NULL, &error);
	if (!connection) {
		g_dbus_error_strip_remote_error (error);
		g_printerr ("Error: could not connect to NetworkManager D-Bus socket: %s\n",
		            error->message);
		g_error_free (error);
		fatal_error ();
	}

	if (!g_dbus_connection_emit_signal (connection,
	                                    NULL,
	                                    "/",
	                                    NM_DHCP_CLIENT_DBUS_IFACE,
	                                    "Event",
	                                    build_signal_parameters (),
	                                    &error)) {
		g_dbus_error_strip_remote_error (error);
		g_printerr ("Error: Could not send DHCP Event signal: %s\n", error->message);
		g_error_free (error);
		fatal_error ();
	}

	if (!g_dbus_connection_flush_sync (connection, NULL, &error)) {
		g_dbus_error_strip_remote_error (error);
		g_printerr ("Error: Could not flush D-Bus connection: %s\n", error->message);
		g_error_free (error);
		fatal_error ();
	}

	g_object_unref (connection);
	return 0;
}
int
main (int argc, char *argv[])
{
	gs_unref_object GDBusConnection *connection = NULL;
	gs_free_error GError *error = NULL;
	gs_unref_variant GVariant *parameters = NULL;
	gs_unref_variant GVariant *result = NULL;
	gboolean success = FALSE;
	guint try_count = 0;
	gint64 time_end;

	nm_g_type_init ();

	/* FIXME: g_dbus_connection_new_for_address_sync() tries to connect to the socket in
	 * non-blocking mode, which can easily fail with EAGAIN, causing the creation of the
	 * socket to fail with "Could not connect: Resource temporarily unavailable".
	 *
	 * We should instead create the GIOStream ourself and block on connecting to
	 * the socket. */
	connection = g_dbus_connection_new_for_address_sync ("unix:path=" NMRUNDIR "/private-dhcp",
	                                                     G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
	                                                     NULL, NULL, &error);
	if (!connection) {
		g_dbus_error_strip_remote_error (error);
		_LOGE ("could not connect to NetworkManager D-Bus socket: %s",
		       error->message);
		goto out;
	}

	parameters = build_signal_parameters ();

	time_end = g_get_monotonic_time () + (200 * 1000L); /* retry for at most 200 milliseconds */

do_notify:
	try_count++;
	result = g_dbus_connection_call_sync (connection,
	                                      NULL,
	                                      NM_DHCP_HELPER_SERVER_OBJECT_PATH,
	                                      NM_DHCP_HELPER_SERVER_INTERFACE_NAME,
	                                      NM_DHCP_HELPER_SERVER_METHOD_NOTIFY,
	                                      parameters,
	                                      NULL,
	                                      G_DBUS_CALL_FLAGS_NONE,
	                                      1000,
	                                      NULL,
	                                      &error);

	if (!result) {
		gs_free char *s_err = NULL;

		s_err = g_dbus_error_get_remote_error (error);
		if (NM_IN_STRSET (s_err, "org.freedesktop.DBus.Error.UnknownMethod")) {
			gint64 remaining_time = time_end - g_get_monotonic_time ();

			/* I am not sure that a race can actually happen, as we register the object
			 * on the server side during GDBusServer:new-connection signal.
			 *
			 * However, there was also a race for subscribing to an event, so let's just
			 * do some retry. */
			if (remaining_time > 0) {
				_LOGi ("failure to call notify: %s (retry %u)", error->message, try_count);
				g_usleep (NM_MIN (NM_CLAMP ((gint64) (100L * (1L << try_count)), 5000, 25000), remaining_time));
				g_clear_error (&error);
				goto do_notify;
			}
		}
		_LOGW ("failure to call notify: %s (try signal via Event)", error->message);
		g_clear_error (&error);

		/* for backward compatibilty, try to emit the signal. There is no stable
		 * API between the dhcp-helper and NetworkManager. However, while upgrading
		 * the NetworkManager package, a newer helper might want to notify an
		 * older server, which still uses the "Event". */
		if (!g_dbus_connection_emit_signal (connection,
		                                    NULL,
		                                    "/",
		                                    NM_DHCP_CLIENT_DBUS_IFACE,
		                                    "Event",
		                                    parameters,
		                                    &error)) {
			g_dbus_error_strip_remote_error (error);
			_LOGE ("could not send DHCP Event signal: %s", error->message);
			goto out;
		}
		/* We were able to send the asynchronous Event. Consider that a success. */
		success = TRUE;
	} else
		success = TRUE;

	if (!g_dbus_connection_flush_sync (connection, NULL, &error)) {
		g_dbus_error_strip_remote_error (error);
		_LOGE ("could not flush D-Bus connection: %s", error->message);
		success = FALSE;
		goto out;
	}

out:
	if (!success)
		kill_pid ();
	return success ? EXIT_SUCCESS : EXIT_FAILURE;
}