From 81945d89710d9b03d829ebd4f040b0e8f3f2b507 Mon Sep 17 00:00:00 2001 From: Yaniv Kamay Date: Wed, 6 Jan 2010 19:03:25 +0200 Subject: server: add new vd interface QTerm2Interface --- server/reds.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++++- server/vd_interface.h | 50 +++++++++++ 2 files changed, 291 insertions(+), 1 deletion(-) (limited to 'server') diff --git a/server/reds.c b/server/reds.c index 2bb707bb..8a2700c6 100644 --- a/server/reds.c +++ b/server/reds.c @@ -378,6 +378,21 @@ void (*log_proc)(CoreInterface *core, LogLevel level, const char* component, } \ } +static int args_is_empty(const VDICmdArg* args) +{ + return !args || args[0].descriptor.type == ARG_TYPE_INVALID; +} + +const int args_is_string(const VDICmdArg* args) +{ + return !args_is_empty(args) && args->descriptor.type == ARG_TYPE_STRING; +} + +const int args_is_int(const VDICmdArg* args) +{ + return !args_is_empty(args) && args->descriptor.type == ARG_TYPE_INT; +} + static ChannelSecurityOptions *find_channel_security(int id) { ChannelSecurityOptions *now = channels_security; @@ -505,6 +520,16 @@ static void reds_do_disable_ticketing(void) core->term_printf(core, "Ticketing is now disabled.\n"); } +static void reds_do_disable_ticketing_2(const VDICmdArg* args) +{ + if (!args_is_empty(args)) { + red_printf("invalid args"); + return; + } + + reds_do_disable_ticketing(); +} + static char *base64decode(const char *input, int length) { BIO *b64; @@ -629,6 +654,16 @@ static void do_reset_statistics() } } +static void do_reset_statistics_2(const VDICmdArg* args) +{ + if (!args_is_empty(args)) { + red_printf("invalid args"); + return; + } + + do_reset_statistics(); +} + void insert_stat_node(StatNodeRef parent, StatNodeRef ref) { StatNode *node = &reds->stat->nodes[ref]; @@ -1153,6 +1188,31 @@ static void do_ping_client(const char *opt, int has_interval, int interval) } } +static void do_ping_client_2(const VDICmdArg* args) +{ + if (args_is_empty(args)) { + do_ping_client(NULL, FALSE, 0); + return; + } + + if (!args_is_string(args)) { + red_printf("invalid args"); + return; + } + + if (args_is_empty(&args[1])) { + do_ping_client(args[0].string_val, FALSE, 0); + return; + } + + if (!args_is_int(&args[1])) { + red_printf("invalid args"); + return; + } + + do_ping_client(args[0].string_val, TRUE, args[1].int_val); +} + static void ping_timer_cb() { if (!reds->peer) { @@ -3440,6 +3500,26 @@ error: free(local_args); } +static void reds_do_set_ticket_2(const VDICmdArg *args) +{ + const char *arg2 = NULL; + + if (!args_is_string(args)) { + red_printf("invalid args"); + return; + } + + if (!args_is_empty(&args[1])) { + if (!args_is_string(&args[1])) { + red_printf("invalid args"); + return; + } + arg2 = args[1].string_val; + } + + reds_do_set_ticket(args[0].string_val, arg2); +} + static void reds_do_set_ticket64(const char *password64, const char *args) { char *password; @@ -3459,6 +3539,26 @@ static void reds_do_set_ticket64(const char *password64, const char *args) free(password); } +static void reds_do_set_ticket64_2(const VDICmdArg *args) +{ + const char *arg2 = NULL; + + if (!args_is_string(args)) { + red_printf("invalid args"); + return; + } + + if (!args_is_empty(&args[1])) { + if (!args_is_string(&args[1])) { + red_printf("invalid args"); + return; + } + arg2 = args[1].string_val; + } + + reds_do_set_ticket64(args[0].string_val, arg2); +} + static void reds_do_info_spice() { core->term_printf(core, "spice info:"); @@ -3554,6 +3654,16 @@ static void reds_do_set_image_compression(const char *val) set_image_compression(real_val); } +static void reds_do_set_image_compression_2(const VDICmdArg *args) +{ + if (!args_is_string(args)) { + red_printf("invalid args"); + return; + } + + reds_do_set_image_compression(args[0].string_val); +} + static int reds_get_streaming_video(const char *val) { if (strcmp(val, "on") == 0) { @@ -3584,6 +3694,16 @@ static void reds_do_set_streaming_video(const char *val) red_dispatcher_on_sv_change(); } +static void reds_do_set_streaming_video_2(const VDICmdArg *args) +{ + if (!args_is_string(args)) { + red_printf("invalid args"); + return; + } + + reds_do_set_streaming_video(args[0].string_val); +} + static void reds_do_set_agent_mouse(const char *val) { int new_val; @@ -3602,6 +3722,16 @@ static void reds_do_set_agent_mouse(const char *val) reds_update_mouse_mode(); } +static void reds_do_set_agent_mouse_2(const VDICmdArg *args) +{ + if (!args_is_string(args)) { + red_printf("invalid args"); + return; + } + + reds_do_set_agent_mouse(args[0].string_val); +} + static void reds_do_set_playback_compression(const char *val) { int on; @@ -3616,6 +3746,16 @@ static void reds_do_set_playback_compression(const char *val) snd_set_playback_compression(on); } +static void reds_do_set_playback_compression_2(const VDICmdArg *args) +{ + if (!args_is_string(args)) { + red_printf("invalid args"); + return; + } + + reds_do_set_playback_compression(args[0].string_val); +} + static OptionsMap _spice_options[] = { {"port", SPICE_OPTION_PORT}, {"sport", SPICE_OPTION_SPORT}, @@ -4625,7 +4765,7 @@ static void add_monitor_action_commands(QTermInterface *mon) mon->add_action_command_handler(mon, "spice", "set_ticket64", "ss?", reds_do_set_ticket64, " [expiration=]" - " [,connected=keep|disconnect|fail]", + "[,connected=keep|disconnect|fail]", "set the spice connection ticket"); mon->add_action_command_handler(mon, "spice", "disable_ticketing", "", reds_do_disable_ticketing, @@ -4647,6 +4787,74 @@ static void add_monitor_action_commands(QTermInterface *mon) #endif } +static void add_monitor_action_commands_2(QTerm2Interface *mon) +{ + VDIArgDescriptor s[] = { + { "arg1", ARG_TYPE_STRING, FALSE}, + { NULL, 0, 0}, + }; + + VDIArgDescriptor empty[] = { + { NULL, 0, 0} + }; + + VDIArgDescriptor s_s_o[] = { + { "arg1", ARG_TYPE_STRING, FALSE}, + { "arg2", ARG_TYPE_STRING, TRUE}, + { NULL, 0, 0} + }; + + VDIArgDescriptor s_o_i_o[] = { + { "arg1", ARG_TYPE_STRING, TRUE}, + { "arg2", ARG_TYPE_INT, TRUE}, + { NULL, 0, 0} + }; + + mon->add_action_command_handler(mon, "spice", "set_image_compression", s, + reds_do_set_image_compression_2, + "<[on|auto_glz|auto_lz|quic|glz|lz|off]>", + ""); + + mon->add_action_command_handler(mon, "spice", "set_streaming_video", s, + reds_do_set_streaming_video_2, + "", + ""); + + mon->add_action_command_handler(mon, "spice", "set_playback_compression", s, + reds_do_set_playback_compression_2, + "", + ""); + + mon->add_action_command_handler(mon, "spice", "set_ticket", s_s_o, + reds_do_set_ticket_2, + " [expiration=]" + "[,connected=keep|disconnect|fail]", + "set the spice connection ticket"); + mon->add_action_command_handler(mon, "spice", "set_ticket64", s_s_o, + reds_do_set_ticket64_2, + " [expiration=]" + "[,connected=keep|disconnect|fail]", + "set the spice connection ticket"); + mon->add_action_command_handler(mon, "spice", "disable_ticketing", empty, + reds_do_disable_ticketing_2, + "", + "entirely disables OTP"); + mon->add_action_command_handler(mon, "spice", "set_agent_mouse", s, + reds_do_set_agent_mouse_2, + "", + ""); +#ifdef RED_STATISTICS + mon->add_action_command_handler(mon, "spice", "reset_stat", empty, + do_reset_statistics_2, + "", + "reset spice statistics"); + mon->add_action_command_handler(mon, "spice", "ping_client", s_o_i_o, + do_ping_client_2, + "[on [interval]|off]", + "ping spice client to measure roundtrip"); +#endif +} + static void add_monitor_info_commands(QTermInterface *mon) { mon->add_info_command_handler(mon, "spice", "state", @@ -4665,6 +4873,24 @@ static void add_monitor_info_commands(QTermInterface *mon) #endif } +static void add_monitor_info_commands_2(QTerm2Interface *mon) +{ + mon->add_info_command_handler(mon, "spice", "state", + reds_do_info_spice, + "show spice state"); + mon->add_info_command_handler(mon, "spice", "ticket", + reds_do_info_ticket, + "show ticket"); +#ifdef RED_STATISTICS + mon->add_info_command_handler(mon, "spice", "stat", + do_info_statistics, + "show spice statistics"); + mon->add_info_command_handler(mon, "spice", "rtt_client", + do_info_rtt_client, + "show rtt to spice client"); +#endif +} + static void attach_to_red_agent(VDIPortInterface *interface) { VDIPortState *state = &reds->agent_state; @@ -4763,6 +4989,20 @@ static void interface_change_notifier(void *opaque, VDInterface *interface, } add_monitor_action_commands((QTermInterface *)interface); add_monitor_info_commands((QTermInterface *)interface); + } else if (strcmp(interface->type, VD_INTERFACE_QTERM2) == 0) { + static int was_here = FALSE; + red_printf("VD_INTERFACE_QTERM2"); + if (was_here) { + return; + } + was_here = TRUE; + if (interface->major_version != VD_INTERFACE_QTERM2_MAJOR || + interface->minor_version < VD_INTERFACE_QTERM2_MINOR) { + red_printf("unsuported qterm interface"); + return; + } + add_monitor_action_commands_2((QTerm2Interface *)interface); + add_monitor_info_commands_2((QTerm2Interface *)interface); } else if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) { red_printf("VD_INTERFACE_TABLET"); if (tablet) { diff --git a/server/vd_interface.h b/server/vd_interface.h index 7b91d11f..89016dba 100644 --- a/server/vd_interface.h +++ b/server/vd_interface.h @@ -268,6 +268,56 @@ struct QTermInterface { void (*remove_info_command_handler)(QTermInterface *term, VDObjectRef obj); }; +#define VD_INTERFACE_QTERM2 "qemu_terminal_2" +#define VD_INTERFACE_QTERM2_MAJOR 1 +#define VD_INTERFACE_QTERM2_MINOR 0 +typedef struct QTerm2Interface QTerm2Interface; + +enum VDIArgType{ + ARG_TYPE_INVALID, + ARG_TYPE_INT, + ARG_TYPE_STRING, +}; + +typedef struct VDIArgDescriptor { + char* name; + int type; + int optional; +} VDIArgDescriptor; + +typedef struct VDICmdArg { + VDIArgDescriptor descriptor; + union { + uint64_t int_val; + const char *string_val; + }; +} VDICmdArg; + +typedef void (*VDICmdHandler)(const VDICmdArg* args); +typedef void (*VDIInfoCmdHandler)(void); + +struct QTerm2Interface { + VDInterface base; + + VDObjectRef (*add_action_command_handler)(QTerm2Interface *term, + const char *module_name, + const char *command_name, + const VDIArgDescriptor *args_type, + VDICmdHandler handler, + const char *params_text, + const char *help_text); + + void (*remove_action_command_handler)(QTerm2Interface *term, VDObjectRef obj); + + VDObjectRef (*add_info_command_handler)(QTerm2Interface *term, + const char *module_name, + const char *command_name, + VDIInfoCmdHandler handler, + const char *help_text); + + void (*remove_info_command_handler)(QTerm2Interface *term, VDObjectRef obj); +}; + #define VD_INTERFACE_PLAYBACK "playback" #define VD_INTERFACE_PLAYBACK_MAJOR 1 #define VD_INTERFACE_PLAYBACK_MINOR 1 -- cgit