|
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 |