~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.h

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
4
 * The contents of this file are subject to the Mozilla Public License Version
 
5
 * 1.1 (the "License"); you may not use this file except in compliance with
 
6
 * the License. You may obtain a copy of the License at
 
7
 * http://www.mozilla.org/MPL/
 
8
 *
 
9
 * Software distributed under the License is distributed on an "AS IS" basis,
 
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
11
 * for the specific language governing rights and limitations under the
 
12
 * License.
 
13
 *
 
14
 * The Original Code is Mozilla IPC.
 
15
 *
 
16
 * The Initial Developer of the Original Code is
 
17
 * Netscape Communications Corporation.
 
18
 * Portions created by the Initial Developer are Copyright (C) 2002
 
19
 * the Initial Developer. All Rights Reserved.
 
20
 *
 
21
 * Contributor(s):
 
22
 *   Darin Fisher <darin@netscape.com>
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the MPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the MPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
#ifndef ipcm_h__
 
39
#define ipcm_h__
 
40
 
 
41
#include "ipcMessage.h"
 
42
#include "ipcMessagePrimitives.h"
 
43
 
 
44
//-----------------------------------------------------------------------------
 
45
 
 
46
//
 
47
// IPCM (IPC Manager) protocol support
 
48
//
 
49
 
 
50
// The IPCM message target identifier:
 
51
extern const nsID IPCM_TARGET;
 
52
 
 
53
//
 
54
// Every IPCM message has the following structure:
 
55
//
 
56
//  +-----------------------------------------+
 
57
//  | (ipc message header)                    |
 
58
//  +-----------------------------------------+
 
59
//  | DWORD : type                            |
 
60
//  +-----------------------------------------+
 
61
//  | DWORD : requestIndex                    |
 
62
//  +-----------------------------------------+
 
63
//  .                                         .
 
64
//  . (payload)                               .
 
65
//  .                                         .
 
66
//  +-----------------------------------------+
 
67
//
 
68
// where |type| is an integer uniquely identifying the message.  the type is
 
69
// composed of a message class identifier and a message number.  there are 3
 
70
// message classes:
 
71
//
 
72
//   ACK - acknowledging a request
 
73
//   REQ - making a request
 
74
//   PSH - providing unrequested, "pushed" information
 
75
//
 
76
// The requestIndex field is initialized when a request is made.  An
 
77
// acknowledgement's requestIndex is equal to that of its corresponding
 
78
// request message.  This enables the requesting side of the message exchange
 
79
// to match acknowledgements to requests.  The requestIndex field is ignored
 
80
// for PSH messages.
 
81
//
 
82
 
 
83
// The IPCM message class is stored in the most significant byte.
 
84
#define IPCM_MSG_CLASS_REQ (1 << 24)
 
85
#define IPCM_MSG_CLASS_ACK (2 << 24)
 
86
#define IPCM_MSG_CLASS_PSH (4 << 24)
 
87
 
 
88
// Requests
 
89
#define IPCM_MSG_REQ_PING                   (IPCM_MSG_CLASS_REQ | 1)
 
90
#define IPCM_MSG_REQ_FORWARD                (IPCM_MSG_CLASS_REQ | 2)
 
91
#define IPCM_MSG_REQ_CLIENT_HELLO           (IPCM_MSG_CLASS_REQ | 3)
 
92
#define IPCM_MSG_REQ_CLIENT_ADD_NAME        (IPCM_MSG_CLASS_REQ | 4)
 
93
#define IPCM_MSG_REQ_CLIENT_DEL_NAME        (IPCM_MSG_CLASS_REQ | 5)
 
94
#define IPCM_MSG_REQ_CLIENT_ADD_TARGET      (IPCM_MSG_CLASS_REQ | 6)
 
95
#define IPCM_MSG_REQ_CLIENT_DEL_TARGET      (IPCM_MSG_CLASS_REQ | 7)
 
96
#define IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME   (IPCM_MSG_CLASS_REQ | 8)
 
97
#define IPCM_MSG_REQ_QUERY_CLIENT_NAMES     (IPCM_MSG_CLASS_REQ | 9)  // TODO
 
98
#define IPCM_MSG_REQ_QUERY_CLIENT_TARGETS   (IPCM_MSG_CLASS_REQ | 10) // TODO
 
99
 
 
100
// Acknowledgements
 
