Added resend functionality and preparations for RSA / Encrpyption
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
bin/
|
bin/
|
||||||
testFile
|
testFile
|
||||||
testFile.recv
|
testFile.recv
|
||||||
testFile2
|
testFile2
|
||||||
|
out/
|
||||||
102
client.go
102
client.go
@@ -1,16 +1,19 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetFile(path string) {
|
func GetFile(path string) {
|
||||||
request := NewRequest(path)
|
request := NewRequest(path)
|
||||||
|
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:13374")
|
udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:13374")
|
||||||
|
// udpAddr, err := net.ResolveUDPAddr("udp", "192.168.2.145:13374")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@@ -31,7 +34,7 @@ func GetFile(path string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bytes := make([]byte, PacketSize)
|
bytes := make([]byte, PacketSize)
|
||||||
file, err := os.Create(path + ".recv")
|
file, err := os.Create("out/" + hex.EncodeToString(request.sid[:]) + ".recv")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -88,61 +91,72 @@ func GetFile(path string) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
lostPackets := make([]uint32, 0)
|
lostPackets := make([]uint32, 0)
|
||||||
lastSync := ackPck.sync
|
|
||||||
needResend := false
|
for i := ackPck.sync + 1; i < endPacket.sync; i++ {
|
||||||
for _, i := range recvPackets {
|
if b, _ := contains(recvPackets, i); !b {
|
||||||
if lastSync+1 != i {
|
|
||||||
lostPackets = append(lostPackets, i)
|
lostPackets = append(lostPackets, i)
|
||||||
needResend = true
|
|
||||||
}
|
}
|
||||||
lastSync = i
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !needResend {
|
for _, i := range lostPackets {
|
||||||
ack := NewAck(&endPacket)
|
fmt.Println(i)
|
||||||
conn.Write(ack.ToBytes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort.Slice(recvPackets, func(i, j int) bool {
|
lastPacket := ackPck
|
||||||
// pckI := recvPackets[i]
|
|
||||||
// pckJ := recvPackets[j]
|
|
||||||
// return pckI.sync < pckJ.sync
|
|
||||||
// })
|
|
||||||
|
|
||||||
// endPacketFound := false
|
for {
|
||||||
// needResend := false
|
if len(lostPackets) == 0 {
|
||||||
// lastSync := request.sync
|
break
|
||||||
// fmt.Println(lastSync)
|
}
|
||||||
// endPacketSync, err := endPacket.GetSync()
|
|
||||||
// if err != nil {
|
|
||||||
// panic(err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for _, packet := range recvPackets {
|
for _, sync := range lostPackets {
|
||||||
// // fmt.Println(packet.sync)
|
|
||||||
// // offset := (int64(packet.sync)-1)*PacketSize - int64(HeaderSize)
|
|
||||||
// // data := packet.data
|
|
||||||
// // fmt.Printf("Data: %v Offset: %v\n", data, offset)
|
|
||||||
|
|
||||||
// if lastSync+1 != packet.sync {
|
fmt.Printf("Request resend for %v\n", sync)
|
||||||
// fmt.Printf("Need Packet %v resend\n", lastSync+1)
|
resend := NewResend(uint32(sync), lastPacket)
|
||||||
// // Add to slice
|
conn.Write(resend.ToBytes())
|
||||||
// needResend = true
|
lastPacket = resend
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fmt.Printf("Writing Packet %v to file\n", packet.sync)
|
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||||
|
|
||||||
// _, err = file.Write(packet.data)
|
_, _, err = conn.ReadFrom(bytes)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// panic(err)
|
if e, ok := err.(net.Error); !ok || !e.Timeout() {
|
||||||
// }
|
// If it's not a timeout, log the error as usual
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// if packet.sync == endPacketSync {
|
pck := PacketFromBytes(bytes)
|
||||||
// endPacketFound = true
|
offset := (int64(pck.sync) - int64(ackPck.sync+1)) * (PacketSize - int64(HeaderSize))
|
||||||
// }
|
// fmt.Printf("Sync: %v, Offset: %v\n", pck.sync, offset)
|
||||||
|
|
||||||
// lastSync = packet.sync
|
_, err = file.WriteAt(pck.data, offset)
|
||||||
// }
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, index := contains(lostPackets, pck.sync)
|
||||||
|
fmt.Printf("Removing sync %v from LostPackets\n", pck.sync)
|
||||||
|
lostPackets = remove(lostPackets, index)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ack := NewAck(&endPacket)
|
||||||
|
conn.Write(ack.ToBytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func remove(s []uint32, i int) []uint32 {
|
||||||
|
s[i] = s[len(s)-1]
|
||||||
|
return s[:len(s)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(s []uint32, e uint32) (bool, int) {
|
||||||
|
for i, a := range s {
|
||||||
|
if a == e {
|
||||||
|
return true, i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, 0
|
||||||
}
|
}
|
||||||
|
|||||||
5
main.go
5
main.go
@@ -8,7 +8,10 @@ const PacketSize = 504
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if os.Args[1] == "server" {
|
if os.Args[1] == "server" {
|
||||||
server := New()
|
server, err := New()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
server.Serve()
|
server.Serve()
|
||||||
} else {
|
} else {
|
||||||
GetFile(os.Args[2])
|
GetFile(os.Args[2])
|
||||||
|
|||||||
51
packets.go
51
packets.go
@@ -21,8 +21,8 @@ type Packet struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func PacketFromBytes(bytes []byte) Packet {
|
func PacketFromBytes(bytes []byte) Packet {
|
||||||
sid := SessionID(bytes[0:32])
|
flag := HeaderFlag(bytes[0])
|
||||||
flag := HeaderFlag(bytes[32])
|
sid := SessionID(bytes[1:33])
|
||||||
sync := binary.LittleEndian.Uint32(bytes[33:37])
|
sync := binary.LittleEndian.Uint32(bytes[33:37])
|
||||||
dataLength := binary.LittleEndian.Uint32(bytes[37:41])
|
dataLength := binary.LittleEndian.Uint32(bytes[37:41])
|
||||||
pck := Packet{
|
pck := Packet{
|
||||||
@@ -30,7 +30,7 @@ func PacketFromBytes(bytes []byte) Packet {
|
|||||||
flag: flag,
|
flag: flag,
|
||||||
sync: sync,
|
sync: sync,
|
||||||
dataLength: dataLength,
|
dataLength: dataLength,
|
||||||
data: bytes[41 : 41+dataLength],
|
data: bytes[HeaderSize : HeaderSize+int(dataLength)],
|
||||||
}
|
}
|
||||||
return pck
|
return pck
|
||||||
}
|
}
|
||||||
@@ -64,6 +64,32 @@ func NewRequest(path string) *Packet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pck *Packet) GetUint32Payload() (uint32, error) {
|
||||||
|
flag := pck.flag
|
||||||
|
if flag != PTE && flag != Ack && flag != End && flag != Resend {
|
||||||
|
return 0, errors.New(fmt.Sprintf("Can not get Sync from Packet Type with flag: %v", flag))
|
||||||
|
}
|
||||||
|
return binary.LittleEndian.Uint32(pck.data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pck *Packet) GetFilePath() (string, error) {
|
||||||
|
if pck.flag != Request {
|
||||||
|
return "", errors.New("Can not get FilePath from Packet that is not Request")
|
||||||
|
}
|
||||||
|
return string(pck.data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResendFile(resendPck *Packet, data []byte) *Packet {
|
||||||
|
sync, _ := resendPck.GetUint32Payload()
|
||||||
|
return &Packet{
|
||||||
|
sid: resendPck.sid,
|
||||||
|
flag: File,
|
||||||
|
sync: sync,
|
||||||
|
dataLength: uint32(len(data)),
|
||||||
|
data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewFile(lastPck *Packet, data []byte) *Packet {
|
func NewFile(lastPck *Packet, data []byte) *Packet {
|
||||||
return &Packet{
|
return &Packet{
|
||||||
sid: lastPck.sid,
|
sid: lastPck.sid,
|
||||||
@@ -110,25 +136,10 @@ func NewPte(fileSize uint32, lastPck *Packet) *Packet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pck *Packet) GetUint32Payload() (uint32, error) {
|
|
||||||
flag := pck.flag
|
|
||||||
if flag != PTE && flag != Ack && flag != End && flag != Resend {
|
|
||||||
return 0, errors.New(fmt.Sprintf("Can not get Sync from Packet Type with flag: %v", flag))
|
|
||||||
}
|
|
||||||
return binary.LittleEndian.Uint32(pck.data), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pck *Packet) GetFilePath() (string, error) {
|
|
||||||
if pck.flag != Request {
|
|
||||||
return "", errors.New("Can not get FilePath from Packet that is not Request")
|
|
||||||
}
|
|
||||||
return string(pck.data), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pck *Packet) ToBytes() []byte {
|
func (pck *Packet) ToBytes() []byte {
|
||||||
arr := make([]byte, HeaderSize+int(pck.dataLength))
|
arr := make([]byte, HeaderSize+int(pck.dataLength))
|
||||||
copy(arr[0:32], pck.sid[:])
|
arr[0] = byte(pck.flag)
|
||||||
arr[32] = byte(pck.flag)
|
copy(arr[1:33], pck.sid[:])
|
||||||
binary.LittleEndian.PutUint32(arr[33:37], pck.sync)
|
binary.LittleEndian.PutUint32(arr[33:37], pck.sync)
|
||||||
binary.LittleEndian.PutUint32(arr[37:41], pck.dataLength)
|
binary.LittleEndian.PutUint32(arr[37:41], pck.dataLength)
|
||||||
copy(arr[41:], pck.data)
|
copy(arr[41:], pck.data)
|
||||||
|
|||||||
72
server.go
72
server.go
@@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -13,16 +15,25 @@ type info struct {
|
|||||||
path string
|
path string
|
||||||
lastSync uint32
|
lastSync uint32
|
||||||
lastPckSend HeaderFlag
|
lastPckSend HeaderFlag
|
||||||
|
key [32]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
sessions map[SessionID]*info
|
sessions map[SessionID]*info
|
||||||
|
rsa *rsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *Server {
|
func New() (*Server, error) {
|
||||||
|
key, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &Server{
|
return &Server{
|
||||||
sessions: make(map[SessionID]*info),
|
sessions: make(map[SessionID]*info),
|
||||||
}
|
rsa: key,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) handlePacket(conn *net.UDPConn, addr *net.UDPAddr, rPacket *Packet) {
|
func (server *Server) handlePacket(conn *net.UDPConn, addr *net.UDPAddr, rPacket *Packet) {
|
||||||
@@ -33,9 +44,42 @@ func (server *Server) handlePacket(conn *net.UDPConn, addr *net.UDPAddr, rPacket
|
|||||||
case Ack:
|
case Ack:
|
||||||
server.handleAck(conn, addr, rPacket)
|
server.handleAck(conn, addr, rPacket)
|
||||||
break
|
break
|
||||||
|
case Resend:
|
||||||
|
server.resend(conn, addr, rPacket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (server *Server) resend(conn *net.UDPConn, addr *net.UDPAddr, pck *Packet) {
|
||||||
|
resend, err := pck.GetUint32Payload()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := server.sessions[pck.sid].path
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// This should be different
|
||||||
|
offset := (int64(resend) - 3) * (PacketSize - int64(HeaderSize))
|
||||||
|
// fmt.Printf("Requested Sync: %v, Calculated Offset: %v\n", resend, offset)
|
||||||
|
buf := make([]byte, PacketSize-HeaderSize)
|
||||||
|
|
||||||
|
_, err = file.ReadAt(buf, offset)
|
||||||
|
if err != nil && !errors.Is(err, io.EOF) {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Resending Packet %v\n", resend)
|
||||||
|
|
||||||
|
resendPck := NewResendFile(pck, buf)
|
||||||
|
|
||||||
|
conn.WriteToUDP(resendPck.ToBytes(), addr)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (server *Server) handleAck(conn *net.UDPConn, addr *net.UDPAddr, pck *Packet) {
|
func (server *Server) handleAck(conn *net.UDPConn, addr *net.UDPAddr, pck *Packet) {
|
||||||
ack, err := pck.GetUint32Payload()
|
ack, err := pck.GetUint32Payload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -88,11 +132,7 @@ func (server *Server) sendData(conn *net.UDPConn, addr *net.UDPAddr, pck *Packet
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
defer file.Close()
|
||||||
// // ONLY FOR TEST
|
|
||||||
// firstPacket := true
|
|
||||||
// var firstFilePckt Packet
|
|
||||||
// // END TEST
|
|
||||||
|
|
||||||
buf := make([]byte, PacketSize-HeaderSize)
|
buf := make([]byte, PacketSize-HeaderSize)
|
||||||
filePck := pck
|
filePck := pck
|
||||||
@@ -107,27 +147,9 @@ func (server *Server) sendData(conn *net.UDPConn, addr *net.UDPAddr, pck *Packet
|
|||||||
filePck = NewFile(filePck, buf[:r])
|
filePck = NewFile(filePck, buf[:r])
|
||||||
fmt.Printf("Sending File Packet %v\n", filePck.sync)
|
fmt.Printf("Sending File Packet %v\n", filePck.sync)
|
||||||
|
|
||||||
// // ONLY FOR TEST
|
|
||||||
// if firstPacket {
|
|
||||||
// firstPacket = false
|
|
||||||
// firstFilePckt = Packet{
|
|
||||||
// sid: filePck.sid,
|
|
||||||
// flag: File,
|
|
||||||
// sync: filePck.sync,
|
|
||||||
// dataLength: filePck.dataLength,
|
|
||||||
// data: make([]byte, filePck.dataLength),
|
|
||||||
// }
|
|
||||||
|
|
||||||
// copy(firstFilePckt.data, filePck.data)
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
// // END
|
|
||||||
conn.WriteToUDP(filePck.ToBytes(), addr)
|
conn.WriteToUDP(filePck.ToBytes(), addr)
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// conn.WriteToUDP(firstFilePckt.ToBytes(), addr)
|
|
||||||
|
|
||||||
eodPck := NewEnd(filePck)
|
eodPck := NewEnd(filePck)
|
||||||
server.sessions[pck.sid].lastSync = eodPck.sync
|
server.sessions[pck.sid].lastSync = eodPck.sync
|
||||||
server.sessions[pck.sid].lastPckSend = eodPck.flag
|
server.sessions[pck.sid].lastPckSend = eodPck.flag
|
||||||
|
|||||||
Reference in New Issue
Block a user