roll skia to 4276
[chromium-blink-merge.git] / base / mach_ipc_mac.h
blobd0898a3e2f30c77d183b2ca51aebe8662519a324
1 // Copyright (c) 2012 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.
5 #ifndef BASE_MACH_IPC_MAC_H_
6 #define BASE_MACH_IPC_MAC_H_
7 #pragma once
9 #include <mach/mach.h>
10 #include <mach/message.h>
11 #include <servers/bootstrap.h>
12 #include <sys/types.h>
14 #include <CoreServices/CoreServices.h>
16 #include "base/base_export.h"
17 #include "base/basictypes.h"
19 //==============================================================================
20 // DISCUSSION:
22 // The three main classes of interest are
24 // MachMessage: a wrapper for a Mach message of the following form
25 // mach_msg_header_t
26 // mach_msg_body_t
27 // optional descriptors
28 // optional extra message data
30 // MachReceiveMessage and MachSendMessage subclass MachMessage
31 // and are used instead of MachMessage which is an abstract base class
33 // ReceivePort:
34 // Represents a Mach port for which we have receive rights
36 // MachPortSender:
37 // Represents a Mach port for which we have send rights
39 // Here's an example to receive a message on a server port:
41 // // This creates our named server port
42 // ReceivePort receivePort("com.Google.MyService");
44 // MachReceiveMessage message;
45 // kern_return_t result = receivePort.WaitForMessage(&message, 0);
47 // if (result == KERN_SUCCESS && message.GetMessageID() == 57) {
48 // mach_port_t task = message.GetTranslatedPort(0);
49 // mach_port_t thread = message.GetTranslatedPort(1);
51 // char *messageString = message.GetData();
53 // printf("message string = %s\n", messageString);
54 // }
56 // Here is an example of using these classes to send a message to this port:
58 // // send to already named port
59 // MachPortSender sender("com.Google.MyService");
60 // MachSendMessage message(57); // our message ID is 57
62 // // add some ports to be translated for us
63 // message.AddDescriptor(mach_task_self()); // our task
64 // message.AddDescriptor(mach_thread_self()); // this thread
66 // char messageString[] = "Hello server!\n";
67 // message.SetData(messageString, strlen(messageString)+1);
68 // // timeout 1000ms
69 // kern_return_t result = sender.SendMessage(message, 1000);
72 #define PRINT_MACH_RESULT(result_, message_) \
73 printf(message_" %s (%d)\n", mach_error_string(result_), result_ );
75 namespace base {
77 //==============================================================================
78 // A wrapper class for mach_msg_port_descriptor_t (with same memory layout)
79 // with convenient constructors and accessors
80 class MachMsgPortDescriptor : public mach_msg_port_descriptor_t {
81 public:
82 // General-purpose constructor
83 MachMsgPortDescriptor(mach_port_t in_name,
84 mach_msg_type_name_t in_disposition) {
85 name = in_name;
86 pad1 = 0;
87 pad2 = 0;
88 disposition = in_disposition;
89 type = MACH_MSG_PORT_DESCRIPTOR;
92 // For passing send rights to a port
93 MachMsgPortDescriptor(mach_port_t in_name) {
94 name = in_name;
95 pad1 = 0;
96 pad2 = 0;
97 disposition = MACH_MSG_TYPE_PORT_SEND;
98 type = MACH_MSG_PORT_DESCRIPTOR;
101 // Copy constructor
102 MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) {
103 name = desc.name;
104 pad1 = desc.pad1;
105 pad2 = desc.pad2;
106 disposition = desc.disposition;
107 type = desc.type;
110 mach_port_t GetMachPort() const {
111 return name;
114 mach_msg_type_name_t GetDisposition() const {
115 return disposition;
118 // For convenience
119 operator mach_port_t() const {
120 return GetMachPort();
124 //==============================================================================
125 // MachMessage: a wrapper for a Mach message
126 // (mach_msg_header_t, mach_msg_body_t, extra data)
128 // This considerably simplifies the construction of a message for sending
129 // and the getting at relevant data and descriptors for the receiver.
131 // This class can be initialized using external storage of an arbitrary size
132 // or it can manage storage internally.
133 // 1. If storage is allocated internally, the combined size of the descriptors
134 // plus data must be less than 1024. But as a benefit no memory allocation is
135 // necessary.
136 // 2. For external storage, a buffer of at least EmptyMessageSize() must be
137 // provided.
139 // A MachMessage object is used by ReceivePort::WaitForMessage
140 // and MachPortSender::SendMessage
142 class BASE_EXPORT MachMessage {
143 public:
144 static const size_t kEmptyMessageSize;
146 virtual ~MachMessage();
148 // The receiver of the message can retrieve the raw data this way
149 u_int8_t *GetData() {
150 return GetDataLength() > 0 ? GetDataPacket()->data : NULL;
153 u_int32_t GetDataLength() {
154 return EndianU32_LtoN(GetDataPacket()->data_length);
157 // The message ID may be used as a code identifying the type of message
158 void SetMessageID(int32_t message_id) {
159 GetDataPacket()->id = EndianU32_NtoL(message_id);
162 int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); }
164 // Adds a descriptor (typically a Mach port) to be translated
165 // returns true if successful, otherwise not enough space
166 bool AddDescriptor(const MachMsgPortDescriptor &desc);
168 int GetDescriptorCount() const {
169 return storage_->body.msgh_descriptor_count;
172 MachMsgPortDescriptor *GetDescriptor(int n);
174 // Convenience method which gets the Mach port described by the descriptor
175 mach_port_t GetTranslatedPort(int n);
177 // A simple message is one with no descriptors
178 bool IsSimpleMessage() const { return GetDescriptorCount() == 0; }
180 // Sets raw data for the message (returns false if not enough space)
181 bool SetData(const void* data, int32_t data_length);
183 protected:
184 // Consider this an abstract base class - must create an actual instance
185 // of MachReceiveMessage or MachSendMessage
186 MachMessage();
188 // Constructor for use with preallocate storage.
189 // storage_length must be >= EmptyMessageSize()
190 MachMessage(void *storage, size_t storage_length);
192 friend class ReceivePort;
193 friend class MachPortSender;
195 // Represents raw data in our message
196 struct MessageDataPacket {
197 int32_t id; // little-endian
198 int32_t data_length; // little-endian
199 u_int8_t data[1]; // actual size limited by storage_length_bytes_
202 MessageDataPacket* GetDataPacket();
204 void SetDescriptorCount(int n);
205 void SetDescriptor(int n, const MachMsgPortDescriptor &desc);
207 // Returns total message size setting msgh_size in the header to this value
208 int CalculateSize();
210 // Returns total storage size that this object can grow to, this is inclusive
211 // of the Mach header.
212 size_t MaxSize() const { return storage_length_bytes_; }
214 mach_msg_header_t *Head() { return &(storage_->head); }
216 private:
217 struct MachMessageData {
218 mach_msg_header_t head;
219 mach_msg_body_t body;
220 // descriptors and data may be embedded here.
221 u_int8_t padding[1024];
224 MachMessageData *storage_;
225 size_t storage_length_bytes_;
226 bool own_storage_; // Is storage owned by this object?
229 //==============================================================================
230 // MachReceiveMessage and MachSendMessage are useful to separate the idea
231 // of a Mach message being sent and being received, and adds increased type
232 // safety:
233 // ReceivePort::WaitForMessage() only accepts a MachReceiveMessage
234 // MachPortSender::SendMessage() only accepts a MachSendMessage
236 //==============================================================================
237 class MachReceiveMessage : public MachMessage {
238 public:
239 MachReceiveMessage() : MachMessage() {}
240 MachReceiveMessage(void *storage, size_t storage_length)
241 : MachMessage(storage, storage_length) {}
243 private:
244 DISALLOW_COPY_AND_ASSIGN(MachReceiveMessage);
247 //==============================================================================
248 class BASE_EXPORT MachSendMessage : public MachMessage {
249 public:
250 explicit MachSendMessage(int32_t message_id);
251 MachSendMessage(void *storage, size_t storage_length, int32_t message_id);
253 private:
254 void Initialize(int32_t message_id);
256 DISALLOW_COPY_AND_ASSIGN(MachSendMessage);
259 //==============================================================================
260 // Represents a Mach port for which we have receive rights
261 class BASE_EXPORT ReceivePort {
262 public:
263 // Creates a new Mach port for receiving messages and registers a name for it
264 explicit ReceivePort(const char *receive_port_name);
266 // Given an already existing Mach port, use it. We take ownership of the
267 // port and deallocate it in our destructor.
268 explicit ReceivePort(mach_port_t receive_port);
270 // Create a new Mach port for receiving messages
271 ReceivePort();
273 ~ReceivePort();
275 // Waits on the Mach port until message received or timeout. If |timeout| is
276 // MACH_MSG_TIMEOUT_NONE, this method waits forever.
277 kern_return_t WaitForMessage(MachReceiveMessage *out_message,
278 mach_msg_timeout_t timeout);
280 // The underlying Mach port that we wrap
281 mach_port_t GetPort() const { return port_; }
283 private:
284 mach_port_t port_;
285 kern_return_t init_result_;
287 DISALLOW_COPY_AND_ASSIGN(ReceivePort);
290 //==============================================================================
291 // Represents a Mach port for which we have send rights
292 class BASE_EXPORT MachPortSender {
293 public:
294 // get a port with send rights corresponding to a named registered service
295 explicit MachPortSender(const char *receive_port_name);
298 // Given an already existing Mach port, use it. Does not take ownership of
299 // |send_port|.
300 explicit MachPortSender(mach_port_t send_port);
302 kern_return_t SendMessage(MachSendMessage &message,
303 mach_msg_timeout_t timeout);
305 private:
306 mach_port_t send_port_;
307 kern_return_t init_result_;
309 DISALLOW_COPY_AND_ASSIGN(MachPortSender);
312 //==============================================================================
313 // Static utility functions.
315 namespace mac {
317 // Returns the number of Mach ports to which the given task has a right.
318 // Note that unless the calling task has send rights to the passed task port,
319 // this will fail unless the calling task is running as root.
320 kern_return_t BASE_EXPORT GetNumberOfMachPorts(mach_port_t task_port,
321 int* port_count);
323 } // namespace mac
325 } // namespace base
327 #endif // BASE_MACH_IPC_MAC_H_