Commit 49452f5e authored by Jeremy White's avatar Jeremy White

Add the ability to specify connect and disconnect callbacks.

These scripts enable a user to do some action (such as changing
screen background color) upon connect and disconnect.
parent 7241128b
......@@ -59,6 +59,7 @@ int main(int argc, char *argv[])
int display_opened = 0;
int spice_started = 0;
int gui_created = 0;
int session_created = 0;
int session_started = 0;
/*------------------------------------------------------------------------
......@@ -81,6 +82,7 @@ int main(int argc, char *argv[])
rc = session_create(&session);
if (rc)
goto exit;
session_created = 1;
/*------------------------------------------------------------------------
** Open the display
......@@ -148,6 +150,9 @@ exit:
if (display_opened)
display_close(&session.display);
if (session_created)
session_destroy(&session);
options_free(&session.options);
return rc;
......
......@@ -60,6 +60,10 @@ void options_free(options_t *options)
options->virtio_path = NULL;
g_free(options->uinput_path);
options->uinput_path = NULL;
g_free(options->on_connect);
options->on_connect = NULL;
g_free(options->on_disconnect);
options->on_disconnect = NULL;
if (options->listen)
free(options->listen);
......@@ -369,6 +373,8 @@ void options_from_config(options_t *options)
options->exit_on_disconnect = bool_option(userkey, systemkey, "spice", "exit-on-disconnect");
options->virtio_path = string_option(userkey, systemkey, "spice", "virtio-path");
options->uinput_path = string_option(userkey, systemkey, "spice", "uinput-path");
options->on_connect = string_option(userkey, systemkey, "spice", "on-connect");
options->on_disconnect = string_option(userkey, systemkey, "spice", "on-disconnect");
options_handle_ssl_file_options(options, userkey, systemkey);
......
......@@ -58,6 +58,8 @@ typedef struct {
int exit_on_disconnect;
char *virtio_path;
char *uinput_path;
char *on_connect;
char *on_disconnect;
/* file names of config files */
char *user_config_file;
......
......@@ -36,6 +36,9 @@
#include <xcb/xcb_aux.h>
#include <xcb/xkb.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "x11spice.h"
#include "session.h"
#include "scan.h"
......@@ -185,11 +188,18 @@ void session_handle_mouse_buttons(session_t *session, uint32_t buttons_state)
session_handle_button_change(session, convert_spice_buttons(0, buttons_state));
}
static void cleanup_process(int pid)
{
if (waitpid(pid, NULL, WNOHANG) == pid)
return;
killpg(pid, SIGKILL);
}
int session_start(session_t *s)
{
int rc = 0;
s->running = FALSE;
s->spice.session = s;
s->display.session = s;
s->scanner.session = s;
......@@ -226,6 +236,7 @@ static void flush_and_lock(session_t *s)
void session_end(session_t *s)
{
session_remote_disconnected();
s->running = 0;
global_session = NULL;
......@@ -235,6 +246,29 @@ void session_end(session_t *s)
display_destroy_screen_images(&s->display);
}
int session_create(session_t *s)
{
int rc = 0;
#if ! GLIB_CHECK_VERSION(2, 32, 0)
g_thread_init(NULL);
#endif
s->cursor_queue = g_async_queue_new_full(free_cursor_queue_item);
s->draw_queue = g_async_queue_new_full(free_draw_queue_item);
s->lock = g_mutex_new();
s->connected = FALSE;
s->connect_pid = 0;
s->disconnect_pid = 0;
return rc;
}
void session_destroy(session_t *s)
{
flush_and_lock(s);
if (s->cursor_queue)
......@@ -248,19 +282,13 @@ void session_end(session_t *s)
g_mutex_free(s->lock);
s->lock = NULL;
}
int session_create(session_t *s)
{
#if ! GLIB_CHECK_VERSION(2, 32, 0)
g_thread_init(NULL);
#endif
s->cursor_queue = g_async_queue_new_full(free_cursor_queue_item);
s->draw_queue = g_async_queue_new_full(free_draw_queue_item);
s->lock = g_mutex_new();
if (s->connect_pid)
cleanup_process(s->connect_pid);
s->connect_pid = 0;
return 0;
if (s->disconnect_pid)
cleanup_process(s->disconnect_pid);
s->disconnect_pid = 0;
}
/* Important note - this is meant to be called from
......@@ -388,16 +416,71 @@ void session_disconnect_client(session_t *session)
spice_server_set_noauth(session->spice.server);
}
static void invoke_on_connect(session_t *session, const char *from)
{
if (session->connect_pid)
cleanup_process(session->connect_pid);
session->connect_pid = fork();
if (session->connect_pid == 0)
{
/* TODO: If would be nice to either close the spice socket after
the fork, or to get CLOEXEC set on the socket after open. */
setsid();
execl(session->options.on_connect, session->options.on_connect, from, NULL);
g_error("Exec of connect command [%s %s] failed", session->options.on_connect, from);
exit(-1);
}
}
static void invoke_on_disconnect(session_t *session)
{
if (session->connect_pid)
cleanup_process(session->connect_pid);
session->connect_pid = 0;
if (session->disconnect_pid)
cleanup_process(session->disconnect_pid);
session->disconnect_pid = fork();
if (session->disconnect_pid == 0)
{
/* TODO: If would be nice to either close the spice socket after
the fork, or to get CLOEXEC set on the socket after open. */
setsid();
execl(session->options.on_disconnect, session->options.on_disconnect, NULL);
g_error("Exec of disconnect command [%s] failed", session->options.on_disconnect);
exit(-1);
}
}
void session_remote_connected(const char *from)
{
if (!global_session)
#define GUI_FROM_PREFIX "Connection from "
char *from_string;
if (!global_session || global_session->connected)
return;
gui_remote_connected(&global_session->gui, from);
global_session->connected = TRUE;
from_string = calloc(1, strlen(from) + strlen(GUI_FROM_PREFIX) + 1);
if (from_string)
{
strcpy(from_string, GUI_FROM_PREFIX);
strcat(from_string, from);
gui_remote_connected(&global_session->gui, from_string);
free(from_string);
}
if (global_session->options.on_connect)
invoke_on_connect(global_session, from);
}
void session_remote_disconnected(void)
{
if (!global_session)
if (!global_session || !global_session->connected)
return;
global_session->connected = FALSE;
if (global_session->options.on_disconnect)
invoke_on_disconnect(global_session);
gui_remote_disconnected(&global_session->gui);
}
......@@ -40,6 +40,10 @@ typedef struct session_struct {
scanner_t scanner;
int running;
int connected;
int connect_pid;
int disconnect_pid;
GMutex *lock;
int draw_command_in_progress;
......@@ -51,6 +55,7 @@ typedef struct session_struct {
** Prototypes
**--------------------------------------------------------------------------*/
int session_create(session_t *s);
void session_destroy(session_t *s);
int session_start(session_t *s);
void session_end(session_t *s);
int session_alive(session_t *s);
......
......@@ -176,7 +176,7 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
event, info->connection_id, info->type, info->id, info->flags);
if (event == SPICE_CHANNEL_EVENT_INITIALIZED && info->type == SPICE_CHANNEL_MAIN) {
char from[NI_MAXHOST + NI_MAXSERV + 128];
strcpy(from, "Remote computer");
strcpy(from, "Remote");
if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
int rc;
char host[NI_MAXHOST];
......@@ -184,7 +184,7 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
rc = getnameinfo((struct sockaddr *) &info->paddr_ext, info->plen_ext, host,
sizeof(host), server, sizeof(server), 0);
if (rc == 0)
snprintf(from, sizeof(from), "Connection from %s:%s", host, server);
snprintf(from, sizeof(from), "%s:%s", host, server);
}
session_remote_connected(from);
}
......
......@@ -43,6 +43,19 @@
#virtio-path=/tmp/xspice-virtio
#uinput-path=/tmp/xspice-uinput
#-----------------------------------------------------------------------------
# Connection callback support
# on_connect Path to an program to be invoked upon connection
# The address information of the connecotr is passed as the first arg.
# on_disconnect Path to a program to be invoked upon disconnect. No args.
#
# *IMPORTANT* - these callbacks can hang up the main spice server process.
# Make sure that they are atomic, process quickly, and cannot linger.
#
#-----------------------------------------------------------------------------
#on-connect=/usr/bin/connect_x11spice
#on-disconnect=/usr/bin/disconnect_x11spice
#-----------------------------------------------------------------------------
# allow-control If set to true, indicates that a remote client is permitted to
# move the mouse or enter keystrokes. Default false.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment