Browse Source

[fsys] file checksums are automatically generated when GetFile is called; [protocol] ACCEPT and REJECT packets do not need to include file ids now; [node] progress on sending directories

main
Unbewohnte 3 years ago
parent
commit
eb7cd49b0e
  1. 24
      src/fsys/file.go
  2. 82
      src/node/node.go
  3. 8
      src/protocol/headers.go
  4. 10
      src/protocol/packetConstruct.go

24
src/fsys/file.go

@ -4,18 +4,18 @@ import (
"fmt"
"os"
"path/filepath"
)
var FileIDsCounter uint64 = 1
"github.com/Unbewohnte/ftu/checksum"
)
// A struct that represents the necessary file information for transportation through node
type File struct {
ID uint64
ID uint64 // Set manually
Name string
Path string
ParentPath string
Size uint64
Checksum string // Set manually
Checksum string
Handler *os.File // Set when .Open() is called
SentBytes uint64 // Set manually during transportation
}
@ -43,7 +43,6 @@ func GetFile(path string) (*File, error) {
}
file := File{
ID: FileIDsCounter,
Name: stats.Name(),
Path: absPath,
ParentPath: filepath.Dir(absPath),
@ -51,8 +50,19 @@ func GetFile(path string) (*File, error) {
Handler: nil,
}
// increment ids counter so the next file will have a different ID
FileIDsCounter++
// get checksum
err = file.Open()
if err != nil {
return nil, err
}
defer file.Handler.Close()
checksum, err := checksum.GetPartialCheckSum(file.Handler)
if err != nil {
return nil, err
}
file.Checksum = checksum
return &file, nil
}

82
src/node/node.go

