Compare commits

..

2 Commits

Author SHA1 Message Date
sdv%sparc.spb.su
53866ece4f workaround for bug=30927
git-svn-id: svn://10.0.0.236/branches/M15-patch@72213 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-14 11:34:36 +00:00
(no author)
350be55313 This commit was manufactured by cvs2svn to create branch 'M15-patch'.
git-svn-id: svn://10.0.0.236/branches/M15-patch@52901 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 02:47:16 +00:00
65 changed files with 105 additions and 9137 deletions

View File

@@ -0,0 +1,105 @@
/*
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.org code.
The Initial Developer of the Original Code is Sun Microsystems,
Inc. Portions created by Sun are
Copyright (C) 1999 Sun Microsystems, Inc. All
Rights Reserved.
Contributor(s):
*/
#ifndef __JavaDOMGlobals_h__
#define __JavaDOMGlobals_h__
#include "jni.h"
#include "prclist.h"
#include "nsError.h"
#ifdef ERROR
#undef ERROR
#endif
class nsISupports;
class nsIDOMNode;
struct PRLogModuleInfo;
struct PRLock;
class JavaDOMGlobals {
public:
static jclass attrClass;
static jclass cDataSectionClass;
static jclass commentClass;
static jclass documentClass;
static jclass documentFragmentClass;
static jclass documentTypeClass;
static jclass domImplementationClass;
static jclass elementClass;
static jclass entityClass;
static jclass entityReferenceClass;
static jclass namedNodeMapClass;
static jclass nodeClass;
static jclass nodeListClass;
static jclass notationClass;
static jclass processingInstructionClass;
static jclass textClass;
static jfieldID nodePtrFID;
static jfieldID nodeListPtrFID;
static jfieldID domImplementationPtrFID;
static jfieldID nodeTypeAttributeFID;
static jfieldID nodeTypeCDataSectionFID;
static jfieldID nodeTypeCommentFID;
static jfieldID nodeTypeDocumentFragmentFID;
static jfieldID nodeTypeDocumentFID;
static jfieldID nodeTypeDocumentTypeFID;
static jfieldID nodeTypeElementFID;
static jfieldID nodeTypeEntityFID;
static jfieldID nodeTypeEntityReferenceFID;
static jfieldID nodeTypeNotationFID;
static jfieldID nodeTypeProcessingInstructionFID;
static jfieldID nodeTypeTextFID;
static jclass domExceptionClass;
static jmethodID domExceptionInitMID;
static jclass runtimeExceptionClass;
static jmethodID runtimeExceptionInitMID;
static const char* const DOM_EXCEPTION_MESSAGE[];
typedef enum ExceptionType { EXCEPTION_RUNTIME,
EXCEPTION_DOM } ExceptionType;
static PRLogModuleInfo* log;
static PRCList garbage;
static PRLock* garbageLock;
static PRInt32 javaMaxInt;
static void Initialize(JNIEnv *env);
static void Destroy(JNIEnv *env);
static jobject CreateNodeSubtype(JNIEnv *env,
nsIDOMNode *node);
static void AddToGarbage(nsISupports* domObject);
static void TakeOutGarbage();
static void ThrowException(JNIEnv *env,
const char * message = NULL,
nsresult rv = NS_OK,
ExceptionType exceptionType = EXCEPTION_RUNTIME);
};
#endif /* __JavaDOMGlobals_h__ */

View File

@@ -1,31 +0,0 @@
#
# 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.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = common daemon testmodule public src extensions build test
include $(topsrcdir)/config/rules.mk

View File

@@ -1,12 +0,0 @@
DAEMON ONLY DIRECTORIES:
daemon/
testmodule/
CLIENT ONLY DIRECTORIES:
public/
src/
build/
test/
SHARED CODE DIRECTORY:
common/

View File

@@ -1,76 +0,0 @@
# ***** 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 = ipc
LIBRARY_NAME = ipc
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = ipc
REQUIRES = xpcom \
string \
necko \
$(NULL)
CPPSRCS = ipcModule.cpp
EXPORTS = ipcCID.h
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/$(LIB_PREFIX)ipc_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)ipccom_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)ipclock_s.$(LIB_SUFFIX) \
$(NULL)
LOCAL_INCLUDES = \
-I$(srcdir)/../src \
-I$(srcdir)/../common \
-I$(srcdir)/../extensions/lock/src \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(LIBS_DIR) \
$(EXTRA_DSO_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,69 +0,0 @@
/* ***** 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 ipcCID_h__
#define ipcCID_h__
#define IPC_SERVICE_CLASSNAME \
"ipcService"
#define IPC_SERVICE_CONTRACTID \
"@mozilla.org/ipc/service;1"
#define IPC_SERVICE_CID \
{ /* 9f12676a-5168-4a08-beb8-edf8a593a1ca */ \
0x9f12676a, \
0x5168, \
0x4a08, \
{0xbe, 0xb8, 0xed, 0xf8, 0xa5, 0x93, 0xa1, 0xca} \
}
//-----------------------------------------------------------------------------
// extensions
// XXX replace CID with one from botbot
#define IPC_LOCKSERVICE_CLASSNAME \
"ipcLockService"
#define IPC_LOCKSERVICE_CONTRACTID \
"@mozilla.org/ipc/lock-service;1"
#define IPC_LOCKSERVICE_CID \
{ /* 7aaeaceb-b207-4b45-bbde-a13276401fc2 */ \
0x7aaeaceb, \
0xb207, \
0x4b45, \
{0xbb, 0xde, 0xa1, 0x32, 0x76, 0x40, 0x1f, 0xc2} \
}
#endif // !ipcCID_h__

View File

@@ -1,141 +0,0 @@
/* ***** 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 "nsIServiceManager.h"
#include "nsIGenericFactory.h"
#include "nsICategoryManager.h"
#include "ipcService.h"
#include "ipcCID.h"
#include "ipcConfig.h"
//-----------------------------------------------------------------------------
// Define the contructor function for the objects
//
// NOTE: This creates an instance of objects by using the default constructor
//-----------------------------------------------------------------------------
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcService, Init)
#if 0
NS_METHOD
ipcServiceRegisterProc(nsIComponentManager *aCompMgr,
nsIFile *aPath,
const char *registryLocation,
const char *componentType,
const nsModuleComponentInfo *info)
{
//
// add ipcService to the XPCOM startup category
//
nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
if (catman) {
nsXPIDLCString prevEntry;
catman->AddCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID, "ipcService",
IPC_SERVICE_CONTRACTID, PR_TRUE, PR_TRUE,
getter_Copies(prevEntry));
}
return NS_OK;
}
NS_METHOD
ipcServiceUnregisterProc(nsIComponentManager *aCompMgr,
nsIFile *aPath,
const char *registryLocation,
const nsModuleComponentInfo *info)
{
nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
if (catman)
catman->DeleteCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID,
IPC_SERVICE_CONTRACTID, PR_TRUE);
return NS_OK;
}
#endif
#ifdef XP_UNIX
#include "ipcSocketProviderUnix.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(ipcSocketProviderUnix)
#define IPC_SOCKETPROVIDER_CLASSNAME \
"ipcSocketProvider"
#define IPC_SOCKETPROVIDER_CID \
{ /* b888f500-ab5d-459c-aab0-bc61e844a503 */ \
0xb888f500, \
0xab5d, \
0x459c, \
{0xaa, 0xb0, 0xbc, 0x61, 0xe8, 0x44, 0xa5, 0x03} \
}
#endif
//-----------------------------------------------------------------------------
// extensions
#include "ipcLockService.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcLockService, Init)
//-----------------------------------------------------------------------------
// Define a table of CIDs implemented by this module along with other
// information like the function to create an instance, contractid, and
// class name.
//-----------------------------------------------------------------------------
static const nsModuleComponentInfo components[] = {
{ IPC_SERVICE_CLASSNAME,
IPC_SERVICE_CID,
IPC_SERVICE_CONTRACTID,
ipcServiceConstructor },
/*
ipcServiceRegisterProc,
ipcServiceUnregisterProc },
*/
#ifdef XP_UNIX
{ IPC_SOCKETPROVIDER_CLASSNAME,
IPC_SOCKETPROVIDER_CID,
NS_NETWORK_SOCKET_CONTRACTID_PREFIX IPC_SOCKET_TYPE,
ipcSocketProviderUnixConstructor, },
#endif
//
// extensions go here:
//
{ IPC_LOCKSERVICE_CLASSNAME,
IPC_LOCKSERVICE_CID,
IPC_LOCKSERVICE_CONTRACTID,
ipcLockServiceConstructor },
};
//-----------------------------------------------------------------------------
// Implement the NSGetModule() exported function for your module
// and the entire implementation of the module object.
//-----------------------------------------------------------------------------
NS_IMPL_NSGETMODULE(ipcModule, components)

View File

@@ -1,70 +0,0 @@
# ***** 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 = ipc
LIBRARY_NAME = ipccom_s
EXPORT_LIBRARY = 1
FORCE_STATIC_LIB = 1
MODULE_NAME = ipc
REQUIRES = \
xpcom \
$(NULL)
CPPSRCS = \
ipcLog.cpp \
ipcConfig.cpp \
ipcMessage.cpp \
ipcMessagePrimitives.cpp \
ipcStringList.cpp \
ipcIDList.cpp \
ipcm.cpp
EXPORTS = \
ipcMessage.h \
ipcMessageQ.h \
ipcm.h \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,75 +0,0 @@
/* ***** 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) 2003
* 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 ***** */
#ifdef XP_WIN
#else
#include <string.h>
#include "ipcConfig.h"
#include "ipcLog.h"
#include "prenv.h"
#include "plstr.h"
static const char kDefaultSocketPrefix[] = "/tmp/.mozilla";
static const char kDefaultSocketSuffix[] = "-ipc/ipcd";
void IPC_GetDefaultSocketPath(char *buf, PRUint32 bufLen)
{
const char *logName;
int len;
PL_strncpyz(buf, kDefaultSocketPrefix, bufLen);
buf += (sizeof(kDefaultSocketPrefix) - 1);
bufLen -= (sizeof(kDefaultSocketPrefix) - 1);
logName = PR_GetEnv("LOGNAME");
if (!logName || !logName[0]) {
logName = PR_GetEnv("USER");
if (!logName || !logName[0]) {
LOG(("could not determine username from environment\n"));
goto end;
}
}
PL_strncpyz(buf, logName, bufLen);
len = strlen(logName);
buf += len;
bufLen -= len;
end:
PL_strncpyz(buf, kDefaultSocketSuffix, bufLen);
}
#endif

View File