101
#define IPCM_MSG_ACK_RESULT                 (IPCM_MSG_CLASS_ACK | 1)
 
102
#define IPCM_MSG_ACK_CLIENT_ID              (IPCM_MSG_CLASS_ACK | 2)
 
103
#define IPCM_MSG_ACK_CLIENT_NAMES           (IPCM_MSG_CLASS_ACK | 3)  // TODO
 
104
#define IPCM_MSG_ACK_CLIENT_TARGETS         (IPCM_MSG_CLASS_ACK | 4)  // TODO
 
105
 
 
106
// Push messages
 
107
#define IPCM_MSG_PSH_CLIENT_STATE           (IPCM_MSG_CLASS_PSH | 1)
 
108
#define IPCM_MSG_PSH_FORWARD                (IPCM_MSG_CLASS_PSH | 2)
 
109
 
 
110
//-----------------------------------------------------------------------------
 
111
 
 
112
//
 
113
// IPCM header
 
114
//
 
115
struct ipcmMessageHeader
 
116
{
 
117
    PRUint32 mType;
 
118
    PRUint32 mRequestIndex;
 
119
};
 
120
 
 
121
//
 
122
// returns IPCM message type.
 
123
//
 
124
static inline int
 
125
IPCM_GetType(const ipcMessage *msg)
 
126
{
 
127
    return ((const ipcmMessageHeader *) msg->Data())->mType;
 
128
}
 
129
 
 
130
//
 
131
// return IPCM message request index.  
 
132
//
 
133
static inline PRUint32
 
134
IPCM_GetRequestIndex(const ipcMessage *msg)
 
135
{
 
136
    return ((const ipcmMessageHeader *) msg->Data())->mRequestIndex;
 
137
}
 
138
 
 
139
//
 
140
// return a request index that is unique to this process.
 
141
//
 
142
NS_HIDDEN_(PRUint32)
 
143
IPCM_NewRequestIndex();
 
144
 
 
145
//-----------------------------------------------------------------------------
 
146
 
 
147
//
 
148
// The IPCM protocol is detailed below:
 
149
//
 
150
 
 
151
// REQUESTS
 
152
 
 
153
//
 
154
// req: IPCM_MSG_REQ_PING
 
155
// ack: IPCM_MSG_ACK_RESULT
 
156
//
 
157
// A PING can be sent from either a client to the daemon, or from the daemon
 
158
// to a client.  The expected acknowledgement is a RESULT message with a status
 
159
// code of 0.
 
160
//
 
161
// This request message has no payload.
 
162
//
 
163
 
 
164
//
 
165
// req: IPCM_MSG_REQ_FORWARD
 
166
// ack: IPCM_MSG_ACK_RESULT
 
167
//
 
168
// A FORWARD is sent when a client wishes to send a message to another client.
 
169
// The payload of this message is another message that should be forwarded by
 
170
// the daemon's IPCM to the specified client.  The expected acknowledgment is
 
171
// a RESULT message with a status code indicating success or failure.
 
172
//
 
173
// When the daemon receives a FORWARD message, it creates a PSH_FORWARD message
 
174
// and sends that on to the destination client.
 
175
//
 
176
// This request message has as its payload:
 
177
//
 
178
//  +-----------------------------------------+
 
179
//  | DWORD : clientID                        |
 
180
//  +-----------------------------------------+
 
181
//  | (innerMsgHeader)                        |
 
182
//  +-----------------------------------------+
 
183
//  | (innerMsgData)                          |
 
184
//  +-----------------------------------------+
 
185
//
 
186
 
 
187
//
 
188
// req: IPCM_MSG_REQ_CLIENT_HELLO
 
189
// ack: IPCM_MSG_REQ_CLIENT_ID <or> IPCM_MSG_REQ_RESULT
 
190
//
 
191
// A CLIENT_HELLO is sent when a client connects to the IPC daemon.  The
 
192
// expected acknowledgement is a CLIENT_ID message informing the new client of
 
193
// its ClientID.  If for some reason the IPC daemon cannot accept the new
 
194
// client, it returns a RESULT message with a failure status code.
 
195
//
 
196
// This request message has no payload.
 
197
//
 
198
 
 
199
//
 
200
// req: IPCM_MSG_REQ_CLIENT_ADD_NAME
 
201
// ack: IPCM_MSG_ACK_RESULT
 
