From 773ce670f1ebb3057fd5990399de5cbada969294 Mon Sep 17 00:00:00 2001 From: "darin%netscape.com" Date: Mon, 4 Nov 2002 06:35:32 +0000 Subject: [PATCH] implement ADD_NAME and DEL_NAME messages. implement part of ADD_TARGET and DEL_TARGET messages. git-svn-id: svn://10.0.0.236/trunk@132926 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/modules/ipc/common/Makefile.in | 1 + .../ipc/common/{ipcQueue.h => ipcList.h} | 75 ++++++++++++++++--- .../ipc/common/ipcMessagePrimitives.cpp | 9 +++ .../modules/ipc/common/ipcMessagePrimitives.h | 16 ++++ mozilla/modules/ipc/common/ipcMessageQ.h | 4 +- mozilla/modules/ipc/common/ipcStringList.cpp | 43 +++++++++++ mozilla/modules/ipc/common/ipcStringList.h | 68 +++++++++++++++++ mozilla/modules/ipc/common/ipcm.cpp | 5 ++ mozilla/modules/ipc/common/ipcm.h | 69 ++++++++++++++++- mozilla/modules/ipc/daemon/ipcClient.cpp | 23 ++++-- mozilla/modules/ipc/daemon/ipcClient.h | 22 +++--- .../modules/ipc/daemon/ipcCommandModule.cpp | 45 +++++++++-- mozilla/modules/ipc/daemon/ipcd.cpp | 2 +- mozilla/modules/ipc/src/ipcService.cpp | 30 +++++++- mozilla/modules/ipc/src/ipcService.h | 3 +- 15 files changed, 374 insertions(+), 41 deletions(-) rename mozilla/modules/ipc/common/{ipcQueue.h => ipcList.h} (68%) create mode 100644 mozilla/modules/ipc/common/ipcStringList.cpp create mode 100644 mozilla/modules/ipc/common/ipcStringList.h diff --git a/mozilla/modules/ipc/common/Makefile.in b/mozilla/modules/ipc/common/Makefile.in index 74da59ec62b..123074ba17d 100644 --- a/mozilla/modules/ipc/common/Makefile.in +++ b/mozilla/modules/ipc/common/Makefile.in @@ -56,6 +56,7 @@ CPPSRCS = \ ipcLog.cpp \ ipcMessage.cpp \ ipcMessagePrimitives.cpp \ + ipcStringList.cpp \ ipcm.cpp EXPORTS = \ diff --git a/mozilla/modules/ipc/common/ipcQueue.h b/mozilla/modules/ipc/common/ipcList.h similarity index 68% rename from mozilla/modules/ipc/common/ipcQueue.h rename to mozilla/modules/ipc/common/ipcList.h index 64b7ecaddb8..afd38ece455 100644 --- a/mozilla/modules/ipc/common/ipcQueue.h +++ b/mozilla/modules/ipc/common/ipcList.h @@ -35,27 +35,47 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef ipcQueue_h__ -#define ipcQueue_h__ +#ifndef ipcList_h__ +#define ipcList_h__ #include "prtypes.h" //----------------------------------------------------------------------------- -// simple queue of objects +// simple list of singly-linked objects. class T must have the following +// structure: +// +// class T { +// ... +// public: +// T *mNext; +// }; +// +// objects added to the list must be allocated with operator new. //----------------------------------------------------------------------------- template -class ipcQueue +class ipcList { public: - ipcQueue() + ipcList() : mHead(NULL) , mTail(NULL) { } - ~ipcQueue() { DeleteAll(); } + ~ipcList() { DeleteAll(); } // - // appends msg to the end of the queue. caller loses ownership of |msg|. + // prepends obj at the beginning of the list. + // + void Prepend(T *obj) + { + obj->mNext = mHead; + mHead = obj; + if (!mTail) + mTail = mHead; + } + + // + // appends obj to the end of the list. // void Append(T *obj) { @@ -68,6 +88,17 @@ public: mTail = mHead = obj; } + // + // inserts b into the list after a. + // + void InsertAfter(T *a, T *b) + { + b->mNext = a->mNext; + a->mNext = b; + if (mTail == a) + mTail = b; + } + // // removes first element w/o deleting it // @@ -77,6 +108,19 @@ public: AdvanceHead(); } + // + // removes element after the given element w/o deleting it + // + void RemoveAfter(T *obj) + { + T *rej = obj->mNext; + if (rej) { + obj->mNext = rej->mNext; + if (rej == mTail) + mTail = obj; + } + } + // // deletes first element // @@ -89,6 +133,18 @@ public: } } + // + // deletes element after the given element + // + void DeleteAfter(T *obj) + { + T *rej = obj->mNext; + if (rej) { + RemoveAfter(obj); + delete rej; + } + } + // // deletes all elements // @@ -99,9 +155,10 @@ public: } T *First() { return mHead; } + T *Last() { return mTail; } PRBool IsEmpty() { return mHead == NULL; } -private: +protected: void AdvanceHead() { mHead = mHead->mNext; @@ -113,4 +170,4 @@ private: T *mTail; }; -#endif // !ipcQueue_h__ +#endif // !ipcList_h__ diff --git a/mozilla/modules/ipc/common/ipcMessagePrimitives.cpp b/mozilla/modules/ipc/common/ipcMessagePrimitives.cpp index 49a7645c44f..48981422036 100644 --- a/mozilla/modules/ipc/common/ipcMessagePrimitives.cpp +++ b/mozilla/modules/ipc/common/ipcMessagePrimitives.cpp @@ -47,3 +47,12 @@ ipcMessage_DWORD_STR::ipcMessage_DWORD_STR(const nsID &target, SetData(0, (char *) &first, sizeof(first)); SetData(sizeof(first), second, sLen + 1); } + +ipcMessage_DWORD_ID::ipcMessage_DWORD_ID(const nsID &target, + PRUint32 first, + const nsID &second) +{ + Init(target, NULL, sizeof(first) + sizeof(nsID)); + SetData(0, (char *) &first, sizeof(first)); + SetData(sizeof(first), (char *) &second, sizeof(nsID)); +} diff --git a/mozilla/modules/ipc/common/ipcMessagePrimitives.h b/mozilla/modules/ipc/common/ipcMessagePrimitives.h index 7765bde6be2..cc795c41dbe 100644 --- a/mozilla/modules/ipc/common/ipcMessagePrimitives.h +++ b/mozilla/modules/ipc/common/ipcMessagePrimitives.h @@ -90,4 +90,20 @@ public: } }; +class ipcMessage_DWORD_ID : public ipcMessage +{ +public: + ipcMessage_DWORD_ID(const nsID &target, PRUint32 first, const nsID &second); + + PRUint32 First() const + { + return ((PRUint32 *) Data())[0]; + } + + const nsID &Second() const + { + return * (const nsID *) (Data() + sizeof(PRUint32)); + } +}; + #endif // !ipcMessagePrimitives_h__ diff --git a/mozilla/modules/ipc/common/ipcMessageQ.h b/mozilla/modules/ipc/common/ipcMessageQ.h index fcf2cdd49df..d372713e676 100644 --- a/mozilla/modules/ipc/common/ipcMessageQ.h +++ b/mozilla/modules/ipc/common/ipcMessageQ.h @@ -39,8 +39,8 @@ #define ipcMessageQ_h__ #include "ipcMessage.h" -#include "ipcQueue.h" +#include "ipcList.h" -typedef ipcQueue ipcMessageQ; +typedef ipcList ipcMessageQ; #endif // !ipcMessageQ_h__ diff --git a/mozilla/modules/ipc/common/ipcStringList.cpp b/mozilla/modules/ipc/common/ipcStringList.cpp new file mode 100644 index 00000000000..91c7f88cb27 --- /dev/null +++ b/mozilla/modules/ipc/common/ipcStringList.cpp @@ -0,0 +1,43 @@ +#include "ipcStringList.h" + +void * +ipcStringNode::operator new(size_t size, const char *str) CPP_THROW_NEW +{ + int len = strlen(str); + + size += len; + + ipcStringNode *node = (ipcStringNode *) ::operator new(size); + if (!node) + return NULL; + + node->mNext = NULL; + memcpy(node->mData, str, len); + node->mData[len] = '\0'; + + return node; +} + +ipcStringNode * +ipcStringList::FindNode(ipcStringNode *node, const char *str) +{ + while (node) { + if (node->Equals(str)) + return node; + node = node->mNext; + } + return NULL; +} + +ipcStringNode * +ipcStringList::FindNodeBefore(ipcStringNode *node, const char *str) +{ + ipcStringNode *prev = NULL; + while (node) { + if (node->Equals(str)) + return prev; + prev = node; + node = node->mNext; + } + return NULL; +} diff --git a/mozilla/modules/ipc/common/ipcStringList.h b/mozilla/modules/ipc/common/ipcStringList.h new file mode 100644 index 00000000000..cde6b5a14b2 --- /dev/null +++ b/mozilla/modules/ipc/common/ipcStringList.h @@ -0,0 +1,68 @@ +#ifndef ipcStringList_h__ +#define ipcStringList_h__ + +#include +#include "plstr.h" +#include "ipcList.h" + +//----------------------------------------------------------------------------- +// string node +//----------------------------------------------------------------------------- + +class ipcStringNode +{ +public: + const char *Value() const { return mData; } + + PRBool Equals(const char *val) const { return strcmp(mData, val) == 0; } + PRBool EqualsIgnoreCase(const char *val) const { return PL_strcasecmp(mData, val) == 0; } + + class ipcStringNode *mNext; +private: + void *operator new(size_t size, const char *str) CPP_THROW_NEW; + + // this is actually bigger + char mData[1]; + + friend class ipcStringList; +}; + +//----------------------------------------------------------------------------- +// singly-linked list of strings +//----------------------------------------------------------------------------- + +class ipcStringList : public ipcList +{ +public: + typedef ipcList Super; + + void Prepend(const char *str) + { + Super::Prepend(new (str) ipcStringNode()); + } + + void Append(const char *str) + { + Super::Append(new (str) ipcStringNode()); + } + + const ipcStringNode *Find(const char *str) const + { + return FindNode(mHead, str); + } + + void FindAndDelete(const char *str) + { + ipcStringNode *node = FindNodeBefore(mHead, str); + if (node) + DeleteAfter(node); + else + DeleteFirst(); + } + +private: + static ipcStringNode *FindNode (ipcStringNode *head, const char *str); + static ipcStringNode *FindNodeBefore(ipcStringNode *head, const char *str); +}; + +#endif // !ipcStringList_h__ diff --git a/mozilla/modules/ipc/common/ipcm.cpp b/mozilla/modules/ipc/common/ipcm.cpp index af922402da2..fa755d8dffe 100644 --- a/mozilla/modules/ipc/common/ipcm.cpp +++ b/mozilla/modules/ipc/common/ipcm.cpp @@ -75,6 +75,11 @@ 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 ipcmMessageClientInfo::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_INFO; +const PRUint32 ipcmMessageClientAddName::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ADD_NAME; +const PRUint32 ipcmMessageClientDelName::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_DEL_NAME; +const PRUint32 ipcmMessageClientAddTarget::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ADD_TARGET; +const PRUint32 ipcmMessageClientDelTarget::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_DEL_TARGET; const PRUint32 ipcmMessageQueryClientByName::MSG_TYPE = IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME; const PRUint32 ipcmMessageForward::MSG_TYPE = IPCM_MSG_TYPE_FORWARD; diff --git a/mozilla/modules/ipc/common/ipcm.h b/mozilla/modules/ipc/common/ipcm.h index e6fae729cc3..b1478f18fec 100644 --- a/mozilla/modules/ipc/common/ipcm.h +++ b/mozilla/modules/ipc/common/ipcm.h @@ -59,7 +59,6 @@ enum { 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 }; @@ -112,7 +111,9 @@ public: // // IPCM_MSG_TYPE_ERROR // -// thie message may be sent from the daemon in response to a query. +// this message may be sent from the daemon in place of an expected +// result. e.g., if a query fails, the daemon will send an error +// message to indicate the failure. // class ipcmMessageError : public ipcMessage_DWORD_DWORD { @@ -165,6 +166,66 @@ public: PRUint32 ClientID() const { return Second(); } }; +// +// IPCM_MSG_TYPE_CLIENT_INFO +// + +// +// IPCM_MSG_TYPE_CLIENT_ADD_NAME +// +class ipcmMessageClientAddName : public ipcMessage_DWORD_STR +{ +public: + static const PRUint32 MSG_TYPE; + + ipcmMessageClientAddName(const char *name) + : ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {} + + const char *Name() const { return Second(); } +}; + +// +// IPCM_MSG_TYPE_CLIENT_DEL_NAME +// +class ipcmMessageClientDelName : public ipcMessage_DWORD_STR +{ +public: + static const PRUint32 MSG_TYPE; + + ipcmMessageClientDelName(const char *name) + : ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {} + + const char *Name() const { return Second(); } +}; + +// +// IPCM_MSG_TYPE_CLIENT_ADD_TARGET +// +class ipcmMessageClientAddTarget : public ipcMessage_DWORD_ID +{ +public: + static const PRUint32 MSG_TYPE; + + ipcmMessageClientAddTarget(const nsID &target) + : ipcMessage_DWORD_ID(IPCM_TARGET, MSG_TYPE, target) {} + + const nsID &Target() const { return Second(); } +}; + +// +// IPCM_MSG_TYPE_CLIENT_DEL_TARGET +// +class ipcmMessageClientDelTarget : public ipcMessage_DWORD_ID +{ +public: + static const PRUint32 MSG_TYPE; + + ipcmMessageClientDelTarget(const nsID &target) + : ipcMessage_DWORD_ID(IPCM_TARGET, MSG_TYPE, target) {} + + const nsID &Target() const { return Second(); } +}; + // // IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME // @@ -187,7 +248,9 @@ public: // 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. +// will forward the contained message to the specified client. there +// is no guarantee that the message will be forwarded, and no error will +// be sent to the sender on failure. // class ipcmMessageForward : public ipcMessage { diff --git a/mozilla/modules/ipc/daemon/ipcClient.cpp b/mozilla/modules/ipc/daemon/ipcClient.cpp index b06d3ecd52a..f46a1778ee9 100644 --- a/mozilla/modules/ipc/daemon/ipcClient.cpp +++ b/mozilla/modules/ipc/daemon/ipcClient.cpp @@ -56,7 +56,6 @@ int ipcClient::Init() { mID = ++gLastID; - mName = NULL; mInMsg = new ipcMessage(); mSendOffset = 0; @@ -71,11 +70,10 @@ ipcClient::Init() int ipcClient::Finalize() { - if (mName) - PL_strfree(mName); if (mInMsg) delete mInMsg; mOutMsgQ.DeleteAll(); + mNames.DeleteAll(); return 0; } @@ -152,13 +150,22 @@ ipcClient::Process(PRFileDesc *fd, int poll_flags) } void -ipcClient::SetName(const char *name) +ipcClient::AddName(const char *name) { - LOG(("setting client name to \"%s\"\n", name)); + LOG(("adding client name: %s\n", name)); - if (mName) - PL_strfree(mName); - mName = PL_strdup(name); + if (HasName(name)) + return; + + mNames.Append(name); +} + +void +ipcClient::DelName(const char *name) +{ + LOG(("deleting client name: %s\n", name)); + + mNames.FindAndDelete(name); } // diff --git a/mozilla/modules/ipc/daemon/ipcClient.h b/mozilla/modules/ipc/daemon/ipcClient.h index f9122ab8574..a35e675aa08 100644 --- a/mozilla/modules/ipc/daemon/ipcClient.h +++ b/mozilla/modules/ipc/daemon/ipcClient.h @@ -38,8 +38,9 @@ #ifndef ipcClient_h__ #define ipcClient_h__ -#include "ipcMessageQ.h" #include "prio.h" +#include "ipcMessageQ.h" +#include "ipcStringList.h" class ipcMessage; @@ -58,10 +59,12 @@ public: int Finalize(); int Process(PRFileDesc *fd, int poll_flags); - int ID() const { return mID; } - const char *Name() const { return mName; } + int ID() const { return mID; } + + void AddName(const char *name); + void DelName(const char *name); + PRBool HasName(const char *name) const { return mNames.Find(name) != NULL; } - void SetName(const char *name); void EnqueueOutboundMsg(ipcMessage *msg) { mOutMsgQ.Append(msg); } private: @@ -69,13 +72,14 @@ private: static int gLastID; - int mID; - char *mName; - ipcMessage *mInMsg; // buffer for incoming message - ipcMessageQ mOutMsgQ; // outgoing message queue + int mID; + ipcStringList mNames; + //ipcList mTargets; + ipcMessage *mInMsg; // buffer for incoming message + ipcMessageQ mOutMsgQ; // outgoing message queue // keep track of the amount of the first message sent - PRUint32 mSendOffset; + PRUint32 mSendOffset; }; #endif // !ipcClient_h__ diff --git a/mozilla/modules/ipc/daemon/ipcCommandModule.cpp b/mozilla/modules/ipc/daemon/ipcCommandModule.cpp index dfa53d8d502..8a9db3e0c85 100644 --- a/mozilla/modules/ipc/daemon/ipcCommandModule.cpp +++ b/mozilla/modules/ipc/daemon/ipcCommandModule.cpp @@ -70,11 +70,45 @@ public: ipcMessageCast msg(rawMsg); const char *name = msg->PrimaryName(); if (name) - client->SetName(name); + client->AddName(name); IPC_SendMsg(client, new ipcmMessageClientID(client->ID())); } + void OnClientAddName(ipcClient *client, const ipcMessage *rawMsg) + { + LOG(("got CLIENT_ADD_NAME\n")); + + ipcMessageCast msg(rawMsg); + const char *name = msg->Name(); + if (name) + client->AddName(name); + } + + void OnClientDelName(ipcClient *client, const ipcMessage *rawMsg) + { + LOG(("got CLIENT_DEL_NAME\n")); + + ipcMessageCast msg(rawMsg); + const char *name = msg->Name(); + if (name) + client->DelName(name); + } + + void OnClientAddTarget(ipcClient *client, const ipcMessage *rawMsg) + { + LOG(("got CLIENT_ADD_TARGET\n")); + + // XXX implement me + } + + void OnClientDelTarget(ipcClient *client, const ipcMessage *rawMsg) + { + LOG(("got CLIENT_DEL_TARGET\n")); + + // XXX implement me + } + void OnQueryClientByName(ipcClient *client, const ipcMessage *rawMsg) { LOG(("got QUERY_CLIENT_BY_NAME\n")); @@ -127,13 +161,12 @@ public: &ipcCommandModule::OnClientHello, NULL, // CLIENT_ID NULL, // CLIENT_INFO - NULL, // CLIENT_ADD_NAME - NULL, // CLIENT_DEL_NAME - NULL, // CLIENT_ADD_TARGET - NULL, // CLIENT_DEL_TARGET + &ipcCommandModule::OnClientAddName, + &ipcCommandModule::OnClientDelName, + &ipcCommandModule::OnClientAddTarget, + &ipcCommandModule::OnClientDelTarget, &ipcCommandModule::OnQueryClientByName, NULL, // QUERY_CLIENT_INFO - NULL, // QUERY_FAILED &ipcCommandModule::OnForward, }; diff --git a/mozilla/modules/ipc/daemon/ipcd.cpp b/mozilla/modules/ipc/daemon/ipcd.cpp index 36015b473e6..6e89b99c1ee 100644 --- a/mozilla/modules/ipc/daemon/ipcd.cpp +++ b/mozilla/modules/ipc/daemon/ipcd.cpp @@ -404,7 +404,7 @@ ipcClient *IPC_GetClientByName(const char *name) { // linear search OK since number of clients should be small for (int i = 1; i < poll_fd_count; ++i) { - if (strcmp(clients[i].Name(), name) == 0) + if (clients[i].HasName(name)) return &clients[i]; } return NULL; diff --git a/mozilla/modules/ipc/src/ipcService.cpp b/mozilla/modules/ipc/src/ipcService.cpp index 4c61a53855a..ec225b97745 100644 --- a/mozilla/modules/ipc/src/ipcService.cpp +++ b/mozilla/modules/ipc/src/ipcService.cpp @@ -205,13 +205,25 @@ ipcService::GetClientID(PRUint32 *clientID) NS_IMETHODIMP ipcService::AddClientAlias(const nsACString &alias) { - return NS_ERROR_NOT_IMPLEMENTED; + NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED); + + ipcMessage *msg = new ipcmMessageClientAddName(PromiseFlatCString(alias).get()); + if (!msg) + return NS_ERROR_OUT_OF_MEMORY; + + return mTransport->SendMsg(msg); } NS_IMETHODIMP ipcService::RemoveClientAlias(const nsACString &alias) { - return NS_ERROR_NOT_IMPLEMENTED; + NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED); + + ipcMessage *msg = new ipcmMessageClientDelName(PromiseFlatCString(alias).get()); + if (!msg) + return NS_ERROR_OUT_OF_MEMORY; + + return mTransport->SendMsg(msg); } NS_IMETHODIMP @@ -262,19 +274,33 @@ ipcService::SetClientObserver(PRUint32 clientID, NS_IMETHODIMP ipcService::SetMessageObserver(const nsID &target, ipcIMessageObserver *observer) { + NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED); + nsIDKey key(target); + PRBool sendAdd = PR_TRUE; ipcIMessageObserver *cobs = (ipcIMessageObserver *) mObserverDB.Get(&key); if (cobs) { NS_RELEASE(cobs); if (!observer) { mObserverDB.Remove(&key); + // + // send CLIENT_DEL_TARGET + // + mTransport->SendMsg(new ipcmMessageClientDelTarget(target)); return NS_OK; } + sendAdd = PR_FALSE; } if (observer) { NS_ADDREF(observer); mObserverDB.Put(&key, observer); + if (sendAdd) { + // + // send CLIENT_ADD_TARGET + // + mTransport->SendMsg(new ipcmMessageClientAddTarget(target)); + } } return NS_OK; } diff --git a/mozilla/modules/ipc/src/ipcService.h b/mozilla/modules/ipc/src/ipcService.h index c58496c484a..84150aac5a8 100644 --- a/mozilla/modules/ipc/src/ipcService.h +++ b/mozilla/modules/ipc/src/ipcService.h @@ -40,6 +40,7 @@ #include "ipcIService.h" #include "ipcTransport.h" +#include "ipcList.h" #include "ipcMessage.h" #include "ipcMessageQ.h" #include "nsIRequest.h" @@ -90,7 +91,7 @@ public: nsCOMPtr mObserver; }; -typedef ipcQueue ipcClientQueryQ; +typedef ipcList ipcClientQueryQ; //---------------------------------------------------------------------------- // ipcService