@@ -1,81 +0,0 @@
/* ***** 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 ipcProto_h__
#define ipcProto_h__
#if defined(XP_WIN)
//
// use WM_COPYDATA messages
//
#include "prprf.h"
#define IPC_WINDOW_CLASS "Mozilla:IPCWindowClass"
#define IPC_WINDOW_NAME "Mozilla:IPCWindow"
#define IPC_CLIENT_WINDOW_CLASS "Mozilla:IPCAppWindowClass"
#define IPC_CLIENT_WINDOW_NAME_PREFIX "Mozilla:IPCAppWindow:"
#define IPC_SYNC_EVENT_NAME "Local\\MozillaIPCSyncEvent"
#define IPC_DAEMON_APP_NAME "mozipcd.exe"
#define IPC_PATH_SEP_CHAR '\\'
#define IPC_MODULES_DIR "ipc\\modules"
#define IPC_CLIENT_WINDOW_NAME_MAXLEN (sizeof(IPC_CLIENT_WINDOW_NAME_PREFIX) + 20)
// writes client name into buf. buf must be at least
// IPC_CLIENT_WINDOW_NAME_MAXLEN bytes in length.
inline void IPC_GetClientWindowName(PRUint32 pid, char *buf)
{
PR_snprintf(buf, IPC_CLIENT_WINDOW_NAME_MAXLEN, "%s%u",
IPC_CLIENT_WINDOW_NAME_PREFIX, pid);
}
#else
#include "prtypes.h"
//
// use UNIX domain socket
//
#define IPC_PORT 0
#define IPC_SOCKET_TYPE "ipc"
#define IPC_DAEMON_APP_NAME "mozipcd"
#define IPC_PATH_SEP_CHAR '/'
#define IPC_MODULES_DIR "ipc/modules"
void IPC_GetDefaultSocketPath(char *buf, PRUint32 bufLen);
#endif
#endif // !ipcProto_h__

View File

@@ -1,62 +0,0 @@
/* ***** 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 "ipcIDList.h"
ipcIDNode *
ipcIDList::FindNode(ipcIDNode *node, const nsID &id)
{
while (node) {
if (node->Equals(id))
return node;
node = node->mNext;
}
return NULL;
}
ipcIDNode *
ipcIDList::FindNodeBefore(ipcIDNode *node, const nsID &id)
{
ipcIDNode *prev = NULL;
while (node) {
if (node->Equals(id))
return prev;
prev = node;
node = node->mNext;
}
return NULL;
}

View File

@@ -1,102 +0,0 @@
/* ***** 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 ipcIDList_h__
#define ipcIDList_h__
#include "nsID.h"
#include "ipcList.h"
//-----------------------------------------------------------------------------
// nsID node
//-----------------------------------------------------------------------------
class ipcIDNode
{
public:
ipcIDNode(const nsID &id)
: mID(id)
{ }
const nsID &Value() const { return mID; }
PRBool Equals(const nsID &id) const { return mID.Equals(id); }
class ipcIDNode *mNext;
private:
nsID mID;
};
//-----------------------------------------------------------------------------
// singly-linked list of nsIDs
//-----------------------------------------------------------------------------
class ipcIDList : public ipcList<ipcIDNode>
{
public:
typedef ipcList<ipcIDNode> Super;
void Prepend(const nsID &id)
{
Super::Prepend(new ipcIDNode(id));
}
void Append(const nsID &id)
{
Super::Append(new ipcIDNode(id));
}
const ipcIDNode *Find(const nsID &id) const
{
return FindNode(mHead, id);
}
void FindAndDelete(const nsID &id)
{
ipcIDNode *node = FindNodeBefore(mHead, id);
if (node)
DeleteAfter(node);
else
DeleteFirst();
}
private:
static ipcIDNode *FindNode (ipcIDNode *head, const nsID &id);
static ipcIDNode *FindNodeBefore(ipcIDNode *head, const nsID &id);
};
#endif // !ipcIDList_h__

View File

@@ -1,176 +0,0 @@
/* ***** 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 ipcList_h__
#define ipcList_h__
#include "prtypes.h"
//-----------------------------------------------------------------------------
// simple list of singly-linked objects. class T must have the following
// structure:
//
// class T {
// ...
// public:
// T *mNext;
// };
//
// objects added to the list must be allocated with operator new.
//-----------------------------------------------------------------------------
template<class T>
class ipcList
{
public:
ipcList()
: mHead(NULL)
, mTail(NULL)
{ }
~ipcList() { DeleteAll(); }
//
// prepends obj at the beginning of the list.
//
void Prepend(T *obj)
{
obj->mNext = mHead;
mHead = obj;
if (!mTail)
mTail = mHead;
}
//
// appends obj to the end of the list.
//
void Append(T *obj)
{
obj->mNext = NULL;
if (mTail) {
mTail->mNext = obj;
mTail = obj;
}
else
mTail = mHead = obj;
}
//
// inserts b into the list after a.
//
void InsertAfter(T *a, T *b)
{
b->mNext = a->mNext;
a->mNext = b;
if (mTail == a)
mTail = b;
}
//
// removes first element w/o deleting it
//
void RemoveFirst()
{
if (mHead)
AdvanceHead();
}
//
// removes element after the given element w/o deleting it
//
void RemoveAfter(T *obj)
{
T *rej = obj->mNext;
if (rej) {
obj->mNext = rej->mNext;
if (rej == mTail)
mTail = obj;
}
}
//
// deletes first element
//
void DeleteFirst()
{
T *first = mHead;
if (first) {
AdvanceHead();
delete first;
}
}
//
// deletes element after the given element
//
void DeleteAfter(T *obj)
{
T *rej = obj->mNext;
if (rej) {
RemoveAfter(obj);
delete rej;
}
}
//
// deletes all elements
//
void DeleteAll()
{
while (mHead)
DeleteFirst();
}
const T *First() const { return mHead; }
T *First() { return mHead; }
const T *Last() const { return mTail; }
T *Last() { return mTail; }
PRBool IsEmpty() const { return mHead == NULL; }
protected:
void AdvanceHead()
{
mHead = mHead->mNext;
if (!mHead)
mTail = NULL;
}
T *mHead;
T *mTail;
};
#endif // !ipcList_h__

View File

@@ -1,115 +0,0 @@
/* ***** 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"
#ifdef IPC_LOGGING
#include <string.h>
#include "prenv.h"
#include "prprf.h"
#include "plstr.h"
PRBool ipcLogEnabled = PR_FALSE;
char ipcLogPrefix[10] = {0};
//-----------------------------------------------------------------------------
// UNIX
//-----------------------------------------------------------------------------
#ifdef XP_UNIX
#include <sys/types.h>
#include <unistd.h>
static inline PRUint32
WritePrefix(char *buf, PRUint32 bufLen)
{
return PR_snprintf(buf, bufLen, "[%u] %s ",
(unsigned) getpid(),
ipcLogPrefix);
}
#endif
//-----------------------------------------------------------------------------
// WIN32
//-----------------------------------------------------------------------------
#ifdef XP_WIN
#include <windows.h>
static inline PRUint32
WritePrefix(char *buf, PRUint32 bufLen)
{
return PR_snprintf(buf, bufLen, "[%u:%u] %s ",
GetCurrentProcessId(),
GetCurrentThreadId(),
ipcLogPrefix);
}
#endif
//-----------------------------------------------------------------------------
// logging API impl
//-----------------------------------------------------------------------------
void
IPC_InitLog(const char *prefix)
{
if (PR_GetEnv("IPC_LOG_ENABLE")) {
ipcLogEnabled = PR_TRUE;
PL_strncpyz(ipcLogPrefix, prefix, sizeof(ipcLogPrefix));
}
}
void
IPC_Log(const char *fmt, ... )
{
va_list ap;
va_start(ap, fmt);
PRUint32 nb = 0;
char buf[512];
if (ipcLogPrefix[0])
nb = WritePrefix(buf, sizeof(buf));
PR_vsnprintf(buf + nb, sizeof(buf) - nb, fmt, ap);
buf[sizeof(buf) - 1] = '\0';
fwrite(buf, strlen(buf), 1, stdout);
va_end(ap);
}
#endif

View File

@@ -1,65 +0,0 @@
/* ***** 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 ipcLog_h__
#define ipcLog_h__
#include "prtypes.h"
#define IPC_LOGGING
#ifdef IPC_LOGGING
extern PRBool ipcLogEnabled;
extern void IPC_InitLog(const char *prefix);
extern void IPC_Log(const char *fmt, ...);
#define IPC_LOG(_args) \
PR_BEGIN_MACRO \
if (ipcLogEnabled) \
IPC_Log _args; \
PR_END_MACRO
#define LOG(args) IPC_LOG(args)
#define LOG_ENABLED() ipcLogEnabled
#else
#define IPC_InitLog(prefix)
#define LOG(args)
#define LOG_ENABLED() (0)
#endif
#endif // !ipcLog_h__

View File

@@ -1,245 +0,0 @@
/* ***** 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 "prlog.h"
#include "ipcMessage.h"
ipcMessage::~ipcMessage()
{
if (mMsgHdr)
free(mMsgHdr);
}
void
ipcMessage::Reset()
{
if (mMsgHdr) {
free(mMsgHdr);
mMsgHdr = NULL;
}
mMsgOffset = 0;
mMsgComplete = PR_FALSE;
}
ipcMessage *
ipcMessage::Clone() const
{
ipcMessage *clone = new ipcMessage();
if (!clone)
return NULL;
// copy buf if non-null
if (mMsgHdr) {
clone->mMsgHdr = (ipcMessageHeader *) malloc(mMsgHdr->mLen);
memcpy(clone->mMsgHdr, mMsgHdr, mMsgHdr->mLen);
}
else
clone->mMsgHdr = NULL;
clone->mMsgOffset = mMsgOffset;
clone->mMsgComplete = mMsgComplete;
return clone;
}
PRStatus
ipcMessage::Init(const nsID &target, const char *data, PRUint32 dataLen)
{
if (mMsgHdr)
free(mMsgHdr);
mMsgComplete = PR_FALSE;
// allocate message data
PRUint32 msgLen = IPC_MSG_HEADER_SIZE + dataLen;
mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
if (!mMsgHdr) {
mMsgHdr = NULL;
return PR_FAILURE;
}
// fill in message data
mMsgHdr->mLen = msgLen;
mMsgHdr->mVersion = IPC_MSG_VERSION;
mMsgHdr->mFlags = 0;
mMsgHdr->mTarget = target;
if (data)
SetData(0, data, dataLen);
mMsgComplete = PR_TRUE;
return PR_SUCCESS;
}
PRStatus
ipcMessage::SetData(PRUint32 offset, const char *data, PRUint32 dataLen)
{
PR_ASSERT(mMsgHdr != NULL);
if (offset + dataLen > DataLen())
return PR_FAILURE;
memcpy((char *) Data() + offset, data, dataLen);
return PR_SUCCESS;
}
PRBool
ipcMessage::Equals(const nsID &target, const char *data, PRUint32 dataLen) const
{
return mMsgComplete &&
mMsgHdr->mTarget.Equals(target) &&
DataLen() == dataLen &&
memcmp(Data(), data, dataLen) == 0;
}
PRBool
ipcMessage::Equals(const ipcMessage *msg) const
{
PRUint32 msgLen = MsgLen();
return mMsgComplete && msg->mMsgComplete &&
msgLen == msg->MsgLen() &&
memcmp(MsgBuf(), msg->MsgBuf(), msgLen) == 0;
}
PRStatus
ipcMessage::WriteTo(char *buf,
PRUint32 bufLen,
PRUint32 *bytesWritten,
PRBool *complete)
{
if (!mMsgComplete)
return PR_FAILURE;
if (mMsgOffset == MsgLen()) {
*bytesWritten = 0;
*complete = PR_TRUE;
return PR_SUCCESS;
}
PRUint32 count = MsgLen() - mMsgOffset;
if (count > bufLen)
count = bufLen;
memcpy(buf, MsgBuf() + mMsgOffset, count);
mMsgOffset += count;
*bytesWritten = count;
*complete = (mMsgOffset == MsgLen());
return PR_SUCCESS;
}
PRStatus
ipcMessage::ReadFrom(const char *buf,
PRUint32 bufLen,
PRUint32 *bytesRead,
PRBool *complete)
{
*bytesRead = 0;
if (mMsgComplete) {
*complete = PR_TRUE;
return PR_SUCCESS;
}
if (mMsgHdr) {
// appending data to buffer
if (mMsgOffset < sizeof(PRUint32)) {
// we haven't learned the message length yet
if (mMsgOffset + bufLen < sizeof(PRUint32)) {
// we still don't know the length of the message!
memcpy((char *) mMsgHdr + mMsgOffset, buf, bufLen);
mMsgOffset += bufLen;
*bytesRead = bufLen;
*complete = PR_FALSE;
return PR_SUCCESS;
}
else {
// we now have enough data to determine the message length
PRUint32 count = sizeof(PRUint32) - mMsgOffset;
memcpy((char *) MsgBuf() + mMsgOffset, buf, count);
mMsgOffset += count;
buf += count;
bufLen -= count;
*bytesRead = count;
if (MsgLen() > IPC_MSG_GUESSED_SIZE) {
// realloc message buffer to the correct size
mMsgHdr = (ipcMessageHeader *) realloc(mMsgHdr, MsgLen());
}
}
}
}
else {
if (bufLen < sizeof(PRUint32)) {
// not enough data available in buffer to determine allocation size
// allocate a partial buffer
PRUint32 msgLen = IPC_MSG_GUESSED_SIZE;
mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
if (!mMsgHdr)
return PR_FAILURE;
memcpy(mMsgHdr, buf, bufLen);
mMsgOffset = bufLen;
*bytesRead = bufLen;
*complete = PR_FALSE;
return PR_SUCCESS;
}
else {
PRUint32 msgLen = *(PRUint32 *) buf;
mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
if (!mMsgHdr)
return PR_FAILURE;
mMsgHdr->mLen = msgLen;
mMsgOffset = 0;
}
}
// have mMsgHdr at this point
PRUint32 count = MsgLen() - mMsgOffset;
if (count > bufLen)
count = bufLen;
memcpy((char *) mMsgHdr + mMsgOffset, buf, count);
mMsgOffset += count;
*bytesRead += count;
*complete = mMsgComplete = (mMsgOffset == MsgLen());
return PR_SUCCESS;
}

View File

@@ -1,198 +0,0 @@
/* ***** 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 ipcMessage_h__
#define ipcMessage_h__
#include "nsID.h"
//
// ipc message format:
//
// +------------------------------------+
// | DWORD : length |
// +------------------+-----------------+
// | WORD : version | WORD : flags |
// +------------------+-----------------+
// | nsID : target |
// +------------------------------------+
// | data |
// +------------------------------------+
//
// header is 24 bytes. flags are defined below. default value of flags is
// zero. protocol implementations should ignore unrecognized flags. target
// is a 16 byte UUID indicating the intended receiver of this message.
//
struct ipcMessageHeader
{
PRUint32 mLen;
PRUint16 mVersion;
PRUint16 mFlags;
nsID mTarget;
};
#define IPC_MSG_VERSION (0x1)
#define IPC_MSG_HEADER_SIZE (sizeof(ipcMessageHeader))
#define IPC_MSG_GUESSED_SIZE (IPC_MSG_HEADER_SIZE + 64)
//
// the IPC message protocol supports synchronous messages. these messages can
// only be sent from a client to the daemon. a daemon module cannot send a
// synchronous message. the client sets the SYNC_QUERY flag to indicate that
// it is expecting a response with the SYNC_REPLY flag set.
//
#define IPC_MSG_FLAG_SYNC_QUERY (0x1)
#define IPC_MSG_FLAG_SYNC_REPLY (0x2)
//-----------------------------------------------------------------------------
// ipcMessage
//-----------------------------------------------------------------------------
class ipcMessage
{
public:
ipcMessage()
: mNext(NULL)
, mMsgHdr(NULL)
, mMsgOffset(0)
, mMsgComplete(PR_FALSE)
{ }
ipcMessage(const nsID &target, const char *data, PRUint32 dataLen)
: mNext(NULL)
, mMsgHdr(NULL)
, mMsgOffset(0)
{ Init(target, data, dataLen); }
~ipcMessage();
//
// reset message to uninitialized state
//
void Reset();
//
// create a copy of this message
//
ipcMessage *Clone() const;
//
// initialize message
//
// param:
// topic - message topic string
// data - message data (may be null to leave data uninitialized)
// dataLen - message data len
//
PRStatus Init(const nsID &target, const char *data, PRUint32 dataLen);
//
// copy data into the message's data section, starting from offset. this
// function can be used to write only a portion of the message's data.
//
// param:
// offset - destination offset
// data - data to write
// dataLen - number of bytes to write
//
PRStatus SetData(PRUint32 offset, const char *data, PRUint32 dataLen);
//
// access message flags
//
void SetFlag(PRUint16 flag) { mMsgHdr->mFlags |= flag; }
void ClearFlag(PRUint16 flag) { mMsgHdr->mFlags &= ~flag; }
PRBool TestFlag(PRUint16 flag) const { return mMsgHdr->mFlags & flag; }
//
// if true, the message is complete and the members of the message
// can be accessed.
//
PRBool IsComplete() const { return mMsgComplete; }
//
// readonly accessors
//
const ipcMessageHeader *Header() const { return mMsgHdr; }
const nsID &Target() const { return mMsgHdr->mTarget; }
const char *Data() const { return (char *) mMsgHdr + IPC_MSG_HEADER_SIZE; }
PRUint32 DataLen() const { return mMsgHdr->mLen - IPC_MSG_HEADER_SIZE; }
const char *MsgBuf() const { return (char *) mMsgHdr; }
PRUint32 MsgLen() const { return mMsgHdr->mLen; }
//
// message comparison functions
//
// param:
// topic - message topic (may be null)
// data - message data (must not be null)
// dataLen - message data length
//
PRBool Equals(const nsID &target, const char *data, PRUint32 dataLen) const;
PRBool Equals(const ipcMessage *msg) const;
//
// write the message to a buffer segment; segment need not be large
// enough to hold entire message. called repeatedly.
//
PRStatus WriteTo(char *buf,
PRUint32 bufLen,
PRUint32 *bytesWritten,
PRBool *complete);
//
// read the message from a buffer segment; segment need not contain
// the entire messgae. called repeatedly.
//
PRStatus ReadFrom(const char *buf,
PRUint32 bufLen,
PRUint32 *bytesRead,
PRBool *complete);
//
// a message can be added to a singly-linked list.
//
class ipcMessage *mNext;
private:
ipcMessageHeader *mMsgHdr;
// XXX document me
PRUint32 mMsgOffset;
PRPackedBool mMsgComplete;
};
#endif // !ipcMessage_h__

View File

@@ -1,58 +0,0 @@
/* ***** 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 "ipcMessagePrimitives.h"
ipcMessage_DWORD_STR::ipcMessage_DWORD_STR(const nsID &target,
PRUint32 first,
const char *second)
{
int sLen = strlen(second);
Init(target, NULL, sizeof(first) + sLen + 1);
SetData(0, (char *) &first, sizeof(first));
SetData(sizeof(first), second, sLen + 1);
}
ipcMessage_DWORD_ID::ipcMessage_DWORD_ID(const nsID &target,
PRUint32 first,
const nsID &second)
{
Init(target, NULL, sizeof(first) + sizeof(nsID));
SetData(0, (char *) &first, sizeof(first));
SetData(sizeof(first), (char *) &second, sizeof(nsID));
}

View File

@@ -1,109 +0,0 @@
/* ***** 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 ipcMessagePrimitives_h__
#define ipcMessagePrimitives_h__
#include "ipcMessage.h"
class ipcMessage_DWORD : public ipcMessage
{
public:
ipcMessage_DWORD(const nsID &target, PRUint32 first)
{
Init(target, (char *) &first, sizeof(first));
}
PRUint32 First() const
{
return ((PRUint32 *) Data())[0];
}
};
class ipcMessage_DWORD_DWORD : public ipcMessage
{
public:
ipcMessage_DWORD_DWORD(const nsID &target, PRUint32 first, PRUint32 second)
{
PRUint32 data[2] = { first, second };
Init(target, (char *) data, sizeof(data));
}
PRUint32 First() const
{
return ((PRUint32 *) Data())[0];
}
PRUint32 Second() const
{
return ((PRUint32 *) Data())[1];
}
};
class ipcMessage_DWORD_STR : public ipcMessage
{
public:
ipcMessage_DWORD_STR(const nsID &target, PRUint32 first, const char *second);
PRUint32 First() const
{
return ((PRUint32 *) Data())[0];
}
const char *Second() const
{
return Data() + sizeof(PRUint32);
}
};
class ipcMessage_DWORD_ID : public ipcMessage
{
public:
ipcMessage_DWORD_ID(const nsID &target, PRUint32 first, const nsID &second);
PRUint32 First() const
{
return ((PRUint32 *) Data())[0];
}
const nsID &Second() const
{
return * (const nsID *) (Data() + sizeof(PRUint32));
}
};
#endif // !ipcMessagePrimitives_h__

View File

@@ -1,46 +0,0 @@
/* ***** 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 ipcMessageQ_h__
#define ipcMessageQ_h__
#include "ipcMessage.h"
#include "ipcList.h"
typedef ipcList<ipcMessage> ipcMessageQ;
#endif // !ipcMessageQ_h__

View File

@@ -1,66 +0,0 @@
/* ***** 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 ipcMessageUtils_h__
#define ipcMessageUtils_h__
class ipcMessage;
//
// given code like this:
//
// const ipcmMessageClientID *msg = (const ipcmMessageClientID *) rawMsg;
//
// we can write:
//
// ipcMessageCast<ipcmMessageClientID> msg(rawMsg);
//
// XXX ipcMessageCast is probably not the best name for this class.
//
template<class T>
class ipcMessageCast
{
public:
ipcMessageCast() : mPtr(NULL) {}
ipcMessageCast(const ipcMessage *ptr) : mPtr((const T *) ptr) {}
void operator=(const ipcMessage *ptr) { mPtr = (const T *) ptr; }
const T *operator->() { return mPtr; }
private:
const T *mPtr;
};
#endif // !ipcMessageUtils_h__

View File

@@ -1,80 +0,0 @@
/* ***** 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 "ipcStringList.h"
void *
ipcStringNode::operator new(size_t size, const char *str) CPP_THROW_NEW
{
int len = strlen(str);
size += len;
ipcStringNode *node = (ipcStringNode *) ::operator new(size);
if (!node)
return NULL;
node->mNext = NULL;
memcpy(node->mData, str, len);
node->mData[len] = '\0';
return node;
}
ipcStringNode *
ipcStringList::FindNode(ipcStringNode *node, const char *str)
{
while (node) {
if (node->Equals(str))
return node;
node = node->mNext;
}
return NULL;
}
ipcStringNode *
ipcStringList::FindNodeBefore(ipcStringNode *node, const char *str)
{
ipcStringNode *prev = NULL;
while (node) {
if (node->Equals(str))
return prev;
prev = node;
node = node->mNext;
}
return NULL;
}

View File

@@ -1,107 +0,0 @@
/* ***** 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 ipcStringList_h__
#define ipcStringList_h__
#include <string.h>
#include "plstr.h"
#include "ipcList.h"
//-----------------------------------------------------------------------------
// string node
//-----------------------------------------------------------------------------
class ipcStringNode
{
public:
ipcStringNode() {}
const char *Value() const { return mData; }
PRBool Equals(const char *val) const { return strcmp(mData, val) == 0; }
PRBool EqualsIgnoreCase(const char *val) const { return PL_strcasecmp(mData, val) == 0; }
class ipcStringNode *mNext;
private:
void *operator new(size_t size, const char *str) CPP_THROW_NEW;
// this is actually bigger
char mData[1];
friend class ipcStringList;
};
//-----------------------------------------------------------------------------
// singly-linked list of strings
//-----------------------------------------------------------------------------
class ipcStringList : public ipcList<ipcStringNode>
{
public:
typedef ipcList<ipcStringNode> Super;
void Prepend(const char *str)
{
Super::Prepend(new (str) ipcStringNode());
}
void Append(const char *str)
{
Super::Append(new (str) ipcStringNode());
}
const ipcStringNode *Find(const char *str) const
{
return FindNode(mHead, str);
}
void FindAndDelete(const char *str)
{
ipcStringNode *node = FindNodeBefore(mHead, str);
if (node)
DeleteAfter(node);
else
DeleteFirst();
}
private:
static ipcStringNode *FindNode (ipcStringNode *head, const char *str);
static ipcStringNode *FindNodeBefore(ipcStringNode *head, const char *str);
};
#endif // !ipcStringList_h__

View File

@@ -1,277 +0,0 @@
/* ***** 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 "ipcm.h"
#include "prlog.h"
const nsID IPCM_TARGET =
{ /* 753ca8ff-c8c2-4601-b115-8c2944da1150 */
0x753ca8ff,
0xc8c2,
0x4601,
{0xb1, 0x15, 0x8c, 0x29, 0x44, 0xda, 0x11, 0x50}
};
//
// MSG_TYPE values
//
const PRUint32 ipcmMessagePing::MSG_TYPE = IPCM_MSG_TYPE_PING;
const PRUint32 ipcmMessageError::MSG_TYPE = IPCM_MSG_TYPE_ERROR;
const PRUint32 ipcmMessageClientHello::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_HELLO;
const PRUint32 ipcmMessageClientID::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ID;
const PRUint32 ipcmMessageClientInfo::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_INFO;
const PRUint32 ipcmMessageClientAddName::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ADD_NAME;
const PRUint32 ipcmMessageClientDelName::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_DEL_NAME;
const PRUint32 ipcmMessageClientAddTarget::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ADD_TARGET;
const PRUint32 ipcmMessageClientDelTarget::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_DEL_TARGET;
const PRUint32 ipcmMessageQueryClientByName::MSG_TYPE = IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME;
const PRUint32 ipcmMessageQueryClientInfo::MSG_TYPE = IPCM_MSG_TYPE_QUERY_CLIENT_INFO;
const PRUint32 ipcmMessageForward::MSG_TYPE = IPCM_MSG_TYPE_FORWARD;
//
// CLIENT_INFO message
//
// +-----------------------------------------+
// | DWORD : MSG_TYPE |
// +--------------------+--------------------+
// | DWORD : clientID |
// +--------------------+--------------------+
// | WORD : nameStart | WORD : nameCount |
// +--------------------+--------------------+
// | WORD : targetStart | WORD : targetCount |
// +--------------------+--------------------+
// | name[0] | (null byte) |
// +--------------------+--------------------+
// . . .
// . . .
// +--------------------+--------------------+
// | name[count - 1] | (null byte) |
// +--------------------+--------------------+
// | target[0] |
// +-----------------------------------------+
// . . .
// . . .
// +-----------------------------------------+
// | target[count - 1] |
// +-----------------------------------------+
//
struct ipcmClientInfoHeader
{
PRUint32 mType;
PRUint32 mID;
PRUint16 mNameStart;
PRUint16 mNameCount;
PRUint16 mTargetStart;
PRUint16 mTargetCount;
};
ipcmMessageClientInfo::ipcmMessageClientInfo(PRUint32 cID, const char *names[], const nsID *targets[])
{
ipcmClientInfoHeader hdr = {0};
hdr.mType = MSG_TYPE;
hdr.mID = cID;
hdr.mNameStart = sizeof(hdr);
PRUint32 i, namesLen = 0;
i = 0;
while (names[i]) {
namesLen += (strlen(names[i]) + 1);
++hdr.mNameCount;
++i;
}
i = 0;
while (targets[i]) {
++hdr.mTargetCount;
++i;
}
//
// compute target array starting offset
//
hdr.mTargetStart = hdr.mNameStart + namesLen;
//
// compute message length
//
PRUint32 dataLen = sizeof(hdr) + namesLen + hdr.mTargetCount * sizeof(nsID);
Init(IPCM_TARGET, NULL, dataLen);
//
// write message data
//
SetData(0, (const char *) &hdr, sizeof(hdr));
PRUint32 offset = sizeof(hdr);
for (i = 0; names[i]; ++i) {
PRUint32 len = strlen(names[i]) + 1;
SetData(offset, names[i], len);
offset += len;
}
for (i = 0; targets[i]; ++i) {
PRUint32 len = sizeof(nsID);
SetData(offset, (const char *) targets[i], len);
offset += len;
}
}
PRUint32
ipcmMessageClientInfo::ClientID() const
{
ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
return hdr->mID;
}
PRUint32
ipcmMessageClientInfo::NameCount() const
{
ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
return hdr->mNameCount;
}
PRUint32
ipcmMessageClientInfo::TargetCount() const
{
ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
return hdr->mTargetCount;
}
const char *
ipcmMessageClientInfo::NextName(const char *name) const
{
ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
if (!name)
return (const char *) hdr + hdr->mNameStart;
name += strlen(name) + 1;
if (name == (const char *) hdr + hdr->mTargetStart)
name = NULL;
return name;
}
const nsID *
ipcmMessageClientInfo::NextTarget(const nsID *target) const
{
ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
if (!target)
return (const nsID *) (Data() + hdr->mTargetStart);
if (++target == (const nsID *) (MsgBuf() + MsgLen()))
target = NULL;
return target;
}
//
// FORWARD message
//
// +-------------------------+
// | DWORD : MSG_TYPE |
// +-------------------------+
// | clientID |
// +-------------------------+
// | innerMsgHeader |
// +-------------------------+
// | innerMsgData |
// +-------------------------+
//
ipcmMessageForward::ipcmMessageForward(PRUint32 cID,
const nsID &target,
const char *data,
PRUint32 dataLen)
{
int len = sizeof(MSG_TYPE) + // MSG_TYPE
sizeof(cID) + // cID
IPC_MSG_HEADER_SIZE + // innerMsgHeader
dataLen; // innerMsgData
Init(IPCM_TARGET, NULL, len);
SetData(0, (char *) &MSG_TYPE, sizeof(MSG_TYPE));
SetData(4, (char *) &cID, sizeof(cID));
ipcMessageHeader hdr;
hdr.mLen = IPC_MSG_HEADER_SIZE + dataLen;
hdr.mVersion = IPC_MSG_VERSION;
hdr.mFlags = 0;
hdr.mTarget = target;
SetData(8, (char *) &hdr, IPC_MSG_HEADER_SIZE);
if (data)
SetInnerData(0, data, dataLen);
}
void
ipcmMessageForward::SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen)
{
SetData(8 + IPC_MSG_HEADER_SIZE + offset, data, dataLen);
}
PRUint32
ipcmMessageForward::DestClientID() const
{
return ((PRUint32 *) Data())[1];
}
const nsID &
ipcmMessageForward::InnerTarget() const
{
ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 8);
return hdr->mTarget;
}
const char *
ipcmMessageForward::InnerData() const
{
return Data() + 8 + IPC_MSG_HEADER_SIZE;
}
PRUint32
ipcmMessageForward::InnerDataLen() const
{
ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 8);
return hdr->mLen - IPC_MSG_HEADER_SIZE;
}

