// Retrieve value from AChord and decrypt it. func (c *Client) achordGet(b *buf) error { p := c.bufGet() defer c.bufPut(p) var n int var err error // BUG(ls): The decision to backoff and retry should be left to // callers. We have no good way to do that yet. We should probably // start by threading context values throughout the FS code so we can // at least support cancelation. Clients then cancel the contexts to // stop the retry loop. Especially important for FUSE as programs // accessing the FS end up unkillable if we don't do this. for i := 0; i < 10; i++ { n, err = c.kv.Get(context.TODO(), b.addr[:], p.data) if err == nil { break } if !netutil.IsTemporary(err) { return err } backoff(i, err) } if err != nil { return err } if n < blockOverhead { return syscall.EIO } pp := p.data[:n] var nonce [24]byte pp = pp[copy(nonce[:], pp):] zp, ok := secretbox.Open(nil, pp, &nonce, &c.key) if !ok { return errAuth } q := zp if b.addr != c.sbp { q, err = c.decode(nil, zp) if err != nil { return err } } copy(b.data, q) b.flags |= bufValid return nil } // Encrypt buffer and upload it to AChord. func (c *Client) achordPut(b *buf) error { p := c.bufGet() defer c.bufPut(p) zp := b.data if b.addr != c.sbp { // never compress or otherwise transform the superblock zp = c.encode(nil, b.data) } var nonce [24]byte if _, err := rand.Read(nonce[:]); err != nil { return err } pp := p.data[copy(p.data, nonce[:]):] q := secretbox.Seal(pp[:0], zp, &nonce, &c.key) var err error for i := 0; i < 10; i++ { err = c.kv.Put(context.TODO(), b.addr[:], p.data[:len(nonce)+len(q)]) if err == nil { b.flags &^= bufDirty break } if !netutil.IsTemporary(err) { return err } backoff(i, err) } return err }