summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2007-06-03 20:11:58 -0400
committerRay Strode <rstrode@redhat.com>2007-06-03 20:11:58 -0400
commitee407ee53bffa7e7c3073237abefd62eb9cd9595 (patch)
tree710932bcb7c66908c6ebf8aec2e07b5002f4f7f3 /src
parenta6f81dcdf95c6be75d2bc4657d23ebb9272e3a2d (diff)
downloadplymouth-ee407ee53bffa7e7c3073237abefd62eb9cd9595.tar.gz
plymouth-ee407ee53bffa7e7c3073237abefd62eb9cd9595.tar.xz
plymouth-ee407ee53bffa7e7c3073237abefd62eb9cd9595.zip
add the start of some classes for tracking boot status
Diffstat (limited to 'src')
-rw-r--r--src/ply-boot-client.c449
-rw-r--r--src/ply-boot-client.h57
-rw-r--r--src/ply-boot-server.c255
-rw-r--r--src/ply-boot-server.h46
-rw-r--r--src/tests/Makefile.am1
5 files changed, 808 insertions, 0 deletions
diff --git a/src/ply-boot-client.c b/src/ply-boot-client.c
new file mode 100644
index 0000000..ebcd76f
--- /dev/null
+++ b/src/ply-boot-client.c
@@ -0,0 +1,449 @@
+/* ply-boot-client.h - APIs for talking to the boot status daemon
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-boot-client.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "ply-event-loop.h"
+#include "ply-list.h"
+#include "ply-logger.h"
+#include "ply-utils.h"
+
+struct _ply_boot_client
+{
+ ply_event_loop_t *loop;
+ ply_fd_watch_t *daemon_can_take_request_watch;
+ ply_fd_watch_t *daemon_has_reply_watch;
+ ply_list_t *requests_to_send;
+ ply_list_t *requests_waiting_for_replies;
+ int socket_fd;
+
+ ply_boot_client_disconnect_handler_t disconnect_handler;
+ void *disconnect_handler_user_data;
+
+ uint32_t is_connected : 1;
+};
+
+typedef struct
+{
+ ply_boot_client_t *client;
+ char *string;
+ ply_boot_client_response_handler_t handler;
+ ply_boot_client_response_handler_t failed_handler;
+ void *user_data;
+} ply_boot_client_request_t;
+
+static void ply_boot_client_cancel_request (ply_boot_client_t *client,
+ ply_boot_client_request_t *request);
+
+
+ply_boot_client_t *
+ply_boot_client_new (void)
+{
+ ply_boot_client_t *client;
+
+ client = calloc (1, sizeof (ply_boot_client_t));
+ client->daemon_can_take_request_watch = NULL;
+ client->daemon_has_reply_watch = NULL;
+ client->requests_to_send = ply_list_new ();
+ client->requests_waiting_for_replies = ply_list_new ();
+ client->loop = NULL;
+ client->is_connected = false;
+ client->disconnect_handler = NULL;
+ client->disconnect_handler_user_data = NULL;
+
+ return client;
+}
+
+static void
+ply_boot_client_cancel_requests (ply_boot_client_t *client)
+{
+ ply_list_node_t *node;
+
+ node = ply_list_get_first_node (client->requests_to_send);
+ while (node != NULL)
+ {
+ ply_boot_client_request_t *request;
+
+ request = (ply_boot_client_request_t *) ply_list_node_get_data (node);
+
+ ply_boot_client_cancel_request (client, request);
+
+ node = ply_list_get_next_node (client->requests_to_send, node);
+ }
+
+ node = ply_list_get_first_node (client->requests_waiting_for_replies);
+ while (node != NULL)
+ {
+ ply_boot_client_request_t *request;
+
+ request = (ply_boot_client_request_t *) ply_list_node_get_data (node);
+
+ ply_boot_client_cancel_request (client, request);
+
+ node = ply_list_get_next_node (client->requests_waiting_for_replies, node);
+ }
+}
+
+void
+ply_boot_client_free (ply_boot_client_t *client)
+{
+ if (client == NULL)
+ return;
+
+ ply_boot_client_cancel_requests (client);
+
+ ply_list_free (client->requests_to_send);
+ ply_list_free (client->requests_waiting_for_replies);
+
+ free (client);
+}
+
+bool
+ply_boot_client_connect (ply_boot_client_t *client,
+ ply_boot_client_disconnect_handler_t disconnect_handler,
+ void *user_data)
+{
+ assert (client != NULL);
+ assert (!client->is_connected);
+ assert (client->disconnect_handler == NULL);
+ assert (client->disconnect_handler_user_data == NULL);
+
+ client->socket_fd =
+ ply_connect_to_unix_socket (PLY_BOOT_PROTOCOL_SOCKET_PATH, true);
+
+ if (client->socket_fd < 0)
+ return false;
+
+ client->disconnect_handler = disconnect_handler;
+ client->disconnect_handler_user_data = user_data;
+
+ client->is_connected = true;
+ return true;
+}
+
+static ply_boot_client_request_t *
+ply_boot_client_request_new (ply_boot_client_t *client,
+ const char *request_string,
+ ply_boot_client_response_handler_t handler,
+ ply_boot_client_response_handler_t failed_handler,
+ void *user_data)
+{
+ ply_boot_client_request_t *request;
+
+ assert (client != NULL);
+ assert (request_string != NULL);
+ assert (handler != NULL);
+
+ request = calloc (1, sizeof (ply_boot_client_request_t));
+ request->client = client;
+ request->string = strdup (request_string);
+ request->handler = handler;
+ request->failed_handler = failed_handler;
+ request->user_data = user_data;
+
+ return request;
+}
+
+static void
+ply_boot_client_request_free (ply_boot_client_request_t *request)
+{
+ if (request == NULL)
+ return;
+ free (request->string);
+ free (request);
+}
+
+static void
+ply_boot_client_cancel_request (ply_boot_client_t *client,
+ ply_boot_client_request_t *request)
+{
+ if (request->failed_handler != NULL)
+ request->failed_handler (request->user_data, request->client);
+
+ ply_boot_client_request_free (request);
+}
+
+static void
+ply_boot_client_process_incoming_replies (ply_boot_client_t *client)
+{
+ ply_list_node_t *request_node;
+ ply_boot_client_request_t *request;
+ uint8_t byte[2] = "";
+
+ assert (client != NULL);
+
+ if (ply_list_get_length (client->requests_waiting_for_replies) == 0)
+ {
+ ply_error ("received unexpected response from boot status daemon");
+ return;
+ }
+
+ request_node = ply_list_get_first_node (client->requests_waiting_for_replies);
+ assert (request_node != NULL);
+
+ request = (ply_boot_client_request_t *) ply_list_node_get_data (request_node);
+ assert (request != NULL);
+
+ if (!ply_read (client->socket_fd, byte, sizeof (uint8_t)))
+ {
+ if (request->failed_handler != NULL)
+ request->failed_handler (request->user_data, client);
+ ply_list_remove_node (client->requests_waiting_for_replies, request_node);
+ return;
+ }
+
+ if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK, sizeof (uint8_t)) != 0)
+ {
+ if (request->failed_handler != NULL)
+ request->failed_handler (request->user_data, client);
+ ply_list_remove_node (client->requests_waiting_for_replies, request_node);
+ return;
+ }
+
+ request->handler (request->user_data, client);
+ ply_list_remove_node (client->requests_waiting_for_replies, request_node);
+
+ if (ply_list_get_length (client->requests_waiting_for_replies) == 0)
+ {
+ ply_event_loop_stop_watching_fd (client->loop,
+ client->daemon_has_reply_watch);
+ client->daemon_has_reply_watch = NULL;
+ }
+}
+
+static bool
+ply_boot_client_send_request (ply_boot_client_t *client,
+ ply_boot_client_request_t *request)
+{
+ if (!ply_write (client->socket_fd, request->string,
+ strlen (request->string)))
+ {
+ ply_boot_client_cancel_request (client, request);
+ return false;
+ }
+
+ if (client->daemon_has_reply_watch == NULL)
+ {
+ assert (ply_list_get_length (client->requests_waiting_for_replies) == 0);
+ client->daemon_has_reply_watch =
+ ply_event_loop_watch_fd (client->loop, client->socket_fd,
+ PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
+ (ply_event_handler_t)
+ ply_boot_client_process_incoming_replies,
+ NULL, client);
+ }
+
+ return true;
+}
+
+static void
+ply_boot_client_process_pending_requests (ply_boot_client_t *client)
+{
+ ply_list_node_t *request_node;
+ ply_boot_client_request_t *request;
+
+ assert (ply_list_get_length (client->requests_to_send) != 0);
+ assert (client->daemon_can_take_request_watch != NULL);
+
+ request_node = ply_list_get_first_node (client->requests_to_send);
+ assert (request_node != NULL);
+
+ request = (ply_boot_client_request_t *) ply_list_node_get_data (request_node);
+ assert (request != NULL);
+
+ ply_list_remove_node (client->requests_to_send, request_node);
+
+ if (ply_boot_client_send_request (client, request))
+ ply_list_append_data (client->requests_waiting_for_replies, request);
+
+ if (ply_list_get_length (client->requests_to_send) == 0)
+ {
+ ply_event_loop_stop_watching_fd (client->loop,
+ client->daemon_can_take_request_watch);
+ client->daemon_can_take_request_watch = NULL;
+ }
+}
+
+static void
+ply_boot_client_queue_request (ply_boot_client_t *client,
+ const char *request_string,
+ ply_boot_client_response_handler_t handler,
+ ply_boot_client_response_handler_t failed_handler,
+ void *user_data)
+{
+ ply_boot_client_request_t *request;
+
+ assert (client != NULL);
+ assert (client->loop != NULL);
+ assert (client->socket_fd >= 0);
+ assert (request_string != NULL);
+ assert (handler != NULL);
+
+ if (client->daemon_can_take_request_watch == NULL)
+ {
+ assert (ply_list_get_length (client->requests_to_send) == 0);
+ client->daemon_can_take_request_watch = ply_event_loop_watch_fd (client->loop, client->socket_fd,
+ PLY_EVENT_LOOP_FD_STATUS_CAN_TAKE_DATA,
+ (ply_event_handler_t)
+ ply_boot_client_process_pending_requests,
+ NULL, client);
+ }
+
+ request = ply_boot_client_request_new (client, request_string, handler,
+ failed_handler, user_data);
+ ply_list_append_data (client->requests_to_send, request);
+}
+
+void
+ply_boot_client_ping_daemon (ply_boot_client_t *client,
+ ply_boot_client_response_handler_t handler,
+ ply_boot_client_response_handler_t failed_handler,
+ void *user_data)
+{
+ assert (client != NULL);
+
+ ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PING,
+ handler, failed_handler, user_data);
+}
+
+void
+ply_boot_client_disconnect (ply_boot_client_t *client)
+{
+ assert (client != NULL);
+
+ close (client->socket_fd);
+ client->socket_fd = -1;
+ client->is_connected = false;
+}
+
+static void
+ply_boot_client_detach_from_event_loop (ply_boot_client_t *client)
+{
+ assert (client != NULL);
+ client->loop = NULL;
+}
+
+static void
+ply_boot_client_on_hangup (ply_boot_client_t *client)
+{
+ assert (client != NULL);
+ ply_boot_client_cancel_requests (client);
+
+ if (client->disconnect_handler != NULL)
+ client->disconnect_handler (client->disconnect_handler_user_data,
+ client);
+}
+
+void
+ply_boot_client_attach_to_event_loop (ply_boot_client_t *client,
+ ply_event_loop_t *loop)
+{
+ assert (client != NULL);
+ assert (loop != NULL);
+ assert (client->loop == NULL);
+ assert (client->socket_fd >= 0);
+
+ client->loop = loop;
+
+ ply_event_loop_watch_fd (client->loop, client->socket_fd,
+ PLY_EVENT_LOOP_FD_STATUS_NONE,
+ NULL,
+ (ply_event_handler_t) ply_boot_client_on_hangup,
+ client);
+
+ ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
+ ply_boot_client_detach_from_event_loop,
+ client);
+
+}
+
+#ifdef PLY_BOOT_CLIENT_ENABLE_TEST
+
+#include <stdio.h>
+
+#include "ply-event-loop.h"
+#include "ply-boot-client.h"
+
+static void
+on_pinged (ply_event_loop_t *loop)
+{
+ printf ("PING!\n");
+ ply_event_loop_exit (loop, 0);
+}
+
+static void
+on_failed (ply_event_loop_t *loop)
+{
+ printf ("FAILED! %m\n");
+ ply_event_loop_exit (loop, 1);
+}
+
+static void
+on_disconnect (ply_event_loop_t *loop)
+{
+ printf ("DISCONNECT!\n");
+ ply_event_loop_exit (loop, 1);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ ply_event_loop_t *loop;
+ ply_boot_client_t *client;
+ int exit_code;
+
+ exit_code = 0;
+
+ loop = ply_event_loop_new ();
+
+ client = ply_boot_client_new ();
+
+ if (!ply_boot_client_connect (client,
+ (ply_boot_client_disconnect_handler_t) on_disconnect,
+ loop))
+ {
+ perror ("could not start boot client");
+ return errno;
+ }
+
+ ply_boot_client_attach_to_event_loop (client, loop);
+ ply_boot_client_ping_daemon (client,
+ (ply_boot_client_response_handler_t) on_pinged,
+ (ply_boot_client_response_handler_t) on_failed,
+ loop);
+
+ exit_code = ply_event_loop_run (loop);
+
+ ply_boot_client_free (client);
+
+ return exit_code;
+}
+
+#endif /* PLY_BOOT_CLIENT_ENABLE_TEST */
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
diff --git a/src/ply-boot-client.h b/src/ply-boot-client.h
new file mode 100644
index 0000000..96d123f
--- /dev/null
+++ b/src/ply-boot-client.h
@@ -0,0 +1,57 @@
+/* ply-boot-client.h - APIs for talking to the boot status daemon
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written By: Ray Strode <rstrode@redhat.com>
+ */
+#ifndef PLY_BOOT_CLIENT_H
+#define PLY_BOOT_CLIENT_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "ply-boot-protocol.h"
+#include "ply-event-loop.h"
+
+typedef struct _ply_boot_client ply_boot_client_t;
+typedef void (* ply_boot_client_response_handler_t) (void *user_data,
+ ply_boot_client_t *client);
+typedef void (* ply_boot_client_disconnect_handler_t) (void *user_data,
+ ply_boot_client_t *client);
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+ply_boot_client_t *ply_boot_client_new (void);
+
+void ply_boot_client_free (ply_boot_client_t *client);
+bool ply_boot_client_connect (ply_boot_client_t *client,
+ ply_boot_client_disconnect_handler_t disconnect_handler,
+ void *user_data);
+void ply_boot_client_ping_daemon (ply_boot_client_t *client,
+ ply_boot_client_response_handler_t handler,
+ ply_boot_client_response_handler_t failed_handler,
+ void *user_data);
+
+void ply_boot_client_disconnect (ply_boot_client_t *client);
+void ply_boot_client_attach_to_event_loop (ply_boot_client_t *client,
+ ply_event_loop_t *loop);
+
+#endif
+
+#endif /* PLY_BOOT_CLIENT_H */
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
diff --git a/src/ply-boot-server.c b/src/ply-boot-server.c
new file mode 100644
index 0000000..f1dc4d2
--- /dev/null
+++ b/src/ply-boot-server.c
@@ -0,0 +1,255 @@
+/* ply-boot-server.c - listens for and processes boot-status events
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-boot-server.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "ply-event-loop.h"
+#include "ply-list.h"
+#include "ply-logger.h"
+#include "ply-utils.h"
+
+typedef struct
+{
+ int fd;
+ ply_fd_watch_t *watch;
+ ply_boot_server_t *server;
+} ply_boot_connection_t;
+
+struct _ply_boot_server
+{
+ ply_event_loop_t *loop;
+ ply_list_t *connections;
+ int socket_fd;
+
+ uint32_t is_listening : 1;
+};
+
+ply_boot_server_t *
+ply_boot_server_new (void)
+{
+ ply_boot_server_t *server;
+
+ server = calloc (1, sizeof (ply_boot_server_t));
+ server->connections = ply_list_new ();
+ server->loop = NULL;
+ server->is_listening = false;
+
+ return server;
+}
+
+void
+ply_boot_server_free (ply_boot_server_t *server)
+{
+ if (server == NULL)
+ return;
+
+ ply_list_free (server->connections);
+ free (server);
+}
+
+static ply_boot_connection_t *
+ply_boot_connection_new (ply_boot_server_t *server,
+ int fd)
+{
+ ply_boot_connection_t *connection;
+
+ connection = calloc (1, sizeof (ply_boot_server_t));
+ connection->fd = fd;
+ connection->server = server;
+ connection->watch = NULL;
+
+ return connection;
+}
+
+static void
+ply_boot_connection_free (ply_boot_connection_t *connection)
+{
+ if (connection == NULL)
+ return;
+
+ close (connection->fd);
+ free (connection);
+}
+
+bool
+ply_boot_server_listen (ply_boot_server_t *server)
+{
+ assert (server != NULL);
+
+ server->socket_fd =
+ ply_listen_to_unix_socket (PLY_BOOT_PROTOCOL_SOCKET_PATH, true);
+
+ if (server->socket_fd < 0)
+ return false;
+
+ return true;
+}
+
+void
+ply_boot_server_stop_listening (ply_boot_server_t *server)
+{
+ assert (server != NULL);
+}
+
+static void
+ply_boot_connection_on_request (ply_boot_connection_t *connection)
+{
+ uint8_t byte;
+
+ assert (connection != NULL);
+ assert (connection->fd >= 0);
+
+ if (read (connection->fd, &byte, sizeof (byte)) != 1)
+ return;
+
+ ply_write (connection->fd,
+ PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK,
+ strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK));
+}
+
+static void
+ply_boot_connection_on_hangup (ply_boot_connection_t *connection)
+{
+ ply_list_node_t *node;
+ ply_boot_server_t *server;
+
+ assert (connection != NULL);
+ assert (connection->server != NULL);
+
+ server = connection->server;
+
+ node = ply_list_find_node (server->connections, connection);
+
+ assert (node != NULL);
+
+ ply_boot_connection_free (connection);
+ ply_list_remove_node (server->connections, node);
+}
+
+static void
+ply_boot_server_on_new_connection (ply_boot_server_t *server)
+{
+ ply_boot_connection_t *connection;
+ int fd;
+
+ assert (server != NULL);
+
+ fd = accept (server->socket_fd, NULL, NULL);
+
+ if (fd < 0)
+ return;
+
+ connection = ply_boot_connection_new (server, fd);
+
+ connection->watch =
+ ply_event_loop_watch_fd (server->loop, fd,
+ PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
+ (ply_event_handler_t)
+ ply_boot_connection_on_request,
+ (ply_event_handler_t)
+ ply_boot_connection_on_hangup,
+ connection);
+
+ ply_list_append_data (server->connections, connection);
+}
+
+static void
+ply_boot_server_on_hangup (ply_boot_server_t *server)
+{
+ assert (server != NULL);
+}
+
+static void
+ply_boot_server_detach_from_event_loop (ply_boot_server_t *server)
+{
+ assert (server != NULL);
+ server->loop = NULL;
+}
+
+void
+ply_boot_server_attach_to_event_loop (ply_boot_server_t *server,
+ ply_event_loop_t *loop)
+{
+ assert (server != NULL);
+ assert (loop != NULL);
+ assert (server->loop == NULL);
+ assert (server->socket_fd >= 0);
+
+ server->loop = loop;
+
+ ply_event_loop_watch_fd (loop, server->socket_fd,
+ PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
+ (ply_event_handler_t)
+ ply_boot_server_on_new_connection,
+ (ply_event_handler_t)
+ ply_boot_server_on_hangup,
+ server);
+ ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
+ ply_boot_server_detach_from_event_loop,
+ server);
+}
+
+#ifdef PLY_BOOT_SERVER_ENABLE_TEST
+
+#include <stdio.h>
+
+#include "ply-event-loop.h"
+#include "ply-boot-server.h"
+
+int
+main (int argc,
+ char **argv)
+{
+ ply_event_loop_t *loop;
+ ply_boot_server_t *server;
+ int exit_code;
+
+ exit_code = 0;
+
+ loop = ply_event_loop_new ();
+
+ server = ply_boot_server_new ();
+
+ if (!ply_boot_server_listen (server))
+ {
+ perror ("could not start boot status daemon");
+ return errno;
+ }
+
+ ply_boot_server_attach_to_event_loop (server, loop);
+ exit_code = ply_event_loop_run (loop);
+
+ ply_boot_server_free (server);
+
+ return exit_code;
+}
+
+#endif /* PLY_BOOT_SERVER_ENABLE_TEST */
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
diff --git a/src/ply-boot-server.h b/src/ply-boot-server.h
new file mode 100644
index 0000000..2fdbd32
--- /dev/null
+++ b/src/ply-boot-server.h
@@ -0,0 +1,46 @@
+/* ply-boot-server.h - APIs for talking to the boot status daemon
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written By: Ray Strode <rstrode@redhat.com>
+ */
+#ifndef PLY_BOOT_SERVER_H
+#define PLY_BOOT_SERVER_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "ply-boot-protocol.h"
+#include "ply-event-loop.h"
+
+typedef struct _ply_boot_server ply_boot_server_t;
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+ply_boot_server_t *ply_boot_server_new (void);
+
+void ply_boot_server_free (ply_boot_server_t *server);
+bool ply_boot_server_listen (ply_boot_server_t *server);
+void ply_boot_server_stop_listening (ply_boot_server_t *server);
+void ply_boot_server_attach_to_event_loop (ply_boot_server_t *server,
+ ply_event_loop_t *loop);
+
+#endif
+
+#endif /* PLY_BOOT_SERVER_H */
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index e4d7773..6fa2e10 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -13,5 +13,6 @@ include $(srcdir)/ply-logger-test.am
include $(srcdir)/ply-list-test.am
include $(srcdir)/ply-event-loop-test.am
include $(srcdir)/ply-boot-client-test.am
+include $(srcdir)/ply-boot-server-test.am
noinst_PROGRAMS = $(TESTS)