From 7fd258dc9d575c1dc6715b9e134a335b28c0e069 Mon Sep 17 00:00:00 2001 From: mr Date: Wed, 28 Jan 2026 17:22:29 +0100 Subject: [PATCH] Daemons Search --- conf/config.go | 24 ++ controllers/identity.go | 41 ---- controllers/peer.go | 80 ------- controllers/version.go | 19 -- daemons/dht/dht.go | 429 ++++++++++++++++++++++++++++++++++++ daemons/pubsub/handler.go | 89 ++++++++ daemons/pubsub/nats.go | 47 ++++ daemons/pubsub/publish.go | 205 +++++++++++++++++ daemons/pubsub/service.go | 127 +++++++++++ daemons/pubsub/subscribe.go | 139 ++++++++++++ daemons/utils.go | 100 +++++++++ go.mod | 125 +++++++++-- go.sum | 304 +++++++++++++++++++++++++ main.go | 42 ++-- models/config.go | 25 --- models/event.go | 30 +++ models/identity.go | 44 ---- models/peer.go | 88 -------- models/storage.go | 206 ----------------- routers/commentsRouter.go | 73 ------ routers/router.go | 36 --- tests/default_test.go | 38 ---- 22 files changed, 1631 insertions(+), 680 deletions(-) create mode 100644 conf/config.go delete mode 100644 controllers/identity.go delete mode 100644 controllers/peer.go delete mode 100644 controllers/version.go create mode 100644 daemons/dht/dht.go create mode 100644 daemons/pubsub/handler.go create mode 100644 daemons/pubsub/nats.go create mode 100644 daemons/pubsub/publish.go create mode 100644 daemons/pubsub/service.go create mode 100644 daemons/pubsub/subscribe.go create mode 100644 daemons/utils.go delete mode 100644 models/config.go create mode 100644 models/event.go delete mode 100644 models/identity.go delete mode 100644 models/peer.go delete mode 100644 models/storage.go delete mode 100644 routers/commentsRouter.go delete mode 100644 routers/router.go delete mode 100644 tests/default_test.go diff --git a/conf/config.go b/conf/config.go new file mode 100644 index 0000000..eb67188 --- /dev/null +++ b/conf/config.go @@ -0,0 +1,24 @@ +package conf + +import "sync" + +type Config struct { + Name string + Hostname string + PSKPath string + PublicKeyPath string + PrivateKeyPath string + DHTEndpointPort int64 + + BootstrapAddresses string +} + +var instance *Config +var once sync.Once + +func GetConfig() *Config { + once.Do(func() { + instance = &Config{} + }) + return instance +} diff --git a/controllers/identity.go b/controllers/identity.go deleted file mode 100644 index 3dc43a6..0000000 --- a/controllers/identity.go +++ /dev/null @@ -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() -} diff --git a/controllers/peer.go b/controllers/peer.go deleted file mode 100644 index bc93c4c..0000000 --- a/controllers/peer.go +++ /dev/null @@ -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() -} diff --git a/controllers/version.go b/controllers/version.go deleted file mode 100644 index 6fa3e9c..0000000 --- a/controllers/version.go +++ /dev/null @@ -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() -} diff --git a/daemons/dht/dht.go b/daemons/dht/dht.go new file mode 100644 index 0000000..8c075ed --- /dev/null +++ b/daemons/dht/dht.go @@ -0,0 +1,429 @@ +package dht + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "oc-discovery/conf" + "oc-discovery/daemons" + "slices" + "strings" + "sync" + "time" + + oclib "cloud.o-forge.io/core/oc-lib" + 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/google/uuid" + "github.com/libp2p/go-libp2p" + dht "github.com/libp2p/go-libp2p-kad-dht" + kad_dht "github.com/libp2p/go-libp2p-kad-dht" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/peer" +) + +type DHTRecord struct { + Name string `json:"name"` + State int `json:"state"` + DID string `json:"did"` + PeerID string `json:"peer_id"` + PubKey []byte `json:"pub_key"` + URL string `json:"url"` + NATSUrl string `json:"nats_url"` + Wallet string `json:"wallet"` + Signature []byte `json:"signature"` + ExpiryDate time.Time `json:"expiry_date"` +} + +type DHTService struct { + Key string + Host host.Host + DHT *dht.IpfsDHT + Cache []string + mutex sync.RWMutex +} + +// TODO kick connection to base... and send on NATS boy +var dhtSingletonService *DHTService + +func GetDHTService() *DHTService { + return dhtSingletonService +} + +func Init(ctx context.Context) (*DHTService, error) { + service := &DHTService{} + priv, err := daemons.LoadKeyFromFile(false) + if err != nil { + return nil, err + } + psk, err := daemons.LoadPSKFromFile() + if err != nil { + return nil, err + } + h, err := libp2p.New( + libp2p.PrivateNetwork(psk), + libp2p.Identity(priv), + libp2p.ListenAddrStrings( + fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", conf.GetConfig().DHTEndpointPort), + ), + ) + if err != nil { + return nil, err + } + service.Host = h + service.DHT, err = kad_dht.New(ctx, h, kad_dht.MaxRecordAge(24*time.Hour)) // every day DHT will purge expired data... if not used. + if err != nil { + return nil, err + } + err = service.DHT.Bootstrap(ctx) + if err != nil { + return nil, err + } + + for _, address := range strings.Split(conf.GetConfig().BootstrapAddresses, ",") { + pi, err := peer.AddrInfoFromString(address) + if err != nil { + return nil, err + } + logger := oclib.GetLogger() + if err := h.Connect(ctx, *pi); err != nil { + logger.Err(fmt.Errorf("Failed to connect to MAIN bootstrap peer %s: %s", pi.ID, err)) + } else { + logger.Info().Msg(fmt.Sprintf("Connected to MAIN bootstrap peer %s", pi.ID)) + } + } + + dhtSingletonService = service + if daemons.VerifyPubWithPriv() { + if _, err := dhtSingletonService.ClaimName(context.Background(), + conf.GetConfig().Name, + conf.GetConfig().Hostname, false); err == nil { + go service.Heartbeat(ctx, 2*time.Minute) + go service.RefreshKeys(ctx, 30*time.Minute) + } + } + + return service, nil +} + +func (d *DHTService) Heartbeat(ctx context.Context, interval time.Duration) { + ticker := time.NewTicker(interval) + go func() { + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + dhtSingletonService.ClaimName(context.Background(), conf.GetConfig().Name, conf.GetConfig().Hostname, true) + } + } + }() +} + +func (d *DHTService) RefreshKeys(ctx context.Context, interval time.Duration) { + ticker := time.NewTicker(interval) + go func() { + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + s := []string{} + d.mutex.Lock() + s = append(s, d.Cache...) + d.mutex.Unlock() + for _, key := range s { + _, _ = d.GetValue(ctx, key) + } + } + } + }() +} + +func (d *DHTService) PutValue( + ctx context.Context, + key string, + value []byte, +) error { + err := d.DHT.PutValue(ctx, key, value) + if err != nil { + return err + } + d.mutex.Lock() + if !slices.Contains(d.Cache, key) { + d.Cache = append(d.Cache, key) + } + d.mutex.Unlock() + return nil +} + +func (d *DHTService) GetValue( + ctx context.Context, + key string, +) (*DHTRecord, error) { + dht, err := d.DHT.GetValue(ctx, key) + if err != nil { + cache := []string{} + d.mutex.Lock() + for _, c := range d.Cache { + if c != key { + cache = append(cache, c) + } + } + d.Cache = cache + d.mutex.Unlock() + return nil, err + } + d.mutex.Lock() + if !slices.Contains(d.Cache, key) { + d.Cache = append(d.Cache, key) + } + d.mutex.Unlock() + var data DHTRecord + json.Unmarshal(dht, &data) + + peerID, err := oclib.GenerateNodeID() + if err != nil { + return nil, err + } + p := &pp.Peer{ + AbstractObject: utils.AbstractObject{ + UUID: uuid.New().String(), + Name: data.Name, + }, + State: pp.ONLINE, + Relation: pp.SELF, + PeerID: peerID, + PublicKey: string(data.PubKey), + Url: data.URL, + NATSUrl: oclib.GetConfig().NATSUrl, + WalletAddress: data.Wallet, + } + b, err := json.Marshal(p) + if err != nil { + return nil, err + } + tools.NewNATSCaller().SetNATSPub(tools.CREATE_RESOURCE, tools.NATSResponse{ + FromApp: "oc-discovery", + Datatype: tools.PEER, + Method: int(tools.CREATE_PEER), + Payload: b, + }) + + /*if founded, _, err := access.Search(nil, fmt.Sprintf("%v", pp.SELF.EnumIndex()), false); + err == nil && len(founded) > 0 && founded[0].(*pp.Peer).Relation != pp.BLACKLIST { + f.(*pp.Peer).State = pp.ONLINE + f.(*pp.Peer).NATSUrl = p.NATSUrl + f.(*pp.Peer).Url = p.Url + f.(*pp.Peer).PeerID = p.PeerID + f.(*pp.Peer).Relation = p.Relation + f.(*pp.Peer).WalletAddress = p.WalletAddress + access.UpdateOne(f, f.GetID()) + }*/ + + return &data, err +} + +func (d *DHTService) generateKey() (string, error) { + s, err := oclib.GenerateNodeID() + if err != nil { + return s, err + } + return "/opencloud/peer/" + s, nil +} + +// Create your peer. +func (d *DHTService) ClaimName( + ctx context.Context, + name string, + endPoint string, + avoidVerification bool, +) (*pp.Peer, error) { + if endPoint == "" { + return nil, errors.New("no endpoint found for peer" + name) + } + + peerID, err := oclib.GenerateNodeID() + if err != nil { + return nil, err + } + + pub := d.Host.Peerstore().PubKey(d.Host.ID()) + pubBytes, _ := pub.Raw() + + now := time.Now() + expiry := now.Add(150 * time.Second) + + rec := DHTRecord{ + Name: name, + PeerID: peerID, + PubKey: pubBytes, + } + + payload, _ := json.Marshal(rec) + sig, _ := daemons.Sign(d.Host.Peerstore().PrivKey(d.Host.ID()), payload) + rec.Signature = sig + + rec.URL = endPoint + rec.NATSUrl = oclib.GetConfig().NATSUrl + rec.State = pp.ONLINE.EnumIndex() + rec.ExpiryDate = expiry + + data, _ := json.Marshal(rec) + + key, err := d.generateKey() + if err != nil { + return nil, err + } + + // retrieve your key name in standard + if !avoidVerification { + old, err := d.GetValue(ctx, key) + if err == nil { + if old.PeerID != peerID { // check if someone claims your name before + return nil, errors.New("name already claimed by another peer") + } + if now.After(old.ExpiryDate) { + payload, _ := json.Marshal(rec) + d.PutValue(ctx, key, payload) + } + } + } + + if err := d.PutValue(ctx, key, data); err != nil { + return nil, err + } + + pubStr := base64.StdEncoding.EncodeToString(pubBytes) + d.Key = key + if err != nil { + return nil, err + } + p := &pp.Peer{ + AbstractObject: utils.AbstractObject{ + UUID: uuid.New().String(), + Name: name, + }, + State: pp.ONLINE, + Relation: pp.SELF, + PeerID: peerID, + PublicKey: pubStr, + Url: endPoint, + NATSUrl: oclib.GetConfig().NATSUrl, + WalletAddress: "my-wallet", + } + + b, err := json.Marshal(p) + if err != nil { + return nil, err + } + tools.NewNATSCaller().SetNATSPub(tools.CREATE_RESOURCE, tools.NATSResponse{ + FromApp: "oc-discovery", + Datatype: tools.PEER, + Method: int(tools.CREATE_PEER), + Payload: b, + }) + return p, nil +} + +// Discover a specific Peer +func (d *DHTService) DiscoverPeers(ctx context.Context, name string) ([]*pp.Peer, error) { + peers := []*pp.Peer{} + key, err := d.generateKey() + if err != nil { + return nil, err + } + datas, _ := d.DHT.SearchValue(ctx, key) + for data := range datas { + var dht *DHTRecord + if err := json.Unmarshal(data, dht); err != nil { + return peers, err + } + if p, err := d.treatPeer(ctx, key, dht); err == nil { + peers = append(peers, p) + } + } + return peers, nil +} + +func (d *DHTService) GetPeer(ctx context.Context, name string) (*pp.Peer, error) { + key, err := d.generateKey() + if err != nil { + return nil, err + } + data, err := d.GetValue(ctx, key) + if err != nil { + return nil, errors.New("no DHT peer not found") + } + return d.treatPeer(ctx, key, data) +} + +func (d *DHTService) treatPeer(ctx context.Context, key string, rec *DHTRecord) (*pp.Peer, error) { + pubKey, err := crypto.UnmarshalPublicKey(rec.PubKey) + if err != nil { + return nil, err + } + + now := time.Now() + dht := DHTRecord{ + Name: rec.Name, + PeerID: rec.PeerID, + PubKey: rec.PubKey, + } + payload, _ := json.Marshal(dht) + + if ok, _ := daemons.Verify(pubKey, payload, rec.Signature); !ok { + return nil, errors.New("invalid signature") + } + pubBytes, _ := pubKey.Raw() + pubStr := base64.StdEncoding.EncodeToString(pubBytes) + + rel := pp.NONE + if d.Key == key { + rel = pp.SELF + } + + p := &pp.Peer{ + AbstractObject: utils.AbstractObject{ + UUID: uuid.New().String(), + Name: rec.Name, + }, + State: pp.ONLINE, + Relation: rel, + PeerID: rec.PeerID, + PublicKey: pubStr, + Url: rec.URL, + NATSUrl: rec.NATSUrl, + WalletAddress: rec.Wallet, + } + if now.After(rec.ExpiryDate) { // is expired + rec.State = pp.OFFLINE.EnumIndex() + p.State = pp.OFFLINE + payload, _ := json.Marshal(rec) + d.PutValue(ctx, key, payload) + + b, err := json.Marshal(p) + if err != nil { + return nil, err + } + tools.NewNATSCaller().SetNATSPub(tools.CREATE_RESOURCE, tools.NATSResponse{ + FromApp: "oc-discovery", + Datatype: tools.PEER, + Method: int(tools.CREATE_PEER), + Payload: b, + }) + return nil, errors.New("peer " + key + " is expired") + } + if p.State == pp.OFFLINE { + return nil, errors.New("peer " + key + " is offline") + } + return p, nil +} + +// TODO : HEARTBEAT diff --git a/daemons/pubsub/handler.go b/daemons/pubsub/handler.go new file mode 100644 index 0000000..4e23b7c --- /dev/null +++ b/daemons/pubsub/handler.go @@ -0,0 +1,89 @@ +package pubsub + +import ( + "context" + "encoding/json" + "errors" + "oc-discovery/daemons" + "oc-discovery/daemons/dht" + "oc-discovery/models" + + "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 *PubSubService) handleEvent(ctx context.Context, topicName string, evt models.Event) error { + action := ps.getTopicName(topicName) + if err := ps.handleEventFromPartner(evt, action); err != nil { + return err + } + if err := ps.handleEventSearch(ctx, evt, action); err != nil { + return err + } + return nil +} + +func (ps *PubSubService) handleEventFromPartner(evt models.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_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 (ps *PubSubService) handleEventSearch( // only : on partner followings. 3 canals for every partner. + ctx context.Context, + evt models.Event, + action tools.PubSubAction, +) error { + if !(action == tools.PB_SEARCH_RESPONSE || action == tools.PB_SEARCH) { + return nil + } + if p, err := dht.GetDHTService().GetPeer(ctx, evt.From); err == nil { + if err := daemons.VerifyPeer([]*peer.Peer{p}, evt); err != nil { + return err + } + switch action { + case tools.PB_SEARCH_RESPONSE: + if err := ps.retrieveResponse(ctx, p, evt); err != nil { + return err + } + case tools.PB_SEARCH: // when someone ask for search. + if p, err := dht.GetDHTService().GetPeer(ctx, evt.From); err == nil { + if err := ps.sendResponse(ctx, p, evt); err != nil { + return err + } + } + default: + return nil + } + } + return nil +} diff --git a/daemons/pubsub/nats.go b/daemons/pubsub/nats.go new file mode 100644 index 0000000..63a28e9 --- /dev/null +++ b/daemons/pubsub/nats.go @@ -0,0 +1,47 @@ +package pubsub + +import ( + "context" + "encoding/json" + "fmt" + + "cloud.o-forge.io/core/oc-lib/tools" +) + +func ListenNATS() { + 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: + GetPubSubService().ToPartnerPublishEvent( + context.Background(), + propalgation.Action, + dt, propalgation.User, + propalgation.Payload, + ) + case tools.PB_SEARCH: + m := map[string]interface{}{} + json.Unmarshal(propalgation.Payload, &m) + GetPubSubService().SearchPublishEvent( + context.Background(), + dt, + fmt.Sprintf("%v", m["type"]), + propalgation.User, + fmt.Sprintf("%v", m["search"]), + ) + } + } + }, + }) +} diff --git a/daemons/pubsub/publish.go b/daemons/pubsub/publish.go new file mode 100644 index 0000000..967f727 --- /dev/null +++ b/daemons/pubsub/publish.go @@ -0,0 +1,205 @@ +package pubsub + +import ( + "context" + "encoding/json" + "errors" + "oc-discovery/daemons" + "oc-discovery/models" + "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" +) + +func (ps *PubSubService) SearchPublishEvent( + ctx context.Context, + dt *tools.DataType, + typ string, + user string, + search string, +) error { + switch typ { + case "partner": + ps.searchPartnersPublishEvent( + ctx, dt, user, search, + ) + case "all": + b, err := json.Marshal(map[string]string{ + "search": search, + }) + if err != nil { + return err + } + ps.searchPublishEvent( + ctx, dt, user, "", b, + ) + case "known": + ps.searchKnownPublishEvent( + ctx, dt, user, search, + ) + default: + return errors.New("no type of research found") + } + return nil +} + +func (ps *PubSubService) searchPartnersPublishEvent( + ctx context.Context, + dt *tools.DataType, + user string, + search string, +) error { + access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil) + f := &dbs.Filters{ + And: map[string][]dbs.Filter{ // search by name if no filters are provided + "state": {{Operator: dbs.EQUAL.String(), Value: peer.ONLINE.EnumIndex()}}, + "relation": {{Operator: dbs.EQUAL.String(), Value: peer.PARTNER.EnumIndex()}}, + }, + } + if search != "" { + f.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}}, + } + } + b, err := json.Marshal(map[string]string{ + "search": search, + }) + if err != nil { + return err + } + peersKnown := access.Search(f, "", false) + for _, known := range peersKnown.Data { + if err := ps.searchPublishEvent(ctx, dt, user, known.GetID(), b); err != nil { + return err + } + } + return nil +} + +func (ps *PubSubService) searchKnownPublishEvent( + ctx context.Context, + dt *tools.DataType, + user string, + search string, +) error { + access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil) + f := &dbs.Filters{ + And: map[string][]dbs.Filter{ // search by name if no filters are provided + "state": {{Operator: dbs.EQUAL.String(), Value: peer.ONLINE.EnumIndex()}}, + "relation": {{Operator: dbs.NOT.String(), Value: &dbs.Filters{ + And: map[string][]dbs.Filter{ + "relation": {{Operator: dbs.EQUAL.String(), Value: peer.BLACKLIST.EnumIndex()}}, + }, + }}}, + }, + } + if search != "" { + f.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}}, + } + } + b, err := json.Marshal(map[string]string{ + "search": search, + }) + if err != nil { + return err + } + peersKnown := access.Search(f, "", false) + for _, known := range peersKnown.Data { + if err := ps.searchPublishEvent(ctx, dt, user, known.GetID(), b); err != nil { + return err + } + } + return nil +} + +func (ps *PubSubService) searchPublishEvent( + ctx context.Context, + dt *tools.DataType, + user string, + peerID 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, peerID, payload, false) +} + +func (ps *PubSubService) ToPartnerPublishEvent( + ctx context.Context, action tools.PubSubAction, dt *tools.DataType, user string, payload []byte) error { + id, err := oclib.GenerateNodeID() + if err != nil { + return err + } + return ps.publishEvent(ctx, dt, action, user, id, 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 + } + evt := models.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) + priv, err := daemons.LoadKeyFromFile(false) + if err != nil { + return err + } + sig, _ := priv.Sign(body) + evt.Signature = sig + + msg, _ := json.Marshal(evt) + + 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 diff --git a/daemons/pubsub/service.go b/daemons/pubsub/service.go new file mode 100644 index 0000000..7fb2078 --- /dev/null +++ b/daemons/pubsub/service.go @@ -0,0 +1,127 @@ +package pubsub + +import ( + "context" + "encoding/json" + "oc-discovery/models" + "strings" + "sync" + + 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/models/resources" + "cloud.o-forge.io/core/oc-lib/tools" + pubsub "github.com/libp2p/go-libp2p-pubsub" +) + +type PubSubService struct { + PS *pubsub.PubSub + Subscription []string + mutex sync.RWMutex +} + +var pubsubSingleton *PubSubService + +func Init(ctx context.Context, ps *pubsub.PubSub) { + pubsubSingleton = &PubSubService{ + PS: ps, + Subscription: []string{}, + } + pubsubSingleton.initSubscribeEvents(ctx) +} + +func GetPubSubService() *PubSubService { + return pubsubSingleton +} + +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 (abs *PubSubService) retrieveResponse(ctx context.Context, p *peer.Peer, event models.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 (abs *PubSubService) sendResponse(ctx context.Context, p *peer.Peer, event models.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.publishEvent(ctx, &ndt, tools.PB_SEARCH_RESPONSE, event.User, peerID, j, true) + } else { + abs.publishEvent(ctx, nil, tools.PB_SEARCH_RESPONSE, event.User, peerID, j, true) + } + } + } + } + return nil +} + +func (abs *PubSubService) 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, + } +} diff --git a/daemons/pubsub/subscribe.go b/daemons/pubsub/subscribe.go new file mode 100644 index 0000000..0506c79 --- /dev/null +++ b/daemons/pubsub/subscribe.go @@ -0,0 +1,139 @@ +package pubsub + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "oc-discovery/daemons" + "oc-discovery/daemons/dht" + "oc-discovery/models" + "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 { + ourPeerID, err := oclib.GenerateNodeID() + if err != nil { + return err + } + if err := ps.subscribeEvents(ctx, nil, tools.PB_SEARCH, "", -1); err != nil { + return err + } + if err := ps.subscribeEvents(ctx, nil, tools.PB_SEARCH, ourPeerID, -1); err != nil { // we subscribe at our proprer deductible search adresse. + return err + } + if err := ps.initPartnersSubscribeEvents(ctx); err != nil { + return nil + } + return nil +} + +func (ps *PubSubService) initPartnersSubscribeEvents(ctx context.Context) error { + // search all your partners : we check in base for this because we keep actively peer state if partners + access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil) + peers := access.Search(nil, fmt.Sprintf("%v", peer.PARTNER.EnumIndex()), false) + for _, p := range peers.Data { + if err := ps.PartnerSubscribeEvents(ctx, p.(*peer.Peer).PeerID); err != nil { + return err + } + } + return nil +} + +func (ps *PubSubService) PartnerSubscribeEvents(ctx context.Context, myPartnerPeerID string) error { + if myPartnerPeerID == "" { + return errors.New("should discover a particular partner peer") + } + for _, action := range []tools.PubSubAction{tools.PB_CREATE, tools.PB_UPDATE, tools.PB_DELETE} { + if err := ps.subscribeEvents(ctx, nil, action, myPartnerPeerID, -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 models.Event + if err := json.Unmarshal(msg.Data, &evt); err != nil { // map to event + continue + } + if p, err := dht.GetDHTService().GetPeer(ctx, evt.From); err == nil { + if err := ps.processEventPeerKnown(ctx, p, evt, topicName); err != nil { + logger.Err(err) + } + } + } +} + +func (ps *PubSubService) processEventPeerKnown( + ctx context.Context, p *peer.Peer, event models.Event, topicName string) error { + if err := daemons.VerifyPeer([]*peer.Peer{p}, event); err != nil { + return err + } + return ps.handleEvent(ctx, topicName, event) +} diff --git a/daemons/utils.go b/daemons/utils.go new file mode 100644 index 0000000..fe9fd0a --- /dev/null +++ b/daemons/utils.go @@ -0,0 +1,100 @@ +package daemons + +import ( + "bytes" + "encoding/base64" + "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 LoadKeyFromFile(isPublic bool) (crypto.PrivKey, error) { + path := conf.GetConfig().PrivateKeyPath + if isPublic { + path = conf.GetConfig().PublicKeyPath + } + data, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + // Try to unmarshal as libp2p private key (supports ed25519, rsa, etc.) + priv, err := crypto.UnmarshalPrivateKey(data) + if err != nil { + return nil, err + } + return priv, nil +} + +func VerifyPubWithPriv() bool { + priv, err := LoadKeyFromFile(false) + if err != nil { + fmt.Println(err) + return false + } + pub, err := LoadKeyFromFile(true) + if err != nil { + fmt.Println(err) + return false + } + return priv.GetPublic().Equals(pub) +} + +func LoadPSKFromFile() (pnet.PSK, error) { + path := conf.GetConfig().PSKPath + data, err := os.ReadFile(path) + if err != nil { + return nil, err + } + // Try to unmarshal as libp2p private key (supports ed25519, rsa, etc.) + psk, err := pnet.DecodeV1PSK(bytes.NewReader(data)) + if err != nil { + return nil, err + } + 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) +} diff --git a/go.mod b/go.mod index 662838d..616a276 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,9 @@ module oc-discovery -go 1.23.0 - -toolchain go1.24.0 +go 1.24.6 require ( - cloud.o-forge.io/core/oc-lib v0.0.0-20250704084459-443546027b27 + cloud.o-forge.io/core/oc-lib v0.0.0-20260128160440-c0d89ea9e1e8 github.com/beego/beego v1.12.13 github.com/beego/beego/v2 v2.3.8 github.com/go-redis/redis v6.15.9+incompatible @@ -13,23 +11,122 @@ require ( 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 ( github.com/beorn7/perks v1.0.1 // indirect github.com/biter777/countries v1.7.5 // 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/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.27.0 // indirect github.com/golang/snappy v1.0.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/hashicorp/golang-lru v1.0.2 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/klauspost/compress v1.18.0 // indirect github.com/kr/text v0.2.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-isatty v0.0.20 // 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/nkeys v0.4.11 // 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/common v0.65.0 // indirect + github.com/prometheus/common v0.66.1 // indirect github.com/prometheus/procfs v0.17.0 // indirect github.com/robfig/cron v1.2.0 // 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/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.mongodb.org/mongo-driver v1.17.4 // indirect - golang.org/x/crypto v0.39.0 // indirect - golang.org/x/net v0.41.0 // indirect - golang.org/x/sync v0.15.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.26.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + golang.org/x/crypto v0.47.0 // indirect + golang.org/x/net v0.49.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/text v0.33.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 8dfe26a..3d257b2 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,22 @@ 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-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-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= 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/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -22,6 +38,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/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/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 v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -40,27 +58,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/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/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/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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/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.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw= 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/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/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.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.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/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-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-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/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -78,8 +114,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-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-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/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.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -101,31 +140,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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/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/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/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 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/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/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/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.8/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/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 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/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= 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/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/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/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/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -138,7 +208,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/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 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/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/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= @@ -149,6 +249,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-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/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.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -158,6 +269,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/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= 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/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -178,14 +314,60 @@ github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= 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/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.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= 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.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/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 v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -193,6 +375,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.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= 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-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -208,6 +392,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.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= 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.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -217,6 +403,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.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0= 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/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= @@ -229,9 +421,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.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= 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-20230509054315-a9deabde6e02 h1:v9ezJDHA1XGxViAUSIoO/Id7Fl63u6d0YmsAm+/p2hs= 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/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= @@ -244,12 +438,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 v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= 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/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.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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= @@ -261,7 +463,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/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 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/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/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= @@ -270,6 +479,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/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/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/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU= go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8= @@ -278,44 +489,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.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= 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-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-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-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.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/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/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/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.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-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-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-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-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/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= 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.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= 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-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-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-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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= 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/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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -326,37 +591,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-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-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-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-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-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.5.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.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/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.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-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.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.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.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/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= 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-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-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.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-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-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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -367,6 +666,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.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= 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/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= @@ -385,5 +686,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.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 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/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= diff --git a/main.go b/main.go index 0d47b1f..02841eb 100644 --- a/main.go +++ b/main.go @@ -1,38 +1,33 @@ package main import ( - "oc-discovery/models" + "context" + "oc-discovery/conf" + "oc-discovery/daemons/dht" + "oc-discovery/daemons/pubsub" _ "oc-discovery/routers" oclib "cloud.o-forge.io/core/oc-lib" - "cloud.o-forge.io/core/oc-lib/logs" beego "github.com/beego/beego/v2/server/web" "github.com/beego/beego/v2/server/web/filter/cors" + pss "github.com/libp2p/go-libp2p-pubsub" ) const appname = "oc-discovery" func main() { + logger := oclib.GetLogger() // Init the oc-lib oclib.Init(appname) // get the right config file o := oclib.GetConfLoader() - models.GetConfig().Port = o.GetIntDefault("port", 8080) - models.GetConfig().LokiUrl = o.GetStringDefault("lokiurl", "") - models.GetConfig().RedisUrl = o.GetStringDefault("redisurl", "localhost:6379") - models.GetConfig().RedisPassword = o.GetStringDefault("redispassword", "") - models.GetConfig().ZincUrl = o.GetStringDefault("zincurl", "http://localhost:4080") - models.GetConfig().ZincLogin = o.GetStringDefault("zinclogin", "admin") - models.GetConfig().ZincPassword = o.GetStringDefault("zincpassword", "admin") - models.GetConfig().IdentityFile = o.GetStringDefault("identityfile", "./identity.json") - models.GetConfig().Defaultpeers = o.GetStringDefault("defaultpeers", "./peers.json") - - // set oc-lib logger - if models.GetConfig().LokiUrl != "" { - logs.CreateLogger(appname) - } + conf.GetConfig().PSKPath = o.GetStringDefault("PSK_PATH", "./psk/psk") + conf.GetConfig().DHTEndpointPort = o.GetInt64Default("DHT_ENDPOINT_PORT", 4001) + conf.GetConfig().PublicKeyPath = o.GetStringDefault("PUBLIC_KEY_PATH", "./pem/public.pem") + conf.GetConfig().PrivateKeyPath = o.GetStringDefault("PRIVATE_KEY_PATH", "./pem/private.pem") + conf.GetConfig().BootstrapAddresses = o.GetStringDefault("BOOTSTRAP_ADDRESSES", "") // Normal beego init beego.BConfig.AppName = appname @@ -46,5 +41,20 @@ func main() { ExposeHeaders: []string{"Content-Length", "Content-Type"}, AllowCredentials: true, })) + ctx := context.Background() + DHT, err := dht.Init(ctx) + if err == nil { + logger.Err(err) + } else { + ps, err := pss.NewGossipSub( + ctx, DHT.Host, + pss.WithMessageSigning(true), + pss.WithStrictSignatureVerification(true), + ) + pubsub.Init(ctx, ps) + if err != nil { + logger.Err(err) + } + } beego.Run() } diff --git a/models/config.go b/models/config.go deleted file mode 100644 index d97e6c9..0000000 --- a/models/config.go +++ /dev/null @@ -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 -} diff --git a/models/event.go b/models/event.go new file mode 100644 index 0000000..7feb9b6 --- /dev/null +++ b/models/event.go @@ -0,0 +1,30 @@ +package models + +import "encoding/json" + +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 (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()) +} diff --git a/models/identity.go b/models/identity.go deleted file mode 100644 index 347ee4f..0000000 --- a/models/identity.go +++ /dev/null @@ -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 -} diff --git a/models/peer.go b/models/peer.go deleted file mode 100644 index be43bb4..0000000 --- a/models/peer.go +++ /dev/null @@ -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 -} diff --git a/models/storage.go b/models/storage.go deleted file mode 100644 index fdfab4b..0000000 --- a/models/storage.go +++ /dev/null @@ -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 -} diff --git a/routers/commentsRouter.go b/routers/commentsRouter.go deleted file mode 100644 index ea24b5b..0000000 --- a/routers/commentsRouter.go +++ /dev/null @@ -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}) - -} diff --git a/routers/router.go b/routers/router.go deleted file mode 100644 index afa9a77..0000000 --- a/routers/router.go +++ /dev/null @@ -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) -} diff --git a/tests/default_test.go b/tests/default_test.go deleted file mode 100644 index af68695..0000000 --- a/tests/default_test.go +++ /dev/null @@ -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) - }) - }) -}