func (m *MessageRetriever) fetchPointers() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() mh, _ := multihash.FromB58String(m.node.Identity.Pretty()) peerOut := ipfs.FindPointersAsync(m.node.Routing.(*routing.IpfsDHT), ctx, mh, m.prefixLen) for p := range peerOut { if len(p.Addrs) > 0 && !m.db.OfflineMessages().Has(p.Addrs[0].String()) { // ipfs if len(p.Addrs[0].Protocols()) == 1 && p.Addrs[0].Protocols()[0].Code == 421 { go m.fetchIPFS(m.ctx, p.ID, p.Addrs[0]) } // https if len(p.Addrs[0].Protocols()) == 2 && p.Addrs[0].Protocols()[0].Code == 421 && p.Addrs[0].Protocols()[1].Code == 443 { enc, err := p.Addrs[0].ValueForProtocol(421) if err != nil { continue } mh, err := multihash.FromB58String(enc) if err != nil { continue } d, err := multihash.Decode(mh) if err != nil { continue } go m.fetchHTTPS(p.ID, string(d.Digest)) } m.db.OfflineMessages().Put(p.Addrs[0].String()) } } }
// converts the Node object into a real dag.Node func deserializeNode(node *Node, dataFieldEncoding string) (*dag.Node, error) { dagnode := new(dag.Node) switch dataFieldEncoding { case "text": dagnode.SetData([]byte(node.Data)) case "base64": data, _ := base64.StdEncoding.DecodeString(node.Data) dagnode.SetData(data) default: return nil, fmt.Errorf("Unkown data field encoding") } dagnode.Links = make([]*dag.Link, len(node.Links)) for i, link := range node.Links { hash, err := mh.FromB58String(link.Hash) if err != nil { return nil, err } dagnode.Links[i] = &dag.Link{ Name: link.Name, Size: link.Size, Hash: hash, } } return dagnode, nil }
// IDB58Decode returns a b58-decoded Peer func IDB58Decode(s string) (ID, error) { m, err := mh.FromB58String(s) if err != nil { return "", err } return ID(m), err }
// converts the Node object into a real dag.Node func deserializeNode(node *Node) (*dag.Node, error) { dagnode := new(dag.Node) dagnode.Data = []byte(node.Data) dagnode.Links = make([]*dag.Link, len(node.Links)) for i, link := range node.Links { hash, err := mh.FromB58String(link.Hash) if err != nil { return nil, err } dagnode.Links[i] = &dag.Link{ Name: link.Name, Size: link.Size, Hash: hash, } } return dagnode, nil }
func addressStringToBytes(p Protocol, s string) ([]byte, error) { switch p.Code { case P_IP4: // ipv4 i := net.ParseIP(s).To4() if i == nil { return nil, fmt.Errorf("failed to parse ip4 addr: %s", s) } return i, nil case P_IP6: // ipv6 i := net.ParseIP(s).To16() if i == nil { return nil, fmt.Errorf("failed to parse ip6 addr: %s", s) } return i, nil // tcp udp dccp sctp case P_TCP, P_UDP, P_DCCP, P_SCTP: i, err := strconv.Atoi(s) if err != nil { return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, err) } if i >= 65536 { return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "greater than 65536") } b := make([]byte, 2) binary.BigEndian.PutUint16(b, uint16(i)) return b, nil case P_IPFS: // ipfs // the address is a varint prefixed multihash string representation m, err := mh.FromB58String(s) if err != nil { return nil, fmt.Errorf("failed to parse ipfs addr: %s %s", s, err) } size := CodeToVarint(len(m)) b := append(size, m...) return b, nil } return []byte{}, fmt.Errorf("failed to parse %s addr: unknown", p.Name) }
// SplitAbsPath clean up and split fpath. It extracts the first component (which // must be a Multihash) and return it separately. func SplitAbsPath(fpath Path) (mh.Multihash, []string, error) { log.Debugf("Resolve: '%s'", fpath) parts := fpath.Segments() if parts[0] == "ipfs" { parts = parts[1:] } // if nothing, bail. if len(parts) == 0 { return nil, nil, ErrNoComponents } // first element in the path is a b58 hash (for now) h, err := mh.FromB58String(parts[0]) if err != nil { log.Debug("given path element is not a base58 string.\n") return nil, nil, err } return h, parts[1:], nil }
func getBlockForKey(req cmds.Request, skey string) (blocks.Block, error) { n, err := req.InvocContext().GetNode() if err != nil { return nil, err } if !u.IsValidHash(skey) { return nil, errors.New("Not a valid hash") } h, err := mh.FromB58String(skey) if err != nil { return nil, err } k := key.Key(h) b, err := n.Blocks.GetBlock(req.Context(), k) if err != nil { return nil, err } log.Debugf("ipfs block: got block with key: %q", b.Key()) return b, nil }
func (n *OpenBazaarNode) SendOfflineMessage(p peer.ID, m *pb.Message) error { log.Debugf("Sending offline message to %s", p.Pretty()) env := pb.Envelope{Message: m, PeerID: n.IpfsNode.Identity.Pretty()} messageBytes, merr := proto.Marshal(&env) if merr != nil { return merr } ciphertext, cerr := n.EncryptMessage(p, messageBytes) if cerr != nil { return cerr } addr, aerr := n.MessageStorage.Store(p, ciphertext) if aerr != nil { return aerr } ctx, cancel := context.WithCancel(context.Background()) defer cancel() mh, mherr := multihash.FromB58String(p.Pretty()) if mherr != nil { return mherr } // TODO: We're just using a default prefix length for now. Eventually we will want to customize this, // but we will need some way to get the recipient's desired prefix length. Likely will be in profile. pointer, err := ipfs.PublishPointer(n.IpfsNode, ctx, mh, 16, addr) if err != nil { return err } if m.MessageType != pb.Message_OFFLINE_ACK { pointer.Purpose = ipfs.MESSAGE err = n.Datastore.Pointers().Put(pointer) if err != nil { return err } } return nil }
// resolveOnce implements resolver. Uses the IPFS routing system to // resolve SFS-like names. func (r *routingResolver) resolveOnce(ctx context.Context, name string) (path.Path, error) { log.Debugf("RoutingResolve: '%s'", name) cached, ok := r.cacheGet(name) if ok { return cached, nil } hash, err := mh.FromB58String(name) if err != nil { // name should be a multihash. if it isn't, error out here. log.Warningf("RoutingResolve: bad input hash: [%s]\n", name) return "", err } // use the routing system to get the name. // /ipns/<name> h := []byte("/ipns/" + string(hash)) var entry *pb.IpnsEntry var pubkey ci.PubKey resp := make(chan error, 2) go func() { ipnsKey := key.Key(h) val, err := r.routing.GetValue(ctx, ipnsKey) if err != nil { log.Warning("RoutingResolve get failed.") resp <- err } entry = new(pb.IpnsEntry) err = proto.Unmarshal(val, entry) if err != nil { resp <- err } resp <- nil }() go func() { // name should be a public key retrievable from ipfs pubk, err := routing.GetPublicKey(r.routing, ctx, hash) if err != nil { resp <- err } pubkey = pubk resp <- nil }() for i := 0; i < 2; i++ { err = <-resp if err != nil { return "", err } } hsh, _ := pubkey.Hash() log.Debugf("pk hash = %s", key.Key(hsh)) // check sig with pk if ok, err := pubkey.Verify(ipnsEntryDataForSig(entry), entry.GetSignature()); err != nil || !ok { return "", fmt.Errorf("Invalid value. Not signed by PrivateKey corresponding to %v", pubkey) } // ok sig checks out. this is a valid name. // check for old style record: valh, err := mh.Cast(entry.GetValue()) if err != nil { // Not a multihash, probably a new record p, err := path.ParsePath(string(entry.GetValue())) if err != nil { return "", err } r.cacheSet(name, p, entry) return p, nil } else { // Its an old style multihash record log.Warning("Detected old style multihash record") p := path.FromKey(key.Key(valh)) r.cacheSet(name, p, entry) return p, nil } }
func addressStringToBytes(p Protocol, s string) ([]byte, error) { switch p.Code { case P_IP4: // ipv4 i := net.ParseIP(s).To4() if i == nil { return nil, fmt.Errorf("failed to parse ip4 addr: %s", s) } return i, nil case P_IP6: // ipv6 i := net.ParseIP(s).To16() if i == nil { return nil, fmt.Errorf("failed to parse ip6 addr: %s", s) } return i, nil // tcp udp dccp sctp case P_TCP, P_UDP, P_DCCP, P_SCTP: i, err := strconv.Atoi(s) if err != nil { return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, err) } if i >= 65536 { return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "greater than 65536") } b := make([]byte, 2) binary.BigEndian.PutUint16(b, uint16(i)) return b, nil case P_ONION: addr := strings.Split(s, ":") if len(addr) != 2 { return nil, fmt.Errorf("failed to parse %s addr: %s does not contain a port number.", p.Name, s) } // onion address without the ".onion" substring if len(addr[0]) != 16 { return nil, fmt.Errorf("failed to parse %s addr: %s not a Tor onion address.", p.Name, s) } onionHostBytes, err := base32.StdEncoding.DecodeString(strings.ToUpper(addr[0])) if err != nil { return nil, fmt.Errorf("failed to decode base32 %s addr: %s %s", p.Name, s, err) } // onion port number i, err := strconv.Atoi(addr[1]) if err != nil { return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, err) } if i >= 65536 { return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "port greater than 65536") } if i < 1 { return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "port less than 1") } onionPortBytes := make([]byte, 2) binary.BigEndian.PutUint16(onionPortBytes, uint16(i)) bytes := []byte{} bytes = append(bytes, onionHostBytes...) bytes = append(bytes, onionPortBytes...) return bytes, nil case P_IPFS: // ipfs // the address is a varint prefixed multihash string representation m, err := mh.FromB58String(s) if err != nil { return nil, fmt.Errorf("failed to parse ipfs addr: %s %s", s, err) } size := CodeToVarint(len(m)) b := append(size, m...) return b, nil } return []byte{}, fmt.Errorf("failed to parse %s addr: unknown", p.Name) }