1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/kasko/testing/test_server.h"
16 :
17 : #include <windows.h>
18 :
19 : #include <string>
20 : #include "base/command_line.h"
21 : #include "base/logging.h"
22 : #include "base/process/kill.h"
23 : #include "base/strings/string_number_conversions.h"
24 : #include "base/test/test_timeouts.h"
25 : #include "syzygy/kasko/testing/launch_python_process.h"
26 : #include "syzygy/kasko/testing/safe_pipe_reader.h"
27 :
28 m : namespace kasko {
29 m : namespace testing {
30 m : namespace {
31 :
32 m : base::Process LaunchServer(HANDLE socket_write_handle,
33 m : const base::FilePath& incoming_directory) {
34 m : base::CommandLine args(base::CommandLine::NO_PROGRAM);
35 : // Pass the handle on the command-line. Although HANDLE is a
36 : // pointer, truncating it on 64-bit machines is okay. See
37 : // http://msdn.microsoft.com/en-us/library/aa384203.aspx
38 : //
39 : // "64-bit versions of Windows use 32-bit handles for
40 : // interoperability. When sharing a handle between 32-bit and 64-bit
41 : // applications, only the lower 32 bits are significant, so it is
42 : // safe to truncate the handle (when passing it from 64-bit to
43 : // 32-bit) or sign-extend the handle (when passing it from 32-bit to
44 : // 64-bit)."
45 m : args.AppendSwitchASCII(
46 m : "--startup-pipe",
47 m : base::IntToString(reinterpret_cast<uintptr_t>(socket_write_handle)));
48 m : args.AppendSwitchPath("--incoming-directory", incoming_directory);
49 :
50 m : return LaunchPythonProcess(
51 m : base::FilePath(L"syzygy/kasko/testing/test_server.py"), args);
52 m : }
53 :
54 m : } // namespace
55 :
56 m : TestServer::TestServer() : port_(0) {
57 m : }
58 :
59 m : TestServer::~TestServer() {
60 m : if (process_.IsValid()) {
61 m : int exit_code = 0;
62 m : if (!process_.WaitForExitWithTimeout(base::TimeDelta(), &exit_code))
63 m : process_.Terminate(1, true);
64 m : }
65 m : }
66 :
67 m : bool TestServer::Start() {
68 m : bool started = false;
69 m : incoming_directory_.CreateUniqueTempDir();
70 m : DCHECK(incoming_directory_.IsValid());
71 :
72 m : if (incoming_directory_.IsValid()) {
73 m : SafePipeReader pipe_reader;
74 m : DCHECK(pipe_reader.IsValid());
75 :
76 m : if (pipe_reader.IsValid()) {
77 m : process_ = LaunchServer(pipe_reader.write_handle(),
78 m : incoming_directory_.path());
79 m : DCHECK(process_.IsValid());
80 :
81 m : if (process_.IsValid()) {
82 m : started = pipe_reader.ReadData(TestTimeouts::action_max_timeout(),
83 m : sizeof(port_), &port_);
84 m : DCHECK(started);
85 m : }
86 m : }
87 m : }
88 :
89 m : return started;
90 m : }
91 :
92 m : } // namespace testing
93 m : } // namespace kasko
|