File: mojo_message.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (160 lines) | stat: -rw-r--r-- 6,451 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_CORE_IPCZ_DRIVER_MOJO_MESSAGE_H_
#define MOJO_CORE_IPCZ_DRIVER_MOJO_MESSAGE_H_

#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>

#include "base/containers/span.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_span.h"
#include "mojo/core/scoped_ipcz_handle.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/c/system/types.h"
#include "third_party/ipcz/include/ipcz/ipcz.h"

namespace mojo::core::ipcz_driver {

// The ipcz-based implementation of Mojo message objects. ipcz API exposes no
// notion of message objects, so this is merely heap storage for data and ipcz
// handles.
class MojoMessage {
 public:
  // Even with an input size of 0, MojoAppendMessageData is expected to allocate
  // *some* storage for message data. This constant therefore sets a lower bound
  // on payload allocation size. 32 bytes is chosen since it's the smallest
  // possible Mojo bindings message size (v0 header + 8 byte payload)
  static constexpr size_t kMinBufferSize = 32;

  MojoMessage();
  MojoMessage(std::vector<uint8_t> data, std::vector<IpczHandle> handles);

  ~MojoMessage();

  static MojoMessage* FromHandle(MojoMessageHandle handle) {
    return reinterpret_cast<MojoMessage*>(handle);
  }

  static std::unique_ptr<MojoMessage> TakeFromHandle(MojoMessageHandle handle) {
    return base::WrapUnique(FromHandle(handle));
  }

  MojoMessageHandle handle() const {
    return reinterpret_cast<MojoMessageHandle>(this);
  }

  base::span<const uint8_t> data() const { return data_; }
  base::span<uint8_t> mutable_data() const { return data_; }
  std::vector<IpczHandle>& handles() { return handles_; }
  uintptr_t context() const { return context_; }

  IpczHandle parcel() const { return parcel_.get(); }

  // Sets the received parcel object backing this message.
  void SetParcel(ScopedIpczHandle parcel);

  // Reserves capacity within a new message object, effectively implementing
  // MojoReserveMessageCapacity().
  MojoResult ReserveCapacity(uint32_t payload_buffer_size,
                             uint32_t* buffer_size);

  // Appends data to a new or partially serialized message, effectively
  // implementing MojoAppendMessageData().
  MojoResult AppendData(uint32_t additional_num_bytes,
                        const MojoHandle* handles,
                        uint32_t num_handles,
                        void** buffer,
                        uint32_t* buffer_size,
                        bool commit_size);

  // Retrieves data from a serialized message, effectively implementing
  // MojoGetMessageData();
  IpczResult GetData(void** buffer,
                     uint32_t* num_bytes,
                     MojoHandle* handles,
                     uint32_t* num_handles,
                     bool consume_handles);

  // Finalizes the Message by ensuring that any attached DataPipe objects also
  // attach their portals alongside the existing attachments. This operation is
  // balanced within SetParcel(), where DataPipes extract their portals from
  // the tail end of the attached handles.
  void AttachDataPipePortals();

  // Sets an unserialized message context on this message, with an optional
  // serializer and destructor.
  MojoResult SetContext(uintptr_t context,
                        MojoMessageContextSerializer serializer,
                        MojoMessageContextDestructor destructor);

  // Forcibly serializes this message if it holds an unserialized context.
  MojoResult Serialize();

  // Functions provided to ipcz when boxing MojoMessage objects for lazy
  // serialization.
  static IpczResult SerializeForIpcz(uintptr_t object,
                                     uint32_t,
                                     const void*,
                                     volatile void* data,
                                     size_t* num_bytes,
                                     IpczHandle* handles,
                                     size_t* num_handles);
  static void DestroyForIpcz(uintptr_t object, uint32_t, const void*);

  // Boxes a MojoMessage object for transmission within another message. This is
  // used to support transmission of unserialized MojoMessages through ipcz,
  // with support for lazy serialization if needed.
  static ScopedIpczHandle Box(std::unique_ptr<MojoMessage> message);

  // Constructs a new MojoMessage from `message`, if `message` contains a single
  // box with an application object or subparcel inside of it. In that case the
  // application object or subparcel is interpreted as an embedded MojoMessage,
  // and that MojoMessage is reconstituted and returned. Otherwise this returns
  // null to indicate that `message` is not a wrapper around another
  // MojoMessage.
  static std::unique_ptr<MojoMessage> UnwrapFrom(MojoMessage& message);

 private:
  IpczResult SerializeForIpczImpl(volatile void* data,
                                  size_t* num_bytes,
                                  IpczHandle* handles,
                                  size_t* num_handles);

  // The parcel backing this message, if any.
  ScopedIpczHandle parcel_;

  // A heap buffer of message data, used only when `parcel_` is null.
  using DataPtr = std::unique_ptr<uint8_t[]>;
  DataPtr data_storage_;
  size_t data_storage_size_ = 0;

  // A view into the message data, whether it's backed by `parcel_` or stored in
  // `data_storage_`.
  base::raw_span<uint8_t, DanglingUntriaged> data_;

  std::vector<IpczHandle> handles_;
  bool handles_consumed_ = false;
  bool size_committed_ = false;

  // Unserialized message state. These values are provided by the application
  // calling MojoSetMessageContext() for lazy serialization. `context_` is an
  // arbitrary opaque value. `serializer_` is invoked when the application must
  // produce a serialized message, with `context_` as an input. `destructor_` is
  // if non-null is called to clean up any application state associated with
  // `context_`.
  //
  // If `context_` is zero, then no unserialized message context has been set by
  // the application.
  uintptr_t context_ = 0;
  MojoMessageContextSerializer serializer_ = nullptr;
  MojoMessageContextDestructor destructor_ = nullptr;
};

}  // namespace mojo::core::ipcz_driver

#endif  // MOJO_CORE_IPCZ_DRIVER_MOJO_MESSAGE_H_