VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.h

Last change on this file was 103472, checked in by vboxsync, 3 months ago

libs/xpcom: Rewrite the IPC client side to reduce the number of memory allocations, bugref:10598

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.0 KB
Line 
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 <iprt/assertcompile.h>
42
43#include "ipcMessageNew.h"
44
45//-----------------------------------------------------------------------------
46
47//
48// IPCM (IPC Manager) protocol support
49//
50
51// The IPCM message target identifier:
52extern const nsID IPCM_TARGET;
53
54//
55// Every IPCM message has the following structure:
56//
57// +-----------------------------------------+
58// | (ipc message header) |
59// +-----------------------------------------+
60// | DWORD : type |
61// +-----------------------------------------+
62// | DWORD : requestIndex |
63// +-----------------------------------------+
64// . .
65// . (payload) .
66// . .
67// +-----------------------------------------+
68//
69// where |type| is an integer uniquely identifying the message. the type is
70// composed of a message class identifier and a message number. there are 3
71// message classes:
72//
73// ACK - acknowledging a request
74// REQ - making a request
75// PSH - providing unrequested, "pushed" information
76//
77// The requestIndex field is initialized when a request is made. An
78// acknowledgement's requestIndex is equal to that of its corresponding
79// request message. This enables the requesting side of the message exchange
80// to match acknowledgements to requests. The requestIndex field is ignored
81// for PSH messages.
82//
83
84// The IPCM message class is stored in the most significant byte.
85#define IPCM_MSG_CLASS_REQ (1 << 24)
86#define IPCM_MSG_CLASS_ACK (2 << 24)
87#define IPCM_MSG_CLASS_PSH (4 << 24)
88
89// Requests
90#define IPCM_MSG_REQ_PING (IPCM_MSG_CLASS_REQ | 1)
91#define IPCM_MSG_REQ_FORWARD (IPCM_MSG_CLASS_REQ | 2)
92#define IPCM_MSG_REQ_CLIENT_HELLO (IPCM_MSG_CLASS_REQ | 3)
93#define IPCM_MSG_REQ_CLIENT_ADD_NAME (IPCM_MSG_CLASS_REQ | 4)
94#define IPCM_MSG_REQ_CLIENT_DEL_NAME (IPCM_MSG_CLASS_REQ | 5)
95#define IPCM_MSG_REQ_CLIENT_ADD_TARGET (IPCM_MSG_CLASS_REQ | 6)
96#define IPCM_MSG_REQ_CLIENT_DEL_TARGET (IPCM_MSG_CLASS_REQ | 7)
97#define IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME (IPCM_MSG_CLASS_REQ | 8)
98#define IPCM_MSG_REQ_QUERY_CLIENT_NAMES (IPCM_MSG_CLASS_REQ | 9) // TODO
99#define IPCM_MSG_REQ_QUERY_CLIENT_TARGETS (IPCM_MSG_CLASS_REQ | 10) // TODO
100
101// Acknowledgements
102#define IPCM_MSG_ACK_RESULT (IPCM_MSG_CLASS_ACK | 1)
103#define IPCM_MSG_ACK_CLIENT_ID (IPCM_MSG_CLASS_ACK | 2)
104#define IPCM_MSG_ACK_CLIENT_NAMES (IPCM_MSG_CLASS_ACK | 3) // TODO
105#define IPCM_MSG_ACK_CLIENT_TARGETS (IPCM_MSG_CLASS_ACK | 4) // TODO
106
107// Push messages
108#define IPCM_MSG_PSH_CLIENT_STATE (IPCM_MSG_CLASS_PSH | 1)
109#define IPCM_MSG_PSH_FORWARD (IPCM_MSG_CLASS_PSH | 2)
110
111//-----------------------------------------------------------------------------
112
113//
114// IPCM header
115//
116typedef struct IPCMMSGHDR
117{
118 uint32_t u32Type;
119 uint32_t u32RequestIndex;
120} IPCMMSGHDR;
121AssertCompileSize(struct IPCMMSGHDR, 8);
122/** Pointer to an IPCM header. */
123typedef IPCMMSGHDR *PIPCMMSGHDR;
124/** Pointer to a const IPCM header. */
125typedef const IPCMMSGHDR *PCIPCMMSGHDR;
126
127
128DECLINLINE(uint32_t) IPCM_GetType(PCIPCMSG pMsg)
129{
130 return ((PCIPCMMSGHDR)IPCMsgGetPayload(pMsg))->u32Type;
131}
132
133
134DECLINLINE(uint32_t) IPCM_GetRequestIndex(PCIPCMSG pMsg)
135{
136 return ((PCIPCMMSGHDR)IPCMsgGetPayload(pMsg))->u32RequestIndex;
137}
138
139
140//
141// return a request index that is unique to this process.
142//
143DECLHIDDEN(uint32_t) 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#define IPCM_ERROR_INVALID_ARG -3 // failure: invalid request argument
278#define IPCM_ERROR_NO_SUCH_DATA -4 // failure: requested data does not exist
279#define IPCM_ERROR_ALREADY_EXISTS -5 // failure: data to set already exists
280
281//
282// ack: IPCM_MSG_ACK_CLIENT_ID
283//
284// This acknowledgement is returned to specify a client ID.
285//
286// The payload consists of a single DWORD value.
287//
288
289// PUSH MESSAGES
290
291//
292// psh: ICPM_MSG_PSH_CLIENT_STATE
293//
294// This message is sent to clients to indicate the status of other clients.
295//
296// The payload consists of:
297//
298// +-----------------------------------------+
299// | DWORD : clientID |
300// +-----------------------------------------+
301// | DWORD : clientState |
302// +-----------------------------------------+
303//
304// where, clientState is one of the following values indicating whether the
305// client has recently connected (up) or disconnected (down):
306//
307#define IPCM_CLIENT_STATE_UP 1
308#define IPCM_CLIENT_STATE_DOWN 2
309
310//
311// psh: IPCM_MSG_PSH_FORWARD
312//
313// This message is sent by the daemon to a client on behalf of another client.
314// The recipient is expected to unpack the contained message and process it.
315//
316// The payload of this message matches the payload of IPCM_MSG_REQ_FORWARD,
317// with the exception that the clientID field is set to the clientID of the
318// sender of the IPCM_MSG_REQ_FORWARD message.
319//
320
321// REQUESTS
322
323/** The ping message consists of just the header. */
324typedef IPCMMSGHDR IPCMMSGPING;
325typedef IPCMMSGPING *PIPCMMSGPING;
326
327DECLINLINE(void) IPCMMsgPingInit(PIPCMMSGPING pThis)
328{
329 pThis->u32Type = IPCM_MSG_REQ_PING;
330 pThis->u32RequestIndex = IPCM_NewRequestIndex();
331}
332
333
334/** The client hello message consists of just the header. */
335typedef IPCMMSGHDR IPCMMSGCLIENTHELLO;
336typedef IPCMMSGCLIENTHELLO *PIPCMMSGCLIENTHELLO;
337
338DECLINLINE(void) IPCMMsgClientHelloInit(PIPCMMSGCLIENTHELLO pThis)
339{
340 pThis->u32Type = IPCM_MSG_REQ_CLIENT_HELLO;
341 pThis->u32RequestIndex = IPCM_NewRequestIndex();
342}
343
344
345typedef struct IPCMMSGFORWARD
346{
347 IPCMMSGHDR Hdr;
348 uint32_t u32ClientId;
349} IPCMMSGFORWARD;
350AssertCompileSize(IPCMMSGFORWARD, 3 * sizeof(uint32_t));
351typedef IPCMMSGFORWARD *PIPCMMSGFORWARD;
352typedef const IPCMMSGFORWARD *PCIPCMMSGFORWARD;
353
354
355DECLINLINE(int) ipcmMsgInitHdrStr(PIPCMSG pMsg, uint32_t u32Type, const char *psz)
356{
357 size_t cbStr = strlen(psz) + 1; /* Includes terminator. */
358 const IPCMMSGHDR Hdr = { u32Type, IPCM_NewRequestIndex() };
359 RTSGSEG aSegs[2];
360
361 aSegs[0].pvSeg = (void *)&Hdr;
362 aSegs[0].cbSeg = sizeof(Hdr);
363
364 aSegs[1].pvSeg = (void *)psz;
365 aSegs[1].cbSeg = cbStr;
366 return IPCMsgInitSg(pMsg, IPCM_TARGET, cbStr + sizeof(Hdr), &aSegs[0], RT_ELEMENTS(aSegs));
367}
368
369
370DECLINLINE(int) IPCMMsgClientAddNameInit(PIPCMSG pMsg, const char *pszName)
371{
372 return ipcmMsgInitHdrStr(pMsg, IPCM_MSG_REQ_CLIENT_ADD_NAME, pszName);
373}
374
375
376DECLINLINE(int) IPCMMsgClientDelNameInit(PIPCMSG pMsg, const char *pszName)
377{
378 return ipcmMsgInitHdrStr(pMsg, IPCM_MSG_REQ_CLIENT_DEL_NAME, pszName);
379}
380
381
382typedef struct IPCMMSGCLIENTADDDELTARGET
383{
384 IPCMMSGHDR Hdr;
385 nsID idTarget;
386} IPCMMSGCLIENTADDDELTARGET;
387AssertCompileSize(IPCMMSGCLIENTADDDELTARGET, 2 * sizeof(uint32_t) + sizeof(nsID));
388typedef IPCMMSGCLIENTADDDELTARGET *PIPCMMSGCLIENTADDDELTARGET;
389typedef const IPCMMSGCLIENTADDDELTARGET *PCIPCMMSGCLIENTADDDELTARGET;
390
391DECLINLINE(void) IPCMMsgAddTargetInit(PIPCMMSGCLIENTADDDELTARGET pThis, const nsID &target)
392{
393 pThis->Hdr.u32Type = IPCM_MSG_REQ_CLIENT_ADD_TARGET;
394 pThis->Hdr.u32RequestIndex = IPCM_NewRequestIndex();
395 pThis->idTarget = target;
396}
397
398
399DECLINLINE(void) IPCMMsgDelTargetInit(PIPCMMSGCLIENTADDDELTARGET pThis, const nsID &target)
400{
401 pThis->Hdr.u32Type = IPCM_MSG_REQ_CLIENT_DEL_TARGET;
402 pThis->Hdr.u32RequestIndex = IPCM_NewRequestIndex();
403 pThis->idTarget = target;
404}
405
406
407DECLINLINE(int) IPCMMsgQueryClientByNameInit(PIPCMSG pMsg, const char *pszName)
408{
409 return ipcmMsgInitHdrStr(pMsg, IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME, pszName);
410}
411
412
413// ACKNOWLEDGEMENTS
414
415typedef struct IPCMMSGRESULT
416{
417 IPCMMSGHDR Hdr;
418 int32_t i32Status;
419} IPCMMSGRESULT;
420AssertCompileSize(IPCMMSGRESULT, 3 * sizeof(uint32_t));
421typedef IPCMMSGRESULT *PIPCMMSGRESULT;
422typedef const IPCMMSGRESULT *PCIPCMMSGRESULT;
423
424typedef struct IPCMMSGCLIENTID
425{
426 IPCMMSGHDR Hdr;
427 uint32_t u32ClientId;
428} IPCMMSGCLIENTID;
429AssertCompileSize(IPCMMSGCLIENTID, 3 * sizeof(uint32_t));
430typedef IPCMMSGCLIENTID *PIPCMMSGCLIENTID;
431typedef const IPCMMSGCLIENTID *PCIPCMMSGCLIENTID;
432
433
434// PUSH MESSAGES
435
436typedef struct IPCMMSGCLIENTSTATE
437{
438 IPCMMSGHDR Hdr;
439 uint32_t u32ClientId;
440 uint32_t u32ClientStatus;
441} IPCMMSGCLIENTSTATE;
442AssertCompileSize(IPCMMSGCLIENTSTATE, 4 * sizeof(uint32_t));
443typedef IPCMMSGCLIENTSTATE *PIPCMMSGCLIENTSTATE;
444typedef const IPCMMSGCLIENTSTATE *PCIPCMMSGCLIENTSTATE;
445
446/**
447 * Helper structure for stack based messages.
448 */
449typedef struct IPCMMSGSTACK
450{
451 IPCMSGHDR Hdr;
452 union
453 {
454 IPCMMSGHDR Hdr;
455 IPCMMSGPING Ping;
456 IPCMMSGCLIENTHELLO ClientHello;
457 IPCMMSGCLIENTADDDELTARGET AddDelTarget;
458 IPCMMSGRESULT Result;
459 IPCMMSGCLIENTID ClientId;
460 IPCMMSGCLIENTSTATE ClientState;
461 } Ipcm;
462} IPCMMSGSTACK;
463
464#endif // !ipcm_h__
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use