Пример #1
0
 def _may_compress(self, dtype, dformat, wire_data):
     if len(wire_data)>256:
         wire_data = compressed_wrapper("clipboard: %s / %s" % (dtype, dformat), wire_data)
         if len(wire_data)>self.max_clipboard_packet_size:
             log.warn("even compressed, clipboard contents are too big and have not been sent:"
                      " %s compressed bytes dropped (maximum is %s)", len(wire_data), self.max_clipboard_packet_size)
             return  None
     return wire_data
Пример #2
0
 def _may_compress(self, dtype, dformat, wire_data):
     if len(wire_data) > 256:
         wire_data = compressed_wrapper(
             "clipboard: %s / %s" % (dtype, dformat), wire_data)
         if len(wire_data) > self.max_clipboard_packet_size:
             log.warn(
                 "even compressed, clipboard contents are too big and have not been sent:"
                 " %s compressed bytes dropped (maximum is %s)",
                 len(wire_data), self.max_clipboard_packet_size)
             return None
     return wire_data
Пример #3
0
    def process_server_packet(self, proto, packet):
        packet_type = packet[0]
        debug("process_server_packet: %s", packet_type)
        if packet_type==Protocol.CONNECTION_LOST:
            self.stop("server connection lost", proto)
            return
        elif packet_type=="hello":
            c = typedict(packet[1])
            maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
            proto.max_packet_size = maxw*maxh*4

            caps = self.filter_server_caps(c)
            #add new encryption caps:
            if self.cipher:
                auth_caps = new_cipher_caps(self.client_protocol, self.cipher, self.encryption_key)
                caps.update(auth_caps)
            packet = ("hello", caps)
        elif packet_type=="info-response":
            #adds proxy info:
            #note: this is only seen by the client application
            #"xpra info" is a new connection, which talks to the proxy server...
            info = packet[1]
            info.update(get_server_info("proxy."))
            info.update(get_thread_info("proxy.", proto))
            info.update(self.get_encoder_info())
        elif packet_type=="lost-window":
            wid = packet[1]
            #mark it as lost so we can drop any current/pending frames
            self.lost_windows.add(wid)
            #queue it so it gets cleaned safely (for video encoders mostly):
            self.encode_queue.put(packet)
            #and fall through so tell the client immediately
        elif packet_type=="draw":
            #use encoder thread:
            self.encode_queue.put(packet)
            #which will queue the packet itself when done:
            return
        elif packet_type=="cursor":
            #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
            #or:
            #packet = ["cursor", ""]
            if len(packet)>=9:
                pixels = packet[8]
                if len(pixels)<64:
                    packet[8] = str(pixels)
                else:
                    packet[8] = compressed_wrapper("cursor", pixels)
        self.queue_client_packet(packet)
Пример #4
0
    def process_server_packet(self, proto, packet):
        packet_type = packet[0]
        log("process_server_packet: %s", packet_type)
        if packet_type == Protocol.CONNECTION_LOST:
            self.stop("server connection lost", proto)
            return
        elif packet_type == "hello":
            c = typedict(packet[1])
            maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
            proto.max_packet_size = maxw * maxh * 4 * 4

            caps = self.filter_server_caps(c)
            #add new encryption caps:
            if self.cipher:
                auth_caps = new_cipher_caps(self.client_protocol, self.cipher,
                                            self.encryption_key)
                caps.update(auth_caps)
            packet = ("hello", caps)
        elif packet_type == "info-response":
            #adds proxy info:
            #note: this is only seen by the client application
            #"xpra info" is a new connection, which talks to the proxy server...
            info = packet[1]
            info.update(self.get_proxy_info(proto))
        elif packet_type == "lost-window":
            wid = packet[1]
            #mark it as lost so we can drop any current/pending frames
            self.lost_windows.add(wid)
            #queue it so it gets cleaned safely (for video encoders mostly):
            self.encode_queue.put(packet)
            #and fall through so tell the client immediately
        elif packet_type == "draw":
            #use encoder thread:
            self.encode_queue.put(packet)
            #which will queue the packet itself when done:
            return
        elif packet_type == "cursor":
            #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
            #or:
            #packet = ["cursor", ""]
            if len(packet) >= 9:
                pixels = packet[8]
                if len(pixels) < 512:
                    packet[8] = str(pixels)
                else:
                    packet[8] = compressed_wrapper("cursor", pixels)
        self.queue_client_packet(packet)
