summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/ipc/ipcd/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/xpcom18a4/ipc/ipcd/daemon')
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/public/Makefile.in52
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModule.h240
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModuleUtil.h151
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/Makefile.in88
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp235
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h144
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp316
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h48
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.cpp245
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.h70
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp235
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h82
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h65
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdStub.cpp77
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp600
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdWin.cpp408
18 files changed, 3059 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/public/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/public/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/Makefile.in
new file mode 100644
index 00000000..ad1a66b7
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/Makefile.in
@@ -0,0 +1,52 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+EXPORTS = \
+ ipcModule.h \
+ ipcModuleUtil.h \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModule.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModule.h
new file mode 100644
index 00000000..2f299f70
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModule.h
@@ -0,0 +1,240 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ipcModule_h__
+#define ipcModule_h__
+
+#include "nsID.h"
+
+//
+// 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;
+
+//-----------------------------------------------------------------------------
+// interface implemented by the module:
+//-----------------------------------------------------------------------------
+
+//
+// the version of ipcModuleMethods data structure.
+//
+#define IPC_MODULE_METHODS_VERSION (1<<16) // 1.0
+
+//
+// each module defines the following structure:
+//
+struct ipcModuleMethods
+{
+ //
+ // 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.
+ //
+ PRUint32 version;
+
+ //
+ // called after this module is registered.
+ //
+ void (* init) (void);
+
+ //
+ // called when this module will no longer be accessed.
+ //
+ void (* shutdown) (void);
+
+ //
+ // called when a new message arrives for this module.
+ //
+ // params:
+ // client - an opaque "handle" to an object representing the client that
+ // sent the message. modules should not store the value of this
+ // beyond the duration fo this function call. (e.g., the handle
+ // may be invalid after this function call returns.) modules
+ // wishing to hold onto a reference to a "client" should store
+ // the client's ID (see IPC_GetClientID).
+ // target - message target
+ // data - message data
+ // dataLen - message data length
+ //
+ void (* handleMsg) (ipcClientHandle client,
+ const nsID &target,
+ const void *data,
+ PRUint32 dataLen);
+
+ //
+ // called when a new client connects to the IPC daemon.
+ //
+ void (* clientUp) (ipcClientHandle client);
+
+ //
+ // called when a client disconnects from the IPC daemon.
+ //
+ void (* clientDown) (ipcClientHandle client);
+};
+
+//-----------------------------------------------------------------------------
+// interface implemented by the daemon:
+//-----------------------------------------------------------------------------
+
+//
+// the version of ipcDaemonMethods data structure.
+//
+#define IPC_DAEMON_METHODS_VERSION (1<<16) // 1.0
+
+//
+// enumeration functions may return FALSE to stop enumeration.
+//
+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.
+ // target - message target
+ // data - message data
+ // dataLen - message data length
+ //
+ // 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 nsID &target,
+ const void *data,
+ PRUint32 dataLen);
+
+ //
+ // 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.
+ // target - message target
+ // data - message data
+ // dataLen - message data length
+ //
+ // 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 nsID &target,
+ const void *data,
+ PRUint32 dataLen);
+
+ //
+ // 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);
+
+ //
+ // 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;
+};
+
+//-----------------------------------------------------------------------------
+
+#define IPC_EXPORT extern "C" NS_EXPORT
+
+//
+// IPC_EXPORT int IPC_GetModules(const ipcDaemonMethods *, const ipcModuleEntry **);
+//
+// params:
+// methods - the daemon's methods
+// entries - the module entries defined by the DSO
+//
+// returns:
+// length of the |entries| array.
+//
+typedef int (* ipcGetModulesFunc) (const ipcDaemonMethods *methods, const ipcModuleEntry **entries);
+
+#endif // !ipcModule_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModuleUtil.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModuleUtil.h
new file mode 100644
index 00000000..0d1703a8
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModuleUtil.h
@@ -0,0 +1,151 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ipcModuleUtil_h__
+#define ipcModuleUtil_h__
+
+#include "prlog.h"
+#include "ipcModule.h"
+
+extern const ipcDaemonMethods *gIPCDaemonMethods;
+
+//-----------------------------------------------------------------------------
+// inline wrapper functions
+//
+// these functions may only be called by a module that uses the
+// IPC_IMPL_GETMODULES macro.
+//-----------------------------------------------------------------------------
+
+inline PRStatus
+IPC_DispatchMsg(ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->dispatchMsg(client, target, data, dataLen);
+}
+
+inline PRStatus
+IPC_SendMsg(ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->sendMsg(client, target, data, dataLen);
+}
+
+inline ipcClientHandle
+IPC_GetClientByID(PRUint32 id)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->getClientByID(id);
+}
+
+inline ipcClientHandle
+IPC_GetClientByName(const char *name)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->getClientByName(name);
+}
+
+inline void
+IPC_EnumClients(ipcClientEnumFunc func, void *closure)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ gIPCDaemonMethods->enumClients(func, closure);
+}
+
+inline PRUint32
+IPC_GetClientID(ipcClientHandle client)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->getClientID(client);
+}
+
+inline PRBool
+IPC_ClientHasName(ipcClientHandle client, const char *name)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->clientHasName(client, name);
+}
+
+inline PRBool
+IPC_ClientHasTarget(ipcClientHandle client, const nsID &target)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->clientHasTarget(client, target);
+}
+
+inline void
+IPC_EnumClientNames(ipcClientHandle client, ipcClientNameEnumFunc func, void *closure)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ gIPCDaemonMethods->enumClientNames(client, func, closure);
+}
+
+inline void
+IPC_EnumClientTargets(ipcClientHandle client, ipcClientTargetEnumFunc func, void *closure)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ gIPCDaemonMethods->enumClientTargets(client, func, closure);
+}
+
+//-----------------------------------------------------------------------------
+// inline composite functions
+//-----------------------------------------------------------------------------
+
+inline PRStatus
+IPC_SendMsg(PRUint32 clientID, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ ipcClient *client = IPC_GetClientByID(clientID);
+ if (!client)
+ return PR_FAILURE;
+ return IPC_SendMsg(client, target, data, dataLen);
+}
+
+//-----------------------------------------------------------------------------
+// module factory macros
+//-----------------------------------------------------------------------------
+
+#define IPC_IMPL_GETMODULES(_modName, _modEntries) \
+ const ipcDaemonMethods *gIPCDaemonMethods; \
+ IPC_EXPORT int \
+ IPC_GetModules(const ipcDaemonMethods *dmeths, \
+ const ipcModuleEntry **ents) { \
+ /* XXX do version checking */ \
+ gIPCDaemonMethods = dmeths; \
+ *ents = _modEntries; \
+ return sizeof(_modEntries) / sizeof(ipcModuleEntry); \
+ }
+
+#endif // !ipcModuleUtil_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/.cvsignore
new file mode 100644
index 00000000..8d974b7c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+mozilla-ipcd
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/Makefile.in
new file mode 100644
index 00000000..e9ef6c38
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/Makefile.in
@@ -0,0 +1,88 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+
+# required for #include "nsID.h"
+REQUIRES = \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ ipcd.cpp \
+ ipcClient.cpp \
+ ipcModuleReg.cpp \
+ ipcCommandModule.cpp
+
+ifeq ($(OS_ARCH),WINNT)
+CPPSRCS += ipcdWin.cpp
+else
+ifeq ($(OS_ARCH),BeOS)
+CPPSRCS += ipcdStub.cpp
+else
+CPPSRCS += ipcdUnix.cpp
+endif
+endif
+
+PROGRAM = mozilla-ipcd$(BIN_SUFFIX)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../shared/src \
+ $(NULL)
+
+include $(topsrcdir)/config/config.mk
+
+LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)ipcdshared_s.$(LIB_SUFFIX) \
+ $(EXTRA_DSO_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+# For fruncate
+ifeq ($(OS_ARCH),Linux)
+DEFINES += -D_BSD_SOURCE
+endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp
new file mode 100644
index 00000000..4f68d175
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp
@@ -0,0 +1,235 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ipcLog.h"
+#include "ipcClient.h"
+#include "ipcMessage.h"
+#include "ipcModuleReg.h"
+#include "ipcd.h"
+#include "ipcm.h"
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+#include "prio.h"
+#endif
+
+PRUint32 ipcClient::gLastID = 0;
+
+//
+// called to initialize this client context
+//
+// assumptions:
+// - object's memory has already been zero'd out.
+//
+void
+ipcClient::Init()
+{
+ mID = ++gLastID;
+
+ // every client must be able to handle IPCM messages.
+ mTargets.Append(IPCM_TARGET);
+
+ // although it is tempting to fire off the NotifyClientUp event at this
+ // time, we must wait until the client sends us a CLIENT_HELLO event.
+ // see ipcCommandModule::OnClientHello.
+}
+
+//
+// called when this client context is going away
+//
+void
+ipcClient::Finalize()
+{
+ IPC_NotifyClientDown(this);
+
+ mNames.DeleteAll();
+ mTargets.DeleteAll();
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+ mInMsg.Reset();
+ mOutMsgQ.DeleteAll();
+#endif
+}
+
+void
+ipcClient::AddName(const char *name)
+{
+ LOG(("adding client name: %s\n", name));
+
+ if (HasName(name))
+ return;
+
+ mNames.Append(name);
+}
+
+PRBool
+ipcClient::DelName(const char *name)
+{
+ LOG(("deleting client name: %s\n", name));
+
+ return mNames.FindAndDelete(name);
+}
+
+void
+ipcClient::AddTarget(const nsID &target)
+{
+ LOG(("adding client target\n"));
+
+ if (HasTarget(target))
+ return;
+
+ mTargets.Append(target);
+}
+
+PRBool
+ipcClient::DelTarget(const nsID &target)
+{
+ LOG(("deleting client target\n"));
+
+ //
+ // cannot remove the IPCM target
+ //
+ if (!target.Equals(IPCM_TARGET))
+ return mTargets.FindAndDelete(target);
+
+ return PR_FALSE;
+}
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+
+//
+// called to process a client socket
+//
+// params:
+// fd - the client socket
+// poll_flags - the state of the client socket
+//
+// return:
+// 0 - to end session with this client
+// PR_POLL_READ - to wait for the client socket to become readable
+// PR_POLL_WRITE - to wait for the client socket to become writable
+//
+int
+ipcClient::Process(PRFileDesc *fd, int inFlags)
+{
+ if (inFlags & (PR_POLL_ERR | PR_POLL_HUP |
+ PR_POLL_EXCEPT | PR_POLL_NVAL)) {
+ LOG(("client socket appears to have closed\n"));
+ return 0;
+ }
+
+ // expect to wait for more data
+ int outFlags = PR_POLL_READ;
+
+ if (inFlags & PR_POLL_READ) {
+ LOG(("client socket is now readable\n"));
+
+ char buf[1024]; // XXX make this larger?
+ PRInt32 n;
+
+ // find out how much data is available for reading...
+ // n = PR_Available(fd);
+
+ n = PR_Read(fd, buf, sizeof(buf));
+ if (n <= 0)
+ return 0; // cancel connection
+
+ const char *ptr = buf;
+ while (n) {
+ PRUint32 nread;
+ PRBool complete;
+
+ if (mInMsg.ReadFrom(ptr, PRUint32(n), &nread, &complete) == PR_FAILURE) {
+ LOG(("message appears to be malformed; dropping client connection\n"));
+ return 0;
+ }
+
+ if (complete) {
+ IPC_DispatchMsg(this, &mInMsg);
+ mInMsg.Reset();
+ }
+
+ n -= nread;
+ ptr += nread;
+ }
+ }
+
+ if (inFlags & PR_POLL_WRITE) {
+ LOG(("client socket is now writable\n"));
+
+ if (mOutMsgQ.First())
+ WriteMsgs(fd);
+ }
+
+ if (mOutMsgQ.First())
+ outFlags |= PR_POLL_WRITE;
+
+ return outFlags;
+}
+
+//
+// called to write out any messages from the outgoing queue.
+//
+int
+ipcClient::WriteMsgs(PRFileDesc *fd)
+{
+ while (mOutMsgQ.First()) {
+ const char *buf = (const char *) mOutMsgQ.First()->MsgBuf();
+ PRInt32 bufLen = (PRInt32) mOutMsgQ.First()->MsgLen();
+
+ if (mSendOffset) {
+ buf += mSendOffset;
+ bufLen -= mSendOffset;
+ }
+
+ PRInt32 nw = PR_Write(fd, buf, bufLen);
+ if (nw <= 0)
+ break;
+
+ LOG(("wrote %d bytes\n", nw));
+
+ if (nw == bufLen) {
+ mOutMsgQ.DeleteFirst();
+ mSendOffset = 0;
+ }
+ else
+ mSendOffset += nw;
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h
new file mode 100644
index 00000000..12e479cf
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h
@@ -0,0 +1,144 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ipcClientUnix_h__
+#define ipcClientUnix_h__
+
+#include "prio.h"
+#include "ipcMessageQ.h"
+#include "ipcStringList.h"
+#include "ipcIDList.h"
+
+#ifdef XP_WIN
+#include <windows.h>
+#endif
+
+//-----------------------------------------------------------------------------
+// ipcClient
+//
+// NOTE: this class is an implementation detail of the IPC daemon. IPC daemon
+// modules (other than the built-in IPCM module) must not access methods on
+// this class directly. use the API provided via ipcd.h instead.
+//-----------------------------------------------------------------------------
+
+class ipcClient
+{
+public:
+ void Init();
+ void Finalize();
+
+ PRUint32 ID() const { return mID; }
+
+ void AddName(const char *name);
+ PRBool DelName(const char *name);
+ PRBool HasName(const char *name) const { return mNames.Find(name) != NULL; }
+
+ void AddTarget(const nsID &target);
+ PRBool DelTarget(const nsID &target);
+ PRBool HasTarget(const nsID &target) const { return mTargets.Find(target) != NULL; }
+
+ // list iterators
+ const ipcStringNode *Names() const { return mNames.First(); }
+ const ipcIDNode *Targets() const { return mTargets.First(); }
+
+ // returns primary client name (the one specified in the "client hello" message)
+ const char *PrimaryName() const { return mNames.First() ? mNames.First()->Value() : NULL; }
+
+ void SetExpectsSyncReply(PRBool val) { mExpectsSyncReply = val; }
+ PRBool GetExpectsSyncReply() const { return mExpectsSyncReply; }
+
+#ifdef XP_WIN
+ PRUint32 PID() const { return mPID; }
+ void SetPID(PRUint32 pid) { mPID = pid; }
+
+ HWND Hwnd() const { return mHwnd; }
+ void SetHwnd(HWND hwnd) { mHwnd = hwnd; }
+#endif
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+ //
+ // called to process a client file descriptor. the value of pollFlags
+ // indicates the state of the socket.
+ //
+ // returns:
+ // 0 - to cancel client connection
+ // PR_POLL_READ - to poll for a readable socket
+ // PR_POLL_WRITE - to poll for a writable socket
+ // (both flags) - to poll for either a readable or writable socket
+ //
+ // 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:
+ static PRUint32 gLastID;
+
+ PRUint32 mID;
+ ipcStringList mNames;
+ ipcIDList mTargets;
+ PRBool mExpectsSyncReply;
+
+#ifdef XP_WIN
+ // on windows, we store the PID of the client process to help us determine
+ // the client from which a message originated. each message has the PID
+ // encoded in it.
+ PRUint32 mPID;
+
+ // the hwnd of the client's message window.
+ HWND mHwnd;
+#endif
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+ ipcMessage mInMsg; // buffer for incoming message
+ ipcMessageQ mOutMsgQ; // outgoing message queue
+
+ // keep track of the amount of the first message sent
+ PRUint32 mSendOffset;
+
+ // utility function for writing out messages.
+ int WriteMsgs(PRFileDesc *fd);
+#endif
+};
+
+#endif // !ipcClientUnix_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp
new file mode 100644
index 00000000..43ac547c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp
@@ -0,0 +1,316 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdlib.h>
+#include <string.h>
+#include "ipcLog.h"
+#include "ipcCommandModule.h"
+#include "ipcModule.h"
+#include "ipcClient.h"
+#include "ipcMessage.h"
+#include "ipcMessageUtils.h"
+#include "ipcModuleReg.h"
+#include "ipcd.h"
+#include "ipcm.h"
+
+struct ipcCommandModule
+{
+ typedef void (* MsgHandler)(ipcClient *, const ipcMessage *);
+
+ //
+ // helpers
+ //
+
+ static char **
+ BuildStringArray(const ipcStringNode *nodes)
+ {
+ size_t count = 0;
+
+ const ipcStringNode *node;
+
+ for (node = nodes; node; node = node->mNext)
+ count++;
+
+ char **strs = (char **) malloc((count + 1) * sizeof(char *));
+ if (!strs)
+ return NULL;
+
+ count = 0;
+ for (node = nodes; node; node = node->mNext, ++count)
+ strs[count] = (char *) node->Value();
+ strs[count] = 0;
+
+ return strs;
+ }
+
+ static nsID **
+ BuildIDArray(const ipcIDNode *nodes)
+ {
+ size_t count = 0;
+
+ const ipcIDNode *node;
+
+ for (node = nodes; node; node = node->mNext)
+ count++;
+
+ nsID **ids = (nsID **) calloc(count + 1, sizeof(nsID *));
+ if (!ids)
+ return NULL;
+
+ count = 0;
+ for (node = nodes; node; node = node->mNext, ++count)
+ ids[count] = (nsID *) &node->Value();
+
+ return ids;
+ }
+
+ //
+ // message handlers
+ //
+
+ static void
+ OnPing(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got PING\n"));
+
+ IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
+ }
+
+ static void
+ OnClientHello(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_HELLO\n"));
+
+ IPC_SendMsg(client, new ipcmMessageClientID(IPCM_GetRequestIndex(rawMsg), client->ID()));
+
+ //
+ // NOTE: it would almost make sense for this notification to live
+ // in the transport layer code. however, clients expect to receive
+ // a CLIENT_ID as the first message following a CLIENT_HELLO, so we
+ // must not allow modules to see a client until after we have sent
+ // the CLIENT_ID message.
+ //
+ IPC_NotifyClientUp(client);
+ }
+
+ static void
+ OnClientAddName(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_ADD_NAME\n"));
+
+ PRInt32 status = IPCM_OK;
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageClientAddName> msg(rawMsg);
+ const char *name = msg->Name();
+ if (name) {
+ ipcClient *result = IPC_GetClientByName(msg->Name());
+ if (result) {
+ LOG((" client with such name already exists (ID = %d)\n", result->ID()));
+ status = IPCM_ERROR_ALREADY_EXISTS;
+ }
+ else
+ client->AddName(name);
+ }
+ else
+ status = IPCM_ERROR_INVALID_ARG;
+
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status));
+ }
+
+ static void
+ OnClientDelName(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_DEL_NAME\n"));
+
+ PRInt32 status = IPCM_OK;
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageClientDelName> msg(rawMsg);
+ const char *name = msg->Name();
+ if (name) {
+ if (!client->DelName(name)) {
+ LOG((" client doesn't have name '%s'\n", name));
+ status = IPCM_ERROR_NO_SUCH_DATA;
+ }
+ }
+ else
+ status = IPCM_ERROR_INVALID_ARG;
+
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status));
+ }
+
+ static void
+ OnClientAddTarget(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_ADD_TARGET\n"));
+
+ PRInt32 status = IPCM_OK;
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageClientAddTarget> msg(rawMsg);
+ if (client->HasTarget(msg->Target())) {
+ LOG((" target already defined for client\n"));
+ status = IPCM_ERROR_ALREADY_EXISTS;
+ }
+ else
+ client->AddTarget(msg->Target());
+
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status));
+ }
+
+ static void
+ OnClientDelTarget(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_DEL_TARGET\n"));
+
+ PRInt32 status = IPCM_OK;
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageClientDelTarget> msg(rawMsg);
+ if (!client->DelTarget(msg->Target())) {
+ LOG((" client doesn't have the given target\n"));
+ status = IPCM_ERROR_NO_SUCH_DATA;
+ }
+
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status));
+ }
+
+ static void
+ OnQueryClientByName(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got QUERY_CLIENT_BY_NAME\n"));
+
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageQueryClientByName> msg(rawMsg);
+
+ ipcClient *result = IPC_GetClientByName(msg->Name());
+ if (result) {
+ LOG((" client exists w/ ID = %u\n", result->ID()));
+ IPC_SendMsg(client, new ipcmMessageClientID(requestIndex, result->ID()));
+ }
+ else {
+ LOG((" client does not exist\n"));
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, IPCM_ERROR_NO_CLIENT));
+ }
+ }
+
+#if 0
+ static void
+ OnQueryClientInfo(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got QUERY_CLIENT_INFO\n"));
+
+ ipcMessageCast<ipcmMessageQueryClientInfo> msg(rawMsg);
+ ipcClient *result = IPC_GetClientByID(msg->ClientID());
+ if (result) {
+ char **names = BuildStringArray(result->Names());
+ nsID **targets = BuildIDArray(result->Targets());
+
+ IPC_SendMsg(client, new ipcmMessageClientInfo(result->ID(),
+ msg->RequestIndex(),
+ (const char **) names,
+ (const nsID **) targets));
+
+ free(names);
+ free(targets);
+ }
+ else {
+ LOG((" client does not exist\n"));
+ IPC_SendMsg(client, new ipcmMessageError(IPCM_ERROR_NO_CLIENT, msg->RequestIndex()));
+ }
+ }
+#endif
+
+ static void
+ OnForward(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got FORWARD\n"));
+
+ ipcMessageCast<ipcmMessageForward> msg(rawMsg);
+
+ ipcClient *dest = IPC_GetClientByID(msg->ClientID());
+ if (!dest) {
+ LOG((" destination client not found!\n"));
+ IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_ERROR_NO_CLIENT));
+ return;
+ }
+ // inform client that its message will be forwarded
+ IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
+
+ ipcMessage *newMsg = new ipcmMessageForward(IPCM_MSG_PSH_FORWARD,
+ client->ID(),
+ msg->InnerTarget(),
+ msg->InnerData(),
+ msg->InnerDataLen());
+ IPC_SendMsg(dest, newMsg);
+ }
+};
+
+void
+IPCM_HandleMsg(ipcClient *client, const ipcMessage *rawMsg)
+{
+ static ipcCommandModule::MsgHandler handlers[] =
+ {
+ ipcCommandModule::OnPing,
+ ipcCommandModule::OnForward,
+ ipcCommandModule::OnClientHello,
+ ipcCommandModule::OnClientAddName,
+ ipcCommandModule::OnClientDelName,
+ ipcCommandModule::OnClientAddTarget,
+ ipcCommandModule::OnClientDelTarget,
+ ipcCommandModule::OnQueryClientByName
+ };
+
+ int type = IPCM_GetType(rawMsg);
+ LOG(("IPCM_HandleMsg [type=%x]\n", type));
+
+ if (!(type & IPCM_MSG_CLASS_REQ)) {
+ LOG(("not a request -- ignoring message\n"));
+ return;
+ }
+
+ type &= ~IPCM_MSG_CLASS_REQ;
+ type--;
+ if (type < 0 || type >= (int) (sizeof(handlers)/sizeof(handlers[0]))) {
+ LOG(("unknown request -- ignoring message\n"));
+ return;
+ }
+
+ (handlers[type])(client, rawMsg);
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h
new file mode 100644
index 00000000..ea146cdc
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h
@@ -0,0 +1,48 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ipcCommandModule_h__
+#define ipcCommandModule_h__
+
+#include "ipcm.h" // for IPCM_TARGET
+
+class ipcClient;
+class ipcMessage;
+
+void IPCM_HandleMsg(ipcClient *, const ipcMessage *);
+
+#endif // !ipcCommandModule_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.cpp
new file mode 100644
index 00000000..09e60ab9
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.cpp
@@ -0,0 +1,245 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "prlink.h"
+#include "prio.h"
+#include "prlog.h"
+#include "plstr.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcModuleReg.h"
+#include "ipcModule.h"
+#include "ipcCommandModule.h"
+#include "ipcd.h"
+
+//-----------------------------------------------------------------------------
+
+struct ipcModuleRegEntry
+{
+ nsID target;
+ ipcModuleMethods *methods;
+ PRLibrary *lib;
+};
+
+#define IPC_MAX_MODULE_COUNT 64
+
+static ipcModuleRegEntry ipcModules[IPC_MAX_MODULE_COUNT];
+static int ipcModuleCount = 0;
+
+//-----------------------------------------------------------------------------
+
+static PRStatus
+AddModule(const nsID &target, ipcModuleMethods *methods, const char *libPath)
+{
+ if (ipcModuleCount == IPC_MAX_MODULE_COUNT) {
+ LOG(("too many modules!\n"));
+ return PR_FAILURE;
+ }
+
+ if (!methods) {
+ PR_NOT_REACHED("null module methods");
+ return PR_FAILURE;
+ }
+
+ //
+ // each ipcModuleRegEntry holds a reference to a PRLibrary, and on
+ // shutdown, each PRLibrary reference will be released. this ensures
+ // that the library will not be unloaded until all of the modules in
+ // that library are shutdown.
+ //
+ ipcModules[ipcModuleCount].target = target;
+ ipcModules[ipcModuleCount].methods = methods;
+ ipcModules[ipcModuleCount].lib = PR_LoadLibrary(libPath);
+
+ ++ipcModuleCount;
+ return PR_SUCCESS;
+}
+
+static void
+InitModuleFromLib(const char *modulesDir, const char *fileName)
+{
+ LOG(("InitModuleFromLib [%s]\n", fileName));
+
+ static const ipcDaemonMethods gDaemonMethods =
+ {
+ IPC_DAEMON_METHODS_VERSION,
+ IPC_DispatchMsg,
+ IPC_SendMsg,
+ IPC_GetClientByID,
+ IPC_GetClientByName,
+ IPC_EnumClients,
+ IPC_GetClientID,
+ IPC_ClientHasName,
+ IPC_ClientHasTarget,
+ IPC_EnumClientNames,
+ IPC_EnumClientTargets
+ };
+
+ int dLen = strlen(modulesDir);
+ int fLen = strlen(fileName);
+
+ char *buf = (char *) malloc(dLen + 1 + fLen + 1);
+ memcpy(buf, modulesDir, dLen);
+ buf[dLen] = IPC_PATH_SEP_CHAR;
+ memcpy(buf + dLen + 1, fileName, fLen);
+ buf[dLen + 1 + fLen] = '\0';
+
+ PRLibrary *lib = PR_LoadLibrary(buf);
+ if (lib) {
+ ipcGetModulesFunc func =
+ (ipcGetModulesFunc) PR_FindFunctionSymbol(lib, "IPC_GetModules");
+
+ LOG((" func=%p\n", (void*) func));
+
+ if (func) {
+ const ipcModuleEntry *entries = NULL;
+ int count = func(&gDaemonMethods, &entries);
+ for (int i=0; i<count; ++i) {
+ if (AddModule(entries[i].target, entries[i].methods, buf) == PR_SUCCESS) {
+ if (entries[i].methods->init)
+ entries[i].methods->init();
+ }
+ }
+ }
+ PR_UnloadLibrary(lib);
+ }
+
+ free(buf);
+}
+
+//-----------------------------------------------------------------------------
+// ipcModuleReg API
+//-----------------------------------------------------------------------------
+
+void
+IPC_InitModuleReg(const char *exePath)
+{
+ if (!(exePath && *exePath))
+ return;
+
+ //
+ // register plug-in modules
+ //
+ char *p = PL_strrchr(exePath, IPC_PATH_SEP_CHAR);
+ if (p == NULL) {
+ LOG(("unexpected exe path\n"));
+ return;
+ }
+
+ int baseLen = p - exePath;
+ int finalLen = baseLen + 1 + sizeof(IPC_MODULES_DIR);
+
+ // build full path to ipc modules
+ char *modulesDir = (char*) malloc(finalLen);
+ memcpy(modulesDir, exePath, baseLen);
+ modulesDir[baseLen] = IPC_PATH_SEP_CHAR;
+ memcpy(modulesDir + baseLen + 1, IPC_MODULES_DIR, sizeof(IPC_MODULES_DIR));
+
+ LOG(("loading libraries in %s\n", modulesDir));
+ //
+ // scan directory for IPC modules
+ //
+ PRDir *dir = PR_OpenDir(modulesDir);
+ if (dir) {
+ PRDirEntry *ent;
+ while ((ent = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
+ //
+ // locate extension, and check if dynamic library
+ //
+
+ const char *p = strrchr(ent->name, '.');
+ if (p && PL_strcasecmp(p, MOZ_DLL_SUFFIX) == 0)
+ InitModuleFromLib(modulesDir, ent->name);
+ }
+ PR_CloseDir(dir);
+ }
+
+ free(modulesDir);
+}
+
+void
+IPC_ShutdownModuleReg()
+{
+ //
+ // shutdown modules in reverse order
+ //
+ while (ipcModuleCount) {
+ ipcModuleRegEntry &entry = ipcModules[--ipcModuleCount];
+ if (entry.methods->shutdown)
+ entry.methods->shutdown();
+ if (entry.lib)
+ PR_UnloadLibrary(entry.lib);
+ }
+}
+
+void
+IPC_NotifyModulesClientUp(ipcClient *client)
+{
+ for (int i = 0; i < ipcModuleCount; ++i) {
+ ipcModuleRegEntry &entry = ipcModules[i];
+ if (entry.methods->clientUp)
+ entry.methods->clientUp(client);
+ }
+}
+
+void
+IPC_NotifyModulesClientDown(ipcClient *client)
+{
+ for (int i = 0; i < ipcModuleCount; ++i) {
+ ipcModuleRegEntry &entry = ipcModules[i];
+ if (entry.methods->clientDown)
+ entry.methods->clientDown(client);
+ }
+}
+
+PRStatus
+IPC_DispatchMsg(ipcClient *client, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ // dispatch message to every module registered under the given target.
+ for (int i=0; i<ipcModuleCount; ++i) {
+ ipcModuleRegEntry &entry = ipcModules[i];
+ if (entry.target.Equals(target)) {
+ if (entry.methods->handleMsg)
+ entry.methods->handleMsg(client, target, data, dataLen);
+ }
+ }
+ return PR_SUCCESS;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.h
new file mode 100644
index 00000000..d3fecd6c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.h
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ipcModuleReg_h__
+#define ipcModuleReg_h__
+
+#include "ipcModule.h"
+
+//
+// called to init the module registry. this may only be called once at
+// startup or once after calling IPC_ShutdownModuleReg.
+//
+// params:
+// exePath - path to the daemon executable. modules are loaded from a
+// directory relative to the daemon executable.
+//
+void IPC_InitModuleReg(const char *exePath);
+
+//
+// called to shutdown the module registry. this may be called more than
+// once and need not follow a call to IPC_InitModuleReg.
+//
+void IPC_ShutdownModuleReg();
+
+//
+// returns the ipcModuleMethods for the given target.
+//
+ipcModuleMethods *IPC_GetModuleByTarget(const nsID &target);
+
+//
+// notifies all modules of client connect/disconnect
+//
+void IPC_NotifyModulesClientUp(ipcClient *);
+void IPC_NotifyModulesClientDown(ipcClient *);
+
+#endif // !ipcModuleReg_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp
new file mode 100644
index 00000000..60aca34a
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp
@@ -0,0 +1,235 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "prlog.h"
+#include "prio.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcMessage.h"
+#include "ipcClient.h"
+#include "ipcModuleReg.h"
+#include "ipcModule.h"
+#include "ipcCommandModule.h"
+#include "ipcdPrivate.h"
+#include "ipcd.h"
+
+//-----------------------------------------------------------------------------
+
+void
+IPC_NotifyParent()
+{
+ PRFileDesc *fd = PR_GetInheritedFD(IPC_STARTUP_PIPE_NAME);
+ if (fd) {
+ char c = IPC_STARTUP_PIPE_MAGIC;
+ PR_Write(fd, &c, 1);
+ PR_Close(fd);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+PRStatus
+IPC_DispatchMsg(ipcClient *client, const ipcMessage *msg)
+{
+ PR_ASSERT(client);
+ PR_ASSERT(msg);
+
+ // remember if client is expecting SYNC_REPLY. we'll add that flag to the
+ // next message sent to the client.
+ if (msg->TestFlag(IPC_MSG_FLAG_SYNC_QUERY)) {
+ PR_ASSERT(client->GetExpectsSyncReply() == PR_FALSE);
+ // XXX shouldn't we remember the TargetID as well, and only set the
+ // SYNC_REPLY flag on the next message sent to the same TargetID?
+ client->SetExpectsSyncReply(PR_TRUE);
+ }
+
+ if (msg->Target().Equals(IPCM_TARGET)) {
+ IPCM_HandleMsg(client, msg);
+ return PR_SUCCESS;
+ }
+
+ return IPC_DispatchMsg(client, msg->Target(), msg->Data(), msg->DataLen());
+}
+
+PRStatus
+IPC_SendMsg(ipcClient *client, ipcMessage *msg)
+{
+ PR_ASSERT(msg);
+
+ if (client == NULL) {
+ //
+ // broadcast
+ //
+ for (int i=0; i<ipcClientCount; ++i)
+ IPC_SendMsg(&ipcClients[i], msg->Clone());
+ delete msg;
+ return PR_SUCCESS;
+ }
+
+ // add SYNC_REPLY flag to message if client is expecting...
+ if (client->GetExpectsSyncReply()) {
+ msg->SetFlag(IPC_MSG_FLAG_SYNC_REPLY);
+ client->SetExpectsSyncReply(PR_FALSE);
+ }
+
+ if (client->HasTarget(msg->Target()))
+ return IPC_PlatformSendMsg(client, msg);
+
+ LOG((" no registered message handler\n"));
+ return PR_FAILURE;
+}
+
+void
+IPC_NotifyClientUp(ipcClient *client)
+{
+ LOG(("IPC_NotifyClientUp: clientID=%d\n", client->ID()));
+
+ // notify modules before other clients
+ IPC_NotifyModulesClientUp(client);
+
+ for (int i=0; i<ipcClientCount; ++i) {
+ if (&ipcClients[i] != client)
+ IPC_SendMsg(&ipcClients[i],
+ new ipcmMessageClientState(client->ID(), IPCM_CLIENT_STATE_UP));
+ }
+}
+
+void
+IPC_NotifyClientDown(ipcClient *client)
+{
+ LOG(("IPC_NotifyClientDown: clientID=%d\n", client->ID()));
+
+ // notify modules before other clients
+ IPC_NotifyModulesClientDown(client);
+
+ for (int i=0; i<ipcClientCount; ++i) {
+ if (&ipcClients[i] != client)
+ IPC_SendMsg(&ipcClients[i],
+ new ipcmMessageClientState(client->ID(), IPCM_CLIENT_STATE_DOWN));
+ }
+}
+
+//-----------------------------------------------------------------------------
+// IPC daemon methods
+//-----------------------------------------------------------------------------
+
+PRStatus
+IPC_SendMsg(ipcClient *client, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ return IPC_SendMsg(client, new ipcMessage(target, (const char *) data, dataLen));
+}
+
+ipcClient *
+IPC_GetClientByID(PRUint32 clientID)
+{
+ // linear search OK since number of clients should be small
+ for (int i = 0; i < ipcClientCount; ++i) {
+ if (ipcClients[i].ID() == clientID)
+ return &ipcClients[i];
+ }
+ return NULL;
+}
+
+ipcClient *
+IPC_GetClientByName(const char *name)
+{
+ // linear search OK since number of clients should be small
+ for (int i = 0; i < ipcClientCount; ++i) {
+ if (ipcClients[i].HasName(name))
+ return &ipcClients[i];
+ }
+ return NULL;
+}
+
+void
+IPC_EnumClients(ipcClientEnumFunc func, void *closure)
+{
+ PR_ASSERT(func);
+ for (int i = 0; i < ipcClientCount; ++i) {
+ if (func(closure, &ipcClients[i], ipcClients[i].ID()) == PR_FALSE)
+ break;
+ }
+}
+
+PRUint32
+IPC_GetClientID(ipcClient *client)
+{
+ PR_ASSERT(client);
+ return client->ID();
+}
+
+PRBool
+IPC_ClientHasName(ipcClient *client, const char *name)
+{
+ PR_ASSERT(client);
+ PR_ASSERT(name);
+ return client->HasName(name);
+}
+
+PRBool
+IPC_ClientHasTarget(ipcClient *client, const nsID &target)
+{
+ PR_ASSERT(client);
+ return client->HasTarget(target);
+}
+
+void
+IPC_EnumClientNames(ipcClient *client, ipcClientNameEnumFunc func, void *closure)
+{
+ PR_ASSERT(client);
+ PR_ASSERT(func);
+ const ipcStringNode *node = client->Names();
+ while (node) {
+ if (func(closure, client, node->Value()) == PR_FALSE)
+ break;
+ node = node->mNext;
+ }
+}
+
+void
+IPC_EnumClientTargets(ipcClient *client, ipcClientTargetEnumFunc func, void *closure)
+{
+ PR_ASSERT(client);
+ PR_ASSERT(func);
+ const ipcIDNode *node = client->Targets();
+ while (node) {
+ if (func(closure, client, node->Value()) == PR_FALSE)
+ break;
+ node = node->mNext;
+ }
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h
new file mode 100644
index 00000000..5a0f2c2a
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h
@@ -0,0 +1,82 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef IPCD_H__
+#define IPCD_H__
+
+#include "ipcModule.h"
+#include "ipcMessage.h"
+
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+
+PRStatus IPC_DispatchMsg (ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen);
+PRStatus IPC_SendMsg (ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen);
+ipcClientHandle IPC_GetClientByID (PRUint32 id);
+ipcClientHandle IPC_GetClientByName (const char *name);
+void IPC_EnumClients (ipcClientEnumFunc func, void *closure);
+PRUint32 IPC_GetClientID (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);
+
+//-----------------------------------------------------------------------------
+// other internal IPCD methods
+//-----------------------------------------------------------------------------
+
+//
+// dispatch message
+//
+PRStatus IPC_DispatchMsg(ipcClientHandle client, const ipcMessage *msg);
+
+//
+// send message, takes ownership of |msg|.
+//
+PRStatus IPC_SendMsg(ipcClientHandle client, ipcMessage *msg);
+
+//
+// dispatch notifications about client connects and disconnects
+//
+void IPC_NotifyClientUp(ipcClientHandle client);
+void IPC_NotifyClientDown(ipcClientHandle client);
+
+#endif // !IPCD_H__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h
new file mode 100644
index 00000000..023b3a03
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h
@@ -0,0 +1,65 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ipcdPrivate_h__
+#define ipcdPrivate_h__
+
+class ipcClient;
+
+//
+// upper limit on the number of active connections
+// XXX may want to make this more dynamic
+//
+#define IPC_MAX_CLIENTS 10000
+
+//
+// array of connected clients
+//
+extern ipcClient *ipcClients;
+extern int ipcClientCount;
+
+//
+// platform specific send message function, takes ownership of |msg|.
+//
+PRStatus IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg);
+
+//
+// notify parent that it can connect to the daemon.
+//
+void IPC_NotifyParent();
+
+#endif // !ipcdPrivate_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdStub.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdStub.cpp
new file mode 100644
index 00000000..10618110
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdStub.cpp
@@ -0,0 +1,77 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ipcd.h"
+#include "ipcdPrivate.h"
+#include "ipcLog.h"
+
+#include "prerror.h"
+
+//-----------------------------------------------------------------------------
+// use this file as a template to add server-side IPC connectivity.
+//
+// NOTE: if your platform supports local domain TCP sockets, then you should
+// be able to make use of ipcConnectionUnix.cpp.
+//-----------------------------------------------------------------------------
+
+// these variables are declared in ipcdPrivate.h and must be initialized by
+// when the daemon starts up.
+ipcClient *ipcClients = NULL;
+int ipcClientCount = 0;
+
+PRStatus
+IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg)
+{
+ const char notimplemented[] = "IPC_PlatformSendMsg not implemented";
+ PR_SetErrorText(sizeof(notimplemented), notimplemented);
+ return PR_FAILURE;
+}
+
+int main(int argc, char **argv)
+{
+ IPC_InitLog("###");
+
+ LOG(("daemon started...\n"));
+
+ /*
+ IPC_InitModuleReg(argv[0]);
+ IPC_ShutdownModuleReg();
+ */
+
+ // let the parent process know that we are up-and-running
+ IPC_NotifyParent();
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp
new file mode 100644
index 00000000..026e9e52
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp
@@ -0,0 +1,600 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(VBOX) && !defined(XP_OS2)
+# include <sys/resource.h>
+# include <errno.h>
+#endif
+
+#ifdef VBOX
+# include <iprt/initterm.h>
+#endif
+
+#include "prio.h"
+#include "prerror.h"
+#include "prthread.h"
+#include "prinrval.h"
+#include "plstr.h"
+#include "prprf.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcMessage.h"
+#include "ipcClient.h"
+#include "ipcModuleReg.h"
+#include "ipcdPrivate.h"
+#include "ipcd.h"
+
+#if 0
+static void
+IPC_Sleep(int seconds)
+{
+ while (seconds > 0) {
+ LOG(("\rsleeping for %d seconds...", seconds));
+ PR_Sleep(PR_SecondsToInterval(1));
+ --seconds;
+ }
+ LOG(("\ndone sleeping\n"));
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// ipc directory and locking...
+//-----------------------------------------------------------------------------
+
+//
+// advisory file locking is used to ensure that only one IPC daemon is active
+// and bound to the local domain socket at a time.
+//
+// XXX this code does not work on OS/2.
+//
+#if !defined(XP_OS2)
+#define IPC_USE_FILE_LOCK
+#endif
+
+#ifdef IPC_USE_FILE_LOCK
+
+enum Status
+{
+ EOk = 0,
+ ELockFileOpen = -1,
+ ELockFileLock = -2,
+ ELockFileOwner = -3,
+};
+
+static int ipcLockFD = 0;
+
+static Status AcquireDaemonLock(const char *baseDir)
+{
+ const char lockName[] = "lock";
+
+ int dirLen = strlen(baseDir);
+ int len = dirLen // baseDir
+ + 1 // "/"
+ + sizeof(lockName); // "lock"
+
+ char *lockFile = (char *) malloc(len);
+ memcpy(lockFile, baseDir, dirLen);
+ lockFile[dirLen] = '/';
+ memcpy(lockFile + dirLen + 1, lockName, sizeof(lockName));
+
+#ifdef VBOX
+ //
+ // Security checks for the directory
+ //
+ struct stat st;
+ if (stat(baseDir, &st) == -1)
+ {
+ printf("Cannot stat '%s'.\n", baseDir);
+ return ELockFileOwner;
+ }
+
+ if (st.st_uid != getuid() && st.st_uid != geteuid())
+ {
+ printf("Wrong owner (%d) of '%s'", st.st_uid, baseDir);
+ if ( !stat("/tmp", &st)
+ && (st.st_mode & 07777) != 01777)
+ printf(" -- check /tmp permissions (%o should be 1777)\n",
+ st.st_mode & 07777);
+ printf(".\n");
+ return ELockFileOwner;
+ }
+
+ if (st.st_mode != (S_IRUSR | S_IWUSR | S_IXUSR | S_IFDIR))
+ {
+ printf("Wrong mode (%o) of '%s'", st.st_mode, baseDir);
+ if ( !stat("/tmp", &st)
+ && (st.st_mode & 07777) != 01777)
+ printf(" -- check /tmp permissions (%o should be 1777)\n",
+ st.st_mode & 07777);
+ printf(".\n");
+ return ELockFileOwner;
+ }
+#endif
+
+ //
+ // open lock file. it remains open until we shutdown.
+ //
+ ipcLockFD = open(lockFile, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+#ifndef VBOX
+ free(lockFile);
+#endif
+
+ if (ipcLockFD == -1)
+ return ELockFileOpen;
+
+#ifdef VBOX
+ //
+ // Security checks for the lock file
+ //
+ if (fstat(ipcLockFD, &st) == -1)
+ {
+ printf("Cannot stat '%s'.\n", lockFile);
+ free(lockFile);
+ return ELockFileOwner;
+ }
+
+ if (st.st_uid != getuid() && st.st_uid != geteuid())
+ {
+ printf("Wrong owner (%d) of '%s'.\n", st.st_uid, lockFile);
+ free(lockFile);
+ return ELockFileOwner;
+ }
+
+ if (st.st_mode != (S_IRUSR | S_IWUSR | S_IFREG))
+ {
+ printf("Wrong mode (%o) of '%s'.\n", st.st_mode, lockFile);
+ free(lockFile);
+ return ELockFileOwner;
+ }
+
+ free(lockFile);
+#endif
+
+ //
+ // we use fcntl for locking. assumption: filesystem should be local.
+ // this API is nice because the lock will be automatically released
+ // when the process dies. it will also be released when the file
+ // descriptor is closed.
+ //
+ struct flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ lock.l_whence = SEEK_SET;
+ if (fcntl(ipcLockFD, F_SETLK, &lock) == -1)
+ return ELockFileLock;
+
+ //
+ // truncate lock file once we have exclusive access to it.
+ //
+ ftruncate(ipcLockFD, 0);
+
+ //
+ // write our PID into the lock file (this just seems like a good idea...
+ // no real purpose otherwise).
+ //
+ char buf[32];
+ int nb = PR_snprintf(buf, sizeof(buf), "%u\n", (unsigned long) getpid());
+ write(ipcLockFD, buf, nb);
+
+ return EOk;
+}
+
+static Status InitDaemonDir(const char *socketPath)
+{
+ LOG(("InitDaemonDir [sock=%s]\n", socketPath));
+
+ char *baseDir = PL_strdup(socketPath);
+
+ //
+ // make sure IPC directory exists (XXX this should be recursive)
+ //
+ char *p = strrchr(baseDir, '/');
+ if (p)
+ p[0] = '\0';
+ mkdir(baseDir, 0700);
+
+ //
+ // if we can't acquire the daemon lock, then another daemon
+ // must be active, so bail.
+ //
+ Status status = AcquireDaemonLock(baseDir);
+
+ PL_strfree(baseDir);
+
+ if (status == EOk) {
+ // delete an existing socket to prevent bind from failing.
+ unlink(socketPath);
+ }
+ return status;
+}
+
+static void ShutdownDaemonDir()
+{
+ LOG(("ShutdownDaemonDir\n"));
+
+ // deleting directory and files underneath it allows another process
+ // to think it has exclusive access. better to just leave the hidden
+ // directory in /tmp and let the OS clean it up via the usual tmpdir
+ // cleanup cron job.
+
+ // this removes the advisory lock, allowing other processes to acquire it.
+ if (ipcLockFD) {
+ close(ipcLockFD);
+ ipcLockFD = 0;
+ }
+}
+
+#endif // IPC_USE_FILE_LOCK
+
+//-----------------------------------------------------------------------------
+// poll list
+//-----------------------------------------------------------------------------
+
+//
+// declared in ipcdPrivate.h
+//
+ipcClient *ipcClients = NULL;
+int ipcClientCount = 0;
+
+//
+// the first element of this array is always zero; this is done so that the
+// k'th element of ipcClientArray corresponds to the k'th element of
+// ipcPollList.
+//
+static ipcClient ipcClientArray[IPC_MAX_CLIENTS + 1];
+
+//
+// element 0 contains the "server socket"
+//
+static PRPollDesc ipcPollList[IPC_MAX_CLIENTS + 1];
+
+//-----------------------------------------------------------------------------
+
+static int AddClient(PRFileDesc *fd)
+{
+ if (ipcClientCount == IPC_MAX_CLIENTS) {
+ LOG(("reached maximum client limit\n"));
+ return -1;
+ }
+
+ int pollCount = ipcClientCount + 1;
+
+ ipcClientArray[pollCount].Init();
+
+ ipcPollList[pollCount].fd = fd;
+ ipcPollList[pollCount].in_flags = PR_POLL_READ;
+ ipcPollList[pollCount].out_flags = 0;
+
+ ++ipcClientCount;
+ return 0;
+}
+
+static int RemoveClient(int clientIndex)
+{
+ PRPollDesc *pd = &ipcPollList[clientIndex];
+
+ PR_Close(pd->fd);
+
+ ipcClientArray[clientIndex].Finalize();
+
+ //
+ // keep the clients and poll_fds contiguous; move the last one into
+ // the spot held by the one that is going away.
+ //
+ int toIndex = clientIndex;
+ int fromIndex = ipcClientCount;
+ if (fromIndex != toIndex) {
+ memcpy(&ipcClientArray[toIndex], &ipcClientArray[fromIndex], sizeof(ipcClient));
+ memcpy(&ipcPollList[toIndex], &ipcPollList[fromIndex], sizeof(PRPollDesc));
+ }
+
+ //
+ // zero out the old entries.
+ //
+ memset(&ipcClientArray[fromIndex], 0, sizeof(ipcClient));
+ memset(&ipcPollList[fromIndex], 0, sizeof(PRPollDesc));
+
+ --ipcClientCount;
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+static void PollLoop(PRFileDesc *listenFD)
+{
+ // the first element of ipcClientArray is unused.
+ memset(ipcClientArray, 0, sizeof(ipcClientArray));
+ ipcClients = ipcClientArray + 1;
+ ipcClientCount = 0;
+
+ ipcPollList[0].fd = listenFD;
+ ipcPollList[0].in_flags = PR_POLL_EXCEPT | PR_POLL_READ;
+
+ while (1) {
+ PRInt32 rv;
+ PRIntn i;
+
+ int pollCount = ipcClientCount + 1;
+
+ ipcPollList[0].out_flags = 0;
+
+ //
+ // poll
+ //
+ // timeout after 5 minutes. if no connections after timeout, then
+ // exit. this timeout ensures that we don't stay resident when no
+ // clients are interested in connecting after spawning the daemon.
+ //
+ // XXX add #define for timeout value
+ //
+ LOG(("calling PR_Poll [pollCount=%d]\n", pollCount));
+ rv = PR_Poll(ipcPollList, pollCount, PR_SecondsToInterval(60 * 5));
+ if (rv == -1) {
+ LOG(("PR_Poll failed [%d]\n", PR_GetError()));
+ return;
+ }
+
+ if (rv > 0) {
+ //
+ // process clients that are ready
+ //
+ for (i = 1; i < pollCount; ++i) {
+ if (ipcPollList[i].out_flags != 0) {
+ ipcPollList[i].in_flags =
+ ipcClientArray[i].Process(ipcPollList[i].fd,
+ ipcPollList[i].out_flags);
+ ipcPollList[i].out_flags = 0;
+ }
+ }
+
+ //
+ // cleanup any dead clients (indicated by a zero in_flags)
+ //
+ for (i = pollCount - 1; i >= 1; --i) {
+ if (ipcPollList[i].in_flags == 0)
+ RemoveClient(i);
+ }
+
+ //
+ // check for new connection
+ //
+ if (ipcPollList[0].out_flags & PR_POLL_READ) {
+ LOG(("got new connection\n"));
+
+ PRNetAddr clientAddr;
+ memset(&clientAddr, 0, sizeof(clientAddr));
+ PRFileDesc *clientFD;
+
+ // @todo : We need to handle errors from accept() especially something like
+ // EMFILE, which happens when we run out of file descriptors.
+ // and puts XPCOMIPCD in a poll/accept endless loop!
+ clientFD = PR_Accept(listenFD, &clientAddr, PR_INTERVAL_NO_WAIT);
+ if (clientFD == NULL) {
+ // ignore this error... perhaps the client disconnected.
+ LOG(("PR_Accept failed [%d]\n", PR_GetError()));
+ }
+ else {
+ // make socket non-blocking
+ PRSocketOptionData opt;
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(clientFD, &opt);
+
+ if (AddClient(clientFD) != 0)
+ PR_Close(clientFD);
+ }
+ }
+ }
+
+ //
+ // shutdown if no clients
+ //
+ if (ipcClientCount == 0) {
+ LOG(("shutting down\n"));
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+PRStatus
+IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg)
+{
+ LOG(("IPC_PlatformSendMsg\n"));
+
+ //
+ // must copy message onto send queue.
+ //
+ client->EnqueueOutboundMsg(msg);
+
+ //
+ // 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;
+}
+
+//-----------------------------------------------------------------------------
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenFD = NULL;
+ PRNetAddr addr;
+
+#ifdef VBOX
+ /* Set up the runtime without loading the support driver. */
+ RTR3InitExe(argc, &argv, 0);
+#endif
+
+ //
+ // ignore SIGINT so <ctrl-c> from terminal only kills the client
+ // which spawned this daemon.
+ //
+ signal(SIGINT, SIG_IGN);
+ // XXX block others? check cartman
+
+ // ensure strict file permissions
+ umask(0077);
+
+ IPC_InitLog("###");
+
+ LOG(("daemon started...\n"));
+
+ //XXX uncomment these lines to test slow starting daemon
+ //IPC_Sleep(2);
+
+ // set socket address
+ addr.local.family = PR_AF_LOCAL;
+ if (argc < 2)
+ IPC_GetDefaultSocketPath(addr.local.path, sizeof(addr.local.path));
+ else
+ PL_strncpyz(addr.local.path, argv[1], sizeof(addr.local.path));
+
+#ifdef IPC_USE_FILE_LOCK
+ Status status = InitDaemonDir(addr.local.path);
+ if (status != EOk) {
+ if (status == ELockFileLock) {
+ LOG(("Another daemon is already running, exiting.\n"));
+ // send a signal to the blocked parent to indicate success
+ IPC_NotifyParent();
+ return 0;
+ }
+ else {
+ LOG(("InitDaemonDir failed (status=%d)\n", status));
+ // don't notify the parent to cause it to fail in PR_Read() after
+ // we terminate
+#ifdef VBOX
+ if (status != ELockFileOwner)
+ printf("Cannot create a lock file for '%s'.\n"
+ "Check permissions.\n", addr.local.path);
+#endif
+ return 0;
+ }
+ }
+#endif
+
+ listenFD = PR_OpenTCPSocket(PR_AF_LOCAL);
+ if (!listenFD) {
+ LOG(("PR_OpenTCPSocket failed [%d]\n", PR_GetError()));
+ }
+ else if (PR_Bind(listenFD, &addr) != PR_SUCCESS) {
+ LOG(("PR_Bind failed [%d]\n", PR_GetError()));
+ }
+ else {
+ IPC_InitModuleReg(argv[0]);
+
+#ifdef VBOX
+ // Use large backlog, as otherwise local sockets can reject connection
+ // attempts. Usually harmless, but causes an unnecessary start attempt
+ // of IPCD (which will terminate straight away), and the next attempt
+ // usually succeeds. But better avoid unnecessary activities.
+ if (PR_Listen(listenFD, 128) != PR_SUCCESS) {
+#else /* !VBOX */
+ if (PR_Listen(listenFD, 5) != PR_SUCCESS) {
+#endif /* !VBOX */
+ LOG(("PR_Listen failed [%d]\n", PR_GetError()));
+ }
+ else {
+#ifndef VBOX
+ // redirect all standard file descriptors to /dev/null for
+ // proper daemonizing
+ PR_Close(PR_STDIN);
+ PR_Open("/dev/null", O_RDONLY, 0);
+ PR_Close(PR_STDOUT);
+ PR_Open("/dev/null", O_WRONLY, 0);
+ PR_Close(PR_STDERR);
+ PR_Open("/dev/null", O_WRONLY, 0);
+#endif
+
+ IPC_NotifyParent();
+
+#if defined(VBOX) && !defined(XP_OS2)
+ // Increase the file table size to 10240 or as high as possible.
+ struct rlimit lim;
+ if (getrlimit(RLIMIT_NOFILE, &lim) == 0)
+ {
+ if ( lim.rlim_cur < 10240
+ && lim.rlim_cur < lim.rlim_max)
+ {
+ lim.rlim_cur = lim.rlim_max <= 10240 ? lim.rlim_max : 10240;
+ if (setrlimit(RLIMIT_NOFILE, &lim) == -1)
+ printf("WARNING: failed to increase file descriptor limit. (%d)\n", errno);
+ }
+ }
+ else
+ printf("WARNING: failed to obtain per-process file-descriptor limit (%d).\n", errno);
+#endif
+
+ PollLoop(listenFD);
+ }
+
+ IPC_ShutdownModuleReg();
+ }
+
+ //IPC_Sleep(5);
+
+#ifdef IPC_USE_FILE_LOCK
+ // it is critical that we release the lock before closing the socket,
+ // otherwise, a client might launch another daemon that would be unable
+ // to acquire the lock and would then leave the client without a daemon.
+
+ ShutdownDaemonDir();
+#endif
+
+ if (listenFD) {
+ LOG(("closing socket\n"));
+ PR_Close(listenFD);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdWin.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdWin.cpp
new file mode 100644
index 00000000..f89fba06
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdWin.cpp
@@ -0,0 +1,408 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <windows.h>
+
+#include "prthread.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcMessage.h"
+#include "ipcClient.h"
+#include "ipcModuleReg.h"
+#include "ipcdPrivate.h"
+#include "ipcd.h"
+#include "ipcm.h"
+
+//
+// declared in ipcdPrivate.h
+//
+ipcClient *ipcClients = NULL;
+int ipcClientCount = 0;
+
+static ipcClient ipcClientArray[IPC_MAX_CLIENTS];
+
+static HWND ipcHwnd = NULL;
+static PRBool ipcShutdown = PR_FALSE;
+
+#define IPC_PURGE_TIMER_ID 1
+#define IPC_WM_SENDMSG (WM_USER + 1)
+#define IPC_WM_SHUTDOWN (WM_USER + 2)
+
+//-----------------------------------------------------------------------------
+// client array manipulation
+//-----------------------------------------------------------------------------
+
+static void
+RemoveClient(ipcClient *client)
+{
+ LOG(("RemoveClient\n"));
+
+ int clientIndex = client - ipcClientArray;
+
+ client->Finalize();
+
+ //
+ // move last ipcClient object down into the spot occupied by this client.
+ //
+ int fromIndex = ipcClientCount - 1;
+ int toIndex = clientIndex;
+ if (toIndex != fromIndex)
+ memcpy(&ipcClientArray[toIndex], &ipcClientArray[fromIndex], sizeof(ipcClient));
+
+ memset(&ipcClientArray[fromIndex], 0, sizeof(ipcClient));
+
+ --ipcClientCount;
+ LOG((" num clients = %u\n", ipcClientCount));
+
+ if (ipcClientCount == 0) {
+ LOG((" shutting down...\n"));
+ KillTimer(ipcHwnd, IPC_PURGE_TIMER_ID);
+ PostQuitMessage(0);
+ ipcShutdown = PR_TRUE;
+ }
+}
+
+static void
+PurgeStaleClients()
+{
+ if (ipcClientCount == 0)
+ return;
+
+ LOG(("PurgeStaleClients [num-clients=%u]\n", ipcClientCount));
+ //
+ // walk the list of supposedly active clients, and verify the existance of
+ // their respective message windows.
+ //
+ char wName[IPC_CLIENT_WINDOW_NAME_MAXLEN];
+ for (int i=ipcClientCount-1; i>=0; --i) {
+ ipcClient *client = &ipcClientArray[i];
+
+ LOG((" checking client at index %u [client-id=%u pid=%u]\n",
+ i, client->ID(), client->PID()));
+
+ IPC_GetClientWindowName(client->PID(), wName);
+
+ // XXX dougt has ideas about how to make this better
+
+ HWND hwnd = FindWindow(IPC_CLIENT_WINDOW_CLASS, wName);
+ if (!hwnd) {
+ LOG((" client window not found; removing client!\n"));
+ RemoveClient(client);
+ }
+ }
+}
+
+static ipcClient *
+AddClient(HWND hwnd, PRUint32 pid)
+{
+ LOG(("AddClient\n"));
+
+ //
+ // before adding a new client, verify that all existing clients are
+ // still up and running. remove any stale clients.
+ //
+ PurgeStaleClients();
+
+ if (ipcClientCount == IPC_MAX_CLIENTS) {
+ LOG((" reached maximum client count!\n"));
+ return NULL;
+ }
+
+ ipcClient *client = &ipcClientArray[ipcClientCount];
+ client->Init();
+ client->SetHwnd(hwnd);
+ client->SetPID(pid); // XXX one function instead of 3
+
+ ++ipcClientCount;
+ LOG((" num clients = %u\n", ipcClientCount));
+
+ if (ipcClientCount == 1)
+ SetTimer(ipcHwnd, IPC_PURGE_TIMER_ID, 1000, NULL);
+
+ return client;
+}
+
+static ipcClient *
+GetClientByPID(PRUint32 pid)
+{
+ for (int i=0; i<ipcClientCount; ++i) {
+ if (ipcClientArray[i].PID() == pid)
+ return &ipcClientArray[i];
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// message processing
+//-----------------------------------------------------------------------------
+
+static void
+ProcessMsg(HWND hwnd, PRUint32 pid, const ipcMessage *msg)
+{
+ LOG(("ProcessMsg [pid=%u len=%u]\n", pid, msg->MsgLen()));
+
+ ipcClient *client = GetClientByPID(pid);
+
+ if (client) {
+ //
+ // if this is an IPCM "client hello" message, then reset the client
+ // instance object.
+ //
+ if (msg->Target().Equals(IPCM_TARGET) &&
+ IPCM_GetType(msg) == IPCM_MSG_REQ_CLIENT_HELLO) {
+ RemoveClient(client);
+ client = NULL;
+ }
+ }
+
+ if (client == NULL) {
+ client = AddClient(hwnd, pid);
+ if (!client)
+ return;
+ }
+
+ IPC_DispatchMsg(client, msg);
+}
+
+//-----------------------------------------------------------------------------
+
+PRStatus
+IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg)
+{
+ LOG(("IPC_PlatformSendMsg [clientID=%u clientPID=%u]\n",
+ client->ID(), client->PID()));
+
+ // use PostMessage to make this asynchronous; otherwise we might get
+ // some wierd SendMessage recursion between processes.
+
+ WPARAM wParam = (WPARAM) client->Hwnd();
+ LPARAM lParam = (LPARAM) msg;
+ if (!PostMessage(ipcHwnd, IPC_WM_SENDMSG, wParam, lParam)) {
+ LOG(("PostMessage failed\n"));
+ delete msg;
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// windows message loop
+//-----------------------------------------------------------------------------
+
+static LRESULT CALLBACK
+WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LOG(("got message [msg=%x wparam=%x lparam=%x]\n", uMsg, wParam, lParam));
+
+ if (uMsg == WM_COPYDATA) {
+ if (ipcShutdown) {
+ LOG(("ignoring message b/c daemon is shutting down\n"));
+ return TRUE;
+ }
+ COPYDATASTRUCT *cd = (COPYDATASTRUCT *) lParam;
+ if (cd && cd->lpData) {
+ ipcMessage msg;
+ PRUint32 bytesRead;
+ PRBool complete;
+ // XXX avoid extra malloc
+ PRStatus rv = msg.ReadFrom((const char *) cd->lpData, cd->cbData,
+ &bytesRead, &complete);
+ if (rv == PR_SUCCESS && complete) {
+ //
+ // grab client PID and hwnd.
+ //
+ ProcessMsg((HWND) wParam, (PRUint32) cd->dwData, &msg);
+ }
+ else
+ LOG(("ignoring malformed message\n"));
+ }
+ return TRUE;
+ }
+
+ if (uMsg == IPC_WM_SENDMSG) {
+ HWND hWndDest = (HWND) wParam;
+ ipcMessage *msg = (ipcMessage *) lParam;
+
+ COPYDATASTRUCT cd;
+ cd.dwData = GetCurrentProcessId();
+ cd.cbData = (DWORD) msg->MsgLen();
+ cd.lpData = (PVOID) msg->MsgBuf();
+
+ LOG(("calling SendMessage...\n"));
+ SendMessage(hWndDest, WM_COPYDATA, (WPARAM) hWnd, (LPARAM) &cd);
+ LOG((" done.\n"));
+
+ delete msg;
+ return 0;
+ }
+
+ if (uMsg == WM_TIMER) {
+ PurgeStaleClients();
+ return 0;
+ }
+
+#if 0
+ if (uMsg == IPC_WM_SHUTDOWN) {
+ //
+ // since this message is handled asynchronously, it is possible
+ // that other clients may have come online since this was issued.
+ // in which case, we need to ignore this message.
+ //
+ if (ipcClientCount == 0) {
+ ipcShutdown = PR_TRUE;
+ PostQuitMessage(0);
+ }
+ return 0;
+ }
+#endif
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+//-----------------------------------------------------------------------------
+// daemon startup synchronization
+//-----------------------------------------------------------------------------
+
+static HANDLE ipcSyncEvent;
+
+static PRBool
+AcquireLock()
+{
+ ipcSyncEvent = CreateEvent(NULL, FALSE, FALSE,
+ IPC_SYNC_EVENT_NAME);
+ if (!ipcSyncEvent) {
+ LOG(("CreateEvent failed [%u]\n", GetLastError()));
+ return PR_FALSE;
+ }
+
+ // check to see if event already existed prior to this call.
+ if (GetLastError() == ERROR_ALREADY_EXISTS) {
+ LOG((" lock already set; exiting...\n"));
+ return PR_FALSE;
+ }
+
+ LOG((" acquired lock\n"));
+ return PR_TRUE;
+}
+
+static void
+ReleaseLock()
+{
+ if (ipcSyncEvent) {
+ LOG(("releasing lock...\n"));
+ CloseHandle(ipcSyncEvent);
+ ipcSyncEvent = NULL;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// main
+//-----------------------------------------------------------------------------
+
+#ifdef DEBUG
+int
+main()
+#else
+int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
+#endif
+{
+ IPC_InitLog("###");
+
+ LOG(("daemon started...\n"));
+
+ if (!AcquireLock()) {
+ // unblock the parent; it should be able to find the IPC window of the
+ // other daemon process.
+ IPC_NotifyParent();
+ return 0;
+ }
+
+ // initialize global data
+ memset(ipcClientArray, 0, sizeof(ipcClientArray));
+ ipcClients = ipcClientArray;
+ ipcClientCount = 0;
+
+ // create message window up front...
+ WNDCLASS wc;
+ memset(&wc, 0, sizeof(wc));
+ wc.lpfnWndProc = WindowProc;
+ wc.lpszClassName = IPC_WINDOW_CLASS;
+
+ RegisterClass(&wc);
+
+ ipcHwnd = CreateWindow(IPC_WINDOW_CLASS, IPC_WINDOW_NAME,
+ 0, 0, 0, 10, 10, NULL, NULL, NULL, NULL);
+
+ // unblock the parent process; it should now look for the IPC window.
+ IPC_NotifyParent();
+
+ if (!ipcHwnd)
+ return -1;
+
+ // load modules relative to the location of the executable...
+ {
+ char path[MAX_PATH];
+ GetModuleFileName(NULL, path, sizeof(path));
+ IPC_InitModuleReg(path);
+ }
+
+ LOG(("entering message loop...\n"));
+ MSG msg;
+ while (GetMessage(&msg, ipcHwnd, 0, 0))
+ DispatchMessage(&msg);
+
+ // unload modules
+ IPC_ShutdownModuleReg();
+
+ //
+ // we release the daemon lock before destroying the window because the
+ // absence of our window is what will cause clients to try to spawn the
+ // daemon.
+ //
+ ReleaseLock();
+
+ //LOG(("sleeping 5 seconds...\n"));
+ //PR_Sleep(PR_SecondsToInterval(5));
+
+ LOG(("destroying message window...\n"));
+ DestroyWindow(ipcHwnd);
+ ipcHwnd = NULL;
+
+ LOG(("exiting\n"));
+ return 0;
+}