diff --git a/src/fsys/dir.go b/src/fsys/dir.go index 996207b..fd5c9fe 100644 --- a/src/fsys/dir.go +++ b/src/fsys/dir.go @@ -91,3 +91,26 @@ func GetDir(path string, recursive bool) (*Directory, error) { return &directory, nil } + +var FILES []*File + +// Returns every file in that directory +func (dir *Directory) GetAllFiles(recursively bool) []*File { + var files []*File = dir.Files + + if recursively { + if len(dir.Directories) == 0 { + return files + } + + for _, innerDir := range dir.Directories { + innerFiles := innerDir.GetAllFiles(recursively) + files = append(files, innerFiles...) + } + + } else { + files = dir.Files + } + + return files +} diff --git a/src/fsys/dir_test.go b/src/fsys/dir_test.go index 70747d9..660caac 100644 --- a/src/fsys/dir_test.go +++ b/src/fsys/dir_test.go @@ -26,7 +26,32 @@ func Test_GetDirRecursive(t *testing.T) { for _, innerDir := range dir.Directories { if innerDir.Size > dir.Size { - t.Errorf("inner dir cannot have a bigger size (%d B) than its parent`s total size (%d B)", innerDir.Size, dir.Size) + t.Fatalf("inner dir cannot have a bigger size (%d B) than its parent`s total size (%d B)", innerDir.Size, dir.Size) } } } + +func Test_GetFiles(t *testing.T) { + dirpath := "../testfiles/" + + dir, err := GetDir(dirpath, true) + if err != nil { + t.Fatalf("%s", err) + } + + // recursive + files := dir.GetAllFiles(true) + + fileCount := 5 + if len(files) != fileCount { + t.Fatalf("expected to get %d files; got %d\n", fileCount, len(files)) + } + + // not recursive + files = dir.GetAllFiles(false) + fileCount = 1 + if len(files) != fileCount { + t.Fatalf("expected to get %d files; got %d\n", fileCount, len(files)) + } + +} diff --git a/src/node/node.go b/src/node/node.go index f4c6da1..89f027a 100644 --- a/src/node/node.go +++ b/src/node/node.go @@ -65,9 +65,9 @@ type Node struct { // Creates a new either a sending or receiving node with specified options func NewNode(options *NodeOptions) (*Node, error) { - var isDir bool if options.IsSending { + // sending node preparation sendingPathStats, err := os.Stat(options.ServerSide.ServingPath) if err != nil { return nil, err @@ -80,6 +80,12 @@ func NewNode(options *NodeOptions) (*Node, error) { case false: isDir = false } + } else { + // receiving node preparation + err := os.MkdirAll(options.ClientSide.DownloadsFolderPath, os.ModePerm) + if err != nil { + return nil, err + } } node := Node{ @@ -252,15 +258,73 @@ func (node *Node) Start() { // react based on a header of a received packet switch incomingPacket.Header { + case protocol.HeaderReady: // the other node is ready to receive file data node.transferInfo.Sending.CanSendBytes = true case protocol.HeaderAccept: + // the receiving node has accepted the transfer node.state.AllowedToTransfer = true fmt.Printf("Transfer allowed. Sending...\n") + // notify it about all the files that are going to be sent + switch node.transferInfo.Sending.IsDirectory { + case true: + // send file packets for the files in the directory + + var filesToSend []*fsys.File + if node.transferInfo.Sending.Recursive { + filesToSend = dir.GetAllFiles(true) + } else { + filesToSend = dir.GetAllFiles(false) + } + + for _, file := range filesToSend { + filePacket, err := protocol.CreateFilePacket(file) + if err != nil { + panic(err) + } + + // encrypt if necessary + if node.netInfo.EncryptionKey != nil { + encryptedBody, err := encryption.Encrypt(node.netInfo.EncryptionKey, filePacket.Body) + if err != nil { + panic(err) + } + filePacket.Body = encryptedBody + } + + err = protocol.SendPacket(node.netInfo.Conn, *filePacket) + if err != nil { + panic(err) + } + } + + case false: + // send a filepacket of a single file + + filePacket, err := protocol.CreateFilePacket(file) + if err != nil { + panic(err) + } + + // encrypt if necessary + if node.netInfo.EncryptionKey != nil { + encryptedBody, err := encryption.Encrypt(node.netInfo.EncryptionKey, filePacket.Body) + if err != nil { + panic(err) + } + filePacket.Body = encryptedBody + } + + err = protocol.SendPacket(node.netInfo.Conn, *filePacket) + if err != nil { + panic(err) + } + } + case protocol.HeaderReject: node.state.Stopped = true @@ -400,40 +464,6 @@ func (node *Node) Start() { if strings.EqualFold(answer, "y") || answer == "" { // yes - if file != nil { - // file - err = os.MkdirAll(filepath.Join(node.transferInfo.Receiving.DownloadsPath), os.ModePerm) - if err != nil { - panic(err) - } - fullFilePath := filepath.Join(node.transferInfo.Receiving.DownloadsPath, file.Name) - - // check if the file already exists; if yes - remove it and replace with a new one - _, err := os.Stat(fullFilePath) - if err == nil { - // exists - // remove it - os.Remove(fullFilePath) - } - - file.Path = fullFilePath - file.Open() - - node.mutex.Lock() - node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles, file) - node.mutex.Unlock() - - } else if dir != nil { - // directory - - // add a new directory to downloads path - node.transferInfo.Receiving.DownloadsPath = filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name) - err = os.MkdirAll(node.transferInfo.Receiving.DownloadsPath, os.ModePerm) - if err != nil { - panic(err) - } - } - // send aceptance packet responsePacketFileIDBuffer := new(bytes.Buffer) binary.Write(responsePacketFileIDBuffer, binary.BigEndian, file.ID) @@ -493,8 +523,42 @@ func (node *Node) Start() { }() case protocol.HeaderFile: - // process an information about a singe file - // (TODO) + // add file to the accepted files; + + file, err := protocol.DecodeFilePacket(incomingPacket) + if err != nil { + panic(err) + } + fullFilePath := filepath.Join(node.transferInfo.Receiving.DownloadsPath, file.Name) + + // check if the file already exists; if yes - remove it and replace with a new one + _, err = os.Stat(fullFilePath) + if err == nil { + // exists + // remove it + os.Remove(fullFilePath) + } + + file.Path = fullFilePath + file.Open() + + node.mutex.Lock() + node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles, file) + node.mutex.Unlock() + + case protocol.HeaderDirectory: + // directory + dir, err := protocol.DecodeDirectoryPacket(incomingPacket) + if err != nil { + panic(err) + } + + // add a new directory to downloads path + node.transferInfo.Receiving.DownloadsPath = filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name) + err = os.MkdirAll(node.transferInfo.Receiving.DownloadsPath, os.ModePerm) + if err != nil { + panic(err) + } case protocol.HeaderFileBytes: // check if this file has been accepted to receive @@ -531,7 +595,7 @@ func (node *Node) Start() { // one of the files has been received completely, // compare checksums and check if it is the last // file in the transfer - // (TODO) + fileIDReader := bytes.NewReader(incomingPacket.Body) var fileID uint64 err := binary.Read(fileIDReader, binary.BigEndian, &fileID) diff --git a/src/protocol/recv.go b/src/protocol/recv.go index 530abc2..aacd0cf 100644 --- a/src/protocol/recv.go +++ b/src/protocol/recv.go @@ -38,7 +38,7 @@ func ReadFromConn(connection net.Conn) ([]byte, error) { packetBuffer.Write(buff[:read]) } - // fmt.Printf("[RECV] read from connection: %s; length: %d\n", packetBuffer.Bytes()[:30], packetBuffer.Len()) + fmt.Printf("[RECV] read from connection: %s; length: %d\n", packetBuffer.Bytes()[:30], packetBuffer.Len()) return packetBuffer.Bytes(), nil } diff --git a/src/protocol/send.go b/src/protocol/send.go index c4d90f2..cb240f8 100644 --- a/src/protocol/send.go +++ b/src/protocol/send.go @@ -20,7 +20,7 @@ func SendPacket(connection net.Conn, packet Packet) error { return err } - // fmt.Printf("[SEND] packet %+s; len: %d\n", packetBytes[:30], len(packetBytes)) + fmt.Printf("[SEND] packet %+s; len: %d\n", packetBytes[:30], len(packetBytes)) // write the result (ie: (packetsize)(header)~(bodybytes)) connection.Write(packetBytes)