swarm/...: There is a response header to show if content was encrypted

DPA.Retrieve() also returns this information
This commit is contained in:
Balint Gabor 2018-04-10 13:54:58 +02:00
parent 3d1a1aa459
commit c342a8c376
11 changed files with 49 additions and 28 deletions

View file

@ -238,7 +238,7 @@ func (self *Api) Upload(uploadDir, index string, toEncrypt bool) (hash string, e
} }
// DPA reader API // DPA reader API
func (self *Api) Retrieve(key storage.Key) storage.LazySectionReader { func (self *Api) Retrieve(key storage.Key) (reader storage.LazySectionReader, isEncrypted bool) {
return self.dpa.Retrieve(key) return self.dpa.Retrieve(key)
} }
@ -344,7 +344,7 @@ func (self *Api) Get(key storage.Key, path string) (reader storage.LazySectionRe
} else { } else {
mimeType = entry.ContentType mimeType = entry.ContentType
log.Trace("content lookup key", "key", key, "mimetype", mimeType) log.Trace("content lookup key", "key", key, "mimetype", mimeType)
reader = self.dpa.Retrieve(key) reader, _ = self.dpa.Retrieve(key)
} }
} else { } else {
status = http.StatusNotFound status = http.StatusNotFound
@ -482,7 +482,7 @@ func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, conte
buf := make([]byte, buffSize) buf := make([]byte, buffSize)
oldReader := self.Retrieve(oldKey) oldReader, _ := self.Retrieve(oldKey)
io.ReadAtLeast(oldReader, buf, int(offset)) io.ReadAtLeast(oldReader, buf, int(offset))
newReader := bytes.NewReader(content) newReader := bytes.NewReader(content)

View file

@ -74,7 +74,7 @@ func TestClientUploadDownloadFiles(t *testing.T) {
Size: int64(len(data)), Size: int64(len(data)),
}, },
} }
hash, err := client.Upload(file, manifest) hash, err := client.Upload(file, manifest, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -168,7 +168,7 @@ func TestClientUploadDownloadDirectory(t *testing.T) {
// upload the directory // upload the directory
client := NewClient(srv.URL) client := NewClient(srv.URL)
defaultPath := filepath.Join(dir, testDirFiles[0]) defaultPath := filepath.Join(dir, testDirFiles[0])
hash, err := client.UploadDirectory(dir, defaultPath, "") hash, err := client.UploadDirectory(dir, defaultPath, "", false)
if err != nil { if err != nil {
t.Fatalf("error uploading directory: %s", err) t.Fatalf("error uploading directory: %s", err)
} }
@ -224,7 +224,7 @@ func TestClientFileList(t *testing.T) {
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
client := NewClient(srv.URL) client := NewClient(srv.URL)
hash, err := client.UploadDirectory(dir, "", "") hash, err := client.UploadDirectory(dir, "", "", false)
if err != nil { if err != nil {
t.Fatalf("error uploading directory: %s", err) t.Fatalf("error uploading directory: %s", err)
} }

View file

@ -273,7 +273,7 @@ func retrieveToFile(quitC chan bool, dpa *storage.DPA, key storage.Key, path str
if err != nil { if err != nil {
return err return err
} }
reader := dpa.Retrieve(key) reader, _ := dpa.Retrieve(key)
writer := bufio.NewWriter(f) writer := bufio.NewWriter(f)
size, err := reader.Size(quitC) size, err := reader.Size(quitC)
if err != nil { if err != nil {

View file

@ -556,13 +556,15 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
} }
// check the root chunk exists by retrieving the file's size // check the root chunk exists by retrieving the file's size
reader := s.api.Retrieve(key) reader, isEncrypted := s.api.Retrieve(key)
if _, err := reader.Size(nil); err != nil { if _, err := reader.Size(nil); err != nil {
getFail.Inc(1) getFail.Inc(1)
Respond(w, r, fmt.Sprintf("root chunk not found %s: %s", key, err), http.StatusNotFound) Respond(w, r, fmt.Sprintf("root chunk not found %s: %s", key, err), http.StatusNotFound)
return return
} }
w.Header().Set("X-Encrypted", fmt.Sprintf("%v", isEncrypted))
switch { switch {
case r.uri.Raw() || r.uri.DeprecatedRaw(): case r.uri.Raw() || r.uri.DeprecatedRaw():
// allow the request to overwrite the content type using a query // allow the request to overwrite the content type using a query
@ -619,11 +621,12 @@ func (s *Server) HandleGetFiles(w http.ResponseWriter, r *Request) {
} }
// retrieve the entry's key and size // retrieve the entry's key and size
reader := s.api.Retrieve(storage.Key(common.Hex2Bytes(entry.Hash))) reader, isEncrypted := s.api.Retrieve(storage.Key(common.Hex2Bytes(entry.Hash)))
size, err := reader.Size(nil) size, err := reader.Size(nil)
if err != nil { if err != nil {
return err return err
} }
w.Header().Set("X-Encrypted", fmt.Sprintf("%v", isEncrypted))
// write a tar header for the entry // write a tar header for the entry
hdr := &tar.Header{ hdr := &tar.Header{

View file

@ -472,7 +472,7 @@ func TestBzzRootRedirect(t *testing.T) {
Size: int64(len(data)), Size: int64(len(data)),
}, },
} }
hash, err := client.Upload(file, "") hash, err := client.Upload(file, "", false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -205,12 +205,12 @@ type manifestTrieEntry struct {
func loadManifest(dpa *storage.DPA, hash storage.Key, quitC chan bool) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand func loadManifest(dpa *storage.DPA, hash storage.Key, quitC chan bool) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand
log.Trace("manifest lookup", "key", hash) log.Trace("manifest lookup", "key", hash)
// retrieve manifest via DPA // retrieve manifest via DPA
manifestReader := dpa.Retrieve(hash) manifestReader, isEncrypted := dpa.Retrieve(hash)
log.Trace("reader retrieved", "key", hash) log.Trace("reader retrieved", "key", hash)
return readManifest(manifestReader, hash, dpa, quitC) return readManifest(manifestReader, hash, dpa, isEncrypted, quitC)
} }
func readManifest(manifestReader storage.LazySectionReader, hash storage.Key, dpa *storage.DPA, quitC chan bool) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand func readManifest(manifestReader storage.LazySectionReader, hash storage.Key, dpa *storage.DPA, isEncrypted bool, quitC chan bool) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand
// TODO check size for oversized manifests // TODO check size for oversized manifests
size, err := manifestReader.Size(quitC) size, err := manifestReader.Size(quitC)
@ -245,7 +245,7 @@ func readManifest(manifestReader storage.LazySectionReader, hash storage.Key, dp
trie = &manifestTrie{ trie = &manifestTrie{
dpa: dpa, dpa: dpa,
encrypted: (len(hash) > dpa.HashSize()), encrypted: isEncrypted,
} }
for _, entry := range man.Entries { for _, entry := range man.Entries {
trie.addEntry(entry, quitC) trie.addEntry(entry, quitC)

View file

@ -44,7 +44,7 @@ func testGetEntry(t *testing.T, path, match string, multiple bool, paths ...stri
quitC := make(chan bool) quitC := make(chan bool)
dpa := storage.NewDPA(nil, storage.NewDPAParams()) dpa := storage.NewDPA(nil, storage.NewDPAParams())
ref := make([]byte, dpa.HashSize()) ref := make([]byte, dpa.HashSize())
trie, err := readManifest(manifest(paths...), ref, dpa, quitC) trie, err := readManifest(manifest(paths...), ref, dpa, false, quitC)
if err != nil { if err != nil {
t.Errorf("unexpected error making manifest: %v", err) t.Errorf("unexpected error making manifest: %v", err)
} }
@ -101,7 +101,7 @@ func TestExactMatch(t *testing.T) {
mf := manifest("shouldBeExactMatch.css", "shouldBeExactMatch.css.map") mf := manifest("shouldBeExactMatch.css", "shouldBeExactMatch.css.map")
dpa := storage.NewDPA(nil, storage.NewDPAParams()) dpa := storage.NewDPA(nil, storage.NewDPAParams())
ref := make([]byte, dpa.HashSize()) ref := make([]byte, dpa.HashSize())
trie, err := readManifest(mf, ref, dpa, quitC) trie, err := readManifest(mf, ref, dpa, false, quitC)
if err != nil { if err != nil {
t.Errorf("unexpected error making manifest: %v", err) t.Errorf("unexpected error making manifest: %v", err)
} }
@ -134,7 +134,7 @@ func TestAddFileWithManifestPath(t *testing.T) {
} }
dpa := storage.NewDPA(nil, storage.NewDPAParams()) dpa := storage.NewDPA(nil, storage.NewDPAParams())
ref := make([]byte, dpa.HashSize()) ref := make([]byte, dpa.HashSize())
trie, err := readManifest(reader, ref, dpa, nil) trie, err := readManifest(reader, ref, dpa, false, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -82,7 +82,7 @@ func (file *SwarmFile) Attr(ctx context.Context, a *fuse.Attr) error {
a.Gid = uint32(os.Getegid()) a.Gid = uint32(os.Getegid())
if file.fileSize == -1 { if file.fileSize == -1 {
reader := file.mountInfo.swarmApi.Retrieve(file.key) reader, _ := file.mountInfo.swarmApi.Retrieve(file.key)
quitC := make(chan bool) quitC := make(chan bool)
size, err := reader.Size(quitC) size, err := reader.Size(quitC)
if err != nil { if err != nil {
@ -99,7 +99,7 @@ func (sf *SwarmFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse
sf.lock.RLock() sf.lock.RLock()
defer sf.lock.RUnlock() defer sf.lock.RUnlock()
if sf.reader == nil { if sf.reader == nil {
sf.reader = sf.mountInfo.swarmApi.Retrieve(sf.key) sf.reader, _ = sf.mountInfo.swarmApi.Retrieve(sf.key)
} }
buf := make([]byte, req.Size) buf := make([]byte, req.Size)
n, err := sf.reader.ReadAt(buf, req.Offset) n, err := sf.reader.ReadAt(buf, req.Offset)

View file

@ -216,7 +216,7 @@ func (r *TestRegistry) APIs() []rpc.API {
} }
func readAll(dpa *storage.DPA, hash []byte) (int64, error) { func readAll(dpa *storage.DPA, hash []byte) (int64, error) {
r := dpa.Retrieve(hash) r, _ := dpa.Retrieve(hash)
buf := make([]byte, 1024) buf := make([]byte, 1024)
var n int var n int
var total int64 var total int64

View file

@ -89,9 +89,12 @@ func NewDPA(store ChunkStore, params *DPAParams) *DPA {
// FS-aware API and httpaccess // FS-aware API and httpaccess
// Chunk retrieval blocks on netStore requests with a timeout so reader will // Chunk retrieval blocks on netStore requests with a timeout so reader will
// report error if retrieval of chunks within requested range time out. // report error if retrieval of chunks within requested range time out.
func (self *DPA) Retrieve(key Key) LazySectionReader { // It returns a reader with the chunk data and whether the content was encrypted
getter := NewHasherStore(self.ChunkStore, self.hashFunc, len(key) > self.hashFunc().Size()) func (self *DPA) Retrieve(key Key) (reader LazySectionReader, isEncrypted bool) {
return TreeJoin(key, getter, 0) isEncrypted = len(key) > self.hashFunc().Size()
getter := NewHasherStore(self.ChunkStore, self.hashFunc, isEncrypted)
reader = TreeJoin(key, getter, 0)
return
} }
// Public API. Main entry point for document storage directly. Used by the // Public API. Main entry point for document storage directly. Used by the

View file

@ -54,7 +54,10 @@ func testDpaRandom(toEncrypt bool, t *testing.T) {
t.Errorf("Store error: %v", err) t.Errorf("Store error: %v", err)
} }
wait() wait()
resultReader := dpa.Retrieve(key) resultReader, isEncrypted := dpa.Retrieve(key)
if isEncrypted != toEncrypt {
t.Fatalf("isEncrypted expected %v got %v", toEncrypt, isEncrypted)
}
resultSlice := make([]byte, len(slice)) resultSlice := make([]byte, len(slice))
n, err := resultReader.ReadAt(resultSlice, 0) n, err := resultReader.ReadAt(resultSlice, 0)
if err != io.EOF { if err != io.EOF {
@ -69,7 +72,10 @@ func testDpaRandom(toEncrypt bool, t *testing.T) {
ioutil.WriteFile("/tmp/slice.bzz.16M", slice, 0666) ioutil.WriteFile("/tmp/slice.bzz.16M", slice, 0666)
ioutil.WriteFile("/tmp/result.bzz.16M", resultSlice, 0666) ioutil.WriteFile("/tmp/result.bzz.16M", resultSlice, 0666)
localStore.memStore = NewMemStore(db, defaultCacheCapacity) localStore.memStore = NewMemStore(db, defaultCacheCapacity)
resultReader = dpa.Retrieve(key) resultReader, isEncrypted = dpa.Retrieve(key)
if isEncrypted != toEncrypt {
t.Fatalf("isEncrypted expected %v got %v", toEncrypt, isEncrypted)
}
for i := range resultSlice { for i := range resultSlice {
resultSlice[i] = 0 resultSlice[i] = 0
} }
@ -109,7 +115,10 @@ func testDPA_capacity(toEncrypt bool, t *testing.T) {
t.Errorf("Store error: %v", err) t.Errorf("Store error: %v", err)
} }
wait() wait()
resultReader := dpa.Retrieve(key) resultReader, isEncrypted := dpa.Retrieve(key)
if isEncrypted != toEncrypt {
t.Fatalf("isEncrypted expected %v got %v", toEncrypt, isEncrypted)
}
resultSlice := make([]byte, len(slice)) resultSlice := make([]byte, len(slice))
n, err := resultReader.ReadAt(resultSlice, 0) n, err := resultReader.ReadAt(resultSlice, 0)
if err != io.EOF { if err != io.EOF {
@ -125,14 +134,20 @@ func testDPA_capacity(toEncrypt bool, t *testing.T) {
memStore.setCapacity(0) memStore.setCapacity(0)
// check whether it is, indeed, empty // check whether it is, indeed, empty
dpa.ChunkStore = memStore dpa.ChunkStore = memStore
resultReader = dpa.Retrieve(key) resultReader, isEncrypted = dpa.Retrieve(key)
if isEncrypted != toEncrypt {
t.Fatalf("isEncrypted expected %v got %v", toEncrypt, isEncrypted)
}
if _, err = resultReader.ReadAt(resultSlice, 0); err == nil { if _, err = resultReader.ReadAt(resultSlice, 0); err == nil {
t.Errorf("Was able to read %d bytes from an empty memStore.", len(slice)) t.Errorf("Was able to read %d bytes from an empty memStore.", len(slice))
} }
// check how it works with localStore // check how it works with localStore
dpa.ChunkStore = localStore dpa.ChunkStore = localStore
// localStore.dbStore.setCapacity(0) // localStore.dbStore.setCapacity(0)
resultReader = dpa.Retrieve(key) resultReader, isEncrypted = dpa.Retrieve(key)
if isEncrypted != toEncrypt {
t.Fatalf("isEncrypted expected %v got %v", toEncrypt, isEncrypted)
}
for i := range resultSlice { for i := range resultSlice {
resultSlice[i] = 0 resultSlice[i] = 0
} }