зеркало из https://github.com/mozilla/gecko-dev.git
major overhaul of daemon plug-in module story. modules now talk to the
daemon through a table of function pointers. this greatly simplifies the linker magic required to allow the modules to talk with the daemon.
This commit is contained in:
Родитель
8f024f2ebc
Коммит
9834a0c693
|
@ -59,7 +59,7 @@ ipcMessage::Reset()
|
|||
}
|
||||
|
||||
ipcMessage *
|
||||
ipcMessage::Clone()
|
||||
ipcMessage::Clone() const
|
||||
{
|
||||
ipcMessage *clone = new ipcMessage();
|
||||
if (!clone)
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
//
|
||||
// create a copy of this message
|
||||
//
|
||||
ipcMessage *Clone();
|
||||
ipcMessage *Clone() const;
|
||||
|
||||
//
|
||||
// initialize message
|
||||
|
|
|
@ -63,7 +63,6 @@ PROGRAM = mozipcd$(BIN_SUFFIX)
|
|||
|
||||
EXPORTS = \
|
||||
ipcModule.h \
|
||||
ipcd.h \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
@ -79,19 +78,19 @@ LIBS = \
|
|||
$(NULL)
|
||||
|
||||
# XXX -rdynamic is probably good for lots of other platforms
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
LIBS += -rdynamic
|
||||
endif
|
||||
#ifeq ($(OS_ARCH),Linux)
|
||||
#LIBS += -rdynamic
|
||||
#endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -DIPC_DAEMON
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
#DEFINES += -DIPC_DAEMON
|
||||
#
|
||||
#ifeq ($(OS_ARCH),WINNT)
|
||||
#
|
||||
# need to install mozipcd.lib, which contains the symbols exported by the
|
||||
# daemon that modules will need to import.
|
||||
#
|
||||
libs:: $(PROGRAM)
|
||||
$(INSTALL) mozipcd.lib $(DIST)/lib
|
||||
endif
|
||||
#libs:: $(PROGRAM)
|
||||
# $(INSTALL) mozipcd.lib $(DIST)/lib
|
||||
#endif
|
||||
|
|
|
@ -43,11 +43,6 @@
|
|||
|
||||
#ifdef XP_UNIX
|
||||
#include "prio.h"
|
||||
#include "ipcdUnix.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "ipcdWin.h"
|
||||
#endif
|
||||
|
||||
PRUint32 ipcClient::gLastID = 0;
|
||||
|
@ -129,36 +124,8 @@ ipcClient::DelTarget(const nsID &target)
|
|||
mTargets.FindAndDelete(target);
|
||||
}
|
||||
|
||||
PRBool
|
||||
ipcClient::EnqueueOutboundMsg(ipcMessage *msg)
|
||||
{
|
||||
LOG(("enqueue outbound message\n"));
|
||||
|
||||
if (!HasTarget(msg->Target())) {
|
||||
LOG((" no registered message handler\n"));
|
||||
delete msg;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
IPC_SendMessageNow(this, msg);
|
||||
delete msg;
|
||||
#endif
|
||||
|
||||
#ifdef XP_UNIX
|
||||
mOutMsgQ.Append(msg);
|
||||
//
|
||||
// the message was successfully put on the queue...
|
||||
//
|
||||
// since our Process method may have already been called, we must ensure
|
||||
// that the PR_POLL_WRITE flag is set.
|
||||
//
|
||||
IPC_ClientWritePending(this);
|
||||
#endif
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef XP_UNIX
|
||||
//
|
||||
// called to process a client socket
|
||||
//
|
||||
|
@ -260,4 +227,5 @@ ipcClient::WriteMsgs(PRFileDesc *fd)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -78,15 +78,6 @@ public:
|
|||
// returns primary client name (the one specified in the "client hello" message)
|
||||
const char *PrimaryName() const { return mNames.First() ? mNames.First()->Value() : NULL; }
|
||||
|
||||
//
|
||||
// returns TRUE if successfully enqueued. will return FALSE if client
|
||||
// does not have a registered message handler for this message's target.
|
||||
//
|
||||
// on success or failure, this function takes ownership of |msg| and will
|
||||
// delete it when appropriate.
|
||||
//
|
||||
PRBool EnqueueOutboundMsg(ipcMessage *msg);
|
||||
|
||||
#ifdef XP_WIN
|
||||
PRUint32 PID() const { return mPID; }
|
||||
void SetPID(PRUint32 pid) { mPID = pid; }
|
||||
|
@ -109,6 +100,12 @@ public:
|
|||
// the socket is non-blocking.
|
||||
//
|
||||
int Process(PRFileDesc *sockFD, int pollFlags);
|
||||
|
||||
//
|
||||
// on success or failure, this function takes ownership of |msg| and will
|
||||
// delete it when appropriate.
|
||||
//
|
||||
void EnqueueOutboundMsg(ipcMessage *msg) { mOutMsgQ.Append(msg); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
|
@ -45,25 +45,22 @@
|
|||
#include "ipcd.h"
|
||||
#include "ipcm.h"
|
||||
|
||||
typedef const char * constCharPtr;
|
||||
|
||||
class ipcCommandModule : public ipcModule
|
||||
struct ipcCommandModule
|
||||
{
|
||||
public:
|
||||
typedef void (ipcCommandModule:: *MsgHandler)(ipcClient *, const ipcMessage *);
|
||||
typedef void (* MsgHandler)(ipcClient *, const ipcMessage *);
|
||||
|
||||
//
|
||||
// message handlers
|
||||
//
|
||||
|
||||
void OnPing(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void OnPing(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
LOG(("got PING\n"));
|
||||
|
||||
IPC_SendMsg(client, new ipcmMessagePing());
|
||||
}
|
||||
|
||||
void OnClientHello(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void OnClientHello(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
LOG(("got CLIENT_HELLO\n"));
|
||||
|
||||
|
@ -75,7 +72,7 @@ public:
|
|||
IPC_SendMsg(client, new ipcmMessageClientID(client->ID()));
|
||||
}
|
||||
|
||||
void OnClientAddName(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void OnClientAddName(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
LOG(("got CLIENT_ADD_NAME\n"));
|
||||
|
||||
|
@ -85,7 +82,7 @@ public:
|
|||
client->AddName(name);
|
||||
}
|
||||
|
||||
void OnClientDelName(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void OnClientDelName(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
LOG(("got CLIENT_DEL_NAME\n"));
|
||||
|
||||
|
@ -95,7 +92,7 @@ public:
|
|||
client->DelName(name);
|
||||
}
|
||||
|
||||
void OnClientAddTarget(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void OnClientAddTarget(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
LOG(("got CLIENT_ADD_TARGET\n"));
|
||||
|
||||
|
@ -103,7 +100,7 @@ public:
|
|||
client->AddTarget(msg->Target());
|
||||
}
|
||||
|
||||
void OnClientDelTarget(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void OnClientDelTarget(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
LOG(("got CLIENT_DEL_TARGET\n"));
|
||||
|
||||
|
@ -111,7 +108,7 @@ public:
|
|||
client->DelTarget(msg->Target());
|
||||
}
|
||||
|
||||
void OnQueryClientByName(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void OnQueryClientByName(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
LOG(("got QUERY_CLIENT_BY_NAME\n"));
|
||||
|
||||
|
@ -127,7 +124,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void OnForward(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void OnForward(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
LOG(("got FORWARD\n"));
|
||||
|
||||
|
@ -145,31 +142,26 @@ public:
|
|||
// ipcModule interface impl
|
||||
//
|
||||
|
||||
void Shutdown()
|
||||
static void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
const nsID &ID()
|
||||
{
|
||||
return IPCM_TARGET;
|
||||
}
|
||||
|
||||
void HandleMsg(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static void HandleMsg(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
static MsgHandler handlers[] =
|
||||
{
|
||||
&ipcCommandModule::OnPing,
|
||||
OnPing,
|
||||
NULL, // ERROR
|
||||
&ipcCommandModule::OnClientHello,
|
||||
OnClientHello,
|
||||
NULL, // CLIENT_ID
|
||||
NULL, // CLIENT_INFO
|
||||
&ipcCommandModule::OnClientAddName,
|
||||
&ipcCommandModule::OnClientDelName,
|
||||
&ipcCommandModule::OnClientAddTarget,
|
||||
&ipcCommandModule::OnClientDelTarget,
|
||||
&ipcCommandModule::OnQueryClientByName,
|
||||
OnClientAddName,
|
||||
OnClientDelName,
|
||||
OnClientAddTarget,
|
||||
OnClientDelTarget,
|
||||
OnQueryClientByName,
|
||||
NULL, // QUERY_CLIENT_INFO
|
||||
&ipcCommandModule::OnForward,
|
||||
OnForward,
|
||||
};
|
||||
|
||||
int type = IPCM_GetMsgType(rawMsg);
|
||||
|
@ -178,14 +170,19 @@ public:
|
|||
if (type < IPCM_MSG_TYPE_UNKNOWN) {
|
||||
if (handlers[type]) {
|
||||
MsgHandler handler = handlers[type];
|
||||
(this->*handler)(client, rawMsg);
|
||||
handler(client, rawMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ipcModule *IPC_GetCommandModule()
|
||||
ipcModuleMethods *IPC_GetCommandModuleMethods()
|
||||
{
|
||||
static ipcCommandModule module;
|
||||
return &module;
|
||||
static ipcModuleMethods methods =
|
||||
{
|
||||
IPC_MODULE_METHODS_VERSION,
|
||||
ipcCommandModule::Shutdown,
|
||||
ipcCommandModule::HandleMsg
|
||||
};
|
||||
return &methods;
|
||||
}
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
#ifndef ipcCommandModule_h__
|
||||
#define ipcCommandModule_h__
|
||||
|
||||
#include "ipcm.h"
|
||||
#include "ipcm.h" // for IPCM_TARGET
|
||||
|
||||
class ipcModule *IPC_GetCommandModule();
|
||||
struct ipcModuleMethods *IPC_GetCommandModuleMethods();
|
||||
|
||||
#endif // !ipcCommandModule_h__
|
||||
|
|
|
@ -40,28 +40,42 @@
|
|||
|
||||
#include "nsID.h"
|
||||
|
||||
#define IPC_EXPORT extern "C" NS_EXPORT
|
||||
|
||||
class ipcMessage;
|
||||
class ipcClient;
|
||||
|
||||
//
|
||||
// a client handle is used to efficiently reference a client instance object
|
||||
// used by the daemon to represent a connection with a particular client app.
|
||||
//
|
||||
// modules should treat it as an opaque type.
|
||||
//
|
||||
typedef class ipcClient *ipcClientHandle;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// abstract module class
|
||||
// interface implemented by the module:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class ipcModule
|
||||
//
|
||||
// the version of ipcModuleMethods data structure.
|
||||
//
|
||||
#define IPC_MODULE_METHODS_VERSION (1<<16) // 1.0
|
||||
|
||||
//
|
||||
// each module defines the following structure:
|
||||
//
|
||||
struct ipcModuleMethods
|
||||
{
|
||||
public:
|
||||
//
|
||||
// called when this module will no longer be accessed. if this module was
|
||||
// allocated on the heap, then it can be free'd.
|
||||
// this field holds the version of the data structure, which is always the
|
||||
// value of IPC_MODULE_METHODS_VERSION against which the module was built.
|
||||
//
|
||||
virtual void Shutdown() = 0;
|
||||
PRUint32 version;
|
||||
|
||||
//
|
||||
// called to determine the ID of this module. the ID of a module
|
||||
// indicates the "message target" for which it will be registered
|
||||
// as a handler.
|
||||
// called when this module will no longer be accessed.
|
||||
//
|
||||
virtual const nsID &ID() = 0;
|
||||
void (* shutdown) (void);
|
||||
|
||||
//
|
||||
// called when a new message arrives for this module.
|
||||
|
@ -78,18 +92,125 @@ public:
|
|||
// msg - the message sent from the client. the target of this message
|
||||
// matches the ID of this module.
|
||||
//
|
||||
virtual void HandleMsg(ipcClient *client, const ipcMessage *msg) = 0;
|
||||
void (* handleMsg) (ipcClientHandle client, const ipcMessage *msg);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// interface implemented by the daemon:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// the version of ipcDaemonMethods data structure.
|
||||
//
|
||||
#define IPC_DAEMON_METHODS_VERSION (1<<16) // 1.0
|
||||
|
||||
typedef PRBool (* ipcClientEnumFunc) (void *closure, ipcClientHandle client, PRUint32 clientID);
|
||||
typedef PRBool (* ipcClientNameEnumFunc) (void *closure, ipcClientHandle client, const char *name);
|
||||
typedef PRBool (* ipcClientTargetEnumFunc) (void *closure, ipcClientHandle client, const nsID &target);
|
||||
|
||||
//
|
||||
// the daemon provides the following structure:
|
||||
//
|
||||
struct ipcDaemonMethods
|
||||
{
|
||||
PRUint32 version;
|
||||
|
||||
//
|
||||
// called to send a message to another module.
|
||||
//
|
||||
// params:
|
||||
// client - identifies the client from which this message originated.
|
||||
// msg - the message to dispatch.
|
||||
//
|
||||
// returns:
|
||||
// PR_SUCCESS if message was dispatched.
|
||||
// PR_FAILURE if message could not be dispatched (possibly because
|
||||
// no module is registered for the given message target).
|
||||
//
|
||||
PRStatus (* dispatchMsg) (ipcClientHandle client, const ipcMessage *msg);
|
||||
|
||||
//
|
||||
// called to send a message to a particular client or to broadcast a
|
||||
// message to all clients.
|
||||
//
|
||||
// params:
|
||||
// client - if null, then broadcast message to all clients. otherwise,
|
||||
// send message to the client specified.
|
||||
// msg - the message to send.
|
||||
//
|
||||
// returns:
|
||||
// PR_SUCCESS if message was sent (or queued up to be sent later).
|
||||
// PR_FAILURE if message could not be sent (possibly because the client
|
||||
// does not have a registered observer for the msg's target).
|
||||
//
|
||||
PRStatus (* sendMsg) (ipcClientHandle client, const ipcMessage *msg);
|
||||
|
||||
//
|
||||
// called to lookup a client handle given its client ID. each client has
|
||||
// a unique ID.
|
||||
//
|
||||
ipcClientHandle (* getClientByID) (PRUint32 clientID);
|
||||
|
||||
//
|
||||
// called to lookup a client by name or alias. names are not necessary
|
||||
// unique to individual clients. this function returns the client first
|
||||
// registered under the given name.
|
||||
//
|
||||
ipcClientHandle (* getClientByName) (const char *name);
|
||||
|
||||
//
|
||||
// called to enumerate all clients.
|
||||
//
|
||||
void (* enumClients) (ipcClientEnumFunc func, void *closure);
|
||||
|
||||
//
|
||||
// returns the client ID of the specified client.
|
||||
//
|
||||
PRUint32 (* getClientID) (ipcClientHandle client);
|
||||
|
||||
//
|
||||
// returns the primary client name (NULL if the client did not specify a name).
|
||||
// this is the name specified by the client in its "client hello" message.
|
||||
//
|
||||
const char * (* getPrimaryClientName) (ipcClientHandle client);
|
||||
|
||||
//
|
||||
// functions for inspecting the names and targets defined for a particular
|
||||
// client instance.
|
||||
//
|
||||
PRBool (* clientHasName) (ipcClientHandle client, const char *name);
|
||||
PRBool (* clientHasTarget) (ipcClientHandle client, const nsID &target);
|
||||
void (* enumClientNames) (ipcClientHandle client, ipcClientNameEnumFunc func, void *closure);
|
||||
void (* enumClientTargets) (ipcClientHandle client, ipcClientTargetEnumFunc func, void *closure);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// interface exported by a DSO implementing one or more modules:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ipcModuleEntry
|
||||
{
|
||||
//
|
||||
// identifies the message target of this module.
|
||||
//
|
||||
nsID target;
|
||||
|
||||
//
|
||||
// module methods
|
||||
//
|
||||
ipcModuleMethods *methods;
|
||||
};
|
||||
|
||||
//
|
||||
// factory method signature for DLLs, which may define more than one ipcModule
|
||||
// implementation. the DLL must export the following symbol:
|
||||
// IPC_EXPORT int IPC_GetModules(ipcDaemonMethods *, ipcModuleEntry **);
|
||||
//
|
||||
// extern "C" ipcModule **IPC_GetModuleList();
|
||||
// params:
|
||||
// methods - the daemon's methods
|
||||
// entries - the module entries defined by the DSO
|
||||
//
|
||||
// return:
|
||||
// null terminated array of modules.
|
||||
// returns:
|
||||
// length of the |entries| array.
|
||||
//
|
||||
typedef ipcModule ** (*ipcGetModuleListFunc)(void);
|
||||
typedef int (* ipcGetModulesFunc) (ipcDaemonMethods *methods, ipcModuleEntry **entries);
|
||||
|
||||
#endif // !ipcModule_h__
|
||||
|
|
|
@ -51,9 +51,9 @@
|
|||
|
||||
struct ipcModuleRegEntry
|
||||
{
|
||||
nsID id;
|
||||
ipcModule *module;
|
||||
PRLibrary *lib;
|
||||
nsID target;
|
||||
ipcModuleMethods *methods;
|
||||
PRLibrary *lib;
|
||||
};
|
||||
|
||||
#define IPC_MAX_MODULE_COUNT 64
|
||||
|
@ -62,15 +62,15 @@ static ipcModuleRegEntry ipcModules[IPC_MAX_MODULE_COUNT];
|
|||
static int ipcModuleCount;
|
||||
|
||||
static PRStatus
|
||||
AddModule(const nsID &id, ipcModule *module, PRLibrary *lib)
|
||||
AddModule(const nsID &target, ipcModuleMethods *methods, PRLibrary *lib)
|
||||
{
|
||||
if (ipcModuleCount == IPC_MAX_MODULE_COUNT) {
|
||||
LOG(("too many modules!\n"));
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
ipcModules[ipcModuleCount].id = id;
|
||||
ipcModules[ipcModuleCount].module = module;
|
||||
ipcModules[ipcModuleCount].target = target;
|
||||
ipcModules[ipcModuleCount].methods = methods;
|
||||
ipcModules[ipcModuleCount].lib = lib;
|
||||
|
||||
++ipcModuleCount;
|
||||
|
@ -82,6 +82,22 @@ InitModuleFromLib(const char *modulesDir, const char *fileName)
|
|||
{
|
||||
LOG(("InitModuleFromLib [%s]\n", fileName));
|
||||
|
||||
static ipcDaemonMethods gDaemonMethods =
|
||||
{
|
||||
IPC_DAEMON_METHODS_VERSION,
|
||||
IPC_DispatchMsg,
|
||||
IPC_SendMsg,
|
||||
IPC_GetClientByID,
|
||||
IPC_GetClientByName,
|
||||
IPC_EnumClients,
|
||||
IPC_GetClientID,
|
||||
IPC_GetPrimaryClientName,
|
||||
IPC_ClientHasName,
|
||||
IPC_ClientHasTarget,
|
||||
IPC_EnumClientNames,
|
||||
IPC_EnumClientTargets
|
||||
};
|
||||
|
||||
int dLen = strlen(modulesDir);
|
||||
int fLen = strlen(fileName);
|
||||
|
||||
|
@ -93,16 +109,16 @@ InitModuleFromLib(const char *modulesDir, const char *fileName)
|
|||
|
||||
PRLibrary *lib = PR_LoadLibrary(buf);
|
||||
if (lib) {
|
||||
ipcGetModuleListFunc func =
|
||||
(ipcGetModuleListFunc) PR_FindFunctionSymbol(lib, "IPC_GetModuleList");
|
||||
ipcGetModulesFunc func =
|
||||
(ipcGetModulesFunc) PR_FindFunctionSymbol(lib, "IPC_GetModules");
|
||||
|
||||
LOG((" func=%p\n", (void*) func));
|
||||
|
||||
if (func) {
|
||||
ipcModule **modules = func();
|
||||
if (modules) {
|
||||
while (*modules) {
|
||||
AddModule((*modules)->ID(), *modules, PR_LoadLibrary(buf));
|
||||
++modules;
|
||||
}
|
||||
}
|
||||
ipcModuleEntry *entries = NULL;
|
||||
int count = func(&gDaemonMethods, &entries);
|
||||
for (int i=0; i<count; ++i)
|
||||
AddModule(entries[i].target, entries[i].methods, PR_LoadLibrary(buf));
|
||||
}
|
||||
PR_UnloadLibrary(lib);
|
||||
}
|
||||
|
@ -117,13 +133,13 @@ InitModuleFromLib(const char *modulesDir, const char *fileName)
|
|||
//
|
||||
// search for a module registered under the specified id
|
||||
//
|
||||
ipcModule *
|
||||
IPC_GetModuleByID(const nsID &id)
|
||||
ipcModuleMethods *
|
||||
IPC_GetModuleByTarget(const nsID &target)
|
||||
{
|
||||
for (int i=0; i<ipcModuleCount; ++i) {
|
||||
ipcModuleRegEntry &entry = ipcModules[i];
|
||||
if (entry.id.Equals(id))
|
||||
return entry.module;
|
||||
if (entry.target.Equals(target))
|
||||
return entry.methods;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -134,8 +150,7 @@ IPC_InitModuleReg(const char *exePath)
|
|||
//
|
||||
// register built-in modules
|
||||
//
|
||||
ipcModule *module = IPC_GetCommandModule();
|
||||
AddModule(module->ID(), module, NULL);
|
||||
AddModule(IPCM_TARGET, IPC_GetCommandModuleMethods(), NULL);
|
||||
|
||||
//
|
||||
// register plug-in modules
|
||||
|
@ -186,8 +201,8 @@ IPC_ShutdownModuleReg()
|
|||
//
|
||||
for (int i = ipcModuleCount - 1; i >= 0; --i) {
|
||||
ipcModuleRegEntry &entry = ipcModules[i];
|
||||
if (entry.module)
|
||||
entry.module->Shutdown();
|
||||
if (entry.methods)
|
||||
entry.methods->shutdown();
|
||||
if (entry.lib)
|
||||
PR_UnloadLibrary(entry.lib);
|
||||
}
|
||||
|
|
|
@ -54,4 +54,9 @@ void IPC_InitModuleReg(const char *exePath);
|
|||
//
|
||||
void IPC_ShutdownModuleReg();
|
||||
|
||||
//
|
||||
// returns the ipcModuleMethods for the given target.
|
||||
//
|
||||
ipcModuleMethods *IPC_GetModuleByTarget(const nsID &target);
|
||||
|
||||
#endif // !ipcModuleReg_h__
|
||||
|
|
|
@ -52,9 +52,9 @@ PRStatus
|
|||
IPC_DispatchMsg(ipcClient *client, const ipcMessage *msg)
|
||||
{
|
||||
// lookup handler for this message's topic and forward message to it.
|
||||
ipcModule *module = IPC_GetModuleByID(msg->Target());
|
||||
if (module) {
|
||||
module->HandleMsg(client, msg);
|
||||
ipcModuleMethods *methods = IPC_GetModuleByTarget(msg->Target());
|
||||
if (methods) {
|
||||
methods->handleMsg(client, msg);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
LOG(("no registered module; ignoring message\n"));
|
||||
|
@ -62,34 +62,23 @@ IPC_DispatchMsg(ipcClient *client, const ipcMessage *msg)
|
|||
}
|
||||
|
||||
PRStatus
|
||||
IPC_SendMsg(ipcClient *client, ipcMessage *msg)
|
||||
IPC_SendMsg(ipcClient *client, const ipcMessage *msg)
|
||||
{
|
||||
if (client == NULL) {
|
||||
int i;
|
||||
//
|
||||
// walk clients array
|
||||
// broadcast
|
||||
//
|
||||
for (i = 0; i < ipcClientCount; ++i)
|
||||
IPC_SendMsg(&ipcClients[i], msg->Clone());
|
||||
|
||||
// send to last client w/o cloning to avoid extra malloc
|
||||
IPC_SendMsg(&ipcClients[i], msg);
|
||||
for (int i=0; i<ipcClientCount; ++i) {
|
||||
if (client->HasTarget(msg->Target()))
|
||||
IPC_PlatformSendMsg(&ipcClients[i], msg);
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
else
|
||||
client->EnqueueOutboundMsg(msg);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
IPC_GetClientID(ipcClient *client)
|
||||
{
|
||||
return client->ID();
|
||||
}
|
||||
|
||||
const char *
|
||||
IPC_GetPrimaryClientName(ipcClient *client)
|
||||
{
|
||||
return client->PrimaryName();
|
||||
if (!client->HasTarget(msg->Target())) {
|
||||
LOG(("no registered message handler\n"));
|
||||
return PR_FAILURE;
|
||||
}
|
||||
return IPC_PlatformSendMsg(client, msg);
|
||||
}
|
||||
|
||||
ipcClient *
|
||||
|
@ -114,6 +103,25 @@ IPC_GetClientByName(const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
IPC_EnumClients(ipcClientEnumFunc func, void *closure)
|
||||
{
|
||||
for (int i = 0; i < ipcClientCount; ++i)
|
||||
func(closure, &ipcClients[i], ipcClients[i].ID());
|
||||
}
|
||||
|
||||
PRUint32
|
||||
IPC_GetClientID(ipcClient *client)
|
||||
{
|
||||
return client->ID();
|
||||
}
|
||||
|
||||
const char *
|
||||
IPC_GetPrimaryClientName(ipcClient *client)
|
||||
{
|
||||
return client->PrimaryName();
|
||||
}
|
||||
|
||||
PRBool
|
||||
IPC_ClientHasName(ipcClient *client, const char *name)
|
||||
{
|
||||
|
@ -127,7 +135,7 @@ IPC_ClientHasTarget(ipcClient *client, const nsID &target)
|
|||
}
|
||||
|
||||
void
|
||||
IPC_EnumerateClientNames(ipcClient *client, ipcClientNameEnumFunc func, void *closure)
|
||||
IPC_EnumClientNames(ipcClient *client, ipcClientNameEnumFunc func, void *closure)
|
||||
{
|
||||
const ipcStringNode *node = client->Names();
|
||||
while (node) {
|
||||
|
@ -138,7 +146,7 @@ IPC_EnumerateClientNames(ipcClient *client, ipcClientNameEnumFunc func, void *cl
|
|||
}
|
||||
|
||||
void
|
||||
IPC_EnumerateClientTargets(ipcClient *client, ipcClientTargetEnumFunc func, void *closure)
|
||||
IPC_EnumClientTargets(ipcClient *client, ipcClientTargetEnumFunc func, void *closure)
|
||||
{
|
||||
const ipcIDNode *node = client->Targets();
|
||||
while (node) {
|
||||
|
|
|
@ -40,84 +40,24 @@
|
|||
|
||||
#include "ipcModule.h"
|
||||
|
||||
#define IPC_EXPORT extern "C" NS_EXPORT
|
||||
#define IPC_IMPORT extern "C" NS_IMPORT
|
||||
|
||||
#ifdef IPC_DAEMON
|
||||
#define IPC_API IPC_EXPORT
|
||||
#else
|
||||
#define IPC_API IPC_IMPORT
|
||||
#endif
|
||||
|
||||
class ipcClient;
|
||||
class ipcMessage;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// IPC daemon API
|
||||
// IPC daemon methods (see struct ipcDaemonMethods)
|
||||
//
|
||||
// these functions may only be called directly from within the daemon. plug-in
|
||||
// modules must access these through the ipcDaemonMethods structure.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// IPC_DispatchMsg
|
||||
//
|
||||
// params:
|
||||
// client - identifies the client from which this message originated.
|
||||
// msg - the message received. this function does not modify |msg|,
|
||||
// and ownership stays with the caller.
|
||||
//
|
||||
IPC_API PRStatus IPC_DispatchMsg(ipcClient *client, const ipcMessage *msg);
|
||||
|
||||
//
|
||||
// IPC_SendMsg
|
||||
//
|
||||
// params:
|
||||
// client - identifies the client that should receive the message.
|
||||
// if null, then the message is broadcast to all clients.
|
||||
// msg - the message to be sent. this function subsumes
|
||||
// ownership of the message. the caller must not attempt
|
||||
// to access |msg| after this function returns.
|
||||
//
|
||||
IPC_API PRStatus IPC_SendMsg(ipcClient *client, ipcMessage *msg);
|
||||
|
||||
//
|
||||
// returns the client ID dynamically generated for the given client.
|
||||
//
|
||||
IPC_API PRUint32 IPC_GetClientID(ipcClient *client);
|
||||
|
||||
//
|
||||
// returns the primary client name (NULL if the client did not specify a name).
|
||||
// this is the name specified by the client in its "client hello" message.
|
||||
//
|
||||
IPC_API const char *IPC_GetPrimaryClientName(ipcClient *client);
|
||||
|
||||
//
|
||||
// client lookup functions
|
||||
//
|
||||
IPC_API ipcClient *IPC_GetClientByID(PRUint32 id);
|
||||
IPC_API ipcClient *IPC_GetClientByName(const char *name);
|
||||
|
||||
//
|
||||
// functions for inspecting the names and targets defined for a particular
|
||||
// client instance.
|
||||
//
|
||||
IPC_API PRBool IPC_ClientHasName(ipcClient *client, const char *name);
|
||||
IPC_API PRBool IPC_ClientHasTarget(ipcClient *client, const nsID &target);
|
||||
|
||||
// return PR_FALSE to end enumeration
|
||||
typedef PRBool (* ipcClientNameEnumFunc)(void *closure, ipcClient *client, const char *name);
|
||||
typedef PRBool (* ipcClientTargetEnumFunc)(void *closure, ipcClient *client, const nsID &target);
|
||||
|
||||
IPC_API void IPC_EnumerateClientNames(ipcClient *client, ipcClientNameEnumFunc func, void *closure);
|
||||
IPC_API void IPC_EnumerateClientTargets(ipcClient *client, ipcClientTargetEnumFunc func, void *closure);
|
||||
|
||||
//
|
||||
// return array of all clients, length equal to |count|.
|
||||
//
|
||||
IPC_API ipcClient *IPC_GetClients(PRUintn *count);
|
||||
|
||||
//
|
||||
// returns the ipcModule object registered under the given module ID.
|
||||
//
|
||||
IPC_API ipcModule *IPC_GetModuleByID(const nsID &moduleID);
|
||||
PRStatus IPC_DispatchMsg (ipcClientHandle client, const ipcMessage *msg);
|
||||
PRStatus IPC_SendMsg (ipcClientHandle client, const ipcMessage *msg);
|
||||
ipcClientHandle IPC_GetClientByID (PRUint32 id);
|
||||
ipcClientHandle IPC_GetClientByName (const char *name);
|
||||
void IPC_EnumClients (ipcClientEnumFunc func, void *closure);
|
||||
PRUint32 IPC_GetClientID (ipcClientHandle client);
|
||||
const char *IPC_GetPrimaryClientName (ipcClientHandle client);
|
||||
PRBool IPC_ClientHasName (ipcClientHandle client, const char *name);
|
||||
PRBool IPC_ClientHasTarget (ipcClientHandle client, const nsID &target);
|
||||
void IPC_EnumClientNames (ipcClientHandle client, ipcClientNameEnumFunc func, void *closure);
|
||||
void IPC_EnumClientTargets (ipcClientHandle client, ipcClientTargetEnumFunc func, void *closure);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// inline helpers
|
||||
|
|
|
@ -15,4 +15,9 @@ class ipcClient;
|
|||
extern ipcClient *ipcClients;
|
||||
extern int ipcClientCount;
|
||||
|
||||
//
|
||||
// platform specific send message function.
|
||||
//
|
||||
PRStatus IPC_PlatformSendMsg(ipcClient *client, const ipcMessage *msg);
|
||||
|
||||
#endif // !ipcdPrivate_h__
|
||||
|
|
|
@ -339,11 +339,24 @@ static void PollLoop(PRFileDesc *listenFD)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
IPC_ClientWritePending(ipcClient *client)
|
||||
PRStatus
|
||||
IPC_PlatformSendMsg(ipcClient *client, const ipcMessage *msg)
|
||||
{
|
||||
LOG(("IPC_PlatformSendMsg\n"));
|
||||
|
||||
//
|
||||
// must copy message onto send queue.
|
||||
//
|
||||
client->EnqueueOutboundMsg(msg->Clone());
|
||||
|
||||
//
|
||||
// since our Process method may have already been called, we must ensure
|
||||
// that the PR_POLL_WRITE flag is set.
|
||||
//
|
||||
int clientIndex = client - ipcClientArray;
|
||||
ipcPollList[clientIndex].in_flags |= PR_POLL_WRITE;
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef ipcdUnix_h__
|
||||
#define ipcdUnix_h__
|
||||
|
||||
//
|
||||
// called by the ipcClient code to ensure that the client socket connection
|
||||
// has PR_POLL_WRITE set.
|
||||
//
|
||||
void IPC_ClientWritePending(ipcClient *);
|
||||
|
||||
#endif // !ipcdUnix_h__
|
|
@ -178,7 +178,7 @@ ProcessMsg(HWND hwnd, PRUint32 pid, const ipcMessage *msg)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
IPC_SendMessageNow(ipcClient *client, const ipcMessage *msg)
|
||||
IPC_PlatformSendMsg(ipcClient *client, const ipcMessage *msg)
|
||||
{
|
||||
LOG(("IPC_SendMessageNow [clientID=%u clientPID=%u]\n",
|
||||
client->ID(), client->PID()));
|
||||
|
@ -188,11 +188,12 @@ IPC_SendMessageNow(ipcClient *client, const ipcMessage *msg)
|
|||
cd.cbData = (DWORD) msg->MsgLen();
|
||||
cd.lpData = (PVOID) msg->MsgBuf();
|
||||
|
||||
|
||||
LOG(("calling SendMessage...\n"));
|
||||
SendMessageA(client->Hwnd(), WM_COPYDATA, 0, (LPARAM) &cd);
|
||||
// SendMessageA(hwnd, WM_COPYDATA, (WPARAM) ipcHwnd, (LPARAM) &cd);
|
||||
LOG((" done.\n"));
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef ipcdWin_h__
|
||||
#define ipcdWin_h__
|
||||
|
||||
void IPC_SendMessageNow(ipcClient *client, const ipcMessage *msg);
|
||||
|
||||
#endif // !ipcdWin_h__
|
|
@ -61,10 +61,6 @@ LOCAL_INCLUDES = \
|
|||
-I$(srcdir)/../common \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
EXTRA_DSO_LIBS = mozipcd
|
||||
endif
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(LIBS_DIR) \
|
||||
$(NSPR_LIBS) \
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#include <stdio.h>
|
||||
#include "ipcModule.h"
|
||||
#include "ipcMessage.h"
|
||||
#include "ipcd.h"
|
||||
|
||||
IPC_EXPORT ipcModule **IPC_GetModuleList();
|
||||
IPC_EXPORT int IPC_GetModules(ipcDaemonMethods *, ipcModuleEntry **);
|
||||
|
||||
static const nsID TestModuleID =
|
||||
{ /* e628fc6e-a6a7-48c7-adba-f241d1128fb8 */
|
||||
|
@ -13,38 +12,44 @@ static const nsID TestModuleID =
|
|||
{0xad, 0xba, 0xf2, 0x41, 0xd1, 0x12, 0x8f, 0xb8}
|
||||
};
|
||||
|
||||
class TestModule : public ipcModule
|
||||
static ipcDaemonMethods *gDaemonMethods;
|
||||
|
||||
struct TestModule
|
||||
{
|
||||
public:
|
||||
void Shutdown()
|
||||
static void Shutdown()
|
||||
{
|
||||
printf("*** TestModule::Shutdown\n");
|
||||
}
|
||||
|
||||
const nsID &ID()
|
||||
{
|
||||
printf("*** TestModule::ID\n");
|
||||
return TestModuleID;
|
||||
}
|
||||
|
||||
void HandleMsg(ipcClient *client, const ipcMessage *msg)
|
||||
static void HandleMsg(ipcClientHandle client, const ipcMessage *msg)
|
||||
{
|
||||
printf("*** TestModule::HandleMsg [%s]\n", msg->Data());
|
||||
ipcMessage *outMsg = new ipcMessage();
|
||||
ipcMessage outMsg;
|
||||
static const char buf[] = "pong";
|
||||
outMsg->Init(TestModuleID, buf, sizeof(buf));
|
||||
IPC_SendMsg(client, outMsg);
|
||||
outMsg.Init(TestModuleID, buf, sizeof(buf));
|
||||
gDaemonMethods->sendMsg(client, &outMsg);
|
||||
}
|
||||
};
|
||||
|
||||
ipcModule **
|
||||
IPC_GetModuleList()
|
||||
int
|
||||
IPC_GetModules(ipcDaemonMethods *daemonMeths, ipcModuleEntry **entries)
|
||||
{
|
||||
static TestModule testMod;
|
||||
static ipcModule *modules[2];
|
||||
printf("*** testmodule: IPC_GetModules\n");
|
||||
|
||||
modules[0] = &testMod;
|
||||
modules[1] = NULL;
|
||||
static ipcModuleMethods methods =
|
||||
{
|
||||
IPC_MODULE_METHODS_VERSION,
|
||||
TestModule::Shutdown,
|
||||
TestModule::HandleMsg
|
||||
};
|
||||
static ipcModuleEntry moduleEntry =
|
||||
{
|
||||
TestModuleID,
|
||||
&methods
|
||||
};
|
||||
|
||||
return modules;
|
||||
gDaemonMethods = daemonMeths;
|
||||
|
||||
*entries = &moduleEntry;
|
||||
return 1;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче