From 302e0b4a4255315bd18284ef793b1a77de5c71ad Mon Sep 17 00:00:00 2001 From: Nikita Kryuchkov Date: Wed, 4 Mar 2020 20:39:12 +0100 Subject: [PATCH 1/5] Remove some panics --- pkg/app/log_store.go | 7 ++-- pkg/router/route_group.go | 5 ++- pkg/router/router.go | 8 +++- pkg/router/router_test.go | 16 ++++++-- pkg/routing/packet.go | 14 +++++-- pkg/routing/packet_test.go | 5 ++- pkg/snet/network.go | 56 +++++++++++++++++++--------- pkg/snet/network_test.go | 4 +- pkg/snet/snettest/env.go | 2 + pkg/transport/entry.go | 37 ++++++++++++------ pkg/transport/entry_test.go | 29 ++++++++------- pkg/transport/handshake.go | 27 ++++++++++---- pkg/transport/managed_transport.go | 2 +- pkg/transport/manager.go | 7 +++- pkg/transport/manager_test.go | 14 ++++++- pkg/util/pathutil/util.go | 4 +- pkg/visor/rpc.go | 8 ++-- pkg/visor/visor.go | 60 +++++++++++++++++++++++------- 18 files changed, 218 insertions(+), 87 deletions(-) diff --git a/pkg/app/log_store.go b/pkg/app/log_store.go index ff0a53287a..c8c2a6523b 100644 --- a/pkg/app/log_store.go +++ b/pkg/app/log_store.go @@ -67,7 +67,7 @@ func newBoltDB(path, appName string) (_ LogStore, err error) { } // Write implements io.Writer -func (l *boltDBappLogs) Write(p []byte) (int, error) { +func (l *boltDBappLogs) Write(p []byte) (n int, err error) { // ensure there is at least timestamp long bytes if len(p) < 37 { return 0, io.ErrShortBuffer @@ -79,9 +79,8 @@ func (l *boltDBappLogs) Write(p []byte) (int, error) { } defer func() { - err := db.Close() - if err != nil { - panic(err) + if closeErr := db.Close(); err == nil { + err = closeErr } }() diff --git a/pkg/router/route_group.go b/pkg/router/route_group.go index 3a3cd96ead..71fd6528a1 100644 --- a/pkg/router/route_group.go +++ b/pkg/router/route_group.go @@ -266,7 +266,10 @@ func (rg *RouteGroup) read(p []byte) (int, error) { } func (rg *RouteGroup) write(data []byte, tp *transport.ManagedTransport, rule routing.Rule) (int, error) { - packet := routing.MakeDataPacket(rule.NextRouteID(), data) + packet, err := routing.MakeDataPacket(rule.NextRouteID(), data) + if err != nil { + return 0, err + } rg.logger.Debugf("Writing packet of type %s, route ID %d and next ID %d", packet.Type(), rule.KeyRouteID(), rule.NextRouteID()) diff --git a/pkg/router/router.go b/pkg/router/router.go index 5655751ec1..0dd3b91bca 100644 --- a/pkg/router/router.go +++ b/pkg/router/router.go @@ -553,9 +553,15 @@ func (r *router) forwardPacket(ctx context.Context, packet routing.Packet, rule } var p routing.Packet + switch packet.Type() { case routing.DataPacket: - p = routing.MakeDataPacket(rule.NextRouteID(), packet.Payload()) + var err error + + p, err = routing.MakeDataPacket(rule.NextRouteID(), packet.Payload()) + if err != nil { + return err + } case routing.KeepAlivePacket: p = routing.MakeKeepAlivePacket(rule.NextRouteID()) case routing.ClosePacket: diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index f915fff28c..da7bdf2adb 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -433,7 +433,9 @@ func testForwardRule(t *testing.T, r0, r1 *router, tp1 *transport.ManagedTranspo r0.saveRouteGroupRules(routing.EdgeRules{Desc: fwdRule.RouteDescriptor(), Forward: fwdRule, Reverse: nil}) // Call handleTransportPacket for r0 (this should in turn, use the rule we added). - packet := routing.MakeDataPacket(fwdRtID[0], []byte("This is a test!")) + packet, err := routing.MakeDataPacket(fwdRtID[0], []byte("This is a test!")) + require.NoError(t, err) + require.NoError(t, r0.handleTransportPacket(context.TODO(), packet)) // r1 should receive the packet handled by r0. @@ -457,7 +459,9 @@ func testIntermediaryForwardRule(t *testing.T, r0, r1 *router, tp1 *transport.Ma require.NoError(t, err) // Call handleTransportPacket for r0 (this should in turn, use the rule we added). - packet := routing.MakeDataPacket(fwdRtID[0], []byte("This is a test!")) + packet, err := routing.MakeDataPacket(fwdRtID[0], []byte("This is a test!")) + require.NoError(t, err) + require.NoError(t, r0.handleTransportPacket(context.TODO(), packet)) // r1 should receive the packet handled by r0. @@ -501,7 +505,9 @@ func testConsumeRule(t *testing.T, r0, r1 *router, tp1 *transport.ManagedTranspo Reverse: cnsmRule, }) - packet := routing.MakeDataPacket(intFwdRtID[0], []byte("test intermediary forward")) + packet, err := routing.MakeDataPacket(intFwdRtID[0], []byte("test intermediary forward")) + require.NoError(t, err) + require.NoError(t, r0.handleTransportPacket(context.TODO(), packet)) recvPacket, err := r1.tm.ReadPacket() @@ -511,7 +517,9 @@ func testConsumeRule(t *testing.T, r0, r1 *router, tp1 *transport.ManagedTranspo assert.Equal(t, dstRtIDs[1], recvPacket.RouteID()) consumeMsg := []byte("test_consume") - packet = routing.MakeDataPacket(dstRtIDs[1], consumeMsg) + packet, err = routing.MakeDataPacket(dstRtIDs[1], consumeMsg) + require.NoError(t, err) + require.NoError(t, r1.handleTransportPacket(context.TODO(), packet)) rg, ok := r1.routeGroup(fwdRtDesc.Invert()) diff --git a/pkg/routing/packet.go b/pkg/routing/packet.go index 6fa7a3d888..7c0891cc81 100644 --- a/pkg/routing/packet.go +++ b/pkg/routing/packet.go @@ -2,6 +2,7 @@ package routing import ( "encoding/binary" + "errors" "fmt" "math" ) @@ -24,6 +25,11 @@ const ( PacketPayloadOffset = PacketHeaderSize ) +var ( + // ErrPayloadTooBig is returned when passed payload is too big (more than math.MaxUint16). + ErrPayloadTooBig = errors.New("packet size exceeded") +) + // PacketType represents packet purpose. type PacketType byte @@ -71,10 +77,10 @@ const ( type RouteID uint32 // MakeDataPacket constructs a new DataPacket. -// If payload size is more than uint16, MakeDataPacket will panic. -func MakeDataPacket(id RouteID, payload []byte) Packet { +// If payload size is more than uint16, MakeDataPacket returns an error. +func MakeDataPacket(id RouteID, payload []byte) (Packet, error) { if len(payload) > math.MaxUint16 { - panic("packet size exceeded") + return Packet{}, ErrPayloadTooBig } packet := make([]byte, PacketHeaderSize+len(payload)) @@ -84,7 +90,7 @@ func MakeDataPacket(id RouteID, payload []byte) Packet { binary.BigEndian.PutUint16(packet[PacketPayloadSizeOffset:], uint16(len(payload))) copy(packet[PacketPayloadOffset:], payload) - return packet + return packet, nil } // MakeClosePacket constructs a new ClosePacket. diff --git a/pkg/routing/packet_test.go b/pkg/routing/packet_test.go index fe413f6bea..6fa39b5bee 100644 --- a/pkg/routing/packet_test.go +++ b/pkg/routing/packet_test.go @@ -4,10 +4,13 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMakeDataPacket(t *testing.T) { - packet := MakeDataPacket(2, []byte("foo")) + packet, err := MakeDataPacket(2, []byte("foo")) + require.NoError(t, err) + expected := []byte{0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3, 0x66, 0x6f, 0x6f} assert.Equal(t, expected, []byte(packet)) diff --git a/pkg/snet/network.go b/pkg/snet/network.go index a84d4397c1..27d734d1c9 100644 --- a/pkg/snet/network.go +++ b/pkg/snet/network.go @@ -86,7 +86,7 @@ func NewRaw(conf Config, dmsgC *dmsg.Client, stcpC *stcp.Client) *Network { } // Init initiates server connections. -func (n *Network) Init(ctx context.Context) error { +func (n *Network) Init(_ context.Context) error { if n.dmsgC != nil { time.Sleep(200 * time.Millisecond) go n.dmsgC.Serve() @@ -169,13 +169,14 @@ func (n *Network) Dial(ctx context.Context, network string, pk cipher.PubKey, po return nil, err } - return makeConn(conn, network), nil + return makeConn(conn, network) case STcpType: conn, err := n.stcpC.Dial(ctx, pk, port) if err != nil { return nil, err } - return makeConn(conn, network), nil + + return makeConn(conn, network) default: return nil, ErrUnknownNetwork } @@ -189,13 +190,15 @@ func (n *Network) Listen(network string, port uint16) (*Listener, error) { if err != nil { return nil, err } - return makeListener(lis, network), nil + + return makeListener(lis, network) case STcpType: lis, err := n.stcpC.Listen(port) if err != nil { return nil, err } - return makeListener(lis, network), nil + + return makeListener(lis, network) default: return nil, ErrUnknownNetwork } @@ -209,9 +212,13 @@ type Listener struct { network string } -func makeListener(l net.Listener, network string) *Listener { - lPK, lPort := disassembleAddr(l.Addr()) - return &Listener{Listener: l, lPK: lPK, lPort: lPort, network: network} +func makeListener(l net.Listener, network string) (*Listener, error) { + lPK, lPort, err := disassembleAddr(l.Addr()) + if err != nil { + return nil, err + } + + return &Listener{Listener: l, lPK: lPK, lPort: lPort, network: network}, nil } // LocalPK returns a local public key of listener. @@ -229,7 +236,8 @@ func (l Listener) AcceptConn() (*Conn, error) { if err != nil { return nil, err } - return makeConn(conn, l.network), nil + + return makeConn(conn, l.network) } // Conn represent a connection between nodes in Skywire. @@ -242,10 +250,18 @@ type Conn struct { network string } -func makeConn(conn net.Conn, network string) *Conn { - lPK, lPort := disassembleAddr(conn.LocalAddr()) - rPK, rPort := disassembleAddr(conn.RemoteAddr()) - return &Conn{Conn: conn, lPK: lPK, rPK: rPK, lPort: lPort, rPort: rPort, network: network} +func makeConn(conn net.Conn, network string) (*Conn, error) { + lPK, lPort, err := disassembleAddr(conn.LocalAddr()) + if err != nil { + return nil, err + } + + rPK, rPort, err := disassembleAddr(conn.RemoteAddr()) + if err != nil { + return nil, err + } + + return &Conn{Conn: conn, lPK: lPK, rPK: rPK, lPort: lPort, rPort: rPort, network: network}, nil } // LocalPK returns local public key of connection. @@ -263,18 +279,24 @@ func (c Conn) RemotePort() uint16 { return c.rPort } // Network returns network of connection. func (c Conn) Network() string { return c.network } -func disassembleAddr(addr net.Addr) (pk cipher.PubKey, port uint16) { +func disassembleAddr(addr net.Addr) (pk cipher.PubKey, port uint16, retErr error) { strs := strings.Split(addr.String(), ":") if len(strs) != 2 { - panic(fmt.Errorf("network.disassembleAddr: %v %s", "invalid addr", addr.String())) + retErr = fmt.Errorf("network.disassembleAddr: %v %s", "invalid addr", addr.String()) + return } + if err := pk.Set(strs[0]); err != nil { - panic(fmt.Errorf("network.disassembleAddr: %v %s", err, addr.String())) + retErr = fmt.Errorf("network.disassembleAddr: %v %s", err, addr.String()) + return } + if strs[1] != "~" { if _, err := fmt.Sscanf(strs[1], "%d", &port); err != nil { - panic(fmt.Errorf("network.disassembleAddr: %v", err)) + retErr = fmt.Errorf("network.disassembleAddr: %v", err) + return } } + return } diff --git a/pkg/snet/network_test.go b/pkg/snet/network_test.go index 556492ae44..9f3da13227 100644 --- a/pkg/snet/network_test.go +++ b/pkg/snet/network_test.go @@ -15,7 +15,9 @@ func TestDisassembleAddr(t *testing.T) { addr := dmsg.Addr{ PK: pk, Port: port, } - gotPK, gotPort := disassembleAddr(addr) + + gotPK, gotPort, err := disassembleAddr(addr) + require.NoError(t, err) require.Equal(t, pk, gotPK) require.Equal(t, port, gotPort) } diff --git a/pkg/snet/snettest/env.go b/pkg/snet/snettest/env.go index c70b3764ad..5d53037f5a 100644 --- a/pkg/snet/snettest/env.go +++ b/pkg/snet/snettest/env.go @@ -32,8 +32,10 @@ func GenKeyPairs(n int) []KeyPair { if err != nil { panic(err) } + pairs[i] = KeyPair{PK: pk, SK: sk} } + return pairs } diff --git a/pkg/transport/entry.go b/pkg/transport/entry.go index fa1e60a99b..ac7c6d18ca 100644 --- a/pkg/transport/entry.go +++ b/pkg/transport/entry.go @@ -1,6 +1,7 @@ package transport import ( + "errors" "fmt" "strings" @@ -8,6 +9,11 @@ import ( "github.com/google/uuid" ) +var ( + // ErrEdgeIndexNotFound is returned when no edge index was found. + ErrEdgeIndexNotFound = errors.New("edge index not found") +) + // Entry is the unsigned representation of a Transport. type Entry struct { @@ -59,6 +65,7 @@ func (e *Entry) EdgeIndex(pk cipher.PubKey) int { return i } } + return -1 } @@ -99,12 +106,13 @@ func (e *Entry) ToBinary() []byte { // Signature returns signature for Entry calculated from binary // representation. -func (e *Entry) Signature(secKey cipher.SecKey) cipher.Sig { +func (e *Entry) Signature(secKey cipher.SecKey) (cipher.Sig, error) { sig, err := cipher.SignPayload(e.ToBinary(), secKey) if err != nil { - panic(err) + return cipher.Sig{}, err } - return sig + + return sig, nil } // SignedEntry holds an Entry and it's associated signatures. @@ -116,27 +124,34 @@ type SignedEntry struct { } // Sign sets Signature for a given PubKey in correct position -func (se *SignedEntry) Sign(pk cipher.PubKey, secKey cipher.SecKey) bool { +func (se *SignedEntry) Sign(pk cipher.PubKey, secKey cipher.SecKey) error { idx := se.Entry.EdgeIndex(pk) if idx == -1 { - return false + return ErrEdgeIndexNotFound } - se.Signatures[idx] = se.Entry.Signature(secKey) - return true + sig, err := se.Entry.Signature(secKey) + if err != nil { + return err + } + + se.Signatures[idx] = sig + + return nil } // Signature gets Signature for a given PubKey from correct position -func (se *SignedEntry) Signature(pk cipher.PubKey) (cipher.Sig, bool) { +func (se *SignedEntry) Signature(pk cipher.PubKey) (cipher.Sig, error) { idx := se.Entry.EdgeIndex(pk) if idx == -1 { - return cipher.Sig{}, false + return cipher.Sig{}, ErrEdgeIndexNotFound } - return se.Signatures[idx], true + + return se.Signatures[idx], nil } // NewSignedEntry creates a SignedEntry with first signature -func NewSignedEntry(entry *Entry, pk cipher.PubKey, secKey cipher.SecKey) (*SignedEntry, bool) { +func NewSignedEntry(entry *Entry, pk cipher.PubKey, secKey cipher.SecKey) (*SignedEntry, error) { se := &SignedEntry{Entry: entry} return se, se.Sign(pk, secKey) } diff --git a/pkg/transport/entry_test.go b/pkg/transport/entry_test.go index 06e5fb39eb..e279b53784 100644 --- a/pkg/transport/entry_test.go +++ b/pkg/transport/entry_test.go @@ -50,16 +50,17 @@ func ExampleSignedEntry_Sign() { fmt.Println("No signatures set") } - if ok := sEntry.Sign(pkA, skA); !ok { - fmt.Println("error signing with skA") + if err := sEntry.Sign(pkA, skA); err != nil { + fmt.Println("error signing with skA: ", err) } + if (!sEntry.Signatures[0].Null() && sEntry.Signatures[1].Null()) || (!sEntry.Signatures[1].Null() && sEntry.Signatures[0].Null()) { fmt.Println("One signature set") } - if ok := sEntry.Sign(pkB, skB); !ok { - fmt.Println("error signing with skB") + if err := sEntry.Sign(pkB, skB); err != nil { + fmt.Println("error signing with skB: ", err) } if !sEntry.Signatures[0].Null() && !sEntry.Signatures[1].Null() { @@ -79,35 +80,37 @@ func ExampleSignedEntry_Signature() { entry := transport.NewEntry(pkA, pkB, "mock", true) sEntry := &transport.SignedEntry{Entry: entry} - if ok := sEntry.Sign(pkA, skA); !ok { + + if err := sEntry.Sign(pkA, skA); err != nil { fmt.Println("Error signing sEntry with (pkA,skA)") } - if ok := sEntry.Sign(pkB, skB); !ok { + + if err := sEntry.Sign(pkB, skB); err != nil { fmt.Println("Error signing sEntry with (pkB,skB)") } idxA := sEntry.Entry.EdgeIndex(pkA) idxB := sEntry.Entry.EdgeIndex(pkB) - sigA, okA := sEntry.Signature(pkA) - sigB, okB := sEntry.Signature(pkB) + sigA, errA := sEntry.Signature(pkA) + sigB, errB := sEntry.Signature(pkB) - if okA && sigA == sEntry.Signatures[idxA] { + if errA == nil && sigA == sEntry.Signatures[idxA] { fmt.Println("SignatureA got") } - if okB && (sigB == sEntry.Signatures[idxB]) { + if errB == nil && (sigB == sEntry.Signatures[idxB]) { fmt.Println("SignatureB got") } // Incorrect case pkC, _ := cipher.GenerateKeyPair() - if _, ok := sEntry.Signature(pkC); !ok { - fmt.Printf("SignatureC got error: invalid pubkey") + if _, err := sEntry.Signature(pkC); err != nil { + fmt.Printf("SignatureC got error: %v\n", err) } // // Output: SignatureA got // SignatureB got - // SignatureC got error: invalid pubkey + // SignatureC got error: edge index not found } diff --git a/pkg/transport/handshake.go b/pkg/transport/handshake.go index f6c67a9f8b..8879b9090b 100644 --- a/pkg/transport/handshake.go +++ b/pkg/transport/handshake.go @@ -31,33 +31,42 @@ func compareEntries(expected, received *Entry) error { if expected.ID != received.ID { return errors.New("received entry's 'tp_id' is not of expected") } + if expected.Edges != received.Edges { return errors.New("received entry's 'edges' is not of expected") } + if expected.Type != received.Type { return errors.New("received entry's 'type' is not of expected") } + if expected.Public != received.Public { return errors.New("received entry's 'public' is not of expected") } + return nil } func receiveAndVerifyEntry(r io.Reader, expected *Entry, remotePK cipher.PubKey) (*SignedEntry, error) { var recvSE SignedEntry + if err := json.NewDecoder(r).Decode(&recvSE); err != nil { return nil, fmt.Errorf("failed to read entry: %s", err) } + if err := compareEntries(expected, recvSE.Entry); err != nil { return nil, err } - sig, ok := recvSE.Signature(remotePK) - if !ok { - return nil, errors.New("invalid remote signature") + + sig, err := recvSE.Signature(remotePK) + if err != nil { + return nil, fmt.Errorf("invalid remote signature: %w", err) } + if err := cipher.VerifyPubKeySignedPayload(remotePK, sig, recvSE.Entry.ToBinary()); err != nil { return nil, err } + return &recvSE, nil } @@ -97,9 +106,9 @@ func MakeSettlementHS(init bool) SettlementHS { //}() // create signed entry and send it to responding visor. - se, ok := NewSignedEntry(&entry, conn.LocalPK(), sk) - if !ok { - return errors.New("failed to sign entry") + se, err := NewSignedEntry(&entry, conn.LocalPK(), sk) + if err != nil { + return fmt.Errorf("failed to sign entry: %w", err) } if err := json.NewEncoder(conn).Encode(se); err != nil { return fmt.Errorf("failed to write entry: %v", err) @@ -125,9 +134,11 @@ func MakeSettlementHS(init bool) SettlementHS { if err != nil { return err } - if ok := recvSE.Sign(conn.LocalPK(), sk); !ok { - return errors.New("failed to sign received entry") + + if err := recvSE.Sign(conn.LocalPK(), sk); err != nil { + return fmt.Errorf("failed to sign received entry: %w", err) } + entry = *recvSE.Entry // Ensure transport is registered. diff --git a/pkg/transport/managed_transport.go b/pkg/transport/managed_transport.go index ffddcf26e5..84389f120b 100644 --- a/pkg/transport/managed_transport.go +++ b/pkg/transport/managed_transport.go @@ -412,7 +412,7 @@ func (mt *ManagedTransport) clearConn() { func (mt *ManagedTransport) updateStatus(isUp bool, tries int) (err error) { if tries < 1 { - panic(fmt.Errorf("mt.updateStatus: invalid input: got tries=%d (want tries > 0)", tries)) + return fmt.Errorf("invalid input") } // If not serving, we should update status to 'DOWN' and ensure 'updateStatus' returns error. diff --git a/pkg/transport/manager.go b/pkg/transport/manager.go index a43b39fff2..3bd15c290a 100644 --- a/pkg/transport/manager.go +++ b/pkg/transport/manager.go @@ -161,6 +161,7 @@ func (tm *Manager) acceptTransport(ctx context.Context, lis *snet.Listener) erro if err != nil { return err } + tm.Logger.Infof("recv transport connection request: type(%s) remote(%s)", lis.Network(), conn.RemotePK()) tm.mx.Lock() @@ -177,18 +178,21 @@ func (tm *Manager) acceptTransport(ctx context.Context, lis *snet.Listener) erro mTp, ok := tm.tps[tpID] if !ok { tm.Logger.Debugln("No TP found, creating new one") + mTp = NewManagedTransport(tm.n, tm.Conf.DiscoveryClient, tm.Conf.LogStore, conn.RemotePK(), lis.Network()) + go func() { mTp.Serve(tm.readCh) + tm.mx.Lock() delete(tm.tps, mTp.Entry.ID) tm.mx.Unlock() }() + tm.tps[tpID] = mTp } else { tm.Logger.Debugln("TP found, accepting...") - } if err := mTp.Accept(ctx, conn); err != nil { @@ -196,6 +200,7 @@ func (tm *Manager) acceptTransport(ctx context.Context, lis *snet.Listener) erro } tm.Logger.Infof("accepted tp: type(%s) remote(%s) tpID(%s) new(%v)", lis.Network(), conn.RemotePK(), tpID, !ok) + return nil } diff --git a/pkg/transport/manager_test.go b/pkg/transport/manager_test.go index 6dfd9a5fff..115306a028 100644 --- a/pkg/transport/manager_test.go +++ b/pkg/transport/manager_test.go @@ -91,7 +91,11 @@ func TestNewManager(t *testing.T) { totalSent2 += i rID := routing.RouteID(i) payload := cipher.RandByte(i) - require.NoError(t, tp2.WritePacket(context.TODO(), routing.MakeDataPacket(rID, payload))) + + packet, err := routing.MakeDataPacket(rID, payload) + require.NoError(t, err) + + require.NoError(t, tp2.WritePacket(context.TODO(), packet)) recv, err := m0.ReadPacket() require.NoError(t, err) @@ -104,7 +108,11 @@ func TestNewManager(t *testing.T) { totalSent1 += i rID := routing.RouteID(i) payload := cipher.RandByte(i) - require.NoError(t, tp1.WritePacket(context.TODO(), routing.MakeDataPacket(rID, payload))) + + packet, err := routing.MakeDataPacket(rID, payload) + require.NoError(t, err) + + require.NoError(t, tp1.WritePacket(context.TODO(), packet)) recv, err := m2.ReadPacket() require.NoError(t, err) @@ -144,7 +152,9 @@ func TestNewManager(t *testing.T) { assert.True(t, entry.IsUp) m2.DeleteTransport(tp2.Entry.ID) + _, err = tpDisc.GetTransportByID(context.TODO(), tpID) + require.NotNil(t, err) require.Contains(t, err.Error(), "not found") }) } diff --git a/pkg/util/pathutil/util.go b/pkg/util/pathutil/util.go index a9737667b8..56b0487db5 100644 --- a/pkg/util/pathutil/util.go +++ b/pkg/util/pathutil/util.go @@ -13,7 +13,7 @@ const ( userRWXGroupRX = 0750 ) -// EnsureDir attempts to create given directory, panics if it fails to do so +// EnsureDir attempts to create given directory. func EnsureDir(path string) error { if _, err := os.Stat(path); os.IsNotExist(err) { return os.MkdirAll(path, userRWXGroupRX) @@ -23,7 +23,7 @@ func EnsureDir(path string) error { } // AtomicWriteFile creates a temp file in which to write data, then calls syscall.Rename to swap it and write it on -// filename for an atomic write. On failure temp file is removed and panics. +// filename for an atomic write. func AtomicWriteFile(filename string, data []byte) error { tempFilePath := filename + tmpSuffix diff --git a/pkg/visor/rpc.go b/pkg/visor/rpc.go index 393004ac22..acc257b4db 100644 --- a/pkg/visor/rpc.go +++ b/pkg/visor/rpc.go @@ -42,16 +42,18 @@ type RPC struct { log logrus.FieldLogger } -func newRPCServer(v *Visor, remoteName string) *rpc.Server { +func newRPCServer(v *Visor, remoteName string) (*rpc.Server, error) { rpcS := rpc.NewServer() rpcG := &RPC{ visor: v, log: v.Logger.PackageLogger("visor_rpc:" + remoteName), } + if err := rpcS.RegisterName(RPCPrefix, rpcG); err != nil { - panic(fmt.Errorf("failed to create visor RPC server: %v", err)) + return nil, fmt.Errorf("failed to create visor RPC server: %v", err) } - return rpcS + + return rpcS, nil } func (r *RPC) logReq(name string, in interface{}) func(out interface{}, err *error) { diff --git a/pkg/visor/visor.go b/pkg/visor/visor.go index e0ec717736..7187096813 100644 --- a/pkg/visor/visor.go +++ b/pkg/visor/visor.go @@ -252,7 +252,9 @@ func (visor *Visor) Start() error { return err } - visor.startApps() + if err := visor.startApps(); err != nil { + return err + } if err := visor.startDmsgPty(ctx); err != nil { return err @@ -269,8 +271,10 @@ func (visor *Visor) Start() error { return nil } -func (visor *Visor) startApps() { - visor.closePreviousApps() +func (visor *Visor) startApps() error { + if err := visor.closePreviousApps(); err != nil { + return err + } for _, ac := range visor.appsConf { if !ac.AutoStart { @@ -283,6 +287,8 @@ func (visor *Visor) startApps() { } }(ac) } + + return nil } func (visor *Visor) startDmsgPty(ctx context.Context) error { @@ -350,7 +356,13 @@ func (visor *Visor) startRPC(ctx context.Context) { if visor.cliLis != nil { visor.logger.Info("Starting RPC interface on ", visor.cliLis.Addr()) - go newRPCServer(visor, "CLI").Accept(visor.cliLis) + srv, err := newRPCServer(visor, "CLI") + if err != nil { + visor.logger.WithError(err).Errorf("Failed to start RPC server") + return + } + + go srv.Accept(visor.cliLis) } if visor.hvErrs != nil { @@ -359,7 +371,11 @@ func (visor *Visor) startRPC(ctx context.Context) { WithField("hypervisor_pk", hvPK) addr := dmsg.Addr{PK: hvPK, Port: skyenv.DmsgHypervisorPort} - rpcS := newRPCServer(visor, addr.PK.String()[:shortHashLen]) + rpcS, err := newRPCServer(visor, addr.PK.String()[:shortHashLen]) + if err != nil { + visor.logger.WithError(err).Errorf("Failed to start RPC server") + return + } go ServeRPCClient(ctx, log, visor.n, rpcS, addr, hvErrs) } @@ -370,19 +386,23 @@ func (visor *Visor) dir() string { return pathutil.VisorDir(visor.conf.Visor.StaticPubKey.String()) } -func (visor *Visor) pidFile() *os.File { +func (visor *Visor) pidFile() (*os.File, error) { f, err := os.OpenFile(filepath.Join(visor.dir(), "apps-pid.txt"), os.O_RDWR|os.O_CREATE, 0600) if err != nil { - panic(err) + return nil, err } - return f + return f, nil } -func (visor *Visor) closePreviousApps() { +func (visor *Visor) closePreviousApps() error { visor.logger.Info("killing previously ran apps if any...") - pids := visor.pidFile() + pids, err := visor.pidFile() + if err != nil { + return err + } + defer func() { if err := pids.Close(); err != nil { visor.logger.Warnf("error closing PID file: %s", err) @@ -408,6 +428,8 @@ func (visor *Visor) closePreviousApps() { if err := pathutil.AtomicWriteFile(pids.Name(), []byte{}); err != nil { visor.logger.WithError(err).Errorf("Failed to empty file %s", pids.Name()) } + + return nil } func (visor *Visor) stopUnhandledApp(name string, pid int) { @@ -572,15 +594,25 @@ func (visor *Visor) SpawnApp(config *AppConfig, startCh chan<- struct{}) (err er } visor.pidMu.Lock() + visor.logger.Infof("storing app %s pid %d", config.App, pid) - visor.persistPID(config.App, pid) + + if err := visor.persistPID(config.App, pid); err != nil { + visor.pidMu.Unlock() + return err + } + visor.pidMu.Unlock() return visor.procManager.Wait(config.App) } -func (visor *Visor) persistPID(name string, pid appcommon.ProcID) { - pidF := visor.pidFile() +func (visor *Visor) persistPID(name string, pid appcommon.ProcID) error { + pidF, err := visor.pidFile() + if err != nil { + return err + } + pidFName := pidF.Name() if err := pidF.Close(); err != nil { visor.logger.WithError(err).Warn("Failed to close PID file") @@ -590,6 +622,8 @@ func (visor *Visor) persistPID(name string, pid appcommon.ProcID) { if err := pathutil.AtomicAppendToFile(pidFName, []byte(data)); err != nil { visor.logger.WithError(err).Warn("Failed to save PID to file") } + + return nil } // StopApp stops running App. From 80f373a982085d63b4935f7cf2e100446748cbaa Mon Sep 17 00:00:00 2001 From: Nikita Kryuchkov Date: Thu, 5 Mar 2020 12:44:03 +0100 Subject: [PATCH 2/5] Make some functions panic again --- pkg/snet/network.go | 47 ++++++++++-------------------- pkg/snet/network_test.go | 3 +- pkg/transport/managed_transport.go | 2 +- 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/pkg/snet/network.go b/pkg/snet/network.go index 27d734d1c9..6d4286a154 100644 --- a/pkg/snet/network.go +++ b/pkg/snet/network.go @@ -169,14 +169,14 @@ func (n *Network) Dial(ctx context.Context, network string, pk cipher.PubKey, po return nil, err } - return makeConn(conn, network) + return makeConn(conn, network), nil case STcpType: conn, err := n.stcpC.Dial(ctx, pk, port) if err != nil { return nil, err } - return makeConn(conn, network) + return makeConn(conn, network), nil default: return nil, ErrUnknownNetwork } @@ -191,14 +191,14 @@ func (n *Network) Listen(network string, port uint16) (*Listener, error) { return nil, err } - return makeListener(lis, network) + return makeListener(lis, network), nil case STcpType: lis, err := n.stcpC.Listen(port) if err != nil { return nil, err } - return makeListener(lis, network) + return makeListener(lis, network), nil default: return nil, ErrUnknownNetwork } @@ -212,13 +212,9 @@ type Listener struct { network string } -func makeListener(l net.Listener, network string) (*Listener, error) { - lPK, lPort, err := disassembleAddr(l.Addr()) - if err != nil { - return nil, err - } - - return &Listener{Listener: l, lPK: lPK, lPort: lPort, network: network}, nil +func makeListener(l net.Listener, network string) *Listener { + lPK, lPort := disassembleAddr(l.Addr()) + return &Listener{Listener: l, lPK: lPK, lPort: lPort, network: network} } // LocalPK returns a local public key of listener. @@ -237,7 +233,7 @@ func (l Listener) AcceptConn() (*Conn, error) { return nil, err } - return makeConn(conn, l.network) + return makeConn(conn, l.network), nil } // Conn represent a connection between nodes in Skywire. @@ -250,18 +246,10 @@ type Conn struct { network string } -func makeConn(conn net.Conn, network string) (*Conn, error) { - lPK, lPort, err := disassembleAddr(conn.LocalAddr()) - if err != nil { - return nil, err - } - - rPK, rPort, err := disassembleAddr(conn.RemoteAddr()) - if err != nil { - return nil, err - } - - return &Conn{Conn: conn, lPK: lPK, rPK: rPK, lPort: lPort, rPort: rPort, network: network}, nil +func makeConn(conn net.Conn, network string) *Conn { + lPK, lPort := disassembleAddr(conn.LocalAddr()) + rPK, rPort := disassembleAddr(conn.RemoteAddr()) + return &Conn{Conn: conn, lPK: lPK, rPK: rPK, lPort: lPort, rPort: rPort, network: network} } // LocalPK returns local public key of connection. @@ -279,22 +267,19 @@ func (c Conn) RemotePort() uint16 { return c.rPort } // Network returns network of connection. func (c Conn) Network() string { return c.network } -func disassembleAddr(addr net.Addr) (pk cipher.PubKey, port uint16, retErr error) { +func disassembleAddr(addr net.Addr) (pk cipher.PubKey, port uint16) { strs := strings.Split(addr.String(), ":") if len(strs) != 2 { - retErr = fmt.Errorf("network.disassembleAddr: %v %s", "invalid addr", addr.String()) - return + panic(fmt.Errorf("network.disassembleAddr: %v %s", "invalid addr", addr.String())) } if err := pk.Set(strs[0]); err != nil { - retErr = fmt.Errorf("network.disassembleAddr: %v %s", err, addr.String()) - return + panic(fmt.Errorf("network.disassembleAddr: %v %s", err, addr.String())) } if strs[1] != "~" { if _, err := fmt.Sscanf(strs[1], "%d", &port); err != nil { - retErr = fmt.Errorf("network.disassembleAddr: %v", err) - return + panic(fmt.Errorf("network.disassembleAddr: %v", err)) } } diff --git a/pkg/snet/network_test.go b/pkg/snet/network_test.go index 9f3da13227..f8a87b1809 100644 --- a/pkg/snet/network_test.go +++ b/pkg/snet/network_test.go @@ -16,8 +16,7 @@ func TestDisassembleAddr(t *testing.T) { PK: pk, Port: port, } - gotPK, gotPort, err := disassembleAddr(addr) - require.NoError(t, err) + gotPK, gotPort := disassembleAddr(addr) require.Equal(t, pk, gotPK) require.Equal(t, port, gotPort) } diff --git a/pkg/transport/managed_transport.go b/pkg/transport/managed_transport.go index 84389f120b..ffddcf26e5 100644 --- a/pkg/transport/managed_transport.go +++ b/pkg/transport/managed_transport.go @@ -412,7 +412,7 @@ func (mt *ManagedTransport) clearConn() { func (mt *ManagedTransport) updateStatus(isUp bool, tries int) (err error) { if tries < 1 { - return fmt.Errorf("invalid input") + panic(fmt.Errorf("mt.updateStatus: invalid input: got tries=%d (want tries > 0)", tries)) } // If not serving, we should update status to 'DOWN' and ensure 'updateStatus' returns error. From 4dff2e377e5af38286895f6c884d2179f73425f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Thu, 5 Mar 2020 20:52:03 +0800 Subject: [PATCH 3/5] Improved logging. * Made rpcutil.LogCall to log RPC call on the server side. * Improved appserver.RPCGateway logging #195 * Changed appcommon.Key to use UUID. --- go.mod | 2 +- go.sum | 4 +- pkg/app/appcommon/key.go | 7 +- pkg/app/appserver/rpc_gateway.go | 57 +++++++------ pkg/app/appserver/server.go | 2 +- pkg/transport/managed_transport.go | 2 +- pkg/util/rpcutil/log_call.go | 36 +++++++++ pkg/visor/rpc.go | 80 +++++++------------ .../SkycoinProject/dmsg/httputil/error.go | 3 +- vendor/modules.txt | 2 +- 10 files changed, 103 insertions(+), 92 deletions(-) create mode 100644 pkg/util/rpcutil/log_call.go diff --git a/go.mod b/go.mod index df84059f88..a37ecaf2aa 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/SkycoinProject/skywire-mainnet go 1.13 require ( - github.com/SkycoinProject/dmsg v0.0.0-20200304115237-130cc9d98ffb + github.com/SkycoinProject/dmsg v0.0.0-20200305081343-7a67392d759d github.com/SkycoinProject/skycoin v0.27.0 github.com/SkycoinProject/yamux v0.0.0-20191213015001-a36efeefbf6a github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 diff --git a/go.sum b/go.sum index 4f8b15bed3..d68e1f8c7a 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/SkycoinProject/dmsg v0.0.0-20200304115237-130cc9d98ffb h1:UPgo4kZ/nFV4jI9djG0esOyZjda4IZGZpGl/ntYRyuM= -github.com/SkycoinProject/dmsg v0.0.0-20200304115237-130cc9d98ffb/go.mod h1:DzykXMLlx6Fx0fGjZsCIRas/MIvxW8DZpmDA6f2nCRk= +github.com/SkycoinProject/dmsg v0.0.0-20200305081343-7a67392d759d h1:2vjoH2HOsRRvqvXQb2K4uQnqaMRJnYiDpsfCRxixzvs= +github.com/SkycoinProject/dmsg v0.0.0-20200305081343-7a67392d759d/go.mod h1:DzykXMLlx6Fx0fGjZsCIRas/MIvxW8DZpmDA6f2nCRk= github.com/SkycoinProject/skycoin v0.26.0/go.mod h1:xqPLOKh5B6GBZlGA7B5IJfQmCy7mwimD9NlqxR3gMXo= github.com/SkycoinProject/skycoin v0.27.0 h1:N3IHxj8ossHOcsxLYOYugT+OaELLncYHJHxbbYLPPmY= github.com/SkycoinProject/skycoin v0.27.0/go.mod h1:xqPLOKh5B6GBZlGA7B5IJfQmCy7mwimD9NlqxR3gMXo= diff --git a/pkg/app/appcommon/key.go b/pkg/app/appcommon/key.go index 525065e7e9..897d13bcea 100644 --- a/pkg/app/appcommon/key.go +++ b/pkg/app/appcommon/key.go @@ -1,6 +1,8 @@ package appcommon -import "github.com/SkycoinProject/dmsg/cipher" +import ( + "github.com/google/uuid" +) // Key is an app key to authenticate within the // app server. @@ -8,6 +10,5 @@ type Key string // GenerateAppKey generates new app key. func GenerateAppKey() Key { - raw, _ := cipher.GenerateKeyPair() - return Key(raw.Hex()) + return Key(uuid.New().String()) } diff --git a/pkg/app/appserver/rpc_gateway.go b/pkg/app/appserver/rpc_gateway.go index 4f4c0a89a2..b2b4123f43 100644 --- a/pkg/app/appserver/rpc_gateway.go +++ b/pkg/app/appserver/rpc_gateway.go @@ -9,6 +9,8 @@ import ( "github.com/SkycoinProject/skycoin/src/util/logging" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/rpcutil" + "github.com/SkycoinProject/skywire-mainnet/pkg/app/appnet" "github.com/SkycoinProject/skywire-mainnet/pkg/app/idmanager" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" @@ -77,7 +79,9 @@ type DialResp struct { } // Dial dials to the remote. -func (r *RPCGateway) Dial(remote *appnet.Addr, resp *DialResp) error { +func (r *RPCGateway) Dial(remote *appnet.Addr, resp *DialResp) (err error) { + defer rpcutil.LogCall(r.log, "Dial", remote)(resp, &err) + reservedConnID, free, err := r.cm.ReserveNextID() if err != nil { return err @@ -96,12 +100,10 @@ func (r *RPCGateway) Dial(remote *appnet.Addr, resp *DialResp) error { } if err := r.cm.Set(*reservedConnID, wrappedConn); err != nil { - if err := wrappedConn.Close(); err != nil { - r.log.WithError(err).Error("error closing conn") + if cErr := wrappedConn.Close(); cErr != nil { + r.log.WithError(cErr).Error("Error closing wrappedConn.") } - free() - return err } @@ -114,7 +116,9 @@ func (r *RPCGateway) Dial(remote *appnet.Addr, resp *DialResp) error { } // Listen starts listening. -func (r *RPCGateway) Listen(local *appnet.Addr, lisID *uint16) error { +func (r *RPCGateway) Listen(local *appnet.Addr, lisID *uint16) (err error) { + defer rpcutil.LogCall(r.log, "Listen", local)(lisID, &err) + nextLisID, free, err := r.lm.ReserveNextID() if err != nil { return err @@ -127,17 +131,14 @@ func (r *RPCGateway) Listen(local *appnet.Addr, lisID *uint16) error { } if err := r.lm.Set(*nextLisID, l); err != nil { - if err := l.Close(); err != nil { - r.log.WithError(err).Error("error closing listener") + if cErr := l.Close(); cErr != nil { + r.log.WithError(cErr).Error("Error closing listener.") } - free() - return err } *lisID = *nextLisID - return nil } @@ -148,35 +149,31 @@ type AcceptResp struct { } // Accept accepts connection from the listener specified by `lisID`. -func (r *RPCGateway) Accept(lisID *uint16, resp *AcceptResp) error { - r.log.Infoln("Inside RPC Accept on server side") +func (r *RPCGateway) Accept(lisID *uint16, resp *AcceptResp) (err error) { + defer rpcutil.LogCall(r.log, "Accept", lisID)(resp, &err) + + log := r.log.WithField("func", "Accept") + log.Debug("Getting listener...") lis, err := r.getListener(*lisID) if err != nil { - r.log.Infoln("Error getting listener on RPC Accept server side") return err } - r.log.Infoln("Reserving next ID on RPC Accept server side") - + log.Debug("Reserving next ID...") connID, free, err := r.cm.ReserveNextID() if err != nil { - r.log.Infoln("Error reserving next ID on RPC Accept server side") return err } - r.log.Infoln("Accepting conn on RPC Accept server side") - + log.Debug("Accepting conn...") conn, err := lis.Accept() if err != nil { - r.log.Warnf("Error accepting conn on RPC Accept server side: %v", err) free() - return err } - r.log.Infoln("Wrapping conn on RPC Accept server side") - + log.Debug("Wrapping conn...") wrappedConn, err := appnet.WrapConn(conn) if err != nil { free() @@ -184,12 +181,10 @@ func (r *RPCGateway) Accept(lisID *uint16, resp *AcceptResp) error { } if err := r.cm.Set(*connID, wrappedConn); err != nil { - if err := wrappedConn.Close(); err != nil { - r.log.WithError(err).Error("error closing DMSG transport") + if cErr := wrappedConn.Close(); cErr != nil { + r.log.WithError(cErr).Error("Failed to close wrappedConn.") } - free() - return err } @@ -264,7 +259,9 @@ func (r *RPCGateway) Read(req *ReadReq, resp *ReadResp) error { } // CloseConn closes connection specified by `connID`. -func (r *RPCGateway) CloseConn(connID *uint16, _ *struct{}) error { +func (r *RPCGateway) CloseConn(connID *uint16, _ *struct{}) (err error) { + defer rpcutil.LogCall(r.log, "CloseConn", connID)(nil, &err) + conn, err := r.popConn(*connID) if err != nil { return err @@ -274,7 +271,9 @@ func (r *RPCGateway) CloseConn(connID *uint16, _ *struct{}) error { } // CloseListener closes listener specified by `lisID`. -func (r *RPCGateway) CloseListener(lisID *uint16, _ *struct{}) error { +func (r *RPCGateway) CloseListener(lisID *uint16, _ *struct{}) (err error) { + defer rpcutil.LogCall(r.log, "CloseConn", lisID)(nil, &err) + lis, err := r.popListener(*lisID) if err != nil { return err diff --git a/pkg/app/appserver/server.go b/pkg/app/appserver/server.go index 7e75a8921a..b2d761b455 100644 --- a/pkg/app/appserver/server.go +++ b/pkg/app/appserver/server.go @@ -33,7 +33,7 @@ func New(log *logging.Logger, sockFile string) *Server { // Register registers an app key in RPC server. func (s *Server) Register(appKey appcommon.Key) error { - logger := logging.MustGetLogger(fmt.Sprintf("rpc_server_%s", appKey)) + logger := logging.MustGetLogger(fmt.Sprintf("app_gateway:%s", appKey)) gateway := NewRPCGateway(logger) return s.rpcS.RegisterName(string(appKey), gateway) diff --git a/pkg/transport/managed_transport.go b/pkg/transport/managed_transport.go index ffddcf26e5..22faa76aa4 100644 --- a/pkg/transport/managed_transport.go +++ b/pkg/transport/managed_transport.go @@ -515,7 +515,7 @@ func (mt *ManagedTransport) WritePacket(ctx context.Context, packet routing.Pack // WARNING: Not thread safe. func (mt *ManagedTransport) readPacket() (packet routing.Packet, err error) { - log := mt.log.WithField("func", "readPacket()") + log := mt.log.WithField("func", "readPacket") var conn *snet.Conn for { diff --git a/pkg/util/rpcutil/log_call.go b/pkg/util/rpcutil/log_call.go new file mode 100644 index 0000000000..a47344da88 --- /dev/null +++ b/pkg/util/rpcutil/log_call.go @@ -0,0 +1,36 @@ +package rpcutil + +import ( + "time" + + "github.com/sirupsen/logrus" +) + +// LogCall is used to log an RPC call from the rpc.Server +func LogCall(log logrus.FieldLogger, method string, in interface{}) func(out interface{}, err *error) { + + // Just in case log is not set. + // However, this is dangerous as it may result in a race condition. + if log == nil { + log = logrus.New() + } + + start := time.Now() + log = log. + WithField("_method", method). + WithField("_received", start.Format(time.Kitchen)) + if in != nil { + log = log.WithField("input", in) + } + + return func(out interface{}, err *error) { + log := log.WithField("_period", time.Since(start).String()) + if out != nil { + log = log.WithField("output", out) + } + if err != nil && *err != nil { + log = log.WithError(*err) + } + log.Info("Request processed.") + } +} diff --git a/pkg/visor/rpc.go b/pkg/visor/rpc.go index 393004ac22..450fd896ed 100644 --- a/pkg/visor/rpc.go +++ b/pkg/visor/rpc.go @@ -14,6 +14,8 @@ import ( "github.com/google/uuid" "github.com/sirupsen/logrus" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/rpcutil" + "github.com/SkycoinProject/skywire-mainnet/pkg/app" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" "github.com/SkycoinProject/skywire-mainnet/pkg/transport" @@ -54,34 +56,6 @@ func newRPCServer(v *Visor, remoteName string) *rpc.Server { return rpcS } -func (r *RPC) logReq(name string, in interface{}) func(out interface{}, err *error) { - - // Just in case r.log is not set. - // However, this is dangerous in production as it may result in a race condition. - if r.log == nil { - r.log = r.visor.Logger.PackageLogger("visor_rpc") - } - - start := time.Now() - log := r.log. - WithField("_method", name). - WithField("_received", start.Format(time.Kitchen)) - if in != nil { - log = log.WithField("input", in) - } - - return func(out interface{}, err *error) { - log := log.WithField("_period", time.Since(start).String()) - if out != nil { - log = log.WithField("output", out) - } - if err != nil && *err != nil { - log = log.WithError(*err) - } - log.Info("Request processed.") - } -} - /* <<< NODE HEALTH >>> */ @@ -95,7 +69,7 @@ type HealthInfo struct { // Health returns health information about the visor func (r *RPC) Health(_ *struct{}, out *HealthInfo) (err error) { - defer r.logReq("Health", nil)(out, &err) + defer rpcutil.LogCall(r.log, "Health", nil)(out, &err) out.TransportDiscovery = http.StatusOK out.RouteFinder = http.StatusOK @@ -122,7 +96,7 @@ func (r *RPC) Health(_ *struct{}, out *HealthInfo) (err error) { // Uptime returns for how long the visor has been running in seconds func (r *RPC) Uptime(_ *struct{}, out *float64) (err error) { - defer r.logReq("Uptime", nil)(out, &err) + defer rpcutil.LogCall(r.log, "Uptime", nil)(out, &err) *out = time.Since(r.visor.startedAt).Seconds() return nil @@ -142,7 +116,7 @@ type AppLogsRequest struct { // LogsSince returns all logs from an specific app since the timestamp func (r *RPC) LogsSince(in *AppLogsRequest, out *[]string) (err error) { - defer r.logReq("LogsSince", in)(out, &err) + defer rpcutil.LogCall(r.log, "LogsSince", in)(out, &err) ls, err := app.NewLogStore(filepath.Join(r.visor.dir(), in.AppName), in.AppName, "bbolt") if err != nil { @@ -199,7 +173,7 @@ type Summary struct { // Summary provides a summary of the AppNode. func (r *RPC) Summary(_ *struct{}, out *Summary) (err error) { - defer r.logReq("Summary", nil)(out, &err) + defer rpcutil.LogCall(r.log, "Summary", nil)(out, &err) var summaries []*TransportSummary r.visor.tm.WalkTransports(func(tp *transport.ManagedTransport) bool { @@ -224,7 +198,7 @@ func (r *RPC) Summary(_ *struct{}, out *Summary) (err error) { // Apps returns list of Apps registered on the Visor. func (r *RPC) Apps(_ *struct{}, reply *[]*AppState) (err error) { - defer r.logReq("Apps", nil)(reply, &err) + defer rpcutil.LogCall(r.log, "Apps", nil)(reply, &err) *reply = r.visor.Apps() return nil @@ -232,14 +206,14 @@ func (r *RPC) Apps(_ *struct{}, reply *[]*AppState) (err error) { // StartApp start App with provided name. func (r *RPC) StartApp(name *string, _ *struct{}) (err error) { - defer r.logReq("StartApp", name)(nil, &err) + defer rpcutil.LogCall(r.log, "StartApp", name)(nil, &err) return r.visor.StartApp(*name) } // StopApp stops App with provided name. func (r *RPC) StopApp(name *string, _ *struct{}) (err error) { - defer r.logReq("StopApp", name)(nil, &err) + defer rpcutil.LogCall(r.log, "StopApp", name)(nil, &err) return r.visor.StopApp(*name) } @@ -252,21 +226,21 @@ type SetAutoStartIn struct { // SetAutoStart sets auto-start settings for an app. func (r *RPC) SetAutoStart(in *SetAutoStartIn, _ *struct{}) (err error) { - defer r.logReq("SetAutoStart", in)(nil, &err) + defer rpcutil.LogCall(r.log, "SetAutoStart", in)(nil, &err) return r.visor.setAutoStart(in.AppName, in.AutoStart) } // SetSocksPassword sets password for skysocks. func (r *RPC) SetSocksPassword(in *string, _ *struct{}) (err error) { - defer r.logReq("SetSocksPassword", in)(nil, &err) + defer rpcutil.LogCall(r.log, "SetSocksPassword", in)(nil, &err) return r.visor.setSocksPassword(*in) } // SetSocksClientPK sets PK for skysocks-client. func (r *RPC) SetSocksClientPK(in *cipher.PubKey, _ *struct{}) (err error) { - defer r.logReq("SetSocksClientPK", in)(nil, &err) + defer rpcutil.LogCall(r.log, "SetSocksClientPK", in)(nil, &err) return r.visor.setSocksClientPK(*in) } @@ -277,7 +251,7 @@ func (r *RPC) SetSocksClientPK(in *cipher.PubKey, _ *struct{}) (err error) { // TransportTypes lists all transport types supported by the Visor. func (r *RPC) TransportTypes(_ *struct{}, out *[]string) (err error) { - defer r.logReq("TransportTypes", nil)(out, &err) + defer rpcutil.LogCall(r.log, "TransportTypes", nil)(out, &err) *out = r.visor.tm.Networks() return nil @@ -292,7 +266,7 @@ type TransportsIn struct { // Transports lists Transports of the Visor and provides a summary of each. func (r *RPC) Transports(in *TransportsIn, out *[]*TransportSummary) (err error) { - defer r.logReq("Transports", in)(out, &err) + defer rpcutil.LogCall(r.log, "Transports", in)(out, &err) typeIncluded := func(tType string) bool { if in.FilterTypes != nil { @@ -327,7 +301,7 @@ func (r *RPC) Transports(in *TransportsIn, out *[]*TransportSummary) (err error) // Transport obtains a Transport Summary of Transport of given Transport ID. func (r *RPC) Transport(in *uuid.UUID, out *TransportSummary) (err error) { - defer r.logReq("Transport", in)(out, &err) + defer rpcutil.LogCall(r.log, "Transport", in)(out, &err) tp := r.visor.tm.Transport(*in) if tp == nil { @@ -347,7 +321,7 @@ type AddTransportIn struct { // AddTransport creates a transport for the visor. func (r *RPC) AddTransport(in *AddTransportIn, out *TransportSummary) (err error) { - defer r.logReq("AddTransport", in)(out, &err) + defer rpcutil.LogCall(r.log, "AddTransport", in)(out, &err) ctx := context.Background() @@ -368,7 +342,7 @@ func (r *RPC) AddTransport(in *AddTransportIn, out *TransportSummary) (err error // RemoveTransport removes a Transport from the visor. func (r *RPC) RemoveTransport(tid *uuid.UUID, _ *struct{}) (err error) { - defer r.logReq("RemoveTransport", tid)(nil, &err) + defer rpcutil.LogCall(r.log, "RemoveTransport", tid)(nil, &err) r.visor.tm.DeleteTransport(*tid) return nil @@ -380,7 +354,7 @@ func (r *RPC) RemoveTransport(tid *uuid.UUID, _ *struct{}) (err error) { // DiscoverTransportsByPK obtains available transports via the transport discovery via given public key. func (r *RPC) DiscoverTransportsByPK(pk *cipher.PubKey, out *[]*transport.EntryWithStatus) (err error) { - defer r.logReq("DiscoverTransportsByPK", pk)(out, &err) + defer rpcutil.LogCall(r.log, "DiscoverTransportsByPK", pk)(out, &err) tpD, err := r.visor.conf.TransportDiscovery() if err != nil { @@ -398,7 +372,7 @@ func (r *RPC) DiscoverTransportsByPK(pk *cipher.PubKey, out *[]*transport.EntryW // DiscoverTransportByID obtains available transports via the transport discovery via a given transport ID. func (r *RPC) DiscoverTransportByID(id *uuid.UUID, out *transport.EntryWithStatus) (err error) { - defer r.logReq("DiscoverTransportByID", id)(out, &err) + defer rpcutil.LogCall(r.log, "DiscoverTransportByID", id)(out, &err) tpD, err := r.visor.conf.TransportDiscovery() if err != nil { @@ -420,7 +394,7 @@ func (r *RPC) DiscoverTransportByID(id *uuid.UUID, out *transport.EntryWithStatu // RoutingRules obtains all routing rules of the RoutingTable. func (r *RPC) RoutingRules(_ *struct{}, out *[]routing.Rule) (err error) { - defer r.logReq("RoutingRules", nil)(out, &err) + defer rpcutil.LogCall(r.log, "RoutingRules", nil)(out, &err) *out = r.visor.router.Rules() return nil @@ -428,7 +402,7 @@ func (r *RPC) RoutingRules(_ *struct{}, out *[]routing.Rule) (err error) { // RoutingRule obtains a routing rule of given RouteID. func (r *RPC) RoutingRule(key *routing.RouteID, rule *routing.Rule) (err error) { - defer r.logReq("RoutingRule", key)(rule, &err) + defer rpcutil.LogCall(r.log, "RoutingRule", key)(rule, &err) *rule, err = r.visor.router.Rule(*key) return err @@ -436,14 +410,14 @@ func (r *RPC) RoutingRule(key *routing.RouteID, rule *routing.Rule) (err error) // SaveRoutingRule saves a routing rule. func (r *RPC) SaveRoutingRule(in *routing.Rule, _ *struct{}) (err error) { - defer r.logReq("SaveRoutingRule", in)(nil, &err) + defer rpcutil.LogCall(r.log, "SaveRoutingRule", in)(nil, &err) return r.visor.router.SaveRule(*in) } // RemoveRoutingRule removes a RoutingRule based on given RouteID key. func (r *RPC) RemoveRoutingRule(key *routing.RouteID, _ *struct{}) (err error) { - defer r.logReq("RemoveRoutingRule", key)(nil, &err) + defer rpcutil.LogCall(r.log, "RemoveRoutingRule", key)(nil, &err) r.visor.router.DelRules([]routing.RouteID{*key}) return nil @@ -462,7 +436,7 @@ type LoopInfo struct { // Loops retrieves loops via rules of the routing table. func (r *RPC) Loops(_ *struct{}, out *[]LoopInfo) (err error) { - defer r.logReq("Loops", nil)(out, &err) + defer rpcutil.LogCall(r.log, "Loops", nil)(out, &err) var loops []LoopInfo @@ -497,7 +471,7 @@ const exitDelay = 100 * time.Millisecond // Restart restarts visor. func (r *RPC) Restart(_ *struct{}, _ *struct{}) (err error) { // @evanlinjin: do not defer this log statement, as the underlying visor.Logger will get closed. - r.logReq("Restart", nil)(nil, nil) + rpcutil.LogCall(r.log, "Restart", nil)(nil, nil) defer func() { if err == nil { @@ -517,7 +491,7 @@ func (r *RPC) Restart(_ *struct{}, _ *struct{}) (err error) { // Exec executes a given command in cmd and writes its output to out. func (r *RPC) Exec(cmd *string, out *[]byte) (err error) { - defer r.logReq("Exec", cmd)(out, &err) + defer rpcutil.LogCall(r.log, "Exec", cmd)(out, &err) *out, err = r.visor.Exec(*cmd) return err @@ -525,7 +499,7 @@ func (r *RPC) Exec(cmd *string, out *[]byte) (err error) { // Update updates visor. func (r *RPC) Update(_ *struct{}, _ *struct{}) (err error) { - defer r.logReq("Update", nil)(nil, &err) + defer rpcutil.LogCall(r.log, "Update", nil)(nil, &err) return r.visor.Update() } diff --git a/vendor/github.com/SkycoinProject/dmsg/httputil/error.go b/vendor/github.com/SkycoinProject/dmsg/httputil/error.go index 5b545990a2..0752c6a05e 100644 --- a/vendor/github.com/SkycoinProject/dmsg/httputil/error.go +++ b/vendor/github.com/SkycoinProject/dmsg/httputil/error.go @@ -1,6 +1,7 @@ package httputil import ( + "bytes" "fmt" "io/ioutil" "net/http" @@ -22,7 +23,7 @@ func ErrorFromResp(resp *http.Response) error { if err != nil && len(msg) == 0 { msg = []byte(fmt.Sprintf("failed to read HTTP response body: %v", err)) } - return &HTTPError{Status: status, Body: string(msg)} + return &HTTPError{Status: status, Body: string(bytes.TrimSpace(msg))} } // Error returns the error message. diff --git a/vendor/modules.txt b/vendor/modules.txt index 2ece7f09d8..9e4174704b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/SkycoinProject/dmsg v0.0.0-20200304115237-130cc9d98ffb +# github.com/SkycoinProject/dmsg v0.0.0-20200305081343-7a67392d759d github.com/SkycoinProject/dmsg github.com/SkycoinProject/dmsg/cipher github.com/SkycoinProject/dmsg/disc From 913bc092895c126c995a6e1c8f2c474d80f100a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Thu, 5 Mar 2020 22:02:33 +0800 Subject: [PATCH 4/5] Further improvements with logging. --- pkg/app/appnet/skywire_networker.go | 16 ++++++++++----- pkg/app/appserver/proc_manager.go | 10 ++++++---- pkg/app/appserver/server.go | 5 +++-- pkg/app/client.go | 11 +++++----- pkg/router/router.go | 14 +++++++++++-- pkg/transport/managed_transport.go | 2 +- pkg/visor/visor.go | 31 +++++++++++++++++++---------- 7 files changed, 60 insertions(+), 29 deletions(-) diff --git a/pkg/app/appnet/skywire_networker.go b/pkg/app/appnet/skywire_networker.go index a7e731588a..4bf78bc5f5 100644 --- a/pkg/app/appnet/skywire_networker.go +++ b/pkg/app/appnet/skywire_networker.go @@ -5,6 +5,7 @@ import ( "errors" "io" "net" + "strings" "sync" "sync/atomic" @@ -87,8 +88,8 @@ func (r *SkywireNetworker) ListenContext(ctx context.Context, addr Addr) (net.Li if atomic.CompareAndSwapInt32(&r.isServing, 0, 1) { go func() { - if err := r.serveLoop(ctx); err != nil { - r.log.WithError(err).Error("error serving") + if err := r.serveLoop(ctx); err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + r.log.WithError(err).Error("serveLoop stopped unexpectedly.") } }() } @@ -98,16 +99,21 @@ func (r *SkywireNetworker) ListenContext(ctx context.Context, addr Addr) (net.Li // serveLoop accepts and serves routes. func (r *SkywireNetworker) serveLoop(ctx context.Context) error { + log := r.log.WithField("func", "serveLoop") + for { - r.log.Infoln("Trying to accept routing group...") + log.Debug("Awaiting to accept route group...") rg, err := r.r.AcceptRoutes(ctx) if err != nil { - r.log.Infof("Error accepting routing group: %v", err) + log.WithError(err).Info("Stopped accepting routes.") return err } - r.log.Infoln("Accepted routing group") + log. + WithField("local", rg.LocalAddr()). + WithField("remote", rg.RemoteAddr()). + Info("Accepted route group.") go r.serve(rg) } diff --git a/pkg/app/appserver/proc_manager.go b/pkg/app/appserver/proc_manager.go index 194aba08e5..9bee5fad05 100644 --- a/pkg/app/appserver/proc_manager.go +++ b/pkg/app/appserver/proc_manager.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os/exec" + "strings" "sync" "github.com/SkycoinProject/skycoin/src/util/logging" @@ -140,11 +141,12 @@ func (m *procManager) StopAll() { defer m.mx.Unlock() for name, proc := range m.procs { - if err := proc.Stop(); err != nil { - m.log.WithError(err).Errorf("(%s) failed to stop app", name) - } else { - m.log.Infof("(%s) app stopped successfully", name) + log := m.log.WithField("app_name", name) + if err := proc.Stop(); err != nil && strings.Contains(err.Error(), "process already finished") { + log.WithError(err).Error("Failed to stop app.") + continue } + log.Infof("App stopped successfully.") } m.procs = make(map[string]*Proc) diff --git a/pkg/app/appserver/server.go b/pkg/app/appserver/server.go index b2d761b455..34781a3b6e 100644 --- a/pkg/app/appserver/server.go +++ b/pkg/app/appserver/server.go @@ -4,6 +4,7 @@ import ( "fmt" "net" "net/rpc" + "strings" "sync" "github.com/SkycoinProject/skycoin/src/util/logging" @@ -81,8 +82,8 @@ func (s *Server) serveConn(conn net.Conn) { <-s.stopCh - if err := conn.Close(); err != nil { - s.log.WithError(err).Error("error closing conn") + if err := conn.Close(); err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + s.log.WithError(err).Error("Unexpected error while closing conn.") } s.done.Done() diff --git a/pkg/app/client.go b/pkg/app/client.go index 50cbc3f04c..dedd2d494f 100644 --- a/pkg/app/client.go +++ b/pkg/app/client.go @@ -6,6 +6,7 @@ import ( "net" "net/rpc" "os" + "strings" "github.com/SkycoinProject/dmsg/cipher" "github.com/SkycoinProject/skycoin/src/util/logging" @@ -115,8 +116,8 @@ func (c *Client) Dial(remote appnet.Addr) (net.Conn, error) { if err != nil { conn.freeConnMx.Unlock() - if err := conn.Close(); err != nil { - c.log.WithError(err).Error("error closing conn") + if err := conn.Close(); err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + c.log.WithError(err).Error("Unexpected error while closing conn.") } return nil, err @@ -201,13 +202,13 @@ func (c *Client) Close() { for _, lis := range listeners { if err := lis.Close(); err != nil { - c.log.WithError(err).Error("error closing listener") + c.log.WithError(err).Error("Error closing listener.") } } for _, conn := range conns { - if err := conn.Close(); err != nil { - c.log.WithError(err).Error("error closing conn") + if err := conn.Close(); err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + c.log.WithError(err).Error("Unexpected error while closing conn.") } } } diff --git a/pkg/router/router.go b/pkg/router/router.go index 5655751ec1..389c159a43 100644 --- a/pkg/router/router.go +++ b/pkg/router/router.go @@ -11,6 +11,7 @@ import ( "sync" "time" + "github.com/SkycoinProject/dmsg" "github.com/SkycoinProject/dmsg/cipher" "github.com/SkycoinProject/skycoin/src/util/logging" @@ -286,7 +287,11 @@ func (r *router) serveTransportManager(ctx context.Context) { for { packet, err := r.tm.ReadPacket() if err != nil { - r.logger.WithError(err).Errorf("Failed to read packet") + if err == transport.ErrNotServing { + r.logger.WithError(err).Info("Stopped reading packets") + return + } + r.logger.WithError(err).Error("Stopped reading packets due to unexpected error.") return } @@ -305,7 +310,12 @@ func (r *router) serveSetup() { for { conn, err := r.sl.AcceptConn() if err != nil { - r.logger.WithError(err).Warnf("setup client stopped serving") + log := r.logger.WithError(err) + if err == dmsg.ErrEntityClosed { + log.Info("Setup client stopped serving.") + } else { + log.Error("Setup client stopped serving due to unexpected error.") + } return } diff --git a/pkg/transport/managed_transport.go b/pkg/transport/managed_transport.go index 22faa76aa4..f5eacab6ae 100644 --- a/pkg/transport/managed_transport.go +++ b/pkg/transport/managed_transport.go @@ -543,7 +543,7 @@ func (mt *ManagedTransport) readPacket() (packet routing.Packet, err error) { log.WithError(err).Debugf("Failed to read packet payload.") return nil, err } - log.WithField("payload_len", len(p)).WithField("payload_raw", p).Debug("Read packet payload.") + log.WithField("payload_len", len(p)).Debug("Read packet payload.") packet = append(h, p...) if n := len(packet); n > routing.PacketHeaderSize { diff --git a/pkg/visor/visor.go b/pkg/visor/visor.go index e0ec717736..53d9e971a9 100644 --- a/pkg/visor/visor.go +++ b/pkg/visor/visor.go @@ -223,8 +223,8 @@ func NewVisor(cfg *Config, logger *logging.MasterLogger, restartCtx *restart.Con visor.appRPCServer = appserver.New(logging.MustGetLogger("app_rpc_server"), visor.conf.AppServerSockFile) go func() { - if err := visor.appRPCServer.ListenAndServe(); err != nil { - visor.logger.WithError(err).Error("error serving RPC") + if err := visor.appRPCServer.ListenAndServe(); err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + visor.logger.WithError(err).Error("Serve app_rpc stopped.") } }() @@ -279,7 +279,10 @@ func (visor *Visor) startApps() { go func(a AppConfig) { if err := visor.SpawnApp(&a, nil); err != nil { - visor.logger.Warnf("App %s stopped working: %v", a.App, err) + visor.logger. + WithError(err). + WithField("app_name", a.App). + Warn("App stopped.") } }(ac) } @@ -456,19 +459,21 @@ func (visor *Visor) Close() (err error) { visor.procManager.StopAll() if err = visor.router.Close(); err != nil { - visor.logger.WithError(err).Error("failed to stop router") + visor.logger.WithError(err).Error("Failed to stop router.") } else { - visor.logger.Info("router stopped successfully") + visor.logger.Info("Router stopped successfully.") } if err := visor.appRPCServer.Close(); err != nil { - visor.logger.WithError(err).Error("error closing RPC server") + visor.logger.WithError(err).Error("RPC server closed with error.") } if err := UnlinkSocketFiles(visor.conf.AppServerSockFile); err != nil { - visor.logger.WithError(err).Errorf("Failed to unlink socket file %s", visor.conf.AppServerSockFile) + visor.logger.WithError(err).WithField("file_name", visor.conf.AppServerSockFile). + Error("Failed to unlink socket file.") } else { - visor.logger.Infof("Socket file %s removed successfully", visor.conf.AppServerSockFile) + visor.logger.WithField("file_name", visor.conf.AppServerSockFile). + Debug("Socket file removed successfully.") } return err @@ -513,7 +518,10 @@ func (visor *Visor) StartApp(appName string) error { go func(app AppConfig) { if err := visor.SpawnApp(&app, startCh); err != nil { - visor.logger.Warnf("App %s stopped working: %v", appName, err) + visor.logger. + WithError(err). + WithField("app_name", appName). + Warn("App stopped.") } }(app) @@ -527,7 +535,10 @@ func (visor *Visor) StartApp(appName string) error { // SpawnApp configures and starts new App. func (visor *Visor) SpawnApp(config *AppConfig, startCh chan<- struct{}) (err error) { - visor.logger.Infof("Starting %s", config.App) + visor.logger. + WithField("app_name", config.App). + WithField("args", config.Args). + Info("Spawning app.") if app, ok := reservedPorts[config.Port]; ok && app != config.App { return fmt.Errorf("can't bind to reserved port %d", config.Port) From 3793153de71c3d03b960ebe232f5d2c6b122a3df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Fri, 6 Mar 2020 17:09:38 +0800 Subject: [PATCH 5/5] Fixes as suggested by @nkryuchkov --- pkg/app/appserver/rpc_gateway.go | 3 +-- pkg/util/rpcutil/log_call.go | 3 +-- pkg/visor/rpc.go | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pkg/app/appserver/rpc_gateway.go b/pkg/app/appserver/rpc_gateway.go index b2b4123f43..815c5177ec 100644 --- a/pkg/app/appserver/rpc_gateway.go +++ b/pkg/app/appserver/rpc_gateway.go @@ -9,11 +9,10 @@ import ( "github.com/SkycoinProject/skycoin/src/util/logging" - "github.com/SkycoinProject/skywire-mainnet/pkg/util/rpcutil" - "github.com/SkycoinProject/skywire-mainnet/pkg/app/appnet" "github.com/SkycoinProject/skywire-mainnet/pkg/app/idmanager" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/rpcutil" ) // RPCIOErr is used to return an error coming from network stack. diff --git a/pkg/util/rpcutil/log_call.go b/pkg/util/rpcutil/log_call.go index a47344da88..80bbf5c407 100644 --- a/pkg/util/rpcutil/log_call.go +++ b/pkg/util/rpcutil/log_call.go @@ -10,7 +10,6 @@ import ( func LogCall(log logrus.FieldLogger, method string, in interface{}) func(out interface{}, err *error) { // Just in case log is not set. - // However, this is dangerous as it may result in a race condition. if log == nil { log = logrus.New() } @@ -24,7 +23,7 @@ func LogCall(log logrus.FieldLogger, method string, in interface{}) func(out int } return func(out interface{}, err *error) { - log := log.WithField("_period", time.Since(start).String()) + log := log.WithField("_elapsed", time.Since(start).String()) if out != nil { log = log.WithField("output", out) } diff --git a/pkg/visor/rpc.go b/pkg/visor/rpc.go index 450fd896ed..a84d2f3fe2 100644 --- a/pkg/visor/rpc.go +++ b/pkg/visor/rpc.go @@ -14,12 +14,11 @@ import ( "github.com/google/uuid" "github.com/sirupsen/logrus" - "github.com/SkycoinProject/skywire-mainnet/pkg/util/rpcutil" - "github.com/SkycoinProject/skywire-mainnet/pkg/app" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" "github.com/SkycoinProject/skywire-mainnet/pkg/transport" "github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/rpcutil" ) const (