1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "base/message_loop.h"
8
9 #include "mozilla/ipc/Transport.h"
10 #include "mozilla/ipc/ProtocolUtils.h"
11
12 using namespace std;
13
14 using base::ProcessHandle;
15
16 namespace mozilla {
17 namespace ipc {
18
19 nsresult
CreateTransport(base::ProcessId aProcIdOne,TransportDescriptor * aOne,TransportDescriptor * aTwo)20 CreateTransport(base::ProcessId aProcIdOne,
21 TransportDescriptor* aOne,
22 TransportDescriptor* aTwo)
23 {
24 wstring id = IPC::Channel::GenerateVerifiedChannelID(std::wstring());
25 // Use MODE_SERVER to force creation of the pipe
26 Transport t(id, Transport::MODE_SERVER, nullptr);
27 HANDLE serverPipe = t.GetServerPipeHandle();
28 if (!serverPipe) {
29 return NS_ERROR_TRANSPORT_INIT;
30 }
31
32 // NB: we create the server pipe immediately, instead of just
33 // grabbing an ID, on purpose. In the current setup, the client
34 // needs to connect to an existing server pipe, so to prevent race
35 // conditions, we create the server side here. When we send the pipe
36 // to the server, we DuplicateHandle it to the server process to give it
37 // access.
38 HANDLE serverDup;
39 DWORD access = 0;
40 DWORD options = DUPLICATE_SAME_ACCESS;
41 if (!DuplicateHandle(serverPipe, base::GetCurrentProcId(), &serverDup, access, options)) {
42 return NS_ERROR_DUPLICATE_HANDLE;
43 }
44
45 aOne->mPipeName = aTwo->mPipeName = id;
46 aOne->mServerPipeHandle = serverDup;
47 aOne->mDestinationProcessId = aProcIdOne;
48 aTwo->mServerPipeHandle = INVALID_HANDLE_VALUE;
49 aTwo->mDestinationProcessId = 0;
50 return NS_OK;
51 }
52
53 HANDLE
TransferHandleToProcess(HANDLE source,base::ProcessId pid)54 TransferHandleToProcess(HANDLE source, base::ProcessId pid)
55 {
56 // At this point we're sending the handle to another process.
57
58 if (source == INVALID_HANDLE_VALUE) {
59 return source;
60 }
61 HANDLE handleDup;
62 DWORD access = 0;
63 DWORD options = DUPLICATE_SAME_ACCESS;
64 bool ok = DuplicateHandle(source, pid, &handleDup, access, options);
65 if (!ok) {
66 return nullptr;
67 }
68
69 // Now close our own copy of the handle (we're supposed to be transferring,
70 // not copying).
71 CloseHandle(source);
72
73 return handleDup;
74 }
75
76 UniquePtr<Transport>
OpenDescriptor(const TransportDescriptor & aTd,Transport::Mode aMode)77 OpenDescriptor(const TransportDescriptor& aTd, Transport::Mode aMode)
78 {
79 if (aTd.mServerPipeHandle != INVALID_HANDLE_VALUE) {
80 MOZ_RELEASE_ASSERT(aTd.mDestinationProcessId == base::GetCurrentProcId());
81 }
82 return MakeUnique<Transport>(aTd.mPipeName, aTd.mServerPipeHandle, aMode, nullptr);
83 }
84
85 UniquePtr<Transport>
OpenDescriptor(const FileDescriptor & aFd,Transport::Mode aMode)86 OpenDescriptor(const FileDescriptor& aFd, Transport::Mode aMode)
87 {
88 NS_NOTREACHED("Not implemented!");
89 return nullptr;
90 }
91
92 TransportDescriptor
DuplicateDescriptor(const TransportDescriptor & aTd)93 DuplicateDescriptor(const TransportDescriptor& aTd)
94 {
95 // We're duplicating this handle in our own process for bookkeeping purposes.
96
97 if (aTd.mServerPipeHandle == INVALID_HANDLE_VALUE) {
98 return aTd;
99 }
100
101 HANDLE serverDup;
102 DWORD access = 0;
103 DWORD options = DUPLICATE_SAME_ACCESS;
104 bool ok = DuplicateHandle(aTd.mServerPipeHandle, base::GetCurrentProcId(),
105 &serverDup, access, options);
106 if (!ok) {
107 AnnotateSystemError();
108 }
109 MOZ_RELEASE_ASSERT(ok);
110
111 TransportDescriptor desc = aTd;
112 desc.mServerPipeHandle = serverDup;
113 return desc;
114 }
115
116 void
CloseDescriptor(const TransportDescriptor & aTd)117 CloseDescriptor(const TransportDescriptor& aTd)
118 {
119 // We're closing our own local copy of the pipe.
120
121 CloseHandle(aTd.mServerPipeHandle);
122 }
123
124 } // namespace ipc
125 } // namespace mozilla
126