Compare commits
7 Commits
main
...
feature/dh
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ca762abbf | |||
| 0ffe98045e | |||
| c3352499fa | |||
| 562d86125e | |||
| d50e5d56f7 | |||
| 38cd862947 | |||
| 7fd258dc9d |
25
conf/config.go
Normal file
25
conf/config.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Name string
|
||||||
|
Hostname string
|
||||||
|
PSKPath string
|
||||||
|
PublicKeyPath string
|
||||||
|
PrivateKeyPath string
|
||||||
|
NodeEndpointPort int64
|
||||||
|
IndexerAddresses string
|
||||||
|
|
||||||
|
NodeMode string
|
||||||
|
}
|
||||||
|
|
||||||
|
var instance *Config
|
||||||
|
var once sync.Once
|
||||||
|
|
||||||
|
func GetConfig() *Config {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = &Config{}
|
||||||
|
})
|
||||||
|
return instance
|
||||||
|
}
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"oc-discovery/models"
|
|
||||||
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Operations about Identitys
|
|
||||||
type IdentityController struct {
|
|
||||||
beego.Controller
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title CreateIdentity
|
|
||||||
// @Description create identitys
|
|
||||||
// @Param body body models.Identity true "body for identity content"
|
|
||||||
// @Success 200 {result} "ok" or error
|
|
||||||
// @Failure 403 body is empty
|
|
||||||
// @router / [post]
|
|
||||||
func (u *IdentityController) Post() {
|
|
||||||
var identity models.Identity
|
|
||||||
json.Unmarshal(u.Ctx.Input.RequestBody, &identity)
|
|
||||||
err := models.UpdateIdentity(&identity)
|
|
||||||
if err != nil {
|
|
||||||
u.Data["json"] = err.Error()
|
|
||||||
} else {
|
|
||||||
u.Data["json"] = "ok"
|
|
||||||
}
|
|
||||||
u.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title Get
|
|
||||||
// @Description get Identity
|
|
||||||
// @Success 200 {object} models.Identity
|
|
||||||
// @router / [get]
|
|
||||||
func (u *IdentityController) GetAll() {
|
|
||||||
identity := models.GetIdentity()
|
|
||||||
u.Data["json"] = identity
|
|
||||||
u.ServeJSON()
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"oc-discovery/models"
|
|
||||||
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Operations about peer
|
|
||||||
type PeerController struct {
|
|
||||||
beego.Controller
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title Create
|
|
||||||
// @Description create peers
|
|
||||||
// @Param body body []models.Peer true "The peer content"
|
|
||||||
// @Success 200 {string} models.Peer.Id
|
|
||||||
// @Failure 403 body is empty
|
|
||||||
// @router / [post]
|
|
||||||
func (o *PeerController) Post() {
|
|
||||||
var ob []models.Peer
|
|
||||||
json.Unmarshal(o.Ctx.Input.RequestBody, &ob)
|
|
||||||
models.AddPeers(ob)
|
|
||||||
o.Data["json"] = map[string]string{"Added": "OK"}
|
|
||||||
o.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title Get
|
|
||||||
// @Description find peer by peerid
|
|
||||||
// @Param peerId path string true "the peerid you want to get"
|
|
||||||
// @Success 200 {peer} models.Peer
|
|
||||||
// @Failure 403 :peerId is empty
|
|
||||||
// @router /:peerId [get]
|
|
||||||
func (o *PeerController) Get() {
|
|
||||||
peerId := o.Ctx.Input.Param(":peerId")
|
|
||||||
|
|
||||||
peer, err := models.GetPeer(peerId)
|
|
||||||
if err != nil {
|
|
||||||
o.Data["json"] = err.Error()
|
|
||||||
} else {
|
|
||||||
o.Data["json"] = peer
|
|
||||||
}
|
|
||||||
|
|
||||||
o.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title Find
|
|
||||||
// @Description find peers with query
|
|
||||||
// @Param query path string true "the keywords you need"
|
|
||||||
// @Success 200 {peers} []models.Peer
|
|
||||||
// @Failure 403
|
|
||||||
// @router /find/:query [get]
|
|
||||||
func (o *PeerController) Find() {
|
|
||||||
query := o.Ctx.Input.Param(":query")
|
|
||||||
peers, err := models.FindPeers(query)
|
|
||||||
if err != nil {
|
|
||||||
o.Data["json"] = err.Error()
|
|
||||||
} else {
|
|
||||||
o.Data["json"] = peers
|
|
||||||
}
|
|
||||||
o.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title Delete
|
|
||||||
// @Description delete the peer
|
|
||||||
// @Param peerId path string true "The peerId you want to delete"
|
|
||||||
// @Success 200 {string} delete success!
|
|
||||||
// @Failure 403 peerId is empty
|
|
||||||
// @router /:peerId [delete]
|
|
||||||
func (o *PeerController) Delete() {
|
|
||||||
peerId := o.Ctx.Input.Param(":peerId")
|
|
||||||
err := models.Delete(peerId)
|
|
||||||
if err != nil {
|
|
||||||
o.Data["json"] = err.Error()
|
|
||||||
} else {
|
|
||||||
o.Data["json"] = "delete success!"
|
|
||||||
}
|
|
||||||
o.ServeJSON()
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VersionController operations for Version
|
|
||||||
type VersionController struct {
|
|
||||||
beego.Controller
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title GetAll
|
|
||||||
// @Description get version
|
|
||||||
// @Success 200
|
|
||||||
// @router / [get]
|
|
||||||
func (c *VersionController) GetAll() {
|
|
||||||
c.Data["json"] = map[string]string{"version": "1"}
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
148
daemons/node/common/common_pubsub.go
Normal file
148
daemons/node/common/common_pubsub.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
|
"github.com/libp2p/go-libp2p/core/host"
|
||||||
|
pp "github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Event struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
From string `json:"from"` // peerID
|
||||||
|
|
||||||
|
User string
|
||||||
|
|
||||||
|
DataType int64 `json:"datatype"`
|
||||||
|
Timestamp int64 `json:"ts"`
|
||||||
|
Payload []byte `json:"payload"`
|
||||||
|
Signature []byte `json:"sig"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEvent(name string, from string, dt *tools.DataType, user string, payload []byte) *Event {
|
||||||
|
priv, err := LoadKeyFromFilePrivate() // your node private key
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
evt := &Event{
|
||||||
|
Type: name,
|
||||||
|
From: from,
|
||||||
|
User: user,
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
if dt != nil {
|
||||||
|
evt.DataType = int64(dt.EnumIndex())
|
||||||
|
} else {
|
||||||
|
evt.DataType = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := json.Marshal(evt)
|
||||||
|
sig, _ := priv.Sign(body)
|
||||||
|
evt.Signature = sig
|
||||||
|
return evt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Event) RawEvent() *Event {
|
||||||
|
return &Event{
|
||||||
|
Type: e.Type,
|
||||||
|
From: e.From,
|
||||||
|
User: e.User,
|
||||||
|
DataType: e.DataType,
|
||||||
|
Timestamp: e.Timestamp,
|
||||||
|
Payload: e.Payload,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Event) toRawByte() ([]byte, error) {
|
||||||
|
return json.Marshal(e.RawEvent())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (event *Event) Verify(p *peer.Peer) error {
|
||||||
|
if p == nil {
|
||||||
|
return errors.New("no peer found")
|
||||||
|
}
|
||||||
|
if p.Relation == peer.BLACKLIST { // if peer is blacklisted... quit...
|
||||||
|
return errors.New("peer is blacklisted")
|
||||||
|
}
|
||||||
|
pubKey, err := PubKeyFromString(p.PublicKey) // extract pubkey from pubkey str
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("pubkey is malformed")
|
||||||
|
}
|
||||||
|
data, err := event.toRawByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} // extract byte from raw event excluding signature.
|
||||||
|
if ok, _ := pubKey.Verify(data, event.Signature); !ok { // then verify if pubkey sign this message...
|
||||||
|
return errors.New("check signature failed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopicNodeActivityPub struct {
|
||||||
|
DID string
|
||||||
|
PeerID string
|
||||||
|
NodeActivity peer.PeerState
|
||||||
|
}
|
||||||
|
|
||||||
|
type LongLivedPubSubService struct {
|
||||||
|
Host host.Host
|
||||||
|
LongLivedPubSubs map[string]*pubsub.Topic
|
||||||
|
PubsubMu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLongLivedPubSubService(h host.Host) *LongLivedPubSubService {
|
||||||
|
return &LongLivedPubSubService{
|
||||||
|
Host: h,
|
||||||
|
LongLivedPubSubs: map[string]*pubsub.Topic{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LongLivedPubSubService) processEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
p *peer.Peer,
|
||||||
|
event *Event,
|
||||||
|
topicName string, handler func(context.Context, string, *Event) error) error {
|
||||||
|
if err := event.Verify(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return handler(ctx, topicName, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
const TopicPubSubNodeActivity = "oc-node-activity"
|
||||||
|
const TopicPubSubSearch = "oc-node-search"
|
||||||
|
|
||||||
|
func (s *LongLivedPubSubService) SubscribeToNodeActivity(ps *pubsub.PubSub) error {
|
||||||
|
ps.RegisterTopicValidator(TopicPubSubNodeActivity, func(ctx context.Context, p pp.ID, m *pubsub.Message) bool {
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if topic, err := ps.Join(TopicPubSubNodeActivity); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
s.PubsubMu.Lock()
|
||||||
|
defer s.PubsubMu.Unlock()
|
||||||
|
s.LongLivedPubSubs[TopicPubSubNodeActivity] = topic
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LongLivedPubSubService) SubscribeToSearch(ps *pubsub.PubSub) error {
|
||||||
|
ps.RegisterTopicValidator(TopicPubSubSearch, func(ctx context.Context, p pp.ID, m *pubsub.Message) bool {
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if topic, err := ps.Join(TopicPubSubSearch); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
s.PubsubMu.Lock()
|
||||||
|
defer s.PubsubMu.Unlock()
|
||||||
|
s.LongLivedPubSubs[TopicPubSubSearch] = topic
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
385
daemons/node/common/common_stream.go
Normal file
385
daemons/node/common/common_stream.go
Normal file
@@ -0,0 +1,385 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"oc-discovery/conf"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
peer "cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"github.com/libp2p/go-libp2p/core/host"
|
||||||
|
"github.com/libp2p/go-libp2p/core/network"
|
||||||
|
pp "github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
"github.com/libp2p/go-libp2p/core/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LongLivedStreamRecordedService[T interface{}] struct {
|
||||||
|
*LongLivedPubSubService
|
||||||
|
StreamRecords map[protocol.ID]map[pp.ID]*StreamRecord[T]
|
||||||
|
StreamMU sync.RWMutex
|
||||||
|
maxNodesConn int
|
||||||
|
isBidirectionnal bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStreamRecordedService[T interface{}](h host.Host, maxNodesConn int, isBidirectionnal bool) *LongLivedStreamRecordedService[T] {
|
||||||
|
service := &LongLivedStreamRecordedService[T]{
|
||||||
|
LongLivedPubSubService: NewLongLivedPubSubService(h),
|
||||||
|
StreamRecords: map[protocol.ID]map[pp.ID]*StreamRecord[T]{},
|
||||||
|
maxNodesConn: maxNodesConn,
|
||||||
|
isBidirectionnal: isBidirectionnal,
|
||||||
|
}
|
||||||
|
go service.StartGC(30 * time.Second)
|
||||||
|
// Garbage collection is needed on every Map of Long-Lived Stream... it may be a top level redesigned
|
||||||
|
go service.Snapshot(1 * time.Hour)
|
||||||
|
return service
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *LongLivedStreamRecordedService[T]) StartGC(interval time.Duration) {
|
||||||
|
go func() {
|
||||||
|
t := time.NewTicker(interval)
|
||||||
|
defer t.Stop()
|
||||||
|
for range t.C {
|
||||||
|
ix.gc()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *LongLivedStreamRecordedService[T]) gc() {
|
||||||
|
ix.StreamMU.Lock()
|
||||||
|
defer ix.StreamMU.Unlock()
|
||||||
|
now := time.Now()
|
||||||
|
streams := ix.StreamRecords[ProtocolHeartbeat]
|
||||||
|
if streams == nil {
|
||||||
|
ix.StreamRecords[ProtocolHeartbeat] = map[pp.ID]*StreamRecord[T]{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for pid, rec := range streams {
|
||||||
|
if now.After(rec.HeartbeatStream.Expiry) || now.Sub(rec.LastSeen) > 2*rec.HeartbeatStream.Expiry.Sub(now) {
|
||||||
|
for _, sstreams := range ix.StreamRecords {
|
||||||
|
if sstreams[pid] != nil {
|
||||||
|
sstreams[pid].Stream.Close()
|
||||||
|
delete(sstreams, pid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ix.PubsubMu.Lock()
|
||||||
|
if ix.LongLivedPubSubs[TopicPubSubNodeActivity] != nil {
|
||||||
|
if b, err := json.Marshal(TopicNodeActivityPub{
|
||||||
|
DID: rec.HeartbeatStream.DID,
|
||||||
|
PeerID: pid.String(),
|
||||||
|
NodeActivity: peer.OFFLINE,
|
||||||
|
}); err == nil {
|
||||||
|
ix.LongLivedPubSubs[TopicPubSubNodeActivity].Publish(context.Background(), b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ix.PubsubMu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *LongLivedStreamRecordedService[T]) Snapshot(interval time.Duration) {
|
||||||
|
go func() {
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
t := time.NewTicker(interval)
|
||||||
|
defer t.Stop()
|
||||||
|
for range t.C {
|
||||||
|
infos := ix.snapshot()
|
||||||
|
for _, inf := range infos {
|
||||||
|
logger.Info().Msg(" -> " + inf.DID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------- Snapshot / Query --------
|
||||||
|
func (ix *LongLivedStreamRecordedService[T]) snapshot() []*StreamRecord[T] {
|
||||||
|
ix.StreamMU.Lock()
|
||||||
|
defer ix.StreamMU.Unlock()
|
||||||
|
|
||||||
|
out := make([]*StreamRecord[T], 0, len(ix.StreamRecords))
|
||||||
|
for _, streams := range ix.StreamRecords {
|
||||||
|
for _, stream := range streams {
|
||||||
|
out = append(out, stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *LongLivedStreamRecordedService[T]) HandleNodeHeartbeat(s network.Stream) {
|
||||||
|
streams := ix.StreamRecords[ProtocolHeartbeat]
|
||||||
|
pid, hb, err := CheckHeartbeat(ix.Host, s, ix.maxNodesConn)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ix.StreamMU.Lock()
|
||||||
|
defer ix.StreamMU.Unlock()
|
||||||
|
if streams == nil {
|
||||||
|
ix.StreamRecords[ProtocolHeartbeat] = map[pp.ID]*StreamRecord[T]{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if record already seen update last seen
|
||||||
|
if rec, ok := streams[*pid]; ok {
|
||||||
|
rec.DID = hb.DID
|
||||||
|
rec.Stream = s
|
||||||
|
rec.HeartbeatStream = hb.Stream
|
||||||
|
rec.LastSeen = time.Unix(hb.Timestamp, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// si je l'handle et que je ne suis pas dans une
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckHeartbeat(h host.Host, s network.Stream, maxNodes int) (*pp.ID, *Heartbeat, error) {
|
||||||
|
if len(h.Network().Peers()) >= maxNodes {
|
||||||
|
return nil, nil, fmt.Errorf("too many connections, try another indexer")
|
||||||
|
}
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
var hb Heartbeat
|
||||||
|
if err := json.NewDecoder(s).Decode(&hb); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
pid, err := pp.Decode(hb.PeerID)
|
||||||
|
hb.Stream.Stream = s // here is the long-lived bidirectionnal heart bit.
|
||||||
|
return &pid, &hb, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type StreamRecord[T interface{}] struct {
|
||||||
|
DID string
|
||||||
|
HeartbeatStream *Stream
|
||||||
|
Stream network.Stream
|
||||||
|
Record T
|
||||||
|
LastSeen time.Time // to check expiry
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stream struct {
|
||||||
|
DID string `json:"did"`
|
||||||
|
Stream network.Stream
|
||||||
|
Expiry time.Time `json:"expiry"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStream[T interface{}](s network.Stream, did string, record T) *Stream {
|
||||||
|
return &Stream{
|
||||||
|
DID: did,
|
||||||
|
Stream: s,
|
||||||
|
Expiry: time.Now().UTC().Add(2 * time.Minute),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProtocolStream map[protocol.ID]map[pp.ID]*Stream
|
||||||
|
|
||||||
|
func (ps ProtocolStream) Get(protocol protocol.ID) map[pp.ID]*Stream {
|
||||||
|
if ps[protocol] == nil {
|
||||||
|
ps[protocol] = map[pp.ID]*Stream{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ps[protocol]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps ProtocolStream) Add(protocol protocol.ID, peerID *pp.ID, s *Stream) error {
|
||||||
|
if ps[protocol] == nil {
|
||||||
|
ps[protocol] = map[pp.ID]*Stream{}
|
||||||
|
}
|
||||||
|
if peerID != nil {
|
||||||
|
if s != nil {
|
||||||
|
ps[protocol][*peerID] = s
|
||||||
|
} else {
|
||||||
|
return errors.New("unable to add stream : stream missing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps ProtocolStream) Delete(protocol protocol.ID, peerID *pp.ID) {
|
||||||
|
if streams, ok := ps[protocol]; ok {
|
||||||
|
if peerID != nil && streams[*peerID] != nil {
|
||||||
|
streams[*peerID].Stream.Close()
|
||||||
|
delete(streams, *peerID)
|
||||||
|
} else {
|
||||||
|
for _, s := range ps {
|
||||||
|
for _, v := range s {
|
||||||
|
v.Stream.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(ps, protocol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProtocolPublish = "/opencloud/record/publish/1.0"
|
||||||
|
ProtocolGet = "/opencloud/record/get/1.0"
|
||||||
|
)
|
||||||
|
|
||||||
|
var StaticIndexers []*pp.AddrInfo = []*pp.AddrInfo{}
|
||||||
|
var StreamIndexers ProtocolStream = ProtocolStream{}
|
||||||
|
|
||||||
|
func ConnectToIndexers(h host.Host, minIndexer int, maxIndexer int, myPID pp.ID) {
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
ctx := context.Background()
|
||||||
|
addresses := strings.Split(conf.GetConfig().IndexerAddresses, ",")
|
||||||
|
|
||||||
|
if len(addresses) > maxIndexer {
|
||||||
|
addresses = addresses[0:maxIndexer]
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, indexerAddr := range addresses {
|
||||||
|
ad, err := pp.AddrInfoFromString(indexerAddr)
|
||||||
|
if err != nil {
|
||||||
|
logger.Err(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if h.Network().Connectedness(ad.ID) != network.Connected {
|
||||||
|
if err := h.Connect(ctx, *ad); err != nil {
|
||||||
|
logger.Err(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StaticIndexers = append(StaticIndexers, ad)
|
||||||
|
// make a privilege streams with indexer.
|
||||||
|
for _, proto := range []protocol.ID{ProtocolPublish, ProtocolGet, ProtocolHeartbeat} {
|
||||||
|
AddStreamProtocol(nil, StreamIndexers, h, proto, ad.ID, myPID, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(StaticIndexers) == 0 {
|
||||||
|
logger.Err(errors.New("you run a node without indexers... your gonna be isolated."))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(StaticIndexers) < minIndexer {
|
||||||
|
// TODO : ask for unknown indexer.
|
||||||
|
}
|
||||||
|
SendHeartbeat(ctx, ProtocolHeartbeat, h, StreamIndexers, StaticIndexers, 20) // your indexer is just like a node for the next indexer.
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddStreamProtocol(ctx *context.Context, protoS ProtocolStream, h host.Host, proto protocol.ID, id pp.ID, mypid pp.ID, onStreamCreated *func(network.Stream)) ProtocolStream {
|
||||||
|
if onStreamCreated == nil {
|
||||||
|
f := func(s network.Stream) {
|
||||||
|
protoS[proto][id] = &Stream{
|
||||||
|
Stream: s,
|
||||||
|
Expiry: time.Now().Add(2 * time.Minute),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onStreamCreated = &f
|
||||||
|
}
|
||||||
|
f := *onStreamCreated
|
||||||
|
if mypid > id {
|
||||||
|
if ctx == nil {
|
||||||
|
c := context.Background()
|
||||||
|
ctx = &c
|
||||||
|
}
|
||||||
|
if protoS[proto] == nil {
|
||||||
|
protoS[proto] = map[pp.ID]*Stream{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if protoS[proto][id] != nil {
|
||||||
|
protoS[proto][id].Expiry = time.Now().Add(2 * time.Minute)
|
||||||
|
} else {
|
||||||
|
s, err := h.NewStream(*ctx, id, proto)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
f(s)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
h.SetStreamHandler(proto, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return protoS
|
||||||
|
}
|
||||||
|
|
||||||
|
type Heartbeat struct {
|
||||||
|
Stream *Stream `json:"stream"`
|
||||||
|
DID string `json:"did"`
|
||||||
|
PeerID string `json:"peer_id"`
|
||||||
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HeartbeatInfo []struct {
|
||||||
|
Info []byte `json:"info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProtocolHeartbeat = "/opencloud/heartbeat/1.0"
|
||||||
|
|
||||||
|
func SendHeartbeat(ctx context.Context, proto protocol.ID, h host.Host, ps ProtocolStream, peers []*pp.AddrInfo, interval time.Duration) {
|
||||||
|
peerID, err := oclib.GenerateNodeID()
|
||||||
|
if err == nil {
|
||||||
|
panic("can't heartbeat daemon failed to start")
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
t := time.NewTicker(interval)
|
||||||
|
defer t.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
hb := Heartbeat{
|
||||||
|
DID: peerID,
|
||||||
|
PeerID: h.ID().String(),
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
}
|
||||||
|
for _, ix := range peers {
|
||||||
|
_ = sendHeartbeat(ctx, h, proto, ix, hb, ps, interval*time.Second)
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendHeartbeat(ctx context.Context, h host.Host, proto protocol.ID, p *pp.AddrInfo, hb Heartbeat, ps ProtocolStream, interval time.Duration) error {
|
||||||
|
streams := ps.Get(proto)
|
||||||
|
if len(streams) == 0 {
|
||||||
|
return errors.New("no stream for protocol heartbeat founded")
|
||||||
|
}
|
||||||
|
pss, exists := streams[p.ID]
|
||||||
|
|
||||||
|
ctxTTL, _ := context.WithTimeout(ctx, 3*interval)
|
||||||
|
// Connect si nécessaire
|
||||||
|
if h.Network().Connectedness(p.ID) != network.Connected {
|
||||||
|
_ = h.Connect(ctxTTL, *p)
|
||||||
|
exists = false // on devra recréer le stream
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crée le stream si inexistant ou fermé
|
||||||
|
if !exists || pss.Stream == nil {
|
||||||
|
s, err := h.NewStream(ctx, p.ID, proto)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pss = &Stream{
|
||||||
|
Stream: s,
|
||||||
|
Expiry: time.Now().UTC().Add(2 * time.Minute),
|
||||||
|
}
|
||||||
|
streams[p.ID] = pss
|
||||||
|
}
|
||||||
|
|
||||||
|
// Envoie le heartbeat
|
||||||
|
ss := json.NewEncoder(pss.Stream)
|
||||||
|
err := ss.Encode(&hb)
|
||||||
|
if err != nil {
|
||||||
|
pss.Stream.Close()
|
||||||
|
pss.Stream = nil // recréera au prochain tick
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pss.Expiry = time.Now().UTC().Add(2 * time.Minute)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func SearchPeer(search string) ([]*peer.Peer, error) {
|
||||||
|
ps := []*peer.Peer{}
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
peers := access.Search(nil, search, false)
|
||||||
|
if len(peers.Data) == 0 {
|
||||||
|
return ps, errors.New("no self available")
|
||||||
|
}
|
||||||
|
for _, p := range peers.Data {
|
||||||
|
ps = append(ps, p.(*peer.Peer))
|
||||||
|
}
|
||||||
|
return ps, nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
114
daemons/node/common/crypto.go
Normal file
114
daemons/node/common/crypto.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/ed25519"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"oc-discovery/conf"
|
||||||
|
"oc-discovery/models"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||||||
|
"github.com/libp2p/go-libp2p/core/pnet"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VerifyPeer(peers []*peer.Peer, event models.Event) error {
|
||||||
|
if len(peers) == 0 {
|
||||||
|
return errors.New("no peer found")
|
||||||
|
}
|
||||||
|
p := peers[0]
|
||||||
|
if p.Relation == peer.BLACKLIST { // if peer is blacklisted... quit...
|
||||||
|
return errors.New("peer is blacklisted")
|
||||||
|
}
|
||||||
|
pubKey, err := PubKeyFromString(p.PublicKey) // extract pubkey from pubkey str
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("pubkey is malformed")
|
||||||
|
}
|
||||||
|
data, err := event.ToRawByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} // extract byte from raw event excluding signature.
|
||||||
|
if ok, _ := pubKey.Verify(data, event.Signature); !ok { // then verify if pubkey sign this message...
|
||||||
|
return errors.New("check signature failed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sign(priv crypto.PrivKey, data []byte) ([]byte, error) {
|
||||||
|
return priv.Sign(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Verify(pub crypto.PubKey, data, sig []byte) (bool, error) {
|
||||||
|
return pub.Verify(data, sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadKeyFromFilePrivate() (crypto.PrivKey, error) {
|
||||||
|
path := conf.GetConfig().PrivateKeyPath
|
||||||
|
fmt.Println("extract " + path)
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Println(data)
|
||||||
|
block, _ := pem.Decode(data)
|
||||||
|
fmt.Println(block.Bytes)
|
||||||
|
keyAny, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
edKey, ok := keyAny.(ed25519.PrivateKey)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("not an ed25519 key")
|
||||||
|
}
|
||||||
|
return crypto.UnmarshalEd25519PrivateKey(edKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadKeyFromFilePublic() (crypto.PubKey, error) {
|
||||||
|
path := conf.GetConfig().PublicKeyPath
|
||||||
|
fmt.Println("extract " + path)
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
block, _ := pem.Decode(data)
|
||||||
|
keyAny, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
edKey, ok := keyAny.(ed25519.PublicKey)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("not an ed25519 key")
|
||||||
|
}
|
||||||
|
// Try to unmarshal as libp2p private key (supports ed25519, rsa, etc.)
|
||||||
|
return crypto.UnmarshalEd25519PublicKey(edKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadPSKFromFile() (pnet.PSK, error) {
|
||||||
|
path := conf.GetConfig().PSKPath
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
psk, err := pnet.DecodeV1PSK(bytes.NewReader(data))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Println("PSK found.")
|
||||||
|
return psk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func PubKeyFromString(s string) (crypto.PubKey, error) {
|
||||||
|
data, err := base64.StdEncoding.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return crypto.UnmarshalPublicKey(data)
|
||||||
|
}
|
||||||
11
daemons/node/common/interface.go
Normal file
11
daemons/node/common/interface.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiscoveryPeer interface {
|
||||||
|
GetPeerRecord(ctx context.Context, key string) (*peer.Peer, error)
|
||||||
|
}
|
||||||
231
daemons/node/indexer/handler.go
Normal file
231
daemons/node/indexer/handler.go
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
package indexer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
pp "cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/utils"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||||||
|
"github.com/libp2p/go-libp2p/core/network"
|
||||||
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PeerRecord struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
DID string `json:"did"` // real PEER ID
|
||||||
|
PeerID string `json:"peer_id"`
|
||||||
|
PubKey []byte `json:"pub_key"`
|
||||||
|
APIUrl string `json:"api_url"`
|
||||||
|
StreamAddress string `json:"stream_address"`
|
||||||
|
NATSAddress string `json:"nats_address"`
|
||||||
|
WalletAddress string `json:"wallet_address"`
|
||||||
|
Signature []byte `json:"signature"`
|
||||||
|
ExpiryDate time.Time `json:"expiry_date"`
|
||||||
|
|
||||||
|
TTL int `json:"ttl"` // max of hop diffusion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PeerRecord) Sign() error {
|
||||||
|
priv, err := common.LoadKeyFromFilePrivate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dht := PeerRecord{
|
||||||
|
Name: p.Name,
|
||||||
|
DID: p.DID,
|
||||||
|
PubKey: p.PubKey,
|
||||||
|
ExpiryDate: p.ExpiryDate,
|
||||||
|
}
|
||||||
|
payload, _ := json.Marshal(dht)
|
||||||
|
b, err := common.Sign(priv, payload)
|
||||||
|
p.Signature = b
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PeerRecord) Verify() (crypto.PubKey, error) {
|
||||||
|
pubKey, err := crypto.UnmarshalPublicKey(p.PubKey) // retrieve pub key in message
|
||||||
|
if err != nil {
|
||||||
|
return pubKey, err
|
||||||
|
}
|
||||||
|
dht := PeerRecord{
|
||||||
|
Name: p.Name,
|
||||||
|
DID: p.DID,
|
||||||
|
PubKey: p.PubKey,
|
||||||
|
ExpiryDate: p.ExpiryDate,
|
||||||
|
}
|
||||||
|
payload, _ := json.Marshal(dht)
|
||||||
|
|
||||||
|
if ok, _ := common.Verify(pubKey, payload, p.Signature); !ok { // verify minimal message was sign per pubKey
|
||||||
|
return pubKey, errors.New("invalid signature")
|
||||||
|
}
|
||||||
|
return pubKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pr *PeerRecord) ExtractPeer(ourkey string, key string, pubKey crypto.PubKey) (bool, *pp.Peer, error) {
|
||||||
|
pubBytes, _ := pubKey.Raw()
|
||||||
|
|
||||||
|
rel := pp.NONE
|
||||||
|
if ourkey == key { // at this point is PeerID is same as our... we are... thats our peer INFO
|
||||||
|
rel = pp.SELF
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &pp.Peer{
|
||||||
|
AbstractObject: utils.AbstractObject{
|
||||||
|
UUID: pr.DID,
|
||||||
|
Name: pr.Name,
|
||||||
|
},
|
||||||
|
State: pp.ONLINE,
|
||||||
|
Relation: rel, // VERIFY.... it crush nothing
|
||||||
|
PeerID: pr.PeerID,
|
||||||
|
PublicKey: base64.StdEncoding.EncodeToString(pubBytes),
|
||||||
|
APIUrl: pr.APIUrl,
|
||||||
|
StreamAddress: pr.StreamAddress,
|
||||||
|
NATSAddress: pr.NATSAddress,
|
||||||
|
WalletAddress: pr.WalletAddress,
|
||||||
|
}
|
||||||
|
if time.Now().After(pr.ExpiryDate) { // is expired
|
||||||
|
p.State = pp.OFFLINE // then is considers OFFLINE
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(p)
|
||||||
|
if err != nil {
|
||||||
|
return pp.SELF == p.Relation, nil, err
|
||||||
|
}
|
||||||
|
tools.NewNATSCaller().SetNATSPub(tools.CREATE_RESOURCE, tools.NATSResponse{
|
||||||
|
FromApp: "oc-discovery",
|
||||||
|
Datatype: tools.PEER,
|
||||||
|
Method: int(tools.CREATE_PEER),
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
if p.State == pp.OFFLINE {
|
||||||
|
return pp.SELF == p.Relation, nil, errors.New("peer " + key + " is offline")
|
||||||
|
}
|
||||||
|
return pp.SELF == p.Relation, p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetValue struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetResponse struct {
|
||||||
|
Found bool `json:"found"`
|
||||||
|
Record PeerRecord `json:"record,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *IndexerService) initNodeHandler() {
|
||||||
|
ix.Host.SetStreamHandler(common.ProtocolHeartbeat, ix.HandleNodeHeartbeat)
|
||||||
|
ix.Host.SetStreamHandler(common.ProtocolPublish, ix.handleNodePublish)
|
||||||
|
ix.Host.SetStreamHandler(common.ProtocolGet, ix.handleNodeGet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *IndexerService) handleNodePublish(s network.Stream) {
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
var rec PeerRecord
|
||||||
|
if err := json.NewDecoder(s).Decode(&rec); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if rec.PeerID == "" || rec.ExpiryDate.Before(time.Now()) { // already expired
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pid, err := peer.Decode(rec.PeerID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ix.StreamMU.Lock()
|
||||||
|
defer ix.StreamMU.Unlock()
|
||||||
|
|
||||||
|
streams := ix.StreamRecords[common.ProtocolPublish]
|
||||||
|
if streams == nil {
|
||||||
|
ix.StreamRecords[common.ProtocolPublish] = map[peer.ID]*common.StreamRecord[PeerRecord]{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if srec, ok := streams[pid]; ok {
|
||||||
|
srec.DID = rec.DID
|
||||||
|
srec.Record = rec
|
||||||
|
srec.LastSeen = time.Now()
|
||||||
|
} else {
|
||||||
|
streams[pid] = &common.StreamRecord[PeerRecord]{ // HeartBeat wil
|
||||||
|
DID: rec.DID,
|
||||||
|
Record: rec,
|
||||||
|
LastSeen: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rec.TTL > 0 {
|
||||||
|
for _, ad := range common.StaticIndexers {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *IndexerService) handleNodeGet(s network.Stream) {
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
var req GetValue
|
||||||
|
if err := json.NewDecoder(s).Decode(&req); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ix.StreamMU.Lock()
|
||||||
|
defer ix.StreamMU.Unlock()
|
||||||
|
|
||||||
|
streams := ix.StreamRecords[common.ProtocolGet]
|
||||||
|
if streams == nil {
|
||||||
|
ix.StreamRecords[common.ProtocolGet] = map[peer.ID]*common.StreamRecord[PeerRecord]{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// simple lookup by PeerID (or DID)
|
||||||
|
for _, rec := range streams {
|
||||||
|
if rec.Record.DID == req.Key || rec.Record.PeerID == req.Key { // OK
|
||||||
|
resp := GetResponse{
|
||||||
|
Found: true,
|
||||||
|
Record: rec.Record,
|
||||||
|
}
|
||||||
|
_ = json.NewEncoder(s).Encode(resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if not found ask to my neighboor indexers
|
||||||
|
if common.StreamIndexers[common.ProtocolPublish] == nil {
|
||||||
|
_ = json.NewEncoder(s).Encode(GetResponse{Found: false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, ad := range common.StaticIndexers {
|
||||||
|
if common.StreamIndexers[common.ProtocolPublish][ad.ID] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
stream := common.StreamIndexers[common.ProtocolPublish][ad.ID]
|
||||||
|
if err := json.NewEncoder(stream.Stream).Encode(GetValue{Key: req.Key}); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp GetResponse
|
||||||
|
if err := json.NewDecoder(stream.Stream).Decode(&resp); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if resp.Found {
|
||||||
|
_ = json.NewEncoder(s).Encode(GetResponse{
|
||||||
|
Found: true,
|
||||||
|
Record: resp.Record,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not found
|
||||||
|
_ = json.NewEncoder(s).Encode(GetResponse{Found: false})
|
||||||
|
}
|
||||||
55
daemons/node/indexer/service.go
Normal file
55
daemons/node/indexer/service.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package indexer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
|
"github.com/libp2p/go-libp2p/core/host"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Index Record is the model for the specialized registry of node connected to Indexer
|
||||||
|
type IndexerService struct {
|
||||||
|
*common.LongLivedStreamRecordedService[PeerRecord]
|
||||||
|
PS *pubsub.PubSub
|
||||||
|
isStrictIndexer bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a pubsub is given... indexer is also an active oc-node. If not... your a strict indexer
|
||||||
|
func NewIndexerService(h host.Host, ps *pubsub.PubSub, maxNode int) *IndexerService {
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
logger.Info().Msg("open indexer mode...")
|
||||||
|
var err error
|
||||||
|
ix := &IndexerService{
|
||||||
|
LongLivedStreamRecordedService: common.NewStreamRecordedService[PeerRecord](h, maxNode, false),
|
||||||
|
isStrictIndexer: ps == nil,
|
||||||
|
}
|
||||||
|
if ps == nil { // generate your fresh gossip for the flow of killed node... EVERYBODY should know !
|
||||||
|
ps, err = pubsub.NewGossipSub(context.Background(), ix.Host)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // can't run your indexer without a propalgation pubsub, of state of node.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ix.PS = ps
|
||||||
|
// later TODO : all indexer laucnh a private replica of them self. DEV OPS
|
||||||
|
if ix.isStrictIndexer {
|
||||||
|
logger.Info().Msg("connect to indexers as strict indexer...")
|
||||||
|
common.ConnectToIndexers(h, 0, 5, ix.Host.ID()) // TODO : make var to change how many indexers are allowed.
|
||||||
|
logger.Info().Msg("subscribe to node activity as strict indexer...")
|
||||||
|
ix.SubscribeToNodeActivity(ix.PS) // now we subscribe to a long run topic named node-activity, to relay message.
|
||||||
|
logger.Info().Msg("subscribe to decentralized search flow as strict indexer...")
|
||||||
|
ix.SubscribeToSearch(ix.PS)
|
||||||
|
}
|
||||||
|
ix.initNodeHandler() // then listen up on every protocol expected
|
||||||
|
return ix
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *IndexerService) Close() {
|
||||||
|
for _, s := range ix.StreamRecords {
|
||||||
|
for _, ss := range s {
|
||||||
|
ss.Stream.Close()
|
||||||
|
ss.HeartbeatStream.Stream.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
daemons/node/nats.go
Normal file
46
daemons/node/nats.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package node
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListenNATS(n Node) {
|
||||||
|
tools.NewNATSCaller().ListenNats(map[tools.NATSMethod]func(tools.NATSResponse){
|
||||||
|
tools.PROPALGATION_EVENT: func(resp tools.NATSResponse) {
|
||||||
|
var propalgation tools.PropalgationMessage
|
||||||
|
err := json.Unmarshal(resp.Payload, &propalgation)
|
||||||
|
var dt *tools.DataType
|
||||||
|
if propalgation.DataType > 0 {
|
||||||
|
dtt := tools.DataType(propalgation.DataType)
|
||||||
|
dt = &dtt
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
switch propalgation.Action {
|
||||||
|
case tools.PB_CREATE:
|
||||||
|
case tools.PB_UPDATE:
|
||||||
|
case tools.PB_DELETE:
|
||||||
|
n.StreamService.ToPartnerPublishEvent(
|
||||||
|
context.Background(),
|
||||||
|
propalgation.Action,
|
||||||
|
dt, resp.User,
|
||||||
|
propalgation.Payload,
|
||||||
|
)
|
||||||
|
case tools.PB_SEARCH:
|
||||||
|
m := map[string]interface{}{}
|
||||||
|
json.Unmarshal(propalgation.Payload, &m)
|
||||||
|
n.PubSubService.SearchPublishEvent(
|
||||||
|
context.Background(),
|
||||||
|
dt,
|
||||||
|
fmt.Sprintf("%v", m["type"]),
|
||||||
|
resp.User,
|
||||||
|
fmt.Sprintf("%v", m["search"]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
245
daemons/node/node.go
Normal file
245
daemons/node/node.go
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
package node
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"oc-discovery/conf"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
"oc-discovery/daemons/node/indexer"
|
||||||
|
"oc-discovery/daemons/node/pubsub"
|
||||||
|
"oc-discovery/daemons/node/stream"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"github.com/libp2p/go-libp2p"
|
||||||
|
pubsubs "github.com/libp2p/go-libp2p-pubsub"
|
||||||
|
pp "github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
*common.LongLivedStreamRecordedService[interface{}] // change type of stream
|
||||||
|
PS *pubsubs.PubSub
|
||||||
|
IndexerService *indexer.IndexerService
|
||||||
|
PubSubService *pubsub.PubSubService
|
||||||
|
StreamService *stream.StreamService
|
||||||
|
PeerID pp.ID
|
||||||
|
isIndexer bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitNode(isNode bool, isIndexer bool) (*Node, error) {
|
||||||
|
if !isNode && !isIndexer {
|
||||||
|
return nil, errors.New("wait... what ? your node need to at least something. Retry we can't be friend in that case")
|
||||||
|
}
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
logger.Info().Msg("retrieving private key...")
|
||||||
|
priv, err := common.LoadKeyFromFilePrivate() // your node private key
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
logger.Info().Msg("retrieving psk file...")
|
||||||
|
psk, err := common.LoadPSKFromFile() // network common private Network. Public OC PSK is Public Network
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
logger.Info().Msg("open a host...")
|
||||||
|
h, err := libp2p.New(
|
||||||
|
libp2p.PrivateNetwork(psk),
|
||||||
|
libp2p.Identity(priv),
|
||||||
|
libp2p.ListenAddrStrings(
|
||||||
|
fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", conf.GetConfig().NodeEndpointPort),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("no host no node")
|
||||||
|
}
|
||||||
|
node := &Node{
|
||||||
|
PeerID: h.ID(),
|
||||||
|
isIndexer: isIndexer,
|
||||||
|
LongLivedStreamRecordedService: common.NewStreamRecordedService[interface{}](h, 1000, false),
|
||||||
|
}
|
||||||
|
var ps *pubsubs.PubSub
|
||||||
|
if isNode {
|
||||||
|
logger.Info().Msg("generate opencloud node...")
|
||||||
|
ps, err = pubsubs.NewGossipSub(context.Background(), node.Host)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // can't run your node without a propalgation pubsub, of state of node.
|
||||||
|
}
|
||||||
|
node.PS = ps
|
||||||
|
logger.Info().Msg("connect to indexers...")
|
||||||
|
common.ConnectToIndexers(node.Host, 0, 5, node.PeerID) // TODO : make var to change how many indexers are allowed.
|
||||||
|
logger.Info().Msg("claims my node...")
|
||||||
|
node.claimInfo(conf.GetConfig().Name, conf.GetConfig().Hostname)
|
||||||
|
logger.Info().Msg("subscribe to decentralized search flow...")
|
||||||
|
node.SubscribeToSearch(node.PS)
|
||||||
|
logger.Info().Msg("run garbage collector...")
|
||||||
|
node.StartGC(30 * time.Second)
|
||||||
|
|
||||||
|
if node.StreamService, err = stream.InitStream(context.Background(), node.Host, node.PeerID, 1000, node); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.PubSubService, err = pubsub.InitPubSub(context.Background(), node.Host, node.PS, node, node.StreamService); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isIndexer {
|
||||||
|
logger.Info().Msg("generate opencloud indexer...")
|
||||||
|
node.IndexerService = indexer.NewIndexerService(node.Host, ps, 5)
|
||||||
|
}
|
||||||
|
logger.Info().Msg("connect to NATS")
|
||||||
|
ListenNATS(*node)
|
||||||
|
logger.Info().Msg("Node is actually running.")
|
||||||
|
return node, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Node) Close() {
|
||||||
|
if d.isIndexer {
|
||||||
|
d.IndexerService.Close()
|
||||||
|
}
|
||||||
|
d.PubSubService.Close()
|
||||||
|
d.StreamService.Close()
|
||||||
|
d.Host.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Node) publishPeerRecord(
|
||||||
|
rec *indexer.PeerRecord,
|
||||||
|
) error {
|
||||||
|
priv, err := common.LoadKeyFromFilePrivate() // your node private key
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if common.StreamIndexers[common.ProtocolPublish] == nil {
|
||||||
|
return errors.New("no protocol Publish is set up on the node")
|
||||||
|
}
|
||||||
|
for _, ad := range common.StaticIndexers {
|
||||||
|
if common.StreamIndexers[common.ProtocolPublish][ad.ID] == nil {
|
||||||
|
return errors.New("no protocol Publish for peer " + ad.ID.String() + " is set up on the node")
|
||||||
|
}
|
||||||
|
stream := common.StreamIndexers[common.ProtocolPublish][ad.ID]
|
||||||
|
base := indexer.PeerRecord{
|
||||||
|
Name: rec.Name,
|
||||||
|
DID: rec.DID,
|
||||||
|
PubKey: rec.PubKey,
|
||||||
|
ExpiryDate: time.Now().UTC().Add(2 * time.Minute),
|
||||||
|
}
|
||||||
|
payload, _ := json.Marshal(base)
|
||||||
|
hash := sha256.Sum256(payload)
|
||||||
|
|
||||||
|
rec.ExpiryDate = base.ExpiryDate
|
||||||
|
rec.Signature, err = priv.Sign(hash[:])
|
||||||
|
rec.TTL = 2
|
||||||
|
if err := json.NewEncoder(stream.Stream).Encode(&rec); err != nil { // then publish on stream
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Node) GetPeerRecord(
|
||||||
|
ctx context.Context,
|
||||||
|
key string,
|
||||||
|
) (*peer.Peer, error) {
|
||||||
|
var err error
|
||||||
|
var info *indexer.PeerRecord
|
||||||
|
if common.StreamIndexers[common.ProtocolPublish] == nil {
|
||||||
|
return nil, errors.New("no protocol Publish is set up on the node")
|
||||||
|
}
|
||||||
|
for _, ad := range common.StaticIndexers {
|
||||||
|
if common.StreamIndexers[common.ProtocolPublish][ad.ID] == nil {
|
||||||
|
return nil, errors.New("no protocol Publish for peer " + ad.ID.String() + " is set up on the node")
|
||||||
|
}
|
||||||
|
stream := common.StreamIndexers[common.ProtocolPublish][ad.ID]
|
||||||
|
if err := json.NewEncoder(stream.Stream).Encode(indexer.GetValue{Key: key}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp indexer.GetResponse
|
||||||
|
if err := json.NewDecoder(stream.Stream).Decode(&resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if resp.Found {
|
||||||
|
info = &resp.Record
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var p *peer.Peer
|
||||||
|
if info != nil {
|
||||||
|
if pk, err := info.Verify(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if ok, p, err := info.ExtractPeer(d.PeerID.String(), key, pk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
if ok {
|
||||||
|
d.publishPeerRecord(info)
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Node) claimInfo(
|
||||||
|
name string,
|
||||||
|
endPoint string, // TODO : endpoint is not necesserry StreamAddress
|
||||||
|
) (*peer.Peer, error) {
|
||||||
|
if endPoint == "" {
|
||||||
|
return nil, errors.New("no endpoint found for peer")
|
||||||
|
}
|
||||||
|
|
||||||
|
peerID, err := oclib.GenerateNodeID()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
priv, err := common.LoadKeyFromFilePrivate()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := common.LoadKeyFromFilePublic()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pubBytes, _ := pub.Raw()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
expiry := now.Add(150 * time.Second)
|
||||||
|
|
||||||
|
rec := &indexer.PeerRecord{
|
||||||
|
Name: name,
|
||||||
|
DID: peerID, // REAL PEER ID
|
||||||
|
PubKey: pubBytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
rec.PeerID = d.Host.ID().String()
|
||||||
|
d.PeerID = d.Host.ID()
|
||||||
|
|
||||||
|
payload, _ := json.Marshal(rec)
|
||||||
|
hash := sha256.Sum256(payload)
|
||||||
|
|
||||||
|
rec.Signature, err = priv.Sign(hash[:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rec.APIUrl = endPoint
|
||||||
|
rec.StreamAddress = "/ip4/" + conf.GetConfig().Hostname + " /tcp/" + fmt.Sprintf("%v", conf.GetConfig().NodeEndpointPort) + " /p2p/" + rec.PeerID
|
||||||
|
rec.NATSAddress = oclib.GetConfig().NATSUrl
|
||||||
|
rec.WalletAddress = "my-wallet"
|
||||||
|
rec.ExpiryDate = expiry
|
||||||
|
|
||||||
|
if err := d.publishPeerRecord(rec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if pk, err := rec.Verify(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
_, p, err := rec.ExtractPeer(peerID, peerID, pk)
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
}
|
||||||
42
daemons/node/pubsub/handler.go
Normal file
42
daemons/node/pubsub/handler.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package pubsub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ps *PubSubService) handleEvent(ctx context.Context, topicName string, evt *common.Event) error {
|
||||||
|
action := ps.getTopicName(topicName)
|
||||||
|
if err := ps.handleEventSearch(ctx, evt, action); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *PubSubService) handleEventSearch( // only : on partner followings. 3 canals for every partner.
|
||||||
|
ctx context.Context,
|
||||||
|
evt *common.Event,
|
||||||
|
action tools.PubSubAction,
|
||||||
|
) error {
|
||||||
|
if !(action == tools.PB_SEARCH_RESPONSE || action == tools.PB_SEARCH) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// TODO VERIFY: FROM SHOULD BE A PEER ID OR A DID
|
||||||
|
if p, err := ps.Node.GetPeerRecord(ctx, evt.From); err == nil {
|
||||||
|
if err := evt.Verify(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch action {
|
||||||
|
case tools.PB_SEARCH: // when someone ask for search.
|
||||||
|
if err := ps.StreamService.SendResponse(p, evt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
70
daemons/node/pubsub/publish.go
Normal file
70
daemons/node/pubsub/publish.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package pubsub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
"oc-discovery/models"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ps *PubSubService) SearchPublishEvent(
|
||||||
|
ctx context.Context, dt *tools.DataType, typ string, user string, search string) error {
|
||||||
|
switch typ {
|
||||||
|
case "known": // define Search Strategy
|
||||||
|
return ps.StreamService.SearchKnownPublishEvent(dt, user, search) //if partners focus only them*/
|
||||||
|
case "partner": // define Search Strategy
|
||||||
|
return ps.StreamService.SearchPartnersPublishEvent(dt, user, search) //if partners focus only them*/
|
||||||
|
case "all": // Gossip PubSub
|
||||||
|
b, err := json.Marshal(map[string]string{"search": search})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ps.searchPublishEvent(ctx, dt, user, b)
|
||||||
|
default:
|
||||||
|
return errors.New("no type of research found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *PubSubService) searchPublishEvent(
|
||||||
|
ctx context.Context, dt *tools.DataType, user string, payload []byte) error {
|
||||||
|
id, err := oclib.GenerateNodeID()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ps.subscribeEvents(ctx, dt, tools.PB_SEARCH_RESPONSE, id, 60); err != nil { // TODO Catpure Event !
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ps.publishEvent(ctx, dt, tools.PB_SEARCH, user, "", payload, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *PubSubService) publishEvent(
|
||||||
|
ctx context.Context, dt *tools.DataType, action tools.PubSubAction, user string,
|
||||||
|
peerID string, payload []byte, chanNamedByDt bool,
|
||||||
|
) error {
|
||||||
|
name := action.String() + "#" + peerID
|
||||||
|
if chanNamedByDt && dt != nil { // if a datatype is precised then : app.action.datatype#peerID
|
||||||
|
name = action.String() + "." + (*dt).String() + "#" + peerID
|
||||||
|
}
|
||||||
|
|
||||||
|
from, err := oclib.GenerateNodeID()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
priv, err := common.LoadKeyFromFilePrivate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
msg, _ := json.Marshal(models.NewEvent(name, from, dt, user, payload, priv))
|
||||||
|
topic, err := ps.PS.Join(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return topic.Publish(ctx, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO REVIEW PUBLISHING + ADD SEARCH ON PUBLIC : YES
|
||||||
|
// TODO : Search should verify DataType
|
||||||
47
daemons/node/pubsub/service.go
Normal file
47
daemons/node/pubsub/service.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package pubsub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
"oc-discovery/daemons/node/stream"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
|
"github.com/libp2p/go-libp2p/core/host"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PubSubService struct {
|
||||||
|
Node common.DiscoveryPeer
|
||||||
|
Host host.Host
|
||||||
|
PS *pubsub.PubSub
|
||||||
|
StreamService *stream.StreamService
|
||||||
|
Subscription []string
|
||||||
|
mutex sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitPubSub(ctx context.Context, h host.Host, ps *pubsub.PubSub, node common.DiscoveryPeer, streamService *stream.StreamService) (*PubSubService, error) {
|
||||||
|
service := &PubSubService{
|
||||||
|
Node: node,
|
||||||
|
Host: h,
|
||||||
|
StreamService: streamService,
|
||||||
|
PS: ps,
|
||||||
|
}
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
logger.Info().Msg("subscribe to events...")
|
||||||
|
service.initSubscribeEvents(ctx)
|
||||||
|
return service, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *PubSubService) getTopicName(topicName string) tools.PubSubAction {
|
||||||
|
ns := strings.Split(topicName, ".")
|
||||||
|
if len(ns) > 0 {
|
||||||
|
return tools.GetActionString(ns[0])
|
||||||
|
}
|
||||||
|
return tools.NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *PubSubService) Close() {
|
||||||
|
}
|
||||||
102
daemons/node/pubsub/subscribe.go
Normal file
102
daemons/node/pubsub/subscribe.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package pubsub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
"slices"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ps *PubSubService) initSubscribeEvents(ctx context.Context) error {
|
||||||
|
if err := ps.subscribeEvents(ctx, nil, tools.PB_SEARCH, "", -1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generic function to subscribe to DHT flow of event
|
||||||
|
func (ps *PubSubService) subscribeEvents(
|
||||||
|
ctx context.Context, dt *tools.DataType, action tools.PubSubAction, peerID string, timeout int,
|
||||||
|
) error {
|
||||||
|
// define a name app.action#peerID
|
||||||
|
name := action.String() + "#" + peerID
|
||||||
|
if dt != nil { // if a datatype is precised then : app.action.datatype#peerID
|
||||||
|
name = action.String() + "." + (*dt).String() + "#" + peerID
|
||||||
|
}
|
||||||
|
topic, err := ps.PS.Join(name) // find out the topic
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sub, err := topic.Subscribe() // then subscribe to it
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ps.mutex.Lock() // add safely in cache your subscription.
|
||||||
|
ps.Subscription = append(ps.Subscription, name)
|
||||||
|
ps.mutex.Unlock()
|
||||||
|
|
||||||
|
// launch loop waiting for results.
|
||||||
|
go ps.waitResults(ctx, sub, name, timeout)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *PubSubService) waitResults(ctx context.Context, sub *pubsub.Subscription, topicName string, timeout int) {
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
defer ctx.Done()
|
||||||
|
for {
|
||||||
|
ps.mutex.Lock() // check safely if cache is actually notified subscribed to topic
|
||||||
|
if !slices.Contains(ps.Subscription, topicName) { // if not kill the loop.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ps.mutex.Unlock()
|
||||||
|
// if still subscribed -> wait for new message
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
if timeout != -1 {
|
||||||
|
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
msg, err := sub.Next(ctx)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, context.DeadlineExceeded) {
|
||||||
|
// timeout hit, no message before deadline kill subsciption.
|
||||||
|
ps.mutex.Lock()
|
||||||
|
subs := []string{}
|
||||||
|
for _, ss := range ps.Subscription {
|
||||||
|
if ss != topicName {
|
||||||
|
subs = append(subs, ss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ps.Subscription = subs
|
||||||
|
ps.mutex.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var evt common.Event
|
||||||
|
if err := json.Unmarshal(msg.Data, &evt); err != nil { // map to event
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if p, err := ps.Node.GetPeerRecord(ctx, evt.From); err == nil {
|
||||||
|
if err := ps.processEvent(ctx, p, &evt, topicName); err != nil {
|
||||||
|
logger.Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *PubSubService) processEvent(
|
||||||
|
ctx context.Context, p *peer.Peer, event *common.Event, topicName string) error {
|
||||||
|
if err := event.Verify(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ps.handleEvent(ctx, topicName, event)
|
||||||
|
}
|
||||||
123
daemons/node/stream/handler.go
Normal file
123
daemons/node/stream/handler.go
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package stream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/resources"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ps *StreamService) getTopicName(topicName string) tools.PubSubAction {
|
||||||
|
ns := strings.Split(topicName, ".")
|
||||||
|
if len(ns) > 0 {
|
||||||
|
return tools.GetActionString(ns[0])
|
||||||
|
}
|
||||||
|
return tools.NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *StreamService) handleEvent(topicName string, evt *common.Event) error {
|
||||||
|
action := ps.getTopicName(topicName)
|
||||||
|
if err := ps.handleEventFromPartner(evt, action); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if action == tools.PB_SEARCH_RESPONSE {
|
||||||
|
if err := ps.retrieveResponse(evt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (abs *StreamService) retrieveResponse(event *common.Event) error { //
|
||||||
|
res, err := resources.ToResource(int(event.DataType), event.Payload)
|
||||||
|
if err != nil || res == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(res.Serialize(res))
|
||||||
|
tools.NewNATSCaller().SetNATSPub(tools.CATALOG_SEARCH_EVENT, tools.NATSResponse{
|
||||||
|
FromApp: "oc-discovery",
|
||||||
|
Datatype: tools.DataType(event.DataType),
|
||||||
|
Method: int(tools.CATALOG_SEARCH_EVENT),
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *StreamService) handleEventFromPartner(evt *common.Event, action tools.PubSubAction) error {
|
||||||
|
if !(action == tools.PB_CREATE || action == tools.PB_UPDATE || action == tools.PB_DELETE) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
resource, err := resources.ToResource(int(evt.DataType), evt.Payload)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(resource)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch action {
|
||||||
|
case tools.PB_SEARCH:
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
peers := access.Search(nil, evt.From, false)
|
||||||
|
if len(peers.Data) > 0 {
|
||||||
|
p := peers.Data[0].(*peer.Peer)
|
||||||
|
// TODO : something if peer is missing in our side !
|
||||||
|
ps.SendResponse(p, evt)
|
||||||
|
} else if p, err := ps.Node.GetPeerRecord(context.Background(), evt.From); err == nil {
|
||||||
|
ps.SendResponse(p, evt)
|
||||||
|
}
|
||||||
|
case tools.PB_CREATE:
|
||||||
|
case tools.PB_UPDATE:
|
||||||
|
tools.NewNATSCaller().SetNATSPub(tools.CREATE_RESOURCE, tools.NATSResponse{
|
||||||
|
FromApp: "oc-discovery",
|
||||||
|
Datatype: tools.DataType(evt.DataType),
|
||||||
|
Method: int(tools.CREATE_RESOURCE),
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
case tools.PB_DELETE:
|
||||||
|
tools.NewNATSCaller().SetNATSPub(tools.REMOVE_RESOURCE, tools.NATSResponse{
|
||||||
|
FromApp: "oc-discovery",
|
||||||
|
Datatype: tools.DataType(evt.DataType),
|
||||||
|
Method: int(tools.REMOVE_RESOURCE),
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
return errors.New("no action authorized available : " + action.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (abs *StreamService) SendResponse(p *peer.Peer, event *common.Event) error {
|
||||||
|
dts := []oclib.LibDataEnum{oclib.LibDataEnum(event.DataType)}
|
||||||
|
if event.DataType == -1 { // expect all resources
|
||||||
|
dts = []oclib.LibDataEnum{oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), oclib.LibDataEnum(oclib.STORAGE_RESOURCE),
|
||||||
|
oclib.LibDataEnum(oclib.PROCESSING_RESOURCE), oclib.LibDataEnum(oclib.DATA_RESOURCE), oclib.LibDataEnum(oclib.WORKFLOW_RESOURCE)}
|
||||||
|
}
|
||||||
|
var m map[string]string
|
||||||
|
err := json.Unmarshal(event.Payload, &m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, dt := range dts {
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(event.DataType), nil)
|
||||||
|
peerID := p.GetID()
|
||||||
|
searched := access.Search(abs.FilterPeer(peerID, m["search"]), "", false)
|
||||||
|
for _, ss := range searched.Data {
|
||||||
|
if j, err := json.Marshal(ss); err == nil {
|
||||||
|
if event.DataType != -1 {
|
||||||
|
ndt := tools.DataType(dt.EnumIndex())
|
||||||
|
abs.PublishResources(&ndt, event.User, peerID, j)
|
||||||
|
} else {
|
||||||
|
abs.PublishResources(nil, event.User, peerID, j)
|
||||||
|
} // TODO : TEMP STREAM !
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
188
daemons/node/stream/publish.go
Normal file
188
daemons/node/stream/publish.go
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
package stream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
"github.com/libp2p/go-libp2p/core/network"
|
||||||
|
pp "github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
"github.com/libp2p/go-libp2p/core/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ps *StreamService) PublishResources(dt *tools.DataType, user string, toPeerID string, resource []byte) error {
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
p := access.LoadOne(toPeerID)
|
||||||
|
if p.Err != "" {
|
||||||
|
return errors.New(p.Err)
|
||||||
|
} else {
|
||||||
|
ad, err := pp.AddrInfoFromString(p.Data.(*peer.Peer).StreamAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ps.write(tools.PB_SEARCH, toPeerID, ad, dt, user, resource, ProtocolSearchResource, p.Data.(*peer.Peer).Relation == peer.PARTNER)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *StreamService) SearchKnownPublishEvent(dt *tools.DataType, user string, search string) error {
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
peers := access.Search(&dbs.Filters{ // filter by like name, short_description, description, owner, url if no filters are provided
|
||||||
|
And: map[string][]dbs.Filter{
|
||||||
|
"": {{Operator: dbs.NOT.String(), Value: dbs.Filters{ // filter by like name, short_description, description, owner, url if no filters are provided
|
||||||
|
And: map[string][]dbs.Filter{
|
||||||
|
"relation": {{Operator: dbs.EQUAL.String(), Value: peer.BLACKLIST}},
|
||||||
|
},
|
||||||
|
}}},
|
||||||
|
},
|
||||||
|
}, search, false)
|
||||||
|
if peers.Err != "" {
|
||||||
|
return errors.New(peers.Err)
|
||||||
|
} else {
|
||||||
|
b, err := json.Marshal(map[string]string{"search": search})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, p := range peers.Data {
|
||||||
|
ad, err := pp.AddrInfoFromString(p.(*peer.Peer).StreamAddress)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ps.write(tools.PB_SEARCH, p.GetID(), ad, dt, user, b, ProtocolSearchResource, p.(*peer.Peer).Relation == peer.PARTNER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *StreamService) SearchPartnersPublishEvent(dt *tools.DataType, user string, search string) error {
|
||||||
|
if peers, err := ps.searchPeer(fmt.Sprintf("%v", peer.PARTNER.EnumIndex())); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
b, err := json.Marshal(map[string]string{"search": search})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, p := range peers {
|
||||||
|
ad, err := pp.AddrInfoFromString(p.StreamAddress)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ps.write(tools.PB_SEARCH, p.GetID(), ad, dt, user, b, ProtocolSearchResource, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *StreamService) ToPartnerPublishEvent(
|
||||||
|
ctx context.Context, action tools.PubSubAction, dt *tools.DataType, user string, payload []byte) error {
|
||||||
|
if *dt == tools.PEER {
|
||||||
|
var p peer.Peer
|
||||||
|
if err := json.Unmarshal(payload, &p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ad, err := pp.AddrInfoFromString(p.StreamAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ps.mu.Lock()
|
||||||
|
defer ps.mu.Unlock()
|
||||||
|
if p.Relation == peer.PARTNER {
|
||||||
|
if ps.Streams[ProtocolHeartbeatPartner] == nil {
|
||||||
|
ps.Streams[ProtocolHeartbeatPartner] = map[pp.ID]*common.Stream{}
|
||||||
|
}
|
||||||
|
ps.ConnectToPartner(ad.ID, ad)
|
||||||
|
} else if ps.Streams[ProtocolHeartbeatPartner] != nil && ps.Streams[ProtocolHeartbeatPartner][ad.ID] != nil {
|
||||||
|
for _, pids := range ps.Streams {
|
||||||
|
if pids[ad.ID] != nil {
|
||||||
|
delete(pids, ad.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if peers, err := ps.searchPeer(fmt.Sprintf("%v", peer.PARTNER.EnumIndex())); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
for _, p := range peers {
|
||||||
|
for _, protocol := range protocols {
|
||||||
|
ad, err := pp.AddrInfoFromString(p.StreamAddress)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ps.write(action, p.GetID(), ad, dt, user, payload, protocol, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StreamService) write(
|
||||||
|
action tools.PubSubAction,
|
||||||
|
did string,
|
||||||
|
peerID *pp.AddrInfo,
|
||||||
|
dt *tools.DataType,
|
||||||
|
user string,
|
||||||
|
payload []byte,
|
||||||
|
proto protocol.ID,
|
||||||
|
isAPartner bool) error {
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
|
||||||
|
name := action.String() + "#" + peerID.ID.String()
|
||||||
|
if dt != nil {
|
||||||
|
name = action.String() + "." + (*dt).String() + "#" + peerID.ID.String()
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
if s.Streams[proto] == nil {
|
||||||
|
s.Streams[proto] = map[pp.ID]*common.Stream{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Streams[proto][peerID.ID] == nil {
|
||||||
|
// should create a very temp stream
|
||||||
|
ctxTTL, err := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
if err == nil {
|
||||||
|
if isAPartner {
|
||||||
|
ctxTTL = context.Background()
|
||||||
|
}
|
||||||
|
if s.Host.Network().Connectedness(peerID.ID) != network.Connected {
|
||||||
|
_ = s.Host.Connect(ctxTTL, *peerID)
|
||||||
|
str, err := s.Host.NewStream(ctxTTL, peerID.ID, ProtocolHeartbeatPartner)
|
||||||
|
if err == nil {
|
||||||
|
s.Streams[ProtocolHeartbeatPartner][peerID.ID] = &common.Stream{
|
||||||
|
DID: did,
|
||||||
|
Stream: str,
|
||||||
|
Expiry: time.Now().UTC().Add(5 * time.Second),
|
||||||
|
}
|
||||||
|
str2, err := s.Host.NewStream(ctxTTL, peerID.ID, proto)
|
||||||
|
if err == nil {
|
||||||
|
s.Streams[proto][peerID.ID] = &common.Stream{
|
||||||
|
DID: did,
|
||||||
|
Stream: str2,
|
||||||
|
Expiry: time.Now().UTC().Add(5 * time.Second),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("no stream available for protocol " + fmt.Sprintf("%v", proto) + " from PID " + peerID.ID.String())
|
||||||
|
}
|
||||||
|
stream := s.Streams[proto][peerID.ID]
|
||||||
|
|
||||||
|
enc := json.NewEncoder(stream.Stream)
|
||||||
|
|
||||||
|
evt := common.NewEvent(name, peerID.ID.String(), dt, user, payload)
|
||||||
|
if err := enc.Encode(evt); err != nil {
|
||||||
|
stream.Stream.Close()
|
||||||
|
logger.Err(err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
231
daemons/node/stream/service.go
Normal file
231
daemons/node/stream/service.go
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
package stream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"oc-discovery/daemons/node/common"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
|
"github.com/libp2p/go-libp2p/core/host"
|
||||||
|
"github.com/libp2p/go-libp2p/core/network"
|
||||||
|
pp "github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
"github.com/libp2p/go-libp2p/core/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ProtocolSearchResource = "/opencloud/resource/search/1.0"
|
||||||
|
const ProtocolCreateResource = "/opencloud/resource/create/1.0"
|
||||||
|
const ProtocolUpdateResource = "/opencloud/resource/update/1.0"
|
||||||
|
const ProtocolDeleteResource = "/opencloud/resource/delete/1.0"
|
||||||
|
|
||||||
|
const ProtocolHeartbeatPartner = "/opencloud/resource/heartbeat/partner/1.0"
|
||||||
|
|
||||||
|
var protocols = []protocol.ID{
|
||||||
|
ProtocolSearchResource,
|
||||||
|
ProtocolCreateResource,
|
||||||
|
ProtocolUpdateResource,
|
||||||
|
ProtocolDeleteResource,
|
||||||
|
}
|
||||||
|
|
||||||
|
type StreamService struct {
|
||||||
|
Key pp.ID
|
||||||
|
Host host.Host
|
||||||
|
Node common.DiscoveryPeer
|
||||||
|
Streams common.ProtocolStream
|
||||||
|
maxNodesConn int
|
||||||
|
mu sync.Mutex
|
||||||
|
// Stream map[protocol.ID]map[pp.ID]*daemons.Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitStream(ctx context.Context, h host.Host, key pp.ID, maxNode int, node common.DiscoveryPeer) (*StreamService, error) {
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
service := &StreamService{
|
||||||
|
Key: key,
|
||||||
|
Node: node,
|
||||||
|
Host: h,
|
||||||
|
Streams: common.ProtocolStream{},
|
||||||
|
maxNodesConn: maxNode,
|
||||||
|
}
|
||||||
|
logger.Info().Msg("handle to partner heartbeat protocol...")
|
||||||
|
service.Host.SetStreamHandler(ProtocolHeartbeatPartner, service.HandlePartnerHeartbeat)
|
||||||
|
logger.Info().Msg("connect to partners...")
|
||||||
|
service.connectToPartners() // we set up a stream
|
||||||
|
go service.StartGC(30 * time.Second)
|
||||||
|
return service, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StreamService) HandlePartnerHeartbeat(stream network.Stream) {
|
||||||
|
pid, hb, err := common.CheckHeartbeat(s.Host, stream, s.maxNodesConn)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
streams := s.Streams[ProtocolHeartbeatPartner]
|
||||||
|
if streams == nil {
|
||||||
|
s.Streams[ProtocolHeartbeatPartner] = map[pp.ID]*common.Stream{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if record already seen update last seen
|
||||||
|
if rec, ok := streams[*pid]; ok {
|
||||||
|
rec.DID = hb.DID
|
||||||
|
rec.Expiry = time.Now().UTC().Add(2 * time.Minute)
|
||||||
|
} else { // if not in stream ?
|
||||||
|
pid := stream.Conn().RemotePeer()
|
||||||
|
ai, err := pp.AddrInfoFromP2pAddr(stream.Conn().RemoteMultiaddr())
|
||||||
|
if err == nil {
|
||||||
|
s.ConnectToPartner(pid, ai)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go s.StartGC(30 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StreamService) connectToPartners() error {
|
||||||
|
peers, err := s.searchPeer(fmt.Sprintf("%v", peer.PARTNER.EnumIndex()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, p := range peers {
|
||||||
|
ad, err := pp.AddrInfoFromString(p.StreamAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pid, err := pp.Decode(p.PeerID)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.ConnectToPartner(pid, ad)
|
||||||
|
// heartbeat your partner.
|
||||||
|
}
|
||||||
|
// TODO if handle... from partner then HeartBeat back
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StreamService) ConnectToPartner(pid pp.ID, ad *pp.AddrInfo) {
|
||||||
|
for _, proto := range protocols {
|
||||||
|
f := func(ss network.Stream) {
|
||||||
|
if s.Streams[proto] == nil {
|
||||||
|
s.Streams[proto] = map[pp.ID]*common.Stream{}
|
||||||
|
}
|
||||||
|
s.Streams[proto][pid] = &common.Stream{
|
||||||
|
Stream: ss,
|
||||||
|
Expiry: time.Now().Add(2 * time.Minute),
|
||||||
|
}
|
||||||
|
go s.readLoop(s.Streams[proto][pid])
|
||||||
|
}
|
||||||
|
s.Streams = common.AddStreamProtocol(nil, s.Streams, s.Host, proto, pid, s.Key, &f)
|
||||||
|
if s.Streams[proto][pid] != nil {
|
||||||
|
go s.readLoop(s.Streams[proto][pid]) // reaaaad...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
common.SendHeartbeat(context.Background(), ProtocolHeartbeatPartner,
|
||||||
|
s.Host, s.Streams, []*pp.AddrInfo{ad}, time.Minute)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StreamService) searchPeer(search string) ([]*peer.Peer, error) {
|
||||||
|
ps := []*peer.Peer{}
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
peers := access.Search(nil, search, false)
|
||||||
|
if len(peers.Data) == 0 {
|
||||||
|
return ps, errors.New("no self available")
|
||||||
|
}
|
||||||
|
for _, p := range peers.Data {
|
||||||
|
ps = append(ps, p.(*peer.Peer))
|
||||||
|
}
|
||||||
|
return ps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ix *StreamService) Close() {
|
||||||
|
for _, s := range ix.Streams {
|
||||||
|
for _, ss := range s {
|
||||||
|
ss.Stream.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StreamService) StartGC(interval time.Duration) {
|
||||||
|
go func() {
|
||||||
|
t := time.NewTicker(interval)
|
||||||
|
defer t.Stop()
|
||||||
|
for range t.C {
|
||||||
|
s.gc()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StreamService) gc() {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
now := time.Now()
|
||||||
|
streams := s.Streams[ProtocolHeartbeatPartner]
|
||||||
|
if streams == nil {
|
||||||
|
s.Streams[ProtocolHeartbeatPartner] = map[pp.ID]*common.Stream{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for pid, rec := range streams {
|
||||||
|
if now.After(rec.Expiry) {
|
||||||
|
for _, sstreams := range s.Streams {
|
||||||
|
if sstreams[pid] != nil {
|
||||||
|
sstreams[pid].Stream.Close()
|
||||||
|
delete(sstreams, pid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *StreamService) readLoop(s *common.Stream) {
|
||||||
|
dec := json.NewDecoder(s.Stream)
|
||||||
|
for {
|
||||||
|
var evt common.Event
|
||||||
|
if err := dec.Decode(&evt); err != nil {
|
||||||
|
s.Stream.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ps.handleEvent(evt.Type, &evt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (abs *StreamService) FilterPeer(peerID string, search string) *dbs.Filters {
|
||||||
|
id, err := oclib.GetMySelf()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
filter := map[string][]dbs.Filter{
|
||||||
|
"creator_id": {{Operator: dbs.EQUAL.String(), Value: id}}, // is my resource...
|
||||||
|
"": {{Operator: dbs.OR.String(), Value: &dbs.Filters{
|
||||||
|
Or: map[string][]dbs.Filter{
|
||||||
|
"abstractobject.access_mode": {{Operator: dbs.EQUAL.String(), Value: 1}}, // if public
|
||||||
|
"abstractinstanciatedresource.instances": {{Operator: dbs.ELEMMATCH.String(), Value: &dbs.Filters{ // or got a partners instances
|
||||||
|
And: map[string][]dbs.Filter{
|
||||||
|
"resourceinstance.partnerships": {{Operator: dbs.ELEMMATCH.String(), Value: &dbs.Filters{
|
||||||
|
And: map[string][]dbs.Filter{
|
||||||
|
"resourcepartnership.peer_groups." + peerID: {{Operator: dbs.EXISTS.String(), Value: true}},
|
||||||
|
},
|
||||||
|
}}},
|
||||||
|
},
|
||||||
|
}}},
|
||||||
|
},
|
||||||
|
}}},
|
||||||
|
}
|
||||||
|
if search != "" {
|
||||||
|
filter[" "] = []dbs.Filter{{Operator: dbs.OR.String(), Value: &dbs.Filters{
|
||||||
|
Or: map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided
|
||||||
|
"abstractintanciatedresource.abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}},
|
||||||
|
"abstractintanciatedresource.abstractresource.type": {{Operator: dbs.LIKE.String(), Value: search}},
|
||||||
|
"abstractintanciatedresource.abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}},
|
||||||
|
"abstractintanciatedresource.abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}},
|
||||||
|
"abstractintanciatedresource.abstractresource.owners.name": {{Operator: dbs.LIKE.String(), Value: search}},
|
||||||
|
"abstractintanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: search}},
|
||||||
|
},
|
||||||
|
}}}
|
||||||
|
}
|
||||||
|
return &dbs.Filters{
|
||||||
|
And: filter,
|
||||||
|
}
|
||||||
|
}
|
||||||
125
go.mod
125
go.mod
@@ -1,11 +1,9 @@
|
|||||||
module oc-discovery
|
module oc-discovery
|
||||||
|
|
||||||
go 1.23.0
|
go 1.24.6
|
||||||
|
|
||||||
toolchain go1.24.0
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250704084459-443546027b27
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260129122033-186ba3e689c7
|
||||||
github.com/beego/beego v1.12.13
|
github.com/beego/beego v1.12.13
|
||||||
github.com/beego/beego/v2 v2.3.8
|
github.com/beego/beego/v2 v2.3.8
|
||||||
github.com/go-redis/redis v6.15.9+incompatible
|
github.com/go-redis/redis v6.15.9+incompatible
|
||||||
@@ -13,23 +11,122 @@ require (
|
|||||||
github.com/tidwall/gjson v1.17.3
|
github.com/tidwall/gjson v1.17.3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/benbjohnson/clock v1.3.5 // indirect
|
||||||
|
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
||||||
|
github.com/dunglas/httpsfv v1.1.0 // indirect
|
||||||
|
github.com/filecoin-project/go-clock v0.1.0 // indirect
|
||||||
|
github.com/flynn/noise v1.1.0 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/google/gopacket v1.1.19 // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
|
github.com/huin/goupnp v1.3.0 // indirect
|
||||||
|
github.com/ipfs/boxo v0.35.2 // indirect
|
||||||
|
github.com/ipfs/go-cid v0.6.0 // indirect
|
||||||
|
github.com/ipfs/go-datastore v0.9.0 // indirect
|
||||||
|
github.com/ipfs/go-log/v2 v2.9.1 // indirect
|
||||||
|
github.com/ipld/go-ipld-prime v0.21.0 // indirect
|
||||||
|
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||||
|
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
|
github.com/koron/go-ssdp v0.0.6 // indirect
|
||||||
|
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||||
|
github.com/libp2p/go-cidranger v1.1.0 // indirect
|
||||||
|
github.com/libp2p/go-flow-metrics v0.3.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p v0.47.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-kbucket v0.8.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-record v0.3.1 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
|
||||||
|
github.com/libp2p/go-msgio v0.3.0 // indirect
|
||||||
|
github.com/libp2p/go-netroute v0.4.0 // indirect
|
||||||
|
github.com/libp2p/go-reuseport v0.4.0 // indirect
|
||||||
|
github.com/libp2p/go-yamux/v5 v5.0.1 // indirect
|
||||||
|
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
|
||||||
|
github.com/miekg/dns v1.1.68 // indirect
|
||||||
|
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
|
||||||
|
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
|
||||||
|
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||||
|
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||||
|
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||||
|
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||||
|
github.com/multiformats/go-multiaddr v0.16.1 // indirect
|
||||||
|
github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
|
||||||
|
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
|
||||||
|
github.com/multiformats/go-multibase v0.2.0 // indirect
|
||||||
|
github.com/multiformats/go-multicodec v0.10.0 // indirect
|
||||||
|
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||||
|
github.com/multiformats/go-multistream v0.6.1 // indirect
|
||||||
|
github.com/multiformats/go-varint v0.1.0 // indirect
|
||||||
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||||
|
github.com/pion/datachannel v1.5.10 // indirect
|
||||||
|
github.com/pion/dtls/v2 v2.2.12 // indirect
|
||||||
|
github.com/pion/dtls/v3 v3.0.6 // indirect
|
||||||
|
github.com/pion/ice/v4 v4.0.10 // indirect
|
||||||
|
github.com/pion/interceptor v0.1.40 // indirect
|
||||||
|
github.com/pion/logging v0.2.3 // indirect
|
||||||
|
github.com/pion/mdns/v2 v2.0.7 // indirect
|
||||||
|
github.com/pion/randutil v0.1.0 // indirect
|
||||||
|
github.com/pion/rtcp v1.2.15 // indirect
|
||||||
|
github.com/pion/rtp v1.8.19 // indirect
|
||||||
|
github.com/pion/sctp v1.8.39 // indirect
|
||||||
|
github.com/pion/sdp/v3 v3.0.13 // indirect
|
||||||
|
github.com/pion/srtp/v3 v3.0.6 // indirect
|
||||||
|
github.com/pion/stun v0.6.1 // indirect
|
||||||
|
github.com/pion/stun/v3 v3.0.0 // indirect
|
||||||
|
github.com/pion/transport/v2 v2.2.10 // indirect
|
||||||
|
github.com/pion/transport/v3 v3.0.7 // indirect
|
||||||
|
github.com/pion/turn/v4 v4.0.2 // indirect
|
||||||
|
github.com/pion/webrtc/v4 v4.1.2 // indirect
|
||||||
|
github.com/polydawn/refmt v0.89.0 // indirect
|
||||||
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
|
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||||
|
github.com/quic-go/webtransport-go v0.10.0 // indirect
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
|
||||||
|
github.com/wlynxg/anet v0.0.5 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.39.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.39.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.39.0 // indirect
|
||||||
|
go.uber.org/dig v1.19.0 // indirect
|
||||||
|
go.uber.org/fx v1.24.0 // indirect
|
||||||
|
go.uber.org/mock v0.5.2 // indirect
|
||||||
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
go.uber.org/zap v1.27.1 // indirect
|
||||||
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
|
||||||
|
golang.org/x/mod v0.32.0 // indirect
|
||||||
|
golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 // indirect
|
||||||
|
golang.org/x/time v0.12.0 // indirect
|
||||||
|
golang.org/x/tools v0.41.0 // indirect
|
||||||
|
gonum.org/v1/gonum v0.17.0 // indirect
|
||||||
|
lukechampine.com/blake3 v1.4.1 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/biter777/countries v1.7.5 // indirect
|
github.com/biter777/countries v1.7.5 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||||
github.com/golang/snappy v1.0.0 // indirect
|
github.com/golang/snappy v1.0.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
|
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
|
||||||
github.com/goraz/onion v0.1.3 // indirect
|
github.com/goraz/onion v0.1.3 // indirect
|
||||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-kad-dht v0.37.1
|
||||||
|
github.com/libp2p/go-libp2p-pubsub v0.15.0
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -38,9 +135,9 @@ require (
|
|||||||
github.com/nats-io/nats.go v1.43.0 // indirect
|
github.com/nats-io/nats.go v1.43.0 // indirect
|
||||||
github.com/nats-io/nkeys v0.4.11 // indirect
|
github.com/nats-io/nkeys v0.4.11 // indirect
|
||||||
github.com/nats-io/nuid v1.0.1 // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
github.com/prometheus/client_golang v1.22.0 // indirect
|
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.65.0 // indirect
|
github.com/prometheus/common v0.66.1 // indirect
|
||||||
github.com/prometheus/procfs v0.17.0 // indirect
|
github.com/prometheus/procfs v0.17.0 // indirect
|
||||||
github.com/robfig/cron v1.2.0 // indirect
|
github.com/robfig/cron v1.2.0 // indirect
|
||||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
@@ -54,11 +151,11 @@ require (
|
|||||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.17.4 // indirect
|
go.mongodb.org/mongo-driver v1.17.4 // indirect
|
||||||
golang.org/x/crypto v0.39.0 // indirect
|
golang.org/x/crypto v0.47.0 // indirect
|
||||||
golang.org/x/net v0.41.0 // indirect
|
golang.org/x/net v0.49.0 // indirect
|
||||||
golang.org/x/sync v0.15.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.33.0 // indirect
|
golang.org/x/sys v0.40.0 // indirect
|
||||||
golang.org/x/text v0.26.0 // indirect
|
golang.org/x/text v0.33.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
310
go.sum
310
go.sum
@@ -6,6 +6,28 @@ cloud.o-forge.io/core/oc-lib v0.0.0-20250604083300-387785b40cb0 h1:iEm/Rf9I0OSCc
|
|||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250604083300-387785b40cb0/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250604083300-387785b40cb0/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250704084459-443546027b27 h1:iogk6pV3gybzQDBXMI6Qd/jvSA1h+3oRE+vLl1MRjew=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250704084459-443546027b27 h1:iogk6pV3gybzQDBXMI6Qd/jvSA1h+3oRE+vLl1MRjew=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250704084459-443546027b27/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250704084459-443546027b27/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260126120055-055e6c70cdd7 h1:LAK86efqe2HNV1Tkym1TpvzL1Xsj3F0ClsK/snfejD0=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260126120055-055e6c70cdd7/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260127143728-3c052bf16572 h1:jrUHgs4DqNWLnLcb5nd4lrJim77+aGkJFACUfMogiu8=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260127143728-3c052bf16572/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128140632-d098d253d8e2 h1:B3TO9nXdpGuPXL4X3QFrRMJ1C4zXCQlLh4XR9aSZoKg=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128140632-d098d253d8e2/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128140807-1c9d7b63c0b3 h1:zAT4ZulAaX+l28QdCMvuXh5XQxn+fU8x6YNJ1zmA7+Q=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128140807-1c9d7b63c0b3/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128152242-743f4a6ff742 h1:vGlUqBhj3G5hvskL1NzfecKCUMH8bL3xx7JkLpv/04M=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128152242-743f4a6ff742/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128152919-7911cf29def8 h1:HT1+PP04wu5DcQ5PA3LtSJ5PcWEyL4FlZB62+v9eLWo=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128152919-7911cf29def8/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128154447-d26789d64e33 h1:WdmHeRtEWV3RsXaEe4HnItGNYLFvMNFggfq9/KtPho0=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128154447-d26789d64e33/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128160440-c0d89ea9e1e8 h1:h7VHJktaTT8TxO4ld3Xjw3LzMsivr3m7mzbNxb44zes=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128160440-c0d89ea9e1e8/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128162702-97cf629e27ec h1:/uvrtEt7A5rwqFPHH8yjujlC33HMjQHhWDIK6I08DrA=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260128162702-97cf629e27ec/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260129121215-c1519f6b26b8 h1:gvUbTwHnYM0Ezzvoa9ylTt+o1lAhS0U79OogbsZ+Pl8=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260129121215-c1519f6b26b8/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260129122033-186ba3e689c7 h1:NRFGRqN+j5g3DrtXMYN5T5XSYICG+OU2DisjBdID3j8=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260129122033-186ba3e689c7/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
@@ -22,6 +44,8 @@ github.com/beego/beego/v2 v2.3.8 h1:wplhB1pF4TxR+2SS4PUej8eDoH4xGfxuHfS7wAk9VBc=
|
|||||||
github.com/beego/beego/v2 v2.3.8/go.mod h1:8vl9+RrXqvodrl9C8yivX1e6le6deCK6RWeq8R7gTTg=
|
github.com/beego/beego/v2 v2.3.8/go.mod h1:8vl9+RrXqvodrl9C8yivX1e6le6deCK6RWeq8R7gTTg=
|
||||||
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
|
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
|
||||||
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
|
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
|
||||||
|
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
||||||
|
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
@@ -40,27 +64,45 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
|
|||||||
github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
|
github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
|
||||||
github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
|
github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
|
||||||
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
|
||||||
|
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
||||||
|
github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54=
|
||||||
|
github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg=
|
||||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
|
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
|
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||||
github.com/etcd-io/etcd v3.3.17+incompatible/go.mod h1:cdZ77EstHBwVtD6iTgzgvogwcjo9m4iOqoijouPJ4bs=
|
github.com/etcd-io/etcd v3.3.17+incompatible/go.mod h1:cdZ77EstHBwVtD6iTgzgvogwcjo9m4iOqoijouPJ4bs=
|
||||||
|
github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU=
|
||||||
|
github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs=
|
||||||
|
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
|
||||||
|
github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||||
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
@@ -78,8 +120,11 @@ github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGK
|
|||||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@@ -101,31 +146,62 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/goraz/onion v0.1.3 h1:KhyvbDA2b70gcz/d5izfwTiOH8SmrvV43AsVzpng3n0=
|
github.com/goraz/onion v0.1.3 h1:KhyvbDA2b70gcz/d5izfwTiOH8SmrvV43AsVzpng3n0=
|
||||||
github.com/goraz/onion v0.1.3/go.mod h1:XEmz1XoBz+wxTgWB8NwuvRm4RAu3vKxvrmYtzK+XCuQ=
|
github.com/goraz/onion v0.1.3/go.mod h1:XEmz1XoBz+wxTgWB8NwuvRm4RAu3vKxvrmYtzK+XCuQ=
|
||||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||||
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
||||||
|
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
||||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
|
github.com/ipfs/boxo v0.35.2 h1:0QZJJh6qrak28abENOi5OA8NjBnZM4p52SxeuIDqNf8=
|
||||||
|
github.com/ipfs/boxo v0.35.2/go.mod h1:bZn02OFWwJtY8dDW9XLHaki59EC5o+TGDECXEbe1w8U=
|
||||||
|
github.com/ipfs/go-cid v0.6.0 h1:DlOReBV1xhHBhhfy/gBNNTSyfOM6rLiIx9J7A4DGf30=
|
||||||
|
github.com/ipfs/go-cid v0.6.0/go.mod h1:NC4kS1LZjzfhK40UGmpXv5/qD2kcMzACYJNntCUiDhQ=
|
||||||
|
github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w=
|
||||||
|
github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
|
||||||
|
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
|
||||||
|
github.com/ipfs/go-log/v2 v2.9.1 h1:3JXwHWU31dsCpvQ+7asz6/QsFJHqFr4gLgQ0FWteujk=
|
||||||
|
github.com/ipfs/go-log/v2 v2.9.1/go.mod h1:evFx7sBiohUN3AG12mXlZBw5hacBQld3ZPHrowlJYoo=
|
||||||
|
github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
|
||||||
|
github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
|
||||||
|
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||||
|
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||||
|
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
|
||||||
|
github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU=
|
||||||
|
github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
@@ -138,7 +214,37 @@ github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDu
|
|||||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
|
||||||
|
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
|
||||||
|
github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
|
||||||
|
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
|
||||||
|
github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784=
|
||||||
|
github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo=
|
||||||
|
github.com/libp2p/go-libp2p v0.47.0 h1:qQpBjSCWNQFF0hjBbKirMXE9RHLtSuzTDkTfr1rw0yc=
|
||||||
|
github.com/libp2p/go-libp2p v0.47.0/go.mod h1:s8HPh7mMV933OtXzONaGFseCg/BE//m1V34p3x4EUOY=
|
||||||
|
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
|
||||||
|
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
|
||||||
|
github.com/libp2p/go-libp2p-kad-dht v0.37.1 h1:jtX8bQIXVCs6/allskNB4m5n95Xvwav7wHAhopGZfS0=
|
||||||
|
github.com/libp2p/go-libp2p-kad-dht v0.37.1/go.mod h1:Uwokdh232k9Y1uMy2yJOK5zb7hpMHn4P8uWS4s9i05Q=
|
||||||
|
github.com/libp2p/go-libp2p-kbucket v0.8.0 h1:QAK7RzKJpYe+EuSEATAaaHYMYLkPDGC18m9jxPLnU8s=
|
||||||
|
github.com/libp2p/go-libp2p-kbucket v0.8.0/go.mod h1:JMlxqcEyKwO6ox716eyC0hmiduSWZZl6JY93mGaaqc4=
|
||||||
|
github.com/libp2p/go-libp2p-pubsub v0.15.0 h1:cG7Cng2BT82WttmPFMi50gDNV+58K626m/wR00vGL1o=
|
||||||
|
github.com/libp2p/go-libp2p-pubsub v0.15.0/go.mod h1:lr4oE8bFgQaifRcoc2uWhWWiK6tPdOEKpUuR408GFN4=
|
||||||
|
github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
|
||||||
|
github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
|
||||||
|
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
|
||||||
|
github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98=
|
||||||
|
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
|
||||||
|
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
|
||||||
|
github.com/libp2p/go-netroute v0.4.0 h1:sZZx9hyANYUx9PZyqcgE/E1GUG3iEtTZHUEvdtXT7/Q=
|
||||||
|
github.com/libp2p/go-netroute v0.4.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA=
|
||||||
|
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
|
||||||
|
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
|
||||||
|
github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg=
|
||||||
|
github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU=
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
|
||||||
|
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
@@ -149,6 +255,17 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
|||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||||
|
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||||
|
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
|
||||||
|
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
|
||||||
|
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU=
|
||||||
|
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc=
|
||||||
|
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
|
||||||
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||||
|
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||||
|
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||||
|
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
@@ -158,6 +275,31 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
|||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||||
|
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
|
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||||
|
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
|
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
|
||||||
|
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
|
||||||
|
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
||||||
|
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
||||||
|
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
|
||||||
|
github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw=
|
||||||
|
github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
|
||||||
|
github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M=
|
||||||
|
github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc=
|
||||||
|
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
|
||||||
|
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
|
||||||
|
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
||||||
|
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
||||||
|
github.com/multiformats/go-multicodec v0.10.0 h1:UpP223cig/Cx8J76jWt91njpK3GTAO1w02sdcjZDSuc=
|
||||||
|
github.com/multiformats/go-multicodec v0.10.0/go.mod h1:wg88pM+s2kZJEQfRCKBNU+g32F5aWBEjyFHXvZLTcLI=
|
||||||
|
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||||
|
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
|
||||||
|
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||||
|
github.com/multiformats/go-multistream v0.6.1 h1:4aoX5v6T+yWmc2raBHsTvzmFhOI8WVOer28DeBBEYdQ=
|
||||||
|
github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw=
|
||||||
|
github.com/multiformats/go-varint v0.1.0 h1:i2wqFp4sdl3IcIxfAonHQV9qU5OsZ4Ts9IOoETFs5dI=
|
||||||
|
github.com/multiformats/go-varint v0.1.0/go.mod h1:5KVAVXegtfmNQQm/lCY+ATvDzvJJhSkUlGQV9wgObdI=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
@@ -178,14 +320,60 @@ github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
|||||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||||
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||||
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||||
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
|
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
|
||||||
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||||
|
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
|
||||||
|
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
|
||||||
|
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
||||||
|
github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
|
||||||
|
github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
|
||||||
|
github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E=
|
||||||
|
github.com/pion/dtls/v3 v3.0.6/go.mod h1:iJxNQ3Uhn1NZWOMWlLxEEHAN5yX7GyPvvKw04v9bzYU=
|
||||||
|
github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4=
|
||||||
|
github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
|
||||||
|
github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4=
|
||||||
|
github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic=
|
||||||
|
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||||
|
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
|
||||||
|
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
|
||||||
|
github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
|
||||||
|
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
|
||||||
|
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||||
|
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||||
|
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
||||||
|
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
||||||
|
github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c=
|
||||||
|
github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
|
||||||
|
github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE=
|
||||||
|
github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
|
||||||
|
github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4=
|
||||||
|
github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
||||||
|
github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4=
|
||||||
|
github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY=
|
||||||
|
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
|
||||||
|
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
|
||||||
|
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
|
||||||
|
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
|
||||||
|
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
|
||||||
|
github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
|
||||||
|
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
|
||||||
|
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
|
||||||
|
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
|
||||||
|
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
|
||||||
|
github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps=
|
||||||
|
github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs=
|
||||||
|
github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54=
|
||||||
|
github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
|
||||||
|
github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
@@ -193,6 +381,8 @@ github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjs
|
|||||||
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||||
|
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||||
|
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
@@ -208,6 +398,8 @@ github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQP
|
|||||||
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||||
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||||
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||||
|
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||||
|
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
@@ -217,6 +409,12 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM
|
|||||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||||
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
||||||
|
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||||
|
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||||
|
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||||
|
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||||
|
github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI=
|
||||||
|
github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow=
|
||||||
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
||||||
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
@@ -229,9 +427,11 @@ github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
|||||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||||
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
||||||
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 h1:v9ezJDHA1XGxViAUSIoO/Id7Fl63u6d0YmsAm+/p2hs=
|
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 h1:v9ezJDHA1XGxViAUSIoO/Id7Fl63u6d0YmsAm+/p2hs=
|
||||||
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02/go.mod h1:RF16/A3L0xSa0oSERcnhd8Pu3IXSDZSK2gmGIMsttFE=
|
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02/go.mod h1:RF16/A3L0xSa0oSERcnhd8Pu3IXSDZSK2gmGIMsttFE=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||||
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
|
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
|
||||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||||
@@ -244,12 +444,20 @@ github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl
|
|||||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
||||||
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||||
@@ -261,7 +469,14 @@ github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso
|
|||||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||||
|
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
|
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
|
||||||
github.com/wendal/errors v0.0.0-20181209125328-7f31f4b264ec/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
github.com/wendal/errors v0.0.0-20181209125328-7f31f4b264ec/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||||
|
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
|
||||||
|
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
|
||||||
|
github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||||
|
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||||
|
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||||
@@ -270,6 +485,8 @@ github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6
|
|||||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||||
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
|
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
|
||||||
go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8=
|
go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8=
|
||||||
@@ -278,44 +495,98 @@ go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeH
|
|||||||
go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||||
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
|
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
|
||||||
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
|
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
|
||||||
|
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
|
||||||
|
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
|
||||||
|
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
|
||||||
|
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
|
||||||
|
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
|
||||||
|
go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4=
|
||||||
|
go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
|
||||||
|
go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg=
|
||||||
|
go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo=
|
||||||
|
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||||
|
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||||
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||||
|
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
|
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||||
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||||
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||||
|
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||||
|
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||||
|
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
|
||||||
|
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||||
|
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||||
|
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||||
|
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -326,37 +597,71 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||||
|
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 h1:O1cMQHRfwNpDfDJerqRoE2oD+AFlyid87D40L/OkkJo=
|
||||||
|
golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
|
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||||
|
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||||
|
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||||
|
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||||
|
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||||
|
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||||
|
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -367,6 +672,8 @@ google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6h
|
|||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -385,5 +692,8 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
||||||
|
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
|
||||||
|
|||||||
52
main.go
52
main.go
@@ -1,11 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"oc-discovery/models"
|
"context"
|
||||||
_ "oc-discovery/routers"
|
"log"
|
||||||
|
"oc-discovery/conf"
|
||||||
|
"oc-discovery/daemons/node"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
oclib "cloud.o-forge.io/core/oc-lib"
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
"cloud.o-forge.io/core/oc-lib/logs"
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
"github.com/beego/beego/v2/server/web/filter/cors"
|
"github.com/beego/beego/v2/server/web/filter/cors"
|
||||||
)
|
)
|
||||||
@@ -19,20 +24,15 @@ func main() {
|
|||||||
|
|
||||||
o := oclib.GetConfLoader()
|
o := oclib.GetConfLoader()
|
||||||
|
|
||||||
models.GetConfig().Port = o.GetIntDefault("port", 8080)
|
conf.GetConfig().Name = o.GetStringDefault("NAME", "opencloud-demo")
|
||||||
models.GetConfig().LokiUrl = o.GetStringDefault("lokiurl", "")
|
conf.GetConfig().Hostname = o.GetStringDefault("HOSTNAME", "localhost")
|
||||||
models.GetConfig().RedisUrl = o.GetStringDefault("redisurl", "localhost:6379")
|
conf.GetConfig().PSKPath = o.GetStringDefault("PSK_PATH", "./psk/psk.key")
|
||||||
models.GetConfig().RedisPassword = o.GetStringDefault("redispassword", "")
|
conf.GetConfig().NodeEndpointPort = o.GetInt64Default("NODE_ENDPOINT_PORT", 4001)
|
||||||
models.GetConfig().ZincUrl = o.GetStringDefault("zincurl", "http://localhost:4080")
|
conf.GetConfig().PublicKeyPath = o.GetStringDefault("PUBLIC_KEY_PATH", "./pem/public.pem")
|
||||||
models.GetConfig().ZincLogin = o.GetStringDefault("zinclogin", "admin")
|
conf.GetConfig().PrivateKeyPath = o.GetStringDefault("PRIVATE_KEY_PATH", "./pem/private.pem")
|
||||||
models.GetConfig().ZincPassword = o.GetStringDefault("zincpassword", "admin")
|
conf.GetConfig().IndexerAddresses = o.GetStringDefault("INDEXER_ADDRESSES", "")
|
||||||
models.GetConfig().IdentityFile = o.GetStringDefault("identityfile", "./identity.json")
|
|
||||||
models.GetConfig().Defaultpeers = o.GetStringDefault("defaultpeers", "./peers.json")
|
|
||||||
|
|
||||||
// set oc-lib logger
|
conf.GetConfig().NodeMode = o.GetStringDefault("NODE_MODE", "node")
|
||||||
if models.GetConfig().LokiUrl != "" {
|
|
||||||
logs.CreateLogger(appname)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal beego init
|
// Normal beego init
|
||||||
beego.BConfig.AppName = appname
|
beego.BConfig.AppName = appname
|
||||||
@@ -46,5 +46,23 @@ func main() {
|
|||||||
ExposeHeaders: []string{"Content-Length", "Content-Type"},
|
ExposeHeaders: []string{"Content-Length", "Content-Type"},
|
||||||
AllowCredentials: true,
|
AllowCredentials: true,
|
||||||
}))
|
}))
|
||||||
beego.Run()
|
|
||||||
|
ctx, stop := signal.NotifyContext(
|
||||||
|
context.Background(),
|
||||||
|
os.Interrupt,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
isNode := strings.Contains(conf.GetConfig().NodeMode, "node")
|
||||||
|
isIndexer := strings.Contains(conf.GetConfig().NodeMode, "indexer")
|
||||||
|
|
||||||
|
if n, err := node.InitNode(isNode, isIndexer); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
<-ctx.Done() // 👈 the only blocking point
|
||||||
|
log.Println("shutting down")
|
||||||
|
n.Close()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import "sync"
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Port int
|
|
||||||
LokiUrl string
|
|
||||||
ZincUrl string
|
|
||||||
ZincLogin string
|
|
||||||
ZincPassword string
|
|
||||||
RedisUrl string
|
|
||||||
RedisPassword string
|
|
||||||
IdentityFile string
|
|
||||||
Defaultpeers string
|
|
||||||
}
|
|
||||||
|
|
||||||
var instance *Config
|
|
||||||
var once sync.Once
|
|
||||||
|
|
||||||
func GetConfig() *Config {
|
|
||||||
once.Do(func() {
|
|
||||||
instance = &Config{}
|
|
||||||
})
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
56
models/event.go
Normal file
56
models/event.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Event struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
From string `json:"from"` // peerID
|
||||||
|
|
||||||
|
User string
|
||||||
|
|
||||||
|
DataType int64 `json:"datatype"`
|
||||||
|
Timestamp int64 `json:"ts"`
|
||||||
|
Payload []byte `json:"payload"`
|
||||||
|
Signature []byte `json:"sig"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEvent(name string, from string, dt *tools.DataType, user string, payload []byte, priv crypto.PrivKey) *Event {
|
||||||
|
evt := &Event{
|
||||||
|
Type: name,
|
||||||
|
From: from,
|
||||||
|
User: user,
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
if dt != nil {
|
||||||
|
evt.DataType = int64(dt.EnumIndex())
|
||||||
|
} else {
|
||||||
|
evt.DataType = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := json.Marshal(evt)
|
||||||
|
sig, _ := priv.Sign(body)
|
||||||
|
evt.Signature = sig
|
||||||
|
return evt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Event) RawEvent() *Event {
|
||||||
|
return &Event{
|
||||||
|
Type: e.Type,
|
||||||
|
From: e.From,
|
||||||
|
User: e.User,
|
||||||
|
DataType: e.DataType,
|
||||||
|
Timestamp: e.Timestamp,
|
||||||
|
Payload: e.Payload,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Event) ToRawByte() ([]byte, error) {
|
||||||
|
return json.Marshal(e.RawEvent())
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/beego/beego/logs"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Me Identity
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
content, err := os.ReadFile("./identity.json")
|
|
||||||
if err != nil {
|
|
||||||
logs.Error("Error when opening file: ", err)
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(content, &Me)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error("Error during Unmarshal(): ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Identity struct {
|
|
||||||
Id string `json:"id,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
PrivateKey string `json:"private_key,omitempty"`
|
|
||||||
PublicAttributes Peer `json:"public_attributes,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetIdentity() (u *Identity) {
|
|
||||||
return &Me
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateIdentity(uu *Identity) error {
|
|
||||||
Me = *uu
|
|
||||||
jsonBytes, err := json.Marshal(uu)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
os.WriteFile("./identity.json", jsonBytes, 0600)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/beego/beego/logs"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Peers []Peer
|
|
||||||
Store Storage
|
|
||||||
)
|
|
||||||
|
|
||||||
type Peer struct {
|
|
||||||
PeerId string `json:"peer_id,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
EntityName string `json:"entity_name,omitempty"`
|
|
||||||
EntityType string `json:"entity_type,omitempty"`
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
Website string `json:"website,omitempty"`
|
|
||||||
Address string `json:"address,omitempty"`
|
|
||||||
Postcode string `json:"postcode,omitempty"`
|
|
||||||
City string `json:"city,omitempty"`
|
|
||||||
Country string `json:"country,omitempty"`
|
|
||||||
Phone string `json:"phone,omitempty"`
|
|
||||||
Email string `json:"email,omitempty"`
|
|
||||||
Activity string `json:"activity,omitempty"`
|
|
||||||
Keywords []string `json:"keywords,omitempty"`
|
|
||||||
ApiUrl string `json:"api_url,omitempty"`
|
|
||||||
PublicKey string `json:"public_key,omitempty"`
|
|
||||||
// internal use
|
|
||||||
Score int64 `json:"score,omitempty"`
|
|
||||||
LastSeenOnline time.Time `json:"last_seen_online,omitempty"`
|
|
||||||
ApiVersion string `json:"api_version,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
c := GetConfig()
|
|
||||||
Store = Storage{c.ZincUrl, c.ZincLogin, c.ZincPassword, c.RedisUrl, c.RedisPassword}
|
|
||||||
Store = Storage{"http://localhost:4080", "admin", "admin", "localhost:6379", ""}
|
|
||||||
//p := Peer{uuid.New().String(), 0, []string{"car", "highway", "images", "video"}, time.Now(), "1", "asf", ""}
|
|
||||||
// pa := []Peer{p}
|
|
||||||
// byteArray, err := json.Marshal(pa)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Fatal(err)
|
|
||||||
// }
|
|
||||||
// ioutil.WriteFile("./peers.json", byteArray, 0644)
|
|
||||||
content, err := ioutil.ReadFile("./peers.json")
|
|
||||||
if err != nil {
|
|
||||||
logs.Error("Error when opening file: ", err)
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(content, &Peers)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error("Error during Unmarshal(): ", err)
|
|
||||||
}
|
|
||||||
Store.ImportData(LoadPeersJson("./peers.json"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddPeers(peers []Peer) (status string) {
|
|
||||||
err := Store.ImportData(peers)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error("Error during Unmarshal(): ", err)
|
|
||||||
return "error"
|
|
||||||
}
|
|
||||||
return "ok"
|
|
||||||
}
|
|
||||||
|
|
||||||
func FindPeers(query string) (peers []Peer, err error) {
|
|
||||||
result, err := Store.FindPeers(query)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPeer(uid string) (*Peer, error) {
|
|
||||||
return Store.GetPeer(uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Delete(PeerId string) error {
|
|
||||||
err := Store.DeletePeer(PeerId)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/beego/beego/logs"
|
|
||||||
"github.com/go-redis/redis"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Storage struct {
|
|
||||||
ZincUrl string
|
|
||||||
ZincLogin string
|
|
||||||
ZincPassword string
|
|
||||||
RedisUrl string
|
|
||||||
RedisPassword string
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadPeersJson(filename string) []Peer {
|
|
||||||
var peers []Peer
|
|
||||||
content, err := os.ReadFile("./peers.json")
|
|
||||||
if err != nil {
|
|
||||||
logs.Error("Error when opening file: ", err)
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(content, &peers)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error("Error during Unmarshal(): ", err)
|
|
||||||
}
|
|
||||||
return peers
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) ImportData(peers []Peer) error {
|
|
||||||
rdb := redis.NewClient(&redis.Options{
|
|
||||||
Addr: s.RedisUrl,
|
|
||||||
Password: s.RedisPassword, // no password set
|
|
||||||
DB: 0, // use default DB
|
|
||||||
})
|
|
||||||
var indexedPeers []map[string]interface{}
|
|
||||||
for _, p := range peers {
|
|
||||||
// Creating data block for indexing
|
|
||||||
indexedPeer := make(map[string]interface{})
|
|
||||||
indexedPeer["_id"] = p.PeerId
|
|
||||||
indexedPeer["name"] = p.Name
|
|
||||||
indexedPeer["keywords"] = p.Keywords
|
|
||||||
indexedPeer["name"] = p.Name
|
|
||||||
indexedPeer["entityname"] = p.EntityName
|
|
||||||
indexedPeer["entitytype"] = p.EntityType
|
|
||||||
indexedPeer["activity"] = p.Activity
|
|
||||||
indexedPeer["address"] = p.Address
|
|
||||||
indexedPeer["postcode"] = p.Postcode
|
|
||||||
indexedPeer["city"] = p.City
|
|
||||||
indexedPeer["country"] = p.Country
|
|
||||||
indexedPeer["description"] = p.Description
|
|
||||||
indexedPeer["apiurl"] = p.ApiUrl
|
|
||||||
indexedPeer["website"] = p.Website
|
|
||||||
indexedPeers = append(indexedPeers, indexedPeer)
|
|
||||||
// Adding peer to Redis (fast retieval and status updates)
|
|
||||||
jsonp, err := json.Marshal(p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = rdb.Set("peer:"+p.PeerId, jsonp, 0).Err()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bulk := map[string]interface{}{"index": "peers", "records": indexedPeers}
|
|
||||||
raw, err := json.Marshal(bulk)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest("POST", s.ZincUrl+"/api/_bulkv2", strings.NewReader(string(raw)))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req.SetBasicAuth(s.ZincLogin, s.ZincPassword)
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36")
|
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
log.Println(resp.StatusCode)
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(string(body))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) FindPeers(queryString string) ([]Peer, error) {
|
|
||||||
var peers []Peer
|
|
||||||
query := `{
|
|
||||||
"search_type": "match",
|
|
||||||
"query":
|
|
||||||
{
|
|
||||||
"term": "` + queryString + `",
|
|
||||||
"start_time": "2020-06-02T14:28:31.894Z",
|
|
||||||
"end_time": "2029-12-02T15:28:31.894Z"
|
|
||||||
},
|
|
||||||
"from": 0,
|
|
||||||
"max_results": 100,
|
|
||||||
"_source": []
|
|
||||||
}`
|
|
||||||
req, err := http.NewRequest("POST", s.ZincUrl+"/api/peers/_search", strings.NewReader(query))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
req.SetBasicAuth(s.ZincLogin, s.ZincPassword)
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36")
|
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
log.Println(resp.StatusCode)
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
value := gjson.Get(string(body), "hits.hits")
|
|
||||||
rdb := redis.NewClient(&redis.Options{
|
|
||||||
Addr: s.RedisUrl,
|
|
||||||
Password: s.RedisPassword, // no password set
|
|
||||||
DB: 0, // use default DB
|
|
||||||
})
|
|
||||||
for _, v := range value.Array() {
|
|
||||||
peerBytes, err := rdb.Get("peer:" + v.Get("_id").Str).Bytes()
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err)
|
|
||||||
} else {
|
|
||||||
var p Peer
|
|
||||||
err = json.Unmarshal(peerBytes, &p)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
peers = append(peers, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return peers, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) GetPeer(uid string) (*Peer, error) {
|
|
||||||
var peer Peer
|
|
||||||
rdb := redis.NewClient(&redis.Options{
|
|
||||||
Addr: s.RedisUrl,
|
|
||||||
Password: s.RedisPassword, // no password set
|
|
||||||
DB: 0, // use default DB
|
|
||||||
})
|
|
||||||
peerBytes, err := rdb.Get("peer:" + uid).Bytes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else {
|
|
||||||
err = json.Unmarshal(peerBytes, &peer)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &peer, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) DeletePeer(uid string) error {
|
|
||||||
// Removing from Redis
|
|
||||||
rdb := redis.NewClient(&redis.Options{
|
|
||||||
Addr: s.RedisUrl,
|
|
||||||
Password: s.RedisPassword, // no password set
|
|
||||||
DB: 0, // use default DB
|
|
||||||
})
|
|
||||||
err := rdb.Unlink("peer:" + uid).Err()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Removing from Index
|
|
||||||
req, err := http.NewRequest("DELETE", s.ZincUrl+"/api/peers/_doc"+uid, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req.SetBasicAuth(s.ZincLogin, s.ZincPassword)
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36")
|
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
log.Println(resp.StatusCode)
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(string(body))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
3
pem/private.pem
Normal file
3
pem/private.pem
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MC4CAQAwBQYDK2VwBCIEIK2oBaOtGNchE09MBRtPd5oEOUcVUQG2ndym5wKExj7R
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
3
pem/public.pem
Normal file
3
pem/public.pem
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MCowBQYDK2VwAyEAZ2nLJBL8a5opfa8nFeVj0SZToW8pl4+zgcSUkeZFRO4=
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
3
psk/psk.key
Normal file
3
psk/psk.key
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/key/swarm/psk/1.0.0/
|
||||||
|
/base16/
|
||||||
|
9018b627b4d0f123d1cfcd16f33b538688ed7588cde9da8c60d587b7022399c1
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package routers
|
|
||||||
|
|
||||||
import (
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
|
||||||
"github.com/beego/beego/v2/server/web/context/param"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-discovery/controllers:IdentityController"] = append(beego.GlobalControllerRouter["oc-discovery/controllers:IdentityController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "Post",
|
|
||||||
Router: `/`,
|
|
||||||
AllowHTTPMethods: []string{"post"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-discovery/controllers:IdentityController"] = append(beego.GlobalControllerRouter["oc-discovery/controllers:IdentityController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "GetAll",
|
|
||||||
Router: `/`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-discovery/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-discovery/controllers:PeerController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "Post",
|
|
||||||
Router: `/`,
|
|
||||||
AllowHTTPMethods: []string{"post"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-discovery/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-discovery/controllers:PeerController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "Get",
|
|
||||||
Router: `/:peerId`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-discovery/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-discovery/controllers:PeerController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "Delete",
|
|
||||||
Router: `/:peerId`,
|
|
||||||
AllowHTTPMethods: []string{"delete"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-discovery/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-discovery/controllers:PeerController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "Find",
|
|
||||||
Router: `/find/:query`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-discovery/controllers:VersionController"] = append(beego.GlobalControllerRouter["oc-discovery/controllers:VersionController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "GetAll",
|
|
||||||
Router: `/`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
// @APIVersion 1.0.0
|
|
||||||
// @Title beego Test API
|
|
||||||
// @Description beego has a very cool tools to autogenerate documents for your API
|
|
||||||
// @Contact astaxie@gmail.com
|
|
||||||
// @TermsOfServiceUrl http://beego.me/
|
|
||||||
// @License AGPL
|
|
||||||
// @LicenseUrl https://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
package routers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"oc-discovery/controllers"
|
|
||||||
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ns := beego.NewNamespace("/oc",
|
|
||||||
beego.NSNamespace("/peer",
|
|
||||||
beego.NSInclude(
|
|
||||||
&controllers.PeerController{},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
beego.NSNamespace("/identity",
|
|
||||||
beego.NSInclude(
|
|
||||||
&controllers.IdentityController{},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
beego.NSNamespace("/version",
|
|
||||||
beego.NSInclude(
|
|
||||||
&controllers.VersionController{},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
beego.AddNamespace(ns)
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
_ "oc-discovery/routers"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/core/logs"
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
_, file, _, _ := runtime.Caller(0)
|
|
||||||
apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
|
|
||||||
beego.TestBeegoInit(apppath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestGet is a sample to run an endpoint test
|
|
||||||
func TestGet(t *testing.T) {
|
|
||||||
r, _ := http.NewRequest("GET", "/oc/version", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
beego.BeeApp.Handlers.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
logs.Info("testing", "TestGet", "Code[%d]\n%s", w.Code, w.Body.String())
|
|
||||||
|
|
||||||
Convey("Subject: Test Station Endpoint\n", t, func() {
|
|
||||||
Convey("Status Code Should Be 200", func() {
|
|
||||||
So(w.Code, ShouldEqual, 200)
|
|
||||||
})
|
|
||||||
Convey("The Result Should Not Be Empty", func() {
|
|
||||||
So(w.Body.Len(), ShouldBeGreaterThan, 0)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user