~ubuntu-branches/ubuntu/trusty/tomahawk/trusty-proposed

« back to all changes in this revision

Viewing changes to thirdparty/breakpad/common/mac/MachIPC.h

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-03-07 21:50:13 UTC
  • Revision ID: package-import@ubuntu.com-20130307215013-6gdjkdds7i9uenvs
Tags: upstream-0.6.0+dfsg
ImportĀ upstreamĀ versionĀ 0.6.0+dfsg

Show diffs side-by-side

added added

removed removed

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