View File

@@ -1,322 +0,0 @@
/* ***** 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 ipcm_h__
#define ipcm_h__
#include "ipcMessage.h"
#include "ipcMessagePrimitives.h"
//
// IPCM (IPC Manager) protocol support
//
extern const nsID IPCM_TARGET;
enum {
IPCM_MSG_TYPE_PING,
IPCM_MSG_TYPE_ERROR,
IPCM_MSG_TYPE_CLIENT_HELLO,
IPCM_MSG_TYPE_CLIENT_ID,
IPCM_MSG_TYPE_CLIENT_INFO,
IPCM_MSG_TYPE_CLIENT_ADD_NAME,
IPCM_MSG_TYPE_CLIENT_DEL_NAME,
IPCM_MSG_TYPE_CLIENT_ADD_TARGET,
IPCM_MSG_TYPE_CLIENT_DEL_TARGET,
IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME,
IPCM_MSG_TYPE_QUERY_CLIENT_INFO,
// IPCM_MSG_TYPE_QUERY_MODULE, // check if module exists
IPCM_MSG_TYPE_FORWARD,
IPCM_MSG_TYPE_UNKNOWN // unknown message type
};
//
// returns IPCM message type.
//
static inline int
IPCM_GetMsgType(const ipcMessage *msg)
{
return ((const ipcMessage_DWORD *) msg)->First();
}
//
// NOTE: this file declares some helper classes that simplify construction
// and parsing of IPCM messages. each class subclasses ipcMessage, but
// adds no additional member variables. operator new should be used
// to allocate one of the IPCM helper classes, e.g.:
//
// ipcMessage *msg = new ipcmMessageClientHello("foo");
//
// given an arbitrary ipcMessage, it can be parsed using logic similar
// to the following:
//
// void func(const ipcMessage *unknown)
// {
// if (unknown->Topic().Equals(IPCM_TARGET)) {
// if (IPCM_GetMsgType(unknown) == IPCM_MSG_TYPE_CLIENT_ID) {
// ipcMessageCast<ipcmMessageClientID> msg(unknown);
// printf("Client ID: %u\n", msg->ClientID());
// }
// }
// }
//
// in other words, these classes are very very lightweight.
//
//
// IPCM_MSG_TYPE_PING
//
// this message may be sent from either the client or the daemon.
// if the daemon receives this message, then it will respond by
// sending back a PING to the client.
//
class ipcmMessagePing : public ipcMessage_DWORD
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessagePing()
: ipcMessage_DWORD(IPCM_TARGET, MSG_TYPE) {}
};
//
// IPCM_MSG_TYPE_ERROR
//
// this message may be sent from the daemon in place of an expected
// result. e.g., if a query fails, the daemon will send an error
// message to indicate the failure.
//
class ipcmMessageError : public ipcMessage_DWORD_DWORD
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageError(PRUint32 reason)
: ipcMessage_DWORD_DWORD(IPCM_TARGET, MSG_TYPE, reason) {}
PRUint32 Reason() const { return Second(); }
};
enum {
IPCM_ERROR_CLIENT_NOT_FOUND = 1
};
//
// IPCM_MSG_TYPE_CLIENT_HELLO
//
// this message is always the first message sent from a client to register
// itself with the daemon. the daemon responds to this message by sending
// the client a CLIENT_ID message informing the client of its client ID.
//
// XXX may want to pass other information here.
//
class ipcmMessageClientHello : public ipcMessage_DWORD
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageClientHello()
: ipcMessage_DWORD(IPCM_TARGET, MSG_TYPE) {}
};
//
// IPCM_MSG_TYPE_CLIENT_ID
//
// this message is sent from the daemon to identify a client's ID.
//
class ipcmMessageClientID : public ipcMessage_DWORD_DWORD
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageClientID(PRUint32 clientID)
: ipcMessage_DWORD_DWORD(IPCM_TARGET, MSG_TYPE, clientID) {}
PRUint32 ClientID() const { return Second(); }
};
//
// IPCM_MSG_TYPE_CLIENT_INFO
//
// this message is sent from the daemon to provide the list of names
// and targets for a particular client.
//
class ipcmMessageClientInfo : public ipcMessage
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageClientInfo(PRUint32 clientID, const char **names, const nsID **targets);
PRUint32 ClientID() const;
PRUint32 NameCount() const;
PRUint32 TargetCount() const;
const char *NextName(const char *name) const;
const nsID *NextTarget(const nsID *target) const;
};
//
// IPCM_MSG_TYPE_CLIENT_ADD_NAME
//
class ipcmMessageClientAddName : public ipcMessage_DWORD_STR
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageClientAddName(const char *name)
: ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {}
const char *Name() const { return Second(); }
};
//
// IPCM_MSG_TYPE_CLIENT_DEL_NAME
//
class ipcmMessageClientDelName : public ipcMessage_DWORD_STR
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageClientDelName(const char *name)
: ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {}
const char *Name() const { return Second(); }
};
//
// IPCM_MSG_TYPE_CLIENT_ADD_TARGET
//
class ipcmMessageClientAddTarget : public ipcMessage_DWORD_ID
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageClientAddTarget(const nsID &target)
: ipcMessage_DWORD_ID(IPCM_TARGET, MSG_TYPE, target) {}
const nsID &Target() const { return Second(); }
};
//
// IPCM_MSG_TYPE_CLIENT_DEL_TARGET
//
class ipcmMessageClientDelTarget : public ipcMessage_DWORD_ID
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageClientDelTarget(const nsID &target)
: ipcMessage_DWORD_ID(IPCM_TARGET, MSG_TYPE, target) {}
const nsID &Target() const { return Second(); }
};
//
// IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME
//
// this message is sent from a client to the daemon to request the ID of the
// client corresponding to the given name. in response the daemon will either
// send a CLIENT_ID or ERROR message.
//
class ipcmMessageQueryClientByName : public ipcMessage_DWORD_STR
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageQueryClientByName(const char *name)
: ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {}
const char *Name() const { return Second(); }
};
//
// IPCM_MSG_TYPE_QUERY_CLIENT_INFO
//
// thie message is sent from a client to the daemon to request complete
// information about the client corresponding to the given client ID. in
// response the daemon will either send a CLIENT_INFO or ERROR message.
//
class ipcmMessageQueryClientInfo : public ipcMessage_DWORD_DWORD
{
public:
static const PRUint32 MSG_TYPE;
ipcmMessageQueryClientInfo(PRUint32 clientID)
: ipcMessage_DWORD_DWORD(IPCM_TARGET, MSG_TYPE, clientID) {}
PRUint32 ClientID() const { return Second(); }
};
//
// IPCM_MSG_TYPE_FORWARD
//
// this message is only sent from the client to the daemon. the daemon
// will forward the contained message to the specified client. there
// is no guarantee that the message will be forwarded, and no error will
// be sent to the sender on failure.
//
class ipcmMessageForward : public ipcMessage
{
public:
static const PRUint32 MSG_TYPE;
//
// params:
// clientID - the client to which the message should be forwarded
// target - the message target
// data - the message data
// dataLen - the message data length
//
ipcmMessageForward(PRUint32 clientID,
const nsID &target,
const char *data,
PRUint32 dataLen);
//
// set inner message data, constrained to the data length passed
// to this class's constructor.
//
void SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen);
PRUint32 DestClientID() const;
const nsID &InnerTarget() const;
const char *InnerData() const;
PRUint32 InnerDataLen() const;
};
#endif // !ipcm_h__

View File

@@ -1,86 +0,0 @@
# ***** 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 = ipc
REQUIRES = \
xpcom \
$(NULL)
CPPSRCS = \
ipcd.cpp \
ipcClient.cpp \
ipcModuleReg.cpp \
ipcCommandModule.cpp
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
CPPSRCS += ipcdWin.cpp
else
CPPSRCS += ipcdUnix.cpp
endif
PROGRAM = mozipcd$(BIN_SUFFIX)
EXPORTS = \
ipcModule.h \
ipcModuleUtil.h \
$(NULL)
LOCAL_INCLUDES = \
-I$(srcdir)/../common \
$(NULL)
include $(topsrcdir)/config/config.mk
LIBS = \
$(EXTRA_DSO_LIBS) \
$(NSPR_LIBS) \
$(DIST)/lib/$(LIB_PREFIX)ipccom_s.$(LIB_SUFFIX) \
$(NULL)
include $(topsrcdir)/config/rules.mk
# For fruncate
ifeq ($(OS_ARCH),Linux)
DEFINES += -D_BSD_SOURCE
endif

View File

@@ -1,233 +0,0 @@
/* ***** 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"
#ifdef XP_UNIX
#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();
#ifdef XP_UNIX
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);
}
void
ipcClient::DelName(const char *name)
{
LOG(("deleting client name: %s\n", name));
mNames.FindAndDelete(name);
}
void
ipcClient::AddTarget(const nsID &target)
{
LOG(("adding client target\n"));
if (HasTarget(target))
return;
mTargets.Append(target);
}
void
ipcClient::DelTarget(const nsID &target)
{
LOG(("deleting client target\n"));
//
// cannot remove the IPCM target
//
if (!target.Equals(IPCM_TARGET))
mTargets.FindAndDelete(target);
}
#ifdef XP_UNIX
//
// 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

View File

@@ -1,144 +0,0 @@
/* ***** 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);
void DelName(const char *name);
PRBool HasName(const char *name) const { return mNames.Find(name) != NULL; }
void AddTarget(const nsID &target);
void 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
#ifdef XP_UNIX
//
// 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
#ifdef XP_UNIX
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__

View File

@@ -1,257 +0,0 @@
/* ***** 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 **) calloc(count + 1, sizeof(char *));
if (!strs)
return NULL;
count = 0;
for (node = nodes; node; node = node->mNext, ++count)
strs[count] = (char *) node->Value();
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 ipcmMessagePing());
}
static void
OnClientHello(ipcClient *client, const ipcMessage *rawMsg)
{
LOG(("got CLIENT_HELLO\n"));
IPC_SendMsg(client, new ipcmMessageClientID(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"));
ipcMessageCast<ipcmMessageClientAddName> msg(rawMsg);
const char *name = msg->Name();
if (name)
client->AddName(name);
}
static void
OnClientDelName(ipcClient *client, const ipcMessage *rawMsg)
{
LOG(("got CLIENT_DEL_NAME\n"));
ipcMessageCast<ipcmMessageClientDelName> msg(rawMsg);
const char *name = msg->Name();
if (name)
client->DelName(name);
}
static void
OnClientAddTarget(ipcClient *client, const ipcMessage *rawMsg)
{
LOG(("got CLIENT_ADD_TARGET\n"));
ipcMessageCast<ipcmMessageClientAddTarget> msg(rawMsg);
client->AddTarget(msg->Target());
}
static void
OnClientDelTarget(ipcClient *client, const ipcMessage *rawMsg)
{
LOG(("got CLIENT_DEL_TARGET\n"));
ipcMessageCast<ipcmMessageClientDelTarget> msg(rawMsg);
client->DelTarget(msg->Target());
}
static void
OnQueryClientByName(ipcClient *client, const ipcMessage *rawMsg)
{
LOG(("got QUERY_CLIENT_BY_NAME\n"));
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(result->ID()));
}
else {
LOG((" client does not exist\n"));
IPC_SendMsg(client, new ipcmMessageError(IPCM_ERROR_CLIENT_NOT_FOUND));
}
}
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(),
(const char **) names,
(const nsID **) targets));
free(names);
free(targets);
}
else {
LOG((" client does not exist\n"));
IPC_SendMsg(client, new ipcmMessageError(IPCM_ERROR_CLIENT_NOT_FOUND));
}
}
static void
OnForward(ipcClient *client, const ipcMessage *rawMsg)
{
LOG(("got FORWARD\n"));
ipcMessageCast<ipcmMessageForward> msg(rawMsg);
ipcClient *dest = IPC_GetClientByID(msg->DestClientID());
if (!dest) {
LOG((" destination client not found!\n"));
return;
}
ipcMessage *newMsg = new ipcMessage(msg->InnerTarget(),
msg->InnerData(),
msg->InnerDataLen());
IPC_SendMsg(dest, newMsg);
}
};
void
IPCM_HandleMsg(ipcClient *client, const ipcMessage *rawMsg)
{
static ipcCommandModule::MsgHandler handlers[] =
{
ipcCommandModule::OnPing,
NULL, // ERROR
ipcCommandModule::OnClientHello,
NULL, // CLIENT_ID
NULL, // CLIENT_INFO
ipcCommandModule::OnClientAddName,
ipcCommandModule::OnClientDelName,
ipcCommandModule::OnClientAddTarget,
ipcCommandModule::OnClientDelTarget,
ipcCommandModule::OnQueryClientByName,
ipcCommandModule::OnQueryClientInfo,
ipcCommandModule::OnForward,
};
int type = IPCM_GetMsgType(rawMsg);
LOG(("IPCM_HandleMsg [type=%d]\n", type));
if (type < IPCM_MSG_TYPE_UNKNOWN) {
if (handlers[type]) {
ipcCommandModule::MsgHandler handler = handlers[type];
handler(client, rawMsg);
}
}
}

View File

@@ -1,48 +0,0 @@
/* ***** 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__

View File

@@ -1,242 +0,0 @@
/* ***** 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"
class ipcMessage;
//
// 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__

View File

@@ -1,244 +0,0 @@
/* ***** 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
//
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_NotifyClientUp(ipcClient *client)
{
for (int i = 0; i < ipcModuleCount; ++i) {
ipcModuleRegEntry &entry = ipcModules[i];
if (entry.methods->clientUp)
entry.methods->clientUp(client);
}
}
void
IPC_NotifyClientDown(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;
}

View File

@@ -1,70 +0,0 @@
/* ***** 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_NotifyClientUp(ipcClient *);
void IPC_NotifyClientDown(ipcClient *);
#endif // !ipcModuleReg_h__

View File

@@ -1,151 +0,0 @@
/* ***** 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__

View File

@@ -1,187 +0,0 @@
/* ***** 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 "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"
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);
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;
}
//-----------------------------------------------------------------------------
// 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;
}
}

View File

@@ -1,76 +0,0 @@
/* ***** 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);
#endif // !IPCD_H__

View File

@@ -1,23 +0,0 @@
#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 100
//
// 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);
#endif // !ipcdPrivate_h__

View File

@@ -1,439 +0,0 @@
/* ***** 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>
#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"
void
IPC_Sleep(int seconds)
{
while (seconds > 0) {
LOG(("\rsleeping for %d seconds...", seconds));
PR_Sleep(PR_SecondsToInterval(1));
--seconds;
}
LOG(("\ndone sleeping\n"));
}
//-----------------------------------------------------------------------------
// ipc directory and locking...
//-----------------------------------------------------------------------------
static int ipcLockFD = 0;
static PRBool 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));
//
// open lock file. it remains open until we shutdown.
//
ipcLockFD = open(lockFile, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
free(lockFile);
if (ipcLockFD == -1)
return PR_FALSE;
//
// 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 PR_FALSE;
//
// 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 PR_TRUE;
}
static PRBool 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.
//
PRBool haveLock = AcquireDaemonLock(baseDir);
PL_strfree(baseDir);
if (haveLock) {
// delete an existing socket to prevent bind from failing.
unlink(socketPath);
}
return haveLock;
}
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;
}
}
//-----------------------------------------------------------------------------
// 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
//
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;
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;
//
// 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
//LOG(("sleeping for 2 seconds...\n"));
//PR_Sleep(PR_SecondsToInterval(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));
if (!InitDaemonDir(addr.local.path)) {
LOG(("InitDaemonDir failed\n"));
goto end;
}
listenFD = PR_OpenTCPSocket(PR_AF_LOCAL);
if (!listenFD) {
LOG(("PR_OpenUDPSocket failed [%d]\n", PR_GetError()));
goto end;
}
if (PR_Bind(listenFD, &addr) != PR_SUCCESS) {
LOG(("PR_Bind failed [%d]\n", PR_GetError()));
goto end;
}
IPC_InitModuleReg(argv[0]);
if (PR_Listen(listenFD, 5) != PR_SUCCESS) {
LOG(("PR_Listen failed [%d]\n", PR_GetError()));
goto end;
}
PollLoop(listenFD);
end:
IPC_ShutdownModuleReg();
//IPC_Sleep(5);
// 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();
if (listenFD) {
LOG(("closing socket\n"));
PR_Close(listenFD);
}
return 0;
}

View File

@@ -1,392 +0,0 @@
/* ***** 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_GetMsgType(msg) == IPCM_MSG_TYPE_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
//-----------------------------------------------------------------------------
int
main(int argc, char **argv)
{
IPC_InitLog("###");
LOG(("daemon started...\n"));
if (!AcquireLock())
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);
if (!ipcHwnd)
return -1;
// load modules
IPC_InitModuleReg(argv[0]);
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;
}

View File

@@ -1,47 +0,0 @@
# ***** 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
DIRS = lock
include $(topsrcdir)/config/rules.mk

View File

@@ -1,47 +0,0 @@
# ***** 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
DIRS = public src
include $(topsrcdir)/config/rules.mk

View File

@@ -1,52 +0,0 @@
# ***** 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 = ipc
XPIDLSRCS = \
ipcILockService.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,91 +0,0 @@
/* ***** 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 "nsISupports.idl"
interface ipcILockNotify;
/**
* This service provides named interprocess locking with either synchronous
* or asynchronous waiting.
*/
[scriptable, uuid(9f6dbe15-d851-4b00-912a-5ac0be88a409)]
interface ipcILockService : nsISupports
{
/**
* Call this method to acquire a named lock. Pass a notification handler
* to be notified asynchronously when the lock is acquired. Otherwise,
* this function will block until the lock is acquired.
*
* @param aLockName
* specifies the name of the lock
* @param aNotify
* notification callback (NULL to synchronously acquire lock)
* @param aWaitIfBusy
* wait for the lock to become available; otherwise, fail if lock
* is already held by some other process.
*/
void acquireLock(in string aLockName,
in ipcILockNotify aNotify,
in boolean aWaitIfBusy);
/**
* Call this method to release a named lock. This method can be called
* before OnAcquireLockComplete has been called, which will effectively
* cancel the request to acquire the named lock. OnAcquireLockComplete
* will not be called after a call to ReleaseLock.
*
* @param aLockName
* specifies the name of the lock
*/
void releaseLock(in string aLockName);
};
[scriptable, uuid(b4ac1160-98a4-4030-aecc-01137a05c94b)]
interface ipcILockNotify : nsISupports
{
/**
* Called to complete a call to AcquireLock.
*
* @status aLockName
* specifies the name of the lock
* @status aStatus
* NS_OK if lock has been acquired; reason for failure otherwise.
*/
void onAcquireLockComplete(in string aLockName,
in nsresult aStatus);
};

