fix: remove recover(), fix buf size, handle errors

fix: remove recover(), fix buf size, handle errors
This commit is contained in:
cubexteam
2026-03-04 18:19:55 +03:00
committed by GitHub
parent b16628dd5d
commit 4435c362be

View File

@@ -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,47 +261,40 @@ 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
}
if !sess.IsConnected() { default:
return if !sess.IsConnected() {
} return
}
if s.handler != nil { if s.handler != nil {
s.handler.OnPacket(sess, payload) s.handler.OnPacket(sess, payload)
}
} }
} }