202
//
 
203
// A CLIENT_ADD_NAME is sent when a client wishes to register an additional
 
204
// name for itself.  The expected acknowledgement is a RESULT message with a
 
205
// status code indicating success or failure.
 
206
//
 
207
// This request message has as its payload a null-terminated ASCII character
 
208
// string indicating the name of the client.
 
209
//
 
210
 
 
211
//
 
212
// req: IPCM_MSG_REQ_CLIENT_DEL_NAME
 
213
// ack: IPCM_MSG_ACK_RESULT
 
214
//
 
215
// A CLIENT_DEL_NAME is sent when a client wishes to unregister a name that it
 
216
// has registered.  The expected acknowledgement is a RESULT message with a
 
217
// status code indicating success or failure.
 
218
//
 
219
// This request message has as its payload a null-terminated ASCII character
 
220
// string indicating the name of the client.
 
221
//
 
222
 
 
223
//
 
224
// req: IPCM_MSG_REQ_CLIENT_ADD_TARGET
 
225
// ack: IPCM_MSG_ACK_RESULT
 
226
//
 
227
// A CLIENT_ADD_TARGET is sent when a client wishes to register an additional
 
228
// target that it supports.  The expected acknowledgement is a RESULT message
 
229
// with a status code indicating success or failure.
 
230
//
 
231
// This request message has as its payload a 128-bit UUID indicating the
 
232
// target to add.
 
233
//
 
234
 
 
235
//
 
236
// req: IPCM_MSG_REQ_CLIENT_DEL_TARGET
 
237
// ack: IPCM_MSG_ACK_RESULT
 
238
//
 
239
// A CLIENT_DEL_TARGET is sent when a client wishes to unregister a target
 
240
// that it has registered.  The expected acknowledgement is a RESULT message
 
241
// with a status code indicating success or failure.
 
242
//
 
243
// This request message has as its payload a 128-bit UUID indicating the
 
244
// target to remove.
 
245
//
 
246
 
 
247
//
 
248
// req: IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME
 
249
// ack: IPCM_MSG_ACK_CLIENT_ID <or> IPCM_MSG_ACK_RESULT
 
250
//
 
251
// A QUERY_CLIENT_BY_NAME may be sent by a client to discover the client that
 
252
// is known by a common name.  If more than one client matches the name, then
 
253
// only the ID of the more recently registered client is returned.  The
 
254
// expected acknowledgement is a CLIENT_ID message carrying the ID of the
 
255
// corresponding client.  If no client matches the given name or if some error
 
256
// occurs, then a RESULT message with a failure status code is returned.
 
257
//
 
258
// This request message has as its payload a null-terminated ASCII character
 
259
// string indicating the client name to query.
 
260
// 
 
261
 
 
262
// ACKNOWLEDGEMENTS
 
263
 
 
264
//
 
265
// ack: IPCM_MSG_ACK_RESULT
 
266
//
 
267
// This acknowledgement is returned to indicate a success or failure status.
 
268
//
 
269
// The payload consists of a single DWORD value.
 
270
//
 
271
// Possible status codes are listed below (negative values indicate failure
 
272
// codes):
 
273
//
 
274
#define IPCM_OK               0  // success: generic
 
275
#define IPCM_ERROR_GENERIC   -1  // failure: generic
 
276
#define IPCM_ERROR_NO_CLIENT -2  // failure: client does not exist
 
277
 
 
278
//
 
279
// ack: IPCM_MSG_ACK_CLIENT_ID
 
280
//
 
281
// This acknowledgement is returned to specify a client ID.
 
282
//
 
283
// The payload consists of a single DWORD value.
 
284
//
 
285
 
 
286
// PUSH MESSAGES
 
287
 
 
288
//
 
289
// psh: ICPM_MSG_PSH_CLIENT_STATE
 
290
//
 
291
// This message is sent to clients to indicate the status of other clients.
 
292
//
 
293
// The payload consists of:
 
294
//
 
295
//  +-----------------------------------------+
 
296
//  | DWORD : clientID                        |
 
297
//  +-----------------------------------------+
 
298
//  | DWORD : clientState                     |
 
299
//  +-----------------------------------------+
 
300
//
 
301
// where, clientState is one of the following values indicating whether the
 
302
// client has recently connected (up) or disconnected (down):
 
303
//
 
