This repository has been archived by the owner on Apr 23, 2020. It is now read-only.
/
server.go
105 lines (94 loc) · 2.33 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package udp
import (
"log"
"net"
"github.com/reusee/closer"
ic "github.com/reusee/inf-chan"
)
type Server struct {
closer.Closer
*Logger
udpConn *net.UDPConn
udpConnClosed bool
newConnsIn chan *Conn
NewConns chan *Conn
}
func NewServer(addrStr string) (*Server, error) {
addr, err := net.ResolveUDPAddr("udp", addrStr)
if err != nil {
return nil, err
}
udpConn, err := net.ListenUDP("udp", addr)
if err != nil {
return nil, err
}
server := &Server{
Logger: newLogger(),
udpConn: udpConn,
newConnsIn: make(chan *Conn),
NewConns: make(chan *Conn),
}
ic.Link(server.newConnsIn, server.NewConns)
server.OnClose(func() {
server.udpConnClosed = true
udpConn.Close()
close(server.newConnsIn)
})
go func() { // listen
conns := make(map[string]*Conn)
for {
// read packet
packetData := make([]byte, 1500)
n, addr, err := udpConn.ReadFromUDP(packetData)
if err != nil {
if server.udpConnClosed {
return
} else {
log.Fatalf("server read error %v", err)
}
}
packetData = packetData[:n]
server.Log("ReadFromUDP length %d", n)
// dispatch
key := addr.String()
conn, ok := conns[key]
if !ok { // new connection
server.newConn(conns, addr, packetData)
} else {
conn.incomingPacketsIn <- packetData
}
}
}()
return server, nil
}
func (s *Server) readPacket(packetData []byte) (uint32, uint32, byte, uint16, []byte) {
serial, ackSerial, flag, windowSize, data := readPacket(packetData)
s.Log("readPacket serial %d ackSerial %d flag %b windowSize %d length %d",
serial, ackSerial, flag, windowSize, len(data))
return serial, ackSerial, flag, windowSize, data
}
func (s *Server) newConn(conns map[string]*Conn, remoteAddr *net.UDPAddr, packetData []byte) {
serial, _, flag, _, _ := s.readPacket(packetData)
if flag&SYNC == 0 { // not a sync packet
s.Log("newConn ignore from %s", remoteAddr.String())
return
}
conn := makeConn()
conn.writeUDP = func(data []byte) error {
_, err := s.udpConn.WriteToUDP(data, remoteAddr)
return err
}
conn.ackSerial = serial + 1
conns[remoteAddr.String()] = conn
conn.OnClose(func() {
delete(conns, remoteAddr.String())
})
s.newConnsIn <- conn
go func() {
if err := conn.handshake(); err != nil {
return
}
conn.start()
}()
s.Log("newConn addr %s serial %d", remoteAddr.String(), serial)
}