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  * As a denial-of-service prevention measure, receiving of file descriptors is disabled by
763  * default on servers. To enable receiving of file descriptors, the server must call
764  * le_msg_EnableFdReception() on their service.
765  *
766  * @warning DO NOT SEND DIRECTORY FILE DESCRIPTORS. That can be exploited to break out of chroot()
767  * jails.
768  *
769  * @section c_messagingFutureEnhancements Future Enhancements
770  *
771  * As an optimization to reduce the number of copies in cases where the sender of a message
772  * already has the message payload of their message assembled somewhere (perhaps as static data
773  * or in another message buffer received earlier from somewhere), a pointer to the payload could
774  * be passed to the message, instead of having to copy the payload into the message.
775  *
776  * @code
777  * msgRef = le_msg_CreateMsg(sessionRef);
778  * le_msg_SetPayloadBuff(msgRef, &msgPayload, sizeof(msgPayload));
779  * msgRef = le_msg_RequestResponse(msgRef, ResponseHandlerFunc, contextPtr);
780  * @endcode
781  *
782  * Perhaps an "iovec" version could be added to do scatter-gather too?
783  *
784  * @section c_messagingDesignNotes Design Notes
785  *
786  * We explored the option of having asynchronous messages automatically released when their
787  * handler function returns, unless the handler calls an "AddRef" function before returning.
788  * That would reduce the amount of code required in the common case. However, we chose to require
789  * that the client release the message explicitly in all cases, because the consequences of using
790  * an invalid reference can be catastrophic and much more difficult to debug than forgetting to
791  * release a message (which will generate pool growth warning messages in the log).
792  *
793  * @section c_messagingTroubleshooting Troubleshooting
794  *
795  * If you're running as the super-user (root), you can trace messaging traffic using @b TBD.
796  * You can also inspect message queues and view lists of outstanding message objects within
797  * processes using the Process Inspector tool.
798  *
799  * If you're leaking messages by forgetting to release them when you're finished with them,
800  * you'll see warning messages in the log indicating your message pool is growing.
801  * You should be able to tell the related messaging service by the name of the expanding pool.
802  *
803  * @todo Finish this section later, when the diagnostic tools become available.
804  *
805  * <HR>
806  *
807  * Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.
808  */
809 
810 
811 /** @file le_messaging.h
812  *
813  * Legato @ref c_messaging include file.
814  *
815  * Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.
816  */
817 
818 #ifndef LE_MESSAGING_H_INCLUDE_GUARD
819 #define LE_MESSAGING_H_INCLUDE_GUARD
820 
821 // =======================================
822 // DATA TYPES
823 // =======================================
824 
825 //--------------------------------------------------------------------------------------------------
826 /**
827  * Reference to a protocol.
828  */
829 //--------------------------------------------------------------------------------------------------
830 typedef struct le_msg_Protocol* le_msg_ProtocolRef_t;
831 
832 //--------------------------------------------------------------------------------------------------
833 /**
834  * Reference to an interface's service instance.
835  */
836 //--------------------------------------------------------------------------------------------------
837 typedef struct le_msg_Interface* le_msg_InterfaceRef_t;
838 
839 //--------------------------------------------------------------------------------------------------
840 /**
841  * Reference to a server's service instance.
842  */
843 //--------------------------------------------------------------------------------------------------
844 typedef struct le_msg_Service* le_msg_ServiceRef_t;
845 
846 //--------------------------------------------------------------------------------------------------
847 /**
848  * Reference to a client's service instance.
849  */
850 //--------------------------------------------------------------------------------------------------
851 typedef struct le_msg_ClientInterface* le_msg_ClientInterfaceRef_t;
852 
853 //--------------------------------------------------------------------------------------------------
854 /**
855  * Reference to a client-server session.
856  */
857 //--------------------------------------------------------------------------------------------------
858 typedef struct le_msg_Session* le_msg_SessionRef_t;
859 
860 //--------------------------------------------------------------------------------------------------
861 /**
862  * Reference to a message.
863  */
864 //--------------------------------------------------------------------------------------------------
865 typedef struct le_msg_Message* le_msg_MessageRef_t;
866 
867 //--------------------------------------------------------------------------------------------------
868 /**
869  * Reference to a handler (call-back) function for events that can occur on a service (such as
870  * opening and closing of sessions and receipt of messages).
871  */
872 //--------------------------------------------------------------------------------------------------
873 typedef struct le_msg_SessionEventHandler* le_msg_SessionEventHandlerRef_t;
874 
875 //--------------------------------------------------------------------------------------------------
876 /**
877  * Handler function prototype for handlers that take session references as their arguments.
878  *
879  * See le_msg_SetSessionCloseHandler(), le_msg_AddServiceOpenHandler(), and
880  * le_msg_AddServiceCloseHandler().
881  *
882  * @param sessionRef [in] Reference to the session that experienced the event.
883  *
884  * @param contextPtr [in] Opaque contextPtr value provided when the handler was registered.
885  */
886 //--------------------------------------------------------------------------------------------------
887 typedef void (* le_msg_SessionEventHandler_t)
888 (
889  le_msg_SessionRef_t sessionRef,
890  void* contextPtr
891 );
892 
893 
894 //--------------------------------------------------------------------------------------------------
895 /**
896  * Receive handler function prototype.
897  *
898  * See le_msg_SetSessionRecvHandler() and le_msg_SetServiceRecvHandler().
899  *
900  * @param msgRef [in] Reference to the received message. Don't forget to release this using
901  * le_msg_ReleaseMsg() when you're finished with it.
902  *
903  * @param contextPtr [in] Opaque contextPtr value provided when the handler was registered.
904  */
905 //--------------------------------------------------------------------------------------------------
906 typedef void (* le_msg_ReceiveHandler_t)
907 (
908  le_msg_MessageRef_t msgRef,
909  void* contextPtr
910 );
911 
912 
913 //--------------------------------------------------------------------------------------------------
914 /**
915  * Asynchronous response callback function prototype.
916  *
917  * See le_msg_RequestResponse().
918  *
919  * @param msgRef [in] Reference to the received response message, or NULL if the transaction
920  * failed and no response was received. If not NULL, don't forget to
921  * release it by calling le_msg_ReleaseMsg() when you're finished with it.
922  *
923  * @param contextPtr [in] Opaque contextPtr value passed to le_msg_RequestResponse().
924  */
925 //--------------------------------------------------------------------------------------------------
926 typedef void (* le_msg_ResponseCallback_t)
927 (
928  le_msg_MessageRef_t msgRef,
929  void* contextPtr
930 );
931 
932 
933 // =======================================
934 // PROTOCOL FUNCTIONS
935 // =======================================
936 
937 //--------------------------------------------------------------------------------------------------
938 /**
939  * Gets a reference to refer to a particular version of a particular protocol.
940  *
941  * @return Protocol reference.
942  */
943 //--------------------------------------------------------------------------------------------------
945 (
946  const char* protocolId, ///< [in] String uniquely identifying the the protocol and version.
947  size_t largestMsgSize ///< [in] Size (in bytes) of the largest message in the protocol.
948 );
949 
950 
951 //--------------------------------------------------------------------------------------------------
952 /**
953  * Gets the unique identifier string of the protocol.
954  *
955  * @return Pointer to the protocol identifier (null-terminated, UTF-8 string).
956  */
957 //--------------------------------------------------------------------------------------------------
958 const char* le_msg_GetProtocolIdStr
959 (
960  le_msg_ProtocolRef_t protocolRef ///< [in] Reference to the protocol.
961 );
962 
963 
964 //--------------------------------------------------------------------------------------------------
965 /**
966  * Gets the protocol's maximum message size.
967  *
968  * @return The size, in bytes.
969  */
970 //--------------------------------------------------------------------------------------------------
972 (
973  le_msg_ProtocolRef_t protocolRef ///< [in] Reference to the protocol.
974 );
975 
976 
977 // =======================================
978 // SESSION FUNCTIONS
979 // =======================================
980 
981 //--------------------------------------------------------------------------------------------------
982 /**
983  * Creates a session that will make use of a protocol to talk to a service on a given client
984  * interface.
985  *
986  * @note This doesn't actually attempt to open the session. It just creates the session
987  * object, allowing the client the opportunity to register handlers for the session
988  * before attempting to open it using le_msg_OpenSession().
989  *
990  * @return Session reference.
991  */
992 //--------------------------------------------------------------------------------------------------
994 (
995  le_msg_ProtocolRef_t protocolRef, ///< [in] Reference to the protocol to be used.
996  const char* interfaceName ///< [in] Name of the client-side interface.
997 );
998 
999 
1000 //--------------------------------------------------------------------------------------------------
1001 /**
1002  * Sets an opaque context value (void pointer) that can be retrieved from that session later using
1003  * le_msg_GetSessionContextPtr().
1004  */
1005 //--------------------------------------------------------------------------------------------------
1007 (
1008  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1009 
1010  void* contextPtr ///< [in] Opaque value to be returned by
1011  /// le_msg_GetSessionContextPtr().
1012 );
1013 
1014 //--------------------------------------------------------------------------------------------------
1015 /**
1016  * Fetches the opaque context value (void pointer) that was set earlier using
1017  * le_msg_SetSessionContextPtr().
1018  *
1019  * @return Context Ptr value passed into le_msg_SetSessionContextPtr(), or NULL if
1020  * le_msg_SetSessionContextPtr() has not been called for this session yet.
1021  */
1022 //--------------------------------------------------------------------------------------------------
1024 (
1025  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1026 );
1027 
1028 
1029 //--------------------------------------------------------------------------------------------------
1030 /**
1031  * Deletes a session. This will end the session and free up any resources associated
1032  * with it. Any pending request-response transactions in this session will be terminated.
1033  * If the far end has registered a session close handler callback, it will be called.
1034  *
1035  * @note Function is only used by clients. On the server side, sessions are automatically
1036  * deleted when they close.
1037  */
1038 //--------------------------------------------------------------------------------------------------
1040 (
1041  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1042 );
1043 
1044 
1045 //--------------------------------------------------------------------------------------------------
1046 /**
1047  * Sets the receive handler callback function to be called when a non-response message arrives
1048  * on this session.
1049  *
1050  * The handler function will be called by the Legato event loop of the thread that created
1051  * the session.
1052  *
1053  * @note This is a client-only function. Servers are expected to use
1054  * le_msg_SetServiceRecvHandler() instead.
1055  */
1056 //--------------------------------------------------------------------------------------------------
1058 (
1059  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1060  le_msg_ReceiveHandler_t handlerFunc,///< [in] Handler function.
1061  void* contextPtr ///< [in] Opaque pointer value to pass to the handler.
1062 );
1063 
1064 
1065 //--------------------------------------------------------------------------------------------------
1066 /**
1067  * Sets the handler callback function to be called when the session is closed from the other
1068  * end. A local termination of the session will not trigger this callback.
1069  *
1070  * The handler function will be called by the Legato event loop of the thread that created
1071  * the session.
1072  *
1073  * @note
1074  * - If this isn't set on the client side, the framework assumes the client is not designed
1075  * to recover from the server terminating the session, and the client process will terminate
1076  * if the session is terminated by the server.
1077  * - This is a client-only function. Servers are expected to use le_msg_AddServiceCloseHandler()
1078  * instead.
1079  */
1080 //--------------------------------------------------------------------------------------------------
1082 (
1083  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1084  le_msg_SessionEventHandler_t handlerFunc,///< [in] Handler function.
1085  void* contextPtr ///< [in] Opaque pointer value to pass to handler.
1086 );
1087 
1088 
1089 //--------------------------------------------------------------------------------------------------
1090 /**
1091  * Opens a session with a service, providing a function to be called-back when the session is
1092  * open.
1093  *
1094  * @note Only clients open sessions. Servers must patiently wait for clients to open sessions
1095  * with them.
1096  *
1097  * @warning If the client and server don't agree on the maximum message size for the protocol,
1098  * a fatal error will be logged and the client process will be killed.
1099  */
1100 //--------------------------------------------------------------------------------------------------
1101 void le_msg_OpenSession
1102 (
1103  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1104  le_msg_SessionEventHandler_t callbackFunc, ///< [in] Function to be called when open.
1105  /// NULL if no notification is needed.
1106  void* contextPtr ///< [in] Opaque value to pass to the callback.
1107 );
1108 
1109 
1110 //--------------------------------------------------------------------------------------------------
1111 /**
1112  * Synchronously open a session with a service. Blocks until the session is open.
1113  *
1114  * This function logs a fatal error and terminates the calling process if unsuccessful.
1115  *
1116  * @note Only clients open sessions. Servers must patiently wait for clients to open sessions
1117  * with them.
1118  *
1119  * @warning If the client and server do not agree on the maximum message size for the protocol,
1120  * a fatal error will be logged and the client process will be killed.
1121  */
1122 //--------------------------------------------------------------------------------------------------
1124 (
1125  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1126 );
1127 
1128 
1129 //--------------------------------------------------------------------------------------------------
1130 /**
1131  * Synchronously open a session with a service. Does not wait for the session to become available
1132  * if not available..
1133  *
1134  * le_msg_TryOpenSessionSync() differs from le_msg_OpenSessionSync() in that
1135  * le_msg_TryOpenSessionSync() will not wait for a server session to become available if it's
1136  * not already available at the time of the call. That is, if the client's interface is not
1137  * bound to any service, or if the service that it's bound to is not currently advertised
1138  * by the server, then le_msg_TryOpenSessionSync() will return an error code, while
1139  * le_msg_OpenSessionSync() will wait until the binding is created or the server advertises
1140  * the service (or both).
1141  *
1142  * @return
1143  * - LE_OK if the session was successfully opened.
1144  * - LE_NOT_FOUND if the server is not currently offering the service to which the client is bound.
1145  * - LE_NOT_PERMITTED if the client interface is not bound to any service (doesn't have a binding).
1146  * - LE_COMM_ERROR if the Service Directory cannot be reached.
1147  *
1148  * @note Only clients open sessions. Servers' must patiently wait for clients to open sessions
1149  * with them.
1150  *
1151  * @warning If the client and server do not agree on the maximum message size for the protocol,
1152  * a fatal error will be logged and the client process will be killed.
1153  */
1154 //--------------------------------------------------------------------------------------------------
1156 (
1157  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1158 );
1159 
1160 
1161 //--------------------------------------------------------------------------------------------------
1162 /**
1163  * Terminates a session.
1164  */
1165 //--------------------------------------------------------------------------------------------------
1167 (
1168  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1169 );
1170 
1171 
1172 //--------------------------------------------------------------------------------------------------
1173 /**
1174  * Fetches a reference to the protocol that is being used for a given session.
1175  *
1176  * @return Reference to the protocol.
1177  */
1178 //--------------------------------------------------------------------------------------------------
1180 (
1181  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1182 );
1183 
1184 
1185 //--------------------------------------------------------------------------------------------------
1186 /**
1187  * Fetches a reference to the interface that is associated with a given session.
1188  *
1189  * @return Reference to the interface.
1190  */
1191 //--------------------------------------------------------------------------------------------------
1193 (
1194  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1195 );
1196 
1197 //--------------------------------------------------------------------------------------------------
1198 /**
1199  * Fetches the user ID of the client at the far end of a given IPC session.
1200  *
1201  * @warning This function can only be called for the server-side of a session.
1202  *
1203  * @return LE_OK if successful.
1204  * LE_CLOSED if the session has closed.
1205  **/
1206 //--------------------------------------------------------------------------------------------------
1208 (
1209  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1210  uid_t* userIdPtr ///< [out] Ptr to where the result is to be stored on success.
1211 );
1212 
1213 //--------------------------------------------------------------------------------------------------
1214 /**
1215  * Fetches the user PID of the client at the far end of a given IPC session.
1216  *
1217  * @warning This function can only be called for the server-side of a session.
1218  *
1219  * @return LE_OK if successful.
1220  * LE_CLOSED if the session has closed.
1221  **/
1222 //--------------------------------------------------------------------------------------------------
1224 (
1225  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1226  pid_t* processIdPtr ///< [out] Ptr to where the result is to be stored on success.
1227 );
1228 
1229 //--------------------------------------------------------------------------------------------------
1230 /**
1231  * Fetches the user credentials of the client at the far end of a given IPC session.
1232  *
1233  * @warning This function can only be called for the server-side of a session.
1234  *
1235  * @return LE_OK if successful.
1236  * LE_CLOSED if the session has closed.
1237  **/
1238 //--------------------------------------------------------------------------------------------------
1240 (
1241  le_msg_SessionRef_t sessionRef, ///< [in] Reference to the session.
1242  uid_t* userIdPtr, ///< [out] Ptr to where the uid is to be stored on success.
1243  pid_t* processIdPtr ///< [out] Ptr to where the pid is to be stored on success.
1244 );
1245 
1246 
1247 
1248 // =======================================
1249 // MESSAGE FUNCTIONS
1250 // =======================================
1251 
1252 //--------------------------------------------------------------------------------------------------
1253 /**
1254  * Creates a message to be sent over a given session.
1255  *
1256  * @return Message reference.
1257  *
1258  * @note
1259  * - Function never returns on failure, there's no need to check the return code.
1260  * - If you see warnings on message pools expanding, then you may be forgetting to
1261  * release the messages you have received.
1262  */
1263 //--------------------------------------------------------------------------------------------------
1265 (
1266  le_msg_SessionRef_t sessionRef ///< [in] Reference to the session.
1267 );
1268 
1269 
1270 //--------------------------------------------------------------------------------------------------
1271 /**
1272  * Adds to the reference count on a message object.
1273  */
1274 //--------------------------------------------------------------------------------------------------
1275 void le_msg_AddRef
1276 (
1277  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1278 );
1279 
1280 
1281 //--------------------------------------------------------------------------------------------------
1282 /**
1283  * Releases a message object, decrementing its reference count. If the reference count has reached
1284  * zero, the message object is deleted.
1285  */
1286 //--------------------------------------------------------------------------------------------------
1287 void le_msg_ReleaseMsg
1288 (
1289  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1290 );
1291 
1292 
1293 //--------------------------------------------------------------------------------------------------
1294 /**
1295  * Checks whether a message requires a response or not.
1296  *
1297  * @note This is intended for use on the server side only.
1298  *
1299  * @return
1300  * - TRUE if the message needs to be responded to using le_msg_Respond().
1301  * - FALSE if the message doesn't need to be responded to, and should be disposed of using
1302  * le_msg_ReleaseMsg() when it's no longer needed.
1303  */
1304 //--------------------------------------------------------------------------------------------------
1306 (
1307  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1308 );
1309 
1310 
1311 //--------------------------------------------------------------------------------------------------
1312 /**
1313  * Gets a pointer to the message payload memory buffer.
1314  *
1315  * @return Pointer to the payload buffer.
1316  *
1317  * @warning Be careful not to overflow this buffer.
1318  */
1319 //--------------------------------------------------------------------------------------------------
1321 (
1322  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1323 );
1324 
1325 
1326 //--------------------------------------------------------------------------------------------------
1327 /**
1328  * Gets the size, in bytes, of the message payload memory buffer.
1329  *
1330  * @return The size, in bytes.
1331  */
1332 //--------------------------------------------------------------------------------------------------
1334 (
1335  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1336 );
1337 
1338 
1339 //--------------------------------------------------------------------------------------------------
1340 /**
1341  * Sets the file descriptor to be sent with this message.
1342  *
1343  * This file descriptor will be closed when the message is sent (or when it's deleted without
1344  * being sent).
1345  *
1346  * At most one file descriptor is allowed to be sent per message.
1347  **/
1348 //--------------------------------------------------------------------------------------------------
1349 void le_msg_SetFd
1350 (
1351  le_msg_MessageRef_t msgRef, ///< [in] Reference to the message.
1352  int fd ///< [in] File descriptor.
1353 );
1354 
1355 
1356 //--------------------------------------------------------------------------------------------------
1357 /**
1358  * Fetches a received file descriptor from the message.
1359  *
1360  * @return The file descriptor, or -1 if no file descriptor was sent with this message or if the
1361  * fd was already fetched from the message.
1362  **/
1363 //--------------------------------------------------------------------------------------------------
1364 int le_msg_GetFd
1365 (
1366  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1367 );
1368 
1369 
1370 //--------------------------------------------------------------------------------------------------
1371 /**
1372  * Sends a message. No response expected.
1373  */
1374 //--------------------------------------------------------------------------------------------------
1375 void le_msg_Send
1376 (
1377  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1378 );
1379 
1380 
1381 //--------------------------------------------------------------------------------------------------
1382 /**
1383  * Gets a reference to the session to which a given message belongs.
1384  *
1385  * @return Session reference.
1386  */
1387 //--------------------------------------------------------------------------------------------------
1389 (
1390  le_msg_MessageRef_t msgRef ///< [in] Reference to the message.
1391 );
1392 
1393 
1394 //--------------------------------------------------------------------------------------------------
1395 /**
1396  * Requests a response from a server by sending it a request. Doesn't block. Instead,
1397  * provides a callback function to be called when the response arrives or the transaction
1398  * terminates without a response (due to the session terminating or the server deleting the
1399  * request without responding).
1400  *
1401  * @note
1402  * - The thread attached to the session (i.e., thread created by the session)
1403  * will trigger the callback from its main event loop. This means if
1404  * that thread doesn't run its main event loop, it won't trigger the callback.
1405  * - Function can only be used on the client side of a session.
1406  */
1407 //--------------------------------------------------------------------------------------------------
1409 (
1410  le_msg_MessageRef_t msgRef, ///< [in] Reference to the request message.
1411  le_msg_ResponseCallback_t handlerFunc,///< [in] Function to be called when transaction done.
1412  void* contextPtr ///< [in] Opaque value to be passed to handler function.
1413 );
1414 
1415 
1416 //--------------------------------------------------------------------------------------------------
1417 /**
1418  * Requests a response from a server by sending it a request. Blocks until the response arrives
1419  * or until the transaction terminates without a response (i.e., if the session terminates or
1420  * the server deletes the request without responding).
1421  *
1422  * @return Reference to the response message, or NULL if the transaction terminated without a
1423  * response.
1424  *
1425  * @note
1426  * - To prevent deadlocks, this function can only be used on the client side of a session.
1427  * Servers can't use this function.
1428  * - To prevent race conditions, only the client thread attached to the session
1429  * (the thread that created the session) is allowed to perform a synchronous
1430  * request-response transaction.
1431  *
1432  * @warning
1433  * - The calling (client) thread will be blocked until the server responds, so no other
1434  * event handling will happen in that client thread until the response is received (or the
1435  * server dies). This function should only be used when the server is certain
1436  * to respond quickly enough to ensure that it will not cause any event response time
1437  * deadlines to be missed by the client. Consider using le_msg_RequestResponse()
1438  * instead.
1439  * - If this function is used when the client and server are in the same thread, then the
1440  * message will be discarded and NULL will be returned. This is a deadlock prevention
1441  * measure.
1442  */
1443 //--------------------------------------------------------------------------------------------------
1445 (
1446  le_msg_MessageRef_t msgRef ///< [in] Reference to the request message.
1447 );
1448 
1449 
1450 //--------------------------------------------------------------------------------------------------
1451 /**
1452  * Sends a response back to the client that send the request message.
1453  *
1454  * Takes a reference to the request message. Copy the response payload (if any) into the
1455  * same payload buffer that held the request payload, then call le_msg_Respond().
1456  *
1457  * The messaging system will delete the message automatically when it's finished sending
1458  * the response.
1459  *
1460  * @note Function can only be used on the server side of a session.
1461  */
1462 //--------------------------------------------------------------------------------------------------
1463 void le_msg_Respond
1464 (
1465  le_msg_MessageRef_t msgRef ///< [in] Reference to the request message.
1466 );
1467 
1468 
1469 // =======================================
1470 // INTERFACE FUNCTIONS
1471 // =======================================
1472 
1473 //--------------------------------------------------------------------------------------------------
1474 /**
1475  * Creates a service that is accessible using a protocol.
1476  *
1477  * @return Service reference.
1478  */
1479 //--------------------------------------------------------------------------------------------------
1481 (
1482  le_msg_ProtocolRef_t protocolRef, ///< [in] Reference to the protocol to be used.
1483  const char* interfaceName ///< [in] Server-side interface name.
1484 );
1485 
1486 
1487 //--------------------------------------------------------------------------------------------------
1488 /**
1489  * Deletes a service. Any open sessions will be terminated.
1490  *
1491  * @note Server-only function.
1492  */
1493 //--------------------------------------------------------------------------------------------------
1495 (
1496  le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service.
1497 );
1498 
1499 //--------------------------------------------------------------------------------------------------
1500 /**
1501  * Registers a function to be called when clients open sessions with this service.
1502  *
1503  * @note Server-only function.
1504  */
1505 //--------------------------------------------------------------------------------------------------
1507 (
1508  le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service.
1509  le_msg_SessionEventHandler_t handlerFunc,///< [in] Handler function.
1510  void* contextPtr ///< [in] Opaque pointer value to pass to handler.
1511 );
1512 
1513 //--------------------------------------------------------------------------------------------------
1514 /**
1515  * Registers a function to be called whenever one of this service's sessions is closed by
1516  * the client.
1517  *
1518  * @note Server-only function.
1519  */
1520 //--------------------------------------------------------------------------------------------------
1522 (
1523  le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service.
1524  le_msg_SessionEventHandler_t handlerFunc,///< [in] Handler function.
1525  void* contextPtr ///< [in] Opaque pointer value to pass to handler.
1526 );
1527 
1528 //--------------------------------------------------------------------------------------------------
1529 /**
1530  * Remove a function previously registered by le_msg_AddServiceOpenHandler or
1531  * le_msg_AddServiceCloseHandler.
1532  *
1533  * @note This is a server-only function.
1534  */
1535 //--------------------------------------------------------------------------------------------------
1537 (
1538  le_msg_SessionEventHandlerRef_t handlerRef ///< [in] Reference to a previously call of
1539  /// le_msg_AddServiceCloseHandler()
1540 );
1541 
1542 //--------------------------------------------------------------------------------------------------
1543 /**
1544  * Registers a function to be called when messages are received from clients via sessions
1545  * that they have open with this service.
1546  *
1547  * @note Server-only function.
1548  */
1549 //--------------------------------------------------------------------------------------------------
1551 (
1552  le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service.
1553  le_msg_ReceiveHandler_t handlerFunc,///< [in] Handler function.
1554  void* contextPtr ///< [in] Opaque pointer value to pass to the handler.
1555 );
1556 
1557 
1558 //--------------------------------------------------------------------------------------------------
1559 /**
1560  * Associates an opaque context value (void pointer) with a given service that can be retrieved
1561  * later using le_msg_GetServiceContextPtr().
1562  *
1563  * @note Server-only function.
1564  */
1565 //--------------------------------------------------------------------------------------------------
1567 (
1568  le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service.
1569 
1570  void* contextPtr ///< [in] Opaque value to be returned by
1571  /// le_msg_GetServiceContextPtr().
1572 );
1573 
1574 
1575 //--------------------------------------------------------------------------------------------------
1576 /**
1577  * Fetches the opaque context value (void pointer) associated with a specified service using
1578  * le_msg_SetServiceContextPtr().
1579  *
1580  * @return Context pointer value, or NULL if le_msg_SetServiceContextPtr() was never called
1581  * for this service.
1582  *
1583  * @note Server-only function.
1584  */
1585 //--------------------------------------------------------------------------------------------------
1587 (
1588  le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service.
1589 );
1590 
1591 
1592 //--------------------------------------------------------------------------------------------------
1593 /**
1594  * Makes a given service available for clients to find.
1595  *
1596  * @note Server-only function.
1597  */
1598 //--------------------------------------------------------------------------------------------------
1600 (
1601  le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service.
1602 );
1603 
1604 
1605 //--------------------------------------------------------------------------------------------------
1606 /**
1607  * Makes a specified service unavailable for clients to find without terminating any ongoing
1608  * sessions.
1609  *
1610  * @note Server-only function.
1611  */
1612 //--------------------------------------------------------------------------------------------------
1613 void le_msg_HideService
1614 (
1615  le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service.
1616 );
1617 
1618 
1619 //--------------------------------------------------------------------------------------------------
1620 /**
1621  * Fetches a pointer to the name of an interface.
1622  *
1623  * @return Pointer to a null-terminated string.
1624  *
1625  * @warning Pointer returned will remain valid only until the interface is deleted.
1626  */
1627 //--------------------------------------------------------------------------------------------------
1628 const char* le_msg_GetInterfaceName
1629 (
1630  le_msg_InterfaceRef_t interfaceRef ///< [in] Reference to the interface.
1631 );
1632 
1633 
1634 //--------------------------------------------------------------------------------------------------
1635 /**
1636  * Fetches a reference to the protocol supported by a specified interface.
1637  *
1638  * @return Protocol reference.
1639  */
1640 //--------------------------------------------------------------------------------------------------
1642 (
1643  le_msg_InterfaceRef_t interfaceRef ///< [in] Reference to the interface.
1644 );
1645 
1646 
1647 //--------------------------------------------------------------------------------------------------
1648 /**
1649  * Check if the calling thread is currently running a Service's message receive handler;
1650  * if so, return a reference to the message object being handled.
1651  *
1652  * @return Reference to the message being handled, or NULL if no Service message receive handler
1653  * is currently running.
1654  **/
1655 //--------------------------------------------------------------------------------------------------
1657 (
1658  void
1659 );
1660 
1661 
1662 //--------------------------------------------------------------------------------------------------
1663 /**
1664  * Logs an error message (at EMERGENCY level) and:
1665  * - if the caller is running a server-side IPC function, kills the connection to the client
1666  * and returns.
1667  * - if the caller is not running a server-side IPC function, kills the caller (doesn't return).
1668  **/
1669 //--------------------------------------------------------------------------------------------------
1670 #define LE_KILL_CLIENT(formatString, ...) \
1671 { \
1672  le_msg_MessageRef_t msgRef = le_msg_GetServiceRxMsg(); \
1673  LE_FATAL_IF(msgRef == NULL, formatString, ##__VA_ARGS__); \
1674  LE_EMERG(formatString, ##__VA_ARGS__); \
1675  le_msg_CloseSession(le_msg_GetSession(msgRef)); \
1676 }
1677 
1678 #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:888
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:851
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:907
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:873
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:858
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:830
void(* le_msg_ResponseCallback_t)(le_msg_MessageRef_t msgRef, void *contextPtr)
Definition: le_messaging.h:927
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:837
void le_msg_OpenSessionSync(le_msg_SessionRef_t sessionRef)
struct le_msg_Message * le_msg_MessageRef_t
Definition: le_messaging.h:865
struct le_msg_Service * le_msg_ServiceRef_t
Definition: le_messaging.h:844
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)