-
Luca Moser authoredLuca Moser authored
dapp.go 3.83 KiB
package networkdelay
import (
"sync"
"time"
"github.com/iotaledger/goshimmer/packages/binary/messagelayer/message"
messageTangle "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle"
"github.com/iotaledger/goshimmer/plugins/autopeering/local"
"github.com/iotaledger/goshimmer/plugins/config"
"github.com/iotaledger/goshimmer/plugins/messagelayer"
"github.com/iotaledger/goshimmer/plugins/remotelog"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/iotaledger/hive.go/events"
"github.com/iotaledger/hive.go/logger"
"github.com/iotaledger/hive.go/node"
"github.com/mr-tron/base58"
)
const (
// PluginName contains the human readable name of the plugin.
PluginName = "NetworkDelay"
// CfgNetworkDelayOriginPublicKey defines the config flag of the issuer node public key.
CfgNetworkDelayOriginPublicKey = "networkdelay.originPublicKey"
remoteLogType = "networkdelay"
)
var (
// App is the "plugin" instance of the network delay application.
app *node.Plugin
once sync.Once
// log holds a reference to the logger used by this app.
log *logger.Logger
remoteLogger *remotelog.RemoteLoggerConn
myID string
myPublicKey ed25519.PublicKey
originPublicKey ed25519.PublicKey
)
// App gets the plugin instance.
func App() *node.Plugin {
once.Do(func () {
app = node.NewPlugin(PluginName, node.Disabled, configure)
})
return app
}
func configure(_ *node.Plugin) {
// configure logger
log = logger.NewLogger(PluginName)
remoteLogger = remotelog.RemoteLogger()
if local.GetInstance() != nil {
myID = local.GetInstance().ID().String()
myPublicKey = local.GetInstance().PublicKey()
}
// get origin public key from config
bytes, err := base58.Decode(config.Node().GetString(CfgNetworkDelayOriginPublicKey))
if err != nil {
log.Fatalf("could not parse %s config entry as base58. %v", CfgNetworkDelayOriginPublicKey, err)
}
originPublicKey, _, err = ed25519.PublicKeyFromBytes(bytes)
if err != nil {
log.Fatalf("could not parse %s config entry as public key. %v", CfgNetworkDelayOriginPublicKey, err)
}
configureWebAPI()
// subscribe to message-layer
messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(onReceiveMessageFromMessageLayer))
}
func onReceiveMessageFromMessageLayer(cachedMessage *message.CachedMessage, cachedMessageMetadata *messageTangle.CachedMessageMetadata) {
defer cachedMessage.Release()
defer cachedMessageMetadata.Release()
solidMessage := cachedMessage.Unwrap()
if solidMessage == nil {
log.Debug("failed to unpack solid message from message layer")
return
}
messagePayload := solidMessage.Payload()
if messagePayload.Type() != Type {
return
}
// check for node identity
issuerPubKey := solidMessage.IssuerPublicKey()
if issuerPubKey != originPublicKey || issuerPubKey == myPublicKey {
return
}
networkDelayObject, ok := messagePayload.(*Object)
if !ok {
log.Info("could not cast payload to network delay object")
return
}
now := time.Now().UnixNano()
// abort if message was sent more than 1min ago
// this should only happen due to a node resyncing
if time.Duration(now-networkDelayObject.sentTime) > time.Minute {
log.Debugf("Received network delay message with >1min delay\n%s", networkDelayObject)
return
}
sendToRemoteLog(networkDelayObject, now)
}
func sendToRemoteLog(networkDelayObject *Object, receiveTime int64) {
m := networkDelay{
NodeID: myID,
ID: networkDelayObject.id.String(),
SentTime: networkDelayObject.sentTime,
ReceiveTime: receiveTime,
Delta: receiveTime - networkDelayObject.sentTime,
Type: remoteLogType,
}
_ = remoteLogger.Send(m)
}
type networkDelay struct {
NodeID string `json:"nodeId"`
ID string `json:"id"`
SentTime int64 `json:"sentTime"`
ReceiveTime int64 `json:"receiveTime"`
Delta int64 `json:"delta"`
Type string `json:"type"`
}