/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
Copyright (C) 2012 Red Hat, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see .
*/
#include
#include
#include "spice-controller-listener.h"
#ifdef G_OS_WIN32
#include
#include "namedpipe.h"
#include "namedpipelistener.h"
#include "win32-util.h"
#endif
#ifdef G_OS_UNIX
#include
#endif
/**
* SpiceControllerListenerError:
* @SPICE_CONTROLLER_LISTENER_ERROR_VALUE: invalid value.
*
* Possible errors of controller listener related functions.
**/
/**
* SPICE_CONTROLLER_LISTENER_ERROR:
*
* The error domain of the controller listener subsystem.
**/
GQuark
spice_controller_listener_error_quark (void)
{
return g_quark_from_static_string ("spice-controller-listener-error");
}
GObject*
spice_controller_listener_new (const gchar *address, GError **error)
{
GObject *listener = NULL;
gchar *addr = NULL;
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
addr = g_strdup (address);
#ifdef G_OS_WIN32
if (addr == NULL)
addr = g_strdup (g_getenv ("SPICE_XPI_NAMEDPIPE"));
if (addr == NULL)
addr = g_strdup_printf ("\\\\.\\pipe\\SpiceController-%" G_GUINT64_FORMAT, (guint64)GetCurrentProcessId ());
#else
if (addr == NULL)
addr = g_strdup (g_getenv ("SPICE_XPI_SOCKET"));
#endif
if (addr == NULL) {
g_set_error (error,
SPICE_CONTROLLER_LISTENER_ERROR,
SPICE_CONTROLLER_LISTENER_ERROR_VALUE,
#ifdef G_OS_WIN32
"Missing namedpipe address"
#else
"Missing socket address"
#endif
);
goto end;
}
g_unlink (addr);
#ifdef G_OS_WIN32
{
SpiceNamedPipe *np;
listener = G_OBJECT (spice_named_pipe_listener_new ());
np = spice_win32_user_pipe_new (addr, error);
if (!np) {
g_object_unref (listener);
listener = NULL;
goto end;
}
spice_named_pipe_listener_add_named_pipe (SPICE_NAMED_PIPE_LISTENER (listener), np);
}
#else
{
listener = G_OBJECT (g_socket_listener_new ());
if (!g_socket_listener_add_address (G_SOCKET_LISTENER (listener),
G_SOCKET_ADDRESS (g_unix_socket_address_new (addr)),
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT,
NULL,
NULL,
error))
g_warning ("failed to add address");
}
#endif
end:
g_free (addr);
return listener;
}
void
spice_controller_listener_accept_async (GObject *listener,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail(G_IS_OBJECT(listener));
#ifdef G_OS_WIN32
spice_named_pipe_listener_accept_async (SPICE_NAMED_PIPE_LISTENER (listener), cancellable, callback, user_data);
#else
g_socket_listener_accept_async (G_SOCKET_LISTENER (listener), cancellable, callback, user_data);
#endif
}
GIOStream*
spice_controller_listener_accept_finish (GObject *listener,
GAsyncResult *result,
GObject **source_object,
GError **error)
{
g_return_val_if_fail(G_IS_OBJECT(listener), NULL);
#ifdef G_OS_WIN32
SpiceNamedPipeConnection *np;
np = spice_named_pipe_listener_accept_finish (SPICE_NAMED_PIPE_LISTENER (listener), result, source_object, error);
if (np)
return G_IO_STREAM (np);
#else
GSocketConnection *socket;
socket = g_socket_listener_accept_finish (G_SOCKET_LISTENER (listener), result, source_object, error);
if (socket)
return G_IO_STREAM (socket);
#endif
return NULL;
}