fix: 测试 WS 客户端按字节流拆包并恢复群事件同步下发
This commit is contained in:
+39
-8
@@ -12,6 +12,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -164,25 +165,35 @@ func (c *tcpMQTT) RemoteAddr() net.Addr {
|
||||
type wsMQTT struct {
|
||||
conn net.Conn
|
||||
r *bufio.Reader
|
||||
buf []byte
|
||||
wmu sync.Mutex
|
||||
}
|
||||
|
||||
func (c *wsMQTT) Send(packet []byte) error {
|
||||
c.wmu.Lock()
|
||||
defer c.wmu.Unlock()
|
||||
return writeWSClientBinary(c.conn, packet)
|
||||
}
|
||||
|
||||
func (c *wsMQTT) Recv() ([]byte, error) {
|
||||
for {
|
||||
if pkt, n, ok := splitMQTTPacket(c.buf); ok {
|
||||
c.buf = c.buf[n:]
|
||||
return pkt, nil
|
||||
}
|
||||
payload, opcode, err := readWSFrame(c.r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch opcode {
|
||||
case 0x2:
|
||||
return payload, nil
|
||||
case 0x0, 0x2:
|
||||
c.buf = append(c.buf, payload...)
|
||||
case 0x8:
|
||||
return nil, io.EOF
|
||||
case 0x9:
|
||||
c.wmu.Lock()
|
||||
_ = writeWSClientControl(c.conn, 0xA, payload)
|
||||
c.wmu.Unlock()
|
||||
case 0xA:
|
||||
continue
|
||||
default:
|
||||
@@ -265,17 +276,37 @@ func writeWSClientFrame(w io.Writer, opcode byte, payload []byte) error {
|
||||
header = append(header, ext[:]...)
|
||||
}
|
||||
header = append(header, mask...)
|
||||
masked := make([]byte, n)
|
||||
frame := make([]byte, len(header)+n)
|
||||
copy(frame, header)
|
||||
for i := 0; i < n; i++ {
|
||||
masked[i] = payload[i] ^ mask[i%4]
|
||||
frame[len(header)+i] = payload[i] ^ mask[i%4]
|
||||
}
|
||||
if _, err := w.Write(header); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := w.Write(masked)
|
||||
_, err := w.Write(frame)
|
||||
return err
|
||||
}
|
||||
|
||||
// splitMQTTPacket 从缓冲头部切出一个完整 MQTT 控制包。不够一包时返回 ok=false。
|
||||
func splitMQTTPacket(b []byte) ([]byte, int, bool) {
|
||||
if len(b) < 2 {
|
||||
return nil, 0, false
|
||||
}
|
||||
rem, mult := 0, 1
|
||||
for i := 1; i < len(b) && i <= 4; i++ {
|
||||
rem += int(b[i]&127) * mult
|
||||
if b[i]&128 == 0 {
|
||||
total := 1 + i + rem
|
||||
if total < 0 || len(b) < total {
|
||||
return nil, 0, false
|
||||
}
|
||||
pkt := make([]byte, total)
|
||||
copy(pkt, b[:total])
|
||||
return pkt, total, true
|
||||
}
|
||||
mult *= 128
|
||||
}
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
func readWSFrame(r *bufio.Reader) (payload []byte, opcode byte, err error) {
|
||||
b0, err := r.ReadByte()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user