javacommons/comms/inc/commsendpoint.h
changeset 21 2a9601315dfc
child 87 1627c337e51e
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This is an abstract base class for Comms endpoints.
       
    15 *
       
    16 */
       
    17 
       
    18 #ifndef COMMSENDPOINT_H
       
    19 #define COMMSENDPOINT_H
       
    20 
       
    21 #include <pthread.h>
       
    22 #include <map>
       
    23 #include <jni.h>
       
    24 
       
    25 #include "javaosheaders.h"
       
    26 #include "scopedlocks.h"
       
    27 
       
    28 #include "transport.h"
       
    29 
       
    30 namespace java
       
    31 {
       
    32 namespace comms
       
    33 {
       
    34 
       
    35 class CommsMessage;
       
    36 class CommsListener;
       
    37 
       
    38 class ListenerWrapper;
       
    39 
       
    40 /**
       
    41 * This is an abstract base class for Comms endpoints. It provides implementation for
       
    42 * registering listeners and for synchronous message sending.
       
    43 *
       
    44 * Comms endpoint provides interprocess communication functionality. Comms communication
       
    45 * is point-to-point meaning that client endpoint can be connected to a single server at a time.
       
    46 * Communication is message based, where users wrap their payload to CommsMessage.
       
    47 * Comms endpoints support synchronous and asynchronous message sending.
       
    48 *
       
    49 * Messages can be sent asynchronously or synchronously. Synchronous message sending blocks until
       
    50 * a reply is received or when specified timeout occurs.
       
    51 *
       
    52 * CommsListener provides a way to receive messages asynchronously. Listeners are registered
       
    53 * to endpoint. When message belonging to listener is received, will Comms endpoint make a
       
    54 * callback for listener. Application can register as many listeners as need.
       
    55 *
       
    56 * Application can register also a default listener, which gets called if there is no registered
       
    57 * listener for received message.
       
    58 *
       
    59 * CommsEndpoint is thread safe.
       
    60 *
       
    61 * Usage:
       
    62 * It is recomended that at least default listener is registered before CommsServerEndpoint
       
    63 * is started. This ensures that no messages are lost.
       
    64 * @code
       
    65 * CommsServerEndpoint comms;
       
    66 * comms.registerDefaultListener(listener);
       
    67 * comms.start(MY_SERVER_NAME);
       
    68 * ...
       
    69 * comms.stop();
       
    70 * @endcode
       
    71 */
       
    72 
       
    73 /**
       
    74 * This constant can be used when timeout functionality of synchronous sendReceive is not needed.
       
    75 * SendReceive method will return when reply is received or when connection is closed.
       
    76 * @see CommsEndpoint::sendReceive()
       
    77 */
       
    78 const int WAIT_FOR_EVER = -1;
       
    79 
       
    80 class CommsEndpoint : public IpcListener
       
    81 {
       
    82 public:
       
    83     /**
       
    84     * A constructor.
       
    85     */
       
    86     OS_IMPORT CommsEndpoint();
       
    87 
       
    88     /**
       
    89     * A destructor.
       
    90     */
       
    91     OS_IMPORT virtual ~CommsEndpoint();
       
    92 
       
    93     /**
       
    94     * Registers message handler for given module id.
       
    95     * CommsListener provides a way to receive messages asynchronously.
       
    96     * Module id identifies to which component message belongs. Every message will contain module id
       
    97     * information that is used to route message to correct listener.
       
    98     *
       
    99     * There can be one registered listener for each module id and same listener can be registered
       
   100     * for multiple module ids.
       
   101     *
       
   102     * Listener registration remains valid during connect/disconnect and start/stop.
       
   103     * @code
       
   104     * CommsClientEndpoint comms;
       
   105     * comms.registerListener(MODULE_ID_A, listenerA);
       
   106     * comms.registerListener(MODULE_ID_B, listenerB);
       
   107     * comms.connect(MY_SERVER_NAME);
       
   108     * @endcode
       
   109     * @param[in] aModuleId Module id, messages with that module id are forwarded to given listener
       
   110     * @param[in] aListener Listener that will be called when message with matching module id is received
       
   111     * @see unregisterListener()
       
   112     * @see send()
       
   113     * @return 0 in success, errno in failure
       
   114     */
       
   115     OS_IMPORT virtual int registerListener(int aModuleId, CommsListener* aListener);
       
   116 
       
   117     /**
       
   118     * Unregisters message handler for given module id.
       
   119     * @code
       
   120     * CommsClientEndpoint comms;
       
   121     * comms.registerListener(MODULE_ID_A, listenerA);
       
   122     * comms.unregisterListener(MODULE_ID_A, listenerA);
       
   123     * @endcode
       
   124     * @param[in] aModuleId Module id, identifies listener that will be removed
       
   125     * @param[in] aListener Listener that will be removed
       
   126     * @see unregisterListener()
       
   127     * @see send()
       
   128     * @return 0 in success, errno in failure
       
   129     */
       
   130     OS_IMPORT virtual int unregisterListener(int aModuleId, CommsListener* aListener);
       
   131 
       
   132     /**
       
   133     * Registers default listener.
       
   134     * There can be only one default listener. Default listener is called if there is no registered listener for received message.
       
   135     * If there is no default listener then received messages without listener will be discarded.
       
   136     * @param[in] aDefaultListener Default message handler that will be called if no other suitable handlers are found
       
   137     * @see unregisterDefaultListener()
       
   138     * @return 0 in success, errno in failure
       
   139     */
       
   140     OS_IMPORT   virtual int registerDefaultListener(CommsListener* aDefaultListener);
       
   141 
       
   142     /**
       
   143     * Unregisters default listener.
       
   144     * @param[in] aDefaultListener Listener that will be removed
       
   145     * @see registerDefaultListener()
       
   146     * @return 0 in success, errno in failure
       
   147     */
       
   148     OS_IMPORT virtual int unregisterDefaultListener(CommsListener* aDefaultListener);
       
   149 
       
   150     /**
       
   151     * Sends a message.
       
   152     * Message recipient must set by CommsMessage::setReceiver() method. It is important that
       
   153     * message header is properly filled because header information is used in message routing.
       
   154     * @code
       
   155     * CommsMessage msg;
       
   156     *
       
   157     * // set the headers
       
   158     * msg.setMessageId(MY_MESSAGE_ID);
       
   159     * msg.setModuleId(MY_MODULE_ID);
       
   160     * msg.setReceiver(CLIENT_ADDRESS);
       
   161     *
       
   162     * // set the payload
       
   163     * msg << "my payload";
       
   164     *
       
   165     * // send message
       
   166     * int rc = comms.send(msg);
       
   167     * @endcode
       
   168     * @param[in] aMessage A message to be sent
       
   169     * @see sendReceive()
       
   170     * @see registerListener()
       
   171     * @return 0 in success, errno in failure
       
   172     */
       
   173     OS_IMPORT virtual int send(CommsMessage& aMessage) = 0;
       
   174 
       
   175     /**
       
   176     * Sends and receives message syncronously.
       
   177     * Method blocks until response message is received or timeout expires.
       
   178     * Message recipient must set by CommsMessage::setReceiver() method. It is important that
       
   179     * message header is properly filled because header information is used in message routing.
       
   180     * @code
       
   181     * CommsMessage msg;
       
   182     *
       
   183     * // set the headers
       
   184     * msg.setMessageId(MY_MESSAGE_ID);
       
   185     * msg.setModuleId(MY_MODULE_ID);
       
   186     *
       
   187     * CommsMessage receivedMessage;
       
   188     * int timeout = 10; //10s
       
   189     *
       
   190     * // send and receive message
       
   191     * int rc = comms.sendReceive(msg, receivedMessage, timeout);
       
   192     * if(rc!=0)
       
   193     * {
       
   194     * LOG("sendReceive failed");
       
   195     * return;
       
   196     * }
       
   197     * int i;
       
   198     * receivedMessage >> i;
       
   199     * @endcode
       
   200     * @param[in] aMessage A message to be sent
       
   201     * @param[out] aReceivedMessage Received message (message content will be empy if method call fails)
       
   202     * @param[in] aTimeoutInSecs Timeout in seconds for how long reply is waited
       
   203     * @see send()
       
   204     * @return 0 in success
       
   205     * @return errno in failure and timeout cases
       
   206     */
       
   207     OS_IMPORT virtual int sendReceive(CommsMessage& aMessage, CommsMessage& aReceivedMessage, int aTimeoutInSecs);
       
   208 
       
   209 protected:
       
   210     /**
       
   211     * Routes received message to waiting sendReceive thread or message listener
       
   212     * @param[in] aMessage Received message
       
   213     * @see -
       
   214     * @return -
       
   215     */
       
   216     OS_IMPORT virtual void handleIpcMessage(CommsMessage& aMessage);
       
   217 
       
   218     /**
       
   219     * Dispatches received message to listener or default listener
       
   220     * @param[in] aMessage Received message
       
   221     * @see -
       
   222     * @return 0 in success, errno in failure
       
   223     */
       
   224     OS_IMPORT virtual int handleMessage(CommsMessage& aMessage);
       
   225 
       
   226     /**
       
   227     * Generates unique message reference
       
   228     * @return message reference
       
   229     */
       
   230     OS_IMPORT virtual int generateMessageReference();
       
   231 
       
   232     // IpcListener methods
       
   233     /**
       
   234     * Callback that is called when underlaying transport stack receives a message
       
   235     * Called in the context of message loop thread.
       
   236     * @param[out] aMsg Received message
       
   237     * @return -
       
   238     */
       
   239     OS_IMPORT virtual void processMessage(const ipcMessage_t* aMsg);
       
   240     /**
       
   241     * Callback that is called when underlaying transport stack's message loop thread starts.
       
   242     * Called in the context of message loop thread.
       
   243     * @param -
       
   244     * @return -
       
   245     */
       
   246     OS_IMPORT virtual void onStart();
       
   247     /**
       
   248     * Callback that is called when underlaying transport stack's message loop thread exits.
       
   249     * Called in the context of message loop thread.
       
   250     * @param -
       
   251     * @return -
       
   252     */
       
   253     OS_IMPORT virtual void onExit();
       
   254 
       
   255 private:
       
   256     ListenerWrapper* mDefaultListener;
       
   257 
       
   258     typedef std::map<const int, ListenerWrapper*> listeners_t;
       
   259     listeners_t mListeners;
       
   260     java::util::ScopedMutex mListenersMutex;
       
   261 
       
   262     int mMessageRefCounter;
       
   263     java::util::ScopedMutex mMessageRefMutex;
       
   264 
       
   265     // sendReceive related stuff
       
   266     int isSendReceiveMessage(CommsMessage& message);
       
   267 
       
   268     typedef struct sendReceiveMessage_s
       
   269     {
       
   270         CommsMessage*   p_message;
       
   271         int*            p_done;
       
   272         int*            p_result;
       
   273     } sendReceiveMessage_t;
       
   274 
       
   275     typedef std::map<int, sendReceiveMessage_t> sendReceiveListeners_t;
       
   276     sendReceiveListeners_t mSendReceiveListeners; // access protected by mSendReceiveMutex
       
   277 
       
   278     pthread_mutex_t mSendReceiveMutex;
       
   279     pthread_cond_t  mSendReceiveCondition;
       
   280 
       
   281 public:
       
   282     /**
       
   283     * Registers Java message handler for given module id.
       
   284     * @param[in] aModuleId Module id, messages with that module id are forwarded to given listener
       
   285     * @param[in] aListener Listener that will be called when message with matching module id is received
       
   286     * @param[in] aEnv JNI context
       
   287     * @see unregisterJavaListener()
       
   288     * @return 0 in success, errno in failure
       
   289     */
       
   290     OS_IMPORT virtual int registerJavaListener(int aModuleId, jobject aListener, JNIEnv* aEnv);
       
   291 
       
   292     /**
       
   293     * Unregisters Java message handler for given module id.
       
   294     * @param[in] aModuleId Module id
       
   295     * @param[in] aListener Listener to be removed
       
   296     * @param[in] aEnv JNI context
       
   297     * @see registerJavaListener()
       
   298     * @return 0 in success, errno in failure
       
   299     */
       
   300     OS_IMPORT virtual int unregisterJavaListener(int aModuleId, jobject aListener, JNIEnv* aEnv);
       
   301 
       
   302     /**
       
   303     * Registers default listener.
       
   304     * There can be only one default listener. Default listener is called if there is no registered listener for received message.
       
   305     * If there is no default listener then received messages without listener will be discarded.
       
   306     * @param[in] aDefaultListener Default message handler
       
   307     * @see unregisterDefaultJavaListener()
       
   308     * @return 0 in success, errno in failure
       
   309     */
       
   310     OS_IMPORT virtual int registerDefaultJavaListener(jobject aListener, JNIEnv* aEnv);
       
   311 
       
   312     /**
       
   313     * Unregisters default listener.
       
   314     * @param[in] aDefaultListener Listener that will be removed
       
   315     * @see registerDefaultJavaListener()
       
   316     * @return 0 in success, errno in failure
       
   317     */
       
   318     OS_IMPORT virtual int unregisterDefaultJavaListener(jobject aListener, JNIEnv* aEnv);
       
   319 
       
   320     /**
       
   321     * Attach internal message loop thread to JVM.
       
   322     * @param[in] aEnv JNI context
       
   323     * @see detachFromVm
       
   324     * @return 0 in success, errno in failure
       
   325     */
       
   326     OS_IMPORT virtual int attachToVm(JNIEnv* aEnv);
       
   327 
       
   328     /**
       
   329     * Detach internal message loop thread from JVM.
       
   330     * @param -
       
   331     * @see attachToVm
       
   332     * @return 0 in success, errno in failure
       
   333     */
       
   334     OS_IMPORT virtual int detachFromVm();
       
   335 
       
   336 protected:
       
   337     JavaVM* mVm;
       
   338     JNIEnv* mJNIEnv;
       
   339 
       
   340 };
       
   341 
       
   342 } // namespace comms
       
   343 } // namespace java
       
   344 
       
   345 
       
   346 #endif // COMMSENDPOINT_H