Peer Discovery -> DHT // no more pubsub state
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"oc-discovery/conf"
|
||||
"oc-discovery/daemons/node/common"
|
||||
"time"
|
||||
|
||||
@@ -30,9 +29,6 @@ type PeerRecord struct {
|
||||
WalletAddress string `json:"wallet_address"`
|
||||
Signature []byte `json:"signature"`
|
||||
ExpiryDate time.Time `json:"expiry_date"`
|
||||
|
||||
TTL int `json:"ttl"` // max of hop diffusion
|
||||
NoPub bool `json:"no_pub"`
|
||||
}
|
||||
|
||||
func (p *PeerRecord) Sign() error {
|
||||
@@ -118,7 +114,8 @@ func (pr *PeerRecord) ExtractPeer(ourkey string, key string, pubKey crypto.PubKe
|
||||
}
|
||||
|
||||
type GetValue struct {
|
||||
Key string `json:"key"`
|
||||
Key string `json:"key"`
|
||||
PeerID peer.ID `json:"peer_id"`
|
||||
}
|
||||
|
||||
type GetResponse struct {
|
||||
@@ -126,8 +123,11 @@ type GetResponse struct {
|
||||
Records map[string]PeerRecord `json:"records,omitempty"`
|
||||
}
|
||||
|
||||
func (ix *IndexerService) genKey(did string) string {
|
||||
return "/node/" + did
|
||||
}
|
||||
|
||||
func (ix *IndexerService) initNodeHandler() {
|
||||
fmt.Println("Node activity")
|
||||
ix.Host.SetStreamHandler(common.ProtocolHeartbeat, ix.HandleNodeHeartbeat)
|
||||
ix.Host.SetStreamHandler(common.ProtocolPublish, ix.handleNodePublish)
|
||||
ix.Host.SetStreamHandler(common.ProtocolGet, ix.handleNodeGet)
|
||||
@@ -139,6 +139,7 @@ func (ix *IndexerService) handleNodePublish(s network.Stream) {
|
||||
for {
|
||||
var rec PeerRecord
|
||||
if err := json.NewDecoder(s).Decode(&rec); err != nil {
|
||||
logger.Err(err)
|
||||
continue
|
||||
}
|
||||
rec2 := PeerRecord{
|
||||
@@ -152,7 +153,7 @@ func (ix *IndexerService) handleNodePublish(s network.Stream) {
|
||||
continue
|
||||
}
|
||||
if rec.PeerID == "" || rec.ExpiryDate.Before(time.Now().UTC()) { // already expired
|
||||
logger.Warn().Msg(rec.PeerID + " is expired.")
|
||||
logger.Err(errors.New(rec.PeerID + " is expired."))
|
||||
continue
|
||||
}
|
||||
pid, err := peer.Decode(rec.PeerID)
|
||||
@@ -162,13 +163,12 @@ func (ix *IndexerService) handleNodePublish(s network.Stream) {
|
||||
|
||||
ix.StreamMU.Lock()
|
||||
|
||||
if ix.StreamRecords[common.ProtocolPublish] == nil {
|
||||
ix.StreamRecords[common.ProtocolPublish] = map[peer.ID]*common.StreamRecord[PeerRecord]{}
|
||||
if ix.StreamRecords[common.ProtocolHeartbeat] == nil {
|
||||
ix.StreamRecords[common.ProtocolHeartbeat] = map[peer.ID]*common.StreamRecord[PeerRecord]{}
|
||||
}
|
||||
streams := ix.StreamRecords[common.ProtocolPublish]
|
||||
streams := ix.StreamRecords[common.ProtocolHeartbeat]
|
||||
|
||||
if srec, ok := streams[pid]; ok {
|
||||
fmt.Println("UPDATE PUBLISH", pid)
|
||||
srec.DID = rec.DID
|
||||
srec.Record = rec
|
||||
srec.HeartbeatStream.UptimeTracker.LastSeen = time.Now().UTC()
|
||||
@@ -179,36 +179,22 @@ func (ix *IndexerService) handleNodePublish(s network.Stream) {
|
||||
}
|
||||
ix.StreamMU.Unlock()
|
||||
|
||||
if ix.LongLivedPubSubs[common.TopicPubSubNodeActivity] != nil && !rec.NoPub {
|
||||
|
||||
if b, err := json.Marshal(common.TopicNodeActivityPub{
|
||||
Disposer: "/ip4/" + conf.GetConfig().Hostname + "/tcp/" + fmt.Sprintf("%v", conf.GetConfig().NodeEndpointPort) + "/p2p/" + ix.Host.ID().String(),
|
||||
DID: rec.DID,
|
||||
Name: rec.Name,
|
||||
PeerID: pid.String(),
|
||||
NodeActivity: pp.ONLINE.EnumIndex(),
|
||||
}); err == nil {
|
||||
ix.LongLivedPubSubs[common.TopicPubSubNodeActivity].Publish(context.Background(), b)
|
||||
}
|
||||
key := ix.genKey(rec.DID)
|
||||
|
||||
data, err := json.Marshal(rec)
|
||||
if err != nil {
|
||||
logger.Err(err)
|
||||
continue
|
||||
}
|
||||
|
||||
if rec.TTL > 0 {
|
||||
rec.NoPub = true
|
||||
for _, ad := range common.StaticIndexers {
|
||||
if ad.ID == s.Conn().RemotePeer() {
|
||||
continue
|
||||
}
|
||||
if common.StreamIndexers[common.ProtocolPublish][ad.ID] == nil {
|
||||
continue
|
||||
}
|
||||
stream := common.StreamIndexers[common.ProtocolPublish][ad.ID]
|
||||
rec.TTL -= 1
|
||||
if err := json.NewEncoder(stream.Stream).Encode(&rec); err != nil { // then publish on stream
|
||||
continue
|
||||
}
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
if err := ix.DHT.PutValue(ctx, key, data); err != nil {
|
||||
logger.Err(err)
|
||||
cancel()
|
||||
continue
|
||||
}
|
||||
cancel()
|
||||
break // response... so quit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,64 +209,40 @@ func (ix *IndexerService) handleNodeGet(s network.Stream) {
|
||||
}
|
||||
ix.StreamMU.Lock()
|
||||
|
||||
if ix.StreamRecords[common.ProtocolGet] == nil {
|
||||
ix.StreamRecords[common.ProtocolGet] = map[peer.ID]*common.StreamRecord[PeerRecord]{}
|
||||
if ix.StreamRecords[common.ProtocolHeartbeat] == nil {
|
||||
ix.StreamRecords[common.ProtocolHeartbeat] = map[peer.ID]*common.StreamRecord[PeerRecord]{}
|
||||
}
|
||||
resp := GetResponse{
|
||||
Found: false,
|
||||
Records: map[string]PeerRecord{},
|
||||
}
|
||||
streams := ix.StreamRecords[common.ProtocolPublish]
|
||||
streams := ix.StreamRecords[common.ProtocolHeartbeat]
|
||||
|
||||
key := ix.genKey(req.Key)
|
||||
// simple lookup by PeerID (or DID)
|
||||
for _, rec := range streams {
|
||||
if rec.Record.DID == req.Key || rec.Record.PeerID == req.Key || rec.Record.Name == req.Key { // OK
|
||||
resp.Found = true
|
||||
resp.Records[rec.Record.PeerID] = rec.Record
|
||||
if rec.Record.DID == req.Key || rec.Record.PeerID == req.Key { // there unique... no need to proceed more...
|
||||
_ = json.NewEncoder(s).Encode(resp)
|
||||
ix.StreamMU.Unlock()
|
||||
return
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
recBytes, err := ix.DHT.SearchValue(ctx, key)
|
||||
if err != nil {
|
||||
logger.Err(err).Msg("Failed to fetch PeerRecord from DHT")
|
||||
cancel()
|
||||
}
|
||||
cancel()
|
||||
for c := range recBytes {
|
||||
var rec PeerRecord
|
||||
if err := json.Unmarshal(c, &rec); err != nil || rec.PeerID != req.PeerID.String() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// if not found ask to my neighboor indexers
|
||||
for pid, dsp := range ix.DisposedPeers {
|
||||
if _, ok := resp.Records[dsp.PeerID]; !ok && (dsp.Name == req.Key || dsp.DID == req.Key || dsp.PeerID == req.Key) {
|
||||
ctxTTL, err := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if ix.Host.Network().Connectedness(pid) != network.Connected {
|
||||
if ad, err := peer.AddrInfoFromString(dsp.Disposer); err == nil {
|
||||
_ = ix.Host.Connect(ctxTTL, *ad)
|
||||
str, err := ix.Host.NewStream(ctxTTL, pid, common.ProtocolGet)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for {
|
||||
if ctxTTL.Err() == context.DeadlineExceeded {
|
||||
break
|
||||
}
|
||||
var subResp GetResponse
|
||||
if err := json.NewDecoder(str).Decode(&resp); err != nil {
|
||||
continue
|
||||
}
|
||||
if subResp.Found {
|
||||
for k, v := range subResp.Records {
|
||||
if _, ok := resp.Records[k]; !ok {
|
||||
resp.Records[k] = v
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resp.Found = true
|
||||
resp.Records[rec.PeerID] = rec
|
||||
if srec, ok := streams[req.PeerID]; ok {
|
||||
srec.DID = rec.DID
|
||||
srec.Record = rec
|
||||
srec.HeartbeatStream.UptimeTracker.LastSeen = time.Now().UTC()
|
||||
}
|
||||
}
|
||||
// Not found
|
||||
_ = json.NewEncoder(s).Encode(resp)
|
||||
ix.StreamMU.Unlock()
|
||||
break // response... so quit
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user