# Exercise 203: microReticulum negotiated Link ping-pong

This exercise builds on Exercises 201 and 202.

Exercise 201 used a `PLAIN` destination to prove that Reticulum packets can move over the LoRa interface. Exercise 202 used announced `SINGLE` destinations to prove identity discovery and encrypted destination-addressed packets.

Exercise 203 adds a negotiated Reticulum `Link`. The nodes still begin by announcing `SINGLE` destinations. After a peer announce is learned, one node opens a `Link` to the peer's `SINGLE` destination. When the link becomes active, both nodes exchange encrypted link packets.

```text
Identity -> SINGLE destination -> announce -> peer learns identity/path -> LINKREQUEST/LRPROOF handshake -> ACTIVE Link -> link DATA packets
```

With AMY and BOB, AMY initiates the link and BOB accepts it. For other pairs, the lower lexical node label initiates, which avoids both peers opening duplicate links at the same time.

## Build, upload, and monitor

In one console:

```bash
source /home/jlpoole/rnsenv/bin/activate
cd /usr/local/src/microreticulum/microReticulumTbeam
pio run -d exercises/203_microReticulum_link_ping_pong -e amy -t upload --upload-port /dev/ttytAMY && \
pio device monitor -d exercises/203_microReticulum_link_ping_pong -e amy
```

In another console:

```bash
source /home/jlpoole/rnsenv/bin/activate
cd /usr/local/src/microreticulum/microReticulumTbeam
pio run -d exercises/203_microReticulum_link_ping_pong -e bob -t upload --upload-port /dev/ttytBOB && \
pio device monitor -d exercises/203_microReticulum_link_ping_pong -e bob
```

The `platformio.ini` maps each environment to its stable USB symlink, so this shorter form should also work once the symlinks exist:

```bash
pio run -d exercises/203_microReticulum_link_ping_pong -e amy -t upload
pio device monitor -d exercises/203_microReticulum_link_ping_pong -e amy
```

## Expected output

At startup each node announces its `SINGLE` destination:

```text
Local SINGLE destination: 2f6c...
TX ANNOUNCE: Amy
```

After the peer is learned, the selected initiator opens a link:

```text
RX ANNOUNCE: label=Bob hash=91a4...
TX LINKREQUEST: opening link to Bob
```

The peer reports the inbound negotiated link, and the initiator reports active status:

```text
RX LINK: inbound link established
LINK ACTIVE: initiator link established
```

Once active, both nodes send and receive packets over the negotiated link:

```text
TX LINK: Amy -> Bob iter=0
RX LINK: Amy -> Bob iter=0 | RSSI=-42.0 SNR=9.5
```

If both nodes only print announces, verify Exercise 202 first. If announces work but no link becomes active, the failure is in the `LINKREQUEST` / `LRPROOF` handshake layer rather than raw LoRa or destination discovery.

## Notes

- The link is established on top of the announced `SINGLE` destination from Exercise 202.
- The identity is generated on each boot, so destination hashes can change after reset.
- Once the link is active, the sketch stops periodic announces. This keeps the console focused on link traffic and avoids repeatedly refreshing a path that both peers already know.
- If microReticulum reports `Path table already has destination ...; keeping existing path entry`, that means a later announce referenced a destination already present in the path table. A real storage failure is still reported as `Failed to add destination ... to path table!`.
- This is the first exercise in the sequence that proves Reticulum negotiated link establishment over the LoRa interface.
