Compare commits

...

16 Commits
2.1.2 ... main

Author SHA1 Message Date
Kasianov Nikolai Alekseevich 1d8f987c27 Removed old email from license notices; minor changes to the program output, help message 2 years ago
Gitea b30d0c3465 No more github 2 years ago
Gitea 6bb927a26e Being idependent from github 2 years ago
Unbewohnte c2bd2cb0cf Apparently my name is spelled differently in English ¯\_(ツ)_/¯ 3 years ago
Unbewohnte 2548fa68e7 Less syscalls to open files on the receiving end 3 years ago
Unbewohnte 8eb2f181fd Symlinks support ! 3 years ago
Unbewohnte 700811b179 [checksum] Micro optimisations; [node] Renamed nodes to receiving and sending; [fsys] ftu now DOES NOT die on 'permission denied's 3 years ago
Unbewohnte 21d16c590f Updated README: I can't be inspired by a thing I've never used, can I ?... Tehehe~ 3 years ago
Unbewohnte 4d12a15a58 [Node] Invalid transfer info printing is >>|FIXED|<< 3 years ago
Unbewohnte 382908c1e5 Updated copyright year 3 years ago
Unbewohnte e4c086b358 make release 3 years ago
Unbewohnte 0ac9cd2b71 v2.2.0; Fixed freezing on big amount of files; Improved transfer data printing; Introduction to some minor bugs with it as well, but that is not a severe problem anyway 3 years ago
Unbewohnte 75cb68dd30 [node] fixed one-file transfer logical issue 3 years ago
Unbewohnte 550c6e26ef [main] changed version 3 years ago
Unbewohnte 74464c9470 [main] verbose output flag changed to ?; [node] added 3 microsecond delay in sender node when sending file info packets 3 years ago
Unbewohnte a8e973645a [main] added a missing new line for verbose output usage message 3 years ago
  1. 34
      Makefile
  2. 13
      README.md
  3. 2
      src/addr/local.go
  4. 16
      src/checksum/checksum.go
  5. 2
      src/checksum/checksum_test.go
  6. 2
      src/encryption/decrypt.go
  7. 2
      src/encryption/encrypt.go
  8. 2
      src/encryption/encryption_test.go
  9. 2
      src/encryption/key.go
  10. 79
      src/fsys/dir.go
  11. 38
      src/fsys/dir_test.go
  12. 6
      src/fsys/file.go
  13. 2
      src/fsys/file_test.go
  14. 70
      src/fsys/symlink.go
  15. 42
      src/fsys/symlink_test.go
  16. 4
      src/go.mod
  17. 30
      src/main.go
  18. 1073
      src/node/node.go
  19. 10
      src/node/options.go
  20. 2
      src/protocol/constants.go
  21. 25
      src/protocol/headers.go
  22. 4
      src/protocol/packet.go
  23. 4
      src/protocol/packetConstruct.go
  24. 4
      src/protocol/packetDecode.go
  25. 2
      src/protocol/protocol_test.go
  26. 2
      src/protocol/recv.go
  27. 60
      src/protocol/send.go
  28. 1
      src/testfiles/testdir/testsymlink2.txt
  29. 1
      src/testfiles/testsymlink.txt

34
Makefile

