---
# System prepended metadata

title: Routing Analysis

---

# Routing Analysis

**Setup Node**
- Acts like a RESTful API.
    - CreateLoop logic: Add rules to associated nodes.
    - CloseLoop (can be initiated by anyone).
- Not following original specs:
    - Disconnection from app-node doesn't shutdown routes/loops.
    - After each request, there is disconnection to setup node.

**Transport Discovery**

**Transport Manager**
- When a transport screws up?
    - Failed forward -> Send close to Setup Node to close loop/routes.

## Processes

**Router**
- App wants to connect to remote app.
    - App calls app.Setup(config)
        - Creates Linux pipes to enable app-node communication.
        - Creates an app.Addr{} containing remote node PK and remote app port.

    - App calls (*app).Dial(addr)
        - (*app.proto).Send is sends FrameCreateLoop to local-node.

    - router.AppManager.Serve() on local-node calls (*appManger.proto).Serve()
        - handles FrameCreateLoop with (*Router).requestLoop(...)
        - Noise KK handshake is initiated (prepares 1st handshake message).
        - Allocates new port with (*PortManager).Alloc()
        - New empty loop is set via (*PortManager).SetLoop(...) - this awaits a remote tpID and rtID.
        - Find routes via RouteFinder with: (*Router).FetchBestRoutes(...)
        - Sets up routes via SetupNode with: (*Router).setupProto() and (*setup.Proto).CreateLoop()
            - Writes **PacketCreateLoop** to setup-node.
            - Handles **PacketConfirmLoop** (from setup-node) with (*router.Router).confirmLoop()
                - Gets `loop` from `portManager` and fills it with noise and *binding* data.
                - 

    * (*router.TransportManager).CreateTransport(...) is called to create a transport with SetupNode
    * setup.NewSetupProtocol(tr) gets called, this returns a setup.Protocol struct that will use the transport with SetupNode
    * setup.CreateLoop(proto, l), where l is the loop structure previously created, is called. This will be handled by setup node and create the rules along the route.
    * From now on, subsequent packets can be send to the remote using the connection returned by Dial. On the app, they will be handled by (*app).forwardPacket(...)
    * This is then handled by (*router).forwardAppPacket(), and will be sent to the next transport in the route
    * Finally, on the remote node, this is also handled by the same function (*router).forwardAppPacket() but sent to the local app instead

- App wants to close connection to remote app (IVAN).
    * (*app.appConn).Close() sends Close frame to local node.
    * (*router.Router).closeLoop() gets called.
    * (*router.Router).destroyLoop() gets called.
        * Finds rule matching given app.LoppAddr by calling (*rotueTable).RangeRules(...) error. // Note: current implementation always returns nil error
        * The rule that was found in the previous step is removed, so further packages are not forwarded
    * (*router.Router).setupProto() is called to stablish a transport to a setup node
    * setup.LoopData is feeded with the information in addr (*app.LoopAddr)
    * setup.CloseLoop() gets called, which sends a *PacketCloseLoop* to the setup node
    * on the setup node side, (*setupNode).CloseLoop gets called
        * setup.ClosedLoop() gets called, which sends a *ClosedLoop* frame to the other end of the loop (the remote node)
    * on the remote node, in (*router).Serve() routine, a LoopClosed packet is received
        * (*router).loopClosed() gets called. destroyLoop is also called, same that in the third step
        * the remote node notifies it's local app by calling (*portBind).conn.Send(app.FrameClose,...)
    * On the remote app (*app).handleProto(...) receives the app.FrameClose packet
        * (*app).closeConn() gets called, which closes and deletes the received app connection  
 
* Forward app packets.
* Forward remote packets.

**Ideal App to App Node Communication**

## Proposed Changes (1)

### Setup Node

- Setup Node should not be using `transport.Manager`, and should use `dmsg.Client` directly.
- Setup Node should reuse transports. Keep a map: `map[cipher.PubKey]transport.Transport`.

### Routing Table

Currently, we are very dependent on `(routing.Table).RangeRules()` to search the contents of `routing.Table`. We should have specific search functions for each search (add methods to `routing.Table` interface).

Motivation:
This allows for a clearer overview of how we interact with the routing table.

Tasks:
- [ ] Document a list of the aforementioned cases.
- [ ] Make a proposal of how we are to change the `routing.Table` interface.
- [ ] Make relevant changes.
- [ ] Test.

### Data Type Changes

Regarding Loops:
- There is no point in hiding local public key from Apps. We can have a unified `Loop` structure, inclusive of: local/remote pks/ports.

### Decoupled Managed Data Transport

Previously named `transport.managedTransport`, it should now be named `transport.managedDataTp` (as we will need `transport.managedSetupTp` which will function differently).

`transport.managedDataTp` should be self-sufficient, and shouldn't depend on `transport.Manager` for restarts. The motivation for this is to decouple the transport-restart logic. 

```golang
type managedDataTp struct {
    local  cipher.Pubkey
    remote cipher.Pubkey
    public bool
    fac    transport.Factory // also provides tp type.
}
```

**Regarding Transport IDs:**
- Transport IDs should be derived from local/remote public keys and the transport type ONLY. Private data transports are not to be registered.
- The least-significant edge should ALWAYS be the initiator.
- The least-significant edge is responsible for re-establishing the transport.
- Maybe using the `big` module to determine least-significant edge will be simpler.

**Regarding the Settlement Handshake:**
- `managedTransport` should be responsible for performing the settlement handshake.

Regarding Read/Write operations:
- Any failure to a transport's read/write should close the associated route (in which the read/write failed).

Regarding Transport logging:
- We also need to remove read/write log chans. Records of read/write should be to a stored `big.Int` value (protected by mutex), and saved to disc in given intervals. The motivation for this is that with the current implementation, the `readLogChan` and `writeLogChan` is not closed, leading to memory leak.

### Transport Manager

Following these above-mentioned changes, `transport.Manager` should work as follows:

- We should have two maps of `managedTransport`s: `map[uuid.UUID]*managedTransport` and `map[cipher.Pubkey]*managedTransport`.
- The aforementioned maps should be filled with saved transports on startup (even though we haven't actually connected).
- The `managedTransport`s is responsible for retrying connection. 

In addition to this, 

- We should be able to determine the transport use-case at the `transport.Manager` layer (whether it is to be used for setup, data, etc.).
- The list of `setup-node` public keys should be provided to the `transport.Manager` instead of the router.
- ``

## Future considerations (WIP)
- Transports need both a *role* and a *type*.
- Roles are as follows:
    - discovery role (for discovering remotes to establish transports with).
    - finder role (for finding possible routes).
    - setup role (for setting up routes).
    - data role (responsible for forwarding actual data).
    - hypervisor role (for interaction with the hypervisor - previously named manager).

- Packets also need to explicitly state their *role*.
