2020-11-25 19:35:31 +00:00
|
|
|
package udp
|
|
|
|
|
|
|
|
import (
|
2021-03-30 20:57:53 +01:00
|
|
|
"context"
|
2020-11-25 19:35:31 +00:00
|
|
|
"log"
|
|
|
|
"mpbl3p/proxy"
|
|
|
|
"net"
|
2021-03-31 18:45:41 +01:00
|
|
|
"time"
|
2020-11-25 19:35:31 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-30 20:57:53 +01:00
|
|
|
func NewListener(ctx context.Context, p *proxy.Proxy, local string, v func() proxy.MacVerifier, g func() proxy.MacGenerator, c func() Congestion) error {
|
2020-11-25 19:35:31 +00:00
|
|
|
laddr, err := net.ResolveUDPAddr("udp", local)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
pconn, err := net.ListenUDP("udp", laddr)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
receivedConnections := make(map[ComparableUdpAddress]*Flow)
|
|
|
|
|
|
|
|
go func() {
|
2021-03-31 18:45:41 +01:00
|
|
|
for ctx.Err() == nil {
|
2020-11-27 17:31:32 +00:00
|
|
|
buf := make([]byte, 6000)
|
2020-11-25 19:35:31 +00:00
|
|
|
|
2021-03-31 18:45:41 +01:00
|
|
|
if err := pconn.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2020-11-27 17:31:32 +00:00
|
|
|
n, addr, err := pconn.ReadFromUDP(buf)
|
2020-11-25 19:35:31 +00:00
|
|
|
if err != nil {
|
2021-03-31 18:45:41 +01:00
|
|
|
if e, ok := err.(net.Error); ok && e.Timeout() {
|
|
|
|
continue
|
|
|
|
}
|
2020-11-25 19:35:31 +00:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2021-04-15 15:28:50 +01:00
|
|
|
// TODO: Support congestion exchange here
|
|
|
|
|
2020-11-25 19:35:31 +00:00
|
|
|
raddr := fromUdpAddress(*addr)
|
|
|
|
if f, exists := receivedConnections[raddr]; exists {
|
2021-03-30 20:57:53 +01:00
|
|
|
log.Println("existing flow. queuing...")
|
|
|
|
if err := f.queueDatagram(ctx, buf[:n]); err != nil {
|
2021-04-15 15:28:50 +01:00
|
|
|
log.Println("error")
|
|
|
|
continue
|
2021-03-30 20:57:53 +01:00
|
|
|
}
|
|
|
|
log.Println("queued")
|
2020-11-25 19:35:31 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-11-29 22:06:38 +00:00
|
|
|
v := v()
|
|
|
|
g := g()
|
|
|
|
|
2020-11-27 20:17:59 +00:00
|
|
|
f := newFlow(c(), v)
|
2020-11-26 22:10:37 +00:00
|
|
|
|
|
|
|
f.writer = pconn
|
2020-11-26 22:46:37 +00:00
|
|
|
f.raddr = addr
|
2020-11-26 22:10:37 +00:00
|
|
|
f.isAlive = true
|
|
|
|
|
2020-11-27 17:31:32 +00:00
|
|
|
log.Printf("received new udp connection: %v\n", f)
|
2020-11-25 19:35:31 +00:00
|
|
|
|
2021-03-30 20:57:53 +01:00
|
|
|
go f.earlyUpdateLoop(ctx, g, 0)
|
2020-11-25 19:35:31 +00:00
|
|
|
|
2020-11-27 17:31:32 +00:00
|
|
|
receivedConnections[raddr] = &f
|
2020-11-25 19:35:31 +00:00
|
|
|
|
2021-03-30 20:57:53 +01:00
|
|
|
p.AddConsumer(ctx, &f, g)
|
|
|
|
p.AddProducer(ctx, &f, v)
|
2020-11-27 17:31:32 +00:00
|
|
|
|
|
|
|
log.Println("handling...")
|
2021-03-31 18:45:41 +01:00
|
|
|
if err := f.queueDatagram(ctx, buf[:n]); err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-11-27 17:31:32 +00:00
|
|
|
log.Println("handled")
|
2020-11-25 19:35:31 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|