@ -35,10 +35,12 @@ type netInfoInfo struct {
// Sending-side node information
type sending struct {
ServingPath string // path to the thing that will be sent
IsDirectory bool // is ServingPath a directory
Recursive bool // recursively send directory
CanSendBytes bool // is the other node ready to receive another piece
ServingPath string // path to the thing that will be sent
IsDirectory bool // is ServingPath a directory
Recursive bool // recursively send directory
CanSendBytes bool // is the other node ready to receive another piece
FilesToSend []*fsys.File
CurrentFileID uint64 // an id of a file that is currently being transported
}
// Receiving-side node information
@ -191,25 +193,25 @@ func (node *Node) Start() {
}
// retrieve information about the file|directory
var file *fsys.File
var dir *fsys.Directory
var fileToSend *fsys.File
var dirToSend *fsys.Directory
switch node.transferInfo.Sending.IsDirectory {
case true:
dir, err = fsys.GetDir(node.transferInfo.Sending.ServingPath, node.transferInfo.Sending.Recursive)
dirToSend, err = fsys.GetDir(node.transferInfo.Sending.ServingPath, node.transferInfo.Sending.Recursive)
if err != nil {
panic(err)
}
case false:
file, err = fsys.GetFile(node.transferInfo.Sending.ServingPath)
fileToSend, err = fsys.GetFile(node.transferInfo.Sending.ServingPath)
if err != nil {
panic(err)
}
}
if dir != nil {
fmt.Printf("Sending \"%s\" (%.2f MB) locally on %s:%d\n", dir.Name, float32(dir.Size)/1024/1024, localIP, node.netInfo.Port)
if dirToSend != nil {
fmt.Printf("Sending \"%s\" (%.2f MB) locally on %s:%d\n", dirToSend.Name, float32(dirToSend.Size)/1024/1024, localIP, node.netInfo.Port)
} else {
fmt.Printf("Sending \"%s\" (%.2f MB) locally on %s:%d\n", file.Name, float32(file.Size)/1024/1024, localIP, node.netInfo.Port)
fmt.Printf("Sending \"%s\" (%.2f MB) locally on %s:%d\n", fileToSend.Name, float32(fileToSend.Size)/1024/1024, localIP, node.netInfo.Port)
}
@ -233,7 +235,7 @@ func (node *Node) Start() {
go protocol.ReceivePackets(node.netInfo.Conn, node.packetPipe)
// send info about file/directory
go protocol.SendTransferOffer(node.netInfo.Conn, file, dir, node.netInfo.EncryptionKey)
go protocol.SendTransferOffer(node.netInfo.Conn, fileToSend, dirToSend, node.netInfo.EncryptionKey)
// mainloop
for {
@ -276,12 +278,18 @@ func (node *Node) Start() {
var filesToSend []*fsys.File
if node.transferInfo.Sending.Recursive {
filesToSend = dir.GetAllFiles(true)
filesToSend = dirToSend.GetAllFiles(true)
} else {
filesToSend = dir.GetAllFiles(false)
filesToSend = dirToSend.GetAllFiles(false)
}
for _, file := range filesToSend {
// notify the other node about all the files that are going to be sent
for counter, file := range filesToSend {
// assign ID and add it to the node sendlist
file.ID = uint64(counter)
node.transferInfo.Sending.FilesToSend = append(node.transferInfo.Sending.FilesToSend, file)
filePacket, err := protocol.CreateFilePacket(file)
if err != nil {
panic(err)
@ -302,10 +310,15 @@ func (node *Node) Start() {
}
}
// set current file id to the first file
node.transferInfo.Sending.CurrentFileID = 0
case false:
// send a filepacket of a single file
fileToSend.ID = 0
node.transferInfo.Sending.FilesToSend = append(node.transferInfo.Sending.FilesToSend, fileToSend)
filePacket, err := protocol.CreateFilePacket(file)
filePacket, err := protocol.CreateFilePacket(node.transferInfo.Sending.FilesToSend[0])
if err != nil {
panic(err)
}
@ -323,6 +336,9 @@ func (node *Node) Start() {
if err != nil {
panic(err)
}
// set current file id to the first and only file
node.transferInfo.Sending.CurrentFileID = 0
}
case protocol.HeaderReject:
@ -332,7 +348,6 @@ func (node *Node) Start() {
case protocol.HeaderDisconnecting:
node.state.Stopped = true
fmt.Printf("%s disconnected\n", node.netInfo.Conn.RemoteAddr())
}
@ -346,17 +361,19 @@ func (node *Node) Start() {
if !node.transferInfo.Sending.Recursive {
} else {
// send bytes of all files one by one
}
case false:
// sending a piece of a single file
err = protocol.SendPiece(file, node.netInfo.Conn, node.netInfo.EncryptionKey)
currentFileID := node.transferInfo.Sending.CurrentFileID
err = protocol.SendPiece(node.transferInfo.Sending.FilesToSend[currentFileID], node.netInfo.Conn, node.netInfo.EncryptionKey)
switch err {
case protocol.ErrorSentAll:
// the file has been sent fully
fileIDBuff := new(bytes.Buffer)
err = binary.Write(fileIDBuff, binary.BigEndian, file.ID)
err = binary.Write(fileIDBuff, binary.BigEndian, node.transferInfo.Sending.FilesToSend[currentFileID].ID)
if err != nil {
panic(err)
}
@ -375,8 +392,8 @@ func (node *Node) Start() {
protocol.SendPacket(node.netInfo.Conn, endFilePacket)
// because there`s still no handling for directories - send
// done packet
// as only one file has been requested to send - there`s nothing else to do
// sending DONE packet
protocol.SendPacket(node.netInfo.Conn, protocol.Packet{
Header: protocol.HeaderDone,
})
@ -391,7 +408,8 @@ func (node *Node) Start() {
default:
node.state.Stopped = true
fmt.Printf("An error occured while sending a piece of \"%s\": %s\n", file.Name, err)
currentFileID := node.transferInfo.Sending.CurrentFileID
fmt.Printf("An error occured while sending a piece of \"%s\": %s\n", node.transferInfo.Sending.FilesToSend[currentFileID].Name, err)
panic(err)
}
@ -465,19 +483,9 @@ func (node *Node) Start() {
// yes
// send aceptance packet
responsePacketFileIDBuffer := new(bytes.Buffer)
binary.Write(responsePacketFileIDBuffer, binary.BigEndian, file.ID)
acceptancePacket := protocol.Packet{
Header: protocol.HeaderAccept,
Body: responsePacketFileIDBuffer.Bytes(),
}
if node.netInfo.EncryptionKey != nil {
err = acceptancePacket.EncryptBody(node.netInfo.EncryptionKey)
if err != nil {
panic(err)
}
}
err = protocol.SendPacket(node.netInfo.Conn, acceptancePacket)
@ -496,19 +504,9 @@ func (node *Node) Start() {
} else {
// no
responsePacketFileIDBuffer := new(bytes.Buffer)
binary.Write(responsePacketFileIDBuffer, binary.BigEndian, file.ID)
rejectionPacket := protocol.Packet{
Header: protocol.HeaderReject,
Body: responsePacketFileIDBuffer.Bytes(),
}
if node.netInfo.EncryptionKey != nil {
err = rejectionPacket.EncryptBody(node.netInfo.EncryptionKey)
if err != nil {
panic(err)
}
}
err = protocol.SendPacket(node.netInfo.Conn, rejectionPacket)

8
src/protocol/headers.go

@ -16,15 +16,13 @@ const HeaderEncryptionKey Header = "ENCRKEY"
// REJECT.
// Sent only by receiver if the receiver has decided to not download the contents.
// The body must contain a file ID in binary.
// ie: REJECT~(file id in binary)
// ie: REJECT~
const HeaderReject Header = "REJECT"
// ACCEPT.
// The opposite of the previous REJECT. Sent by receiver when
// he has agreed to download the file|directory. The body must contain
// the ID of a file in binary that is allowed to upload
// ie: ACCEPT~(file id in binary)
// he has agreed to download the file|directory.
// ie: ACCEPT~
const HeaderAccept Header = "ACCEPT"
// DONE.

10
src/protocol/packetConstruct.go

@ -5,7 +5,6 @@ import (
"bytes"
"encoding/binary"
"github.com/Unbewohnte/ftu/checksum"
"github.com/Unbewohnte/ftu/fsys"
)
@ -36,14 +35,9 @@ func CreateFilePacket(file *fsys.File) (*Packet, error) {
binary.Write(fPacketBodyBuff, binary.BigEndian, &file.Size)
// checksum
fileChecksum, err := checksum.GetPartialCheckSum(file.Handler)
if err != nil {
return nil, err
}
checksumLen := uint64(len([]byte(fileChecksum)))
checksumLen := uint64(len([]byte(file.Checksum)))
binary.Write(fPacketBodyBuff, binary.BigEndian, &checksumLen)
fPacketBodyBuff.Write([]byte(fileChecksum))
fPacketBodyBuff.Write([]byte(file.Checksum))
filePacket.Body = fPacketBodyBuff.Bytes()

Loading…
Cancel
Save