def run(self): debug("ProxyProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(), os.getuid(), os.getgid()) #change uid and gid: if os.getgid() != self.gid: os.setgid(self.gid) if os.getuid() != self.uid: os.setuid(self.uid) debug("ProxyProcess.run() new uid=%s, gid=%s", os.getuid(), os.getgid()) if self.env_options: #TODO: whitelist env update? os.environ.update(self.env_options) log.info("new proxy started for client %s and server %s", self.client_conn, self.server_conn) if not USE_THREADING: signal.signal(signal.SIGTERM, self.signal_quit) signal.signal(signal.SIGINT, self.signal_quit) debug("registered signal handler %s", self.signal_quit) make_daemon_thread(self.server_message_queue, "server message queue").start() self.main_queue = Queue() #setup protocol wrappers: self.server_packets = Queue(PROXY_QUEUE_SIZE) self.client_packets = Queue(PROXY_QUEUE_SIZE) self.client_protocol = Protocol(self, self.client_conn, self.process_client_packet, self.get_client_packet) self.client_protocol.restore_state(self.client_state) self.server_protocol = Protocol(self, self.server_conn, self.process_server_packet, self.get_server_packet) #server connection tweaks: self.server_protocol.large_packets.append("draw") self.server_protocol.large_packets.append("keymap-changed") self.server_protocol.large_packets.append("server-settings") self.server_protocol.set_compression_level( self.session_options.get("compression_level", 0)) debug("starting network threads") self.server_protocol.start() self.client_protocol.start() #forward the hello packet: hello_packet = ("hello", self.filter_client_caps(self.caps)) self.queue_server_packet(hello_packet) try: try: self.run_queue() except KeyboardInterrupt, e: self.stop(str(e)) finally: debug("ProxyProcess.run() ending %s", os.getpid())
def __init__(self, scheduler, conn, process_packet_cb, get_packet_cb=None): """ You must call this constructor and source_has_more() from the main thread. """ assert scheduler is not None assert conn is not None self.timeout_add = scheduler.timeout_add self.idle_add = scheduler.idle_add self._conn = conn if FAKE_JITTER > 0: from xpra.net.fake_jitter import FakeJitter fj = FakeJitter(self.timeout_add, process_packet_cb) self._process_packet_cb = fj.process_packet_cb else: self._process_packet_cb = process_packet_cb self._write_queue = Queue(1) self._read_queue = Queue(20) self._read_queue_put = self._read_queue.put # Invariant: if .source is None, then _source_has_more == False self._get_packet_cb = get_packet_cb #counters: self.input_stats = {} self.input_packetcount = 0 self.input_raw_packetcount = 0 self.output_stats = {} self.output_packetcount = 0 self.output_raw_packetcount = 0 #initial value which may get increased by client/server after handshake: self.max_packet_size = 256 * 1024 self.abs_max_packet_size = 256 * 1024 * 1024 self.large_packets = ["hello"] self.send_aliases = {} self.receive_aliases = {} self._log_stats = None #None here means auto-detect self._closed = False self.encoder = "none" self._encoder = self.noencode self.compressor = "none" self._compress = compression.nocompress self.compression_level = 0 self.cipher_in = None self.cipher_in_name = None self.cipher_in_block_size = 0 self.cipher_out = None self.cipher_out_name = None self.cipher_out_block_size = 0 self._write_lock = Lock() from xpra.daemon_thread import make_daemon_thread self._write_thread = make_daemon_thread(self._write_thread_loop, "write") self._read_thread = make_daemon_thread(self._read_thread_loop, "read") self._read_parser_thread = make_daemon_thread( self._read_parse_thread_loop, "parse") self._write_format_thread = make_daemon_thread( self._write_format_thread_loop, "format") self._source_has_more = threading.Event()
def run(self): debug("ProxyProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(), os.getuid(), os.getgid()) #change uid and gid: if os.getgid()!=self.gid: os.setgid(self.gid) if os.getuid()!=self.uid: os.setuid(self.uid) debug("ProxyProcess.run() new uid=%s, gid=%s", os.getuid(), os.getgid()) if self.env_options: #TODO: whitelist env update? os.environ.update(self.env_options) log.info("new proxy started for client %s and server %s", self.client_conn, self.server_conn) signal.signal(signal.SIGTERM, self.signal_quit) signal.signal(signal.SIGINT, self.signal_quit) debug("registered signal handler %s", self.signal_quit) make_daemon_thread(self.server_message_queue, "server message queue").start() self.main_queue = Queue() #setup protocol wrappers: self.server_packets = Queue(PROXY_QUEUE_SIZE) self.client_packets = Queue(PROXY_QUEUE_SIZE) self.client_protocol = Protocol(self, self.client_conn, self.process_client_packet, self.get_client_packet) self.client_protocol.restore_state(self.client_state) self.server_protocol = Protocol(self, self.server_conn, self.process_server_packet, self.get_server_packet) #server connection tweaks: self.server_protocol.large_packets.append("draw") self.server_protocol.large_packets.append("window-icon") self.server_protocol.large_packets.append("keymap-changed") self.server_protocol.large_packets.append("server-settings") self.server_protocol.set_compression_level(self.session_options.get("compression_level", 0)) self.lost_windows = set() self.encode_queue = Queue() self.encode_thread = make_daemon_thread(self.encode_loop, "encode") self.encode_thread.start() debug("starting network threads") self.server_protocol.start() self.client_protocol.start() #forward the hello packet: hello_packet = ("hello", self.filter_client_caps(self.caps)) self.queue_server_packet(hello_packet) try: try: self.run_queue() except KeyboardInterrupt, e: self.stop(str(e)) finally: debug("ProxyProcess.run() ending %s", os.getpid())
def __init__(self, scheduler, conn, process_packet_cb, get_packet_cb=None): """ You must call this constructor and source_has_more() from the main thread. """ assert scheduler is not None assert conn is not None self.timeout_add = scheduler.timeout_add self.idle_add = scheduler.idle_add self._conn = conn if FAKE_JITTER > 0: from xpra.net.fake_jitter import FakeJitter fj = FakeJitter(self.timeout_add, process_packet_cb) self._process_packet_cb = fj.process_packet_cb else: self._process_packet_cb = process_packet_cb self._write_queue = Queue(1) self._read_queue = Queue(20) self._read_queue_put = self._read_queue.put # Invariant: if .source is None, then _source_has_more == False self._get_packet_cb = get_packet_cb # counters: self.input_stats = {} self.input_packetcount = 0 self.input_raw_packetcount = 0 self.output_stats = {} self.output_packetcount = 0 self.output_raw_packetcount = 0 # initial value which may get increased by client/server after handshake: self.max_packet_size = 256 * 1024 self.abs_max_packet_size = 256 * 1024 * 1024 self.large_packets = ["hello"] self.send_aliases = {} self.receive_aliases = {} self._log_stats = None # None here means auto-detect self._closed = False self.encoder = "none" self._encoder = self.noencode self.compressor = "none" self._compress = compression.nocompress self.compression_level = 0 self.cipher_in = None self.cipher_in_name = None self.cipher_in_block_size = 0 self.cipher_out = None self.cipher_out_name = None self.cipher_out_block_size = 0 self._write_lock = Lock() from xpra.daemon_thread import make_daemon_thread self._write_thread = make_daemon_thread(self._write_thread_loop, "write") self._read_thread = make_daemon_thread(self._read_thread_loop, "read") self._read_parser_thread = make_daemon_thread(self._read_parse_thread_loop, "parse") self._write_format_thread = make_daemon_thread(self._write_format_thread_loop, "format") self._source_has_more = threading.Event()
def start_tcp_proxy(self, proto, data): log("start_tcp_proxy(%s, %s)", proto, data[:10]) client_connection = proto.steal_connection() self._potential_protocols.remove(proto) #connect to web server: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) host, port = self._tcp_proxy.split(":", 1) try: web_server_connection = _socket_connect(sock, (host, int(port)), "web-proxy-for-%s" % proto, "tcp") except: log.warn("failed to connect to proxy: %s:%s", host, port) proto.gibberish("invalid packet header", data) return log("proxy connected to tcp server at %s:%s : %s", host, port, web_server_connection) web_server_connection.write(data) p = XpraProxy(client_connection, web_server_connection) self._tcp_proxy_clients.append(p) def run_proxy(): p.run() log("run_proxy() %s ended", p) if p in self._tcp_proxy_clients: self._tcp_proxy_clients.remove(p) t = make_daemon_thread(run_proxy, "web-proxy-for-%s" % proto) t.start() log.info("client %s forwarded to proxy server %s:%s", client_connection, host, port)
def start(self): if self.last_UI_thread_time>0: log.warn("UI thread watcher already started!") return #run once to initialize: self.UI_thread_wakeup() if self.polling_timeout>0: make_daemon_thread(self.poll_UI_loop, "UI thread polling").start() else: log("not starting an IO polling thread") if FAKE_UI_LOCKUPS>0: #watch out: sleeping in UI thread! def sleep_in_ui_thread(*args): time.sleep(FAKE_UI_LOCKUPS) return True self.timeout_add((10+FAKE_UI_LOCKUPS)*1000, sleep_in_ui_thread)
def start_tcp_proxy(self, proto, data): log("start_tcp_proxy(%s, %s)", proto, data[:10]) #any buffers read after we steal the connection will be placed in this temporary queue: temp_read_buffer = Queue() client_connection = proto.steal_connection(temp_read_buffer.put) try: self._potential_protocols.remove(proto) except: pass #might already have been removed by now #connect to web server: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) host, port = self._tcp_proxy.split(":", 1) try: web_server_connection = _socket_connect(sock, (host, int(port)), "web-proxy-for-%s" % proto, "tcp") except: log.warn("failed to connect to proxy: %s:%s", host, port) proto.gibberish("invalid packet header", data) return log("proxy connected to tcp server at %s:%s : %s", host, port, web_server_connection) sock.settimeout(self._socket_timeout) ioe = proto.wait_for_io_threads_exit(0.5 + self._socket_timeout) if not ioe: log.warn("proxy failed to stop all existing network threads!") self.disconnect_protocol(proto, "internal threading error") return #now that we own it, we can start it again: client_connection.set_active(True) #and we can use blocking sockets: self.set_socket_timeout(client_connection, None) #prevent deadlocks on exit: sock.settimeout(1) log("pushing initial buffer to its new destination: %s", repr_ellipsized(data)) web_server_connection.write(data) while not temp_read_buffer.empty(): buf = temp_read_buffer.get() if buf: log("pushing read buffer to its new destination: %s", repr_ellipsized(buf)) web_server_connection.write(buf) p = XpraProxy(client_connection, web_server_connection) self._tcp_proxy_clients.append(p) def run_proxy(): p.run() log("run_proxy() %s ended", p) if p in self._tcp_proxy_clients: self._tcp_proxy_clients.remove(p) t = make_daemon_thread(run_proxy, "web-proxy-for-%s" % proto) t.start() log.info("client %s forwarded to proxy server %s:%s", client_connection, host, port)
def start(self): if self.last_UI_thread_time > 0: log.warn("UI thread watcher already started!") return #run once to initialize: self.UI_thread_wakeup() if self.polling_timeout > 0: make_daemon_thread(self.poll_UI_loop, "UI thread polling").start() else: log("not starting an IO polling thread") if FAKE_UI_LOCKUPS > 0: #watch out: sleeping in UI thread! def sleep_in_ui_thread(*args): time.sleep(FAKE_UI_LOCKUPS) return True self.timeout_add((10 + FAKE_UI_LOCKUPS) * 1000, sleep_in_ui_thread)
def __init__(self, conn, process_packet_cb, get_packet_cb=None): """ You must call this constructor and source_has_more() from the main thread. """ assert conn is not None self._conn = conn if FAKE_JITTER > 0: fj = FakeJitter(process_packet_cb) self._process_packet_cb = fj.process_packet_cb else: self._process_packet_cb = process_packet_cb self._write_queue = Queue(1) self._read_queue = Queue(20) # Invariant: if .source is None, then _source_has_more == False self._get_packet_cb = get_packet_cb #counters: self.input_packetcount = 0 self.input_raw_packetcount = 0 self.output_packetcount = 0 self.output_raw_packetcount = 0 #initial value which may get increased by client/server after handshake: self.max_packet_size = 32 * 1024 self.large_packets = ["hello"] self.aliases = {} self.chunked_compression = True self._closed = False self._encoder = self.bencode self._decompressor = decompressobj() self._compression_level = 0 self.cipher_in = None self.cipher_in_name = None self.cipher_in_block_size = 0 self.cipher_out = None self.cipher_out_name = None self.cipher_out_block_size = 0 self._write_lock = Lock() self._write_thread = make_daemon_thread(self._write_thread_loop, "write") self._read_thread = make_daemon_thread(self._read_thread_loop, "read") self._read_parser_thread = make_daemon_thread( self._read_parse_thread_loop, "parse") self._write_format_thread = make_daemon_thread( self._write_format_thread_loop, "format") self._source_has_more = threading.Event()
def __init__(self, conn, process_packet_cb, get_packet_cb=None): """ You must call this constructor and source_has_more() from the main thread. """ assert conn is not None self._conn = conn if FAKE_JITTER>0: fj = FakeJitter(process_packet_cb) self._process_packet_cb = fj.process_packet_cb else: self._process_packet_cb = process_packet_cb self._write_queue = Queue(1) self._read_queue = Queue(20) # Invariant: if .source is None, then _source_has_more == False self._get_packet_cb = get_packet_cb #counters: self.input_packetcount = 0 self.input_raw_packetcount = 0 self.output_packetcount = 0 self.output_raw_packetcount = 0 #initial value which may get increased by client/server after handshake: self.max_packet_size = 32*1024 self.large_packets = ["hello"] self.aliases = {} self.chunked_compression = True self._closed = False self._encoder = self.bencode self._decompressor = decompressobj() self._compression_level = 0 self.cipher_in = None self.cipher_in_name = None self.cipher_in_block_size = 0 self.cipher_out = None self.cipher_out_name = None self.cipher_out_block_size = 0 self._write_lock = Lock() self._write_thread = make_daemon_thread(self._write_thread_loop, "write") self._read_thread = make_daemon_thread(self._read_thread_loop, "read") self._read_parser_thread = make_daemon_thread(self._read_parse_thread_loop, "parse") self._write_format_thread = make_daemon_thread(self._write_format_thread_loop, "format") self._source_has_more = threading.Event()
def start_tcp_proxy(self, proto, data): log("start_tcp_proxy(%s, %s)", proto, data[:10]) #any buffers read after we steal the connection will be placed in this temporary queue: temp_read_buffer = Queue() client_connection = proto.steal_connection(temp_read_buffer.put) try: self._potential_protocols.remove(proto) except: pass #might already have been removed by now #connect to web server: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) host, port = self._tcp_proxy.split(":", 1) try: web_server_connection = _socket_connect(sock, (host, int(port)), "web-proxy-for-%s" % proto, "tcp") except: log.warn("failed to connect to proxy: %s:%s", host, port) proto.gibberish("invalid packet header", data) return log("proxy connected to tcp server at %s:%s : %s", host, port, web_server_connection) sock.settimeout(self._socket_timeout) ioe = proto.wait_for_io_threads_exit(0.5+self._socket_timeout) if not ioe: log.warn("proxy failed to stop all existing network threads!") self.disconnect_protocol(proto, "internal threading error") return #now that we own it, we can start it again: client_connection.set_active(True) #and we can use blocking sockets: self.set_socket_timeout(client_connection, None) #prevent deadlocks on exit: sock.settimeout(1) log("pushing initial buffer to its new destination: %s", repr_ellipsized(data)) web_server_connection.write(data) while not temp_read_buffer.empty(): buf = temp_read_buffer.get() if buf: log("pushing read buffer to its new destination: %s", repr_ellipsized(buf)) web_server_connection.write(buf) p = XpraProxy(client_connection, web_server_connection) self._tcp_proxy_clients.append(p) def run_proxy(): p.run() log("run_proxy() %s ended", p) if p in self._tcp_proxy_clients: self._tcp_proxy_clients.remove(p) t = make_daemon_thread(run_proxy, "web-proxy-for-%s" % proto) t.start() log.info("client %s forwarded to proxy server %s:%s", client_connection, host, port)
def invalid_header(self, proto, data): netlog( "invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s", proto, len(data or ""), repr_ellipsized(data), proto.input_packetcount, self._tcp_proxy) if proto.input_packetcount == 0 and self._tcp_proxy and not proto._closed: #start a new proxy in a thread def run_proxy(): self.start_tcp_proxy(proto, data) t = make_daemon_thread(run_proxy, "web-proxy-for-%s" % proto) t.start() return err = "invalid packet format, not an xpra client?" proto.gibberish(err, data)
def invalid_header(self, proto, data): netlog( "invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s", proto, len(data or ""), repr_ellipsized(data), proto.input_packetcount, self._tcp_proxy, ) if proto.input_packetcount == 0 and self._tcp_proxy and not proto._closed: # start a new proxy in a thread def run_proxy(): self.start_tcp_proxy(proto, data) t = make_daemon_thread(run_proxy, "web-proxy-for-%s" % proto) t.start() return err = "invalid packet format, not an xpra client?" proto.gibberish(err, data)
process = ProxyInstanceProcess( uid, gid, env_options, session_options, self._socket_dir, self.video_encoders, self.csc_modules, client_conn, client_state, cipher, encryption_key, server_conn, c, message_queue) log("starting %s from pid=%s", process, os.getpid()) process.start() log("process started") #FIXME: remove processes that have terminated self.processes[process] = (display, message_queue) finally: #now we can close our handle on the connection: client_conn.close() server_conn.close() make_daemon_thread(do_start_proxy, "start_proxy(%s)" % client_conn).start() def reap(self): dead = [] for p in self.processes.keys(): live = p.is_alive() if not live: dead.append(p) for p in dead: del self.processes[p] def sigchld(self, *args): log("sigchld(%s)", args) self.idle_add(self.reap) log("processes: %s", self.processes)
assert uid!=0 and gid!=0 message_queue = MQueue() process = ProxyInstanceProcess(uid, gid, env_options, session_options, self._socket_dir, self.video_encoders, self.csc_modules, client_conn, client_state, cipher, encryption_key, server_conn, c, message_queue) log("starting %s from pid=%s", process, os.getpid()) process.start() log("process started") #FIXME: remove processes that have terminated self.processes[process] = (display, message_queue) finally: #now we can close our handle on the connection: client_conn.close() server_conn.close() make_daemon_thread(do_start_proxy, "start_proxy(%s)" % client_conn).start() def reap(self): dead = [] for p in self.processes.keys(): live = p.is_alive() if not live: dead.append(p) for p in dead: del self.processes[p] def sigchld(self, *args): log("sigchld(%s)", args) self.idle_add(self.reap) log("processes: %s", self.processes)
def run(self): log("ProxyProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(), os.getuid(), os.getgid()) #change uid and gid: if os.getgid() != self.gid: os.setgid(self.gid) if os.getuid() != self.uid: os.setuid(self.uid) log("ProxyProcess.run() new uid=%s, gid=%s", os.getuid(), os.getgid()) if self.env_options: #TODO: whitelist env update? os.environ.update(self.env_options) self.video_init() log.info("new proxy started for client %s and server %s", self.client_conn, self.server_conn) signal.signal(signal.SIGTERM, self.signal_quit) signal.signal(signal.SIGINT, self.signal_quit) log("registered signal handler %s", self.signal_quit) make_daemon_thread(self.server_message_queue, "server message queue").start() if self.create_control_socket(): self.control_socket_thread = make_daemon_thread( self.control_socket_loop, "control") self.control_socket_thread.start() self.main_queue = Queue() #setup protocol wrappers: self.server_packets = Queue(PROXY_QUEUE_SIZE) self.client_packets = Queue(PROXY_QUEUE_SIZE) self.client_protocol = Protocol(self, self.client_conn, self.process_client_packet, self.get_client_packet) self.client_protocol.restore_state(self.client_state) self.server_protocol = Protocol(self, self.server_conn, self.process_server_packet, self.get_server_packet) #server connection tweaks: self.server_protocol.large_packets.append("draw") self.server_protocol.large_packets.append("window-icon") self.server_protocol.large_packets.append("keymap-changed") self.server_protocol.large_packets.append("server-settings") self.server_protocol.set_compression_level( self.session_options.get("compression_level", 0)) self.server_protocol.enable_default_encoder() self.lost_windows = set() self.encode_queue = Queue() self.encode_thread = make_daemon_thread(self.encode_loop, "encode") self.encode_thread.start() log("starting network threads") self.server_protocol.start() self.client_protocol.start() #forward the hello packet: hello_packet = ("hello", self.filter_client_caps(self.caps)) self.queue_server_packet(hello_packet) self.timeout_add(VIDEO_TIMEOUT * 1000, self.timeout_video_encoders) try: try: self.run_queue() except KeyboardInterrupt as e: self.stop(str(e)) finally: log("ProxyProcess.run() ending %s", os.getpid())
class ProxyServer(ServerCore): """ This is the proxy server you can launch with "xpra proxy", once authenticated, it will dispatch the connection to the session found using the authenticator's get_sessions() function. """ def __init__(self): log("ProxyServer.__init__()") ServerCore.__init__(self) self._max_connections = MAX_CONCURRENT_CONNECTIONS self.main_loop = None #keep track of the proxy process instances #the display they're on and the message queue we can # use to communicate with them self.processes = {} self.idle_add = gobject.idle_add self.timeout_add = gobject.timeout_add self.source_remove = gobject.source_remove self._socket_timeout = PROXY_SOCKET_TIMEOUT signal.signal(signal.SIGCHLD, self.sigchld) def init(self, opts): log("ProxyServer.init(%s)", opts) if not opts.auth: raise Exception("The proxy server requires an authentication mode") ServerCore.init(self, opts) def get_server_mode(self): return "proxy" def init_aliases(self): pass def do_run(self): self.main_loop = gobject.MainLoop() self.main_loop.run() def stop_all_proxies(self): processes = self.processes self.processes = {} log("stop_all_proxies() will stop proxy processes: %s", processes) for process, v in processes.items(): disp, mq = v log("stop_all_proxies() stopping process %s for display %s", process, disp) mq.put("stop") log("stop_all_proxies() done") def cleanup(self): self.stop_all_proxies() ServerCore.cleanup(self) def do_quit(self): self.main_loop.quit() log.info("Proxy Server process ended") def add_listen_socket(self, socktype, sock): sock.listen(5) gobject.io_add_watch(sock, gobject.IO_IN, self._new_connection, sock) self.socket_types[sock] = socktype def verify_connection_accepted(self, protocol): #if we start a proxy, the protocol will be closed #(a new one is created in the proxy process) if not protocol._closed: self.send_disconnect(protocol, "connection timeout") def hello_oked(self, proto, packet, c, auth_caps): if c.boolget("stop_request"): self.clean_quit() return self.accept_client(proto, c) self.start_proxy(proto, c, auth_caps) def start_proxy(self, client_proto, c, auth_caps): assert client_proto.authenticator is not None #find the target server session: def disconnect(msg): self.send_disconnect(client_proto, msg) sessions = client_proto.authenticator.get_sessions() if sessions is None: disconnect("no sessions found") return debug("start_proxy(%s, {..}, %s) found sessions: %s", client_proto, auth_caps, sessions) uid, gid, displays, env_options, session_options = sessions #debug("unused options: %s, %s", env_options, session_options) if len(displays) == 0: disconnect("no displays found") return display = c.strget("display") proxy_virtual_display = os.environ["DISPLAY"] #ensure we don't loop back to the proxy: if proxy_virtual_display in displays: displays.remove(proxy_virtual_display) if display == proxy_virtual_display: disconnect("invalid display") return if display: if display not in displays: disconnect("display not found") return else: if len(displays) != 1: disconnect( "please specify a display (more than one available)") return display = displays[0] debug("start_proxy(%s, {..}, %s) using server display at: %s", client_proto, auth_caps, display) def parse_error(*args): disconnect("invalid display string") log.warn("parse error on %s: %s", display, args) raise Exception("parse error on %s: %s" % (display, args)) opts = make_defaults_struct() opts.username = c.strget("username") disp_desc = parse_display_name(parse_error, opts, display) debug("display description(%s) = %s", display, disp_desc) try: server_conn = connect_to(disp_desc) except Exception, e: log.error("cannot start proxy connection to %s: %s", disp_desc, e) disconnect("failed to connect to display") return debug("server connection=%s", server_conn) client_conn = client_proto.steal_connection() client_state = client_proto.save_state() cipher = None encryption_key = None if auth_caps: cipher = auth_caps.get("cipher") if cipher: encryption_key = self.get_encryption_key( client_proto.authenticator) debug("start_proxy(..) client connection=%s", client_conn) debug("start_proxy(..) client state=%s", client_state) #this may block, so run it in a thread: def do_start_proxy(): debug("do_start_proxy()") try: #stop IO in proxy: #(it may take up to _socket_timeout until the thread exits) client_conn.set_active(False) ioe = client_proto.wait_for_io_threads_exit( 0.1 + self._socket_timeout) if not ioe: log.error("IO threads have failed to terminate!") return #now we can go back to using blocking sockets: self.set_socket_timeout(client_conn, None) client_conn.set_active(True) assert uid != 0 and gid != 0 message_queue = MQueue() process = ProxyProcess(uid, gid, env_options, session_options, client_conn, client_state, cipher, encryption_key, server_conn, c, message_queue) debug("starting %s from pid=%s", process, os.getpid()) process.start() debug("process started") #FIXME: remove processes that have terminated self.processes[process] = (display, message_queue) finally: #now we can close our handle on the connection: client_conn.close() server_conn.close() make_daemon_thread(do_start_proxy, "start_proxy(%s)" % client_conn).start()
def start_proxy(self, client_proto, c, auth_caps): assert client_proto.authenticator is not None #find the target server session: def disconnect(reason, *extras): self.send_disconnect(client_proto, reason, *extras) try: sessions = client_proto.authenticator.get_sessions() except Exception as e: log.error("failed to get the list of sessions: %s", e) disconnect(AUTHENTICATION_ERROR) return if sessions is None: disconnect(SESSION_NOT_FOUND, "no sessions found") return log("start_proxy(%s, {..}, %s) found sessions: %s", client_proto, auth_caps, sessions) uid, gid, displays, env_options, session_options = sessions #log("unused options: %s, %s", env_options, session_options) if len(displays)==0: disconnect(SESSION_NOT_FOUND, "no displays found") return display = c.strget("display") proxy_virtual_display = os.environ.get("DISPLAY") #ensure we don't loop back to the proxy: if proxy_virtual_display in displays: displays.remove(proxy_virtual_display) if display==proxy_virtual_display: disconnect(SESSION_NOT_FOUND, "invalid display") return if display: if display not in displays: disconnect(SESSION_NOT_FOUND, "display not found") return else: if len(displays)!=1: disconnect(SESSION_NOT_FOUND, "please specify a display (more than one available)") return display = displays[0] log("start_proxy(%s, {..}, %s) using server display at: %s", client_proto, auth_caps, display) def parse_error(*args): disconnect(SESSION_NOT_FOUND, "invalid display string") log.warn("parse error on %s: %s", display, args) raise Exception("parse error on %s: %s" % (display, args)) opts = make_defaults_struct() opts.username = client_proto.authenticator.username disp_desc = parse_display_name(parse_error, opts, display) log("display description(%s) = %s", display, disp_desc) try: server_conn = connect_to(disp_desc) except Exception as e: log.error("cannot start proxy connection to %s: %s", disp_desc, e, exc_info=True) disconnect(SESSION_NOT_FOUND, "failed to connect to display") return log("server connection=%s", server_conn) #no other packets should be arriving until the proxy instance responds to the initial hello packet def unexpected_packet(packet): if packet: log.warn("received an unexpected packet on the proxy connection: %s", repr_ellipsized(packet)) client_conn = client_proto.steal_connection(unexpected_packet) client_state = client_proto.save_state() cipher = None encryption_key = None if auth_caps: cipher = auth_caps.get("cipher") if cipher: encryption_key = self.get_encryption_key(client_proto.authenticator) log("start_proxy(..) client connection=%s", client_conn) log("start_proxy(..) client state=%s", client_state) #this may block, so run it in a thread: def do_start_proxy(): log("do_start_proxy()") try: ioe = client_proto.wait_for_io_threads_exit(0.5+self._socket_timeout) if not ioe: log.error("some network IO threads have failed to terminate!") return #now we can go back to using blocking sockets: self.set_socket_timeout(client_conn, None) client_conn.set_active(True) self.set_socket_timeout(server_conn, None) assert uid!=0 and gid!=0 message_queue = MQueue() process = ProxyInstanceProcess(uid, gid, env_options, session_options, self._socket_dir, self.video_encoders, self.csc_modules, client_conn, client_state, cipher, encryption_key, server_conn, c, message_queue) log("starting %s from pid=%s", process, os.getpid()) process.start() log("process started") #FIXME: remove processes that have terminated self.processes[process] = (display, message_queue) finally: #now we can close our handle on the connection: client_conn.close() server_conn.close() make_daemon_thread(do_start_proxy, "start_proxy(%s)" % client_conn).start()
def start_proxy(self, client_proto, c, auth_caps): assert client_proto.authenticator is not None #find the target server session: def disconnect(reason, *extras): self.send_disconnect(client_proto, reason, *extras) try: sessions = client_proto.authenticator.get_sessions() except Exception as e: log.error("failed to get the list of sessions: %s", e) disconnect(AUTHENTICATION_ERROR) return if sessions is None: disconnect(SESSION_NOT_FOUND, "no sessions found") return log("start_proxy(%s, {..}, %s) found sessions: %s", client_proto, auth_caps, sessions) uid, gid, displays, env_options, session_options = sessions #log("unused options: %s, %s", env_options, session_options) if len(displays) == 0: disconnect(SESSION_NOT_FOUND, "no displays found") return display = c.strget("display") proxy_virtual_display = os.environ.get("DISPLAY") #ensure we don't loop back to the proxy: if proxy_virtual_display in displays: displays.remove(proxy_virtual_display) if display == proxy_virtual_display: disconnect(SESSION_NOT_FOUND, "invalid display") return if display: if display not in displays: disconnect(SESSION_NOT_FOUND, "display not found") return else: if len(displays) != 1: disconnect( SESSION_NOT_FOUND, "please specify a display (more than one available)") return display = displays[0] log("start_proxy(%s, {..}, %s) using server display at: %s", client_proto, auth_caps, display) def parse_error(*args): disconnect(SESSION_NOT_FOUND, "invalid display string") log.warn("parse error on %s: %s", display, args) raise Exception("parse error on %s: %s" % (display, args)) opts = make_defaults_struct() opts.username = client_proto.authenticator.username disp_desc = parse_display_name(parse_error, opts, display) log("display description(%s) = %s", display, disp_desc) try: server_conn = connect_to(disp_desc) except Exception as e: log.error("cannot start proxy connection to %s: %s", disp_desc, e, exc_info=True) disconnect(SESSION_NOT_FOUND, "failed to connect to display") return log("server connection=%s", server_conn) #no other packets should be arriving until the proxy instance responds to the initial hello packet def unexpected_packet(packet): if packet: log.warn( "received an unexpected packet on the proxy connection: %s", repr_ellipsized(packet)) client_conn = client_proto.steal_connection(unexpected_packet) client_state = client_proto.save_state() cipher = None encryption_key = None if auth_caps: cipher = auth_caps.get("cipher") if cipher: encryption_key = self.get_encryption_key( client_proto.authenticator) log("start_proxy(..) client connection=%s", client_conn) log("start_proxy(..) client state=%s", client_state) #this may block, so run it in a thread: def do_start_proxy(): log("do_start_proxy()") try: ioe = client_proto.wait_for_io_threads_exit( 0.5 + self._socket_timeout) if not ioe: log.error( "some network IO threads have failed to terminate!") return #now we can go back to using blocking sockets: self.set_socket_timeout(client_conn, None) client_conn.set_active(True) self.set_socket_timeout(server_conn, None) assert uid != 0 and gid != 0 message_queue = MQueue() process = ProxyInstanceProcess( uid, gid, env_options, session_options, self._socket_dir, self.video_encoders, self.csc_modules, client_conn, client_state, cipher, encryption_key, server_conn, c, message_queue) log("starting %s from pid=%s", process, os.getpid()) process.start() log("process started") #FIXME: remove processes that have terminated self.processes[process] = (display, message_queue) finally: #now we can close our handle on the connection: client_conn.close() server_conn.close() make_daemon_thread(do_start_proxy, "start_proxy(%s)" % client_conn).start()