github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/p2p/datasets.go (about) 1 package p2p 2 3 // TODO (ramfox): relies on old `depQriProtocolID` 4 // Should have its own protocol & protobuf & not rely on the Message struct 5 6 import ( 7 "context" 8 "encoding/json" 9 "fmt" 10 11 peer "github.com/libp2p/go-libp2p-core/peer" 12 "github.com/qri-io/qri/base" 13 p2putil "github.com/qri-io/qri/p2p/p2putil" 14 reporef "github.com/qri-io/qri/repo/ref" 15 ) 16 17 // MtDatasets is a dataset list message 18 const MtDatasets = p2putil.MsgType("list_datasets") 19 20 // listMax is the highest number of entries a list request should return 21 const listMax = 30 22 23 // DatasetsListParams encapsulates options for requesting datasets 24 type DatasetsListParams struct { 25 Term string 26 Limit int 27 Offset int 28 } 29 30 // RequestDatasetsList gets a list of a peer's datasets 31 func (n *QriNode) RequestDatasetsList(ctx context.Context, pid peer.ID, p DatasetsListParams) ([]reporef.DatasetRef, error) { 32 log.Debugf("%s RequestDatasetList: %s", n.ID, pid) 33 34 if pid == n.ID { 35 // requesting self isn't a network operation 36 return n.Repo.References(p.Offset, p.Limit) 37 } 38 39 if !n.Online { 40 return nil, fmt.Errorf("not connected to p2p network") 41 } 42 43 req, err := p2putil.NewJSONBodyMessage(n.ID, MtDatasets, p) 44 if err != nil { 45 log.Debug(err.Error()) 46 return nil, err 47 } 48 49 req = req.WithHeaders("phase", "request") 50 51 s, err := n.host.NewStream(ctx, pid, depQriProtocolID) 52 if err != nil { 53 return nil, fmt.Errorf("error opening stream: %s", err.Error()) 54 } 55 defer s.Close() 56 57 ws := p2putil.WrapStream(s) 58 if err := ws.SendMessage(req); err != nil { 59 return nil, err 60 } 61 62 res, err := ws.ReceiveMessage() 63 if err != nil { 64 return nil, err 65 } 66 67 ref := []reporef.DatasetRef{} 68 err = json.Unmarshal(res.Body, &ref) 69 return ref, err 70 } 71 72 func (n *QriNode) handleDatasetsList(ws *p2putil.WrappedStream, msg p2putil.Message) (hangup bool) { 73 hangup = true 74 switch msg.Header("phase") { 75 case "request": 76 dlp := DatasetsListParams{} 77 if err := json.Unmarshal(msg.Body, &dlp); err != nil { 78 log.Debugf("%s %s", n.ID, err.Error()) 79 return 80 } 81 82 if dlp.Limit == 0 || dlp.Limit > listMax { 83 dlp.Limit = listMax 84 } 85 86 refs, err := base.ListDatasets(context.TODO(), n.Repo, dlp.Term, "", dlp.Offset, dlp.Limit, true, false) 87 if err != nil { 88 log.Error(err) 89 return 90 } 91 92 reply, err := msg.UpdateJSON(refs) 93 reply = reply.WithHeaders("phase", "response") 94 if err := ws.SendMessage(reply); err != nil { 95 log.Debug(err.Error()) 96 return 97 } 98 } 99 100 return 101 }