OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # Virtual Me2Me implementation. This script runs and manages the processes | 6 # Virtual Me2Me implementation. This script runs and manages the processes |
7 # required for a Virtual Me2Me desktop, which are: X server, X desktop | 7 # required for a Virtual Me2Me desktop, which are: X server, X desktop |
8 # session, and Host process. | 8 # session, and Host process. |
9 # This script is intended to run continuously as a background daemon | 9 # This script is intended to run continuously as a background daemon |
10 # process, running under an ordinary (non-root) user account. | 10 # process, running under an ordinary (non-root) user account. |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 | 197 |
198 def __init__(self, sizes): | 198 def __init__(self, sizes): |
199 self.x_proc = None | 199 self.x_proc = None |
200 self.session_proc = None | 200 self.session_proc = None |
201 self.host_proc = None | 201 self.host_proc = None |
202 self.child_env = None | 202 self.child_env = None |
203 self.sizes = sizes | 203 self.sizes = sizes |
204 self.pulseaudio_pipe = None | 204 self.pulseaudio_pipe = None |
205 self.server_supports_exact_resize = False | 205 self.server_supports_exact_resize = False |
206 self.host_ready = False | 206 self.host_ready = False |
| 207 self.ssh_auth_sockname = None |
207 g_desktops.append(self) | 208 g_desktops.append(self) |
208 | 209 |
209 @staticmethod | 210 @staticmethod |
210 def get_unused_display_number(): | 211 def get_unused_display_number(): |
211 """Return a candidate display number for which there is currently no | 212 """Return a candidate display number for which there is currently no |
212 X Server lock file""" | 213 X Server lock file""" |
213 display = FIRST_X_DISPLAY_NUMBER | 214 display = FIRST_X_DISPLAY_NUMBER |
214 while os.path.exists(X_LOCK_FILE_TEMPLATE % display): | 215 while os.path.exists(X_LOCK_FILE_TEMPLATE % display): |
215 display += 1 | 216 display += 1 |
216 return display | 217 return display |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 return False | 298 return False |
298 | 299 |
299 self.child_env["PULSE_CONFIG_PATH"] = pulse_path | 300 self.child_env["PULSE_CONFIG_PATH"] = pulse_path |
300 self.child_env["PULSE_RUNTIME_PATH"] = pulse_path | 301 self.child_env["PULSE_RUNTIME_PATH"] = pulse_path |
301 self.child_env["PULSE_STATE_PATH"] = pulse_path | 302 self.child_env["PULSE_STATE_PATH"] = pulse_path |
302 self.child_env["PULSE_SINK"] = sink_name | 303 self.child_env["PULSE_SINK"] = sink_name |
303 self.pulseaudio_pipe = pipe_name | 304 self.pulseaudio_pipe = pipe_name |
304 | 305 |
305 return True | 306 return True |
306 | 307 |
| 308 def _setup_gnubby(self): |
| 309 self.ssh_auth_sockname = ("/tmp/chromoting.%s.ssh_auth_sock" % |
| 310 os.environ["USER"]) |
| 311 |
307 def _launch_x_server(self, extra_x_args): | 312 def _launch_x_server(self, extra_x_args): |
308 x_auth_file = os.path.expanduser("~/.Xauthority") | 313 x_auth_file = os.path.expanduser("~/.Xauthority") |
309 self.child_env["XAUTHORITY"] = x_auth_file | 314 self.child_env["XAUTHORITY"] = x_auth_file |
310 devnull = open(os.devnull, "rw") | 315 devnull = open(os.devnull, "rw") |
311 display = self.get_unused_display_number() | 316 display = self.get_unused_display_number() |
312 | 317 |
313 # Run "xauth add" with |child_env| so that it modifies the same XAUTHORITY | 318 # Run "xauth add" with |child_env| so that it modifies the same XAUTHORITY |
314 # file which will be used for the X session. | 319 # file which will be used for the X session. |
315 ret_code = subprocess.call("xauth add :%d . `mcookie`" % display, | 320 ret_code = subprocess.call("xauth add :%d . `mcookie`" % display, |
316 env=self.child_env, shell=True) | 321 env=self.child_env, shell=True) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 | 359 |
355 self.child_env["DISPLAY"] = ":%d" % display | 360 self.child_env["DISPLAY"] = ":%d" % display |
356 self.child_env["CHROME_REMOTE_DESKTOP_SESSION"] = "1" | 361 self.child_env["CHROME_REMOTE_DESKTOP_SESSION"] = "1" |
357 | 362 |
358 # Use a separate profile for any instances of Chrome that are started in | 363 # Use a separate profile for any instances of Chrome that are started in |
359 # the virtual session. Chrome doesn't support sharing a profile between | 364 # the virtual session. Chrome doesn't support sharing a profile between |
360 # multiple DISPLAYs, but Chrome Sync allows for a reasonable compromise. | 365 # multiple DISPLAYs, but Chrome Sync allows for a reasonable compromise. |
361 chrome_profile = os.path.join(CONFIG_DIR, "chrome-profile") | 366 chrome_profile = os.path.join(CONFIG_DIR, "chrome-profile") |
362 self.child_env["CHROME_USER_DATA_DIR"] = chrome_profile | 367 self.child_env["CHROME_USER_DATA_DIR"] = chrome_profile |
363 | 368 |
| 369 # Set SSH_AUTH_SOCK to the file name to listen on. |
| 370 if self.ssh_auth_sockname: |
| 371 self.child_env["SSH_AUTH_SOCK"] = self.ssh_auth_sockname |
| 372 |
364 # Wait for X to be active. | 373 # Wait for X to be active. |
365 for _test in range(5): | 374 for _test in range(5): |
366 proc = subprocess.Popen("xdpyinfo", env=self.child_env, stdout=devnull) | 375 proc = subprocess.Popen("xdpyinfo", env=self.child_env, stdout=devnull) |
367 _pid, retcode = os.waitpid(proc.pid, 0) | 376 _pid, retcode = os.waitpid(proc.pid, 0) |
368 if retcode == 0: | 377 if retcode == 0: |
369 break | 378 break |
370 time.sleep(0.5) | 379 time.sleep(0.5) |
371 if retcode != 0: | 380 if retcode != 0: |
372 raise Exception("Could not connect to Xvfb.") | 381 raise Exception("Could not connect to Xvfb.") |
373 else: | 382 else: |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 self.session_proc = subprocess.Popen(xsession_command, | 435 self.session_proc = subprocess.Popen(xsession_command, |
427 stdin=open(os.devnull, "r"), | 436 stdin=open(os.devnull, "r"), |
428 cwd=HOME_DIR, | 437 cwd=HOME_DIR, |
429 env=self.child_env) | 438 env=self.child_env) |
430 if not self.session_proc.pid: | 439 if not self.session_proc.pid: |
431 raise Exception("Could not start X session") | 440 raise Exception("Could not start X session") |
432 | 441 |
433 def launch_session(self, x_args): | 442 def launch_session(self, x_args): |
434 self._init_child_env() | 443 self._init_child_env() |
435 self._setup_pulseaudio() | 444 self._setup_pulseaudio() |
| 445 self._setup_gnubby() |
436 self._launch_x_server(x_args) | 446 self._launch_x_server(x_args) |
437 self._launch_x_session() | 447 self._launch_x_session() |
438 | 448 |
439 def launch_host(self, host_config): | 449 def launch_host(self, host_config): |
440 # Start remoting host | 450 # Start remoting host |
441 args = [locate_executable(HOST_BINARY_NAME), "--host-config=-"] | 451 args = [locate_executable(HOST_BINARY_NAME), "--host-config=-"] |
442 if self.pulseaudio_pipe: | 452 if self.pulseaudio_pipe: |
443 args.append("--audio-pipe-name=%s" % self.pulseaudio_pipe) | 453 args.append("--audio-pipe-name=%s" % self.pulseaudio_pipe) |
444 if self.server_supports_exact_resize: | 454 if self.server_supports_exact_resize: |
445 args.append("--server-supports-exact-resize") | 455 args.append("--server-supports-exact-resize") |
| 456 if self.ssh_auth_sockname: |
| 457 args.append("--ssh-auth-sockname=%s" % self.ssh_auth_sockname) |
446 | 458 |
447 # Have the host process use SIGUSR1 to signal a successful start. | 459 # Have the host process use SIGUSR1 to signal a successful start. |
448 def sigusr1_handler(signum, frame): | 460 def sigusr1_handler(signum, frame): |
449 _ = signum, frame | 461 _ = signum, frame |
450 logging.info("Host ready to receive connections.") | 462 logging.info("Host ready to receive connections.") |
451 self.host_ready = True | 463 self.host_ready = True |
452 if (ParentProcessLogger.instance() and | 464 if (ParentProcessLogger.instance() and |
453 False not in [desktop.host_ready for desktop in g_desktops]): | 465 False not in [desktop.host_ready for desktop in g_desktops]): |
454 ParentProcessLogger.instance().release_parent() | 466 ParentProcessLogger.instance().release_parent() |
455 | 467 |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 else: | 1201 else: |
1190 logging.info("Host exited with status %s." % os.WEXITSTATUS(status)) | 1202 logging.info("Host exited with status %s." % os.WEXITSTATUS(status)) |
1191 elif os.WIFSIGNALED(status): | 1203 elif os.WIFSIGNALED(status): |
1192 logging.info("Host terminated by signal %s." % os.WTERMSIG(status)) | 1204 logging.info("Host terminated by signal %s." % os.WTERMSIG(status)) |
1193 | 1205 |
1194 | 1206 |
1195 if __name__ == "__main__": | 1207 if __name__ == "__main__": |
1196 logging.basicConfig(level=logging.DEBUG, | 1208 logging.basicConfig(level=logging.DEBUG, |
1197 format="%(asctime)s:%(levelname)s:%(message)s") | 1209 format="%(asctime)s:%(levelname)s:%(message)s") |
1198 sys.exit(main()) | 1210 sys.exit(main()) |
OLD | NEW |