adding IPC framework -- NOT PART OF THE BUILD

This commit is contained in:
darin%netscape.com 2002-10-31 08:19:27 +00:00
Родитель 8546c64322
Коммит d34899750d
36 изменённых файлов: 4582 добавлений и 0 удалений

31
modules/ipc/Makefile.in Normal file
Просмотреть файл

@ -0,0 +1,31 @@
#
# 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 build test
include $(topsrcdir)/config/rules.mk

12
modules/ipc/README Normal file
Просмотреть файл

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

Просмотреть файл

@ -0,0 +1,75 @@
# ***** 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 \
ipc \
$(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) \
$(NULL)
LOCAL_INCLUDES = \
-I$(srcdir)/../src \
-I$(srcdir)/../util \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(LIBS_DIR) \
$(EXTRA_DSO_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,63 @@
/* ***** 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} \
}
#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 // !ipcCID_h__

Просмотреть файл

@ -0,0 +1,72 @@
/* ***** 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 "nsIGenericFactory.h"
#include "ipcService.h"
#include "ipcSocketProvider.h"
#include "ipcCID.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)
NS_GENERIC_FACTORY_CONSTRUCTOR(ipcSocketProvider)
////////////////////////////////////////////////////////////////////////
// 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, },
{ IPC_SOCKETPROVIDER_CLASSNAME,
IPC_SOCKETPROVIDER_CID,
NS_NETWORK_SOCKET_CONTRACTID_PREFIX "ipc",
ipcSocketProviderConstructor, },
};
////////////////////////////////////////////////////////////////////////
// Implement the NSGetModule() exported function for your module
// and the entire implementation of the module object.
//
NS_IMPL_NSGETMODULE(ipcModule, components)

Просмотреть файл

@ -0,0 +1,66 @@
# ***** 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 = \
ipcMessage.cpp \
ipcMessageQ.cpp \
ipcm.cpp
EXPORTS = \
ipcMessage.h \
ipcMessageQ.h \
ipcm.h \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,71 @@
/* ***** 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)
//
// XXX since win9x/me doesn't support named pipes, we resort to using a
// localhost TCP/IP socket (for now). this is not a great solution for
// several reasons:
// (1) we have to agree on a port number.
// (2) opens up a big security hole that needs to be plugged somehow.
//
// we should probably use WM_COPYDATA instead.
//
#define IPC_USE_INET 1
#define IPC_PORT 14400
#define IPC_SOCKET_TYPE nsnull
#define IPC_DEFAULT_SOCKET_PATH ""
#define IPC_DAEMON_APP_NAME "mozipcd.exe"
#define IPC_PATH_SEP_CHAR '\\'
#define IPC_PATH_SEP_CHAR_S "\\"
#else
//
// use UNIX domain socket
//
#define IPC_PORT 0
#define IPC_SOCKET_TYPE "ipc"
#define IPC_DEFAULT_SOCKET_PATH "/tmp/sock"
#define IPC_DAEMON_APP_NAME "mozipcd"
#define IPC_PATH_SEP_CHAR '/'
#define IPC_PATH_SEP_CHAR_S "/"
#endif
#endif // !ipcProto_h__

Просмотреть файл

@ -0,0 +1,245 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla IPC.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <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()
{
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;
}

Просмотреть файл

@ -0,0 +1,177 @@
/* ***** 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 for future use and must be zero in this
// version of the ipc message format. 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)
//-----------------------------------------------------------------------------
// ipcMessage
//-----------------------------------------------------------------------------
class ipcMessage
{
public:
ipcMessage()
: mNext(NULL)
, mMsgHdr(NULL)
, mMsgOffset(0)
, mMsgComplete(PR_FALSE)
{ }
~ipcMessage();
//
// reset message to uninitialized state
//
void Reset();
//
// create a copy of this message
//
ipcMessage *Clone();
//
// 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);
//
// 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__

Просмотреть файл

@ -0,0 +1,76 @@
/* ***** 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 "ipcMessageQ.h"
#include "ipcMessage.h"
void
ipcMessageQ::Append(ipcMessage *msg)
{
msg->mNext = NULL;
if (mTail) {
mTail->mNext = msg;
mTail = msg;
}
else
mTail = mHead = msg;
}
void
ipcMessageQ::AdvanceHead()
{
mHead = mHead->mNext;
if (!mHead)
mTail = NULL;
}
void
ipcMessageQ::DeleteFirst()
{
ipcMessage *first = mHead;
if (first) {
AdvanceHead();
delete first;
}
}
void
ipcMessageQ::DeleteAll()
{
while (mHead)
DeleteFirst();
}

Просмотреть файл

@ -0,0 +1,88 @@
/* ***** 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 "prtypes.h"
class ipcMessage;
//-----------------------------------------------------------------------------
// simple queue of ipcMessage objects
//-----------------------------------------------------------------------------
class ipcMessageQ
{
public:
ipcMessageQ()
: mHead(NULL)
, mTail(NULL)
{ }
~ipcMessageQ() { DeleteAll(); }
//
// appends msg to the end of the queue. caller loses ownership of |msg|.
//
void Append(ipcMessage *msg);
//
// removes first element w/o deleting it
//
void RemoveFirst() { if (mHead) AdvanceHead(); }
//
// deletes first element
//
void DeleteFirst();
//
// deletes all elements
//
void DeleteAll();
ipcMessage *First() { return mHead; }
PRBool IsEmpty() { return mHead == NULL; }
private:
void AdvanceHead();
ipcMessage *mHead;
ipcMessage *mTail;
};
#endif // !ipcMessageQ_h__

248
modules/ipc/common/ipcm.cpp Normal file
Просмотреть файл

@ -0,0 +1,248 @@
/* ***** 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}
};
static const char IPCM_PING[] = { (char) IPCM_MSG_PING };
static const PRUint32 IPCM_PING_LEN = sizeof(IPCM_PING);
static const char IPCM_CNAME[] = { (char) IPCM_MSG_CNAME };
static const PRUint32 IPCM_CNAME_LEN = sizeof(IPCM_CNAME);
//
// +--------------------+
// | BYTE : msgType |
// +--------------------+
// | (variable) |
// +--------------------+
//
int
IPCM_GetMsgType(const ipcMessage *msg)
{
// make sure message topic matches
if (msg->Target().Equals(IPCM_TARGET)) {
// the type is encoded as the first byte
char type = msg->Data()[0];
if (type < IPCM_MSG_UNKNOWN)
return type;
}
return IPCM_MSG_UNKNOWN;
}
//
// PING message
//
// +----------------------+
// | BYTE - IPCM_MSG_PING |
// +----------------------+
//
const char ipcmMessagePING::MSG_TYPE = (char) IPCM_MSG_PING;
ipcmMessagePING::ipcmMessagePING()
{
Init(IPCM_TARGET, &MSG_TYPE, 1);
}
//
// CNAME message
//
// +-----------------------+
// | BYTE - IPCM_MSG_CNAME |
// +-----------------------+
// | clientName |
// +-----------------------+
// | null |
// +-----------------------+
//
const char ipcmMessageCNAME::MSG_TYPE = (char) IPCM_MSG_CNAME;
ipcmMessageCNAME::ipcmMessageCNAME(const char *cName)
{
int cLen = strlen(cName);
int dataLen = 1 + // msg_type
cLen + // cName
1; // null
Init(IPCM_TARGET, NULL, dataLen);
SetData(0, &MSG_TYPE, 1);
SetData(1, cName, cLen + 1);
}
const char *
ipcmMessageCNAME::ClientName() const
{
// make sure data is null terminated
const char *data = Data();
if (data[DataLen() - 1] != '\0')
return NULL;
return Data() + 1;
}
//
// CENUM message
//
// +-----------------------+
// | BYTE - IPCM_MSG_CENUM |
// +-----------------------+
//
const char ipcmMessageCENUM::MSG_TYPE = (char) IPCM_MSG_CENUM;
ipcmMessageCENUM::ipcmMessageCENUM()
{
Init(IPCM_TARGET, &MSG_TYPE, 1);
}
//
// CLIST message
//
// +-----------------------+
// | BYTE - IPCM_MSG_CLIST |
// +-----------------------+
// | cname[0] |
// +-----------------------+
// | null |
// +-----------------------+
// . .
// . .
// +-----------------------+
// | cname[num - 1] |
// +-----------------------+
// | null |
// +-----------------------+
//
const char ipcmMessageCLIST::MSG_TYPE = (char) IPCM_MSG_CLIST;
ipcmMessageCLIST::ipcmMessageCLIST(const char *cNames[], PRUint32 num)
{
PRUint32 i, dataLen = 1;
for (i = 0; i < num; ++i) {
dataLen += strlen(cNames[i]);
dataLen ++;
}
Init(IPCM_TARGET, NULL, dataLen);
PRUint32 offset = 1;
for (i = 0; i < num; ++i) {
PRUint32 len = strlen(cNames[i]);
SetData(offset, cNames[i], len + 1);
offset += len + 1;
}
}
const char *
ipcmMessageCLIST::NextClientName(const char *cName) const
{
if (!cName)
return Data() + 1;
cName += strlen(cName) + 1;
if (cName == MsgBuf() + MsgLen())
cName = NULL;
return cName;
}
//
// FWD message
//
// +----------------------+
// | BYTE - IPCM_MSG_FWD |
// +----------------------+
// | dest_client |
// +----------------------+
// | null |
// +----------------------+
// | dest_msg |
// +----------------------+
//
const char ipcmMessageFWD::MSG_TYPE = (char) IPCM_MSG_FWD;
ipcmMessageFWD::ipcmMessageFWD(const char *dClient, const ipcMessage *dMsg)
{
int cLen = strlen(dClient);
int dataLen = 1 + // msg_type
cLen + // dest_client
1 + // null
dMsg->MsgLen(); // dest_msg
Init(IPCM_TARGET, NULL, dataLen);
SetData(0, &MSG_TYPE, 1);
SetData(1, dClient, cLen + 1);
SetData(1 + cLen + 1, dMsg->MsgBuf(), dMsg->MsgLen());
}
const char *
ipcmMessageFWD::DestClient() const
{
return Data() + 1;
}
PRStatus
ipcmMessageFWD::DestMessage(ipcMessage *msg) const
{
const char *ptr = DestClient();
// XXX use a custom loop here to avoid walking off the end of the buffer
PRUint32 cLen = strlen(ptr);
PRUint32 dLen = MsgLen() - 1 - cLen - 1;
PRUint32 bytesRead;
PRBool complete;
ptr += (cLen + 1);
if (msg->ReadFrom(ptr, dLen, &bytesRead, &complete) != PR_SUCCESS || !complete)
return PR_FAILURE;
return PR_SUCCESS;
}

174
modules/ipc/common/ipcm.h Normal file
Просмотреть файл

@ -0,0 +1,174 @@
/* ***** 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"
//
// IPCM (IPC Manager) protocol support
//
extern const nsID IPCM_TARGET;
enum {
IPCM_MSG_PING,
IPCM_MSG_CNAME,
IPCM_MSG_CENUM,
IPCM_MSG_CLIST,
IPCM_MSG_FWD,
IPCM_MSG_UNKNOWN // unknown message type
};
//
// returns IPCM message type.
//
int IPCM_GetMsgType(const ipcMessage *msg);
//
// 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 ipcmMessageCNAME("foo");
//
// given an arbitrary ipcMessage, it can be parsed using logic similar
// to the following:
//
// ipcMessage *msg = ...
// if (strcmp(msg->Topic(), "ipcm") == 0) {
// if (IPCM_GetMsgType(msg) == IPCM_MSG_CNAME) {
// ipcmMessageCNAME *cnameMsg = (ipcmMessageCNAME *) msg;
// printf("client name: %s\n", cnameMsg->ClientName());
// }
// }
//
// in other words, these classes are very very lightweight.
//
//
// IPCM_MSG_PING
//
// this message may be sent from either the client or the daemon.
//
class ipcmMessagePING : public ipcMessage
{
public:
static const char MSG_TYPE;
ipcmMessagePING();
};
//
// IPCM_MSG_CNAME
//
// this message is sent from a client to specify its name.
//
class ipcmMessageCNAME : public ipcMessage
{
public:
static const char MSG_TYPE;
ipcmMessageCNAME(const char *cName);
//
// extracts the "client name"
//
const char *ClientName() const;
};
//
// IPCM_MSG_CENUM
//
// this message is sent from a client to request a CLIST response.
//
class ipcmMessageCENUM : public ipcMessage
{
public:
static const char MSG_TYPE;
ipcmMessageCENUM();
};
//
// IPCM_MSG_CLIST
//
// this message is sent from the daemon in response to a CENUM request. the
// message contains the list of clients by name.
//
class ipcmMessageCLIST : public ipcMessage
{
public:
static const char MSG_TYPE;
ipcmMessageCLIST(const char *clientNames[], PRUint32 numClients);
//
// extracts the next client name from the message. if null is passed in, then
// the first client name in the list is returned. null is returned if there
// aren't anymore client names. (the returned client name acts as an iterator.)
//
const char *NextClientName(const char *clientName = NULL) const;
};
//
// IPCM_MSG_FWD
//
// this message is only sent from the client to the daemon. the daemon
// will forward the contained message to the specified client.
//
class ipcmMessageFWD : public ipcMessage
{
public:
static const char MSG_TYPE;
ipcmMessageFWD(const char *destClient, const ipcMessage *destMsg);
//
// extracts the "destination client name"
//
const char *DestClient() const;
//
// extracts (a copy of) the "destination message"
//
PRStatus DestMessage(ipcMessage *destMsg) const;
};
#endif // !ipcm_h__

Просмотреть файл

@ -0,0 +1,87 @@
# ***** 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 \
$(NULL)
PROGRAM = mozipcd$(BIN_SUFFIX)
EXPORTS = \
ipcModule.h \
ipcd.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
DEFINES += -DIPC_DAEMON
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
#
# need to install mozipcd.lib, which contains the symbols exported by the
# daemon that modules will need to import.
#
libs:: $(PROGRAM)
$(INSTALL) mozipcd.lib $(DIST)/lib
endif

Просмотреть файл

@ -0,0 +1,191 @@
/* ***** 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 <stdio.h>
#include "ipcClient.h"
#include "ipcMessage.h"
#include "ipcd.h"
#include "prio.h"
#include "plstr.h"
int ipcClient::gLastID = 0;
//
// called to initialize this client context
//
// return:
// 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::Init()
{
mID = ++gLastID;
mName = NULL;
mInMsg = new ipcMessage();
mSendOffset = 0;
// wait for the client to send us a command
return PR_POLL_READ;
}
//
// called when this client context is going away
//
int
ipcClient::Finalize()
{
if (mName)
PL_strfree(mName);
if (mInMsg)
delete mInMsg;
mOutMsgQ.DeleteAll();
return 0;
}
//
// 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 poll_flags)
{
if ((poll_flags & PR_POLL_ERR) ||
(poll_flags & PR_POLL_HUP) ||
(poll_flags & PR_POLL_EXCEPT) ||
(poll_flags & PR_POLL_NVAL)) {
//
// expect Finalize method to be called next.
//
printf("### client socket appears to have closed\n");
return 0;
}
// always wait for more data
int ret_flags = PR_POLL_READ;
if (poll_flags & PR_POLL_READ) {
printf("### client socket is now readable\n");
char buf[1024];
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
char *ptr = buf;
while (n) {
PRUint32 nread;
PRBool complete;
mInMsg->ReadFrom(ptr, PRUint32(n), &nread, &complete);
if (complete) {
IPC_DispatchMsg(this, mInMsg);
mInMsg->Reset();
}
n -= nread;
ptr += nread;
}
}
if (poll_flags & PR_POLL_WRITE) {
printf("### client socket is now writable\n");
if (mOutMsgQ.First())
WriteMsgs(fd);
}
if (mOutMsgQ.First())
ret_flags |= PR_POLL_WRITE;
return ret_flags;
}
void
ipcClient::SetName(const char *name)
{
printf("### setting client name to \"%s\"\n", name);
if (mName)
PL_strfree(mName);
mName = PL_strdup(name);
}
//
// 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;
printf("### wrote %d bytes\n", nw);
if (nw == bufLen)
mOutMsgQ.DeleteFirst();
else
mSendOffset += nw;
}
return 0;
}

Просмотреть файл

@ -0,0 +1,81 @@
/* ***** 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 ipcClient_h__
#define ipcClient_h__
#include "ipcMessageQ.h"
#include "prio.h"
class ipcMessage;
//-----------------------------------------------------------------------------
// 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:
int Init();
int Finalize();
int Process(PRFileDesc *fd, int poll_flags);
int ID() const { return mID; }
const char *Name() const { return mName; }
void SetName(const char *name);
void EnqueueOutboundMsg(ipcMessage *msg) { mOutMsgQ.Append(msg); }
private:
int WriteMsgs(PRFileDesc *fd);
static int gLastID;
int mID;
char *mName;
ipcMessage *mInMsg; // buffer for incoming message
ipcMessageQ mOutMsgQ; // outgoing message queue
// keep track of the amount of the first message sent
PRUint32 mSendOffset;
};
#endif // !ipcClient_h__

Просмотреть файл

@ -0,0 +1,117 @@
/* ***** 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 <stdio.h>
#include <string.h>
#include "ipcCommandModule.h"
#include "ipcModule.h"
#include "ipcClient.h"
#include "ipcMessage.h"
#include "ipcd.h"
#include "ipcm.h"
typedef const char * constCharPtr;
class ipcCommandModule : public ipcModule
{
public:
void Shutdown()
{
}
const nsID &ID()
{
return IPCM_TARGET;
}
void HandleMsg(ipcClient *client, const ipcMessage *msg)
{
// XXX replace w/ function table
switch (IPCM_GetMsgType(msg)) {
case IPCM_MSG_PING:
printf("### got ping\n");
{
IPC_SendMsg(client, new ipcmMessagePING());
}
break;
case IPCM_MSG_CNAME:
printf("### got cname\n");
{
const char *name = ((const ipcmMessageCNAME *) msg)->ClientName();
if (name)
client->SetName(name);
}
break;
case IPCM_MSG_CENUM:
printf("### got cenum\n");
{
int len;
ipcClient *clients = IPC_GetClients(&len);
if (clients) {
constCharPtr *clist = new constCharPtr[len-1];
if (clist) {
for (int i = 0; i < len; ++i) {
if (clients + i != client)
clist[i] = clients[i].Name();
}
IPC_SendMsg(client, new ipcmMessageCLIST(clist, len-1));
delete[] clist;
}
}
}
break;
case IPCM_MSG_FWD:
printf("### got fwd\n");
{
const ipcmMessageFWD *fMsg = (const ipcmMessageFWD *) msg;
ipcClient *client = IPC_GetClientByName(fMsg->DestClient());
ipcMessage *newMsg = new ipcMessage();
if (fMsg->DestMessage(newMsg) == PR_SUCCESS)
IPC_SendMsg(client, newMsg);
}
break;
default:
printf("### got unknown message\n");
}
}
};
ipcModule *IPC_GetCommandModule()
{
static ipcCommandModule module;
return &module;
}

Просмотреть файл

@ -0,0 +1,45 @@
/* ***** 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"
class ipcModule *IPC_GetCommandModule();
#endif // !ipcCommandModule_h__

Просмотреть файл

@ -0,0 +1,95 @@
/* ***** 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;
class ipcClient;
//-----------------------------------------------------------------------------
// abstract module class
//-----------------------------------------------------------------------------
class ipcModule
{
public:
//
// called when this module will no longer be accessed. if this module was
// allocated on the heap, then it can be free'd.
//
virtual void Shutdown() = 0;
//
// called to determine the ID of this module. the ID of a module
// indicates the "message target" for which it will be registered
// as a handler.
//
virtual const nsID &ID() = 0;
//
// 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).
//
// msg - the message sent from the client. the target of this message
// matches the ID of this module.
//
virtual void HandleMsg(ipcClient *client, const ipcMessage *msg) = 0;
};
//
// factory method signature for DLLs, which may define more than one ipcModule
// implementation. the DLL must export the following symbol:
//
// extern "C" ipcModule **IPC_GetModuleList();
//
// return:
// null terminated array of modules.
//
typedef ipcModule ** (*ipcGetModuleListFunc)(void);
#endif // !ipcModule_h__

Просмотреть файл

@ -0,0 +1,173 @@
/* ***** 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 <stdio.h>
#include <stdlib.h>
#include "prlink.h"
#include "prio.h"
#include "plstr.h"
#include "ipcConfig.h"
#include "ipcModuleReg.h"
#include "ipcModule.h"
#include "ipcCommandModule.h"
#include "ipcd.h"
struct ipcModuleRegEntry
{
nsID id;
ipcModule *module;
PRLibrary *lib;
};
#define IPC_MAX_MODULE_COUNT 64
static ipcModuleRegEntry ipcModules[IPC_MAX_MODULE_COUNT];
static int ipcModuleCount;
static PRStatus
AddModule(const nsID &id, ipcModule *module, PRLibrary *lib)
{
if (ipcModuleCount == IPC_MAX_MODULE_COUNT) {
printf("### too many modules!\n");
return PR_FAILURE;
}
ipcModules[ipcModuleCount].id = id;
ipcModules[ipcModuleCount].module = module;
ipcModules[ipcModuleCount].lib = lib;
++ipcModuleCount;
return PR_SUCCESS;
}
static void
InitModuleFromLib(const char *modulesDir, const char *fileName)
{
printf("### InitModuleFromLib [%s]\n", fileName);
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) {
ipcGetModuleListFunc func =
(ipcGetModuleListFunc) PR_FindFunctionSymbol(lib, "IPC_GetModuleList");
if (func) {
ipcModule **modules = func();
if (modules) {
while (*modules) {
AddModule((*modules)->ID(), *modules, PR_LoadLibrary(buf));
++modules;
}
}
}
PR_UnloadLibrary(lib);
}
free(buf);
}
//-----------------------------------------------------------------------------
// ipcModuleReg API
//-----------------------------------------------------------------------------
//
// search for a module registered under the specified id
//
ipcModule *
IPC_GetModuleByID(const nsID &id)
{
for (int i=0; i<ipcModuleCount; ++i) {
ipcModuleRegEntry &entry = ipcModules[i];
if (entry.id.Equals(id))
return entry.module;
}
return NULL;
}
void
IPC_InitModuleReg(const char *modulesDir)
{
ipcModule *module = IPC_GetCommandModule();
AddModule(module->ID(), module, NULL);
if (modulesDir) {
printf("### 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);
}
}
}
void
IPC_ShutdownModuleReg()
{
//
// shutdown modules in reverse order
//
for (int i = ipcModuleCount - 1; i >= 0; --i) {
ipcModuleRegEntry &entry = ipcModules[i];
if (entry.module)
entry.module->Shutdown();
if (entry.lib)
PR_UnloadLibrary(entry.lib);
}
// memset(ipcModules, 0, sizeof(ipcModules));
ipcModuleCount = 0;
}

Просмотреть файл

@ -0,0 +1,49 @@
/* ***** 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/shutdown module registry.
//
void IPC_InitModuleReg(const char *moduleDir);
void IPC_ShutdownModuleReg();
#endif // !ipcModuleReg_h__

415
modules/ipc/daemon/ipcd.cpp Normal file
Просмотреть файл

@ -0,0 +1,415 @@
/* ***** 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef XP_UNIX
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "prio.h"
#include "prerror.h"
#include "prthread.h"
#include "prinrval.h"
#include "plstr.h"
#include "ipcConfig.h"
#include "ipcMessage.h"
#include "ipcClient.h"
#include "ipcModuleReg.h"
#include "ipcModule.h"
#include "ipcd.h"
#ifdef IPC_USE_INET
#include "prnetdb.h"
#endif
//-----------------------------------------------------------------------------
// upper limit on the number of active connections
// XXX may want to make this more dynamic
#define MAX_CLIENTS 100
//
// the first element of this array is always zero; this is done so that the
// n'th element of |clients| corresponds to the n'th element of |poll_fds|.
//
static ipcClient clients[MAX_CLIENTS + 1];
static PRPollDesc poll_fds[MAX_CLIENTS + 1];
static int poll_fd_count;
//-----------------------------------------------------------------------------
static int AddClient(PRFileDesc *fd)
{
if (poll_fd_count == MAX_CLIENTS + 1) {
printf("### reached maximum client limit\n");
return -1;
}
poll_fds[poll_fd_count].fd = fd;
poll_fds[poll_fd_count].in_flags = clients[poll_fd_count].Init();
poll_fds[poll_fd_count].out_flags = 0;
++poll_fd_count;
return 0;
}
static int RemoveClient(int client_index)
{
PRPollDesc *pd = &poll_fds[client_index];
PR_Close(pd->fd);
clients[client_index].Finalize();
//
// keep the clients and poll_fds contiguous; move the last one into
// the spot held by the one that is going away.
//
int to_idx = client_index;
int from_idx = poll_fd_count - 1;
if (from_idx != to_idx) {
memcpy(&clients[to_idx], &clients[from_idx], sizeof(ipcClient));
memcpy(&poll_fds[to_idx], &poll_fds[from_idx], sizeof(PRPollDesc));
}
//
// zero out the old entries.
//
memset(&clients[from_idx], 0, sizeof(ipcClient));
memset(&poll_fds[from_idx], 0, sizeof(PRPollDesc));
--poll_fd_count;
return 0;
}
//-----------------------------------------------------------------------------
static void Process(PRFileDesc *listen_fd)
{
poll_fd_count = 1;
poll_fds[0].fd = listen_fd;
poll_fds[0].in_flags = PR_POLL_EXCEPT | PR_POLL_READ;
while (1) {
PRInt32 rv;
PRIntn i;
poll_fds[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.
//
rv = PR_Poll(poll_fds, poll_fd_count, PR_SecondsToInterval(60 * 5));
if (rv == -1) {
printf("### PR_Poll failed [%d]\n", PR_GetError());
return;
}
if (rv > 0) {
//
// process clients that are ready
//
for (i = 1; i < poll_fd_count; ++i) {
if (poll_fds[i].out_flags != 0) {
poll_fds[i].in_flags = clients[i].Process(poll_fds[i].fd, poll_fds[i].out_flags);
poll_fds[i].out_flags = 0;
}
}
//
// cleanup any dead clients (indicated by a zero in_flags)
//
for (i = poll_fd_count - 1; i >= 1; --i) {
if (poll_fds[i].in_flags == 0)
RemoveClient(i);
}
//
// check for new connection
//
if (poll_fds[0].out_flags & PR_POLL_READ) {
printf("### got new connection\n");
PRNetAddr client_addr;
memset(&client_addr, 0, sizeof(client_addr));
PRFileDesc *client_fd;
client_fd = PR_Accept(listen_fd, &client_addr, PR_INTERVAL_NO_WAIT);
if (client_fd == NULL) {
printf("### PR_Accept failed [%d]\n", PR_GetError());
return;
}
// make socket non-blocking
PRSocketOptionData opt;
opt.option = PR_SockOpt_Nonblocking;
opt.value.non_blocking = PR_TRUE;
PR_SetSocketOption(client_fd, &opt);
if (AddClient(client_fd) != 0)
PR_Close(client_fd);
}
}
//
// shutdown if no clients
//
if (poll_fd_count == 1) {
printf("### shutting down\n");
break;
}
}
}
//-----------------------------------------------------------------------------
static void InitModuleReg(const char *exePath)
{
static const char modDir[] = "ipc/modules";
char *p = PL_strrchr(exePath, IPC_PATH_SEP_CHAR);
if (p == NULL) {
printf("### unexpected exe path\n");
return;
}
int baseLen = p - exePath;
int finalLen = baseLen + 1 + sizeof(modDir);
// build full path to ipc modules
char *buf = (char*) malloc(finalLen);
memcpy(buf, exePath, baseLen);
buf[baseLen] = IPC_PATH_SEP_CHAR;
memcpy(buf + baseLen + 1, modDir, sizeof(modDir));
IPC_InitModuleReg(buf);
free(buf);
}
#ifdef XP_UNIX
#include <signal.h>
#endif
int main(int argc, char **argv)
{
PRFileDesc *listen_fd;
PRNetAddr addr;
#ifdef XP_UNIX
signal(SIGINT, SIG_IGN);
umask(0077); // ensure strict file permissions
#endif
start:
#ifdef IPC_USE_INET
listen_fd = PR_OpenTCPSocket(PR_AF_INET);
if (!listen_fd) {
printf("### PR_OpenUDPSocket failed [%d]\n", PR_GetError());
return -1;
}
PR_InitializeNetAddr(PR_IpAddrLoopback, IPC_PORT, &addr);
#else
const char *socket_path;
if (argc < 2)
socket_path = IPC_DEFAULT_SOCKET_PATH;
else
socket_path = argv[1];
listen_fd = PR_OpenTCPSocket(PR_AF_LOCAL);
if (!listen_fd) {
printf("### PR_OpenUDPSocket failed [%d]\n", PR_GetError());
return -1;
}
addr.local.family = PR_AF_LOCAL;
PL_strncpyz(addr.local.path, socket_path, sizeof(addr.local.path));
#endif
if (PR_Bind(listen_fd, &addr) != PR_SUCCESS) {
printf("### PR_Bind failed [%d]\n", PR_GetError());
//
// failure here indicates that another process may be bound
// to the socket already. let's try connecting to that socket.
// if connect fails, then the socket is probably stale.
//
if (PR_Connect(listen_fd, &addr, PR_SecondsToInterval(2)) == PR_SUCCESS) {
//
// looks like another process is active. silently exit.
//
printf("### looks like another instance of the daemon is active; sleeping...\n");
//
// sleep here to avoid triggering the shutdown procedure in the
// other daemon. 10 seconds should be long enough for the client
// to have established a connection.
//
PR_Sleep(PR_SecondsToInterval(10));
printf("### exiting\n");
PR_Close(listen_fd);
return 0;
}
//
// OK, the socket is probably stale.
//
printf("### socket appears to be stale\n");
#ifdef IPC_USE_INET
printf("### waiting for TIMEWAIT period to expire...\n");
PR_Sleep(PR_SecondsToInterval(60));
#else
printf("### deleting socket at %s\n", socket_path);
PR_Delete(socket_path);
#endif
PR_Close(listen_fd);
goto start;
}
InitModuleReg(argv[0]);
if (PR_Listen(listen_fd, 5) != PR_SUCCESS) {
printf("### PR_Listen failed [%d]\n", PR_GetError());
return -1;
}
Process(listen_fd);
IPC_ShutdownModuleReg();
//
// XXX enable this delay for startup testing
//
//printf("### sleeping for 5 seconds...\n");
//PR_Sleep(PR_SecondsToInterval(5));
#ifndef IPC_USE_INET
printf("### deleting socket at %s\n", socket_path);
//
// we delete the file itself first to avoid a race between shutting
// ourselves down and another instance of the daemon starting up.
//
if (PR_Delete(socket_path) != PR_SUCCESS) {
printf("### PR_Delete failed [%d]\n", PR_GetError());
return -1;
}
#endif
printf("### closing socket\n");
if (PR_Close(listen_fd) != PR_SUCCESS) {
printf("### PR_Close failed [%d]\n", PR_GetError());
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// IPC API
//-----------------------------------------------------------------------------
int IPC_DispatchMsg(ipcClient *client, const ipcMessage *msg)
{
// lookup handler for this message's topic and forward message to it.
ipcModule *module = IPC_GetModuleByID(msg->Target());
if (module)
module->HandleMsg(client, msg);
else
printf("### no registered module; ignoring message\n");
return 0;
}
int IPC_SendMsg(ipcClient *client, ipcMessage *msg)
{
if (client == NULL) {
int i;
//
// walk clients array
//
for (i = 1; i < poll_fd_count - 1; ++i)
IPC_SendMsg(&clients[i], msg->Clone());
// send to last client w/o cloning to avoid extra malloc
IPC_SendMsg(&clients[i], msg);
}
else {
client->EnqueueOutboundMsg(msg);
//
// since this client's Process method may have already been
// called, we need to explicitly set the PR_POLL_WRITE flag.
//
int client_index = client - clients;
poll_fds[client_index].in_flags |= PR_POLL_WRITE;
}
return 0;
}
ipcClient *IPC_GetClientByID(int clientID)
{
// linear search OK since number of clients should be small
for (int i = 1; i < poll_fd_count; ++i) {
if (clients[i].ID() == clientID)
return &clients[i];
}
return NULL;
}
ipcClient *IPC_GetClientByName(const char *name)
{
// linear search OK since number of clients should be small
for (int i = 1; i < poll_fd_count; ++i) {
if (strcmp(clients[i].Name(), name) == 0)
return &clients[i];
}
return NULL;
}
ipcClient *IPC_GetClients(int *count)
{
*count = poll_fd_count - 1;
return &clients[1];
}

110
modules/ipc/daemon/ipcd.h Normal file
Просмотреть файл

@ -0,0 +1,110 @@
/* ***** 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"
#ifdef IPC_DAEMON
#define IPC_METHOD _declspec(dllexport)
#else
#define IPC_METHOD _declspec(dllimport)
#endif
class ipcClient;
class ipcMessage;
//-----------------------------------------------------------------------------
// IPC daemon API
//-----------------------------------------------------------------------------
extern "C" {
//
// IPC_DispatchMsg
//
// params:
// client - identifies the client from which this message originated.
// msg - the message received. this function does not modify |msg|,
// and ownership stays with the caller.
//
int IPC_DispatchMsg(ipcClient *client, const ipcMessage *msg);
//
// IPC_SendMsg
//
// params:
// client - identifies the client that should receive the message.
// if null, then the message is broadcast to all clients.
// msg - the message to be sent. this function subsumes
// ownership of the message. the caller must not attempt
// to access |msg| after this function returns.
// return:
// 0 - on success
//
IPC_METHOD int IPC_SendMsg(ipcClient *client, ipcMessage *msg);
//
// returns the client ID dynamically generated for the given client.
//
int IPC_GetClientID(ipcClient *client);
//
// returns the client name (NULL if the client did not specify a name).
//
const char *IPC_GetClientName(ipcClient *client);
//
// client lookup functions
//
ipcClient *IPC_GetClientByID(int clientID);
ipcClient *IPC_GetClientByName(const char *clientName);
//
// return array of all clients, length equal to |count|.
//
ipcClient *IPC_GetClients(int *count);
//
// returns the ipcModule object registered under the given module ID.
//
ipcModule *IPC_GetModuleByID(const nsID &moduleID);
} // extern "C"
#endif // !IPCD_H__

Просмотреть файл

@ -0,0 +1,52 @@
# ***** 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

Просмотреть файл

@ -0,0 +1,209 @@
/* ***** 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 nsISimpleEnumerator;
interface ipcIMessageObserver;
interface ipcIClientObserver;
/**
* the IPC service provides the means to communicate with an external IPC
* daemon and/or other mozilla-based applications sharing the same user
* profile. 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 for the current profile. (there is one IPC
* daemon per profile.) the IPC daemon will be automatically started if
* necessary. when a connection has been established, the IPC service will
* broadcast an "ipc-startup" notification using the observer service.
*
* when the connection to the IPC daemon is closed (due to error, profile
* change, or normal shutdown), 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. this 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
{
/**
* returns the "client ID" assigned to this application by the IPC daemon.
* this number is the name given to our application for the current
* session. after a profile change, our client ID will change.
*
* @throws NS_ERROR_NOT_AVAILABLE if no connection to the IPC daemon.
*/
readonly attribute unsigned long clientID;
/**
* client aliases give the client a way to register itself under multiple
* names. for example, the mozilla browser might register itself under
* the name "mozilla", but it could also register itself under the aliases
* "browser", "mail", "news", "addrbook", and so on. aliases provide a
* simple mechanism for clients to discover other clients.
*/
void addClientAlias(in ACString aAlias);
void removeClientAlias(in ACString aAlias);
/**
* query info about a particular client given its client name.
*
* @param aNameOrAlias name or alias of the client being queried.
* @param aObserver client observer to be notified.
*
* @return integer token identifying this request.
*/
unsigned long queryClientByName(in ACString aNameOrAlias,
in ipcIClientObserver aObserver);
/**
* query info about a particular client given its client ID.
*
* @return integer token identifying this request.
*/
unsigned long queryClientByID(in unsigned long aClientID,
in ipcIClientObserver aObserver);
/**
* set client observer. observer is notified whenever the status of
* a client changes.
*
* @param aClientID the ID of the client to observe.
* @param aObserver the client observer.
*/
void setClientObserver(in unsigned long aClientID,
in ipcIClientObserver aObserver);
/**
* 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 the IPC daemon. there is no guarantee
* that the message will be delivered.
*
* @param aTarget the target of the message. this is the ID of the
* daemon module that should receive this message.
* @param aData the data of the message.
* @param aDataLen the data length of the message.
*/
[noscript] void sendMessage(in nsIDRef aTarget,
in string aData,
in unsigned long aDataLen);
/**
* forward message asynchronously via the IPC daemon to another application
* process. there is no guarantee that the message will be delivered.
*
* @param aClientID the client ID of the foreign application that should
* receive this message.
*
* other parameters are identical to those for sendMessage.
*/
[noscript] void forwardMessage(in unsigned long aClientID,
in nsIDRef aTarget,
in string aData,
in unsigned long aDataLen);
};
[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.
*/
[noscript] void onMessageAvailable(in nsIDRef aTarget,
in string aData,
in unsigned long aDataLen);
};
[scriptable, uuid(e858d450-62b2-482d-99bb-3b5425aa28cc)]
interface ipcIClientInfo : nsISupports
{
readonly attribute unsigned long ID;
readonly attribute ACString name;
readonly attribute nsISimpleEnumerator aliases;
readonly attribute nsISimpleEnumerator targets;
};
[scriptable, uuid(42283079-030c-4b13-b069-a08b7ad5eab2)]
interface ipcIClientObserver : nsISupports
{
/**
* client status values
*/
const unsigned long CLIENT_UP = 1;
const unsigned long CLIENT_DOWN = 2;
/**
* @param aRequestToken the request token returned from the call that
* initiated this observation. 0 if initiated
* from a setClientObserver call.
* @param aClientInfo client info.
* @param aStatus client status (e.g. CLIENT_UP).
*/
void onClientStatus(in unsigned long aRequestToken,
in ipcIClientInfo aClientInfo,
in unsigned long aStatus);
// XXX do we care about changes to the aliases and targets supported
// by a client? if so, how should we pass this information up?
};

