Browse Source

[fsys] fixed relative path finding; [node] fixed recursive transfer of a directory

main
Unbewohnte 3 years ago
parent
commit
6ec5eabc93
  1. 31
      src/fsys/dir.go
  2. 36
      src/fsys/dir_test.go
  3. 19
      src/fsys/file.go
  4. 107
      src/node/node.go
  5. 2
      src/protocol/packetConstruct.go
  6. 7
      src/protocol/send.go
  7. 1
      src/testfiles/testdir3/nested1/nested2/testfilen.txt

31
src/fsys/dir.go

@ -65,10 +65,6 @@ func GetDir(path string, recursive bool) (*Directory, error) {
return nil, err return nil, err
} }
for _, file := range innerDir.Files {
file.RelativeParentPath = filepath.Join(directory.Name, innerDir.Name, file.Name)
}
directory.Size += innerDir.Size directory.Size += innerDir.Size
innerDirs = append(innerDirs, innerDir) innerDirs = append(innerDirs, innerDir)
@ -83,8 +79,6 @@ func GetDir(path string, recursive bool) (*Directory, error) {
return nil, err return nil, err
} }
innerFile.RelativeParentPath = filepath.Join(directory.Name, innerFile.Name)
directory.Size += innerFile.Size directory.Size += innerFile.Size
innerFiles = append(innerFiles, innerFile) innerFiles = append(innerFiles, innerFile)
@ -98,16 +92,16 @@ func GetDir(path string, recursive bool) (*Directory, error) {
} }
// Returns every file in that directory // Returns every file in that directory
func (dir *Directory) GetAllFiles(recursively bool) []*File { func (dir *Directory) GetAllFiles(recursive bool) []*File {
var files []*File = dir.Files var files []*File = dir.Files
if recursively { if recursive {
if len(dir.Directories) == 0 { if len(dir.Directories) == 0 {
return files return files
} }
for _, innerDir := range dir.Directories { for _, innerDir := range dir.Directories {
innerFiles := innerDir.GetAllFiles(recursively) innerFiles := innerDir.GetAllFiles(recursive)
files = append(files, innerFiles...) files = append(files, innerFiles...)
} }
@ -117,3 +111,22 @@ func (dir *Directory) GetAllFiles(recursively bool) []*File {
return files return files
} }
// Sets `RelativeParentPath` relative to the given base path.
// file with such path:
// /home/user/directory/somefile.txt
// had a relative path like that:
// /directory/somefile.txt
// (where base path is /home/user/directory)
func (dir *Directory) SetRelativePaths(base string, recursive bool) error {
for _, file := range dir.GetAllFiles(recursive) {
relPath, err := filepath.Rel(base, file.Path)
if err != nil {
return err
}
file.RelativeParentPath = relPath
}
return nil
}

36
src/fsys/dir_test.go

@ -1,6 +1,8 @@
package fsys package fsys
import "testing" import (
"testing"
)
func Test_GetDir(t *testing.T) { func Test_GetDir(t *testing.T) {
dirpath := "../testfiles/" dirpath := "../testfiles/"
@ -30,13 +32,6 @@ func Test_GetDirRecursive(t *testing.T) {
} }
} }
// t.Errorf("[initialdir] %+v", dir.Files[0])
// for _, dir := range dir.Directories {
// for countf, file := range dir.Files {
// t.Errorf("[%d] %+v\n", countf, file)
// }
// }
} }
func Test_GetFiles(t *testing.T) { func Test_GetFiles(t *testing.T) {
@ -50,7 +45,7 @@ func Test_GetFiles(t *testing.T) {
// recursive // recursive
files := dir.GetAllFiles(true) files := dir.GetAllFiles(true)
fileCount := 5 fileCount := 6
if len(files) != fileCount { if len(files) != fileCount {
t.Fatalf("expected to get %d files; got %d\n", fileCount, len(files)) t.Fatalf("expected to get %d files; got %d\n", fileCount, len(files))
} }
@ -63,3 +58,26 @@ func Test_GetFiles(t *testing.T) {
} }
} }
// func Test_SetRelativePaths(t *testing.T) {
// dirpath := "../testfiles/"
// dir, err := GetDir(dirpath, true)
// if err != nil {
// t.Fatalf("%s", err)
// }
// absDirPath, err := filepath.Abs(dirpath)
// if err != nil {
// t.Fatalf("%s", err)
// }
// err = dir.SetRelativePaths(absDirPath, true)
// if err != nil {
// t.Fatalf("%s", err)
// }
// for count, file := range dir.GetAllFiles(true) {
// t.Errorf("[%d] %v\n", count, file.RelativeParentPath)
// }
// }

