blob: 2e5aba31c1d32024a6b9e3b6355198df064ddab9 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include <lib/user_copy/user_ptr.h>
#include <zircon/types.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/unique_ptr.h>
constexpr uint32_t kMaxMessageSize = 65536u;
constexpr uint32_t kMaxMessageHandles = 64u;
// ensure public constants are aligned
static_assert(ZX_CHANNEL_MAX_MSG_BYTES == kMaxMessageSize, "");
static_assert(ZX_CHANNEL_MAX_MSG_HANDLES == kMaxMessageHandles, "");
class Handle;
class MessagePacket : public fbl::DoublyLinkedListable<fbl::unique_ptr<MessagePacket>> {
public:
// Creates a message packet containing the provided data and space for
// |num_handles| handles. The handles array is uninitialized and must
// be completely overwritten by clients.
static zx_status_t Create(user_ptr<const void> data, uint32_t data_size,
uint32_t num_handles,
fbl::unique_ptr<MessagePacket>* msg);
static zx_status_t Create(const void* data, uint32_t data_size,
uint32_t num_handles,
fbl::unique_ptr<MessagePacket>* msg);
uint32_t data_size() const { return data_size_; }
// Copies the packet's |data_size()| bytes to |buf|.
// Returns an error if |buf| points to a bad user address.
zx_status_t CopyDataTo(user_ptr<void> buf) const {
return buf.copy_array_to_user(data(), data_size_);
}
uint32_t num_handles() const { return num_handles_; }
Handle* const* handles() const { return handles_; }
Handle** mutable_handles() { return handles_; }
void set_owns_handles(bool own_handles) { owns_handles_ = own_handles; }
// zx_channel_call treats the leading bytes of the payload as
// a transaction id of type zx_txid_t.
zx_txid_t get_txid() const {
if (data_size_ < sizeof(zx_txid_t)) {
return 0;
} else {
return *(reinterpret_cast<const zx_txid_t*>(data()));
}
}
private:
MessagePacket(uint32_t data_size, uint32_t num_handles, Handle** handles);
~MessagePacket();
// Allocates a new packet that can hold the specified amount of
// data/handles.
static zx_status_t NewPacket(uint32_t data_size, uint32_t num_handles,
fbl::unique_ptr<MessagePacket>* msg);
// Create() uses malloc(), so we must delete using free().
static void operator delete(void* ptr) {
free(ptr);
}
friend class fbl::unique_ptr<MessagePacket>;
// Handles and data are stored in the same buffer: num_handles_ Handle*
// entries first, then the data buffer.
void* data() const { return static_cast<void*>(handles_ + num_handles_); }
Handle** const handles_;
const uint32_t data_size_;
const uint16_t num_handles_;
bool owns_handles_;
};