Просмотреть файл

@ -0,0 +1,65 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla IPC.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2002
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Darin Fisher <darin@netscape.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
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 \
ipcSocketProvider.cpp
LOCAL_INCLUDES = \
-I$(srcdir)/../common \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,193 @@
/* ***** 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 "ipcConfig.h"
#include "ipcService.h"
#include "plstr.h"
static PRBool PR_CALLBACK
ipcReleaseMessageObserver(nsHashKey *aKey, void *aData, void* aClosure)
{
ipcIMessageObserver *obs = (ipcIMessageObserver *) aData;
NS_RELEASE(obs);
return PR_TRUE;
}
//-----------------------------------------------------------------------------
// ipcService
//-----------------------------------------------------------------------------
ipcService::ipcService()
{
NS_INIT_ISUPPORTS();
}
ipcService::~ipcService()
{
if (mTransport) {
mTransport->Shutdown();
NS_RELEASE(mTransport);
}
mObserverDB.Reset(ipcReleaseMessageObserver, nsnull);
}
nsresult
ipcService::Init()
{
nsresult rv;
mTransport = new ipcTransport();
if (!mTransport)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTransport);
// XXX use directory service to locate socket
rv = mTransport->Init(NS_LITERAL_CSTRING(IPC_DEFAULT_SOCKET_PATH), this);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
//-----------------------------------------------------------------------------
// interface impl
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(ipcService, ipcIService)
NS_IMETHODIMP
ipcService::GetClientID(PRUint32 *clientID)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ipcService::AddClientAlias(const nsACString &alias)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ipcService::RemoveClientAlias(const nsACString &alias)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ipcService::QueryClientByName(const nsACString &name,
ipcIClientObserver *observer,
PRUint32 *token)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ipcService::QueryClientByID(PRUint32 clientID,
ipcIClientObserver *observer,
PRUint32 *token)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ipcService::SetClientObserver(PRUint32 clientID,
ipcIClientObserver *observer)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ipcService::SetMessageObserver(const nsID &target, ipcIMessageObserver *observer)
{
nsIDKey key(target);
ipcIMessageObserver *cobs = (ipcIMessageObserver *) mObserverDB.Get(&key);
if (cobs) {
NS_RELEASE(cobs);
if (!observer) {
mObserverDB.Remove(&key);
return NS_OK;
}
}
if (observer) {
NS_ADDREF(observer);
mObserverDB.Put(&key, observer);
}
return NS_OK;
}
NS_IMETHODIMP
ipcService::SendMessage(const nsID &target,
const char *data,
PRUint32 dataLen)
{
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
ipcMessage *msg = new ipcMessage();
if (!msg)
return NS_ERROR_OUT_OF_MEMORY;
msg->Init(target, data, dataLen);
mTransport->SendMsg(msg);
return NS_OK;
}
NS_IMETHODIMP
ipcService::ForwardMessage(PRUint32 clientID,
const nsID &target,
const char *data,
PRUint32 dataLen)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//-----------------------------------------------------------------------------
// ipcTransportObserver impl
//-----------------------------------------------------------------------------
void
ipcService::OnMsgAvailable(const ipcMessage *msg)
{
nsIDKey key(msg->Target());
ipcIMessageObserver *observer = (ipcIMessageObserver *) mObserverDB.Get(&key);
if (observer)
observer->OnMessageAvailable(msg->Target(),
msg->Data(),
msg->DataLen());
}

Просмотреть файл

@ -0,0 +1,75 @@
/* ***** 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 "ipcIService.h"
#include "ipcTransport.h"
#include "ipcMessage.h"
#include "ipcMessageQ.h"
#include "nsIRequest.h"
#include "nsIStreamListener.h"
#include "nsIStreamProvider.h"
#include "nsCOMPtr.h"
#include "nsHashtable.h"
//----------------------------------------------------------------------------
// ipcService
//----------------------------------------------------------------------------
class ipcService : public ipcIService
, public ipcTransportObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IPCISERVICE
ipcService();
virtual ~ipcService();
nsresult Init();
private:
// ipcTransportObserver:
void OnMsgAvailable(const ipcMessage *);
nsHashtable mObserverDB;
ipcTransport *mTransport;
};
#endif // !ipcService_h__

Просмотреть файл

@ -0,0 +1,64 @@
/* ***** 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 "ipcSocketProvider.h"
NS_IMETHODIMP
ipcSocketProvider::NewSocket(const char *host,
PRInt32 port,
const char *proxyHost,
PRInt32 proxyPort,
PRFileDesc **fd,
nsISupports **securityInfo)
{
*fd = PR_OpenTCPSocket(PR_AF_LOCAL);
return NS_OK;
}
NS_IMETHODIMP
ipcSocketProvider::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(ipcSocketProvider, nsISocketProvider)

Просмотреть файл

@ -0,0 +1,53 @@
/* ***** 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 ipcSocketProvider_h__
#define ipcSocketProvider_h__
#include "nsISocketProvider.h"
class ipcSocketProvider : public nsISocketProvider
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISOCKETPROVIDER
ipcSocketProvider() { NS_INIT_ISUPPORTS(); }
virtual ~ipcSocketProvider() { }
};
#endif // !ipcSocketProvider_h__

Просмотреть файл

@ -0,0 +1,537 @@
/* ***** 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 "nsISocketTransportService.h"
#include "nsISocketTransport.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIFile.h"
#include "nsIProcess.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsNetCID.h"
#include "netCore.h"
#include "prerror.h"
#include "plstr.h"
#include "ipcConfig.h"
#include "ipcTransport.h"
#include "ipcm.h"
#define LOG(args) printf args
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
//-----------------------------------------------------------------------------
// ipcTransport
//-----------------------------------------------------------------------------
ipcTransport::~ipcTransport()
{
if (mFD)
PR_Close(mFD);
}
nsresult
ipcTransport::Init(const nsACString &socketPath, ipcTransportObserver *obs)
{
LOG((">>> ipcTransport::Init\n"));
mSocketPath = socketPath;
mObserver = obs;
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);
}
return Connect();
}
nsresult
ipcTransport::Shutdown()
{
LOG((">>> ipcTransport::Shutdown\n"));
mHaveConnection = PR_FALSE;
if (mReadRequest) {
mReadRequest->Cancel(NS_BINDING_ABORTED);
mReadRequest = nsnull;
}
if (mWriteRequest) {
mWriteRequest->Cancel(NS_BINDING_ABORTED);
mWriteRequest = nsnull;
mWriteSuspended = PR_FALSE;
}
mTransport = nsnull;
return NS_OK;
}
nsresult
ipcTransport::SendMsg(ipcMessage *msg)
{
NS_ENSURE_ARG_POINTER(msg);
LOG((">>> ipcTransport::SendMsg [dataLen=%u]\n", msg->DataLen()));
if (!mHaveConnection) {
LOG((">>> delaying message until connected\n"));
mDelayedQ.Append(msg);
return NS_OK;
}
return SendMsg_Internal(msg);
}
nsresult
ipcTransport::SendMsg_Internal(ipcMessage *msg)
{
LOG((">>> ipcTransport::SendMsg_Internal [dataLen=%u]\n", msg->DataLen()));
mSendQ.EnqueueMsg(msg);
if (!mWriteRequest) {
if (!mTransport)
return NS_ERROR_FAILURE;
nsresult rv = mTransport->AsyncWrite(&mSendQ, nsnull, 0, PRUint32(-1), 0,
getter_AddRefs(mWriteRequest));
if (NS_FAILED(rv)) return rv;
}
if (mWriteSuspended) {
mWriteRequest->Resume();
mWriteSuspended = PR_FALSE;
}
return NS_OK;
}
nsresult
ipcTransport::Connect()
{
nsresult rv;
LOG((">>> ipcTransport::Connect\n"));
if (++mConnectionAttemptCount > 20) {
LOG((">>> giving up after 20 unsuccessful connection attempts\n"));
return NS_ERROR_ABORT;
}
rv = CreateTransport();
if (NS_FAILED(rv)) return rv;
rv = mTransport->AsyncRead(&mReceiver, nsnull, 0, PRUint32(-1), 0,
getter_AddRefs(mReadRequest));
return rv;
}
void
ipcTransport::OnMsgAvailable(const ipcMessage *msg)
{
LOG((">>> ipcTransport::OnMsgAvailable [dataLen=%u]\n", msg->DataLen()));
//
// all IPCM messages stop here.
//
if (msg->Target().Equals(IPCM_TARGET)) {
//
// check for startup PING
//
if (!mHaveConnection) {
if (IPCM_GetMsgType(msg) == IPCM_MSG_PING) {
LOG((">>> connection established!\n"));
mHaveConnection = PR_TRUE;
//
// move messages off the delayed queue
//
while (!mDelayedQ.IsEmpty()) {
ipcMessage *msg = mDelayedQ.First();
mDelayedQ.RemoveFirst();
SendMsg_Internal(msg);
}
}
else
LOG((">>> received bogus response to our ping!\n"));
}
}
else if (mObserver)
mObserver->OnMsgAvailable(msg);
}
void
ipcTransport::OnStartRequest(nsIRequest *req)
{
nsresult status;
req->GetStatus(&status);
if (NS_SUCCEEDED(status) && !mHaveConnection && !mSentInitialMsgs) {
//
// send "startup messages"
//
// PING - expect a PING in response to this message
// CNAME - expect nothing in response to this message
//
SendMsg_Internal(new ipcmMessagePING());
SendMsg_Internal(new ipcmMessageCNAME("test-app")); // XXX need real client name
mSentInitialMsgs = PR_TRUE;
}
}
void
ipcTransport::OnStopRequest(nsIRequest *req, nsresult status)
{
LOG((">>> ipcTransport::OnStopRequest [status=%x]\n", status));
if (status == NS_BINDING_ABORTED)
return;
if (NS_FAILED(status) && !mTimer) {
nsresult rv;
//
// connection failure
//
rv = SpawnDaemon();
if (NS_FAILED(rv)) {
LOG((">>> failed to spawn daemon [rv=%x]\n", rv));
return;
}
//
// re-initialize connection after timeout
//
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
LOG((">>> failed to create timer [rv=%x]\n", rv));
return;
}
// use a simple exponential growth algorithm n*2^(n-1)
PRUint32 ms = 1000 * (1 << (mConnectionAttemptCount - 1));
LOG((">>> waiting %u milliseconds\n", ms));
rv = mTimer->Init(this, ms, nsITimer::TYPE_ONE_SHOT);
if (NS_FAILED(rv)) {
LOG((">>> failed to initialize timer [rv=%x]\n", rv));
return;
}
}
if (req == mReadRequest)
mReadRequest = nsnull;
else if (req == mWriteRequest) {
mWriteRequest = nsnull;
mWriteSuspended = PR_FALSE;
}
}
nsresult
ipcTransport::CreateTransport()
{
nsresult rv;
nsCOMPtr<nsISocketTransportService> sts(
do_GetService(kSocketTransportServiceCID, &rv));
if (NS_FAILED(rv)) return rv;
rv = sts->CreateTransportOfType(IPC_SOCKET_TYPE,
"127.0.0.1",
IPC_PORT,
nsnull,
1024,
1024*16,
getter_AddRefs(mTransport));
if (NS_FAILED(rv)) return rv;
#ifndef IPC_USE_INET
nsCOMPtr<nsISocketTransport> st(do_QueryInterface(mTransport, &rv));
if (NS_FAILED(rv)) return rv;
PRNetAddr addr;
addr.local.family = PR_AF_LOCAL;
PL_strncpyz(addr.local.path, mSocketPath.get(), sizeof(addr.local.path));
rv = st->SetAddress(&addr);
#endif
return rv;
}
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);
}
NS_IMPL_THREADSAFE_ISUPPORTS0(ipcTransport)
NS_IMETHODIMP
ipcTransport::Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
{
LOG((">>> ipcTransport::Observe [topic=%s]\n", topic));
if (strcmp(topic, "timer-callback") == 0) {
//
// try reconnecting to the daemon
//
Shutdown();
Connect();
mTimer = nsnull;
}
else if (strcmp(topic, "xpcom-shutdown") == 0 ||
strcmp(topic, "profile-change-net-teardown") == 0)
Shutdown();
return NS_OK;
}
//-----------------------------------------------------------------------------
// ipcSendQueue
//-----------------------------------------------------------------------------
NS_IMETHODIMP_(nsrefcnt)
ipcSendQueue::AddRef()
{
return mTransport->AddRef();
}
NS_IMETHODIMP_(nsrefcnt)
ipcSendQueue::Release()
{
return mTransport->Release();
}
NS_IMPL_QUERY_INTERFACE2(ipcSendQueue, nsIStreamProvider, nsIRequestObserver)
NS_IMETHODIMP
ipcSendQueue::OnStartRequest(nsIRequest *request,
nsISupports *context)
{
LOG((">>> ipcSendQueue::OnStartRequest\n"));
if (mTransport)
mTransport->OnStartRequest(request);
return NS_OK;
}
NS_IMETHODIMP
ipcSendQueue::OnStopRequest(nsIRequest *request,
nsISupports *context,
nsresult status)
{
LOG((">>> ipcSendQueue::OnStopRequest [status=%x]\n", status));
if (mTransport)
mTransport->OnStopRequest(request, status);
return NS_OK;
}
struct ipcWriteState
{
ipcMessage *msg;
PRBool complete;
};
static NS_METHOD ipcWriteMessage(nsIOutputStream *stream,
void *closure,
char *segment,
PRUint32 offset,
PRUint32 count,
PRUint32 *countWritten)
{
ipcWriteState *state = (ipcWriteState *) closure;
if (state->msg->WriteTo(segment, count,
countWritten, &state->complete) != PR_SUCCESS)
return NS_ERROR_UNEXPECTED;
return NS_OK;
}
NS_IMETHODIMP
ipcSendQueue::OnDataWritable(nsIRequest *request,
nsISupports *context,
nsIOutputStream *stream,
PRUint32 offset,
PRUint32 count)
{
PRUint32 n;
nsresult rv;
ipcWriteState state;
PRBool wroteSomething = PR_FALSE;
LOG((">>> ipcSendQueue::OnDataWritable\n"));
while (!mQueue.IsEmpty()) {
state.msg = mQueue.First();
state.complete = PR_FALSE;
rv = stream->WriteSegments(ipcWriteMessage, &state, count, &n);
if (NS_FAILED(rv))
break;
if (state.complete) {
LOG((">>> wrote message %u bytes\n", mQueue.First()->MsgLen()));
mQueue.DeleteFirst();
}
wroteSomething = PR_TRUE;
}
if (wroteSomething)
return NS_OK;
LOG((">>> suspending write request\n"));
mTransport->SetWriteSuspended(PR_TRUE);
return NS_BASE_STREAM_WOULD_BLOCK;
}
//----------------------------------------------------------------------------
// ipcReceiver
//----------------------------------------------------------------------------
NS_IMETHODIMP_(nsrefcnt)
ipcReceiver::AddRef()
{
return mTransport->AddRef();
}
NS_IMETHODIMP_(nsrefcnt)
ipcReceiver::Release()
{
return mTransport->Release();
}
NS_IMPL_QUERY_INTERFACE2(ipcReceiver, nsIStreamListener, nsIRequestObserver)
NS_IMETHODIMP
ipcReceiver::OnStartRequest(nsIRequest *request,
nsISupports *context)
{
LOG((">>> ipcReceiver::OnStartRequest\n"));
if (mTransport)
mTransport->OnStartRequest(request);
return NS_OK;
}
NS_IMETHODIMP
ipcReceiver::OnStopRequest(nsIRequest *request,
nsISupports *context,
nsresult status)
{
LOG((">>> ipcReceiver::OnStopRequest [status=%x]\n", status));
if (mTransport)
mTransport->OnStopRequest(request, status);
return NS_OK;
}
static NS_METHOD ipcReadMessage(nsIInputStream *stream,
void *closure,
const char *segment,
PRUint32 offset,
PRUint32 count,
PRUint32 *countRead)
{
ipcReceiver *receiver = (ipcReceiver *) closure;
return receiver->ReadSegment(segment, count, countRead);
}
NS_IMETHODIMP
ipcReceiver::OnDataAvailable(nsIRequest *request,
nsISupports *context,
nsIInputStream *stream,
PRUint32 offset,
PRUint32 count)
{
LOG((">>> ipcReceiver::OnDataAvailable [count=%u]\n", count));
PRUint32 countRead;
return stream->ReadSegments(ipcReadMessage, this, count, &countRead);
}
nsresult
ipcReceiver::ReadSegment(const char *ptr, PRUint32 count, PRUint32 *countRead)
{
*countRead = 0;
while (count) {
PRUint32 nread;
PRBool complete;
mMsg.ReadFrom(ptr, count, &nread, &complete);
if (complete) {
mTransport->OnMsgAvailable(&mMsg);
mMsg.Reset();
}
count -= nread;
ptr += nread;
*countRead += nread;
}
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,177 @@
/* ***** 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 "nsIStreamListener.h"
#include "nsIStreamProvider.h"
#include "nsITransport.h"
#include "nsITimer.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "prio.h"
#include "ipcMessage.h"
#include "ipcMessageQ.h"
class ipcTransport;
//----------------------------------------------------------------------------
// ipcTransportObserver interface
//----------------------------------------------------------------------------
class ipcTransportObserver
{
public:
virtual void OnMsgAvailable(const ipcMessage *) = 0;
};
//----------------------------------------------------------------------------
// ipcSendQueue
//----------------------------------------------------------------------------
class ipcSendQueue : public nsIStreamProvider
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMPROVIDER
ipcSendQueue(ipcTransport *transport)
: mTransport(transport)
{ }
virtual ~ipcSendQueue() { }
void EnqueueMsg(ipcMessage *msg) { mQueue.Append(msg); }
PRBool IsEmpty() { return mQueue.IsEmpty(); }
private:
ipcTransport *mTransport;
ipcMessageQ mQueue;
};
//-----------------------------------------------------------------------------
// ipcReceiver
//-----------------------------------------------------------------------------
class ipcReceiver : public nsIStreamListener
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
ipcReceiver(ipcTransport *transport)
: mTransport(transport)
{ }
virtual ~ipcReceiver() { }
nsresult ReadSegment(const char *, PRUint32 count, PRUint32 *countRead);
private:
ipcTransport *mTransport;
ipcMessage mMsg; // message in progress
};
//-----------------------------------------------------------------------------
// ipcTransport
//-----------------------------------------------------------------------------
class ipcTransport : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
ipcTransport()
: mSendQ(this)
, mReceiver(this)
, mObserver(nsnull)
, mFD(nsnull)
, mWriteSuspended(PR_FALSE)
, mSentInitialMsgs(PR_FALSE)
, mHaveConnection(PR_FALSE)
, mConnectionAttemptCount(0)
{ }
virtual ~ipcTransport();
nsresult Init(const nsACString &socketPath, ipcTransportObserver *);
nsresult Shutdown();
// takes ownership of |msg|
nsresult SendMsg(ipcMessage *msg);
public:
// internal to implementation
void OnMsgAvailable(const ipcMessage *);
void SetWriteSuspended(PRBool val) { mWriteSuspended = val; }
void OnStartRequest(nsIRequest *req);
void OnStopRequest(nsIRequest *req, nsresult status);
PRFileDesc *FD() { return mFD; }
private:
//
// helpers
//
nsresult Connect();
nsresult SendMsg_Internal(ipcMessage *msg);
nsresult CreateTransport();
nsresult SpawnDaemon();
//
// data
//
ipcSendQueue mSendQ;
ipcReceiver mReceiver;
ipcMessageQ mDelayedQ;
ipcTransportObserver *mObserver;
nsCOMPtr<nsITransport> mTransport;
nsCOMPtr<nsIRequest> mReadRequest;
nsCOMPtr<nsIRequest> mWriteRequest;
nsCOMPtr<nsITimer> mTimer;
nsCString mSocketPath;
PRFileDesc *mFD;
PRPackedBool mWriteSuspended;
PRPackedBool mSentInitialMsgs;
PRPackedBool mHaveConnection;
PRUint8 mConnectionAttemptCount;
};
#endif // !ipcTransport_h__

Просмотреть файл

@ -0,0 +1,54 @@
#
# 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)
LOCAL_INCLUDES = \
-I$(srcdir)/../util \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,207 @@
/* ***** 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 "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include "nsIComponentRegistrar.h"
#include "nsLiteralString.h"
static const nsID TestTargetID =
{ /* 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;
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 char *data, PRUint32 dataLen)
{
printf("*** got message: [%s]\n", data);
if (--gMsgCount == 0)
gKeepRunning = PR_FALSE;
return NS_OK;
}
void SendMsg(ipcIService *ipc, const nsID &target, const char *data, PRUint32 dataLen)
{
printf("*** sending message: [dataLen=%u]\n", dataLen);
ipc->SendMessage(target, data, dataLen);
gMsgCount++;
}
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)");
ipcServ->SetMessageObserver(TestTargetID, 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, TestTargetID, data, strlen(data)+1);
while (gKeepRunning)
gEventQ->ProcessPendingEvents();
printf("*** processing remaining events\n");
// process any remaining events
PLEvent *ev;
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;
}

Просмотреть файл

@ -0,0 +1,84 @@
# ***** 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
IS_COMPONENT = 1
MODULE_NAME = testmodule
REQUIRES = xpcom \
ipc \
$(NULL)
CPPSRCS = TestModule.cpp
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/$(LIB_PREFIX)ipccom_s.$(LIB_SUFFIX) \
$(NULL)
LOCAL_INCLUDES = \
-I$(srcdir)/../common \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
EXTRA_DSO_LIBS = mozipcd
endif
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

Просмотреть файл

@ -0,0 +1,51 @@
#include <stdio.h>
#include "nscore.h"
#include "ipcModule.h"
#include "ipcMessage.h"
#include "ipcd.h"
extern "C" NS_EXPORT ipcModule **IPC_GetModuleList();
static const nsID TestModuleID =
{ /* e628fc6e-a6a7-48c7-adba-f241d1128fb8 */
0xe628fc6e,
0xa6a7,
0x48c7,
{0xad, 0xba, 0xf2, 0x41, 0xd1, 0x12, 0x8f, 0xb8}
};
class TestModule : public ipcModule
{
public:
void Shutdown()
{
printf("*** TestModule::Shutdown\n");
}
const nsID &ID()
{
printf("*** TestModule::ID\n");
return TestModuleID;
}
void HandleMsg(ipcClient *client, const ipcMessage *msg)
{
printf("*** TestModule::HandleMsg [%s]\n", msg->Data());
ipcMessage *outMsg = new ipcMessage();
static const char buf[] = "pong";
outMsg->Init(TestModuleID, buf, sizeof(buf));
IPC_SendMsg(client, outMsg);
}
};
ipcModule **
IPC_GetModuleList()
{
static TestModule testMod;
static ipcModule *modules[2];
modules[0] = &testMod;
modules[1] = NULL;
return modules;
}