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 !
- 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 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 encryption; FIXED via AES encryption of packets` body - [x]
- Messy and hard to follow code && file structure; FIXED? - [x]

2
protocol/constants.go

@ -4,7 +4,7 @@ package protocol
// MAXPACKETSIZE.
// How many bytes can contain one packet (header + body) at maximum
// (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.
// 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
type File struct {
type file struct {
Filename string
Filesize uint64
CheckSum checksum.CheckSum
@ -16,7 +16,7 @@ type File struct {
// Goes through all files in the downloads directory and compares their
// 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)
if err != nil {
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
type Receiver struct {
DownloadsFolder string
Connection net.Conn
IncomingPackets chan protocol.Packet
FileToDownload *File
EncryptionKey []byte
ReadyToReceive bool
Stopped bool
FileBytesPacketCounter uint64
DownloadsFolder string
Connection net.Conn
IncomingPackets chan protocol.Packet
FileToDownload *file
EncryptionKey []byte
ReadyToReceive bool
Stopped bool
TransferInfo *transferInfo
}
// Creates a new client with default fields
@ -40,7 +40,6 @@ func NewReceiver(downloadsFolder string) *Receiver {
incomingPacketsChan := make(chan protocol.Packet, 5000)
var PacketCounter uint64 = 0
fmt.Println("Created a new receiver")
return &Receiver{
DownloadsFolder: downloadsFolder,
@ -48,11 +47,14 @@ func NewReceiver(downloadsFolder string) *Receiver {
IncomingPackets: incomingPacketsChan,
Stopped: false,
ReadyToReceive: false,
FileToDownload: &File{
FileToDownload: &file{
Filename: "",
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.
// The choice of acceptance is given to the user
func (r *Receiver) HandleFileOffer() error {
// inform the user about the file
fmt.Printf(`
@ -122,7 +123,7 @@ func (r *Receiver) HandleFileOffer() error {
// accept the file
// check if the file with the same name is present
doesExist, err := r.CheckIfFileAlreadyExists()
doesExist, err := r.checkIfFileAlreadyExists()
if err != nil {
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)
}
r.TransferInfo.ApproximateNumberOfFilePackets = uint64(float32(r.FileToDownload.Filesize) / float32(protocol.MAXPACKETSIZE))
return nil
}
@ -171,11 +174,38 @@ func (r *Receiver) WritePieceOfFile(filePacket protocol.Packet) error {
// just write the bytes
file.Write(filePacket.Body)
file.Close()
r.FileBytesPacketCounter++
r.TransferInfo.ReceivedFileBytesPackets++
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
func (r *Receiver) ReceivePackets() {
for {
@ -212,8 +242,7 @@ func (r *Receiver) ReceivePackets() {
// in any order and react correspondingly
func (r *Receiver) MainLoop() {
go r.ReceivePackets()
// r.Stop()
go r.PrintTransferInfo(time.Second * 3)
for {
if r.Stopped {
@ -291,8 +320,8 @@ func (r *Receiver) MainLoop() {
// the sender has completed its mission,
// checking hashes and exiting
fmt.Println("Got ", r.FileBytesPacketCounter, " file packets in total")
fmt.Println("Checking checksums...")
fmt.Println("Got ", r.TransferInfo.ReceivedFileBytesPackets, " file packets in total")
fmt.Println("Comparing checksums...")
file, err := os.Open(filepath.Join(r.DownloadsFolder, r.FileToDownload.Filename))
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
type File struct {
type file struct {
path string
Filename string
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
func getFile(path string) (*File, error) {
func getFile(path string) (*file, error) {
info, err := os.Stat(path)
if err != nil {
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 &File{
return &file{
path: path,
Filename: info.Name(),
Filesize: uint64(info.Size()),

81
sender/sender.go

@ -5,6 +5,7 @@ import (
"net"
"os"
"strconv"
"time"
"github.com/Unbewohnte/FTU/checksum"
"github.com/Unbewohnte/FTU/encryption"
@ -13,16 +14,16 @@ import (
// The main sender struct
type Sender struct {
Port int
FileToTransfer *File
Listener net.Listener
Connection net.Conn
IncomingPackets chan protocol.Packet
EncryptionKey []byte
SentFileBytesPackets uint64
TransferAllowed bool
ReceiverIsReady bool
Stopped bool
Port int
FileToTransfer *file
Listener net.Listener
Connection net.Conn
IncomingPackets chan protocol.Packet
EncryptionKey []byte
TransferInfo *transferInfo
TransferAllowed bool
ReceiverIsReady bool
Stopped bool
}
// Creates a new sender with default|necessary fields
@ -49,21 +50,23 @@ func NewSender(port int, filepath string) *Sender {
// !!!
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)
return &Sender{
Port: port,
FileToTransfer: fileToTransfer,
Listener: listener,
Connection: nil,
IncomingPackets: incomingPacketsChan,
SentFileBytesPackets: filepacketCounter,
EncryptionKey: key,
TransferAllowed: false,
ReceiverIsReady: false,
Stopped: false,
Port: port,
FileToTransfer: fileToTransfer,
Listener: listener,
Connection: nil,
IncomingPackets: incomingPacketsChan,
TransferInfo: &transferInfo{
SentFileBytesPackets: 0,
ApproximateNumberOfFilePackets: uint64(float32(fileToTransfer.Filesize) / float32(protocol.MAXPACKETSIZE)),
},
EncryptionKey: key,
TransferAllowed: false,
ReceiverIsReady: false,
Stopped: false,
}
}
@ -166,7 +169,7 @@ func (s *Sender) SendOffer() error {
func (s *Sender) SendPiece() error {
// if no data to send - exit
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()
}
@ -198,14 +201,41 @@ func (s *Sender) SendPiece() error {
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.SentBytes += uint64(read)
s.SentFileBytesPackets++
s.TransferInfo.SentFileBytesPackets++
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
func (s *Sender) ReceivePackets() {
for {
@ -237,6 +267,7 @@ func (s *Sender) ReceivePackets() {
func (s *Sender) MainLoop() {
go s.ReceivePackets()
go s.PrintTransferInfo(time.Second * 3)
// instantly sending an encryption key, following the protocol`s rule
err := s.SendEncryptionKey()

6
sender/transferinfo.go

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