@ -10,31 +10,31 @@ INSTALLATION_SCRIPT := install.sh
all:
cd $(SRC_DIR) && go build && mv $(EXE_NAME) ..
pkgrelease:
release:
rm -rf $(RELEASE_DIR)
mkdir $(RELEASE_DIR)
mkdir $(RELEASE_DIR)/linux_amd64
mkdir $(RELEASE_DIR)/darwin_amd64
mkdir $(RELEASE_DIR)/windows_amd64
mkdir $(RELEASE_DIR)/ftu_linux_amd64
mkdir $(RELEASE_DIR)/ftu_darwin_amd64
mkdir $(RELEASE_DIR)/ftu_windows_amd64
cd $(SRC_DIR) && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ftu && mv ftu ../$(RELEASE_DIR)/linux_amd64
cd $(SRC_DIR) && CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ftu && mv ftu ../$(RELEASE_DIR)/darwin_amd64
cd $(SRC_DIR) && CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ftu.exe && mv ftu.exe ../$(RELEASE_DIR)/windows_amd64
cd $(SRC_DIR) && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ftu && mv ftu ../$(RELEASE_DIR)/ftu_linux_amd64
cd $(SRC_DIR) && CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ftu && mv ftu ../$(RELEASE_DIR)/ftu_darwin_amd64
cd $(SRC_DIR) && CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ftu.exe && mv ftu.exe ../$(RELEASE_DIR)/ftu_windows_amd64
cp $(LICENSE_FILE) $(RELEASE_DIR)/linux_amd64
cp $(INSTALLATION_SCRIPT) $(RELEASE_DIR)/linux_amd64
cp $(LICENSE_FILE) $(RELEASE_DIR)/ftu_linux_amd64
cp $(INSTALLATION_SCRIPT) $(RELEASE_DIR)/ftu_linux_amd64
cp $(LICENSE_FILE) $(RELEASE_DIR)/darwin_amd64
cp $(LICENSE_FILE) $(RELEASE_DIR)/windows_amd64
cp $(LICENSE_FILE) $(RELEASE_DIR)/ftu_darwin_amd64
cp $(LICENSE_FILE) $(RELEASE_DIR)/ftu_windows_amd64
cd $(RELEASE_DIR) && zip -r linux_amd64 linux_amd64/
cd $(RELEASE_DIR) && zip -r darwin_amd64 darwin_amd64/
cd $(RELEASE_DIR) && zip -r windows_amd64 windows_amd64/
cd $(RELEASE_DIR) && zip -r ftu_linux_amd64 ftu_linux_amd64/
cd $(RELEASE_DIR) && zip -r ftu_darwin_amd64 ftu_darwin_amd64/
cd $(RELEASE_DIR) && zip -r ftu_windows_amd64 ftu_windows_amd64/
rm -rf $(RELEASE_DIR)/linux_amd64
rm -rf $(RELEASE_DIR)/darwin_amd64
rm -rf $(RELEASE_DIR)/windows_amd64
rm -rf $(RELEASE_DIR)/ftu_linux_amd64
rm -rf $(RELEASE_DIR)/ftu_darwin_amd64
rm -rf $(RELEASE_DIR)/ftu_windows_amd64
race:
cd $(SRC_DIR) && go build -race && mv $(EXE_NAME) ..

13
README.md

