Browse Source

Added printing state of the transfer feature

main 1.2.1
Unbewohnte 3 years ago
parent
commit
c1cab012f4
  1. 2
      README.md
  2. 2
      protocol/constants.go
  3. 4
      receiver/file.go
  4. 65
      receiver/receiver.go
  5. 6
      receiver/transferinfo.go
  6. 6
      sender/file.go
  7. 81
      sender/sender.go
  8. 6
      sender/transferinfo.go

2
README.md

@ -33,7 +33,7 @@ Thus, with a connection and a way of communication, the sender will send some pa
- **VERY** expensive on resources; somewhat FIXED - [x], no more **json manipulations**, only **raw bytes**`s wizardry ! - **VERY** expensive on resources; somewhat FIXED - [x], no more **json manipulations**, only **raw bytes**`s wizardry !
- If `MAXFILEDATASIZE` is bigger than appr. 1024 - the packets on the other end will not be unmarshalled due to error ??; FIXED - [x], unnecessary, wrong, deprecated, **destroyed !!!** - If `MAXFILEDATASIZE` is bigger than appr. 1024 - the packets on the other end will not be unmarshalled due to error ??; FIXED - [x], unnecessary, wrong, deprecated, **destroyed !!!**
- Lack of proper error-handling; somewhat FIXED - [x] - Lack of proper error-handling; somewhat FIXED - [x]
- Lack of information about the process of transferring (ETA, lost packets, etc.); FIXED - [ ] - Lack of information about the process of transferring; FIXED - [x]
- No way to verify if the transferred file is not corrupted; FIXED via checksum- [x] - No way to verify if the transferred file is not corrupted; FIXED via checksum- [x]
- No encryption; FIXED via AES encryption of packets` body - [x] - No encryption; FIXED via AES encryption of packets` body - [x]
- Messy and hard to follow code && file structure; FIXED? - [x] - Messy and hard to follow code && file structure; FIXED? - [x]

2
protocol/constants.go

@ -4,7 +4,7 @@ package protocol
// MAXPACKETSIZE. // MAXPACKETSIZE.
// How many bytes can contain one packet (header + body) at maximum // How many bytes can contain one packet (header + body) at maximum
// (packets with size bigger than MAXPACKETSIZE are invalid and will not be sent) // (packets with size bigger than MAXPACKETSIZE are invalid and will not be sent)
const MAXPACKETSIZE uint = 51200 // 50 kilobytes const MAXPACKETSIZE uint = 512000 // 50 kilobytes
// PACKETSIZEDELIMETER. // PACKETSIZEDELIMETER.
// Character that delimits one and the other sides of the next incoming packet. // Character that delimits one and the other sides of the next incoming packet.

4
receiver/file.go

