Skip to content

Commit

Permalink
#1123 move mdns code to server, separate it from socket creation
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@22683 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed May 9, 2019
1 parent 9309f90 commit 072ba6b
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 83 deletions.
71 changes: 8 additions & 63 deletions src/xpra/scripts/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,12 +347,6 @@ def hosts(host_str):
return ["0.0.0.0", "::"]
return [host_str]

def add_mdns(mdns_recs, socktype, host_str, port):
recs = mdns_recs.setdefault(socktype.lower(), [])
for host in hosts(host_str):
rec = (host, port)
if rec not in recs:
recs.append(rec)

def create_sockets(opts, error_cb):
from xpra.server.socket_util import (
Expand All @@ -370,11 +364,8 @@ def create_sockets(opts, error_cb):
bind_rfb = parse_bind_ip(opts.bind_rfb, 5900)
bind_vsock = parse_bind_vsock(opts.bind_vsock)

mdns_recs = {}
sockets = []

rfb_upgrades = int(opts.rfb_upgrade)>0
ssl_opt = opts.ssl.lower()
min_port = int(opts.min_port)
def add_tcp_socket(socktype, host_str, iport):
if iport!=0 and iport<min_port:
Expand All @@ -383,19 +374,16 @@ def add_tcp_socket(socktype, host_str, iport):
socket = setup_tcp_socket(host, iport, socktype)
host, iport = socket[2]
sockets.append(socket)
add_mdns(mdns_recs, socktype, host, iport)
def add_udp_socket(socktype, host_str, iport):
if iport!=0 and iport<min_port:
error_cb("invalid %s port number %i (minimum value is %i)" % (socktype, iport, min_port))
for host in hosts(host_str):
socket = setup_udp_socket(host, iport, socktype)
host, iport = socket[2]
sockets.append(socket)
add_mdns(mdns_recs, socktype, host, iport)
# Initialize the TCP sockets before the display,
# That way, errors won't make us kill the Xvfb
# (which may not be ours to kill at that point)
ws_upgrades = opts.html and (os.path.isabs(opts.html) or opts.html.lower() in list(TRUE_OPTIONS)+["auto"])
ssh_upgrades = opts.ssh_upgrade
if ssh_upgrades:
try:
Expand All @@ -412,45 +400,28 @@ def add_udp_socket(socktype, host_str, iport):
log("setting up SSL sockets: %s", csv(bind_ssl))
for host, iport in bind_ssl:
add_tcp_socket("ssl", host, iport)
if ws_upgrades:
add_mdns(mdns_recs, "wss", host, iport)
log("setting up SSH sockets: %s", csv(bind_ssh))
for host, iport in bind_ssh:
add_tcp_socket("ssh", host, iport)
log("setting up https / wss (secure websockets): %s", csv(bind_wss))
for host, iport in bind_wss:
add_tcp_socket("wss", host, iport)
tcp_ssl = ssl_opt in TRUE_OPTIONS or (ssl_opt=="auto" and opts.ssl_cert)
log("setting up TCP sockets: %s", csv(bind_tcp))
for host, iport in bind_tcp:
add_tcp_socket("tcp", host, iport)
if tcp_ssl:
add_mdns(mdns_recs, "ssl", host, iport)
if ws_upgrades:
add_mdns(mdns_recs, "ws", host, iport)
if ws_upgrades and tcp_ssl:
add_mdns(mdns_recs, "wss", host, iport)
if ssh_upgrades:
add_mdns(mdns_recs, "ssh", host, iport)
if rfb_upgrades:
add_mdns(mdns_recs, "rfb", host, iport)
log("setting up UDP sockets: %s", csv(bind_udp))
for host, iport in bind_udp:
add_udp_socket("udp", host, iport)
log("setting up http / ws (websockets): %s", csv(bind_ws))
for host, iport in bind_ws:
add_tcp_socket("ws", host, iport)
if tcp_ssl:
add_mdns(mdns_recs, "wss", host, iport)
log("setting up rfb sockets: %s", csv(bind_rfb))
for host, iport in bind_rfb:
add_tcp_socket("rfb", host, iport)
add_mdns(mdns_recs, "rfb", host, iport)
log("setting up vsock sockets: %s", csv(bind_vsock))
for cid, iport in bind_vsock:
socket = setup_vsock_socket(cid, iport)
sockets.append(socket)
#add_mdns(mdns_recs, "vsock", str(cid), iport)

# systemd socket activation:
if POSIX:
Expand All @@ -464,10 +435,7 @@ def add_udp_socket(socktype, host_str, iport):
for stype, socket, addr in sd_sockets:
sockets.append(setup_sd_listen_socket(stype, socket, addr))
log("%s : %s", (stype, [addr]), socket)
if stype=="tcp":
host, iport = addr
add_mdns(mdns_recs, "tcp", host, iport)
return sockets, mdns_recs
return sockets

def run_server(error_cb, opts, mode, xpra_file, extra_args, desktop_display=None):
#add finally hook to ensure we will run the cleanups
Expand Down Expand Up @@ -723,9 +691,7 @@ def do_run_server(error_cb, opts, mode, xpra_file, extra_args, desktop_display=N
if (starting or starting_desktop) and desktop_display and opts.notifications and not opts.dbus_launch:
print_DE_warnings()

from xpra.log import Logger
log = Logger("server")
sockets, mdns_recs = create_sockets(opts, error_cb)
sockets = create_sockets(opts, error_cb)

sanitize_env()
if POSIX:
Expand All @@ -744,6 +710,8 @@ def do_run_server(error_cb, opts, mode, xpra_file, extra_args, desktop_display=N
except KeyError:
pass
os.environ.update(protected_env)
from xpra.log import Logger
log = Logger("server")
log("env=%s", os.environ)

UINPUT_UUID_LEN = 12
Expand Down Expand Up @@ -914,14 +882,9 @@ def noerr(fn, *args):
opts.mmap_group, opts.socket_permissions,
username, uid, gid)
netlog("setting up local sockets: %s", local_sockets)
ssh_port = get_ssh_port()
ssh_access = ssh_port>0 and opts.ssh.lower().strip() not in FALSE_OPTIONS
for socktype, socket, sockpath, cleanup_socket in local_sockets:
sockets.append((socktype, socket, sockpath, cleanup_socket))
netlog("%s %s : %s", socktype, sockpath, socket)
if opts.mdns and ssh_access:
netlog("ssh %s:%s : %s", "", ssh_port, socket)
add_mdns(mdns_recs, "ssh", "", ssh_port)
if POSIX and (starting or upgrading or starting_desktop or upgrading_desktop):
#all unix domain sockets:
ud_paths = [sockpath for stype, _, sockpath, _ in local_sockets if stype=="unix-domain"]
Expand Down Expand Up @@ -964,17 +927,20 @@ def noerr(fn, *args):
app.init_virtual_devices(devices)

try:
app.display_name = display_name
app.init(opts)
app.init_sockets(sockets)
app.init_dbus(dbus_pid, dbus_env)
if xvfb_pid or clobber:
app.init_display_pid(xvfb_pid)
app.original_desktop_display = desktop_display
app.exec_cwd = opts.chdir or cwd
app.init(opts)
del opts
if not app.server_ready():
return 1
app.server_init()
app.setup()
app.init_when_ready(_when_ready)
except InitException as e:
log.error("xpra server initialization error:")
log.error(" %s", e)
Expand All @@ -987,27 +953,6 @@ def noerr(fn, *args):
app.cleanup()
return 1

#publish mdns records:
if opts.mdns:
from xpra.platform.info import get_username
from xpra.server.socket_util import mdns_publish
mdns_info = {
"display" : display_name,
"username" : get_username(),
"uuid" : app.uuid,
"platform" : sys.platform,
"type" : app.session_type,
}
MDNS_EXPOSE_NAME = envbool("XPRA_MDNS_EXPOSE_NAME", True)
if MDNS_EXPOSE_NAME and app.session_name:
mdns_info["name"] = app.session_name
for mdns_mode, listen_on in mdns_recs.items():
mdns_publish(display_name, mdns_mode, listen_on, mdns_info)

del opts

app.init_when_ready(_when_ready)

try:
log("running %s", app.run)
r = app.run()
Expand Down
93 changes: 88 additions & 5 deletions src/xpra/server/server_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from xpra.platform import set_name
from xpra.platform.paths import get_app_dir
from xpra.os_util import (
filedata_nocrlf, get_machine_id, get_user_uuid, platform_name,
filedata_nocrlf, get_machine_id, get_user_uuid, platform_name, get_ssh_port,
strtobytes, bytestostr, get_hex_uuid,
getuid, monotonic_time, get_peercred, hexstr,
WIN32, POSIX, PYTHON3, BITS,
Expand All @@ -58,6 +58,7 @@
authlog = Logger("auth")
timeoutlog = Logger("timeout")
dbuslog = Logger("dbus")
mdnslog = Logger("mdns")

main_thread = threading.current_thread()

Expand Down Expand Up @@ -174,9 +175,6 @@ def nn(x):
log.error("failed to get frame info: %s", e)
return info

def notimplemented(*_args):
raise NotImplementedError()


class ServerCore(object):
"""
Expand All @@ -193,6 +191,7 @@ def __init__(self):
self.child_reaper = None
self.original_desktop_display = None
self.session_type = "unknown"
self.display_name = ""

self._closing = False
self._upgrading = False
Expand All @@ -204,7 +203,7 @@ def __init__(self):
self._tcp_proxy_clients = []
self._tcp_proxy = ""
self._rfb_upgrade = 0
self._ssl_wrap_socket = notimplemented
self._ssl_wrap_socket = None
self._accept_timeout = SOCKET_TIMEOUT + 1
self.ssl_mode = None
self._html = False
Expand Down Expand Up @@ -233,6 +232,7 @@ def __init__(self):
self.session_name = u""

#Features:
self.mdns = False
self.encryption = None
self.encryption_keyfile = None
self.tcp_encryption = None
Expand Down Expand Up @@ -290,6 +290,7 @@ def init(self, opts):
self.ssh_upgrade = opts.ssh_upgrade
self.dbus_control = opts.dbus_control
self.pidfile = opts.pidfile
self.mdns = opts.mdns
self.init_html_proxy(opts)
self.init_auth(opts)
self.init_ssl(opts)
Expand Down Expand Up @@ -326,6 +327,7 @@ def server_ready(self):
return True

def server_init(self):
self.mdns_publish()
self.start_listen_sockets()

def setup(self):
Expand Down Expand Up @@ -420,6 +422,7 @@ def cleanup(self):
p.quit()
netlog("cleanup will disconnect: %s", self._potential_protocols)
self.cancel_touch_timer()
self.mdns_cleanup()
if self._upgrading:
reason = SERVER_UPGRADE
else:
Expand Down Expand Up @@ -725,6 +728,84 @@ def init_sockets(self, sockets):
self._socket_info = sockets


def mdns_publish(self):
from xpra.scripts.server import hosts
#find all the records we want to publish:
mdns_recs = {}
for socktype, _, info, _ in self._socket_info:
socktypes = self.get_mdns_socktypes(socktype)
mdnslog("mdns_publish() info=%s, socktypes(%s)=%s", info, socktype, socktypes)
for st in socktypes:
recs = mdns_recs.setdefault(st, [])
if socktype=="unix-domain":
assert st=="ssh"
host = "*"
iport = get_ssh_port()
else:
host, iport = info
for h in hosts(host):
rec = (h, iport)
if rec not in recs:
recs.append(rec)
mdnslog("mdns_publish() recs[%s]=%s", st, recs)
from xpra.server.socket_util import mdns_publish
mdns_info = self.get_mdns_info()
MDNS_EXPOSE_NAME = envbool("XPRA_MDNS_EXPOSE_NAME", True)
if MDNS_EXPOSE_NAME and self.session_name:
mdns_info["name"] = self.session_name
self.mdns_publishers = []
for mdns_mode, listen_on in mdns_recs.items():
ap = mdns_publish(self.display_name, mdns_mode, listen_on, mdns_info)
ap.start()
self.mdns_publishers.append(ap)

def get_mdns_socktypes(self, socktype):
#for a given socket type,
#what socket types we should expose via mdns
if socktype in ("vsock", "named-pipe"):
#cannot be accessed remotely
return ()
ssh_access = get_ssh_port()>0 #and opts.ssh.lower().strip() not in FALSE_OPTIONS
ssl = bool(self._ssl_wrap_socket)
#only available with the RFBServer
rfb_upgrades = getattr(self, "_rfb_upgrade", False)
socktypes = [socktype]
if socktype=="tcp":
if ssl:
socktypes.append("ssl")
if self._html:
socktypes.append("ws")
if self._html and ssl:
socktypes.append("wss")
if self.ssh_upgrade:
socktypes.append("ssh")
if rfb_upgrades:
socktypes.append("rfb")
elif socktype=="ws":
if ssl:
socktypes.append("wss")
elif socktype=="unix-domain":
if ssh_access:
socktypes = ["ssh"]
return socktypes

def get_mdns_info(self):
from xpra.platform.info import get_username
return {
"display" : self.display_name,
"username" : get_username(),
"uuid" : self.uuid,
"platform" : sys.platform,
"type" : self.session_type,
}

def mdns_cleanup(self):
mp = self.mdns_publishers
self.mdns_publishers = []
for ap in mp:
ap.stop()


def start_listen_sockets(self):
### All right, we're ready to accept customers:
for socktype, sock, info, _ in self._socket_info:
Expand Down Expand Up @@ -948,6 +1029,8 @@ def handle_new_connection(self, conn, sock, address, socktype, peername, socket_
peek_data, line1 = self.peek_connection(conn, PEEK_TIMEOUT)

def ssl_wrap():
if not self._ssl_wrap_socket:
raise Exception("no ssl support")
ssl_sock = self._ssl_wrap_socket(sock)
ssllog("ssl wrapped socket(%s)=%s", sock, ssl_sock)
if ssl_sock is None:
Expand Down
6 changes: 1 addition & 5 deletions src/xpra/server/server_util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This file is part of Xpra.
# Copyright (C) 2017-2018 Antoine Martin <[email protected]>
# Copyright (C) 2017-2019 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

Expand All @@ -12,10 +12,6 @@
from xpra.scripts.config import InitException


def add_cleanup(fn):
from xpra.scripts.server import add_cleanup as ac
ac(fn)

def sh_quotemeta(s):
return "'" + s.replace("'", "'\\''") + "'"

Expand Down
Loading

0 comments on commit 072ba6b

Please sign in to comment.