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