# High Level Overview

## **This Page**

1. [Purpose](#bkmrk-1%29-purpose "1) Purpose")
2. [High-level design](#bkmrk-2%29-high-level-design "2) High-level design")
3. [External dependencies](#bkmrk-3%29-external-dependen "3) External dependencies")

---

## **Purpose**

<span style="white-space: pre-wrap;">The packet dispatcher is used to decode protobuf frames. </span>

Application code usually wants:

- **strongly typed**<span style="white-space: pre-wrap;"> decoded payloads</span>
- **one handler**<span style="white-space: pre-wrap;"> per packet type</span>
- **decoupling** between input reception and packet processing

This module solves that by:

1. **receiving** <span style="white-space: pre-wrap;">a raw protobuf </span>`<span class="editor-theme-code">receive_frame</span>`
2. **decoding** <span style="white-space: pre-wrap;">it into </span>`<span class="editor-theme-code">PBEnvelope</span>`
3. **determining** `<span class="editor-theme-code">which_payload</span>`
4. **finding** <span style="white-space: pre-wrap;">the corresponding handler </span>
5. **copying** <span style="white-space: pre-wrap;">the decoded payload </span>**into** <span style="white-space: pre-wrap;">that handler’s (freeRTOS) </span>**queue**
6. <span style="white-space: pre-wrap;">letting a dedicated task </span>**call callback** for this handler

<span style="white-space: pre-wrap;">In short, each packet type gets its own handler callback, queue and task. That makes the system modular and easy to extend, at least conceptually. So the module acts as a bridge between </span>**transport-level bytes** <span style="white-space: pre-wrap;">and </span>**application-level packet handler.**

<p class="callout success"><span style="white-space: pre-wrap;">In practical terms, it is a </span>**decode-and-dispatch layer**<span style="white-space: pre-wrap;"> between an </span>**input source**<span style="white-space: pre-wrap;"> that receives raw bytes and </span>**a set of application handlers**<span style="white-space: pre-wrap;"> that want already-decoded payloads</span></p>

<p class="callout warning"><span style="white-space: pre-wrap;">The implementation has </span>**some assumptions and hazards**<span style="white-space: pre-wrap;"> that absolutely need to be understood before you start messing with its internal structure.</span></p>

---

## **High-level design**

The design has three major parts:

- Global handler registry  
    <span style="white-space: pre-wrap;">The global handler registry contains an </span>**array** <span style="white-space: pre-wrap;">of packet handler tasks (see </span>[packet\_handler\_config\_t](https://bookstack.roboteamtwente.nl/link/229#bkmrk-b.-packet_handler_co)<span style="white-space: pre-wrap;"> ). A packet handler task configures (amongst other things) the callback function for a certain type of packet.</span>  
    <span style="white-space: pre-wrap;">The array of configs is given by the caller at initialization time. This array is stored globally and </span>**used by dispatch logic for packet type lookup**.

<p class="callout info"><span style="white-space: pre-wrap;">What we call a </span>**packet** is a raw protobuf.  
<span style="white-space: pre-wrap;">What we call a </span>**handler** is a (configuration of a) callback function for a specific protobuf/packet.</p>

- One queue &amp; task per packet type  
    <span style="white-space: pre-wrap;">The dispatcher takes each handler configuration and creates </span>**1 FreeRTOS queue** and **1 FreeRTOS task**<span style="white-space: pre-wrap;">. When receiving messages, the dispatcher enqueues decoded payloads into the corresponding queue. </span>**The corresponding task blocks that queue and calls the handler callback** (which saved in the registry).

<p class="callout success"><span style="white-space: pre-wrap;">The task takes the </span>**correspoding** payload out of the queue and calls the specified handler/callback function. By corresponding we mean that each type of packet has their own queue.</p>

- Shared decode step  
    <span style="white-space: pre-wrap;">Incoming frames are decoded into a global static </span>`<span class="editor-theme-code">PBEnvelope</span>`<span style="white-space: pre-wrap;"> object: </span>`<span class="editor-theme-code">static PBEnvelope DecodingEnvelopeCurrent;</span>`.  
    <span style="white-space: pre-wrap;">The dispatcher then copies </span>`<span class="editor-theme-code">DecodingEnvelopeCurrent.payload</span>`<span style="white-space: pre-wrap;"> into a handler queue. </span>**This detail matters a lot for concurrency and payload sizing.**

#### NOTE on handler task lifecycles

<p class="callout danger">Each handler task is intended to live forever.</p>

<span style="white-space: pre-wrap;">A task is responsible for passing a specific packet type from the corresponding queue to the correct callback. As stated above, a handler task </span>**gets created by the dispatcher** <span style="white-space: pre-wrap;">according to the configuration (see </span>[packet\_handler\_config\_t](https://bookstack.roboteamtwente.nl/link/229#bkmrk-b.-packet_handler_co)<span style="white-space: pre-wrap;"> ) done by the caller when initializing the dispatcher.</span>

##### Lifecycle

1. **Created by** `<span class="editor-theme-code">PacketHandlerStart()</span>`<span style="white-space: pre-wrap;"> </span>  
    <span style="white-space: pre-wrap;">As part of </span>[PacketDispatcherInit()](#bkmrk-c.-packetdispatcheri "c. PacketDispatcherInit()").
2. **Validate configuration**  
    <span style="white-space: pre-wrap;">Task\_name, handler and queue need to be present for it to work. These params are set in </span>[packet\_handler\_config\_t](https://bookstack.roboteamtwente.nl/link/229#bkmrk-b.-packet_handler_co)<span style="white-space: pre-wrap;">. If you use the </span>[macros](https://bookstack.roboteamtwente.nl/books/embedded-infastructure/page/helper-macros-for-handler-config "Helper Macros for Static Handler Config"), this should be fine.
3. **Allocate local packet buffer**
4. **Block forever on queue receive**  
    So, when we receive a packet in the corresponding queue, we wait for it to be handled.
5. **Process packets as they arrive**  
    The processing is done by the callback specified in the handler.

##### Terminates only if...

- <span style="white-space: pre-wrap;">config is </span>**invalid**
- <span style="white-space: pre-wrap;">queue is </span>**null**
- <span style="white-space: pre-wrap;">heap </span>**allocation fails** <span style="white-space: pre-wrap;">for packet buffer </span>

In those cases it deletes itself.

<p class="callout danger">At the moment, there is no restart or supervision mechanism in this module!</p>

---

## **External dependencies**

<p class="callout warning">This is not a standalone module. It sits in the middle of RTOS tasking, protobuf decoding, and transport reception.</p>

This module depends on:

<table id="bkmrk-specifically-used-pi"><colgroup><col style="width: 303px;"></col><col style="width: 279px;"></col></colgroup><tbody><tr><td></td><td>**specifically used pieces**

</td></tr><tr><td>FreeRTOS

</td><td>- `<span class="editor-theme-code">xQueueCreateStatic</span>`
- `<span class="editor-theme-code">xQueueReceive</span>`
- `<span class="editor-theme-code">xQueueSend</span>`
- `<span class="editor-theme-code">xTaskCreate</span>`
- `<span class="editor-theme-code">vTaskDelete</span>`

</td></tr><tr><td>nanopb / protobuf decoding

</td><td>- `<span class="editor-theme-code">pb_istream_from_buffer</span>`
- `<span class="editor-theme-code">pb_decode</span>`

</td></tr><tr><td>`<span class="editor-theme-code">PBEnvelope</span>`<span style="white-space: pre-wrap;"> generated protobuf definitions</span>

</td><td>- `<span class="editor-theme-code">PBEnvelope_fields</span>`
- `<span class="editor-theme-code">PBEnvelope_size</span>`

</td></tr><tr><td>[Logging library](https://bookstack.roboteamtwente.nl/books/embedded-infastructure/page/logging "Logging")

</td><td></td></tr><tr><td>[Result Library](https://bookstack.roboteamtwente.nl/books/embedded-infastructure/page/result-library "Result Library")

</td><td></td></tr><tr><td>`<span class="editor-theme-code">stm/ethernet_udp.h</span>`

</td><td>- `<span class="editor-theme-code">receive_frame</span>`

</td></tr></tbody></table>