2 * Copyright (C) 2010-2016 Canonical Ltd.
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation, either version 3 of the License, or (at your option) any later
7 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
16 #include <gio/gunixsocketaddress.h>
18 #include "greeter-socket.h"
24 static guint signals[LAST_SIGNAL] = { 0 };
26 struct GreeterSocketPrivate
28 /* Path of socket to use */
31 /* Listening UNIX socket */
34 /* Source for listening for connections */
37 /* Socket to greeter */
38 GSocket *greeter_socket;
40 /* Greeter connected on this socket */
44 G_DEFINE_TYPE (GreeterSocket, greeter_socket, G_TYPE_OBJECT);
47 greeter_socket_new (const gchar *path)
49 GreeterSocket *socket;
51 socket = g_object_new (GREETER_SOCKET_TYPE, NULL);
52 socket->priv->path = g_strdup (path);
58 greeter_disconnected_cb (Greeter *greeter, GreeterSocket *socket)
60 if (greeter == socket->priv->greeter)
62 g_clear_object (&socket->priv->greeter);
63 g_clear_object (&socket->priv->greeter_socket);
68 greeter_connect_cb (GSocket *s, GIOCondition condition, GreeterSocket *socket)
73 new_socket = g_socket_accept (socket->priv->socket, NULL, &error);
75 g_warning ("Failed to accept greeter connection: %s", error->message);
76 g_clear_error (&error);
78 return G_SOURCE_CONTINUE;
80 /* Greeter already connected */
81 if (socket->priv->greeter)
83 g_socket_close (new_socket, NULL);
84 g_object_unref (new_socket);
85 return G_SOURCE_CONTINUE;
88 socket->priv->greeter_socket = new_socket;
89 g_signal_emit (socket, signals[CREATE_GREETER], 0, &socket->priv->greeter);
90 g_signal_connect (socket->priv->greeter, GREETER_SIGNAL_DISCONNECTED, G_CALLBACK (greeter_disconnected_cb), socket);
91 greeter_set_file_descriptors (socket->priv->greeter, g_socket_get_fd (new_socket), g_socket_get_fd (new_socket));
93 return G_SOURCE_CONTINUE;
97 greeter_socket_start (GreeterSocket *socket, GError **error)
99 GSocketAddress *address;
102 g_return_val_if_fail (socket != NULL, FALSE);
103 g_return_val_if_fail (socket->priv->socket == NULL, FALSE);
105 socket->priv->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error);
106 if (!socket->priv->socket)
109 unlink (socket->priv->path);
110 address = g_unix_socket_address_new (socket->priv->path);
111 result = g_socket_bind (socket->priv->socket, address, FALSE, error);
112 g_object_unref (address);
115 if (!g_socket_listen (socket->priv->socket, error))
118 socket->priv->source = g_socket_create_source (socket->priv->socket, G_IO_IN, NULL);
119 g_source_set_callback (socket->priv->source, (GSourceFunc) greeter_connect_cb, socket, NULL);
120 g_source_attach (socket->priv->source, NULL);
122 /* Allow to be written to */
123 if (chmod (socket->priv->path, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
127 g_file_error_from_errno (errno),
128 "Failed to set permissions on greeter socket %s: %s",
138 greeter_socket_init (GreeterSocket *socket)
140 socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket, GREETER_SOCKET_TYPE, GreeterSocketPrivate);
144 greeter_socket_finalize (GObject *object)
146 GreeterSocket *self = GREETER_SOCKET (object);
148 if (self->priv->path)
149 unlink (self->priv->path);
150 g_free (self->priv->path);
151 g_clear_object (&self->priv->socket);
152 g_clear_object (&self->priv->source);
153 g_clear_object (&self->priv->greeter_socket);
154 g_clear_object (&self->priv->greeter);
156 G_OBJECT_CLASS (greeter_socket_parent_class)->finalize (object);
160 greeter_socket_class_init (GreeterSocketClass *klass)
162 GObjectClass *object_class = G_OBJECT_CLASS (klass);
164 object_class->finalize = greeter_socket_finalize;
166 signals[CREATE_GREETER] =
167 g_signal_new (GREETER_SOCKET_SIGNAL_CREATE_GREETER,
168 G_TYPE_FROM_CLASS (klass),
170 G_STRUCT_OFFSET (GreeterSocketClass, create_greeter),
171 g_signal_accumulator_first_wins,
176 g_type_class_add_private (klass, sizeof (GreeterSocketPrivate));