Пример #5
0
    def process_server_packet(self, proto, packet):
        packet_type = packet[0]
        debug("process_server_packet: %s", packet_type)
        if packet_type==Protocol.CONNECTION_LOST:
            self.stop("server connection lost", proto)
            return
        elif packet_type=="hello":
            c = typedict(packet[1])
            maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
            proto.max_packet_size = maxw*maxh*4

            caps = self.filter_server_caps(c)
            #add new encryption caps:
            if self.cipher:
                auth_caps = new_cipher_caps(self.client_protocol, self.cipher, self.encryption_key)
                caps.update(auth_caps)
            packet = ("hello", caps)
        elif packet_type=="info-response":
            #adds proxy info:
            #note: this is only seen by the client application
            #"xpra info" is a new connection, which talks to the proxy server...
            info = packet[1]
            info.update(get_server_info("proxy."))
            info.update(get_thread_info("proxy.", proto))
            info.update(self.get_encoder_info())
        elif packet_type=="lost-window":
            wid = packet[1]
            ve = self.video_encoders.get(wid)
            if ve:
                ve.clean()
                del self.video_encoders[wid]
        elif packet_type=="draw":
            self.process_draw(packet)
        elif packet_type=="cursor":
            #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
            #or:
            #packet = ["cursor", ""]
            if len(packet)>=9:
                pixels = packet[8]
                if len(pixels)<64:
                    packet[8] = str(pixels)
                else:
                    packet[8] = compressed_wrapper("cursor", pixels)
        self.queue_client_packet(packet)
Пример #6
0
    def process_server_packet(self, proto, packet):
        packet_type = packet[0]
        debug("process_server_packet: %s", packet_type)
        if packet_type == Protocol.CONNECTION_LOST:
            self.stop("server connection lost", proto)
            return
        elif packet_type == "hello":
            c = typedict(packet[1])
            maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
            proto.max_packet_size = maxw * maxh * 4

            caps = self.filter_server_caps(c)
            #add new encryption caps:
            if self.cipher:
                auth_caps = new_cipher_caps(self.client_protocol, self.cipher,
                                            self.encryption_key)
                caps.update(auth_caps)
            packet = ("hello", caps)
        elif packet_type == "info-response":
            #adds proxy info:
            info = packet[1]
            info.update(get_server_info("proxy."))
            info.update(get_thread_info("proxy.", proto))
        elif packet_type == "draw":
            #packet = ["draw", wid, x, y, outw, outh, coding, data, self._damage_packet_sequence, outstride, client_options]
            #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)
            coding = packet[6]
            if coding != "mmap":
                data = packet[7]
                packet[7] = Compressed("%s pixels" % coding, data)
        elif packet_type == "cursor":
            #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
            #or:
            #packet = ["cursor", ""]
            if len(packet) >= 9:
                pixels = packet[8]
                if len(pixels) < 64:
                    packet[8] = str(pixels)
                else:
                    packet[8] = compressed_wrapper("cursor", pixels)
        self.queue_client_packet(packet)
Пример #7
0
    def process_server_packet(self, proto, packet):
        packet_type = packet[0]
        debug("process_server_packet: %s", packet_type)
        if packet_type==Protocol.CONNECTION_LOST:
            self.stop("server connection lost", proto)
            return
        elif packet_type=="hello":
            c = typedict(packet[1])
            maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
            proto.max_packet_size = maxw*maxh*4

            caps = self.filter_server_caps(c)
            #add new encryption caps:
            if self.cipher:
                auth_caps = new_cipher_caps(self.client_protocol, self.cipher, self.encryption_key)
                caps.update(auth_caps)
            packet = ("hello", caps)
        elif packet_type=="info-response":
            #adds proxy info:
            info = packet[1]
            info.update(get_server_info("proxy."))
            info.update(get_thread_info("proxy.", proto))
        elif packet_type=="draw":
            #packet = ["draw", wid, x, y, outw, outh, coding, data, self._damage_packet_sequence, outstride, client_options]
            #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)
            coding = packet[6]
            if coding!="mmap":
                data = packet[7]
                packet[7] = Compressed("%s pixels" % coding, data)
        elif packet_type=="cursor":
            #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
            #or:
            #packet = ["cursor", ""]
            if len(packet)>=9:
                pixels = packet[8]
                if len(pixels)<64:
                    packet[8] = str(pixels)
                else:
                    packet[8] = compressed_wrapper("cursor", pixels)
        self.queue_client_packet(packet)