19
src/fsys/file.go

@ -54,7 +54,7 @@ func GetFile(path string) (*File, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer file.Handler.Close() defer file.Close()
checksum, err := checksum.GetPartialCheckSum(file.Handler) checksum, err := checksum.GetPartialCheckSum(file.Handler)
if err != nil { if err != nil {
@ -68,6 +68,10 @@ func GetFile(path string) (*File, error) {
// Opens file for read/write operations // Opens file for read/write operations
func (file *File) Open() error { func (file *File) Open() error {
if file.Handler != nil {
file.Close()
}
handler, err := os.OpenFile(file.Path, os.O_CREATE|os.O_RDWR, os.ModePerm) handler, err := os.OpenFile(file.Path, os.O_CREATE|os.O_RDWR, os.ModePerm)
if err != nil { if err != nil {
return err return err
@ -76,3 +80,16 @@ func (file *File) Open() error {
return nil return nil
} }
// file.Handler.Close wrapper
func (file *File) Close() error {
if file.Handler != nil {
err := file.Handler.Close()
if err != nil {
return err
}
file.Handler = nil
}
return nil
}

107
src/node/node.go

@ -84,10 +84,17 @@ func NewNode(options *NodeOptions) (*Node, error) {
} }
} else { } else {
// receiving node preparation // receiving node preparation
err := os.MkdirAll(options.ClientSide.DownloadsFolderPath, os.ModePerm) var err error
options.ClientSide.DownloadsFolderPath, err = filepath.Abs(options.ClientSide.DownloadsFolderPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = os.MkdirAll(options.ClientSide.DownloadsFolderPath, os.ModePerm)
if err != nil {
return nil, err
}
} }
node := Node{ node := Node{
@ -219,7 +226,7 @@ func (node *Node) Start() {
fmt.Printf("Sending \"%s\" (%.3f %s) locally on %s:%d\n", dirToSend.Name, size, sizeLevel, localIP, node.netInfo.Port) fmt.Printf("Sending \"%s\" (%.3f %s) locally on %s:%d\n", dirToSend.Name, size, sizeLevel, localIP, node.netInfo.Port)
} else { } else {
size := float32(dirToSend.Size) / 1024 / 1024 size := float32(fileToSend.Size) / 1024 / 1024
sizeLevel := "MiB" sizeLevel := "MiB"
if size >= 1024 { if size >= 1024 {
// GiB // GiB
@ -292,12 +299,11 @@ func (node *Node) Start() {
case true: case true:
// send file packets for the files in the directory // send file packets for the files in the directory
var filesToSend []*fsys.File err = dirToSend.SetRelativePaths(dirToSend.Path, node.transferInfo.Sending.Recursive)
if node.transferInfo.Sending.Recursive { if err != nil {
filesToSend = dirToSend.GetAllFiles(true) panic(err)
} else {
filesToSend = dirToSend.GetAllFiles(false)
} }
filesToSend := dirToSend.GetAllFiles(node.transferInfo.Sending.Recursive)
// notify the other node about all the files that are going to be sent // notify the other node about all the files that are going to be sent
for counter, file := range filesToSend { for counter, file := range filesToSend {
@ -309,6 +315,8 @@ func (node *Node) Start() {
// set current file id to the first file // set current file id to the first file
node.transferInfo.Sending.CurrentFileIndex = 0 node.transferInfo.Sending.CurrentFileIndex = 0
// fmt.Printf("[%d] rel path: %s\n", file.ID, file.RelativeParentPath)
filePacket, err := protocol.CreateFilePacket(file) filePacket, err := protocol.CreateFilePacket(file)
if err != nil { if err != nil {
panic(err) panic(err)
@ -327,6 +335,7 @@ func (node *Node) Start() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
case false: case false:
@ -370,24 +379,24 @@ func (node *Node) Start() {
// Transfer section // Transfer section
if len(node.transferInfo.Sending.FilesToSend) == 0 {
// if there`s nothing else to send - create and send DONE packet
protocol.SendPacket(node.netInfo.Conn, protocol.Packet{
Header: protocol.HeaderDone,
})
fmt.Printf("Transfer ended successfully\n")
node.state.Stopped = true
}
// if allowed to transfer and the other node is ready to receive packets - send one piece // if allowed to transfer and the other node is ready to receive packets - send one piece
// and wait for it to be ready again // and wait for it to be ready again
if node.state.AllowedToTransfer && node.transferInfo.Sending.CanSendBytes { if node.state.AllowedToTransfer && node.transferInfo.Sending.CanSendBytes {
if len(node.transferInfo.Sending.FilesToSend) == 0 {
// if there`s nothing else to send - create and send DONE packet
protocol.SendPacket(node.netInfo.Conn, protocol.Packet{
Header: protocol.HeaderDone,
})
fmt.Printf("Transfer ended successfully\n")
node.state.Stopped = true
}
// sending a piece of a single file // sending a piece of a single file
currentFileIndex := node.transferInfo.Sending.CurrentFileIndex currentFileIndex := node.transferInfo.Sending.CurrentFileIndex
err = protocol.SendPiece(node.transferInfo.Sending.FilesToSend[currentFileIndex], node.netInfo.Conn, node.netInfo.EncryptionKey) err = protocol.SendPiece(node.transferInfo.Sending.FilesToSend[currentFileIndex], node.netInfo.Conn, node.netInfo.EncryptionKey)
switch err { switch err {
case protocol.ErrorSentAll: case protocol.ErrorSentAll:
@ -520,18 +529,18 @@ func (node *Node) Start() {
if strings.EqualFold(answer, "y") || answer == "" { if strings.EqualFold(answer, "y") || answer == "" {
// yes // yes
// // in case it`s a directory - create it now // in case it`s a directory - create it now
// if dir != nil { if dir != nil {
// err = os.MkdirAll(filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name), os.ModePerm) err = os.MkdirAll(filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name), os.ModePerm)
// if err != nil { if err != nil {
// // well, just download all files in the default downloads folder then // well, just download all files in the default downloads folder then
// fmt.Printf("[ERROR] could not create a directory\n") fmt.Printf("[ERROR] could not create a directory\n")
// } else { } else {
// // also download everything in a newly created directory // also download everything in a newly created directory
// node.transferInfo.Receiving.DownloadsPath = filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name) node.transferInfo.Receiving.DownloadsPath = filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name)
// } }
// } }
// send aceptance packet // send aceptance packet
acceptancePacket := protocol.Packet{ acceptancePacket := protocol.Packet{
@ -578,10 +587,7 @@ func (node *Node) Start() {
panic(err) panic(err)
} }
file.Path, err = filepath.Abs(filepath.Join(node.transferInfo.Receiving.DownloadsPath, file.RelativeParentPath)) file.Path = filepath.Join(node.transferInfo.Receiving.DownloadsPath, file.RelativeParentPath)
if err != nil {
panic(err)
}
// create all underlying directories right ahead // create all underlying directories right ahead
err = os.MkdirAll(filepath.Dir(file.Path), os.ModePerm) err = os.MkdirAll(filepath.Dir(file.Path), os.ModePerm)
@ -597,8 +603,6 @@ func (node *Node) Start() {
os.Remove(file.Path) os.Remove(file.Path)
} }
file.Open()
node.mutex.Lock() node.mutex.Lock()
node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles, file) node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles, file)
node.mutex.Unlock() node.mutex.Unlock()
@ -620,8 +624,31 @@ func (node *Node) Start() {
// append provided bytes to the file // append provided bytes to the file
err = acceptedFile.Open()
if err != nil {
panic(err)
}
fileBytes := fileBytesBuffer.Bytes() fileBytes := fileBytesBuffer.Bytes()
_, err = acceptedFile.Handler.Write(fileBytes)
wrote, err := acceptedFile.Handler.WriteAt(fileBytes, int64(acceptedFile.SentBytes))
if err != nil {
panic(err)
// // fmt.Printf("[Debug] %+v\n", acceptedFile)
// // this file won`t be completed, so it`ll be ignored
// // remove this file from the pool
// node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles[:index], node.transferInfo.Receiving.AcceptedFiles[index+1:]...)
// fmt.Printf("[ERROR] an error occured when receiving a file \"%s\": %s. This file will not be completed", acceptedFile.Name, err)
// // remove it from the filesystem
// os.Remove(acceptedFile.Path)
}
acceptedFile.SentBytes += uint64(wrote)
err = acceptedFile.Close()
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -652,8 +679,10 @@ func (node *Node) Start() {
if acceptedFile.ID == fileID { if acceptedFile.ID == fileID {
// accepted // accepted
// close the handler afterwards err = acceptedFile.Open()
defer acceptedFile.Handler.Close() if err != nil {
panic(err)
}
// remove this file from the pool // remove this file from the pool
node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles[:index], node.transferInfo.Receiving.AcceptedFiles[index+1:]...) node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles[:index], node.transferInfo.Receiving.AcceptedFiles[index+1:]...)
@ -667,9 +696,11 @@ func (node *Node) Start() {
fmt.Printf("\n| Checking hashes for file \"%s\"\n", acceptedFile.Name) fmt.Printf("\n| Checking hashes for file \"%s\"\n", acceptedFile.Name)
if realChecksum != acceptedFile.Checksum { if realChecksum != acceptedFile.Checksum {
fmt.Printf("| %s --- %s file is corrupted\n", realChecksum, acceptedFile.Checksum) fmt.Printf("| %s --- %s file is corrupted\n", realChecksum, acceptedFile.Checksum)
acceptedFile.Close()
break break
} else { } else {
fmt.Printf("| %s --- %s\n", realChecksum, acceptedFile.Checksum) fmt.Printf("| %s --- %s\n", realChecksum, acceptedFile.Checksum)
acceptedFile.Close()
break break
} }
} }

2
src/protocol/packetConstruct.go

@ -14,7 +14,7 @@ func CreateFilePacket(file *fsys.File) (*Packet, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer file.Handler.Close() defer file.Close()
//(id in binary)(filename length in binary)(filename)(filesize)(checksum length in binary)(checksum)(relative path to the upper directory size in binary if present)(relative path) //(id in binary)(filename length in binary)(filename)(filesize)(checksum length in binary)(checksum)(relative path to the upper directory size in binary if present)(relative path)

7
src/protocol/send.go

@ -125,7 +125,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
if err != nil { if err != nil {
return err return err
} }
defer file.Handler.Close() defer file.Close()
if file.SentBytes == 0 { if file.SentBytes == 0 {
file.Handler.Seek(0, io.SeekStart) file.Handler.Seek(0, io.SeekStart)
@ -142,7 +142,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
packetBodyBuff := new(bytes.Buffer) packetBodyBuff := new(bytes.Buffer)
// write file ID first // write file ID first
err = binary.Write(packetBodyBuff, binary.BigEndian, &file.ID) err = binary.Write(packetBodyBuff, binary.BigEndian, file.ID)
if err != nil { if err != nil {
return err return err
} }
@ -165,6 +165,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
if err != nil { if err != nil {
return err return err
} }
file.SentBytes += uint64(read)
packetBodyBuff.Write(fileBytes) packetBodyBuff.Write(fileBytes)
@ -183,7 +184,5 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
return err return err
} }
file.SentBytes += uint64(read)
return nil return nil
} }

1
src/testfiles/testdir3/nested1/nested2/testfilen.txt

@ -0,0 +1 @@
test
Loading…
Cancel
Save