blob: 8398a4bcfd1ddc60733aae18cb4bac76b330bffd [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// Copyright 2013 The Chromium Authors. All rights reserved.
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_EDK_SYSTEM_RAW_CHANNEL_H_
6#define MOJO_EDK_SYSTEM_RAW_CHANNEL_H_
7
Viet-Trung Luu11b1e042015-09-17 14:44:18 -07008#include <memory>
James Robinson646469d2014-10-03 15:33:28 -07009#include <vector>
10
Viet-Trung Luu2fcb5be2015-11-30 12:16:33 -080011#include "mojo/edk/platform/platform_handle.h"
Viet-Trung Luu7b73f3a2015-12-15 12:36:27 -080012#include "mojo/edk/platform/platform_handle_watcher.h"
Viet-Trung Luu2fcb5be2015-11-30 12:16:33 -080013#include "mojo/edk/platform/scoped_platform_handle.h"
Viet-Trung Luu7b73f3a2015-12-15 12:36:27 -080014#include "mojo/edk/platform/task_runner.h"
James Robinson646469d2014-10-03 15:33:28 -070015#include "mojo/edk/system/message_in_transit.h"
Viet-Trung Luu4f857d52015-06-25 11:31:19 -070016#include "mojo/edk/system/message_in_transit_queue.h"
Viet-Trung Luud42e48a2015-11-03 14:54:55 -080017#include "mojo/edk/util/mutex.h"
Viet-Trung Luu7b73f3a2015-12-15 12:36:27 -080018#include "mojo/edk/util/ref_ptr.h"
Viet-Trung Luud42e48a2015-11-03 14:54:55 -080019#include "mojo/edk/util/thread_annotations.h"
Viet-Trung Luub6f36fa2016-01-28 16:36:03 -080020#include "mojo/edk/util/weak_ptr.h"
Viet-Trung Luu7d5ced22015-06-24 15:21:39 -070021#include "mojo/public/cpp/system/macros.h"
James Robinson646469d2014-10-03 15:33:28 -070022
James Robinson646469d2014-10-03 15:33:28 -070023namespace mojo {
24namespace system {
25
26// |RawChannel| is an interface and base class for objects that wrap an OS
27// "pipe". It presents the following interface to users:
28// - Receives and dispatches messages on an I/O thread (running a
29// |MessageLoopForIO|.
30// - Provides a thread-safe way of writing messages (|WriteMessage()|);
31// writing/queueing messages will not block and is atomic from the point of
32// view of the caller. If necessary, messages are queued (to be written on
33// the aforementioned thread).
34//
35// OS-specific implementation subclasses are to be instantiated using the
36// |Create()| static factory method.
37//
Viet-Trung Luueefb95f2015-09-11 15:56:15 -070038// With the exception of |WriteMessage()| and |IsWriteBufferEmpty()|, this class
39// is thread-unsafe (and in general its methods should only be used on the I/O
40// thread, i.e., the thread on which |Init()| is called).
Viet-Trung Luu535e5d92015-09-18 11:12:49 -070041class RawChannel {
James Robinson646469d2014-10-03 15:33:28 -070042 public:
Viet-Trung Luu85edf242015-01-21 16:01:28 -080043 // This object may be destroyed on any thread (if |Init()| was called, after
44 // |Shutdown()| was called).
James Robinson646469d2014-10-03 15:33:28 -070045 virtual ~RawChannel();
46
47 // The |Delegate| is only accessed on the same thread as the message loop
48 // (passed in on creation).
Viet-Trung Luu535e5d92015-09-18 11:12:49 -070049 class Delegate {
James Robinson646469d2014-10-03 15:33:28 -070050 public:
51 enum Error {
52 // Failed read due to raw channel shutdown (e.g., on the other side).
53 ERROR_READ_SHUTDOWN,
54 // Failed read due to raw channel being broken (e.g., if the other side
55 // died without shutting down).
56 ERROR_READ_BROKEN,
57 // Received a bad message.
58 ERROR_READ_BAD_MESSAGE,
59 // Unknown read error.
60 ERROR_READ_UNKNOWN,
61 // Generic write error.
62 ERROR_WRITE
63 };
64
Viet-Trung Luu85edf242015-01-21 16:01:28 -080065 // Called when a message is read. This may call the |RawChannel|'s
66 // |Shutdown()| and then (if desired) destroy it.
James Robinson646469d2014-10-03 15:33:28 -070067 virtual void OnReadMessage(
68 const MessageInTransit::View& message_view,
Viet-Trung Luu2fcb5be2015-11-30 12:16:33 -080069 std::unique_ptr<std::vector<platform::ScopedPlatformHandle>>
Viet-Trung Luu6f395e32015-11-25 12:24:07 -080070 platform_handles) = 0;
James Robinson646469d2014-10-03 15:33:28 -070071
Viet-Trung Luu85edf242015-01-21 16:01:28 -080072 // Called when there's a (fatal) error. This may call the |RawChannel|'s
73 // |Shutdown()| and then (if desired) destroy it.
James Robinson646469d2014-10-03 15:33:28 -070074 //
75 // For each raw channel, there'll be at most one |ERROR_READ_...| and at
76 // most one |ERROR_WRITE| notification. After |OnError(ERROR_READ_...)|,
77 // |OnReadMessage()| won't be called again.
78 virtual void OnError(Error error) = 0;
79
80 protected:
81 virtual ~Delegate() {}
82 };
83
84 // Static factory method. |handle| should be a handle to a
85 // (platform-appropriate) bidirectional communication channel (e.g., a socket
86 // on POSIX, a named pipe on Windows).
Viet-Trung Luua1e901b2015-09-17 18:15:08 -070087 static std::unique_ptr<RawChannel> Create(
Viet-Trung Luu2fcb5be2015-11-30 12:16:33 -080088 platform::ScopedPlatformHandle handle);
James Robinson646469d2014-10-03 15:33:28 -070089
90 // This must be called (on an I/O thread) before this object is used. Does
91 // *not* take ownership of |delegate|. Both the I/O thread and |delegate| must
92 // remain alive until |Shutdown()| is called (unless this fails); |delegate|
Viet-Trung Luu1d7c0102015-01-15 14:51:14 -080093 // will no longer be used after |Shutdown()|.
Viet-Trung Luu7b73f3a2015-12-15 12:36:27 -080094 void Init(util::RefPtr<platform::TaskRunner>&& io_task_runner,
95 platform::PlatformHandleWatcher* io_watcher,
96 Delegate* delegate) MOJO_NOT_THREAD_SAFE;
James Robinson646469d2014-10-03 15:33:28 -070097
98 // This must be called (on the I/O thread) before this object is destroyed.
Viet-Trung Luueefb95f2015-09-11 15:56:15 -070099 void Shutdown() MOJO_NOT_THREAD_SAFE;
James Robinson646469d2014-10-03 15:33:28 -0700100
101 // Writes the given message (or schedules it to be written). |message| must
102 // have no |Dispatcher|s still attached (i.e.,
103 // |SerializeAndCloseDispatchers()| should have been called). This method is
104 // thread-safe and may be called from any thread. Returns true on success.
Viet-Trung Luu266a79f2015-09-18 08:27:48 -0700105 bool WriteMessage(std::unique_ptr<MessageInTransit> message);
James Robinson646469d2014-10-03 15:33:28 -0700106
107 // Returns true if the write buffer is empty (i.e., all messages written using
108 // |WriteMessage()| have actually been sent.
109 // TODO(vtl): We should really also notify our delegate when the write buffer
110 // becomes empty (or something like that).
111 bool IsWriteBufferEmpty();
112
113 // Returns the amount of space needed in the |MessageInTransit|'s
114 // |TransportData|'s "platform handle table" per platform handle (to be
115 // attached to a message). (This amount may be zero.)
116 virtual size_t GetSerializedPlatformHandleSize() const = 0;
117
118 protected:
119 // Result of I/O operations.
120 enum IOResult {
121 IO_SUCCEEDED,
122 // Failed due to a (probably) clean shutdown (e.g., of the other end).
123 IO_FAILED_SHUTDOWN,
124 // Failed due to the connection being broken (e.g., the other end dying).
125 IO_FAILED_BROKEN,
126 // Failed due to some other (unexpected) reason.
127 IO_FAILED_UNKNOWN,
128 IO_PENDING
129 };
130
Viet-Trung Luu535e5d92015-09-18 11:12:49 -0700131 class ReadBuffer {
James Robinson646469d2014-10-03 15:33:28 -0700132 public:
133 ReadBuffer();
134 ~ReadBuffer();
135
136 void GetBuffer(char** addr, size_t* size);
137
138 private:
139 friend class RawChannel;
140
141 // We store data from |[Schedule]Read()|s in |buffer_|. The start of
142 // |buffer_| is always aligned with a message boundary (we will copy memory
143 // to ensure this), but |buffer_| may be larger than the actual number of
144 // bytes we have.
145 std::vector<char> buffer_;
146 size_t num_valid_bytes_;
147
Viet-Trung Luu7d5ced22015-06-24 15:21:39 -0700148 MOJO_DISALLOW_COPY_AND_ASSIGN(ReadBuffer);
James Robinson646469d2014-10-03 15:33:28 -0700149 };
150
Viet-Trung Luu535e5d92015-09-18 11:12:49 -0700151 class WriteBuffer {
James Robinson646469d2014-10-03 15:33:28 -0700152 public:
153 struct Buffer {
154 const char* addr;
155 size_t size;
156 };
157
158 explicit WriteBuffer(size_t serialized_platform_handle_size);
159 ~WriteBuffer();
160
161 // Returns true if there are (more) platform handles to be sent (from the
162 // front of |message_queue_|).
163 bool HavePlatformHandlesToSend() const;
164 // Gets platform handles to be sent (from the front of |message_queue_|).
165 // This should only be called if |HavePlatformHandlesToSend()| returned
166 // true. There are two components to this: the actual |PlatformHandle|s
167 // (which should be closed once sent) and any additional serialization
168 // information (which will be embedded in the message's data; there are
169 // |GetSerializedPlatformHandleSize()| bytes per handle). Once all platform
170 // handles have been sent, the message data should be written next (see
171 // |GetBuffers()|).
Viet-Trung Luu4f857d52015-06-25 11:31:19 -0700172 // TODO(vtl): Maybe this method should be const, but
173 // |PlatformHandle::CloseIfNecessary()| isn't const (and actually modifies
174 // state).
James Robinson646469d2014-10-03 15:33:28 -0700175 void GetPlatformHandlesToSend(size_t* num_platform_handles,
Viet-Trung Luu2fcb5be2015-11-30 12:16:33 -0800176 platform::PlatformHandle** platform_handles,
James Robinson646469d2014-10-03 15:33:28 -0700177 void** serialization_data);
178
179 // Gets buffers to be written. These buffers will always come from the front
180 // of |message_queue_|. Once they are completely written, the front
181 // |MessageInTransit| should be popped (and destroyed); this is done in
182 // |OnWriteCompletedNoLock()|.
183 void GetBuffers(std::vector<Buffer>* buffers) const;
184
185 private:
186 friend class RawChannel;
187
188 const size_t serialized_platform_handle_size_;
189
Viet-Trung Luu4f857d52015-06-25 11:31:19 -0700190 MessageInTransitQueue message_queue_;
James Robinson646469d2014-10-03 15:33:28 -0700191 // Platform handles are sent before the message data, but doing so may
192 // require several passes. |platform_handles_offset_| indicates the position
193 // in the first message's vector of platform handles to send next.
194 size_t platform_handles_offset_;
195 // The first message's data may have been partially sent. |data_offset_|
196 // indicates the position in the first message's data to start the next
197 // write.
198 size_t data_offset_;
199
Viet-Trung Luu7d5ced22015-06-24 15:21:39 -0700200 MOJO_DISALLOW_COPY_AND_ASSIGN(WriteBuffer);
James Robinson646469d2014-10-03 15:33:28 -0700201 };
202
203 RawChannel();
204
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700205 // |result| must not be |IO_PENDING|. Must be called on the I/O thread. This
206 // object may be destroyed by this call.
207 void OnReadCompleted(IOResult io_result, size_t bytes_read)
208 MOJO_LOCKS_EXCLUDED(write_mutex_);
209 // |result| must not be |IO_PENDING|. Must be called on the I/O thread. This
210 // object may be destroyed by this call.
James Robinson646469d2014-10-03 15:33:28 -0700211 void OnWriteCompleted(IOResult io_result,
212 size_t platform_handles_written,
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700213 size_t bytes_written) MOJO_LOCKS_EXCLUDED(write_mutex_);
James Robinson646469d2014-10-03 15:33:28 -0700214
Viet-Trung Luu2072acc2015-12-16 10:44:24 -0800215 const util::RefPtr<platform::TaskRunner>& io_task_runner() const {
216 return io_task_runner_;
217 }
218 platform::PlatformHandleWatcher* io_watcher() const { return io_watcher_; }
Viet-Trung Luud42e48a2015-11-03 14:54:55 -0800219 util::Mutex& write_mutex() MOJO_LOCK_RETURNED(write_mutex_) {
220 return write_mutex_;
221 }
James Robinson646469d2014-10-03 15:33:28 -0700222
223 // Should only be called on the I/O thread.
224 ReadBuffer* read_buffer() { return read_buffer_.get(); }
225
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700226 WriteBuffer* write_buffer_no_lock()
227 MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_) {
James Robinson646469d2014-10-03 15:33:28 -0700228 return write_buffer_.get();
229 }
230
231 // Adds |message| to the write message queue. Implementation subclasses may
232 // override this to add any additional "control" messages needed. This is
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700233 // called (on any thread).
Viet-Trung Luu266a79f2015-09-18 08:27:48 -0700234 virtual void EnqueueMessageNoLock(std::unique_ptr<MessageInTransit> message)
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700235 MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_);
James Robinson646469d2014-10-03 15:33:28 -0700236
237 // Handles any control messages targeted to the |RawChannel| (or
238 // implementation subclass). Implementation subclasses may override this to
239 // handle any implementation-specific control messages, but should call
240 // |RawChannel::OnReadMessageForRawChannel()| for any remaining messages.
241 // Returns true on success and false on error (e.g., invalid control message).
242 // This is only called on the I/O thread.
243 virtual bool OnReadMessageForRawChannel(
244 const MessageInTransit::View& message_view);
245
246 // Reads into |read_buffer()|.
247 // This class guarantees that:
248 // - the area indicated by |GetBuffer()| will stay valid until read completion
249 // (but please also see the comments for |OnShutdownNoLock()|);
250 // - a second read is not started if there is a pending read;
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700251 // - the method is called on the I/O thread.
James Robinson646469d2014-10-03 15:33:28 -0700252 //
253 // The implementing subclass must guarantee that:
254 // - |bytes_read| is untouched unless |Read()| returns |IO_SUCCEEDED|;
255 // - if the method returns |IO_PENDING|, |OnReadCompleted()| will be called on
256 // the I/O thread to report the result, unless |Shutdown()| is called.
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700257 virtual IOResult Read(size_t* bytes_read)
258 MOJO_LOCKS_EXCLUDED(write_mutex_) = 0;
James Robinson646469d2014-10-03 15:33:28 -0700259 // Similar to |Read()|, except that the implementing subclass must also
260 // guarantee that the method doesn't succeed synchronously, i.e., it only
261 // returns |IO_FAILED_...| or |IO_PENDING|.
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700262 virtual IOResult ScheduleRead() MOJO_LOCKS_EXCLUDED(write_mutex_) = 0;
James Robinson646469d2014-10-03 15:33:28 -0700263
264 // Called by |OnReadCompleted()| to get the platform handles associated with
265 // the given platform handle table (from a message). This should only be
266 // called when |num_platform_handles| is nonzero. Returns null if the
267 // |num_platform_handles| handles are not available. Only called on the I/O
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700268 // thread.
Viet-Trung Luu2fcb5be2015-11-30 12:16:33 -0800269 virtual std::unique_ptr<std::vector<platform::ScopedPlatformHandle>>
Viet-Trung Luu6f395e32015-11-25 12:24:07 -0800270 GetReadPlatformHandles(size_t num_platform_handles,
271 const void* platform_handle_table)
272 MOJO_LOCKS_EXCLUDED(write_mutex_) = 0;
James Robinson646469d2014-10-03 15:33:28 -0700273
274 // Writes contents in |write_buffer_no_lock()|.
275 // This class guarantees that:
276 // - the |PlatformHandle|s given by |GetPlatformHandlesToSend()| and the
277 // buffer(s) given by |GetBuffers()| will remain valid until write
278 // completion (see also the comments for |OnShutdownNoLock()|);
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700279 // - a second write is not started if there is a pending write.
James Robinson646469d2014-10-03 15:33:28 -0700280 //
281 // The implementing subclass must guarantee that:
282 // - |platform_handles_written| and |bytes_written| are untouched unless
283 // |WriteNoLock()| returns |IO_SUCCEEDED|;
284 // - if the method returns |IO_PENDING|, |OnWriteCompleted()| will be called
285 // on the I/O thread to report the result, unless |Shutdown()| is called.
286 virtual IOResult WriteNoLock(size_t* platform_handles_written,
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700287 size_t* bytes_written)
288 MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_) = 0;
James Robinson646469d2014-10-03 15:33:28 -0700289 // Similar to |WriteNoLock()|, except that the implementing subclass must also
290 // guarantee that the method doesn't succeed synchronously, i.e., it only
291 // returns |IO_FAILED_...| or |IO_PENDING|.
292 virtual IOResult ScheduleWriteNoLock() = 0;
293
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700294 // Must be called on the I/O thread.
295 virtual void OnInit() MOJO_LOCKS_EXCLUDED(write_mutex_) = 0;
James Robinson646469d2014-10-03 15:33:28 -0700296 // On shutdown, passes the ownership of the buffers to subclasses, which may
Viet-Trung Luu85edf242015-01-21 16:01:28 -0800297 // want to preserve them if there are pending read/writes. After this is
298 // called, |OnReadCompleted()| must no longer be called. Must be called on the
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700299 // I/O thread.
Viet-Trung Luu11b1e042015-09-17 14:44:18 -0700300 virtual void OnShutdownNoLock(std::unique_ptr<ReadBuffer> read_buffer,
301 std::unique_ptr<WriteBuffer> write_buffer)
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700302 MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_) = 0;
James Robinson646469d2014-10-03 15:33:28 -0700303
304 private:
305 // Converts an |IO_FAILED_...| for a read to a |Delegate::Error|.
306 static Delegate::Error ReadIOResultToError(IOResult io_result);
307
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700308 // Calls |delegate_->OnError(error)|. Must be called on the I/O thread. This
309 // object may be destroyed by this call.
310 void CallOnError(Delegate::Error error) MOJO_LOCKS_EXCLUDED(write_mutex_);
James Robinson646469d2014-10-03 15:33:28 -0700311
312 // If |io_result| is |IO_SUCCESS|, updates the write buffer and schedules a
313 // write operation to run later if there is more to write. If |io_result| is
314 // failure or any other error occurs, cancels pending writes and returns
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700315 // false. May only be called if |write_stopped_| is false.
James Robinson646469d2014-10-03 15:33:28 -0700316 bool OnWriteCompletedNoLock(IOResult io_result,
317 size_t platform_handles_written,
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700318 size_t bytes_written)
319 MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_);
James Robinson646469d2014-10-03 15:33:28 -0700320
321 // Set in |Init()| and never changed (hence usable on any thread without
322 // locking):
Viet-Trung Luu7b73f3a2015-12-15 12:36:27 -0800323 util::RefPtr<platform::TaskRunner> io_task_runner_;
James Robinson646469d2014-10-03 15:33:28 -0700324
325 // Only used on the I/O thread:
Viet-Trung Luu7b73f3a2015-12-15 12:36:27 -0800326 platform::PlatformHandleWatcher* io_watcher_;
James Robinson646469d2014-10-03 15:33:28 -0700327 Delegate* delegate_;
Viet-Trung Luu85edf242015-01-21 16:01:28 -0800328 bool* set_on_shutdown_;
Viet-Trung Luu11b1e042015-09-17 14:44:18 -0700329 std::unique_ptr<ReadBuffer> read_buffer_;
James Robinson646469d2014-10-03 15:33:28 -0700330
Viet-Trung Luud42e48a2015-11-03 14:54:55 -0800331 util::Mutex write_mutex_; // Protects the following members.
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700332 bool write_stopped_ MOJO_GUARDED_BY(write_mutex_);
Viet-Trung Luu11b1e042015-09-17 14:44:18 -0700333 std::unique_ptr<WriteBuffer> write_buffer_ MOJO_GUARDED_BY(write_mutex_);
James Robinson646469d2014-10-03 15:33:28 -0700334
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700335 // This is used for posting tasks from write threads to the I/O thread. The
336 // weak pointers it produces are only used/invalidated on the I/O thread.
Viet-Trung Luub6f36fa2016-01-28 16:36:03 -0800337 util::WeakPtrFactory<RawChannel> weak_ptr_factory_
Viet-Trung Luueefb95f2015-09-11 15:56:15 -0700338 MOJO_GUARDED_BY(write_mutex_);
James Robinson646469d2014-10-03 15:33:28 -0700339
Viet-Trung Luu7d5ced22015-06-24 15:21:39 -0700340 MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannel);
James Robinson646469d2014-10-03 15:33:28 -0700341};
342
343} // namespace system
344} // namespace mojo
345
346#endif // MOJO_EDK_SYSTEM_RAW_CHANNEL_H_