le_messaging.h

Go to the documentation of this file.
1 /**
2  * @page c_messaging Low-level Messaging API
3  *
4  * @ref le_messaging.h "API Reference"
5  *
6  * <HR>
7  *
8  * Message-based interfaces in Legato are implemented in layers.
9  * This low-level messaging API is at the bottom layer.
10  * It's designed to support higher layers of the messaging system. But it's also
11  * intended to be easy to hand-code low-level messaging in C, when necessary.
12  *
13  * This low-level messaging API supports:
14  * - remote party identification (addressing)
15  * - very late (runtime) discovery and binding of parties
16  * - in-process and inter-process message delivery
17  * - location transparency
18  * - sessions
19  * - access control
20  * - request/reply transactions
21  * - message buffer memory management
22  * - support for single-threaded and multi-threaded programs
23  * - some level of protection from protocol mismatches between parties in a session.
24  *
25  * This API is integrated with the Legato Event Loop API so components can interact with each
26  * other using messaging without having to create threads or file descriptor
27  * sets that block other software from handling other events. Support for
28  * integration with legacy POSIX-based programs is also provided.
29  *
30  * @section c_messagingInteractionModel Interaction Model
31  *
32  * The Legato low-level messaging system follows a service-oriented pattern:
33  * - Service providers advertise their service.
34  * - Clients open sessions with those services
35  * - Both sides can send and receive messages through the session.
36  *
37  * Clients and servers can both send one-way messages within a session.
38  * Clients can start a request-response transaction by sending a request to the server,
39  * and the server can send a response. Request-response transactions can be blocking or
40  * non-blocking (with a completion callback). If the server dies or terminates the session
41  * before sending the response, Legato will automatically terminate the transaction.
42  *
43  * Servers are prevented from sending blocking requests to clients as a safety measure.
44  * If a server were to block waiting for one of its clients, it would open up the server
45  * to being blocked indefinitely by one of its clients, which would allow one client to cause
46  * a server to deny service to other clients. Also, if a client started a blocking request-response
47  * transaction at the same time that the server started a blocking request-response transaction
48  * in the other direction, a deadlock would occur.
49  *
50  * @section c_messagingAddressing Addressing
51  *
52  * Servers and clients have interfaces that can been connected to each other via bindings. Both
53  * client-side and server-side interfaces are identified by name, but the names don't have to match
54  * for them to be bound to each other. The binding determines which server-side interface will
55  * be connected to when a client opens a session.
56  *
57  * Server-side interfaces are also known as "services".
58  *
59  * When a session is opened by a client, a session reference is provided to both the client
60  * and the server. Messages are then sent within the session using the session reference.
61  * This session reference becomes invalid when the session is closed.
62  *
63  * @section c_messagingProtocols Protocols
64  *
65  * Communication between client and server is done using a message-based protocol. This protocol
66  * is defined at a higher layer than this API, so this API doesn't know the structure of the
67  * message payloads or the correct message sequences. That means this API can't check
68  * for errors in the traffic it carries. However, it does provide a basic mechanism for detecting
69  * protocol mismatches by forcing both client and server to provide the protocol identifier
70  * of the protocol to be used. The client and server must also provide
71  * the maximum message size, as an extra sanity check.
72  *
73  * To make this possible, the client and server must independently call
74  * @c le_msg_GetProtocolRef(), to get a reference to a "Protocol" object that encapsulates these
75  * protocol details:
76  *
77  * @code
78  * protocolRef = le_msg_GetProtocolRef(MY_PROTOCOL_ID, sizeof(myproto_Msg_t));
79  * @endcode
80  *
81  * @note In this example, the protocol identifier (which is a string uniquely identifying a
82  * specific version of a specific protocol) and the message structure
83  * would be defined elsewhere, in a header file shared between the client and the
84  * server. The structure @c myproto_Msg_t contains a
85  * @c union of all of the different messages included in the protocol, thereby
86  * making @c myproto_Msg_t as big as the biggest message in the protocol.
87  *
88  * When a server creates a service (by calling le_msg_CreateService()) and when a client creates
89  * a session (by calling le_msg_CreateSession()), they are required to provide a reference to a
90  * Protocol object that they obtained from le_msg_GetProtocolRef().
91  *
92  * @section c_messagingClientUsage Client Usage Model
93  *
94  * @ref c_messagingClientSending <br>
95  * @ref c_messagingClientReceiving <br>
96  * @ref c_messagingClientClosing <br>
97  * @ref c_messagingClientMultithreading <br>
98  * @ref c_messagingClientExample
99  *
100  * Clients that want to use a service do the following:
101  * -# Get a reference to the protocol they want to use by calling @c le_msg_GetProtocolRef().
102  * -# Create a session using @c le_msg_CreateSession(), passing in the protocol reference and
103  * the client's interface name.
104  * -# Optionally register a message receive callback using @c le_msg_SetSessionRecvHandler().
105  * -# Open the session using le_msg_OpenSession(), le_msg_OpenSessionSync(), or
106  * le_msg_TryOpenSessionSync().
107  *
108  * @code
109  * protocolRef = le_msg_GetProtocolRef(PROTOCOL_ID, sizeof(myproto_Msg_t));
110  * sessionRef = le_msg_CreateSession(protocolRef, MY_INTERFACE_NAME);
111  * le_msg_SetSessionRecvHandler(sessionRef, NotifyMsgHandlerFunc, NULL);
112  * le_msg_OpenSession(sessionRef, SessionOpenHandlerFunc, NULL);
113  * @endcode
114  *
115  * The Legato framework takes care of setting up any IPC connections, as needed (or not, if the
116  * client and server happen to be in the same process).
117  *
118  * When the session opens, the Event Loop will call the "session open handler" call-back function
119  * that was passed into le_msg_OpenSession().
120  *
121  * le_msg_OpenSessionSync() is a synchronous alternative to le_msg_OpenSession(). The difference
122  * is that le_msg_OpenSessionSync() will not return until the session has opened or failed to
123  * open (most likely due to permissions settings).
124  *
125  * le_msg_TryOpenSessionSync() is like le_msg_OpenSessionSync() except that it will not wait
126  * for a server session to become available if it's not already available at the time of the
127  * call. That is, if the client's interface is not bound to any service, or if the service that
128  * it's bound to is not currently advertised by the server, then le_msg_TryOpenSessionSync()
129  * will return an error code.
130  *
131  * @subsection c_messagingClientSending Sending a Message
132  *
133  * Before sending a message, the client must first allocate the message from the session's message
134  * pool using le_msg_CreateMsg(). It can then get a pointer to the payload part of the
135  * message using le_msg_GetPayloadPtr(). Once the message payload is populated, the client sends
136  * the message.
137  *
138  * @code
139  * msgRef = le_msg_CreateMsg(sessionRef);
140  * msgPayloadPtr = le_msg_GetPayloadPtr(msgRef);
141  * msgPayloadPtr->... = ...; // <-- Populate message payload...
142  * @endcode
143  *
144  * If no response is required from the server, the client sends the message using le_msg_Send().
145  * At this point, the client has handed off the message to the messaging system, and the messaging
146  * system will delete the message automatically once it has finished sending it.
147  *
148  * @code
149  * le_msg_Send(msgRef);
150  * @endcode
151  *
152  * If the client expects a response from the server, the client can use
153  * le_msg_RequestResponse() to send their message and specify a callback function to be called
154  * when the response arrives. This callback will be called by the event loop of the thread that
155  * created the session (i.e., the thread that called le_msg_CreateSession()).
156  *
157  * @code
158  * le_msg_RequestResponse(msgRef, ResponseHandlerFunc, NULL);
159  * @endcode
160  *
161  * If the client expects an immediate response from the server, and the client wants to block until
162  * that response is received, it can use le_msg_RequestSyncResponse() instead of
163  * le_msg_RequestResponse(). However, keep in mind that blocking the client thread will
164  * block all event handlers that share that thread. That's why le_msg_RequestSyncResponse() should
165  * only be used when the server is expected to respond immediately, or when the client thread
166  * is not shared by other event handlers.
167  *
168  * @code
169  * responseMsgRef = le_msg_RequestSyncResponse(msgRef);
170  * @endcode
171  *
172  * @warning If the client and server are running in the same thread, and the
173  * client calls le_msg_RequestSyncResponse(), it will return an error immediately, instead of
174  * blocking the thread. If the thread were blocked in this scenario, the server would also be
175  * blocked and would therefore be unable to receive the request and respond to it, resulting in
176  * a deadlock.
177  *
178  * When the client is finished with it, the <b> client must release its reference
179  * to the response message </b> by calling le_msg_ReleaseMsg().
180  *
181  * @code
182  * le_msg_ReleaseMsg(responseMsgRef);
183  * @endcode
184  *
185  * @subsection c_messagingClientReceiving Receiving a Non-Response Message
186  *
187  * When a server sends a message to the client that is not a response to a request from the client,
188  * that non-response message will be passed to the receive handler that the client
189  * registered using le_msg_SetSessionRecvHandler(). In fact, this is the only kind of message
190  * that will result in that receive handler being called.
191  *
192  * @note Some protocols don't include any messages that are not responses to client requests,
193  * which is why it's optional to register a receive handler on the client side.
194  *
195  * The payload of a received message can be accessed using le_msg_GetPayloadPtr(), and the client
196  * can check what session the message arrived through by calling le_msg_GetSession().
197  *
198  * When the client is finished with the message, the <b> client must release its reference
199  * to the message </b> by calling le_msg_ReleaseMsg().
200  *
201  * @code
202  * // Function will be called whenever the server sends us a notification message.
203  * static void NotifyHandlerFunc
204  * (
205  * le_msg_MessageRef_t msgRef, // Reference to the received message.
206  * void* contextPtr // contextPtr passed into le_msg_SetSessionRecvHandler().
207  * )
208  * {
209  * // Process notification message from the server.
210  * myproto_Msg_t* msgPayloadPtr = le_msg_GetPayloadPtr(msgRef);
211  * ...
212  *
213  * // Release the message, now that we are finished with it.
214  * le_msg_ReleaseMsg(msgRef);
215  * }
216  *
217  * COMPONENT_INIT
218  * {
219  * le_msg_ProtocolRef_t protocolRef;
220  * le_msg_SessionRef_t sessionRef;
221  *
222  * protocolRef = le_msg_GetProtocolRef(PROTOCOL_ID, sizeof(myproto_Msg_t));
223  * sessionRef = le_msg_CreateSession(protocolRef, MY_INTERFACE_NAME);
224  * le_msg_SetSessionRecvHandler(sessionRef, NotifyHandlerFunc, NULL);
225  * le_msg_OpenSession(sessionRef, SessionOpenHandlerFunc, NULL);
226  * }
227  * @endcode
228  *
229  * @subsection c_messagingClientClosing Closing Sessions
230  *
231  * When the client is done using a service, it can close the session using le_msg_CloseSession().
232  * This will leave the session object in existence, though, so that it can be opened again
233  * using le_msg_OpenSession().
234  *
235  * @code
236  * le_msg_CloseSession(sessionRef);
237  * @endcode
238  *
239  * To delete a session object, call le_msg_DeleteSession(). This will automatically close the
240  * session, if it's still open (but won't automatically delete any messages).
241  *
242  * @code
243  * le_msg_DeleteSession(sessionRef);
244  * @endcode
245  *
246  * @note If a client process dies while it has a session open, that session will be
247  * automatically closed and deleted by the Legato framework, so there's no need to register process
248  * clean-up handlers or anything like that for this purpose.
249  *
250  * Additionally, clients can choose to call le_msg_SetSessionCloseHandler() to register to be
251  * notified when a session gets closed by the server. Servers often keep state on behalf of their
252  * clients, and if the server closes the session (or if the system closes the session because the
253  * server died), the client most likely will still be operating under the assumption (now false)
254  * that the server is maintaining state on its behalf. If a client is designed to recover from
255  * the server losing its state, the client can register a close handler and handle the close.
256  *
257  * @code
258  * le_msg_SetSessionCloseHandler(sessionRef, SessionCloseHandler, NULL);
259  * @endcode
260  *
261  * However, most clients are not designed to recover from their session being closed by someone
262  * else, so if a close handler is not registered by a client and the session closes for some
263  * reason other than the client calling le_msg_CloseSession(), then the client process
264  * will be terminated.
265  *
266  * @note If the client closes the session, the client-side session close handler will not be called,
267  * even if one is registered.
268  *
269  * @subsection c_messagingClientMultithreading Multithreading
270  *
271  * The Low-Level Messaging API is thread safe, but not async safe.
272  *
273  * When a client creates a session, that session gets "attached" to the thread that created it
274  * (i.e., the thread that called le_msg_CreateSession()). That thread will then call any callbacks
275  * registered for that session.
276  *
277  * Note that this implies that if the client thread that creates the session does not
278  * run the Legato event loop then no callbacks will ever be called for that session.
279  * To work around this, move the session creation to another thread that that uses the Legato event
280  * loop.
281  *
282  * Furthermore, to prevent race conditions, only the thread that is attached to a given session
283  * is allowed to call le_msg_RequestSyncResponse() for that session.
284  *
285  * @subsection c_messagingClientExample Sample Code
286  *
287  * @code
288  * // Function will be called whenever the server sends us a notification message.
289  * static void NotifyHandlerFunc
290  * (
291  * le_msg_MessageRef_t msgRef, // Reference to the received message.
292  * void* contextPtr // contextPtr passed into le_msg_SetSessionRecvHandler().
293  * )
294  * {
295  * // Process notification message from the server.
296  * myproto_Msg_t* msgPayloadPtr = le_msg_GetPayloadPtr(msgRef);
297  * ...
298  *
299  * // Release the message, now that we are finished with it.
300  * le_msg_ReleaseMsg(msgRef);
301  * }
302  *
303  * // Function will be called whenever the server sends us a response message or our
304  * // request-response transaction fails.
305  * static void ResponseHandlerFunc
306  * (
307  * le_msg_MessageRef_t msgRef, // Reference to response message (NULL if transaction failed).
308  * void* contextPtr // contextPtr passed into le_msg_RequestResponse().
309  * )
310  * {
311  * // Check if we got a response.
312  * if (msgRef == NULL)
313  * {
314  * // Transaction failed. No response received.
315  * // This might happen if the server deleted the request without sending a response,
316  * // or if we had registered a "Session End Handler" and the session terminated before
317  * // the response was sent.
318  * LE_ERROR("Transaction failed!");
319  * }
320  * else
321  * {
322  * // Process response message from the server.
323  * myproto_Msg_t* msgPayloadPtr = le_msg_GetPayloadPtr(msgRef);
324  * ...
325  *
326  * // Release the response message, now that we are finished with it.
327  * le_msg_ReleaseMsg(msgRef);
328  * }
329  * }
330  *
331  * // Function will be called when the client-server session opens.
332  * static void SessionOpenHandlerFunc
333  * (
334  * le_msg_SessionRef_t sessionRef, // Reference tp the session that opened.
335  * void* contextPtr // contextPtr passed into le_msg_OpenSession().
336  * )
337  * {
338  * le_msg_MessageRef_t msgRef;
339  * myproto_Msg_t* msgPayloadPtr;
340  *
341  * // Send a request to the server.
342  * msgRef = le_msg_CreateMsg(sessionRef);
343  * msgPayloadPtr = le_msg_GetPayloadPtr(msgRef);
344  * msgPayloadPtr->... = ...; // <-- Populate message payload...
345  * le_msg_RequestResponse(msgRef, ResponseHandlerFunc, NULL);
346  * }
347  *
348  * COMPONENT_INIT
349  * {
350  * le_msg_ProtocolRef_t protocolRef;
351  * le_msg_SessionRef_t sessionRef;
352  *
353  * // Open a session.
354  * protocolRef = le_msg_GetProtocolRef(PROTOCOL_ID, sizeof(myproto_Msg_t));
355  * sessionRef = le_msg_CreateSession(protocolRef, MY_INTERFACE_NAME);
356  * le_msg_SetSessionRecvHandler(sessionRef, NotifyHandlerFunc, NULL);
357  * le_msg_OpenSession(sessionRef, SessionOpenHandlerFunc, NULL);
358  * }
359  * @endcode
360  *
361  * @section c_messagingServerUsage Server Usage Model
362  *
363  * @ref c_messagingServerProcessingMessages <br>
364  * @ref c_messagingServerSendingNonResponse <br>
365  * @ref c_messagingServerCleanUp <br>
366  * @ref c_messagingRemovingService <br>
367  * @ref c_messagingServerMultithreading <br>
368  * @ref c_messagingServerExample
369  *
370  * Servers that wish to offer a service do the following:
371  * -# Get a reference to the protocol they want to use by calling le_msg_GetProtocolRef().
372  * -# Create a Service object using le_msg_CreateService(), passing in the protocol reference and
373  * the service name.
374  * -# Call le_msg_SetServiceRecvHandler() to register a function to handle messages received from
375  * clients.
376  * -# Advertise the service using le_msg_AdvertiseService().
377  *
378  * @code
379  * protocolRef = le_msg_GetProtocolRef(PROTOCOL_ID, sizeof(myproto_Msg_t));
380  * serviceRef = le_msg_CreateService(protocolRef, SERVER_INTERFACE_NAME);
381  * le_msg_SetServiceRecvHandler(serviceRef, RequestMsgHandlerFunc, NULL);
382  * le_msg_AdvertiseService(serviceRef);
383  * @endcode
384  *
385  * Once the service is advertised, clients can open it and start sending it messages. The server
386  * will receive messages via callbacks to the function it registered using
387  * le_msg_SetServiceRecvHandler().
388  *
389  * Servers also have the option of being notified when sessions are opened by clients. They
390  * get this notification by registering a handler function using le_msg_AddServiceOpenHandler().
391  *
392  * @code
393  * // Function will be called whenever a client opens a session with our service.
394  * static void SessionOpenHandlerFunc
395  * (
396  * le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session object.
397  * void* contextPtr ///< [in] contextPtr passed to le_msg_SetSessionOpenHandler().
398  * )
399  * {
400  * // Handle new session opening...
401  * ...
402  * }
403  *
404  * COMPONENT_INIT
405  * {
406  * le_msg_ProtocolRef_t protocolRef;
407  * le_msg_ServiceRef_t serviceRef;
408  *
409  * // Create my service and advertise it.
410  * protocolRef = le_msg_GetProtocolRef(PROTOCOL_ID, sizeof(myproto_Msg_t));
411  * serviceRef = le_msg_CreateService(protocolRef, SERVER_INTERFACE_NAME);
412  * le_msg_AddServiceOpenHandler(serviceRef, SessionOpenHandlerFunc, NULL);
413  * le_msg_AdvertiseService(serviceRef);
414  * }
415  * @endcode
416  *
417  * Both the "Open Handler" and the "Receive Handler" will be called by the Legato event loop in
418  * the thread that registered those handlers (which must also be the same thread that created the
419  * service).
420  *
421  * @subsection c_messagingServerProcessingMessages Processing Messages from Clients
422  *
423  * The payload of any received message can be accessed using le_msg_GetPayloadPtr().
424  *
425  * If a received message does not require a response (i.e., if the client sent it using
426  * le_msg_Send()), then when the server is finished with the message, the server must release
427  * the message by calling le_msg_ReleaseMsg().
428  *
429  * @code
430  * void RequestMsgHandlerFunc
431  * (
432  * le_msg_MessageRef_t msgRef // Reference to the received message.
433  * )
434  * {
435  * myproto_Msg_t* msgPtr = le_msg_GetPayloadPtr(msgRef);
436  * LE_INFO("Received request '%s'", msgPtr->request.string);
437  *
438  * // No response required and I'm done with this message, so release it.
439  * le_msg_ReleaseMsg(msgRef);
440  * }
441  * @endcode
442  *
443  * If a received message requires a response (i.e., if the client sent it using
444  * le_msg_RequestResponse() or le_msg_RequestSyncResponse()), the server must eventually respond
445  * to that message by calling le_msg_Respond() on that message. le_msg_Respond() sends the message
446  * back to the client that sent the request. The response payload is stored inside the same
447  * payload buffer that contained the request payload.
448  *
449  * To do this, the request payload pointer can be cast to a pointer to the response
450  * payload structure, and then the response payload can be written into it.
451  *
452  * @code
453  * void RequestMsgHandlerFunc
454  * (
455  * le_msg_MessageRef_t msgRef // Reference to the received message.
456  * )
457  * {
458  * myproto_RequestMsg_t* requestPtr = le_msg_GetPayloadPtr(msgRef);
459  * myproto_ResponseMsg_t* responsePtr;
460  *
461  * LE_INFO("Received request '%s'", requestPtr->string);
462  *
463  * responsePtr = (myproto_ResponseMsg_t*)requestPtr;
464  * responsePtr->value = Value;
465  * le_msg_Respond(msgRef);
466  * }
467  * @endcode
468  *
469  * Alternatively, the request payload structure and the response payload structure could be placed
470  * into a union together.
471  *
472  * @code
473  * typedef union
474  * {
475  * myproto_Request_t request;
476  * myproto_Response_t response;
477  * }
478  * myproto_Msg_t;
479  *
480  * ...
481  *
482  * void RequestMsgHandlerFunc
483  * (
484  * le_msg_MessageRef_t msgRef // Reference to the received message.
485  * )
486  * {
487  * myproto_Msg_t* msgPtr = le_msg_GetPayloadPtr(msgRef);
488  * LE_INFO("Received request '%s'", msgPtr->request.string);
489  * msgPtr->response.value = Value;
490  * le_msg_Respond(msgRef);
491  * }
492  * @endcode
493  *
494  * @warning Of course, once you've started writing the response payload into the buffer, the request payload
495  * is no longer available, so if you still need it, copy it somewhere else first.
496  *
497  * @note The server doesn't have to send the response back to the client right away. It could
498  * hold onto the request for an indefinite amount of time, for whatever reason.
499  *
500  * Whenever any message is received from a client, the message is associated with the session
501  * through which the client sent it. A reference to the session can be retrieved from the message,
502  * if needed, by calling le_msg_GetSession(). This can be handy for tagging things in the
503  * server's internal data structures that need to be cleaned up when the client closes the session
504  * (see @ref c_messagingServerCleanUp for more on this).
505  *
506  * The function le_msg_NeedsResponse() can be used to check if a received message requires a
507  * response or not.
508  *
509  * @subsection c_messagingServerSendingNonResponse Sending Non-Response Messages to Clients
510  *
511  * If a server wants to send a non-response message to a client, it first needs a reference
512  * to the session that client opened. It could have got the session reference from a previous
513  * message received from the client (by calling le_msg_GetSession() on that message).
514  * Or, it could have got the session reference from a Session Open Handler callback (see
515  * le_msg_AddServiceOpenHandler()). Either way, once it has the session reference, it can call
516  * le_msg_CreateMsg() to create a message from that session's server-side message pool. The
517  * message can then be populated and sent in the same way that a client would send a message
518  * to the server using le_msg_GetPayloadPtr() and le_msg_Send().
519  *
520  * @todo Explain how to configure the sizes of the server-side message pools.
521  *
522  * @code
523  * // Function will be called whenever a client opens a session with our service.
524  * static void SessionOpenHandlerFunc
525  * (
526  * le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session object.
527  * void* contextPtr ///< [in] contextPtr passed to le_msg_SetSessionOpenHandler().
528  * )
529  * {
530  * le_msg_MessageRef_t msgRef;
531  * myproto_Msg_t* msgPayloadPtr;
532  *
533  * // Send a "Welcome" message to the client.
534  * msgRef = le_msg_CreateMsg(sessionRef);
535  * msgPayloadPtr = le_msg_GetPayloadPtr(msgRef);
536  * msgPayloadPtr->... = ...; // <-- Populate message payload...
537  * le_msg_Send(msgRef);
538  * }
539  *
540  * COMPONENT_INIT
541  * {
542  * le_msg_ProtocolRef_t protocolRef;
543  * le_msg_ServiceRef_t serviceRef;
544  *
545  * // Create my service and advertise it.
546  * protocolRef = le_msg_GetProtocolRef(PROTOCOL_ID, sizeof(myproto_Msg_t));
547  * serviceRef = le_msg_CreateService(protocolRef, SERVER_INTERFACE_NAME);
548  * le_msg_AddServiceOpenHandler(serviceRef, SessionOpenHandlerFunc, NULL);
549  * le_msg_AdvertiseService(serviceRef);
550  * }
551  * @endcode
552  *
553  * @subsection c_messagingServerCleanUp Cleaning up when Sessions Close
554  *
555  * If a server keeps state on behalf of its clients, it can call le_msg_AddServiceCloseHandler()
556  * to ask to be notified when clients close sessions with a given service. This allows the server
557  * to clean up any state associated with a given session when the client closes that session
558  * (or when the system closes the session because the client died). The close handler is passed a
559  * session reference, so the server can check its internal data structures and clean up anything
560  * that it has previously tagged with that same session reference.
561  *
562  * @note Servers don't delete sessions. On the server side, sessions are automatically deleted
563  * when they close.
564  *
565  * @subsection c_messagingRemovingService Removing Service
566  *
567  * If a server wants to stop offering a service, it can hide the service by calling
568  * le_msg_HideService(). This will not terminate any sessions that are already open, but it
569  * will prevent clients from opening new sessions until it's advertised again.
570  *
571  * @warning Watch out for race conditions here. It's possible that a client is in the process
572  * of opening a session when you decide to hide your service. In this case, a new session may
573  * open after you hid the service. Be prepared to handle that gracefully.
574  *
575  * The server also has the option to delete the service. This hides the service and closes
576  * all open sessions.
577  *
578  * If a server process dies, the Legato framework will automatically delete all of its services.
579  *
580  * @subsection c_messagingServerMultithreading Multithreading
581  *
582  * The Low-Level Messaging API is thread safe, but not async safe.
583  *
584  * When a server creates a service, that service gets attached to the thread that created it
585  * (i.e., the thread that called le_msg_CreateService()). That thread will call any handler
586  * functions registered for that service.
587  *
588  * This implies that if the thread that creates the service doesn't
589  * run the Legato event loop, then no callbacks will ever be called for that service.
590  * To work around this, you could move the service to another thread that that runs the Legato event
591  * loop.
592  *
593  * @subsection c_messagingServerExample Sample Code
594  *
595  * @code
596  * void RequestMsgHandlerFunc
597  * (
598  * le_msg_MessageRef_t msgRef, // Reference to the received message.
599  * void* contextPtr ///< [in] contextPtr passed to le_msg_SetServiceRecvHandler().
600  * )
601  * {
602  * // Check the message type to decide what to do.
603  * myproto_Msg_t* msgPtr = le_msg_GetPayloadPtr(msgRef);
604  * switch (msgPtr->type)
605  * {
606  * case MYPROTO_MSG_TYPE_SET_VALUE:
607  * // Message doesn't require a response.
608  * Value = msgPtr->...;
609  * le_msg_ReleaseMsg(msgRef);
610  * break;
611  *
612  * case MYPROTO_MSG_TYPE_GET_VALUE:
613  * // Message is a request that requires a response.
614  * // Notice that we just reuse the request message buffer for the response.
615  * msgPtr->... = Value;
616  * le_msg_Respond(msgRef);
617  * break;
618  *
619  * default:
620  * // Unexpected message type!
621  * LE_ERROR("Received unexpected message type %d from session %s.",
622  * msgPtr->type,
623  * le_msg_GetInterfaceName(le_msg_GetSessionInterface(le_msg_GetSession(msgRef))));
624  * le_msg_ReleaseMsg(msgRef);
625  * }
626  * }
627  *
628  * COMPONENT_INIT
629  * {
630  * le_msg_ProtocolRef_t protocolRef;
631  * le_msg_ServiceRef_t serviceRef;
632  *
633  * // Create my service and advertise it.
634  * protocolRef = le_msg_GetProtocolRef(PROTOCOL_ID, sizeof(myproto_Msg_t));
635  * serviceRef = le_msg_CreateService(protocolRef, SERVER_INTERFACE_NAME);
636  * le_msg_SetServiceRecvHandler(serviceRef, RequestMsgHandlerFunc, NULL);
637  * le_msg_AdvertiseService(serviceRef);
638  * }
639  * @endcode
640  *
641  * @section c_messagingStartUp Start Up Sequencing
642  *
643  * Worthy of special mention is the fact that the low-level messaging system can be used to
644  * solve the age-old problem of coordinating the start-up sequence of processes that interact with
645  * each other. Far too often, the start-up sequence of multiple interacting processes is addressed
646  * using hacks like polling or sleeping for arbitrary lengths of time. These solutions can
647  * waste a lot of CPU cycles and battery power, slow down start-up, and (in the case of arbitrary
648  * sleeps) introduce race conditions that can cause failures in the field.
649  *
650  * In Legato, a messaging client can attempt to open a session before the server process has even
651  * started. The client will be notified asynchronously (via callback) when the server advertises
652  * its service.
653  *
654  * In this way, clients are guaranteed to wait for the servers they use, without the inefficiency
655  * of polling, and without having to add code elsewhere to coordinate the start-up sequence.
656  * If there's work that needs to be done by the client at start-up before it opens
657  * a session with the server, the client is allowed to do that work in parallel with the start-up
658  * of the server, so the CPU can be more fully utilized to shorten the overall duration of the
659  * start-up sequence.
660  *
661  * @section c_messagingMemoryManagement Memory Management
662  *
663  * Message buffer memory is allocated and controlled behind the scenes, inside the Messaging API.
664  * This allows the Messaging API to
665  * - take some steps to remove programmer pitfalls,
666  * - provide some built-in remote troubleshooting features
667  * - encapsulate the IPC implementation, allowing for future optimization and porting.
668  *
669  * Each message object is allocated from a session. The sessions' message pool sizes can
670  * be tuned through component and application configuration files and device configuration
671  * settings.
672  *
673  * @todo Explain how to configure message pools.
674  *
675  * Generally speaking, message payload sizes are determined by the protocol that is being used.
676  * Application protocols and the packing of messages into message buffers are the domain of
677  * higher-layers of the software stack. But, at this low layer, servers and clients just declare
678  * the name and version of the protocol, and the size of the largest message in the protocol.
679  * From this, they obtain a protocol reference that they provide to sessions when they create
680  * them.
681  *
682  * @section c_messagingSecurity Security
683  *
684  * Security is provided in the form of authentication and access control.
685  *
686  * Clients cannot open sessions with servers until their client-side interface is "bound" to a
687  * server-side interface (service). The binding thereby provides configuration of both routing and
688  * access control.
689  *
690  * Neither the client-side nor the server-side IPC sockets are named. Therefore, no process other
691  * than the Service Directory has access to these sockets. The Service Directory passes client
692  * connections to the appropriate server based on the binding configuration of the client's interface.
693  *
694  * The binding configuration is kept in the "system" configuration tree, so clients that do not
695  * have write access to the "system" configuration tree have no control over their own binding
696  * configuration. By default, sandboxed apps do not have any access (read or write) to the
697  * "system" configuration tree.
698  *
699  * @section c_messagingGetClientInfo Get Client Info
700  *
701  * In rare cases, a server may wish to check the user ID of the remote client. Generally,
702  * this is not necessary because the IPC system enforces user-based access control restrictions
703  * automatically before allowing an IPC connection to be established. However, sometimes it
704  * may be useful when the service wishes to change the way it behaves, based on what user is
705  * connected to it.
706  *
707  * le_msg_GetClientUserId() can be used to fetch the user ID of the client at the far end of a
708  * given IPC session.
709  *
710  * @code
711  * uid_t clientUserId;
712  * if (le_msg_GetClientUserId(sessionRef, &clientUserId) != LE_OK)
713  * {
714  * // The session must have closed.
715  * ...
716  * }
717  * else
718  * {
719  * LE_INFO("My client has user ID %ud.", clientUserId);
720  * }
721  * @endcode
722  *
723  * le_msg_GetClientProcessId() can be used to fetch the process ID from the client.
724  *
725  * @code
726  * pid_t clientProcessId;
727  * if (le_msg_GetClientProcessId (sessionRef, &clientProcessId) != LE_OK)
728  * {
729  * {
730  * // The session must have closed.
731  * ...
732  * }
733  * else
734  * {
735  * LE_INFO("My client has process ID %ud.", clientProcessId);
736  * }
737  * @endcode
738  *
739  * le_msg_GetClientUserCreds() can be used to fetch the user credentials from the client.
740  *
741  * @code
742  * le_msg_SessionRef_t sessionRef,
743  * uid_t* userIdPtr,
744  * pid_t* processIdPtr
745  * @endcode
746  *
747  * @section c_messagingSendingFileDescriptors Sending File Descriptors
748  *
749  * It's possible to send an open file descriptor through an IPC session by adding an fd to a
750  * message before sending it. On the sender's side, le_msg_SetFd() is used to set the
751  * file descriptor to be sent. On the receiver's side, le_msg_GetFd() is used to get the fd
752  * from the message.
753  *
754  * The IPC API will close the original fd in the sender's address space once it has
755  * been sent, so if the sender still needs the fd open on its side, it should duplicate the fd
756  * (e.g., using dup() ) before sending it.
757  *
758  * On the receiving side, if the fd is not extracted from the message, it will be closed when
759  * the message is released. The fd can only be extracted from the message once. Subsequent
760  * calls to le_msg_GetFd() will return -1.
761  *
762  * @warning DO NOT SEND DIRECTORY FILE DESCRIPTORS. They can be exploited and used to break out of
763  * chroot() jails.
764  *
765  * @section c_messagingFutureEnhancements Future Enhancements
766  *
767  * As an optimization to reduce the number of copies in cases where the sender of a message
768  * already has the message payload of their message assembled somewhere (perhaps as static data
769  * or in another message buffer received earlier from somewhere), a pointer to the payload could
770  * be passed to the message, instead of having to copy the payload into the message.
771  *
772  * @code
773  * msgRef = le_msg_CreateMsg(sessionRef);
774  * le_msg_SetPayloadBuff(msgRef, &msgPayload, sizeof(msgPayload));
775  * msgRef = le_msg_RequestResponse(msgRef, ResponseHandlerFunc, contextPtr);
776  * @endcode
777  *
778  * Perhaps an "iovec" version could be added to do scatter-gather too?
779  *
780  * @section c_messagingDesignNotes Design Notes
781  *
782  * We explored the option of having asynchronous messages automatically released when their
783  * handler function returns, unless the handler calls an "AddRef" function before returning.
784  * That would reduce the amount of code required in the common case. However, we chose to require
785  * that the client release the message explicitly in all cases, because the consequences of using
786  * an invalid reference can be catastrophic and much more difficult to debug than forgetting to
787  * release a message (which will generate pool growth warning messages in the log).
788  *
789  * @section c_messagingTroubleshooting Troubleshooting
790  *
791  * If you're running as the super-user (root), you can trace messaging traffic using @b TBD.
792  * You can also inspect message queues and view lists of outstanding message objects within
793  * processes using the Process Inspector tool.
794  *
795  * If you're leaking messages by forgetting to release them when you're finished with them,
796  * you'll see warning messages in the log indicating your message pool is growing.
797  * You should be able to tell the related messaging service by the name of the expanding pool.
798  *
799  * @todo Finish this section later, when the diagnostic tools become available.
800  *
801  * <HR>
802  *
803  * Copyright (C) Sierra Wireless Inc.
804  */
805 
806 
807 /** @file le_messaging.h
808  *
809  * Legato @ref c_messaging include file.
810  *
811  * Copyright (C) Sierra Wireless Inc.
812  */
813 
814 #ifndef LE_MESSAGING_H_INCLUDE_GUARD
815 #define LE_MESSAGING_H_INCLUDE_GUARD
816 
817 // =======================================
818 // DATA TYPES
819 // =======================================
820 
821 //--------------------------------------------------------------------------------------------------
822 /**
823  * Reference to a protocol.
824  */
825 //--------------------------------------------------------------------------------------------------
826 typedef struct le_msg_Protocol* le_msg_ProtocolRef_t;
827 
828 //--------------------------------------------------------------------------------------------------
829 /**
830  * Reference to an interface's service instance.
831  */
832 //--------------------------------------------------------------------------------------------------
833 typedef struct le_msg_Interface* le_msg_InterfaceRef_t;
834 
835 //--------------------------------------------------------------------------------------------------
836 /**
837  * Reference to a server's service instance.
838  */
839 //--------------------------------------------------------------------------------------------------
840 typedef struct le_msg_Service* le_msg_ServiceRef_t;
841 
842 //--------------------------------------------------------------------------------------------------
843 /**
844  * Reference to a client's service instance.
845  */
846 //--------------------------------------------------------------------------------------------------
847 typedef struct le_msg_ClientInterface* le_msg_ClientInterfaceRef_t;
848 
849 //--------------------------------------------------------------------------------------------------
850 /**
851  * Reference to a client-server session.
852  */
853 //--------------------------------------------------------------------------------------------------
854 typedef struct le_msg_Session* le_msg_SessionRef_t;
855 
856 //--------------------------------------------------------------------------------------------------
857 /**
858  * Reference to a message.
859  */
860 //--------------------------------------------------------------------------------------------------
861 typedef struct le_msg_Message* le_msg_MessageRef_t;
862 
863 //--------------------------------------------------------------------------------------------------
864 /**
865  * Reference to a handler (call-back) function for events that can occur on a service (such as
866  * opening and closing of sessions and receipt of messages).
867  */
868 //--------------------------------------------------------------------------------------------------
869 typedef struct le_msg_SessionEventHandler* le_msg_SessionEventHandlerRef_t;
870 
871 //--------------------------------------------------------------------------------------------------
872 /**
873  * Handler function prototype for handlers that take session references as their arguments.
874  *
875  * See le_msg_SetSessionCloseHandler(), le_msg_AddServiceOpenHandler(), and
876  * le_msg_AddServiceCloseHandler().
877  *
878  * @param sessionRef [in] Reference to the session that experienced the event.
879  *
880  * @param contextPtr [in] Opaque contextPtr value provided when the handler was registered.
881  */
882 //--------------------------------------------------------------------------------------------------
883 typedef void (* le_msg_SessionEventHandler_t)
884 (
885  le_msg_SessionRef_t sessionRef,
886  void* contextPtr
887 );
888 
889 
890 //--------------------------------------------------------------------------------------------------
891 /**
892  * Receive handler function prototype.
893  *
894  * See le_msg_SetSessionRecvHandler() and le_msg_SetServiceRecvHandler().
895  *
896  * @param msgRef [in] Reference to the received message. Don't forget to release this using
897  * le_msg_ReleaseMsg() when you're finished with it.
898  *
899  * @param contextPtr [in] Opaque contextPtr value provided when the handler was registered.
900  */
901 //--------------------------------------------------------------------------------------------------
902 typedef void (* le_msg_ReceiveHandler_t)
903 (
904  le_msg_MessageRef_t msgRef,
905  void* contextPtr
906 );
907 
908 
909 //--------------------------------------------------------------------------------------------------
910 /**
911  * Asynchronous response callback function prototype.
912  *
913  * See le_msg_RequestResponse().
914  *
915  * @param msgRef [in] Reference to the received response message, or NULL if the transaction
916  * failed and no response was received. If not NULL, don't forget to
917  * release it by calling le_msg_ReleaseMsg() when you're finished with it.
918  *
919  * @param contextPtr [in] Opaque contextPtr value passed to le_msg_RequestResponse().
920  */
921 //--------------------------------------------------------------------------------------------------
922 typedef void (* le_msg_ResponseCallback_t)
923 (
924  le_msg_MessageRef_t msgRef,
925  void* contextPtr
926 );
927 
928 
929 // =======================================
930 // PROTOCOL FUNCTIONS
931 // =======================================
932 
933 //--------------------------------------------------------------------------------------------------
934 /**
935  * Gets a reference to refer to a particular version of a particular protocol.
936  *
937  * @return Protocol reference.
938  */
939 //--------------------------------------------------------------------------------------------------
941 (
942  const char* protocolId, ///< [in] String uniquely identifying the the protocol and version.
943  size_t largestMsgSize ///< [in] Size (in bytes) of the largest message in the protocol.
944 );
945 
946 
947 //--------------------------------------------------------------------------------------------------
948 /**
949  * Gets the unique identifier string of the protocol.
950  *
951  * @return Pointer to the protocol identifier (null-terminated, UTF-8 string).
952  */
953 //--------------------------------------------------------------------------------------------------
954 const char* le_msg_GetProtocolIdStr
955 (
956  le_msg_ProtocolRef_t protocolRef ///< [in] Reference to the protocol.
957 );
958 
959 
960 //--------------------------------------------------------------------------------------------------
961 /**
962  * Gets the protocol's maximum message size.
963  *
964  * @return The size, in bytes.
965  */
966 //--------------------------------------------------------------------------------------------------
968 (
969  le_msg_ProtocolRef_t protocolRef ///< [in] Reference to the protocol.
970 );
971 
972 
973 // =======================================
974 // SESSION FUNCTIONS
975 // =======================================
976 
977 //--------------------------------------------------------------------------------------------------
978 /**
979  * Creates a session that will make use of a protocol to talk to a service on a given client
980  * interface.
981  *
982  * @note This doesn't actually attempt to open the session. It just creates the session
983  * object, allowing the client the opportunity to register handlers for the session
984  * before attempting to open it using le_msg_OpenSession().
985  *
986  * @return Session reference.
987  */
988 //--------------------------------------------------------------------------------------------------
990 (
991  le_msg_ProtocolRef_t protocolRef, ///< [in] Reference to the protocol to be used.
992  const char* interfaceName ///< [in] Name of the client-side interface.
993 );
994 
995 
996 //--------------------------------------------------------------------------------------------------
997 /**
998  * Sets an opaque context value (void pointer) that can be retrieved from that session later using
999  * le_msg_GetSessionContextPtr().
1000  */
1001 //--------------------------------------------------------------------------------------------------
1003 (
1004  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1005 
1006  void* contextPtr ///< [in] Opaque value to be returned by
1007  /// le_msg_GetSessionContextPtr().
1008 );
1009 
1010 //--------------------------------------------------------------------------------------------------
1011 /**
1012  * Fetches the opaque context value (void pointer) that was set earlier using
1013  * le_msg_SetSessionContextPtr().
1014  *
1015  * @return Context Ptr value passed into le_msg_SetSessionContextPtr(), or NULL if
1016  * le_msg_SetSessionContextPtr() has not been called for this session yet.
1017  */
1018 //--------------------------------------------------------------------------------------------------
1020 (
1021  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1022 );
1023 
1024 
1025 //--------------------------------------------------------------------------------------------------
1026 /**
1027  * Deletes a session. This will end the session and free up any resources associated
1028  * with it. Any pending request-response transactions in this session will be terminated.
1029  * If the far end has registered a session close handler callback, it will be called.
1030  *
1031  * @note Function is only used by clients. On the server side, sessions are automatically
1032  * deleted when they close.
1033  */
1034 //--------------------------------------------------------------------------------------------------
1036 (
1037  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1038 );
1039 
1040 
1041 //--------------------------------------------------------------------------------------------------
1042 /**
1043  * Sets the receive handler callback function to be called when a non-response message arrives
1044  * on this session.
1045  *
1046  * The handler function will be called by the Legato event loop of the thread that created
1047  * the session.
1048  *
1049  * @note This is a client-only function. Servers are expected to use
1050  * le_msg_SetServiceRecvHandler() instead.
1051  */
1052 //--------------------------------------------------------------------------------------------------
1054 (
1055  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1056  le_msg_ReceiveHandler_t handlerFunc,///< [in] Handler function.
1057  void* contextPtr ///< [in] Opaque pointer value to pass to the handler.
1058 );
1059 
1060 
1061 //--------------------------------------------------------------------------------------------------
1062 /**
1063  * Sets the handler callback function to be called when the session is closed from the other
1064  * end. A local termination of the session will not trigger this callback.
1065  *
1066  * The handler function will be called by the Legato event loop of the thread that created
1067  * the session.
1068  *
1069  * @note
1070  * - If this isn't set on the client side, the framework assumes the client is not designed
1071  * to recover from the server terminating the session, and the client process will terminate
1072  * if the session is terminated by the server.
1073  * - This is a client-only function. Servers are expected to use le_msg_AddServiceCloseHandler()
1074  * instead.
1075  */
1076 //--------------------------------------------------------------------------------------------------
1078 (
1079  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1080  le_msg_SessionEventHandler_t handlerFunc,///< [in] Handler function.
1081  void* contextPtr ///< [in] Opaque pointer value to pass to handler.
1082 );
1083 
1084 
1085 //--------------------------------------------------------------------------------------------------
1086 /**
1087  * Opens a session with a service, providing a function to be called-back when the session is
1088  * open.
1089  *
1090  * @note Only clients open sessions. Servers must patiently wait for clients to open sessions
1091  * with them.
1092  *
1093  * @warning If the client and server don't agree on the maximum message size for the protocol,
1094  * a fatal error will be logged and the client process will be killed.
1095  */
1096 //--------------------------------------------------------------------------------------------------
1097 void le_msg_OpenSession
1098 (
1099  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1100  le_msg_SessionEventHandler_t callbackFunc, ///< [in] Function to be called when open.
1101  /// NULL if no notification is needed.
1102  void* contextPtr ///< [in] Opaque value to pass to the callback.
1103 );
1104 
1105 
1106 //--------------------------------------------------------------------------------------------------
1107 /**
1108  * Synchronously open a session with a service. Blocks until the session is open.
1109  *
1110  * This function logs a fatal error and terminates the calling process if unsuccessful.
1111  *
1112  * @note Only clients open sessions. Servers must patiently wait for clients to open sessions
1113  * with them.
1114  *
1115  * @warning If the client and server do not agree on the maximum message size for the protocol,
1116  * a fatal error will be logged and the client process will be killed.
1117  */
1118 //--------------------------------------------------------------------------------------------------
1120 (
1121  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1122 );
1123 
1124 
1125 //--------------------------------------------------------------------------------------------------
1126 /**
1127  * Synchronously open a session with a service. Does not wait for the session to become available
1128  * if not available..
1129  *
1130  * le_msg_TryOpenSessionSync() differs from le_msg_OpenSessionSync() in that
1131  * le_msg_TryOpenSessionSync() will not wait for a server session to become available if it's
1132  * not already available at the time of the call. That is, if the client's interface is not
1133  * bound to any service, or if the service that it's bound to is not currently advertised
1134  * by the server, then le_msg_TryOpenSessionSync() will return an error code, while
1135  * le_msg_OpenSessionSync() will wait until the binding is created or the server advertises
1136  * the service (or both).
1137  *
1138  * @return
1139  * - LE_OK if the session was successfully opened.
1140  * - LE_NOT_FOUND if the server is not currently offering the service to which the client is bound.
1141  * - LE_NOT_PERMITTED if the client interface is not bound to any service (doesn't have a binding).
1142  * - LE_COMM_ERROR if the Service Directory cannot be reached.
1143  *
1144  * @note Only clients open sessions. Servers' must patiently wait for clients to open sessions
1145  * with them.
1146  *
1147  * @warning If the client and server do not agree on the maximum message size for the protocol,
1148  * a fatal error will be logged and the client process will be killed.
1149  */
1150 //--------------------------------------------------------------------------------------------------
1152 (
1153  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1154 );
1155 
1156 
1157 //--------------------------------------------------------------------------------------------------
1158 /**
1159  * Terminates a session.
1160  */
1161 //--------------------------------------------------------------------------------------------------
1163 (
1164  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1165 );
1166 
1167 
1168 //--------------------------------------------------------------------------------------------------
1169 /**
1170  * Fetches a reference to the protocol that is being used for a given session.
1171  *
1172  * @return Reference to the protocol.
1173  */
1174 //--------------------------------------------------------------------------------------------------
1176 (
1177  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1178 );
1179 
1180 
1181 //--------------------------------------------------------------------------------------------------
1182 /**
1183  * Fetches a reference to the interface that is associated with a given session.
1184  *
1185  * @return Reference to the interface.
1186  */
1187 //--------------------------------------------------------------------------------------------------
1189 (
1190  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1191 );
1192 
1193 //--------------------------------------------------------------------------------------------------
1194 /**
1195  * Fetches the user ID of the client at the far end of a given IPC session.
1196  *
1197  * @warning This function can only be called for the server-side of a session.
1198  *
1199  * @return LE_OK if successful.
1200  * LE_CLOSED if the session has closed.
1201  **/
1202 //--------------------------------------------------------------------------------------------------
1204 (
1205  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1206  uid_t* userIdPtr ///< [out] Ptr to where the result is to be stored on success.
1207 );
1208 
1209 //--------------------------------------------------------------------------------------------------
1210 /**
1211  * Fetches the user PID of the client at the far end of a given IPC session.
1212  *
1213  * @warning This function can only be called for the server-side of a session.
1214  *
1215  * @return LE_OK if successful.
1216  * LE_CLOSED if the session has closed.
1217  **/
1218 //--------------------------------------------------------------------------------------------------
1220 (
1221  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1222  pid_t* processIdPtr ///< [out] Ptr to where the result is to be stored on success.
1223 );
1224 
1225 //--------------------------------------------------------------------------------------------------
1226 /**
1227  * Fetches the user credentials of the client at the far end of a given IPC session.
1228  *
1229  * @warning This function can only be called for the server-side of a session.
1230  *
1231  * @return LE_OK if successful.
1232  * LE_CLOSED if the session has closed.
1233  **/
1234 //--------------------------------------------------------------------------------------------------
1236 (
1237  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1238  uid_t* userIdPtr, ///< [out] Ptr to where the uid is to be stored on success.
1239  pid_t* processIdPtr ///< [out] Ptr to where the pid is to be stored on success.
1240 );
1241 
1242 
1243 
1244 // =======================================
1245 // MESSAGE FUNCTIONS
1246 // =======================================
1247 
1248 //--------------------------------------------------------------------------------------------------
1249 /**
1250  * Creates a message to be sent over a given session.
1251  *
1252  * @return Message reference.
1253  *
1254  * @note
1255  * - Function never returns on failure, there's no need to check the return code.
1256  * - If you see warnings on message pools expanding, then you may be forgetting to
1257  * release the messages you have received.
1258  */
1259 //--------------------------------------------------------------------------------------------------
1261 (
1262  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1263 );
1264 
1265 
1266 //--------------------------------------------------------------------------------------------------
1267 /**
1268  * Adds to the reference count on a message object.
1269  */
1270 //--------------------------------------------------------------------------------------------------
1271 void le_msg_AddRef
1272 (
1273  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1274 );
1275 
1276 
1277 //--------------------------------------------------------------------------------------------------
1278 /**
1279  * Releases a message object, decrementing its reference count. If the reference count has reached
1280  * zero, the message object is deleted.
1281  */
1282 //--------------------------------------------------------------------------------------------------
1283 void le_msg_ReleaseMsg
1284 (
1285  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1286 );
1287 
1288 
1289 //--------------------------------------------------------------------------------------------------
1290 /**
1291  * Checks whether a message requires a response or not.
1292  *
1293  * @note This is intended for use on the server side only.
1294  *
1295  * @return
1296  * - TRUE if the message needs to be responded to using le_msg_Respond().
1297  * - FALSE if the message doesn't need to be responded to, and should be disposed of using
1298  * le_msg_ReleaseMsg() when it's no longer needed.
1299  */
1300 //--------------------------------------------------------------------------------------------------
1302 (
1303  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1304 );
1305 
1306 
1307 //--------------------------------------------------------------------------------------------------
1308 /**
1309  * Gets a pointer to the message payload memory buffer.
1310  *
1311  * @return Pointer to the payload buffer.
1312  *
1313  * @warning Be careful not to overflow this buffer.
1314  */
1315 //--------------------------------------------------------------------------------------------------
1317 (
1318  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1319 );
1320 
1321 
1322 //--------------------------------------------------------------------------------------------------
1323 /**
1324  * Gets the size, in bytes, of the message payload memory buffer.
1325  *
1326  * @return The size, in bytes.
1327  */
1328 //--------------------------------------------------------------------------------------------------
1330 (
1331  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1332 );
1333 
1334 
1335 //--------------------------------------------------------------------------------------------------
1336 /**
1337  * Sets the file descriptor to be sent with this message.
1338  *
1339  * This file descriptor will be closed when the message is sent (or when it's deleted without
1340  * being sent).
1341  *
1342  * At most one file descriptor is allowed to be sent per message.
1343  **/
1344 //--------------------------------------------------------------------------------------------------
1345 void le_msg_SetFd
1346 (
1347  le_msg_MessageRef_t msgRef, ///< [in] Reference to the message.
1348  int fd ///< [in] File descriptor.
1349 );
1350 
1351 
1352 //--------------------------------------------------------------------------------------------------
1353 /**
1354  * Fetches a received file descriptor from the message.
1355  *
1356  * @return The file descriptor, or -1 if no file descriptor was sent with this message or if the
1357  * fd was already fetched from the message.
1358  **/
1359 //--------------------------------------------------------------------------------------------------
1360 int le_msg_GetFd
1361 (
1362  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1363 );
1364 
1365 
1366 //--------------------------------------------------------------------------------------------------
1367 /**
1368  * Sends a message. No response expected.
1369  */
1370 //--------------------------------------------------------------------------------------------------
1371 void le_msg_Send
1372 (
1373  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1374 );
1375 
1376 
1377 //--------------------------------------------------------------------------------------------------
1378 /**
1379  * Gets a reference to the session to which a given message belongs.
1380  *
1381  * @return Session reference.
1382  */
1383 //--------------------------------------------------------------------------------------------------
1385 (
1386  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1387 );
1388 
1389 
1390 //--------------------------------------------------------------------------------------------------
1391 /**
1392  * Requests a response from a server by sending it a request. Doesn't block. Instead,
1393  * provides a callback function to be called when the response arrives or the transaction
1394  * terminates without a response (due to the session terminating or the server deleting the
1395  * request without responding).
1396  *
1397  * @note
1398  * - The thread attached to the session (i.e., thread created by the session)
1399  * will trigger the callback from its main event loop. This means if
1400  * that thread doesn't run its main event loop, it won't trigger the callback.
1401  * - Function can only be used on the client side of a session.
1402  */
1403 //--------------------------------------------------------------------------------------------------
1405 (
1406  le_msg_MessageRef_t msgRef, ///< [in] Reference to the request message.
1407  le_msg_ResponseCallback_t handlerFunc,///< [in] Function to be called when transaction done.
1408  void* contextPtr ///< [in] Opaque value to be passed to handler function.
1409 );
1410 
1411 
1412 //--------------------------------------------------------------------------------------------------
1413 /**
1414  * Requests a response from a server by sending it a request. Blocks until the response arrives
1415  * or until the transaction terminates without a response (i.e., if the session terminates or
1416  * the server deletes the request without responding).
1417  *
1418  * @return Reference to the response message, or NULL if the transaction terminated without a
1419  * response.
1420  *
1421  * @note
1422  * - To prevent deadlocks, this function can only be used on the client side of a session.
1423  * Servers can't use this function.
1424  * - To prevent race conditions, only the client thread attached to the session
1425  * (the thread that created the session) is allowed to perform a synchronous
1426  * request-response transaction.
1427  *
1428  * @warning
1429  * - The calling (client) thread will be blocked until the server responds, so no other
1430  * event handling will happen in that client thread until the response is received (or the
1431  * server dies). This function should only be used when the server is certain
1432  * to respond quickly enough to ensure that it will not cause any event response time
1433  * deadlines to be missed by the client. Consider using le_msg_RequestResponse()
1434  * instead.
1435  * - If this function is used when the client and server are in the same thread, then the
1436  * message will be discarded and NULL will be returned. This is a deadlock prevention
1437  * measure.
1438  */
1439 //--------------------------------------------------------------------------------------------------
1441 (
1442  le_msg_MessageRef_t msgRef ///< [in] Reference to the request message.
1443 );
1444 
1445 
1446 //--------------------------------------------------------------------------------------------------
1447 /**
1448  * Sends a response back to the client that send the request message.
1449  *
1450  * Takes a reference to the request message. Copy the response payload (if any) into the
1451  * same payload buffer that held the request payload, then call le_msg_Respond().
1452  *
1453  * The messaging system will delete the message automatically when it's finished sending
1454  * the response.
1455  *
1456  * @note Function can only be used on the server side of a session.
1457  */
1458 //--------------------------------------------------------------------------------------------------
1459 void le_msg_Respond
1460 (
1461  le_msg_MessageRef_t msgRef ///< [in] Reference to the request message.
1462 );
1463 
1464 
1465 // =======================================
1466 // INTERFACE FUNCTIONS
1467 // =======================================
1468 
1469 //--------------------------------------------------------------------------------------------------
1470 /**
1471  * Creates a service that is accessible using a protocol.
1472  *
1473  * @return Service reference.
1474  */
1475 //--------------------------------------------------------------------------------------------------
1477 (
1478  le_msg_ProtocolRef_t protocolRef, ///< [in] Reference to the protocol to be used.
1479  const char* interfaceName ///< [in] Server-side interface name.
1480 );
1481 
1482 
1483 //--------------------------------------------------------------------------------------------------
1484 /**
1485  * Deletes a service. Any open sessions will be terminated.
1486  *
1487  * @note Server-only function.
1488  */
1489 //--------------------------------------------------------------------------------------------------
1491 (
1492  le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service.
1493 );
1494 
1495 //--------------------------------------------------------------------------------------------------
1496 /**
1497  * Registers a function to be called when clients open sessions with this service.
1498  *
1499  * @note Server-only function.
1500  */
1501 //--------------------------------------------------------------------------------------------------
1503 (
1504  le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service.
1505  le_msg_SessionEventHandler_t handlerFunc,///< [in] Handler function.
1506  void* contextPtr ///< [in] Opaque pointer value to pass to handler.
1507 );
1508 
1509 //--------------------------------------------------------------------------------------------------
1510 /**
1511  * Registers a function to be called whenever one of this service's sessions is closed by
1512  * the client.
1513  *
1514  * @note Server-only function.
1515  */
1516 //--------------------------------------------------------------------------------------------------
1518 (
1519  le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service.
1520  le_msg_SessionEventHandler_t handlerFunc,///< [in] Handler function.
1521  void* contextPtr ///< [in] Opaque pointer value to pass to handler.
1522 );
1523 
1524 //--------------------------------------------------------------------------------------------------
1525 /**
1526  * Remove a function previously registered by le_msg_AddServiceOpenHandler or
1527  * le_msg_AddServiceCloseHandler.
1528  *
1529  * @note This is a server-only function.
1530  */
1531 //--------------------------------------------------------------------------------------------------
1533 (
1534  le_msg_SessionEventHandlerRef_t handlerRef ///< [in] Reference to a previously call of
1535  /// le_msg_AddServiceCloseHandler()
1536 );
1537 
1538 //--------------------------------------------------------------------------------------------------
1539 /**
1540  * Registers a function to be called when messages are received from clients via sessions
1541  * that they have open with this service.
1542  *
1543  * @note Server-only function.
1544  */
1545 //--------------------------------------------------------------------------------------------------
1547 (
1548  le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service.
1549  le_msg_ReceiveHandler_t handlerFunc,///< [in] Handler function.
1550  void* contextPtr ///< [in] Opaque pointer value to pass to the handler.
1551 );
1552 
1553 
1554 //--------------------------------------------------------------------------------------------------
1555 /**
1556  * Associates an opaque context value (void pointer) with a given service that can be retrieved
1557  * later using le_msg_GetServiceContextPtr().
1558  *
1559  * @note Server-only function.
1560  */
1561 //--------------------------------------------------------------------------------------------------
1563 (
1564  le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service.
1565 
1566  void* contextPtr ///< [in] Opaque value to be returned by
1567  /// le_msg_GetServiceContextPtr().
1568 );
1569 
1570 
1571 //--------------------------------------------------------------------------------------------------
1572 /**
1573  * Fetches the opaque context value (void pointer) associated with a specified service using
1574  * le_msg_SetServiceContextPtr().
1575  *
1576  * @return Context pointer value, or NULL if le_msg_SetServiceContextPtr() was never called
1577  * for this service.
1578  *
1579  * @note Server-only function.
1580  */
1581 //--------------------------------------------------------------------------------------------------
1583 (
1584  le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service.
1585 );
1586 
1587 
1588 //--------------------------------------------------------------------------------------------------
1589 /**
1590  * Makes a given service available for clients to find.
1591  *
1592  * @note Server-only function.
1593  */
1594 //--------------------------------------------------------------------------------------------------
1596 (
1597  le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service.
1598 );
1599 
1600 
1601 //--------------------------------------------------------------------------------------------------
1602 /**
1603  * Makes a specified service unavailable for clients to find without terminating any ongoing
1604  * sessions.
1605  *
1606  * @note Server-only function.
1607  */
1608 //--------------------------------------------------------------------------------------------------
1609 void le_msg_HideService
1610 (
1611  le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service.
1612 );
1613 
1614 
1615 //--------------------------------------------------------------------------------------------------
1616 /**
1617  * Fetches a pointer to the name of an interface.
1618  *
1619  * @return Pointer to a null-terminated string.
1620  *
1621  * @warning Pointer returned will remain valid only until the interface is deleted.
1622  */
1623 //--------------------------------------------------------------------------------------------------
1624 const char* le_msg_GetInterfaceName
1625 (
1626  le_msg_InterfaceRef_t interfaceRef ///< [in] Reference to the interface.
1627 );
1628 
1629 
1630 //--------------------------------------------------------------------------------------------------
1631 /**
1632  * Fetches a reference to the protocol supported by a specified interface.
1633  *
1634  * @return Protocol reference.
1635  */
1636 //--------------------------------------------------------------------------------------------------
1638 (
1639  le_msg_InterfaceRef_t interfaceRef ///< [in] Reference to the interface.
1640 );
1641 
1642 
1643 //--------------------------------------------------------------------------------------------------
1644 /**
1645  * Check if the calling thread is currently running a Service's message receive handler;
1646  * if so, return a reference to the message object being handled.
1647  *
1648  * @return Reference to the message being handled, or NULL if no Service message receive handler
1649  * is currently running.
1650  **/
1651 //--------------------------------------------------------------------------------------------------
1653 (
1654  void
1655 );
1656 
1657 
1658 //--------------------------------------------------------------------------------------------------
1659 /**
1660  * Logs an error message (at EMERGENCY level) and:
1661  * - if the caller is running a server-side IPC function, kills the connection to the client
1662  * and returns.
1663  * - if the caller is not running a server-side IPC function, kills the caller (doesn't return).
1664  **/
1665 //--------------------------------------------------------------------------------------------------
1666 #define LE_KILL_CLIENT(formatString, ...) \
1667 { \
1668  le_msg_MessageRef_t msgRef = le_msg_GetServiceRxMsg(); \
1669  LE_FATAL_IF(msgRef == NULL, formatString, ##__VA_ARGS__); \
1670  LE_EMERG(formatString, ##__VA_ARGS__); \
1671  le_msg_CloseSession(le_msg_GetSession(msgRef)); \
1672 }
1673 
1674 #endif // LEGATO_MESSAGING_INCLUDE_GUARD
le_msg_MessageRef_t le_msg_GetServiceRxMsg(void)
void le_msg_AddRef(le_msg_MessageRef_t msgRef)
le_msg_ProtocolRef_t le_msg_GetProtocolRef(const char *protocolId, size_t largestMsgSize)
bool le_msg_NeedsResponse(le_msg_MessageRef_t msgRef)
size_t le_msg_GetProtocolMaxMsgSize(le_msg_ProtocolRef_t protocolRef)
void le_msg_ReleaseMsg(le_msg_MessageRef_t msgRef)
le_result_t le_msg_GetClientUserCreds(le_msg_SessionRef_t sessionRef, uid_t *userIdPtr, pid_t *processIdPtr)
le_result_t
Definition: le_basics.h:35
void * le_msg_GetServiceContextPtr(le_msg_ServiceRef_t serviceRef)
void le_msg_SetServiceRecvHandler(le_msg_ServiceRef_t serviceRef, le_msg_ReceiveHandler_t handlerFunc, void *contextPtr)
void * le_msg_GetSessionContextPtr(le_msg_SessionRef_t sessionRef)
void(* le_msg_SessionEventHandler_t)(le_msg_SessionRef_t sessionRef, void *contextPtr)
Definition: le_messaging.h:884
le_result_t le_msg_TryOpenSessionSync(le_msg_SessionRef_t sessionRef)
void le_msg_AdvertiseService(le_msg_ServiceRef_t serviceRef)
void le_msg_DeleteSession(le_msg_SessionRef_t sessionRef)
const char * le_msg_GetProtocolIdStr(le_msg_ProtocolRef_t protocolRef)
void le_msg_SetSessionRecvHandler(le_msg_SessionRef_t sessionRef, le_msg_ReceiveHandler_t handlerFunc, void *contextPtr)
void * le_msg_GetPayloadPtr(le_msg_MessageRef_t msgRef)
const char * le_msg_GetInterfaceName(le_msg_InterfaceRef_t interfaceRef)
struct le_msg_ClientInterface * le_msg_ClientInterfaceRef_t
Definition: le_messaging.h:847
size_t le_msg_GetMaxPayloadSize(le_msg_MessageRef_t msgRef)
le_msg_SessionRef_t le_msg_GetSession(le_msg_MessageRef_t msgRef)
void le_msg_SetFd(le_msg_MessageRef_t msgRef, int fd)
void(* le_msg_ReceiveHandler_t)(le_msg_MessageRef_t msgRef, void *contextPtr)
Definition: le_messaging.h:903
void le_msg_Send(le_msg_MessageRef_t msgRef)
le_msg_ProtocolRef_t le_msg_GetInterfaceProtocol(le_msg_InterfaceRef_t interfaceRef)
struct le_msg_SessionEventHandler * le_msg_SessionEventHandlerRef_t
Definition: le_messaging.h:869
le_msg_SessionRef_t le_msg_CreateSession(le_msg_ProtocolRef_t protocolRef, const char *interfaceName)
void le_msg_CloseSession(le_msg_SessionRef_t sessionRef)
void le_msg_DeleteService(le_msg_ServiceRef_t serviceRef)
le_msg_ServiceRef_t le_msg_CreateService(le_msg_ProtocolRef_t protocolRef, const char *interfaceName)
le_msg_InterfaceRef_t le_msg_GetSessionInterface(le_msg_SessionRef_t sessionRef)
le_msg_MessageRef_t le_msg_CreateMsg(le_msg_SessionRef_t sessionRef)
le_msg_SessionEventHandlerRef_t le_msg_AddServiceOpenHandler(le_msg_ServiceRef_t serviceRef, le_msg_SessionEventHandler_t handlerFunc, void *contextPtr)
int le_msg_GetFd(le_msg_MessageRef_t msgRef)
struct le_msg_Session * le_msg_SessionRef_t
Definition: le_messaging.h:854
void le_msg_RequestResponse(le_msg_MessageRef_t msgRef, le_msg_ResponseCallback_t handlerFunc, void *contextPtr)
void le_msg_RemoveServiceHandler(le_msg_SessionEventHandlerRef_t handlerRef)
void le_msg_HideService(le_msg_ServiceRef_t serviceRef)
void le_msg_SetSessionContextPtr(le_msg_SessionRef_t sessionRef, void *contextPtr)
le_result_t le_msg_GetClientProcessId(le_msg_SessionRef_t sessionRef, pid_t *processIdPtr)
void le_msg_OpenSession(le_msg_SessionRef_t sessionRef, le_msg_SessionEventHandler_t callbackFunc, void *contextPtr)
void le_msg_SetServiceContextPtr(le_msg_ServiceRef_t serviceRef, void *contextPtr)
le_msg_ProtocolRef_t le_msg_GetSessionProtocol(le_msg_SessionRef_t sessionRef)
void le_msg_Respond(le_msg_MessageRef_t msgRef)
struct le_msg_Protocol * le_msg_ProtocolRef_t
Definition: le_messaging.h:826
void(* le_msg_ResponseCallback_t)(le_msg_MessageRef_t msgRef, void *contextPtr)
Definition: le_messaging.h:923
le_result_t le_msg_GetClientUserId(le_msg_SessionRef_t sessionRef, uid_t *userIdPtr)
le_msg_MessageRef_t le_msg_RequestSyncResponse(le_msg_MessageRef_t msgRef)
struct le_msg_Interface * le_msg_InterfaceRef_t
Definition: le_messaging.h:833
void le_msg_OpenSessionSync(le_msg_SessionRef_t sessionRef)
struct le_msg_Message * le_msg_MessageRef_t
Definition: le_messaging.h:861
struct le_msg_Service * le_msg_ServiceRef_t
Definition: le_messaging.h:840
le_msg_SessionEventHandlerRef_t le_msg_AddServiceCloseHandler(le_msg_ServiceRef_t serviceRef, le_msg_SessionEventHandler_t handlerFunc, void *contextPtr)
void le_msg_SetSessionCloseHandler(le_msg_SessionRef_t sessionRef, le_msg_SessionEventHandler_t handlerFunc, void *contextPtr)