13ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Copyright (c) 2007, Google Inc.
23ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// All rights reserved.
33ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
43ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Redistribution and use in source and binary forms, with or without
53ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// modification, are permitted provided that the following conditions are
63ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// met:
73ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
83ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Redistributions of source code must retain the above copyright
93ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// notice, this list of conditions and the following disclaimer.
103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Redistributions in binary form must reproduce the above
113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// copyright notice, this list of conditions and the following disclaimer
123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// in the documentation and/or other materials provided with the
133ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// distribution.
143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Neither the name of Google Inc. nor the names of its
153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// contributors may be used to endorse or promote products derived from
163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// this software without specific prior written permission.
173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
223ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  MachIPC.h
313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  Some helpful wrappers for using Mach IPC calls
333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#ifndef MACH_IPC_H__
353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#define MACH_IPC_H__
363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <mach/mach.h>
383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <mach/message.h>
393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <servers/bootstrap.h>
403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <sys/types.h>
413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <CoreServices/CoreServices.h>
433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// DISCUSSION:
463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// The three main classes of interest are
483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  MachMessage:    a wrapper for a mach message of the following form
503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   mach_msg_header_t
513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   mach_msg_body_t
523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   optional descriptors
533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   optional extra message data
543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  MachReceiveMessage and MachSendMessage subclass MachMessage
563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    and are used instead of MachMessage which is an abstract base class
573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  ReceivePort:
593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    Represents a mach port for which we have receive rights
603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  MachPortSender:
623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    Represents a mach port for which we have send rights
633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Here's an example to receive a message on a server port:
653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//        // This creates our named server port
673ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//        ReceivePort receivePort("com.Google.MyService");
683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//        MachReceiveMessage message;
703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//        kern_return_t result = receivePort.WaitForMessage(&message, 0);
713ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//        if (result == KERN_SUCCESS && message.GetMessageID() == 57) {
733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//          mach_port_t task = message.GetTranslatedPort(0);
743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//          mach_port_t thread = message.GetTranslatedPort(1);
753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//          char *messageString = message.GetData();
773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//          printf("message string = %s\n", messageString);
793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//        }
803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Here is an example of using these classes to send a message to this port:
823ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    // send to already named port
843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    MachPortSender sender("com.Google.MyService");
853ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    MachSendMessage message(57);      // our message ID is 57
863ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
873ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    // add some ports to be translated for us
883ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    message.AddDescriptor(mach_task_self());     // our task
893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    message.AddDescriptor(mach_thread_self());   // this thread
903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    char messageString[] = "Hello server!\n";
923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    message.SetData(messageString, strlen(messageString)+1);
933ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    kern_return_t result = sender.SendMessage(message, 1000); // timeout 1000ms
953ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
963ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
97a599ae80aa44f2f6dbe8c5b86d2e503a8c7b6639ted.mielczarek@gmail.comnamespace google_breakpad {
983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#define PRINT_MACH_RESULT(result_, message_) \
993ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  printf(message_" %s (%d)\n", mach_error_string(result_), result_ );
1003ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
1023ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A wrapper class for mach_msg_port_descriptor_t (with same memory layout)
1033ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// with convenient constructors and accessors
1043ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass MachMsgPortDescriptor : public mach_msg_port_descriptor_t {
1053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
1063ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // General-purpose constructor
1073ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MachMsgPortDescriptor(mach_port_t in_name,
1083ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid                        mach_msg_type_name_t in_disposition) {
1093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    name = in_name;
1103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    pad1 = 0;
1113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    pad2 = 0;
1123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    disposition = in_disposition;
1133ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    type = MACH_MSG_PORT_DESCRIPTOR;
1143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // For passing send rights to a port
1173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MachMsgPortDescriptor(mach_port_t in_name) {
1183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    name = in_name;
1193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    pad1 = 0;
1203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    pad2 = 0;
1213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    disposition = MACH_MSG_TYPE_COPY_SEND;
1223ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    type = MACH_MSG_PORT_DESCRIPTOR;
1233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Copy constructor
1263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) {
1273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    name = desc.name;
1283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    pad1 = desc.pad1;
1293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    pad2 = desc.pad2;
1303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    disposition = desc.disposition;
1313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    type = desc.type;
1323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t GetMachPort() const {
1353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    return name;
1363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_msg_type_name_t GetDisposition() const {
1393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    return disposition;
1403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // For convenience
1433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  operator mach_port_t() const {
1443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    return GetMachPort();
1453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
1473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
1493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// MachMessage: a wrapper for a mach message
1503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  (mach_msg_header_t, mach_msg_body_t, extra data)
1513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  This considerably simplifies the construction of a message for sending
1533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  and the getting at relevant data and descriptors for the receiver.
1543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  Currently the combined size of the descriptors plus data must be
1563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  less than 1024.  But as a benefit no memory allocation is necessary.
1573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// TODO: could consider adding malloc() support for very large messages
1593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  A MachMessage object is used by ReceivePort::WaitForMessage
1613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  and MachPortSender::SendMessage
1623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass MachMessage {
1643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
1653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // The receiver of the message can retrieve the raw data this way
1676162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint8_t *GetData() {
1683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    return GetDataLength() > 0 ? GetDataPacket()->data : NULL;
1693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1716162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t GetDataLength() {
1723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    return EndianU32_LtoN(GetDataPacket()->data_length);
1733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // The message ID may be used as a code identifying the type of message
1763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  void SetMessageID(int32_t message_id) {
1773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    GetDataPacket()->id = EndianU32_NtoL(message_id);
1783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); }
1813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1823ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Adds a descriptor (typically a mach port) to be translated
1833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // returns true if successful, otherwise not enough space
1843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  bool AddDescriptor(const MachMsgPortDescriptor &desc);
1853ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1863ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  int GetDescriptorCount() const { return body.msgh_descriptor_count; }
1873ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MachMsgPortDescriptor *GetDescriptor(int n);
1883ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Convenience method which gets the mach port described by the descriptor
1903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t GetTranslatedPort(int n);
1913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // A simple message is one with no descriptors
1933ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  bool IsSimpleMessage() const { return GetDescriptorCount() == 0; }
1943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1953ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Sets raw data for the message (returns false if not enough space)
1963ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  bool SetData(void *data, int32_t data_length);
1973ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid protected:
1993ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Consider this an abstract base class - must create an actual instance
2003ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // of MachReceiveMessage or MachSendMessage
2013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2023ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MachMessage() {
2033ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    memset(this, 0, sizeof(MachMessage));
2043ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
2053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2063ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  friend class ReceivePort;
2073ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  friend class MachPortSender;
2083ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Represents raw data in our message
2103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  struct MessageDataPacket {
2113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    int32_t      id;          // little-endian
2123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    int32_t      data_length; // little-endian
2136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint8_t      data[1];     // actual size limited by sizeof(MachMessage)
2143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  };
2153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MessageDataPacket* GetDataPacket();
2173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  void SetDescriptorCount(int n);
2193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  void SetDescriptor(int n, const MachMsgPortDescriptor &desc);
2203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Returns total message size setting msgh_size in the header to this value
2224ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach  mach_msg_size_t CalculateSize();
2233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_msg_header_t  head;
2253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_msg_body_t    body;
2266162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint8_t            padding[1024]; // descriptors and data may be embedded here
2273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
2283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
2303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// MachReceiveMessage and MachSendMessage are useful to separate the idea
2313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// of a mach message being sent and being received, and adds increased type
2323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// safety:
2333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  ReceivePort::WaitForMessage() only accepts a MachReceiveMessage
2343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  MachPortSender::SendMessage() only accepts a MachSendMessage
2353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
2373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass MachReceiveMessage : public MachMessage {
2383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
2393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MachReceiveMessage() : MachMessage() {};
2403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
2413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
2433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass MachSendMessage : public MachMessage {
2443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
2453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MachSendMessage(int32_t message_id);
2463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
2473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
2493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Represents a mach port for which we have receive rights
2503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass ReceivePort {
2513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
2523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Creates a new mach port for receiving messages and registers a name for it
253315fd78199bc606ee02cb085dacadd58e0fc40c8ted.mielczarek@gmail.com  explicit ReceivePort(const char *receive_port_name);
2543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Given an already existing mach port, use it.  We take ownership of the
2563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // port and deallocate it in our destructor.
257315fd78199bc606ee02cb085dacadd58e0fc40c8ted.mielczarek@gmail.com  explicit ReceivePort(mach_port_t receive_port);
2583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Create a new mach port for receiving messages
2603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  ReceivePort();
2613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  ~ReceivePort();
2633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Waits on the mach port until message received or timeout
2653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kern_return_t WaitForMessage(MachReceiveMessage *out_message,
2663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid                               mach_msg_timeout_t timeout);
2673ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // The underlying mach port that we wrap
2693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t  GetPort() const { return port_; }
2703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2713ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid private:
2723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  ReceivePort(const ReceivePort&);  // disable copy c-tor
2733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t   port_;
2753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kern_return_t init_result_;
2763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
2773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
2793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Represents a mach port for which we have send rights
2803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass MachPortSender {
2813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
2823ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // get a port with send rights corresponding to a named registered service
283315fd78199bc606ee02cb085dacadd58e0fc40c8ted.mielczarek@gmail.com  explicit MachPortSender(const char *receive_port_name);
2843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2853ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2863ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Given an already existing mach port, use it.
287315fd78199bc606ee02cb085dacadd58e0fc40c8ted.mielczarek@gmail.com  explicit MachPortSender(mach_port_t send_port);
2883ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kern_return_t SendMessage(MachSendMessage &message,
2903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid                            mach_msg_timeout_t timeout);
2913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid private:
2933ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  MachPortSender(const MachPortSender&);  // disable copy c-tor
2943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2953ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t   send_port_;
2963ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kern_return_t init_result_;
2973ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
2983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
299a599ae80aa44f2f6dbe8c5b86d2e503a8c7b6639ted.mielczarek@gmail.com}  // namespace google_breakpad
300a599ae80aa44f2f6dbe8c5b86d2e503a8c7b6639ted.mielczarek@gmail.com
3013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#endif // MACH_IPC_H__
302