1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef BASE_MACH_IPC_MAC_H_
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BASE_MACH_IPC_MAC_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <mach/mach.h>
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <mach/message.h>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <servers/bootstrap.h>
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/types.h>
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <CoreServices/CoreServices.h>
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//==============================================================================
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// DISCUSSION:
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The three main classes of interest are
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//  MachMessage:    a wrapper for a Mach message of the following form
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   mach_msg_header_t
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   mach_msg_body_t
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   optional descriptors
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   optional extra message data
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  MachReceiveMessage and MachSendMessage subclass MachMessage
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    and are used instead of MachMessage which is an abstract base class
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  ReceivePort:
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//    Represents a Mach port for which we have receive rights
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  MachPortSender:
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//    Represents a Mach port for which we have send rights
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Here's an example to receive a message on a server port:
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//        // This creates our named server port
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//        ReceivePort receivePort("com.Google.MyService");
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//        MachReceiveMessage message;
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//        kern_return_t result = receivePort.WaitForMessage(&message, 0);
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//        if (result == KERN_SUCCESS && message.GetMessageID() == 57) {
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//          mach_port_t task = message.GetTranslatedPort(0);
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//          mach_port_t thread = message.GetTranslatedPort(1);
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//          char *messageString = message.GetData();
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//          printf("message string = %s\n", messageString);
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//        }
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Here is an example of using these classes to send a message to this port:
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    // send to already named port
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    MachPortSender sender("com.Google.MyService");
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    MachSendMessage message(57);      // our message ID is 57
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    // add some ports to be translated for us
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    message.AddDescriptor(mach_task_self());     // our task
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    message.AddDescriptor(mach_thread_self());   // this thread
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    char messageString[] = "Hello server!\n";
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    message.SetData(messageString, strlen(messageString)+1);
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    // timeout 1000ms
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    kern_return_t result = sender.SendMessage(message, 1000);
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define PRINT_MACH_RESULT(result_, message_) \
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  printf(message_" %s (%d)\n", mach_error_string(result_), result_ );
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//==============================================================================
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A wrapper class for mach_msg_port_descriptor_t (with same memory layout)
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// with convenient constructors and accessors
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MachMsgPortDescriptor : public mach_msg_port_descriptor_t {
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // General-purpose constructor
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachMsgPortDescriptor(mach_port_t in_name,
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        mach_msg_type_name_t in_disposition) {
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name = in_name;
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pad1 = 0;
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pad2 = 0;
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    disposition = in_disposition;
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    type = MACH_MSG_PORT_DESCRIPTOR;
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // For passing send rights to a port
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachMsgPortDescriptor(mach_port_t in_name) {
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name = in_name;
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pad1 = 0;
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pad2 = 0;
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    disposition = MACH_MSG_TYPE_PORT_SEND;
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    type = MACH_MSG_PORT_DESCRIPTOR;
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Copy constructor
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) {
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    name = desc.name;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pad1 = desc.pad1;
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pad2 = desc.pad2;
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    disposition = desc.disposition;
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    type = desc.type;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  mach_port_t GetMachPort() const {
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return name;
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  mach_msg_type_name_t GetDisposition() const {
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return disposition;
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // For convenience
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  operator mach_port_t() const {
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GetMachPort();
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//==============================================================================
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// MachMessage: a wrapper for a Mach message
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  (mach_msg_header_t, mach_msg_body_t, extra data)
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  This considerably simplifies the construction of a message for sending
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  and the getting at relevant data and descriptors for the receiver.
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  This class can be initialized using external storage of an arbitrary size
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  or it can manage storage internally.
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  1. If storage is allocated internally, the combined size of the descriptors
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  plus data must be less than 1024.  But as a benefit no memory allocation is
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  necessary.
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  2. For external storage, a buffer of at least EmptyMessageSize() must be
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  provided.
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  A MachMessage object is used by ReceivePort::WaitForMessage
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  and MachPortSender::SendMessage
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MachMessage {
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const size_t kEmptyMessageSize;
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~MachMessage();
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The receiver of the message can retrieve the raw data this way
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  u_int8_t *GetData() {
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GetDataLength() > 0 ? GetDataPacket()->data : NULL;
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  u_int32_t GetDataLength() {
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return EndianU32_LtoN(GetDataPacket()->data_length);
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The message ID may be used as a code identifying the type of message
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetMessageID(int32_t message_id) {
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    GetDataPacket()->id = EndianU32_NtoL(message_id);
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); }
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Adds a descriptor (typically a Mach port) to be translated
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // returns true if successful, otherwise not enough space
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool AddDescriptor(const MachMsgPortDescriptor &desc);
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int GetDescriptorCount() const {
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return storage_->body.msgh_descriptor_count;
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachMsgPortDescriptor *GetDescriptor(int n);
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Convenience method which gets the Mach port described by the descriptor
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  mach_port_t GetTranslatedPort(int n);
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A simple message is one with no descriptors
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool IsSimpleMessage() const { return GetDescriptorCount() == 0; }
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Sets raw data for the message (returns false if not enough space)
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool SetData(const void* data, int32_t data_length);
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Consider this an abstract base class - must create an actual instance
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of MachReceiveMessage or MachSendMessage
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachMessage();
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Constructor for use with preallocate storage.
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // storage_length must be >= EmptyMessageSize()
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachMessage(void *storage, size_t storage_length);
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  friend class ReceivePort;
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  friend class MachPortSender;
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Represents raw data in our message
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct MessageDataPacket {
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t  id;          // little-endian
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t  data_length; // little-endian
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    u_int8_t data[1];     // actual size limited by storage_length_bytes_
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageDataPacket* GetDataPacket();
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetDescriptorCount(int n);
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetDescriptor(int n, const MachMsgPortDescriptor &desc);
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns total message size setting msgh_size in the header to this value
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int CalculateSize();
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns total storage size that this object can grow to, this is inclusive
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // of the Mach header.
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t MaxSize() const { return storage_length_bytes_; }
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  mach_msg_header_t *Head() { return &(storage_->head); }
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct MachMessageData {
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    mach_msg_header_t  head;
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    mach_msg_body_t    body;
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // descriptors and data may be embedded here.
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    u_int8_t           padding[1024];
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachMessageData *storage_;
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t storage_length_bytes_;
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool own_storage_;  // Is storage owned by this object?
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//==============================================================================
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MachReceiveMessage and MachSendMessage are useful to separate the idea
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// of a Mach message being sent and being received, and adds increased type
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// safety:
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  ReceivePort::WaitForMessage() only accepts a MachReceiveMessage
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  MachPortSender::SendMessage() only accepts a MachSendMessage
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//==============================================================================
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MachReceiveMessage : public MachMessage {
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachReceiveMessage() : MachMessage() {}
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachReceiveMessage(void *storage, size_t storage_length)
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : MachMessage(storage, storage_length) {}
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DISALLOW_COPY_AND_ASSIGN(MachReceiveMessage);
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//==============================================================================
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MachSendMessage : public MachMessage {
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit MachSendMessage(int32_t message_id);
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MachSendMessage(void *storage, size_t storage_length, int32_t message_id);
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Initialize(int32_t message_id);
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(MachSendMessage);
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//==============================================================================
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Represents a Mach port for which we have receive rights
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ReceivePort {
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Creates a new Mach port for receiving messages and registers a name for it
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit ReceivePort(const char *receive_port_name);
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Given an already existing Mach port, use it.  We take ownership of the
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // port and deallocate it in our destructor.
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit ReceivePort(mach_port_t receive_port);
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create a new Mach port for receiving messages
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ReceivePort();
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~ReceivePort();
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Waits on the Mach port until message received or timeout.  If |timeout| is
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // MACH_MSG_TIMEOUT_NONE, this method waits forever.
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  kern_return_t WaitForMessage(MachReceiveMessage *out_message,
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               mach_msg_timeout_t timeout);
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // The underlying Mach port that we wrap
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  mach_port_t  GetPort() const { return port_; }
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  mach_port_t   port_;
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  kern_return_t init_result_;
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(ReceivePort);
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//==============================================================================
2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Represents a Mach port for which we have send rights
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MachPortSender {
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // get a port with send rights corresponding to a named registered service
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit MachPortSender(const char *receive_port_name);
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Given an already existing Mach port, use it. Does not take ownership of
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |send_port|.
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit MachPortSender(mach_port_t send_port);
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  kern_return_t SendMessage(MachSendMessage &message,
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            mach_msg_timeout_t timeout);
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  mach_port_t   send_port_;
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  kern_return_t init_result_;
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(MachPortSender);
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // BASE_MACH_IPC_MAC_H_
314