@ -16,7 +16,7 @@ In order to transfer one file on one computer to another - they need to establis
In order to establish a connection - there needs to be a 1) sender (server) (the owner of the file), waiting for connections, and a 2) receiver (client), who will try to connect to a sender (server). If the requirements are met - client will connect to server and the packet exchange will begin.
The server and the client needs to communicate with packets according to certain rules, given by a [protocol](https://github.com/Unbewohnte/ftu/tree/main/src/protocol).
The server and the client needs to communicate with packets according to certain rules, given by a [protocol](http://unbewohnte.xyz:3000/Unbewohnte/ftu/src/branch/main/src/protocol).
The packet has its header and body. They are divided into several groups of use by headers, this way we can specify what kind of data is stored inside packet`s body and react accordingly.
@ -28,13 +28,13 @@ Thus, with a connection and a way of communication, the sender will send some pa
## ● Installation
### ● From release (Pre-compiled)
- Proceed to [releases page](https://github.com/Unbewohnte/ftu/releases)
- Proceed to [releases page](http://unbewohnte.xyz:3000/Unbewohnte/ftu/releases)
- Choose a version/architecture you have and download an archive
- Unpack an archive
- If on GNU/Linux - run `chmod +x install.sh && sudo ./install.sh`
### ● From source (Compile it yourself) (You need [Go](https://golang.org/dl/) and [git](https://git-scm.com/) to be installed on your machine)
- `git clone https://github.com/Unbewohnte/ftu.git`
- `git clone http://unbewohnte.xyz:3000/Unbewohnte/ftu`
- `cd` into the folder
- If on GNU/Linux - run `make && sudo make install` or `make && chmod +x install.sh && sudo ./install`
- else - cd into src/ folder and simply run `go build`; after that you`re free to put the binary wherever you desire
@ -46,7 +46,7 @@ Now you have ftu installed !
## ● Usage
`ftu -h` - to print a usage message
`ftu [FLAGS]`
`ftu [FLAGs]`
### ● FLAGs
- -p [uint] for port
@ -54,6 +54,7 @@ Now you have ftu installed !
- -a [ip_address|domain_name] address to connect to (cannot be used with -s)
- -d [path_to_directory] where the files will be downloaded to (cannot be used with -s)
- -s [path_to_file|directory] to send it (cannot be used with -a)
- -? [true|false] to turn on|off verbose output
- -v print version text
- -l print license
@ -82,9 +83,5 @@ creates a node that will send every file in the directory !RECUSRIVELY!
---
## ● Inspired by [croc](https://github.com/schollz/croc)
---
## ● License
GPLv3 license

2
src/addr/local.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

16
src/checksum/checksum.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -21,6 +21,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
package checksum
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"io"
@ -36,8 +37,8 @@ import (
// GetPartialCheckSum is default method used to get a file checksum by sender and receiver
func GetPartialCheckSum(file *os.File) (string, error) {
// "capturing" CHUNKSIZE bytes and then skipping STEP bytes before the next chunk until the last one
const CHUNKS uint = 100
const CHUNKSIZE uint = 100
const CHUNKS uint = 50
const CHUNKSIZE uint = 50
const STEP uint = 250
fileStats, err := file.Stat()
@ -48,7 +49,7 @@ func GetPartialCheckSum(file *os.File) (string, error) {
fileSize := fileStats.Size()
if fileSize < int64(CHUNKS*CHUNKSIZE+STEP*(CHUNKS-1)) {
// file is too small to chop it in chunks, so just doing full checksum
// file is too small to chop it in chunks, so just get the full checksum
checksum, err := getFullCheckSum(file)
if err != nil {
@ -62,19 +63,20 @@ func GetPartialCheckSum(file *os.File) (string, error) {
return "", err
}
var capturedChunks string
// var capturedChunks string
var capturedChunks bytes.Buffer
var read uint64 = 0
for i := 0; uint(i) < CHUNKS; i++ {
buffer := make([]byte, CHUNKSIZE)
r, _ := file.ReadAt(buffer, int64(read))
capturedChunks += string(buffer)
capturedChunks.Write(buffer)
read += uint64(r)
read += uint64(STEP)
}
checksumBytes := sha256.Sum256([]byte(capturedChunks))
checksumBytes := sha256.Sum256(capturedChunks.Bytes())
checksum := hex.EncodeToString(checksumBytes[:])
return checksum, nil

2
src/checksum/checksum_test.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

2
src/encryption/decrypt.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

2
src/encryption/encrypt.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

2
src/encryption/encryption_test.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

2
src/encryption/key.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

79
src/fsys/dir.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -22,6 +22,7 @@ package fsys
import (
"fmt"
"io/fs"
"os"
"path/filepath"
)
@ -32,6 +33,7 @@ type Directory struct {
Path string
Size uint64
RelativeParentPath string // Relative path to the directory, where the highest point in the hierarchy is the upmost parent dir. Set manually
Symlinks []*Symlink
Files []*File
Directories []*Directory
}
@ -63,12 +65,13 @@ func GetDir(path string, recursive bool) (*Directory, error) {
// loop through each entry in the directory
entries, err := os.ReadDir(absPath)
if err != nil {
if err != nil && err != fs.ErrPermission {
return nil, err
}
var innerDirs []*Directory
var innerFiles []*File
var innerSymlinks []*Symlink
for _, entry := range entries {
entryInfo, err := entry.Info()
if err != nil {
@ -92,21 +95,42 @@ func GetDir(path string, recursive bool) (*Directory, error) {
// if not - skip the directory and only work with the files
} else {
innerFilePath := filepath.Join(absPath, entryInfo.Name())
// not a directory
innerFile, err := GetFile(innerFilePath)
if err != nil {
return nil, err
}
switch entryInfo.Mode()&os.ModeSymlink != 0 {
case true:
// it is a symlink
innerSymlinkPath := filepath.Join(absPath, entryInfo.Name())
symlink, err := GetSymlink(innerSymlinkPath, false)
if err != nil {
// skip this symlink
continue
}
directory.Size += innerFile.Size
innerSymlinks = append(innerSymlinks, symlink)
innerFiles = append(innerFiles, innerFile)
case false:
// it is a usual file
innerFilePath := filepath.Join(absPath, entryInfo.Name())
innerFile, err := GetFile(innerFilePath)
if err != nil {
// skip this file
continue
}
directory.Size += innerFile.Size
innerFiles = append(innerFiles, innerFile)
}
}
}
directory.Directories = innerDirs
directory.Files = innerFiles
directory.Symlinks = innerSymlinks
return &directory, nil
}
@ -132,7 +156,27 @@ func (dir *Directory) GetAllFiles(recursive bool) []*File {
return files
}
// Sets `RelativeParentPath` relative to the given base path.
// Returns every symlink in that directory
func (dir *Directory) GetAllSymlinks(recursive bool) []*Symlink {
var symlinks []*Symlink = dir.Symlinks
if recursive {
if len(dir.Directories) == 0 {
return symlinks
}
for _, innerDir := range dir.Directories {
innerSymlinks := innerDir.GetAllSymlinks(recursive)
symlinks = append(symlinks, innerSymlinks...)
}
} else {
symlinks = dir.Symlinks
}
return symlinks
}
// Sets `RelativeParentPath` relative to the given base path for files and `Path`, `TargetPath` for symlinks so the
// file with such path:
// /home/user/directory/somefile.txt
// had a relative path like that:
@ -148,5 +192,20 @@ func (dir *Directory) SetRelativePaths(base string, recursive bool) error {
file.RelativeParentPath = relPath
}
for _, symlink := range dir.GetAllSymlinks(recursive) {
symRelPath, err := filepath.Rel(base, symlink.Path)
if err != nil {
return err
}
symlink.Path = symRelPath
symRelTargetPath, err := filepath.Rel(base, symlink.TargetPath)
if err != nil {
return err
}
symlink.TargetPath = symRelTargetPath
}
return nil
}

38
src/fsys/dir_test.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -21,6 +21,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
package fsys
import (
"os"
"path/filepath"
"testing"
)
@ -79,25 +81,23 @@ func Test_GetFiles(t *testing.T) {
}
// func Test_SetRelativePaths(t *testing.T) {
// dirpath := "../testfiles/"
func Test_GetSymlinks(t *testing.T) {
dirpath := "../testfiles/"
// dir, err := GetDir(dirpath, true)
// if err != nil {
// t.Fatalf("%s", err)
// }
os.Symlink(filepath.Join(dirpath, "testfile.txt"), filepath.Join(dirpath, "testsymlink.txt"))
os.Symlink(filepath.Join(dirpath, "testdir", "testfile2.txt"), filepath.Join(dirpath, "testdir", "testsymlink2.txt"))
// absDirPath, err := filepath.Abs(dirpath)
// if err != nil {
// t.Fatalf("%s", err)
// }
dir, err := GetDir(dirpath, true)
if err != nil {
t.Fatalf("%s", err)
}
// err = dir.SetRelativePaths(absDirPath, true)
// if err != nil {
// t.Fatalf("%s", err)
// }
// recursive
symlinks := dir.GetAllSymlinks(true)
symlinkCount := 2
// for count, file := range dir.GetAllFiles(true) {
// t.Errorf("[%d] %v\n", count, file.RelativeParentPath)
// }
// }
if len(symlinks) != symlinkCount {
t.Fatalf("expected to get %d symlinks; got %d\n", symlinkCount, len(symlinks))
}
}

6
src/fsys/file.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -25,7 +25,7 @@ import (
"os"
"path/filepath"
"github.com/Unbewohnte/ftu/checksum"
"unbewohnte/ftu/checksum"
)
// A struct that represents the necessary file information for transportation through node
@ -45,7 +45,7 @@ var ErrorNotFile error = fmt.Errorf("not a file")
// Get general information about a file with the
// future ability to open it.
// NOTE that Handler field is nil BY DEFAULT until you
// manually call a (file *File) Open() function to open it !
// manually call (file *File).Open() to open it !
func GetFile(path string) (*File, error) {
absPath, err := filepath.Abs(path)
if err != nil {

2
src/fsys/file_test.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

70
src/fsys/symlink.go

@ -0,0 +1,70 @@
/*
ftu - file transferring utility.
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package fsys
import (
"fmt"
"os"
)
type Symlink struct {
TargetPath string
Path string
}
// Checks whether path is referring to a symlink or not
func IsSymlink(path string) (bool, error) {
stats, err := os.Lstat(path)
if err != nil {
return false, err
}
isSymlink := stats.Mode()&os.ModeSymlink != 0
return isSymlink, nil
}
var ErrorNotSymlink error = fmt.Errorf("not a symlink")
// get necessary information about a symlink in a filesystem. If check is false -
// does not check if path REALLY refers to a symlink
func GetSymlink(path string, check bool) (*Symlink, error) {
if check {
isSymlink, err := IsSymlink(path)
if err != nil {
return nil, err
}
if !isSymlink {
return nil, ErrorNotSymlink
}
}
target, err := os.Readlink(path)
if err != nil {
return nil, err
}
symlink := Symlink{
TargetPath: target,
Path: path,
}
return &symlink, nil
}

42
src/fsys/symlink_test.go

@ -0,0 +1,42 @@
/*
ftu - file transferring utility.
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package fsys
import (
"os"
"path/filepath"
"testing"
)
func Test_IsSymlink(t *testing.T) {
dirpath := "../testfiles/"
symlinkPath := filepath.Join(dirpath, "testsymlink.txt")
os.Symlink(filepath.Join(dirpath, "testfile.txt"), symlinkPath)
isSymlink, err := IsSymlink(symlinkPath)
if err != nil {
t.Fatalf("%s\n", err)
}
if !isSymlink {
t.Fatalf("%s expected to be a symlink\n", symlinkPath)
}
}

4
src/go.mod

@ -1,3 +1,3 @@
module github.com/Unbewohnte/ftu
module unbewohnte/ftu
go 1.17
go 1.18

30
src/main.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte (https://unbewohnte.xyz/))
This file is a part of ftu
@ -26,13 +26,13 @@ import (
"fmt"
"os"
"github.com/Unbewohnte/ftu/node"
"unbewohnte/ftu/node"
)
var (
VERSION string = "v2.1.2"
VERSION string = "v2.3.3"
versionInformation string = fmt.Sprintf("ftu %s\n\nCopyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))\nThis program comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it under certain conditions; type \"ftu -l\" for details.\n", VERSION)
versionInformation string = fmt.Sprintf("ftu %s\nfile transferring utility\n\nCopyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)\nThis program comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it under certain conditions; type \"ftu -l\" for details.\n", VERSION)
//go:embed COPYING
licenseInformation string
@ -43,7 +43,7 @@ var (
ADDRESS *string = flag.String("a", "", "Specifies an address to connect to")
DOWNLOADS_DIR *string = flag.String("d", ".", "Downloads folder")
SEND *string = flag.String("s", "", "Specify a file|directory to send")
VERBOSE *bool = flag.Bool("vp", false, "Turn on/off verbose output")
VERBOSE *bool = flag.Bool("?", false, "Turn on/off verbose output")
PRINT_VERSION *bool = flag.Bool("v", false, "Print version information")
PRINT_LICENSE *bool = flag.Bool("l", false, "Print license information")
@ -52,15 +52,15 @@ var (
func init() {
flag.Usage = func() {
fmt.Printf("ftu -[FLAG]...\n\n")
fmt.Printf("ftu -[FLAGs]\n\n")
fmt.Printf("[FLAGs]\n\n")
fmt.Printf("| -p [Uinteger_here] for port\n")
fmt.Printf("| -r [true|false] for recursive sending of a directory\n")
fmt.Printf("| -p [integer] for port\n")
fmt.Printf("| -r [true|false] send recursively or not\n")
fmt.Printf("| -a [ip_address|domain_name] address to connect to (cannot be used with -s)\n")
fmt.Printf("| -d [path_to_directory] where the files will be downloaded to (cannot be used with -s)\n")
fmt.Printf("| -s [path_to_file|directory] to send it (cannot be used with -a)\n")
fmt.Printf("| -vp [true|false] to turn on|off verbose output")
fmt.Printf("| -s [path_to_file|directory] send it (cannot be used with -a)\n")
fmt.Printf("| -? [true|false] turn on|off verbose output\n")
fmt.Printf("| -l print license information\n")
fmt.Printf("| -v print version information\n\n\n")
@ -98,12 +98,12 @@ func init() {
// validate flags
if *SEND == "" && *ADDRESS == "" {
fmt.Printf("Neither sending nor receiving flag was specified. Run ftu -h for help\n")
fmt.Printf("[ERROR] Neither sending nor receiving flag was specified. Run ftu -h for help\n")
os.Exit(-1)
}
if *SEND != "" && *ADDRESS != "" {
fmt.Printf("Can`t send and receive at the same time. Specify only -s or -a\n")
fmt.Printf("[ERROR] Can't send and receive at the same time. Specify either -s or -a\n")
os.Exit(-1)
}
@ -122,11 +122,11 @@ func main() {
VerboseOutput: *VERBOSE,
IsSending: isSending,
WorkingPort: *PORT,
ServerSide: &node.ServerSideNodeOptions{
SenderSide: &node.SenderNodeOptions{
ServingPath: *SEND,
Recursive: *RECUSRIVE,
},
ClientSide: &node.ClientSideNodeOptions{
ReceiverSide: &node.ReceiverNodeOptions{
ConnectionAddr: *ADDRESS,
DownloadsFolderPath: *DOWNLOADS_DIR,
},
@ -134,7 +134,7 @@ func main() {
node, err := node.NewNode(&nodeOptions)
if err != nil {
fmt.Printf("Error constructing a new node: %s\n", err)
fmt.Printf("[ERROR] Error constructing a new node: %s\n", err)
os.Exit(-1)
}

1073
src/node/node.go

File diff suppressed because it is too large Load Diff

10
src/node/options.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -20,12 +20,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
package node
type ServerSideNodeOptions struct {
type SenderNodeOptions struct {
ServingPath string
Recursive bool
}
type ClientSideNodeOptions struct {
type ReceiverNodeOptions struct {
ConnectionAddr string
DownloadsFolderPath string
}
@ -35,6 +35,6 @@ type NodeOptions struct {
IsSending bool
WorkingPort uint
VerboseOutput bool
ServerSide *ServerSideNodeOptions
ClientSide *ClientSideNodeOptions
SenderSide *SenderNodeOptions
ReceiverSide *ReceiverNodeOptions
}

2
src/protocol/constants.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

25
src/protocol/headers.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -29,7 +29,7 @@ type Header string
//// and (size) is 8 bytes long big-endian binary encoded uint64
// ENCRKEY.
// The FIRST header to be sent. Sent immediately after the connection has been established
// The FIRST header to be sent if you`re going to encrypt the transfer. Sent immediately after the connection has been established
// by sender. Body contains a size of a key and the key itself.
// ie: ENCRKEY~(size)(encryption key)
const HeaderEncryptionKey Header = "ENCRKEY"
@ -41,7 +41,7 @@ const HeaderReject Header = "REJECT"
// ACCEPT.
// The opposite of the previous REJECT. Sent by receiver when
// he has agreed to download the file|directory.
// it has agreed to download the file|directory.
// ie: ACCEPT~
const HeaderAccept Header = "ACCEPT"
@ -55,19 +55,11 @@ const HeaderDone Header = "DONE"
// READY.
// Sent by receiver when it has read and processed the last
// FILEBYTES packet or when it has information about all the files and it`s ready to
// receive bytes (FILESINFODONE). The sender is not allowed to "spam" FILEBYTES
// packets without the permission of receiver.
// FILEBYTES or FILE packet. The sender is not allowed to "spam" FILEBYTES or FILE
// packets without the permission (packet with this header) from receiver.
// ie: READY!~
const HeaderReady Header = "READY"
// FILESINFODONE.
// Sent by sender after it`s announced about all the files that are
// going to be sent. It is not allowed to send any file bytes before
// packet with this header was sent.
// ie: FILESINFODONE~
const HeaderFilesInfoDone Header = "FILESINFODONE"
// BYE!.
// Packet with this header can be sent both by receiver and sender.
// It`s used when the sender or the receiver are going to disconnect
@ -122,3 +114,10 @@ const HeaderDirectory Header = "DIRECTORY"
// Body must contain a file ID.
// ie: ALREADYHAVE~(file ID in binary)
const HeaderAlreadyHave Header = "ALREADYHAVE"
// SYMLINK
// Sent by sender AFTER ALL FILES has been sent already. Indicates that there
// is a symlink in some place that points to some other already received file.
// Body must contain information where the symlink is and the target file.
// ie: SYMLINK~(string size in binary)(location in the filesystem)(string size in binary)(location of a target)
const HeaderSymlink Header = "SYMLINK"

4
src/protocol/packet.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -31,7 +31,7 @@ import (
"fmt"
"strings"
"github.com/Unbewohnte/ftu/encryption"
"unbewohnte/ftu/encryption"
)
// Internal representation of packet before|after the transportation

4
src/protocol/packetConstruct.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -25,7 +25,7 @@ import (
"bytes"
"encoding/binary"
"github.com/Unbewohnte/ftu/fsys"
"unbewohnte/ftu/fsys"
)
// constructs a ready to send FILE packet

4
src/protocol/packetDecode.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -26,7 +26,7 @@ import (
"encoding/binary"
"fmt"
"github.com/Unbewohnte/ftu/fsys"
"unbewohnte/ftu/fsys"
)
var ErrorWrongPacket error = fmt.Errorf("wrong type of packet header")

2
src/protocol/protocol_test.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

2
src/protocol/recv.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu

60
src/protocol/send.go

@ -1,6 +1,6 @@
/*
ftu - file transferring utility.
Copyright (C) 2021 Kasyanov Nikolay Alexeevich (Unbewohnte (https://unbewohnte.xyz/))
Copyright (C) 2021,2022 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This file is a part of ftu
@ -28,8 +28,8 @@ import (
"io"
"net"
"github.com/Unbewohnte/ftu/encryption"
"github.com/Unbewohnte/ftu/fsys"
"unbewohnte/ftu/encryption"
"unbewohnte/ftu/fsys"
)
// Sends given packet to connection.
@ -137,13 +137,15 @@ func SendTransferOffer(connection net.Conn, file *fsys.File, dir *fsys.Directory
var ErrorSentAll error = fmt.Errorf("sent the whole file")
// sends a piece of file to the connection; The next calls will send
// Sends a piece of file to the connection; The next calls will send
// another piece util the file has been fully sent. If encrKey is not nil - encrypts each packet with
// this key
func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
// this key. Returns amount of filebytes written to the connection
func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) (uint64, error) {
var sentBytes uint64 = 0
err := file.Open()
if err != nil {
return err
return sentBytes, err
}
defer file.Close()
@ -152,7 +154,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
}
if file.Size == file.SentBytes {
return ErrorSentAll
return sentBytes, ErrorSentAll
}
fileBytesPacket := Packet{
@ -164,7 +166,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
// write file ID first
err = binary.Write(packetBodyBuff, binary.BigEndian, file.ID)
if err != nil {
return err
return sentBytes, err
}
// fill the remaining space of packet with the contents of a file
@ -172,7 +174,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
if encrKey != nil {
// account for padding
canSendBytes -= 32
canSendBytes -= 48
}
if (file.Size - file.SentBytes) < canSendBytes {
@ -183,9 +185,10 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
read, err := file.Handler.ReadAt(fileBytes, int64(file.SentBytes))
if err != nil {
return err
return sentBytes, err
}
file.SentBytes += uint64(read)
sentBytes += uint64(canSendBytes)
packetBodyBuff.Write(fileBytes)
@ -194,12 +197,45 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error {
if encrKey != nil {
err = fileBytesPacket.EncryptBody(encrKey)
if err != nil {
return err
return sentBytes, err
}
}
// send it to the other side
err = SendPacket(connection, fileBytesPacket)
if err != nil {
return 0, err
}
return sentBytes, nil
}
// Sends a symlink to the other side. If encrKey is not nil - encrypts the packet with this key
func SendSymlink(symlink *fsys.Symlink, connection net.Conn, encrKey []byte) error {
symlinkPacket := Packet{
Header: HeaderSymlink,
}
symlinkPacketBodyBuff := new(bytes.Buffer)
// SYMLINK~(string size in binary)(location in the filesystem)(string size in binary)(location of a target)
binary.Write(symlinkPacketBodyBuff, binary.BigEndian, uint64(len(symlink.Path)))
symlinkPacketBodyBuff.Write([]byte(symlink.Path))
binary.Write(symlinkPacketBodyBuff, binary.BigEndian, uint64(len(symlink.TargetPath)))
symlinkPacketBodyBuff.Write([]byte(symlink.TargetPath))
symlinkPacket.Body = symlinkPacketBodyBuff.Bytes()
if encrKey != nil {
err := symlinkPacket.EncryptBody(encrKey)
if err != nil {
return err
}
}
err := SendPacket(connection, symlinkPacket)
if err != nil {
return err
}

1
src/testfiles/testdir/testsymlink2.txt

@ -0,0 +1 @@
../testfiles/testdir/testfile2.txt

1
src/testfiles/testsymlink.txt

@ -0,0 +1 @@
../testfiles/testfile.txt
Loading…
Cancel
Save