github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/action_get.go (about) 1 package holochain 2 3 import ( 4 "errors" 5 "fmt" 6 . "github.com/holochain/holochain-proto/hash" 7 peer "github.com/libp2p/go-libp2p-peer" 8 "reflect" 9 ) 10 11 //------------------------------------------------------------ 12 // Get 13 14 type APIFnGet struct { 15 action ActionGet 16 } 17 18 func (fn *APIFnGet) Name() string { 19 return fn.action.Name() 20 } 21 22 func (fn *APIFnGet) Args() []Arg { 23 return []Arg{{Name: "hash", Type: HashArg}, {Name: "options", Type: MapArg, MapType: reflect.TypeOf(GetOptions{}), Optional: true}} 24 } 25 26 func callGet(h *Holochain, req GetReq, options *GetOptions) (response interface{}, err error) { 27 a := ActionGet{req: req, options: options} 28 fn := &APIFnGet{action: a} 29 response, err = fn.Call(h) 30 return 31 } 32 33 func (fn *APIFnGet) Call(h *Holochain) (response interface{}, err error) { 34 a := &fn.action 35 if a.options.Local { 36 response, err = a.getLocal(h.chain) 37 return 38 } 39 if a.options.Bundle { 40 bundle := h.Chain().BundleStarted() 41 if bundle == nil { 42 err = ErrBundleNotStarted 43 return 44 } 45 response, err = a.getLocal(bundle.chain) 46 return 47 } 48 rsp, err := h.dht.Query(a.req.H, GET_REQUEST, a.req) 49 if err != nil { 50 51 // follow the modified hash 52 if a.req.StatusMask == StatusDefault && err == ErrHashModified { 53 var hash Hash 54 hash, err = NewHash(rsp.(GetResp).FollowHash) 55 if err != nil { 56 return 57 } 58 if hash.String() == a.req.H.String() { 59 err = errors.New("FollowHash loop detected") 60 return 61 } 62 req := GetReq{H: hash, StatusMask: StatusDefault, GetMask: a.options.GetMask} 63 modResp, err := callGet(h, req, a.options) 64 if err == nil { 65 response = modResp 66 } 67 } 68 return 69 } 70 switch t := rsp.(type) { 71 case GetResp: 72 response = t 73 default: 74 err = fmt.Errorf("expected GetResp response from GET_REQUEST, got: %T", t) 75 return 76 } 77 return 78 } 79 80 type ActionGet struct { 81 req GetReq 82 options *GetOptions 83 } 84 85 func (a *ActionGet) Name() string { 86 return "get" 87 } 88 89 func (a *ActionGet) getLocal(chain *Chain) (resp GetResp, err error) { 90 var entry Entry 91 var entryType string 92 entry, entryType, err = chain.GetEntry(a.req.H) 93 if err != nil { 94 return 95 } 96 resp = GetResp{Entry: *entry.(*GobEntry)} 97 mask := a.options.GetMask 98 resp.EntryType = entryType 99 if (mask & GetMaskEntry) != 0 { 100 resp.Entry = *entry.(*GobEntry) 101 resp.EntryType = entryType 102 } 103 return 104 } 105 106 func (a *ActionGet) SysValidation(h *Holochain, def *EntryDef, pkg *Package, sources []peer.ID) (err error) { 107 return 108 } 109 110 func (a *ActionGet) Receive(dht *DHT, msg *Message) (response interface{}, err error) { 111 var entryData []byte 112 //var status int 113 req := msg.Body.(GetReq) 114 mask := req.GetMask 115 if mask == GetMaskDefault { 116 mask = GetMaskEntry 117 } 118 resp := GetResp{} 119 // always get the entry type despite what the mas says because we need it for the switch below. 120 entryData, resp.EntryType, resp.Sources, _, err = dht.Get(req.H, req.StatusMask, req.GetMask|GetMaskEntryType) 121 if err == nil { 122 if (mask & GetMaskEntry) != 0 { 123 switch resp.EntryType { 124 case DNAEntryType: 125 // TODO: make this add the requester to the blockedlist rather than panicing, see ticket #421 126 err = errors.New("nobody should actually get the DNA!") 127 return 128 case KeyEntryType: 129 resp.Entry = GobEntry{C: string(entryData)} 130 default: 131 var e GobEntry 132 err = e.Unmarshal(entryData) 133 if err != nil { 134 return 135 } 136 resp.Entry = e 137 } 138 } 139 } else { 140 if err == ErrHashModified { 141 resp.FollowHash = string(entryData) 142 } else if err == ErrHashNotFound { 143 closest := dht.h.node.betterPeersForHash(&req.H, msg.From, true, CloserPeerCount) 144 if len(closest) > 0 { 145 err = nil 146 resp := CloserPeersResp{} 147 resp.CloserPeers = dht.h.node.peers2PeerInfos(closest) 148 response = resp 149 return 150 } 151 } 152 } 153 154 response = resp 155 return 156 }