xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #1213: https.patch

File https.patch, 9.1 KB (added by Antoine Martin, 5 years ago)

very hackish patch which sort of works for https but not for wss

  • xpra/server/server_core.py

     
    3131from xpra.scripts.config import InitException, parse_bool
    3232from xpra.net.bytestreams import SocketConnection, log_new_connection, inject_ssl_socket_info, pretty_socket, SOCKET_TIMEOUT
    3333from xpra.platform import set_name
    34 from xpra.os_util import load_binary_file, get_machine_id, get_user_uuid, platform_name, SIGNAMES
     34from xpra.os_util import load_binary_file, get_machine_id, get_user_uuid, platform_name, Queue, SIGNAMES
    3535from xpra.version_util import version_compat_check, get_version_info_full, get_platform_info, get_host_info, local_version
    3636from xpra.net.protocol import Protocol, get_network_caps, sanity_checks
    3737from xpra.net.crypto import crypto_backend_init, new_cipher_caps, \
     
    548548            netlog.error("Error: %s connection failed:", socktype)
    549549            netlog.error(" %s", msg)
    550550            if conn.remote:
    551                 netlog.error(" %s", conn.remote)
     551                netlog.error(" %s", pretty_socket(conn.remote))
    552552            try:
    553553                sock.settimeout(1)
    554554                conn.write("disconnect: %s?\n" % msg)
     
    570570            except IOError as e:
    571571                netlog("socket wrapping failed", exc_info=True)
    572572                conn_err(str(e))
     573                return
    573574        if v and v[0] not in ("P", ord("P")):
    574575            try:
    575576                c = ord(v[0])
     
    613614        protocol.start()
    614615        self.timeout_add(SOCKET_TIMEOUT*1000, self.verify_connection_accepted, protocol)
    615616
    616     def may_wrap_socket(self, conn, v):
     617    def may_wrap_socket(self, conn, v, read_data=None):
    617618        """
    618619            Returns:
    619620            * a flag indicating if we should continue processing this connection
     
    621622            * the connection object (which may now be wrapped, ie: for ssl)
    622623            * new peek data "v" (which may now be empty),
    623624        """
    624         if not v or v[0] in ("P", ord("P")):
     625        if not v:
     626            netlog("may_wrap_socket: no data, not wrapping")
     627            return True, conn, v
     628        if v[0] in ("P", ord("P")):
     629            netlog("may_wrap_socket: xpra protocol header '%s', not wrapping", v[0])
    625630            #xpra packet header, no need to wrap this connection
    626631            return True, conn, v
    627632        frominfo = pretty_socket(conn.remote)
    628633        if self._html:
    629634            line1 = v.splitlines()[0]
     635            netlog("line1=%s", repr_ellipsized(line1))
    630636            if line1.find("HTTP/")>0:
    631637                if line1.startswith("GET ") or line1.startswith("POST "):
    632638                    parts = line1.split(" ")
     
    636642                    netlog.info("New http connection received from %s", frominfo)
    637643                    tname = "websockify-proxy"
    638644                def run_websockify():
    639                     self.start_websockify(conn, conn.remote)
     645                    self.start_websockify(conn, conn.remote, read_data)
    640646                start_thread(run_websockify, "%s-for-%s" % (tname, frominfo), daemon=True)
    641647                return False, conn, None
    642648        if self._ssl_wrap_socket and v[0] in (chr(0x16), 0x16):
     
    645651            sock = self._ssl_wrap_socket(sock)
    646652            conn = SocketConnection(sock, sockname, address, target, socktype)
    647653            #we cannot peek on SSL sockets, just clear the unencrypted data:
     654            netlog("may_wrap_socket SSL: %s", conn)
    648655            return True, conn, None
    649656        elif self._tcp_proxy:
    650657            netlog.info("New tcp proxy connection received from %s", frominfo)
    651658            def run_proxy():
    652659                self.start_tcp_proxy(conn, conn.remote)
    653             start_thread(run_proxy, "tcp-proxy-for-%s" % frominfo, daemon=True)
     660            t = start_thread(run_proxy, "tcp-proxy-for-%s" % frominfo, daemon=True)
     661            netlog("may_wrap_socket handling via tcp proxy thread %s", t)
    654662            return False, conn, None
    655663        return True, conn, v
    656664
    657665    def invalid_header(self, proto, data):
    658         netlog("invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s, html=%s, ssl=%s", proto, len(data or ""), repr_ellipsized(data), proto.input_packetcount, self._tcp_proxy, self._html, bool(self._ssl_wrap_socket))
    659         err = "invalid packet format, not an xpra client?"
    660         proto.gibberish(err, data)
     666        netlog.warn("invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s, html=%s, ssl=%s", proto, len(data or ""), repr_ellipsized(data), proto.input_packetcount, self._tcp_proxy, self._html, bool(self._ssl_wrap_socket))
     667        read_data = Queue()
     668        read_data.put(data)
     669        def read_callback(packet):
     670            log.info("read_callback(%s)", nonl(packet))
     671            if packet:
     672                read_data.put(packet)
     673        conn = proto.steal_connection(read_callback)
     674        #conn = proto._conn
     675        #proto._read_queue_put = read_callback
     676        netlog.warn("invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s, html=%s, ssl=%s", proto, len(data or ""), repr_ellipsized(data), proto.input_packetcount, self._tcp_proxy, self._html, bool(self._ssl_wrap_socket))
     677        time.sleep(0.5)
     678        cont, _, data = self.may_wrap_socket(conn, data, read_data)
     679        if cont:
     680            err = "invalid packet format, not an xpra client?"
     681            proto.gibberish(err, data)
     682            #we've stolen the connection from the protocol,
     683            #so we have to close the connection directly:
     684            try:
     685                conn.close()
     686            except:
     687                pass
    661688
    662 
    663     def start_websockify(self, conn, frominfo):
    664         netlog("start_websockify(%s, %s) www dir=%s", conn, frominfo, self._www_dir)
     689    def start_websockify(self, conn, frominfo, read_data=None):
     690        netlog("start_websockify(%s, %s, %s) www dir=%s", conn, frominfo, nonl(read_data), self._www_dir)
    665691        from xpra.net.websocket import WebSocketConnection, WSRequestHandler
    666692        try:
    667693            sock = conn._socket
    668694            sock.setblocking(1)
    669             if sys.platform.startswith("win"):
    670                 from xpra.net.bytestreams import untilConcludes
    671                 #workaround for win32 servers (this should not be needed on any other platform)
    672                 #which don't seem to honour our request to use blocking sockets
    673                 #maybe this should go in websockify somewhere?
     695            #sock.settimeout(0)
     696            from xpra.net.bytestreams import untilConcludes
     697            #workaround for win32 servers (this should not be needed on any other platform)
     698            #which don't seem to honour our request to use blocking sockets
     699            #maybe this should go in websockify somewhere?
     700            #optionally, we can inject data which has already been read from the socket
     701            if sys.platform.startswith("win") or read_data:
    674702                saved_recv = sock.recv
    675703                saved_send = sock.send
    676                 def recv(*args):
    677                     return untilConcludes(conn.is_active, saved_recv, *args)
     704                saved_makefile = sock.makefile
     705                def is_active(*args):
     706                    return True
     707                def makefile(self, mode='r', bufsize=-1):
     708                    traceback.print_stack()
     709                    log.warn("makefile%s" % ((mode, bufsize), ))
     710                    f = saved_makefile(mode, bufsize)
     711                    if mode==-1:
     712                        while not read_data.empty():
     713                            f._rbuf.write(read_data.get())
     714                    return f
     715                    #TODO: append to rbuf:
     716                    #self._rbuf
     717                #proto._read_queue_put = read_callback
     718                def recv(bufsize, *args):
     719                    log.info("recv(%i, %s)", bufsize, args)
     720                    #if read_data and read_data.qsize()>0:
     721                    #return read_data.get()
     722                    return saved_recv(bufsize, *args)
     723                    #return untilConcludes(conn.is_active, saved_recv, bufsize, *args)
    678724                def send(*args):
    679                     return untilConcludes(conn.is_active, saved_send, *args)
     725                    return saved_send(*args)
     726                    #return untilConcludes(conn.is_active, saved_send, *args)
    680727                sock.recv = recv
    681728                sock.send = send
     729                sock.makefile = makefile
    682730            def new_websocket_client(wsh):
    683731                netlog("new_websocket_client(%s) socket=%s", wsh, sock)
    684732                wsc = WebSocketConnection(sock, conn.local, conn.remote, conn.target, conn.info, wsh)
  • xpra/net/websocket.py

     
    2929        self._new_websocket_client = new_websocket_client
    3030        server = AdHocStruct()
    3131        server.logger = log
    32         server.run_once = True
     32        server.run_once = False
    3333        server.verbose = WEBSOCKET_DEBUG
    3434        WebSocketRequestHandler.__init__(self, sock, addr, server)
    3535