IPC Client & Server reference


#1

Hi,

I have 3 components (1 server & 2 clients) executed in differents applications connected between IPCs. What I need is to know from server side what client is connected. I know the next Legato functions but I don’t know well how to use it:

MyServer_GetServiceRef() 
le_msg_GetClientUserId(sessionRef, &clientUserId);

I’ve check the le_msg_GetClientUserId example in the Legato documentation but I can’t implement well. This is the code:

le_msg_SessionRef_t *sessionRef;
*sessionRef = MyServer_GetServiceRef();
uid_t clientUserId;
if (le_msg_GetClientUserId(sessionRef, &clientUserId) != LE_OK)
{
}
else
{
    LE_INFO("My client has user ID %ud.", clientUserId);
}

The error: error: passing argument 1 of ‘le_msg_GetClientUserId’ from incompatible pointer type [-Werror]

Probably I’m getting service reference wrong but I’ve tried to do it with:

le_msg_SessionRef_t sessionRef;
sessionRef = MyServer_GetServiceRef();
uid_t clientUserId;
if (le_msg_GetClientUserId(sessionRef, &clientUserId) != LE_OK)
//...

In this case, the error: error: passing argument 1 of ‘le_msg_GetClientUserId’ from incompatible pointer type [-Werror]

What is the right way?

Note: If i force sessionRef to a integer value not using the function “MyServer_GetServiceRef()” it seems to work but I think is not the right way.

le_msg_SessionRef_t sessionRef = 0;
uid_t clientUserId;
if (le_msg_GetClientUserId(sessionRef, &clientUserId) != LE_OK)
//...

#2

Hi,

Finally, the code worked doing this:

    le_msg_SessionRef_t sessionRef = 0;
    sessionRef = MyServer_GetClientSessionRef();

    uid_t clientUserId;
    if (le_msg_GetClientUserId(sessionRef, &clientUserId) != LE_OK)
    {
    }
    else
    {
        LE_INFO("My client has user ID %ud", clientUserId);
    }

The difference is the sessionRef initialization.

But now I have another question. I’m trying to do the same in other application. This application is unsandboxed and I can’t get the ID (only if I put the application sandboxed). Is this a Legato limitation?

Note: MyServer component is running within an unsandboxed application.

Thank you


#3

When running as a unsandboxed app your UserID is 0, or root.

If you need a way to distinguish clients in this case, then perhaps you can add something to your API?

ENUM client_types
{
    CLIENT_A,
    CLIENT_B
};

FUNCTION SetClientId(client_types clientType);
le_msg_SessionRef_t ClientARef = NULL;
le_msg_SessionRef_t ClientBRef = NULL;

void MyServer_SetClientId(MyServer_client_types clientType)
{
    le_msg_SessionRef_t clientSessionRef = MyServer_GetClientSessionRef();

    switch (clientType)
    {
        case MYSERVER_CLIENT_A:
            ClientARef = clientSessionRef;
            break;

        case MYSERVER_CLIENT_B:
            ClientBRef = clientSessionRef;
            break;
    }
}

-Kelly


#4

Hi,

Thanks for your support and your suggestion. I’m trying to solve in this way but I’ve never created a ENUM or other within an .api file. Following the instructions and the documentation here:
http://www.legato.io/legato-docs/15_01_1/language_independent_syntax.html

This is what I have:

ENUM client_types
{
    CLIENT_A,
    CLIENT_B
};

FUNCTION SetClientId
(
        client_types clientType IN
)
void MyServer_SetClientId(MyServer_client_types_t clientType) { .. }

I had to change MyServer_client_types -> MyServer_client_types_t because the code didn’t compile. Is it right?

The reason is because of the content of this file: MyServer_server.h

typedef enum
{
    MYSERVER_CLIENT_A,
    MYSERVER_CLIENT_B
}
MyServer_client_type_t;

So, at compilation time, I don’t have any errors but when I’m trying to execute the client (and server is running) this is the log file:

02:20:53 =ERR= | serviceDirectory[613]/serviceDirectory_exe T=main | serviceDirectory.c DispatchToServer() 739 | Client (uid 1012 'appMyClient', pid 28896) disagrees with server (uid 0 'root', pid 28561) on protocol ID of service 'MyClient'
02:20:53 *EMR* | MyClient[28896]/framework T=main | messagingSession.c ReceiveSessionOpenResponse() 735 | Unexpected server response (-5).
02:20:53 *CRT* | supervisor[608]/security T=main | app.c app_SigChildHandler() 1635 | The process 'MyClient' in app 'MyClient' has faulted and will be ignored in accordance with its fault policy.

What I’m doing wrong?

Note: I’m not using this function from the client side but myclient_interface.h file contains:

typedef enum { MYCLIENT_CLIENT_A, MYCLIENT_CLIENT_B } myclient_client_type_t;

void myclient_SetClientId
(
    myclient_client_type_t client
        ///< [IN]
);

Thanks

Daniel


#5

Hi,

From the runtime error, there is a mismatch between the client and server. This error usually happens if you makes changes to the .api file but don’t update both the client and server. Did you rebuild and re-install both the client and the server?

Also, related to your original question, you said that the server needs to know which client is connected. What does it do with this information? Is it just for local data on the server, or for something else?

– Zeljko


#6

Hi zblazek,

I don’t understand why could it be a rebuild error… because I have in my workspace the server component and the app which is linked and the same for the client component and app. So when I compile, I’m compiling all applications and components.

Regarding to the original question, this is needed because server will share different information depending on which client is connected or asking for data. Does it make sense?

Daniel


#7

Another option then is to export 2 instances of your API.

So, in your server you could have something along the lines of:

provides:
{
    api:
    {
        instA = myApi.api
        instB = myApi.api
    }
}

Then in your server.c

int instA_Server(void)
{
    return ClientAResponse;
}

int instB_Server(void)
{
    return ClientBResponse;
}

And you can bind the clients to their respective service instances.