Changeset 103378 in vbox
- Timestamp:
- Feb 15, 2024 8:45:24 AM (12 months ago)
- svn:sync-xref-src-repo-rev:
- 161696
- Location:
- trunk/src/libs/xpcom18a4
- Files:
-
- 2 deleted
- 9 edited
- 1 copied
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/Makefile.kmk
r103331 r103378 846 846 ipc/ipcd/daemon/src/ipcd.cpp \ 847 847 ipc/ipcd/daemon/src/ipcClient.cpp \ 848 ipc/ipcd/daemon/src/ipcCommandModule.cpp \ 849 ipc/ipcd/daemon/src/ipcdUnix.cpp 848 ipc/ipcd/daemon/src/ipcCommandModule.cpp 850 849 VBoxXPCOMIPCD_LDFLAGS.darwin = -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxXPCOMIPCD.dylib 851 850 VBoxXPCOMIPCD_LIBS = \ -
trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp
r103331 r103378 36 36 * ***** END LICENSE BLOCK ***** */ 37 37 #define LOG_GROUP LOG_GROUP_IPC 38 #include <iprt/asm.h> 38 39 #include <iprt/assert.h> 39 40 #include <iprt/errcore.h> … … 42 43 43 44 #include "ipcClient.h" 44 #include "ipcMessage.h"45 45 #include "ipcd.h" 46 46 #include "ipcm.h" 47 47 48 PRUint32 ipcClient::gLastID = 0; 48 static volatile uint32_t g_idClientLast = 0; 49 49 50 50 51 // … … 54 55 // - object's memory has already been zero'd out. 55 56 // 56 void 57 ipcClient::Init(uint32_t idPoll, RTSOCKET hSock) 58 { 59 mID = ++gLastID; 57 DECLHIDDEN(int) ipcdClientInit(PIPCDCLIENT pThis, PIPCDSTATE pIpcd, uint32_t idPoll, RTSOCKET hSock) 58 { 59 pThis->idClient = ASMAtomicIncU32(&g_idClientLast); 60 60 61 61 // every client must be able to handle IPCM messages. 62 mTargets.Append(IPCM_TARGET); 63 64 m_hSock = hSock; 65 m_idPoll = idPoll; 66 m_fUsed = true; 62 pThis->mTargets.Append(IPCM_TARGET); 63 64 pThis->pIpcd = pIpcd; 65 pThis->hSock = hSock; 66 pThis->idPoll = idPoll; 67 pThis->fPollEvts = RTPOLL_EVT_READ; 68 pThis->fUsed = true; 69 70 RTListInit(&pThis->LstMsgsOut); 67 71 68 72 // although it is tempting to fire off the NotifyClientUp event at this 69 73 // time, we must wait until the client sends us a CLIENT_HELLO event. 70 74 // see ipcCommandModule::OnClientHello. 75 76 return IPCMsgInit(&pThis->MsgIn, 0 /*cbBuf*/); 71 77 } 72 78 … … 74 80 // called when this client context is going away 75 81 // 76 void 77 ipcClient::Finalize() 78 { 79 RTSocketClose(m_hSock);80 m_hSock = NIL_RTSOCKET; 81 82 IPC_NotifyClientDown(this); 83 84 mNames.DeleteAll();85 mTargets.DeleteAll(); 86 87 mInMsg.Reset();88 mOutMsgQ.DeleteAll(); 89 m_fUsed = false;90 } 91 92 void 93 ipcClient::AddName(const char *name)94 { 95 LogFlowFunc(("adding client name: %s\n", name));96 97 if ( HasName(name))82 DECLHIDDEN(void) ipcdClientDestroy(PIPCDCLIENT pThis) 83 { 84 RTSocketClose(pThis->hSock); 85 pThis->hSock = NIL_RTSOCKET; 86 87 IPC_NotifyClientDown(pThis); 88 89 pThis->mNames.DeleteAll(); 90 pThis->mTargets.DeleteAll(); 91 92 IPCMsgFree(&pThis->MsgIn, false /*fFreeStruct*/); 93 pThis->fUsed = false; 94 95 /** @todo Free all outgoing messages. */ 96 } 97 98 99 DECLHIDDEN(void) ipcdClientAddName(PIPCDCLIENT pThis, const char *pszName) 100 { 101 LogFlowFunc(("adding client name: %s\n", pszName)); 102 103 if (ipcdClientHasName(pThis, pszName)) 98 104 return; 99 105 100 mNames.Append(name);101 } 102 103 PRBool 104 ipcClient::DelName(const char *name)105 { 106 LogFlowFunc(("deleting client name: %s\n", name));107 108 return mNames.FindAndDelete(name);109 } 110 111 void 112 ipcClient::AddTarget(const nsID &target)106 pThis->mNames.Append(pszName); 107 } 108 109 110 DECLHIDDEN(bool) ipcdClientDelName(PIPCDCLIENT pThis, const char *pszName) 111 { 112 LogFlowFunc(("deleting client name: %s\n", pszName)); 113 114 return pThis->mNames.FindAndDelete(pszName); 115 } 116 117 118 DECLHIDDEN(void) ipcdClientAddTarget(PIPCDCLIENT pThis, const nsID *target) 113 119 { 114 120 LogFlowFunc(("adding client target\n")); 115 121 116 if ( HasTarget(target))122 if (ipcdClientHasTarget(pThis, target)) 117 123 return; 118 124 119 mTargets.Append(target);120 } 121 122 PRBool 123 ipcClient::DelTarget(const nsID &target)125 pThis->mTargets.Append(*target); 126 } 127 128 129 DECLHIDDEN(bool) ipcdClientDelTarget(PIPCDCLIENT pThis, const nsID *target) 124 130 { 125 131 LogFlowFunc(("deleting client target\n")); … … 128 134 // cannot remove the IPCM target 129 135 // 130 if (!target.Equals(IPCM_TARGET)) 131 return mTargets.FindAndDelete(target); 132 133 return PR_FALSE; 134 } 135 136 // 137 // called to process a client socket 138 // 139 // params: 140 // poll_flags - the state of the client socket 141 // 142 // return: 143 // 0 - to end session with this client 144 // PR_POLL_READ - to wait for the client socket to become readable 145 // PR_POLL_WRITE - to wait for the client socket to become writable 146 // 147 uint32_t 148 ipcClient::Process(uint32_t inFlags) 149 { 150 if (inFlags & RTPOLL_EVT_ERROR) 136 if (!target->Equals(IPCM_TARGET)) 137 return pThis->mTargets.FindAndDelete(*target); 138 139 return false; 140 } 141 142 // 143 // called to write out any messages from the outgoing queue. 144 // 145 static int ipcdClientWriteMsgs(PIPCDCLIENT pThis) 146 { 147 while (!RTListIsEmpty(&pThis->LstMsgsOut)) 148 { 149 PIPCMSG pMsg = RTListGetFirst(&pThis->LstMsgsOut, IPCMSG, NdMsg); 150 const uint8_t *pbBuf = (const uint8_t *)IPCMsgGetBuf(pMsg); 151 size_t cbBuf = IPCMsgGetSize(pMsg); 152 153 if (pThis->offMsgOutBuf) 154 { 155 Assert(cbBuf > pThis->offMsgOutBuf); 156 pbBuf += pThis->offMsgOutBuf; 157 cbBuf -= pThis->offMsgOutBuf; 158 } 159 160 size_t cbWritten = 0; 161 int vrc = RTSocketWriteNB(pThis->hSock, pbBuf, cbBuf, &cbWritten); 162 if (vrc == VINF_SUCCESS) 163 { /* likely */ Assert(cbWritten > 0); } 164 else 165 { 166 Assert( RT_FAILURE(vrc) 167 || (vrc == VINF_TRY_AGAIN && cbWritten == 0)); 168 break; 169 } 170 171 LogFlowFunc(("wrote %d bytes\n", cbWritten)); 172 173 if (cbWritten == cbBuf) 174 { 175 RTListNodeRemove(&pMsg->NdMsg); 176 IPC_PutMsgIntoCache(pThis->pIpcd, pMsg); 177 pThis->offMsgOutBuf = 0; 178 } 179 else 180 pThis->offMsgOutBuf += cbWritten; 181 } 182 183 return 0; 184 } 185 186 DECLHIDDEN(uint32_t) ipcdClientProcess(PIPCDCLIENT pThis, uint32_t fPollFlags) 187 { 188 if (fPollFlags & RTPOLL_EVT_ERROR) 151 189 { 152 190 LogFlowFunc(("client socket appears to have closed\n")); … … 154 192 } 155 193 156 // expect to wait for more data 157 uint32_t outFlags = RTPOLL_EVT_READ; 158 159 if (inFlags & RTPOLL_EVT_READ) { 194 uint32_t fOutFlags = RTPOLL_EVT_READ; 195 196 if (fPollFlags & RTPOLL_EVT_READ) { 160 197 LogFlowFunc(("client socket is now readable\n")); 161 198 162 char buf[_1K];199 uint8_t abBuf[_1K]; 163 200 size_t cbRead = 0; 164 int vrc = RTSocketReadNB( m_hSock, &buf[0], sizeof(buf), &cbRead);201 int vrc = RTSocketReadNB(pThis->hSock, &abBuf[0], sizeof(abBuf), &cbRead); 165 202 Assert(vrc != VINF_TRY_AGAIN); 166 203 … … 168 205 return 0; // cancel connection 169 206 170 const char *ptr = buf;207 const uint8_t *pb = abBuf; 171 208 while (cbRead) 172 209 { 173 PRUint32 nread; 174 PRBool complete; 175 176 if (mInMsg.ReadFrom(ptr, PRUint32(cbRead), &nread, &complete) == PR_FAILURE) { 210 size_t cbProcessed; 211 bool fDone; 212 213 int vrc = IPCMsgReadFrom(&pThis->MsgIn, pb, cbRead, &cbProcessed, &fDone); 214 if (RT_FAILURE(vrc)) 215 { 177 216 LogFlowFunc(("message appears to be malformed; dropping client connection\n")); 178 217 return 0; 179 218 } 180 219 181 if ( complete)220 if (fDone) 182 221 { 183 IPC_DispatchMsg( this, &mInMsg);184 mInMsg.Reset();222 IPC_DispatchMsg(pThis, &pThis->MsgIn); 223 IPCMsgReset(&pThis->MsgIn); 185 224 } 186 225 187 cbRead -= nread; 188 ptr += nread; 189 } 190 } 191 192 if (inFlags & RTPOLL_EVT_WRITE) { 226 cbRead -= cbProcessed; 227 pb += cbProcessed; 228 } 229 } 230 231 if (fPollFlags & RTPOLL_EVT_WRITE) 232 { 193 233 LogFlowFunc(("client socket is now writable\n")); 194 234 195 if (mOutMsgQ.First()) 196 WriteMsgs(); 197 } 198 199 if (mOutMsgQ.First()) 200 outFlags |= RTPOLL_EVT_WRITE; 201 202 return outFlags; 203 } 204 205 // 206 // called to write out any messages from the outgoing queue. 207 // 208 int 209 ipcClient::WriteMsgs() 210 { 211 while (mOutMsgQ.First()) 212 { 213 const char *buf = (const char *) mOutMsgQ.First()->MsgBuf(); 214 PRInt32 bufLen = (PRInt32) mOutMsgQ.First()->MsgLen(); 215 216 if (mSendOffset) 217 { 218 buf += mSendOffset; 219 bufLen -= mSendOffset; 220 } 221 222 size_t cbWritten = 0; 223 int vrc = RTSocketWriteNB(m_hSock, buf, bufLen, &cbWritten); 224 if (vrc == VINF_SUCCESS) 225 { /* likely */ Assert(cbWritten > 0); } 226 else 227 { 228 Assert( RT_FAILURE(vrc) 229 || (vrc == VINF_TRY_AGAIN && cbWritten == 0)); 230 break; 231 } 232 233 LogFlowFunc(("wrote %d bytes\n", cbWritten)); 234 235 if (cbWritten == bufLen) 236 { 237 mOutMsgQ.DeleteFirst(); 238 mSendOffset = 0; 239 } 240 else 241 mSendOffset += cbWritten; 242 } 243 244 return 0; 245 } 246 235 if (!RTListIsEmpty(&pThis->LstMsgsOut)) 236 ipcdClientWriteMsgs(pThis); 237 } 238 239 if (!RTListIsEmpty(&pThis->LstMsgsOut)) 240 fOutFlags |= RTPOLL_EVT_WRITE; 241 242 return fOutFlags; 243 } -
trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h
r103331 r103378 42 42 #include <iprt/socket.h> 43 43 44 #include "ipcMessageQ.h" 44 #include "ipcMessageNew.h" 45 45 46 #include "ipcStringList.h" 46 47 #include "ipcIDList.h" 47 48 48 //----------------------------------------------------------------------------- 49 // ipcClient 49 50 /** Pointer to the IPCD manager state. */ 51 typedef struct IPCDSTATE *PIPCDSTATE; 52 53 /** 54 * IPC daemon client state. 55 * 56 * @note Treat these as opaque and use the accessor functions below. 57 */ 58 typedef struct IPCDCLIENT 59 { 60 /** Node for the list of clients. */ 61 RTLISTNODE NdClients; 62 /** The owning IPCD state. */ 63 PIPCDSTATE pIpcd; 64 /** Flag whether the client state is currently in use. */ 65 bool fUsed; 66 /** The poll ID for this client. */ 67 uint32_t idPoll; 68 /** Poll event flags */ 69 uint32_t fPollEvts; 70 71 /** Client ID .*/ 72 uint32_t idClient; 73 /** Client socket. */ 74 RTSOCKET hSock; 75 /** The current incoming message. */ 76 IPCMSG MsgIn; 77 /** List of outgoing messages. */ 78 RTLISTANCHOR LstMsgsOut; 79 /** How much of the current message in the output buffer was already sent. */ 80 uint32_t offMsgOutBuf; 81 82 bool fExpectsSyncReply; 83 ipcStringList mNames; 84 ipcIDList mTargets; 85 } IPCDCLIENT; 86 /** Pointer to an IPCD client state. */ 87 typedef IPCDCLIENT *PIPCDCLIENT; 88 /** Pointer to a const IPCD client state. */ 89 typedef const IPCDCLIENT *PCIPCDCLIENT; 90 91 92 DECLINLINE(PIPCDSTATE) ipcdClientGetDaemonState(PCIPCDCLIENT pThis) 93 { 94 return pThis->pIpcd; 95 } 96 97 98 DECLINLINE(uint32_t) ipcdClientGetId(PCIPCDCLIENT pThis) 99 { 100 return pThis->idClient; 101 } 102 103 104 DECLINLINE(void) ipcdClientEnqueueOutboundMsg(PIPCDCLIENT pThis, PIPCMSG pMsg) 105 { 106 RTListAppend(&pThis->LstMsgsOut, &pMsg->NdMsg); 107 } 108 109 DECLINLINE(bool) ipcdClientHasName(PCIPCDCLIENT pThis, const char *pszName) 110 { 111 return pThis->mNames.Find(pszName) != NULL; 112 } 113 114 DECLHIDDEN(void) ipcdClientAddName(PIPCDCLIENT pThis, const char *pszName); 115 116 DECLHIDDEN(bool) ipcdClientDelName(PIPCDCLIENT pThis, const char *pszName); 117 118 DECLINLINE(bool) ipcdClientHasTarget(PCIPCDCLIENT pThis, const nsID *target) 119 { 120 return pThis->mTargets.Find(*target) != NULL; 121 } 122 123 DECLHIDDEN(void) ipcdClientAddTarget(PIPCDCLIENT pThis, const nsID *target); 124 125 DECLHIDDEN(bool) ipcdClientDelTarget(PIPCDCLIENT pThis, const nsID *target); 126 127 DECLHIDDEN(int) ipcdClientInit(PIPCDCLIENT pThis, PIPCDSTATE pIpcd, uint32_t idPoll, RTSOCKET hSock); 128 129 DECLHIDDEN(void) ipcdClientDestroy(PIPCDCLIENT pThis); 130 50 131 // 51 // NOTE: this class is an implementation detail of the IPC daemon. IPC daemon 52 // modules (other than the built-in IPCM module) must not access methods on 53 // this class directly. use the API provided via ipcd.h instead. 54 //----------------------------------------------------------------------------- 132 // called to process a client file descriptor. the value of pollFlags 133 // indicates the state of the socket. 134 // 135 // returns: 136 // 0 - to cancel client connection 137 // RTPOLL_EVT_READ - to poll for a readable socket 138 // RTPOLL_EVT_WRITE - to poll for a writable socket 139 // (both flags) - to poll for either a readable or writable socket 140 // 141 // the socket is non-blocking. 142 // 143 DECLHIDDEN(uint32_t) ipcdClientProcess(PIPCDCLIENT pThis, uint32_t fPollFlags); 55 144 56 class ipcClient 145 DECLINLINE(void) ipcdClientSetExpectsSyncReply(PIPCDCLIENT pThis, bool f) 57 146 { 58 public: 59 /** Node for the list of clients. */ 60 RTLISTNODE NdClients; 61 bool m_fUsed; 62 uint32_t m_idPoll; 63 uint32_t m_fPollEvts; 147 pThis->fExpectsSyncReply = f; 148 } 64 149 65 void Init(uint32_t idPoll, RTSOCKET hSock); 66 void Finalize(); 67 68 PRUint32 ID() const { return mID; } 69 70 void AddName(const char *name); 71 PRBool DelName(const char *name); 72 PRBool HasName(const char *name) const { return mNames.Find(name) != NULL; } 73 74 void AddTarget(const nsID &target); 75 PRBool DelTarget(const nsID &target); 76 PRBool HasTarget(const nsID &target) const { return mTargets.Find(target) != NULL; } 77 78 // list iterators 79 const ipcStringNode *Names() const { return mNames.First(); } 80 const ipcIDNode *Targets() const { return mTargets.First(); } 81 82 // returns primary client name (the one specified in the "client hello" message) 83 const char *PrimaryName() const { return mNames.First() ? mNames.First()->Value() : NULL; } 84 85 void SetExpectsSyncReply(PRBool val) { mExpectsSyncReply = val; } 86 PRBool GetExpectsSyncReply() const { return mExpectsSyncReply; } 87 88 // 89 // called to process a client file descriptor. the value of pollFlags 90 // indicates the state of the socket. 91 // 92 // returns: 93 // 0 - to cancel client connection 94 // RTPOLL_EVT_READ - to poll for a readable socket 95 // RTPOLL_EVT_WRITE - to poll for a writable socket 96 // (both flags) - to poll for either a readable or writable socket 97 // 98 // the socket is non-blocking. 99 // 100 uint32_t Process(uint32_t pollFlags); 101 102 // 103 // on success or failure, this function takes ownership of |msg| and will 104 // delete it when appropriate. 105 // 106 void EnqueueOutboundMsg(ipcMessage *msg) { mOutMsgQ.Append(msg); } 107 108 private: 109 static PRUint32 gLastID; 110 111 PRUint32 mID; 112 ipcStringList mNames; 113 ipcIDList mTargets; 114 PRBool mExpectsSyncReply; 115 116 ipcMessage mInMsg; // buffer for incoming message 117 ipcMessageQ mOutMsgQ; // outgoing message queue 118 119 // keep track of the amount of the first message sent 120 PRUint32 mSendOffset; 121 122 /** Client socket. */ 123 RTSOCKET m_hSock; 124 125 // utility function for writing out messages. 126 int WriteMsgs(); 127 }; 150 DECLINLINE(bool) ipcdClientGetExpectsSyncReply(PCIPCDCLIENT pThis) 151 { 152 return pThis->fExpectsSyncReply; 153 } 128 154 129 155 #endif // !ipcClientUnix_h__ -
trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp
r102249 r103378 40 40 #include "ipcCommandModule.h" 41 41 #include "ipcClient.h" 42 #include "ipcMessage.h" 43 #include "ipcMessageUtils.h" 42 #include "ipcMessageNew.h" 44 43 #include "ipcd.h" 45 44 #include "ipcm.h" … … 47 46 #include <VBox/log.h> 48 47 49 struct ipcCommandModule 50 { 51 typedef void (* MsgHandler)(ipcClient *, const ipcMessage *); 48 typedef void FNIPCMMSGHANDLER(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg); 49 /** Pointer to a IPCM message handler. */ 50 typedef FNIPCMMSGHANDLER *PFNIPCMMSGHANDLER; 51 52 53 DECLINLINE(uint32_t) IPCM_GetType(PCIPCMSG pMsg) 54 { 55 return ((const ipcmMessageHeader *)IPCMsgGetPayload(pMsg))->mType; 56 } 57 58 59 DECLINLINE(uint32_t) IPCM_GetRequestIndex(PCIPCMSG pMsg) 60 { 61 return ((const ipcmMessageHeader *)IPCMsgGetPayload(pMsg))->mRequestIndex; 62 } 63 64 // 65 // message handlers 66 // 67 68 static DECLCALLBACK(void) ipcmOnPing(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) RT_NOTHROW_DEF 69 { 70 Log(("got PING\n")); 71 72 const uint32_t aResp[3] = { IPCM_MSG_ACK_RESULT, IPCM_GetRequestIndex(pMsg), IPCM_OK }; 73 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 74 } 75 76 static DECLCALLBACK(void) ipcmOnClientHello(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) RT_NOTHROW_DEF 77 { 78 Log(("got CLIENT_HELLO\n")); 79 80 const uint32_t aResp[3] = { IPCM_MSG_ACK_CLIENT_ID, IPCM_GetRequestIndex(pMsg), ipcdClientGetId(pIpcClient) }; 81 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 52 82 53 83 // 54 // helpers 84 // NOTE: it would almost make sense for this notification to live 85 // in the transport layer code. however, clients expect to receive 86 // a CLIENT_ID as the first message following a CLIENT_HELLO, so we 87 // must not allow modules to see a client until after we have sent 88 // the CLIENT_ID message. 55 89 // 56 57 static char ** 58 BuildStringArray(const ipcStringNode *nodes) 59 { 60 size_t count = 0; 61 62 const ipcStringNode *node; 63 64 for (node = nodes; node; node = node->mNext) 65 count++; 66 67 char **strs = (char **) malloc((count + 1) * sizeof(char *)); 68 if (!strs) 69 return NULL; 70 71 count = 0; 72 for (node = nodes; node; node = node->mNext, ++count) 73 strs[count] = (char *) node->Value(); 74 strs[count] = 0; 75 76 return strs; 77 } 78 79 static nsID ** 80 BuildIDArray(const ipcIDNode *nodes) 81 { 82 size_t count = 0; 83 84 const ipcIDNode *node; 85 86 for (node = nodes; node; node = node->mNext) 87 count++; 88 89 nsID **ids = (nsID **) calloc(count + 1, sizeof(nsID *)); 90 if (!ids) 91 return NULL; 92 93 count = 0; 94 for (node = nodes; node; node = node->mNext, ++count) 95 ids[count] = (nsID *) &node->Value(); 96 97 return ids; 98 } 99 100 // 101 // message handlers 102 // 103 104 static void 105 OnPing(ipcClient *client, const ipcMessage *rawMsg) 106 { 107 Log(("got PING\n")); 108 109 IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK)); 110 } 111 112 static void 113 OnClientHello(ipcClient *client, const ipcMessage *rawMsg) 114 { 115 Log(("got CLIENT_HELLO\n")); 116 117 IPC_SendMsg(client, new ipcmMessageClientID(IPCM_GetRequestIndex(rawMsg), client->ID())); 118 119 // 120 // NOTE: it would almost make sense for this notification to live 121 // in the transport layer code. however, clients expect to receive 122 // a CLIENT_ID as the first message following a CLIENT_HELLO, so we 123 // must not allow modules to see a client until after we have sent 124 // the CLIENT_ID message. 125 // 126 IPC_NotifyClientUp(client); 127 } 128 129 static void 130 OnClientAddName(ipcClient *client, const ipcMessage *rawMsg) 131 { 132 Log(("got CLIENT_ADD_NAME\n")); 133 134 PRInt32 status = IPCM_OK; 135 PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg); 136 137 ipcMessageCast<ipcmMessageClientAddName> msg(rawMsg); 138 const char *name = msg->Name(); 139 if (name) { 140 ipcClient *result = IPC_GetClientByName(msg->Name()); 141 if (result) { 142 Log((" client with such name already exists (ID = %d)\n", result->ID())); 143 status = IPCM_ERROR_ALREADY_EXISTS; 144 } 145 else 146 client->AddName(name); 147 } 148 else 149 status = IPCM_ERROR_INVALID_ARG; 150 151 IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status)); 152 } 153 154 static void 155 OnClientDelName(ipcClient *client, const ipcMessage *rawMsg) 156 { 157 Log(("got CLIENT_DEL_NAME\n")); 158 159 PRInt32 status = IPCM_OK; 160 PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg); 161 162 ipcMessageCast<ipcmMessageClientDelName> msg(rawMsg); 163 const char *name = msg->Name(); 164 if (name) { 165 if (!client->DelName(name)) { 166 Log((" client doesn't have name '%s'\n", name)); 167 status = IPCM_ERROR_NO_SUCH_DATA; 168 } 169 } 170 else 171 status = IPCM_ERROR_INVALID_ARG; 172 173 IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status)); 174 } 175 176 static void 177 OnClientAddTarget(ipcClient *client, const ipcMessage *rawMsg) 178 { 179 Log(("got CLIENT_ADD_TARGET\n")); 180 181 PRInt32 status = IPCM_OK; 182 PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg); 183 184 ipcMessageCast<ipcmMessageClientAddTarget> msg(rawMsg); 185 if (client->HasTarget(msg->Target())) { 186 Log((" target already defined for client\n")); 90 IPC_NotifyClientUp(pIpcClient); 91 } 92 93 static DECLCALLBACK(void) ipcmOnClientAddName(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) RT_NOTHROW_DEF 94 { 95 Log(("got CLIENT_ADD_NAME\n")); 96 97 int32_t status = IPCM_OK; 98 uint32_t requestIndex = IPCM_GetRequestIndex(pMsg); 99 100 const char *pszName = (const char *)((uint8_t *)IPCMsgGetPayload(pMsg) + 2 * sizeof(uint32_t)); 101 if (pszName) 102 { 103 PIPCDCLIENT pIpcClientResult = IPC_GetClientByName(ipcdClientGetDaemonState(pIpcClient), pszName); 104 if (pIpcClientResult) 105 { 106 Log((" client with such name already exists (ID = %d)\n", ipcdClientGetId(pIpcClientResult))); 187 107 status = IPCM_ERROR_ALREADY_EXISTS; 188 108 } 189 109 else 190 client->AddTarget(msg->Target()); 191 192 IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status)); 193 } 194 195 static void 196 OnClientDelTarget(ipcClient *client, const ipcMessage *rawMsg) 197 { 198 Log(("got CLIENT_DEL_TARGET\n")); 199 200 PRInt32 status = IPCM_OK; 201 PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg); 202 203 ipcMessageCast<ipcmMessageClientDelTarget> msg(rawMsg); 204 if (!client->DelTarget(msg->Target())) { 205 Log((" client doesn't have the given target\n")); 110 ipcdClientAddName(pIpcClient, pszName); 111 } 112 else 113 status = IPCM_ERROR_INVALID_ARG; 114 115 const uint32_t aResp[3] = { IPCM_MSG_ACK_RESULT, requestIndex, (uint32_t)status }; 116 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 117 } 118 119 static DECLCALLBACK(void) ipcmOnClientDelName(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) RT_NOTHROW_DEF 120 { 121 Log(("got CLIENT_DEL_NAME\n")); 122 123 PRInt32 status = IPCM_OK; 124 PRUint32 requestIndex = IPCM_GetRequestIndex(pMsg); 125 126 const char *pszName = (const char *)((uint8_t *)IPCMsgGetPayload(pMsg) + 2 * sizeof(uint32_t)); 127 if (pszName) 128 { 129 if (!ipcdClientDelName(pIpcClient, pszName)) 130 { 131 Log((" client doesn't have name '%s'\n", pszName)); 206 132 status = IPCM_ERROR_NO_SUCH_DATA; 207 133 } 208 209 IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status)); 210 } 211 212 static void 213 OnQueryClientByName(ipcClient *client, const ipcMessage *rawMsg) 214 { 215 Log(("got QUERY_CLIENT_BY_NAME\n")); 216 217 PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg); 218 219 ipcMessageCast<ipcmMessageQueryClientByName> msg(rawMsg); 220 221 ipcClient *result = IPC_GetClientByName(msg->Name()); 222 if (result) { 223 Log((" client exists w/ ID = %u\n", result->ID())); 224 IPC_SendMsg(client, new ipcmMessageClientID(requestIndex, result->ID())); 225 } 226 else { 227 Log((" client does not exist\n")); 228 IPC_SendMsg(client, new ipcmMessageResult(requestIndex, IPCM_ERROR_NO_CLIENT)); 229 } 230 } 231 232 #if 0 233 static void 234 OnQueryClientInfo(ipcClient *client, const ipcMessage *rawMsg) 235 { 236 Log(("got QUERY_CLIENT_INFO\n")); 237 238 ipcMessageCast<ipcmMessageQueryClientInfo> msg(rawMsg); 239 ipcClient *result = IPC_GetClientByID(msg->ClientID()); 240 if (result) { 241 char **names = BuildStringArray(result->Names()); 242 nsID **targets = BuildIDArray(result->Targets()); 243 244 IPC_SendMsg(client, new ipcmMessageClientInfo(result->ID(), 245 msg->RequestIndex(), 246 (const char **) names, 247 (const nsID **) targets)); 248 249 free(names); 250 free(targets); 251 } 252 else { 253 Log((" client does not exist\n")); 254 IPC_SendMsg(client, new ipcmMessageError(IPCM_ERROR_NO_CLIENT, msg->RequestIndex())); 255 } 256 } 257 #endif 258 259 static void 260 OnForward(ipcClient *client, const ipcMessage *rawMsg) 261 { 262 Log(("got FORWARD\n")); 263 264 ipcMessageCast<ipcmMessageForward> msg(rawMsg); 265 266 ipcClient *dest = IPC_GetClientByID(msg->ClientID()); 267 if (!dest) { 268 Log((" destination client not found!\n")); 269 IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_ERROR_NO_CLIENT)); 270 return; 271 } 272 // inform client that its message will be forwarded 273 IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK)); 274 275 ipcMessage *newMsg = new ipcmMessageForward(IPCM_MSG_PSH_FORWARD, 276 client->ID(), 277 msg->InnerTarget(), 278 msg->InnerData(), 279 msg->InnerDataLen()); 280 IPC_SendMsg(dest, newMsg); 281 } 282 }; 283 284 void 285 IPCM_HandleMsg(ipcClient *client, const ipcMessage *rawMsg) 286 { 287 static ipcCommandModule::MsgHandler handlers[] = 288 { 289 ipcCommandModule::OnPing, 290 ipcCommandModule::OnForward, 291 ipcCommandModule::OnClientHello, 292 ipcCommandModule::OnClientAddName, 293 ipcCommandModule::OnClientDelName, 294 ipcCommandModule::OnClientAddTarget, 295 ipcCommandModule::OnClientDelTarget, 296 ipcCommandModule::OnQueryClientByName 134 } 135 else 136 status = IPCM_ERROR_INVALID_ARG; 137 138 const uint32_t aResp[3] = { IPCM_MSG_ACK_RESULT, IPCM_GetRequestIndex(pMsg), (uint32_t)status }; 139 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 140 } 141 142 static DECLCALLBACK(void) ipcmOnClientAddTarget(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) RT_NOTHROW_DEF 143 { 144 Log(("got CLIENT_ADD_TARGET\n")); 145 146 PRInt32 status = IPCM_OK; 147 PRUint32 requestIndex = IPCM_GetRequestIndex(pMsg); 148 149 const nsID *pidTarget = (const nsID *)((uint8_t *)IPCMsgGetPayload(pMsg) + 2 * sizeof(uint32_t)); 150 if (ipcdClientHasTarget(pIpcClient, pidTarget)) 151 { 152 Log((" target already defined for client\n")); 153 status = IPCM_ERROR_ALREADY_EXISTS; 154 } 155 else 156 ipcdClientAddTarget(pIpcClient, pidTarget); 157 158 const uint32_t aResp[3] = { IPCM_MSG_ACK_RESULT, IPCM_GetRequestIndex(pMsg), (uint32_t)status }; 159 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 160 } 161 162 static DECLCALLBACK(void) ipcmOnClientDelTarget(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) RT_NOTHROW_DEF 163 { 164 Log(("got CLIENT_DEL_TARGET\n")); 165 166 PRInt32 status = IPCM_OK; 167 PRUint32 requestIndex = IPCM_GetRequestIndex(pMsg); 168 169 const nsID *pidTarget = (const nsID *)((uint8_t *)IPCMsgGetPayload(pMsg) + 2 * sizeof(uint32_t)); 170 if (!ipcdClientDelTarget(pIpcClient, pidTarget)) 171 { 172 Log((" client doesn't have the given target\n")); 173 status = IPCM_ERROR_NO_SUCH_DATA; 174 } 175 176 const uint32_t aResp[3] = { IPCM_MSG_ACK_RESULT, IPCM_GetRequestIndex(pMsg), (uint32_t)status }; 177 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 178 } 179 180 static DECLCALLBACK(void) ipcmOnQueryClientByName(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) RT_NOTHROW_DEF 181 { 182 Log(("got QUERY_CLIENT_BY_NAME\n")); 183 184 PRUint32 requestIndex = IPCM_GetRequestIndex(pMsg); 185 186 const char *pszName = (const char *)((uint8_t *)IPCMsgGetPayload(pMsg) + 2 * sizeof(uint32_t)); 187 PIPCDCLIENT pIpcClientResult = IPC_GetClientByName(ipcdClientGetDaemonState(pIpcClient), pszName); 188 if (pIpcClientResult) 189 { 190 Log((" client exists w/ ID = %u\n", ipcdClientGetId(pIpcClientResult))); 191 const uint32_t aResp[3] = { IPCM_MSG_ACK_CLIENT_ID, requestIndex, ipcdClientGetId(pIpcClientResult) }; 192 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 193 } 194 else 195 { 196 Log((" client does not exist\n")); 197 const uint32_t aResp[3] = { IPCM_MSG_ACK_RESULT, requestIndex, (uint32_t)IPCM_ERROR_NO_CLIENT }; 198 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 199 } 200 } 201 202 static DECLCALLBACK(void) ipcmOnForward(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) RT_NOTHROW_DEF 203 { 204 Log(("got FORWARD\n")); 205 206 uint32_t idClient = *(uint32_t *)((uint8_t *)IPCMsgGetPayload(pMsg) + 2 * sizeof(uint32_t)); 207 PIPCDCLIENT pIpcClientDst = IPC_GetClientByID(ipcdClientGetDaemonState(pIpcClient), idClient); 208 if (!pIpcClientDst) 209 { 210 Log((" destination client not found!\n")); 211 const uint32_t aResp[3] = { IPCM_MSG_ACK_RESULT, IPCM_GetRequestIndex(pMsg), (uint32_t)IPCM_ERROR_NO_CLIENT }; 212 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 213 return; 214 } 215 // inform client that its message will be forwarded 216 const uint32_t aResp[3] = { IPCM_MSG_ACK_RESULT, IPCM_GetRequestIndex(pMsg), IPCM_OK }; 217 IPC_SendMsg(pIpcClient, IPCM_TARGET, &aResp[0], sizeof(aResp)); 218 219 uint32_t aIpcmFwdHdr[3] = { IPCM_MSG_PSH_FORWARD, IPCM_NewRequestIndex(), ipcdClientGetId(pIpcClient) }; 220 RTSGSEG aSegs[2]; 221 222 aSegs[0].pvSeg = &aIpcmFwdHdr[0]; 223 aSegs[0].cbSeg = sizeof(aIpcmFwdHdr); 224 225 aSegs[1].pvSeg = (uint8_t *)IPCMsgGetPayload(pMsg) + sizeof(aIpcmFwdHdr); 226 aSegs[1].cbSeg = IPCMsgGetPayloadSize(pMsg) - sizeof(aIpcmFwdHdr); 227 228 IPC_SendMsgSg(pIpcClientDst, IPCM_TARGET, IPCMsgGetPayloadSize(pMsg), &aSegs[0], RT_ELEMENTS(aSegs)); 229 } 230 231 232 DECLHIDDEN(void) IPCM_HandleMsg(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) 233 { 234 static const PFNIPCMMSGHANDLER aHandlers[] = 235 { 236 ipcmOnPing, 237 ipcmOnForward, 238 ipcmOnClientHello, 239 ipcmOnClientAddName, 240 ipcmOnClientDelName, 241 ipcmOnClientAddTarget, 242 ipcmOnClientDelTarget, 243 ipcmOnQueryClientByName 297 244 }; 298 245 299 int type = IPCM_GetType(rawMsg); 300 Log(("IPCM_HandleMsg [type=%x]\n", type)); 301 302 if (!(type & IPCM_MSG_CLASS_REQ)) { 246 uint32_t u32Type = IPCM_GetType(pMsg); 247 Log(("IPCM_HandleMsg [u32Type=%x]\n", u32Type)); 248 249 if (!(u32Type & IPCM_MSG_CLASS_REQ)) 250 { 303 251 Log(("not a request -- ignoring message\n")); 304 252 return; 305 253 } 306 254 307 type &= ~IPCM_MSG_CLASS_REQ; 308 type--; 309 if (type < 0 || type >= (int) (sizeof(handlers)/sizeof(handlers[0]))) { 255 u32Type &= ~IPCM_MSG_CLASS_REQ; 256 u32Type--; 257 if (u32Type >= RT_ELEMENTS(aHandlers)) 258 { 310 259 Log(("unknown request -- ignoring message\n")); 311 260 return; 312 261 } 313 262 314 (handlers[type])(client, rawMsg);315 } 263 aHandlers[u32Type](pIpcClient, pMsg); 264 } -
trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h
r1 r103378 39 39 #define ipcCommandModule_h__ 40 40 41 #include "ipcm.h" // for IPCM_TARGET 41 #include "ipcMessageNew.h" 42 #include "ipcClient.h" 42 43 43 class ipcClient; 44 class ipcMessage; 45 46 void IPCM_HandleMsg(ipcClient *, const ipcMessage *); 44 DECLHIDDEN(void) IPCM_HandleMsg(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg); 47 45 48 46 #endif // !ipcCommandModule_h__ -
trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp
r103377 r103378 61 61 62 62 #include "ipcConfig.h" 63 #include "ipcMessage .h"63 #include "ipcMessageNew.h" 64 64 #include "ipcClient.h" 65 #include "ipc dPrivate.h"65 #include "ipcCommandModule.h" 66 66 #include "ipcd.h" 67 67 #include "ipcm.h" 68 69 70 // 71 // upper limit on the number of active connections 72 // XXX may want to make this more dynamic 73 // 74 #define IPC_MAX_CLIENTS 100 75 76 /** How many messages should stay in the message cache. */ 77 #define IPC_MAX_MSGS_IN_CACHE 5 68 78 69 79 /** … … 72 82 typedef struct IPCDSTATE 73 83 { 74 RTSOCKET hSockListen; 75 int fdListen; 76 int ipcLockFD; 77 int ipcClientCount; 78 79 // 80 // the first element of this array is always zero; this is done so that the 81 // k'th element of ipcClientArray corresponds to the k'th element of 82 // ipcPollList. 83 // 84 ipcClient ipcClientArray[IPC_MAX_CLIENTS]; 85 86 RTPOLLSET hPollSet; 87 RTTHREAD hThread; 84 RTSOCKET hSockListen; 85 int fdListen; 86 int ipcLockFD; 87 int ipcClientCount; 88 89 IPCDCLIENT ipcClientArray[IPC_MAX_CLIENTS]; 90 RTLISTANCHOR LstIpcClients; 91 92 RTLISTANCHOR LstIpcMsgsFree; 93 uint32_t cIpcMsgsFree; 94 95 RTPOLLSET hPollSet; 96 RTTHREAD hThread; 88 97 } IPCDSTATE; 89 98 typedef IPCDSTATE *PIPCDSTATE; … … 251 260 252 261 //----------------------------------------------------------------------------- 253 // poll list254 //-----------------------------------------------------------------------------255 256 //257 // declared in ipcdPrivate.h258 //259 DECL_HIDDEN_DATA(RTLISTANCHOR) g_LstIpcClients;260 static RTPOLLSET g_hPollSet = NIL_RTPOLLSET;261 262 263 //-----------------------------------------------------------------------------264 262 265 263 static int AddClient(PIPCDSTATE pThis, RTSOCKET hSock) … … 273 271 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->ipcClientArray); i++) 274 272 { 275 if (!pThis->ipcClientArray[i]. m_fUsed)276 { 277 pThis->ipcClientArray[i].Init(i, hSock);278 pThis->ipcClientArray[i].m_fPollEvts = RTPOLL_EVT_READ;279 intvrc = RTPollSetAddSocket(pThis->hPollSet, hSock, RTPOLL_EVT_READ, i);273 if (!pThis->ipcClientArray[i].fUsed) 274 { 275 int vrc = ipcdClientInit(&pThis->ipcClientArray[i], pThis, i, hSock); 276 if (RT_SUCCESS(vrc)) 277 vrc = RTPollSetAddSocket(pThis->hPollSet, hSock, RTPOLL_EVT_READ, i); 280 278 if (RT_SUCCESS(vrc)) 281 279 { 282 RTListAppend(& g_LstIpcClients, &pThis->ipcClientArray[i].NdClients);280 RTListAppend(&pThis->LstIpcClients, &pThis->ipcClientArray[i].NdClients); 283 281 pThis->ipcClientCount++; 284 282 return 0; 285 283 } 286 284 287 pThis->ipcClientArray[i].Finalize();285 ipcdClientDestroy(&pThis->ipcClientArray[i]); 288 286 break; 289 287 } … … 300 298 301 299 RTListNodeRemove(&pThis->ipcClientArray[idClient].NdClients); 302 pThis->ipcClientArray[idClient].Finalize();300 ipcdClientDestroy(&pThis->ipcClientArray[idClient]); 303 301 pThis->ipcClientCount--; 304 302 return 0; … … 309 307 static void PollLoop(PIPCDSTATE pThis) 310 308 { 311 RTListInit(&g_LstIpcClients);312 313 309 for (;;) 314 310 { … … 356 352 else 357 353 { 358 uint32_t fNewFlags = pThis->ipcClientArray[idPoll].Process(fEvents);354 uint32_t fNewFlags = ipcdClientProcess(&pThis->ipcClientArray[idPoll], fEvents); 359 355 if (!fNewFlags) 360 356 { … … 369 365 } 370 366 } 371 else if (pThis->ipcClientArray[idPoll]. m_fPollEvts != fNewFlags)367 else if (pThis->ipcClientArray[idPoll].fPollEvts != fNewFlags) 372 368 { 373 369 /* Change flags. */ 374 370 vrc = RTPollSetEventsChange(pThis->hPollSet, idPoll, fNewFlags); 375 371 AssertRC(vrc); 376 pThis->ipcClientArray[idPoll]. m_fPollEvts = fNewFlags;372 pThis->ipcClientArray[idPoll].fPollEvts = fNewFlags; 377 373 } 378 374 } … … 382 378 //----------------------------------------------------------------------------- 383 379 384 PRStatus 385 IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg) 380 static int ipcdPlatformSendMsg(PIPCDCLIENT pIpcClient, PIPCMSG pMsg) 386 381 { 387 382 LogFlowFunc(("IPC_PlatformSendMsg\n")); 388 383 389 // 390 // must copy message onto send queue. 391 // 392 client->EnqueueOutboundMsg(msg); 393 394 // 395 // since our Process method may have already been called, we must ensure 396 // that the RTPOLL_EVT_WRITE flag is set. 397 // 398 if (!(client->m_fPollEvts & RTPOLL_EVT_WRITE)) 399 { 400 client->m_fPollEvts |= RTPOLL_EVT_WRITE; 401 int vrc = RTPollSetEventsChange(g_hPollSet, client->m_idPoll, client->m_fPollEvts); 384 PIPCDSTATE pThis = ipcdClientGetDaemonState(pIpcClient); 385 386 ipcdClientEnqueueOutboundMsg(pIpcClient, pMsg); 387 388 /* 389 * Since our Process method may have already been called, we must ensure 390 * that the RTPOLL_EVT_WRITE flag is set. 391 */ 392 if (!(pIpcClient->fPollEvts & RTPOLL_EVT_WRITE)) 393 { 394 pIpcClient->fPollEvts |= RTPOLL_EVT_WRITE; 395 int vrc = RTPollSetEventsChange(pThis->hPollSet, pIpcClient->idPoll, pIpcClient->fPollEvts); 402 396 AssertRC(vrc); 403 397 } 404 398 405 return PR_SUCCESS; 399 return VINF_SUCCESS; 400 } 401 402 403 //----------------------------------------------------------------------------- 404 405 DECLHIDDEN(int) IPC_DispatchMsg(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg) 406 { 407 AssertPtr(pIpcClient); 408 AssertPtr(pMsg); 409 410 // remember if client is expecting SYNC_REPLY. we'll add that flag to the 411 // next message sent to the client. 412 if (IPCMsgIsFlagSet(pMsg, IPC_MSG_FLAG_SYNC_QUERY)) 413 { 414 Assert(!ipcdClientGetExpectsSyncReply(pIpcClient)); 415 // XXX shouldn't we remember the TargetID as well, and only set the 416 // SYNC_REPLY flag on the next message sent to the same TargetID? 417 ipcdClientSetExpectsSyncReply(pIpcClient, true); 418 } 419 420 if (IPCMsgGetTarget(pMsg)->Equals(IPCM_TARGET)) 421 IPCM_HandleMsg(pIpcClient, pMsg); 422 423 return VINF_SUCCESS; 424 } 425 426 427 DECLHIDDEN(int) IPC_SendMsg(PIPCDCLIENT pIpcClient, PIPCMSG pMsg) 428 { 429 Assert(pMsg); 430 Assert(pIpcClient); 431 432 // add SYNC_REPLY flag to message if client is expecting... 433 if (ipcdClientGetExpectsSyncReply(pIpcClient)) { 434 pMsg->pMsgHdr->u16Flags |= IPC_MSG_FLAG_SYNC_REPLY; 435 ipcdClientSetExpectsSyncReply(pIpcClient, false); 436 } 437 438 if (ipcdClientHasTarget(pIpcClient, IPCMsgGetTarget(pMsg))) 439 return ipcdPlatformSendMsg(pIpcClient, pMsg); 440 441 Log((" no registered message handler\n")); 442 return VERR_NOT_FOUND; 443 } 444 445 446 DECLHIDDEN(void) IPC_NotifyClientUp(PIPCDCLIENT pIpcClient) 447 { 448 Log(("IPC_NotifyClientUp: clientID=%d\n", ipcdClientGetId(pIpcClient))); 449 450 PIPCDSTATE pThis = ipcdClientGetDaemonState(pIpcClient); 451 PIPCDCLIENT pIt; 452 RTListForEach(&pThis->LstIpcClients, pIt, IPCDCLIENT, NdClients) 453 { 454 if (pIt != pIpcClient) 455 { 456 uint32_t aResp[4] = { IPCM_MSG_PSH_CLIENT_STATE, 0, ipcdClientGetId(pIpcClient), IPCM_CLIENT_STATE_UP }; 457 IPC_SendMsg(pIt, IPCM_TARGET, &aResp[0], sizeof(aResp)); 458 } 459 } 460 } 461 462 463 DECLHIDDEN(void) IPC_NotifyClientDown(PIPCDCLIENT pIpcClient) 464 { 465 Log(("IPC_NotifyClientDown: clientID=%d\n", ipcdClientGetId(pIpcClient))); 466 467 PIPCDSTATE pThis = ipcdClientGetDaemonState(pIpcClient); 468 PIPCDCLIENT pIt; 469 RTListForEach(&pThis->LstIpcClients, pIt, IPCDCLIENT, NdClients) 470 { 471 if (pIt != pIpcClient) 472 { 473 uint32_t aResp[4] = { IPCM_MSG_PSH_CLIENT_STATE, 0, ipcdClientGetId(pIpcClient), IPCM_CLIENT_STATE_DOWN }; 474 IPC_SendMsg(pIt, IPCM_TARGET, &aResp[0], sizeof(aResp)); 475 } 476 } 477 } 478 479 //----------------------------------------------------------------------------- 480 // IPC daemon methods 481 //----------------------------------------------------------------------------- 482 483 DECLHIDDEN(int) IPC_SendMsg(PIPCDCLIENT pIpcClient, const nsID &target, const void *pvData, size_t cbData) 484 { 485 RTSGSEG Seg = { (void *)pvData, cbData }; 486 return IPC_SendMsgSg(pIpcClient, target, cbData, &Seg, 1); 487 } 488 489 490 DECLHIDDEN(int) IPC_SendMsgSg(PIPCDCLIENT pIpcClient, const nsID &target, size_t cbTotal, PCRTSGSEG paSegs, uint32_t cSegs) 491 { 492 PIPCDSTATE pThis = ipcdClientGetDaemonState(pIpcClient); 493 PIPCMSG pMsg = NULL; 494 495 if (!pThis->cIpcMsgsFree) 496 { 497 pMsg = IPCMsgNewSg(target, cbTotal, paSegs, cSegs); 498 if (!pMsg) 499 return VERR_NO_MEMORY; 500 } 501 else 502 { 503 pMsg = RTListRemoveFirst(&pThis->LstIpcMsgsFree, IPCMSG, NdMsg); 504 AssertPtr(pMsg); 505 pThis->cIpcMsgsFree--; 506 507 int vrc = IPCMsgInitSg(pMsg, target, cbTotal, paSegs, cSegs); 508 if (RT_FAILURE(vrc)) 509 { 510 RTListAppend(&pThis->LstIpcMsgsFree, &pMsg->NdMsg); 511 pThis->cIpcMsgsFree++; 512 return vrc; 513 } 514 } 515 516 return IPC_SendMsg(pIpcClient, pMsg); 517 } 518 519 520 DECLHIDDEN(void) IPC_PutMsgIntoCache(PIPCDSTATE pIpcd, PIPCMSG pMsg) 521 { 522 if (pIpcd->cIpcMsgsFree < IPC_MAX_MSGS_IN_CACHE) 523 { /*likely*/ } 524 else 525 { 526 IPCMsgFree(pMsg, true /*fFreeStruct*/); 527 return; 528 } 529 530 pIpcd->cIpcMsgsFree++; 531 IPCMsgReset(pMsg); 532 RTListAppend(&pIpcd->LstIpcMsgsFree, &pMsg->NdMsg); 533 } 534 535 536 DECLHIDDEN(PIPCDCLIENT) IPC_GetClientByID(PIPCDSTATE pIpcd, uint32_t idClient) 537 { 538 // linear search OK since number of clients should be small 539 PIPCDCLIENT pIt; 540 RTListForEach(&pIpcd->LstIpcClients, pIt, IPCDCLIENT, NdClients) 541 { 542 if (ipcdClientGetId(pIt) == idClient) 543 return pIt; 544 } 545 return NULL; 546 } 547 548 549 DECLHIDDEN(PIPCDCLIENT) IPC_GetClientByName(PIPCDSTATE pIpcd, const char *pszName) 550 { 551 // linear search OK since number of clients should be small 552 PIPCDCLIENT pIt; 553 RTListForEach(&pIpcd->LstIpcClients, pIt, IPCDCLIENT, NdClients) 554 { 555 if (ipcdClientHasName(pIt, pszName)) 556 return pIt; 557 } 558 return NULL; 406 559 } 407 560 … … 409 562 static int ipcdInit(PIPCDSTATE pThis, const char *pszSocketPath) 410 563 { 564 RTListInit(&pThis->LstIpcClients); 565 RTListInit(&pThis->LstIpcMsgsFree); 566 pThis->cIpcMsgsFree = 0; 411 567 pThis->fdListen = 0; 412 568 pThis->hPollSet = NIL_RTPOLLSET; … … 435 591 // we terminate 436 592 if (status != ELockFileOwner) 437 printf( ("Cannot create a lock file for '%s'.\n"438 "Check permissions.\n", addr.sun_path) );593 printf("Cannot create a lock file for '%s'.\n" 594 "Check permissions.\n", addr.sun_path); 439 595 return VERR_INVALID_PARAMETER; 440 596 } … … 495 651 } 496 652 497 g_hPollSet = pThis->hPollSet;498 499 653 vrc = RTPollSetAddSocket(pThis->hPollSet, pThis->hSockListen, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, UINT32_MAX - 1); 500 654 if (RT_FAILURE(vrc)) … … 540 694 AssertRC(vrc); 541 695 pThis->hSockListen = NIL_RTSOCKET; 696 } 697 698 /* Free all the cached messages. */ 699 PIPCMSG pIt, pItNext; 700 RTListForEachSafe(&pThis->LstIpcMsgsFree, pIt, pItNext, IPCMSG, NdMsg) 701 { 702 RTListNodeRemove(&pIt->NdMsg); 703 IPCMsgFree(pIt, true /*fFreeStruct*/); 542 704 } 543 705 } -
trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h
r101934 r103378 39 39 #define IPCD_H__ 40 40 41 #include "ipcMessage.h"41 #include <iprt/sg.h> 42 42 43 // 44 // a client handle is used to efficiently reference a client instance object 45 // used by the daemon to represent a connection with a particular client app. 46 // 47 // modules should treat it as an opaque type. 48 // 49 typedef class ipcClient *ipcClientHandle; 50 51 // 52 // enumeration functions may return FALSE to stop enumeration. 53 // 54 typedef PRBool (* ipcClientEnumFunc) (void *closure, ipcClientHandle client, PRUint32 clientID); 55 typedef PRBool (* ipcClientNameEnumFunc) (void *closure, ipcClientHandle client, const char *name); 56 typedef PRBool (* ipcClientTargetEnumFunc) (void *closure, ipcClientHandle client, const nsID &target); 43 #include "ipcClient.h" 44 #include "ipcMessageNew.h" 57 45 58 46 //----------------------------------------------------------------------------- … … 63 51 //----------------------------------------------------------------------------- 64 52 65 PRStatus IPC_DispatchMsg (ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen); 66 PRStatus IPC_SendMsg (ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen); 67 ipcClientHandle IPC_GetClientByID (PRUint32 id); 68 ipcClientHandle IPC_GetClientByName (const char *name); 69 void IPC_EnumClients (ipcClientEnumFunc func, void *closure); 70 PRUint32 IPC_GetClientID (ipcClientHandle client); 71 PRBool IPC_ClientHasName (ipcClientHandle client, const char *name); 72 PRBool IPC_ClientHasTarget (ipcClientHandle client, const nsID &target); 73 void IPC_EnumClientNames (ipcClientHandle client, ipcClientNameEnumFunc func, void *closure); 74 void IPC_EnumClientTargets (ipcClientHandle client, ipcClientTargetEnumFunc func, void *closure); 53 DECLHIDDEN(int) IPC_SendMsg(PIPCDCLIENT pIpcClient, const nsID &target, const void *pvData, size_t cbData); 54 DECLHIDDEN(int) IPC_SendMsgSg(PIPCDCLIENT pIpcClient, const nsID &target, size_t cbTotal, PCRTSGSEG paSegs, uint32_t cSegs); 55 DECLHIDDEN(PIPCDCLIENT) IPC_GetClientByID(PIPCDSTATE pIpcd, uint32_t idClient); 56 DECLHIDDEN(PIPCDCLIENT) IPC_GetClientByName(PIPCDSTATE pIpcd, const char *pszName); 75 57 76 //----------------------------------------------------------------------------- 77 // other internal IPCD methods 78 //----------------------------------------------------------------------------- 58 DECLHIDDEN(void) IPC_PutMsgIntoCache(PIPCDSTATE pIpcd, PIPCMSG pMsg); 79 59 80 60 // 81 61 // dispatch message 82 62 // 83 PRStatus IPC_DispatchMsg(ipcClientHandle client, const ipcMessage *msg);63 DECLHIDDEN(int) IPC_DispatchMsg(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg); 84 64 85 65 // 86 66 // send message, takes ownership of |msg|. 87 67 // 88 PRStatus IPC_SendMsg(ipcClientHandle client, ipcMessage *msg);68 DECLHIDDEN(int) IPC_SendMsg(PIPCDCLIENT pIpcClient, PIPCMSG pMsg); 89 69 90 70 // 91 71 // dispatch notifications about client connects and disconnects 92 72 // 93 void IPC_NotifyClientUp(ipcClientHandle client);94 void IPC_NotifyClientDown(ipcClientHandle client);73 DECLHIDDEN(void) IPC_NotifyClientUp(PIPCDCLIENT pIpcClient); 74 DECLHIDDEN(void) IPC_NotifyClientDown(PIPCDCLIENT pIpcClient); 95 75 96 76 #endif // !IPCD_H__ -
trunk/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.cpp
r102334 r103378 46 46 ipcMessage::~ipcMessage() 47 47 { 48 if (mMsgHdr) 49 RTMemFree(mMsgHdr); 48 if (m_pvBuf) 49 RTMemFree(m_pvBuf); 50 51 mMsgHdr = NULL; 52 m_pvBuf = NULL; 53 m_cbBufMax = 0; 50 54 } 51 55 … … 53 57 ipcMessage::Reset() 54 58 { 55 if (mMsgHdr) { 56 RTMemFree(mMsgHdr); 57 mMsgHdr = NULL; 58 } 59 60 mMsgOffset = 0; 59 mMsgHdr = NULL; 60 mMsgOffset = 0; 61 61 mMsgComplete = PR_FALSE; 62 63 /* For large messages we don't want to keep the memory around forever. */ 64 if (m_cbBufMax > _16K) 65 { 66 RTMemFree(m_pvBuf); 67 m_pvBuf = NULL; 68 m_cbBufMax = 0; 69 } 62 70 } 63 71 … … 71 79 // copy buf if non-null 72 80 if (mMsgHdr) { 73 clone->mMsgHdr = (ipcMessageHeader *) RTMemDup(mMsgHdr, mMsgHdr->mLen); 81 clone->mMsgHdr = (ipcMessageHeader *) RTMemDup(mMsgHdr, mMsgHdr->mLen); 82 clone->m_pvBuf = clone->mMsgHdr; 83 clone->m_cbBufMax = mMsgHdr->mLen; 74 84 } 75 85 else … … 85 95 ipcMessage::Init(const nsID &target, const char *data, PRUint32 dataLen) 86 96 { 87 if (mMsgHdr)88 RTMemFree(mMsgHdr);89 90 97 mMsgComplete = PR_FALSE; 91 98 92 99 // allocate message data 93 100 PRUint32 msgLen = IPC_MSG_HEADER_SIZE + dataLen; 94 mMsgHdr = (ipcMessageHeader *) RTMemAlloc(msgLen); 95 if (!mMsgHdr) { 96 mMsgHdr = NULL; 97 return PR_FAILURE; 98 } 101 if (m_cbBufMax < msgLen) 102 { 103 void *pvNew = RTMemRealloc(m_pvBuf, msgLen); 104 if (!pvNew) 105 return PR_FAILURE; 106 107 m_pvBuf = pvNew; 108 m_cbBufMax = msgLen; 109 } 110 111 mMsgHdr = (ipcMessageHeader *)m_pvBuf; 99 112 100 113 // fill in message data … … 203 216 *bytesRead = count; 204 217 205 if (MsgLen() > IPC_MSG_GUESSED_SIZE) {218 if (MsgLen() > m_cbBufMax) { 206 219 // realloc message buffer to the correct size 207 mMsgHdr = (ipcMessageHeader *) RTMemRealloc(mMsgHdr, MsgLen()); 220 void *pvNew = RTMemRealloc(m_pvBuf, MsgLen()); 221 if (!pvNew) 222 return PR_FAILURE; 223 m_pvBuf = pvNew; 224 m_cbBufMax = MsgLen(); 225 mMsgHdr = (ipcMessageHeader *)m_pvBuf; 208 226 } 209 227 } … … 215 233 // allocate a partial buffer 216 234 PRUint32 msgLen = IPC_MSG_GUESSED_SIZE; 217 mMsgHdr = (ipcMessageHeader *) RTMemAlloc(msgLen); 218 if (!mMsgHdr) 219 return PR_FAILURE; 235 if (msgLen > m_cbBufMax) 236 { 237 void *pvNew = RTMemRealloc(m_pvBuf, msgLen); 238 if (!pvNew) 239 return PR_FAILURE; 240 m_pvBuf = pvNew; 241 m_cbBufMax = msgLen; 242 mMsgHdr = (ipcMessageHeader *)m_pvBuf; 243 } 244 220 245 memcpy(mMsgHdr, buf, bufLen); 221 246 mMsgOffset = bufLen; … … 226 251 else { 227 252 PRUint32 msgLen = *(PRUint32 *) buf; 228 mMsgHdr = (ipcMessageHeader *) RTMemAlloc(msgLen); 229 if (!mMsgHdr) 230 return PR_FAILURE; 253 if (msgLen > m_cbBufMax) 254 { 255 void *pvNew = RTMemRealloc(m_pvBuf, msgLen); 256 if (!pvNew) 257 return PR_FAILURE; 258 m_pvBuf = pvNew; 259 m_cbBufMax = msgLen; 260 } 261 mMsgHdr = (ipcMessageHeader *)m_pvBuf; 231 262 mMsgHdr->mLen = msgLen; 232 263 mMsgOffset = 0; -
trunk/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.h
r1 r103378 100 100 , mMsgOffset(0) 101 101 , mMsgComplete(PR_FALSE) 102 , m_cbBufMax(0) 103 , m_pvBuf(NULL) 102 104 { } 103 105 ipcMessage(const nsID &target, const char *data, PRUint32 dataLen) … … 106 108 , mMsgHdr(NULL) 107 109 , mMsgOffset(0) 110 , m_cbBufMax(0) 111 , m_pvBuf(NULL) 108 112 { Init(target, data, dataLen); } 109 113 ~ipcMessage() NS_HIDDEN; … … 210 214 PRUint32 mMsgOffset; 211 215 PRPackedBool mMsgComplete; 216 217 size_t m_cbBufMax; 218 void *m_pvBuf; 212 219 }; 213 220 -
trunk/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageNew.h
r103333 r103378 36 36 * ***** END LICENSE BLOCK ***** */ 37 37 38 #ifndef ipcMessage_h__ 39 #define ipcMessage_h__ 38 #ifndef ipcMessageNew_h__ 39 #define ipcMessageNew_h__ 40 41 #include <iprt/assert.h> 42 #include <iprt/assertcompile.h> 43 #include <iprt/cdefs.h> 44 #include <iprt/err.h> 45 #include <iprt/list.h> 46 #include <iprt/types.h> 47 #include <iprt/mem.h> 48 #include <iprt/sg.h> 40 49 41 50 #include "nsID.h" … … 58 67 // is a 16 byte UUID indicating the intended receiver of this message. 59 68 // 60 61 struct ipcMessageHeader 62 { 63 PRUint32 mLen; 64 PRUint16 mVersion; 65 PRUint16 mFlags; 66 nsID mTarget; 67 }; 68 69 #define IPC_MSG_VERSION (0x1) 70 #define IPC_MSG_HEADER_SIZE (sizeof(ipcMessageHeader)) 71 #define IPC_MSG_GUESSED_SIZE (IPC_MSG_HEADER_SIZE + 64) 69 typedef struct IPCMSGHDR 70 { 71 /** Size of the message in bytes, including this header. */ 72 uint32_t cbMsg; 73 /** The version of the IPC message header. */ 74 uint16_t u16Version; 75 /** Flags for the message. */ 76 uint16_t u16Flags; 77 /** The target ID for this message. */ 78 nsID idTarget; 79 } IPCMSGHDR; 80 AssertCompileSize(IPCMSGHDR, 4 + 2 + 2 + 16); 81 /** Pointer to the IPC message header. */ 82 typedef IPCMSGHDR *PIPCMSGHDR; 83 /** Pointer to a const IPC message header. */ 84 typedef const IPCMSGHDR *PCIPCMSGHDR; 85 86 /** IPC message version. */ 87 #define IPC_MSG_HDR_VERSION UINT16_C(0x1) 72 88 73 89 // … … 77 93 // it is expecting a response with the SYNC_REPLY flag set. 78 94 // 79 #define IPC_MSG_ FLAG_SYNC_QUERY (0x1)80 #define IPC_MSG_ FLAG_SYNC_REPLY (0x2)95 #define IPC_MSG_HDR_FLAG_SYNC_QUERY RT_BIT(0) 96 #define IPC_MSG_HDR_FLAG_SYNC_REPLY RT_BIT(1) 81 97 82 98 // … … 85 101 // in WaitTarget(). 86 102 // 87 #define IPC_MSG_FLAG_IN_PROCESS (0x4) 88 89 //----------------------------------------------------------------------------- 90 // ipcMessage 91 //----------------------------------------------------------------------------- 92 93 class ipcMessage 94 { 95 public: 96 ipcMessage() 97 : mNext(NULL) 98 , mMetaData(0) 99 , mMsgHdr(NULL) 100 , mMsgOffset(0) 101 , mMsgComplete(PR_FALSE) 102 { } 103 ipcMessage(const nsID &target, const char *data, PRUint32 dataLen) 104 : mNext(NULL) 105 , mMetaData(0) 106 , mMsgHdr(NULL) 107 , mMsgOffset(0) 108 { Init(target, data, dataLen); } 109 ~ipcMessage() NS_HIDDEN; 110 111 // 112 // reset message to uninitialized state 113 // 114 NS_HIDDEN_(void) Reset(); 115 116 // 117 // create a copy of this message 118 // 119 NS_HIDDEN_(ipcMessage *) Clone() const; 120 121 // 122 // initialize message 123 // 124 // param: 125 // topic - message topic string 126 // data - message data (may be null to leave data uninitialized) 127 // dataLen - message data len 128 // 129 NS_HIDDEN_(PRStatus) Init(const nsID &target, const char *data, PRUint32 dataLen); 130 131 // 132 // copy data into the message's data section, starting from offset. this 133 // function can be used to write any portion of the message's data. 134 // 135 // param: 136 // offset - destination offset 137 // data - data to write 138 // dataLen - number of bytes to write 139 // 140 NS_HIDDEN_(PRStatus) SetData(PRUint32 offset, const char *data, PRUint32 dataLen); 141 142 // 143 // access message flags 144 // 145 void SetFlag(PRUint16 flag) { mMsgHdr->mFlags |= flag; } 146 void ClearFlag(PRUint16 flag) { mMsgHdr->mFlags &= ~flag; } 147 PRBool TestFlag(PRUint16 flag) const { return mMsgHdr->mFlags & flag; } 148 149 // 150 // if true, the message is complete and the members of the message 151 // can be accessed. 152 // 153 PRBool IsComplete() const { return mMsgComplete; } 154 155 // 156 // readonly accessors 157 // 158 const ipcMessageHeader *Header() const { return mMsgHdr; } 159 const nsID &Target() const { return mMsgHdr->mTarget; } 160 const char *Data() const { return (char *) mMsgHdr + IPC_MSG_HEADER_SIZE; } 161 PRUint32 DataLen() const { return mMsgHdr->mLen - IPC_MSG_HEADER_SIZE; } 162 const char *MsgBuf() const { return (char *) mMsgHdr; } 163 PRUint32 MsgLen() const { return mMsgHdr->mLen; } 164 165 // 166 // message comparison functions 167 // 168 // param: 169 // topic - message topic (may be null) 170 // data - message data (must not be null) 171 // dataLen - message data length 172 // 173 NS_HIDDEN_(PRBool) Equals(const nsID &target, const char *data, PRUint32 dataLen) const; 174 NS_HIDDEN_(PRBool) Equals(const ipcMessage *msg) const; 175 176 // 177 // write the message to a buffer segment; segment need not be large 178 // enough to hold entire message. called repeatedly. 179 // 180 NS_HIDDEN_(PRStatus) WriteTo(char *buf, 181 PRUint32 bufLen, 182 PRUint32 *bytesWritten, 183 PRBool *complete); 184 185 // 186 // read the message from a buffer segment; segment need not contain 187 // the entire messgae. called repeatedly. 188 // 189 NS_HIDDEN_(PRStatus) ReadFrom(const char *buf, 190 PRUint32 bufLen, 191 PRUint32 *bytesRead, 192 PRBool *complete); 193 194 // 195 // a message can be added to a singly-linked list. 196 // 197 class ipcMessage *mNext; 198 199 // 200 // meta data associated with this message object. the owner of the 201 // ipcMessage object is free to use this field for any purpose. by 202 // default, it is initialized to 0. 203 // 204 PRUint32 mMetaData; 205 206 private: 207 ipcMessageHeader *mMsgHdr; 208 209 // XXX document me 210 PRUint32 mMsgOffset; 211 PRPackedBool mMsgComplete; 212 }; 213 214 #endif // !ipcMessage_h__ 103 #define IPC_MSG_HDR_FLAG_IN_PROCESS RT_BIT(2) 104 105 106 /** 107 * IPC message structure. 108 */ 109 typedef struct IPCMSG 110 { 111 /** List node for putting the message onto a list. */ 112 RTLISTNODE NdMsg; 113 /** Pointer to the IPC message header. */ 114 PIPCMSGHDR pMsgHdr; 115 /** Size of the message buffer in bytes (maximum size of the buffer). */ 116 size_t cbBuf; 117 /** Pointer to the message buffer. */ 118 uint8_t *pbBuf; 119 /** Offset into the message buffer to append data to. */ 120 uint32_t offAppend; 121 /** Flag whether the message is complete and the buffer is therefore readonly right now. */ 122 bool fReadonly; 123 } IPCMSG; 124 /** Pointer to an IPC message. */ 125 typedef IPCMSG *PIPCMSG; 126 /** Pointer to a const IPC message. */ 127 typedef const IPCMSG *PCIPCMSG; 128 129 130 DECLINLINE(int) IPCMsgInit(PIPCMSG pThis, size_t cbBuf) 131 { 132 Assert(!pThis->pbBuf); 133 134 pThis->pbBuf = (uint8_t *)RTMemAlloc(sizeof(*pThis->pMsgHdr) + cbBuf); 135 if (RT_UNLIKELY(!pThis->pbBuf)) 136 return VERR_NO_MEMORY; 137 138 pThis->cbBuf = sizeof(*pThis->pMsgHdr) + cbBuf; 139 pThis->offAppend = 0; 140 pThis->fReadonly = false; 141 pThis->pMsgHdr = NULL; 142 return VINF_SUCCESS; 143 } 144 145 146 /** 147 * Allocates a new IPC message structure which can hold the given amount of data initially. 148 * 149 * @returns Pointer to the IPC message structure or NULL if out of memory. 150 * @param cbMsg Size of the payload message buffer in bytes, can be 0 if not known at allocation time. 151 */ 152 DECLINLINE(PIPCMSG) IPCMsgAlloc(size_t cbMsg) 153 { 154 PIPCMSG pThis = (PIPCMSG)RTMemAllocZ(sizeof(*pThis)); 155 if (RT_UNLIKELY(!pThis)) 156 return NULL; 157 158 if (cbMsg) 159 { 160 pThis->pbBuf = (uint8_t *)RTMemAlloc(sizeof(*pThis->pMsgHdr) + cbMsg); 161 if (RT_UNLIKELY(!pThis->pbBuf)) 162 { 163 RTMemFree(pThis); 164 return NULL; 165 } 166 167 pThis->cbBuf = sizeof(*pThis->pMsgHdr) + cbMsg; 168 } 169 170 return pThis; 171 } 172 173 174 /** 175 * Frees the given message and all associated resources. 176 * 177 * @param pThis The IPC message to free. 178 * @param fFreeStruct Flag whether to free the structure (true) or just the message buffer (false). 179 */ 180 DECLINLINE(void) IPCMsgFree(PIPCMSG pThis, bool fFreeStruct) 181 { 182 if (pThis->pbBuf) 183 RTMemFree(pThis->pbBuf); 184 pThis->pbBuf = NULL; 185 pThis->pMsgHdr = NULL; 186 pThis->cbBuf = 0; 187 pThis->offAppend = 0; 188 pThis->fReadonly = false; 189 190 if (fFreeStruct) 191 RTMemFree(pThis); 192 } 193 194 195 /** 196 * Reset the given message structure to accept a new message. 197 * 198 * @param pThis The IPC message to reset. 199 */ 200 DECLINLINE(void) IPCMsgReset(PIPCMSG pThis) 201 { 202 pThis->pMsgHdr = NULL; 203 pThis->offAppend = 0; 204 pThis->fReadonly = false; 205 } 206 207 208 /** 209 * Returns a pointer to the message data including the header. 210 * 211 * @param pThis The IPC message. 212 */ 213 DECLINLINE(void *) IPCMsgGetBuf(PCIPCMSG pThis) 214 { 215 AssertReturn(pThis->pMsgHdr, NULL); 216 217 return pThis->pMsgHdr; 218 } 219 220 221 /** 222 * Returns the size of the message in bytes including the header. 223 * 224 * @param pThis The IPC message. 225 */ 226 DECLINLINE(size_t) IPCMsgGetSize(PCIPCMSG pThis) 227 { 228 AssertReturn(pThis->pMsgHdr, 0); 229 230 return pThis->pMsgHdr->cbMsg; 231 } 232 233 234 /** 235 * Returns the message header of the given message. 236 * 237 * @returns Pointer to the IPC message header. 238 * @param pThis The IPC message. 239 */ 240 DECLINLINE(PCIPCMSGHDR) IPCMsgGetHdr(PCIPCMSG pThis) 241 { 242 Assert(pThis->pMsgHdr); 243 return pThis->pMsgHdr; 244 } 245 246 247 DECLINLINE(const nsID *) IPCMsgGetTarget(PCIPCMSG pThis) 248 { 249 AssertReturn(pThis->pMsgHdr, NULL); 250 return &pThis->pMsgHdr->idTarget; 251 } 252 253 254 /** 255 * Returns a pointer to the message payload data. 256 * 257 * @param pThis The IPC message. 258 */ 259 DECLINLINE(void *) IPCMsgGetPayload(PCIPCMSG pThis) 260 { 261 AssertReturn(pThis->pMsgHdr, NULL); 262 263 return pThis->pMsgHdr + 1; 264 } 265 266 267 /** 268 * Returns the size of the message payload in bytes. 269 * 270 * @param pThis The IPC message. 271 */ 272 DECLINLINE(size_t) IPCMsgGetPayloadSize(PCIPCMSG pThis) 273 { 274 AssertReturn(pThis->pMsgHdr, 0); 275 276 return pThis->pMsgHdr->cbMsg - sizeof(*pThis->pMsgHdr); 277 } 278 279 280 /** 281 * Returns whether the message is readonly (or complete). 282 * 283 * @returns Flag whether the message is readonly. 284 * @param pThis The IPC message. 285 */ 286 DECLINLINE(bool) IPCMsgIsReadonly(PCIPCMSG pThis) 287 { 288 return pThis->fReadonly; 289 } 290 291 292 /** 293 * Returns whether the given flag is set in the message header. 294 * 295 * @returns true if the flag is set false it is clear. 296 * @param pThis The IPC message. 297 * @param fFlag The flag (or combination) to check. 298 */ 299 DECLINLINE(bool) IPCMsgIsFlagSet(PCIPCMSG pThis, uint16_t fFlag) 300 { 301 return RT_BOOL(pThis->pMsgHdr->u16Flags & fFlag); 302 } 303 304 305 /** 306 * Sets the given flag in the message header. 307 * 308 * @param pThis The IPC message. 309 * @param fFlag The flag to set. 310 */ 311 DECLINLINE(void) IPCMsgSetFlag(PIPCMSG pThis, uint16_t fFlag) 312 { 313 pThis->pMsgHdr->u16Flags |= fFlag; 314 } 315 316 317 /** 318 * Init worker for a given message frame. 319 * 320 * @param pThis The message to initialize. 321 * @param target the target for the message. 322 * @param cbTotal Size of the payload in bytes. 323 * @param paSegs Pointer to the segment array making up the message payload. 324 * @param cSegs Number of segments in the array. 325 */ 326 DECLINLINE(void) ipcMsgInitWorker(PIPCMSG pThis, const nsID &target, size_t cbTotal, PCRTSGSEG paSegs, uint32_t cSegs) 327 { 328 pThis->pMsgHdr = (PIPCMSGHDR)pThis->pbBuf; 329 pThis->pMsgHdr->cbMsg = sizeof(*pThis->pMsgHdr) + cbTotal; 330 pThis->pMsgHdr->u16Version = IPC_MSG_HDR_VERSION; 331 pThis->pMsgHdr->u16Flags = 0; 332 pThis->pMsgHdr->idTarget = target; 333 334 uint8_t *pb = (uint8_t *)(pThis->pMsgHdr + 1); 335 for (uint32_t i = 0; i < cSegs; i++) 336 { 337 memcpy(pb, paSegs[i].pvSeg, paSegs[i].cbSeg); 338 pb += paSegs[i].cbSeg; 339 } 340 341 pThis->fReadonly = true; 342 } 343 344 345 /** 346 * Allocates a new message with the given target and content. 347 * 348 * @returns Pointer to the allocated message structure or NULL if out of memory. 349 * @param target The target for the message. 350 * @param cbTotal Size of the payload in bytes. 351 * @param paSegs Pointer to the segment array making up the message payload. 352 * @param cSegs Number of segments in the array. 353 */ 354 DECLINLINE(PIPCMSG) IPCMsgNewSg(const nsID &target, size_t cbTotal, PCRTSGSEG paSegs, uint32_t cSegs) 355 { 356 PIPCMSG pThis = IPCMsgAlloc(cbTotal); 357 if (RT_LIKELY(pThis)) 358 ipcMsgInitWorker(pThis, target, cbTotal, paSegs, cSegs); 359 360 return pThis; 361 } 362 363 364 /** 365 * Initializes a given message frame, growing the data buffer if necessary. 366 * 367 * @param pThis The message to initialize. 368 * @param target the target for the message. 369 * @param cbTotal Size of the payload in bytes. 370 * @param paSegs Pointer to the segment array making up the message payload. 371 * @param cSegs Number of segments in the array. 372 */ 373 DECLINLINE(int) IPCMsgInitSg(PIPCMSG pThis, const nsID &target, size_t cbTotal, PCRTSGSEG paSegs, uint32_t cSegs) 374 { 375 uint32_t cbMsg = sizeof(*pThis->pMsgHdr) + cbTotal; 376 if (pThis->cbBuf < cbMsg) 377 { 378 uint8_t *pbBufNew = (uint8_t *)RTMemRealloc(pThis->pbBuf, cbMsg); 379 if (!pbBufNew) 380 return VERR_NO_MEMORY; 381 382 pThis->pbBuf = pbBufNew; 383 pThis->cbBuf = cbMsg; 384 } 385 386 ipcMsgInitWorker(pThis, target, cbTotal, paSegs, cSegs); 387 return VINF_SUCCESS; 388 } 389 390 391 /** 392 * Reads data for the given message from the given buffer. 393 * 394 * @returns IPRT status code. 395 * @param pThis The message to read into. 396 * @param pvData The data buffer holding message data. 397 * @param cbData Size of the data buffer in bytes. 398 * @param pcbRead Where to store the number of bytes read from the data buffer. 399 * @param pfDone Where to store the flag whether the message is complete and can be parsed after returning from this call. 400 */ 401 DECLINLINE(int) IPCMsgReadFrom(PIPCMSG pThis, const void *pvData, size_t cbData, size_t *pcbRead, bool *pfDone) 402 { 403 size_t cbHdrRead = 0; 404 if (!pThis->pMsgHdr) 405 { 406 /* No full header received yet. */ 407 Assert(pThis->cbBuf >= sizeof(*pThis->pMsgHdr)); 408 409 cbHdrRead = RT_MIN(cbData, sizeof(*pThis->pMsgHdr) - pThis->offAppend); 410 memcpy(pThis->pbBuf + pThis->offAppend, pvData, cbHdrRead); 411 412 pThis->offAppend += cbHdrRead; 413 Assert(pThis->offAppend <= sizeof(*pThis->pMsgHdr)); 414 if (pThis->offAppend == sizeof(*pThis->pMsgHdr)) 415 { 416 /* Complete header received. */ 417 pThis->pMsgHdr = (PIPCMSGHDR)pThis->pbBuf; 418 419 if (pThis->pMsgHdr->cbMsg > pThis->cbBuf) 420 { 421 Assert(pThis->pMsgHdr->cbMsg < 10 * _1M); 422 423 uint8_t *pbBufNew = (uint8_t *)RTMemRealloc(pThis->pbBuf, pThis->pMsgHdr->cbMsg); 424 if (!pbBufNew) 425 return VERR_NO_MEMORY; 426 427 pThis->pbBuf = pbBufNew; 428 pThis->pMsgHdr = (PIPCMSGHDR)pbBufNew; 429 pThis->cbBuf = pThis->pMsgHdr->cbMsg; 430 } 431 432 /* fall through below after adjusting the buffer pointers. */ 433 pvData = (const uint8_t *)pvData + cbHdrRead; 434 cbData -= cbHdrRead; 435 } 436 else 437 { 438 *pfDone = false; 439 *pcbRead = cbHdrRead; 440 return VINF_SUCCESS; 441 } 442 } 443 444 Assert(pThis->pMsgHdr); 445 Assert(pThis->pMsgHdr->cbMsg <= pThis->cbBuf); 446 447 /* We know the size of the message because a full message header was received already. */ 448 size_t cbLeft = pThis->pMsgHdr->cbMsg - pThis->offAppend; 449 cbData = RT_MIN(cbData, cbLeft); 450 Assert(pThis->offAppend + cbData <= pThis->cbBuf); 451 452 if (cbData == cbLeft) 453 *pfDone = true; 454 else 455 *pfDone = false; 456 457 memcpy(pThis->pbBuf + pThis->offAppend, pvData, cbData); 458 pThis->offAppend += cbData; 459 *pcbRead = cbData + cbHdrRead; 460 return VINF_SUCCESS; 461 } 462 463 #endif // !ipcMessageNew_h__ -
trunk/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.h
r7029 r103378 39 39 #define ipcm_h__ 40 40 41 #include <iprt/assertcompile.h> 42 41 43 #include "ipcMessage.h" 42 44 #include "ipcMessagePrimitives.h" … … 118 120 PRUint32 mRequestIndex; 119 121 }; 122 AssertCompileSize(struct ipcmMessageHeader, 8); 120 123 121 124 //
Note:
See TracChangeset
for help on using the changeset viewer.