diff --git a/config.json b/config.json index 9b8fe5db33408029aa287792424d4b1997d395b5..b702dcb030c64fa5b6b5237d8b6ce9cd152f3304 100644 --- a/config.json +++ b/config.json @@ -1,49 +1,64 @@ { "analysis": { - "serveraddress": "ressims.iota.cafe:188", - "serverport": 0 + "client": { + "serverAddress": "ressims.iota.cafe:188" + }, + "server": { + "port": 0 + }, + "httpServer": { + "bindAddress": "0.0.0.0:80" + } }, "autopeering": { - "address": "0.0.0.0", - "entrynodes": [ + "entryNodes": [ "V8LYtWWcPYYDTTXLeIEFjJEuWlsjDiI0+Pq/Cx9ai6g=@116.202.49.178:14626" ], "port": 14626 }, + "dashboard": { + "bindAddress": "0.0.0.0:8081" + }, "database": { "directory": "mainnetdb" }, "gossip": { "port": 14666 }, - "webapi": { - "bindAddress": "0.0.0.0:8080", - "auth": { - "username": "goshimmer", - "password": "goshimmer", - "privateKey": "uUUavNbdr32jE9CqnSMCKt4HMu9AZ2K4rKekUSPx9jk83eyeM7xewv5CqUKYMC9" - } - }, "graph": { - "webrootPath": "./IOTAtangle/webroot", - "socketioPath": "./socket.io-client/dist/socket.io.js", + "bindAddress": "127.0.0.1:8083", "domain": "", - "host": "127.0.0.1", - "port": 8083, - "networkName": "GoShimmer" + "networkName": "GoShimmer", + "socketIOPath": "socket.io-client/dist/socket.io.js", + "webrootPath": "IOTAtangle/webroot" }, "logger": { - "Level": "info", - "DisableCaller": false, - "DisableStacktrace": false, - "Encoding": "console", - "OutputPaths": [ + "level": "info", + "disableCaller": false, + "disableStacktrace": false, + "encoding": "console", + "outputPaths": [ "goshimmer.log" - ] + ], + "disableEvents": false + }, + "network": { + "bindAddress": "0.0.0.0", + "externalAddress": "auto" }, "node": { - "disableplugins": "", - "enableplugins": [], - "loglevel": 0 + "disablePlugins": [], + "enablePlugins": [] + }, + "webapi": { + "auth": { + "password": "goshimmer", + "privateKey": "", + "username": "goshimmer" + }, + "bindAddress": "0.0.0.0:8080" + }, + "zeromq": { + "port": 5556 } -} \ No newline at end of file +} diff --git a/packages/autopeering/discover/manager_test.go b/packages/autopeering/discover/manager_test.go index afe6a3899c5e9aeb3de0b5c19e922f4b6f232ffd..fb0132a1b4f1b074a53409f8e4bed9bd62f335e4 100644 --- a/packages/autopeering/discover/manager_test.go +++ b/packages/autopeering/discover/manager_test.go @@ -33,7 +33,9 @@ func (m *NetworkMock) DiscoveryRequest(p *peer.Peer) ([]*peer.Peer, error) { } func newNetworkMock() *NetworkMock { - local, _ := peer.NewLocal("mock", "0", peer.NewMemoryDB(log)) + services := service.New() + services.Update(service.PeeringKey, "mock", "local") + local, _ := peer.NewLocal(services, peer.NewMemoryDB(log)) return &NetworkMock{ // no database needed loc: local, diff --git a/packages/autopeering/discover/protocol_test.go b/packages/autopeering/discover/protocol_test.go index fd294f7bcacedfcbba2a13b247ddbcf088feb08e..92a5740dd64f69e2301bf070ab6c2a1e11251102 100644 --- a/packages/autopeering/discover/protocol_test.go +++ b/packages/autopeering/discover/protocol_test.go @@ -31,8 +31,11 @@ func init() { // newTest creates a new discovery server and also returns the teardown. func newTest(t require.TestingT, trans transport.Transport, logger *logger.Logger, masters ...*peer.Peer) (*server.Server, *Protocol, func()) { l := logger.Named(trans.LocalAddr().String()) + + services := service.New() + services.Update(service.PeeringKey, trans.LocalAddr().Network(), trans.LocalAddr().String()) db := peer.NewMemoryDB(l.Named("db")) - local, err := peer.NewLocal(trans.LocalAddr().Network(), trans.LocalAddr().String(), db) + local, err := peer.NewLocal(services, db) require.NoError(t, err) cfg := Config{ @@ -40,7 +43,7 @@ func newTest(t require.TestingT, trans transport.Transport, logger *logger.Logge MasterPeers: masters, } prot := New(local, cfg) - srv := server.Listen(local, trans, l.Named("srv"), prot) + srv := server.Serve(local, trans, l.Named("srv"), prot) prot.Start(srv) teardown := func() { diff --git a/packages/autopeering/peer/local.go b/packages/autopeering/peer/local.go index 19595a32cc5244806a12b1394bff342dc9f1dc58..989d0ff83402f4983bd0a7c33015f43a2aab5d40 100644 --- a/packages/autopeering/peer/local.go +++ b/packages/autopeering/peer/local.go @@ -44,7 +44,7 @@ func newLocal(key PrivateKey, serviceRecord *service.Record, db DB) *Local { // NewLocal creates a new local peer linked to the provided db. // If an optional seed is provided, the seed is used to generate the private key. Without a seed, // the provided key is loaded from the provided database and generated if not stored there. -func NewLocal(network string, address string, db DB, seed ...[]byte) (*Local, error) { +func NewLocal(serviceRecord *service.Record, db DB, seed ...[]byte) (*Local, error) { var key PrivateKey if len(seed) > 0 { key = PrivateKey(ed25519.NewKeyFromSeed(seed[0])) @@ -62,10 +62,6 @@ func NewLocal(network string, address string, db DB, seed ...[]byte) (*Local, er if l := len(key); l != ed25519.PrivateKeySize { return nil, fmt.Errorf("invalid key length: %d, need %d", l, ed25519.PrivateKeySize) } - // update the external address used for the peering - serviceRecord := service.New() - serviceRecord.Update(service.PeeringKey, network, address) - return newLocal(key, serviceRecord, db), nil } diff --git a/packages/autopeering/peer/local_test.go b/packages/autopeering/peer/local_test.go index aa50862c1a5243afc8586707027475f4e6f3414e..469ef80f7c7a6f9a7b596cef7a4fcc6debb9af5f 100644 --- a/packages/autopeering/peer/local_test.go +++ b/packages/autopeering/peer/local_test.go @@ -28,36 +28,45 @@ func TestPublicKey(t *testing.T) { assert.EqualValues(t, pub, local.PublicKey()) } -func newTestLocal(t require.TestingT) *Local { - priv, err := generatePrivateKey() - require.NoError(t, err) - return newLocal(priv, newTestServiceRecord(), nil) -} - func TestAddress(t *testing.T) { - local := newTestLocal(t) + local := newTestLocal(t, nil) address := local.Services().Get(service.PeeringKey).String() assert.EqualValues(t, address, local.Address()) } func TestPrivateSalt(t *testing.T) { - p := newTestLocal(t) + p := newTestLocal(t, nil) - salt, _ := salt.NewSalt(time.Second * 10) - p.SetPrivateSalt(salt) + s, _ := salt.NewSalt(time.Second * 10) + p.SetPrivateSalt(s) got := p.GetPrivateSalt() - assert.Equal(t, salt, got, "Private salt") + assert.Equal(t, s, got, "Private salt") } func TestPublicSalt(t *testing.T) { - p := newTestLocal(t) + p := newTestLocal(t, nil) - salt, _ := salt.NewSalt(time.Second * 10) - p.SetPublicSalt(salt) + s, _ := salt.NewSalt(time.Second * 10) + p.SetPublicSalt(s) got := p.GetPublicSalt() - assert.Equal(t, salt, got, "Public salt") + assert.Equal(t, s, got, "Public salt") +} + +func newTestLocal(t require.TestingT, db DB) *Local { + var priv PrivateKey + var err error + if db == nil { + priv, err = generatePrivateKey() + require.NoError(t, err) + } else { + priv, err = db.LocalPrivateKey() + require.NoError(t, err) + } + services := service.New() + services.Update(service.PeeringKey, testNetwork, testAddress) + return newLocal(priv, services, db) } diff --git a/packages/autopeering/peer/mapdb_test.go b/packages/autopeering/peer/mapdb_test.go index 5c7580b743e31b3d064e618c8d292e04b53cd0ed..494f669181661461f3636b79add9e715cba463f6 100644 --- a/packages/autopeering/peer/mapdb_test.go +++ b/packages/autopeering/peer/mapdb_test.go @@ -58,12 +58,9 @@ func TestMapDBSeedPeers(t *testing.T) { func TestMapDBLocal(t *testing.T) { db := NewMemoryDB(log) - l1, err := NewLocal(testNetwork, testAddress, db) - require.NoError(t, err) + l1 := newTestLocal(t, db) assert.Equal(t, len(l1.PublicKey()), ed25519.PublicKeySize) - l2, err := NewLocal(testNetwork, testAddress, db) - require.NoError(t, err) - + l2 := newTestLocal(t, db) assert.Equal(t, l1, l2) } diff --git a/packages/autopeering/selection/manager_test.go b/packages/autopeering/selection/manager_test.go index af24ee4161a1f0aebe465a3d868fdca54db3cff1..cf5a961f77999fff984a77f75a483d6867b0bf22 100644 --- a/packages/autopeering/selection/manager_test.go +++ b/packages/autopeering/selection/manager_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/iotaledger/goshimmer/packages/autopeering/peer" + "github.com/iotaledger/goshimmer/packages/autopeering/peer/service" "github.com/iotaledger/goshimmer/packages/autopeering/salt" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/logger" @@ -186,7 +187,9 @@ type networkMock struct { } func newNetworkMock(name string, mgrMap map[peer.ID]*manager, log *logger.Logger) *networkMock { - local, _ := peer.NewLocal("mock", name, peer.NewMemoryDB(log)) + services := service.New() + services.Update(service.PeeringKey, "mock", name) + local, _ := peer.NewLocal(services, peer.NewMemoryDB(log)) return &networkMock{ loc: local, mgr: mgrMap, diff --git a/packages/autopeering/selection/protocol_test.go b/packages/autopeering/selection/protocol_test.go index ce6e59e1ba299fcdf1fec458ffbabd0406101b5d..c2e99035602946d2bfa9b60dfdbe49dd46714881 100644 --- a/packages/autopeering/selection/protocol_test.go +++ b/packages/autopeering/selection/protocol_test.go @@ -6,6 +6,7 @@ import ( "github.com/iotaledger/goshimmer/packages/autopeering/discover" "github.com/iotaledger/goshimmer/packages/autopeering/peer" + "github.com/iotaledger/goshimmer/packages/autopeering/peer/service" "github.com/iotaledger/goshimmer/packages/autopeering/salt" "github.com/iotaledger/goshimmer/packages/autopeering/server" "github.com/iotaledger/goshimmer/packages/autopeering/transport" @@ -31,15 +32,18 @@ func (d dummyDiscovery) GetVerifiedPeers() []*peer.Peer { retur // newTest creates a new neighborhood server and also returns the teardown. func newTest(t require.TestingT, trans transport.Transport) (*server.Server, *Protocol, func()) { l := log.Named(trans.LocalAddr().String()) + + services := service.New() + services.Update(service.PeeringKey, trans.LocalAddr().Network(), trans.LocalAddr().String()) db := peer.NewMemoryDB(l.Named("db")) - local, err := peer.NewLocal(trans.LocalAddr().Network(), trans.LocalAddr().String(), db) + local, err := peer.NewLocal(services, db) require.NoError(t, err) // add the new peer to the global map for dummyDiscovery peerMap[local.ID()] = &local.Peer prot := New(local, dummyDiscovery{}, Config{Log: l}) - srv := server.Listen(local, trans, l.Named("srv"), prot) + srv := server.Serve(local, trans, l.Named("srv"), prot) prot.Start(srv) teardown := func() { @@ -155,8 +159,11 @@ func TestProtocol(t *testing.T) { // newTest creates a new server handling discover as well as neighborhood and also returns the teardown. func newFullTest(t require.TestingT, trans transport.Transport, masterPeers ...*peer.Peer) (*server.Server, *Protocol, func()) { l := log.Named(trans.LocalAddr().String()) + + services := service.New() + services.Update(service.PeeringKey, trans.LocalAddr().Network(), trans.LocalAddr().String()) db := peer.NewMemoryDB(l.Named("db")) - local, err := peer.NewLocal(trans.LocalAddr().Network(), trans.LocalAddr().String(), db) + local, err := peer.NewLocal(services, db) require.NoError(t, err) discovery := discover.New(local, discover.Config{ @@ -167,7 +174,7 @@ func newFullTest(t require.TestingT, trans transport.Transport, masterPeers ...* Log: l.Named("sel"), }) - srv := server.Listen(local, trans, l.Named("srv"), discovery, selection) + srv := server.Serve(local, trans, l.Named("srv"), discovery, selection) discovery.Start(srv) selection.Start(srv) diff --git a/packages/autopeering/server/server.go b/packages/autopeering/server/server.go index 88ca6cc55daa53d44da03e69e7f05875c2b5ee1b..d1bca6aabd5a12d3ed9f663ebf9d2d9b449d1b00 100644 --- a/packages/autopeering/server/server.go +++ b/packages/autopeering/server/server.go @@ -68,10 +68,10 @@ type reply struct { matchedRequest chan<- bool // a matching request is indicated via this channel } -// Listen starts a new peer server using the given transport layer for communication. +// Serve starts a new peer server using the given transport layer for communication. // Sent data is signed using the identity of the local peer, // received data with a valid peer signature is handled according to the provided Handler. -func Listen(local *peer.Local, t transport.Transport, log *logger.Logger, h ...Handler) *Server { +func Serve(local *peer.Local, t transport.Transport, log *logger.Logger, h ...Handler) *Server { srv := &Server{ local: local, trans: t, @@ -88,7 +88,10 @@ func Listen(local *peer.Local, t transport.Transport, log *logger.Logger, h ...H go srv.replyLoop() go srv.readLoop() - log.Debugw("server started", "addr", srv.LocalAddr(), "#handlers", len(h)) + log.Debugw("server started", + "network", srv.LocalAddr().Network(), + "address", srv.LocalAddr().String(), + "#handlers", len(h)) return srv } diff --git a/packages/autopeering/server/server_test.go b/packages/autopeering/server/server_test.go index 58bc5a60e3134a2f03bb423bf4d9bfddd13682c6..e6725fc0facfcc568ecc20b5277d09fdd089cacb 100644 --- a/packages/autopeering/server/server_test.go +++ b/packages/autopeering/server/server_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/iotaledger/goshimmer/packages/autopeering/peer" + "github.com/iotaledger/goshimmer/packages/autopeering/peer/service" "github.com/iotaledger/goshimmer/packages/autopeering/salt" "github.com/iotaledger/goshimmer/packages/autopeering/transport" "github.com/iotaledger/hive.go/logger" @@ -96,8 +97,9 @@ func unmarshal(data []byte) (Message, error) { } func TestSrvEncodeDecodePing(t *testing.T) { - // create minimal server just containing the local peer - local, err := peer.NewLocal("dummy", "local", peer.NewMemoryDB(log)) + services := service.New() + services.Update(service.PeeringKey, "dummy", "local") + local, err := peer.NewLocal(services, peer.NewMemoryDB(log)) require.NoError(t, err) s := &Server{local: local} @@ -114,8 +116,11 @@ func TestSrvEncodeDecodePing(t *testing.T) { func newTestServer(t require.TestingT, name string, trans transport.Transport) (*Server, func()) { l := log.Named(name) + + services := service.New() + services.Update(service.PeeringKey, trans.LocalAddr().Network(), trans.LocalAddr().String()) db := peer.NewMemoryDB(l.Named("db")) - local, err := peer.NewLocal(trans.LocalAddr().Network(), trans.LocalAddr().String(), db) + local, err := peer.NewLocal(services, db) require.NoError(t, err) s, _ := salt.NewSalt(100 * time.Second) @@ -123,7 +128,7 @@ func newTestServer(t require.TestingT, name string, trans transport.Transport) ( s, _ = salt.NewSalt(100 * time.Second) local.SetPublicSalt(s) - srv := Listen(local, trans, l, HandlerFunc(handle)) + srv := Serve(local, trans, l, HandlerFunc(handle)) teardown := func() { srv.Close() diff --git a/packages/gossip/manager_test.go b/packages/gossip/manager_test.go index eb86bf01e7d173dc088923d7aeba6612613797f0..ea19d48097cd9c1ec16ccdecef5e4a66ab6f249c 100644 --- a/packages/gossip/manager_test.go +++ b/packages/gossip/manager_test.go @@ -27,46 +27,6 @@ var ( func getTestTransaction([]byte) ([]byte, error) { return testTxData, nil } -func getTCPAddress(t require.TestingT) string { - tcpAddr, err := net.ResolveTCPAddr("tcp", "localhost:0") - require.NoError(t, err) - lis, err := net.ListenTCP("tcp", tcpAddr) - require.NoError(t, err) - - addr := lis.Addr().String() - require.NoError(t, lis.Close()) - - return addr -} - -func newTestManager(t require.TestingT, name string) (*Manager, func(), *peer.Peer) { - l := log.Named(name) - db := peer.NewMemoryDB(l.Named("db")) - local, err := peer.NewLocal("peering", name, db) - require.NoError(t, err) - - // enable TCP gossipping - require.NoError(t, local.UpdateService(service.GossipKey, "tcp", getTCPAddress(t))) - - mgr := NewManager(local, getTestTransaction, l) - - srv, err := server.ListenTCP(local, l) - require.NoError(t, err) - - // update the service with the actual address - require.NoError(t, local.UpdateService(service.GossipKey, srv.LocalAddr().Network(), srv.LocalAddr().String())) - - // start the actual gossipping - mgr.Start(srv) - - detach := func() { - mgr.Close() - srv.Close() - db.Close() - } - return mgr, detach, &local.Peer -} - func TestClose(t *testing.T) { _, detach := newEventMock(t) defer detach() @@ -409,6 +369,38 @@ func TestTxRequest(t *testing.T) { e.AssertExpectations(t) } +func newTestManager(t require.TestingT, name string) (*Manager, func(), *peer.Peer) { + l := log.Named(name) + + services := service.New() + services.Update(service.PeeringKey, "peering", name) + db := peer.NewMemoryDB(l.Named("db")) + local, err := peer.NewLocal(services, db) + require.NoError(t, err) + + laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0") + require.NoError(t, err) + lis, err := net.ListenTCP("tcp", laddr) + require.NoError(t, err) + + // enable TCP gossipping + require.NoError(t, local.UpdateService(service.GossipKey, lis.Addr().Network(), lis.Addr().String())) + + srv := server.ServeTCP(local, lis, l) + + // start the actual gossipping + mgr := NewManager(local, getTestTransaction, l) + mgr.Start(srv) + + detach := func() { + mgr.Close() + srv.Close() + _ = lis.Close() + db.Close() + } + return mgr, detach, &local.Peer +} + func newEventMock(t mock.TestingT) (*eventMock, func()) { e := &eventMock{} e.Test(t) diff --git a/packages/gossip/server/server.go b/packages/gossip/server/server.go index bb52798c93bd7e6a43aace85cdae9d41745bc84c..c3853ac04955d9f867a4d82c48b7b55987f460f5 100644 --- a/packages/gossip/server/server.go +++ b/packages/gossip/server/server.go @@ -77,39 +77,22 @@ type accept struct { conn net.Conn // the actual network connection } -// ListenTCP creates the object and starts listening for incoming connections. -func ListenTCP(local *peer.Local, log *zap.SugaredLogger) (*TCP, error) { +// ServeTCP creates the object and starts listening for incoming connections. +func ServeTCP(local *peer.Local, listener *net.TCPListener, log *zap.SugaredLogger) *TCP { t := &TCP{ local: local, + publicAddr: local.Services().Get(service.GossipKey), + listener: listener, log: log, addAcceptMatcher: make(chan *acceptMatcher), acceptReceived: make(chan accept), closing: make(chan struct{}), } - - t.publicAddr = local.Services().Get(service.GossipKey) if t.publicAddr == nil { - return nil, ErrNoGossip - } - tcpAddr, err := net.ResolveTCPAddr(t.publicAddr.Network(), t.publicAddr.String()) - if err != nil { - return nil, err - } - // if the ip is an external ip, set it to unspecified - if tcpAddr.IP.IsGlobalUnicast() { - if tcpAddr.IP.To4() != nil { - tcpAddr.IP = net.IPv4zero - } else { - tcpAddr.IP = net.IPv6unspecified - } + panic(ErrNoGossip) } - listener, err := net.ListenTCP(t.publicAddr.Network(), tcpAddr) - if err != nil { - return nil, err - } - t.listener = listener - t.log.Debugw("listening started", + t.log.Debugw("server started", "network", listener.Addr().Network(), "address", listener.Addr().String(), ) @@ -118,7 +101,7 @@ func ListenTCP(local *peer.Local, log *zap.SugaredLogger) (*TCP, error) { go t.run() go t.listenLoop() - return t, nil + return t } // Close stops listening on the gossip address. diff --git a/packages/gossip/server/server_test.go b/packages/gossip/server/server_test.go index 9aa398fb88a8f5fa53ed545591a3fe1f1113e641..5f2778a10e2aad2b20061ff0473c46f847403a2a 100644 --- a/packages/gossip/server/server_test.go +++ b/packages/gossip/server/server_test.go @@ -17,48 +17,17 @@ const graceTime = 5 * time.Millisecond var log = logger.NewExampleLogger("server") -func getTCPAddress(t require.TestingT) string { - laddr, err := net.ResolveTCPAddr("tcp", "localhost:0") - require.NoError(t, err) - lis, err := net.ListenTCP("tcp", laddr) - require.NoError(t, err) - - addr := lis.Addr().String() - require.NoError(t, lis.Close()) - - return addr -} - -func newTest(t require.TestingT, name string) (*TCP, func()) { - l := log.Named(name) - db := peer.NewMemoryDB(l.Named("db")) - local, err := peer.NewLocal("peering", name, db) - require.NoError(t, err) - - // enable TCP gossipping - require.NoError(t, local.UpdateService(service.GossipKey, "tcp", getTCPAddress(t))) - - trans, err := ListenTCP(local, l) - require.NoError(t, err) - - teardown := func() { - trans.Close() - db.Close() - } - return trans, teardown -} - func getPeer(t *TCP) *peer.Peer { return &t.local.Peer } func TestClose(t *testing.T) { - _, teardown := newTest(t, "A") + _, teardown := newTestServer(t, "A") teardown() } func TestUnansweredAccept(t *testing.T) { - transA, closeA := newTest(t, "A") + transA, closeA := newTestServer(t, "A") defer closeA() _, err := transA.AcceptPeer(getPeer(transA)) @@ -66,7 +35,7 @@ func TestUnansweredAccept(t *testing.T) { } func TestCloseWhileAccepting(t *testing.T) { - transA, closeA := newTest(t, "A") + transA, closeA := newTestServer(t, "A") var wg sync.WaitGroup wg.Add(1) @@ -82,7 +51,7 @@ func TestCloseWhileAccepting(t *testing.T) { } func TestUnansweredDial(t *testing.T) { - transA, closeA := newTest(t, "A") + transA, closeA := newTestServer(t, "A") defer closeA() // create peer with invalid gossip address @@ -95,7 +64,7 @@ func TestUnansweredDial(t *testing.T) { } func TestNoHandshakeResponse(t *testing.T) { - transA, closeA := newTest(t, "A") + transA, closeA := newTestServer(t, "A") defer closeA() // accept and read incoming connections @@ -119,7 +88,7 @@ func TestNoHandshakeResponse(t *testing.T) { } func TestNoHandshakeRequest(t *testing.T) { - transA, closeA := newTest(t, "A") + transA, closeA := newTestServer(t, "A") defer closeA() var wg sync.WaitGroup @@ -140,9 +109,9 @@ func TestNoHandshakeRequest(t *testing.T) { } func TestConnect(t *testing.T) { - transA, closeA := newTest(t, "A") + transA, closeA := newTestServer(t, "A") defer closeA() - transB, closeB := newTest(t, "B") + transB, closeB := newTestServer(t, "B") defer closeB() var wg sync.WaitGroup @@ -153,7 +122,7 @@ func TestConnect(t *testing.T) { c, err := transA.AcceptPeer(getPeer(transB)) assert.NoError(t, err) if assert.NotNil(t, c) { - c.Close() + _ = c.Close() } }() time.Sleep(graceTime) @@ -162,7 +131,7 @@ func TestConnect(t *testing.T) { c, err := transB.DialPeer(getPeer(transA)) assert.NoError(t, err) if assert.NotNil(t, c) { - c.Close() + _ = c.Close() } }() @@ -170,11 +139,11 @@ func TestConnect(t *testing.T) { } func TestWrongConnect(t *testing.T) { - transA, closeA := newTest(t, "A") + transA, closeA := newTestServer(t, "A") defer closeA() - transB, closeB := newTest(t, "B") + transB, closeB := newTestServer(t, "B") defer closeB() - transC, closeC := newTest(t, "C") + transC, closeC := newTestServer(t, "C") defer closeC() var wg sync.WaitGroup @@ -194,3 +163,30 @@ func TestWrongConnect(t *testing.T) { wg.Wait() } + +func newTestServer(t require.TestingT, name string) (*TCP, func()) { + l := log.Named(name) + + services := service.New() + services.Update(service.PeeringKey, "peering", name) + db := peer.NewMemoryDB(l.Named("db")) + local, err := peer.NewLocal(services, db) + require.NoError(t, err) + + laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0") + require.NoError(t, err) + lis, err := net.ListenTCP("tcp", laddr) + require.NoError(t, err) + + // enable TCP gossipping + require.NoError(t, local.UpdateService(service.GossipKey, lis.Addr().Network(), lis.Addr().String())) + + srv := ServeTCP(local, lis, l) + + teardown := func() { + srv.Close() + _ = lis.Close() + db.Close() + } + return srv, teardown +} diff --git a/packages/parameter/parameter.go b/packages/parameter/parameter.go index fa1adfee757902a5e66d847b47800381db05bab0..7d390f1fb76675fdb95a58512c1b04544af5a4c5 100644 --- a/packages/parameter/parameter.go +++ b/packages/parameter/parameter.go @@ -1,6 +1,7 @@ package parameter import ( + "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/parameter" flag "github.com/spf13/pflag" "github.com/spf13/viper" @@ -11,10 +12,26 @@ var ( configName = flag.StringP("config", "c", "config", "Filename of the config file without the file extension") configDirPath = flag.StringP("config-dir", "d", ".", "Path to the directory containing the config file") - // Viper - NodeConfig = viper.New() + // viper + NodeConfig *viper.Viper + + // logger + defaultLoggerConfig = logger.Config{ + Level: "info", + DisableCaller: false, + DisableStacktrace: false, + Encoding: "console", + OutputPaths: []string{"goshimmer.log"}, + DisableEvents: false, + } ) +func init() { + // set the default logger config + NodeConfig = viper.New() + NodeConfig.SetDefault(logger.ViperKey, defaultLoggerConfig) +} + // FetchConfig fetches config values from a dir defined via CLI flag --config-dir (or the current working dir if not set). // // It automatically reads in a single config file starting with "config" (can be changed via the --config CLI flag) diff --git a/plugins/analysis/client/parameters.go b/plugins/analysis/client/parameters.go index a60d1432827112503c231c499b30dffc32253342..b875fadf36853578cfc8ef31e1d843459e72cfa5 100644 --- a/plugins/analysis/client/parameters.go +++ b/plugins/analysis/client/parameters.go @@ -5,7 +5,7 @@ import ( ) const ( - CFG_SERVER_ADDRESS = "analysis.serverAddress" + CFG_SERVER_ADDRESS = "analysis.client.serverAddress" ) func init() { diff --git a/plugins/analysis/server/parameters.go b/plugins/analysis/server/parameters.go index e27b4a9e2a746de3406cff8645685959deca5dbb..a8d66903b7079edcfd7d0b87f0ed154366327dfa 100644 --- a/plugins/analysis/server/parameters.go +++ b/plugins/analysis/server/parameters.go @@ -5,7 +5,7 @@ import ( ) const ( - CFG_SERVER_PORT = "analysis.serverPort" + CFG_SERVER_PORT = "analysis.server.port" ) func init() { diff --git a/plugins/analysis/webinterface/httpserver/parameters.go b/plugins/analysis/webinterface/httpserver/parameters.go new file mode 100644 index 0000000000000000000000000000000000000000..a32ab36fd895ad1d470a4a63afd32f8ca7db311e --- /dev/null +++ b/plugins/analysis/webinterface/httpserver/parameters.go @@ -0,0 +1,13 @@ +package httpserver + +import ( + flag "github.com/spf13/pflag" +) + +const ( + CFG_BIND_ADDRESS = "analysis.httpServer.bindAddress" +) + +func init() { + flag.String(CFG_BIND_ADDRESS, "0.0.0.0:80", "the bind address for the web API") +} diff --git a/plugins/analysis/webinterface/httpserver/plugin.go b/plugins/analysis/webinterface/httpserver/plugin.go index d8330000f20d3c980ebbd95f452a07bae9ec28ba..c84fabe599f9c30f316ce63f88f142c2e3bc18d5 100644 --- a/plugins/analysis/webinterface/httpserver/plugin.go +++ b/plugins/analysis/webinterface/httpserver/plugin.go @@ -3,9 +3,9 @@ package httpserver import ( "errors" "net/http" - "sync" "time" + "github.com/iotaledger/goshimmer/packages/parameter" "github.com/iotaledger/goshimmer/packages/shutdown" "github.com/iotaledger/hive.go/daemon" "github.com/iotaledger/hive.go/logger" @@ -25,36 +25,46 @@ func Configure() { log = logger.NewLogger(name) router = http.NewServeMux() - httpServer = &http.Server{Addr: ":80", Handler: router} + + httpServer = &http.Server{ + Addr: parameter.NodeConfig.GetString(CFG_BIND_ADDRESS), + Handler: router, + } router.Handle("/datastream", websocket.Handler(dataStream)) router.HandleFunc("/", index) } func Run() { + log.Infof("Starting %s ...", name) if err := daemon.BackgroundWorker(name, start, shutdown.ShutdownPriorityAnalysis); err != nil { log.Errorf("Error starting as daemon: %s", err) } } func start(shutdownSignal <-chan struct{}) { - var wg sync.WaitGroup - wg.Add(1) + stopped := make(chan struct{}) go func() { - defer wg.Done() - log.Infof(name+" started: address=%s", httpServer.Addr) - if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { - log.Warnf("Error listening: %s", err) + log.Infof("Started %s: http://%s", name, httpServer.Addr) + if err := httpServer.ListenAndServe(); err != nil { + if !errors.Is(err, http.ErrServerClosed) { + log.Errorf("Error serving: %s", err) + } + close(stopped) } }() - <-shutdownSignal - log.Info("Stopping " + name + " ...") + + select { + case <-shutdownSignal: + case <-stopped: + } + + log.Infof("Stopping %s ...", name) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() if err := httpServer.Shutdown(ctx); err != nil { - log.Errorf("Error closing: %s", err) + log.Errorf("Error stopping: %s", err) } - wg.Wait() - log.Info("Stopping " + name + " ... done") + log.Info("Stopping %s ... done", name) } diff --git a/plugins/autopeering/autopeering.go b/plugins/autopeering/autopeering.go index 76c8122a6b0b467dc012e5e37c8d2c70cfd5b780..18d04fc07d8f3e352a40900859493b4933dc757f 100644 --- a/plugins/autopeering/autopeering.go +++ b/plugins/autopeering/autopeering.go @@ -57,31 +57,30 @@ func configureAP() { func start(shutdownSignal <-chan struct{}) { defer log.Info("Stopping " + name + " ... done") - loc := local.GetInstance() - peeringAddr := loc.Services().Get(service.PeeringKey) - udpAddr, err := net.ResolveUDPAddr(peeringAddr.Network(), peeringAddr.String()) + lPeer := local.GetInstance() + // use the port of the peering service + peeringAddr := lPeer.Services().Get(service.PeeringKey) + _, peeringPort, err := net.SplitHostPort(peeringAddr.String()) if err != nil { - log.Fatalf("ResolveUDPAddr: %v", err) + panic(err) } - - // if the ip is an external ip, set it to unspecified - if udpAddr.IP.IsGlobalUnicast() { - if udpAddr.IP.To4() != nil { - udpAddr.IP = net.IPv4zero - } else { - udpAddr.IP = net.IPv6unspecified - } + // resolve the bind address + address := net.JoinHostPort(parameter.NodeConfig.GetString(local.CFG_BIND), peeringPort) + localAddr, err := net.ResolveUDPAddr(peeringAddr.Network(), address) + if err != nil { + log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err) } // check that discovery is working and the port is open log.Info("Testing service ...") - checkConnection(udpAddr, &loc.Peer) + checkConnection(localAddr, &lPeer.Peer) log.Info("Testing service ... done") - conn, err := net.ListenUDP(peeringAddr.Network(), udpAddr) + conn, err := net.ListenUDP(peeringAddr.Network(), localAddr) if err != nil { - log.Fatalf("ListenUDP: %v", err) + log.Fatalf("Error listening: %v", err) } + defer conn.Close() // use the UDP connection for transport trans := transport.Conn(conn, func(network, address string) (net.Addr, error) { return net.ResolveUDPAddr(network, address) }) @@ -93,7 +92,7 @@ func start(shutdownSignal <-chan struct{}) { } // start a server doing discovery and peering - srv := server.Listen(loc, trans, log.Named("srv"), handlers...) + srv := server.Serve(lPeer, trans, log.Named("srv"), handlers...) defer srv.Close() // start the discovery on that connection @@ -106,8 +105,8 @@ func start(shutdownSignal <-chan struct{}) { defer Selection.Close() } - log.Infof(name+" started: address=%s/%s", peeringAddr.String(), peeringAddr.Network()) - log.Debugf(name+" server started: PubKey=%s", base64.StdEncoding.EncodeToString(loc.PublicKey())) + log.Infof(name+" started: Address=%s/%s", peeringAddr.String(), peeringAddr.Network()) + log.Infof(name+" started: PubKey=%s", base64.StdEncoding.EncodeToString(lPeer.PublicKey())) <-shutdownSignal log.Info("Stopping " + name + " ...") diff --git a/plugins/autopeering/local/local.go b/plugins/autopeering/local/local.go index c5ca19a1109dbc0eff75a2f836905624d1d047fe..6b694b72c524d1bb17387d79313ed2510495623c 100644 --- a/plugins/autopeering/local/local.go +++ b/plugins/autopeering/local/local.go @@ -5,9 +5,11 @@ import ( "encoding/base64" "net" "strconv" + "strings" "sync" "github.com/iotaledger/goshimmer/packages/autopeering/peer" + "github.com/iotaledger/goshimmer/packages/autopeering/peer/service" "github.com/iotaledger/goshimmer/packages/netutil" "github.com/iotaledger/goshimmer/packages/parameter" "github.com/iotaledger/hive.go/logger" @@ -21,24 +23,30 @@ var ( func configureLocal() *peer.Local { log := logger.NewLogger("Local") - ip := net.ParseIP(parameter.NodeConfig.GetString(CFG_ADDRESS)) - if ip == nil { - log.Fatalf("Invalid %s address: %s", CFG_ADDRESS, parameter.NodeConfig.GetString(CFG_ADDRESS)) - } - if ip.IsUnspecified() { - log.Info("Querying public IP ...") - myIp, err := netutil.GetPublicIP(!netutil.IsIPv4(ip)) + var externalIP net.IP + if str := parameter.NodeConfig.GetString(CFG_EXTERNAL); strings.ToLower(str) == "auto" { + log.Info("Querying external IP ...") + ip, err := netutil.GetPublicIP(false) if err != nil { - log.Fatalf("Error querying public IP: %s", err) + log.Fatalf("Error querying external IP: %s", err) + } + log.Infof("External IP queried: address=%s", ip.String()) + externalIP = ip + } else { + externalIP = net.ParseIP(str) + if externalIP == nil { + log.Fatalf("Invalid IP address (%s): %s", CFG_EXTERNAL, str) } - ip = myIp - log.Infof("Public IP queried: address=%s", ip.String()) + } + if !externalIP.IsGlobalUnicast() { + log.Fatalf("IP is not a global unicast address: %s", externalIP.String()) } - port := strconv.Itoa(parameter.NodeConfig.GetInt(CFG_PORT)) + peeringPort := strconv.Itoa(parameter.NodeConfig.GetInt(CFG_PORT)) - // create a new local node - db := peer.NewPersistentDB(log) + // announce the peering service + services := service.New() + services.Update(service.PeeringKey, "udp", net.JoinHostPort(externalIP.String(), peeringPort)) // the private key seed of the current local can be returned the following way: // key, _ := db.LocalPrivateKey() @@ -46,8 +54,7 @@ func configureLocal() *peer.Local { // set the private key from the seed provided in the config var seed [][]byte - if parameter.NodeConfig.IsSet(CFG_SEED) { - str := parameter.NodeConfig.GetString(CFG_SEED) + if str := parameter.NodeConfig.GetString(CFG_SEED); str != "" { bytes, err := base64.StdEncoding.DecodeString(str) if err != nil { log.Fatalf("Invalid %s: %s", CFG_SEED, err) @@ -58,7 +65,7 @@ func configureLocal() *peer.Local { seed = append(seed, bytes) } - local, err := peer.NewLocal("udp", net.JoinHostPort(ip.String(), port), db, seed...) + local, err := peer.NewLocal(services, peer.NewPersistentDB(log), seed...) if err != nil { log.Fatalf("Error creating local: %s", err) } diff --git a/plugins/autopeering/local/parameters.go b/plugins/autopeering/local/parameters.go index ab7629e83418fa195453b14edb1d9915c21e079e..9ffa15c81fe7fbc745b3c85723dda0af8a32a20a 100644 --- a/plugins/autopeering/local/parameters.go +++ b/plugins/autopeering/local/parameters.go @@ -5,13 +5,15 @@ import ( ) const ( - CFG_ADDRESS = "autopeering.address" - CFG_PORT = "autopeering.port" - CFG_SEED = "autopeering.seed" + CFG_BIND = "network.bindAddress" + CFG_EXTERNAL = "network.externalAddress" + CFG_PORT = "autopeering.port" + CFG_SEED = "autopeering.seed" ) func init() { - flag.String(CFG_ADDRESS, "0.0.0.0", "address to bind for incoming peering requests") - flag.Int(CFG_PORT, 14626, "udp port for incoming peering requests") + flag.String(CFG_BIND, "0.0.0.0", "bind address for global services such as autopeering and gossip") + flag.String(CFG_EXTERNAL, "auto", "external IP address under which the node is reachable; or 'auto' to determine it automatically") + flag.Int(CFG_PORT, 14626, "UDP port for incoming peering requests") flag.BytesBase64(CFG_SEED, nil, "private key seed used to derive the node identity; optional Base64 encoded 256-bit string") } diff --git a/plugins/dashboard/parameters.go b/plugins/dashboard/parameters.go new file mode 100644 index 0000000000000000000000000000000000000000..1031a27367673d5576a9f10c4892c1e1e31f6d80 --- /dev/null +++ b/plugins/dashboard/parameters.go @@ -0,0 +1,13 @@ +package dashboard + +import ( + flag "github.com/spf13/pflag" +) + +const ( + CFG_BIND_ADDRESS = "dashboard.bindAddress" +) + +func init() { + flag.String(CFG_BIND_ADDRESS, "0.0.0.0:8081", "the bind address for the dashboard") +} diff --git a/plugins/dashboard/plugin.go b/plugins/dashboard/plugin.go index 5fa26f69825702d1c9f340499261e8eb3512465c..bf820c5582c86e32afc4db78a9c4c43ca13a7363 100644 --- a/plugins/dashboard/plugin.go +++ b/plugins/dashboard/plugin.go @@ -1,9 +1,11 @@ package dashboard import ( + "errors" "net/http" "time" + "github.com/iotaledger/goshimmer/packages/parameter" "github.com/iotaledger/goshimmer/packages/shutdown" "github.com/iotaledger/goshimmer/plugins/metrics" "github.com/iotaledger/hive.go/daemon" @@ -13,17 +15,24 @@ import ( "golang.org/x/net/context" ) -var server *http.Server +var ( + log *logger.Logger + httpServer *http.Server +) + +const name = "Dashboard" -var router *http.ServeMux +var PLUGIN = node.NewPlugin(name, node.Disabled, configure, run) -var PLUGIN = node.NewPlugin("Dashboard", node.Disabled, configure, run) -var log *logger.Logger +func configure(*node.Plugin) { + log = logger.NewLogger(name) -func configure(plugin *node.Plugin) { - log = logger.NewLogger("Dashboard") - router = http.NewServeMux() - server = &http.Server{Addr: ":8081", Handler: router} + router := http.NewServeMux() + + httpServer = &http.Server{ + Addr: parameter.NodeConfig.GetString(CFG_BIND_ADDRESS), + Handler: router, + } router.HandleFunc("/dashboard", ServeHome) router.HandleFunc("/ws", ServeWs) @@ -37,17 +46,36 @@ func configure(plugin *node.Plugin) { })) } -func run(plugin *node.Plugin) { - daemon.BackgroundWorker("Dashboard Updater", func(shutdownSignal <-chan struct{}) { - go func() { - if err := server.ListenAndServe(); err != nil { - log.Error(err.Error()) +func run(*node.Plugin) { + log.Infof("Starting %s ...", name) + if err := daemon.BackgroundWorker(name, workerFunc, shutdown.ShutdownPriorityDashboard); err != nil { + log.Errorf("Error starting as daemon: %s", err) + } +} + +func workerFunc(shutdownSignal <-chan struct{}) { + stopped := make(chan struct{}) + go func() { + log.Infof("Started %s: http://%s/dashboard", name, httpServer.Addr) + if err := httpServer.ListenAndServe(); err != nil { + if !errors.Is(err, http.ErrServerClosed) { + log.Errorf("Error serving: %s", err) } - }() + close(stopped) + } + }() + + select { + case <-shutdownSignal: + case <-stopped: + } + + log.Infof("Stopping %s ...", name) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() - <-shutdownSignal - ctx, cancel := context.WithTimeout(context.Background(), 0*time.Second) - defer cancel() - _ = server.Shutdown(ctx) - }, shutdown.ShutdownPriorityDashboard) + if err := httpServer.Shutdown(ctx); err != nil { + log.Errorf("Error stopping: %s", err) + } + log.Infof("Stopping %s ... done", name) } diff --git a/plugins/gossip/gossip.go b/plugins/gossip/gossip.go index 5a6904c5accdeb4780e1efd607f501f3f81e24cf..63536632bf4b648935833ddc78873405ceb174c2 100644 --- a/plugins/gossip/gossip.go +++ b/plugins/gossip/gossip.go @@ -27,15 +27,17 @@ var ( func configureGossip() { lPeer := local.GetInstance() - port := strconv.Itoa(parameter.NodeConfig.GetInt(GOSSIP_PORT)) - - host, _, err := net.SplitHostPort(lPeer.Address()) + peeringAddr := lPeer.Services().Get(service.PeeringKey) + external, _, err := net.SplitHostPort(peeringAddr.String()) if err != nil { - log.Fatalf("invalid peering address: %v", err) + panic(err) } - err = lPeer.UpdateService(service.GossipKey, "tcp", net.JoinHostPort(host, port)) + + // announce the gossip service + gossipPort := strconv.Itoa(parameter.NodeConfig.GetInt(GOSSIP_PORT)) + err = lPeer.UpdateService(service.GossipKey, "tcp", net.JoinHostPort(external, gossipPort)) if err != nil { - log.Fatalf("could not update services: %v", err) + log.Fatalf("could not update services: %s", err) } mgr = gp.NewManager(lPeer, loadTransaction, log) @@ -44,23 +46,38 @@ func configureGossip() { func start(shutdownSignal <-chan struct{}) { defer log.Info("Stopping " + name + " ... done") - loc := local.GetInstance() - srv, err := server.ListenTCP(loc, log) + lPeer := local.GetInstance() + // use the port of the gossip service + gossipAddr := lPeer.Services().Get(service.GossipKey) + _, gossipPort, err := net.SplitHostPort(gossipAddr.String()) + if err != nil { + panic(err) + } + // resolve the bind address + address := net.JoinHostPort(parameter.NodeConfig.GetString(local.CFG_BIND), gossipPort) + localAddr, err := net.ResolveTCPAddr(gossipAddr.Network(), address) if err != nil { - log.Fatalf("ListenTCP: %v", err) + log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err) } + + listener, err := net.ListenTCP(gossipAddr.Network(), localAddr) + if err != nil { + log.Fatalf("Error listening: %v", err) + } + defer listener.Close() + + srv := server.ServeTCP(lPeer, listener, log) defer srv.Close() //check that the server is working and the port is open log.Info("Testing service ...") - checkConnection(srv, &loc.Peer) + checkConnection(srv, &lPeer.Peer) log.Info("Testing service ... done") mgr.Start(srv) defer mgr.Close() - gossipAddr := loc.Services().Get(service.GossipKey) - log.Infof(name+" started: address=%s/%s", gossipAddr.String(), gossipAddr.Network()) + log.Infof("%s started: Address=%s/%s", name, gossipAddr.String(), gossipAddr.Network()) <-shutdownSignal log.Info("Stopping " + name + " ...") diff --git a/plugins/graph/graph.go b/plugins/graph/graph.go index 6b5442e80ac5c92520f4538e4b62683f41525e53..e0946cc3a2e8a5c38644cf6fb0e0cfe750bed436 100644 --- a/plugins/graph/graph.go +++ b/plugins/graph/graph.go @@ -66,7 +66,7 @@ func onConnectHandler(s socketio.Conn) error { log.Info(infoMsg) socketioServer.JoinRoom("broadcast", s) - config := &wsConfig{NetworkName: parameter.NodeConfig.GetString("graph.networkName")} + config := &wsConfig{NetworkName: parameter.NodeConfig.GetString(CFG_NETWORK)} var initTxs []*wsTransaction txRingBuffer.Do(func(tx interface{}) { diff --git a/plugins/graph/parameters.go b/plugins/graph/parameters.go index 5bc63869964237f21beb5a453d3b485138b973eb..5fbef46f389b43390aeaef3c1a9e3b47e7ae787b 100644 --- a/plugins/graph/parameters.go +++ b/plugins/graph/parameters.go @@ -1,26 +1,22 @@ package graph import ( - "github.com/iotaledger/goshimmer/packages/parameter" + "github.com/iotaledger/goshimmer/plugins/cli" + flag "github.com/spf13/pflag" ) -func init() { - - // "Path to IOTA Tangle Visualiser webroot files" - parameter.NodeConfig.SetDefault("graph.webrootPath", "IOTAtangle/webroot") - - // "Path to socket.io.js" - parameter.NodeConfig.SetDefault("graph.socketioPath", "socket.io-client/dist/socket.io.js") - - // "Set the domain on which IOTA Tangle Visualiser is served" - parameter.NodeConfig.SetDefault("graph.domain", "") - - // "Set the host to which the IOTA Tangle Visualiser listens" - parameter.NodeConfig.SetDefault("graph.host", "127.0.0.1") - - // "IOTA Tangle Visualiser webserver port" - parameter.NodeConfig.SetDefault("graph.port", 8083) +const ( + CFG_WEBROOT = "graph.webrootPath" + CFG_SOCKET_IO = "graph.socketioPath" + CFG_DOMAIN = "graph.domain" + CFG_BIND_ADDRESS = "graph.bindAddress" + CFG_NETWORK = "graph.networkName" +) - // "Name of the network shown in IOTA Tangle Visualiser" - parameter.NodeConfig.SetDefault("graph.networkName", "meets HORNET") +func init() { + flag.String(CFG_WEBROOT, "IOTAtangle/webroot", "Path to IOTA Tangle Visualiser webroot files") + flag.String(CFG_SOCKET_IO, "socket.io-client/dist/socket.io.js", "Path to socket.io.js") + flag.String(CFG_DOMAIN, "", "Set the domain on which IOTA Tangle Visualiser is served") + flag.String(CFG_BIND_ADDRESS, "127.0.0.1:8083", "the bind address for the IOTA Tangle Visualizer") + flag.String(CFG_NETWORK, cli.AppName, "Name of the network shown in IOTA Tangle Visualiser") } diff --git a/plugins/graph/plugin.go b/plugins/graph/plugin.go index f6dcc3eea3cd10d4db3f9483117bea6208ba8706..af5861654331de80acf31a44c52676fc21f8d41d 100644 --- a/plugins/graph/plugin.go +++ b/plugins/graph/plugin.go @@ -1,7 +1,7 @@ package graph import ( - "fmt" + "errors" "net/http" "time" @@ -39,7 +39,7 @@ var ( ) func downloadSocketIOHandler(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, parameter.NodeConfig.GetString("graph.socketioPath")) + http.ServeFile(w, r, parameter.NodeConfig.GetString(CFG_SOCKET_IO)) } func configureSocketIOServer() error { @@ -72,11 +72,11 @@ func configure(plugin *node.Plugin) { // socket.io and web server server = &http.Server{ - Addr: fmt.Sprintf("%s:%d", parameter.NodeConfig.GetString("graph.host"), parameter.NodeConfig.GetInt("graph.port")), + Addr: parameter.NodeConfig.GetString(CFG_BIND_ADDRESS), Handler: router, } - fs := http.FileServer(http.Dir(parameter.NodeConfig.GetString("graph.webrootPath"))) + fs := http.FileServer(http.Dir(parameter.NodeConfig.GetString(CFG_WEBROOT))) if err := configureSocketIOServer(); err != nil { log.Panicf("Graph: %v", err.Error()) @@ -92,7 +92,7 @@ func configure(plugin *node.Plugin) { }, workerpool.WorkerCount(newTxWorkerCount), workerpool.QueueSize(newTxWorkerQueueSize)) } -func run(plugin *node.Plugin) { +func run(*node.Plugin) { notifyNewTx := events.NewClosure(func(transaction *value_transaction.ValueTransaction) { newTxWorkerPool.TrySubmit(transaction) @@ -111,23 +111,33 @@ func run(plugin *node.Plugin) { daemon.BackgroundWorker("Graph Webserver", func(shutdownSignal <-chan struct{}) { go socketioServer.Serve() + stopped := make(chan struct{}) go func() { + log.Infof("You can now access IOTA Tangle Visualiser using: http://%s", parameter.NodeConfig.GetString(CFG_BIND_ADDRESS)) if err := server.ListenAndServe(); err != nil { - log.Error(err.Error()) + if !errors.Is(err, http.ErrServerClosed) { + log.Errorf("Error serving: %s", err) + } } + close(stopped) }() - log.Infof("You can now access IOTA Tangle Visualiser using: http://%s:%d", parameter.NodeConfig.GetString("graph.host"), parameter.NodeConfig.GetInt("graph.port")) + select { + case <-shutdownSignal: + case <-stopped: + } - <-shutdownSignal - log.Info("Stopping Graph ...") - - socketioServer.Close() - - ctx, cancel := context.WithTimeout(context.Background(), 0*time.Second) + log.Info("Stopping Graph Webserver ...") + ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - _ = server.Shutdown(ctx) - log.Info("Stopping Graph ... done") + if err := server.Shutdown(ctx); err != nil { + log.Errorf("Error stopping: %s", err) + } + + if err := socketioServer.Close(); err != nil { + log.Errorf("Error closing Socket.IO server: %s", err) + } + log.Info("Stopping Graph Webserver ... done") }, shutdown.ShutdownPriorityGraph) }