304
#define IPCM_CLIENT_STATE_UP     1
 
305
#define IPCM_CLIENT_STATE_DOWN   2
 
306
 
 
307
//
 
308
// psh: IPCM_MSG_PSH_FORWARD
 
309
//
 
310
// This message is sent by the daemon to a client on behalf of another client.
 
311
// The recipient is expected to unpack the contained message and process it.
 
312
// 
 
313
// The payload of this message matches the payload of IPCM_MSG_REQ_FORWARD,
 
314
// with the exception that the clientID field is set to the clientID of the
 
315
// sender of the IPCM_MSG_REQ_FORWARD message.
 
316
//
 
317
 
 
318
//-----------------------------------------------------------------------------
 
319
 
 
320
//
 
321
// NOTE: This file declares some helper classes that simplify constructing
 
322
//       and parsing IPCM messages.  Each class subclasses ipcMessage, but
 
323
//       adds no additional member variables.  |operator new| should be used
 
324
//       to allocate one of the IPCM helper classes, e.g.:
 
325
//         
 
326
//          ipcMessage *msg = new ipcmMessageClientHello("foo");
 
327
//
 
328
//       Given an arbitrary ipcMessage, it can be parsed using logic similar
 
329
//       to the following:
 
330
//
 
331
//          void func(const ipcMessage *unknown)
 
332
//          {
 
333
//            if (unknown->Topic().Equals(IPCM_TARGET)) {
 
334
//              if (IPCM_GetMsgType(unknown) == IPCM_MSG_TYPE_CLIENT_ID) {
 
335
//                ipcMessageCast<ipcmMessageClientID> msg(unknown);
 
336
//                printf("Client ID: %u\n", msg->ClientID());
 
337
//              }
 
338
//            }
 
339
//          }
 
340
//
 
341
 
 
342
// REQUESTS
 
343
 
 
344
class ipcmMessagePing : public ipcMessage_DWORD_DWORD
 
345
{
 
346
public:
 
347
    ipcmMessagePing()
 
348
        : ipcMessage_DWORD_DWORD(
 
349
            IPCM_TARGET,
 
350
            IPCM_MSG_REQ_PING,
 
351
            IPCM_NewRequestIndex()) {}
 
352
};
 
353
 
 
354
class ipcmMessageForward : public ipcMessage
 
355
{
 
356
public:
 
357
    // @param type        the type of this message: IPCM_MSG_{REQ,PSH}_FORWARD
 
358
    // @param clientID    the client id of the sender or receiver
 
359
    // @param target      the message target
 
360
    // @param data        the message data
 
361
    // @param dataLen     the message data length
 
362
    ipcmMessageForward(PRUint32 type,
 
363
                       PRUint32 clientID,
 
364
                       const nsID &target,
 
365
                       const char *data,
 
366
                       PRUint32 dataLen) NS_HIDDEN;
 
367
 
 
368
    // set inner message data, constrained to the data length passed
 
369
    // to this class's constructor.
 
370
    NS_HIDDEN_(void) SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen);
 
371
 
 
372
    NS_HIDDEN_(PRUint32)     ClientID() const;
 
373
    NS_HIDDEN_(const nsID &) InnerTarget() const;
 
374
    NS_HIDDEN_(const char *) InnerData() const;
 
375
    NS_HIDDEN_(PRUint32)     InnerDataLen() const;
 
376
};
 
377
 
 
378
class ipcmMessageClientHello : public ipcMessage_DWORD_DWORD
 
379
{
 
380
public:
 
381
    ipcmMessageClientHello()
 
382
        : ipcMessage_DWORD_DWORD(
 
383
            IPCM_TARGET,
 
384
            IPCM_MSG_REQ_CLIENT_HELLO,
 
385
            IPCM_NewRequestIndex()) {}
 
386
};
 
387
 
 
388
class ipcmMessageClientAddName : public ipcMessage_DWORD_DWORD_STR
 
389
{
 
390
public:
 
391
    ipcmMessageClientAddName(const char *name)
 
392
        : ipcMessage_DWORD_DWORD_STR(
 
393
            IPCM_TARGET,
 
394
            IPCM_MSG_REQ_CLIENT_ADD_NAME,
 
395
            IPCM_NewRequestIndex(),
 
396
            name) {}
 
397
 
 
398
    const char *Name() const { return Third(); }
 
399
};
 