View File

@@ -1,70 +0,0 @@
# ***** 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
DIRS = module
MODULE = ipc
LIBRARY_NAME = ipclock_s
EXPORT_LIBRARY = 1
FORCE_STATIC_LIB = 1
MODULE_NAME = ipc
REQUIRES = \
xpcom \
string \
$(NULL)
CPPSRCS = \
ipcLockProtocol.cpp \
ipcLockService.cpp \
$(NULL)
LOCAL_INCLUDES = \
-I$(srcdir)/../../../common \
$(NULL)
EXPORTS = \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,50 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "prlog.h"
#include "ipcLockProtocol.h"
//-----------------------------------------------------------------------------
static inline PRUint8 get_opcode(const PRUint8 *buf)
{
return (buf[0] & 0x0f);
}
static inline PRUint8 get_flags(const PRUint8 *buf)
{
return (buf[0] & 0xf0) >> 4;
}
static inline const char *get_key(const PRUint8 *buf)
{
return ((const char *) buf) + 1;
}
//-----------------------------------------------------------------------------
PRUint8 *
IPC_FlattenLockMsg(const ipcLockMsg *msg, PRUint32 *bufLen)
{
PRUint32 len = 1 // header byte
+ strlen(msg->key) // key
+ 1; // null terminator
PRUint8 *buf = (PRUint8 *) malloc(len);
if (!buf)
return NULL;
buf[0] = (msg->opcode | (msg->flags << 4));
memcpy(&buf[1], msg->key, len - 1);
*bufLen = len;
return buf;
}
void
IPC_UnflattenLockMsg(const PRUint8 *buf, PRUint32 bufLen, ipcLockMsg *msg)
{
PR_ASSERT(bufLen > 2); // malformed buffer otherwise
msg->opcode = get_opcode(buf);
msg->flags = get_flags(buf);
msg->key = get_key(buf);
}

View File

@@ -1,60 +0,0 @@
#ifndef ipcLockProtocol_h__
#define ipcLockProtocol_h__
#include "prtypes.h"
//
// ipc lock message format:
//
// +----------------------------------+
// | opcode : 4 bits |
// +----------------------------------+
// | flags : 4 bits |
// +----------------------------------+
// | key : null terminated string |
// +----------------------------------+
//
// lock opcodes
#define IPC_LOCK_OP_ACQUIRE 1
#define IPC_LOCK_OP_RELEASE 2
#define IPC_LOCK_OP_STATUS_ACQUIRED 3
#define IPC_LOCK_OP_STATUS_FAILED 4
#define IPC_LOCK_OP_STATUS_BUSY 5
// lock flags
#define IPC_LOCK_FL_NONBLOCKING 1
// data structure for representing lock request message
struct ipcLockMsg
{
PRUint8 opcode;
PRUint8 flags;
const char * key;
};
//
// flatten a lock message
//
// returns a malloc'd buffer containing the flattened message. on return,
// bufLen contains the length of the flattened message.
//
PRUint8 *IPC_FlattenLockMsg(const ipcLockMsg *msg, PRUint32 *bufLen);
//
// unflatten a lock message
//
void IPC_UnflattenLockMsg(const PRUint8 *buf, PRUint32 bufLen, ipcLockMsg *msg);
//
// TargetID for message passing
//
#define IPC_LOCK_TARGETID \
{ /* 703ada8a-2d38-4d5d-9d39-03d1ccceb567 */ \
0x703ada8a, \
0x2d38, \
0x4d5d, \
{0x9d, 0x39, 0x03, 0xd1, 0xcc, 0xce, 0xb5, 0x67} \
}
#endif // !ipcLockProtocol_h__

View File

@@ -1,117 +0,0 @@
#include <stdlib.h>
#include "nsIServiceManager.h"
#include "ipcLockService.h"
#include "ipcLockProtocol.h"
#include "ipcCID.h"
#include "ipcLog.h"
static NS_DEFINE_IID(kIPCServiceCID, IPC_SERVICE_CID);
static const nsID kLockTargetID = IPC_LOCK_TARGETID;
ipcLockService::ipcLockService()
{
}
ipcLockService::~ipcLockService()
{
}
nsresult
ipcLockService::Init()
{
nsresult rv;
mIPCService = do_GetService(kIPCServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
return mIPCService->SetMessageObserver(kLockTargetID, this);
}
NS_IMPL_ISUPPORTS1(ipcLockService, ipcILockService)
NS_IMETHODIMP
ipcLockService::AcquireLock(const char *lockName, ipcILockNotify *notify, PRBool waitIfBusy)
{
LOG(("ipcLockService::AcquireLock [lock=%s sync=%u wait=%u]\n",
lockName, notify == nsnull, waitIfBusy));
ipcLockMsg msg;
msg.opcode = IPC_LOCK_OP_ACQUIRE;
msg.flags = (waitIfBusy ? 0 : IPC_LOCK_FL_NONBLOCKING);
msg.key = lockName;
PRUint32 bufLen;
PRUint8 *buf = IPC_FlattenLockMsg(&msg, &bufLen);
if (!buf)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = mIPCService->SendMessage(0, kLockTargetID, buf, bufLen, (notify == nsnull));
free(buf);
if (NS_FAILED(rv)) {
LOG((" SendMessage failed [rv=%x]\n", rv));
return rv;
}
if (notify) {
nsCStringKey hashKey(lockName);
mPendingTable.Put(&hashKey, notify);
}
return NS_OK;
}
NS_IMETHODIMP
ipcLockService::ReleaseLock(const char *lockName)
{
LOG(("ipcLockService::ReleaseLock [lock=%s]\n", lockName));
ipcLockMsg msg;
msg.opcode = IPC_LOCK_OP_RELEASE;
msg.flags = 0;
msg.key = lockName;
PRUint32 bufLen;
PRUint8 *buf = IPC_FlattenLockMsg(&msg, &bufLen);
if (!buf)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = mIPCService->SendMessage(0, kLockTargetID, buf, bufLen, PR_FALSE);
free(buf);
if (NS_FAILED(rv)) return rv;
nsCStringKey hashKey(lockName);
mPendingTable.Remove(&hashKey);
return NS_OK;
}
NS_IMETHODIMP
ipcLockService::OnMessageAvailable(const nsID &target, const PRUint8 *data, PRUint32 dataLen)
{
ipcLockMsg msg;
IPC_UnflattenLockMsg(data, dataLen, &msg);
LOG(("ipcLockService::OnMessageAvailable [lock=%s opcode=%u]\n", msg.key, msg.opcode));
nsresult status;
if (msg.opcode == IPC_LOCK_OP_STATUS_ACQUIRED)
status = NS_OK;
else
status = NS_ERROR_FAILURE;
NotifyComplete(msg.key, status);
return NS_OK;
}
void
ipcLockService::NotifyComplete(const char *lockName, nsresult status)
{
nsCStringKey hashKey(lockName);
nsISupports *obj = mPendingTable.Get(&hashKey); // ADDREFS
if (obj) {
nsCOMPtr<ipcILockNotify> notify = do_QueryInterface(obj);
NS_RELEASE(obj);
if (notify)
notify->OnAcquireLockComplete(lockName, status);
}
}

View File

@@ -1,32 +0,0 @@
#ifndef ipcLockService_h__
#define ipcLockService_h__
#include "ipcILockService.h"
#include "ipcIService.h"
#include "ipcList.h"
#include "nsCOMPtr.h"
#include "nsHashtable.h"
class ipcLockService : public ipcILockService
, public ipcIMessageObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IPCILOCKSERVICE
NS_DECL_IPCIMESSAGEOBSERVER
ipcLockService();
virtual ~ipcLockService();
nsresult Init();
private:
void NotifyComplete(const char *lockName, nsresult status);
nsCOMPtr<ipcIService> mIPCService;
// map from lockname to locknotify for pending notifications
nsSupportsHashtable mPendingTable;
};
#endif // !ipcLockService_h__

View File

