Avi Drissman | d387f092 | 2022-09-14 20:51:31 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef MOJO_CORE_CHANNEL_POSIX_H_ |
| 6 | #define MOJO_CORE_CHANNEL_POSIX_H_ |
| 7 | |
Joseph Koshy | 23851dc | 2022-12-16 18:02:49 | [diff] [blame] | 8 | #include "base/containers/circular_deque.h" |
Lei Zhang | b856768 | 2023-01-06 17:54:04 | [diff] [blame] | 9 | #include "base/memory/scoped_refptr.h" |
Ken Rockot | 49a5e7a2 | 2024-11-28 00:43:21 | [diff] [blame] | 10 | #include "base/message_loop/io_watcher.h" |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 11 | #include "base/synchronization/lock.h" |
| 12 | #include "base/task/current_thread.h" |
Sean Maher | e672a66 | 2023-01-09 21:42:28 | [diff] [blame] | 13 | #include "base/task/single_thread_task_runner.h" |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 14 | #include "base/thread_annotations.h" |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 15 | #include "build/build_config.h" |
Ken Rockot | 49a5e7a2 | 2024-11-28 00:43:21 | [diff] [blame] | 16 | #include "mojo/core/channel.h" |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 17 | |
| 18 | namespace mojo { |
| 19 | namespace core { |
| 20 | |
| 21 | class MessageView; |
| 22 | |
| 23 | class ChannelPosix : public Channel, |
| 24 | public base::CurrentThread::DestructionObserver, |
Ken Rockot | 49a5e7a2 | 2024-11-28 00:43:21 | [diff] [blame] | 25 | public base::IOWatcher::FdWatcher { |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 26 | public: |
| 27 | ChannelPosix(Delegate* delegate, |
| 28 | ConnectionParams connection_params, |
| 29 | HandlePolicy handle_policy, |
| 30 | scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); |
| 31 | |
Peter Boström | feef05a | 2021-10-05 21:35:08 | [diff] [blame] | 32 | ChannelPosix(const ChannelPosix&) = delete; |
| 33 | ChannelPosix& operator=(const ChannelPosix&) = delete; |
| 34 | |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 35 | void Start() override; |
| 36 | void ShutDownImpl() override; |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 37 | void Write(MessagePtr message) override LOCKS_EXCLUDED(write_lock_); |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 38 | void LeakHandle() override; |
| 39 | bool GetReadPlatformHandles(const void* payload, |
| 40 | size_t payload_size, |
| 41 | size_t num_handles, |
| 42 | const void* extra_header, |
| 43 | size_t extra_header_size, |
| 44 | std::vector<PlatformHandle>* handles, |
| 45 | bool* deferred) override; |
Ken Rockot | 36d44a57 | 2022-08-15 23:19:57 | [diff] [blame] | 46 | bool GetReadPlatformHandlesForIpcz( |
| 47 | size_t num_handles, |
| 48 | std::vector<PlatformHandle>& handles) override; |
Brian Geffon | 12b581a | 2021-02-03 23:48:03 | [diff] [blame] | 49 | bool OnControlMessage(Message::MessageType message_type, |
| 50 | const void* payload, |
| 51 | size_t payload_size, |
| 52 | std::vector<PlatformHandle> handles) override; |
| 53 | |
| 54 | protected: |
| 55 | ~ChannelPosix() override; |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 56 | virtual void StartOnIOThread() LOCKS_EXCLUDED(write_lock_); |
| 57 | virtual void ShutDownOnIOThread() LOCKS_EXCLUDED(write_lock_ |
| 58 | #if BUILDFLAG(IS_IOS) |
| 59 | , |
| 60 | fds_to_close_lock_ |
| 61 | #endif // BUILDFLAG(IS_IOS) |
| 62 | ); |
| 63 | virtual void OnWriteError(Error error) LOCKS_EXCLUDED(write_lock_); |
Brian Geffon | 12b581a | 2021-02-03 23:48:03 | [diff] [blame] | 64 | |
| 65 | void RejectUpgradeOffer(); |
| 66 | void AcceptUpgradeOffer(); |
| 67 | |
| 68 | // Keeps the Channel alive at least until explicit shutdown on the IO thread. |
| 69 | scoped_refptr<Channel> self_; |
| 70 | |
| 71 | scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 72 | |
| 73 | private: |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 74 | void WaitForWriteOnIOThread() LOCKS_EXCLUDED(write_lock_); |
| 75 | void WaitForWriteOnIOThreadNoLock() EXCLUSIVE_LOCKS_REQUIRED(write_lock_); |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 76 | |
| 77 | // base::CurrentThread::DestructionObserver: |
| 78 | void WillDestroyCurrentMessageLoop() override; |
| 79 | |
Ken Rockot | 49a5e7a2 | 2024-11-28 00:43:21 | [diff] [blame] | 80 | // base::IOWatcher::FdWatcher: |
| 81 | void OnFdReadable(int fd) override; |
| 82 | void OnFdWritable(int fd) override LOCKS_EXCLUDED(write_lock_); |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 83 | |
| 84 | // Attempts to write a message directly to the channel. If the full message |
| 85 | // cannot be written, it's queued and a wait is initiated to write the message |
| 86 | // ASAP on the I/O thread. |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 87 | bool WriteNoLock(MessageView message_view) |
| 88 | EXCLUSIVE_LOCKS_REQUIRED(write_lock_) |
| 89 | #if BUILDFLAG(IS_IOS) |
| 90 | LOCKS_EXCLUDED(fds_to_close_lock_) |
| 91 | #endif // BUILDFLAG(IS_IOS) |
| 92 | ; |
| 93 | bool FlushOutgoingMessagesNoLock() EXCLUSIVE_LOCKS_REQUIRED(write_lock_); |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 94 | |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 95 | bool WriteOutgoingMessagesWithWritev() EXCLUSIVE_LOCKS_REQUIRED(write_lock_); |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 96 | |
| 97 | // FlushOutgoingMessagesWritevNoLock is equivalent to |
| 98 | // FlushOutgoingMessagesNoLock except it looks for opportunities to make |
| 99 | // only a single write syscall by using writev(2) instead of write(2). In |
| 100 | // most situations this is very straight forward; however, when a handle |
| 101 | // needs to be transferred we cannot use writev(2) and instead will fall |
| 102 | // back to the standard write. |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 103 | bool FlushOutgoingMessagesWritevNoLock() |
| 104 | EXCLUSIVE_LOCKS_REQUIRED(write_lock_); |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 105 | |
Xiaohan Wang | aa41c68 | 2022-01-14 18:50:49 | [diff] [blame] | 106 | #if BUILDFLAG(IS_IOS) |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 107 | bool CloseHandles(const int* fds, size_t num_fds) |
| 108 | LOCKS_EXCLUDED(fds_to_close_lock_); |
Xiaohan Wang | aa41c68 | 2022-01-14 18:50:49 | [diff] [blame] | 109 | #endif // BUILDFLAG(IS_IOS) |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 110 | |
Ken Rockot | ef861163 | 2023-04-04 02:57:50 | [diff] [blame] | 111 | // The socket over which to communicate. |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 112 | base::ScopedFD socket_; |
| 113 | |
Peter Boström | 7518796 | 2024-01-31 23:26:24 | [diff] [blame] | 114 | // These watchers must only be accessed on the IO thread. These are locked for |
| 115 | // allowing concurrent nullptr checking the unique_ptr but not dereferencing |
| 116 | // outside of the `io_task_runner_`. |
Ken Rockot | 49a5e7a2 | 2024-11-28 00:43:21 | [diff] [blame] | 117 | std::unique_ptr<base::IOWatcher::FdWatch> read_watcher_ |
Peter Boström | 7518796 | 2024-01-31 23:26:24 | [diff] [blame] | 118 | GUARDED_BY(write_lock_); |
Ken Rockot | 49a5e7a2 | 2024-11-28 00:43:21 | [diff] [blame] | 119 | std::unique_ptr<base::IOWatcher::FdWatch> write_watcher_ |
Peter Boström | 7518796 | 2024-01-31 23:26:24 | [diff] [blame] | 120 | GUARDED_BY(write_lock_); |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 121 | |
| 122 | base::circular_deque<base::ScopedFD> incoming_fds_; |
| 123 | |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 124 | base::Lock write_lock_; |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 125 | bool pending_write_ GUARDED_BY(write_lock_) = false; |
| 126 | bool reject_writes_ GUARDED_BY(write_lock_) = false; |
| 127 | base::circular_deque<MessageView> outgoing_messages_ GUARDED_BY(write_lock_); |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 128 | |
| 129 | bool leak_handle_ = false; |
| 130 | |
Xiaohan Wang | aa41c68 | 2022-01-14 18:50:49 | [diff] [blame] | 131 | #if BUILDFLAG(IS_IOS) |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 132 | base::Lock fds_to_close_lock_; |
Peter Boström | d5c1e144 | 2024-01-31 21:38:50 | [diff] [blame] | 133 | std::vector<base::ScopedFD> fds_to_close_ GUARDED_BY(fds_to_close_lock_); |
Xiaohan Wang | aa41c68 | 2022-01-14 18:50:49 | [diff] [blame] | 134 | #endif // BUILDFLAG(IS_IOS) |
Brian Geffon | e6bc5ff | 2021-01-05 20:07:48 | [diff] [blame] | 135 | }; |
| 136 | |
| 137 | } // namespace core |
| 138 | } // namespace mojo |
| 139 | |
Lei Zhang | 4d3c581 | 2021-04-21 20:31:05 | [diff] [blame] | 140 | #endif // MOJO_CORE_CHANNEL_POSIX_H_ |