400
 
 
401
class ipcmMessageClientDelName : public ipcMessage_DWORD_DWORD_STR
 
402
{
 
403
public:
 
404
    ipcmMessageClientDelName(const char *name)
 
405
        : ipcMessage_DWORD_DWORD_STR(
 
406
            IPCM_TARGET,
 
407
            IPCM_MSG_REQ_CLIENT_DEL_NAME,
 
408
            IPCM_NewRequestIndex(),
 
409
            name) {}
 
410
 
 
411
    const char *Name() const { return Third(); }
 
412
};
 
413
 
 
414
class ipcmMessageClientAddTarget : public ipcMessage_DWORD_DWORD_ID
 
415
{
 
416
public:
 
417
    ipcmMessageClientAddTarget(const nsID &target)
 
418
        : ipcMessage_DWORD_DWORD_ID(
 
419
            IPCM_TARGET,
 
420
            IPCM_MSG_REQ_CLIENT_ADD_TARGET,
 
421
            IPCM_NewRequestIndex(),
 
422
            target) {}
 
423
 
 
424
    const nsID &Target() const { return Third(); }
 
425
};
 
426
 
 
427
class ipcmMessageClientDelTarget : public ipcMessage_DWORD_DWORD_ID
 
428
{
 
429
public:
 
430
    ipcmMessageClientDelTarget(const nsID &target)
 
431
        : ipcMessage_DWORD_DWORD_ID(
 
432
            IPCM_TARGET,
 
433
            IPCM_MSG_REQ_CLIENT_ADD_TARGET,
 
434
            IPCM_NewRequestIndex(),
 
435
            target) {}
 
436
 
 
437
    const nsID &Target() const { return Third(); }
 
438
};
 
439
 
 
440
class ipcmMessageQueryClientByName : public ipcMessage_DWORD_DWORD_STR
 
441
{
 
442
public:
 
443
    ipcmMessageQueryClientByName(const char *name)
 
444
        : ipcMessage_DWORD_DWORD_STR(
 
445
            IPCM_TARGET,
 
446
            IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME,
 
447
            IPCM_NewRequestIndex(),
 
448
            name) {}
 
449
 
 
450
    const char *Name() const { return Third(); }
 
451
    PRUint32 RequestIndex() const { return Second(); }
 
452
};
 
453
 
 
454
// ACKNOWLEDGEMENTS
 
455
 
 
456
class ipcmMessageResult : public ipcMessage_DWORD_DWORD_DWORD
 
457
{
 
458
public:
 
459
    ipcmMessageResult(PRUint32 requestIndex, PRInt32 status)
 
460
        : ipcMessage_DWORD_DWORD_DWORD(
 
461
            IPCM_TARGET,
 
462
            IPCM_MSG_ACK_RESULT,
 
463
            requestIndex,
 
464
            (PRUint32) status) {}
 
465
 
 
466
    PRInt32 Status() const { return (PRInt32) Third(); }
 
467
};
 
468
 
 
469
class ipcmMessageClientID : public ipcMessage_DWORD_DWORD_DWORD
 
470
{
 
471
public:
 
472
    ipcmMessageClientID(PRUint32 requestIndex, PRUint32 clientID)
 
473
        : ipcMessage_DWORD_DWORD_DWORD(
 
474
            IPCM_TARGET,
 
475
            IPCM_MSG_ACK_CLIENT_ID,
 
476
            requestIndex,
 
477
            clientID) {}
 
478
 
 
479
    PRUint32 ClientID() const { return Third(); }
 
480
};
 
481
 
 
482
// PUSH MESSAGES
 
483
 
 
484
class ipcmMessageClientState : public ipcMessage_DWORD_DWORD_DWORD_DWORD
 
485
{
 
486
public:
 
487
    ipcmMessageClientState(PRUint32 clientID, PRUint32 clientStatus)
 
488
        : ipcMessage_DWORD_DWORD_DWORD_DWORD(
 
489
            IPCM_TARGET,
 
490
            IPCM_MSG_PSH_CLIENT_STATE,
 
491
            0,
 
492
            clientID,
 
493
            clientStatus) {}
 
494
 
 
495
    PRUint32 ClientID() const { return Third(); }
 
496
    PRUint32 ClientState() const { return Fourth(); }
 
497
};
 
498
 
 
499
#endif // !ipcm_h__