source: proiecte/PPPP/gdm/daemon/gdm-product-slave.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 42.0 KB
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21#include "config.h"
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <fcntl.h>
26#include <unistd.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/wait.h>
30#include <errno.h>
31#include <pwd.h>
32#include <grp.h>
33
34#include <glib.h>
35#include <glib/gi18n.h>
36#include <glib/gstdio.h>
37#include <glib-object.h>
38
39#define DBUS_API_SUBJECT_TO_CHANGE
40#include <dbus/dbus-glib.h>
41#include <dbus/dbus-glib-lowlevel.h>
42
43#include <X11/Xlib.h> /* for Display */
44
45#include "gdm-common.h"
46
47#include "gdm-product-slave.h"
48#include "gdm-product-slave-glue.h"
49
50#include "gdm-server.h"
51#include "gdm-session-direct.h"
52
53extern char **environ;
54
55#define GDM_PRODUCT_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_PRODUCT_SLAVE, GdmProductSlavePrivate))
56
57#define GDM_DBUS_NAME                      "org.gnome.DisplayManager"
58#define GDM_DBUS_PRODUCT_DISPLAY_INTERFACE "org.gnome.DisplayManager.ProductDisplay"
59
60#define RELAY_SERVER_DBUS_PATH      "/org/gnome/DisplayManager/SessionRelay"
61#define RELAY_SERVER_DBUS_INTERFACE "org.gnome.DisplayManager.SessionRelay"
62
63#define MAX_CONNECT_ATTEMPTS 10
64
65struct GdmProductSlavePrivate
66{
67        char             *id;
68        GPid              pid;
69
70        char             *relay_address;
71
72        GPid              server_pid;
73        Display          *server_display;
74        guint             connection_attempts;
75
76        GdmServer        *server;
77        GdmSessionDirect *session;
78        DBusConnection   *session_relay_connection;
79
80        DBusGProxy       *product_display_proxy;
81        DBusGConnection  *connection;
82};
83
84enum {
85        PROP_0,
86        PROP_DISPLAY_ID,
87};
88
89static void     gdm_product_slave_class_init    (GdmProductSlaveClass *klass);
90static void     gdm_product_slave_init          (GdmProductSlave      *product_slave);
91static void     gdm_product_slave_finalize      (GObject             *object);
92
93G_DEFINE_TYPE (GdmProductSlave, gdm_product_slave, GDM_TYPE_SLAVE)
94
95static gboolean
96send_dbus_string_method (DBusConnection *connection,
97                         const char     *method,
98                         const char     *payload)
99{
100        DBusError       error;
101        DBusMessage    *message;
102        DBusMessage    *reply;
103        DBusMessageIter iter;
104        const char     *str;
105
106        if (payload != NULL) {
107                str = payload;
108        } else {
109                str = "";
110        }
111
112        g_debug ("GdmProductSlave: Calling %s", method);
113        message = dbus_message_new_method_call (NULL,
114                                                RELAY_SERVER_DBUS_PATH,
115                                                RELAY_SERVER_DBUS_INTERFACE,
116                                                method);
117        if (message == NULL) {
118                g_warning ("Couldn't allocate the D-Bus message");
119                return FALSE;
120        }
121
122        dbus_message_iter_init_append (message, &iter);
123        dbus_message_iter_append_basic (&iter,
124                                        DBUS_TYPE_STRING,
125                                        &str);
126
127        dbus_error_init (&error);
128        reply = dbus_connection_send_with_reply_and_block (connection,
129                                                           message,
130                                                           -1,
131                                                           &error);
132
133        dbus_message_unref (message);
134
135        if (dbus_error_is_set (&error)) {
136                g_warning ("%s %s raised: %s\n",
137                           method,
138                           error.name,
139                           error.message);
140                return FALSE;
141        }
142        if (reply != NULL) {
143                dbus_message_unref (reply);
144        }
145        dbus_connection_flush (connection);
146
147        return TRUE;
148}
149
150static gboolean
151send_dbus_void_method (DBusConnection *connection,
152                       const char     *method)
153{
154        DBusError       error;
155        DBusMessage    *message;
156        DBusMessage    *reply;
157
158        g_debug ("GdmProductSlave: Calling %s", method);
159        message = dbus_message_new_method_call (NULL,
160                                                RELAY_SERVER_DBUS_PATH,
161                                                RELAY_SERVER_DBUS_INTERFACE,
162                                                method);
163        if (message == NULL) {
164                g_warning ("Couldn't allocate the D-Bus message");
165                return FALSE;
166        }
167
168        dbus_error_init (&error);
169        reply = dbus_connection_send_with_reply_and_block (connection,
170                                                           message,
171                                                           -1,
172                                                           &error);
173
174        dbus_message_unref (message);
175
176        if (dbus_error_is_set (&error)) {
177                g_warning ("%s %s raised: %s\n",
178                           method,
179                           error.name,
180                           error.message);
181                return FALSE;
182        }
183        if (reply != NULL) {
184                dbus_message_unref (reply);
185        }
186        dbus_connection_flush (connection);
187
188        return TRUE;
189}
190
191
192static gboolean
193send_dbus_int_method (DBusConnection *connection,
194                      const char     *method,
195                      int             payload)
196{
197        DBusError       error;
198        DBusMessage    *message;
199        DBusMessage    *reply;
200        DBusMessageIter iter;
201
202        g_debug ("GdmSessionWorker: Calling %s", method);
203        message = dbus_message_new_method_call (NULL,
204                                                RELAY_SERVER_DBUS_PATH,
205                                                RELAY_SERVER_DBUS_INTERFACE,
206                                                method);
207        if (message == NULL) {
208                g_warning ("Couldn't allocate the D-Bus message");
209                return FALSE;
210        }
211
212        dbus_message_iter_init_append (message, &iter);
213        dbus_message_iter_append_basic (&iter,
214                                        DBUS_TYPE_INT32,
215                                        &payload);
216
217        dbus_error_init (&error);
218        reply = dbus_connection_send_with_reply_and_block (connection,
219                                                           message,
220                                                           -1,
221                                                           &error);
222        dbus_message_unref (message);
223        if (reply != NULL) {
224                dbus_message_unref (reply);
225        }
226        dbus_connection_flush (connection);
227
228        if (dbus_error_is_set (&error)) {
229                g_debug ("%s %s raised: %s\n",
230                         method,
231                         error.name,
232                         error.message);
233                return FALSE;
234        }
235
236        return TRUE;
237}
238
239static void
240relay_session_started (GdmProductSlave *slave,
241                       int              pid)
242{
243        send_dbus_int_method (slave->priv->session_relay_connection,
244                              "SessionStarted",
245                              pid);
246}
247
248static void
249relay_session_opened (GdmProductSlave *slave)
250{
251        send_dbus_void_method (slave->priv->session_relay_connection,
252                               "Opened");
253}
254
255static void
256on_session_opened (GdmSession      *session,
257                   GdmProductSlave *slave)
258{
259        g_debug ("GdmProductSlave: session opened");
260
261        relay_session_opened (slave);
262}
263
264static void
265disconnect_relay (GdmProductSlave *slave)
266{
267        /* drop the connection */
268
269        dbus_connection_close (slave->priv->session_relay_connection);
270        slave->priv->session_relay_connection = NULL;
271}
272
273static void
274on_session_started (GdmSession      *session,
275                    int              pid,
276                    GdmProductSlave *slave)
277{
278        g_debug ("GdmProductSlave: session started");
279
280        relay_session_started (slave, pid);
281
282        disconnect_relay (slave);
283}
284
285static void
286on_session_exited (GdmSession      *session,
287                   int              exit_code,
288                   GdmProductSlave *slave)
289{
290        g_debug ("GdmProductSlave: session exited with code %d", exit_code);
291
292        gdm_slave_stopped (GDM_SLAVE (slave));
293}
294
295static void
296on_session_died (GdmSession      *session,
297                 int              signal_number,
298                 GdmProductSlave *slave)
299{
300        g_debug ("GdmProductSlave: session died with signal %d, (%s)",
301                 signal_number,
302                 g_strsignal (signal_number));
303
304        gdm_slave_stopped (GDM_SLAVE (slave));
305}
306
307static void
308setup_server (GdmProductSlave *slave)
309{
310        /* Set the busy cursor */
311        gdm_slave_set_busy_cursor (GDM_SLAVE (slave));
312}
313
314static gboolean
315add_user_authorization (GdmProductSlave *slave,
316                        char           **filename)
317{
318        char    *username;
319        gboolean ret;
320
321        username = gdm_session_direct_get_username (slave->priv->session);
322
323        ret = gdm_slave_add_user_authorization (GDM_SLAVE (slave),
324                                                username,
325                                                filename);
326        g_debug ("GdmProductSlave: Adding user authorization for %s: %s", username, *filename);
327
328        g_free (username);
329
330        return ret;
331}
332
333static gboolean
334setup_session (GdmProductSlave *slave)
335{
336        char *auth_file;
337        char *display_device;
338
339        auth_file = NULL;
340        add_user_authorization (slave, &auth_file);
341
342        g_assert (auth_file != NULL);
343
344        display_device = NULL;
345        if (slave->priv->server != NULL) {
346                display_device = gdm_server_get_display_device (slave->priv->server);
347        }
348
349        g_object_set (slave->priv->session,
350                      "display-device", display_device,
351                      "user-x11-authority-file", auth_file,
352                      NULL);
353
354        g_free (display_device);
355        g_free (auth_file);
356
357        gdm_session_start_session (GDM_SESSION (slave->priv->session));
358
359        return TRUE;
360}
361
362static gboolean
363idle_connect_to_display (GdmProductSlave *slave)
364{
365        gboolean res;
366
367        slave->priv->connection_attempts++;
368
369        res = gdm_slave_connect_to_x11_display (GDM_SLAVE (slave));
370        if (res) {
371                /* FIXME: handle wait-for-go */
372
373                setup_server (slave);
374                setup_session (slave);
375        } else {
376                if (slave->priv->connection_attempts >= MAX_CONNECT_ATTEMPTS) {
377                        g_warning ("Unable to connect to display after %d tries - bailing out", slave->priv->connection_attempts);
378                        exit (1);
379                }
380                return TRUE;
381        }
382
383        return FALSE;
384}
385
386static void
387on_server_ready (GdmServer       *server,
388                 GdmProductSlave *slave)
389{
390        g_timeout_add (500, (GSourceFunc)idle_connect_to_display, slave);
391}
392
393static void
394on_server_exited (GdmServer       *server,
395                  int              exit_code,
396                  GdmProductSlave *slave)
397{
398        g_debug ("GdmProductSlave: server exited with code %d\n", exit_code);
399
400        gdm_slave_stopped (GDM_SLAVE (slave));
401}
402
403static void
404on_server_died (GdmServer       *server,
405                int              signal_number,
406                GdmProductSlave *slave)
407{
408        g_debug ("GdmProductSlave: server died with signal %d, (%s)",
409                 signal_number,
410                 g_strsignal (signal_number));
411
412        gdm_slave_stopped (GDM_SLAVE (slave));
413}
414
415static gboolean
416gdm_product_slave_create_server (GdmProductSlave *slave)
417{
418        char    *display_name;
419        char    *auth_file;
420        gboolean display_is_local;
421
422        g_object_get (slave,
423                      "display-is-local", &display_is_local,
424                      "display-name", &display_name,
425                      "display-x11-authority-file", &auth_file,
426                      NULL);
427
428        /* if this is local display start a server if one doesn't
429         * exist */
430        if (display_is_local) {
431                gboolean res;
432
433                slave->priv->server = gdm_server_new (display_name, auth_file);
434                g_signal_connect (slave->priv->server,
435                                  "exited",
436                                  G_CALLBACK (on_server_exited),
437                                  slave);
438                g_signal_connect (slave->priv->server,
439                                  "died",
440                                  G_CALLBACK (on_server_died),
441                                  slave);
442                g_signal_connect (slave->priv->server,
443                                  "ready",
444                                  G_CALLBACK (on_server_ready),
445                                  slave);
446
447                res = gdm_server_start (slave->priv->server);
448                if (! res) {
449                        g_warning (_("Could not start the X "
450                                     "server (your graphical environment) "
451                                     "due to some internal error. "
452                                     "Please contact your system administrator "
453                                     "or check your syslog to diagnose. "
454                                     "In the meantime this display will be "
455                                     "disabled.  Please restart GDM when "
456                                     "the problem is corrected."));
457                        exit (1);
458                }
459
460                g_debug ("GdmProductSlave: Started X server");
461        } else {
462                g_timeout_add (500, (GSourceFunc)idle_connect_to_display, slave);
463        }
464
465        g_free (display_name);
466        g_free (auth_file);
467
468        return TRUE;
469}
470
471static void
472on_session_setup_complete (GdmSession      *session,
473                           GdmProductSlave *slave)
474{
475        send_dbus_void_method (slave->priv->session_relay_connection,
476                               "SetupComplete");
477}
478
479static void
480on_session_setup_failed (GdmSession      *session,
481                         const char      *message,
482                         GdmProductSlave *slave)
483{
484        send_dbus_string_method (slave->priv->session_relay_connection,
485                                 "SetupFailed",
486                                 message);
487}
488
489static void
490on_session_reset_complete (GdmSession      *session,
491                           GdmProductSlave *slave)
492{
493        send_dbus_void_method (slave->priv->session_relay_connection,
494                               "ResetComplete");
495}
496
497static void
498on_session_reset_failed (GdmSession      *session,
499                         const char      *message,
500                         GdmProductSlave *slave)
501{
502        send_dbus_string_method (slave->priv->session_relay_connection,
503                                 "ResetFailed",
504                                 message);
505}
506
507static void
508on_session_authenticated (GdmSession      *session,
509                          GdmProductSlave *slave)
510{
511        send_dbus_void_method (slave->priv->session_relay_connection,
512                               "Authenticated");
513}
514
515static void
516on_session_authentication_failed (GdmSession      *session,
517                                  const char      *message,
518                                  GdmProductSlave *slave)
519{
520        send_dbus_string_method (slave->priv->session_relay_connection,
521                                 "AuthenticationFailed",
522                                 message);
523}
524
525static void
526on_session_authorized (GdmSession      *session,
527                       GdmProductSlave *slave)
528{
529        send_dbus_void_method (slave->priv->session_relay_connection,
530                               "Authorized");
531}
532
533static void
534on_session_authorization_failed (GdmSession      *session,
535                                 const char      *message,
536                                 GdmProductSlave *slave)
537{
538        send_dbus_string_method (slave->priv->session_relay_connection,
539                                 "AuthorizationFailed",
540                                 message);
541}
542
543static void
544on_session_accredited (GdmSession      *session,
545                       GdmProductSlave *slave)
546{
547        send_dbus_void_method (slave->priv->session_relay_connection,
548                               "Accredited");
549}
550
551static void
552on_session_accreditation_failed (GdmSession      *session,
553                                 const char      *message,
554                                 GdmProductSlave *slave)
555{
556        send_dbus_string_method (slave->priv->session_relay_connection,
557                                 "AccreditationFailed",
558                                 message);
559}
560
561static void
562on_session_info (GdmSession      *session,
563                 const char      *text,
564                 GdmProductSlave *slave)
565{
566        send_dbus_string_method (slave->priv->session_relay_connection,
567                                 "Info",
568                                 text);
569}
570
571static void
572on_session_problem (GdmSession      *session,
573                    const char      *text,
574                    GdmProductSlave *slave)
575{
576        send_dbus_string_method (slave->priv->session_relay_connection,
577                                 "Problem",
578                                 text);
579}
580
581static void
582on_session_info_query (GdmSession      *session,
583                       const char      *text,
584                       GdmProductSlave *slave)
585{
586        send_dbus_string_method (slave->priv->session_relay_connection,
587                                 "InfoQuery",
588                                 text);
589}
590
591static void
592on_session_secret_info_query (GdmSession      *session,
593                              const char      *text,
594                              GdmProductSlave *slave)
595{
596        send_dbus_string_method (slave->priv->session_relay_connection,
597                                 "SecretInfoQuery",
598                                 text);
599}
600
601static void
602on_relay_setup (GdmProductSlave *slave,
603                DBusMessage     *message)
604{
605        DBusError   error;
606        const char *service_name;
607        dbus_bool_t res;
608
609        service_name = NULL;
610
611        dbus_error_init (&error);
612        res = dbus_message_get_args (message,
613                                     &error,
614                                     DBUS_TYPE_STRING, &service_name,
615                                     DBUS_TYPE_INVALID);
616        if (res) {
617                g_debug ("GdmProductSlave: Relay Setup");
618                gdm_session_setup (GDM_SESSION (slave->priv->session),
619                                   service_name);
620        } else {
621                g_warning ("Unable to get arguments: %s", error.message);
622                dbus_error_free (&error);
623        }
624}
625
626static void
627on_relay_setup_for_user (GdmProductSlave *slave,
628                         DBusMessage     *message)
629{
630        DBusError   error;
631        const char *service_name;
632        const char *username;
633        dbus_bool_t res;
634
635        username = NULL;
636        service_name = NULL;
637
638        dbus_error_init (&error);
639        res = dbus_message_get_args (message,
640                                     &error,
641                                     DBUS_TYPE_STRING, &service_name,
642                                     DBUS_TYPE_STRING, &username,
643                                     DBUS_TYPE_INVALID);
644        if (res) {
645                g_debug ("GdmProductSlave: Relay SetupForUser");
646                gdm_session_setup_for_user (GDM_SESSION (slave->priv->session),
647                                            service_name,
648                                            username);
649        } else {
650                g_warning ("Unable to get arguments: %s", error.message);
651                dbus_error_free (&error);
652        }
653}
654
655static void
656on_relay_authenticate (GdmProductSlave *slave,
657                       DBusMessage     *message)
658{
659        g_debug ("GdmProductSlave: Relay Authenticate");
660
661        gdm_session_authenticate (GDM_SESSION (slave->priv->session));
662}
663
664static void
665on_relay_authorize (GdmProductSlave *slave,
666                    DBusMessage     *message)
667{
668        g_debug ("GdmProductSlave: Relay Authorize");
669
670        gdm_session_authorize (GDM_SESSION (slave->priv->session));
671}
672
673static void
674on_relay_establish_credentials (GdmProductSlave *slave,
675                                DBusMessage     *message)
676{
677        g_debug ("GdmProductSlave: Relay EstablishCredentials");
678
679        gdm_session_accredit (GDM_SESSION (slave->priv->session), GDM_SESSION_CRED_ESTABLISH);
680}
681
682static void
683on_relay_refresh_credentials (GdmProductSlave *slave,
684                              DBusMessage     *message)
685{
686        g_debug ("GdmProductSlave: Relay RefreshCredentials");
687
688        gdm_session_accredit (GDM_SESSION (slave->priv->session), GDM_SESSION_CRED_REFRESH);
689}
690
691static void
692on_relay_answer_query (GdmProductSlave *slave,
693                       DBusMessage     *message)
694{
695        DBusError   error;
696        const char *text;
697        dbus_bool_t res;
698
699        dbus_error_init (&error);
700        res = dbus_message_get_args (message,
701                                     &error,
702                                     DBUS_TYPE_STRING, &text,
703                                     DBUS_TYPE_INVALID);
704        if (res) {
705                g_debug ("GdmProductSlave: Relay AnswerQuery");
706                gdm_session_answer_query (GDM_SESSION (slave->priv->session), text);
707        } else {
708                g_warning ("Unable to get arguments: %s", error.message);
709                dbus_error_free (&error);
710        }
711}
712
713static void
714on_relay_session_selected (GdmProductSlave *slave,
715                           DBusMessage     *message)
716{
717        DBusError   error;
718        const char *text;
719        dbus_bool_t res;
720
721        dbus_error_init (&error);
722        res = dbus_message_get_args (message,
723                                     &error,
724                                     DBUS_TYPE_STRING, &text,
725                                     DBUS_TYPE_INVALID);
726        if (res) {
727                g_debug ("GdmProductSlave: Session selected %s", text);
728                gdm_session_select_session (GDM_SESSION (slave->priv->session), text);
729        } else {
730                g_warning ("Unable to get arguments: %s", error.message);
731                dbus_error_free (&error);
732        }
733}
734
735static void
736on_relay_language_selected (GdmProductSlave *slave,
737                            DBusMessage     *message)
738{
739        DBusError   error;
740        const char *text;
741        dbus_bool_t res;
742
743        dbus_error_init (&error);
744        res = dbus_message_get_args (message,
745                                     &error,
746                                     DBUS_TYPE_STRING, &text,
747                                     DBUS_TYPE_INVALID);
748        if (res) {
749                g_debug ("GdmProductSlave: Language selected %s", text);
750                gdm_session_select_language (GDM_SESSION (slave->priv->session), text);
751        } else {
752                g_warning ("Unable to get arguments: %s", error.message);
753                dbus_error_free (&error);
754        }
755}
756
757static void
758on_relay_layout_selected (GdmProductSlave *slave,
759                          DBusMessage     *message)
760{
761        DBusError   error;
762        const char *text;
763        dbus_bool_t res;
764
765        dbus_error_init (&error);
766        res = dbus_message_get_args (message,
767                                     &error,
768                                     DBUS_TYPE_STRING, &text,
769                                     DBUS_TYPE_INVALID);
770        if (res) {
771                g_debug ("GdmProductSlave: Layout selected %s", text);
772                gdm_session_select_layout (GDM_SESSION (slave->priv->session), text);
773        } else {
774                g_warning ("Unable to get arguments: %s", error.message);
775                dbus_error_free (&error);
776        }
777}
778
779static void
780on_relay_user_selected (GdmProductSlave *slave,
781                        DBusMessage     *message)
782{
783        g_debug ("GdmProductSlave: Greeter user selected");
784}
785
786static void
787on_relay_open (GdmProductSlave *slave,
788               DBusMessage     *message)
789{
790        gdm_session_open (GDM_SESSION (slave->priv->session));
791}
792
793static void
794on_relay_start_session (GdmProductSlave *slave,
795                        DBusMessage     *message)
796{
797        gdm_product_slave_create_server (slave);
798}
799
800static void
801create_new_session (GdmProductSlave *slave)
802{
803        gboolean       display_is_local;
804        char          *display_id;
805        char          *display_name;
806        char          *display_hostname;
807        char          *display_device;
808        char          *display_x11_authority_file;
809
810        g_debug ("GdmProductSlave: Creating new session");
811
812        g_object_get (slave,
813                      "display-id", &display_id,
814                      "display-name", &display_name,
815                      "display-hostname", &display_hostname,
816                      "display-is-local", &display_is_local,
817                      "display-x11-authority-file", &display_x11_authority_file,
818                      NULL);
819
820        /* FIXME: we don't yet have a display device! */
821        display_device = g_strdup ("");
822
823        slave->priv->session = gdm_session_direct_new (display_id,
824                                                       display_name,
825                                                       display_hostname,
826                                                       display_device,
827                                                       display_x11_authority_file,
828                                                       display_is_local);
829        g_free (display_id);
830        g_free (display_name);
831        g_free (display_hostname);
832        g_free (display_device);
833
834        g_signal_connect (slave->priv->session,
835                          "opened",
836                          G_CALLBACK (on_session_opened),
837                          slave);
838        g_signal_connect (slave->priv->session,
839                          "setup-complete",
840                          G_CALLBACK (on_session_setup_complete),
841                          slave);
842        g_signal_connect (slave->priv->session,
843                          "setup-failed",
844                          G_CALLBACK (on_session_setup_failed),
845                          slave);
846        g_signal_connect (slave->priv->session,
847                          "reset-complete",
848                          G_CALLBACK (on_session_reset_complete),
849                          slave);
850        g_signal_connect (slave->priv->session,
851                          "reset-failed",
852                          G_CALLBACK (on_session_reset_failed),
853                          slave);
854        g_signal_connect (slave->priv->session,
855                          "authenticated",
856                          G_CALLBACK (on_session_authenticated),
857                          slave);
858        g_signal_connect (slave->priv->session,
859                          "authentication-failed",
860                          G_CALLBACK (on_session_authentication_failed),
861                          slave);
862        g_signal_connect (slave->priv->session,
863                          "authorized",
864                          G_CALLBACK (on_session_authorized),
865                          slave);
866        g_signal_connect (slave->priv->session,
867                          "authorization-failed",
868                          G_CALLBACK (on_session_authorization_failed),
869                          slave);
870        g_signal_connect (slave->priv->session,
871                          "accredited",
872                          G_CALLBACK (on_session_accredited),
873                          slave);
874        g_signal_connect (slave->priv->session,
875                          "accreditation-failed",
876                          G_CALLBACK (on_session_accreditation_failed),
877                          slave);
878
879        g_signal_connect (slave->priv->session,
880                          "info",
881                          G_CALLBACK (on_session_info),
882                          slave);
883        g_signal_connect (slave->priv->session,
884                          "problem",
885                          G_CALLBACK (on_session_problem),
886                          slave);
887        g_signal_connect (slave->priv->session,
888                          "info-query",
889                          G_CALLBACK (on_session_info_query),
890                          slave);
891        g_signal_connect (slave->priv->session,
892                          "secret-info-query",
893                          G_CALLBACK (on_session_secret_info_query),
894                          slave);
895
896        g_signal_connect (slave->priv->session,
897                          "session-started",
898                          G_CALLBACK (on_session_started),
899                          slave);
900        g_signal_connect (slave->priv->session,
901                          "session-exited",
902                          G_CALLBACK (on_session_exited),
903                          slave);
904        g_signal_connect (slave->priv->session,
905                          "session-died",
906                          G_CALLBACK (on_session_died),
907                          slave);
908}
909
910static void
911on_relay_cancelled (GdmProductSlave *slave,
912                    DBusMessage     *message)
913{
914        g_debug ("GdmProductSlave: Relay cancelled");
915
916        if (slave->priv->session != NULL) {
917                gdm_session_close (GDM_SESSION (slave->priv->session));
918                g_object_unref (slave->priv->session);
919        }
920
921        create_new_session (slave);
922}
923
924static void
925get_relay_address (GdmProductSlave *slave)
926{
927        GError  *error;
928        char    *text;
929        gboolean res;
930
931        text = NULL;
932        error = NULL;
933        res = dbus_g_proxy_call (slave->priv->product_display_proxy,
934                                 "GetRelayAddress",
935                                 &error,
936                                 G_TYPE_INVALID,
937                                 G_TYPE_STRING, &text,
938                                 G_TYPE_INVALID);
939        if (! res) {
940                g_warning ("Unable to get relay address: %s", error->message);
941                g_error_free (error);
942        } else {
943                g_free (slave->priv->relay_address);
944                slave->priv->relay_address = g_strdup (text);
945                g_debug ("GdmProductSlave: Got relay address: %s", slave->priv->relay_address);
946        }
947
948        g_free (text);
949}
950
951static DBusHandlerResult
952relay_dbus_handle_message (DBusConnection *connection,
953                           DBusMessage    *message,
954                           void           *user_data,
955                           dbus_bool_t     local_interface)
956{
957        GdmProductSlave *slave = GDM_PRODUCT_SLAVE (user_data);
958
959#if 0
960        g_message ("obj_path=%s interface=%s method=%s destination=%s",
961                   dbus_message_get_path (message),
962                   dbus_message_get_interface (message),
963                   dbus_message_get_member (message),
964                   dbus_message_get_destination (message));
965#endif
966
967        g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
968        g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
969
970        if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Setup")) {
971                on_relay_setup (slave, message);
972        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "SetupForUser")) {
973                on_relay_setup_for_user (slave, message);
974        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Authenticate")) {
975                on_relay_authenticate (slave, message);
976        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Authorize")) {
977                on_relay_authorize (slave, message);
978        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "EstablishCredentials")) {
979                on_relay_establish_credentials (slave, message);
980        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "RefreshCredentials")) {
981                on_relay_refresh_credentials (slave, message);
982        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "AnswerQuery")) {
983                on_relay_answer_query (slave, message);
984        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "SessionSelected")) {
985                on_relay_session_selected (slave, message);
986        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "LanguageSelected")) {
987                on_relay_language_selected (slave, message);
988        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "LayoutSelected")) {
989                on_relay_layout_selected (slave, message);
990        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "UserSelected")) {
991                on_relay_user_selected (slave, message);
992        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "StartSession")) {
993                on_relay_start_session (slave, message);
994        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Open")) {
995                on_relay_open (slave, message);
996        } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Cancelled")) {
997                on_relay_cancelled (slave, message);
998        } else {
999                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1000        }
1001
1002        return DBUS_HANDLER_RESULT_HANDLED;
1003}
1004
1005static DBusHandlerResult
1006relay_dbus_filter_function (DBusConnection *connection,
1007                            DBusMessage    *message,
1008                            void           *user_data)
1009{
1010        GdmProductSlave *slave = GDM_PRODUCT_SLAVE (user_data);
1011        const char      *path;
1012
1013        path = dbus_message_get_path (message);
1014
1015        g_debug ("GdmProductSlave: obj_path=%s interface=%s method=%s",
1016                 dbus_message_get_path (message),
1017                 dbus_message_get_interface (message),
1018                 dbus_message_get_member (message));
1019
1020        if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")
1021            && strcmp (path, DBUS_PATH_LOCAL) == 0) {
1022
1023                g_debug ("GdmProductSlave: Got disconnected from the server");
1024
1025                dbus_connection_unref (connection);
1026                slave->priv->connection = NULL;
1027
1028        } else if (dbus_message_is_signal (message,
1029                                           DBUS_INTERFACE_DBUS,
1030                                           "NameOwnerChanged")) {
1031                g_debug ("GdmProductSlave: Name owner changed?");
1032        } else {
1033                return relay_dbus_handle_message (connection, message, user_data, FALSE);
1034        }
1035
1036        return DBUS_HANDLER_RESULT_HANDLED;
1037}
1038
1039static gboolean
1040connect_to_session_relay (GdmProductSlave *slave)
1041{
1042        DBusError       error;
1043
1044        get_relay_address (slave);
1045
1046        g_debug ("GdmProductSlave: connecting to session relay address: %s", slave->priv->relay_address);
1047
1048        dbus_error_init (&error);
1049        slave->priv->session_relay_connection = dbus_connection_open_private (slave->priv->relay_address, &error);
1050        if (slave->priv->session_relay_connection == NULL) {
1051                if (dbus_error_is_set (&error)) {
1052                        g_warning ("error opening connection: %s", error.message);
1053                        dbus_error_free (&error);
1054                } else {
1055                        g_warning ("Unable to open connection");
1056                }
1057                exit (1);
1058        }
1059
1060        dbus_connection_setup_with_g_main (slave->priv->session_relay_connection, NULL);
1061        dbus_connection_set_exit_on_disconnect (slave->priv->session_relay_connection, FALSE);
1062
1063        dbus_connection_add_filter (slave->priv->session_relay_connection,
1064                                    relay_dbus_filter_function,
1065                                    slave,
1066                                    NULL);
1067
1068        return TRUE;
1069}
1070
1071static gboolean
1072gdm_product_slave_start (GdmSlave *slave)
1073{
1074        gboolean ret;
1075        GError  *error;
1076        char    *display_id;
1077
1078        ret = FALSE;
1079
1080        GDM_SLAVE_CLASS (gdm_product_slave_parent_class)->start (slave);
1081
1082        g_object_get (slave,
1083                      "display-id", &display_id,
1084                      NULL);
1085
1086        error = NULL;
1087        GDM_PRODUCT_SLAVE (slave)->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
1088        if (GDM_PRODUCT_SLAVE (slave)->priv->connection == NULL) {
1089                if (error != NULL) {
1090                        g_critical ("error getting system bus: %s", error->message);
1091                        g_error_free (error);
1092                }
1093                exit (1);
1094        }
1095
1096        error = NULL;
1097        GDM_PRODUCT_SLAVE (slave)->priv->product_display_proxy = dbus_g_proxy_new_for_name_owner (GDM_PRODUCT_SLAVE (slave)->priv->connection,
1098                                                                                                  GDM_DBUS_NAME,
1099                                                                                                  display_id,
1100                                                                                                  GDM_DBUS_PRODUCT_DISPLAY_INTERFACE,
1101                                                                                                  &error);
1102        if (GDM_PRODUCT_SLAVE (slave)->priv->product_display_proxy == NULL) {
1103                if (error != NULL) {
1104                        g_warning ("Failed to create display proxy %s: %s", display_id, error->message);
1105                        g_error_free (error);
1106                } else {
1107                        g_warning ("Unable to create display proxy");
1108                }
1109                goto out;
1110        }
1111
1112        create_new_session (GDM_PRODUCT_SLAVE (slave));
1113
1114        connect_to_session_relay (GDM_PRODUCT_SLAVE (slave));
1115
1116        ret = TRUE;
1117
1118 out:
1119        g_free (display_id);
1120
1121        return ret;
1122}
1123
1124static gboolean
1125gdm_product_slave_stop (GdmSlave *slave)
1126{
1127        g_debug ("GdmProductSlave: Stopping product_slave");
1128
1129        GDM_SLAVE_CLASS (gdm_product_slave_parent_class)->stop (slave);
1130
1131        if (GDM_PRODUCT_SLAVE (slave)->priv->session != NULL) {
1132                gdm_session_close (GDM_SESSION (GDM_PRODUCT_SLAVE (slave)->priv->session));
1133                g_object_unref (GDM_PRODUCT_SLAVE (slave)->priv->session);
1134                GDM_PRODUCT_SLAVE (slave)->priv->session = NULL;
1135        }
1136
1137        if (GDM_PRODUCT_SLAVE (slave)->priv->server != NULL) {
1138                gdm_server_stop (GDM_PRODUCT_SLAVE (slave)->priv->server);
1139                g_object_unref (GDM_PRODUCT_SLAVE (slave)->priv->server);
1140                GDM_PRODUCT_SLAVE (slave)->priv->server = NULL;
1141        }
1142
1143        if (GDM_PRODUCT_SLAVE (slave)->priv->product_display_proxy != NULL) {
1144                g_object_unref (GDM_PRODUCT_SLAVE (slave)->priv->product_display_proxy);
1145        }
1146
1147        return TRUE;
1148}
1149
1150static void
1151gdm_product_slave_set_property (GObject      *object,
1152                                guint         prop_id,
1153                                const GValue *value,
1154                                GParamSpec   *pspec)
1155{
1156        switch (prop_id) {
1157        default:
1158                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1159                break;
1160        }
1161}
1162
1163static void
1164gdm_product_slave_get_property (GObject    *object,
1165                                guint       prop_id,
1166                                GValue     *value,
1167                                GParamSpec *pspec)
1168{
1169        switch (prop_id) {
1170        default:
1171                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1172                break;
1173        }
1174}
1175
1176static GObject *
1177gdm_product_slave_constructor (GType                  type,
1178                               guint                  n_construct_properties,
1179                               GObjectConstructParam *construct_properties)
1180{
1181        GdmProductSlave      *product_slave;
1182
1183        product_slave = GDM_PRODUCT_SLAVE (G_OBJECT_CLASS (gdm_product_slave_parent_class)->constructor (type,
1184                                                                                                         n_construct_properties,
1185                                                                                                         construct_properties));
1186        return G_OBJECT (product_slave);
1187}
1188
1189static void
1190gdm_product_slave_class_init (GdmProductSlaveClass *klass)
1191{
1192        GObjectClass  *object_class = G_OBJECT_CLASS (klass);
1193        GdmSlaveClass *slave_class = GDM_SLAVE_CLASS (klass);
1194
1195        object_class->get_property = gdm_product_slave_get_property;
1196        object_class->set_property = gdm_product_slave_set_property;
1197        object_class->constructor = gdm_product_slave_constructor;
1198        object_class->finalize = gdm_product_slave_finalize;
1199
1200        slave_class->start = gdm_product_slave_start;
1201        slave_class->stop = gdm_product_slave_stop;
1202
1203        g_type_class_add_private (klass, sizeof (GdmProductSlavePrivate));
1204
1205        dbus_g_object_type_install_info (GDM_TYPE_PRODUCT_SLAVE, &dbus_glib_gdm_product_slave_object_info);
1206}
1207
1208static void
1209gdm_product_slave_init (GdmProductSlave *slave)
1210{
1211        slave->priv = GDM_PRODUCT_SLAVE_GET_PRIVATE (slave);
1212}
1213
1214static void
1215gdm_product_slave_finalize (GObject *object)
1216{
1217        GdmProductSlave *slave;
1218
1219        g_return_if_fail (object != NULL);
1220        g_return_if_fail (GDM_IS_PRODUCT_SLAVE (object));
1221
1222        slave = GDM_PRODUCT_SLAVE (object);
1223
1224        g_return_if_fail (slave->priv != NULL);
1225
1226        gdm_product_slave_stop (GDM_SLAVE (slave));
1227
1228        G_OBJECT_CLASS (gdm_product_slave_parent_class)->finalize (object);
1229}
1230
1231GdmSlave *
1232gdm_product_slave_new (const char *id)
1233{
1234        GObject *object;
1235
1236        object = g_object_new (GDM_TYPE_PRODUCT_SLAVE,
1237                               "display-id", id,
1238                               NULL);
1239
1240        return GDM_SLAVE (object);
1241}
Note: See TracBrowser for help on using the repository browser.