mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 11:58:55 +00:00
patch for bug 242248 "IPC synchronous message support needs to be reworked" (not yet used for anything)
This commit is contained in:
parent
5a1e4899be
commit
3518a0fd5b
@ -45,11 +45,16 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = ipcd
|
||||
|
||||
EXPORTS = \
|
||||
ipcdclient.h \
|
||||
ipcCID.h \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
ipcIService.idl \
|
||||
ipcIMessageObserver.idl \
|
||||
ipcIClientObserver.idl \
|
||||
ipcIClientQueryHandler.idl \
|
||||
ipcIClientInfo.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -46,6 +46,6 @@ interface ipcIClientObserver : nsISupports
|
||||
const unsigned long CLIENT_UP = 1;
|
||||
const unsigned long CLIENT_DOWN = 2;
|
||||
|
||||
void onClientStatus(in unsigned long aClientID,
|
||||
in unsigned long aClientStatus);
|
||||
void onClientStateChange(in unsigned long aClientID,
|
||||
in unsigned long aClientState);
|
||||
};
|
||||
|
@ -44,6 +44,9 @@
|
||||
interface ipcIMessageObserver : nsISupports
|
||||
{
|
||||
/**
|
||||
* @param aSenderID
|
||||
* the client id of the sender of this message. if sent by the
|
||||
* daemon (or a deamon module), then this will have a value of 0.
|
||||
* @param aTarget
|
||||
* the target of the message, corresponding to the target this
|
||||
* observer was registered under. this parameter is passed to allow
|
||||
@ -53,7 +56,8 @@ interface ipcIMessageObserver : nsISupports
|
||||
* @param aDataLen
|
||||
* the data length of the message.
|
||||
*/
|
||||
void onMessageAvailable(in nsIDRef aTarget,
|
||||
void onMessageAvailable(in unsigned long aSenderID,
|
||||
in nsIDRef aTarget,
|
||||
[array, const, size_is(aDataLen)]
|
||||
in octet aData,
|
||||
in unsigned long aDataLen);
|
||||
|
@ -39,7 +39,6 @@
|
||||
|
||||
interface ipcIMessageObserver;
|
||||
interface ipcIClientObserver;
|
||||
interface ipcIClientQueryHandler;
|
||||
|
||||
/**
|
||||
* ipcIService
|
||||
@ -82,7 +81,7 @@ interface ipcIService : nsISupports
|
||||
*
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if no connection to the IPC daemon.
|
||||
*/
|
||||
readonly attribute unsigned long clientID;
|
||||
readonly attribute unsigned long ID;
|
||||
|
||||
/**
|
||||
* this process can appear under several client names. use the following
|
||||
@ -95,71 +94,42 @@ interface ipcIService : nsISupports
|
||||
*
|
||||
* XXX An IPC client name resembles a XPCOM contract ID.
|
||||
*/
|
||||
void addClientName(in string aName);
|
||||
void removeClientName(in string aName);
|
||||
void addName(in string aName);
|
||||
void removeName(in string aName);
|
||||
|
||||
/**
|
||||
* add a new observer of client status change notifications.
|
||||
*/
|
||||
void addClientObserver(in ipcIClientObserver aObserver);
|
||||
|
||||
/**
|
||||
* remove an observer of client status change notifications.
|
||||
*/
|
||||
void removeClientObserver(in ipcIClientObserver aObserver);
|
||||
|
||||
/**************************************************************************
|
||||
* client query methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* query info about a particular client given its client name. the
|
||||
* observer's onClientInfo method is called with the result of the lookup,
|
||||
* or if there is no client matching the given name, the observer's
|
||||
* onClientDown method will be called instead.
|
||||
*
|
||||
* @param aName
|
||||
* the name of the client being queried.
|
||||
* @param aHandler
|
||||
* the handler to be notified with result.
|
||||
* @param aSync
|
||||
* block the calling thread until the query completes.
|
||||
*
|
||||
* @return integer value identifying this query.
|
||||
* resolve the given client name to the id of a connected client. this
|
||||
* involves a round trip to the daemon, and as a result the calling thread
|
||||
* may block on this function call while waiting for the daemon to respond.
|
||||
*/
|
||||
unsigned long queryClientByName(in string aName,
|
||||
in ipcIClientQueryHandler aHandler,
|
||||
in boolean aSync);
|
||||
unsigned long resolveClientName(in string aName);
|
||||
|
||||
|
||||
/**
|
||||
* query info about a particular client given its client ID. the observer's
|
||||
* onClientInfo method is called with the result of the lookup, or if there
|
||||
* is no client matching the given name, the observer's onClientDown method
|
||||
* will be called instead.
|
||||
*
|
||||
* @param aClientID
|
||||
* the ID of the client being queried.
|
||||
* @param aHandler
|
||||
* the handler to be notified with result.
|
||||
* @param aSync
|
||||
* block the calling thread until the query completes.
|
||||
*
|
||||
* @return integer value identifying this query.
|
||||
* tests whether a particular client is connected to the IPC daemon.
|
||||
*/
|
||||
unsigned long queryClientByID(in unsigned long aClientID,
|
||||
in ipcIClientQueryHandler aHandler,
|
||||
in boolean aSync);
|
||||
boolean clientExists(in unsigned long aClientID);
|
||||
|
||||
/**
|
||||
* called to cancel a pending query.
|
||||
*
|
||||
* @param aQueryID
|
||||
* the return value from one of the "query" methods.
|
||||
*/
|
||||
void cancelQuery(in unsigned long aQueryID);
|
||||
|
||||
/**
|
||||
* set client observer. observer's onClientUp method is called whenever
|
||||
* a new client comes online, and the observer's onClientDown method is
|
||||
* called whenever a client goes offline.
|
||||
*
|
||||
* @param aObserver
|
||||
* the client observer.
|
||||
*/
|
||||
void setClientObserver(in ipcIClientObserver aObserver);
|
||||
|
||||
// XXX need other functions to enumerate clients, clients implementing targets, etc.
|
||||
// enumerator getClients();
|
||||
// enumerator getClientsSupportingTarget(in nsIDRef aTarget);
|
||||
// enumerator getClientNames(in unsigned long aClientID);
|
||||
// enumerator getClientTargets(in unsigned long aClientID);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
@ -176,7 +146,7 @@ interface ipcIService : nsISupports
|
||||
* 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);
|
||||
void defineTarget(in nsIDRef aTarget, in ipcIMessageObserver aObserver);
|
||||
|
||||
/**
|
||||
* send message asynchronously to a client or a module in the IPC daemon.
|
||||
@ -192,33 +162,50 @@ interface ipcIService : nsISupports
|
||||
* the message data.
|
||||
* @param aDataLen
|
||||
* the message length.
|
||||
* @param aSync
|
||||
* block the calling thread until a response to this message is
|
||||
* received.
|
||||
*/
|
||||
void sendMessage(in unsigned long aClientID,
|
||||
void sendMessage(in unsigned long aReceiverID,
|
||||
in nsIDRef aTarget,
|
||||
[array, const, size_is(aDataLen)]
|
||||
in octet aData,
|
||||
in unsigned long aDataLen,
|
||||
in boolean aSync);
|
||||
in unsigned long aDataLen);
|
||||
|
||||
/**
|
||||
* block the calling thread until a matching message is received.
|
||||
*
|
||||
* @param aSenderID
|
||||
* pass 0 to wait for a message from the daemon. pass PR_UINT32_MAX
|
||||
* to wait for a message from any source. otherwise, pass a client
|
||||
* id to wait for a message from that particular client.
|
||||
* @param aTarget
|
||||
* wait for a message to be delivered to this target.
|
||||
* @param aObserver
|
||||
* this observer's OnMessageAvailable method is called when a
|
||||
* matching message is available. pass null to use the default
|
||||
* observer associated with aTarget.
|
||||
* @param aTimeout
|
||||
* indicates maximum length of time in milliseconds that this
|
||||
* function may block the calling thread.
|
||||
*
|
||||
* @throws IPC_ERROR_WOULD_BLOCK if the timeout expires.
|
||||
*
|
||||
* the observer's OnMessageAvailable method may throw IPC_WAIT_NEXT_MESSAGE
|
||||
* to indicate that it does not wish to handle the message that it was
|
||||
* given, and that it will wait to be called with the next message. this
|
||||
* enables the observer to keep messages in the queue that do not match the
|
||||
* desired message. messages that remain in the queue will be dispatched
|
||||
* asynchronously to the default message handler after waitMessage finishes.
|
||||
*
|
||||
* NOTE: this function may hang the calling thread until a matching message
|
||||
* is received, so use it with caution.
|
||||
*/
|
||||
void waitMessage(in unsigned long aSenderID,
|
||||
in nsIDRef aTarget,
|
||||
in ipcIMessageObserver aObserver,
|
||||
in unsigned long aTimeout);
|
||||
};
|
||||
|
||||
%{C++
|
||||
// singleton implementing ipcIService
|
||||
#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} \
|
||||
}
|
||||
|
||||
// category and observer event defines
|
||||
// category and observer event defines (XXX not yet implemented)
|
||||
#define IPC_SERVICE_STARTUP_CATEGORY "ipc-startup-category"
|
||||
#define IPC_SERVICE_STARTUP_TOPIC "ipc-startup"
|
||||
#define IPC_SERVICE_SHUTDOWN_TOPIC "ipc-shutdown"
|
||||
|
228
ipc/ipcd/client/public/ipcdclient.h
Normal file
228
ipc/ipcd/client/public/ipcdclient.h
Normal file
@ -0,0 +1,228 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla IPC.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@meer.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef ipcdclient_h__
|
||||
#define ipcdclient_h__
|
||||
|
||||
/*****************************************************************************
|
||||
* This file provides a client-side API to the IPC daemon.
|
||||
*
|
||||
* This API can be used to communicate with other clients of the IPC daemon
|
||||
* as well as modules running inside the IPC daemon.
|
||||
*
|
||||
* This API is meant to be used only on the application's main thread. It is
|
||||
* assumed that callbacks can be dispatched via the main thread's event queue.
|
||||
*/
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsID.h"
|
||||
#include "nsError.h"
|
||||
#include "ipcIMessageObserver.h"
|
||||
#include "ipcIClientObserver.h"
|
||||
|
||||
/* This API is only provided for the extensions compiled into the IPCDC
|
||||
* library, hence this API is hidden in the final DSO. */
|
||||
#define IPC_METHOD NS_HIDDEN_(nsresult)
|
||||
|
||||
/* This value can be used to represent the client id of any client connected
|
||||
* to the IPC daemon. */
|
||||
#define IPC_SENDER_ANY PR_UINT32_MAX
|
||||
|
||||
/* This error code can only be returned by OnMessageAvailable, when called by
|
||||
* IPC_WaitMessage. See IPC_WaitMessage for a description of how this error
|
||||
* code may be used. */
|
||||
#define IPC_WAIT_NEXT_MESSAGE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 10)
|
||||
|
||||
/* This error code is returned by IPC_WaitMessage under certain conditions. */
|
||||
#define IPC_ERROR_WOULD_BLOCK NS_BASE_STREAM_WOULD_BLOCK
|
||||
|
||||
/*****************************************************************************
|
||||
* Initialization and Shutdown
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensures that this process is connected to the IPC daemon. If it is already
|
||||
* connected, then this function call has no effect. Each call to IPC_Init
|
||||
* should be balanced by a call to IPC_Shutdown. A reference counter is used
|
||||
* to determine when to disconnect from the IPC daemon.
|
||||
*/
|
||||
IPC_METHOD IPC_Init();
|
||||
|
||||
/**
|
||||
* Disconnects this process from the IPC daemon. Must be called once for
|
||||
* every call to IPC_Init when the IPC connection is no longer needed.
|
||||
*/
|
||||
IPC_METHOD IPC_Shutdown();
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* The core messaging API
|
||||
*/
|
||||
|
||||
/**
|
||||
* Call this method to define a message target. A message target is defined
|
||||
* by a UUID and a message observer. This observer is notified asynchronously
|
||||
* whenever a message is sent to this target in this process.
|
||||
*
|
||||
* This function has three main effects:
|
||||
* o If the message target is already defined, then this function simply resets
|
||||
* its message observer.
|
||||
* o If the message target is not already defined, then the IPC daemon will be
|
||||
* notified of the existance of this message target.
|
||||
* o If null is passed for the message observer, then the message target is
|
||||
* removed, and the daemon is notified of the removal of this message target.
|
||||
*/
|
||||
IPC_METHOD IPC_DefineTarget(
|
||||
const nsID &aTarget,
|
||||
ipcIMessageObserver *aObserver
|
||||
);
|
||||
|
||||
/**
|
||||
* This function sends a message to the IPC daemon asynchronously. If
|
||||
* aReceiverID is non-zero, then the message is forwarded to the client
|
||||
* corresponding to that identifier.
|
||||
*
|
||||
* If there is no client corresponding to aRecieverID, then the IPC daemon will
|
||||
* simply drop the message.
|
||||
*/
|
||||
IPC_METHOD IPC_SendMessage(
|
||||
PRUint32 aReceiverID,
|
||||
const nsID &aTarget,
|
||||
const PRUint8 *aData,
|
||||
PRUint32 aDataLen
|
||||
);
|
||||
|
||||
/**
|
||||
* This function blocks the calling thread until a message for the given target
|
||||
* is received (optionally from the specified client).
|
||||
*
|
||||
* The aSenderID parameter is interpreted as follows:
|
||||
* o If aSenderID is 0, then this function waits for a message to be sent by
|
||||
* the IPC daemon.
|
||||
* o If aSenderID is IPC_SENDER_ANY, then this function waits for a message
|
||||
* to be sent from any source.
|
||||
* o Otherwise, this function waits for a message to be sent by client with
|
||||
* ID given by aSenderID. If aSenderID does not identify a valid client,
|
||||
* then this function will return an error.
|
||||
*
|
||||
* The aObserver parameter is interpreted as follows:
|
||||
* o If aObserver is null, then the default message observer for the target
|
||||
* is invoked when the next message is received.
|
||||
* o Otherwise, aObserver will be inovked when the next message is received.
|
||||
*
|
||||
* The aTimeout parameter is interpreted as follows:
|
||||
* o If aTimeout is PR_INTERVAL_NO_TIMEOUT, then this function will block
|
||||
* until a matching message is received.
|
||||
* o If aTimeout is PR_INTERVAL_NO_WAIT, then this function will only inspect
|
||||
* the current queue of messages. If no matching message is found, then
|
||||
* IPC_ERROR_WOULD_BLOCK is returned.
|
||||
* o Otherwise, aTimeout specifies the maximum amount of time to wait for a
|
||||
* matching message to be received. If no matching message is found after
|
||||
* the timeout expires, then IPC_ERROR_WOULD_BLOCK is returned.
|
||||
*
|
||||
* If aObserver's OnMessageAvailable function returns IPC_WAIT_NEXT_MESSAGE,
|
||||
* then the function will continue blocking until the next matching message
|
||||
* is received. Bypassed messages will be dispatched to the default message
|
||||
* observer when the thread's event queue is processed.
|
||||
*
|
||||
* This function runs the risk of hanging the calling thread indefinitely if
|
||||
* no matching message is ever received.
|
||||
*/
|
||||
IPC_METHOD IPC_WaitMessage(
|
||||
PRUint32 aSenderID,
|
||||
const nsID &aTarget,
|
||||
ipcIMessageObserver *aObserver = nsnull,
|
||||
PRIntervalTime aTimeout = PR_INTERVAL_NO_TIMEOUT
|
||||
);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the "ClientID" of the current process.
|
||||
*/
|
||||
IPC_METHOD IPC_GetID(
|
||||
PRUint32 *aClientID
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds a new name for the current process. The IPC daemon is notified of this
|
||||
* change, which allows other processes to discover this process by the given
|
||||
* name.
|
||||
*/
|
||||
IPC_METHOD IPC_AddName(
|
||||
const char *aName
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes a name associated with the current process.
|
||||
*/
|
||||
IPC_METHOD IPC_RemoveName(
|
||||
const char *aName
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds client observer.
|
||||
*/
|
||||
IPC_METHOD IPC_AddClientObserver(
|
||||
ipcIClientObserver *aObserver
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes client observer.
|
||||
*/
|
||||
IPC_METHOD IPC_RemoveClientObserver(
|
||||
ipcIClientObserver *aObserver
|
||||
);
|
||||
|
||||
/**
|
||||
* Resolves the given client name to a client ID of a process connected to
|
||||
* the IPC daemon.
|
||||
*/
|
||||
IPC_METHOD IPC_ResolveClientName(
|
||||
const char *aName,
|
||||
PRUint32 *aClientID
|
||||
);
|
||||
|
||||
/**
|
||||
* Tests whether the client is connected to the IPC daemon.
|
||||
*/
|
||||
IPC_METHOD IPC_ClientExists(
|
||||
PRUint32 aClientID,
|
||||
PRBool *aResult
|
||||
);
|
||||
|
||||
#endif /* ipcdclient_h__ */
|
@ -55,8 +55,8 @@ REQUIRES = \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
ipcdclient.cpp \
|
||||
ipcService.cpp \
|
||||
ipcTransport.cpp \
|
||||
ipcModuleFactory.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
@ -42,6 +42,9 @@
|
||||
|
||||
class ipcMessage;
|
||||
|
||||
#define IPC_METHOD_PRIVATE_(type) NS_HIDDEN_(type)
|
||||
#define IPC_METHOD_PRIVATE IPC_METHOD_PRIVATE_(nsresult)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Platform specific IPC connection API.
|
||||
*/
|
||||
@ -57,7 +60,7 @@ class ipcMessage;
|
||||
*
|
||||
* NOTE: This function must be called on the main thread.
|
||||
*/
|
||||
nsresult IPC_Connect(const char *daemonPath);
|
||||
IPC_METHOD_PRIVATE IPC_Connect(const char *daemonPath);
|
||||
|
||||
/**
|
||||
* IPC_Disconnect
|
||||
@ -68,7 +71,7 @@ nsresult IPC_Connect(const char *daemonPath);
|
||||
*
|
||||
* NOTE: This function must be called on the main thread.
|
||||
*/
|
||||
nsresult IPC_Disconnect();
|
||||
IPC_METHOD_PRIVATE IPC_Disconnect();
|
||||
|
||||
/**
|
||||
* IPC_SendMsg
|
||||
@ -82,7 +85,7 @@ nsresult IPC_Disconnect();
|
||||
*
|
||||
* NOTE: This function may be called on any thread.
|
||||
*/
|
||||
nsresult IPC_SendMsg(ipcMessage *msg);
|
||||
IPC_METHOD_PRIVATE IPC_SendMsg(ipcMessage *msg);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Cross-platform IPC connection methods.
|
||||
@ -99,7 +102,7 @@ nsresult IPC_SendMsg(ipcMessage *msg);
|
||||
* @param daemonPath
|
||||
* Specifies the path to the IPC daemon executable.
|
||||
*/
|
||||
nsresult IPC_SpawnDaemon(const char *daemonPath);
|
||||
IPC_METHOD_PRIVATE IPC_SpawnDaemon(const char *daemonPath);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* IPC connection callbacks (not implemented by the connection code).
|
||||
@ -115,7 +118,7 @@ nsresult IPC_SpawnDaemon(const char *daemonPath);
|
||||
* described by the |error| parameter. If |error| is NS_OK, then it means the
|
||||
* connection was closed in response to a call to IPC_Disconnect.
|
||||
*/
|
||||
void IPC_OnConnectionEnd(nsresult error);
|
||||
IPC_METHOD_PRIVATE_(void) IPC_OnConnectionEnd(nsresult error);
|
||||
|
||||
/**
|
||||
* IPC_OnMessageAvailable
|
||||
@ -124,6 +127,6 @@ void IPC_OnConnectionEnd(nsresult error);
|
||||
* daemon. The ipcMessage object, |msg|, must be deleted by the implementation
|
||||
* of IPC_OnMessageAvailable when the object is no longer needed.
|
||||
*/
|
||||
void IPC_OnMessageAvailable(ipcMessage *msg);
|
||||
IPC_METHOD_PRIVATE_(void) IPC_OnMessageAvailable(ipcMessage *msg);
|
||||
|
||||
#endif // ipcConnection_h__
|
||||
|
@ -40,6 +40,8 @@
|
||||
#include "nsICategoryManager.h"
|
||||
#include "ipcService.h"
|
||||
#include "ipcConfig.h"
|
||||
#include "ipcCID.h"
|
||||
#include "ipcLockCID.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Define the contructor function for the objects
|
||||
@ -93,6 +95,45 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcLockService, Init)
|
||||
#include "tmTransactionService.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(tmTransactionService)
|
||||
|
||||
#if 0
|
||||
#include "ipcDConnectService.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcDConnectService, Init)
|
||||
|
||||
// enable this code to make the IPC DCONNECT service auto-start.
|
||||
NS_METHOD
|
||||
ipcDConnectServiceRegisterProc(nsIComponentManager *aCompMgr,
|
||||
nsIFile *aPath,
|
||||
const char *registryLocation,
|
||||
const char *componentType,
|
||||
const nsModuleComponentInfo *info)
|
||||
{
|
||||
//
|
||||
// add ipcService to the XPCOM startup category
|
||||
//
|
||||
nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
|
||||
if (catman) {
|
||||
nsXPIDLCString prevEntry;
|
||||
catman->AddCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID, "ipcDConnectService",
|
||||
IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE, PR_TRUE,
|
||||
getter_Copies(prevEntry));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
ipcDConnectServiceUnregisterProc(nsIComponentManager *aCompMgr,
|
||||
nsIFile *aPath,
|
||||
const char *registryLocation,
|
||||
const nsModuleComponentInfo *info)
|
||||
{
|
||||
nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
|
||||
if (catman)
|
||||
catman->DeleteCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID,
|
||||
IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Define a table of CIDs implemented by this module along with other
|
||||
// information like the function to create an instance, contractid, and
|
||||
@ -118,6 +159,12 @@ static const nsModuleComponentInfo components[] = {
|
||||
IPC_TRANSACTIONSERVICE_CID,
|
||||
IPC_TRANSACTIONSERVICE_CONTRACTID,
|
||||
tmTransactionServiceConstructor },
|
||||
#if 0
|
||||
{ IPC_DCONNECTSERVICE_CLASSNAME,
|
||||
IPC_DCONNECTSERVICE_CID,
|
||||
IPC_DCONNECTSERVICE_CONTRACTID,
|
||||
ipcDConnectServiceConstructor },
|
||||
#endif
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -14,9 +14,8 @@
|
||||
*
|
||||
* 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 of the Original Code is IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
@ -36,472 +35,69 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "plstr.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsCategoryManagerUtils.h"
|
||||
#include "nsEventQueueUtils.h"
|
||||
|
||||
#include "ipcConfig.h"
|
||||
#include "ipcLog.h"
|
||||
#include "ipcService.h"
|
||||
#include "ipcMessageUtils.h"
|
||||
#include "ipcm.h"
|
||||
|
||||
#include "ipcIMessageObserver.h"
|
||||
#include "ipcIClientObserver.h"
|
||||
#include "ipcIClientQueryHandler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
ipcReleaseMessageObserver(nsHashKey *aKey, void *aData, void* aClosure)
|
||||
{
|
||||
ipcIMessageObserver *obs = (ipcIMessageObserver *) aData;
|
||||
NS_RELEASE(obs);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ipcClientQuery
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class ipcClientQuery
|
||||
{
|
||||
public:
|
||||
ipcClientQuery(PRUint32 cID, ipcIClientQueryHandler *handler)
|
||||
: mNext(nsnull)
|
||||
, mQueryID(++gLastQueryID)
|
||||
, mClientID(cID)
|
||||
, mHandler(handler)
|
||||
{ }
|
||||
|
||||
static PRUint32 gLastQueryID;
|
||||
|
||||
void SetClientID(PRUint32 cID) { mClientID = cID; }
|
||||
void OnQueryComplete(nsresult status, const ipcmMessageClientInfo *msg);
|
||||
|
||||
PRUint32 QueryID() { return mQueryID; }
|
||||
PRBool IsCanceled() { return mHandler.get() == NULL; }
|
||||
|
||||
ipcClientQuery *mNext;
|
||||
private:
|
||||
PRUint32 mQueryID;
|
||||
PRUint32 mClientID;
|
||||
nsCOMPtr<ipcIClientQueryHandler> mHandler;
|
||||
};
|
||||
|
||||
PRUint32 ipcClientQuery::gLastQueryID = 0;
|
||||
|
||||
void
|
||||
ipcClientQuery::OnQueryComplete(nsresult status, const ipcmMessageClientInfo *msg)
|
||||
{
|
||||
NS_ASSERTION(mHandler, "no handler");
|
||||
|
||||
PRUint32 nameCount = 0;
|
||||
PRUint32 targetCount = 0;
|
||||
const char **names = NULL;
|
||||
const nsID **targets = NULL;
|
||||
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
nameCount = msg->NameCount();
|
||||
targetCount = msg->TargetCount();
|
||||
PRUint32 i;
|
||||
|
||||
names = (const char **) malloc(nameCount * sizeof(char *));
|
||||
const char *lastName = NULL;
|
||||
for (i = 0; i < nameCount; ++i) {
|
||||
lastName = msg->NextName(lastName);
|
||||
names[i] = lastName;
|
||||
}
|
||||
|
||||
targets = (const nsID **) malloc(targetCount * sizeof(nsID *));
|
||||
const nsID *lastTarget = NULL;
|
||||
for (i = 0; i < targetCount; ++i) {
|
||||
lastTarget = msg->NextTarget(lastTarget);
|
||||
targets[i] = lastTarget;
|
||||
}
|
||||
}
|
||||
|
||||
mHandler->OnQueryComplete(mQueryID,
|
||||
status,
|
||||
mClientID,
|
||||
names, nameCount,
|
||||
targets, targetCount);
|
||||
mHandler = NULL;
|
||||
|
||||
if (names)
|
||||
free(names);
|
||||
if (targets)
|
||||
free(targets);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ipcService
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ipcService::ipcService()
|
||||
: mTransport(nsnull)
|
||||
, mClientID(0)
|
||||
{
|
||||
IPC_InitLog(">>>");
|
||||
}
|
||||
|
||||
ipcService::~ipcService()
|
||||
{
|
||||
NS_ASSERTION(mTransport == nsnull, "no xpcom-shutdown event??");
|
||||
}
|
||||
|
||||
nsresult
|
||||
ipcService::Init()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observ(do_GetService("@mozilla.org/observer-service;1"));
|
||||
if (observ)
|
||||
observ->AddObserver(this, "xpcom-shutdown", PR_FALSE);
|
||||
|
||||
nsresult rv;
|
||||
mTransport = new ipcTransport();
|
||||
if (!mTransport)
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
else {
|
||||
rv = mTransport->Init(this, &mClientID);
|
||||
if (NS_FAILED(rv))
|
||||
mTransport = nsnull;
|
||||
else {
|
||||
//
|
||||
// broadcast IPC startup...
|
||||
//
|
||||
NS_CreateServicesFromCategory(IPC_SERVICE_STARTUP_CATEGORY,
|
||||
NS_STATIC_CAST(ipcIService *, this),
|
||||
IPC_SERVICE_STARTUP_TOPIC);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
ipcService::Shutdown()
|
||||
{
|
||||
//
|
||||
// broadcast IPC shutdown...
|
||||
//
|
||||
nsCOMPtr<nsIObserverService> observ(
|
||||
do_GetService("@mozilla.org/observer-service;1"));
|
||||
if (observ)
|
||||
observ->NotifyObservers(NS_STATIC_CAST(ipcIService *, this),
|
||||
IPC_SERVICE_SHUTDOWN_TOPIC, nsnull);
|
||||
|
||||
// error out any pending queries
|
||||
while (mQueryQ.First()) {
|
||||
ipcClientQuery *query = mQueryQ.First();
|
||||
query->OnQueryComplete(NS_ERROR_ABORT, NULL);
|
||||
mQueryQ.DeleteFirst();
|
||||
}
|
||||
|
||||
// disconnect any message observers
|
||||
mObserverDB.Reset(ipcReleaseMessageObserver, nsnull);
|
||||
|
||||
// drop daemon connection
|
||||
if (mTransport) {
|
||||
mTransport->Shutdown();
|
||||
mTransport = nsnull;
|
||||
}
|
||||
|
||||
mClientID = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ipcService::OnIPCMClientID(const ipcmMessageClientID *msg)
|
||||
{
|
||||
LOG(("ipcService::OnIPCMClientID\n"));
|
||||
|
||||
ipcClientQuery *query = mQueryQ.First();
|
||||
if (!query) {
|
||||
NS_WARNING("no pending query; ignoring message.");
|
||||
return;
|
||||
}
|
||||
|
||||
PRUint32 cID = msg->ClientID();
|
||||
PRBool sync = msg->TestFlag(IPC_MSG_FLAG_SYNC_REPLY);
|
||||
|
||||
//
|
||||
// (1) store client ID in query
|
||||
// (2) move query to end of queue
|
||||
// (3) issue CLIENT_INFO request
|
||||
//
|
||||
query->SetClientID(cID);
|
||||
|
||||
mQueryQ.RemoveFirst();
|
||||
mQueryQ.Append(query);
|
||||
|
||||
mTransport->SendMsg(new ipcmMessageQueryClientInfo(cID), sync);
|
||||
}
|
||||
|
||||
void
|
||||
ipcService::OnIPCMClientInfo(const ipcmMessageClientInfo *msg)
|
||||
{
|
||||
LOG(("ipcService::OnIPCMClientInfo\n"));
|
||||
|
||||
ipcClientQuery *query = mQueryQ.First();
|
||||
if (!query) {
|
||||
NS_WARNING("no pending query; ignoring message.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!query->IsCanceled())
|
||||
query->OnQueryComplete(NS_OK, msg);
|
||||
|
||||
mQueryQ.DeleteFirst();
|
||||
}
|
||||
|
||||
void
|
||||
ipcService::OnIPCMError(const ipcmMessageError *msg)
|
||||
{
|
||||
LOG(("ipcService::OnIPCMError [reason=0x%08x]\n", msg->Reason()));
|
||||
|
||||
ipcClientQuery *query = mQueryQ.First();
|
||||
if (!query) {
|
||||
NS_WARNING("no pending query; ignoring message.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!query->IsCanceled())
|
||||
query->OnQueryComplete(NS_ERROR_FAILURE, NULL);
|
||||
|
||||
mQueryQ.DeleteFirst();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// interface impl
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS2(ipcService, ipcIService, nsIObserver)
|
||||
NS_IMPL_ISUPPORTS1(ipcService, ipcIService)
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::GetClientID(PRUint32 *clientID)
|
||||
ipcService::GetID(PRUint32 *aID)
|
||||
{
|
||||
NS_ENSURE_TRUE(mClientID != 0, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
*clientID = mClientID;
|
||||
return NS_OK;
|
||||
return IPC_GetID(aID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::AddClientName(const char *name)
|
||||
ipcService::AddName(const char *aName)
|
||||
{
|
||||
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
ipcMessage *msg = new ipcmMessageClientAddName(name);
|
||||
if (!msg)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return mTransport->SendMsg(msg);
|
||||
return IPC_AddName(aName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::RemoveClientName(const char *name)
|
||||
ipcService::RemoveName(const char *aName)
|
||||
{
|
||||
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
ipcMessage *msg = new ipcmMessageClientDelName(name);
|
||||
if (!msg)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return mTransport->SendMsg(msg);
|
||||
return IPC_RemoveName(aName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::QueryClientByName(const char *name,
|
||||
ipcIClientQueryHandler *handler,
|
||||
PRBool sync,
|
||||
PRUint32 *queryID)
|
||||
ipcService::AddClientObserver(ipcIClientObserver *aObserver)
|
||||
{
|
||||
if (!mTransport)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
ipcMessage *msg;
|
||||
|
||||
msg = new ipcmMessageQueryClientByName(name);
|
||||
if (!msg)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = mTransport->SendMsg(msg, sync);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
ipcClientQuery *query = new ipcClientQuery(0, handler);
|
||||
if (queryID)
|
||||
*queryID = query->QueryID();
|
||||
mQueryQ.Append(query);
|
||||
return NS_OK;
|
||||
return IPC_AddClientObserver(aObserver);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::QueryClientByID(PRUint32 clientID,
|
||||
ipcIClientQueryHandler *handler,
|
||||
PRBool sync,
|
||||
PRUint32 *queryID)
|
||||
ipcService::RemoveClientObserver(ipcIClientObserver *aObserver)
|
||||
{
|
||||
if (!mTransport)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
ipcMessage *msg;
|
||||
|
||||
msg = new ipcmMessageQueryClientInfo(clientID);
|
||||
if (!msg)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = mTransport->SendMsg(msg, sync);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
ipcClientQuery *query = new ipcClientQuery(clientID, handler);
|
||||
if (queryID)
|
||||
*queryID = query->QueryID();
|
||||
mQueryQ.Append(query);
|
||||
return NS_OK;
|
||||
return IPC_RemoveClientObserver(aObserver);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::CancelQuery(PRUint32 queryID)
|
||||
ipcService::ResolveClientName(const char *aName, PRUint32 *aID)
|
||||
{
|
||||
ipcClientQuery *query = mQueryQ.First();
|
||||
while (query) {
|
||||
if (query->QueryID() == queryID) {
|
||||
query->OnQueryComplete(NS_ERROR_ABORT, NULL);
|
||||
break;
|
||||
}
|
||||
query = query->mNext;
|
||||
}
|
||||
return NS_OK;
|
||||
return IPC_ResolveClientName(aName, aID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::SetClientObserver(ipcIClientObserver *observer)
|
||||
ipcService::ClientExists(PRUint32 aClientID, PRBool *aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return IPC_ClientExists(aClientID, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::SetMessageObserver(const nsID &target, ipcIMessageObserver *observer)
|
||||
ipcService::DefineTarget(const nsID &aTarget, ipcIMessageObserver *aObserver)
|
||||
{
|
||||
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsIDKey key(target);
|
||||
PRBool sendAdd = PR_TRUE;
|
||||
|
||||
ipcIMessageObserver *cobs = (ipcIMessageObserver *) mObserverDB.Get(&key);
|
||||
if (cobs) {
|
||||
NS_RELEASE(cobs);
|
||||
if (!observer) {
|
||||
mObserverDB.Remove(&key);
|
||||
//
|
||||
// send CLIENT_DEL_TARGET
|
||||
//
|
||||
mTransport->SendMsg(new ipcmMessageClientDelTarget(target));
|
||||
return NS_OK;
|
||||
}
|
||||
sendAdd = PR_FALSE;
|
||||
}
|
||||
if (observer) {
|
||||
NS_ADDREF(observer);
|
||||
mObserverDB.Put(&key, observer);
|
||||
if (sendAdd) {
|
||||
//
|
||||
// send CLIENT_ADD_TARGET
|
||||
//
|
||||
mTransport->SendMsg(new ipcmMessageClientAddTarget(target));
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
return IPC_DefineTarget(aTarget, aObserver);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::SendMessage(PRUint32 clientID,
|
||||
const nsID &target,
|
||||
const PRUint8 *data,
|
||||
PRUint32 dataLen,
|
||||
PRBool sync)
|
||||
ipcService::SendMessage(PRUint32 aReceiverID, const nsID &aTarget,
|
||||
const PRUint8 *aData, PRUint32 aDataLen)
|
||||
{
|
||||
NS_ENSURE_TRUE(mTransport, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (target.Equals(IPCM_TARGET)) {
|
||||
NS_ERROR("do not try to talk to the IPCM target directly");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ipcMessage *msg;
|
||||
if (clientID)
|
||||
msg = new ipcmMessageForward(clientID, target, (const char *) data, dataLen);
|
||||
else
|
||||
msg = new ipcMessage(target, (const char *) data, dataLen);
|
||||
|
||||
if (!msg)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return mTransport->SendMsg(msg, sync);
|
||||
return IPC_SendMessage(aReceiverID, aTarget, aData, aDataLen);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsIObserver impl
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcService::Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
|
||||
ipcService::WaitMessage(PRUint32 aSenderID, const nsID &aTarget,
|
||||
ipcIMessageObserver *aObserver,
|
||||
PRUint32 aTimeout)
|
||||
{
|
||||
if (strcmp(topic, "xpcom-shutdown") == 0)
|
||||
Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ipcTransportObserver impl
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ipcService::OnConnectionLost()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
ipcService::OnMessageAvailable(const ipcMessage *msg)
|
||||
{
|
||||
LOG(("ipcService::OnMessageAvailable [msg=%p]\n", msg));
|
||||
|
||||
if (msg->Target().Equals(IPCM_TARGET)) {
|
||||
//
|
||||
// all IPCM messages stop here.
|
||||
//
|
||||
PRUint32 type = IPCM_GetMsgType(msg);
|
||||
switch (type) {
|
||||
case IPCM_MSG_TYPE_CLIENT_ID:
|
||||
OnIPCMClientID((const ipcmMessageClientID *) msg);
|
||||
break;
|
||||
case IPCM_MSG_TYPE_CLIENT_INFO:
|
||||
OnIPCMClientInfo((const ipcmMessageClientInfo *) msg);
|
||||
break;
|
||||
case IPCM_MSG_TYPE_ERROR:
|
||||
OnIPCMError((const ipcmMessageError *) msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsIDKey key(msg->Target());
|
||||
ipcIMessageObserver *observer = (ipcIMessageObserver *) mObserverDB.Get(&key);
|
||||
if (observer)
|
||||
observer->OnMessageAvailable(msg->Target(),
|
||||
(const PRUint8 *) msg->Data(),
|
||||
msg->DataLen());
|
||||
}
|
||||
return IPC_WaitMessage(aSenderID, aTarget, aObserver, PR_MillisecondsToInterval(aTimeout));
|
||||
}
|
||||
|
@ -38,52 +38,19 @@
|
||||
#ifndef ipcService_h__
|
||||
#define ipcService_h__
|
||||
|
||||
#include "nsHashtable.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "plevent.h"
|
||||
|
||||
#include "ipcIService.h"
|
||||
#include "ipcTransport.h"
|
||||
#include "ipcList.h"
|
||||
#include "ipcMessage.h"
|
||||
#include "ipcMessageQ.h"
|
||||
#include "ipcm.h"
|
||||
|
||||
typedef ipcList<class ipcClientQuery> ipcClientQueryQ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ipcService
|
||||
//----------------------------------------------------------------------------
|
||||
#include "ipcdclient.h"
|
||||
|
||||
class ipcService : public ipcIService
|
||||
, public ipcTransportObserver
|
||||
, public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IPCISERVICE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
ipcService();
|
||||
virtual ~ipcService();
|
||||
|
||||
nsresult Init();
|
||||
void Shutdown();
|
||||
|
||||
// ipcTransportObserver:
|
||||
void OnConnectionLost();
|
||||
void OnMessageAvailable(const ipcMessage *);
|
||||
NS_HIDDEN_(nsresult) Init() { return IPC_Init(); }
|
||||
|
||||
private:
|
||||
nsresult ErrorAccordingToIPCM(PRUint32 err);
|
||||
void OnIPCMClientID(const ipcmMessageClientID *);
|
||||
void OnIPCMClientInfo(const ipcmMessageClientInfo *);
|
||||
void OnIPCMError(const ipcmMessageError *);
|
||||
|
||||
nsHashtable mObserverDB;
|
||||
nsRefPtr<ipcTransport> mTransport;
|
||||
ipcClientQueryQ mQueryQ;
|
||||
PRUint32 mClientID;
|
||||
~ipcService() { IPC_Shutdown(); }
|
||||
};
|
||||
|
||||
#endif // !ipcService_h__
|
||||
#endif // !defined( ipcService_h__ )
|
||||
|
@ -126,7 +126,7 @@ end:
|
||||
if (attr)
|
||||
PR_DestroyProcessAttr(attr);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ipcTransport
|
||||
|
1129
ipc/ipcd/client/src/ipcdclient.cpp
Normal file
1129
ipc/ipcd/client/src/ipcdclient.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -107,7 +107,7 @@ struct ipcCommandModule
|
||||
{
|
||||
LOG(("got PING\n"));
|
||||
|
||||
IPC_SendMsg(client, new ipcmMessagePing());
|
||||
IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -115,7 +115,7 @@ struct ipcCommandModule
|
||||
{
|
||||
LOG(("got CLIENT_HELLO\n"));
|
||||
|
||||
IPC_SendMsg(client, new ipcmMessageClientID(client->ID()));
|
||||
IPC_SendMsg(client, new ipcmMessageClientID(IPCM_GetRequestIndex(rawMsg), client->ID()));
|
||||
|
||||
//
|
||||
// NOTE: it would almost make sense for this notification to live
|
||||
@ -136,6 +136,9 @@ struct ipcCommandModule
|
||||
const char *name = msg->Name();
|
||||
if (name)
|
||||
client->AddName(name);
|
||||
|
||||
// TODO: send better status code (e.g., suppose name already defined for client)
|
||||
IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -147,6 +150,9 @@ struct ipcCommandModule
|
||||
const char *name = msg->Name();
|
||||
if (name)
|
||||
client->DelName(name);
|
||||
|
||||
// TODO: send better status code (e.g., suppose name not defined for client)
|
||||
IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -156,6 +162,9 @@ struct ipcCommandModule
|
||||
|
||||
ipcMessageCast<ipcmMessageClientAddTarget> msg(rawMsg);
|
||||
client->AddTarget(msg->Target());
|
||||
|
||||
// TODO: send better status code (e.g., suppose target already defined for client)
|
||||
IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -165,6 +174,9 @@ struct ipcCommandModule
|
||||
|
||||
ipcMessageCast<ipcmMessageClientDelTarget> msg(rawMsg);
|
||||
client->DelTarget(msg->Target());
|
||||
|
||||
// TODO: send better status code (e.g., suppose target not defined for client)
|
||||
IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -172,18 +184,22 @@ struct ipcCommandModule
|
||||
{
|
||||
LOG(("got QUERY_CLIENT_BY_NAME\n"));
|
||||
|
||||
PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
|
||||
|
||||
ipcMessageCast<ipcmMessageQueryClientByName> msg(rawMsg);
|
||||
|
||||
ipcClient *result = IPC_GetClientByName(msg->Name());
|
||||
if (result) {
|
||||
LOG((" client exists w/ ID = %u\n", result->ID()));
|
||||
IPC_SendMsg(client, new ipcmMessageClientID(result->ID()));
|
||||
IPC_SendMsg(client, new ipcmMessageClientID(requestIndex, result->ID()));
|
||||
}
|
||||
else {
|
||||
LOG((" client does not exist\n"));
|
||||
IPC_SendMsg(client, new ipcmMessageError(IPCM_ERROR_CLIENT_NOT_FOUND));
|
||||
IPC_SendMsg(client, new ipcmMessageResult(requestIndex, IPCM_ERROR_NO_CLIENT));
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
OnQueryClientInfo(ipcClient *client, const ipcMessage *rawMsg)
|
||||
{
|
||||
@ -196,6 +212,7 @@ struct ipcCommandModule
|
||||
nsID **targets = BuildIDArray(result->Targets());
|
||||
|
||||
IPC_SendMsg(client, new ipcmMessageClientInfo(result->ID(),
|
||||
msg->RequestIndex(),
|
||||
(const char **) names,
|
||||
(const nsID **) targets));
|
||||
|
||||
@ -204,9 +221,10 @@ struct ipcCommandModule
|
||||
}
|
||||
else {
|
||||
LOG((" client does not exist\n"));
|
||||
IPC_SendMsg(client, new ipcmMessageError(IPCM_ERROR_CLIENT_NOT_FOUND));
|
||||
IPC_SendMsg(client, new ipcmMessageError(IPCM_ERROR_CLIENT_NOT_FOUND, msg->RequestIndex()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
OnForward(ipcClient *client, const ipcMessage *rawMsg)
|
||||
@ -215,14 +233,20 @@ struct ipcCommandModule
|
||||
|
||||
ipcMessageCast<ipcmMessageForward> msg(rawMsg);
|
||||
|
||||
ipcClient *dest = IPC_GetClientByID(msg->DestClientID());
|
||||
ipcClient *dest = IPC_GetClientByID(msg->ClientID());
|
||||
if (!dest) {
|
||||
LOG((" destination client not found!\n"));
|
||||
IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_ERROR_NO_CLIENT));
|
||||
return;
|
||||
}
|
||||
ipcMessage *newMsg = new ipcMessage(msg->InnerTarget(),
|
||||
msg->InnerData(),
|
||||
msg->InnerDataLen());
|
||||
// inform client that its message will be forwarded
|
||||
IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
|
||||
|
||||
ipcMessage *newMsg = new ipcmMessageForward(IPCM_MSG_PSH_FORWARD,
|
||||
client->ID(),
|
||||
msg->InnerTarget(),
|
||||
msg->InnerData(),
|
||||
msg->InnerDataLen());
|
||||
IPC_SendMsg(dest, newMsg);
|
||||
}
|
||||
};
|
||||
@ -233,26 +257,29 @@ IPCM_HandleMsg(ipcClient *client, const ipcMessage *rawMsg)
|
||||
static ipcCommandModule::MsgHandler handlers[] =
|
||||
{
|
||||
ipcCommandModule::OnPing,
|
||||
NULL, // ERROR
|
||||
ipcCommandModule::OnForward,
|
||||
ipcCommandModule::OnClientHello,
|
||||
NULL, // CLIENT_ID
|
||||
NULL, // CLIENT_INFO
|
||||
ipcCommandModule::OnClientAddName,
|
||||
ipcCommandModule::OnClientDelName,
|
||||
ipcCommandModule::OnClientAddTarget,
|
||||
ipcCommandModule::OnClientDelTarget,
|
||||
ipcCommandModule::OnQueryClientByName,
|
||||
ipcCommandModule::OnQueryClientInfo,
|
||||
ipcCommandModule::OnForward,
|
||||
ipcCommandModule::OnQueryClientByName
|
||||
};
|
||||
|
||||
int type = IPCM_GetMsgType(rawMsg);
|
||||
LOG(("IPCM_HandleMsg [type=%d]\n", type));
|
||||
int type = IPCM_GetType(rawMsg);
|
||||
LOG(("IPCM_HandleMsg [type=%x]\n", type));
|
||||
|
||||
if (type < IPCM_MSG_TYPE_UNKNOWN) {
|
||||
if (handlers[type]) {
|
||||
ipcCommandModule::MsgHandler handler = handlers[type];
|
||||
handler(client, rawMsg);
|
||||
}
|
||||
if (!(type & IPCM_MSG_CLASS_REQ)) {
|
||||
LOG(("not a request -- ignoring message\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
type &= ~IPCM_MSG_CLASS_REQ;
|
||||
type--;
|
||||
if (type < 0 || type >= (int) (sizeof(handlers)/sizeof(handlers[0]))) {
|
||||
LOG(("unknown request -- ignoring message\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
(handlers[type])(client, rawMsg);
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ IPC_ShutdownModuleReg()
|
||||
}
|
||||
|
||||
void
|
||||
IPC_NotifyClientUp(ipcClient *client)
|
||||
IPC_NotifyModulesClientUp(ipcClient *client)
|
||||
{
|
||||
for (int i = 0; i < ipcModuleCount; ++i) {
|
||||
ipcModuleRegEntry &entry = ipcModules[i];
|
||||
@ -221,7 +221,7 @@ IPC_NotifyClientUp(ipcClient *client)
|
||||
}
|
||||
|
||||
void
|
||||
IPC_NotifyClientDown(ipcClient *client)
|
||||
IPC_NotifyModulesClientDown(ipcClient *client)
|
||||
{
|
||||
for (int i = 0; i < ipcModuleCount; ++i) {
|
||||
ipcModuleRegEntry &entry = ipcModules[i];
|
||||
|
@ -64,7 +64,7 @@ ipcModuleMethods *IPC_GetModuleByTarget(const nsID &target);
|
||||
//
|
||||
// notifies all modules of client connect/disconnect
|
||||
//
|
||||
void IPC_NotifyClientUp(ipcClient *);
|
||||
void IPC_NotifyClientDown(ipcClient *);
|
||||
void IPC_NotifyModulesClientUp(ipcClient *);
|
||||
void IPC_NotifyModulesClientDown(ipcClient *);
|
||||
|
||||
#endif // !ipcModuleReg_h__
|
||||
|
@ -73,6 +73,8 @@ IPC_DispatchMsg(ipcClient *client, const ipcMessage *msg)
|
||||
// next message sent to the client.
|
||||
if (msg->TestFlag(IPC_MSG_FLAG_SYNC_QUERY)) {
|
||||
PR_ASSERT(client->GetExpectsSyncReply() == PR_FALSE);
|
||||
// XXX shouldn't we remember the TargetID as well, and only set the
|
||||
// SYNC_REPLY flag on the next message sent to the same TargetID?
|
||||
client->SetExpectsSyncReply(PR_TRUE);
|
||||
}
|
||||
|
||||
@ -112,6 +114,32 @@ IPC_SendMsg(ipcClient *client, ipcMessage *msg)
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
IPC_NotifyClientUp(ipcClient *client)
|
||||
{
|
||||
// notify modules before other clients
|
||||
IPC_NotifyModulesClientUp(client);
|
||||
|
||||
for (int i=0; i<ipcClientCount; ++i) {
|
||||
if (&ipcClients[i] != client)
|
||||
IPC_SendMsg(&ipcClients[i],
|
||||
new ipcmMessageClientState(client->ID(), IPCM_CLIENT_STATE_UP));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IPC_NotifyClientDown(ipcClient *client)
|
||||
{
|
||||
// notify modules before other clients
|
||||
IPC_NotifyModulesClientDown(client);
|
||||
|
||||
for (int i=0; i<ipcClientCount; ++i) {
|
||||
if (&ipcClients[i] != client)
|
||||
IPC_SendMsg(&ipcClients[i],
|
||||
new ipcmMessageClientState(client->ID(), IPCM_CLIENT_STATE_DOWN));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// IPC daemon methods
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -73,4 +73,10 @@ PRStatus IPC_DispatchMsg(ipcClientHandle client, const ipcMessage *msg);
|
||||
//
|
||||
PRStatus IPC_SendMsg(ipcClientHandle client, ipcMessage *msg);
|
||||
|
||||
//
|
||||
// dispatch notifications about client connects and disconnects
|
||||
//
|
||||
void IPC_NotifyClientUp(ipcClientHandle client);
|
||||
void IPC_NotifyClientDown(ipcClientHandle client);
|
||||
|
||||
#endif // !IPCD_H__
|
||||
|
@ -45,6 +45,10 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = ipcd
|
||||
|
||||
EXPORTS = \
|
||||
ipcLockCID.h \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
ipcILockService.idl \
|
||||
ipcILockNotify.idl \
|
||||
|
@ -74,18 +74,3 @@ interface ipcILockService : nsISupports
|
||||
*/
|
||||
void releaseLock(in string aLockName);
|
||||
};
|
||||
|
||||
%{C++
|
||||
// singleton implementing ipcILockService
|
||||
#define IPC_LOCKSERVICE_CLASSNAME \
|
||||
"ipcLockService"
|
||||
#define IPC_LOCKSERVICE_CONTRACTID \
|
||||
"@mozilla.org/ipc/lock-service;1"
|
||||
#define IPC_LOCKSERVICE_CID \
|
||||
{ /* d9e56bf8-e32e-4b6d-87f1-06d73b0ce7ca */ \
|
||||
0xd9e56bf8, \
|
||||
0xe32e, \
|
||||
0x4b6d, \
|
||||
{0x87, 0xf1, 0x06, 0xd7, 0x3b, 0x0c, 0xe7, 0xca} \
|
||||
}
|
||||
%}
|
||||
|
@ -79,7 +79,8 @@ struct ipcLockMsg
|
||||
PRUint8 *IPC_FlattenLockMsg(const ipcLockMsg *msg, PRUint32 *bufLen);
|
||||
|
||||
//
|
||||
// unflatten a lock message
|
||||
// unflatten a lock message. upon return, msg->key points into buf, so
|
||||
// buf must not be deallocated until after msg is no longer needed.
|
||||
//
|
||||
void IPC_UnflattenLockMsg(const PRUint8 *buf, PRUint32 bufLen, ipcLockMsg *msg);
|
||||
|
||||
|
@ -42,29 +42,23 @@
|
||||
#include "ipcLockProtocol.h"
|
||||
#include "ipcLog.h"
|
||||
|
||||
static NS_DEFINE_IID(kIPCServiceCID, IPC_SERVICE_CID);
|
||||
static const nsID kLockTargetID = IPC_LOCK_TARGETID;
|
||||
|
||||
ipcLockService::ipcLockService()
|
||||
{
|
||||
}
|
||||
|
||||
ipcLockService::~ipcLockService()
|
||||
{
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
ipcLockService::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mIPCService = do_GetService(kIPCServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = IPC_Init();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return mIPCService->SetMessageObserver(kLockTargetID, this);
|
||||
return IPC_DefineTarget(kLockTargetID, this);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ipcLockService, ipcILockService)
|
||||
NS_IMPL_ISUPPORTS2(ipcLockService, ipcILockService, ipcIMessageObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcLockService::AcquireLock(const char *lockName, ipcILockNotify *notify, PRBool waitIfBusy)
|
||||
@ -82,7 +76,7 @@ ipcLockService::AcquireLock(const char *lockName, ipcILockNotify *notify, PRBool
|
||||
if (!buf)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = mIPCService->SendMessage(0, kLockTargetID, buf, bufLen, (notify == nsnull));
|
||||
nsresult rv = IPC_SendMessage(0, kLockTargetID, buf, bufLen);
|
||||
free(buf);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG((" SendMessage failed [rv=%x]\n", rv));
|
||||
@ -92,9 +86,16 @@ ipcLockService::AcquireLock(const char *lockName, ipcILockNotify *notify, PRBool
|
||||
if (notify) {
|
||||
nsCStringKey hashKey(lockName);
|
||||
mPendingTable.Put(&hashKey, notify);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
// block the calling thread until we get a response from the daemon
|
||||
|
||||
mSyncLockName = lockName;
|
||||
rv = IPC_WaitMessage(0, kLockTargetID, nsnull, PR_INTERVAL_NO_TIMEOUT);
|
||||
mSyncLockName = nsnull;
|
||||
|
||||
return NS_FAILED(rv) ? rv : mSyncLockStatus;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -112,7 +113,7 @@ ipcLockService::ReleaseLock(const char *lockName)
|
||||
if (!buf)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = mIPCService->SendMessage(0, kLockTargetID, buf, bufLen, PR_FALSE);
|
||||
nsresult rv = IPC_SendMessage(0, kLockTargetID, buf, bufLen);
|
||||
free(buf);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -123,12 +124,13 @@ ipcLockService::ReleaseLock(const char *lockName)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ipcLockService::OnMessageAvailable(const nsID &target, const PRUint8 *data, PRUint32 dataLen)
|
||||
ipcLockService::OnMessageAvailable(PRUint32 unused, const nsID &target,
|
||||
const PRUint8 *data, PRUint32 dataLen)
|
||||
{
|
||||
ipcLockMsg msg;
|
||||
IPC_UnflattenLockMsg(data, dataLen, &msg);
|
||||
|
||||
LOG(("ipcLockService::OnMessageAvailable [lock=%s opcode=%u]\n", msg.key, msg.opcode));
|
||||
LOG(("ipcLockService::OnMessageAvailable [lock=%s opcode=%u sync-lock=%s]\n", msg.key, msg.opcode, mSyncLockName));
|
||||
|
||||
nsresult status;
|
||||
if (msg.opcode == IPC_LOCK_OP_STATUS_ACQUIRED)
|
||||
@ -136,6 +138,16 @@ ipcLockService::OnMessageAvailable(const nsID &target, const PRUint8 *data, PRUi
|
||||
else
|
||||
status = NS_ERROR_FAILURE;
|
||||
|
||||
// handle synchronous waiting case first
|
||||
if (mSyncLockName) {
|
||||
if (strcmp(mSyncLockName, msg.key) == 0) {
|
||||
mSyncLockStatus = status;
|
||||
return NS_OK;
|
||||
}
|
||||
return IPC_WAIT_NEXT_MESSAGE;
|
||||
}
|
||||
|
||||
// otherwise, this is an asynchronous notification
|
||||
NotifyComplete(msg.key, status);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -39,9 +39,8 @@
|
||||
#define ipcLockService_h__
|
||||
|
||||
#include "ipcILockService.h"
|
||||
#include "ipcIService.h"
|
||||
#include "ipcIMessageObserver.h"
|
||||
#include "ipcList.h"
|
||||
#include "ipcdclient.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
@ -53,18 +52,20 @@ public:
|
||||
NS_DECL_IPCILOCKSERVICE
|
||||
NS_DECL_IPCIMESSAGEOBSERVER
|
||||
|
||||
ipcLockService();
|
||||
virtual ~ipcLockService();
|
||||
|
||||
nsresult Init();
|
||||
ipcLockService() : mSyncLockName(nsnull) {}
|
||||
~ipcLockService() { IPC_Shutdown(); }
|
||||
NS_HIDDEN_(nsresult) Init();
|
||||
|
||||
private:
|
||||
void NotifyComplete(const char *lockName, nsresult status);
|
||||
|
||||
nsCOMPtr<ipcIService> mIPCService;
|
||||
NS_HIDDEN_(void) NotifyComplete(const char *lockName, nsresult status);
|
||||
|
||||
// map from lockname to locknotify for pending notifications
|
||||
nsSupportsHashtable mPendingTable;
|
||||
nsSupportsHashtable mPendingTable;
|
||||
|
||||
// if non-null, then this is the name of the lock we are trying to
|
||||
// synchronously acquire.
|
||||
const char *mSyncLockName;
|
||||
nsresult mSyncLockStatus;
|
||||
};
|
||||
|
||||
#endif // !ipcLockService_h__
|
||||
|
@ -119,66 +119,76 @@ ipcLockModule_AcquireLock(PRUint32 cid, PRUint8 flags, const char *key)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipcLockModule_ReleaseLock(PRUint32 cid, const char *key)
|
||||
static PRBool
|
||||
ipcLockModule_ReleaseLockHelper(PRUint32 cid, const char *key, ipcLockContext *ctx)
|
||||
{
|
||||
printf("$$$ releasing lock [key=%s]\n", key);
|
||||
|
||||
PRBool removeEntry = PR_FALSE;
|
||||
|
||||
//
|
||||
// lock is already acquired _or_ maybe client is on the pending list.
|
||||
//
|
||||
if (ctx->mOwnerID == cid) {
|
||||
if (ctx->mNextPending) {
|
||||
//
|
||||
// remove this element from the list. since this is the
|
||||
// first element in the list, instead of removing it we
|
||||
// shift the data from the next context into this one and
|
||||
// delete the next context.
|
||||
//
|
||||
ipcLockContext *next = ctx->mNextPending;
|
||||
ctx->mOwnerID = next->mOwnerID;
|
||||
ctx->mNextPending = next->mNextPending;
|
||||
delete next;
|
||||
//
|
||||
// notify client that it now owns the lock
|
||||
//
|
||||
ipcLockModule_Send(ctx->mOwnerID, key, IPC_LOCK_OP_STATUS_ACQUIRED);
|
||||
}
|
||||
else {
|
||||
delete ctx;
|
||||
removeEntry = PR_TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ipcLockContext *prev;
|
||||
for (;;) {
|
||||
prev = ctx;
|
||||
ctx = ctx->mNextPending;
|
||||
if (!ctx)
|
||||
break;
|
||||
if (ctx->mOwnerID == cid) {
|
||||
// remove ctx from list
|
||||
prev->mNextPending = ctx->mNextPending;
|
||||
delete ctx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return removeEntry;
|
||||
}
|
||||
|
||||
static void
|
||||
ipcLockModule_ReleaseLock(PRUint32 cid, const char *key)
|
||||
{
|
||||
if (!gLockTable)
|
||||
return;
|
||||
|
||||
ipcLockContext *ctx;
|
||||
|
||||
ctx = (ipcLockContext *) PL_HashTableLookup(gLockTable, key);
|
||||
if (ctx) {
|
||||
//
|
||||
// lock is already acquired _or_ maybe client is on the pending list.
|
||||
//
|
||||
if (ctx->mOwnerID == cid) {
|
||||
if (ctx->mNextPending) {
|
||||
//
|
||||
// remove this element from the list. since this is the
|
||||
// first element in the list, instead of removing it we
|
||||
// shift the data from the next context into this one and
|
||||
// delete the next context.
|
||||
//
|
||||
ipcLockContext *next = ctx->mNextPending;
|
||||
ctx->mOwnerID = next->mOwnerID;
|
||||
ctx->mNextPending = next->mNextPending;
|
||||
delete next;
|
||||
//
|
||||
// notify client that it now owns the lock
|
||||
//
|
||||
ipcLockModule_Send(ctx->mOwnerID, key, IPC_LOCK_OP_STATUS_ACQUIRED);
|
||||
}
|
||||
else {
|
||||
delete ctx;
|
||||
PL_HashTableRemove(gLockTable, key);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ipcLockContext *prev;
|
||||
for (;;) {
|
||||
prev = ctx;
|
||||
ctx = ctx->mNextPending;
|
||||
if (!ctx)
|
||||
break;
|
||||
if (ctx->mOwnerID == cid) {
|
||||
// remove ctx from list
|
||||
prev->mNextPending = ctx->mNextPending;
|
||||
delete ctx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ctx && ipcLockModule_ReleaseLockHelper(cid, key, ctx))
|
||||
PL_HashTableRemove(gLockTable, key);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
ipcLockModule_ReleaseByCID(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
PRUint32 cid = *(PRUint32 *) arg;
|
||||
ipcLockModule_ReleaseLock(cid, (const char *) he->key);
|
||||
ipcLockModule_ReleaseLockHelper(cid, (const char *) he->key,
|
||||
(ipcLockContext *) he->value);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,8 @@ tmTransactionService::~tmTransactionService() {
|
||||
if (qmap)
|
||||
delete qmap;
|
||||
}
|
||||
|
||||
IPC_Shutdown();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -112,12 +114,15 @@ NS_IMPL_ISUPPORTS2(tmTransactionService,
|
||||
NS_IMETHODIMP
|
||||
tmTransactionService::Init(const nsACString & aNamespace) {
|
||||
|
||||
// register with the IPC service
|
||||
ipcService = do_GetService("@mozilla.org/ipc/service;1");
|
||||
if (!ipcService)
|
||||
return NS_ERROR_FAILURE;
|
||||
if(NS_FAILED(ipcService->SetMessageObserver(kTransModuleID, this)))
|
||||
return NS_ERROR_FAILURE;
|
||||
nsresult rv;
|
||||
|
||||
rv = IPC_Init();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = IPC_DefineTarget(kTransModuleID, this);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// get the lock service
|
||||
lockService = do_GetService("@mozilla.org/ipc/lock-service;1");
|
||||
@ -185,6 +190,7 @@ tmTransactionService::Attach(const nsACString & aDomainName,
|
||||
// acquire a lock if neccessary
|
||||
if (aLockingCall)
|
||||
lockService->AcquireLock(joinedQueueName, nsnull, PR_TRUE);
|
||||
// XXX need to handle lock failures
|
||||
|
||||
if (NS_SUCCEEDED(trans.Init(0, // no IPC client
|
||||
TM_NO_ID, // qID gets returned to us
|
||||
@ -269,7 +275,8 @@ tmTransactionService::PostTransaction(const nsACString & aDomainName,
|
||||
// ipcIMessageObserver
|
||||
|
||||
NS_IMETHODIMP
|
||||
tmTransactionService::OnMessageAvailable(const nsID & aTarget,
|
||||
tmTransactionService::OnMessageAvailable(const PRUint32 aSenderID,
|
||||
const nsID & aTarget,
|
||||
const PRUint8 *aData,
|
||||
PRUint32 aDataLength) {
|
||||
|
||||
@ -319,13 +326,12 @@ void
|
||||
tmTransactionService::SendMessage(tmTransaction *aTrans, PRBool aSync) {
|
||||
|
||||
NS_ASSERTION(aTrans, "tmTransactionService::SendMessage called with null transaction");
|
||||
NS_ASSERTION(ipcService, "Failed to get the ipcService");
|
||||
|
||||
ipcService->SendMessage(0,
|
||||
kTransModuleID,
|
||||
aTrans->GetRawMessage(),
|
||||
aTrans->GetRawMessageLength(),
|
||||
aSync);
|
||||
IPC_SendMessage(0, kTransModuleID,
|
||||
aTrans->GetRawMessage(),
|
||||
aTrans->GetRawMessageLength());
|
||||
if (aSync)
|
||||
IPC_WaitMessage(0, kTransModuleID, nsnull, PR_INTERVAL_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -38,7 +38,7 @@
|
||||
#ifndef _tmTransactionService_H_
|
||||
#define _tmTransactionService_H_
|
||||
|
||||
#include "ipcIService.h"
|
||||
#include "ipcdclient.h"
|
||||
#include "ipcILockService.h"
|
||||
#include "ipcIMessageObserver.h"
|
||||
#include "ipcITransactionService.h"
|
||||
@ -187,7 +187,6 @@ protected:
|
||||
tmVector mQueueMaps; // queue - name - domain mappings
|
||||
tmVector mWaitingMessages; // messages sent before ATTACH_REPLY
|
||||
|
||||
nsCOMPtr<ipcIService> ipcService; // cache the ipc service
|
||||
nsCOMPtr<ipcILockService> lockService; // cache the lock service
|
||||
|
||||
private:
|
||||
|
@ -64,7 +64,7 @@ inline void IPC_GetClientWindowName(PRUint32 pid, char *buf)
|
||||
}
|
||||
|
||||
#else
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
//
|
||||
// use UNIX domain socket
|
||||
//
|
||||
@ -79,7 +79,7 @@ inline void IPC_GetClientWindowName(PRUint32 pid, char *buf)
|
||||
#define IPC_MODULES_DIR "ipc/modules"
|
||||
#endif
|
||||
|
||||
void IPC_GetDefaultSocketPath(char *buf, PRUint32 bufLen);
|
||||
NS_HIDDEN_(void) IPC_GetDefaultSocketPath(char *buf, PRUint32 bufLen);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -95,8 +95,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static ipcIDNode *FindNode (ipcIDNode *head, const nsID &id);
|
||||
static ipcIDNode *FindNodeBefore(ipcIDNode *head, const nsID &id);
|
||||
static NS_HIDDEN_(ipcIDNode *) FindNode (ipcIDNode *head, const nsID &id);
|
||||
static NS_HIDDEN_(ipcIDNode *) FindNodeBefore(ipcIDNode *head, const nsID &id);
|
||||
};
|
||||
|
||||
#endif // !ipcIDList_h__
|
||||
|
@ -161,6 +161,17 @@ public:
|
||||
|
||||
PRBool IsEmpty() const { return mHead == NULL; }
|
||||
|
||||
//
|
||||
// moves contents of list to another list
|
||||
//
|
||||
void MoveTo(ipcList<T> &other)
|
||||
{
|
||||
other.mHead = mHead;
|
||||
other.mTail = mTail;
|
||||
mHead = NULL;
|
||||
mTail = NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
void AdvanceHead()
|
||||
{
|
||||
|
@ -38,6 +38,7 @@
|
||||
#ifndef ipcLog_h__
|
||||
#define ipcLog_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "prtypes.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -47,8 +48,8 @@
|
||||
#ifdef IPC_LOGGING
|
||||
|
||||
extern PRBool ipcLogEnabled;
|
||||
extern void IPC_InitLog(const char *prefix);
|
||||
extern void IPC_Log(const char *fmt, ...);
|
||||
extern NS_HIDDEN_(void) IPC_InitLog(const char *prefix);
|
||||
extern NS_HIDDEN_(void) IPC_Log(const char *fmt, ...);
|
||||
|
||||
#define IPC_LOG(_args) \
|
||||
PR_BEGIN_MACRO \
|
||||
|
@ -88,26 +88,28 @@ class ipcMessage
|
||||
public:
|
||||
ipcMessage()
|
||||
: mNext(NULL)
|
||||
, mMetaData(0)
|
||||
, mMsgHdr(NULL)
|
||||
, mMsgOffset(0)
|
||||
, mMsgComplete(PR_FALSE)
|
||||
{ }
|
||||
ipcMessage(const nsID &target, const char *data, PRUint32 dataLen)
|
||||
: mNext(NULL)
|
||||
, mMetaData(0)
|
||||
, mMsgHdr(NULL)
|
||||
, mMsgOffset(0)
|
||||
{ Init(target, data, dataLen); }
|
||||
~ipcMessage();
|
||||
~ipcMessage() NS_HIDDEN;
|
||||
|
||||
//
|
||||
// reset message to uninitialized state
|
||||
//
|
||||
void Reset();
|
||||
NS_HIDDEN_(void) Reset();
|
||||
|
||||
//
|
||||
// create a copy of this message
|
||||
//
|
||||
ipcMessage *Clone() const;
|
||||
NS_HIDDEN_(ipcMessage *) Clone() const;
|
||||
|
||||
//
|
||||
// initialize message
|
||||
@ -117,7 +119,7 @@ public:
|
||||
// data - message data (may be null to leave data uninitialized)
|
||||
// dataLen - message data len
|
||||
//
|
||||
PRStatus Init(const nsID &target, const char *data, PRUint32 dataLen);
|
||||
NS_HIDDEN_(PRStatus) Init(const nsID &target, const char *data, PRUint32 dataLen);
|
||||
|
||||
//
|
||||
// copy data into the message's data section, starting from offset. this
|
||||
@ -128,7 +130,7 @@ public:
|
||||
// data - data to write
|
||||
// dataLen - number of bytes to write
|
||||
//
|
||||
PRStatus SetData(PRUint32 offset, const char *data, PRUint32 dataLen);
|
||||
NS_HIDDEN_(PRStatus) SetData(PRUint32 offset, const char *data, PRUint32 dataLen);
|
||||
|
||||
//
|
||||
// access message flags
|
||||
@ -161,32 +163,39 @@ public:
|
||||
// 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;
|
||||
NS_HIDDEN_(PRBool) Equals(const nsID &target, const char *data, PRUint32 dataLen) const;
|
||||
NS_HIDDEN_(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);
|
||||
NS_HIDDEN_(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);
|
||||
NS_HIDDEN_(PRStatus) ReadFrom(const char *buf,
|
||||
PRUint32 bufLen,
|
||||
PRUint32 *bytesRead,
|
||||
PRBool *complete);
|
||||
|
||||
//
|
||||
// a message can be added to a singly-linked list.
|
||||
//
|
||||
class ipcMessage *mNext;
|
||||
|
||||
//
|
||||
// meta data associated with this message object. the owner of the
|
||||
// ipcMessage object is free to use this field for any purpose. by
|
||||
// default, it is initialized to 0.
|
||||
//
|
||||
PRUint32 mMetaData;
|
||||
|
||||
private:
|
||||
ipcMessageHeader *mMsgHdr;
|
||||
|
||||
|
@ -43,16 +43,39 @@ ipcMessage_DWORD_STR::ipcMessage_DWORD_STR(const nsID &target,
|
||||
const char *second)
|
||||
{
|
||||
int sLen = strlen(second);
|
||||
Init(target, NULL, sizeof(first) + sLen + 1);
|
||||
SetData(0, (char *) &first, sizeof(first));
|
||||
SetData(sizeof(first), second, sLen + 1);
|
||||
Init(target, NULL, 4 + sLen + 1);
|
||||
SetData(0, (char *) &first, 4);
|
||||
SetData(4, second, sLen + 1);
|
||||
}
|
||||
|
||||
ipcMessage_DWORD_DWORD_STR::ipcMessage_DWORD_DWORD_STR(const nsID &target,
|
||||
PRUint32 first,
|
||||
PRUint32 second,
|
||||
const char *third)
|
||||
{
|
||||
int sLen = strlen(third);
|
||||
Init(target, NULL, 8 + sLen + 1);
|
||||
SetData(0, (char *) &first, 4);
|
||||
SetData(4, (char *) &second, 4);
|
||||
SetData(8, third, sLen + 1);
|
||||
}
|
||||
|
||||
ipcMessage_DWORD_ID::ipcMessage_DWORD_ID(const nsID &target,
|
||||
PRUint32 first,
|
||||
const nsID &second)
|
||||
{
|
||||
Init(target, NULL, sizeof(first) + sizeof(nsID));
|
||||
SetData(0, (char *) &first, sizeof(first));
|
||||
SetData(sizeof(first), (char *) &second, sizeof(nsID));
|
||||
Init(target, NULL, 4 + sizeof(nsID));
|
||||
SetData(0, (char *) &first, 4);
|
||||
SetData(4, (char *) &second, sizeof(nsID));
|
||||
}
|
||||
|
||||
ipcMessage_DWORD_DWORD_ID::ipcMessage_DWORD_DWORD_ID(const nsID &target,
|
||||
PRUint32 first,
|
||||
PRUint32 second,
|
||||
const nsID &third)
|
||||
{
|
||||
Init(target, NULL, 8 + sizeof(nsID));
|
||||
SetData(0, (char *) &first, 4);
|
||||
SetData(4, (char *) &second, 4);
|
||||
SetData(8, (char *) &third, sizeof(nsID));
|
||||
}
|
||||
|
@ -74,10 +74,65 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ipcMessage_DWORD_DWORD_DWORD : public ipcMessage
|
||||
{
|
||||
public:
|
||||
ipcMessage_DWORD_DWORD_DWORD(const nsID &target, PRUint32 first, PRUint32 second, PRUint32 third)
|
||||
{
|
||||
PRUint32 data[3] = { first, second, third };
|
||||
Init(target, (char *) data, sizeof(data));
|
||||
}
|
||||
|
||||
PRUint32 First() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[0];
|
||||
}
|
||||
|
||||
PRUint32 Second() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[1];
|
||||
}
|
||||
|
||||
PRUint32 Third() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[2];
|
||||
}
|
||||
};
|
||||
|
||||
class ipcMessage_DWORD_DWORD_DWORD_DWORD : public ipcMessage
|
||||
{
|
||||
public:
|
||||
ipcMessage_DWORD_DWORD_DWORD_DWORD(const nsID &target, PRUint32 first, PRUint32 second, PRUint32 third, PRUint32 fourth)
|
||||
{
|
||||
PRUint32 data[4] = { first, second, third, fourth };
|
||||
Init(target, (char *) data, sizeof(data));
|
||||
}
|
||||
|
||||
PRUint32 First() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[0];
|
||||
}
|
||||
|
||||
PRUint32 Second() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[1];
|
||||
}
|
||||
|
||||
PRUint32 Third() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[2];
|
||||
}
|
||||
|
||||
PRUint32 Fourth() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[3];
|
||||
}
|
||||
};
|
||||
|
||||
class ipcMessage_DWORD_STR : public ipcMessage
|
||||
{
|
||||
public:
|
||||
ipcMessage_DWORD_STR(const nsID &target, PRUint32 first, const char *second);
|
||||
ipcMessage_DWORD_STR(const nsID &target, PRUint32 first, const char *second) NS_HIDDEN;
|
||||
|
||||
PRUint32 First() const
|
||||
{
|
||||
@ -90,10 +145,31 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ipcMessage_DWORD_DWORD_STR : public ipcMessage
|
||||
{
|
||||
public:
|
||||
ipcMessage_DWORD_DWORD_STR(const nsID &target, PRUint32 first, PRUint32 second, const char *second) NS_HIDDEN;
|
||||
|
||||
PRUint32 First() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[0];
|
||||
}
|
||||
|
||||
PRUint32 Second() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[1];
|
||||
}
|
||||
|
||||
const char *Third() const
|
||||
{
|
||||
return Data() + 2 * sizeof(PRUint32);
|
||||
}
|
||||
};
|
||||
|
||||
class ipcMessage_DWORD_ID : public ipcMessage
|
||||
{
|
||||
public:
|
||||
ipcMessage_DWORD_ID(const nsID &target, PRUint32 first, const nsID &second);
|
||||
ipcMessage_DWORD_ID(const nsID &target, PRUint32 first, const nsID &second) NS_HIDDEN;
|
||||
|
||||
PRUint32 First() const
|
||||
{
|
||||
@ -106,4 +182,25 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ipcMessage_DWORD_DWORD_ID : public ipcMessage
|
||||
{
|
||||
public:
|
||||
ipcMessage_DWORD_DWORD_ID(const nsID &target, PRUint32 first, PRUint32 second, const nsID &third) NS_HIDDEN;
|
||||
|
||||
PRUint32 First() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[0];
|
||||
}
|
||||
|
||||
PRUint32 Second() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[1];
|
||||
}
|
||||
|
||||
const nsID &Third() const
|
||||
{
|
||||
return * (const nsID *) (Data() + 2 * sizeof(PRUint32));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !ipcMessagePrimitives_h__
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "plstr.h"
|
||||
#include "xpcom-config.h"
|
||||
#include "nscore.h"
|
||||
#include "ipcList.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -101,8 +101,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static ipcStringNode *FindNode (ipcStringNode *head, const char *str);
|
||||
static ipcStringNode *FindNodeBefore(ipcStringNode *head, const char *str);
|
||||
static NS_HIDDEN_(ipcStringNode *) FindNode (ipcStringNode *head, const char *str);
|
||||
static NS_HIDDEN_(ipcStringNode *) FindNodeBefore(ipcStringNode *head, const char *str);
|
||||
};
|
||||
|
||||
#endif // !ipcStringList_h__
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "ipcm.h"
|
||||
#include "prlog.h"
|
||||
#include "pratom.h"
|
||||
|
||||
const nsID IPCM_TARGET =
|
||||
{ /* 753ca8ff-c8c2-4601-b115-8c2944da1150 */
|
||||
@ -47,6 +47,15 @@ const nsID IPCM_TARGET =
|
||||
{0xb1, 0x15, 0x8c, 0x29, 0x44, 0xda, 0x11, 0x50}
|
||||
};
|
||||
|
||||
PRUint32
|
||||
IPCM_NewRequestIndex()
|
||||
{
|
||||
static PRInt32 sRequestIndex;
|
||||
return (PRUint32) PR_AtomicIncrement(&sRequestIndex);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
//
|
||||
// MSG_TYPE values
|
||||
//
|
||||
@ -62,6 +71,7 @@ const PRUint32 ipcmMessageClientDelTarget::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_DEL_T
|
||||
const PRUint32 ipcmMessageQueryClientByName::MSG_TYPE = IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME;
|
||||
const PRUint32 ipcmMessageQueryClientInfo::MSG_TYPE = IPCM_MSG_TYPE_QUERY_CLIENT_INFO;
|
||||
const PRUint32 ipcmMessageForward::MSG_TYPE = IPCM_MSG_TYPE_FORWARD;
|
||||
const PRUint32 ipcmMessageClientStatus::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_STATUS;
|
||||
|
||||
//
|
||||
// CLIENT_INFO message
|
||||
@ -71,6 +81,8 @@ const PRUint32 ipcmMessageForward::MSG_TYPE = IPCM_MSG_TYPE_FORWARD;
|
||||
// +--------------------+--------------------+
|
||||
// | DWORD : clientID |
|
||||
// +--------------------+--------------------+
|
||||
// | DWORD : requestIndex |
|
||||
// +--------------------+--------------------+
|
||||
// | WORD : nameStart | WORD : nameCount |
|
||||
// +--------------------+--------------------+
|
||||
// | WORD : targetStart | WORD : targetCount |
|
||||
@ -95,18 +107,20 @@ struct ipcmClientInfoHeader
|
||||
{
|
||||
PRUint32 mType;
|
||||
PRUint32 mID;
|
||||
PRUint32 mRequestIndex;
|
||||
PRUint16 mNameStart;
|
||||
PRUint16 mNameCount;
|
||||
PRUint16 mTargetStart;
|
||||
PRUint16 mTargetCount;
|
||||
};
|
||||
|
||||
ipcmMessageClientInfo::ipcmMessageClientInfo(PRUint32 cID, const char *names[], const nsID *targets[])
|
||||
ipcmMessageClientInfo::ipcmMessageClientInfo(PRUint32 cID, PRUint32 rIdx, const char *names[], const nsID *targets[])
|
||||
{
|
||||
ipcmClientInfoHeader hdr = {0};
|
||||
|
||||
hdr.mType = MSG_TYPE;
|
||||
hdr.mID = cID;
|
||||
hdr.mRequestIndex = rIdx;
|
||||
hdr.mNameStart = sizeof(hdr);
|
||||
|
||||
PRUint32 i, namesLen = 0;
|
||||
@ -163,6 +177,13 @@ ipcmMessageClientInfo::ClientID() const
|
||||
return hdr->mID;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
ipcmMessageClientInfo::RequestIndex() const
|
||||
{
|
||||
ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
|
||||
return hdr->mRequestIndex;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
ipcmMessageClientInfo::NameCount() const
|
||||
{
|
||||
@ -203,6 +224,7 @@ ipcmMessageClientInfo::NextTarget(const nsID *target) const
|
||||
target = NULL;
|
||||
return target;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// FORWARD message
|
||||
@ -218,20 +240,24 @@ ipcmMessageClientInfo::NextTarget(const nsID *target) const
|
||||
// +-------------------------+
|
||||
//
|
||||
|
||||
ipcmMessageForward::ipcmMessageForward(PRUint32 cID,
|
||||
ipcmMessageForward::ipcmMessageForward(PRUint32 type,
|
||||
PRUint32 cID,
|
||||
const nsID &target,
|
||||
const char *data,
|
||||
PRUint32 dataLen)
|
||||
{
|
||||
int len = sizeof(MSG_TYPE) + // MSG_TYPE
|
||||
sizeof(cID) + // cID
|
||||
IPC_MSG_HEADER_SIZE + // innerMsgHeader
|
||||
dataLen; // innerMsgData
|
||||
int len = sizeof(ipcmMessageHeader) + // IPCM header
|
||||
sizeof(cID) + // cID
|
||||
IPC_MSG_HEADER_SIZE + // innerMsgHeader
|
||||
dataLen; // innerMsgData
|
||||
|
||||
Init(IPCM_TARGET, NULL, len);
|
||||
|
||||
SetData(0, (char *) &MSG_TYPE, sizeof(MSG_TYPE));
|
||||
SetData(4, (char *) &cID, sizeof(cID));
|
||||
ipcmMessageHeader ipcmHdr =
|
||||
{ type, IPCM_NewRequestIndex() };
|
||||
|
||||
SetData(0, (char *) &ipcmHdr, sizeof(ipcmHdr));
|
||||
SetData(sizeof(ipcmHdr), (char *) &cID, sizeof(cID));
|
||||
|
||||
ipcMessageHeader hdr;
|
||||
hdr.mLen = IPC_MSG_HEADER_SIZE + dataLen;
|
||||
@ -239,7 +265,7 @@ ipcmMessageForward::ipcmMessageForward(PRUint32 cID,
|
||||
hdr.mFlags = 0;
|
||||
hdr.mTarget = target;
|
||||
|
||||
SetData(8, (char *) &hdr, IPC_MSG_HEADER_SIZE);
|
||||
SetData(sizeof(ipcmHdr) + sizeof(cID), (char *) &hdr, IPC_MSG_HEADER_SIZE);
|
||||
if (data)
|
||||
SetInnerData(0, data, dataLen);
|
||||
}
|
||||
@ -247,31 +273,31 @@ ipcmMessageForward::ipcmMessageForward(PRUint32 cID,
|
||||
void
|
||||
ipcmMessageForward::SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen)
|
||||
{
|
||||
SetData(8 + IPC_MSG_HEADER_SIZE + offset, data, dataLen);
|
||||
SetData(sizeof(ipcmMessageHeader) + 4 + IPC_MSG_HEADER_SIZE + offset, data, dataLen);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
ipcmMessageForward::DestClientID() const
|
||||
ipcmMessageForward::ClientID() const
|
||||
{
|
||||
return ((PRUint32 *) Data())[1];
|
||||
return ((PRUint32 *) Data())[2];
|
||||
}
|
||||
|
||||
const nsID &
|
||||
ipcmMessageForward::InnerTarget() const
|
||||
{
|
||||
ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 8);
|
||||
ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 12);
|
||||
return hdr->mTarget;
|
||||
}
|
||||
|
||||
const char *
|
||||
ipcmMessageForward::InnerData() const
|
||||
{
|
||||
return Data() + 8 + IPC_MSG_HEADER_SIZE;
|
||||
return Data() + 12 + IPC_MSG_HEADER_SIZE;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
ipcmMessageForward::InnerDataLen() const
|
||||
{
|
||||
ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 8);
|
||||
ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 12);
|
||||
return hdr->mLen - IPC_MSG_HEADER_SIZE;
|
||||
}
|
||||
|
@ -41,47 +41,291 @@
|
||||
#include "ipcMessage.h"
|
||||
#include "ipcMessagePrimitives.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// IPCM (IPC Manager) protocol support
|
||||
//
|
||||
|
||||
// The IPCM message target identifier:
|
||||
extern const nsID IPCM_TARGET;
|
||||
|
||||
enum {
|
||||
IPCM_MSG_TYPE_PING,
|
||||
IPCM_MSG_TYPE_ERROR,
|
||||
IPCM_MSG_TYPE_CLIENT_HELLO,
|
||||
IPCM_MSG_TYPE_CLIENT_ID,
|
||||
IPCM_MSG_TYPE_CLIENT_INFO,
|
||||
IPCM_MSG_TYPE_CLIENT_ADD_NAME,
|
||||
IPCM_MSG_TYPE_CLIENT_DEL_NAME,
|
||||
IPCM_MSG_TYPE_CLIENT_ADD_TARGET,
|
||||
IPCM_MSG_TYPE_CLIENT_DEL_TARGET,
|
||||
IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME,
|
||||
IPCM_MSG_TYPE_QUERY_CLIENT_INFO,
|
||||
// IPCM_MSG_TYPE_QUERY_MODULE, // check if module exists
|
||||
IPCM_MSG_TYPE_FORWARD,
|
||||
IPCM_MSG_TYPE_UNKNOWN // unknown message type
|
||||
//
|
||||
// Every IPCM message has the following structure:
|
||||
//
|
||||
// +-----------------------------------------+
|
||||
// | (ipc message header) |
|
||||
// +-----------------------------------------+
|
||||
// | DWORD : type |
|
||||
// +-----------------------------------------+
|
||||
// | DWORD : requestIndex |
|
||||
// +-----------------------------------------+
|
||||
// . .
|
||||
// . (payload) .
|
||||
// . .
|
||||
// +-----------------------------------------+
|
||||
//
|
||||
// where |type| is an integer uniquely identifying the message. the type is
|
||||
// composed of a message class identifier and a message number. there are 3
|
||||
// message classes:
|
||||
//
|
||||
// ACK - acknowledging a request
|
||||
// REQ - making a request
|
||||
// PSH - providing unrequested, "pushed" information
|
||||
//
|
||||
// The requestIndex field is initialized when a request is made. An
|
||||
// acknowledgement's requestIndex is equal to that of its corresponding
|
||||
// request message. This enables the requesting side of the message exchange
|
||||
// to match acknowledgements to requests. The requestIndex field is ignored
|
||||
// for PSH messages.
|
||||
//
|
||||
|
||||
// The IPCM message class is stored in the most significant byte.
|
||||
#define IPCM_MSG_CLASS_REQ (1 << 24)
|
||||
#define IPCM_MSG_CLASS_ACK (2 << 24)
|
||||
#define IPCM_MSG_CLASS_PSH (4 << 24)
|
||||
|
||||
// Requests
|
||||
#define IPCM_MSG_REQ_PING (IPCM_MSG_CLASS_REQ | 1)
|
||||
#define IPCM_MSG_REQ_FORWARD (IPCM_MSG_CLASS_REQ | 2)
|
||||
#define IPCM_MSG_REQ_CLIENT_HELLO (IPCM_MSG_CLASS_REQ | 3)
|
||||
#define IPCM_MSG_REQ_CLIENT_ADD_NAME (IPCM_MSG_CLASS_REQ | 4)
|
||||
#define IPCM_MSG_REQ_CLIENT_DEL_NAME (IPCM_MSG_CLASS_REQ | 5)
|
||||
#define IPCM_MSG_REQ_CLIENT_ADD_TARGET (IPCM_MSG_CLASS_REQ | 6)
|
||||
#define IPCM_MSG_REQ_CLIENT_DEL_TARGET (IPCM_MSG_CLASS_REQ | 7)
|
||||
#define IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME (IPCM_MSG_CLASS_REQ | 8)
|
||||
#define IPCM_MSG_REQ_QUERY_CLIENT_NAMES (IPCM_MSG_CLASS_REQ | 9) // TODO
|
||||
#define IPCM_MSG_REQ_QUERY_CLIENT_TARGETS (IPCM_MSG_CLASS_REQ | 10) // TODO
|
||||
|
||||
// Acknowledgements
|
||||
#define IPCM_MSG_ACK_RESULT (IPCM_MSG_CLASS_ACK | 1)
|
||||
#define IPCM_MSG_ACK_CLIENT_ID (IPCM_MSG_CLASS_ACK | 2)
|
||||
#define IPCM_MSG_ACK_CLIENT_NAMES (IPCM_MSG_CLASS_ACK | 3) // TODO
|
||||
#define IPCM_MSG_ACK_CLIENT_TARGETS (IPCM_MSG_CLASS_ACK | 4) // TODO
|
||||
|
||||
// Push messages
|
||||
#define IPCM_MSG_PSH_CLIENT_STATE (IPCM_MSG_CLASS_PSH | 1)
|
||||
#define IPCM_MSG_PSH_FORWARD (IPCM_MSG_CLASS_PSH | 2)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// IPCM header
|
||||
//
|
||||
struct ipcmMessageHeader
|
||||
{
|
||||
PRUint32 mType;
|
||||
PRUint32 mRequestIndex;
|
||||
};
|
||||
|
||||
//
|
||||
// returns IPCM message type.
|
||||
//
|
||||
static inline int
|
||||
IPCM_GetMsgType(const ipcMessage *msg)
|
||||
IPCM_GetType(const ipcMessage *msg)
|
||||
{
|
||||
return ((const ipcMessage_DWORD *) msg)->First();
|
||||
return ((const ipcmMessageHeader *) msg->Data())->mType;
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
// return IPCM message request index.
|
||||
//
|
||||
static inline PRUint32
|
||||
IPCM_GetRequestIndex(const ipcMessage *msg)
|
||||
{
|
||||
return ((const ipcmMessageHeader *) msg->Data())->mRequestIndex;
|
||||
}
|
||||
|
||||
//
|
||||
// return a request index that is unique to this process.
|
||||
//
|
||||
NS_HIDDEN_(PRUint32)
|
||||
IPCM_NewRequestIndex();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// The IPCM protocol is detailed below:
|
||||
//
|
||||
|
||||
// REQUESTS
|
||||
|
||||
//
|
||||
// req: IPCM_MSG_REQ_PING
|
||||
// ack: IPCM_MSG_ACK_RESULT
|
||||
//
|
||||
// A PING can be sent from either a client to the daemon, or from the daemon
|
||||
// to a client. The expected acknowledgement is a RESULT message with a status
|
||||
// code of 0.
|
||||
//
|
||||
// This request message has no payload.
|
||||
//
|
||||
|
||||
//
|
||||
// req: IPCM_MSG_REQ_FORWARD
|
||||
// ack: IPCM_MSG_ACK_RESULT
|
||||
//
|
||||
// A FORWARD is sent when a client wishes to send a message to another client.
|
||||
// The payload of this message is another message that should be forwarded by
|
||||
// the daemon's IPCM to the specified client. The expected acknowledgment is
|
||||
// a RESULT message with a status code indicating success or failure.
|
||||
//
|
||||
// When the daemon receives a FORWARD message, it creates a PSH_FORWARD message
|
||||
// and sends that on to the destination client.
|
||||
//
|
||||
// This request message has as its payload:
|
||||
//
|
||||
// +-----------------------------------------+
|
||||
// | DWORD : clientID |
|
||||
// +-----------------------------------------+
|
||||
// | (innerMsgHeader) |
|
||||
// +-----------------------------------------+
|
||||
// | (innerMsgData) |
|
||||
// +-----------------------------------------+
|
||||
//
|
||||
|
||||
//
|
||||
// req: IPCM_MSG_REQ_CLIENT_HELLO
|
||||
// ack: IPCM_MSG_REQ_CLIENT_ID <or> IPCM_MSG_REQ_RESULT
|
||||
//
|
||||
// A CLIENT_HELLO is sent when a client connects to the IPC daemon. The
|
||||
// expected acknowledgement is a CLIENT_ID message informing the new client of
|
||||
// its ClientID. If for some reason the IPC daemon cannot accept the new
|
||||
// client, it returns a RESULT message with a failure status code.
|
||||
//
|
||||
// This request message has no payload.
|
||||
//
|
||||
|
||||
//
|
||||
// req: IPCM_MSG_REQ_CLIENT_ADD_NAME
|
||||
// ack: IPCM_MSG_ACK_RESULT
|
||||
//
|
||||
// A CLIENT_ADD_NAME is sent when a client wishes to register an additional
|
||||
// name for itself. The expected acknowledgement is a RESULT message with a
|
||||
// status code indicating success or failure.
|
||||
//
|
||||
// This request message has as its payload a null-terminated ASCII character
|
||||
// string indicating the name of the client.
|
||||
//
|
||||
|
||||
//
|
||||
// req: IPCM_MSG_REQ_CLIENT_DEL_NAME
|
||||
// ack: IPCM_MSG_ACK_RESULT
|
||||
//
|
||||
// A CLIENT_DEL_NAME is sent when a client wishes to unregister a name that it
|
||||
// has registered. The expected acknowledgement is a RESULT message with a
|
||||
// status code indicating success or failure.
|
||||
//
|
||||
// This request message has as its payload a null-terminated ASCII character
|
||||
// string indicating the name of the client.
|
||||
//
|
||||
|
||||
//
|
||||
// req: IPCM_MSG_REQ_CLIENT_ADD_TARGET
|
||||
// ack: IPCM_MSG_ACK_RESULT
|
||||
//
|
||||
// A CLIENT_ADD_TARGET is sent when a client wishes to register an additional
|
||||
// target that it supports. The expected acknowledgement is a RESULT message
|
||||
// with a status code indicating success or failure.
|
||||
//
|
||||
// This request message has as its payload a 128-bit UUID indicating the
|
||||
// target to add.
|
||||
//
|
||||
|
||||
//
|
||||
// req: IPCM_MSG_REQ_CLIENT_DEL_TARGET
|
||||
// ack: IPCM_MSG_ACK_RESULT
|
||||
//
|
||||
// A CLIENT_DEL_TARGET is sent when a client wishes to unregister a target
|
||||
// that it has registered. The expected acknowledgement is a RESULT message
|
||||
// with a status code indicating success or failure.
|
||||
//
|
||||
// This request message has as its payload a 128-bit UUID indicating the
|
||||
// target to remove.
|
||||
//
|
||||
|
||||
//
|
||||
// req: IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME
|
||||
// ack: IPCM_MSG_ACK_CLIENT_ID <or> IPCM_MSG_ACK_RESULT
|
||||
//
|
||||
// A QUERY_CLIENT_BY_NAME may be sent by a client to discover the client that
|
||||
// is known by a common name. If more than one client matches the name, then
|
||||
// only the ID of the more recently registered client is returned. The
|
||||
// expected acknowledgement is a CLIENT_ID message carrying the ID of the
|
||||
// corresponding client. If no client matches the given name or if some error
|
||||
// occurs, then a RESULT message with a failure status code is returned.
|
||||
//
|
||||
// This request message has as its payload a null-terminated ASCII character
|
||||
// string indicating the client name to query.
|
||||
//
|
||||
|
||||
// ACKNOWLEDGEMENTS
|
||||
|
||||
//
|
||||
// ack: IPCM_MSG_ACK_RESULT
|
||||
//
|
||||
// This acknowledgement is returned to indicate a success or failure status.
|
||||
//
|
||||
// The payload consists of a single DWORD value.
|
||||
//
|
||||
// Possible status codes are listed below (negative values indicate failure
|
||||
// codes):
|
||||
//
|
||||
#define IPCM_OK 0 // success: generic
|
||||
#define IPCM_ERROR_GENERIC -1 // failure: generic
|
||||
#define IPCM_ERROR_NO_CLIENT -2 // failure: client does not exist
|
||||
|
||||
//
|
||||
// ack: IPCM_MSG_ACK_CLIENT_ID
|
||||
//
|
||||
// This acknowledgement is returned to specify a client ID.
|
||||
//
|
||||
// The payload consists of a single DWORD value.
|
||||
//
|
||||
|
||||
// PUSH MESSAGES
|
||||
|
||||
//
|
||||
// psh: ICPM_MSG_PSH_CLIENT_STATE
|
||||
//
|
||||
// This message is sent to clients to indicate the status of other clients.
|
||||
//
|
||||
// The payload consists of:
|
||||
//
|
||||
// +-----------------------------------------+
|
||||
// | DWORD : clientID |
|
||||
// +-----------------------------------------+
|
||||
// | DWORD : clientState |
|
||||
// +-----------------------------------------+
|
||||
//
|
||||
// where, clientState is one of the following values indicating whether the
|
||||
// client has recently connected (up) or disconnected (down):
|
||||
//
|
||||
#define IPCM_CLIENT_STATE_UP 1
|
||||
#define IPCM_CLIENT_STATE_DOWN 2
|
||||
|
||||
//
|
||||
// psh: IPCM_MSG_PSH_FORWARD
|
||||
//
|
||||
// This message is sent by the daemon to a client on behalf of another client.
|
||||
// The recipient is expected to unpack the contained message and process it.
|
||||
//
|
||||
// The payload of this message matches the payload of IPCM_MSG_REQ_FORWARD,
|
||||
// with the exception that the clientID field is set to the clientID of the
|
||||
// sender of the IPCM_MSG_REQ_FORWARD message.
|
||||
//
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// NOTE: This file declares some helper classes that simplify constructing
|
||||
// and parsing IPCM messages. Each class subclasses ipcMessage, but
|
||||
// adds no additional member variables. |operator new| should be used
|
||||
// to allocate one of the IPCM helper classes, e.g.:
|
||||
//
|
||||
// ipcMessage *msg = new ipcmMessageClientHello("foo");
|
||||
//
|
||||
// given an arbitrary ipcMessage, it can be parsed using logic similar
|
||||
// Given an arbitrary ipcMessage, it can be parsed using logic similar
|
||||
// to the following:
|
||||
//
|
||||
// void func(const ipcMessage *unknown)
|
||||
@ -94,229 +338,162 @@ IPCM_GetMsgType(const ipcMessage *msg)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// in other words, these classes are very very lightweight.
|
||||
//
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_PING
|
||||
//
|
||||
// this message may be sent from either the client or the daemon.
|
||||
// if the daemon receives this message, then it will respond by
|
||||
// sending back a PING to the client.
|
||||
//
|
||||
class ipcmMessagePing : public ipcMessage_DWORD
|
||||
// REQUESTS
|
||||
|
||||
class ipcmMessagePing : public ipcMessage_DWORD_DWORD
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessagePing()
|
||||
: ipcMessage_DWORD(IPCM_TARGET, MSG_TYPE) {}
|
||||
: ipcMessage_DWORD_DWORD(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_REQ_PING,
|
||||
IPCM_NewRequestIndex()) {}
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_ERROR
|
||||
//
|
||||
// this message may be sent from the daemon in place of an expected
|
||||
// result. e.g., if a query fails, the daemon will send an error
|
||||
// message to indicate the failure.
|
||||
//
|
||||
class ipcmMessageError : public ipcMessage_DWORD_DWORD
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageError(PRUint32 reason)
|
||||
: ipcMessage_DWORD_DWORD(IPCM_TARGET, MSG_TYPE, reason) {}
|
||||
|
||||
PRUint32 Reason() const { return Second(); }
|
||||
};
|
||||
|
||||
enum {
|
||||
IPCM_ERROR_CLIENT_NOT_FOUND = 1
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_CLIENT_HELLO
|
||||
//
|
||||
// this message is always the first message sent from a client to register
|
||||
// itself with the daemon. the daemon responds to this message by sending
|
||||
// the client a CLIENT_ID message informing the client of its client ID.
|
||||
//
|
||||
// XXX may want to pass other information here.
|
||||
//
|
||||
class ipcmMessageClientHello : public ipcMessage_DWORD
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageClientHello()
|
||||
: ipcMessage_DWORD(IPCM_TARGET, MSG_TYPE) {}
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_CLIENT_ID
|
||||
//
|
||||
// this message is sent from the daemon to identify a client's ID.
|
||||
//
|
||||
class ipcmMessageClientID : public ipcMessage_DWORD_DWORD
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageClientID(PRUint32 clientID)
|
||||
: ipcMessage_DWORD_DWORD(IPCM_TARGET, MSG_TYPE, clientID) {}
|
||||
|
||||
PRUint32 ClientID() const { return Second(); }
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_CLIENT_INFO
|
||||
//
|
||||
// this message is sent from the daemon to provide the list of names
|
||||
// and targets for a particular client.
|
||||
//
|
||||
class ipcmMessageClientInfo : public ipcMessage
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageClientInfo(PRUint32 clientID, const char **names, const nsID **targets);
|
||||
|
||||
PRUint32 ClientID() const;
|
||||
PRUint32 NameCount() const;
|
||||
PRUint32 TargetCount() const;
|
||||
|
||||
const char *NextName(const char *name) const;
|
||||
const nsID *NextTarget(const nsID *target) const;
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_CLIENT_ADD_NAME
|
||||
//
|
||||
class ipcmMessageClientAddName : public ipcMessage_DWORD_STR
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageClientAddName(const char *name)
|
||||
: ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {}
|
||||
|
||||
const char *Name() const { return Second(); }
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_CLIENT_DEL_NAME
|
||||
//
|
||||
class ipcmMessageClientDelName : public ipcMessage_DWORD_STR
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageClientDelName(const char *name)
|
||||
: ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {}
|
||||
|
||||
const char *Name() const { return Second(); }
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_CLIENT_ADD_TARGET
|
||||
//
|
||||
class ipcmMessageClientAddTarget : public ipcMessage_DWORD_ID
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageClientAddTarget(const nsID &target)
|
||||
: ipcMessage_DWORD_ID(IPCM_TARGET, MSG_TYPE, target) {}
|
||||
|
||||
const nsID &Target() const { return Second(); }
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_CLIENT_DEL_TARGET
|
||||
//
|
||||
class ipcmMessageClientDelTarget : public ipcMessage_DWORD_ID
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageClientDelTarget(const nsID &target)
|
||||
: ipcMessage_DWORD_ID(IPCM_TARGET, MSG_TYPE, target) {}
|
||||
|
||||
const nsID &Target() const { return Second(); }
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME
|
||||
//
|
||||
// this message is sent from a client to the daemon to request the ID of the
|
||||
// client corresponding to the given name. in response the daemon will either
|
||||
// send a CLIENT_ID or an ERROR message.
|
||||
//
|
||||
class ipcmMessageQueryClientByName : public ipcMessage_DWORD_STR
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageQueryClientByName(const char *name)
|
||||
: ipcMessage_DWORD_STR(IPCM_TARGET, MSG_TYPE, name) {}
|
||||
|
||||
const char *Name() const { return Second(); }
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_QUERY_CLIENT_INFO
|
||||
//
|
||||
// this message is sent from a client to the daemon to request complete
|
||||
// information about the client corresponding to the given client ID. in
|
||||
// response the daemon will either send a CLIENT_INFO or an ERROR message.
|
||||
//
|
||||
class ipcmMessageQueryClientInfo : public ipcMessage_DWORD_DWORD
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
ipcmMessageQueryClientInfo(PRUint32 clientID)
|
||||
: ipcMessage_DWORD_DWORD(IPCM_TARGET, MSG_TYPE, clientID) {}
|
||||
|
||||
PRUint32 ClientID() const { return Second(); }
|
||||
};
|
||||
|
||||
//
|
||||
// IPCM_MSG_TYPE_FORWARD
|
||||
//
|
||||
// this message is only sent from the client to the daemon. the daemon
|
||||
// will forward the contained message to the specified client. there
|
||||
// is no guarantee that the message will be forwarded, and no error will
|
||||
// be sent to the sender on failure.
|
||||
//
|
||||
class ipcmMessageForward : public ipcMessage
|
||||
{
|
||||
public:
|
||||
static const PRUint32 MSG_TYPE;
|
||||
|
||||
//
|
||||
// params:
|
||||
// clientID - the client to which the message should be forwarded
|
||||
// target - the message target
|
||||
// data - the message data
|
||||
// dataLen - the message data length
|
||||
//
|
||||
ipcmMessageForward(PRUint32 clientID,
|
||||
// @param type the type of this message: IPCM_MSG_{REQ,PSH}_FORWARD
|
||||
// @param clientID the client id of the sender or receiver
|
||||
// @param target the message target
|
||||
// @param data the message data
|
||||
// @param dataLen the message data length
|
||||
ipcmMessageForward(PRUint32 type,
|
||||
PRUint32 clientID,
|
||||
const nsID &target,
|
||||
const char *data,
|
||||
PRUint32 dataLen);
|
||||
PRUint32 dataLen) NS_HIDDEN;
|
||||
|
||||
//
|
||||
// set inner message data, constrained to the data length passed
|
||||
// to this class's constructor.
|
||||
//
|
||||
void SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen);
|
||||
NS_HIDDEN_(void) SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen);
|
||||
|
||||
PRUint32 DestClientID() const;
|
||||
const nsID &InnerTarget() const;
|
||||
const char *InnerData() const;
|
||||
PRUint32 InnerDataLen() const;
|
||||
NS_HIDDEN_(PRUint32) ClientID() const;
|
||||
NS_HIDDEN_(const nsID &) InnerTarget() const;
|
||||
NS_HIDDEN_(const char *) InnerData() const;
|
||||
NS_HIDDEN_(PRUint32) InnerDataLen() const;
|
||||
};
|
||||
|
||||
class ipcmMessageClientHello : public ipcMessage_DWORD_DWORD
|
||||
{
|
||||
public:
|
||||
ipcmMessageClientHello()
|
||||
: ipcMessage_DWORD_DWORD(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_REQ_CLIENT_HELLO,
|
||||
IPCM_NewRequestIndex()) {}
|
||||
};
|
||||
|
||||
class ipcmMessageClientAddName : public ipcMessage_DWORD_DWORD_STR
|
||||
{
|
||||
public:
|
||||
ipcmMessageClientAddName(const char *name)
|
||||
: ipcMessage_DWORD_DWORD_STR(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_REQ_CLIENT_ADD_NAME,
|
||||
IPCM_NewRequestIndex(),
|
||||
name) {}
|
||||
|
||||
const char *Name() const { return Third(); }
|
||||
};
|
||||
|
||||
class ipcmMessageClientDelName : public ipcMessage_DWORD_DWORD_STR
|
||||
{
|
||||
public:
|
||||
ipcmMessageClientDelName(const char *name)
|
||||
: ipcMessage_DWORD_DWORD_STR(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_REQ_CLIENT_DEL_NAME,
|
||||
IPCM_NewRequestIndex(),
|
||||
name) {}
|
||||
|
||||
const char *Name() const { return Third(); }
|
||||
};
|
||||
|
||||
class ipcmMessageClientAddTarget : public ipcMessage_DWORD_DWORD_ID
|
||||
{
|
||||
public:
|
||||
ipcmMessageClientAddTarget(const nsID &target)
|
||||
: ipcMessage_DWORD_DWORD_ID(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_REQ_CLIENT_ADD_TARGET,
|
||||
IPCM_NewRequestIndex(),
|
||||
target) {}
|
||||
|
||||
const nsID &Target() const { return Third(); }
|
||||
};
|
||||
|
||||
class ipcmMessageClientDelTarget : public ipcMessage_DWORD_DWORD_ID
|
||||
{
|
||||
public:
|
||||
ipcmMessageClientDelTarget(const nsID &target)
|
||||
: ipcMessage_DWORD_DWORD_ID(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_REQ_CLIENT_ADD_TARGET,
|
||||
IPCM_NewRequestIndex(),
|
||||
target) {}
|
||||
|
||||
const nsID &Target() const { return Third(); }
|
||||
};
|
||||
|
||||
class ipcmMessageQueryClientByName : public ipcMessage_DWORD_DWORD_STR
|
||||
{
|
||||
public:
|
||||
ipcmMessageQueryClientByName(const char *name)
|
||||
: ipcMessage_DWORD_DWORD_STR(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME,
|
||||
IPCM_NewRequestIndex(),
|
||||
name) {}
|
||||
|
||||
const char *Name() const { return Third(); }
|
||||
PRUint32 RequestIndex() const { return Second(); }
|
||||
};
|
||||
|
||||
// ACKNOWLEDGEMENTS
|
||||
|
||||
class ipcmMessageResult : public ipcMessage_DWORD_DWORD_DWORD
|
||||
{
|
||||
public:
|
||||
ipcmMessageResult(PRUint32 requestIndex, PRInt32 status)
|
||||
: ipcMessage_DWORD_DWORD_DWORD(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_ACK_RESULT,
|
||||
requestIndex,
|
||||
(PRUint32) status) {}
|
||||
|
||||
PRInt32 Status() const { return (PRInt32) Third(); }
|
||||
};
|
||||
|
||||
class ipcmMessageClientID : public ipcMessage_DWORD_DWORD_DWORD
|
||||
{
|
||||
public:
|
||||
ipcmMessageClientID(PRUint32 requestIndex, PRUint32 clientID)
|
||||
: ipcMessage_DWORD_DWORD_DWORD(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_ACK_CLIENT_ID,
|
||||
requestIndex,
|
||||
clientID) {}
|
||||
|
||||
PRUint32 ClientID() const { return Third(); }
|
||||
};
|
||||
|
||||
// PUSH MESSAGES
|
||||
|
||||
class ipcmMessageClientState : public ipcMessage_DWORD_DWORD_DWORD_DWORD
|
||||
{
|
||||
public:
|
||||
ipcmMessageClientState(PRUint32 clientID, PRUint32 clientStatus)
|
||||
: ipcMessage_DWORD_DWORD_DWORD_DWORD(
|
||||
IPCM_TARGET,
|
||||
IPCM_MSG_PSH_CLIENT_STATE,
|
||||
0,
|
||||
clientID,
|
||||
clientStatus) {}
|
||||
|
||||
PRUint32 ClientID() const { return Third(); }
|
||||
PRUint32 ClientState() const { return Fourth(); }
|
||||
};
|
||||
|
||||
#endif // !ipcm_h__
|
||||
|
@ -40,6 +40,8 @@
|
||||
#include "ipcIClientQueryHandler.h"
|
||||
#include "ipcILockService.h"
|
||||
#include "ipcILockNotify.h"
|
||||
#include "ipcCID.h"
|
||||
#include "ipcLockCID.h"
|
||||
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
@ -75,7 +77,6 @@ static const nsID kTestTargetID =
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static nsIEventQueue* gEventQ = nsnull;
|
||||
static PRBool gKeepRunning = PR_TRUE;
|
||||
//static PRInt32 gMsgCount = 0;
|
||||
static ipcIService *gIpcServ = nsnull;
|
||||
static ipcILockService *gIpcLockServ = nsnull;
|
||||
|
||||
@ -84,8 +85,19 @@ SendMsg(ipcIService *ipc, PRUint32 cID, const nsID &target, const char *data, PR
|
||||
{
|
||||
printf("*** sending message: [to-client=%u dataLen=%u]\n", cID, dataLen);
|
||||
|
||||
ipc->SendMessage(cID, target, (const PRUint8 *) data, dataLen, sync);
|
||||
// gMsgCount++;
|
||||
nsresult rv;
|
||||
|
||||
rv = ipc->SendMessage(cID, target, (const PRUint8 *) data, dataLen);
|
||||
if (NS_FAILED(rv)) {
|
||||
printf("*** sending message failed: rv=%x\n", rv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sync) {
|
||||
rv = ipc->WaitMessage(cID, target, nsnull, PR_UINT32_MAX);
|
||||
if (NS_FAILED(rv))
|
||||
printf("*** waiting for message failed: rv=%x\n", rv);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -95,25 +107,19 @@ class myIpcMessageObserver : public ipcIMessageObserver
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IPCIMESSAGEOBSERVER
|
||||
|
||||
myIpcMessageObserver() {}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(myIpcMessageObserver, ipcIMessageObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
myIpcMessageObserver::OnMessageAvailable(const nsID &target, const PRUint8 *data, PRUint32 dataLen)
|
||||
myIpcMessageObserver::OnMessageAvailable(PRUint32 sender, const nsID &target, const PRUint8 *data, PRUint32 dataLen)
|
||||
{
|
||||
printf("*** got message: [%s]\n", (const char *) data);
|
||||
|
||||
// if (--gMsgCount == 0)
|
||||
// gKeepRunning = PR_FALSE;
|
||||
|
||||
printf("*** got message: [sender=%u data=%s]\n", sender, (const char *) data);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
class myIpcClientQueryHandler : public ipcIClientQueryHandler
|
||||
{
|
||||
public:
|
||||
@ -160,6 +166,7 @@ myIpcClientQueryHandler::OnQueryComplete(PRUint32 aQueryID,
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -205,16 +212,17 @@ int main(int argc, char **argv)
|
||||
rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
|
||||
RETURN_IF_FAILED(rv, "GetThreadEventQueue");
|
||||
|
||||
printf("*** getting ipc service\n");
|
||||
nsCOMPtr<ipcIService> ipcServ(do_GetService(IPC_SERVICE_CONTRACTID, &rv));
|
||||
RETURN_IF_FAILED(rv, "do_GetService(ipcServ)");
|
||||
NS_ADDREF(gIpcServ = ipcServ);
|
||||
|
||||
if (argc > 1) {
|
||||
printf("*** using client name [%s]\n", argv[1]);
|
||||
gIpcServ->AddClientName(argv[1]);
|
||||
gIpcServ->AddName(argv[1]);
|
||||
}
|
||||
|
||||
ipcServ->SetMessageObserver(kTestTargetID, new myIpcMessageObserver());
|
||||
ipcServ->DefineTarget(kTestTargetID, new myIpcMessageObserver());
|
||||
|
||||
const char data[] =
|
||||
"01 this is a really long message.\n"
|
||||
@ -279,9 +287,18 @@ int main(int argc, char **argv)
|
||||
"60 this is a really long message.\n";
|
||||
SendMsg(ipcServ, 0, kTestTargetID, data, sizeof(data), PR_TRUE);
|
||||
|
||||
PRUint32 queryID;
|
||||
nsCOMPtr<ipcIClientQueryHandler> handler(new myIpcClientQueryHandler());
|
||||
ipcServ->QueryClientByName("foopy", handler, PR_FALSE, &queryID);
|
||||
// PRUint32 queryID;
|
||||
// nsCOMPtr<ipcIClientQueryHandler> handler(new myIpcClientQueryHandler());
|
||||
// ipcServ->QueryClientByName("foopy", handler, PR_FALSE, &queryID);
|
||||
|
||||
PRUint32 foopyID;
|
||||
nsresult foopyRv = ipcServ->ResolveClientName("foopy", &foopyID);
|
||||
printf("*** query for 'foopy' returned [rv=%x id=%u]\n", foopyRv, foopyID);
|
||||
|
||||
if (NS_SUCCEEDED(foopyRv)) {
|
||||
const char hello[] = "hello friend!";
|
||||
SendMsg(ipcServ, foopyID, kTestTargetID, hello, sizeof(hello));
|
||||
}
|
||||
|
||||
//
|
||||
// test lock service
|
||||
|
Loading…
x
Reference in New Issue
Block a user