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