Add announcePeer feature.
TODO: fix sync write congestion control Request timeout
This commit is contained in:
14
utp/conn.go
14
utp/conn.go
@@ -19,7 +19,7 @@ type Conn struct {
|
||||
recvID uint16
|
||||
sendID uint16
|
||||
|
||||
in chan packet
|
||||
in chan Packet
|
||||
reads chan readReq
|
||||
writes chan writeReq
|
||||
closeReq chan struct{}
|
||||
@@ -150,10 +150,10 @@ func (c *Conn) retrans() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) recv(p packet) (bool, error) {
|
||||
switch p.hdr.typ {
|
||||
func (c *Conn) recv(p Packet) (bool, error) {
|
||||
switch p.Hdr.typ {
|
||||
case Syn:
|
||||
c.ack = p.hdr.seq
|
||||
c.ack = p.Hdr.seq
|
||||
if err := c.sendState(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -161,18 +161,18 @@ func (c *Conn) recv(p packet) (bool, error) {
|
||||
select {
|
||||
case <-c.ready:
|
||||
default:
|
||||
c.ack = p.hdr.seq - 1
|
||||
c.ack = p.Hdr.seq - 1
|
||||
close(c.ready)
|
||||
}
|
||||
var remaining []sent
|
||||
for _, s := range c.unacked {
|
||||
if seqLess(p.hdr.ack, s.seq) {
|
||||
if seqLess(p.Hdr.ack, s.seq) {
|
||||
remaining = append(remaining, s)
|
||||
}
|
||||
}
|
||||
c.unacked = remaining
|
||||
case Data:
|
||||
seq, payload := p.hdr.seq, p.payload
|
||||
seq, payload := p.Hdr.seq, p.Payload
|
||||
if seq == c.ack+1 {
|
||||
c.deliver(payload)
|
||||
c.ack++
|
||||
|
||||
@@ -57,6 +57,7 @@ func decode(buf []byte) header {
|
||||
|
||||
type Socket struct {
|
||||
conn *net.UDPConn
|
||||
dhtCh chan<- Packet
|
||||
mu sync.RWMutex
|
||||
conns map[uint16]*Conn
|
||||
accepts chan *Conn
|
||||
@@ -64,30 +65,24 @@ type Socket struct {
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
type packet struct {
|
||||
hdr header
|
||||
payload []byte
|
||||
addr *net.UDPAddr
|
||||
type Packet struct {
|
||||
Hdr header
|
||||
Payload []byte
|
||||
Raw []byte
|
||||
Addr *net.UDPAddr
|
||||
}
|
||||
|
||||
func New(addr string) (*Socket, error) {
|
||||
a, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn, err := net.ListenUDP("udp", a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func New(conn *net.UDPConn, dhtCh chan<- Packet) *Socket {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
s := &Socket{
|
||||
conn: conn,
|
||||
dhtCh: dhtCh,
|
||||
conns: make(map[uint16]*Conn),
|
||||
accepts: make(chan *Conn, 16),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
return s, nil
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Socket) Start() {
|
||||
@@ -101,30 +96,42 @@ func (s *Socket) reader() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if n == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
data := append([]byte(nil), buf[:n]...)
|
||||
|
||||
if data[0] == 'd' {
|
||||
select {
|
||||
case s.dhtCh <- Packet{Raw: data, Addr: addr}:
|
||||
default:
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if n < headerSize {
|
||||
continue
|
||||
}
|
||||
hdr := decode(buf)
|
||||
payload := make([]byte, n-headerSize)
|
||||
copy(payload, buf[headerSize:n])
|
||||
|
||||
if hdr.typ == Syn {
|
||||
s.handleSyn(hdr, payload, addr)
|
||||
pkt := NewPacket(data, addr)
|
||||
if pkt.Hdr.typ == Syn {
|
||||
s.handleSyn(pkt)
|
||||
} else {
|
||||
s.dispatch(hdr, payload)
|
||||
s.dispatch(pkt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Socket) handleSyn(hdr header, payload []byte, addr *net.UDPAddr) {
|
||||
c := s.newConn(hdr.connID, addr, false)
|
||||
func (s *Socket) handleSyn(pkt Packet) {
|
||||
c := s.newConn(pkt.Hdr.connID, pkt.Addr, false)
|
||||
|
||||
s.mu.Lock()
|
||||
s.conns[c.recvID] = c
|
||||
s.mu.Unlock()
|
||||
|
||||
go c.run()
|
||||
c.in <- packet{hdr, payload, addr}
|
||||
c.in <- pkt
|
||||
|
||||
select {
|
||||
case s.accepts <- c:
|
||||
@@ -133,14 +140,14 @@ func (s *Socket) handleSyn(hdr header, payload []byte, addr *net.UDPAddr) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Socket) dispatch(hdr header, payload []byte) {
|
||||
func (s *Socket) dispatch(pkt Packet) {
|
||||
s.mu.RLock()
|
||||
c := s.conns[hdr.connID]
|
||||
c := s.conns[pkt.Hdr.connID]
|
||||
s.mu.RUnlock()
|
||||
|
||||
if c != nil {
|
||||
select {
|
||||
case c.in <- packet{hdr, payload, nil}:
|
||||
case c.in <- pkt:
|
||||
default:
|
||||
}
|
||||
}
|
||||
@@ -157,7 +164,7 @@ func (s *Socket) newConn(peerID uint16, addr *net.UDPAddr, initiator bool) *Conn
|
||||
c := &Conn{
|
||||
sock: s,
|
||||
addr: addr,
|
||||
in: make(chan packet, 16),
|
||||
in: make(chan Packet, 256),
|
||||
reads: make(chan readReq),
|
||||
writes: make(chan writeReq),
|
||||
closeReq: make(chan struct{}),
|
||||
@@ -202,6 +209,10 @@ func (s *Socket) Close() {
|
||||
s.cancel()
|
||||
}
|
||||
|
||||
func (s *Socket) LocalPort() int {
|
||||
return s.conn.LocalAddr().(*net.UDPAddr).Port
|
||||
}
|
||||
|
||||
func randUint16() uint16 {
|
||||
var b [2]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
@@ -209,3 +220,15 @@ func randUint16() uint16 {
|
||||
}
|
||||
return binary.BigEndian.Uint16(b[:])
|
||||
}
|
||||
|
||||
func NewPacket(data []byte, addr *net.UDPAddr) Packet {
|
||||
pkt := Packet{
|
||||
Raw: data,
|
||||
Addr: addr,
|
||||
}
|
||||
if len(data) >= headerSize {
|
||||
pkt.Hdr = decode(data)
|
||||
pkt.Payload = data[headerSize:]
|
||||
}
|
||||
return pkt
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user