# How to use services correctly in libcanard

**URL:** <https://forum.opencyphal.org/t/how-to-use-services-correctly-in-libcanard/927>\
**Category:** Libcanard\
**Created:** [August 23, 2020, 8:21am UTC](https://forum.opencyphal.org/t/how-to-use-services-correctly-in-libcanard/927 "2020-08-23T08:21:13Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![anur](https://forum.opencyphal.org/letter_avatar_proxy/v4/letter/a/8e8cbc/32.png) [@anur](https://forum.opencyphal.org/u/anur)\
**Post date:** [August 23, 2020, 8:21am UTC](https://forum.opencyphal.org/t/how-to-use-services-correctly-in-libcanard/927/1 "2020-08-23T08:21:14Z")

</div>

I am a bit stuck in understanding a proper way of using the services.

So if I am correct, I need both publisher and subscriber to perform the service call as there is no callback in v1.0.

At the beginning, I assume we would need a subscriber:

```auto
(void) canardRxSubscribe(&ins, // Subscribe to an arbitrary service response.
                         CanardTransferKindResponse,
                         123, // The Service-ID to subscribe to.
                         1024, // The maximum payload size (max DSDL object size).
                         CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC,
                         &my_service_subscription);

```

Then, if I want to call a service, I just need to create a transfer object and push it (publish):

```auto
const CanardTransfer transfer = {
    .timestamp_usec = transmission_deadline, // Zero if transmission deadline is not limited.
    .priority = CanardPriorityNominal,
    .transfer_kind = CanardTransferKindMessage,
    .port_id = 123, // This is the service-ID.
    .remote_node_id = CANARD_NODE_ID_UNSET,   
    .transfer_id = my_message_transfer_id,
    .payload_size = 47,
    .payload = "\x2D\x00" "Sancho, it strikes me thou art in great fear.",
};

int32_t result = canardTxPush(&ins, &transfer);

```

This will send a message to the remote\_id, the remote\_id will read the service id and transfer id and do some tasks and send back the payload.  
And after publishing this, I would then need to accept a frame:

```auto
CanardTransfer transfer;
const int8_t result = canardRxAccept(&ins,
                                     &received_frame, // The CAN frame received from the bus.
                                     redundant_interface_index, // If the transport is not redundant, use 0.
                                     &transfer);

```

Is that a correct flow? I got this understanding from reading the header file

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [August 23, 2020, 9:01am UTC](https://forum.opencyphal.org/t/how-to-use-services-correctly-in-libcanard/927/2 "2020-08-23T09:01:52Z")

</div>

Not quite. See, we have two kinds of communication: messages and services. Messages can be published and subscribed to; services can be invoked (or called) and provided (or served). You can’t “publish” a service call or “subscribe” to a service, it doesn’t make sense. In Libcanard, there is a bit of an implementation-specific terminology mishap: it uses “subscribe” in the sense of “tell the library that the application wants to receive this kind of transfers”; the mishap is because I couldn’t find a better word to use. Maybe I should have used “listen” instead, like `canardRxListen`? I wonder if we should change it.

So if you want to provide a service, you tell the library to receive service request transfers, like this:

```auto
// Configure the library to listen for register access service requests.
CanardRxSubscription srv_register_access;
(void) canardRxSubscribe(&canard,
                         CanardTransferKindRequest,
                         RegisterAccessServiceID,
                         1024U, // Larger buffers are OK.
                         CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC,
                         &srv_register_access);

```

Then you handle the calls like this:

```auto
// Process received frames, if any.
CanardFrame rxf;
uint8_t buffer[64];
while (socketcanPop(sock, &rxf, sizeof(buffer), buffer, 1000) > 0) // Error handling not implemented
{
    CanardTransfer transfer;
    if (canardRxAccept(&canard, &rxf, 0, &transfer))
    {
        if ((transfer.transfer_kind == CanardTransferKindRequest) &&
            (transfer.port_id == RegisterAccessServiceID))
        {
            handleRegisterAccess(&canard, &transfer);
        }
        free((void*) transfer.payload);
    }
}

```

```auto
static void handleRegisterAccess(CanardInstance* const canard, const CanardTransfer* const request_transfer)
{
    <... business logic not shown ...>
    // Send the response back. Make sure to re-use the same priority and transfer-ID.
    CanardTransfer response_transfer = *request_transfer;
    response_transfer.transfer_kind = CanardTransferKindResponse;
    response_transfer.payload_size = response_size;
    response_transfer.payload = response;
    (void) canardTxPush(canard, &response_transfer);
}

```

When invoking a service, you inverse the logic: listen for service response transfers and emit service request transfers. When receiving the responses, match them by their transfer-ID value.

The examples above have been copy-pasted from this demo: [Automatic configuration of port identifiers](https://forum.opencyphal.org/t/automatic-configuration-of-port-identifiers/840/3)