Пример #8
0
 def send_cursor(self):
     self.send_cursor_pending = False
     self.cursor_data = X11Keyboard.get_cursor_image()
     if self.cursor_data is not None:
         pixels = self.cursor_data[7]
         log("send_cursor() cursor=%s", self.cursor_data[:7]+["%s bytes" % len(pixels)]+self.cursor_data[8:])
         if self.default_cursor_data is not None and str(pixels)==str(self.default_cursor_data[7]):
             log("send_cursor(): default cursor - clearing it")
             self.cursor_data = None
         elif pixels is not None:
             #convert bytearray to string:
             pixels = str(pixels)
             if len(pixels)<64:
                 self.cursor_data[7] = pixels
             else:
                 self.cursor_data[7] = compressed_wrapper("cursor", pixels)
     else:
         log("send_cursor() failed to get cursor image")
     for ss in self._server_sources.values():
         ss.send_cursor(self.cursor_data)
     return False
Пример #9
0
def rgb_encode(coding, image, rgb_formats, supports_transparency, speed,
               rgb_zlib, rgb_lz4, encoding_client_options, supports_rgb24zlib):
    pixel_format = image.get_pixel_format()
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s", (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4, encoding_client_options, supports_rgb24zlib), pixel_format, rgb_formats)
    if pixel_format not in rgb_formats:
        if not rgb_reformat(image, rgb_formats, supports_transparency):
            raise Exception(
                "cannot find compatible rgb format to use for %s! (supported: %s)"
                % (pixel_format, rgb_formats))
        #get the new format:
        pixel_format = image.get_pixel_format()
        #switch encoding if necessary:
        if len(pixel_format) == 4 and coding == "rgb24":
            coding = "rgb32"
        elif len(pixel_format) == 3 and coding == "rgb32":
            coding = "rgb24"
    #always tell client which pixel format we are sending:
    options = {"rgb_format": pixel_format}
    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()

    #special case for when rowstride is so much bigger than the width
    #that we would end up sending large chunks of padding with each row of pixels
    #this happens with XShm pixel data (the default)
    stride = image.get_rowstride()
    width = image.get_width()
    rstride = roundup(width * len(pixel_format),
                      4)  #a reasonable stride: rounded up to 4
    height = image.get_height()
    if stride > 8 and rstride < stride:
        al = len(pixels)  #current buffer size
        el = rstride * height  #desirable size we could have
        if al - el > 1024 and el * 110 / 100 < al:  #is it worth re-striding to save space?
            #we'll save at least 1KB and 10%, do it
            #Note: we could also change the pixel format whilst we're at it
            # and convert BGRX to RGB for example (assuming RGB is also supported by the client)
            rows = []
            for y in range(height):
                rows.append(pixels[stride * y:stride * y + rstride])
            pixels = "".join(rows)
            log(
                "rgb_encode: %s pixels re-stride saving %i%% from %s (%s bytes) to %s (%s bytes)",
                pixel_format, 100 - 100 * el / al, stride, al, rstride, el)
            stride = rstride

    #compression
    #by default, wire=raw:
    raw_data = str(pixels)
    wire_data = raw_data
    level = 0
    algo = "not"
    if rgb_zlib or rgb_lz4:
        level = max(0, min(5, int(115 - speed) / 20))
        if len(pixels) < 1024:
            #fewer pixels, make it more likely we won't bother compressing:
            level = level / 2
    if level > 0:
        lz4 = use_lz4 and rgb_lz4 and level <= 3
        wire_data = compressed_wrapper(coding, pixels, level=level, lz4=lz4)
        raw_data = wire_data.data
        #log("%s/%s data compressed from %s bytes down to %s (%s%%) with lz4=%s",
        #         coding, pixel_format, len(pixels), len(raw_data), int(100.0*len(raw_data)/len(pixels)), self.rgb_lz4)
        if len(raw_data) >= (len(pixels) - 32):
            #compressed is actually bigger! (use uncompressed)
            level = 0
            wire_data = str(pixels)
            raw_data = wire_data
        else:
            if lz4:
                options["lz4"] = True
                algo = "lz4"
            else:
                options["zlib"] = level
                algo = "zlib"
    if pixel_format.upper().find("A") >= 0 or pixel_format.upper().find(
            "X") >= 0:
        bpp = 32
    else:
        bpp = 24
    log(
        "rgb_encode using level=%s, %s compressed %sx%s in %s/%s: %s bytes down to %s",
        level, algo, image.get_width(), image.get_height(), coding,
        pixel_format, len(pixels), len(raw_data))
    if not encoding_client_options or not supports_rgb24zlib:
        return coding, wire_data, {}, width, height, stride, bpp
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, Compressed(coding,
                              raw_data), options, width, height, stride, bpp
