Client agent

Interprocess communication code default_client.c

This article is mainly some client-side agent related codes, mainly the creation of the agent, the acquisition of service name and feature name in the agent, etc
File path: \ distributedschedule_samgr_lite\samgr_endpoint\source\default_client.c

Bedding of data structure

The implementation of this part of the client needs some structures to support
saname is mainly the name of the service and feature

//Identify service name and function name
struct SaName {
    const char *service;        //name of service
    const char *feature;        //name of feature
};
//Header information of client agent
struct IClientHeader {
    SaName key;             //The ID of the sa, including the name of the service and the name of the feature
    SvcIdentity target;     //Access address of the target (server)
    uint32 deadId;
    const IpcContext *context;  //IPC communication context
};
//Client proxy entry
struct IClientEntry {
    //Interface inheritance
    INHERIT_IUNKNOWNENTRY(IClientProxy);
};
#pragma pack(1)
struct IDefaultClient {
    IClientHeader header;   //Client proxy header
    IClientEntry entry;     //Client proxy channel
};
#pragma pack()
//Default proxy entry
static const IClientEntry DEFAULT_ENTRY = {CLIENT_IPROXY_BEGIN, .Invoke = ProxyInvoke, IPROXY_END};

Function implementation

1. Creation of client agent
This function is to create a client proxy, but it will get the relevant parameter interface. First, query the main endpoint for the access address of the specified service and function. If an invalid value is returned, the service and function do not exist or are not registered. If the query is successful, it will be used as the target address of the current client agent. Then use the factory method to create the corresponding client agent and update the members of the agent. Finally, register the death callback function and return the proxy interface.
Introduction to parameters:

  • Context: IPC communication context
  • Service: service name
  • feature: function name
IUnknown *SAMGR_CreateIProxy(const IpcContext *context, const char *service, const char *feature)
{
    //Send a request to query the access address of the specified service and function to the main endpoint through the endpoint of the current process
    SvcIdentity identity = QueryIdentity(context, service, feature);
    if (identity.handle == INVALID_INDEX) {
        //The access address returned is an invalid value
        return NULL;
    }
    //Use the factory method to create client proxies for services and functions
    IDefaultClient *client = SAMGR_CreateIClient(service, feature, sizeof(IClientHeader));
    if (client == NULL) {
        //Failed to create through the creator. Apply for memory creation by yourself
        client = SAMGR_Malloc(sizeof(IDefaultClient));
        if (client == NULL) {
            return NULL;
        }
        //Configure the default portal for the client agent
        client->entry = DEFAULT_ENTRY;
    }
    //Assign a value to the client header. An IClientHeader pointer is defined here for the convenience of assignment
    IClientHeader *header = &client->header;
    header->target = identity;      //Specifies the access address of the target that the client agent is targeting
    //The key value is used to identify which service and function the current agent is associated with
    header->key.service = service;  //Service name
    header->key.feature = feature;  //Function name
    header->context = context;      //IPC context of the current process, identifying the entry of IPC communication access
    //Register the death callback function, which is triggered when the process disconnects from the remote service
    (void)RegisterDeathCallback(context, identity, OnServiceExit, client, &header->deadId);
    IClientEntry *entry = &client->entry;
    //Assign a value to the function pointer in the client's entry
    entry->iUnknown.Invoke = ProxyInvoke;   //Function of agent
    entry->iUnknown.AddRef = AddRef;        //Increase reference count
    entry->iUnknown.Release = Release;      //Reduce reference count
    //Get IUnknown interface object from entry
    return GET_IUNKNOWN(*entry);
}

2. Get service and feature access addresses
Query the client proxy interface according to the service name and function name, and the proxy interface is associated with the access address of the service and function. Get the IDefaultClient member in the interface, and finally get the access address of services and functions from the member header field.
Parameter introduction:

  • Service: service name
  • feature: function name
SvcIdentity SAMGR_GetRemoteIdentity(const char *service, const char *feature)
{
    SvcIdentity identity = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
    //Find the specified proxy interface according to the service name and function name. If it exists, it returns; if it does not exist, it is created and returned
    IUnknown *iUnknown = SAMGR_FindServiceApi(service, feature);
    if (iUnknown == NULL) {
        return identity;
    }
    IClientProxy *proxy = NULL;
    //Query the subclass objects of the IUnknown interface of the specified version, and save the results in the proxy
    if (iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&proxy) != EC_SUCCESS || proxy == NULL) {
        return identity;
    }
    //Gets the IDefaultClient member of the agent
    struct IDefaultClient *client = GET_OBJECT(proxy, struct IDefaultClient, entry.iUnknown);
    //Get the target address information in the header
    identity = client->header.target;
    //Release reference
    proxy->Release((IUnknown *)proxy);
    return identity;
}

3. Get information in saname
We mentioned earlier that the name information of the service and feature is stored in the saname. This function is to obtain the information in the saname in the proxy interface. Because header.key is a data of saname type, here is the name of the service name and feature

SaName *SAMGR_GetSAName(const IUnknown *proxy)
{
    //Gets the IDefaultClient member of the proxy interface
    IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown);
    //Returns the SaName information in the header
    return &(client->header.key);
}

4. Compare whether the stored contents of the two key s are consistent
We know that the key stores the saname type structure information, mainly the service name and special certificate name. Sometimes the two keys may store the same information, but there are different structure name information, or the two variables need to be compared to see whether they are consistent. At this time, we define the function to judge whether the two can be consistent.
The main principle is based on the strcmp function in the basic function library of c language. Because the two variable information are arrays of char type, we can directly compare the corresponding strings in the structure.

int SAMGR_CompareSAName(const SaName *key1, const SaName *key2)
{
    //If equal, return 0
    if (key1 == key2) {
        return 0;
    }
    //Judge whether the service addresses of key1 and key2 are the same
    if (key1->service != key2->service) {
        //If not, the content pointed to is compared
        int ret = strcmp(key1->service, key2->service);
        if (ret != 0) {
            //Returns if not equal
            return ret;
        }
    }
    //The service s of key1 and key2 point to the same value
    //Compare whether the address pointed to by the feature is the same
    if (key1->feature == key2->feature) {
        return 0;
    }
    //The service cannot be NULL, but the subordinate functions of the service can be NULL. Therefore, it is necessary to determine whether the feature points to NULL
    if (key1->feature == NULL) {
        return -1;
    }
    if (key2->feature == NULL) {
        return 1;
    }
    //Compare what the feature pointer points to
    return strcmp(key1->feature, key2->feature);
}

This is part of the code, and the rest will be supplemented later!

Posted on Thu, 28 Oct 2021 14:29:22 -0400 by Sooz719