VirtualBox

Changeset 103378 in vbox


Ignore:
Timestamp:
Feb 15, 2024 8:45:24 AM (12 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
161696
Message:

libs/xpcom: Rewrite the IPCD daemon and cut down on the number of memory allocations made for messages, bugref:10598

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  
    846846        ipc/ipcd/daemon/src/ipcd.cpp \
    847847        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
    850849VBoxXPCOMIPCD_LDFLAGS.darwin = -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxXPCOMIPCD.dylib
    851850VBoxXPCOMIPCD_LIBS = \
  • trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp

    r103331 r103378  
    3636 * ***** END LICENSE BLOCK ***** */
    3737#define LOG_GROUP LOG_GROUP_IPC
     38#include <iprt/asm.h>
    3839#include <iprt/assert.h>
    3940#include <iprt/errcore.h>
     
    4243
    4344#include "ipcClient.h"
    44 #include "ipcMessage.h"
    4545#include "ipcd.h"
    4646#include "ipcm.h"
    4747
    48 PRUint32 ipcClient::gLastID = 0;
     48static volatile uint32_t g_idClientLast = 0;
     49
    4950
    5051//
     
    5455//  - object's memory has already been zero'd out.
    5556//
    56 void
    57 ipcClient::Init(uint32_t idPoll, RTSOCKET hSock)
    58 {
    59     mID = ++gLastID;
     57DECLHIDDEN(int) ipcdClientInit(PIPCDCLIENT pThis, PIPCDSTATE pIpcd, uint32_t idPoll, RTSOCKET hSock)
     58{
     59    pThis->idClient = ASMAtomicIncU32(&g_idClientLast);
    6060
    6161    // 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);
    6771
    6872    // although it is tempting to fire off the NotifyClientUp event at this
    6973    // time, we must wait until the client sends us a CLIENT_HELLO event.
    7074    // see ipcCommandModule::OnClientHello.
     75
     76    return IPCMsgInit(&pThis->MsgIn, 0 /*cbBuf*/);
    7177}
    7278
     
    7480// called when this client context is going away
    7581//
    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))
     82DECLHIDDEN(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
     99DECLHIDDEN(void) ipcdClientAddName(PIPCDCLIENT pThis, const char *pszName)
     100{
     101    LogFlowFunc(("adding client name: %s\n", pszName));
     102
     103    if (ipcdClientHasName(pThis, pszName))
    98104        return;
    99105
    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
     110DECLHIDDEN(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
     118DECLHIDDEN(void) ipcdClientAddTarget(PIPCDCLIENT pThis, const nsID *target)
    113119{
    114120    LogFlowFunc(("adding client target\n"));
    115121
    116     if (HasTarget(target))
     122    if (ipcdClientHasTarget(pThis, target))
    117123        return;
    118124
    119     mTargets.Append(target);
    120 }
    121 
    122 PRBool
    123 ipcClient::DelTarget(const nsID &target)
     125    pThis->mTargets.Append(*target);
     126}
     127
     128
     129DECLHIDDEN(bool) ipcdClientDelTarget(PIPCDCLIENT pThis, const nsID *target)
    124130{
    125131    LogFlowFunc(("deleting client target\n"));
     
    128134    // cannot remove the IPCM target
    129135    //
    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//
     145static 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
     186DECLHIDDEN(uint32_t) ipcdClientProcess(PIPCDCLIENT pThis, uint32_t fPollFlags)
     187{
     188    if (fPollFlags & RTPOLL_EVT_ERROR)
    151189    {
    152190        LogFlowFunc(("client socket appears to have closed\n"));
     
    154192    }
    155193
    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) {
    160197        LogFlowFunc(("client socket is now readable\n"));
    161198
    162         char buf[_1K];
     199        uint8_t abBuf[_1K];
    163200        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);
    165202        Assert(vrc != VINF_TRY_AGAIN);
    166203
     
    168205            return 0; // cancel connection
    169206
    170         const char *ptr = buf;
     207        const uint8_t *pb = abBuf;
    171208        while (cbRead)
    172209        {
    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            {
    177216                LogFlowFunc(("message appears to be malformed; dropping client connection\n"));
    178217                return 0;
    179218            }
    180219
    181             if (complete)
     220            if (fDone)
    182221            {
    183                 IPC_DispatchMsg(this, &mInMsg);
    184                 mInMsg.Reset();
     222                IPC_DispatchMsg(pThis, &pThis->MsgIn);
     223                IPCMsgReset(&pThis->MsgIn);
    185224            }
    186225
    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    {
    193233        LogFlowFunc(("client socket is now writable\n"));
    194234
    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  
    4242#include <iprt/socket.h>
    4343
    44 #include "ipcMessageQ.h"
     44#include "ipcMessageNew.h"
     45
    4546#include "ipcStringList.h"
    4647#include "ipcIDList.h"
    4748
    48 //-----------------------------------------------------------------------------
    49 // ipcClient
     49
     50/** Pointer to the IPCD manager state. */
     51typedef struct IPCDSTATE *PIPCDSTATE;
     52
     53/**
     54 * IPC daemon client state.
     55 *
     56 * @note Treat these as opaque and use the accessor functions below.
     57 */
     58typedef 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. */
     87typedef IPCDCLIENT *PIPCDCLIENT;
     88/** Pointer to a const IPCD client state. */
     89typedef const IPCDCLIENT *PCIPCDCLIENT;
     90
     91
     92DECLINLINE(PIPCDSTATE) ipcdClientGetDaemonState(PCIPCDCLIENT pThis)
     93{
     94    return pThis->pIpcd;
     95}
     96
     97
     98DECLINLINE(uint32_t) ipcdClientGetId(PCIPCDCLIENT pThis)
     99{
     100    return pThis->idClient;
     101}
     102
     103
     104DECLINLINE(void) ipcdClientEnqueueOutboundMsg(PIPCDCLIENT pThis, PIPCMSG pMsg)
     105{
     106    RTListAppend(&pThis->LstMsgsOut, &pMsg->NdMsg);
     107}
     108
     109DECLINLINE(bool) ipcdClientHasName(PCIPCDCLIENT pThis, const char *pszName)
     110{
     111    return pThis->mNames.Find(pszName) != NULL;
     112}
     113
     114DECLHIDDEN(void) ipcdClientAddName(PIPCDCLIENT pThis, const char *pszName);
     115
     116DECLHIDDEN(bool) ipcdClientDelName(PIPCDCLIENT pThis, const char *pszName);
     117
     118DECLINLINE(bool) ipcdClientHasTarget(PCIPCDCLIENT pThis, const nsID *target)
     119{
     120    return pThis->mTargets.Find(*target) != NULL;
     121}
     122
     123DECLHIDDEN(void) ipcdClientAddTarget(PIPCDCLIENT pThis, const nsID *target);
     124
     125DECLHIDDEN(bool) ipcdClientDelTarget(PIPCDCLIENT pThis, const nsID *target);
     126
     127DECLHIDDEN(int) ipcdClientInit(PIPCDCLIENT pThis, PIPCDSTATE pIpcd, uint32_t idPoll, RTSOCKET hSock);
     128
     129DECLHIDDEN(void) ipcdClientDestroy(PIPCDCLIENT pThis);
     130
    50131//
    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//
     143DECLHIDDEN(uint32_t) ipcdClientProcess(PIPCDCLIENT pThis, uint32_t fPollFlags);
    55144
    56 class ipcClient
     145DECLINLINE(void) ipcdClientSetExpectsSyncReply(PIPCDCLIENT pThis, bool f)
    57146{
    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}
    64149
    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 };
     150DECLINLINE(bool) ipcdClientGetExpectsSyncReply(PCIPCDCLIENT pThis)
     151{
     152    return pThis->fExpectsSyncReply;
     153}
    128154
    129155#endif // !ipcClientUnix_h__
  • trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp

    r102249 r103378  
    4040#include "ipcCommandModule.h"
    4141#include "ipcClient.h"
    42 #include "ipcMessage.h"
    43 #include "ipcMessageUtils.h"
     42#include "ipcMessageNew.h"
    4443#include "ipcd.h"
    4544#include "ipcm.h"
     
    4746#include <VBox/log.h>
    4847
    49 struct ipcCommandModule
    50 {
    51     typedef void (* MsgHandler)(ipcClient *, const ipcMessage *);
     48typedef void FNIPCMMSGHANDLER(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg);
     49/** Pointer to a IPCM message handler. */
     50typedef FNIPCMMSGHANDLER *PFNIPCMMSGHANDLER;
     51
     52
     53DECLINLINE(uint32_t) IPCM_GetType(PCIPCMSG pMsg)
     54{
     55    return ((const ipcmMessageHeader *)IPCMsgGetPayload(pMsg))->mType;
     56}
     57
     58
     59DECLINLINE(uint32_t) IPCM_GetRequestIndex(PCIPCMSG pMsg)
     60{
     61    return ((const ipcmMessageHeader *)IPCMsgGetPayload(pMsg))->mRequestIndex;
     62}
     63
     64//
     65// message handlers
     66//
     67
     68static 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
     76static 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));
    5282
    5383    //
    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.
    5589    //
    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
     93static 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)));
    187107            status = IPCM_ERROR_ALREADY_EXISTS;
    188108        }
    189109        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
     119static 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));
    206132            status = IPCM_ERROR_NO_SUCH_DATA;
    207133        }
    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
     142static 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
     162static 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
     180static 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
     202static 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
     232DECLHIDDEN(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
    297244    };
    298245
    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    {
    303251        Log(("not a request -- ignoring message\n"));
    304252        return;
    305253    }
    306254
    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    {
    310259        Log(("unknown request -- ignoring message\n"));
    311260        return;
    312261    }
    313262
    314     (handlers[type])(client, rawMsg);
    315 }
     263    aHandlers[u32Type](pIpcClient, pMsg);
     264}
  • trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h

    r1 r103378  
    3939#define ipcCommandModule_h__
    4040
    41 #include "ipcm.h" // for IPCM_TARGET
     41#include "ipcMessageNew.h"
     42#include "ipcClient.h"
    4243
    43 class ipcClient;
    44 class ipcMessage;
    45 
    46 void IPCM_HandleMsg(ipcClient *, const ipcMessage *);
     44DECLHIDDEN(void) IPCM_HandleMsg(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg);
    4745
    4846#endif // !ipcCommandModule_h__
  • trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp

    r103377 r103378  
    6161
    6262#include "ipcConfig.h"
    63 #include "ipcMessage.h"
     63#include "ipcMessageNew.h"
    6464#include "ipcClient.h"
    65 #include "ipcdPrivate.h"
     65#include "ipcCommandModule.h"
    6666#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
    6878
    6979/**
     
    7282typedef struct IPCDSTATE
    7383{
    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;
    8897} IPCDSTATE;
    8998typedef IPCDSTATE *PIPCDSTATE;
     
    251260
    252261//-----------------------------------------------------------------------------
    253 // poll list
    254 //-----------------------------------------------------------------------------
    255 
    256 //
    257 // declared in ipcdPrivate.h
    258 //
    259 DECL_HIDDEN_DATA(RTLISTANCHOR) g_LstIpcClients;
    260 static RTPOLLSET g_hPollSet = NIL_RTPOLLSET;
    261 
    262 
    263 //-----------------------------------------------------------------------------
    264262
    265263static int AddClient(PIPCDSTATE pThis, RTSOCKET hSock)
     
    273271    for (uint32_t i = 0; i < RT_ELEMENTS(pThis->ipcClientArray); i++)
    274272    {
    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             int vrc = 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);
    280278            if (RT_SUCCESS(vrc))
    281279            {
    282                 RTListAppend(&g_LstIpcClients, &pThis->ipcClientArray[i].NdClients);
     280                RTListAppend(&pThis->LstIpcClients, &pThis->ipcClientArray[i].NdClients);
    283281                pThis->ipcClientCount++;
    284282                return 0;
    285283            }
    286284
    287             pThis->ipcClientArray[i].Finalize();
     285            ipcdClientDestroy(&pThis->ipcClientArray[i]);
    288286            break;
    289287        }
     
    300298
    301299    RTListNodeRemove(&pThis->ipcClientArray[idClient].NdClients);
    302     pThis->ipcClientArray[idClient].Finalize();
     300    ipcdClientDestroy(&pThis->ipcClientArray[idClient]);
    303301    pThis->ipcClientCount--;
    304302    return 0;
     
    309307static void PollLoop(PIPCDSTATE pThis)
    310308{
    311     RTListInit(&g_LstIpcClients);
    312 
    313309    for (;;)
    314310    {
     
    356352        else
    357353        {
    358             uint32_t fNewFlags = pThis->ipcClientArray[idPoll].Process(fEvents);
     354            uint32_t fNewFlags = ipcdClientProcess(&pThis->ipcClientArray[idPoll], fEvents);
    359355            if (!fNewFlags)
    360356            {
     
    369365                }
    370366            }
    371             else if (pThis->ipcClientArray[idPoll].m_fPollEvts != fNewFlags)
     367            else if (pThis->ipcClientArray[idPoll].fPollEvts != fNewFlags)
    372368            {
    373369                /* Change flags. */
    374370                vrc = RTPollSetEventsChange(pThis->hPollSet, idPoll, fNewFlags);
    375371                AssertRC(vrc);
    376                 pThis->ipcClientArray[idPoll].m_fPollEvts = fNewFlags;
     372                pThis->ipcClientArray[idPoll].fPollEvts = fNewFlags;
    377373            }
    378374        }
     
    382378//-----------------------------------------------------------------------------
    383379
    384 PRStatus
    385 IPC_PlatformSendMsg(ipcClient  *client, ipcMessage *msg)
     380static int ipcdPlatformSendMsg(PIPCDCLIENT pIpcClient, PIPCMSG pMsg)
    386381{
    387382    LogFlowFunc(("IPC_PlatformSendMsg\n"));
    388383
    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);
    402396        AssertRC(vrc);
    403397    }
    404398
    405     return PR_SUCCESS;
     399    return VINF_SUCCESS;
     400}
     401
     402
     403//-----------------------------------------------------------------------------
     404
     405DECLHIDDEN(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
     427DECLHIDDEN(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
     446DECLHIDDEN(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
     463DECLHIDDEN(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
     483DECLHIDDEN(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
     490DECLHIDDEN(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
     520DECLHIDDEN(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
     536DECLHIDDEN(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
     549DECLHIDDEN(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;
    406559}
    407560
     
    409562static int ipcdInit(PIPCDSTATE pThis, const char *pszSocketPath)
    410563{
     564    RTListInit(&pThis->LstIpcClients);
     565    RTListInit(&pThis->LstIpcMsgsFree);
     566    pThis->cIpcMsgsFree   = 0;
    411567    pThis->fdListen       = 0;
    412568    pThis->hPollSet       = NIL_RTPOLLSET;
     
    435591            // we terminate
    436592            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);
    439595            return VERR_INVALID_PARAMETER;
    440596        }
     
    495651    }
    496652
    497     g_hPollSet = pThis->hPollSet;
    498 
    499653    vrc = RTPollSetAddSocket(pThis->hPollSet, pThis->hSockListen, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, UINT32_MAX - 1);
    500654    if (RT_FAILURE(vrc))
     
    540694        AssertRC(vrc);
    541695        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*/);
    542704    }
    543705}
  • trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h

    r101934 r103378  
    3939#define IPCD_H__
    4040
    41 #include "ipcMessage.h"
     41#include <iprt/sg.h>
    4242
    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"
    5745
    5846//-----------------------------------------------------------------------------
     
    6351//-----------------------------------------------------------------------------
    6452
    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);
     53DECLHIDDEN(int)         IPC_SendMsg(PIPCDCLIENT pIpcClient, const nsID &target, const void *pvData, size_t cbData);
     54DECLHIDDEN(int)         IPC_SendMsgSg(PIPCDCLIENT pIpcClient, const nsID &target, size_t cbTotal, PCRTSGSEG paSegs, uint32_t cSegs);
     55DECLHIDDEN(PIPCDCLIENT) IPC_GetClientByID(PIPCDSTATE pIpcd, uint32_t idClient);
     56DECLHIDDEN(PIPCDCLIENT) IPC_GetClientByName(PIPCDSTATE pIpcd, const char *pszName);
    7557
    76 //-----------------------------------------------------------------------------
    77 // other internal IPCD methods
    78 //-----------------------------------------------------------------------------
     58DECLHIDDEN(void)        IPC_PutMsgIntoCache(PIPCDSTATE pIpcd, PIPCMSG pMsg);
    7959
    8060//
    8161// dispatch message
    8262//
    83 PRStatus IPC_DispatchMsg(ipcClientHandle client, const ipcMessage *msg);
     63DECLHIDDEN(int) IPC_DispatchMsg(PIPCDCLIENT pIpcClient, PCIPCMSG pMsg);
    8464
    8565//
    8666// send message, takes ownership of |msg|.
    8767//
    88 PRStatus IPC_SendMsg(ipcClientHandle client, ipcMessage *msg);
     68DECLHIDDEN(int) IPC_SendMsg(PIPCDCLIENT pIpcClient, PIPCMSG pMsg);
    8969
    9070//
    9171// dispatch notifications about client connects and disconnects
    9272//
    93 void IPC_NotifyClientUp(ipcClientHandle client);
    94 void IPC_NotifyClientDown(ipcClientHandle client);
     73DECLHIDDEN(void) IPC_NotifyClientUp(PIPCDCLIENT pIpcClient);
     74DECLHIDDEN(void) IPC_NotifyClientDown(PIPCDCLIENT pIpcClient);
    9575
    9676#endif // !IPCD_H__
  • trunk/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.cpp

    r102334 r103378  
    4646ipcMessage::~ipcMessage()
    4747{
    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;
    5054}
    5155
     
    5357ipcMessage::Reset()
    5458{
    55     if (mMsgHdr) {
    56         RTMemFree(mMsgHdr);
    57         mMsgHdr = NULL;
    58     }
    59 
    60     mMsgOffset = 0;
     59    mMsgHdr      = NULL;
     60    mMsgOffset   = 0;
    6161    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    }
    6270}
    6371
     
    7179    // copy buf if non-null
    7280    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;
    7484    }
    7585    else
     
    8595ipcMessage::Init(const nsID &target, const char *data, PRUint32 dataLen)
    8696{
    87     if (mMsgHdr)
    88         RTMemFree(mMsgHdr);
    89 
    9097    mMsgComplete = PR_FALSE;
    9198
    9299    // allocate message data
    93100    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;
    99112
    100113    // fill in message data
     
    203216                *bytesRead = count;
    204217
    205                 if (MsgLen() > IPC_MSG_GUESSED_SIZE) {
     218                if (MsgLen() > m_cbBufMax) {
    206219                    // 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;
    208226                }
    209227            }
     
    215233            // allocate a partial buffer
    216234            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
    220245            memcpy(mMsgHdr, buf, bufLen);
    221246            mMsgOffset = bufLen;
     
    226251        else {
    227252            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;
    231262            mMsgHdr->mLen = msgLen;
    232263            mMsgOffset = 0;
  • trunk/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.h

    r1 r103378  
    100100        , mMsgOffset(0)
    101101        , mMsgComplete(PR_FALSE)
     102        , m_cbBufMax(0)
     103        , m_pvBuf(NULL)
    102104        { }
    103105    ipcMessage(const nsID &target, const char *data, PRUint32 dataLen)
     
    106108        , mMsgHdr(NULL)
    107109        , mMsgOffset(0)
     110        , m_cbBufMax(0)
     111        , m_pvBuf(NULL)
    108112        { Init(target, data, dataLen); }
    109113   ~ipcMessage() NS_HIDDEN;
     
    210214    PRUint32          mMsgOffset;
    211215    PRPackedBool      mMsgComplete;
     216
     217    size_t            m_cbBufMax;
     218    void              *m_pvBuf;
    212219};
    213220
  • trunk/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageNew.h

    r103333 r103378  
    3636 * ***** END LICENSE BLOCK ***** */
    3737
    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>
    4049
    4150#include "nsID.h"
     
    5867// is a 16 byte UUID indicating the intended receiver of this message.
    5968//
    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)
     69typedef 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;
     80AssertCompileSize(IPCMSGHDR, 4 + 2 + 2 + 16);
     81/** Pointer to the IPC message header. */
     82typedef IPCMSGHDR *PIPCMSGHDR;
     83/** Pointer to a const IPC message header. */
     84typedef const IPCMSGHDR *PCIPCMSGHDR;
     85
     86/** IPC message version. */
     87#define IPC_MSG_HDR_VERSION         UINT16_C(0x1)
    7288
    7389//
     
    7793// it is expecting a response with the SYNC_REPLY flag set.
    7894//
    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)
    8197
    8298//
     
    85101// in WaitTarget().
    86102//
    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 */
     109typedef 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. */
     125typedef IPCMSG *PIPCMSG;
     126/** Pointer to a const IPC message. */
     127typedef const IPCMSG *PCIPCMSG;
     128
     129
     130DECLINLINE(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 */
     152DECLINLINE(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 */
     180DECLINLINE(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 */
     200DECLINLINE(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 */
     213DECLINLINE(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 */
     226DECLINLINE(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 */
     240DECLINLINE(PCIPCMSGHDR) IPCMsgGetHdr(PCIPCMSG pThis)
     241{
     242    Assert(pThis->pMsgHdr);
     243    return pThis->pMsgHdr;
     244}
     245
     246
     247DECLINLINE(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 */
     259DECLINLINE(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 */
     272DECLINLINE(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 */
     286DECLINLINE(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 */
     299DECLINLINE(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 */
     311DECLINLINE(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 */
     326DECLINLINE(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 */
     354DECLINLINE(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 */
     373DECLINLINE(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 */
     401DECLINLINE(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  
    3939#define ipcm_h__
    4040
     41#include <iprt/assertcompile.h>
     42
    4143#include "ipcMessage.h"
    4244#include "ipcMessagePrimitives.h"
     
    118120    PRUint32 mRequestIndex;
    119121};
     122AssertCompileSize(struct ipcmMessageHeader, 8);
    120123
    121124//
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette