Browse Source

Protocol improvements, bug fix, added a bit of logic in handling of the file offer

main 1.1.1
Unbewohnte 3 years ago
parent
commit
9bdc836b28
  1. 5
      README.md
  2. 5
      protocol/constants.go
  3. 21
      protocol/packet.go
  4. 22
      receiver/file.go
  5. 49
      receiver/receiver.go
  6. 35
      sender/ip.go
  7. 29
      sender/sender.go

5
README.md

@ -49,15 +49,14 @@ Thus, with a connection and a way of communication, the sender will send some pa
--- ---
## Known issues|problems|lack of features|reasons why it`s bad ## Known issues|problems|lack of features|reasons why it`s bad
- **VERY** slow; somewhat FIXED - [x], now **a little** faster than before - **VERY** slow; somewhat FIXED - [x], now **faster** than before
- **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 !!!** (But now present in the other form, unfortunately) - 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 (ETA, lost packets, etc.); FIXED - [ ]
- 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 - [ ] - No encryption; FIXED - [ ]
- Messy and hard to follow code && file structure; partially FIXED (protocol is looking fairly good rn) - [ X ] - Messy and hard to follow code && file structure; partially FIXED (protocol is looking fairly good rn) - [ X ]
- Lack of downloads` management; FIXED - [ ]
- No way to stop the download/upload and resume it later or even during the next connection; FIXED - [ ] - No way to stop the download/upload and resume it later or even during the next connection; FIXED - [ ]
- No tests; FIXED - [ ] - No tests; FIXED - [ ]

5
protocol/constants.go

@ -4,10 +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 = 1024 // the same problem as in the previous versions: if the packet is big enough - the conn.Read() const MAXPACKETSIZE uint = 10240 // 10 kilobytes
// will result in some sort of error where it does not read the intended amount of bytes (less, in fact),
// which is strange, but I guess that
// I just do something wrong in my code
// 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.

21
protocol/packet.go

@ -118,10 +118,25 @@ func ReadFromConn(connection net.Conn) (Packet, error) {
} }
// have a packetsize, now reading the whole packet // have a packetsize, now reading the whole packet
packetBuff := make([]byte, packetSize) packetBytes := new(bytes.Buffer)
connection.Read(packetBuff)
left := packetSize
for {
if left == 0 {
break
}
buff := make([]byte, 1024)
if left < len(buff) {
buff = make([]byte, left)
}
r, _ := connection.Read(buff)
left -= r
packetBytes.Write(buff[:r])
}
packet := BytesToPacket(packetBuff) packet := BytesToPacket(packetBytes.Bytes())
return packet, nil return packet, nil
} }

22
receiver/file.go

@ -1,6 +1,11 @@
package receiver package receiver
import "github.com/Unbewohnte/FTU/checksum" import (
"fmt"
"os"
"github.com/Unbewohnte/FTU/checksum"
)
// Receiver`s file struct. Used internally by receiver // Receiver`s file struct. Used internally by receiver
type File struct { type File struct {
@ -8,3 +13,18 @@ type File struct {
Filesize uint64 Filesize uint64
CheckSum checksum.CheckSum CheckSum checksum.CheckSum
} }
// 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) {
contents, err := os.ReadDir(r.DownloadsFolder)
if err != nil {
return false, fmt.Errorf("could not get contents of the downloads` directory: %s", err)
}
for _, file := range contents {
if file.Name() == r.FileToDownload.Filename {
return true, nil
}
}
return false, nil
}

49
receiver/receiver.go

@ -7,6 +7,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/Unbewohnte/FTU/checksum" "github.com/Unbewohnte/FTU/checksum"
"github.com/Unbewohnte/FTU/protocol" "github.com/Unbewohnte/FTU/protocol"
@ -118,10 +119,35 @@ func (r *Receiver) HandleFileOffer() error {
} }
// accept the file // accept the file
// check if the file with the same name is present
doesExist, err := r.CheckIfFileAlreadyExists()
if err != nil {
return fmt.Errorf("could not check if the file with the same name alredy exists: %s", err)
}
if doesExist {
fmt.Printf(`
| Looks like that there is a file with the same name in your downloads directory, do you want to overwrite it ? [Y/N]: `)
fmt.Scanln(&input)
input = strings.TrimSpace(input)
input = strings.ToLower(input)
if input == "y" {
err = os.Remove(filepath.Join(r.DownloadsFolder, r.FileToDownload.Filename))
if err != nil {
return fmt.Errorf("could not remove the file: %s", err)
}
} else {
// user did not agree to overwrite, adding checksum to the name
r.FileToDownload.Filename = fmt.Sprint(time.Now().Unix()) + r.FileToDownload.Filename
}
}
acceptancePacket := protocol.Packet{ acceptancePacket := protocol.Packet{
Header: protocol.HeaderAccept, Header: protocol.HeaderAccept,
} }
err := protocol.SendPacket(r.Connection, acceptancePacket) err = protocol.SendPacket(r.Connection, acceptancePacket)
if err != nil { if err != nil {
return fmt.Errorf("could not send an acceptance packet: %s", err) return fmt.Errorf("could not send an acceptance packet: %s", err)
} }
@ -180,7 +206,11 @@ func (r *Receiver) MainLoop() {
readyPacket := protocol.Packet{ readyPacket := protocol.Packet{
Header: protocol.HeaderReady, Header: protocol.HeaderReady,
} }
protocol.SendPacket(r.Connection, readyPacket) err := protocol.SendPacket(r.Connection, readyPacket)
if err != nil {
fmt.Printf("Could not send the packet: %s\nExiting...", err)
r.Stop()
}
r.ReadyToReceive = false r.ReadyToReceive = false
} }
@ -216,12 +246,23 @@ func (r *Receiver) MainLoop() {
case protocol.HeaderDone: case protocol.HeaderDone:
if r.FileToDownload.Filename != "" && r.FileToDownload.Filesize != 0 && r.FileToDownload.CheckSum != [32]byte{} { if r.FileToDownload.Filename != "" && r.FileToDownload.Filesize != 0 && r.FileToDownload.CheckSum != [32]byte{} {
r.HandleFileOffer() err := r.HandleFileOffer()
if err != nil {
fmt.Printf("Could not handle a file download confirmation: %s\nExiting...", err)
r.Stop()
}
r.ReadyToReceive = true r.ReadyToReceive = true
} else {
fmt.Println("Not enough data about the file was sent. Exiting...")
r.Stop()
} }
case protocol.HeaderFileBytes: case protocol.HeaderFileBytes:
r.WritePieceOfFile(incomingPacket) err := r.WritePieceOfFile(incomingPacket)
if err != nil {
fmt.Printf("Could not write a piece of file: %s\nExiting...", err)
r.Stop()
}
r.ReadyToReceive = true r.ReadyToReceive = true
case protocol.HeaderDisconnecting: case protocol.HeaderDisconnecting:

35
sender/ip.go

@ -0,0 +1,35 @@
package sender
import (
"fmt"
"io"
"net"
"net/http"
)
// gets a local ip. Borrowed from StackOverflow, thank you, whoever I brought it from
func GetLocalIP() (string, error) {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
return "", err
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.String(), nil
}
// gets a remote ip. Borrowed from StackOverflow, thank you, whoever I brought it from
func GetRemoteIP() (string, error) {
resp, err := http.Get("https://api.ipify.org?format=text")
if err != nil {
return "", fmt.Errorf("could not make a request to get your remote IP: %s", err)
}
defer resp.Body.Close()
ip, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("could not read a response: %s", err)
}
return string(ip), nil
}

29
sender/sender.go

@ -2,9 +2,7 @@ package sender
import ( import (
"fmt" "fmt"
"io"
"net" "net"
"net/http"
"os" "os"
"strconv" "strconv"
@ -12,33 +10,6 @@ import (
"github.com/Unbewohnte/FTU/protocol" "github.com/Unbewohnte/FTU/protocol"
) )
// gets a local ip. Borrowed from StackOverflow, thank you, whoever I brought it from
func GetLocalIP() (string, error) {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
return "", err
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.String(), nil
}
// gets a remote ip. Borrowed from StackOverflow, thank you, whoever I brought it from
func GetRemoteIP() (string, error) {
resp, err := http.Get("https://api.ipify.org?format=text")
if err != nil {
return "", fmt.Errorf("could not make a request to get your remote IP: %s", err)
}
defer resp.Body.Close()
ip, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("could not read a response: %s", err)
}
return string(ip), nil
}
// The main sender struct // The main sender struct
type Sender struct { type Sender struct {
Port int Port int

Loading…
Cancel
Save