package client import ( "github.com/iotaledger/goshimmer/packages/accountability" "github.com/iotaledger/goshimmer/packages/daemon" "github.com/iotaledger/goshimmer/packages/network" "github.com/iotaledger/goshimmer/packages/node" "github.com/iotaledger/goshimmer/plugins/analysis/types/addnode" "github.com/iotaledger/goshimmer/plugins/analysis/types/connectnodes" "github.com/iotaledger/goshimmer/plugins/analysis/types/disconnectnodes" "github.com/iotaledger/goshimmer/plugins/analysis/types/ping" "github.com/iotaledger/goshimmer/plugins/autopeering/instances/acceptedneighbors" "github.com/iotaledger/goshimmer/plugins/autopeering/instances/chosenneighbors" "github.com/iotaledger/goshimmer/plugins/autopeering/instances/knownpeers" "github.com/iotaledger/goshimmer/plugins/autopeering/types/peer" "net" "time" ) func Run(plugin *node.Plugin) { daemon.BackgroundWorker(func() { shuttingDown := false for !shuttingDown { if conn, err := net.Dial("tcp", *SERVER_ADDRESS.Value); err != nil { plugin.LogDebug("Could not connect to reporting server: " + err.Error()) } else { managedConn := network.NewManagedConnection(conn) eventDispatchers := getEventDispatchers(managedConn) reportCurrentStatus(eventDispatchers) setupHooks(managedConn, eventDispatchers) shuttingDown = keepConnectionAlive(managedConn) } } }) } func getEventDispatchers(conn *network.ManagedConnection) *EventDispatchers { return &EventDispatchers{ AddNode: func(nodeId []byte) { conn.Write((&addnode.Packet{ NodeId: nodeId }).Marshal()) }, ConnectNodes: func(sourceId []byte, targetId []byte) { conn.Write((&connectnodes.Packet{ SourceId: sourceId, TargetId: targetId }).Marshal()) }, DisconnectNodes: func(sourceId []byte, targetId []byte) { conn.Write((&disconnectnodes.Packet{ SourceId: sourceId, TargetId: targetId }).Marshal()) }, } } func reportCurrentStatus(eventDispatchers *EventDispatchers) { eventDispatchers.AddNode(accountability.OWN_ID.Identifier) reportChosenNeighbors(eventDispatchers) } func setupHooks(conn *network.ManagedConnection, eventDispatchers *EventDispatchers) { // define hooks //////////////////////////////////////////////////////////////////////////////////////////////////// onDiscoverPeer := func(p *peer.Peer) { eventDispatchers.AddNode(p.Identity.Identifier) } onAddAcceptedNeighbor := func(p *peer.Peer) { eventDispatchers.ConnectNodes(p.Identity.Identifier, accountability.OWN_ID.Identifier) } onRemoveAcceptedNeighbor := func(p *peer.Peer) { eventDispatchers.DisconnectNodes(p.Identity.Identifier, accountability.OWN_ID.Identifier) } onAddChosenNeighbor := func(p *peer.Peer) { eventDispatchers.ConnectNodes(accountability.OWN_ID.Identifier, p.Identity.Identifier) } onRemoveChosenNeighbor := func(p *peer.Peer) { eventDispatchers.DisconnectNodes(accountability.OWN_ID.Identifier, p.Identity.Identifier) } // setup hooks ///////////////////////////////////////////////////////////////////////////////////////////////////// knownpeers.INSTANCE.Events.Add.Attach(onDiscoverPeer) acceptedneighbors.INSTANCE.Events.Add.Attach(onAddAcceptedNeighbor) acceptedneighbors.INSTANCE.Events.Remove.Attach(onRemoveAcceptedNeighbor) chosenneighbors.INSTANCE.Events.Add.Attach(onAddChosenNeighbor) chosenneighbors.INSTANCE.Events.Remove.Attach(onRemoveChosenNeighbor) // clean up hooks on close ///////////////////////////////////////////////////////////////////////////////////////// var onClose func() onClose = func() { knownpeers.INSTANCE.Events.Add.Detach(onDiscoverPeer) acceptedneighbors.INSTANCE.Events.Add.Detach(onAddAcceptedNeighbor) acceptedneighbors.INSTANCE.Events.Remove.Detach(onRemoveAcceptedNeighbor) chosenneighbors.INSTANCE.Events.Add.Detach(onAddChosenNeighbor) chosenneighbors.INSTANCE.Events.Remove.Detach(onRemoveChosenNeighbor) conn.Events.Close.Detach(onClose) } conn.Events.Close.Attach(onClose) } func reportChosenNeighbors(dispatchers *EventDispatchers) { for _, chosenNeighbor := range chosenneighbors.INSTANCE.Peers { dispatchers.AddNode(chosenNeighbor.Identity.Identifier) } for _, chosenNeighbor := range chosenneighbors.INSTANCE.Peers { dispatchers.ConnectNodes(accountability.OWN_ID.Identifier, chosenNeighbor.Identity.Identifier) } } func keepConnectionAlive(conn *network.ManagedConnection) bool { go conn.Read(make([]byte, 1)) ticker := time.NewTicker(1 * time.Second) for { select { case <- daemon.ShutdownSignal: return true case <- ticker.C: if _, err := conn.Write((&ping.Packet{}).Marshal()); err != nil { return false } } } }