mirror of https://gitee.com/openkylin/qemu.git
Merge remote branch 'spice/config.2' into staging
This commit is contained in:
commit
2d8418ba8a
|
@ -361,12 +361,69 @@ QemuOptsList qemu_spice_opts = {
|
|||
{
|
||||
.name = "port",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
},{
|
||||
.name = "tls-port",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
},{
|
||||
.name = "addr",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "ipv4",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},{
|
||||
.name = "ipv6",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},{
|
||||
.name = "password",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "disable-ticketing",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},{
|
||||
.name = "x509-dir",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "x509-key-file",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "x509-key-password",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "x509-cert-file",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "x509-cacert-file",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "x509-dh-key-file",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "tls-ciphers",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "tls-channel",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "plaintext-channel",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "image-compression",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "jpeg-wan-compression",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "zlib-glz-wan-compression",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "streaming-video",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "agent-mouse",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},{
|
||||
.name = "playback-compression",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},
|
||||
{ /* end if list */ }
|
||||
},
|
||||
|
|
|
@ -680,7 +680,14 @@ Enable the spice remote desktop protocol. Valid options are
|
|||
@table @option
|
||||
|
||||
@item port=<nr>
|
||||
Set the TCP port spice is listening on.
|
||||
Set the TCP port spice is listening on for plaintext channels.
|
||||
|
||||
@item addr=<addr>
|
||||
Set the IP address spice is listening on. Default is any address.
|
||||
|
||||
@item ipv4
|
||||
@item ipv6
|
||||
Force using the specified IP version.
|
||||
|
||||
@item password=<secret>
|
||||
Set the password you need to authenticate.
|
||||
|
@ -688,6 +695,48 @@ Set the password you need to authenticate.
|
|||
@item disable-ticketing
|
||||
Allow client connects without authentication.
|
||||
|
||||
@item tls-port=<nr>
|
||||
Set the TCP port spice is listening on for encrypted channels.
|
||||
|
||||
@item x509-dir=<dir>
|
||||
Set the x509 file directory. Expects same filenames as -vnc $display,x509=$dir
|
||||
|
||||
@item x509-key-file=<file>
|
||||
@item x509-key-password=<file>
|
||||
@item x509-cert-file=<file>
|
||||
@item x509-cacert-file=<file>
|
||||
@item x509-dh-key-file=<file>
|
||||
The x509 file names can also be configured individually.
|
||||
|
||||
@item tls-ciphers=<list>
|
||||
Specify which ciphers to use.
|
||||
|
||||
@item tls-channel=[main|display|inputs|record|playback|tunnel]
|
||||
@item plaintext-channel=[main|display|inputs|record|playback|tunnel]
|
||||
Force specific channel to be used with or without TLS encryption. The
|
||||
options can be specified multiple times to configure multiple
|
||||
channels. The special name "default" can be used to set the default
|
||||
mode. For channels which are not explicitly forced into one mode the
|
||||
spice client is allowed to pick tls/plaintext as he pleases.
|
||||
|
||||
@item image-compression=[auto_glz|auto_lz|quic|glz|lz|off]
|
||||
Configure image compression (lossless).
|
||||
Default is auto_glz.
|
||||
|
||||
@item jpeg-wan-compression=[auto|never|always]
|
||||
@item zlib-glz-wan-compression=[auto|never|always]
|
||||
Configure wan image compression (lossy for slow links).
|
||||
Default is auto.
|
||||
|
||||
@item streaming-video=[off|all|filter]
|
||||
Configure video stream detection. Default is filter.
|
||||
|
||||
@item agent-mouse=[on|off]
|
||||
Enable/disable passing mouse events via vdagent. Default is on.
|
||||
|
||||
@item playback-compression=[on|off]
|
||||
Enable/disable audio stream compression (using celt 0.5.1). Default is on.
|
||||
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
|
|
208
ui/spice-core.c
208
ui/spice-core.c
|
@ -22,6 +22,7 @@
|
|||
#include "qemu-spice.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-x509.h"
|
||||
#include "monitor.h"
|
||||
|
||||
/* core bits */
|
||||
|
@ -136,25 +137,181 @@ static SpiceCoreInterface core_interface = {
|
|||
.watch_remove = watch_remove,
|
||||
};
|
||||
|
||||
/* config string parsing */
|
||||
|
||||
static int name2enum(const char *string, const char *table[], int entries)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (string) {
|
||||
for (i = 0; i < entries; i++) {
|
||||
if (!table[i]) {
|
||||
continue;
|
||||
}
|
||||
if (strcmp(string, table[i]) != 0) {
|
||||
continue;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int parse_name(const char *string, const char *optname,
|
||||
const char *table[], int entries)
|
||||
{
|
||||
int value = name2enum(string, table, entries);
|
||||
|
||||
if (value != -1) {
|
||||
return value;
|
||||
}
|
||||
fprintf(stderr, "spice: invalid %s: %s\n", optname, string);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if SPICE_SERVER_VERSION >= 0x000600 /* 0.6.0 */
|
||||
|
||||
static const char *stream_video_names[] = {
|
||||
[ SPICE_STREAM_VIDEO_OFF ] = "off",
|
||||
[ SPICE_STREAM_VIDEO_ALL ] = "all",
|
||||
[ SPICE_STREAM_VIDEO_FILTER ] = "filter",
|
||||
};
|
||||
#define parse_stream_video(_name) \
|
||||
name2enum(_name, stream_video_names, ARRAY_SIZE(stream_video_names))
|
||||
|
||||
#endif /* >= 0.6.0 */
|
||||
|
||||
static const char *compression_names[] = {
|
||||
[ SPICE_IMAGE_COMPRESS_OFF ] = "off",
|
||||
[ SPICE_IMAGE_COMPRESS_AUTO_GLZ ] = "auto_glz",
|
||||
[ SPICE_IMAGE_COMPRESS_AUTO_LZ ] = "auto_lz",
|
||||
[ SPICE_IMAGE_COMPRESS_QUIC ] = "quic",
|
||||
[ SPICE_IMAGE_COMPRESS_GLZ ] = "glz",
|
||||
[ SPICE_IMAGE_COMPRESS_LZ ] = "lz",
|
||||
};
|
||||
#define parse_compression(_name) \
|
||||
parse_name(_name, "image compression", \
|
||||
compression_names, ARRAY_SIZE(compression_names))
|
||||
|
||||
static const char *wan_compression_names[] = {
|
||||
[ SPICE_WAN_COMPRESSION_AUTO ] = "auto",
|
||||
[ SPICE_WAN_COMPRESSION_NEVER ] = "never",
|
||||
[ SPICE_WAN_COMPRESSION_ALWAYS ] = "always",
|
||||
};
|
||||
#define parse_wan_compression(_name) \
|
||||
parse_name(_name, "wan compression", \
|
||||
wan_compression_names, ARRAY_SIZE(wan_compression_names))
|
||||
|
||||
/* functions for the rest of qemu */
|
||||
|
||||
static int add_channel(const char *name, const char *value, void *opaque)
|
||||
{
|
||||
int security = 0;
|
||||
int rc;
|
||||
|
||||
if (strcmp(name, "tls-channel") == 0) {
|
||||
security = SPICE_CHANNEL_SECURITY_SSL;
|
||||
}
|
||||
if (strcmp(name, "plaintext-channel") == 0) {
|
||||
security = SPICE_CHANNEL_SECURITY_NONE;
|
||||
}
|
||||
if (security == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(value, "default") == 0) {
|
||||
rc = spice_server_set_channel_security(spice_server, NULL, security);
|
||||
} else {
|
||||
rc = spice_server_set_channel_security(spice_server, value, security);
|
||||
}
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "spice: failed to set channel security for %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
const char *password;
|
||||
int port;
|
||||
const char *password, *str, *x509_dir, *addr,
|
||||
*x509_key_password = NULL,
|
||||
*x509_dh_file = NULL,
|
||||
*tls_ciphers = NULL;
|
||||
char *x509_key_file = NULL,
|
||||
*x509_cert_file = NULL,
|
||||
*x509_cacert_file = NULL;
|
||||
int port, tls_port, len, addr_flags, streaming_video;
|
||||
spice_image_compression_t compression;
|
||||
spice_wan_compression_t wan_compr;
|
||||
|
||||
if (!opts) {
|
||||
return;
|
||||
}
|
||||
port = qemu_opt_get_number(opts, "port", 0);
|
||||
if (!port) {
|
||||
tls_port = qemu_opt_get_number(opts, "tls-port", 0);
|
||||
if (!port && !tls_port) {
|
||||
return;
|
||||
}
|
||||
password = qemu_opt_get(opts, "password");
|
||||
|
||||
if (tls_port) {
|
||||
x509_dir = qemu_opt_get(opts, "x509-dir");
|
||||
if (NULL == x509_dir) {
|
||||
x509_dir = ".";
|
||||
}
|
||||
len = strlen(x509_dir) + 32;
|
||||
|
||||
str = qemu_opt_get(opts, "x509-key-file");
|
||||
if (str) {
|
||||
x509_key_file = qemu_strdup(str);
|
||||
} else {
|
||||
x509_key_file = qemu_malloc(len);
|
||||
snprintf(x509_key_file, len, "%s/%s", x509_dir, X509_SERVER_KEY_FILE);
|
||||
}
|
||||
|
||||
str = qemu_opt_get(opts, "x509-cert-file");
|
||||
if (str) {
|
||||
x509_cert_file = qemu_strdup(str);
|
||||
} else {
|
||||
x509_cert_file = qemu_malloc(len);
|
||||
snprintf(x509_cert_file, len, "%s/%s", x509_dir, X509_SERVER_CERT_FILE);
|
||||
}
|
||||
|
||||
str = qemu_opt_get(opts, "x509-cacert-file");
|
||||
if (str) {
|
||||
x509_cacert_file = qemu_strdup(str);
|
||||
} else {
|
||||
x509_cacert_file = qemu_malloc(len);
|
||||
snprintf(x509_cacert_file, len, "%s/%s", x509_dir, X509_CA_CERT_FILE);
|
||||
}
|
||||
|
||||
x509_key_password = qemu_opt_get(opts, "x509-key-password");
|
||||
x509_dh_file = qemu_opt_get(opts, "x509-dh-file");
|
||||
tls_ciphers = qemu_opt_get(opts, "tls-ciphers");
|
||||
}
|
||||
|
||||
addr = qemu_opt_get(opts, "addr");
|
||||
addr_flags = 0;
|
||||
if (qemu_opt_get_bool(opts, "ipv4", 0)) {
|
||||
addr_flags |= SPICE_ADDR_FLAG_IPV4_ONLY;
|
||||
} else if (qemu_opt_get_bool(opts, "ipv6", 0)) {
|
||||
addr_flags |= SPICE_ADDR_FLAG_IPV6_ONLY;
|
||||
}
|
||||
|
||||
spice_server = spice_server_new();
|
||||
spice_server_set_port(spice_server, port);
|
||||
spice_server_set_addr(spice_server, addr ? addr : "", addr_flags);
|
||||
if (port) {
|
||||
spice_server_set_port(spice_server, port);
|
||||
}
|
||||
if (tls_port) {
|
||||
spice_server_set_tls(spice_server, tls_port,
|
||||
x509_cacert_file,
|
||||
x509_cert_file,
|
||||
x509_key_file,
|
||||
x509_key_password,
|
||||
x509_dh_file,
|
||||
tls_ciphers);
|
||||
}
|
||||
if (password) {
|
||||
spice_server_set_ticket(spice_server, password, 0, 0, 0);
|
||||
}
|
||||
|
@ -162,13 +319,52 @@ void qemu_spice_init(void)
|
|||
spice_server_set_noauth(spice_server);
|
||||
}
|
||||
|
||||
/* TODO: make configurable via cmdline */
|
||||
spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
|
||||
compression = SPICE_IMAGE_COMPRESS_AUTO_GLZ;
|
||||
str = qemu_opt_get(opts, "image-compression");
|
||||
if (str) {
|
||||
compression = parse_compression(str);
|
||||
}
|
||||
spice_server_set_image_compression(spice_server, compression);
|
||||
|
||||
wan_compr = SPICE_WAN_COMPRESSION_AUTO;
|
||||
str = qemu_opt_get(opts, "jpeg-wan-compression");
|
||||
if (str) {
|
||||
wan_compr = parse_wan_compression(str);
|
||||
}
|
||||
spice_server_set_jpeg_compression(spice_server, wan_compr);
|
||||
|
||||
wan_compr = SPICE_WAN_COMPRESSION_AUTO;
|
||||
str = qemu_opt_get(opts, "zlib-glz-wan-compression");
|
||||
if (str) {
|
||||
wan_compr = parse_wan_compression(str);
|
||||
}
|
||||
spice_server_set_zlib_glz_compression(spice_server, wan_compr);
|
||||
|
||||
#if SPICE_SERVER_VERSION >= 0x000600 /* 0.6.0 */
|
||||
|
||||
str = qemu_opt_get(opts, "streaming-video");
|
||||
if (str) {
|
||||
streaming_video = parse_stream_video(str);
|
||||
spice_server_set_streaming_video(spice_server, streaming_video);
|
||||
}
|
||||
|
||||
spice_server_set_agent_mouse
|
||||
(spice_server, qemu_opt_get_bool(opts, "agent-mouse", 1));
|
||||
spice_server_set_playback_compression
|
||||
(spice_server, qemu_opt_get_bool(opts, "playback-compression", 1));
|
||||
|
||||
#endif /* >= 0.6.0 */
|
||||
|
||||
qemu_opt_foreach(opts, add_channel, NULL, 0);
|
||||
|
||||
spice_server_init(spice_server, &core_interface);
|
||||
using_spice = 1;
|
||||
|
||||
qemu_spice_input_init();
|
||||
|
||||
qemu_free(x509_key_file);
|
||||
qemu_free(x509_cert_file);
|
||||
qemu_free(x509_cacert_file);
|
||||
}
|
||||
|
||||
int qemu_spice_add_interface(SpiceBaseInstance *sin)
|
||||
|
|
Loading…
Reference in New Issue