2013-09-11 14:08:08 +04:00
/*
Copyright ( C ) 2013 Proxmox Server Solutions GmbH
Copyright : spiceterm is under GNU GPL , the GNU General Public License .
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 ; version 2 dated June , 1991.
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 .
Author : Dietmar Maurer < dietmar @ proxmox . com >
*/
2013-08-05 11:26:20 +04:00
# include <stdlib.h>
# include <stdio.h>
# include <sys/time.h>
# include <signal.h>
# include <string.h>
# include <glib.h>
# include <spice/macros.h>
2013-09-11 13:57:01 +04:00
# include "event_loop.h"
2013-08-05 11:26:20 +04:00
2013-09-11 14:56:28 +04:00
static int debug = 0 ;
2013-09-10 13:57:19 +04:00
2013-08-05 11:26:20 +04:00
# define DPRINTF(x, format, ...) { \
if ( x < = debug ) { \
printf ( " %s: " format " \n " , __FUNCTION__ , # # __VA_ARGS__ ) ; \
} \
}
2013-09-10 13:57:19 +04:00
static GMainLoop * main_loop ;
2013-08-05 11:26:20 +04:00
static SpiceCoreInterface core ;
typedef struct SpiceTimer {
2013-09-10 13:57:19 +04:00
GSource * source ;
2013-08-05 11:26:20 +04:00
SpiceTimerFunc func ;
int ms ;
void * opaque ;
} Timer ;
static SpiceTimer * timer_add ( SpiceTimerFunc func , void * opaque )
{
2013-09-10 13:57:19 +04:00
g_return_val_if_fail ( func ! = NULL , NULL ) ;
2013-08-05 12:07:05 +04:00
SpiceTimer * timer = g_new0 ( SpiceTimer , 1 ) ;
2013-08-05 11:26:20 +04:00
timer - > func = func ;
timer - > opaque = opaque ;
2013-09-10 13:57:19 +04:00
2013-08-05 11:26:20 +04:00
return timer ;
}
2013-09-10 13:57:19 +04:00
static gboolean timer_callback ( gpointer data )
2013-08-05 11:26:20 +04:00
{
2013-09-10 13:57:19 +04:00
SpiceTimer * timer = ( SpiceTimer * ) data ;
g_assert ( timer ! = NULL ) ;
g_assert ( timer - > func ! = NULL ) ;
timer - > func ( timer - > opaque ) ;
return FALSE ;
2013-08-05 11:26:20 +04:00
}
static void timer_start ( SpiceTimer * timer , uint32_t ms )
{
2013-09-10 13:57:19 +04:00
g_return_if_fail ( timer ! = NULL ) ;
g_return_if_fail ( ms ! = 0 ) ;
if ( timer - > source ! = NULL ) {
g_source_destroy ( timer - > source ) ;
}
timer - > source = g_timeout_source_new ( ms ) ;
g_assert ( timer - > source ! = NULL ) ;
g_source_set_callback ( timer - > source , timer_callback , timer , NULL ) ;
g_source_attach ( timer - > source , NULL ) ;
2013-08-05 11:26:20 +04:00
}
static void timer_cancel ( SpiceTimer * timer )
{
2013-09-10 13:57:19 +04:00
g_return_if_fail ( timer ! = NULL ) ;
if ( timer - > source ! = NULL ) {
g_source_destroy ( timer - > source ) ;
timer - > source = NULL ;
}
2013-08-05 11:26:20 +04:00
timer - > ms = 0 ;
}
static void timer_remove ( SpiceTimer * timer )
{
2013-09-10 13:57:19 +04:00
g_return_if_fail ( timer ! = NULL ) ;
timer_cancel ( timer ) ;
g_free ( timer ) ;
2013-08-05 11:26:20 +04:00
}
struct SpiceWatch {
2013-09-10 13:57:19 +04:00
GIOChannel * channel ;
guint evid ;
2013-08-05 11:26:20 +04:00
int fd ;
int event_mask ;
SpiceWatchFunc func ;
void * opaque ;
} ;
2013-09-10 13:57:19 +04:00
static gboolean watch_callback ( GIOChannel * source , GIOCondition condition , gpointer data )
{
SpiceWatch * watch = ( SpiceWatch * ) data ;
g_assert ( watch ! = NULL ) ;
g_assert ( watch - > func ! = NULL ) ;
if ( condition & G_IO_OUT ) {
watch - > func ( watch - > fd , SPICE_WATCH_EVENT_WRITE , watch - > opaque ) ;
}
if ( condition & G_IO_IN ) {
watch - > func ( watch - > fd , SPICE_WATCH_EVENT_READ , watch - > opaque ) ;
}
return TRUE ;
}
static GIOCondition event_mask_to_condition ( int event_mask )
{
GIOCondition condition = 0 ;
if ( event_mask & SPICE_WATCH_EVENT_READ ) {
condition | = G_IO_IN ;
}
if ( event_mask & SPICE_WATCH_EVENT_WRITE ) {
condition | = G_IO_OUT ;
}
2013-08-05 11:26:20 +04:00
2013-09-10 13:57:19 +04:00
return condition ;
}
2013-08-05 11:26:20 +04:00
static SpiceWatch * watch_add ( int fd , int event_mask , SpiceWatchFunc func , void * opaque )
{
2013-08-05 12:07:05 +04:00
SpiceWatch * watch = g_new0 ( SpiceWatch , 1 ) ;
2013-08-05 11:26:20 +04:00
2013-09-11 14:56:28 +04:00
DPRINTF ( 1 , " adding %p, fd=%d " , watch , fd ) ;
2013-09-10 13:57:19 +04:00
2013-08-05 11:26:20 +04:00
watch - > fd = fd ;
watch - > event_mask = event_mask ;
watch - > func = func ;
watch - > opaque = opaque ;
2013-09-10 13:57:19 +04:00
watch - > channel = g_io_channel_unix_new ( fd ) ;
g_assert ( watch - > channel ! = NULL ) ;
g_io_channel_set_encoding ( watch - > channel , NULL , NULL ) ;
GIOCondition condition = event_mask_to_condition ( event_mask ) ;
watch - > evid = g_io_add_watch ( watch - > channel , condition , watch_callback , watch ) ;
2013-08-05 11:26:20 +04:00
return watch ;
}
static void watch_update_mask ( SpiceWatch * watch , int event_mask )
{
2013-09-10 13:57:19 +04:00
g_assert ( watch ! = NULL ) ;
2013-09-11 14:56:28 +04:00
DPRINTF ( 1 , " fd %d to %d " , watch - > fd , event_mask ) ;
2013-09-10 13:57:19 +04:00
2013-08-05 11:26:20 +04:00
watch - > event_mask = event_mask ;
2013-09-10 13:57:19 +04:00
g_source_remove ( watch - > evid ) ;
2013-08-05 11:26:20 +04:00
2013-09-10 13:57:19 +04:00
GIOCondition condition = event_mask_to_condition ( event_mask ) ;
watch - > evid = g_io_add_watch ( watch - > channel , condition , watch_callback , watch ) ;
2013-08-05 11:26:20 +04:00
}
2013-09-10 13:57:19 +04:00
static void watch_remove ( SpiceWatch * watch )
2013-08-05 11:26:20 +04:00
{
2013-09-10 13:57:19 +04:00
g_assert ( watch ! = NULL ) ;
2013-08-05 11:26:20 +04:00
2013-09-11 14:56:28 +04:00
DPRINTF ( 1 , " remove %p (fd %d) " , watch , watch - > fd ) ;
2013-08-05 11:26:20 +04:00
2013-09-10 13:57:19 +04:00
g_source_remove ( watch - > evid ) ;
g_io_channel_unref ( watch - > channel ) ;
2013-08-05 11:26:20 +04:00
2013-09-10 13:57:19 +04:00
g_free ( watch ) ;
2013-08-05 11:26:20 +04:00
}
2013-09-10 13:57:19 +04:00
static void channel_event ( int event , SpiceChannelEventInfo * info )
2013-08-05 11:26:20 +04:00
{
2013-09-11 14:56:28 +04:00
DPRINTF ( 1 , " channel event con, type, id, event: %d, %d, %d, %d " ,
2013-09-10 13:57:19 +04:00
info - > connection_id , info - > type , info - > id , event ) ;
2013-08-05 11:26:20 +04:00
}
void basic_event_loop_mainloop ( void )
{
2013-09-10 13:57:19 +04:00
g_main_loop_run ( main_loop ) ;
2013-08-05 11:26:20 +04:00
}
static void ignore_sigpipe ( void )
{
struct sigaction act ;
memset ( & act , 0 , sizeof ( act ) ) ;
sigfillset ( & act . sa_mask ) ;
act . sa_handler = SIG_IGN ;
sigaction ( SIGPIPE , & act , NULL ) ;
}
SpiceCoreInterface * basic_event_loop_init ( void )
{
2013-09-10 13:57:19 +04:00
main_loop = g_main_loop_new ( NULL , FALSE ) ;
2013-08-05 11:26:20 +04:00
memset ( & core , 0 , sizeof ( core ) ) ;
core . base . major_version = SPICE_INTERFACE_CORE_MAJOR ;
2013-09-10 13:57:19 +04:00
core . base . minor_version = SPICE_INTERFACE_CORE_MINOR ;
2013-08-05 11:26:20 +04:00
core . timer_add = timer_add ;
core . timer_start = timer_start ;
core . timer_cancel = timer_cancel ;
core . timer_remove = timer_remove ;
core . watch_add = watch_add ;
core . watch_update_mask = watch_update_mask ;
core . watch_remove = watch_remove ;
core . channel_event = channel_event ;
2013-09-10 13:57:19 +04:00
2013-08-05 11:26:20 +04:00
ignore_sigpipe ( ) ;
2013-09-10 13:57:19 +04:00
2013-08-05 11:26:20 +04:00
return & core ;
}