@@ -1,77 +0,0 @@
# ***** 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 = ipc
LIBRARY_NAME = lockmodule
EXPORT_LIBRARY = 1
MODULE_NAME = ipc
REQUIRES = xpcom \
$(NULL)
CPPSRCS = ipcLockModule.cpp
LOCAL_INCLUDES = \
-I$(srcdir)/.. \
$(NULL)
EXTRA_OBJS = ../ipcLockProtocol.$(OBJ_SUFFIX)
EXTRA_DSO_LDOPTS = \
$(LIBS_DIR) \
$(NSPR_LIBS) \
$(EXTRA_DSO_LIBS) \
$(EXTRA_OBJS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
_IPC_FILES = \
$(LIB_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX) \
$(NULL)
libs:: $(_IPC_FILES)
$(INSTALL) $^ $(DIST)/bin/ipc/modules
install:: $(_IPC_FILES)
$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/ipc/modules

View File

@@ -1,238 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include "ipcModuleUtil.h"
#include "ipcLockProtocol.h"
#include "plhash.h"
static const nsID kLockTargetID = IPC_LOCK_TARGETID;
static void
ipcLockModule_Send(PRUint32 cid, const char *key, PRUint8 opcode)
{
ipcLockMsg msg = { opcode, 0, key };
PRUint32 bufLen;
PRUint8 *buf = IPC_FlattenLockMsg(&msg, &bufLen);
if (!buf)
return;
IPC_SendMsg(cid, kLockTargetID, buf, bufLen);
free(buf);
}
//-----------------------------------------------------------------------------
//
// gLockTable stores mapping from lock name to ipcLockContext
//
static PLHashTable *gLockTable = NULL;
//-----------------------------------------------------------------------------
struct ipcLockContext
{
PRUint32 mOwnerID; // client ID of this lock's owner
struct ipcLockContext *mNextPending; // pointer to client next in line to
// acquire this lock.
ipcLockContext(PRUint32 ownerID)
: mOwnerID(ownerID)
, mNextPending(NULL) {}
};
static void
ipcLockModule_AcquireLock(PRUint32 cid, PRUint8 flags, const char *key)
{
printf("$$$ acquiring lock [key=%s]\n", key);
if (!gLockTable)
return;
ipcLockContext *ctx;
ctx = (ipcLockContext *) PL_HashTableLookup(gLockTable, key);
if (ctx) {
//
// lock is already acquired, add this client to the queue. make
// sure this client doesn't already own the lock or live on the queue.
//
while (ctx->mOwnerID != cid && ctx->mNextPending)
ctx = ctx->mNextPending;
if (ctx->mOwnerID != cid) {
//
// if nonblocking, then send busy status message. otherwise,
// proceed to add this client to the pending queue.
//
if (flags & IPC_LOCK_FL_NONBLOCKING)
ipcLockModule_Send(cid, key, IPC_LOCK_OP_STATUS_BUSY);
else
ctx->mNextPending = new ipcLockContext(cid);
}
}
else {
//
// ok, add this lock to the table, and notify client that it now owns
// the lock!
//
ctx = new ipcLockContext(cid);
if (!ctx)
return;
PL_HashTableAdd(gLockTable, key, ctx);
ipcLockModule_Send(cid, key, IPC_LOCK_OP_STATUS_ACQUIRED);
}
}
static void
ipcLockModule_ReleaseLock(PRUint32 cid, const char *key)
{
printf("$$$ releasing lock [key=%s]\n", key);
if (!gLockTable)
return;
ipcLockContext *ctx;
ctx = (ipcLockContext *) PL_HashTableLookup(gLockTable, key);
if (ctx) {
//
// lock is already acquired _or_ maybe client is on the pending list.
//
if (ctx->mOwnerID == cid) {
if (ctx->mNextPending) {
//
// remove this element from the list. since this is the
// first element in the list, instead of removing it we
// shift the data from the next context into this one and
// delete the next context.
//
ipcLockContext *next = ctx->mNextPending;
ctx->mOwnerID = next->mOwnerID;
ctx->mNextPending = next->mNextPending;
delete next;
//
// notify client that it now owns the lock
//
ipcLockModule_Send(ctx->mOwnerID, key, IPC_LOCK_OP_STATUS_ACQUIRED);
}
else {
delete ctx;
PL_HashTableRemove(gLockTable, key);
}
}
else {
ipcLockContext *prev;
for (;;) {
prev = ctx;
ctx = ctx->mNextPending;
if (!ctx)
break;
if (ctx->mOwnerID == cid) {
// remove ctx from list
prev->mNextPending = ctx->mNextPending;
delete ctx;
break;
}
}
}
}
}
PR_STATIC_CALLBACK(PRIntn)
ipcLockModule_ReleaseByCID(PLHashEntry *he, PRIntn i, void *arg)
{
PRUint32 cid = *(PRUint32 *) arg;
ipcLockModule_ReleaseLock(cid, (const char *) he->key);
return HT_ENUMERATE_NEXT;
}
//-----------------------------------------------------------------------------
static void
ipcLockModule_Init()
{
printf("$$$ ipcLockModule_Init\n");
gLockTable = PL_NewHashTable(32,
PL_HashString,
PL_CompareStrings,
PL_CompareValues,
NULL,
NULL);
}
static void
ipcLockModule_Shutdown()
{
printf("$$$ ipcLockModule_Shutdown\n");
if (gLockTable) {
// XXX walk table destroying all ipcLockContext objects
PL_HashTableDestroy(gLockTable);
gLockTable = NULL;
}
}
static void
ipcLockModule_HandleMsg(ipcClientHandle client,
const nsID &target,
const void *data,
PRUint32 dataLen)
{
PRUint32 cid = IPC_GetClientID(client);
printf("$$$ ipcLockModule_HandleMsg [cid=%u]\n", cid);
ipcLockMsg msg;
IPC_UnflattenLockMsg((const PRUint8 *) data, dataLen, &msg);
switch (msg.opcode) {
case IPC_LOCK_OP_ACQUIRE:
ipcLockModule_AcquireLock(cid, msg.flags, msg.key);
break;
case IPC_LOCK_OP_RELEASE:
ipcLockModule_ReleaseLock(cid, msg.key);
break;
default:
PR_NOT_REACHED("invalid opcode");
}
}
static void
ipcLockModule_ClientUp(ipcClientHandle client)
{
printf("$$$ ipcLockModule_ClientUp [%u]\n", IPC_GetClientID(client));
}
static void
ipcLockModule_ClientDown(ipcClientHandle client)
{
PRUint32 cid = IPC_GetClientID(client);
printf("$$$ ipcLockModule_ClientDown [%u]\n", cid);
//
// enumerate lock table, release any locks held by this client.
//
PL_HashTableEnumerateEntries(gLockTable, ipcLockModule_ReleaseByCID, &cid);
}
//-----------------------------------------------------------------------------
static ipcModuleMethods gLockMethods =
{
IPC_MODULE_METHODS_VERSION,
ipcLockModule_Init,
ipcLockModule_Shutdown,
ipcLockModule_HandleMsg,
ipcLockModule_ClientUp,
ipcLockModule_ClientDown
};
static ipcModuleEntry gLockModuleEntry[] =
{
{ IPC_LOCK_TARGETID, &gLockMethods }
};
IPC_IMPL_GETMODULES(ipcLockModule, gLockModuleEntry)

View File

@@ -1,52 +0,0 @@
# ***** 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 = ipc
XPIDLSRCS = \
ipcIService.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,280 +0,0 @@
/* ***** 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 "nsISupports.idl"
interface ipcIMessageObserver;
interface ipcIClientObserver;
interface ipcIClientQueryHandler;
/**
* ipcIService
*
* the IPC service provides the means to communicate with an external IPC
* daemon and/or other mozilla-based applications on the same physical system.
* the IPC daemon hosts modules (some builtin and others dynamically loaded)
* with which applications may interact.
*
* at application startup, the IPC service will attempt to establish a
* connection with the IPC daemon. the IPC daemon will be automatically
* started if necessary. when a connection has been established, the IPC
* service will enumerate the "ipc-startup-category" and broadcast an
* "ipc-startup" notification using the observer service.
*
* when the connection to the IPC daemon is closed, an "ipc-shutdown"
* notification will be broadcast.
*
* each client has a name. the client name need not be unique across all
* clients, but it is usually good if it is. the IPC service does not require
* unique names. instead, the IPC daemon assigns each client a unique ID that
* is good for the current "session." clients can query other clients by name
* or by ID. the IPC service supports forwarding messages from one client to
* another via the IPC daemon.
*
* for performance reasons, this system should not be used to transfer large
* amounts of data. instead, applications may choose to utilize shared memory,
* and rely on the IPC service for synchronization and small message transfer
* only.
*/
[scriptable, uuid(53d3e3a7-528f-4b09-9eab-9416272568c0)]
interface ipcIService : nsISupports
{
/**************************************************************************
* properties of this process
*/
/**
* returns the "client ID" assigned to this process by the IPC daemon.
*
* @throws NS_ERROR_NOT_AVAILABLE if no connection to the IPC daemon.
*/
readonly attribute unsigned long clientID;
/**
* this process can appear under several client names. use the following
* methods to add or remove names for this process.
*
* for example, the mozilla browser might have the primary name "mozilla",
* but it could also register itself under the names "browser", "mail",
* "news", "addrbook", etc. other IPC clients can then query the IPC
* daemon for the client named "mail" in order to talk with a mail program.
*
* XXX An IPC client name resembles a XPCOM contract ID.
*/
void addClientName(in string aName);
void removeClientName(in string aName);
/**************************************************************************
* client query methods
*/
/**
* query info about a particular client given its client name. the
* observer's onClientInfo method is called with the result of the lookup,
* or if there is no client matching the given name, the observer's
* onClientDown method will be called instead.
*
* @param aName
* the name of the client being queried.
* @param aHandler
* the handler to be notified with result.
* @param aSync
* block the calling thread until the query completes.
*
* @return integer value identifying this query.
*/
unsigned long queryClientByName(in string aName,
in ipcIClientQueryHandler aHandler,
in boolean aSync);
/**
* query info about a particular client given its client ID. the observer's
* onClientInfo method is called with the result of the lookup, or if there
* is no client matching the given name, the observer's onClientDown method
* will be called instead.
*
* @param aClientID
* the ID of the client being queried.
* @param aHandler
* the handler to be notified with result.
* @param aSync
* block the calling thread until the query completes.
*
* @return integer value identifying this query.
*/
unsigned long queryClientByID(in unsigned long aClientID,
in ipcIClientQueryHandler aHandler,
in boolean aSync);
/**
* called to cancel a pending query.
*
* @param aQueryID
* the return value from one of the "query" methods.
*/
void cancelQuery(in unsigned long aQueryID);
/**
* set client observer. observer's onClientUp method is called whenever
* a new client comes online, and the observer's onClientDown method is
* called whenever a client goes offline.
*
* @param aObserver
* the client observer.
*/
void setClientObserver(in ipcIClientObserver aObserver);
// XXX need other functions to enumerate clients, clients implementing targets, etc.
/**************************************************************************
* message methods
*/
/**
* set a message observer for a particular message target.
*
* @param aTarget
* the message target being observed. any existing observer will
* be replaced.
* @param aObserver
* the message observer to receive incoming messages for the
* specified target. pass null to remove the existing observer.
*/
void setMessageObserver(in nsIDRef aTarget, in ipcIMessageObserver aObserver);
/**
* send message asynchronously to a client or a module in the IPC daemon.
* there is no guarantee that the message will be delivered.
*
* @param aClientID
* the client ID of the foreign application that should receive this
* message. pass 0 to send a message to a module in the IPC daemon.
* @param aTarget
* the target of the message. if aClientID is 0, then this is the
* ID of the daemon module that should receive this message.
* @param aData
* the message data.
* @param aDataLen
* the message length.
* @param aSync
* block the calling thread until a response to this message is
* received.
*/
void sendMessage(in unsigned long aClientID,
in nsIDRef aTarget,
[array, const, size_is(aDataLen)]
in octet aData,
in unsigned long aDataLen,
in boolean aSync);
};
/**
* ipcIMessageObserver
*/
[scriptable, uuid(e40a4a3c-2dc1-470e-ab7f-5675fe1f1384)]
interface ipcIMessageObserver : nsISupports
{
/**
* @param aTarget
* the target of the message, corresponding to the target this
* observer was registered under. this parameter is passed to allow
* an observer instance to receive messages for more than one target.
* @param aData
* the data of the message.
* @param aDataLen
* the data length of the message.
*/
void onMessageAvailable(in nsIDRef aTarget,
[array, const, size_is(aDataLen)]
in octet aData,
in unsigned long aDataLen);
};
/**
* ipcIClientObserver
*/
[scriptable, uuid(42283079-030c-4b13-b069-a08b7ad5eab2)]
interface ipcIClientObserver : nsISupports
{
const unsigned long CLIENT_UP = 1;
const unsigned long CLIENT_DOWN = 2;
void onClientStatus(in unsigned long aClientID,
in unsigned long aClientStatus);
};
/**
* ipcIClientQueryHandler
*
* the methods on this interface are called when the result of a client query
* becomes available.
*/
[scriptable, uuid(6fefea5c-f747-4bb0-972f-2a7b363a01db)]
interface ipcIClientQueryHandler : nsISupports
{
/**
* called on completion of a client query.
*
* @param aQueryID
* the return value from one of the "query" methods.
* @param aStatus
* the status of the query. if this is a failure code, then the
* query failed, otherwise the query succeeded. the value of this
* parameter explains the reason for any failure.
* @param aClientID
* ...
*/
void onQueryComplete(in unsigned long aQueryID,
in nsresult aStatus,
in unsigned long aClientID,
[array, size_is(aNameCount)]
in string aClientNames,
in unsigned long aNameCount,
[array, const, size_is(aTargetCount)]
in nsIDPtr aClientTargets,
in unsigned long aTargetCount);
};
%{C++
#define IPC_SERVICE_STARTUP_CATEGORY "ipc-startup-category"
#define IPC_SERVICE_STARTUP_TOPIC "ipc-startup"
#define IPC_SERVICE_SHUTDOWN_TOPIC "ipc-shutdown"
#define IPC_SERVICE_PREF_PRIMARY_CLIENT_NAME "ipc.primary-client-name"
%}

View File

@@ -1,73 +0,0 @@
# ***** 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 = ipc
LIBRARY_NAME = ipc_s
EXPORT_LIBRARY = 1
FORCE_STATIC_LIB = 1
MODULE_NAME = ipc
REQUIRES = \
xpcom \
string \
necko \
$(NULL)
CPPSRCS = \
ipcService.cpp \
ipcTransport.cpp \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
CPPSRCS += ipcTransportWin.cpp
else
CPPSRCS += ipcTransportUnix.cpp
CPPSRCS += ipcSocketProviderUnix.cpp
endif
LOCAL_INCLUDES = \
-I$(srcdir)/../common \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,556 +0,0 @@
/* ***** 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 "plstr.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsIEventQueue.h"
#include "nsIObserverService.h"
#include "nsICategoryManager.h"
#include "nsCategoryManagerUtils.h"
#include "nsNetError.h"
#include "nsEventQueueUtils.h"
#include "ipcConfig.h"
#include "ipcLog.h"
#include "ipcService.h"
#include "ipcMessageUtils.h"
#include "ipcm.h"
//-----------------------------------------------------------------------------
// helpers
//-----------------------------------------------------------------------------
static PRBool PR_CALLBACK
ipcReleaseMessageObserver(nsHashKey *aKey, void *aData, void* aClosure)
{
ipcIMessageObserver *obs = (ipcIMessageObserver *) aData;
NS_RELEASE(obs);
return PR_TRUE;
}
//----------------------------------------------------------------------------
// ipcClientQuery
//----------------------------------------------------------------------------
class ipcClientQuery
{
public:
ipcClientQuery(PRUint32 cID, ipcIClientQueryHandler *handler)
: mNext(nsnull)
, mQueryID(++gLastQueryID)
, mClientID(cID)
, mHandler(handler)
{ }
static PRUint32 gLastQueryID;
void SetClientID(PRUint32 cID) { mClientID = cID; }
void OnQueryComplete(nsresult status, const ipcmMessageClientInfo *msg);
PRUint32 QueryID() { return mQueryID; }
PRBool IsCanceled() { return mHandler.get() == NULL; }
ipcClientQuery *mNext;
private:
PRUint32 mQueryID;
PRUint32 mClientID;
nsCOMPtr<ipcIClientQueryHandler> mHandler;
};
PRUint32 ipcClientQuery::gLastQueryID = 0;
void
ipcClientQuery::OnQueryComplete(nsresult status, const ipcmMessageClientInfo *msg)
{
NS_ASSERTION(mHandler, "no handler");
PRUint32 nameCount = 0;
PRUint32 targetCount = 0;
const char **names = NULL;
const nsID **targets = NULL;
if (NS_SUCCEEDED(status)) {
nameCount = msg->NameCount();
targetCount = msg->TargetCount();
PRUint32 i;
names = (const char **) malloc(nameCount * sizeof(char *));
const char *lastName = NULL;
for (i = 0; i < nameCount; ++i) {
lastName = msg->NextName(lastName);
names[i] = lastName;
}
targets = (const nsID **) malloc(targetCount * sizeof(nsID *));
const nsID *lastTarget = NULL;
for (i = 0; i < targetCount; ++i) {
lastTarget = msg->NextTarget(lastTarget);
targets[i] = lastTarget;
}
}
mHandler->OnQueryComplete(mQueryID,
status,
mClientID,
names, nameCount,
targets, targetCount);
mHandler = NULL;
if (names)
free(names);
if (targets)
free(targets);
}
//-----------------------------------------------------------------------------
// ipcService
//-----------------------------------------------------------------------------
ipcService::ipcService()
: mTransport(nsnull)
, mClientID(0)
#if 0
, mDelayedMsgQ(nsnull)
, mWaiting(PR_FALSE)
, mInWaitMessage(PR_FALSE)
#endif
{
NS_INIT_ISUPPORTS();
IPC_InitLog(">>>");
}
ipcService::~ipcService()
{
NS_ASSERTION(mTransport == nsnull, "no xpcom-shutdown event??");
}
nsresult
ipcService::Init()
{
nsresult rv;
nsCOMPtr<nsIObserverService> observ(do_GetService("@mozilla.org/observer-service;1"));
if (observ) {
observ->AddObserver(this, "xpcom-shutdown", PR_FALSE);
observ->AddObserver(this, "profile-change-net-teardown", PR_FALSE);
observ->AddObserver(this, "profile-change-net-restore", PR_FALSE);
}
mTransport = new ipcTransport();
if (!mTransport)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTransport);
rv = mTransport->Init(this);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
void
ipcService::OnIPCMClientID(const ipcmMessageClientID *msg)
{
LOG(("ipcService::OnIPCMClientID\n"));
ipcClientQuery *query = mQueryQ.First();
if (!query) {
NS_WARNING("no pending query; ignoring message.");
return;
}
PRUint32 cID = msg->ClientID();
PRBool sync = msg->TestFlag(IPC_MSG_FLAG_SYNC_REPLY);
//
// (1) store client ID in query
// (2) move query to end of queue
// (3) issue CLIENT_INFO request
//
query->SetClientID(cID);
mQueryQ.RemoveFirst();
mQueryQ.Append(query);
mTransport->SendMsg(new ipcmMessageQueryClientInfo(cID), sync);
}
void
ipcService::OnIPCMClientInfo(const ipcmMessageClientInfo *msg)
{
LOG(("ipcService::OnIPCMClientInfo\n"));
ipcClientQuery *query = mQueryQ.First();
if (!query) {
NS_WARNING("no pending query; ignoring message.");
return;
}
if (!query->IsCanceled())
query->OnQueryComplete(NS_OK, msg);
mQueryQ.DeleteFirst();
}
void
ipcService::OnIPCMError(const ipcmMessageError *msg)
{
LOG(("ipcService::OnIPCMError [reason=0x%08x]\n", msg->Reason()));
ipcClientQuery *query = mQueryQ.First();
if (!query) {
NS_WARNING("no pending query; ignoring message.");
return;
}
if (!query->IsCanceled())
query->OnQueryComplete(NS_ERROR_FAILURE, NULL);
mQueryQ.DeleteFirst();
}
//-----------------------------------------------------------------------------
ipcService::
ProcessDelayedMsgQ_Event::ProcessDelayedMsgQ_Event(ipcService *serv,
ipcMessageQ *msgQ)
{
NS_ADDREF(mServ = serv);
mMsgQ = msgQ;
}
ipcService::
ProcessDelayedMsgQ_Event::~ProcessDelayedMsgQ_Event()
{
NS_RELEASE(mServ);
}
void * PR_CALLBACK
ipcService::ProcessDelayedMsgQ_EventHandler(PLEvent *plevent)
{
LOG(("ipcService::ProcessDelayedMsgQ_EventHandler\n"));
ProcessDelayedMsgQ_Event *ev = (ProcessDelayedMsgQ_Event *) plevent;
while (!ev->mMsgQ->IsEmpty()) {
ipcMessage *msg = ev->mMsgQ->First();
ev->mMsgQ->RemoveFirst();
ev->mServ->OnMessageAvailable(msg);
delete msg;
}
return nsnull;
}
void PR_CALLBACK
ipcService::ProcessDelayedMsgQ_EventCleanup(PLEvent *plevent)
{
delete (ProcessDelayedMsgQ_Event *) plevent;
}
//-----------------------------------------------------------------------------
// interface impl
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS2(ipcService, ipcIService, nsIObserver)
NS_IMETHODIMP
ipcService::GetClientID(PRUint32 *clientID)
{
if (mClientID == 0)
return NS_ERROR_NOT_AVAILABLE;
*clientID = mClientID;
return NS_OK;
}
NS_IMETHODIMP
ipcService::AddClientName(const char *name)
{
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
ipcMessage *msg = new ipcmMessageClientAddName(name);
if (!msg)
return NS_ERROR_OUT_OF_MEMORY;
return mTransport->SendMsg(msg);
}
NS_IMETHODIMP
ipcService::RemoveClientName(const char *name)
{
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
ipcMessage *msg = new ipcmMessageClientDelName(name);
if (!msg)
return NS_ERROR_OUT_OF_MEMORY;
return mTransport->SendMsg(msg);
}
NS_IMETHODIMP
ipcService::QueryClientByName(const char *name,
ipcIClientQueryHandler *handler,
PRBool sync,
PRUint32 *queryID)
{
if (!mTransport)
return NS_ERROR_NOT_AVAILABLE;
ipcMessage *msg;
msg = new ipcmMessageQueryClientByName(name);
if (!msg)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv;
rv = mTransport->SendMsg(msg, sync);
if (NS_FAILED(rv)) return rv;
ipcClientQuery *query = new ipcClientQuery(0, handler);
if (queryID)
*queryID = query->QueryID();
mQueryQ.Append(query);
return NS_OK;
}
NS_IMETHODIMP
ipcService::QueryClientByID(PRUint32 clientID,
ipcIClientQueryHandler *handler,
PRBool sync,
PRUint32 *queryID)
{
if (!mTransport)
return NS_ERROR_NOT_AVAILABLE;
ipcMessage *msg;
msg = new ipcmMessageQueryClientInfo(clientID);
if (!msg)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv;
rv = mTransport->SendMsg(msg, sync);
if (NS_FAILED(rv)) return rv;
ipcClientQuery *query = new ipcClientQuery(clientID, handler);
if (queryID)
*queryID = query->QueryID();
mQueryQ.Append(query);
return NS_OK;
}
NS_IMETHODIMP
ipcService::CancelQuery(PRUint32 queryID)
{
ipcClientQuery *query = mQueryQ.First();
while (query) {
if (query->QueryID() == queryID) {
query->OnQueryComplete(NS_BINDING_ABORTED, NULL);
break;
}
query = query->mNext;
}
return NS_OK;
}
NS_IMETHODIMP
ipcService::SetClientObserver(ipcIClientObserver *observer)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ipcService::SetMessageObserver(const nsID &target, ipcIMessageObserver *observer)
{
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
nsIDKey key(target);
PRBool sendAdd = PR_TRUE;
ipcIMessageObserver *cobs = (ipcIMessageObserver *) mObserverDB.Get(&key);
if (cobs) {
NS_RELEASE(cobs);
if (!observer) {
mObserverDB.Remove(&key);
//
// send CLIENT_DEL_TARGET
//
mTransport->SendMsg(new ipcmMessageClientDelTarget(target));
return NS_OK;
}
sendAdd = PR_FALSE;
}
if (observer) {
NS_ADDREF(observer);
mObserverDB.Put(&key, observer);
if (sendAdd) {
//
// send CLIENT_ADD_TARGET
//
mTransport->SendMsg(new ipcmMessageClientAddTarget(target));
}
}
return NS_OK;
}
NS_IMETHODIMP
ipcService::SendMessage(PRUint32 clientID,
const nsID &target,
const PRUint8 *data,
PRUint32 dataLen,
PRBool sync)
{
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
if (target.Equals(IPCM_TARGET)) {
NS_ERROR("do not try to talk to the IPCM target directly");
return NS_ERROR_INVALID_ARG;
}
ipcMessage *msg;
if (clientID)
msg = new ipcmMessageForward(clientID, target, (const char *) data, dataLen);
else
msg = new ipcMessage(target, (const char *) data, dataLen);
if (!msg)
return NS_ERROR_OUT_OF_MEMORY;
return mTransport->SendMsg(msg, sync);
}
//-----------------------------------------------------------------------------
// nsIObserver impl
//-----------------------------------------------------------------------------
NS_IMETHODIMP
ipcService::Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
{
if (strcmp(topic, "xpcom-shutdown") == 0 ||
strcmp(topic, "profile-change-net-teardown") == 0) {
// disconnect any message observers
mObserverDB.Reset(ipcReleaseMessageObserver, nsnull);
// drop daemon connection
if (mTransport)
mTransport->Shutdown();
}
else if (strcmp(topic, "profile-change-net-restore") == 0) {
if (mTransport)
mTransport->Init(this);
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// ipcTransportObserver impl
//-----------------------------------------------------------------------------
void
ipcService::OnConnectionEstablished(PRUint32 clientID)
{
mClientID = clientID;
//
// enumerate ipc startup category...
//
NS_CreateServicesFromCategory(IPC_SERVICE_STARTUP_CATEGORY,
NS_STATIC_CAST(ipcIService *, this),
IPC_SERVICE_STARTUP_TOPIC);
}
void
ipcService::OnConnectionLost()
{
mClientID = 0;
//
// error out any pending queries
//
while (mQueryQ.First()) {
ipcClientQuery *query = mQueryQ.First();
query->OnQueryComplete(NS_BINDING_ABORTED, NULL);
mQueryQ.DeleteFirst();
}
//
// broadcast ipc shutdown...
//
nsCOMPtr<nsIObserverService> observ(
do_GetService("@mozilla.org/observer-service;1"));
if (observ)
observ->NotifyObservers(NS_STATIC_CAST(ipcIService *, this),
IPC_SERVICE_SHUTDOWN_TOPIC, nsnull);
}
void
ipcService::OnMessageAvailable(const ipcMessage *msg)
{
LOG(("ipcService::OnMessageAvailable [msg=%p]\n", msg));
if (msg->Target().Equals(IPCM_TARGET)) {
//
// all IPCM messages stop here.
//
PRUint32 type = IPCM_GetMsgType(msg);
switch (type) {
case IPCM_MSG_TYPE_CLIENT_ID:
OnIPCMClientID((const ipcmMessageClientID *) msg);
break;
case IPCM_MSG_TYPE_CLIENT_INFO:
OnIPCMClientInfo((const ipcmMessageClientInfo *) msg);
break;
case IPCM_MSG_TYPE_ERROR:
OnIPCMError((const ipcmMessageError *) msg);
break;
}
}
else {
nsIDKey key(msg->Target());
ipcIMessageObserver *observer = (ipcIMessageObserver *) mObserverDB.Get(&key);
if (observer)
observer->OnMessageAvailable(msg->Target(),
(const PRUint8 *) msg->Data(),
msg->DataLen());
}
}

View File

@@ -1,110 +0,0 @@
/* ***** 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 ipcService_h__
#define ipcService_h__
#include "nsIRequest.h"
#include "nsCOMPtr.h"
#include "nsHashtable.h"
#include "plevent.h"
#include "ipcIService.h"
#include "ipcTransport.h"
#include "ipcList.h"
#include "ipcMessage.h"
#include "ipcMessageQ.h"
#include "ipcm.h"
typedef ipcList<class ipcClientQuery> ipcClientQueryQ;
//----------------------------------------------------------------------------
// ipcService
//----------------------------------------------------------------------------
class ipcService : public ipcIService
, public ipcTransportObserver
, public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IPCISERVICE
NS_DECL_NSIOBSERVER
ipcService();
virtual ~ipcService();
nsresult Init();
// ipcTransportObserver:
void OnConnectionEstablished(PRUint32 clientID);
void OnConnectionLost();
void OnMessageAvailable(const ipcMessage *);
//PRBool InWaitMessage() { return mInWaitMessage; }
private:
nsresult ErrorAccordingToIPCM(PRUint32 err);
void OnIPCMClientID(const ipcmMessageClientID *);
void OnIPCMClientInfo(const ipcmMessageClientInfo *);
void OnIPCMError(const ipcmMessageError *);
struct ProcessDelayedMsgQ_Event : PLEvent {
ProcessDelayedMsgQ_Event(ipcService *, ipcMessageQ *);
~ProcessDelayedMsgQ_Event();
ipcService *mServ;
ipcMessageQ *mMsgQ;
};
PR_STATIC_CALLBACK(void*) ProcessDelayedMsgQ_EventHandler(PLEvent *);
PR_STATIC_CALLBACK(void) ProcessDelayedMsgQ_EventCleanup(PLEvent *);
nsHashtable mObserverDB;
ipcTransport *mTransport;
PRUint32 mClientID;
ipcClientQueryQ mQueryQ;
#if 0
// WaitMessage support
ipcMessageQ *mDelayedMsgQ;
nsID mWaitingTarget;
PRPackedBool mWaiting;
PRPackedBool mInWaitMessage;
#endif
};
#endif // !ipcService_h__

View File

@@ -1,187 +0,0 @@
/* ***** 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 <stdlib.h>
#include <string.h>
#include "private/pprio.h"
#include "plstr.h"
#include "nsReadableUtils.h"
#include "nsMemory.h"
#include "ipcSocketProviderUnix.h"
#include "ipcLog.h"
static PRDescIdentity ipcIOLayerIdentity;
static PRIOMethods ipcIOLayerMethods;
static char *ipcIOSocketPath;
static PRStatus PR_CALLBACK
ipcIOLayerConnect(PRFileDesc* fd, const PRNetAddr* a, PRIntervalTime timeout)
{
if (!fd || !fd->lower)
return PR_FAILURE;
PRStatus status;
if (!ipcIOSocketPath || !ipcIOSocketPath[0]) {
NS_ERROR("not initialized");
return PR_FAILURE;
}
//
// ignore passed in address.
//
PRNetAddr addr;
addr.local.family = PR_AF_LOCAL;
PL_strncpyz(addr.local.path, ipcIOSocketPath, sizeof(addr.local.path));
status = fd->lower->methods->connect(fd->lower, &addr, timeout);
if (status != PR_SUCCESS)
return status;
//
// now that we have a connected socket; do some security checks on the
// file descriptor.
//
// (1) make sure owner matches
// (2) make sure permissions match expected permissions
//
// if these conditions aren't met then bail.
//
int unix_fd = PR_FileDesc2NativeHandle(fd->lower);
struct stat st;
if (fstat(unix_fd, &st) == -1) {
NS_ERROR("stat failed");
return PR_FAILURE;
}
if (st.st_uid != getuid() && st.st_uid != geteuid()) {
//
// on OSX 10.1.5, |fstat| has a bug when passed a file descriptor to
// a socket. it incorrectly returns a UID of 0. however, |stat|
// succeeds, but using |stat| introduces a race condition.
//
// XXX come up with a better security check.
//
if (st.st_uid != 0) {
NS_ERROR("userid check failed");
return PR_FAILURE;
}
if (stat(ipcIOSocketPath, &st) == -1) {
NS_ERROR("stat failed");
return PR_FAILURE;
}
if (st.st_uid != getuid() && st.st_uid != geteuid()) {
NS_ERROR("userid check failed");
return PR_FAILURE;
}
}
return PR_SUCCESS;
}
static void InitIPCMethods()
{
ipcIOLayerIdentity = PR_GetUniqueIdentity("moz:ipc-layer");
ipcIOLayerMethods = *PR_GetDefaultIOMethods();
ipcIOLayerMethods.connect = ipcIOLayerConnect;
}
NS_IMETHODIMP
ipcSocketProviderUnix::NewSocket(const char *host,
PRInt32 port,
const char *proxyHost,
PRInt32 proxyPort,
PRFileDesc **fd,
nsISupports **securityInfo)
{
static PRBool firstTime = PR_TRUE;
if (firstTime) {
InitIPCMethods();
firstTime = PR_FALSE;
}
PRFileDesc *sock = PR_OpenTCPSocket(PR_AF_LOCAL);
if (!sock) return NS_ERROR_OUT_OF_MEMORY;
PRFileDesc *layer = PR_CreateIOLayerStub(ipcIOLayerIdentity, &ipcIOLayerMethods);
if (!layer)
goto loser;
layer->secret = nsnull;
if (PR_PushIOLayer(sock, PR_GetLayersIdentity(sock), layer) != PR_SUCCESS)
goto loser;
*fd = sock;
return NS_OK;
loser:
if (layer)
layer->dtor(layer);
if (sock)
PR_Close(sock);
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
ipcSocketProviderUnix::AddToSocket(const char *host,
PRInt32 port,
const char *proxyHost,
PRInt32 proxyPort,
PRFileDesc *fd,
nsISupports **securityInfo)
{
NS_NOTREACHED("unexpected");
return NS_ERROR_UNEXPECTED;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(ipcSocketProviderUnix, nsISocketProvider)
void
ipcSocketProviderUnix::SetSocketPath(const char *socketPath)
{
if (ipcIOSocketPath)
free(ipcIOSocketPath);
ipcIOSocketPath = socketPath ? strdup(socketPath) : nsnull;
}

View File

@@ -1,58 +0,0 @@
/* ***** 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 ipcSocketProviderUnix_h__
#define ipcSocketProviderUnix_h__
#include "nsISocketProvider.h"
class ipcSocketProviderUnix : public nsISocketProvider
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISOCKETPROVIDER
ipcSocketProviderUnix() { NS_INIT_ISUPPORTS(); }
virtual ~ipcSocketProviderUnix() { }
//
// called to initialize the socket path
//
static void SetSocketPath(const char *socketPath);
};
#endif // !ipcSocketProviderUnix_h__

View File

@@ -1,341 +0,0 @@
/* ***** 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 "nsIServiceManager.h"
#include "nsIObserverService.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIFile.h"
#include "nsIProcess.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsEventQueueUtils.h"
#include "nsAutoLock.h"
#include "nsNetCID.h"
#include "netCore.h"
#include "prerror.h"
#include "plstr.h"
#include "ipcConfig.h"
#include "ipcLog.h"
#include "ipcMessageUtils.h"
#include "ipcTransport.h"
#include "ipcm.h"
//-----------------------------------------------------------------------------
// ipcTransport
//-----------------------------------------------------------------------------
nsresult
ipcTransport::Init(ipcTransportObserver *obs)
{
LOG(("ipcTransport::Init\n"));
mObserver = obs;
nsresult rv = PlatformInit();
if (NS_FAILED(rv)) return rv;
return Connect();
}
nsresult
ipcTransport::Shutdown()
{
LOG(("ipcTransport::Shutdown\n"));
mObserver = 0;
return Disconnect();
}
nsresult
ipcTransport::SendMsg(ipcMessage *msg, PRBool sync)
{
NS_ENSURE_ARG_POINTER(msg);
NS_ENSURE_TRUE(mObserver, NS_ERROR_NOT_INITIALIZED);
LOG(("ipcTransport::SendMsg [msg=%p dataLen=%u]\n", msg, msg->DataLen()));
ipcMessage *syncReply = nsnull;
{
nsAutoMonitor mon(mMonitor);
nsresult rv;
if (sync) {
msg->SetFlag(IPC_MSG_FLAG_SYNC_QUERY);
// flag before sending to avoid race with background thread.
mSyncWaiting = PR_TRUE;
}
if (mHaveConnection) {
rv = SendMsg_Internal(msg);
if (NS_FAILED(rv)) return rv;
}
else {
LOG((" delaying message until connected\n"));
mDelayedQ.Append(msg);
}
if (sync) {
if (!mSyncReplyMsg) {
LOG((" waiting for response...\n"));
mon.Wait();
}
if (!mSyncReplyMsg) {
LOG((" sync request timed out or was canceled\n"));
return NS_ERROR_FAILURE;
}
syncReply = mSyncReplyMsg;
mSyncReplyMsg = nsnull;
}
}
if (syncReply) {
// NOTE: may re-enter SendMsg
mObserver->OnMessageAvailable(syncReply);
delete syncReply;
}
return NS_OK;
}
void
ipcTransport::ProcessIncomingMsgQ()
{
LOG(("ipcTransport::ProcessIncomingMsgQ\n"));
// we can't hold mMonitor while calling into the observer, so we grab
// mIncomingMsgQ and NULL it out inside the monitor to prevent others
// from modifying it while we iterate over it.
ipcMessageQ *inQ;
{
nsAutoMonitor mon(mMonitor);
inQ = mIncomingMsgQ;
mIncomingMsgQ = nsnull;
}
if (inQ) {
while (!inQ->IsEmpty()) {
ipcMessage *msg = inQ->First();
if (mObserver)
mObserver->OnMessageAvailable(msg);
inQ->DeleteFirst();
}
delete inQ;
}
}
void *
ipcTransport::ProcessIncomingMsgQ_EventHandler(PLEvent *ev)
{
ipcTransport *self = (ipcTransport *) PL_GetEventOwner(ev);
self->ProcessIncomingMsgQ();
return nsnull;
}
void *
ipcTransport::ConnectionEstablished_EventHandler(PLEvent *ev)
{
ipcTransport *self = (ipcTransport *) PL_GetEventOwner(ev);
if (self->mObserver)
self->mObserver->OnConnectionEstablished(self->mClientID);
return nsnull;
}
void *
ipcTransport::ConnectionLost_EventHandler(PLEvent *ev)
{
ipcTransport *self = (ipcTransport *) PL_GetEventOwner(ev);
if (self->mObserver)
self->mObserver->OnConnectionLost();
return nsnull;
}
void
ipcTransport::Generic_EventCleanup(PLEvent *ev)
{
ipcTransport *self = (ipcTransport *) PL_GetEventOwner(ev);
NS_RELEASE(self);
delete ev;
}
// called on a background thread
void
ipcTransport::OnMessageAvailable(ipcMessage *rawMsg)
{
LOG(("ipcTransport::OnMessageAvailable [msg=%p dataLen=%u]\n",
rawMsg, rawMsg->DataLen()));
//
// XXX FIX COMMENTS XXX
//
// 1- append to incoming message queue
//
// 2- post event to main thread to handle incoming message queue
// or if sync waiting, unblock waiter so it can scan incoming
// message queue.
//
PRBool dispatchEvent = PR_FALSE;
PRBool connectEvent = PR_FALSE;
{
nsAutoMonitor mon(mMonitor);
if (!mHaveConnection) {
if (rawMsg->Target().Equals(IPCM_TARGET)) {
if (IPCM_GetMsgType(rawMsg) == IPCM_MSG_TYPE_CLIENT_ID) {
LOG((" connection established!\n"));
mHaveConnection = PR_TRUE;
// remember our client ID
ipcMessageCast<ipcmMessageClientID> msg(rawMsg);
mClientID = msg->ClientID();
connectEvent = PR_TRUE;
// move messages off the delayed message queue
while (!mDelayedQ.IsEmpty()) {
ipcMessage *msg = mDelayedQ.First();
mDelayedQ.RemoveFirst();
SendMsg_Internal(msg);
}
return;
}
}
LOG((" received unexpected first message!\n"));
return;
}
LOG((" mSyncWaiting=%u MSG_FLAG_SYNC_REPLY=%u\n",
mSyncWaiting, rawMsg->TestFlag(IPC_MSG_FLAG_SYNC_REPLY) != 0));
if (mSyncWaiting && rawMsg->TestFlag(IPC_MSG_FLAG_SYNC_REPLY)) {
mSyncReplyMsg = rawMsg;
mSyncWaiting = PR_FALSE;
mon.Notify();
}
else {
if (!mIncomingMsgQ) {
mIncomingMsgQ = new ipcMessageQ();
if (!mIncomingMsgQ)
return;
dispatchEvent = PR_TRUE;
}
mIncomingMsgQ->Append(rawMsg);
}
LOG((" connectEvent=%u dispatchEvent=%u mSyncReplyMsg=%p mIncomingMsgQ=%p\n",
connectEvent, dispatchEvent, mSyncReplyMsg, mIncomingMsgQ));
}
if (connectEvent)
ProxyToMainThread(ConnectionEstablished_EventHandler);
if (dispatchEvent)
ProxyToMainThread(ProcessIncomingMsgQ_EventHandler);
}
void
ipcTransport::ProxyToMainThread(PLHandleEventProc proc)
{
LOG(("ipcTransport::ProxyToMainThread\n"));
nsCOMPtr<nsIEventQueue> eq;
NS_GetMainEventQ(getter_AddRefs(eq));
if (eq) {
PLEvent *ev = new PLEvent();
PL_InitEvent(ev, this, proc, Generic_EventCleanup);
NS_ADDREF_THIS();
if (eq->PostEvent(ev) == PR_FAILURE) {
LOG((" PostEvent failed"));
NS_RELEASE_THIS();
delete ev;
}
}
}
nsresult
ipcTransport::SpawnDaemon()
{
LOG(("ipcTransport::SpawnDaemon\n"));
nsresult rv;
nsCOMPtr<nsIFile> file;
rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, getter_AddRefs(file));
if (NS_FAILED(rv)) return rv;
rv = file->AppendNative(NS_LITERAL_CSTRING(IPC_DAEMON_APP_NAME));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIProcess> proc(do_CreateInstance(NS_PROCESS_CONTRACTID,&rv));
if (NS_FAILED(rv)) return rv;
rv = proc->Init(file);
if (NS_FAILED(rv)) return rv;
PRUint32 pid;
return proc->Run(PR_FALSE, nsnull, 0, &pid);
}
// called on a background thread
nsresult
ipcTransport::OnConnectFailure()
{
LOG(("ipcTransport::OnConnectFailure\n"));
nsresult rv;
if (!mSpawnedDaemon) {
//
// spawn daemon on connection failure
//
rv = SpawnDaemon();
if (NS_FAILED(rv)) {
LOG((" failed to spawn daemon [rv=%x]\n", rv));
return rv;
}
mSpawnedDaemon = PR_TRUE;
}
Disconnect();
PRUint32 ms = 50 * mConnectionAttemptCount;
LOG((" sleeping for %u ms...\n", ms));
PR_Sleep(PR_MillisecondsToInterval(ms));
Connect();
return NS_OK;
}
NS_IMPL_THREADSAFE_ISUPPORTS0(ipcTransport)

View File

@@ -1,169 +0,0 @@
/* ***** 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 ipcTransport_h__
#define ipcTransport_h__
#include "nsIObserver.h"
#include "nsITimer.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "prmon.h"
#include "ipcMessage.h"
#include "ipcMessageQ.h"
#ifdef XP_UNIX
#include "ipcTransportUnix.h"
typedef nsISocketEventHandler ipcTransportSuper;
#else
typedef nsISupports ipcTransportSuper;
#endif
//----------------------------------------------------------------------------
// ipcTransportObserver interface
//----------------------------------------------------------------------------
class ipcTransportObserver
{
public:
virtual void OnConnectionEstablished(PRUint32 clientID) = 0;
virtual void OnConnectionLost() = 0;
virtual void OnMessageAvailable(const ipcMessage *) = 0;
};
//-----------------------------------------------------------------------------
// ipcTransport
//-----------------------------------------------------------------------------
class ipcTransport : public ipcTransportSuper
{
public:
NS_DECL_ISUPPORTS
ipcTransport()
: mMonitor(PR_NewMonitor())
, mObserver(nsnull)
, mIncomingMsgQ(nsnull)
, mSyncReplyMsg(nsnull)
, mSyncWaiting(nsnull)
, mSentHello(PR_FALSE)
, mHaveConnection(PR_FALSE)
, mSpawnedDaemon(PR_FALSE)
, mConnectionAttemptCount(0)
, mClientID(0)
{}
virtual ~ipcTransport()
{
PR_DestroyMonitor(mMonitor);
#ifdef XP_UNIX
if (mReceiver)
((ipcReceiver *) mReceiver.get())->ClearTransport();
#endif
}
nsresult Init(ipcTransportObserver *observer);
nsresult Shutdown();
// takes ownership of |msg|
nsresult SendMsg(ipcMessage *msg, PRBool sync = PR_FALSE);
PRBool HaveConnection() const { return mHaveConnection; }
public:
//
// internal to implementation
//
void OnMessageAvailable(ipcMessage *); // takes ownership
private:
//
// helpers
//
nsresult PlatformInit();
nsresult Connect();
nsresult Disconnect();
nsresult OnConnectFailure();
nsresult SendMsg_Internal(ipcMessage *msg);
nsresult SpawnDaemon();
void ProxyToMainThread(PLHandleEventProc);
void ProcessIncomingMsgQ();
PR_STATIC_CALLBACK(void *) ProcessIncomingMsgQ_EventHandler(PLEvent *);
PR_STATIC_CALLBACK(void *) ConnectionEstablished_EventHandler(PLEvent *);
PR_STATIC_CALLBACK(void *) ConnectionLost_EventHandler(PLEvent *);
PR_STATIC_CALLBACK(void) Generic_EventCleanup(PLEvent *);
//
// data
//
PRMonitor *mMonitor;
ipcTransportObserver *mObserver; // weak reference
ipcMessageQ mDelayedQ;
ipcMessageQ *mIncomingMsgQ;
ipcMessage *mSyncReplyMsg;
PRPackedBool mSyncWaiting;
PRPackedBool mSentHello;
PRPackedBool mHaveConnection;
PRPackedBool mSpawnedDaemon;
PRUint32 mConnectionAttemptCount;
PRUint32 mClientID;
#ifdef XP_UNIX
nsCOMPtr<nsIInputStreamNotify> mReceiver;
nsCOMPtr<nsISocketTransport> mTransport;
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsIOutputStream> mOutputStream;
//
// unix specific helpers
//
nsresult CreateTransport();
nsresult GetSocketPath(nsACString &);
public:
NS_DECL_NSISOCKETEVENTHANDLER
//
// internal helper methods
//
void OnConnectionLost(nsresult reason);
#endif
};
#endif // !ipcTransport_h__

View File

@@ -1,355 +0,0 @@
/* ***** 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 "prenv.h"
#include "nsIThread.h"
#include "nsIFile.h"
#include "nsIServiceManager.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "ipcSocketProviderUnix.h"
#include "nsISocketTransportService.h"
#include "nsEventQueueUtils.h"
#include "nsStreamUtils.h"
#include "nsNetCID.h"
#include "nsNetError.h"
#include "nsCOMPtr.h"
#include "ipcConfig.h"
#include "ipcLog.h"
#include "ipcTransportUnix.h"
#include "ipcTransport.h"
#include "ipcm.h"
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
#define IPC_BUFFER_SEGMENT_SIZE 4096
// for use with nsISocketTransportService::PostEvent
enum {
IPC_TRANSPORT_EVENT_CONNECT,
IPC_TRANSPORT_EVENT_DISCONNECT,
IPC_TRANSPORT_EVENT_SENDMSG
};
//-----------------------------------------------------------------------------
// ipcTransport (XP_UNIX specific methods)
//-----------------------------------------------------------------------------
nsresult
ipcTransport::PlatformInit()
{
PRNetAddr addr; // this way we know our buffer is large enough ;-)
IPC_GetDefaultSocketPath(addr.local.path, sizeof(addr.local.path));
ipcSocketProviderUnix::SetSocketPath(addr.local.path);
return NS_OK;
}
static NS_METHOD ipcWriteMessage(nsIOutputStream *stream,
void *closure,
char *segment,
PRUint32 offset,
PRUint32 count,
PRUint32 *countWritten)
{
ipcMessage *msg = (ipcMessage *) closure;
PRBool complete;
PRStatus rv = msg->WriteTo(segment, count, countWritten, &complete);
NS_ASSERTION(rv == PR_SUCCESS, "failed to write message");
// stop writing once the message has been completely written.
if (*countWritten == 0 && complete)
return NS_BASE_STREAM_CLOSED;
return NS_OK;
}
// runs on main thread or socket thread
nsresult
ipcTransport::SendMsg_Internal(ipcMessage *msg)
{
LOG(("ipcTransport::SendMsg_Internal [msg=%p dataLen=%u]\n", msg, msg->DataLen()));
if (nsIThread::IsMainThread()) {
LOG((" proxy to socket thread\n"));
nsresult rv;
nsCOMPtr<nsISocketTransportService> sts(
do_GetService(kSocketTransportServiceCID, &rv)); // XXX cache service
if (NS_FAILED(rv)) return rv;
return sts->PostEvent(this, IPC_TRANSPORT_EVENT_SENDMSG, 0, msg);
}
NS_ENSURE_TRUE(mOutputStream, NS_ERROR_NOT_INITIALIZED);
nsresult rv;
PRUint32 n;
rv = mOutputStream->WriteSegments(ipcWriteMessage, msg, msg->MsgLen(), &n);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(n == msg->MsgLen(), "not all bytes written");
delete msg; // done with message
return NS_OK;
}
// runs on main thread or socket thread
nsresult
ipcTransport::Connect()
{
LOG(("ipcTransport::Connect\n"));
if (++mConnectionAttemptCount > 20) {
LOG((" giving up after 20 unsuccessful connection attempts\n"));
return NS_ERROR_ABORT;
}
nsresult rv;
if (nsIThread::IsMainThread()) {
LOG((" proxy to socket thread\n"));
nsCOMPtr<nsISocketTransportService> sts(
do_GetService(kSocketTransportServiceCID, &rv)); // XXX cache service
if (NS_FAILED(rv)) return rv;
return sts->PostEvent(this, IPC_TRANSPORT_EVENT_CONNECT, 0, nsnull);
}
rv = CreateTransport();
if (NS_FAILED(rv)) return rv;
//
// send CLIENT_HELLO; expect CLIENT_ID in response.
//
rv = SendMsg_Internal(new ipcmMessageClientHello());
if (NS_FAILED(rv)) return rv;
//
// put the receiver to work...
//
nsCOMPtr<nsIAsyncInputStream> asyncIn = do_QueryInterface(mInputStream, &rv);
if (NS_FAILED(rv)) return rv;
if (!mReceiver) {
mReceiver = new ipcReceiver(this);
if (!mReceiver)
return NS_ERROR_OUT_OF_MEMORY;
}
return asyncIn->AsyncWait(mReceiver, 0, nsnull);
}
// runs on main thread or socket thread
nsresult
ipcTransport::Disconnect()
{
if (nsIThread::IsMainThread()) {
LOG((" proxy to socket thread\n"));
nsresult rv;
nsCOMPtr<nsISocketTransportService> sts(
do_GetService(kSocketTransportServiceCID, &rv)); // XXX cache service
if (NS_FAILED(rv)) return rv;
return sts->PostEvent(this, IPC_TRANSPORT_EVENT_DISCONNECT, 0, nsnull);
}
mHaveConnection = PR_FALSE;
if (mTransport) {
mTransport->Close(NS_BINDING_ABORTED);
mTransport = nsnull;
mInputStream = nsnull;
mOutputStream = nsnull;
}
return NS_OK;
}
// runs on socket transport thread
void
ipcTransport::OnConnectionLost(nsresult reason)
{
LOG(("ipcTransport::OnConnectionLost [reason=%x]\n", reason));
PRBool hadConnection = mHaveConnection;
Disconnect();
if (hadConnection)
ProxyToMainThread(ConnectionLost_EventHandler);
if (reason == NS_BINDING_ABORTED)
return;
if (NS_FAILED(reason))
OnConnectFailure();
}
nsresult
ipcTransport::CreateTransport()
{
nsresult rv;
nsCOMPtr<nsISocketTransportService> sts(
do_GetService(kSocketTransportServiceCID, &rv));
if (NS_FAILED(rv)) return rv;
const char *types[] = { IPC_SOCKET_TYPE };
rv = sts->CreateTransport(types, 1,
NS_LITERAL_CSTRING("127.0.0.1"), IPC_PORT, nsnull,
getter_AddRefs(mTransport));
if (NS_FAILED(rv)) return rv;
// open a blocking, buffered output stream (buffer size is unlimited)
rv = mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
IPC_BUFFER_SEGMENT_SIZE, PRUint32(-1),
getter_AddRefs(mOutputStream));
if (NS_FAILED(rv)) return rv;
// open a non-blocking, buffered input stream (buffer size limited)
rv = mTransport->OpenInputStream(0, IPC_BUFFER_SEGMENT_SIZE, 4,
getter_AddRefs(mInputStream));
return rv;
}
nsresult
ipcTransport::GetSocketPath(nsACString &socketPath)
{
nsCOMPtr<nsIFile> file;
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(file));
if (!file)
return NS_ERROR_FAILURE;
const char *logName = PR_GetEnv("LOGNAME");
if (!(logName && *logName)) {
logName = PR_GetEnv("USER");
if (!(logName && *logName)) {
LOG(("could not determine username from environment\n"));
return NS_ERROR_FAILURE;
}
}
nsCAutoString leaf;
leaf = NS_LITERAL_CSTRING(".mozilla-ipc-")
+ nsDependentCString(logName);
file->AppendNative(leaf);
file->AppendNative(NS_LITERAL_CSTRING("ipcd"));
file->GetNativePath(socketPath);
return NS_OK;
}
//----------------------------------------------------------------------------
// ipcTransport::nsISocketEventHandler
//----------------------------------------------------------------------------
NS_IMETHODIMP
ipcTransport::OnSocketEvent(PRUint32 type, PRUint32 uparam, void *vparam)
{
switch (type) {
case IPC_TRANSPORT_EVENT_CONNECT:
Connect();
break;
case IPC_TRANSPORT_EVENT_DISCONNECT:
Disconnect();
break;
case IPC_TRANSPORT_EVENT_SENDMSG:
SendMsg_Internal((ipcMessage *) vparam);
break;
}
return NS_OK;
}
//----------------------------------------------------------------------------
// ipcReceiver
//----------------------------------------------------------------------------
NS_IMPL_THREADSAFE_ISUPPORTS1(ipcReceiver, nsIInputStreamNotify)
NS_METHOD
ipcReceiver::ReadSegment(nsIInputStream *stream,
void *closure,
const char *ptr,
PRUint32 offset,
PRUint32 count,
PRUint32 *countRead)
{
ipcReceiver *self = (ipcReceiver *) closure;
*countRead = 0;
while (count) {
PRUint32 nread;
PRBool complete;
if (!self->mMsg) {
self->mMsg = new ipcMessage();
if (!self->mMsg)
return (self->mStatus = NS_ERROR_OUT_OF_MEMORY);
}
self->mMsg->ReadFrom(ptr, count, &nread, &complete);
if (complete) {
self->mTransport->OnMessageAvailable(self->mMsg); // hand over ownership
self->mMsg = nsnull;
}
count -= nread;
ptr += nread;
*countRead += nread;
}
return NS_OK;
}
NS_IMETHODIMP
ipcReceiver::OnInputStreamReady(nsIAsyncInputStream *stream)
{
LOG(("ipcReceiver::OnInputStreamReady\n"));
nsresult rv;
PRUint32 n;
rv = stream->ReadSegments(ReadSegment, this, IPC_BUFFER_SEGMENT_SIZE, &n);
if (NS_SUCCEEDED(rv)) {
rv = mStatus;
if (NS_SUCCEEDED(rv) && n == 0)
rv = NS_BASE_STREAM_CLOSED;
}
if (NS_FAILED(rv)) {
mTransport->OnConnectionLost(rv);
return NS_OK;
}
// continue reading...
return stream->AsyncWait(this, 0, nsnull);
}

View File

@@ -1,82 +0,0 @@
/* ***** 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 ipcTransportUnix_h__
#define ipcTransportUnix_h__
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsISocketTransport.h"
#include "nsISocketTransportService.h"
#include "prio.h"
#include "ipcMessageQ.h"
class ipcTransport;
//-----------------------------------------------------------------------------
// ipcReceiver
//-----------------------------------------------------------------------------
class ipcReceiver : public nsIInputStreamNotify
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIINPUTSTREAMNOTIFY
ipcReceiver(ipcTransport *transport)
: mTransport(transport)
, mMsg(nsnull)
, mStatus(NS_OK)
{ }
virtual ~ipcReceiver() { }
// called by the transport when it is going away.
void ClearTransport() { mTransport = nsnull; }
private:
static NS_METHOD ReadSegment(nsIInputStream *, void *, const char *,
PRUint32, PRUint32, PRUint32 *);
// the transport owns the receiver, so this back pointer does not need
// to be an owning reference.
ipcTransport *mTransport;
ipcMessage *mMsg; // message in progress
nsresult mStatus;
};
#endif // !ipcTransportUnix_h__

View File

@@ -1,315 +0,0 @@
/* ***** 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 "prprf.h"
#include "prmon.h"
#include "prthread.h"
#include "plevent.h"
#include "nsIServiceManager.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsAutoLock.h"
#include "ipcConfig.h"
#include "ipcLog.h"
#include "ipcTransport.h"
#include "ipcm.h"
//-----------------------------------------------------------------------------
// windows message thread
//-----------------------------------------------------------------------------
#define IPC_WM_SENDMSG (WM_USER + 0x1)
#define IPC_WM_SHUTDOWN (WM_USER + 0x2)
static nsresult ipcThreadStatus = NS_OK;
static PRThread *ipcThread = NULL;
static PRMonitor *ipcMonitor = NULL;
static HWND ipcDaemonHwnd = NULL;
static HWND ipcLocalHwnd = NULL;
static PRBool ipcShutdown = PR_FALSE; // not accessed on message thread!!
static ipcTransport *ipcTrans = NULL; // not accessed on message thread!!
//-----------------------------------------------------------------------------
// window proc
//-----------------------------------------------------------------------------
static LRESULT CALLBACK
ipcThreadWindowProc(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) {
COPYDATASTRUCT *cd = (COPYDATASTRUCT *) lParam;
if (cd && cd->lpData) {
ipcMessage *msg = new ipcMessage();
PRUint32 bytesRead;
PRBool complete;
PRStatus rv = msg->ReadFrom((const char *) cd->lpData, cd->cbData,
&bytesRead, &complete);
if (rv == PR_SUCCESS && complete && ipcTrans)
ipcTrans->OnMessageAvailable(msg); // takes ownership of msg
else {
LOG((" unable to deliver message [complete=%u]\n", complete));
delete msg;
}
}
return TRUE;
}
if (uMsg == IPC_WM_SENDMSG) {
ipcMessage *msg = (ipcMessage *) lParam;
if (msg) {
LOG((" sending message...\n"));
COPYDATASTRUCT cd;
cd.dwData = GetCurrentProcessId();
cd.cbData = (DWORD) msg->MsgLen();
cd.lpData = (PVOID) msg->MsgBuf();
SendMessageA(ipcDaemonHwnd, WM_COPYDATA, (WPARAM) hWnd, (LPARAM) &cd);
LOG((" done.\n"));
delete msg;
}
return 0;
}
if (uMsg == IPC_WM_SHUTDOWN) {
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//-----------------------------------------------------------------------------
// ipc thread functions
//-----------------------------------------------------------------------------
static void
ipcThreadFunc(void *arg)
{
LOG(("entering message thread\n"));
DWORD pid = GetCurrentProcessId();
WNDCLASS wc;
memset(&wc, 0, sizeof(wc));
wc.lpfnWndProc = ipcThreadWindowProc;
wc.lpszClassName = IPC_CLIENT_WINDOW_CLASS;
RegisterClass(&wc);
char wName[sizeof(IPC_CLIENT_WINDOW_NAME_PREFIX) + 20];
PR_snprintf(wName, sizeof(wName), "%s%u", IPC_CLIENT_WINDOW_NAME_PREFIX, pid);
ipcLocalHwnd = CreateWindow(IPC_CLIENT_WINDOW_CLASS, wName,
0, 0, 0, 10, 10, NULL, NULL, NULL, NULL);
{
nsAutoMonitor mon(ipcMonitor);
if (!ipcLocalHwnd)
ipcThreadStatus = NS_ERROR_FAILURE;
mon.Notify();
}
if (ipcLocalHwnd) {
MSG msg;
while (GetMessage(&msg, ipcLocalHwnd, 0, 0))
DispatchMessage(&msg);
ipcShutdown = PR_TRUE; // assuming atomic memory write
DestroyWindow(ipcLocalHwnd);
ipcLocalHwnd = NULL;
}
LOG(("exiting message thread\n"));
return;
}
static PRStatus
ipcThreadInit(ipcTransport *transport)
{
if (ipcThread)
return PR_FAILURE;
NS_ADDREF(ipcTrans = transport);
ipcShutdown = PR_FALSE;
ipcMonitor = PR_NewMonitor();
if (!ipcMonitor)
return PR_FAILURE;
// spawn message thread
ipcThread = PR_CreateThread(PR_USER_THREAD, ipcThreadFunc, NULL,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_JOINABLE_THREAD, 0);
if (!ipcThread) {
NS_WARNING("thread creation failed");
return PR_FAILURE;
}
// wait for hidden window to be created
{
nsAutoMonitor mon(ipcMonitor);
while (!ipcLocalHwnd && NS_SUCCEEDED(ipcThreadStatus))
mon.Wait();
}
if (NS_FAILED(ipcThreadStatus)) {
NS_WARNING("message thread failed");
return PR_FAILURE;
}
return PR_SUCCESS;
}
static PRStatus
ipcThreadShutdown()
{
if (PR_AtomicSet(&ipcShutdown, PR_TRUE) == PR_FALSE) {
LOG(("posting IPC_WM_SHUTDOWN message\n"));
PostMessage(ipcLocalHwnd, IPC_WM_SHUTDOWN, 0, 0);
}
LOG(("joining w/ message thread...\n"));
PR_JoinThread(ipcThread);
ipcThread = NULL;
//
// ok, now the message thread is dead
//
PR_DestroyMonitor(ipcMonitor);
ipcMonitor = NULL;
NS_RELEASE(ipcTrans);
// NS_RELEASE(ipcEventQ);
return PR_SUCCESS;
}
//-----------------------------------------------------------------------------
// windows specific ipcTransport impl
//-----------------------------------------------------------------------------
nsresult
ipcTransport::PlatformInit()
{
return NS_OK;
}
nsresult
ipcTransport::Disconnect()
{
mHaveConnection = PR_FALSE;
if (ipcThread)
ipcThreadShutdown();
// clear our reference to the daemon's HWND.
ipcDaemonHwnd = NULL;
return NS_OK;
}
nsresult
ipcTransport::Connect()
{
LOG(("ipcTransport::Connect\n"));
if (++mConnectionAttemptCount > 20) {
LOG((" giving up after 20 unsuccessful connection attempts\n"));
return NS_ERROR_ABORT;
}
NS_ENSURE_TRUE(ipcDaemonHwnd == NULL, NS_ERROR_ALREADY_INITIALIZED);
ipcDaemonHwnd = FindWindow(IPC_WINDOW_CLASS, IPC_WINDOW_NAME);
if (!ipcDaemonHwnd) {
LOG((" daemon does not appear to be running\n"));
//
// daemon does not exist
//
return OnConnectFailure();
}
//
// delay creation of the message thread until we know the daemon exists.
//
if (!ipcThread)
ipcThreadInit(this);
//
// send CLIENT_HELLO; expect CLIENT_ID in response.
//
SendMsg_Internal(new ipcmMessageClientHello());
mSentHello = PR_TRUE;
#if 0
// XXX need something else here
//
// begin a timer. if the timer fires before we get a CLIENT_ID, then
// assume the connection attempt failed.
//
nsresult rv;
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
rv = mTimer->Init(this, 1000, nsITimer::TYPE_ONE_SHOT);
return rv;
#endif
return NS_OK;
}
nsresult
ipcTransport::SendMsg_Internal(ipcMessage *msg)
{
LOG(("ipcTransport::SendMsg_Internal\n"));
if (ipcShutdown) {
NS_WARNING("unable to send message b/c message thread is shutdown\n");
goto loser;
}
if (!PostMessage(ipcLocalHwnd, IPC_WM_SENDMSG, 0, (LPARAM) msg)) {
LOG((" PostMessage failed w/ error = %u\n", GetLastError()));
goto loser;
}
return NS_OK;
loser:
delete msg;
return NS_ERROR_FAILURE;
}

View File

@@ -1,50 +0,0 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = test_ipc
REQUIRES = xpcom \
string \
ipc \
$(NULL)
CPPSRCS = \
TestIPC.cpp \
$(NULL)
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
include $(topsrcdir)/config/config.mk
LIBS = \
$(EXTRA_DSO_LIBS) \
$(MOZ_JS_LIBS) \
$(XPCOM_LIBS) \
$(NSPR_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,316 +0,0 @@
/* ***** 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 "ipcIService.h"
#include "ipcILockService.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include "nsIComponentRegistrar.h"
#include "nsString.h"
#include "prmem.h"
static const nsID kIPCMTargetID =
{ /* 753ca8ff-c8c2-4601-b115-8c2944da1150 */
0x753ca8ff,
0xc8c2,
0x4601,
{0xb1, 0x15, 0x8c, 0x29, 0x44, 0xda, 0x11, 0x50}
};
static const nsID kTestTargetID =
{ /* e628fc6e-a6a7-48c7-adba-f241d1128fb8 */
0xe628fc6e,
0xa6a7,
0x48c7,
{0xad, 0xba, 0xf2, 0x41, 0xd1, 0x12, 0x8f, 0xb8}
};
#define RETURN_IF_FAILED(rv, step) \
PR_BEGIN_MACRO \
if (NS_FAILED(rv)) { \
printf("*** %s failed: rv=%x\n", step, rv); \
return rv;\
} \
PR_END_MACRO
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static nsIEventQueue* gEventQ = nsnull;
static PRBool gKeepRunning = PR_TRUE;
//static PRInt32 gMsgCount = 0;
static ipcIService *gIpcServ = nsnull;
static ipcILockService *gIpcLockServ = nsnull;
static void
SendMsg(ipcIService *ipc, PRUint32 cID, const nsID &target, const char *data, PRUint32 dataLen, PRBool sync = PR_FALSE)
{
printf("*** sending message: [to-client=%u dataLen=%u]\n", cID, dataLen);
ipc->SendMessage(cID, target, (const PRUint8 *) data, dataLen, sync);
// gMsgCount++;
}
//-----------------------------------------------------------------------------
class myIpcMessageObserver : public ipcIMessageObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IPCIMESSAGEOBSERVER
myIpcMessageObserver() { NS_INIT_ISUPPORTS(); }
};
NS_IMPL_ISUPPORTS1(myIpcMessageObserver, ipcIMessageObserver)
NS_IMETHODIMP
myIpcMessageObserver::OnMessageAvailable(const nsID &target, const PRUint8 *data, PRUint32 dataLen)
{
printf("*** got message: [%s]\n", (const char *) data);
// if (--gMsgCount == 0)
// gKeepRunning = PR_FALSE;
return NS_OK;
}
//-----------------------------------------------------------------------------
class myIpcClientQueryHandler : public ipcIClientQueryHandler
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IPCICLIENTQUERYHANDLER
};
NS_IMPL_ISUPPORTS1(myIpcClientQueryHandler, ipcIClientQueryHandler)
NS_IMETHODIMP
myIpcClientQueryHandler::OnQueryComplete(PRUint32 aQueryID,
nsresult aStatus,
PRUint32 aClientID,
const char **aNames,
PRUint32 aNameCount,
const nsID **aTargets,
PRUint32 aTargetCount)
{
printf("*** query complete [queryID=%u status=0x%x clientID=%u]\n",
aQueryID, aStatus, aClientID);
PRUint32 i;
printf("*** names:\n");
for (i = 0; i < aNameCount; ++i)
printf("*** %d={%s}\n", i, aNames[i]);
printf("*** targets:\n");
for (i = 0; i < aTargetCount; ++i) {
const char *trailer;
if (aTargets[i]->Equals(kTestTargetID))
trailer = " (TEST_TARGET_ID)";
else if (aTargets[i]->Equals(kIPCMTargetID))
trailer = " (IPCM_TARGET_ID)";
else
trailer = " (unknown)";
char *str = aTargets[i]->ToString();
printf("*** %d=%s%s\n", i, str, trailer);
PR_Free(str);
}
if (aClientID != 0) {
const char hello[] = "hello friend!";
SendMsg(gIpcServ, aClientID, kTestTargetID, hello, sizeof(hello));
}
return NS_OK;
}
//-----------------------------------------------------------------------------
class myIpcLockNotify : public ipcILockNotify
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IPCILOCKNOTIFY
};
NS_IMPL_ISUPPORTS1(myIpcLockNotify, ipcILockNotify)
NS_IMETHODIMP
myIpcLockNotify::OnAcquireLockComplete(const char *lockName, nsresult status)
{
printf("*** OnAcquireLockComplete [lock=%s status=%x]\n", lockName, status);
gIpcLockServ->ReleaseLock(lockName);
return NS_OK;
}
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
nsresult rv;
{
nsCOMPtr<nsIServiceManager> servMan;
NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
if (registrar)
registrar->AutoRegister(nsnull);
// Create the Event Queue for this thread...
nsCOMPtr<nsIEventQueueService> eqs =
do_GetService(kEventQueueServiceCID, &rv);
RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)");
rv = eqs->CreateMonitoredThreadEventQueue();
RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue");
rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
RETURN_IF_FAILED(rv, "GetThreadEventQueue");
nsCOMPtr<ipcIService> ipcServ(do_GetService("@mozilla.org/ipc/service;1", &rv));
RETURN_IF_FAILED(rv, "do_GetService(ipcServ)");
NS_ADDREF(gIpcServ = ipcServ);
if (argc > 1) {
printf("*** using client name [%s]\n", argv[1]);
gIpcServ->AddClientName(argv[1]);
}
ipcServ->SetMessageObserver(kTestTargetID, new myIpcMessageObserver());
const char *data =
"01 this is a really long message.\n"
"02 this is a really long message.\n"
"03 this is a really long message.\n"
"04 this is a really long message.\n"
"05 this is a really long message.\n"
"06 this is a really long message.\n"
"07 this is a really long message.\n"
"08 this is a really long message.\n"
"09 this is a really long message.\n"
"10 this is a really long message.\n"
"11 this is a really long message.\n"
"12 this is a really long message.\n"
"13 this is a really long message.\n"
"14 this is a really long message.\n"
"15 this is a really long message.\n"
"16 this is a really long message.\n"
"17 this is a really long message.\n"
"18 this is a really long message.\n"
"19 this is a really long message.\n"
"20 this is a really long message.\n"
"21 this is a really long message.\n"
"22 this is a really long message.\n"
"23 this is a really long message.\n"
"24 this is a really long message.\n"
"25 this is a really long message.\n"
"26 this is a really long message.\n"
"27 this is a really long message.\n"
"28 this is a really long message.\n"
"29 this is a really long message.\n"
"30 this is a really long message.\n"
"31 this is a really long message.\n"
"32 this is a really long message.\n"
"33 this is a really long message.\n"
"34 this is a really long message.\n"
"35 this is a really long message.\n"
"36 this is a really long message.\n"
"37 this is a really long message.\n"
"38 this is a really long message.\n"
"39 this is a really long message.\n"
"40 this is a really long message.\n"
"41 this is a really long message.\n"
"42 this is a really long message.\n"
"43 this is a really long message.\n"
"44 this is a really long message.\n"
"45 this is a really long message.\n"
"46 this is a really long message.\n"
"47 this is a really long message.\n"
"48 this is a really long message.\n"
"49 this is a really long message.\n"
"50 this is a really long message.\n"
"51 this is a really long message.\n"
"52 this is a really long message.\n"
"53 this is a really long message.\n"
"54 this is a really long message.\n"
"55 this is a really long message.\n"
"56 this is a really long message.\n"
"57 this is a really long message.\n"
"58 this is a really long message.\n"
"59 this is a really long message.\n"
"60 this is a really long message.\n";
SendMsg(ipcServ, 0, kTestTargetID, data, strlen(data)+1, PR_TRUE);
PRUint32 queryID;
nsCOMPtr<ipcIClientQueryHandler> handler(new myIpcClientQueryHandler());
ipcServ->QueryClientByName("foopy", handler, PR_FALSE, &queryID);
//
// test lock service
//
nsCOMPtr<ipcILockService> lockService = do_GetService("@mozilla.org/ipc/lock-service;1", &rv);
RETURN_IF_FAILED(rv, "do_GetService(ipcLockServ)");
NS_ADDREF(gIpcLockServ = lockService);
nsCOMPtr<ipcILockNotify> notify(new myIpcLockNotify());
gIpcLockServ->AcquireLock("blah", notify, PR_TRUE);
rv = gIpcLockServ->AcquireLock("foo", nsnull, PR_TRUE);
printf("*** sync AcquireLock returned [rv=%x]\n", rv);
PLEvent *ev;
while (gKeepRunning) {
gEventQ->WaitForEvent(&ev);
gEventQ->HandleEvent(ev);
}
NS_RELEASE(gIpcServ);
printf("*** processing remaining events\n");
// process any remaining events
while (NS_SUCCEEDED(gEventQ->GetEvent(&ev)) && ev)
gEventQ->HandleEvent(ev);
printf("*** done\n");
} // this scopes the nsCOMPtrs
// no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
rv = NS_ShutdownXPCOM(nsnull);
NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
return 0;
}

