fix: remove recover(), fix buf size, handle errors
fix: remove recover(), fix buf size, handle errors
This commit is contained in:
@@ -47,12 +47,12 @@ func (s *Server) Start(ip string, port int) error {
|
|||||||
func (s *Server) Shutdown() {
|
func (s *Server) Shutdown() {
|
||||||
s.running = false
|
s.running = false
|
||||||
if s.conn != nil {
|
if s.conn != nil {
|
||||||
s.conn.Close()
|
_ = s.conn.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) readLoop() {
|
func (s *Server) readLoop() {
|
||||||
buf := make([]byte, 2048)
|
buf := make([]byte, MaxMTU+100)
|
||||||
for s.running {
|
for s.running {
|
||||||
n, addr, err := s.conn.ReadFromUDP(buf)
|
n, addr, err := s.conn.ReadFromUDP(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -63,10 +63,7 @@ func (s *Server) readLoop() {
|
|||||||
}
|
}
|
||||||
data := make([]byte, n)
|
data := make([]byte, n)
|
||||||
copy(data, buf[:n])
|
copy(data, buf[:n])
|
||||||
go func(a *net.UDPAddr, d []byte) {
|
go s.handlePacket(addr, data)
|
||||||
defer func() { recover() }()
|
|
||||||
s.handlePacket(a, d)
|
|
||||||
}(addr, data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +108,7 @@ func (s *Server) handlePacket(addr *net.UDPAddr, data []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
pong := BuildUnconnectedPong(ts, s.guid, s.motdFunc())
|
pong := BuildUnconnectedPong(ts, s.guid, s.motdFunc())
|
||||||
s.conn.WriteToUDP(pong, addr)
|
_, _ = s.conn.WriteToUDP(pong, addr)
|
||||||
|
|
||||||
case id == 0x05:
|
case id == 0x05:
|
||||||
proto, mtu, ok := ParseOCR1(data)
|
proto, mtu, ok := ParseOCR1(data)
|
||||||
@@ -121,7 +118,7 @@ func (s *Server) handlePacket(addr *net.UDPAddr, data []byte) {
|
|||||||
if mtu > MaxMTU {
|
if mtu > MaxMTU {
|
||||||
mtu = MaxMTU
|
mtu = MaxMTU
|
||||||
}
|
}
|
||||||
s.conn.WriteToUDP(BuildOpenConnectionReply1(s.guid, mtu), addr)
|
_, _ = s.conn.WriteToUDP(BuildOpenConnectionReply1(s.guid, mtu), addr)
|
||||||
|
|
||||||
case id == 0x07:
|
case id == 0x07:
|
||||||
clientGUID, _, mtu, ok := ParseOCR2(data)
|
clientGUID, _, mtu, ok := ParseOCR2(data)
|
||||||
@@ -140,7 +137,7 @@ func (s *Server) handlePacket(addr *net.UDPAddr, data []byte) {
|
|||||||
sess := NewSession(s.conn, addr, clientGUID, mtu)
|
sess := NewSession(s.conn, addr, clientGUID, mtu)
|
||||||
s.sessions[key] = sess
|
s.sessions[key] = sess
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
s.conn.WriteToUDP(BuildOpenConnectionReply2(s.guid, *addr, mtu), addr)
|
_, _ = s.conn.WriteToUDP(BuildOpenConnectionReply2(s.guid, *addr, mtu), addr)
|
||||||
|
|
||||||
case id >= 0x80 && id <= 0x8f:
|
case id >= 0x80 && id <= 0x8f:
|
||||||
sess := s.getSession(addr)
|
sess := s.getSession(addr)
|
||||||
@@ -150,14 +147,12 @@ func (s *Server) handlePacket(addr *net.UDPAddr, data []byte) {
|
|||||||
s.handleDatagram(sess, data)
|
s.handleDatagram(sess, data)
|
||||||
|
|
||||||
case id == 0xc0:
|
case id == 0xc0:
|
||||||
sess := s.getSession(addr)
|
if sess := s.getSession(addr); sess != nil {
|
||||||
if sess != nil {
|
|
||||||
sess.HandleACK(data)
|
sess.HandleACK(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
case id == 0xa0:
|
case id == 0xa0:
|
||||||
sess := s.getSession(addr)
|
if sess := s.getSession(addr); sess != nil {
|
||||||
if sess != nil {
|
|
||||||
sess.HandleNACK(data)
|
sess.HandleNACK(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,16 +167,16 @@ func (s *Server) handleDatagram(sess *Session, data []byte) {
|
|||||||
sess.mu.Lock()
|
sess.mu.Lock()
|
||||||
sess.lastRecv = time.Now()
|
sess.lastRecv = time.Now()
|
||||||
|
|
||||||
if sess.recvSeqs[dg.SeqNum] {
|
if _, seen := sess.recvSeqs[dg.SeqNum]; seen {
|
||||||
sess.mu.Unlock()
|
sess.mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sess.recvSeqs[dg.SeqNum] = true
|
sess.recvSeqs[dg.SeqNum] = struct{}{}
|
||||||
sess.pendingACK = append(sess.pendingACK, dg.SeqNum)
|
sess.pendingACK = append(sess.pendingACK, dg.SeqNum)
|
||||||
|
|
||||||
if dg.SeqNum > sess.recvSeq+1 {
|
if dg.SeqNum > sess.recvSeq+1 {
|
||||||
for n := sess.recvSeq + 1; n < dg.SeqNum; n++ {
|
for n := sess.recvSeq + 1; n < dg.SeqNum; n++ {
|
||||||
if !sess.recvSeqs[n] {
|
if _, seen := sess.recvSeqs[n]; !seen {
|
||||||
sess.pendingNACK = append(sess.pendingNACK, n)
|
sess.pendingNACK = append(sess.pendingNACK, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,29 +196,27 @@ func (s *Server) handleFrame(sess *Session, f *Frame) {
|
|||||||
sess.mu.Lock()
|
sess.mu.Lock()
|
||||||
buf, ok := sess.splitMap[f.SplitID]
|
buf, ok := sess.splitMap[f.SplitID]
|
||||||
if !ok {
|
if !ok {
|
||||||
buf = &splitBuf{count: f.SplitCount, parts: make(map[uint32][]byte)}
|
buf = &splitBuf{count: f.SplitCount, parts: make(map[uint32][]byte, f.SplitCount)}
|
||||||
sess.splitMap[f.SplitID] = buf
|
sess.splitMap[f.SplitID] = buf
|
||||||
}
|
}
|
||||||
buf.parts[f.SplitIndex] = f.Payload
|
buf.parts[f.SplitIndex] = f.Payload
|
||||||
assembled := false
|
var assembled []byte
|
||||||
var full []byte
|
|
||||||
if uint32(len(buf.parts)) >= buf.count {
|
if uint32(len(buf.parts)) >= buf.count {
|
||||||
|
assembled = make([]byte, 0, int(buf.count)*len(f.Payload))
|
||||||
for i := uint32(0); i < buf.count; i++ {
|
for i := uint32(0); i < buf.count; i++ {
|
||||||
full = append(full, buf.parts[i]...)
|
assembled = append(assembled, buf.parts[i]...)
|
||||||
}
|
}
|
||||||
delete(sess.splitMap, f.SplitID)
|
delete(sess.splitMap, f.SplitID)
|
||||||
assembled = true
|
|
||||||
}
|
}
|
||||||
sess.mu.Unlock()
|
sess.mu.Unlock()
|
||||||
if assembled {
|
if assembled != nil {
|
||||||
combined := &Frame{
|
s.handleFrame(sess, &Frame{
|
||||||
Reliability: f.Reliability,
|
Reliability: f.Reliability,
|
||||||
MessageIndex: f.MessageIndex,
|
MessageIndex: f.MessageIndex,
|
||||||
OrderIndex: f.OrderIndex,
|
OrderIndex: f.OrderIndex,
|
||||||
OrderChannel: f.OrderChannel,
|
OrderChannel: f.OrderChannel,
|
||||||
Payload: full,
|
Payload: assembled,
|
||||||
}
|
})
|
||||||
s.handleFrame(sess, combined)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -268,48 +261,41 @@ func (s *Server) dispatch(sess *Session, payload []byte) {
|
|||||||
}
|
}
|
||||||
id := payload[0]
|
id := payload[0]
|
||||||
|
|
||||||
if id == 0x09 {
|
switch id {
|
||||||
|
case 0x09:
|
||||||
_, timestamp, ok := ParseConnectionRequest(payload)
|
_, timestamp, ok := ParseConnectionRequest(payload)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
accepted := BuildConnectionRequestAccepted(*sess.Addr, timestamp, sess.Timestamp())
|
accepted := BuildConnectionRequestAccepted(*sess.Addr, timestamp, sess.Timestamp())
|
||||||
sess.Send(accepted, ReliableOrdered, 0)
|
sess.Send(accepted, ReliableOrdered, 0)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if id == 0x13 {
|
case 0x13:
|
||||||
sess.SetConnected()
|
sess.SetConnected()
|
||||||
if s.handler != nil {
|
if s.handler != nil {
|
||||||
s.handler.OnConnect(sess)
|
s.handler.OnConnect(sess)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if id == 0x15 {
|
case 0x15:
|
||||||
s.removeSession(sess)
|
s.removeSession(sess)
|
||||||
if s.handler != nil {
|
if s.handler != nil {
|
||||||
s.handler.OnDisconnect(sess)
|
s.handler.OnDisconnect(sess)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if id == 0x00 {
|
case 0x00:
|
||||||
t, ok := ParseConnectedPing(payload)
|
t, ok := ParseConnectedPing(payload)
|
||||||
if ok {
|
if ok {
|
||||||
pong := BuildConnectedPong(t, sess.Timestamp())
|
sess.Send(BuildConnectedPong(t, sess.Timestamp()), Unreliable, 0)
|
||||||
sess.Send(pong, Unreliable, 0)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
if !sess.IsConnected() {
|
if !sess.IsConnected() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.handler != nil {
|
if s.handler != nil {
|
||||||
s.handler.OnPacket(sess, payload)
|
s.handler.OnPacket(sess, payload)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) getSession(addr *net.UDPAddr) *Session {
|
func (s *Server) getSession(addr *net.UDPAddr) *Session {
|
||||||
|
|||||||
Reference in New Issue
Block a user