Server IPC Callback/Handler/Event


#1

Hi everyone,

I’m trying to use the event-driven programing provide by Legato, I manage to create a client IPC which send data to a server IPC and everything work fine (api/cdef/adef files, system project …). But now i would like to get a response from my server IPC without blocking my client (my server can send a response immediately or 1 hour later).

I read the different concepts : .api Syntax , C language support. I understand their is callbacks but I have no idea how to use them on the server.c.

Can someone explain/show to me ? :slight_smile:

Regards.
Guillaume


#2

Hi GuillaumeCarel

I find this confusing as well. Maybe you need an event

http://legato.io/legato-docs/latest/apiFilesSyntax.html#apiFilesSyntax_event

and a HANDLER in the .api?

http://legato.io/legato-docs/latest/apiFilesSyntax.html#apiFilesSyntax_handler

Cheers

John


#3

Hi john,

Thank you for you reply, I think that what i need, but my question is how my server trigger this event ?

Guillaume.


#4

Hi Guillaume

Is this the info you need?

http://legato.io/legato-docs/latest/basicEvents.html

John


#5

Oh i see ! Yeah that what i need thank you very much !

I’m an engineering student and Event-driven programming and Legato are new for me. So it’s really difficult for me to make link between the concepts. Once again thanks for your help John :slight_smile:

Guillaume


#6

Hi John,

Have you use the [async] option for an IPC server ?

I have an incomprehensible conflicting types error on my function that send data from my client to my server when I only add this option to my server .cdef. The server has working fine in the classic “sync mode”.

I checked the auto-generated interfaces.h file on my server but the types are good …

Regards.


#7

I just add a return in the COMPONENT_INIT and now I have :


#8

Hi, Guillaume,

When you use the [async] option on the server side, it changes the function prototypes.

When using the default (synchronous) mode, the response message is sent to the client when the server returns from the request handing function. But when using asynchronous mode, the response message is not sent to the client until the server calls a separate “respond” function. The request handling function is passed an additional “command reference” (not my favourite name for that, because it’s not called a “command” anywhere else, but that’s what we have). This command reference is passed to the “respond” function, so the IPC code knows which request is being responded to.

Cheers,

–Jen


#9

Hi Jen,

I don’t understand how to use the le_eventLoop.h between applications, the section (Layered Publish-Subscribe Handlers) is too dry for me …

  • What I have : a client that retrieve the GPS location and send it with IPC to a server that send them via UDP to an other device --> work fine :white_check_mark:
  • What I want : a server that callback a client’s function without blocking the client
  • What I understand : my client will send to the server the handler that will be called back, and it’s the server that register this handler with le_eventLoop

Like the exemple event/handler in .api I wrote my file :

Like the exemple Layered Publish-Subscribe Handlers I copied the sample (hello is the name of the interface udp.api):

I don’t understand the link between the code of the .api file and the ServerComponent.c , how do I link the event/handler of the .api file to the event/handler of the ServerComponent.c ? How am I suppose to add the server function hello_registerHandler to the udp.api with this strange return type : ChangeHandlerRef_t ?

Regards.
Guillaume


#10

Hi, Guillaume,

The short answer is that you implement this function in your server:

//--------------------------------------------------------------------------------------------------
/**
 * Add handler function for EVENT 'hello_ResponseEvent'
 */
//--------------------------------------------------------------------------------------------------
hello_ResponseEventHandlerRef_t hello_AddResponseEventHandler
(
    hello_ServerResponseFunc_t handlerPtr,
    void* contextPtr
)
{
    return (hello_ResponseEventHandlerRef_t)hello_registerHandler(handlerPtr, contextPtr);
}

This function will be called by the server-side, auto-generated IPC code when it receives the event handler registration request message from the client side. The typecast is all you need to make the compiler happy about the pointer types being different. Because these are treated as opaque pointer types by the IPC code, the only restrictions on their values are:

  1. They must be the same size (sizeof(void*))
  2. NULL (0) is reserved as an “invalid” value that is used to indicate that the registration failed.

Keep in mind that the layered pub-sub events thing is separate from the IPC. It’s really just intended to manage a list of registered event handler functions for you so you don’t have to build your own list of registered handlers and iterate over that when you need to call all the handlers. It can be used without IPC if you want (to implement regular C APIs that have callbacks, for example). Sorry, that layered pub-sub event stuff is a bit ugly. I’ve never really been happy with the way that turned out. But, for now, that’s what we have. Suggestions for improvement are welcome.

If you want to see exactly how the IPC code works, you can run ifgen and ask it to generate the code for your .api file. E.g.,

ifgen --gen-all --name-prefix hello udp.api

If you open up hello_server.c and look for the function Handle_hello_AddResponseEventHandler(), you’ll see that it calls hello_AddResponseEventHandler(). The mk tools will make sure that hello_server.c is generated, compiled, and linked with your server executable, so as long as you provide an implementation of hello_AddResponseEventHandler() in your server it will be called when the Add Response Event Handler message arrives from the client.

Also, you’ll see that hello_server.c contains a function called AsyncResponse_hello_AddResponseEventHandler(). This is the actual handler function that gets passed to your hello_AddResponseEventHandler() (and becomes your second-layer handler). So, when you call the handler function that you were given, it actually calls this generated code, which sends a message to the client side to tell it to call your real client-side function. Have a look at hello_client.c to see how that side works.

Cheers,

–Jen