xref: /aosp_15_r20/external/cronet/ipc/ipc_message_attachment.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ipc/ipc_message_attachment.h"
6 
7 #include "base/files/scoped_file.h"
8 #include "base/logging.h"
9 #include "base/notreached.h"
10 #include "build/build_config.h"
11 #include "ipc/ipc_mojo_handle_attachment.h"
12 #include "mojo/public/cpp/system/platform_handle.h"
13 
14 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
15 #include <unistd.h>
16 
17 #include "base/posix/eintr_wrapper.h"
18 #include "ipc/ipc_platform_file_attachment_posix.h"
19 #endif
20 
21 #if BUILDFLAG(IS_MAC)
22 #include "ipc/mach_port_attachment_mac.h"
23 #endif
24 
25 #if BUILDFLAG(IS_WIN)
26 #include "ipc/handle_attachment_win.h"
27 #endif
28 
29 #if BUILDFLAG(IS_FUCHSIA)
30 #include "ipc/handle_attachment_fuchsia.h"
31 #endif
32 
33 namespace IPC {
34 
35 namespace {
36 
37 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TakeOrDupFile(internal::PlatformFileAttachment * attachment)38 base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
39   return attachment->Owns()
40              ? base::ScopedFD(attachment->TakePlatformFile())
41              : base::ScopedFD(HANDLE_EINTR(dup(attachment->file())));
42 }
43 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
44 
45 }  // namespace
46 
47 MessageAttachment::MessageAttachment() = default;
48 
49 MessageAttachment::~MessageAttachment() = default;
50 
TakeMojoHandle()51 mojo::ScopedHandle MessageAttachment::TakeMojoHandle() {
52   switch (GetType()) {
53     case Type::MOJO_HANDLE:
54       return static_cast<internal::MojoHandleAttachment*>(this)->TakeHandle();
55 
56 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
57     case Type::PLATFORM_FILE: {
58       // We dup() the handles in IPC::Message to transmit.
59       // IPC::MessageAttachmentSet has intricate lifetime semantics for FDs, so
60       // just to dup()-and-own them is the safest option.
61       base::ScopedFD file =
62           TakeOrDupFile(static_cast<internal::PlatformFileAttachment*>(this));
63       if (!file.is_valid()) {
64         DPLOG(WARNING) << "Failed to dup FD to transmit.";
65         return mojo::ScopedHandle();
66       }
67       return mojo::WrapPlatformFile(std::move(file));
68     }
69 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
70 
71 #if BUILDFLAG(IS_MAC)
72     case Type::MACH_PORT: {
73       auto* attachment = static_cast<internal::MachPortAttachmentMac*>(this);
74       MojoPlatformHandle platform_handle = {
75           sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT,
76           static_cast<uint64_t>(attachment->get_mach_port())};
77       MojoHandle wrapped_handle;
78       if (MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle) !=
79           MOJO_RESULT_OK) {
80         return mojo::ScopedHandle();
81       }
82       attachment->reset_mach_port_ownership();
83       return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle));
84     }
85 #elif BUILDFLAG(IS_FUCHSIA)
86     case Type::FUCHSIA_HANDLE: {
87       auto* attachment = static_cast<internal::HandleAttachmentFuchsia*>(this);
88       MojoPlatformHandle platform_handle = {
89           sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE,
90           static_cast<uint64_t>(attachment->Take())};
91       MojoHandle wrapped_handle;
92       if (MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle) !=
93           MOJO_RESULT_OK) {
94         return mojo::ScopedHandle();
95       }
96       return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle));
97     }
98 #elif BUILDFLAG(IS_WIN)
99     case Type::WIN_HANDLE:
100       return mojo::WrapPlatformFile(base::win::ScopedHandle(
101           static_cast<internal::HandleAttachmentWin*>(this)->Take()));
102 #endif
103     default:
104       break;
105   }
106   NOTREACHED();
107   return mojo::ScopedHandle();
108 }
109 
110 // static
CreateFromMojoHandle(mojo::ScopedHandle handle,Type type)111 scoped_refptr<MessageAttachment> MessageAttachment::CreateFromMojoHandle(
112     mojo::ScopedHandle handle,
113     Type type) {
114   if (type == Type::MOJO_HANDLE)
115     return new internal::MojoHandleAttachment(std::move(handle));
116 
117   MojoPlatformHandle platform_handle = {sizeof(platform_handle), 0, 0};
118   MojoResult unwrap_result = MojoUnwrapPlatformHandle(
119       handle.release().value(), nullptr, &platform_handle);
120   if (unwrap_result != MOJO_RESULT_OK)
121     return nullptr;
122 
123 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
124   if (type == Type::PLATFORM_FILE) {
125     base::PlatformFile file = base::kInvalidPlatformFile;
126     if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
127       file = static_cast<base::PlatformFile>(platform_handle.value);
128     return new internal::PlatformFileAttachment(file);
129   }
130 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
131 
132 #if BUILDFLAG(IS_MAC)
133   if (type == Type::MACH_PORT) {
134     mach_port_t mach_port = MACH_PORT_NULL;
135     if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT)
136       mach_port = static_cast<mach_port_t>(platform_handle.value);
137     return new internal::MachPortAttachmentMac(
138         mach_port, internal::MachPortAttachmentMac::FROM_WIRE);
139   }
140 #elif BUILDFLAG(IS_FUCHSIA)
141   if (type == Type::FUCHSIA_HANDLE) {
142     zx::handle zx_handle;
143     if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE)
144       zx_handle.reset(static_cast<zx_handle_t>(platform_handle.value));
145     return new internal::HandleAttachmentFuchsia(std::move(zx_handle));
146   }
147 #elif BUILDFLAG(IS_WIN)
148   if (type == Type::WIN_HANDLE) {
149     base::PlatformFile platform_file = base::kInvalidPlatformFile;
150     if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE) {
151       platform_file =
152           reinterpret_cast<base::PlatformFile>(platform_handle.value);
153     }
154     return new internal::HandleAttachmentWin(
155         platform_file, internal::HandleAttachmentWin::FROM_WIRE);
156   }
157 #endif
158   NOTREACHED();
159   return nullptr;
160 }
161 
162 }  // namespace IPC
163