diff --git a/.gitignore b/.gitignore index 3f69f2ac2..1b685c0bd 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ .idea/ /skywire.json +/*-config.json /apps/ /skywire/ /local/ diff --git a/pkg/node/rpc.go b/pkg/node/rpc.go index 5e0c0fa3d..110b5122d 100644 --- a/pkg/node/rpc.go +++ b/pkg/node/rpc.go @@ -34,28 +34,6 @@ type RPC struct { node *Node } -// RPCClient represents a RPC Client implementation. -type RPCClient interface { - Summary() (*Summary, error) - - Apps() ([]*AppState, error) - StartApp(appName string) error - StopApp(appName string) error - SetAutoStart(appName string, autostart bool) error - - TransportTypes() ([]string, error) - Transports(types []string, pks []cipher.PubKey, logs bool) ([]*TransportSummary, error) - Transport(tid uuid.UUID) (*TransportSummary, error) - AddTransport(remote cipher.PubKey, tpType string, public bool, timeout time.Duration) (*TransportSummary, error) - RemoveTransport(tid uuid.UUID) error - - RoutingRules() ([]*RoutingEntry, error) - RoutingRule(key routing.RouteID) (routing.Rule, error) - AddRoutingRule(rule routing.Rule) (routing.RouteID, error) - SetRoutingRule(key routing.RouteID, rule routing.Rule) error - RemoveRoutingRule(key routing.RouteID) error -} - /* <<< NODE SUMMARY >>> */ @@ -273,3 +251,33 @@ func (r *RPC) RemoveRoutingRule(key *routing.RouteID, _ *struct{}) error { <<< LOOPS MANAGEMENT >>> >>> TODO(evanlinjin): Implement. */ + +// LoopInfo is a human-understandable representation of a loop. +type LoopInfo struct { + AppRule routing.Rule + FwdRule routing.Rule +} + +// Loops retrieves loops via rules of the routing table. +func (r *RPC) Loops(_ *struct{}, out *[]LoopInfo) error { + var loops []LoopInfo + err := r.node.rt.RangeRules(func(_ routing.RouteID, rule routing.Rule) (next bool) { + if rule.Type() == routing.RuleApp { + loops = append(loops, LoopInfo{AppRule: rule}) + } + return true + }) + if err != nil { + return err + } + for i, l := range loops { + fwdRID := l.AppRule.RouteID() + rule, err := r.node.rt.Rule(fwdRID) + if err != nil { + return err + } + loops[i].FwdRule = rule + } + *out = loops + return nil +} diff --git a/pkg/node/rpc_client.go b/pkg/node/rpc_client.go index 033e75656..39c5ad5ca 100644 --- a/pkg/node/rpc_client.go +++ b/pkg/node/rpc_client.go @@ -15,6 +15,30 @@ import ( "github.com/skycoin/skywire/pkg/transport" ) +// RPCClient represents a RPC Client implementation. +type RPCClient interface { + Summary() (*Summary, error) + + Apps() ([]*AppState, error) + StartApp(appName string) error + StopApp(appName string) error + SetAutoStart(appName string, autostart bool) error + + TransportTypes() ([]string, error) + Transports(types []string, pks []cipher.PubKey, logs bool) ([]*TransportSummary, error) + Transport(tid uuid.UUID) (*TransportSummary, error) + AddTransport(remote cipher.PubKey, tpType string, public bool, timeout time.Duration) (*TransportSummary, error) + RemoveTransport(tid uuid.UUID) error + + RoutingRules() ([]*RoutingEntry, error) + RoutingRule(key routing.RouteID) (routing.Rule, error) + AddRoutingRule(rule routing.Rule) (routing.RouteID, error) + SetRoutingRule(key routing.RouteID, rule routing.Rule) error + RemoveRoutingRule(key routing.RouteID) error + + Loops() ([]LoopInfo, error) +} + // RPCClient provides methods to call an RPC Server. // It implements RPCClient type rpcClient struct { @@ -137,6 +161,13 @@ func (rc *rpcClient) RemoveRoutingRule(key routing.RouteID) error { return rc.Call("RemoveRoutingRule", &key, &struct{}{}) } +// Loops calls Loops. +func (rc *rpcClient) Loops() ([]LoopInfo, error) { + var loops []LoopInfo + err := rc.Call("Loops", &struct{}{}, &loops) + return loops, err +} + // MockRPCClient mocks RPCClient. type mockRPCClient struct { s *Summary @@ -164,19 +195,26 @@ func NewMockRPCClient(r *rand.Rand, maxTps int, maxRules int) (cipher.PubKey, RP ruleExp := time.Now().Add(time.Hour * 24) for i := 0; i < r.Intn(maxRules+1); i++ { remotePK, _ := cipher.GenerateKeyPair() - var rule routing.Rule if r.Int()%2 == 0 { var lpRaw, rpRaw [2]byte r.Read(lpRaw[:]) r.Read(rpRaw[:]) lp := binary.BigEndian.Uint16(lpRaw[:]) rp := binary.BigEndian.Uint16(rpRaw[:]) - rule = routing.AppRule(ruleExp, routing.RouteID(r.Uint32()), remotePK, rp, lp) + revRID := routing.RouteID(r.Uint32()) + rule := routing.AppRule(ruleExp, revRID, remotePK, rp, lp) + if _, err := rt.AddRule(rule); err != nil { + panic(err) + } + revRule := routing.ForwardRule(ruleExp, routing.RouteID(r.Uint32()), uuid.New()) + if _, err := rt.AddRule(revRule); err != nil { + panic(err) + } } else { - rule = routing.ForwardRule(ruleExp, routing.RouteID(r.Uint32()), uuid.New()) - } - if _, err := rt.AddRule(rule); err != nil { - panic(err) + rule := routing.ForwardRule(ruleExp, routing.RouteID(r.Uint32()), uuid.New()) + if _, err := rt.AddRule(rule); err != nil { + panic(err) + } } } return localPK, &mockRPCClient{ @@ -368,3 +406,26 @@ func (mc *mockRPCClient) SetRoutingRule(key routing.RouteID, rule routing.Rule) func (mc *mockRPCClient) RemoveRoutingRule(key routing.RouteID) error { return mc.rt.DeleteRules(key) } + +// Loops implements RPCClient. +func (mc *mockRPCClient) Loops() ([]LoopInfo, error) { + var loops []LoopInfo + err := mc.rt.RangeRules(func(_ routing.RouteID, rule routing.Rule) (next bool) { + if rule.Type() == routing.RuleApp { + loops = append(loops, LoopInfo{AppRule: rule}) + } + return true + }) + if err != nil { + return nil, err + } + for i, l := range loops { + fwdRID := l.AppRule.RouteID() + rule, err := mc.rt.Rule(fwdRID) + if err != nil { + return nil, err + } + loops[i].FwdRule = rule + } + return loops, nil +} diff --git a/pkg/router/loop_list.go b/pkg/router/loop_list.go index cd33ebdfd..7641f93df 100644 --- a/pkg/router/loop_list.go +++ b/pkg/router/loop_list.go @@ -19,7 +19,7 @@ type loop struct { type loopList struct { sync.Mutex - loops map[app.Addr]*loop + loops map[app.Addr]*loop // key: remote address (pk+port), value: forwarding transport and route ID. } func newLoopList() *loopList { diff --git a/pkg/router/port_manager.go b/pkg/router/port_manager.go index f16c3f6e2..718ba9c88 100644 --- a/pkg/router/port_manager.go +++ b/pkg/router/port_manager.go @@ -89,13 +89,13 @@ func (pm *portManager) Get(port uint16) (*portBind, error) { return b, nil } -func (pm *portManager) GetLoop(port uint16, raddr *app.Addr) (*loop, error) { - b, err := pm.Get(port) +func (pm *portManager) GetLoop(localPort uint16, remoteAddr *app.Addr) (*loop, error) { + b, err := pm.Get(localPort) if err != nil { return nil, err } - l := b.loops.get(raddr) + l := b.loops.get(remoteAddr) if l == nil { return nil, errors.New("unknown loop") } diff --git a/pkg/routing/rule.go b/pkg/routing/rule.go index 91b2809e6..14b40a08f 100644 --- a/pkg/routing/rule.go +++ b/pkg/routing/rule.go @@ -32,7 +32,9 @@ const ( RuleForward ) -// Rule represents a rule in a RoutingTable. +// Rule represents a routing rule. +// There are two types of routing rules; App and Forward. +// type Rule []byte // Expiry returns rule's expiration time. diff --git a/skywire-config.json b/skywire-config.json deleted file mode 100755 index 9d530c085..000000000 --- a/skywire-config.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "version": "1.0", - "node": { - "static_public_key": "0381bbb4518eb4417110925212a1540d41270dceb0753434dd6095a3241ff899dc", - "static_secret_key": "4f4688d047d964f6a9724419d93fa4466f0656003376d8789cbf48ec40f002fa" - }, - "messaging": { - "discovery": "https://messaging.discovery.skywire.skycoin.net", - "server_count": 1 - }, - "transport": { - "discovery": "https://transport.discovery.skywire.skycoin.net", - "log_store": { - "type": "file", - "location": "./skywire/transport_logs" - } - }, - "routing": { - "setup_nodes": [ - "0324579f003e6b4048bae2def4365e634d8e0e3054a20fc7af49daf2a179658557" - ], - "route_finder": "https://routefinder.skywire.skycoin.net/", - "table": { - "type": "boltdb", - "location": "./skywire/routing.db" - } - }, - "apps": [ - { - "version": "1.0", - "app": "chat", - "auto_start": true, - "port": 1, - "args": [] - }, - { - "version": "1.0", - "app": "therealssh", - "auto_start": true, - "port": 2, - "args": [] - }, - { - "version": "1.0", - "app": "therealproxy", - "auto_start": true, - "port": 3, - "args": [ - "-passcode", - "JQgoyeiz7zE=" - ] - } - ], - "trusted_nodes": [], - "manager_nodes": [], - "apps_path": "./apps", - "local_path": "./local", - "log_level": "info", - "interfaces": { - "rpc": "localhost:3435" - } -} \ No newline at end of file