This repository has been archived on 2025-10-15. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Uftp/cmd/hellogo.go
2023-10-10 09:21:06 +02:00

248 lines
3.9 KiB
Go

package main
import (
"encoding/binary"
"encoding/hex"
"fmt"
"net"
"os"
"sort"
)
const PacketSize = 504
type packet struct {
syn uint32
// Flag
len uint32
data []byte
}
func (packet packet) ToBytes() []byte {
arr := make([]byte, 4+4+len(packet.data))
binary.LittleEndian.PutUint32(arr[0:4], packet.syn)
binary.LittleEndian.PutUint32(arr[4:8], packet.len)
for i := 0; i < len(packet.data); i++ {
arr[8+i] = packet.data[i]
}
return arr
}
func makePacketFrombytes(bytes []byte) packet {
syn := binary.LittleEndian.Uint32(bytes[0:4])
len := binary.LittleEndian.Uint32(bytes[4:8])
data := bytes[8:(8 + len)]
return packet{syn: syn, len: len, data: data}
}
func check(e error) {
if e != nil {
panic(e)
}
}
func sendFile(conn *net.UDPConn, addr *net.UDPAddr) {
dat, err := os.ReadFile("testFile")
check(err)
offset := 0
syn := 0
for {
fmt.Printf("Sending Syn %v to addr %v\n", syn, addr.IP.String())
remaining := PacketSize
if offset+PacketSize > len(dat) {
remaining = len(dat) - offset
}
pck := packet{
data: dat[offset : offset+remaining],
len: uint32(remaining),
syn: uint32(syn),
}
conn.WriteToUDP(pck.ToBytes(), addr)
syn += 1
offset = offset + remaining
if offset >= len(dat) {
break
}
}
endPacket := packet{
len: 0,
syn: uint32(syn),
}
conn.WriteToUDP(endPacket.ToBytes(), addr)
}
func checkFileTest() {
dat, err := os.ReadFile("testFile")
check(err)
offset := 0
syn := 0
for {
remaining := PacketSize
if offset+PacketSize > len(dat) {
remaining = len(dat) - offset
}
pck := packet{
data: dat[offset : offset+remaining],
len: uint32(remaining),
syn: uint32(syn),
}
str := hex.EncodeToString(pck.ToBytes())
fmt.Println(pck)
fmt.Println(str)
// conn.WriteToUDP(pck.ToBytes(), addr)
offset = offset + remaining
syn += 1
if offset >= len(dat) {
break
}
}
}
func resend(conn *net.UDPConn, addr *net.UDPAddr, syn uint32) {
dat, err := os.ReadFile("testFile")
check(err)
index := int((syn + 1) * PacketSize)
remaining := PacketSize
if index+PacketSize > len(dat) {
remaining = len(dat) - index
}
pck := packet{
data: dat[index : index+remaining],
syn: syn,
len: uint32(remaining),
}
conn.WriteToUDP(pck.ToBytes(), addr)
}
func server() {
udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:13374")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
conn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
for {
var buf [PacketSize]byte
_, addr, err := conn.ReadFromUDP(buf[0:])
if err != nil {
fmt.Println(err)
return
}
pck := makePacketFrombytes(buf[0:])
if pck.len == 0 {
sendFile(conn, addr)
} else {
resend(conn, addr, pck.syn)
}
}
}
func client() {
// Resolve the string address to a UDP address
udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:13374")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// Dial to the address with UDP
conn, err := net.DialUDP("udp", nil, udpAddr)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
initPacket := packet{
syn: 0,
len: 0,
}
// Send a message to the server
_, err = conn.Write(initPacket.ToBytes())
fmt.Println("send...")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
bytes := make([]byte, 512)
var syns []int
var endSyn uint32 = 0
for {
_, _, err := conn.ReadFrom(bytes)
check(err)
pck := makePacketFrombytes(bytes)
// if pck.syn != currSyn {
// fmt.Println("Out of Sync")
// r.PushFront(currSyn)
// }
syns = append(syns, int(pck.syn))
fmt.Println(pck)
// currSyn += 1
if pck.len == 0 {
endSyn = pck.syn
break
}
}
sort.Ints(syns)
if len(syns) != int(endSyn+1) {
}
for i := 0; i < int(endSyn); i++ {
if i < len(syns) {
if syns[i] != i {
fmt.Printf("Out of Sync on Packet %v\n", i)
}
} else {
fmt.Printf("Out of Sync on Packet %v\n", i)
}
}
}
func main() {
if os.Args[1] == "server" {
server()
} else {
client()
}
}