Skip to content

Commit

Permalink
#3995 send the modified packet
Browse files Browse the repository at this point in the history
  • Loading branch information
totaam committed Sep 12, 2023
1 parent 42ad1f5 commit 7b92b21
Showing 1 changed file with 29 additions and 23 deletions.
52 changes: 29 additions & 23 deletions xpra/server/proxy/proxy_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,17 +361,19 @@ def process_client_packet(self, proto, packet : PacketType) -> None:
else:
self.stop(None, "disconnect from client", *reasons)
elif packet_type=="send-file" and packet[6]:
packet = self.replace_packet_item(packet, 6, Compressed("file-data", packet[6]))
packet = self.compressed_marker(packet, 6,"file-data")
elif packet_type=="send-file-chunk" and packet[3]:
packet = self.replace_packet_item(packet, 3, Compressed("file-chunk-data", packet[3]))
packet = self.compressed_marker(packet, 3, "file-chunk-data")
self.queue_server_packet(packet)

def compressed_marker(self, packet : PacketType, index:int, description:str):
return self.replace_packet_item(packet, index, Compressed(description, packet[index], can_inline=False))

def replace_packet_item(self, packet : PacketType, index:int, new_value:Any) -> PacketType:
# make the packet data mutable and replace the contents at `index`:
assert index>0
lpacket = list(packet)
lpacket[index] = Compressed("file-data", packet[index])
lpacket[index] = new_value
# noinspection PyTypeChecker
return tuple(lpacket)

Expand Down Expand Up @@ -517,10 +519,9 @@ def process_server_packet(self, proto, packet : PacketType) -> None:
#which will queue the packet itself when done:
return
elif packet_type=="sound-data":
sound_data = packet[2]
if sound_data:
if packet[2]:
#best if we use raw packets for the actual sound-data chunk:
packet = self.replace_packet_item(packet, 2, Compressed("sound-data", sound_data))
packet = self.compressed_marker(packet, 2, "sound-data")
#we do want to reformat cursor packets...
#as they will have been uncompressed by the network layer already:
elif packet_type=="cursor":
Expand All @@ -534,10 +535,10 @@ def process_server_packet(self, proto, packet : PacketType) -> None:
packet = self._packet_recompress(packet, 5, "icon")
elif packet_type=="send-file":
if packet[6]:
packet = self.replace_packet_item(packet, 6, Compressed("file-data", packet[6]))
packet = self.compressed_marker(packet, 6, "file-data")
elif packet_type=="send-file-chunk":
if packet[3]:
packet = self.replace_packet_item(packet, 3, Compressed("file-chunk-data", packet[3]))
packet = self.compressed_marker(packet, 3, "file-chunk-data")
elif packet_type=="challenge":
password = self.disp_desc.get("password", self.session_options.get("password"))
log("password from %s / %s = %s", self.disp_desc, self.session_options, password)
Expand Down Expand Up @@ -612,9 +613,7 @@ def delvideo(wid:int):
ve.clean()
elif packet_type=="draw":
#modify the packet with the video encoder:
if self.process_draw(packet):
#then send it as normal:
self.queue_client_packet(packet)
self.process_draw(packet)
elif packet_type=="check-video-timeout":
#not a real packet, this is added by the timeout check:
wid = packet[1]
Expand All @@ -638,12 +637,14 @@ def process_draw(self, packet : PacketType) -> bool:
encoding = bytestostr(encoding)
#never modify mmap or scroll packets:
if encoding in ("mmap", "scroll"):
return True
self.queue_client_packet(packet)
return
#we can only use video encoders on RGB data:
if encoding not in ("rgb24", "rgb32", "r210", "BGR565"):
#this prevents compression and inlining of pixel data:
packet = self.replace_packet_item(packet, 7, Compressed(f"{encoding} pixels", pixels))
return True
packet = self.compressed_marker(packet, 7, f"{encoding} pixels")
self.queue_client_packet(packet)
return
client_options = typedict(client_options)
#we have a proxy video packet:
rgb_format = client_options.strget("rgb_format", "")
Expand All @@ -655,7 +656,8 @@ def send_updated(packet:PacketType, encoding, compressed_data, updated_client_op
packet = self.replace_packet_item(packet, 7, compressed_data)
packet = self.replace_packet_item(packet, 10, updated_client_options)
enclog("returning %s bytes from %s, options=%s", len(compressed_data), len(pixels), updated_client_options)
return wid not in self.lost_windows
if wid not in self.lost_windows:
self.queue_client_packet(packet)

def passthrough(strip_alpha=True) -> bool:
enclog("proxy draw: %s passthrough (rowstride: %s vs %s, strip alpha=%s)",
Expand All @@ -681,25 +683,27 @@ def passthrough(strip_alpha=True) -> bool:
new_client_options = client_options
wrapped = Compressed(f"{encoding} pixels", cdata)
#rgb32 is always supported by all clients:
return send_updated(updated, encoding, wrapped, new_client_options)
send_updated(updated, encoding, wrapped, new_client_options)

proxy_video = client_options.boolget("proxy", False)
if PASSTHROUGH_RGB:
#we are dealing with rgb data, so we can pass it through:
return passthrough(proxy_video)
passthrough(proxy_video)
return
if not self.video_encoder_types or not client_options or not proxy_video:
#ensure we don't try to re-compress the pixel data in the network layer:
#(re-add the "compressed" marker that gets lost when we re-assemble packets)
packet = self.replace_packet_item(packet, 7, Compressed(f"{encoding} pixels", packet[7]))
return True
packet = self.compressed_marker(packet, 7, f"{encoding} pixels")
self.queue_client_packet(packet)
return

#video encoding: find existing encoder
ve = self.video_encoders.get(wid)
if ve:
if ve in self.lost_windows:
#we cannot clean the video encoder here, there may be more frames queue up
#"lost-window" in encode_loop will take care of it safely
return False
return
#we must verify that the encoder is still valid
#and scrap it if not (ie: when window is resized)
if ve.get_width()!=width or ve.get_height()!=height:
Expand Down Expand Up @@ -736,10 +740,12 @@ def passthrough(strip_alpha=True) -> bool:
if first_time(f"no-video-no-PIL-{rgb_format}"):
enclog.warn("Warning: no video encoder found for rgb format %s", rgb_format)
enclog.warn(" sending as plain RGB")
return passthrough(True)
passthrough(True)
return
enclog("no video encoder available: sending as jpeg")
coding, compressed_data, client_options = enc_pillow.encode("jpeg", image, quality, speed, False)[:3]
return send_updated(packet, coding, compressed_data, client_options)
send_updated(packet, coding, compressed_data, client_options)
return

enclog("creating new video encoder %s for window %s", spec, wid)
ve = spec.make_instance()
Expand All @@ -765,7 +771,7 @@ def passthrough(strip_alpha=True) -> bool:
if k not in out_options and k in client_options:
out_options[k] = client_options[k]
self.video_encoders_last_used_time[wid] = monotonic()
return send_updated(packet, ve.get_encoding(), Compressed(encoding, data), out_options)
send_updated(packet, ve.get_encoding(), Compressed(encoding, data), out_options)

def timeout_video_encoders(self) -> bool:
#have to be careful as another thread may come in...
Expand Down

0 comments on commit 7b92b21

Please sign in to comment.