From 40b33e4bfae64628b2990a19959913a08739f758 Mon Sep 17 00:00:00 2001 From: "darin%netscape.com" Date: Fri, 1 Nov 2002 09:08:25 +0000 Subject: [PATCH] 1) updated IPCM protocol 2) added ipcMessage primitives to simplify IPCM protocol implementation 3) added ipcMessageCast to simplify casting raw messages to specific types 4) added function table in ipcCommandModule git-svn-id: svn://10.0.0.236/trunk@132815 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/modules/ipc/common/Makefile.in | 1 + mozilla/modules/ipc/common/ipcMessage.h | 4 + .../ipc/common/ipcMessagePrimitives.cpp | 49 +++++ .../modules/ipc/common/ipcMessagePrimitives.h | 93 +++++++++ mozilla/modules/ipc/common/ipcMessageUtils.h | 64 +++++++ mozilla/modules/ipc/common/ipcm.cpp | 181 +++++++----------- mozilla/modules/ipc/common/ipcm.h | 145 +++++++++----- .../modules/ipc/daemon/ipcCommandModule.cpp | 110 +++++++---- mozilla/modules/ipc/src/ipcService.cpp | 19 +- mozilla/modules/ipc/src/ipcTransport.cpp | 27 ++- mozilla/modules/ipc/src/ipcTransport.h | 4 +- 11 files changed, 472 insertions(+), 225 deletions(-) create mode 100644 mozilla/modules/ipc/common/ipcMessagePrimitives.cpp create mode 100644 mozilla/modules/ipc/common/ipcMessagePrimitives.h create mode 100644 mozilla/modules/ipc/common/ipcMessageUtils.h diff --git a/mozilla/modules/ipc/common/Makefile.in b/mozilla/modules/ipc/common/Makefile.in index bc9f3d9672c..a9117e6374c 100644 --- a/mozilla/modules/ipc/common/Makefile.in +++ b/mozilla/modules/ipc/common/Makefile.in @@ -55,6 +55,7 @@ REQUIRES = \ CPPSRCS = \ ipcMessage.cpp \ ipcMessageQ.cpp \ + ipcMessagePrimitives.cpp \ ipcm.cpp EXPORTS = \ diff --git a/mozilla/modules/ipc/common/ipcMessage.h b/mozilla/modules/ipc/common/ipcMessage.h index e2e6af53591..a1a9ba2321b 100644 --- a/mozilla/modules/ipc/common/ipcMessage.h +++ b/mozilla/modules/ipc/common/ipcMessage.h @@ -83,6 +83,10 @@ public: , mMsgOffset(0) , mMsgComplete(PR_FALSE) { } + ipcMessage(const nsID &target, const char *data, PRUint32 dataLen) + : mNext(NULL) + , mMsgOffset(0) + { Init(target, data, dataLen); } ~ipcMessage(); // diff --git a/mozilla/modules/ipc/common/ipcMessagePrimitives.cpp b/mozilla/modules/ipc/common/ipcMessagePrimitives.cpp new file mode 100644 index 00000000000..49a7645c44f --- /dev/null +++ b/mozilla/modules/ipc/common/ipcMessagePrimitives.cpp @@ -0,0 +1,49 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPC. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include "ipcMessagePrimitives.h" + +ipcMessage_DWORD_STR::ipcMessage_DWORD_STR(const nsID &target, + PRUint32 first, + const char *second) +{ + int sLen = strlen(second); + Init(target, NULL, sizeof(first) + sLen + 1); + SetData(0, (char *) &first, sizeof(first)); + SetData(sizeof(first), second, sLen + 1); +} diff --git a/mozilla/modules/ipc/common/ipcMessagePrimitives.h b/mozilla/modules/ipc/common/ipcMessagePrimitives.h new file mode 100644 index 00000000000..7765bde6be2 --- /dev/null +++ b/mozilla/modules/ipc/common/ipcMessagePrimitives.h @@ -0,0 +1,93 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPC. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef ipcMessagePrimitives_h__ +#define ipcMessagePrimitives_h__ + +#include "ipcMessage.h" + +class ipcMessage_DWORD : public ipcMessage +{ +public: + ipcMessage_DWORD(const nsID &target, PRUint32 first) + { + Init(target, (char *) &first, sizeof(first)); + } + + PRUint32 First() const + { + return ((PRUint32 *) Data())[0]; + } +}; + +class ipcMessage_DWORD_DWORD : public ipcMessage +{ +public: + ipcMessage_DWORD_DWORD(const nsID &target, PRUint32 first, PRUint32 second) + { + PRUint32 data[2] = { first, second }; + Init(target, (char *) data, sizeof(data)); + } + + PRUint32 First() const + { + return ((PRUint32 *) Data())[0]; + } + + PRUint32 Second() const + { + return ((PRUint32 *) Data())[1]; + } +}; + +class ipcMessage_DWORD_STR : public ipcMessage +{ +public: + ipcMessage_DWORD_STR(const nsID &target, PRUint32 first, const char *second); + + PRUint32 First() const + { + return ((PRUint32 *) Data())[0]; + } + + const char *Second() const + { + return Data() + sizeof(PRUint32); + } +}; + +#endif // !ipcMessagePrimitives_h__ diff --git a/mozilla/modules/ipc/common/ipcMessageUtils.h b/mozilla/modules/ipc/common/ipcMessageUtils.h new file mode 100644 index 00000000000..f5801d16f8a --- /dev/null +++ b/mozilla/modules/ipc/common/ipcMessageUtils.h @@ -0,0 +1,64 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPC. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef ipcMessageUtils_h__ +#define ipcMessageUtils_h__ + +// +// given code like this: +// +// const ipcmMessageClientID *msg = (const ipcmMessageClientID *) rawMsg; +// +// we can write: +// +// ipcMessageCast msg(rawMsg); +// +// XXX ipcMessageCast is probably not the best name for this class. +// +template +class ipcMessageCast +{ +public: + ipcMessageCast() : mPtr(NULL) {} + ipcMessageCast(const ipcMessage *ptr) : mPtr((const T *) ptr) {} + void operator=(const ipcMessage *ptr) { mPtr = (const T *) ptr; } + const T *operator->() { return mPtr; } +private: + const T *mPtr; +}; + +#endif // !ipcMessageUtils_h__ diff --git a/mozilla/modules/ipc/common/ipcm.cpp b/mozilla/modules/ipc/common/ipcm.cpp index d7c5fa910b0..bfbf3b87ce3 100644 --- a/mozilla/modules/ipc/common/ipcm.cpp +++ b/mozilla/modules/ipc/common/ipcm.cpp @@ -47,15 +47,9 @@ const nsID IPCM_TARGET = {0xb1, 0x15, 0x8c, 0x29, 0x44, 0xda, 0x11, 0x50} }; -static const char IPCM_PING[] = { (char) IPCM_MSG_PING }; -static const PRUint32 IPCM_PING_LEN = sizeof(IPCM_PING); - -static const char IPCM_CNAME[] = { (char) IPCM_MSG_CNAME }; -static const PRUint32 IPCM_CNAME_LEN = sizeof(IPCM_CNAME); - // // +--------------------+ -// | BYTE : msgType | +// | DWORD : MSG_TYPE | // +--------------------+ // | (variable) | // +--------------------+ @@ -67,80 +61,24 @@ IPCM_GetMsgType(const ipcMessage *msg) // make sure message topic matches if (msg->Target().Equals(IPCM_TARGET)) { // the type is encoded as the first byte - char type = msg->Data()[0]; - if (type < IPCM_MSG_UNKNOWN) + PRUint32 type = * (PRUint32 *) msg->Data(); + if (type < IPCM_MSG_TYPE_UNKNOWN) return type; } - return IPCM_MSG_UNKNOWN; + return IPCM_MSG_TYPE_UNKNOWN; } // -// PING message -// -// +----------------------+ -// | BYTE - IPCM_MSG_PING | -// +----------------------+ +// MSG_TYPE values // +const PRUint32 ipcmMessagePing::MSG_TYPE = IPCM_MSG_TYPE_PING; +const PRUint32 ipcmMessageError::MSG_TYPE = IPCM_MSG_TYPE_ERROR; +const PRUint32 ipcmMessageClientHello::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_HELLO; +const PRUint32 ipcmMessageClientID::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ID; +const PRUint32 ipcmMessageQueryClientByName::MSG_TYPE = IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME; +const PRUint32 ipcmMessageForward::MSG_TYPE = IPCM_MSG_TYPE_FORWARD; -const char ipcmMessagePING::MSG_TYPE = (char) IPCM_MSG_PING; - -ipcmMessagePING::ipcmMessagePING() -{ - Init(IPCM_TARGET, &MSG_TYPE, 1); -} - -// -// CNAME message -// -// +-----------------------+ -// | BYTE - IPCM_MSG_CNAME | -// +-----------------------+ -// | clientName | -// +-----------------------+ -// | null | -// +-----------------------+ -// - -const char ipcmMessageCNAME::MSG_TYPE = (char) IPCM_MSG_CNAME; - -ipcmMessageCNAME::ipcmMessageCNAME(const char *cName) -{ - int cLen = strlen(cName); - int dataLen = 1 + // msg_type - cLen + // cName - 1; // null - - Init(IPCM_TARGET, NULL, dataLen); - SetData(0, &MSG_TYPE, 1); - SetData(1, cName, cLen + 1); -} - -const char * -ipcmMessageCNAME::ClientName() const -{ - // make sure data is null terminated - const char *data = Data(); - if (data[DataLen() - 1] != '\0') - return NULL; - - return Data() + 1; -} - -// -// CENUM message -// -// +-----------------------+ -// | BYTE - IPCM_MSG_CENUM | -// +-----------------------+ -// - -const char ipcmMessageCENUM::MSG_TYPE = (char) IPCM_MSG_CENUM; - -ipcmMessageCENUM::ipcmMessageCENUM() -{ - Init(IPCM_TARGET, &MSG_TYPE, 1); -} - +#if 0 // // CLIST message // @@ -192,57 +130,76 @@ ipcmMessageCLIST::NextClientName(const char *cName) const cName = NULL; return cName; } +#endif // // FWD message // -// +----------------------+ -// | BYTE - IPCM_MSG_FWD | -// +----------------------+ -// | dest_client | -// +----------------------+ -// | null | -// +----------------------+ -// | dest_msg | -// +----------------------+ +// +-------------------------------+ +// | DWORD : IPCM_MSG_TYPE_FORWARD | +// +-------------------------------+ +// | clientID | +// +-------------------------------+ +// | innerMsgHeader | +// +-------------------------------+ +// | innerMsgData | +// +-------------------------------+ // -const char ipcmMessageFWD::MSG_TYPE = (char) IPCM_MSG_FWD; - -ipcmMessageFWD::ipcmMessageFWD(const char *dClient, const ipcMessage *dMsg) +ipcmMessageForward::ipcmMessageForward(PRUint32 cID, + const nsID &target, + const char *data, + PRUint32 dataLen) { - int cLen = strlen(dClient); - int dataLen = 1 + // msg_type - cLen + // dest_client - 1 + // null - dMsg->MsgLen(); // dest_msg + int len = sizeof(MSG_TYPE) + // MSG_TYPE + sizeof(cID) + // cID + IPC_MSG_HEADER_SIZE + // innerMsgHeader + dataLen; // innerMsgData - Init(IPCM_TARGET, NULL, dataLen); - SetData(0, &MSG_TYPE, 1); - SetData(1, dClient, cLen + 1); - SetData(1 + cLen + 1, dMsg->MsgBuf(), dMsg->MsgLen()); + Init(IPCM_TARGET, NULL, len); + + SetData(0, (char *) &MSG_TYPE, sizeof(MSG_TYPE)); + SetData(1, (char *) &cID, sizeof(cID)); + + ipcMessageHeader hdr; + hdr.mLen = IPC_MSG_HEADER_SIZE + dataLen; + hdr.mVersion = IPC_MSG_VERSION; + hdr.mFlags = 0; + hdr.mTarget = target; + + SetData(1 + sizeof(cID), (char *) &hdr, IPC_MSG_HEADER_SIZE); + if (data) + SetInnerData(0, data, dataLen); +} + +void +ipcmMessageForward::SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen) +{ + SetData(8 + IPC_MSG_HEADER_SIZE + offset, data, dataLen); +} + +PRUint32 +ipcmMessageForward::DestClientID() const +{ + return * (PRUint32 *) (Data() + 4); +} + +const nsID & +ipcmMessageForward::InnerTarget() const +{ + ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 8); + return hdr->mTarget; } const char * -ipcmMessageFWD::DestClient() const +ipcmMessageForward::InnerData() const { - return Data() + 1; + return Data() + 8 + IPC_MSG_HEADER_SIZE; } -PRStatus -ipcmMessageFWD::DestMessage(ipcMessage *msg) const +PRUint32 +ipcmMessageForward::InnerDataLen() const { - const char *ptr = DestClient(); - - // XXX use a custom loop here to avoid walking off the end of the buffer - PRUint32 cLen = strlen(ptr); - PRUint32 dLen = MsgLen() - 1 - cLen - 1; - PRUint32 bytesRead; - PRBool complete; - - ptr += (cLen + 1); - if (msg->ReadFrom(ptr, dLen, &bytesRead, &complete) != PR_SUCCESS || !complete) - return PR_FAILURE; - - return PR_SUCCESS; + ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 8); + return hdr->mLen - IPC_MSG_HEADER_SIZE; } diff --git a/mozilla/modules/ipc/common/ipcm.h b/mozilla/modules/ipc/common/ipcm.h index 865ba614a06..2f57b2850b7 100644 --- a/mozilla/modules/ipc/common/ipcm.h +++ b/mozilla/modules/ipc/common/ipcm.h @@ -39,6 +39,7 @@ #define ipcm_h__ #include "ipcMessage.h" +#include "ipcMessagePrimitives.h" // // IPCM (IPC Manager) protocol support @@ -47,12 +48,20 @@ extern const nsID IPCM_TARGET; enum { - IPCM_MSG_PING, - IPCM_MSG_CNAME, - IPCM_MSG_CENUM, - IPCM_MSG_CLIST, - IPCM_MSG_FWD, - IPCM_MSG_UNKNOWN // unknown message type + IPCM_MSG_TYPE_PING, + IPCM_MSG_TYPE_ERROR, + IPCM_MSG_TYPE_CLIENT_HELLO, + IPCM_MSG_TYPE_CLIENT_ID, + IPCM_MSG_TYPE_CLIENT_INFO, + IPCM_MSG_TYPE_CLIENT_ADD_NAME, + IPCM_MSG_TYPE_CLIENT_DEL_NAME, + IPCM_MSG_TYPE_CLIENT_ADD_TARGET, + IPCM_MSG_TYPE_CLIENT_DEL_TARGET, + IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME, + IPCM_MSG_TYPE_QUERY_CLIENT_INFO, + IPCM_MSG_TYPE_QUERY_FAILED, + IPCM_MSG_TYPE_FORWARD, + IPCM_MSG_TYPE_UNKNOWN // unknown message type }; // @@ -66,109 +75,141 @@ int IPCM_GetMsgType(const ipcMessage *msg); // adds no additional member variables. operator new should be used // to allocate one of the IPCM helper classes, e.g.: // -// ipcMessage *msg = new ipcmMessageCNAME("foo"); +// ipcMessage *msg = new ipcmMessageClientHello("foo"); // // given an arbitrary ipcMessage, it can be parsed using logic similar // to the following: // -// ipcMessage *msg = ... -// if (strcmp(msg->Topic(), "ipcm") == 0) { -// if (IPCM_GetMsgType(msg) == IPCM_MSG_CNAME) { -// ipcmMessageCNAME *cnameMsg = (ipcmMessageCNAME *) msg; -// printf("client name: %s\n", cnameMsg->ClientName()); -// } +// void func(const ipcMessage *unknown) +// { +// if (unknown->Topic().Equals(IPCM_TARGET)) { +// if (IPCM_GetMsgType(unknown) == IPCM_MSG_TYPE_CLIENT_ID) { +// ipcMessageCast msg(unknown); +// printf("Client ID: %u\n", msg->ClientID()); +// } +// } // } // // in other words, these classes are very very lightweight. // // -// IPCM_MSG_PING +// IPCM_MSG_TYPE_PING // // this message may be sent from either the client or the daemon. // -class ipcmMessagePING : public ipcMessage +class ipcmMessagePing : public ipcMessage_DWORD { public: - static const char MSG_TYPE; + static const PRUint32 MSG_TYPE; - ipcmMessagePING(); + ipcmMessagePing() + : ipcMessage_DWORD(IPCM_TARGET, MSG_TYPE) {} }; // -// IPCM_MSG_CNAME +// IPCM_MSG_TYPE_ERROR // -// this message is sent from a client to specify its name. +// thie message may be sent from the daemon in response to a query. // -class ipcmMessageCNAME : public ipcMessage +class ipcmMessageError : public ipcMessage_DWORD_DWORD { public: - static const char MSG_TYPE; + static const PRUint32 MSG_TYPE; - ipcmMessageCNAME(const char *cName); + ipcmMessageError(PRUint32 reason) + : ipcMessage_DWORD_DWORD(IPCM_TARGET, MSG_TYPE, reason) {} - // - // extracts the "client name" - // - const char *ClientName() const; + PRUint32 Reason() const { return Second(); } }; // -// IPCM_MSG_CENUM +// IPCM_MSG_TYPE_CLIENT_HELLO // -// this message is sent from a client to request a CLIST response. +// this message is always the first message sent from a client to register +// itself with the daemon. the daemon responds to this message by sending +// the client a CLIENT_ID message informing the client of its client ID. // -class ipcmMessageCENUM : public ipcMessage +// XXX may want to pass other information here. +// +class ipcmMessageClientHello : public ipcMessage_DWORD_STR { public: - static const char MSG_TYPE; + static const PRUint32 MSG_TYPE; - ipcmMessageCENUM(); + ipcmMessageClientHello(const char *primaryName) + : ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, primaryName) {} + + const char *PrimaryName() const { return Second(); } }; // -// IPCM_MSG_CLIST +// IPCM_MSG_TYPE_CLIENT_ID // -// this message is sent from the daemon in response to a CENUM request. the -// message contains the list of clients by name. +// this message is sent from the daemon to identify a client's ID. // -class ipcmMessageCLIST : public ipcMessage +class ipcmMessageClientID : public ipcMessage_DWORD_DWORD { public: - static const char MSG_TYPE; + static const PRUint32 MSG_TYPE; - ipcmMessageCLIST(const char *clientNames[], PRUint32 numClients); + ipcmMessageClientID(PRUint32 clientID) + : ipcMessage_DWORD_DWORD(IPCM_TARGET, MSG_TYPE, clientID) {} - // - // extracts the next client name from the message. if null is passed in, then - // the first client name in the list is returned. null is returned if there - // aren't anymore client names. (the returned client name acts as an iterator.) - // - const char *NextClientName(const char *clientName = NULL) const; + PRUint32 ClientID() const { return Second(); } }; // -// IPCM_MSG_FWD +// IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME +// +// this message is sent from a client to the daemon to request the ID of the +// client corresponding to the given name or alias. in response the daemon +// will either send a CLIENT_ID or ERROR message. +// +class ipcmMessageQueryClientByName : public ipcMessage_DWORD_STR +{ +public: + static const PRUint32 MSG_TYPE; + + ipcmMessageQueryClientByName(const char *name) + : ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {} + + const char *Name() const { return Second(); } +}; + +// +// IPCM_MSG_TYPE_FORWARD // // this message is only sent from the client to the daemon. the daemon // will forward the contained message to the specified client. // -class ipcmMessageFWD : public ipcMessage +class ipcmMessageForward : public ipcMessage { public: - static const char MSG_TYPE; - - ipcmMessageFWD(const char *destClient, const ipcMessage *destMsg); + static const PRUint32 MSG_TYPE; // - // extracts the "destination client name" + // params: + // clientID - the client to which the message should be forwarded + // target - the message target + // data - the message data + // dataLen - the message data length // - const char *DestClient() const; + ipcmMessageForward(PRUint32 clientID, + const nsID &target, + const char *data, + PRUint32 dataLen); // - // extracts (a copy of) the "destination message" + // set inner message data, constrained to the data length passed + // to this class's constructor. // - PRStatus DestMessage(ipcMessage *destMsg) const; + void SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen); + + PRUint32 DestClientID() const; + const nsID &InnerTarget() const; + const char *InnerData() const; + PRUint32 InnerDataLen() const; }; #endif // !ipcm_h__ diff --git a/mozilla/modules/ipc/daemon/ipcCommandModule.cpp b/mozilla/modules/ipc/daemon/ipcCommandModule.cpp index 1891794f174..c6adf668b56 100644 --- a/mozilla/modules/ipc/daemon/ipcCommandModule.cpp +++ b/mozilla/modules/ipc/daemon/ipcCommandModule.cpp @@ -41,6 +41,7 @@ #include "ipcModule.h" #include "ipcClient.h" #include "ipcMessage.h" +#include "ipcMessageUtils.h" #include "ipcd.h" #include "ipcm.h" @@ -49,6 +50,49 @@ typedef const char * constCharPtr; class ipcCommandModule : public ipcModule { public: + typedef void (ipcCommandModule:: *MsgHandler)(ipcClient *, const ipcMessage *); + + // + // message handlers + // + + void handlePing(ipcClient *client, const ipcMessage *rawMsg) + { + printf("### got PING\n"); + + IPC_SendMsg(client, new ipcmMessagePing()); + } + + void handleClientHello(ipcClient *client, const ipcMessage *rawMsg) + { + printf("### got CLIENT_HELLO\n"); + + ipcMessageCast msg(rawMsg); + const char *name = msg->PrimaryName(); + if (name) + client->SetName(name); + + IPC_SendMsg(client, new ipcmMessageClientID(client->ID())); + } + + void handleForward(ipcClient *client, const ipcMessage *rawMsg) + { + printf("### got FORWARD\n"); + + ipcMessageCast msg(rawMsg); + ipcClient *dest = IPC_GetClientByID(msg->DestClientID()); + + ipcMessage *newMsg = new ipcMessage(); + newMsg->Init(msg->InnerTarget(), + msg->InnerData(), + msg->InnerDataLen()); + IPC_SendMsg(dest, newMsg); + } + + // + // ipcModule interface impl + // + void Shutdown() { } @@ -58,55 +102,43 @@ public: return IPCM_TARGET; } - void HandleMsg(ipcClient *client, const ipcMessage *msg) + void HandleMsg(ipcClient *client, const ipcMessage *rawMsg) { - // XXX replace w/ function table - switch (IPCM_GetMsgType(msg)) { - case IPCM_MSG_PING: - printf("### got ping\n"); - { - IPC_SendMsg(client, new ipcmMessagePING()); + static MsgHandler handlers[] = + { + &ipcCommandModule::handlePing, + NULL, // ERROR + &ipcCommandModule::handleClientHello, + NULL, // CLIENT_ID + NULL, // CLIENT_INFO + NULL, // CLIENT_ADD_NAME + NULL, // CLIENT_DEL_NAME + NULL, // CLIENT_ADD_TARGET + NULL, // CLIENT_DEL_TARGET + NULL, // QUERY_CLIENT_BY_NAME + NULL, // QUERY_CLIENT_INFO + NULL, // QUERY_FAILED + &ipcCommandModule::handleForward, + }; + + int type = IPCM_GetMsgType(rawMsg); + if (type < IPCM_MSG_TYPE_UNKNOWN) { + if (handlers[type]) { + MsgHandler handler = handlers[type]; + (this->*handler)(client, rawMsg); } - break; - case IPCM_MSG_CNAME: - printf("### got cname\n"); - { - const char *name = ((const ipcmMessageCNAME *) msg)->ClientName(); - if (name) - client->SetName(name); - } - break; - case IPCM_MSG_CENUM: - printf("### got cenum\n"); - { - int len; - ipcClient *clients = IPC_GetClients(&len); - if (clients) { - constCharPtr *clist = new constCharPtr[len-1]; - if (clist) { - for (int i = 0; i < len; ++i) { - if (clients + i != client) - clist[i] = clients[i].Name(); - } - IPC_SendMsg(client, new ipcmMessageCLIST(clist, len-1)); - delete[] clist; - } - } - } - break; + } + +#if 0 case IPCM_MSG_FWD: printf("### got fwd\n"); { - const ipcmMessageFWD *fMsg = (const ipcmMessageFWD *) msg; - ipcClient *client = IPC_GetClientByName(fMsg->DestClient()); - ipcMessage *newMsg = new ipcMessage(); - if (fMsg->DestMessage(newMsg) == PR_SUCCESS) - IPC_SendMsg(client, newMsg); } break; default: printf("### got unknown message\n"); } +#endif } }; diff --git a/mozilla/modules/ipc/src/ipcService.cpp b/mozilla/modules/ipc/src/ipcService.cpp index 943c04abcb8..254690e2d5d 100644 --- a/mozilla/modules/ipc/src/ipcService.cpp +++ b/mozilla/modules/ipc/src/ipcService.cpp @@ -35,9 +35,11 @@ * * ***** END LICENSE BLOCK ***** */ +#include "plstr.h" + #include "ipcConfig.h" #include "ipcService.h" -#include "plstr.h" +#include "ipcm.h" static PRBool PR_CALLBACK ipcReleaseMessageObserver(nsHashKey *aKey, void *aData, void* aClosure) @@ -158,15 +160,20 @@ ipcService::SendMessage(PRUint32 clientID, { NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED); - if (clientID != 0) - return NS_ERROR_NOT_IMPLEMENTED; + if (target.Equals(IPCM_TARGET)) { + NS_ERROR("do not try to talk to the IPCM target directly"); + return NS_ERROR_INVALID_ARG; + } + + ipcMessage *msg; + if (clientID) + msg = new ipcmMessageForward(clientID, target, data, dataLen); + else + msg = new ipcMessage(target, data, dataLen); - ipcMessage *msg = new ipcMessage(); if (!msg) return NS_ERROR_OUT_OF_MEMORY; - msg->Init(target, data, dataLen); - mTransport->SendMsg(msg); return NS_OK; } diff --git a/mozilla/modules/ipc/src/ipcTransport.cpp b/mozilla/modules/ipc/src/ipcTransport.cpp index 67e08cac308..4f364c52af1 100644 --- a/mozilla/modules/ipc/src/ipcTransport.cpp +++ b/mozilla/modules/ipc/src/ipcTransport.cpp @@ -164,21 +164,25 @@ ipcTransport::Connect() } void -ipcTransport::OnMsgAvailable(const ipcMessage *msg) +ipcTransport::OnMsgAvailable(const ipcMessage *rawMsg) { - LOG((">>> ipcTransport::OnMsgAvailable [dataLen=%u]\n", msg->DataLen())); + LOG((">>> ipcTransport::OnMsgAvailable [dataLen=%u]\n", rawMsg->DataLen())); // // all IPCM messages stop here. // - if (msg->Target().Equals(IPCM_TARGET)) { + if (rawMsg->Target().Equals(IPCM_TARGET)) { // // check for startup PING // if (!mHaveConnection) { - if (IPCM_GetMsgType(msg) == IPCM_MSG_PING) { + if (IPCM_GetMsgType(rawMsg) == IPCM_MSG_TYPE_CLIENT_ID) { LOG((">>> connection established!\n")); mHaveConnection = PR_TRUE; + /* XXX inform the service that we now know our ID + ipcMessageCast msg(rawMsg); + msg->ClientID(); + */ // // move messages off the delayed queue // @@ -193,7 +197,7 @@ ipcTransport::OnMsgAvailable(const ipcMessage *msg) } } else if (mObserver) - mObserver->OnMsgAvailable(msg); + mObserver->OnMsgAvailable(rawMsg); } void @@ -202,17 +206,12 @@ ipcTransport::OnStartRequest(nsIRequest *req) nsresult status; req->GetStatus(&status); - if (NS_SUCCEEDED(status) && !mHaveConnection && !mSentInitialMsgs) { + if (NS_SUCCEEDED(status) && !mHaveConnection && !mSentHello) { // - // send "startup messages" + // send CLIENT_HELLO; expect CLIENT_ID in response. // - // PING - expect a PING in response to this message - // CNAME - expect nothing in response to this message - // - SendMsg_Internal(new ipcmMessagePING()); - SendMsg_Internal(new ipcmMessageCNAME("test-app")); // XXX need real client name - - mSentInitialMsgs = PR_TRUE; + SendMsg_Internal(new ipcmMessageClientHello("test-app")); // XXX need real client name + mSentHello = PR_TRUE; } } diff --git a/mozilla/modules/ipc/src/ipcTransport.h b/mozilla/modules/ipc/src/ipcTransport.h index e9ac2ef0de0..f9ca0f8b086 100644 --- a/mozilla/modules/ipc/src/ipcTransport.h +++ b/mozilla/modules/ipc/src/ipcTransport.h @@ -126,7 +126,7 @@ public: , mObserver(nsnull) , mFD(nsnull) , mWriteSuspended(PR_FALSE) - , mSentInitialMsgs(PR_FALSE) + , mSentHello(PR_FALSE) , mHaveConnection(PR_FALSE) , mConnectionAttemptCount(0) { } @@ -169,7 +169,7 @@ private: nsCString mSocketPath; PRFileDesc *mFD; PRPackedBool mWriteSuspended; - PRPackedBool mSentInitialMsgs; + PRPackedBool mSentHello; PRPackedBool mHaveConnection; PRUint8 mConnectionAttemptCount; };