ipc/chromium/src/chrome/common/mach_ipc_mac.h

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

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

mercurial