View File

@@ -1,75 +0,0 @@
# ***** 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 = testmodule
LIBRARY_NAME = testmodule
EXPORT_LIBRARY = 1
MODULE_NAME = testmodule
REQUIRES = xpcom \
ipc \
$(NULL)
CPPSRCS = TestModule.cpp
LOCAL_INCLUDES = \
-I$(srcdir)/../common \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(LIBS_DIR) \
$(NSPR_LIBS) \
$(EXTRA_DSO_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
_IPC_FILES = \
$(LIB_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX) \
$(NULL)
libs:: $(_IPC_FILES)
$(INSTALL) $^ $(DIST)/bin/ipc/modules
install:: $(_IPC_FILES)
$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/ipc/modules

View File

@@ -1,62 +0,0 @@
#include <stdio.h>
#include "ipcModuleUtil.h"
#define TEST_MODULE_ID \
{ /* e628fc6e-a6a7-48c7-adba-f241d1128fb8 */ \
0xe628fc6e, \
0xa6a7, \
0x48c7, \
{0xad, 0xba, 0xf2, 0x41, 0xd1, 0x12, 0x8f, 0xb8} \
}
static const nsID kTestModuleID = TEST_MODULE_ID;
struct TestModule
{
static void Init()
{
printf("*** TestModule::Init\n");
}
static void Shutdown()
{
printf("*** TestModule::Shutdown\n");
}
static void HandleMsg(ipcClientHandle client,
const nsID &target,
const void *data,
PRUint32 dataLen)
{
printf("*** TestModule::HandleMsg [%s]\n", (const char *) data);
static const char buf[] = "pong";
IPC_SendMsg(client, kTestModuleID, buf, sizeof(buf));
}
static void ClientUp(ipcClientHandle client)
{
printf("*** TestModule::ClientUp [%u]\n", IPC_GetClientID(client));
}
static void ClientDown(ipcClientHandle client)
{
printf("*** TestModule::ClientDown [%u]\n", IPC_GetClientID(client));
}
};
static ipcModuleMethods gTestMethods =
{
IPC_MODULE_METHODS_VERSION,
TestModule::Init,
TestModule::Shutdown,
TestModule::HandleMsg,
TestModule::ClientUp,
TestModule::ClientDown
};
static ipcModuleEntry gTestModuleEntry[] =
{
{ TEST_MODULE_ID, &gTestMethods }
};
IPC_IMPL_GETMODULES(TestModule, gTestModuleEntry)