Back to index

lightning-sunbird  0.9+nobinonly
ipcm.h
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla IPC.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2002
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Darin Fisher <darin@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef ipcm_h__
00039 #define ipcm_h__
00040 
00041 #include "ipcMessage.h"
00042 #include "ipcMessagePrimitives.h"
00043 
00044 //-----------------------------------------------------------------------------
00045 
00046 //
00047 // IPCM (IPC Manager) protocol support
00048 //
00049 
00050 // The IPCM message target identifier:
00051 extern const nsID IPCM_TARGET;
00052 
00053 //
00054 // Every IPCM message has the following structure:
00055 //
00056 //  +-----------------------------------------+
00057 //  | (ipc message header)                    |
00058 //  +-----------------------------------------+
00059 //  | DWORD : type                            |
00060 //  +-----------------------------------------+
00061 //  | DWORD : requestIndex                    |
00062 //  +-----------------------------------------+
00063 //  .                                         .
00064 //  . (payload)                               .
00065 //  .                                         .
00066 //  +-----------------------------------------+
00067 //
00068 // where |type| is an integer uniquely identifying the message.  the type is
00069 // composed of a message class identifier and a message number.  there are 3
00070 // message classes:
00071 //
00072 //   ACK - acknowledging a request
00073 //   REQ - making a request
00074 //   PSH - providing unrequested, "pushed" information
00075 //
00076 // The requestIndex field is initialized when a request is made.  An
00077 // acknowledgement's requestIndex is equal to that of its corresponding
00078 // request message.  This enables the requesting side of the message exchange
00079 // to match acknowledgements to requests.  The requestIndex field is ignored
00080 // for PSH messages.
00081 //
00082 
00083 // The IPCM message class is stored in the most significant byte.
00084 #define IPCM_MSG_CLASS_REQ (1 << 24)
00085 #define IPCM_MSG_CLASS_ACK (2 << 24)
00086 #define IPCM_MSG_CLASS_PSH (4 << 24)
00087 
00088 // Requests
00089 #define IPCM_MSG_REQ_PING                   (IPCM_MSG_CLASS_REQ | 1)
00090 #define IPCM_MSG_REQ_FORWARD                (IPCM_MSG_CLASS_REQ | 2)
00091 #define IPCM_MSG_REQ_CLIENT_HELLO           (IPCM_MSG_CLASS_REQ | 3)
00092 #define IPCM_MSG_REQ_CLIENT_ADD_NAME        (IPCM_MSG_CLASS_REQ | 4)
00093 #define IPCM_MSG_REQ_CLIENT_DEL_NAME        (IPCM_MSG_CLASS_REQ | 5)
00094 #define IPCM_MSG_REQ_CLIENT_ADD_TARGET      (IPCM_MSG_CLASS_REQ | 6)
00095 #define IPCM_MSG_REQ_CLIENT_DEL_TARGET      (IPCM_MSG_CLASS_REQ | 7)
00096 #define IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME   (IPCM_MSG_CLASS_REQ | 8)
00097 #define IPCM_MSG_REQ_QUERY_CLIENT_NAMES     (IPCM_MSG_CLASS_REQ | 9)  // TODO
00098 #define IPCM_MSG_REQ_QUERY_CLIENT_TARGETS   (IPCM_MSG_CLASS_REQ | 10) // TODO
00099 
00100 // Acknowledgements
00101 #define IPCM_MSG_ACK_RESULT                 (IPCM_MSG_CLASS_ACK | 1)
00102 #define IPCM_MSG_ACK_CLIENT_ID              (IPCM_MSG_CLASS_ACK | 2)
00103 #define IPCM_MSG_ACK_CLIENT_NAMES           (IPCM_MSG_CLASS_ACK | 3)  // TODO
00104 #define IPCM_MSG_ACK_CLIENT_TARGETS         (IPCM_MSG_CLASS_ACK | 4)  // TODO
00105 
00106 // Push messages
00107 #define IPCM_MSG_PSH_CLIENT_STATE           (IPCM_MSG_CLASS_PSH | 1)
00108 #define IPCM_MSG_PSH_FORWARD                (IPCM_MSG_CLASS_PSH | 2)
00109 
00110 //-----------------------------------------------------------------------------
00111 
00112 //
00113 // IPCM header
00114 //
00115 struct ipcmMessageHeader
00116 {
00117     PRUint32 mType;
00118     PRUint32 mRequestIndex;
00119 };
00120 
00121 //
00122 // returns IPCM message type.
00123 //
00124 static inline int
00125 IPCM_GetType(const ipcMessage *msg)
00126 {
00127     return ((const ipcmMessageHeader *) msg->Data())->mType;
00128 }
00129 
00130 //
00131 // return IPCM message request index.  
00132 //
00133 static inline PRUint32
00134 IPCM_GetRequestIndex(const ipcMessage *msg)
00135 {
00136     return ((const ipcmMessageHeader *) msg->Data())->mRequestIndex;
00137 }
00138 
00139 //
00140 // return a request index that is unique to this process.
00141 //
00142 NS_HIDDEN_(PRUint32)
00143 IPCM_NewRequestIndex();
00144 
00145 //-----------------------------------------------------------------------------
00146 
00147 //
00148 // The IPCM protocol is detailed below:
00149 //
00150 
00151 // REQUESTS
00152 
00153 //
00154 // req: IPCM_MSG_REQ_PING
00155 // ack: IPCM_MSG_ACK_RESULT
00156 //
00157 // A PING can be sent from either a client to the daemon, or from the daemon
00158 // to a client.  The expected acknowledgement is a RESULT message with a status
00159 // code of 0.
00160 //
00161 // This request message has no payload.
00162 //
00163 
00164 //
00165 // req: IPCM_MSG_REQ_FORWARD
00166 // ack: IPCM_MSG_ACK_RESULT
00167 //
00168 // A FORWARD is sent when a client wishes to send a message to another client.
00169 // The payload of this message is another message that should be forwarded by
00170 // the daemon's IPCM to the specified client.  The expected acknowledgment is
00171 // a RESULT message with a status code indicating success or failure.
00172 //
00173 // When the daemon receives a FORWARD message, it creates a PSH_FORWARD message
00174 // and sends that on to the destination client.
00175 //
00176 // This request message has as its payload:
00177 //
00178 //  +-----------------------------------------+
00179 //  | DWORD : clientID                        |
00180 //  +-----------------------------------------+
00181 //  | (innerMsgHeader)                        |
00182 //  +-----------------------------------------+
00183 //  | (innerMsgData)                          |
00184 //  +-----------------------------------------+
00185 //
00186 
00187 //
00188 // req: IPCM_MSG_REQ_CLIENT_HELLO
00189 // ack: IPCM_MSG_REQ_CLIENT_ID <or> IPCM_MSG_REQ_RESULT
00190 //
00191 // A CLIENT_HELLO is sent when a client connects to the IPC daemon.  The
00192 // expected acknowledgement is a CLIENT_ID message informing the new client of
00193 // its ClientID.  If for some reason the IPC daemon cannot accept the new
00194 // client, it returns a RESULT message with a failure status code.
00195 //
00196 // This request message has no payload.
00197 //
00198 
00199 //
00200 // req: IPCM_MSG_REQ_CLIENT_ADD_NAME
00201 // ack: IPCM_MSG_ACK_RESULT
00202 //
00203 // A CLIENT_ADD_NAME is sent when a client wishes to register an additional
00204 // name for itself.  The expected acknowledgement is a RESULT message with a
00205 // status code indicating success or failure.
00206 //
00207 // This request message has as its payload a null-terminated ASCII character
00208 // string indicating the name of the client.
00209 //
00210 
00211 //
00212 // req: IPCM_MSG_REQ_CLIENT_DEL_NAME
00213 // ack: IPCM_MSG_ACK_RESULT
00214 //
00215 // A CLIENT_DEL_NAME is sent when a client wishes to unregister a name that it
00216 // has registered.  The expected acknowledgement is a RESULT message with a
00217 // status code indicating success or failure.
00218 //
00219 // This request message has as its payload a null-terminated ASCII character
00220 // string indicating the name of the client.
00221 //
00222 
00223 //
00224 // req: IPCM_MSG_REQ_CLIENT_ADD_TARGET
00225 // ack: IPCM_MSG_ACK_RESULT
00226 //
00227 // A CLIENT_ADD_TARGET is sent when a client wishes to register an additional
00228 // target that it supports.  The expected acknowledgement is a RESULT message
00229 // with a status code indicating success or failure.
00230 //
00231 // This request message has as its payload a 128-bit UUID indicating the
00232 // target to add.
00233 //
00234 
00235 //
00236 // req: IPCM_MSG_REQ_CLIENT_DEL_TARGET
00237 // ack: IPCM_MSG_ACK_RESULT
00238 //
00239 // A CLIENT_DEL_TARGET is sent when a client wishes to unregister a target
00240 // that it has registered.  The expected acknowledgement is a RESULT message
00241 // with a status code indicating success or failure.
00242 //
00243 // This request message has as its payload a 128-bit UUID indicating the
00244 // target to remove.
00245 //
00246 
00247 //
00248 // req: IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME
00249 // ack: IPCM_MSG_ACK_CLIENT_ID <or> IPCM_MSG_ACK_RESULT
00250 //
00251 // A QUERY_CLIENT_BY_NAME may be sent by a client to discover the client that
00252 // is known by a common name.  If more than one client matches the name, then
00253 // only the ID of the more recently registered client is returned.  The
00254 // expected acknowledgement is a CLIENT_ID message carrying the ID of the
00255 // corresponding client.  If no client matches the given name or if some error
00256 // occurs, then a RESULT message with a failure status code is returned.
00257 //
00258 // This request message has as its payload a null-terminated ASCII character
00259 // string indicating the client name to query.
00260 // 
00261 
00262 // ACKNOWLEDGEMENTS
00263 
00264 //
00265 // ack: IPCM_MSG_ACK_RESULT
00266 //
00267 // This acknowledgement is returned to indicate a success or failure status.
00268 //
00269 // The payload consists of a single DWORD value.
00270 //
00271 // Possible status codes are listed below (negative values indicate failure
00272 // codes):
00273 //
00274 #define IPCM_OK               0  // success: generic
00275 #define IPCM_ERROR_GENERIC   -1  // failure: generic
00276 #define IPCM_ERROR_NO_CLIENT -2  // failure: client does not exist
00277 
00278 //
00279 // ack: IPCM_MSG_ACK_CLIENT_ID
00280 //
00281 // This acknowledgement is returned to specify a client ID.
00282 //
00283 // The payload consists of a single DWORD value.
00284 //
00285 
00286 // PUSH MESSAGES
00287 
00288 //
00289 // psh: ICPM_MSG_PSH_CLIENT_STATE
00290 //
00291 // This message is sent to clients to indicate the status of other clients.
00292 //
00293 // The payload consists of:
00294 //
00295 //  +-----------------------------------------+
00296 //  | DWORD : clientID                        |
00297 //  +-----------------------------------------+
00298 //  | DWORD : clientState                     |
00299 //  +-----------------------------------------+
00300 //
00301 // where, clientState is one of the following values indicating whether the
00302 // client has recently connected (up) or disconnected (down):
00303 //
00304 #define IPCM_CLIENT_STATE_UP     1
00305 #define IPCM_CLIENT_STATE_DOWN   2
00306 
00307 //
00308 // psh: IPCM_MSG_PSH_FORWARD
00309 //
00310 // This message is sent by the daemon to a client on behalf of another client.
00311 // The recipient is expected to unpack the contained message and process it.
00312 // 
00313 // The payload of this message matches the payload of IPCM_MSG_REQ_FORWARD,
00314 // with the exception that the clientID field is set to the clientID of the
00315 // sender of the IPCM_MSG_REQ_FORWARD message.
00316 //
00317 
00318 //-----------------------------------------------------------------------------
00319 
00320 //
00321 // NOTE: This file declares some helper classes that simplify constructing
00322 //       and parsing IPCM messages.  Each class subclasses ipcMessage, but
00323 //       adds no additional member variables.  |operator new| should be used
00324 //       to allocate one of the IPCM helper classes, e.g.:
00325 //         
00326 //          ipcMessage *msg = new ipcmMessageClientHello("foo");
00327 //
00328 //       Given an arbitrary ipcMessage, it can be parsed using logic similar
00329 //       to the following:
00330 //
00331 //          void func(const ipcMessage *unknown)
00332 //          {
00333 //            if (unknown->Topic().Equals(IPCM_TARGET)) {
00334 //              if (IPCM_GetMsgType(unknown) == IPCM_MSG_TYPE_CLIENT_ID) {
00335 //                ipcMessageCast<ipcmMessageClientID> msg(unknown);
00336 //                printf("Client ID: %u\n", msg->ClientID());
00337 //              }
00338 //            }
00339 //          }
00340 //
00341 
00342 // REQUESTS
00343 
00344 class ipcmMessagePing : public ipcMessage_DWORD_DWORD
00345 {
00346 public:
00347     ipcmMessagePing()
00348         : ipcMessage_DWORD_DWORD(
00349             IPCM_TARGET,
00350             IPCM_MSG_REQ_PING,
00351             IPCM_NewRequestIndex()) {}
00352 };
00353 
00354 class ipcmMessageForward : public ipcMessage
00355 {
00356 public:
00357     // @param type        the type of this message: IPCM_MSG_{REQ,PSH}_FORWARD
00358     // @param clientID    the client id of the sender or receiver
00359     // @param target      the message target
00360     // @param data        the message data
00361     // @param dataLen     the message data length
00362     ipcmMessageForward(PRUint32 type,
00363                        PRUint32 clientID,
00364                        const nsID &target,
00365                        const char *data,
00366                        PRUint32 dataLen) NS_HIDDEN;
00367 
00368     // set inner message data, constrained to the data length passed
00369     // to this class's constructor.
00370     NS_HIDDEN_(void) SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen);
00371 
00372     NS_HIDDEN_(PRUint32)     ClientID() const;
00373     NS_HIDDEN_(const nsID &) InnerTarget() const;
00374     NS_HIDDEN_(const char *) InnerData() const;
00375     NS_HIDDEN_(PRUint32)     InnerDataLen() const;
00376 };
00377 
00378 class ipcmMessageClientHello : public ipcMessage_DWORD_DWORD
00379 {
00380 public:
00381     ipcmMessageClientHello()
00382         : ipcMessage_DWORD_DWORD(
00383             IPCM_TARGET,
00384             IPCM_MSG_REQ_CLIENT_HELLO,
00385             IPCM_NewRequestIndex()) {}
00386 };
00387 
00388 class ipcmMessageClientAddName : public ipcMessage_DWORD_DWORD_STR
00389 {
00390 public:
00391     ipcmMessageClientAddName(const char *name)
00392         : ipcMessage_DWORD_DWORD_STR(
00393             IPCM_TARGET,
00394             IPCM_MSG_REQ_CLIENT_ADD_NAME,
00395             IPCM_NewRequestIndex(),
00396             name) {}
00397 
00398     const char *Name() const { return Third(); }
00399 };
00400 
00401 class ipcmMessageClientDelName : public ipcMessage_DWORD_DWORD_STR
00402 {
00403 public:
00404     ipcmMessageClientDelName(const char *name)
00405         : ipcMessage_DWORD_DWORD_STR(
00406             IPCM_TARGET,
00407             IPCM_MSG_REQ_CLIENT_DEL_NAME,
00408             IPCM_NewRequestIndex(),
00409             name) {}
00410 
00411     const char *Name() const { return Third(); }
00412 };
00413 
00414 class ipcmMessageClientAddTarget : public ipcMessage_DWORD_DWORD_ID
00415 {
00416 public:
00417     ipcmMessageClientAddTarget(const nsID &target)
00418         : ipcMessage_DWORD_DWORD_ID(
00419             IPCM_TARGET,
00420             IPCM_MSG_REQ_CLIENT_ADD_TARGET,
00421             IPCM_NewRequestIndex(),
00422             target) {}
00423 
00424     const nsID &Target() const { return Third(); }
00425 };
00426 
00427 class ipcmMessageClientDelTarget : public ipcMessage_DWORD_DWORD_ID
00428 {
00429 public:
00430     ipcmMessageClientDelTarget(const nsID &target)
00431         : ipcMessage_DWORD_DWORD_ID(
00432             IPCM_TARGET,
00433             IPCM_MSG_REQ_CLIENT_ADD_TARGET,
00434             IPCM_NewRequestIndex(),
00435             target) {}
00436 
00437     const nsID &Target() const { return Third(); }
00438 };
00439 
00440 class ipcmMessageQueryClientByName : public ipcMessage_DWORD_DWORD_STR
00441 {
00442 public:
00443     ipcmMessageQueryClientByName(const char *name)
00444         : ipcMessage_DWORD_DWORD_STR(
00445             IPCM_TARGET,
00446             IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME,
00447             IPCM_NewRequestIndex(),
00448             name) {}
00449 
00450     const char *Name() const { return Third(); }
00451     PRUint32 RequestIndex() const { return Second(); }
00452 };
00453 
00454 // ACKNOWLEDGEMENTS
00455 
00456 class ipcmMessageResult : public ipcMessage_DWORD_DWORD_DWORD
00457 {
00458 public:
00459     ipcmMessageResult(PRUint32 requestIndex, PRInt32 status)
00460         : ipcMessage_DWORD_DWORD_DWORD(
00461             IPCM_TARGET,
00462             IPCM_MSG_ACK_RESULT,
00463             requestIndex,
00464             (PRUint32) status) {}
00465 
00466     PRInt32 Status() const { return (PRInt32) Third(); }
00467 };
00468 
00469 class ipcmMessageClientID : public ipcMessage_DWORD_DWORD_DWORD
00470 {
00471 public:
00472     ipcmMessageClientID(PRUint32 requestIndex, PRUint32 clientID)
00473         : ipcMessage_DWORD_DWORD_DWORD(
00474             IPCM_TARGET,
00475             IPCM_MSG_ACK_CLIENT_ID,
00476             requestIndex,
00477             clientID) {}
00478 
00479     PRUint32 ClientID() const { return Third(); }
00480 };
00481 
00482 // PUSH MESSAGES
00483 
00484 class ipcmMessageClientState : public ipcMessage_DWORD_DWORD_DWORD_DWORD
00485 {
00486 public:
00487     ipcmMessageClientState(PRUint32 clientID, PRUint32 clientStatus)
00488         : ipcMessage_DWORD_DWORD_DWORD_DWORD(
00489             IPCM_TARGET,
00490             IPCM_MSG_PSH_CLIENT_STATE,
00491             0,
00492             clientID,
00493             clientStatus) {}
00494 
00495     PRUint32 ClientID() const { return Third(); }
00496     PRUint32 ClientState() const { return Fourth(); }
00497 };
00498 
00499 #endif // !ipcm_h__