improved vnc encodings handling

This commit is contained in:
Maxim Devaev 2022-07-21 13:16:42 +03:00
parent 508a6e9b58
commit af4eb77231

View File

@ -419,6 +419,8 @@ class RfbClient(RfbClientStream): # pylint: disable=too-many-instance-attribute
logger = get_logger(0) logger = get_logger(0)
encodings_count = (await self._read_struct("encodings number", "x H"))[0] encodings_count = (await self._read_struct("encodings number", "x H"))[0]
if encodings_count == 0:
raise RfbError("Empty encodings list received")
if encodings_count > 1024: if encodings_count > 1024:
raise RfbError(f"Too many encodings: {encodings_count}") raise RfbError(f"Too many encodings: {encodings_count}")
@ -426,17 +428,25 @@ class RfbClient(RfbClientStream): # pylint: disable=too-many-instance-attribute
logger.info("[main] %s: Client features (SetEncodings):", self._remote) logger.info("[main] %s: Client features (SetEncodings):", self._remote)
for item in self._encodings.get_summary(): for item in self._encodings.get_summary():
logger.info("[main] %s: ... %s", self._remote, item) logger.info("[main] %s: ... %s", self._remote, item)
self.__check_tight_jpeg() self.__check_encodings()
if self._encodings.has_ext_keys: # Preferred method if self._encodings.has_ext_keys: # Preferred method
await self._write_fb_update("ExtKeys FBUR", 0, 0, RfbEncodings.EXT_KEYS, drain=True) await self._write_fb_update("ExtKeys FBUR", 0, 0, RfbEncodings.EXT_KEYS, drain=True)
await self._on_set_encodings() await self._on_set_encodings()
async def __handle_fb_update_request(self) -> None: async def __handle_fb_update_request(self) -> None:
self.__check_tight_jpeg() # If we don't receive SetEncodings from client self.__check_encodings()
await self._read_struct("FBUR", "? HH HH") # Ignore any arguments, just perform the full update await self._read_struct("FBUR", "? HH HH") # Ignore any arguments, just perform the full update
await self._on_fb_update_request() await self._on_fb_update_request()
def __check_encodings(self) -> None:
# JpegCompression may only be used when the client has advertized
# a quality level using the JPEG Quality Level Pseudo-encoding
if len(self._encodings.encodings) == 0:
raise RfbError("The client did not send SetEncodings")
if not self._encodings.has_tight or self._encodings.tight_jpeg_quality == 0:
raise RfbError("Tight JPEG encoding is not supported by client")
async def __handle_key_event(self) -> None: async def __handle_key_event(self) -> None:
(state, code) = await self._read_struct("key event", "? xx L") (state, code) = await self._read_struct("key event", "? xx L")
await self._on_key_event(code, state) # type: ignore await self._on_key_event(code, state) # type: ignore
@ -474,9 +484,3 @@ class RfbClient(RfbClientStream): # pylint: disable=too-many-instance-attribute
if code & 0x80: if code & 0x80:
code = (0xE0 << 8) | (code & ~0x80) code = (0xE0 << 8) | (code & ~0x80)
await self._on_ext_key_event(code, bool(state)) await self._on_ext_key_event(code, bool(state))
def __check_tight_jpeg(self) -> None:
# JpegCompression may only be used when the client has advertized
# a quality level using the JPEG Quality Level Pseudo-encoding
if not self._encodings.has_tight or self._encodings.tight_jpeg_quality == 0:
raise RfbError(f"Tight JPEG encoding is not supported by client: {self._encodings}")