Пример #10
0
def rgb_encode(coding, image, rgb_formats, supports_transparency, speed, rgb_zlib=True, rgb_lz4=True, encoding_client_options=True, supports_rgb24zlib=True):
    pixel_format = image.get_pixel_format()
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s", (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4, encoding_client_options, supports_rgb24zlib), pixel_format, rgb_formats)
    if pixel_format not in rgb_formats:
        if not rgb_reformat(image, rgb_formats, supports_transparency):
            raise Exception("cannot find compatible rgb format to use for %s! (supported: %s)" % (pixel_format, rgb_formats))
        #get the new format:
        pixel_format = image.get_pixel_format()
        #switch encoding if necessary:
        if len(pixel_format)==4 and coding=="rgb24":
            coding = "rgb32"
        elif len(pixel_format)==3 and coding=="rgb32":
            coding = "rgb24"
    #always tell client which pixel format we are sending:
    options = {"rgb_format" : pixel_format}
    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()

    #special case for when rowstride is so much bigger than the width
    #that we would end up sending large chunks of padding with each row of pixels
    #this happens with XShm pixel data (the default)
    stride = image.get_rowstride()
    width = image.get_width()
    rstride = roundup(width*len(pixel_format), 4)   #a reasonable stride: rounded up to 4
    height = image.get_height()
    if stride>8 and rstride<stride:
        al = len(pixels)                    #current buffer size
        el = rstride*height                 #desirable size we could have
        if al-el>1024 and el*110/100<al:    #is it worth re-striding to save space?
            #we'll save at least 1KB and 10%, do it
            #Note: we could also change the pixel format whilst we're at it
            # and convert BGRX to RGB for example (assuming RGB is also supported by the client)
            rows = []
            for y in range(height):
                rows.append(pixels[stride*y:stride*y+rstride])
            pixels = "".join(rows)
            log("rgb_encode: %s pixels re-stride saving %i%% from %s (%s bytes) to %s (%s bytes)", pixel_format, 100-100*el/al, stride, al, rstride, el)
            stride = rstride

    #compression
    #by default, wire=raw:
    raw_data = str(pixels)
    wire_data = raw_data
    level = 0
    algo = "not"
    if rgb_zlib or rgb_lz4:
        level = max(0, min(5, int(115-speed)/20))
        if len(pixels)<1024:
            #fewer pixels, make it more likely we won't bother compressing:
            level = level / 2
    if level>0:
        lz4 = use_lz4 and rgb_lz4 and level<=3
        wire_data = compressed_wrapper(coding, pixels, level=level, lz4=lz4)
        raw_data = wire_data.data
        #log("%s/%s data compressed from %s bytes down to %s (%s%%) with lz4=%s",
        #         coding, pixel_format, len(pixels), len(raw_data), int(100.0*len(raw_data)/len(pixels)), self.rgb_lz4)
        if len(raw_data)>=(len(pixels)-32):
            #compressed is actually bigger! (use uncompressed)
            level = 0
            wire_data = str(pixels)
            raw_data = wire_data
        else:
            if lz4:
                options["lz4"] = True
                algo = "lz4"
            else:
                options["zlib"] = level
                algo = "zlib"
    if pixel_format.upper().find("A")>=0 or pixel_format.upper().find("X")>=0:
        bpp = 32
    else:
        bpp = 24
    log("rgb_encode using level=%s, %s compressed %sx%s in %s/%s: %s bytes down to %s", level, algo, image.get_width(), image.get_height(), coding, pixel_format, len(pixels), len(raw_data))
    if not encoding_client_options or not supports_rgb24zlib:
        return  coding, wire_data, {}, width, height, stride, bpp
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, Compressed(coding, raw_data), options, width, height, stride, bpp