Chromium Code Reviews| Index: mojo/edk/system/channel.h |
| diff --git a/mojo/edk/system/channel.h b/mojo/edk/system/channel.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..52e8b1e1eb5cee5a903f2c0bf9f86152c5251614 |
| --- /dev/null |
| +++ b/mojo/edk/system/channel.h |
| @@ -0,0 +1,179 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef MOJO_EDK_SYSTEM_CHANNEL_H_ |
| +#define MOJO_EDK_SYSTEM_CHANNEL_H_ |
| + |
| +#include "base/logging.h" |
| +#include "base/macros.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/task_runner.h" |
| +#include "mojo/edk/embedder/platform_handle_vector.h" |
| +#include "mojo/edk/embedder/scoped_platform_handle.h" |
| + |
| +namespace mojo { |
| +namespace edk { |
| + |
| +const size_t kChannelMessageAlignment = 8; |
| + |
| +// Channel provides a thread-safe interface to read and write arbitrary |
| +// delimited messages over an underlying I/O channel, optionally transferring |
| +// one or more platform handles in the process. |
| +class Channel : public base::RefCountedThreadSafe<Channel> { |
| + public: |
| + struct Message; |
| + |
| + using MessagePtr = scoped_ptr<Message>; |
| + |
| + // A message to be written to a channel. |
| + struct Message { |
| + struct Header { |
| + // Message size in bytes, including the header. |
| + uint32_t num_bytes; |
| + |
| + // Number of attached handles. |
| + uint16_t num_handles; |
| + |
| + // Zero |
| + uint16_t padding; |
| + }; |
| + |
| + // Allocates and owns a buffer for message data with enough capacity for |
| + // |payload_size| bytes plus a header. Takes ownership of |handles|, which |
| + // may be null. |
| + Message(size_t payload_size, size_t num_handles); |
| + |
| + ~Message(); |
| + |
| + // Constructs a Message from serialized message data. |
| + static MessagePtr Deserialize(const void* data, size_t data_num_bytes); |
| + |
| + const void* data() const { return data_; } |
| + size_t data_num_bytes() const { return size_; } |
| + |
| + void* mutable_payload() { return static_cast<void*>(header_ + 1); } |
| + const void* payload() const { |
| + return static_cast<const void*>(header_ + 1); |
| + } |
| + size_t payload_size() const; |
| + |
| + size_t num_handles() const { return header_->num_handles; } |
| + bool has_handles() const { return header_->num_handles > 0; } |
| + PlatformHandle* handles(); |
| + |
| + // Note: SetHandles() and TakeHandles() invalidate any previous value of |
| + // handles(). |
| + void SetHandles(ScopedPlatformHandleVectorPtr new_handles); |
| + ScopedPlatformHandleVectorPtr TakeHandles(); |
| + |
| + private: |
| + size_t size_; |
| + char* data_; |
| + Header* header_; |
| + |
| +#if defined(OS_WIN) |
| + // On Windows, handles are serialized in the data buffer along with the |
| + // rest of the payload. |
| + PlatformHandle* handles_ = nullptr; |
| +#else |
| + ScopedPlatformHandleVectorPtr handle_vector_; |
| +#endif |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Message); |
| + }; |
| + |
| + // Delegate methods are called from the I/O task runner with which the Channel |
| + // was created (see Channel::Create). |
| + class Delegate { |
| + public: |
| + virtual ~Delegate() {} |
| + |
| + // Notify of a received message. |payload| is not owned and must not be |
| + // retained; it will be null if |payload_size| is 0. |handles| are |
| + // transferred to the callee. |
| + virtual void OnChannelMessage(const void* payload, |
| + size_t payload_size, |
| + ScopedPlatformHandleVectorPtr handles) = 0; |
| + |
| + // Notify that an error has occured and the Channel will cease operation. |
| + virtual void OnChannelError() = 0; |
| + }; |
| + |
| + // Creates a new Channel around a |platform_handle|, taking ownership of the |
| + // handle. All I/O on the handle will be performed on |io_task_runner|. |
| + // Note that ShutDown() MUST be called on the Channel some time before |
| + // |delegate| is destroyed. |
| + static scoped_refptr<Channel> Create( |
| + Delegate* delegate, |
| + ScopedPlatformHandle platform_handle, |
| + scoped_refptr<base::TaskRunner> io_task_runner); |
| + |
| + // Request that the channel be shut down. This should always be called before |
| + // releasing the last reference to a Channel to ensure that it's cleaned up |
| + // on its I/O task runner's thread. |
| + // |
| + // Delegate methods will no longer be invoked after this call. |
| + void ShutDown(); |
|
Anand Mistry (off Chromium)
2016/01/28 02:26:24
It's not clear which threads these can be called o
|
| + |
| + // Begin processing I/O events. Delegate methods must only be invoked after |
| + // this call. |
| + virtual void Start() = 0; |
| + |
| + // Stop processing I/O events. |
| + virtual void ShutDownImpl() = 0; |
| + |
| + // Queues an outgoing message on the Channel. This message will either |
| + // eventually be written or will fail to write and trigger |
| + // Delegate::OnChannelError. |
| + virtual void Write(MessagePtr message) = 0; |
| + |
| + protected: |
| + explicit Channel(Delegate* delegate); |
| + virtual ~Channel(); |
| + |
| + // Called by the implementation when it wants somewhere to stick data. |
| + // |*buffer_capacity| may be set by the caller to indicate the desired buffer |
| + // size. If 0, a sane default size will be used instead. |
| + // |
| + // Returns the address of a buffer which can be written to, and indicates its |
| + // actual capacity in |*buffer_capacity|. |
| + char* GetReadBuffer(size_t* buffer_capacity); |
| + |
| + // Called by the implementation when new data is available in the read |
| + // buffer. Returns false to indicate an error. Upon success, |
| + // |*next_read_size_hint| will be set to a recommended size for the next |
| + // read done by the implementation. |
| + bool OnReadComplete(size_t bytes_read, size_t* next_read_size_hint); |
| + |
| + // Called by the implementation when something goes horribly wrong. It is NOT |
| + // OK to call this synchronously from any public interface methods. |
| + void OnError(); |
| + |
| + // Retrieves the set of platform handles read for a given message. |payload| |
| + // and |payload_size| correspond to the full message body. Depending on |
| + // the Channel implementation, this body may encode platform handles, or |
| + // handles may be stored and managed elsewhere by the implementation. |
| + // If |num_handles| handles cannot be returned, this must return null. |
| + // The implementation may also adjust the values of |*payload| and/or |
| + // |*payload_size| to hide handle data from the user. |
| + virtual ScopedPlatformHandleVectorPtr GetReadPlatformHandles( |
| + size_t num_handles, |
| + void** payload, |
| + size_t* payload_size) = 0; |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<Channel>; |
| + |
| + class ReadBuffer; |
| + |
| + Delegate* delegate_; |
| + const scoped_ptr<ReadBuffer> read_buffer_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Channel); |
| +}; |
| + |
| +} // namespace edk |
| +} // namespace mojo |
| + |
| +#endif // MOJO_EDK_SYSTEM_CHANNEL_H_ |