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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 | 185 |
186 def __init__(self, sizes): | 186 def __init__(self, sizes): |
187 self.x_proc = None | 187 self.x_proc = None |
188 self.session_proc = None | 188 self.session_proc = None |
189 self.host_proc = None | 189 self.host_proc = None |
190 self.child_env = None | 190 self.child_env = None |
191 self.sizes = sizes | 191 self.sizes = sizes |
192 self.pulseaudio_pipe = None | 192 self.pulseaudio_pipe = None |
193 self.server_supports_exact_resize = False | 193 self.server_supports_exact_resize = False |
194 self.host_ready = False | 194 self.host_ready = False |
| 195 self.ssh_auth_sockname = None |
195 g_desktops.append(self) | 196 g_desktops.append(self) |
196 | 197 |
197 @staticmethod | 198 @staticmethod |
198 def get_unused_display_number(): | 199 def get_unused_display_number(): |
199 """Return a candidate display number for which there is currently no | 200 """Return a candidate display number for which there is currently no |
200 X Server lock file""" | 201 X Server lock file""" |
201 display = FIRST_X_DISPLAY_NUMBER | 202 display = FIRST_X_DISPLAY_NUMBER |
202 while os.path.exists(X_LOCK_FILE_TEMPLATE % display): | 203 while os.path.exists(X_LOCK_FILE_TEMPLATE % display): |
203 display += 1 | 204 display += 1 |
204 return display | 205 return display |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 return False | 286 return False |
286 | 287 |
287 self.child_env["PULSE_CONFIG_PATH"] = pulse_path | 288 self.child_env["PULSE_CONFIG_PATH"] = pulse_path |
288 self.child_env["PULSE_RUNTIME_PATH"] = pulse_path | 289 self.child_env["PULSE_RUNTIME_PATH"] = pulse_path |
289 self.child_env["PULSE_STATE_PATH"] = pulse_path | 290 self.child_env["PULSE_STATE_PATH"] = pulse_path |
290 self.child_env["PULSE_SINK"] = sink_name | 291 self.child_env["PULSE_SINK"] = sink_name |
291 self.pulseaudio_pipe = pipe_name | 292 self.pulseaudio_pipe = pipe_name |
292 | 293 |
293 return True | 294 return True |
294 | 295 |
| 296 def _setup_gnubby(self): |
| 297 self.ssh_auth_sockname = ("/tmp/chromoting.%s.ssh_auth_sock" % |
| 298 os.environ["USER"]) |
| 299 |
295 def _launch_x_server(self, extra_x_args): | 300 def _launch_x_server(self, extra_x_args): |
296 x_auth_file = os.path.expanduser("~/.Xauthority") | 301 x_auth_file = os.path.expanduser("~/.Xauthority") |
297 self.child_env["XAUTHORITY"] = x_auth_file | 302 self.child_env["XAUTHORITY"] = x_auth_file |
298 devnull = open(os.devnull, "rw") | 303 devnull = open(os.devnull, "rw") |
299 display = self.get_unused_display_number() | 304 display = self.get_unused_display_number() |
300 | 305 |
301 # Run "xauth add" with |child_env| so that it modifies the same XAUTHORITY | 306 # Run "xauth add" with |child_env| so that it modifies the same XAUTHORITY |
302 # file which will be used for the X session. | 307 # file which will be used for the X session. |
303 ret_code = subprocess.call("xauth add :%d . `mcookie`" % display, | 308 ret_code = subprocess.call("xauth add :%d . `mcookie`" % display, |
304 env=self.child_env, shell=True) | 309 env=self.child_env, shell=True) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 | 347 |
343 self.child_env["DISPLAY"] = ":%d" % display | 348 self.child_env["DISPLAY"] = ":%d" % display |
344 self.child_env["CHROME_REMOTE_DESKTOP_SESSION"] = "1" | 349 self.child_env["CHROME_REMOTE_DESKTOP_SESSION"] = "1" |
345 | 350 |
346 # Use a separate profile for any instances of Chrome that are started in | 351 # Use a separate profile for any instances of Chrome that are started in |
347 # the virtual session. Chrome doesn't support sharing a profile between | 352 # the virtual session. Chrome doesn't support sharing a profile between |
348 # multiple DISPLAYs, but Chrome Sync allows for a reasonable compromise. | 353 # multiple DISPLAYs, but Chrome Sync allows for a reasonable compromise. |
349 chrome_profile = os.path.join(CONFIG_DIR, "chrome-profile") | 354 chrome_profile = os.path.join(CONFIG_DIR, "chrome-profile") |
350 self.child_env["CHROME_USER_DATA_DIR"] = chrome_profile | 355 self.child_env["CHROME_USER_DATA_DIR"] = chrome_profile |
351 | 356 |
| 357 # Set SSH_AUTH_SOCK to the file name to listen on. |
| 358 if self.ssh_auth_sockname: |
| 359 self.child_env["SSH_AUTH_SOCK"] = self.ssh_auth_sockname |
| 360 |
352 # Wait for X to be active. | 361 # Wait for X to be active. |
353 for _test in range(5): | 362 for _test in range(5): |
354 proc = subprocess.Popen("xdpyinfo", env=self.child_env, stdout=devnull) | 363 proc = subprocess.Popen("xdpyinfo", env=self.child_env, stdout=devnull) |
355 _pid, retcode = os.waitpid(proc.pid, 0) | 364 _pid, retcode = os.waitpid(proc.pid, 0) |
356 if retcode == 0: | 365 if retcode == 0: |
357 break | 366 break |
358 time.sleep(0.5) | 367 time.sleep(0.5) |
359 if retcode != 0: | 368 if retcode != 0: |
360 raise Exception("Could not connect to Xvfb.") | 369 raise Exception("Could not connect to Xvfb.") |
361 else: | 370 else: |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 self.session_proc = subprocess.Popen(xsession_command, | 423 self.session_proc = subprocess.Popen(xsession_command, |
415 stdin=open(os.devnull, "r"), | 424 stdin=open(os.devnull, "r"), |
416 cwd=HOME_DIR, | 425 cwd=HOME_DIR, |
417 env=self.child_env) | 426 env=self.child_env) |
418 if not self.session_proc.pid: | 427 if not self.session_proc.pid: |
419 raise Exception("Could not start X session") | 428 raise Exception("Could not start X session") |
420 | 429 |
421 def launch_session(self, x_args): | 430 def launch_session(self, x_args): |
422 self._init_child_env() | 431 self._init_child_env() |
423 self._setup_pulseaudio() | 432 self._setup_pulseaudio() |
| 433 self._setup_gnubby() |
424 self._launch_x_server(x_args) | 434 self._launch_x_server(x_args) |
425 self._launch_x_session() | 435 self._launch_x_session() |
426 | 436 |
427 def launch_host(self, host_config): | 437 def launch_host(self, host_config): |
428 # Start remoting host | 438 # Start remoting host |
429 args = [locate_executable(HOST_BINARY_NAME), "--host-config=-"] | 439 args = [locate_executable(HOST_BINARY_NAME), "--host-config=-"] |
430 if self.pulseaudio_pipe: | 440 if self.pulseaudio_pipe: |
431 args.append("--audio-pipe-name=%s" % self.pulseaudio_pipe) | 441 args.append("--audio-pipe-name=%s" % self.pulseaudio_pipe) |
432 if self.server_supports_exact_resize: | 442 if self.server_supports_exact_resize: |
433 args.append("--server-supports-exact-resize") | 443 args.append("--server-supports-exact-resize") |
| 444 if self.ssh_auth_sockname: |
| 445 args.append("--ssh-auth-sockname=%s" % self.ssh_auth_sockname) |
434 | 446 |
435 # Have the host process use SIGUSR1 to signal a successful start. | 447 # Have the host process use SIGUSR1 to signal a successful start. |
436 def sigusr1_handler(signum, frame): | 448 def sigusr1_handler(signum, frame): |
437 _ = signum, frame | 449 _ = signum, frame |
438 logging.info("Host ready to receive connections.") | 450 logging.info("Host ready to receive connections.") |
439 self.host_ready = True | 451 self.host_ready = True |
440 if (ParentProcessLogger.instance() and | 452 if (ParentProcessLogger.instance() and |
441 False not in [desktop.host_ready for desktop in g_desktops]): | 453 False not in [desktop.host_ready for desktop in g_desktops]): |
442 ParentProcessLogger.instance().release_parent() | 454 ParentProcessLogger.instance().release_parent() |
443 | 455 |
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 else: | 1173 else: |
1162 logging.info("Host exited with status %s." % os.WEXITSTATUS(status)) | 1174 logging.info("Host exited with status %s." % os.WEXITSTATUS(status)) |
1163 elif os.WIFSIGNALED(status): | 1175 elif os.WIFSIGNALED(status): |
1164 logging.info("Host terminated by signal %s." % os.WTERMSIG(status)) | 1176 logging.info("Host terminated by signal %s." % os.WTERMSIG(status)) |
1165 | 1177 |
1166 | 1178 |
1167 if __name__ == "__main__": | 1179 if __name__ == "__main__": |
1168 logging.basicConfig(level=logging.DEBUG, | 1180 logging.basicConfig(level=logging.DEBUG, |
1169 format="%(asctime)s:%(levelname)s:%(message)s") | 1181 format="%(asctime)s:%(levelname)s:%(message)s") |
1170 sys.exit(main()) | 1182 sys.exit(main()) |
OLD | NEW |