diff options
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | doc/lightdm-gobject-1-sections.txt | 8 | ||||
-rw-r--r-- | doc/tmpl/greeter.sgml | 66 | ||||
-rw-r--r-- | greeters/gtk/lightdm-gtk-greeter.c | 81 | ||||
-rw-r--r-- | greeters/qt/greeter.cpp | 12 | ||||
-rw-r--r-- | greeters/qt/greeter.h | 2 | ||||
-rw-r--r-- | liblightdm-gobject/greeter.c | 248 | ||||
-rw-r--r-- | liblightdm-gobject/lightdm/greeter.h | 9 | ||||
-rw-r--r-- | liblightdm-qt/QLightDM/Greeter | 11 | ||||
-rw-r--r-- | liblightdm-qt/greeter.cpp | 209 | ||||
-rw-r--r-- | src/greeter.c | 9 | ||||
-rw-r--r-- | tests/src/test-gobject-greeter.c | 156 |
12 files changed, 373 insertions, 445 deletions
@@ -18,11 +18,14 @@ Overview of changes in lightdm 0.9.0 - XDMCP keys now stored in keys.conf * liblightdm API changes: - Both libraries are now version 1 and have API and ABI guarantees. - - Added a session-failed signal to indicate if the session didn't start - and the greeter should try authorizing again. - Face images are now local paths not URIs - liblightdm-gobject now uses lightdm_ prefix instead of ldm_ - Non-greeter functions are now moved out of the Greeter class + - connect_to_server() is now called connect_sync and blocks until + completion. + - start_session() is now called start_session_sync and blocks until + completion. The quit signal is removed, and the greeter should quit if + this method returns TRUE. - login() is now called authenticate() - Greeters now have hints instead of configuration (greeters should load their own configuration from /etc/lightdm if they need it). diff --git a/doc/lightdm-gobject-1-sections.txt b/doc/lightdm-gobject-1-sections.txt index 0e71ca85..e3d1821d 100644 --- a/doc/lightdm-gobject-1-sections.txt +++ b/doc/lightdm-gobject-1-sections.txt @@ -118,17 +118,14 @@ LIGHTDM_USER_LIST_GET_CLASS <SECTION> <FILE>greeter</FILE> <TITLE>Greeter Interface</TITLE> -connected autologin_timer_expired show_message show_prompt authentication_complete -session_failed -quit LightDMMessageType LightDMPromptType lightdm_greeter_new -lightdm_greeter_connect_to_server +lightdm_greeter_connect_sync lightdm_greeter_get_default_session_hint lightdm_greeter_get_hint lightdm_greeter_get_has_guest_account_hint @@ -146,8 +143,7 @@ lightdm_greeter_cancel_authentication lightdm_greeter_get_in_authentication lightdm_greeter_get_is_authenticated lightdm_greeter_get_authentication_user -lightdm_greeter_start_session -lightdm_greeter_start_default_session +lightdm_greeter_start_session_sync <SUBSECTION Standard> LIGHTDM_GREETER LIGHTDM_IS_GREETER diff --git a/doc/tmpl/greeter.sgml b/doc/tmpl/greeter.sgml index c3e2761e..d12b2998 100644 --- a/doc/tmpl/greeter.sgml +++ b/doc/tmpl/greeter.sgml @@ -16,22 +16,25 @@ int main () { LightDMGreeter *greeter = lightdm_greeter_new (); - g_object_connect (greeter, "connected", G_CALLBACK (connected_cb), NULL); g_object_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL); g_object_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL); - g_object_connect (greeter, "session-failed", G_CALLBACK (session_failed_cb), NULL); - g_object_connect (greeter, "quit", G_CALLBACK (quit_cb), NULL); - if (!lightdm_greeter_connect_to_server (LIGHTDM_GREETER (greeter))) { + if (!lightdm_greeter_connect_sync (LIGHTDM_GREETER (greeter))) { // Log an error - return 0; + return EXIT_FAILURE; } -} -static void connected_cb (LightDMGreeter *greeter) -{ - // Start authentication - lightdm_greeter_authenticate (greeter, NULL); + while (TRUE) + { + // Start authentication + while (!lightdm_greeter_get_is_authenticated (greeter)) + lightdm_greeter_authenticate (greeter, NULL); + + if (lightdm_greeter_start_session_sync (greeter, NULL)) + return EXIT_SUCCESS; + } + + return EXIT_SUCCESS; } static void show_prompt_cb (LightDMGreeter *greeter, const char *text, LightDMPromptType type) @@ -55,12 +58,6 @@ static void authentication_complete_cb (LightDMGreeter *greeter) } } -static void session_failed_cb (LightDMGreeter *greeter) -{ - // Display a warning and reset the greeter - reset_login_screen (``Failed to login''); -} - static void quit_cb (LightDMGreeter *greeter) { // Clean up @@ -83,14 +80,6 @@ static void quit_cb (LightDMGreeter *greeter) <!-- ##### SECTION Image ##### --> -<!-- ##### USER_FUNCTION connected ##### --> -<para> - -</para> - -@greeter: - - <!-- ##### USER_FUNCTION autologin_timer_expired ##### --> <para> @@ -127,22 +116,6 @@ static void quit_cb (LightDMGreeter *greeter) @greeter: -<!-- ##### USER_FUNCTION session_failed ##### --> -<para> - -</para> - -@greeter: - - -<!-- ##### USER_FUNCTION quit ##### --> -<para> - -</para> - -@greeter: - - <!-- ##### ENUM LightDMMessageType ##### --> <para> @@ -168,7 +141,7 @@ static void quit_cb (LightDMGreeter *greeter) @Returns: -<!-- ##### FUNCTION lightdm_greeter_connect_to_server ##### --> +<!-- ##### FUNCTION lightdm_greeter_connect_sync ##### --> <para> </para> @@ -328,20 +301,13 @@ static void quit_cb (LightDMGreeter *greeter) @Returns: -<!-- ##### FUNCTION lightdm_greeter_start_session ##### --> +<!-- ##### FUNCTION lightdm_greeter_start_session_sync ##### --> <para> </para> @greeter: @session: - - -<!-- ##### FUNCTION lightdm_greeter_start_default_session ##### --> -<para> - -</para> - -@greeter: +@Returns: diff --git a/greeters/gtk/lightdm-gtk-greeter.c b/greeters/gtk/lightdm-gtk-greeter.c index 02fdbb16..8bf6543b 100644 --- a/greeters/gtk/lightdm-gtk-greeter.c +++ b/greeters/gtk/lightdm-gtk-greeter.c @@ -183,16 +183,18 @@ authentication_complete_cb (LightDMGreeter *greeter) if (lightdm_greeter_get_is_authenticated (greeter)) { gchar *session = get_session (); - lightdm_greeter_start_session (greeter, session); + if (lightdm_greeter_start_session_sync (greeter, session)) + exit (EXIT_SUCCESS); + else + gtk_label_set_text (GTK_LABEL (message_label), "Failed to authenticate"); g_free (session); } else - { gtk_label_set_text (GTK_LABEL (message_label), "Failed to authenticate"); - gtk_widget_show (message_label); - if (lightdm_greeter_get_hide_users_hint (greeter)) - lightdm_greeter_authenticate (greeter, NULL); - } + + gtk_widget_show (message_label); + if (lightdm_greeter_get_hide_users_hint (greeter)) + lightdm_greeter_authenticate (greeter, NULL); } static void @@ -283,23 +285,6 @@ shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter) gtk_widget_destroy (dialog); } -static gboolean -fade_timer_cb (gpointer data) -{ - gdouble opacity; - - opacity = gtk_window_get_opacity (GTK_WINDOW (window)); - opacity -= 0.1; - if (opacity <= 0) - { - gtk_main_quit (); - return FALSE; - } - gtk_window_set_opacity (GTK_WINDOW (window), opacity); - - return TRUE; -} - static void user_added_cb (LightDMUserList *user_list, LightDMUser *user) { @@ -370,13 +355,6 @@ user_removed_cb (LightDMUserList *user_list, LightDMUser *user) gtk_list_store_remove (GTK_LIST_STORE (model), &iter); } -static void -quit_cb (LightDMGreeter *greeter, const gchar *username) -{ - /* Fade out the greeter */ - g_timeout_add (40, (GSourceFunc) fade_timer_cb, NULL); -} - void a11y_font_cb (GtkWidget *widget); G_MODULE_EXPORT void @@ -479,8 +457,8 @@ load_user_list () -1); } -static void -connected_cb (LightDMGreeter *greeter) +int +main(int argc, char **argv) { GdkWindow *root; GdkDisplay *display; @@ -494,6 +472,21 @@ connected_cb (LightDMGreeter *greeter) gchar *rc_file, *background_image; GError *error = NULL; + /* Disable global menus */ + unsetenv ("UBUNTU_MENUPROXY"); + + signal (SIGTERM, sigterm_cb); + + gtk_init (&argc, &argv); + + greeter = lightdm_greeter_new (); + g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL); + g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL); + g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL); + g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (autologin_timer_expired_cb), NULL); + if (!lightdm_greeter_connect_sync (greeter)) + return EXIT_FAILURE; + display = gdk_display_get_default (); screen = gdk_display_get_default_screen (display); screen_width = gdk_screen_get_width (screen); @@ -513,7 +506,7 @@ connected_cb (LightDMGreeter *greeter) if (!gtk_builder_add_from_file (builder, GREETER_DATA_DIR "/greeter.ui", &error)) { g_warning ("Error loading UI: %s", error->message); - return; + return EXIT_FAILURE; } g_clear_error (&error); window = GTK_WIDGET (gtk_builder_get_object (builder, "greeter_window")); @@ -604,28 +597,8 @@ connected_cb (LightDMGreeter *greeter) gtk_widget_show (window); gtk_widget_grab_focus (user_view); -} - -int -main(int argc, char **argv) -{ - /* Disable global menus */ - unsetenv ("UBUNTU_MENUPROXY"); - - signal (SIGTERM, sigterm_cb); - - gtk_init (&argc, &argv); - - greeter = lightdm_greeter_new (); - g_signal_connect (greeter, "connected", G_CALLBACK (connected_cb), NULL); - g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL); - g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL); - g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL); - g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (autologin_timer_expired_cb), NULL); - g_signal_connect (greeter, "quit", G_CALLBACK (quit_cb), NULL); - lightdm_greeter_connect_to_server (greeter); gtk_main (); - return 0; + return EXIT_SUCCESS; } diff --git a/greeters/qt/greeter.cpp b/greeters/qt/greeter.cpp index ee51fd34..ce280217 100644 --- a/greeters/qt/greeter.cpp +++ b/greeters/qt/greeter.cpp @@ -34,13 +34,13 @@ Greeter::Greeter() : background->setPixmap(QPixmap("/usr/share/wallpapers/Horos/contents/images/1920x1200.png")); m_greeter = new QLightDM::Greeter(this); - m_greeter->connectToServer(); - connect(m_greeter, SIGNAL(quit()), this, SLOT(close())); + if (!m_greeter->connectSync()) + close(); m_prompt = new LoginPrompt(m_greeter, this); m_prompt->move(this->width()/2 - m_prompt->width()/2, this->height()/2 - m_prompt->height()/2); m_prompt->setAutoFillBackground(true); - connect(m_prompt, SIGNAL(startSession()), SLOT(onStartSession())); + connect(m_prompt, SIGNAL(startSessionSync()), SLOT(onStartSession())); m_panel = new Panel(m_greeter, this); m_panel->setGeometry(QRect(QPoint(0, screen.height() - m_panel->height()), screen.bottomRight())); @@ -52,6 +52,6 @@ Greeter::~Greeter() { } -void Greeter::onStartSession() { - m_greeter->startSession(m_panel->session()); -}
\ No newline at end of file +bool Greeter::onStartSession() { + return m_greeter->startSessionSync(m_panel->session()); +} diff --git a/greeters/qt/greeter.h b/greeters/qt/greeter.h index 0ec20aa7..c0f32243 100644 --- a/greeters/qt/greeter.h +++ b/greeters/qt/greeter.h @@ -30,7 +30,7 @@ public: ~Greeter(); private slots: - void onStartSession(); + bool onStartSession(); private: QLightDM::Greeter *m_greeter; diff --git a/liblightdm-gobject/greeter.c b/liblightdm-gobject/greeter.c index fe821030..053972d6 100644 --- a/liblightdm-gobject/greeter.c +++ b/liblightdm-gobject/greeter.c @@ -33,13 +33,10 @@ enum { }; enum { - CONNECTED, SHOW_PROMPT, SHOW_MESSAGE, AUTHENTICATION_COMPLETE, - SESSION_FAILED, AUTOLOGIN_TIMER_EXPIRED, - QUIT, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -82,10 +79,9 @@ typedef enum typedef enum { SERVER_MESSAGE_CONNECTED = 0, - SERVER_MESSAGE_QUIT, SERVER_MESSAGE_PROMPT_AUTHENTICATION, SERVER_MESSAGE_END_AUTHENTICATION, - SERVER_MESSAGE_SESSION_FAILED, + SERVER_MESSAGE_SESSION_RESULT } ServerMessage; /** @@ -157,19 +153,18 @@ write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *off } static guint32 -read_int (LightDMGreeter *greeter, gsize *offset) +read_int (guint8 *message, gsize message_length, gsize *offset) { - LightDMGreeterPrivate *priv = GET_PRIVATE (greeter); guint32 value; guint8 *buffer; - if (priv->n_read - *offset < int_length ()) + if (message_length - *offset < int_length ()) { - g_warning ("Not enough space for int, need %i, got %zi", int_length (), priv->n_read - *offset); + g_warning ("Not enough space for int, need %i, got %zi", int_length (), message_length - *offset); return 0; } - buffer = priv->read_buffer + *offset; + buffer = message + *offset; value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; *offset += int_length (); @@ -177,21 +172,20 @@ read_int (LightDMGreeter *greeter, gsize *offset) } static gchar * -read_string (LightDMGreeter *greeter, gsize *offset) +read_string (guint8 *message, gsize message_length, gsize *offset) { - LightDMGreeterPrivate *priv = GET_PRIVATE (greeter); guint32 length; gchar *value; - length = read_int (greeter, offset); - if (priv->n_read - *offset < length) + length = read_int (message, message_length, offset); + if (message_length - *offset < length) { - g_warning ("Not enough space for string, need %u, got %zu", length, priv->n_read - *offset); + g_warning ("Not enough space for string, need %u, got %zu", length, message_length - *offset); return g_strdup (""); } value = g_malloc (sizeof (gchar) * (length + 1)); - memcpy (value, priv->read_buffer + *offset, length); + memcpy (value, message + *offset, length); value[length] = '\0'; *offset += length; @@ -211,28 +205,29 @@ write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gs write_int (buffer, buffer_length, length, offset); } -static guint32 get_packet_length (LightDMGreeter *greeter) +static guint32 +get_message_length (guint8 *message, gsize message_length) { gsize offset = 4; - return read_int (greeter, &offset); + return read_int (message, message_length, &offset); } static void -handle_connected (LightDMGreeter *greeter, guint32 length, gsize *offset) +handle_connected (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset) { LightDMGreeterPrivate *priv = GET_PRIVATE (greeter); gchar *version; GString *hint_string; int timeout; - version = read_string (greeter, offset); + version = read_string (message, message_length, offset); hint_string = g_string_new (""); - while (*offset < length) + while (*offset < message_length) { gchar *name, *value; - name = read_string (greeter, offset); - value = read_string (greeter, offset); + name = read_string (message, message_length, offset); + value = read_string (message, message_length, offset); g_hash_table_insert (priv->hints, name, value); g_string_append_printf (hint_string, " %s=%s", name, value); } @@ -248,16 +243,15 @@ handle_connected (LightDMGreeter *greeter, guint32 length, gsize *offset) g_debug ("Setting autologin timer for %d seconds", timeout); priv->autologin_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter); } - g_signal_emit (G_OBJECT (greeter), signals[CONNECTED], 0); } static void -handle_prompt_authentication (LightDMGreeter *greeter, gsize *offset) +handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset) { LightDMGreeterPrivate *priv = GET_PRIVATE (greeter); guint32 sequence_number, n_messages, i; - sequence_number = read_int (greeter, offset); + sequence_number = read_int (message, message_length, offset); if (sequence_number != priv->authenticate_sequence_number) { g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number); @@ -270,7 +264,7 @@ handle_prompt_authentication (LightDMGreeter *greeter, gsize *offset) return; } - n_messages = read_int (greeter, offset); + n_messages = read_int (message, message_length, offset); g_debug ("Prompt user with %d message(s)", n_messages); for (i = 0; i < n_messages; i++) @@ -278,8 +272,8 @@ handle_prompt_authentication (LightDMGreeter *greeter, gsize *offset) int msg_style; gchar *msg; - msg_style = read_int (greeter, offset); - msg = read_string (greeter, offset); + msg_style = read_int (message, message_length, offset); + msg = read_string (message, message_length, offset); // FIXME: Should stop on prompts? switch (msg_style) @@ -303,13 +297,13 @@ handle_prompt_authentication (LightDMGreeter *greeter, gsize *offset) } static void -handle_end_authentication (LightDMGreeter *greeter, gsize *offset) +handle_end_authentication (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset) { LightDMGreeterPrivate *priv = GET_PRIVATE (greeter); guint32 sequence_number, return_code; - sequence_number = read_int (greeter, offset); - return_code = read_int (greeter, offset); + sequence_number = read_int (message, message_length, offset); + return_code = read_int (message, message_length, offset); if (sequence_number != priv->authenticate_sequence_number) { @@ -325,35 +319,23 @@ handle_end_authentication (LightDMGreeter *greeter, gsize *offset) g_free (priv->authentication_user); priv->authentication_user = NULL; } + g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0); priv->in_authentication = FALSE; } -static void -handle_session_failed (LightDMGreeter *greeter, gsize *offset) -{ - g_debug ("Session failed to start"); - g_signal_emit (G_OBJECT (greeter), signals[SESSION_FAILED], 0); -} - -static void -handle_quit (LightDMGreeter *greeter, gsize *offset) -{ - g_debug ("Got quit request from server"); - g_signal_emit (G_OBJECT (greeter), signals[QUIT], 0); -} - -static gboolean -read_packet (LightDMGreeter *greeter, gboolean block) +static guint8 * +read_message (LightDMGreeter *greeter, gsize *length, gboolean block) { LightDMGreeterPrivate *priv = GET_PRIVATE (greeter); gsize n_to_read, n_read; + guint8 *buffer; GError *error = NULL; - /* Read the header, or the whole packet if we already have that */ + /* Read the header, or the whole message if we already have that */ n_to_read = HEADER_SIZE; if (priv->n_read >= HEADER_SIZE) - n_to_read += get_packet_length (greeter); + n_to_read += get_message_length (priv->read_buffer, priv->n_read); do { @@ -381,73 +363,72 @@ read_packet (LightDMGreeter *greeter, gboolean block) /* If have header, rerun for content */ if (priv->n_read == HEADER_SIZE) { - n_to_read = get_packet_length (greeter); + n_to_read = get_message_length (priv->read_buffer, priv->n_read); if (n_to_read > 0) { priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read); - return read_packet (greeter, block); + return read_message (greeter, length, block); } } - return TRUE; + buffer = priv->read_buffer; + *length = priv->n_read; + + priv->read_buffer = g_malloc (priv->n_read); + priv->n_read = 0; + + return buffer; } static gboolean from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data) { LightDMGreeter *greeter = data; - LightDMGreeterPrivate *priv = GET_PRIVATE (greeter); - gsize offset; - guint32 id, length; + guint8 *message; + gsize message_length, offset; + guint32 id; - if (!read_packet (greeter, FALSE)) + message = read_message (greeter, &message_length, FALSE); + if (!message) return TRUE; offset = 0; - id = read_int (greeter, &offset); - length = read_int (greeter, &offset); + id = read_int (message, message_length, &offset); + read_int (message, message_length, &offset); switch (id) { - case SERVER_MESSAGE_CONNECTED: - handle_connected (greeter, length, &offset); - break; case SERVER_MESSAGE_PROMPT_AUTHENTICATION: - handle_prompt_authentication (greeter, &offset); + handle_prompt_authentication (greeter, message, message_length, &offset); break; case SERVER_MESSAGE_END_AUTHENTICATION: - handle_end_authentication (greeter, &offset); - break; - case SERVER_MESSAGE_SESSION_FAILED: - handle_session_failed (greeter, &offset); - break; - case SERVER_MESSAGE_QUIT: - handle_quit (greeter, &offset); + handle_end_authentication (greeter, message, message_length, &offset); break; default: g_warning ("Unknown message from server: %d", id); break; } - - priv->n_read = 0; + g_free (message); return TRUE; } /** - * lightdm_greeter_connect_to_server: + * lightdm_greeter_connect_sync: * @greeter: The greeter to connect * - * Connects the greeter to the display manager. + * Connects the greeter to the display manager. Will block until connected. * * Return value: #TRUE if successfully connected **/ gboolean -lightdm_greeter_connect_to_server (LightDMGreeter *greeter) +lightdm_greeter_connect_sync (LightDMGreeter *greeter) { LightDMGreeterPrivate *priv; const gchar *fd; guint8 message[MAX_MESSAGE_LENGTH]; - gsize offset = 0; + guint8 *response; + gsize response_length, offset = 0; + guint32 id; g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE); @@ -477,6 +458,20 @@ lightdm_greeter_connect_to_server (LightDMGreeter *greeter) write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset); write_message (greeter, message, offset); + response = read_message (greeter, &response_length, TRUE); + if (!response) + return FALSE; + + offset = 0; + id = read_int (response, response_length, &offset); + read_int (response, response_length, &offset); + if (id == SERVER_MESSAGE_CONNECTED) + handle_connected (greeter, response, response_length, &offset); + else + g_warning ("Expected CONNECTED message, got %d", id); + + g_free (response); + return TRUE; } @@ -816,39 +811,53 @@ lightdm_greeter_get_authentication_user (LightDMGreeter *greeter) } /** - * lightdm_greeter_start_session: + * lightdm_greeter_start_session_sync: * @greeter: A #LightDMGreeter - * @session: (allow-none): The session to log into or #NULL to use the default + * @session: (allow-none): The session to log into or #NULL to use the default. + * + * Start a session for the authenticated user. * - * Start a session for the logged in user. + * Return value: TRUE if the session was started. **/ -void -lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session) +gboolean +lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session) { + LightDMGreeterPrivate *priv = GET_PRIVATE (greeter); guint8 message[MAX_MESSAGE_LENGTH]; - gsize offset = 0; + guint8 *response; + gsize response_length, offset = 0; + guint32 id, return_code = 1; + + g_return_val_if_fail (LIGHTDM_IS_GREETER (greeter), FALSE); + g_return_val_if_fail (priv->is_authenticated, FALSE); - g_return_if_fail (LIGHTDM_IS_GREETER (greeter)); - if (!session) + { session = ""; + g_debug ("Starting default session"); + } + else + g_debug ("Starting session %s", session); - g_debug ("Starting session %s", session); write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset); write_string (message, MAX_MESSAGE_LENGTH, session, &offset); write_message (greeter, message, offset); -} -/** - * lightdm_greeter_start_default_session: - * @greeter: A #LightDMGreeter - * - * Start the default session for the authenticated user. - **/ -void -lightdm_greeter_start_default_session (LightDMGreeter *greeter) -{ - lightdm_greeter_start_session (greeter, NULL); + response = read_message (greeter, &response_length, TRUE); + if (!response) + return FALSE; + + offset = 0; + id = read_int (response, response_length, &offset); + read_int (response, response_length, &offset); + if (id == SERVER_MESSAGE_SESSION_RESULT) + return_code = read_int (response, response_length, &offset); + else + g_warning ("Expected SESSION_RESULT message, got %d", id); + + g_free (response); + + return return_code == 0; } static void @@ -1069,22 +1078,6 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass) G_PARAM_READABLE)); /** - * LightDMGreeter::connected: - * @greeter: A #LightDMGreeter - * - * The ::connected signal gets emitted when the greeter connects to the - * LightDM server. - **/ - signals[CONNECTED] = - g_signal_new ("connected", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (LightDMGreeterClass, connected), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** * LightDMGreeter::show-prompt: * @greeter: A #LightDMGreeter * @text: Prompt text @@ -1144,22 +1137,6 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass) G_TYPE_NONE, 0); /** - * LightDMGreeter::session-failed: - * @greeter: A #LightDMGreeter - * - * The ::session-failed signal gets emitted when the deamon has failed - * to start the requested session. - **/ - signals[SESSION_FAILED] = - g_signal_new ("session-failed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (LightDMGreeterClass, session_failed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** * LightDMGreeter::autologin-timer-expired: * @greeter: A #LightDMGreeter * @@ -1174,19 +1151,4 @@ lightdm_greeter_class_init (LightDMGreeterClass *klass) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - /** - * LightDMGreeter::quit: - * @greeter: A #LightDMGreeter - * - * The ::quit signal gets emitted when the greeter should exit. - **/ - signals[QUIT] = - g_signal_new ("quit", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (LightDMGreeterClass, quit), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); } diff --git a/liblightdm-gobject/lightdm/greeter.h b/liblightdm-gobject/lightdm/greeter.h index f8b98276..b0786ef7 100644 --- a/liblightdm-gobject/lightdm/greeter.h +++ b/liblightdm-gobject/lightdm/greeter.h @@ -54,20 +54,17 @@ typedef struct { GObjectClass parent_class; - void (*connected)(LightDMGreeter *greeter); void (*show_prompt)(LightDMGreeter *greeter, const gchar *text, LightDMPromptType type); void (*show_message)(LightDMGreeter *greeter, const gchar *text, LightDMMessageType type); void (*authentication_complete)(LightDMGreeter *greeter); - void (*session_failed)(LightDMGreeter *greeter); void (*autologin_timer_expired)(LightDMGreeter *greeter); - void (*quit)(LightDMGreeter *greeter); } LightDMGreeterClass; GType lightdm_greeter_get_type (void); LightDMGreeter *lightdm_greeter_new (void); -gboolean lightdm_greeter_connect_to_server (LightDMGreeter *greeter); +gboolean lightdm_greeter_connect_sync (LightDMGreeter *greeter); const gchar *lightdm_greeter_get_hint (LightDMGreeter *greeter, const gchar *name); @@ -103,9 +100,7 @@ gboolean lightdm_greeter_get_is_authenticated (LightDMGreeter *greeter); const gchar *lightdm_greeter_get_authentication_user (LightDMGreeter *greeter); -void lightdm_greeter_start_session (LightDMGreeter *greeter, const gchar *session); - -void lightdm_greeter_start_default_session (LightDMGreeter *greeter); +gboolean lightdm_greeter_start_session_sync (LightDMGreeter *greeter, const gchar *session); G_END_DECLS diff --git a/liblightdm-qt/QLightDM/Greeter b/liblightdm-qt/QLightDM/Greeter index 83d7d75b..f6170e31 100644 --- a/liblightdm-qt/QLightDM/Greeter +++ b/liblightdm-qt/QLightDM/Greeter @@ -59,21 +59,18 @@ namespace QLightDM QString authenticationUser() const; public slots: - void connectToServer(); + bool connectSync(); void authenticate(const QString &username=QString()); void authenticateAsGuest(); void respond(const QString &response); void cancelAuthentication(); - void startSession(const QString &session=QString()); + bool startSessionSync(const QString &session=QString()); signals: - void connected(); void showPrompt(QString prompt, PromptType type); void showMessage(QString message, MessageType type); void authenticationComplete(); - void sessionFailed(); void autologinTimerExpired(); - void quit(); private slots: void onRead(int fd); @@ -84,9 +81,7 @@ namespace QLightDM void writeString(QString value); void writeHeader(int id, int length); void flush(); - int getPacketLength(); - int readInt(int *offset); - QString readString(int *offset); + char *readMessage(int *length, bool block); }; }; diff --git a/liblightdm-qt/greeter.cpp b/liblightdm-qt/greeter.cpp index 950af627..69aee65f 100644 --- a/liblightdm-qt/greeter.cpp +++ b/liblightdm-qt/greeter.cpp @@ -42,10 +42,9 @@ typedef enum typedef enum { SERVER_MESSAGE_CONNECTED = 0, - SERVER_MESSAGE_QUIT, SERVER_MESSAGE_PROMPT_AUTHENTICATION, SERVER_MESSAGE_END_AUTHENTICATION, - SERVER_MESSAGE_SESSION_FAILED, + SERVER_MESSAGE_SESSION_RESULT } ServerMessage; #define HEADER_SIZE 8 @@ -69,12 +68,11 @@ public: bool cancellingAuthentication; }; - Greeter::Greeter(QObject *parent) : QObject(parent), d(new GreeterPrivate) { - d->readBuffer = (char *)malloc (HEADER_SIZE); + d->readBuffer = (char *)malloc(HEADER_SIZE); d->nRead = 0; d->authenticateSequenceNumber = 0; } @@ -128,38 +126,38 @@ void Greeter::flush() fsync(d->toServerFd); } -int Greeter::getPacketLength() -{ - int offset = intLength(); - return readInt(&offset); -} - -int Greeter::readInt(int *offset) +static int readInt(char *message, int messageLength, int *offset) { - if(d->nRead - *offset < intLength()) { - qDebug() << "Not enough space for int, need " << intLength() << ", got " << (d->nRead - *offset); + if(messageLength - *offset < intLength()) { + qDebug() << "Not enough space for int, need " << intLength() << ", got " << (messageLength - *offset); return 0; } - char *buffer = d->readBuffer + *offset; + char *buffer = message + *offset; int value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; *offset += intLength(); return value; } -QString Greeter::readString(int *offset) +static int getMessageLength(char *message, int messageLength) +{ + int offset = intLength(); + return readInt(message, messageLength, &offset); +} + +static QString readString(char *message, int messageLength, int *offset) { - int length = readInt(offset); - if(d->nRead - *offset < length) { - qDebug() << "Not enough space for string, need " << length << ", got " << (d->nRead - *offset); + int length = readInt(message, messageLength, offset); + if(messageLength - *offset < length) { + qDebug() << "Not enough space for string, need " << length << ", got " << (messageLength - *offset); return ""; } - char *start = d->readBuffer + *offset; + char *start = message + *offset; *offset += length; return QString::fromUtf8(start, length); } -void Greeter::connectToServer() +bool Greeter::connectSync() { QDBusConnection busType = QDBusConnection::systemBus(); QString ldmBus(qgetenv("LIGHTDM_BUS")); @@ -170,7 +168,7 @@ void Greeter::connectToServer() char* fd = getenv("LIGHTDM_TO_SERVER_FD"); if(!fd) { qDebug() << "No LIGHTDM_TO_SERVER_FD environment variable"; - return; + return false; } d->toServerFd = atoi(fd); @@ -181,7 +179,7 @@ void Greeter::connectToServer() fd = getenv("LIGHTDM_FROM_SERVER_FD"); if(!fd) { qDebug() << "No LIGHTDM_FROM_SERVER_FD environment variable"; - return; + return false; } d->fromServerFd = atoi(fd); @@ -192,6 +190,38 @@ void Greeter::connectToServer() writeHeader(GREETER_MESSAGE_CONNECT, stringLength(VERSION)); writeString(VERSION); flush(); + + int responseLength; + char *response = readMessage(&responseLength, false); + if (!response) + return false; + + int offset = 0; + int id = readInt(response, responseLength, &offset); + int length = readInt(response, responseLength, &offset); + bool connected = false; + if (id == SERVER_MESSAGE_CONNECTED) + { + QString version = readString(response, responseLength, &offset); + QString hintString = ""; + while (offset < length) + { + QString name = readString(response, responseLength, &offset); + QString value = readString(response, responseLength, &offset); + hintString.append (" "); + hintString.append (name); + hintString.append ("="); + hintString.append (value); + } + + qDebug() << "Connected version=" << version << hintString; + connected = true; + } + else + qDebug() << "Expected CONNECTED message, got " << id; + free(response); + + return connected; } void Greeter::authenticate(const QString &username) @@ -254,95 +284,115 @@ QString Greeter::authenticationUser() const return d->authenticationUser; } -void Greeter::startSession(const QString &session) +bool Greeter::startSessionSync(const QString &session) { - qDebug() << "Starting session " << session; + if (session == "") + qDebug() << "Starting default session"; + else + qDebug() << "Starting session " << session; + writeHeader(GREETER_MESSAGE_START_SESSION, stringLength(session)); writeString(session); flush(); + + int responseLength; + char *response = readMessage(&responseLength, false); + if (!response) + return false; + + int offset = 0; + int id = readInt(response, responseLength, &offset); + readInt(response, responseLength, &offset); + int returnCode = -1; + if (id == SERVER_MESSAGE_SESSION_RESULT) + returnCode = readInt(response, responseLength, &offset); + else + qDebug() << "Expected SESSION_RESULT message, got " << id; + free(response); + + return returnCode == 0; } -void Greeter::onRead(int fd) +char *Greeter::readMessage(int *length, bool block) { - //qDebug() << "Reading from server"; - + /* Read the header, or the whole message if we already have that */ int nToRead = HEADER_SIZE; if(d->nRead >= HEADER_SIZE) - nToRead += getPacketLength(); + nToRead += getMessageLength(d->readBuffer, d->nRead); - ssize_t nRead; - nRead = read(fd, d->readBuffer + d->nRead, nToRead - d->nRead); - if(nRead < 0) - { - qDebug() << "Error reading from server"; - return; - } - if (nRead == 0) - { - qDebug() << "EOF reading from server"; - return; - } + do + { + ssize_t nRead = read(d->fromServerFd, d->readBuffer + d->nRead, nToRead - d->nRead); + if(nRead < 0) + { + qDebug() << "Error reading from server"; + return NULL; + } + if (nRead == 0) + { + qDebug() << "EOF reading from server"; + return NULL; + } + + qDebug() << "Read " << nRead << " octets from daemon"; + d->nRead += nRead; + } while(d->nRead < nToRead && block); - //qDebug() << "Read " << nRead << "octets"; - d->nRead += nRead; + /* Stop if haven't got all the data we want */ if(d->nRead != nToRead) - return; + return NULL; /* If have header, rerun for content */ if(d->nRead == HEADER_SIZE) { - nToRead = getPacketLength(); + nToRead = getMessageLength(d->readBuffer, d->nRead); if(nToRead > 0) { d->readBuffer = (char *)realloc(d->readBuffer, HEADER_SIZE + nToRead); - onRead(fd); - return; + return readMessage(length, block); } } + char *buffer = d->readBuffer; + *length = d->nRead; + + d->readBuffer = (char *)malloc(d->nRead); + d->nRead = 0; + + return buffer; +} + +void Greeter::onRead(int fd) +{ + qDebug() << "Reading from server"; + + int messageLength; + char *message = readMessage(&messageLength, false); + if (!message) + return; + int offset = 0; - int id = readInt(&offset); - int length = readInt(&offset); + int id = readInt(message, messageLength, &offset); + int length = readInt(message, messageLength, &offset); int nMessages, sequenceNumber, returnCode; QString version, username; - QString hintString = ""; switch(id) { - case SERVER_MESSAGE_CONNECTED: - version = readString(&offset); - while (offset < length) - { - QString name = readString(&offset); - QString value = readString(&offset); - hintString.append (" "); - hintString.append (name); - hintString.append ("="); - hintString.append (value); - } - - qDebug() << "Connected version=" << version << hintString; - - emit connected(); - break; - case SERVER_MESSAGE_QUIT: - qDebug() << "Got quit request from server"; - emit quit(); - break; case SERVER_MESSAGE_PROMPT_AUTHENTICATION: - sequenceNumber = readInt(&offset); + sequenceNumber = readInt(message, messageLength, &offset); if (sequenceNumber == d->authenticateSequenceNumber && !d->cancellingAuthentication) { - nMessages = readInt(&offset); + nMessages = readInt(message, messageLength, &offset); qDebug() << "Prompt user with " << nMessages << " message(s)"; for(int i = 0; i < nMessages; i++) { - int msg_style = readInt (&offset); - QString msg = readString (&offset); + int msgStyle = readInt(message, messageLength, &offset); + QString msg = readString(message, messageLength, &offset); // FIXME: Should stop on prompts? - switch (msg_style) + switch (msgStyle) { case PAM_PROMPT_ECHO_OFF: emit showPrompt(msg, PROMPT_TYPE_SECRET); @@ -361,8 +411,8 @@ void Greeter::onRead(int fd) } break; case SERVER_MESSAGE_END_AUTHENTICATION: - sequenceNumber = readInt(&offset); - returnCode = readInt(&offset); + sequenceNumber = readInt(message, messageLength, &offset); + returnCode = readInt(message, messageLength, &offset); if (sequenceNumber == d->authenticateSequenceNumber) { @@ -378,15 +428,10 @@ void Greeter::onRead(int fd) else qDebug () << "Ignoring end authentication with invalid sequence number " << sequenceNumber; break; - case SERVER_MESSAGE_SESSION_FAILED: - qDebug() << "Session failed to start"; - emit sessionFailed(); - break; default: qDebug() << "Unknown message from server: " << id; } - - d->nRead = 0; + free(message); } QString Greeter::getHint(QString name) const diff --git a/src/greeter.c b/src/greeter.c index 55157dd2..12d068b9 100644 --- a/src/greeter.c +++ b/src/greeter.c @@ -71,10 +71,9 @@ typedef enum typedef enum { SERVER_MESSAGE_CONNECTED = 0, - SERVER_MESSAGE_QUIT, SERVER_MESSAGE_PROMPT_AUTHENTICATION, SERVER_MESSAGE_END_AUTHENTICATION, - SERVER_MESSAGE_SESSION_FAILED, + SERVER_MESSAGE_SESSION_RESULT } ServerMessage; Greeter * @@ -376,7 +375,8 @@ handle_start_session (Greeter *greeter, gchar *session) guint8 message[MAX_MESSAGE_LENGTH]; gsize offset = 0; - write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_SESSION_FAILED, 0, &offset); + write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_SESSION_RESULT, int_length (), &offset); + write_int (message, MAX_MESSAGE_LENGTH, 1, &offset); write_message (greeter, message, offset); } } @@ -571,7 +571,8 @@ greeter_quit (Greeter *greeter) g_return_if_fail (greeter != NULL); - write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_QUIT, 0, &offset); + write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_SESSION_RESULT, int_length (), &offset); + write_int (message, MAX_MESSAGE_LENGTH, 0, &offset); write_message (greeter, message, offset); } diff --git a/tests/src/test-gobject-greeter.c b/tests/src/test-gobject-greeter.c index 27ddb2f2..41aad994 100644 --- a/tests/src/test-gobject-greeter.c +++ b/tests/src/test-gobject-greeter.c @@ -10,68 +10,6 @@ static xcb_connection_t *connection = NULL; static GKeyFile *config; static void -connected_cb (LightDMGreeter *greeter) -{ - gchar *login_lock; - FILE *f; - - notify_status ("GREETER CONNECTED-TO-DAEMON"); - - if (g_key_file_get_boolean (config, "test-greeter-config", "crash-xserver", NULL)) - { - const gchar *name = "SIGSEGV"; - notify_status ("GREETER CRASH-XSERVER"); - xcb_intern_atom (connection, FALSE, strlen (name), name); - xcb_flush (connection); - } - - /* Automatically log in as requested user */ - if (lightdm_greeter_get_select_user_hint (greeter)) - { - notify_status ("GREETER AUTHENTICATE-SELECTED USERNAME=%s", lightdm_greeter_get_select_user_hint (greeter)); - lightdm_greeter_authenticate (greeter, lightdm_greeter_get_select_user_hint (greeter)); - return; - } - - login_lock = g_build_filename (g_getenv ("LIGHTDM_TEST_HOME_DIR"), ".greeter-logged-in", NULL); - f = fopen (login_lock, "r"); - if (f == NULL) - { - if (g_key_file_get_boolean (config, "test-greeter-config", "login-guest", NULL)) - { - notify_status ("GREETER AUTHENTICATE-GUEST"); - lightdm_greeter_authenticate_as_guest (greeter); - } - else if (g_key_file_get_boolean (config, "test-greeter-config", "prompt-username", NULL)) - { - notify_status ("GREETER AUTHENTICATE"); - lightdm_greeter_authenticate (greeter, NULL); - } - else - { - gchar *username; - - username = g_key_file_get_string (config, "test-greeter-config", "username", NULL); - if (!username) - return; - - notify_status ("GREETER AUTHENTICATE USERNAME=%s", username); - lightdm_greeter_authenticate (greeter, username); - g_free (username); - } - - /* Write lock to stop repeatedly logging in */ - f = fopen (login_lock, "w"); - fclose (f); - } - else - { - g_debug ("Not logging in, lock file detected %s", login_lock); - fclose (f); - } -} - -static void show_message_cb (LightDMGreeter *greeter, const gchar *text, LightDMMessageType type) { notify_status ("GREETER SHOW-MESSAGE TEXT=\"%s\"", text); @@ -109,21 +47,16 @@ static void authentication_complete_cb (LightDMGreeter *greeter) { notify_status ("GREETER AUTHENTICATION-COMPLETE AUTHENTICATED=%s", lightdm_greeter_get_is_authenticated (greeter) ? "TRUE" : "FALSE"); - if (lightdm_greeter_get_is_authenticated (greeter)) - lightdm_greeter_start_default_session (greeter); -} - -static void -session_failed_cb (LightDMGreeter *greeter) -{ - notify_status ("GREETER SESSION-FAILED"); -} + if (!lightdm_greeter_get_is_authenticated (greeter)) + return; -static void -quit_cb (LightDMGreeter *greeter) -{ - notify_status ("GREETER QUIT"); - exit (EXIT_SUCCESS); + if (lightdm_greeter_start_session_sync (greeter, NULL)) + { + notify_status ("GREETER QUIT"); + exit (EXIT_SUCCESS); + } + else + notify_status ("GREETER SESSION-FAILED"); } static void @@ -136,6 +69,7 @@ signal_cb (int signum) int main (int argc, char **argv) { + GMainLoop *main_loop; LightDMGreeter *greeter; signal (SIGINT, signal_cb); @@ -148,29 +82,87 @@ main (int argc, char **argv) g_key_file_load_from_file (config, g_getenv ("LIGHTDM_TEST_CONFIG"), G_KEY_FILE_NONE, NULL); g_type_init (); + main_loop = g_main_loop_new (NULL, FALSE); connection = xcb_connect (NULL, NULL); if (xcb_connection_has_error (connection)) { - fprintf (stderr, "Error connecting\n"); + fprintf (stderr, "Error connecting to X server\n"); return EXIT_FAILURE; } notify_status ("GREETER CONNECT-XSERVER %s", getenv ("DISPLAY")); greeter = lightdm_greeter_new (); - g_signal_connect (greeter, "connected", G_CALLBACK (connected_cb), NULL); g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL); g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL); g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL); - g_signal_connect (greeter, "session-failed", G_CALLBACK (session_failed_cb), NULL); - g_signal_connect (greeter, "quit", G_CALLBACK (quit_cb), NULL); notify_status ("GREETER CONNECT-TO-DAEMON"); - lightdm_greeter_connect_to_server (greeter); + if (!lightdm_greeter_connect_sync (greeter)) + return EXIT_FAILURE; + + notify_status ("GREETER CONNECTED-TO-DAEMON"); + + if (g_key_file_get_boolean (config, "test-greeter-config", "crash-xserver", NULL)) + { + const gchar *name = "SIGSEGV"; + notify_status ("GREETER CRASH-XSERVER"); + xcb_intern_atom (connection, FALSE, strlen (name), name); + xcb_flush (connection); + } + + /* Automatically log in as requested user */ + if (lightdm_greeter_get_select_user_hint (greeter)) + { + notify_status ("GREETER AUTHENTICATE-SELECTED USERNAME=%s", lightdm_greeter_get_select_user_hint (greeter)); + lightdm_greeter_authenticate (greeter, lightdm_greeter_get_select_user_hint (greeter)); + } + else + { + gchar *login_lock; + FILE *f; + + login_lock = g_build_filename (g_getenv ("LIGHTDM_TEST_HOME_DIR"), ".greeter-logged-in", NULL); + f = fopen (login_lock, "r"); + if (f == NULL) + { + if (g_key_file_get_boolean (config, "test-greeter-config", "login-guest", NULL)) + { + notify_status ("GREETER AUTHENTICATE-GUEST"); + lightdm_greeter_authenticate_as_guest (greeter); + } + else if (g_key_file_get_boolean (config, "test-greeter-config", "prompt-username", NULL)) + { + notify_status ("GREETER AUTHENTICATE"); + lightdm_greeter_authenticate (greeter, NULL); + } + else + { + gchar *username; + + username = g_key_file_get_string (config, "test-greeter-config", "username", NULL); + if (username) + { + notify_status ("GREETER AUTHENTICATE USERNAME=%s", username); + lightdm_greeter_authenticate (greeter, username); + g_free (username); + } + } + + /* Write lock to stop repeatedly logging in */ + f = fopen (login_lock, "w"); + fclose (f); + } + else + { + g_debug ("Not logging in, lock file detected %s", login_lock); + fclose (f); + } + } - g_main_loop_run (g_main_loop_new (NULL, FALSE)); + g_main_loop_run (main_loop); return EXIT_SUCCESS; } |