diff --git a/pve-spiceterm.spec b/pve-spiceterm.spec index e310152..49fcdd7 100644 --- a/pve-spiceterm.spec +++ b/pve-spiceterm.spec @@ -3,8 +3,8 @@ Name: pve-%sname Summary: SPICE Terminal Emulator -Version: 3.1.1 -Release: alt4 +Version: 3.2.2 +Release: alt1 License: GPLv2 Group: Networking/WWW Url: https://git.proxmox.com/ @@ -38,6 +38,9 @@ sed -i 's|\ -Werror||' src/Makefile %_man1dir/%sname.1* %changelog +* Thu Sep 30 2021 Valery Inozemtsev 3.2.2-alt1 +- 3.2-2 + * Mon Jan 18 2021 Valery Inozemtsev 3.1.1-alt4 - fixed keymaps path (closes: #39553) diff --git a/spiceterm/Makefile b/spiceterm/Makefile index 11f0a18..db644b5 100644 --- a/spiceterm/Makefile +++ b/spiceterm/Makefile @@ -9,6 +9,7 @@ BUILDDIR ?= ${PACKAGE}-${DEB_VERSION_UPSTREAM} export VERSION=$(DEB_VERSION_UPSTREAM) DEB=${PACKAGE}_${DEB_VERSION_UPSTREAM_REVISION}_${DEB_BUILD_ARCH}.deb +DBG_DEB=${PACKAGE}-dbgsym_${DEB_VERSION_UPSTREAM_REVISION}_${DEB_BUILD_ARCH}.deb DSC=${PACKAGE}_${DEB_VERSION_UPSTREAM_REVISION}.dsc ${BUILDDIR}: src/ debian/ @@ -34,7 +35,7 @@ dinstall: ${DEB} .PHONY: upload upload: ${DEB} - tar cf - ${DEB} | ssh repoman@repo.proxmox.com -- upload --product pve --dist buster --arch ${ARCH} + tar cf - ${DEB} ${DBG_DEB} | ssh repoman@repo.proxmox.com -- upload --product pve --dist bullseye --arch ${ARCH} .PHONY: distclean clean distclean: clean diff --git a/spiceterm/debian/changelog b/spiceterm/debian/changelog index 5e07924..15b256f 100644 --- a/spiceterm/debian/changelog +++ b/spiceterm/debian/changelog @@ -1,3 +1,16 @@ +spiceterm (3.2-2) bullseye; urgency=medium + + * fix exit on client disconnect with newer libspice-server dependency's + behavior change + + -- Proxmox Support Team Wed, 23 Jun 2021 10:12:34 +0200 + +spiceterm (3.2-1) bullseye; urgency=medium + + * re-build for Debian 11 Bullseye / Proxmox VE 7 + + -- Proxmox Support Team Sun, 16 May 2021 18:54:53 +0200 + spiceterm (3.1-1) pve; urgency=medium * rebuild for PVE 6.0 / Debian Buster diff --git a/spiceterm/debian/compat b/spiceterm/debian/compat index b4de394..48082f7 100644 --- a/spiceterm/debian/compat +++ b/spiceterm/debian/compat @@ -1 +1 @@ -11 +12 diff --git a/spiceterm/debian/control b/spiceterm/debian/control index 3b68844..61c67e4 100644 --- a/spiceterm/debian/control +++ b/spiceterm/debian/control @@ -2,7 +2,7 @@ Source: spiceterm Section: admin Priority: optional Maintainer: Proxmox Support Team -Build-Depends: debhelper (>= 11), +Build-Depends: debhelper (>= 12), libglib2.0-dev, libspice-protocol-dev, libspice-server-dev, diff --git a/spiceterm/src/Makefile b/spiceterm/src/Makefile index 229866e..0c9c007 100644 --- a/spiceterm/src/Makefile +++ b/spiceterm/src/Makefile @@ -34,7 +34,7 @@ install: spiceterm spiceterm.1 mkdir -p ${DESTDIR}/usr/share/man/man1 install -m 0644 spiceterm.1 ${DESTDIR}/usr/share/man/man1 mkdir -p ${DESTDIR}/usr/bin - install -s -m 0755 spiceterm ${DESTDIR}/usr/bin + install -m 0755 spiceterm ${DESTDIR}/usr/bin .PHONY: test test: spiceterm diff --git a/spiceterm/src/screen.c b/spiceterm/src/screen.c index 3c00aeb..ee6e34a 100644 --- a/spiceterm/src/screen.c +++ b/spiceterm/src/screen.c @@ -1,6 +1,6 @@ /* - Copyright (C) 2013 Proxmox Server Solutions GmbH + Copyright (C) 2013 - 2021 Proxmox Server Solutions GmbH Copyright: spiceterm is under GNU GPL, the GNU General Public License. @@ -46,7 +46,7 @@ #include "spiceterm.h" static int debug = 0; - + #define DPRINTF(x, format, ...) { \ if (x <= debug) { \ printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \ @@ -69,7 +69,7 @@ int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, /* Parts cribbed from spice-display.h/.c/qxl.c */ -typedef struct SimpleSpiceUpdate { +typedef struct __attribute__ ((__packed__)) SimpleSpiceUpdate { QXLCommandExt ext; // needs to be first member QXLDrawable drawable; QXLImage image; @@ -77,7 +77,7 @@ typedef struct SimpleSpiceUpdate { int cache_id; // do not free bitmap if cache_id != 0 } SimpleSpiceUpdate; -static void +static void spice_screen_destroy_update(SimpleSpiceUpdate *update) { if (!update) { @@ -94,32 +94,32 @@ spice_screen_destroy_update(SimpleSpiceUpdate *update) g_free(update); } -static void +static void release_qxl_command_ext(QXLCommandExt *ext) { g_assert(ext != NULL); switch (ext->cmd.type) { - case QXL_CMD_DRAW: - spice_screen_destroy_update((void*)ext); - break; - case QXL_CMD_SURFACE: - free(ext); - break; - case QXL_CMD_CURSOR: { - QXLCursorCmd *cmd = (QXLCursorCmd *)(unsigned long)ext->cmd.data; - if (cmd->type == QXL_CURSOR_SET) { - free(cmd); + case QXL_CMD_DRAW: + spice_screen_destroy_update((void*)ext); + break; + case QXL_CMD_SURFACE: + free(ext); + break; + case QXL_CMD_CURSOR: { + QXLCursorCmd *cmd = (QXLCursorCmd *)(unsigned long)ext->cmd.data; + if (cmd->type == QXL_CURSOR_SET) { + free(cmd); + } + free(ext); + break; } - free(ext); - break; - } - default: - abort(); + default: + abort(); } } -static void +static void release_resource(QXLInstance *qin, struct QXLReleaseInfoExt release_info) { QXLCommandExt *ext = (QXLCommandExt*)(unsigned long)release_info.info->id; @@ -130,7 +130,7 @@ release_resource(QXLInstance *qin, struct QXLReleaseInfoExt release_info) static int unique = 0x0ffff + 1; -static void +static void set_cmd(QXLCommandExt *ext, uint32_t type, QXLPHYSICAL data) { ext->cmd.type = type; @@ -140,7 +140,7 @@ set_cmd(QXLCommandExt *ext, uint32_t type, QXLPHYSICAL data) ext->flags = 0; } -static void +static void simple_set_release_info(QXLReleaseInfo *info, intptr_t ptr) { info->id = ptr; @@ -149,7 +149,7 @@ simple_set_release_info(QXLReleaseInfo *info, intptr_t ptr) /* Note: push_command/get_command are called from different threads */ -static void +static void push_command(SpiceScreen *spice_screen, QXLCommandExt *ext) { int need_wakeup = 1; @@ -180,8 +180,12 @@ push_command(SpiceScreen *spice_screen, QXLCommandExt *ext) /* bitmap are freed, so they must be allocated with g_malloc */ static SimpleSpiceUpdate * -spice_screen_update_from_bitmap_cmd(uint32_t surface_id, QXLRect bbox, uint8_t *bitmap, int cache_id) -{ +spice_screen_update_from_bitmap_cmd( + uint32_t surface_id, + QXLRect bbox, + uint8_t *bitmap, + int cache_id +) { SimpleSpiceUpdate *update; QXLDrawable *drawable; QXLImage *image; @@ -233,14 +237,16 @@ spice_screen_update_from_bitmap_cmd(uint32_t surface_id, QXLRect bbox, uint8_t * } static SimpleSpiceUpdate * -spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c, - int fg, int bg, gboolean uline) -{ - int top, left; - uint8_t *dst; +spice_screen_draw_char_cmd( + SpiceScreen *spice_screen, + int x, + int y, + int c, + int fg, + int bg, + gboolean uline +) { uint8_t *bitmap = NULL; - int bw, bh; - int i, j; QXLRect bbox; int cache_id = 0; CachedImage *ce; @@ -252,15 +258,12 @@ spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c, } } - left = x*8; - top = y*16; - - bw = 8; - bh = 16; + int bw = 8, bh = 16; + int left = x * bw, top = y * bh; if (!bitmap) { - bitmap = dst = g_malloc(bw * bh * 4); - + uint8_t *dst = bitmap = g_malloc(bw * bh * 4); + unsigned char *data = vt_font_data + c*16; unsigned char d = *data; @@ -274,35 +277,35 @@ spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c, unsigned char bgc_blue = default_blu[color_table[bg]]; unsigned char bgc_green = default_grn[color_table[bg]]; - for (j = 0; j < 16; j++) { + for (int j = 0; j < 16; j++) { gboolean ul = (j == 14) && uline; - for (i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { if (i == 0) { d=*data; data++; } if (ul || d&0x80) { - *(dst) = fgc_blue; + *(dst+0) = fgc_blue; *(dst+1) = fgc_green; *(dst+2) = fgc_red; *(dst+3) = 0; } else { - *(dst) = bgc_blue; + *(dst+0) = bgc_blue; *(dst+1) = bgc_green; *(dst+2) = bgc_red; *(dst+3) = 0; } - d<<=1; + d <<= 1; dst += 4; } } - if (cache_id != 0) { - ce = g_new(CachedImage, 1); - ce->cache_id = cache_id; - ce->bitmap = bitmap; - g_hash_table_insert(spice_screen->image_cache, &ce->cache_id, ce); - } + if (cache_id != 0) { + ce = g_new(CachedImage, 1); + ce->cache_id = cache_id; + ce->bitmap = bitmap; + g_hash_table_insert(spice_screen->image_cache, &ce->cache_id, ce); + } } bbox.left = left; bbox.top = top; @@ -311,10 +314,16 @@ spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c, return spice_screen_update_from_bitmap_cmd(0, bbox, bitmap, cache_id); } -void -spice_screen_scroll(SpiceScreen *spice_screen, int x1, int y1, - int x2, int y2, int src_x, int src_y) -{ +void +spice_screen_scroll( + SpiceScreen *spice_screen, + int x1, + int y1, + int x2, + int y2, + int src_x, + int src_y +) { SimpleSpiceUpdate *update; QXLDrawable *drawable; QXLRect bbox; @@ -348,7 +357,7 @@ spice_screen_scroll(SpiceScreen *spice_screen, int x1, int y1, push_command(spice_screen, &update->ext); } -void +void spice_screen_clear(SpiceScreen *spice_screen, int x1, int y1, int x2, int y2) { SimpleSpiceUpdate *update; @@ -381,10 +390,12 @@ spice_screen_clear(SpiceScreen *spice_screen, int x1, int y1, int x2, int y2) push_command(spice_screen, &update->ext); } -static void -create_primary_surface(SpiceScreen *spice_screen, uint32_t width, - uint32_t height) -{ +static void +create_primary_surface( + SpiceScreen *spice_screen, + uint32_t width, + uint32_t height +) { QXLDevSurfaceCreate surface = { 0, }; g_assert(height > 0); @@ -425,7 +436,7 @@ QXLDevMemSlot slot = { .qxl_ram_size = ~0, }; -static void +static void attache_worker(QXLInstance *qin, QXLWorker *_qxl_worker) { SpiceScreen *spice_screen = SPICE_CONTAINEROF(qin, SpiceScreen, qxl_instance); @@ -433,26 +444,26 @@ attache_worker(QXLInstance *qin, QXLWorker *_qxl_worker) if (spice_screen->qxl_worker) { g_assert_not_reached(); } - + spice_screen->qxl_worker = _qxl_worker; spice_qxl_add_memslot(&spice_screen->qxl_instance, &slot); create_primary_surface(spice_screen, spice_screen->width, spice_screen->height); spice_server_vm_start(spice_screen->server); } -static void +static void set_compression_level(QXLInstance *qin, int level) { /* not used */ } -static void +static void set_mm_time(QXLInstance *qin, uint32_t mm_time) { /* not used */ } -static void +static void get_init_info(QXLInstance *qin, QXLDevInitInfo *info) { memset(info, 0, sizeof(*info)); @@ -464,14 +475,14 @@ get_init_info(QXLInstance *qin, QXLDevInitInfo *info) } /* called from spice_server thread (i.e. red_worker thread) */ -static int +static int get_command(QXLInstance *qin, struct QXLCommandExt *ext) { SpiceScreen *spice_screen = SPICE_CONTAINEROF(qin, SpiceScreen, qxl_instance); int res = FALSE; g_mutex_lock(&spice_screen->command_mutex); - + if ((spice_screen->commands_end - spice_screen->commands_start) == 0) { res = FALSE; goto ret; @@ -490,7 +501,7 @@ ret: } void -discard_pending_commands(SpiceScreen *spice_screen) +discard_pending_commands(SpiceScreen *spice_screen) { int pos; @@ -502,7 +513,7 @@ discard_pending_commands(SpiceScreen *spice_screen) g_mutex_unlock(&spice_screen->command_mutex); } -static int +static int req_cmd_notification(QXLInstance *qin) { //SpiceScreen *spice_screen = SPICE_CONTAINEROF(qin, SpiceScreen, qxl_instance); @@ -519,7 +530,7 @@ static struct { uint8_t data[CURSOR_WIDTH * CURSOR_HEIGHT * 4]; // 32bit per pixel } cursor; -static void +static void cursor_init() { cursor.cursor.header.unique = 0; @@ -540,19 +551,19 @@ cursor_init() cursor.cursor.chunk.prev_chunk = cursor.cursor.chunk.next_chunk = 0; } -static int +static int get_cursor_command(QXLInstance *qin, struct QXLCommandExt *ext) { SpiceScreen *spice_screen = SPICE_CONTAINEROF(qin, SpiceScreen, qxl_instance); - + QXLCursorCmd *cursor_cmd; QXLCommandExt *cmd; - if (spice_screen->cursor_set) + if (spice_screen->cursor_set) return FALSE; - + spice_screen->cursor_set = 1; - + cmd = calloc(sizeof(QXLCommandExt), 1); cursor_cmd = calloc(sizeof(QXLCursorCmd), 1); @@ -575,7 +586,7 @@ get_cursor_command(QXLInstance *qin, struct QXLCommandExt *ext) return TRUE; } -static int +static int req_cursor_notification(QXLInstance *qin) { /* not used */ @@ -583,13 +594,13 @@ req_cursor_notification(QXLInstance *qin) return TRUE; } -static void +static void notify_update(QXLInstance *qin, uint32_t update_id) { /* not used */ } -static int +static int flush_resources(QXLInstance *qin) { /* not used */ @@ -597,7 +608,7 @@ flush_resources(QXLInstance *qin) return TRUE; } -static int +static int client_monitors_config(QXLInstance *qin, VDAgentMonitorsConfig *monitors_config) { /* not used */ @@ -605,10 +616,12 @@ client_monitors_config(QXLInstance *qin, VDAgentMonitorsConfig *monitors_config) return 0; } -static void -set_client_capabilities(QXLInstance *qin, uint8_t client_present, - uint8_t caps[58]) -{ +static void +set_client_capabilities( + QXLInstance *qin, + uint8_t client_present, + uint8_t caps[58] +) { SpiceScreen *spice_screen = SPICE_CONTAINEROF(qin, SpiceScreen, qxl_instance); DPRINTF(1, "present %d caps %d", client_present, caps[0]); @@ -623,7 +636,7 @@ set_client_capabilities(QXLInstance *qin, uint8_t client_present, static int client_count = 0; -static void +static void client_connected(SpiceScreen *spice_screen) { client_count++; @@ -631,9 +644,9 @@ client_connected(SpiceScreen *spice_screen) DPRINTF(1, "client_count = %d", client_count); } -static void +static void client_disconnected(SpiceScreen *spice_screen) -{ +{ if (client_count > 0) { client_count--; DPRINTF(1, "client_count = %d", client_count); @@ -641,7 +654,7 @@ client_disconnected(SpiceScreen *spice_screen) } } -static void +static void do_conn_timeout(void *opaque) { // SpiceScreen *spice_screen = opaque; @@ -678,10 +691,14 @@ QXLInterface display_sif = { }; -void -spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar2 ch, - TextAttributes attrib) -{ +void +spice_screen_draw_char( + SpiceScreen *spice_screen, + int x, + int y, + gunichar2 ch, + TextAttributes attrib +) { int fg, bg; int invers; @@ -689,7 +706,7 @@ spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar2 ch, invers = attrib.selected ? 0 : 1; } else { invers = attrib.selected ? 1 : 0; - } + } if (invers) { bg = attrib.fgcol; @@ -713,9 +730,12 @@ spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar2 ch, } SpiceScreen * -spice_screen_new(SpiceCoreInterface *core, uint32_t width, uint32_t height, - SpiceTermOptions *opts) -{ +spice_screen_new( + SpiceCoreInterface *core, + uint32_t width, + uint32_t height, + SpiceTermOptions *opts +) { SpiceScreen *spice_screen = g_new0(SpiceScreen, 1); SpiceServer* server = spice_server_new(); char *x509_key_file = "/etc/pve/local/pve-ssl.key"; @@ -750,13 +770,15 @@ spice_screen_new(SpiceCoreInterface *core, uint32_t width, uint32_t height, // spice_server_set_port(spice_server, port); //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESS_OFF); - spice_server_set_tls(server, opts->port, - x509_cacert_file, - x509_cert_file, - x509_key_file, - x509_key_password, - x509_dh_file, - tls_ciphers); + spice_server_set_tls( + server, opts->port, + x509_cacert_file, + x509_cert_file, + x509_key_file, + x509_key_password, + x509_dh_file, + tls_ciphers + ); if (opts->noauth) { spice_server_set_noauth(server); @@ -767,6 +789,8 @@ spice_screen_new(SpiceCoreInterface *core, uint32_t width, uint32_t height, } } + spice_server_set_exit_on_disconnect(server, 1); + int res = spice_server_init(server, core); if (res != 0) { g_error("spice_server_init failed, res = %d\n", res); @@ -784,10 +808,12 @@ spice_screen_new(SpiceCoreInterface *core, uint32_t width, uint32_t height, return spice_screen; } -void -spice_screen_resize(SpiceScreen *spice_screen, uint32_t width, - uint32_t height) -{ +void +spice_screen_resize( + SpiceScreen *spice_screen, + uint32_t width, + uint32_t height +) { if (spice_screen->width == width && spice_screen->height == height) { return; } @@ -795,7 +821,7 @@ spice_screen_resize(SpiceScreen *spice_screen, uint32_t width, discard_pending_commands(spice_screen); spice_qxl_destroy_primary_surface(&spice_screen->qxl_instance, 0); - + create_primary_surface(spice_screen, width, height); spice_screen_clear(spice_screen, 0, 0, width, height);