@ -8,7 +8,7 @@ import (
) )
// Receiver`s file struct. Used internally by receiver // Receiver`s file struct. Used internally by receiver
type File struct { type file struct {
Filename string Filename string
Filesize uint64 Filesize uint64
CheckSum checksum.CheckSum CheckSum checksum.CheckSum
@ -16,7 +16,7 @@ type File struct {
// Goes through all files in the downloads directory and compares their // Goes through all files in the downloads directory and compares their
// names with the name of the file that is about to be downloaded // names with the name of the file that is about to be downloaded
func (r *Receiver) CheckIfFileAlreadyExists() (bool, error) { func (r *Receiver) checkIfFileAlreadyExists() (bool, error) {
contents, err := os.ReadDir(r.DownloadsFolder) contents, err := os.ReadDir(r.DownloadsFolder)
if err != nil { if err != nil {
return false, fmt.Errorf("could not get contents of the downloads` directory: %s", err) return false, fmt.Errorf("could not get contents of the downloads` directory: %s", err)

65
receiver/receiver.go

@ -16,14 +16,14 @@ import (
// Representation of a receiver // Representation of a receiver
type Receiver struct { type Receiver struct {
DownloadsFolder string DownloadsFolder string
Connection net.Conn Connection net.Conn
IncomingPackets chan protocol.Packet IncomingPackets chan protocol.Packet
FileToDownload *File FileToDownload *file
EncryptionKey []byte EncryptionKey []byte
ReadyToReceive bool ReadyToReceive bool
Stopped bool Stopped bool
FileBytesPacketCounter uint64 TransferInfo *transferInfo
} }
// Creates a new client with default fields // Creates a new client with default fields
@ -40,7 +40,6 @@ func NewReceiver(downloadsFolder string) *Receiver {
incomingPacketsChan := make(chan protocol.Packet, 5000) incomingPacketsChan := make(chan protocol.Packet, 5000)
var PacketCounter uint64 = 0
fmt.Println("Created a new receiver") fmt.Println("Created a new receiver")
return &Receiver{ return &Receiver{
DownloadsFolder: downloadsFolder, DownloadsFolder: downloadsFolder,
@ -48,11 +47,14 @@ func NewReceiver(downloadsFolder string) *Receiver {
IncomingPackets: incomingPacketsChan, IncomingPackets: incomingPacketsChan,
Stopped: false, Stopped: false,
ReadyToReceive: false, ReadyToReceive: false,
FileToDownload: &File{ FileToDownload: &file{
Filename: "", Filename: "",
Filesize: 0, Filesize: 0,
}, },
FileBytesPacketCounter: PacketCounter, TransferInfo: &transferInfo{
ReceivedFileBytesPackets: 0,
ApproximateNumberOfFilePackets: 0,
},
} }
} }
@ -88,7 +90,6 @@ func (r *Receiver) Connect(addr string) error {
// Handles the input from the user after the sender sent "DOYOUACCEPT?" packet. // Handles the input from the user after the sender sent "DOYOUACCEPT?" packet.
// The choice of acceptance is given to the user // The choice of acceptance is given to the user
func (r *Receiver) HandleFileOffer() error { func (r *Receiver) HandleFileOffer() error {
// inform the user about the file // inform the user about the file
fmt.Printf(` fmt.Printf(`
@ -122,7 +123,7 @@ func (r *Receiver) HandleFileOffer() error {
// accept the file // accept the file
// check if the file with the same name is present // check if the file with the same name is present
doesExist, err := r.CheckIfFileAlreadyExists() doesExist, err := r.checkIfFileAlreadyExists()
if err != nil { if err != nil {
return fmt.Errorf("could not check if the file with the same name alredy exists: %s", err) return fmt.Errorf("could not check if the file with the same name alredy exists: %s", err)
} }
@ -154,6 +155,8 @@ func (r *Receiver) HandleFileOffer() error {
return fmt.Errorf("could not send an acceptance packet: %s", err) return fmt.Errorf("could not send an acceptance packet: %s", err)
} }
r.TransferInfo.ApproximateNumberOfFilePackets = uint64(float32(r.FileToDownload.Filesize) / float32(protocol.MAXPACKETSIZE))
return nil return nil
} }
@ -171,11 +174,38 @@ func (r *Receiver) WritePieceOfFile(filePacket protocol.Packet) error {
// just write the bytes // just write the bytes
file.Write(filePacket.Body) file.Write(filePacket.Body)
file.Close() file.Close()
r.FileBytesPacketCounter++ r.TransferInfo.ReceivedFileBytesPackets++
return nil return nil
} }
// Prints a brief information about the state of the transfer
func (r *Receiver) PrintTransferInfo(pauseDuration time.Duration) {
next := time.Now().UTC()
for {
if r.TransferInfo.ReceivedFileBytesPackets == 0 {
time.Sleep(time.Second)
continue
}
now := time.Now().UTC()
if !now.After(next) {
continue
}
next = now.Add(pauseDuration)
fmt.Printf(`
| Received packets/Approximate number of packets
| (%d|%d) (%.2f%%/100%%)
`, r.TransferInfo.ReceivedFileBytesPackets,
r.TransferInfo.ApproximateNumberOfFilePackets,
float32(r.TransferInfo.ReceivedFileBytesPackets)/float32(r.TransferInfo.ApproximateNumberOfFilePackets)*100)
time.Sleep(pauseDuration)
}
}
// Listens in an endless loop; reads incoming packets, decrypts their BODY and puts into channel // Listens in an endless loop; reads incoming packets, decrypts their BODY and puts into channel
func (r *Receiver) ReceivePackets() { func (r *Receiver) ReceivePackets() {
for { for {
@ -212,8 +242,7 @@ func (r *Receiver) ReceivePackets() {
// in any order and react correspondingly // in any order and react correspondingly
func (r *Receiver) MainLoop() { func (r *Receiver) MainLoop() {
go r.ReceivePackets() go r.ReceivePackets()
go r.PrintTransferInfo(time.Second * 3)
// r.Stop()
for { for {
if r.Stopped { if r.Stopped {
@ -291,8 +320,8 @@ func (r *Receiver) MainLoop() {
// the sender has completed its mission, // the sender has completed its mission,
// checking hashes and exiting // checking hashes and exiting
fmt.Println("Got ", r.FileBytesPacketCounter, " file packets in total") fmt.Println("Got ", r.TransferInfo.ReceivedFileBytesPackets, " file packets in total")
fmt.Println("Checking checksums...") fmt.Println("Comparing checksums...")
file, err := os.Open(filepath.Join(r.DownloadsFolder, r.FileToDownload.Filename)) file, err := os.Open(filepath.Join(r.DownloadsFolder, r.FileToDownload.Filename))
if err != nil { if err != nil {

6
receiver/transferinfo.go

@ -0,0 +1,6 @@
package receiver
type transferInfo struct {
ReceivedFileBytesPackets uint64
ApproximateNumberOfFilePackets uint64
}

6
sender/file.go

@ -8,7 +8,7 @@ import (
) )
// Struct that represents the served file. Used internally in the sender // Struct that represents the served file. Used internally in the sender
type File struct { type file struct {
path string path string
Filename string Filename string
Filesize uint64 Filesize uint64
@ -19,7 +19,7 @@ type File struct {
} }
// Prepares a file for serving. Used for preparing info before sending a fileinfo packet by sender // Prepares a file for serving. Used for preparing info before sending a fileinfo packet by sender
func getFile(path string) (*File, error) { func getFile(path string) (*file, error) {
info, err := os.Stat(path) info, err := os.Stat(path)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get a fileinfo: %s", err) return nil, fmt.Errorf("could not get a fileinfo: %s", err)
@ -33,7 +33,7 @@ func getFile(path string) (*File, error) {
return nil, fmt.Errorf("could not get a partial file checksum: %s", err) return nil, fmt.Errorf("could not get a partial file checksum: %s", err)
} }
return &File{ return &file{
path: path, path: path,
Filename: info.Name(), Filename: info.Name(),
Filesize: uint64(info.Size()), Filesize: uint64(info.Size()),

81
sender/sender.go

@ -5,6 +5,7 @@ import (
"net" "net"
"os" "os"
"strconv" "strconv"
"time"
"github.com/Unbewohnte/FTU/checksum" "github.com/Unbewohnte/FTU/checksum"
"github.com/Unbewohnte/FTU/encryption" "github.com/Unbewohnte/FTU/encryption"
@ -13,16 +14,16 @@ import (
// The main sender struct // The main sender struct
type Sender struct { type Sender struct {
Port int Port int
FileToTransfer *File FileToTransfer *file
Listener net.Listener Listener net.Listener
Connection net.Conn Connection net.Conn
IncomingPackets chan protocol.Packet IncomingPackets chan protocol.Packet
EncryptionKey []byte EncryptionKey []byte
SentFileBytesPackets uint64 TransferInfo *transferInfo
TransferAllowed bool TransferAllowed bool
ReceiverIsReady bool ReceiverIsReady bool
Stopped bool Stopped bool
} }
// Creates a new sender with default|necessary fields // Creates a new sender with default|necessary fields
@ -49,21 +50,23 @@ func NewSender(port int, filepath string) *Sender {
// !!! // !!!
key := encryption.Generate32AESkey() key := encryption.Generate32AESkey()
fmt.Printf("GENERATED ENCRYPTION KEY: %s\n", key) fmt.Printf("Generated an encryption key: %s\n", key)
var filepacketCounter uint64
fmt.Printf("Created a new sender at %s:%d (remote)\n%s:%d (local)\n", remoteIP, port, localIP, port) fmt.Printf("Created a new sender at %s:%d (remote)\n%s:%d (local)\n", remoteIP, port, localIP, port)
return &Sender{ return &Sender{
Port: port, Port: port,
FileToTransfer: fileToTransfer, FileToTransfer: fileToTransfer,
Listener: listener, Listener: listener,
Connection: nil, Connection: nil,
IncomingPackets: incomingPacketsChan, IncomingPackets: incomingPacketsChan,
SentFileBytesPackets: filepacketCounter, TransferInfo: &transferInfo{
EncryptionKey: key, SentFileBytesPackets: 0,
TransferAllowed: false, ApproximateNumberOfFilePackets: uint64(float32(fileToTransfer.Filesize) / float32(protocol.MAXPACKETSIZE)),
ReceiverIsReady: false, },
Stopped: false, EncryptionKey: key,
TransferAllowed: false,
ReceiverIsReady: false,
Stopped: false,
} }
} }
@ -166,7 +169,7 @@ func (s *Sender) SendOffer() error {
func (s *Sender) SendPiece() error { func (s *Sender) SendPiece() error {
// if no data to send - exit // if no data to send - exit
if s.FileToTransfer.LeftBytes == 0 { if s.FileToTransfer.LeftBytes == 0 {
fmt.Printf("Done. Sent %d file packets\n", s.SentFileBytesPackets) fmt.Printf("Done. Sent %d file packets\n", s.TransferInfo.SentFileBytesPackets)
s.Stop() s.Stop()
} }
@ -198,14 +201,41 @@ func (s *Sender) SendPiece() error {
return fmt.Errorf("could not send a file packet : %s", err) return fmt.Errorf("could not send a file packet : %s", err)
} }
// doing a "logging" for the next time // doing a "logging" for the next piece
s.FileToTransfer.LeftBytes -= uint64(read) s.FileToTransfer.LeftBytes -= uint64(read)
s.FileToTransfer.SentBytes += uint64(read) s.FileToTransfer.SentBytes += uint64(read)
s.SentFileBytesPackets++ s.TransferInfo.SentFileBytesPackets++
return nil return nil
} }
// Prints a brief information about the state of the transfer
func (s *Sender) PrintTransferInfo(pauseDuration time.Duration) {
next := time.Now().UTC()
for {
if !s.TransferAllowed {
time.Sleep(time.Second)
continue
}
now := time.Now().UTC()
if !now.After(next) {
continue
}
next = now.Add(pauseDuration)
fmt.Printf(`
| Sent packets/Approximate number of packets
| (%d|%d) (%.2f%%/100%%)
`, s.TransferInfo.SentFileBytesPackets,
s.TransferInfo.ApproximateNumberOfFilePackets,
float32(s.TransferInfo.SentFileBytesPackets)/float32(s.TransferInfo.ApproximateNumberOfFilePackets)*100)
time.Sleep(pauseDuration)
}
}
// Listens in an endless loop; reads incoming packets, decrypts their BODY and puts into channel // Listens in an endless loop; reads incoming packets, decrypts their BODY and puts into channel
func (s *Sender) ReceivePackets() { func (s *Sender) ReceivePackets() {
for { for {
@ -237,6 +267,7 @@ func (s *Sender) ReceivePackets() {
func (s *Sender) MainLoop() { func (s *Sender) MainLoop() {
go s.ReceivePackets() go s.ReceivePackets()
go s.PrintTransferInfo(time.Second * 3)
// instantly sending an encryption key, following the protocol`s rule // instantly sending an encryption key, following the protocol`s rule
err := s.SendEncryptionKey() err := s.SendEncryptionKey()

6
sender/transferinfo.go

@ -0,0 +1,6 @@
package sender
type transferInfo struct {
SentFileBytesPackets uint64
ApproximateNumberOfFilePackets uint64
}
Loading…
Cancel
Save