diff -r f5050f1da672 -r 04becd199f91 javacommons/comms/inc/commsendpoint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javacommons/comms/inc/commsendpoint.h Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,346 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: This is an abstract base class for Comms endpoints. +* +*/ + +#ifndef COMMSENDPOINT_H +#define COMMSENDPOINT_H + +#include +#include +#include + +#include "javaosheaders.h" +#include "scopedlocks.h" + +#include "transport.h" + +namespace java +{ +namespace comms +{ + +class CommsMessage; +class CommsListener; + +class ListenerWrapper; + +/** +* This is an abstract base class for Comms endpoints. It provides implementation for +* registering listeners and for synchronous message sending. +* +* Comms endpoint provides interprocess communication functionality. Comms communication +* is point-to-point meaning that client endpoint can be connected to a single server at a time. +* Communication is message based, where users wrap their payload to CommsMessage. +* Comms endpoints support synchronous and asynchronous message sending. +* +* Messages can be sent asynchronously or synchronously. Synchronous message sending blocks until +* a reply is received or when specified timeout occurs. +* +* CommsListener provides a way to receive messages asynchronously. Listeners are registered +* to endpoint. When message belonging to listener is received, will Comms endpoint make a +* callback for listener. Application can register as many listeners as need. +* +* Application can register also a default listener, which gets called if there is no registered +* listener for received message. +* +* CommsEndpoint is thread safe. +* +* Usage: +* It is recomended that at least default listener is registered before CommsServerEndpoint +* is started. This ensures that no messages are lost. +* @code +* CommsServerEndpoint comms; +* comms.registerDefaultListener(listener); +* comms.start(MY_SERVER_NAME); +* ... +* comms.stop(); +* @endcode +*/ + +/** +* This constant can be used when timeout functionality of synchronous sendReceive is not needed. +* SendReceive method will return when reply is received or when connection is closed. +* @see CommsEndpoint::sendReceive() +*/ +const int WAIT_FOR_EVER = -1; + +class CommsEndpoint : public IpcListener +{ +public: + /** + * A constructor. + */ + OS_IMPORT CommsEndpoint(); + + /** + * A destructor. + */ + OS_IMPORT virtual ~CommsEndpoint(); + + /** + * Registers message handler for given module id. + * CommsListener provides a way to receive messages asynchronously. + * Module id identifies to which component message belongs. Every message will contain module id + * information that is used to route message to correct listener. + * + * There can be one registered listener for each module id and same listener can be registered + * for multiple module ids. + * + * Listener registration remains valid during connect/disconnect and start/stop. + * @code + * CommsClientEndpoint comms; + * comms.registerListener(MODULE_ID_A, listenerA); + * comms.registerListener(MODULE_ID_B, listenerB); + * comms.connect(MY_SERVER_NAME); + * @endcode + * @param[in] aModuleId Module id, messages with that module id are forwarded to given listener + * @param[in] aListener Listener that will be called when message with matching module id is received + * @see unregisterListener() + * @see send() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int registerListener(int aModuleId, CommsListener* aListener); + + /** + * Unregisters message handler for given module id. + * @code + * CommsClientEndpoint comms; + * comms.registerListener(MODULE_ID_A, listenerA); + * comms.unregisterListener(MODULE_ID_A, listenerA); + * @endcode + * @param[in] aModuleId Module id, identifies listener that will be removed + * @param[in] aListener Listener that will be removed + * @see unregisterListener() + * @see send() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int unregisterListener(int aModuleId, CommsListener* aListener); + + /** + * Registers default listener. + * There can be only one default listener. Default listener is called if there is no registered listener for received message. + * If there is no default listener then received messages without listener will be discarded. + * @param[in] aDefaultListener Default message handler that will be called if no other suitable handlers are found + * @see unregisterDefaultListener() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int registerDefaultListener(CommsListener* aDefaultListener); + + /** + * Unregisters default listener. + * @param[in] aDefaultListener Listener that will be removed + * @see registerDefaultListener() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int unregisterDefaultListener(CommsListener* aDefaultListener); + + /** + * Sends a message. + * Message recipient must set by CommsMessage::setReceiver() method. It is important that + * message header is properly filled because header information is used in message routing. + * @code + * CommsMessage msg; + * + * // set the headers + * msg.setMessageId(MY_MESSAGE_ID); + * msg.setModuleId(MY_MODULE_ID); + * msg.setReceiver(CLIENT_ADDRESS); + * + * // set the payload + * msg << "my payload"; + * + * // send message + * int rc = comms.send(msg); + * @endcode + * @param[in] aMessage A message to be sent + * @see sendReceive() + * @see registerListener() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int send(CommsMessage& aMessage) = 0; + + /** + * Sends and receives message syncronously. + * Method blocks until response message is received or timeout expires. + * Message recipient must set by CommsMessage::setReceiver() method. It is important that + * message header is properly filled because header information is used in message routing. + * @code + * CommsMessage msg; + * + * // set the headers + * msg.setMessageId(MY_MESSAGE_ID); + * msg.setModuleId(MY_MODULE_ID); + * + * CommsMessage receivedMessage; + * int timeout = 10; //10s + * + * // send and receive message + * int rc = comms.sendReceive(msg, receivedMessage, timeout); + * if(rc!=0) + * { + * LOG("sendReceive failed"); + * return; + * } + * int i; + * receivedMessage >> i; + * @endcode + * @param[in] aMessage A message to be sent + * @param[out] aReceivedMessage Received message (message content will be empy if method call fails) + * @param[in] aTimeoutInSecs Timeout in seconds for how long reply is waited + * @see send() + * @return 0 in success + * @return errno in failure and timeout cases + */ + OS_IMPORT virtual int sendReceive(CommsMessage& aMessage, CommsMessage& aReceivedMessage, int aTimeoutInSecs); + +protected: + /** + * Routes received message to waiting sendReceive thread or message listener + * @param[in] aMessage Received message + * @see - + * @return - + */ + OS_IMPORT virtual void handleIpcMessage(CommsMessage& aMessage); + + /** + * Dispatches received message to listener or default listener + * @param[in] aMessage Received message + * @see - + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int handleMessage(CommsMessage& aMessage); + + /** + * Generates unique message reference + * @return message reference + */ + OS_IMPORT virtual int generateMessageReference(); + + // IpcListener methods + /** + * Callback that is called when underlaying transport stack receives a message + * Called in the context of message loop thread. + * @param[out] aMsg Received message + * @return - + */ + OS_IMPORT virtual void processMessage(const ipcMessage_t* aMsg); + /** + * Callback that is called when underlaying transport stack's message loop thread starts. + * Called in the context of message loop thread. + * @param - + * @return - + */ + OS_IMPORT virtual void onStart(); + /** + * Callback that is called when underlaying transport stack's message loop thread exits. + * Called in the context of message loop thread. + * @param - + * @return - + */ + OS_IMPORT virtual void onExit(); + +private: + ListenerWrapper* mDefaultListener; + + typedef std::map listeners_t; + listeners_t mListeners; + java::util::ScopedMutex mListenersMutex; + + int mMessageRefCounter; + java::util::ScopedMutex mMessageRefMutex; + + // sendReceive related stuff + int isSendReceiveMessage(CommsMessage& message); + + typedef struct sendReceiveMessage_s + { + CommsMessage* p_message; + int* p_done; + int* p_result; + } sendReceiveMessage_t; + + typedef std::map sendReceiveListeners_t; + sendReceiveListeners_t mSendReceiveListeners; // access protected by mSendReceiveMutex + + pthread_mutex_t mSendReceiveMutex; + pthread_cond_t mSendReceiveCondition; + +public: + /** + * Registers Java message handler for given module id. + * @param[in] aModuleId Module id, messages with that module id are forwarded to given listener + * @param[in] aListener Listener that will be called when message with matching module id is received + * @param[in] aEnv JNI context + * @see unregisterJavaListener() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int registerJavaListener(int aModuleId, jobject aListener, JNIEnv* aEnv); + + /** + * Unregisters Java message handler for given module id. + * @param[in] aModuleId Module id + * @param[in] aListener Listener to be removed + * @param[in] aEnv JNI context + * @see registerJavaListener() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int unregisterJavaListener(int aModuleId, jobject aListener, JNIEnv* aEnv); + + /** + * Registers default listener. + * There can be only one default listener. Default listener is called if there is no registered listener for received message. + * If there is no default listener then received messages without listener will be discarded. + * @param[in] aDefaultListener Default message handler + * @see unregisterDefaultJavaListener() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int registerDefaultJavaListener(jobject aListener, JNIEnv* aEnv); + + /** + * Unregisters default listener. + * @param[in] aDefaultListener Listener that will be removed + * @see registerDefaultJavaListener() + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int unregisterDefaultJavaListener(jobject aListener, JNIEnv* aEnv); + + /** + * Attach internal message loop thread to JVM. + * @param[in] aEnv JNI context + * @see detachFromVm + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int attachToVm(JNIEnv* aEnv); + + /** + * Detach internal message loop thread from JVM. + * @param - + * @see attachToVm + * @return 0 in success, errno in failure + */ + OS_IMPORT virtual int detachFromVm(); + +protected: + JavaVM* mVm; + JNIEnv* mJNIEnv; + +}; + +} // namespace comms +} // namespace java + + +#endif // COMMSENDPOINT_H