1*9712c20fSFrederick Mayle // Copyright 2007 Google LLC 2*9712c20fSFrederick Mayle // 3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without 4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are 5*9712c20fSFrederick Mayle // met: 6*9712c20fSFrederick Mayle // 7*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright 8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer. 9*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above 10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer 11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the 12*9712c20fSFrederick Mayle // distribution. 13*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its 14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from 15*9712c20fSFrederick Mayle // this software without specific prior written permission. 16*9712c20fSFrederick Mayle // 17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*9712c20fSFrederick Mayle // 29*9712c20fSFrederick Mayle // MachIPC.h 30*9712c20fSFrederick Mayle // 31*9712c20fSFrederick Mayle // Some helpful wrappers for using Mach IPC calls 32*9712c20fSFrederick Mayle 33*9712c20fSFrederick Mayle #ifndef MACH_IPC_H__ 34*9712c20fSFrederick Mayle #define MACH_IPC_H__ 35*9712c20fSFrederick Mayle 36*9712c20fSFrederick Mayle #import <mach/mach.h> 37*9712c20fSFrederick Mayle #import <mach/message.h> 38*9712c20fSFrederick Mayle #import <servers/bootstrap.h> 39*9712c20fSFrederick Mayle #import <sys/types.h> 40*9712c20fSFrederick Mayle 41*9712c20fSFrederick Mayle #import <CoreServices/CoreServices.h> 42*9712c20fSFrederick Mayle 43*9712c20fSFrederick Mayle //============================================================================== 44*9712c20fSFrederick Mayle // DISCUSSION: 45*9712c20fSFrederick Mayle // 46*9712c20fSFrederick Mayle // The three main classes of interest are 47*9712c20fSFrederick Mayle // 48*9712c20fSFrederick Mayle // MachMessage: a wrapper for a mach message of the following form 49*9712c20fSFrederick Mayle // mach_msg_header_t 50*9712c20fSFrederick Mayle // mach_msg_body_t 51*9712c20fSFrederick Mayle // optional descriptors 52*9712c20fSFrederick Mayle // optional extra message data 53*9712c20fSFrederick Mayle // 54*9712c20fSFrederick Mayle // MachReceiveMessage and MachSendMessage subclass MachMessage 55*9712c20fSFrederick Mayle // and are used instead of MachMessage which is an abstract base class 56*9712c20fSFrederick Mayle // 57*9712c20fSFrederick Mayle // ReceivePort: 58*9712c20fSFrederick Mayle // Represents a mach port for which we have receive rights 59*9712c20fSFrederick Mayle // 60*9712c20fSFrederick Mayle // MachPortSender: 61*9712c20fSFrederick Mayle // Represents a mach port for which we have send rights 62*9712c20fSFrederick Mayle // 63*9712c20fSFrederick Mayle // Here's an example to receive a message on a server port: 64*9712c20fSFrederick Mayle // 65*9712c20fSFrederick Mayle // // This creates our named server port 66*9712c20fSFrederick Mayle // ReceivePort receivePort("com.Google.MyService"); 67*9712c20fSFrederick Mayle // 68*9712c20fSFrederick Mayle // MachReceiveMessage message; 69*9712c20fSFrederick Mayle // kern_return_t result = receivePort.WaitForMessage(&message, 0); 70*9712c20fSFrederick Mayle // 71*9712c20fSFrederick Mayle // if (result == KERN_SUCCESS && message.GetMessageID() == 57) { 72*9712c20fSFrederick Mayle // mach_port_t task = message.GetTranslatedPort(0); 73*9712c20fSFrederick Mayle // mach_port_t thread = message.GetTranslatedPort(1); 74*9712c20fSFrederick Mayle // 75*9712c20fSFrederick Mayle // char* messageString = message.GetData(); 76*9712c20fSFrederick Mayle // 77*9712c20fSFrederick Mayle // printf("message string = %s\n", messageString); 78*9712c20fSFrederick Mayle // } 79*9712c20fSFrederick Mayle // 80*9712c20fSFrederick Mayle // Here is an example of using these classes to send a message to this port: 81*9712c20fSFrederick Mayle // 82*9712c20fSFrederick Mayle // // send to already named port 83*9712c20fSFrederick Mayle // MachPortSender sender("com.Google.MyService"); 84*9712c20fSFrederick Mayle // MachSendMessage message(57); // our message ID is 57 85*9712c20fSFrederick Mayle // 86*9712c20fSFrederick Mayle // // add some ports to be translated for us 87*9712c20fSFrederick Mayle // message.AddDescriptor(mach_task_self()); // our task 88*9712c20fSFrederick Mayle // message.AddDescriptor(mach_thread_self()); // this thread 89*9712c20fSFrederick Mayle // 90*9712c20fSFrederick Mayle // char messageString[] = "Hello server!\n"; 91*9712c20fSFrederick Mayle // message.SetData(messageString, strlen(messageString)+1); 92*9712c20fSFrederick Mayle // 93*9712c20fSFrederick Mayle // kern_return_t result = sender.SendMessage(message, 1000); // timeout 1000ms 94*9712c20fSFrederick Mayle // 95*9712c20fSFrederick Mayle 96*9712c20fSFrederick Mayle namespace google_breakpad { 97*9712c20fSFrederick Mayle #define PRINT_MACH_RESULT(result_, message_) \ 98*9712c20fSFrederick Mayle printf(message_" %s (%d)\n", mach_error_string(result_), result_ ); 99*9712c20fSFrederick Mayle 100*9712c20fSFrederick Mayle //============================================================================== 101*9712c20fSFrederick Mayle // A wrapper class for mach_msg_port_descriptor_t (with same memory layout) 102*9712c20fSFrederick Mayle // with convenient constructors and accessors 103*9712c20fSFrederick Mayle class MachMsgPortDescriptor : public mach_msg_port_descriptor_t { 104*9712c20fSFrederick Mayle public: 105*9712c20fSFrederick Mayle // General-purpose constructor MachMsgPortDescriptor(mach_port_t in_name,mach_msg_type_name_t in_disposition)106*9712c20fSFrederick Mayle MachMsgPortDescriptor(mach_port_t in_name, 107*9712c20fSFrederick Mayle mach_msg_type_name_t in_disposition) { 108*9712c20fSFrederick Mayle name = in_name; 109*9712c20fSFrederick Mayle pad1 = 0; 110*9712c20fSFrederick Mayle pad2 = 0; 111*9712c20fSFrederick Mayle disposition = in_disposition; 112*9712c20fSFrederick Mayle type = MACH_MSG_PORT_DESCRIPTOR; 113*9712c20fSFrederick Mayle } 114*9712c20fSFrederick Mayle 115*9712c20fSFrederick Mayle // For passing send rights to a port MachMsgPortDescriptor(mach_port_t in_name)116*9712c20fSFrederick Mayle MachMsgPortDescriptor(mach_port_t in_name) { 117*9712c20fSFrederick Mayle name = in_name; 118*9712c20fSFrederick Mayle pad1 = 0; 119*9712c20fSFrederick Mayle pad2 = 0; 120*9712c20fSFrederick Mayle disposition = MACH_MSG_TYPE_COPY_SEND; 121*9712c20fSFrederick Mayle type = MACH_MSG_PORT_DESCRIPTOR; 122*9712c20fSFrederick Mayle } 123*9712c20fSFrederick Mayle 124*9712c20fSFrederick Mayle // Copy constructor MachMsgPortDescriptor(const MachMsgPortDescriptor & desc)125*9712c20fSFrederick Mayle MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) { 126*9712c20fSFrederick Mayle name = desc.name; 127*9712c20fSFrederick Mayle pad1 = desc.pad1; 128*9712c20fSFrederick Mayle pad2 = desc.pad2; 129*9712c20fSFrederick Mayle disposition = desc.disposition; 130*9712c20fSFrederick Mayle type = desc.type; 131*9712c20fSFrederick Mayle } 132*9712c20fSFrederick Mayle GetMachPort()133*9712c20fSFrederick Mayle mach_port_t GetMachPort() const { 134*9712c20fSFrederick Mayle return name; 135*9712c20fSFrederick Mayle } 136*9712c20fSFrederick Mayle GetDisposition()137*9712c20fSFrederick Mayle mach_msg_type_name_t GetDisposition() const { 138*9712c20fSFrederick Mayle return disposition; 139*9712c20fSFrederick Mayle } 140*9712c20fSFrederick Mayle 141*9712c20fSFrederick Mayle // For convenience mach_port_t()142*9712c20fSFrederick Mayle operator mach_port_t() const { 143*9712c20fSFrederick Mayle return GetMachPort(); 144*9712c20fSFrederick Mayle } 145*9712c20fSFrederick Mayle }; 146*9712c20fSFrederick Mayle 147*9712c20fSFrederick Mayle //============================================================================== 148*9712c20fSFrederick Mayle // MachMessage: a wrapper for a mach message 149*9712c20fSFrederick Mayle // (mach_msg_header_t, mach_msg_body_t, extra data) 150*9712c20fSFrederick Mayle // 151*9712c20fSFrederick Mayle // This considerably simplifies the construction of a message for sending 152*9712c20fSFrederick Mayle // and the getting at relevant data and descriptors for the receiver. 153*9712c20fSFrederick Mayle // 154*9712c20fSFrederick Mayle // Currently the combined size of the descriptors plus data must be 155*9712c20fSFrederick Mayle // less than 1024. But as a benefit no memory allocation is necessary. 156*9712c20fSFrederick Mayle // 157*9712c20fSFrederick Mayle // TODO: could consider adding malloc() support for very large messages 158*9712c20fSFrederick Mayle // 159*9712c20fSFrederick Mayle // A MachMessage object is used by ReceivePort::WaitForMessage 160*9712c20fSFrederick Mayle // and MachPortSender::SendMessage 161*9712c20fSFrederick Mayle // 162*9712c20fSFrederick Mayle class MachMessage { 163*9712c20fSFrederick Mayle public: 164*9712c20fSFrederick Mayle 165*9712c20fSFrederick Mayle // The receiver of the message can retrieve the raw data this way GetData()166*9712c20fSFrederick Mayle uint8_t* GetData() { 167*9712c20fSFrederick Mayle return GetDataLength() > 0 ? GetDataPacket()->data : NULL; 168*9712c20fSFrederick Mayle } 169*9712c20fSFrederick Mayle GetDataLength()170*9712c20fSFrederick Mayle uint32_t GetDataLength() { 171*9712c20fSFrederick Mayle return EndianU32_LtoN(GetDataPacket()->data_length); 172*9712c20fSFrederick Mayle } 173*9712c20fSFrederick Mayle 174*9712c20fSFrederick Mayle // The message ID may be used as a code identifying the type of message SetMessageID(int32_t message_id)175*9712c20fSFrederick Mayle void SetMessageID(int32_t message_id) { 176*9712c20fSFrederick Mayle GetDataPacket()->id = EndianU32_NtoL(message_id); 177*9712c20fSFrederick Mayle } 178*9712c20fSFrederick Mayle GetMessageID()179*9712c20fSFrederick Mayle int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); } 180*9712c20fSFrederick Mayle 181*9712c20fSFrederick Mayle // Adds a descriptor (typically a mach port) to be translated 182*9712c20fSFrederick Mayle // returns true if successful, otherwise not enough space 183*9712c20fSFrederick Mayle bool AddDescriptor(const MachMsgPortDescriptor& desc); 184*9712c20fSFrederick Mayle GetDescriptorCount()185*9712c20fSFrederick Mayle int GetDescriptorCount() const { return body.msgh_descriptor_count; } 186*9712c20fSFrederick Mayle MachMsgPortDescriptor* GetDescriptor(int n); 187*9712c20fSFrederick Mayle 188*9712c20fSFrederick Mayle // Convenience method which gets the mach port described by the descriptor 189*9712c20fSFrederick Mayle mach_port_t GetTranslatedPort(int n); 190*9712c20fSFrederick Mayle 191*9712c20fSFrederick Mayle // A simple message is one with no descriptors IsSimpleMessage()192*9712c20fSFrederick Mayle bool IsSimpleMessage() const { return GetDescriptorCount() == 0; } 193*9712c20fSFrederick Mayle 194*9712c20fSFrederick Mayle // Sets raw data for the message (returns false if not enough space) 195*9712c20fSFrederick Mayle bool SetData(void* data, int32_t data_length); 196*9712c20fSFrederick Mayle 197*9712c20fSFrederick Mayle protected: 198*9712c20fSFrederick Mayle // Consider this an abstract base class - must create an actual instance 199*9712c20fSFrederick Mayle // of MachReceiveMessage or MachSendMessage 200*9712c20fSFrederick Mayle MachMessage()201*9712c20fSFrederick Mayle MachMessage() { 202*9712c20fSFrederick Mayle memset(this, 0, sizeof(MachMessage)); 203*9712c20fSFrederick Mayle } 204*9712c20fSFrederick Mayle 205*9712c20fSFrederick Mayle friend class ReceivePort; 206*9712c20fSFrederick Mayle friend class MachPortSender; 207*9712c20fSFrederick Mayle 208*9712c20fSFrederick Mayle // Represents raw data in our message 209*9712c20fSFrederick Mayle struct MessageDataPacket { 210*9712c20fSFrederick Mayle int32_t id; // little-endian 211*9712c20fSFrederick Mayle int32_t data_length; // little-endian 212*9712c20fSFrederick Mayle uint8_t data[1]; // actual size limited by sizeof(MachMessage) 213*9712c20fSFrederick Mayle }; 214*9712c20fSFrederick Mayle 215*9712c20fSFrederick Mayle MessageDataPacket* GetDataPacket(); 216*9712c20fSFrederick Mayle 217*9712c20fSFrederick Mayle void SetDescriptorCount(int n); 218*9712c20fSFrederick Mayle void SetDescriptor(int n, const MachMsgPortDescriptor& desc); 219*9712c20fSFrederick Mayle 220*9712c20fSFrederick Mayle // Returns total message size setting msgh_size in the header to this value 221*9712c20fSFrederick Mayle mach_msg_size_t CalculateSize(); 222*9712c20fSFrederick Mayle 223*9712c20fSFrederick Mayle mach_msg_header_t head; 224*9712c20fSFrederick Mayle mach_msg_body_t body; 225*9712c20fSFrederick Mayle uint8_t padding[1024]; // descriptors and data may be embedded here 226*9712c20fSFrederick Mayle }; 227*9712c20fSFrederick Mayle 228*9712c20fSFrederick Mayle //============================================================================== 229*9712c20fSFrederick Mayle // MachReceiveMessage and MachSendMessage are useful to separate the idea 230*9712c20fSFrederick Mayle // of a mach message being sent and being received, and adds increased type 231*9712c20fSFrederick Mayle // safety: 232*9712c20fSFrederick Mayle // ReceivePort::WaitForMessage() only accepts a MachReceiveMessage 233*9712c20fSFrederick Mayle // MachPortSender::SendMessage() only accepts a MachSendMessage 234*9712c20fSFrederick Mayle 235*9712c20fSFrederick Mayle //============================================================================== 236*9712c20fSFrederick Mayle class MachReceiveMessage : public MachMessage { 237*9712c20fSFrederick Mayle public: MachReceiveMessage()238*9712c20fSFrederick Mayle MachReceiveMessage() : MachMessage() {} 239*9712c20fSFrederick Mayle }; 240*9712c20fSFrederick Mayle 241*9712c20fSFrederick Mayle //============================================================================== 242*9712c20fSFrederick Mayle class MachSendMessage : public MachMessage { 243*9712c20fSFrederick Mayle public: 244*9712c20fSFrederick Mayle MachSendMessage(int32_t message_id); 245*9712c20fSFrederick Mayle }; 246*9712c20fSFrederick Mayle 247*9712c20fSFrederick Mayle //============================================================================== 248*9712c20fSFrederick Mayle // Represents a mach port for which we have receive rights 249*9712c20fSFrederick Mayle class ReceivePort { 250*9712c20fSFrederick Mayle public: 251*9712c20fSFrederick Mayle // Creates a new mach port for receiving messages and registers a name for it 252*9712c20fSFrederick Mayle explicit ReceivePort(const char* receive_port_name); 253*9712c20fSFrederick Mayle 254*9712c20fSFrederick Mayle // Given an already existing mach port, use it. We take ownership of the 255*9712c20fSFrederick Mayle // port and deallocate it in our destructor. 256*9712c20fSFrederick Mayle explicit ReceivePort(mach_port_t receive_port); 257*9712c20fSFrederick Mayle 258*9712c20fSFrederick Mayle // Create a new mach port for receiving messages 259*9712c20fSFrederick Mayle ReceivePort(); 260*9712c20fSFrederick Mayle 261*9712c20fSFrederick Mayle ~ReceivePort(); 262*9712c20fSFrederick Mayle 263*9712c20fSFrederick Mayle // Waits on the mach port until message received or timeout 264*9712c20fSFrederick Mayle kern_return_t WaitForMessage(MachReceiveMessage* out_message, 265*9712c20fSFrederick Mayle mach_msg_timeout_t timeout); 266*9712c20fSFrederick Mayle 267*9712c20fSFrederick Mayle // The underlying mach port that we wrap GetPort()268*9712c20fSFrederick Mayle mach_port_t GetPort() const { return port_; } 269*9712c20fSFrederick Mayle 270*9712c20fSFrederick Mayle private: 271*9712c20fSFrederick Mayle ReceivePort(const ReceivePort&); // disable copy c-tor 272*9712c20fSFrederick Mayle 273*9712c20fSFrederick Mayle mach_port_t port_; 274*9712c20fSFrederick Mayle kern_return_t init_result_; 275*9712c20fSFrederick Mayle }; 276*9712c20fSFrederick Mayle 277*9712c20fSFrederick Mayle //============================================================================== 278*9712c20fSFrederick Mayle // Represents a mach port for which we have send rights 279*9712c20fSFrederick Mayle class MachPortSender { 280*9712c20fSFrederick Mayle public: 281*9712c20fSFrederick Mayle // get a port with send rights corresponding to a named registered service 282*9712c20fSFrederick Mayle explicit MachPortSender(const char* receive_port_name); 283*9712c20fSFrederick Mayle 284*9712c20fSFrederick Mayle 285*9712c20fSFrederick Mayle // Given an already existing mach port, use it. 286*9712c20fSFrederick Mayle explicit MachPortSender(mach_port_t send_port); 287*9712c20fSFrederick Mayle 288*9712c20fSFrederick Mayle kern_return_t SendMessage(MachSendMessage& message, 289*9712c20fSFrederick Mayle mach_msg_timeout_t timeout); 290*9712c20fSFrederick Mayle 291*9712c20fSFrederick Mayle private: 292*9712c20fSFrederick Mayle MachPortSender(const MachPortSender&); // disable copy c-tor 293*9712c20fSFrederick Mayle 294*9712c20fSFrederick Mayle mach_port_t send_port_; 295*9712c20fSFrederick Mayle kern_return_t init_result_; 296*9712c20fSFrederick Mayle }; 297*9712c20fSFrederick Mayle 298*9712c20fSFrederick Mayle } // namespace google_breakpad 299*9712c20fSFrederick Mayle 300*9712c20fSFrederick Mayle #endif // MACH_IPC_H__ 301