merge develop into master #21

Merged
JakeHillion merged 149 commits from develop into master 2021-05-12 00:22:59 +01:00
11 changed files with 349 additions and 25 deletions
Showing only changes of commit 7c2b8782f1 - Show all commits

View File

@ -5,14 +5,19 @@ import (
"time"
)
type Packet struct {
type Packet interface {
Marshal(generator MacGenerator) []byte
Raw() []byte
}
type SimplePacket struct {
Data []byte
timestamp time.Time
}
// create a packet from the raw data of an IP packet
func NewPacket(data []byte) Packet {
return Packet{
func NewSimplePacket(data []byte) Packet {
return SimplePacket{
Data: data,
timestamp: time.Now(),
}
@ -25,10 +30,10 @@ func UnmarshalPacket(raw []byte, verifier MacVerifier) (Packet, error) {
sum := raw[len(raw)-verifier.CodeLength():]
if err := verifier.Verify(data, sum); err != nil {
return Packet{}, err
return SimplePacket{}, err
}
p := Packet{
p := SimplePacket{
Data: data[:len(data)-8],
}
@ -39,12 +44,12 @@ func UnmarshalPacket(raw []byte, verifier MacVerifier) (Packet, error) {
}
// get the raw data of the IP packet
func (p Packet) Raw() []byte {
func (p SimplePacket) Raw() []byte {
return p.Data
}
// produce the wrapped format of a packet
func (p Packet) Marshal(generator MacGenerator) []byte {
func (p SimplePacket) Marshal(generator MacGenerator) []byte {
// length of data + length of timestamp (8 byte) + length of checksum
slice := make([]byte, len(p.Data)+8+generator.CodeLength())

View File

@ -121,13 +121,13 @@ func (f *InitiatedFlow) Produce(v proxy.MacVerifier) (proxy.Packet, error) {
func (f *Flow) Produce(v proxy.MacVerifier) (proxy.Packet, error) {
if !f.isAlive {
return proxy.Packet{}, shared.ErrDeadConnection
return nil, shared.ErrDeadConnection
}
data, err := f.produceMarshalled()
if err != nil {
f.isAlive = false
return proxy.Packet{}, err
return nil, err
}
return proxy.UnmarshalPacket(data, v)

View File

@ -61,14 +61,14 @@ func (t *SourceSink) Source() (proxy.Packet, error) {
read, err := t.tun.Read(buf)
if err != nil {
return proxy.Packet{}, err
return nil, err
}
if read == 0 {
return proxy.Packet{}, io.EOF
return nil, io.EOF
}
return proxy.NewPacket(buf[:read]), nil
return proxy.NewSimplePacket(buf[:read]), nil
}
var good, bad float64

11
udp/congestion.go Normal file
View File

@ -0,0 +1,11 @@
package udp
type Congestion interface {
Sequence() uint64
ReceivedAck(uint64)
NextAck() uint64
ReceivedNack(uint64)
NextNack() uint64
}

58
udp/congestion/reno.go Normal file
View File

@ -0,0 +1,58 @@
package congestion
import "time"
type NewReno struct {
sequence chan uint64
packetTimes map[uint64]time.Time
nextAck uint64
nextNack uint64
rtt float64
}
func NewNewReno() *NewReno {
c := NewReno{
sequence: make(chan uint64),
packetTimes: make(map[uint64]time.Time),
}
go func() {
var s uint64
for {
if s == 0 {
continue
}
c.sequence <- s
s++
}
}()
return &c
}
// It is assumed that ReceivedAck will only be called by one thread
func (c *NewReno) ReceivedAck(uint64) {
}
// It is assumed that ReceivedNack will only be called by one thread
func (c *NewReno) ReceivedNack(uint64) {
}
func (c *NewReno) Sequence() uint64 {
s := <-c.sequence
c.packetTimes[s] = time.Now()
return s
}
func (c *NewReno) NextAck() uint64 {
return c.nextAck
}
func (c *NewReno) NextNack() uint64 {
return c.nextNack
}

57
udp/flow.go Normal file
View File

@ -0,0 +1,57 @@
package udp
import (
"errors"
"mpbl3p/proxy"
"net"
"time"
)
type PacketWriter interface {
WriteToUDP(b []byte, addr *net.UDPAddr) (int, error)
}
type PacketConn interface {
PacketWriter
ReadFromUDP(b []byte) (int, *net.UDPAddr, error)
}
type Ack struct {
time time.Time
packet uint64
sent bool
}
type Flow struct {
writer PacketWriter
raddr net.UDPAddr
isAlive bool
congestion Congestion
}
func (f *Flow) IsAlive() bool {
return f.isAlive
}
func (f *Flow) Consume(pp proxy.Packet, g proxy.MacGenerator) error {
p := Packet{
seq: f.congestion.Sequence(),
data: pp,
}
p.ack = f.congestion.NextAck()
p.nack = f.congestion.NextNack()
return errors.New("not implemented")
}
func (f *Flow) Produce(v proxy.MacVerifier) (proxy.Packet, error) {
return proxy.Packet{}, errors.New("not implemented")
}
func (f *Flow) handleDatagram(p []byte) {
// TODO: Congestion control - read off the ACKs for the send half
// TODO: Congestion control - schedule ACKs for this side
}

77
udp/listener.go Normal file
View File

@ -0,0 +1,77 @@
package udp
import (
"log"
"mpbl3p/proxy"
"net"
)
type ComparableUdpAddress struct {
IP [16]byte
Port int
Zone string
}
func fromUdpAddress(address net.UDPAddr) ComparableUdpAddress {
var ip [16]byte
for i, b := range []byte(address.IP) {
ip[i] = b
}
return ComparableUdpAddress{
IP: ip,
Port: address.Port,
Zone: address.Zone,
}
}
func NewListener(p *proxy.Proxy, local string, v proxy.MacVerifier) error {
laddr, err := net.ResolveUDPAddr("udp", local)
if err != nil {
return err
}
pconn, err := net.ListenUDP("udp", laddr)
if err != nil {
return err
}
err = pconn.SetWriteBuffer(0)
if err != nil {
panic(err)
}
receivedConnections := make(map[ComparableUdpAddress]*Flow)
go func() {
for {
buf := make([]byte, 1500)
_, addr, err := pconn.ReadFromUDP(buf)
if err != nil {
panic(err)
}
raddr := fromUdpAddress(*addr)
if f, exists := receivedConnections[raddr]; exists {
f.handleDatagram(buf)
continue
}
f := Flow{
writer: pconn,
raddr: *addr,
isAlive: true,
}
receivedConnections[raddr] = &f
log.Printf("received new connection: %v\n", f)
p.AddConsumer(&f)
p.AddProducer(&f, v)
}
}()
return nil
}

11
udp/packet.go Normal file
View File

@ -0,0 +1,11 @@
package udp
import "mpbl3p/proxy"
type Packet struct {
ack uint64
nack uint64
seq uint64
data proxy.Packet
}

64
utils/heap.go Normal file
View File

@ -0,0 +1,64 @@
package utils
import "errors"
var ErrorEmptyHeap = errors.New("attempted to extract from empty heap")
// A MinHeap for Uint64
type Uint64Heap struct {
data []uint64
}
func (h *Uint64Heap) swap(x, y int) {
h.data[x] = h.data[x] ^ h.data[y]
h.data[y] = h.data[y] ^ h.data[x]
h.data[x] = h.data[x] ^ h.data[y]
}
func (h *Uint64Heap) Insert(new uint64) uint64 {
h.data = append(h.data, new)
child := len(h.data) - 1
for child != 0 {
parent := (child - 1) / 2
if h.data[parent] > h.data[child] {
h.swap(parent, child)
} else {
break
}
child = parent
}
return h.data[0]
}
func (h *Uint64Heap) Extract() (uint64, error) {
if len(h.data) == 0 {
return 0, ErrorEmptyHeap
}
min := h.data[0]
h.data[0] = h.data[len(h.data)-1]
h.data = h.data[:len(h.data)-1]
parent := 0
for {
left, right := parent*2+1, parent*2+2
if (left < len(h.data) && h.data[parent] > h.data[left]) || (right < len(h.data) && h.data[parent] > h.data[right]) {
if right < len(h.data) && h.data[left] > h.data[right] {
h.swap(parent, right)
parent = right
} else {
h.swap(parent, left)
parent = left
}
} else {
return min, nil
}
}
}
func (h *Uint64Heap) Peek() uint64 {
return h.data[0]
}

54
utils/heap_test.go Normal file
View File

@ -0,0 +1,54 @@
package utils
import (
"fmt"
"github.com/stretchr/testify/assert"
"math/rand"
"testing"
"time"
)
func SlowHeapSort(in []uint64) []uint64 {
out := make([]uint64, len(in))
var heap Uint64Heap
for _, x := range in {
heap.Insert(x)
}
for i := range out {
var err error
out[i], err = heap.Extract()
if err != nil {
panic(err)
}
}
return out
}
func TestUint64Heap(t *testing.T) {
t.Run("EquivalentToMerge", func(t *testing.T) {
const ArrayLength = 50
sortedArray := make([]uint64, ArrayLength)
array := make([]uint64, ArrayLength)
for i := range array {
sortedArray[i] = uint64(i)
array[i] = uint64(i)
}
rand.Seed(time.Now().Unix())
for i := 0; i < 100; i++ {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
rand.Shuffle(50, func(i, j int) { array[i], array[j] = array[j], array[i] })
heapSorted := SlowHeapSort(array)
assert.Equal(t, sortedArray, heapSorted)
})
}
})
}

View File

@ -1,13 +0,0 @@
package utils
var NextId = make(chan int)
func init() {
go func() {
i := 0
for {
NextId <- i
i += 1
}
}()
}