github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/bs.go (about) 1 // Copyright (C) 2013-2018, The MetaCurrency Project (Eric Harris-Braun, Arthur Brock, et. al.) 2 // Use of this source code is governed by GPLv3 found in the LICENSE file 3 //---------------------------------------------------------------------------------------- 4 5 // implements bootstrap server access 6 7 package holochain 8 9 import ( 10 "bytes" 11 "encoding/json" 12 "errors" 13 "fmt" 14 peer "github.com/libp2p/go-libp2p-peer" 15 pstore "github.com/libp2p/go-libp2p-peerstore" 16 ma "github.com/multiformats/go-multiaddr" 17 "io/ioutil" 18 "net/http" 19 "strings" 20 "time" 21 ) 22 23 const ( 24 BootstrapTTL = time.Minute * 5 25 ) 26 27 type BSReq struct { 28 Version int 29 NodeID string 30 NodeAddr string 31 } 32 33 type BSResp struct { 34 Req BSReq 35 Remote string 36 LastSeen time.Time 37 } 38 39 func (h *Holochain) BSpost() (err error) { 40 if h.node == nil { 41 return errors.New("Node hasn't been initialized yet.") 42 } 43 nodeID := h.nodeIDStr 44 req := BSReq{Version: 1, NodeID: nodeID, NodeAddr: h.node.ExternalAddr().String()} 45 host := h.Config.BootstrapServer 46 id := h.DNAHash() 47 url := fmt.Sprintf("http://%s/%s/%s", host, id.String(), nodeID) 48 var b []byte 49 b, err = json.Marshal(req) 50 //var resp *http.Response 51 if err == nil { 52 var resp *http.Response 53 resp, err = http.Post(url, "application/json", bytes.NewBuffer(b)) 54 if err == nil { 55 resp.Body.Close() 56 } 57 58 } 59 return 60 } 61 62 func (h *Holochain) checkBSResponses(nodes []BSResp) (err error) { 63 myNodeID := h.nodeIDStr 64 for _, r := range nodes { 65 h.dht.dlog.Logf("checking returned node: %v", r) 66 67 var id peer.ID 68 var addr ma.Multiaddr 69 id, err = peer.IDB58Decode(r.Req.NodeID) 70 if err == nil { 71 //@TODO figure when to use Remote or r.NodeAddr 72 x := strings.Split(r.Remote, ":") 73 y := strings.Split(r.Req.NodeAddr, "/") 74 port := y[len(y)-1] 75 76 // assume the multi-address is the ip address as the bootstrap server saw it 77 // with port number advertised by the node in it's multi-address 78 79 addr, err = ma.NewMultiaddr("/ip4/" + x[0] + "/tcp/" + port) 80 if err == nil { 81 // don't "discover" ourselves 82 if r.Req.NodeID != myNodeID { 83 h.dht.dlog.Logf("discovered peer via bs: %s (%v)", r.Req.NodeID, addr) 84 go func() { 85 err = h.AddPeer(pstore.PeerInfo{ID: id, Addrs: []ma.Multiaddr{addr}}) 86 }() 87 } 88 89 } 90 } 91 } 92 return 93 } 94 95 func (h *Holochain) BSget() (err error) { 96 if h.node == nil { 97 return errors.New("Node hasn't been initialized yet.") 98 } 99 host := h.Config.BootstrapServer 100 if host == "" { 101 return 102 } 103 id := h.DNAHash() 104 url := fmt.Sprintf("http://%s/%s", host, id.String()) 105 106 var req *http.Request 107 108 req, err = http.NewRequest("GET", url, nil) 109 if err != nil { 110 return 111 } 112 req.Close = true 113 client := http.DefaultClient 114 var resp *http.Response 115 resp, err = client.Do(req) 116 117 // resp, err = http.Get(url) 118 if err == nil { 119 var b []byte 120 b, err = ioutil.ReadAll(resp.Body) 121 if err == nil { 122 var nodes []BSResp 123 err = json.Unmarshal(b, &nodes) 124 if err == nil { 125 err = h.checkBSResponses(nodes) 126 127 } 128 } 129 resp.Body.Close() 130 131 } 132 return 133 }