# 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*.