xpra icon
Bug tracker and wiki

Ticket #1504: ssl-late-wrap.patch

File ssl-late-wrap.patch, 24.8 KB (added by Antoine Martin, 3 years ago)

work in progress patch - also adds bind-ws and bind-wss options

  • xpra/net/bytestreams.py

     
    345345                }
    346346
    347347
     348def get_ssl_socket_info(s):
     349    d = {"ssl" : True}
     350    if not s:
     351        return d
     352    for k,fn in {
     353                 "compression"      : "compression",
     354                 "alpn-protocol"    : "selected_alpn_protocol",
     355                 "npn-protocol"     : "selected_npn_protocol",
     356                 "version"          : "version",
     357                 }.items():
     358        sfn = getattr(s, fn, None)
     359        if sfn:
     360            v = sfn()
     361            if v is not None:
     362                d[k] = v
     363    cipher_fn = getattr(s, "cipher", None)
     364    if cipher_fn:
     365        cipher = cipher_fn()
     366        if cipher:
     367            d["cipher"] = {
     368                           "name"       : cipher[0],
     369                           "protocol"   : cipher[1],
     370                           "bits"       : cipher[2],
     371                           }
     372    return d
    348373
     374class SSLSocketConnection(SocketConnection):
     375
     376    def get_info(self):
     377        i = SocketConnection.get_info(self)
     378        i.update(get_ssl_socket_info(self._socket))
     379        return i
     380
     381
    349382def set_socket_timeout(conn, timeout=None):
    350383    #FIXME: this is ugly, but less intrusive than the alternative?
    351384    log("set_socket_timeout(%s, %s)", conn, timeout)
     
    365398    log("ssl=%s, socket class=%s", ssl, type(sock))
    366399    if ssl and isinstance(sock, ssl.SSLSocket):
    367400        #inject extra ssl info into the socket class:
    368         def get_ssl_socket_info(sock):
     401        def _get_ssl_socket_info(sock):
    369402            d = sock.do_get_socket_info()
    370             d["ssl"] = True
    371             s = sock._socket
    372             if not s:
    373                 return d
    374             for k,fn in {
    375                          "compression"      : "compression",
    376                          "alpn-protocol"    : "selected_alpn_protocol",
    377                          "npn-protocol"     : "selected_npn_protocol",
    378                          "version"          : "version",
    379                          }.items():
    380                 sfn = getattr(s, fn, None)
    381                 if sfn:
    382                     v = sfn()
    383                     if v is not None:
    384                         d[k] = v
    385             cipher_fn = getattr(s, "cipher", None)
    386             if cipher_fn:
    387                 cipher = cipher_fn()
    388                 if cipher:
    389                     d["cipher"] = {
    390                                    "name"       : cipher[0],
    391                                    "protocol"   : cipher[1],
    392                                    "bits"       : cipher[2],
    393                                    }
     403            d.update(get_ssl_socket_info(sock._socket))
    394404            return d
    395         conn.get_socket_info = types.MethodType(get_ssl_socket_info, conn)
     405        conn.get_socket_info = types.MethodType(_get_ssl_socket_info, conn)
    396406
     407
    397408def log_new_connection(conn):
    398409    """ logs the new connection message """
    399410    sock = conn._socket
  • xpra/scripts/config.py

     
    437437                    "auth"              : str,
    438438                    "vsock-auth"        : str,
    439439                    "tcp-auth"          : str,
     440                    "ws-auth"           : str,
     441                    "wss-auth"          : str,
    440442                    "ssl-auth"          : str,
    441443                    "wm-name"           : str,
    442444                    "session-name"      : str,
     
    590592                    "bind"              : list,
    591593                    "bind-vsock"        : list,
    592594                    "bind-tcp"          : list,
     595                    "bind-ws"           : list,
     596                    "bind-wss"          : list,
    593597                    "bind-ssl"          : list,
    594598                    "start-env"         : list,
    595599                    "env"               : list,
     
    608612    "start-after-connect", "start-child-after-connect",
    609613    "start-on-connect", "start-child-on-connect",
    610614    ]
    611 BIND_OPTIONS = ["bind", "bind-tcp", "bind-ssl", "bind-vsock"]
     615BIND_OPTIONS = ["bind", "bind-tcp", "bind-ssl", "bind-ws", "bind-wss", "bind-vsock"]
    612616
    613617#keep track of the options added since v1,
    614618#so we can generate command lines that work with older supported versions:
     
    672676    "av-sync", "global-menus",
    673677    "printing", "file-transfer", "open-command", "open-files", "start-new-commands",
    674678    "mmap", "mmap-group", "mdns",
    675     "auth", "vsock-auth", "tcp-auth", "ssl-auth",
    676     "bind", "bind-vsock", "bind-tcp", "bind-ssl",
     679    "auth", "vsock-auth", "tcp-auth", "ws-auth", "wss-auth", "ssl-auth",
     680    "bind", "bind-vsock", "bind-tcp", "bind-ssl", "bind-ws", "bind-wss",
    677681    "start", "start-child",
    678682    "start-after-connect", "start-child-after-connect",
    679683    "start-on-connect", "start-child-on-connect",
     
    792796                    "auth"              : "",
    793797                    "vsock-auth"        : "",
    794798                    "tcp-auth"          : "",
     799                    "ws-auth"           : "",
     800                    "wss-auth"          : "",
    795801                    "ssl-auth"          : "",
    796802                    "wm-name"           : DEFAULT_NET_WM_NAME,
    797803                    "session-name"      : "",
     
    935941                    "bind"              : bind_dirs,
    936942                    "bind-vsock"        : [],
    937943                    "bind-tcp"          : [],
     944                    "bind-ws"           : [],
     945                    "bind-wss"          : [],
    938946                    "bind-ssl"          : [],
    939947                    "start"             : [],
    940948                    "start-child"       : [],
  • xpra/scripts/main.py

     
    527527                          metavar="[HOST]:[PORT]",
    528528                          help="Listen for connections over TCP (use --tcp-auth to secure it)."
    529529                            + " You may specify this option multiple times with different host and port combinations")
     530        group.add_option("--bind-ws", action="append",
     531                          dest="bind_ws", default=list(defaults.bind_ws or []),
     532                          metavar="[HOST]:[PORT]",
     533                          help="Listen for connections over Websocket (use --ws-auth to secure it)."
     534                            + " You may specify this option multiple times with different host and port combinations")
     535        group.add_option("--bind-wss", action="append",
     536                          dest="bind_wss", default=list(defaults.bind_wss or []),
     537                          metavar="[HOST]:[PORT]",
     538                          help="Listen for connections over HTTPS / wss (secure Websocket). Use --wss-auth to secure it."
     539                            + " You may specify this option multiple times with different host and port combinations")
    530540        group.add_option("--bind-ssl", action="append",
    531541                          dest="bind_ssl", default=list(defaults.bind_ssl or []),
    532542                          metavar="[HOST]:PORT",
    533                           help="Listen for connections over SSL (use --ssl-auth to secure it)."
     543                          help="Listen for connections over SSL. Use --ssl-auth to secure it."
    534544                            + " You may specify this option multiple times with different host and port combinations")
    535545    else:
    536         ignore({"bind"      : defaults.bind})
    537         ignore({"bind-tcp"  : defaults.bind_tcp})
    538         ignore({"bind-ssl"  : defaults.bind_ssl})
     546        ignore({
     547            "bind"      : defaults.bind,
     548            "bind-tcp"  : defaults.bind_tcp,
     549            "bind-ws"   : defaults.bind_ws,
     550            "bind-wss"  : defaults.bind_wss,
     551            "bind-ssl"  : defaults.bind_ssl,
     552            })
    539553    try:
    540554        from xpra.net import vsock
    541555    except:
     
    947961    group.add_option("--tcp-auth", action="store",
    948962                      dest="tcp_auth", default=defaults.tcp_auth,
    949963                      help="The authentication module to use for TCP sockets (default: '%default')")
     964    group.add_option("--ws-auth", action="store",
     965                      dest="ws_auth", default=defaults.ws_auth,
     966                      help="The authentication module to use for Websockets (default: '%default')")
     967    group.add_option("--wss-auth", action="store",
     968                      dest="wss_auth", default=defaults.wss_auth,
     969                      help="The authentication module to use for Secure Websockets (default: '%default')")
    950970    group.add_option("--ssl-auth", action="store",
    951971                      dest="ssl_auth", default=defaults.ssl_auth,
    952972                      help="The authentication module to use for SSL sockets (default: '%default')")
  • xpra/scripts/server.py

     
    361361    from xpra.server.socket_util import parse_bind_tcp, parse_bind_vsock
    362362    bind_tcp = parse_bind_tcp(opts.bind_tcp)
    363363    bind_ssl = parse_bind_tcp(opts.bind_ssl)
     364    bind_ws = parse_bind_tcp(opts.bind_ws)
     365    bind_wss = parse_bind_tcp(opts.bind_wss)
    364366    bind_vsock = parse_bind_vsock(opts.bind_vsock)
    365367
    366368    assert mode in ("start", "start-desktop", "upgrade", "shadow", "proxy")
     
    541543    wrap_socket_fn = None
    542544    need_ssl = False
    543545    ssl_opt = opts.ssl.lower()
    544     if ssl_opt in TRUE_OPTIONS or bind_ssl:
     546    if ssl_opt in TRUE_OPTIONS or bind_ssl or bind_wss:
    545547        need_ssl = True
    546548    if opts.bind_tcp:
    547549        if ssl_opt=="auto" and opts.ssl_cert:
     
    560562            cpaths = csv("'%s'" % x for x in (opts.ssl_cert, opts.ssl_key) if x)
    561563            raise InitException("cannot create SSL socket, check your certificate paths (%s): %s" % (cpaths, e))
    562564
     565    # Initialize the TCP sockets before the display,
     566    # That way, errors won't make us kill the Xvfb
     567    # (which may not be ours to kill at that point)
    563568    from xpra.server.socket_util import setup_tcp_socket, setup_vsock_socket, setup_local_sockets
    564569    netlog("setting up SSL sockets: %s", bind_ssl)
    565570    for host, iport in bind_ssl:
    566         _, tcp_socket, host_port = setup_tcp_socket(host, iport, "SSL")
    567         socket = ("SSL", wrap_socket_fn(tcp_socket), host_port)
     571        socket = setup_tcp_socket(host, iport, "SSL")
    568572        sockets.append(socket)
    569573        rec = "ssl", [(host, iport)]
    570574        netlog("%s : %s", rec, socket)
    571575        mdns_recs.append(rec)
    572 
    573     # Initialize the TCP sockets before the display,
    574     # That way, errors won't make us kill the Xvfb
    575     # (which may not be ours to kill at that point)
     576    netlog("setting up secure websockets: %s", bind_tcp)
     577    for host, iport in bind_wss:
     578        socket = setup_tcp_socket(host, iport, "wss")
     579        sockets.append(socket)
     580        rec = "wss", [(host, iport)]
     581        netlog("%s : %s", rec, socket)
     582        mdns_recs.append(rec)
    576583    tcp_ssl = ssl_opt in TRUE_OPTIONS or (ssl_opt=="auto" and opts.ssl_cert)
    577     def add_tcp_mdns_rec(host, iport):
    578         rec = "tcp", [(host, iport)]
     584    def add_tcp_mdns_rec(host, iport, socktype="tcp", securesocktype="ssl"):
     585        rec = socktype, [(host, iport)]
    579586        netlog("%s : %s", rec, socket)
    580587        mdns_recs.append(rec)
    581588        if tcp_ssl:
    582             #SSL is also available on this TCP socket:
    583             rec = "ssl", [(host, iport)]
     589            #SSL is also available on this socket:
     590            rec = securesocktype, [(host, iport)]
    584591            netlog("%s : %s", rec, socket)
    585592            mdns_recs.append(rec)
    586593    netlog("setting up TCP sockets: %s", bind_tcp)
     
    588595        socket = setup_tcp_socket(host, iport)
    589596        sockets.append(socket)
    590597        add_tcp_mdns_rec(host, iport)
    591 
    592     # VSOCK:
     598    netlog("setting up websockets: %s", bind_ws)
     599    for host, iport in bind_ws:
     600        socket = setup_tcp_socket(host, iport, "ws")
     601        sockets.append(socket)
     602        add_tcp_mdns_rec(host, iport, "ws", "wss")
    593603    netlog("setting up vsock sockets: %s", bind_vsock)
    594604    for cid, iport in bind_vsock:
    595605        socket = setup_vsock_socket(cid, iport)
  • xpra/server/server_core.py

     
    2929from xpra.scripts.main import _socket_connect, full_version_str
    3030from xpra.scripts.server import deadly_signal
    3131from xpra.scripts.config import InitException, parse_bool, python_platform
    32 from xpra.net.bytestreams import SocketConnection, log_new_connection, inject_ssl_socket_info, pretty_socket, SOCKET_TIMEOUT
     32from xpra.net.bytestreams import SocketConnection, SSLSocketConnection, log_new_connection, inject_ssl_socket_info, pretty_socket, SOCKET_TIMEOUT
    3333from xpra.net.net_util import get_network_caps, get_info as get_net_info
    3434from xpra.platform import set_name
    3535from xpra.os_util import load_binary_file, get_machine_id, get_user_uuid, platform_name, bytestostr, get_hex_uuid, monotonic_time, get_peercred, SIGNAMES, WIN32, OSX, POSIX
     
    143143        self.start_time = monotonic_time()
    144144        self.auth_class = None
    145145        self.tcp_auth_class = None
     146        self.ws_auth_class = None
     147        self.wss_auth_class = None
    146148        self.ssl_auth_class = None
    147149        self.vsock_auth_class = None
    148150        self._when_ready = []
     
    284286    def init_auth(self, opts):
    285287        self.auth_class = self.get_auth_module("unix-domain", opts.auth, opts)
    286288        self.tcp_auth_class = self.get_auth_module("tcp", opts.tcp_auth or opts.auth, opts)
     289        self.ws_auth_class = self.get_auth_module("ws", opts.ws_auth, opts)
     290        self.wss_auth_class = self.get_auth_module("wss", opts.wss_auth, opts)
    287291        self.ssl_auth_class = self.get_auth_module("ssl", opts.ssl_auth or opts.tcp_auth or opts.auth, opts)
    288292        self.vsock_auth_class = self.get_auth_module("vsock", opts.vsock_auth, opts)
    289         authlog("init_auth(..) auth class=%s, tcp auth class=%s, ssl auth class=%s, vsock auth class=%s", self.auth_class, self.tcp_auth_class, self.ssl_auth_class, self.vsock_auth_class)
     293        authlog("init_auth(..) auth=%s, tcp auth=%s, ws auth=%s, wss auth=%s, ssl auth=%s, vsock auth=%s",
     294                self.auth_class, self.tcp_auth_class, self.ws_auth_class, self.wss_auth_class, self.ssl_auth_class, self.vsock_auth_class)
    290295
    291296    def get_auth_module(self, socket_type, auth_str, opts):
    292297        authlog("get_auth_module(%s, %s, {..})", socket_type, auth_str)
     
    584589            from xpra.platform.win32.namedpipes.connection import NamedPipeConnection
    585590            conn = NamedPipeConnection(listener.pipe_name, pipe_handle)
    586591            netlog.info("New %s connection received on %s", socktype, conn.target)
    587             return self.make_protocol(socktype, conn, frominfo=conn.target)
     592            return self.make_protocol(socktype, conn)
    588593
    589594        try:
    590595            sock, address = listener.accept()
     
    598603            peername = sock.getpeername()
    599604        except:
    600605            peername = str(address)
    601         sockname = sock.getsockname()
    602         target = peername or sockname
    603         sock.settimeout(self._socket_timeout)
    604606        #limit number of concurrent network connections:
    605         if socktype not in ("unix-domain", "named-pipe") and len(self._potential_protocols)>=self._max_connections:
     607        if socktype not in ("unix-domain", ) and len(self._potential_protocols)>=self._max_connections:
    606608            netlog.error("Error: too many connections (%i)", len(self._potential_protocols))
    607             netlog.error(" ignoring new one: %s", target)
     609            netlog.error(" ignoring new one: %s", peername)
    608610            sock.close()
    609611            return True
    610         netlog("new_connection(%s) sock=%s, timeout=%s, sockname=%s, address=%s, peername=%s. timeout=%s", args, sock, self._socket_timeout, sockname, address, peername, self._socket_timeout)
     612        sockname = sock.getsockname()
     613        target = peername or sockname
     614        sock.settimeout(self._socket_timeout)
     615        netlog("new_connection(%s) sock=%s, timeout=%s, address=%s, peername=%s. timeout=%s", args, sock, self._socket_timeout, address, peername, self._socket_timeout)
    611616        conn = SocketConnection(sock, sockname, address, target, socktype)
    612617
    613618        #from here on, we run in a thread, so we can poll (peek does)
    614         start_thread(self.handle_new_connection, "new-%s-connection" % socktype, True, args=(conn, sock, socktype))
     619        start_thread(self.handle_new_connection, "new-%s-connection" % socktype, True, args=(conn, sock, address, socktype, peername))
    615620        return True
    616621
    617     def handle_new_connection(self, conn, sock, socktype):
     622    def handle_new_connection(self, conn, sock, address, socktype, peername):
    618623        """
    619624            Use peek to decide what sort of connection this is,
    620625            and start the appropriate handler for it.
     
    631636                conn.close()
    632637            except Exception as e:
    633638                netlog("error sending '%s': %s", nonl(msg), e)
     639        sockname = sock.getsockname()
     640        target = peername or sockname
     641        sock.settimeout(self._socket_timeout)
     642
    634643        #peek so we can detect invalid clients early,
    635644        #or handle non-xpra traffic:
    636645        PEEK_SIZE = 8192
    637646        try:
    638             v = conn.peek(PEEK_SIZE)
     647            peek_data = conn.peek(PEEK_SIZE)
    639648        except:
    640             v = None
     649            peek_data = ""
     650        log.info("PEEK=%s", binascii.hexlify(peek_data))
     651
     652        if socktype=="SSL" or socktype=="wss":
     653            #always start by wrapping with SSL:
     654            ssl_sock = self._ssl_wrap_socket(sock)
     655            if ssl_sock is None:
     656                #None means EOF! (we don't want to import ssl bits here)
     657                netlog("ignoring SSL EOF error")
     658                return
     659            ssl_conn = SSLSocketConnection(ssl_sock, sockname, address, target, socktype)
     660            log_new_connection(conn)
     661            handle_as_https = False
     662            if socktype=="wss" or self.ssl_mode=="www":
     663                handle_as_https = True
     664            elif self.ssl_mode=="auto":
     665                #look for HTTPS request to handle:
     666                line1 = peek_data.splitlines()[0]
     667                httplog("line 1=%s", repr_ellipsized(line1))
     668                if line1.find("HTTP/")>0 or peek_data.find("\x08http/1.1")>0:
     669                    handle_as_https = True
     670            if handle_as_https:
     671                self.start_http_socket(ssl_conn, True, peek_data)
     672            else:
     673                self.make_protocol(socktype, ssl_conn)
     674            return
     675
     676        elif socktype=="ws":
     677            log_new_connection(conn)
     678            self.start_http_socket(conn, False, peek_data)
     679            return
     680
    641681        if socktype=="tcp" and (self._html or self._tcp_proxy or self._ssl_wrap_socket):
    642682            #see if the packet data is actually xpra or something else
    643683            #that we need to handle via a tcp proxy, ssl wrapper or the websockify adapter:
    644684            try:
    645                 cont, conn, v = self.may_wrap_socket(conn, socktype, v)
     685                cont, conn, v = self.may_wrap_socket(conn, socktype, peek_data)
    646686                if not cont:
    647687                    return
    648688            except IOError as e:
     
    653693            msg = self.guess_header_protocol(v)
    654694            conn_err("invalid packet header, %s" % msg)
    655695            return True
     696        conn = SocketConnection(sock, sockname, address, target, socktype)
    656697        sock.settimeout(self._socket_timeout)
    657698        inject_ssl_socket_info(conn)
    658699        log_new_connection(conn)
     
    659700        self.make_protocol(socktype, conn)
    660701
    661702
    662     def make_protocol(self, socktype, conn, frominfo=""):
     703    def make_protocol(self, socktype, conn):
     704        socktype = socktype.lower()
    663705        protocol = Protocol(self, conn, self.process_packet)
    664706        self._potential_protocols.append(protocol)
    665707        protocol.large_packets.append("info-response")
     
    671713            protocol.auth_class = self.tcp_auth_class
    672714            protocol.encryption = self.tcp_encryption
    673715            protocol.keyfile = self.tcp_encryption_keyfile
    674         elif socktype=="SSL":
     716        elif socktype=="ssl":
    675717            protocol.auth_class = self.ssl_auth_class
     718        elif socktype=="ws":
     719            protocol.auth_class = self.ws_auth_class
     720        elif socktype=="wss":
     721            protocol.auth_class = self.wss_auth_class
    676722        elif socktype=="vsock":
    677723            protocol.auth_class = self.vsock_auth_class
    678724        else:
     
    688734            protocol.set_cipher_in(protocol.encryption, DEFAULT_IV, password, DEFAULT_SALT, DEFAULT_ITERATIONS, INITIAL_PADDING)
    689735        protocol.start()
    690736        self.timeout_add(self._accept_timeout*1000, self.verify_connection_accepted, protocol)
     737        return protocol
    691738
    692739    def may_wrap_socket(self, conn, socktype, peek_data=""):
    693740        """
     
    725772            line1 = peek_data.splitlines()[0]
    726773            httplog("line 1=%s", repr_ellipsized(line1))
    727774            if line1.find("HTTP/")>0 or (is_ssl and (self.ssl_mode=="www" or (self.ssl_mode=="auto" and peek_data.find("\x08http/1.1")>0))):
    728                 http_proto = "http"+["","s"][int(is_ssl)]
    729                 if line1.startswith("GET ") or line1.startswith("POST "):
    730                     parts = line1.split(" ")
    731                     httplog("New %s %s request received from %s for '%s'", http_proto, parts[0], frominfo, parts[1])
    732                     tname = "%s-request" % parts[0]
    733                     req_info = "%s %s" % (http_proto, parts[0])
    734                 else:
    735                     httplog("New %s connection received from %s", http_proto, frominfo)
    736                     req_info = "ws"+["","s"][int(is_ssl)]
    737                     tname = "%s-proxy" % req_info
    738                 start_thread(self.start_websockify, "%s-for-%s" % (tname, frominfo), daemon=True, args=(conn, req_info, conn.remote))
     775                self.start_http_socket(conn, is_ssl, peek_data)
    739776                return False, conn, None
    740777        if self._tcp_proxy:
    741778            netlog.info("New tcp proxy connection received from %s", frominfo)
     
    767804            "/Info"         : self.http_info_request,
    768805            }
    769806
    770     def start_websockify(self, conn, req_info, frominfo):
    771         wslog("start_websockify(%s, %s, %s) www dir=%s", conn, req_info, frominfo, self._www_dir)
     807    def start_http_socket(self, conn, is_ssl=False, peek_data=""):
     808        frominfo = pretty_socket(conn.remote)
     809        line1 = peek_data.splitlines()[0]
     810        http_proto = "http"+["","s"][int(is_ssl)]
     811        if line1.startswith("GET ") or line1.startswith("POST "):
     812            parts = line1.split(" ")
     813            httplog("New %s %s request received from %s for '%s'", http_proto, parts[0], frominfo, parts[1])
     814            tname = "%s-request" % parts[0]
     815            req_info = "%s %s" % (http_proto, parts[0])
     816        else:
     817            httplog("New %s connection received from %s", http_proto, frominfo)
     818            req_info = "ws"+["","s"][int(is_ssl)]
     819            tname = "%s-proxy" % req_info
     820        #we start a new thread,
     821        #only so that the websocket handler thread is named correctly:
     822        start_thread(self.start_websockify, "%s-for-%s" % (tname, frominfo), daemon=True, args=(conn, is_ssl, req_info, conn.remote))
     823
     824    def start_websockify(self, conn, is_ssl, req_info, frominfo):
     825        wslog("start_websockify(%s, %s, %s, %s) www dir=%s", conn, is_ssl, req_info, frominfo, self._www_dir)
    772826        from xpra.net.websocket import WebSocketConnection, WSRequestHandler
    773827        try:
    774828            sock = conn._socket
     
    787841                    return untilConcludes(wsc.is_active, saved_send, *args)
    788842                sock.recv = recv
    789843                sock.send = send
    790                 self.make_protocol("tcp", wsc, frominfo)
     844                socktype = "ws%s" % ["","s"][int(is_ssl)]
     845                self.make_protocol(socktype, wsc)
    791846            scripts = self.get_http_scripts()
    792847            WSRequestHandler(sock, frominfo, new_websocket_client, self._www_dir, scripts)
    793848            return
  • xpra/server/socket_util.py

     
    9999    listener.bind(sockaddr)
    100100    return listener
    101101
    102 def setup_tcp_socket(host, iport, socktype="TCP"):
     102def setup_tcp_socket(host, iport, socktype="tcp"):
    103103    from xpra.log import Logger
    104104    log = Logger("network")
    105105    try:
     
    114114        except:
    115115            pass
    116116    add_cleanup(cleanup_tcp_socket)
    117     return "tcp", tcp_socket, (host, iport)
     117    return socktype, tcp_socket, (host, iport)
    118118
    119119
    120120def parse_bind_tcp(bind_tcp):