Add keepalive command and sequence handling to new protocol
This commit is contained in:
+34
-20
@@ -49,6 +49,7 @@ type Conn struct {
|
|||||||
seq uint16
|
seq uint16
|
||||||
seqCmd uint16
|
seqCmd uint16
|
||||||
avSeq uint32
|
avSeq uint32
|
||||||
|
kaSeq uint32
|
||||||
|
|
||||||
// DTLS
|
// DTLS
|
||||||
main *dtls.Conn
|
main *dtls.Conn
|
||||||
@@ -317,8 +318,6 @@ func (c *Conn) WriteAndWait(req []byte, timeout time.Duration, ok func(res []byt
|
|||||||
|
|
||||||
func (c *Conn) WriteAndWaitIOCtrl(cmd uint16, payload []byte, expectCmd uint16, timeout time.Duration) ([]byte, error) {
|
func (c *Conn) WriteAndWaitIOCtrl(cmd uint16, payload []byte, expectCmd uint16, timeout time.Duration) ([]byte, error) {
|
||||||
frame := c.buildIOCtrlFrame(payload)
|
frame := c.buildIOCtrlFrame(payload)
|
||||||
|
|
||||||
// Retry send every second
|
|
||||||
var t *time.Timer
|
var t *time.Timer
|
||||||
t = time.AfterFunc(1, func() {
|
t = time.AfterFunc(1, func() {
|
||||||
if _, err := c.main.Write(frame); err == nil && t != nil {
|
if _, err := c.main.Write(frame); err == nil && t != nil {
|
||||||
@@ -588,15 +587,23 @@ func (c *Conn) reader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NEW protocol (0xCC51)
|
// NEW protocol (0xCC51)
|
||||||
if c.newProto && n >= NewHeaderSize+NewAuthSize && binary.LittleEndian.Uint16(buf[:2]) == MagicNewProto {
|
if c.newProto && n >= 12 && binary.LittleEndian.Uint16(buf[:2]) == MagicNewProto {
|
||||||
if binary.LittleEndian.Uint16(buf[4:]) == CmdNewDTLS {
|
cmd := binary.LittleEndian.Uint16(buf[4:])
|
||||||
ch := byte(binary.LittleEndian.Uint16(buf[12:]) >> 8)
|
switch cmd {
|
||||||
dtls := buf[NewHeaderSize : n-NewAuthSize]
|
case CmdNewKeepalive:
|
||||||
switch ch {
|
if n >= NewKeepaliveSize {
|
||||||
case IOTCChannelMain:
|
_ = c.Write(c.buildNewKeepalive())
|
||||||
c.queue(c.mainBuf, dtls)
|
}
|
||||||
case IOTCChannelBack:
|
case CmdNewDTLS:
|
||||||
c.queue(c.speakBuf, dtls)
|
if n >= NewHeaderSize+NewAuthSize {
|
||||||
|
ch := byte(binary.LittleEndian.Uint16(buf[12:]) >> 8)
|
||||||
|
dtls := buf[NewHeaderSize : n-NewAuthSize]
|
||||||
|
switch ch {
|
||||||
|
case IOTCChannelMain:
|
||||||
|
c.queue(c.mainBuf, dtls)
|
||||||
|
case IOTCChannelBack:
|
||||||
|
c.queue(c.speakBuf, dtls)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@@ -696,7 +703,6 @@ func (c *Conn) buildDisco(stage byte) []byte {
|
|||||||
binary.LittleEndian.PutUint16(b[4:], OldDiscoBodySize) // body size
|
binary.LittleEndian.PutUint16(b[4:], OldDiscoBodySize) // body size
|
||||||
binary.LittleEndian.PutUint16(b[8:], CmdDiscoReq) // 0x0601
|
binary.LittleEndian.PutUint16(b[8:], CmdDiscoReq) // 0x0601
|
||||||
binary.LittleEndian.PutUint16(b[10:], 0x0021) // flags
|
binary.LittleEndian.PutUint16(b[10:], 0x0021) // flags
|
||||||
|
|
||||||
body := b[OldHeaderSize:]
|
body := b[OldHeaderSize:]
|
||||||
copy(body[:UIDSize], c.uid)
|
copy(body[:UIDSize], c.uid)
|
||||||
copy(body[36:], "\x01\x01\x02\x04") // unknown
|
copy(body[36:], "\x01\x01\x02\x04") // unknown
|
||||||
@@ -720,8 +726,6 @@ func (c *Conn) buildNewDisco(seq, ticket uint16, isResponse bool) []byte {
|
|||||||
binary.LittleEndian.PutUint16(b[14:], ticket)
|
binary.LittleEndian.PutUint16(b[14:], ticket)
|
||||||
copy(b[16:24], c.sid)
|
copy(b[16:24], c.sid)
|
||||||
copy(b[24:32], "\x00\x08\x03\x04\x1d\x00\x00\x00") // SDK 4.3.8.0
|
copy(b[24:32], "\x00\x08\x03\x04\x1d\x00\x00\x00") // SDK 4.3.8.0
|
||||||
|
|
||||||
// HMAC-SHA1(UID+AuthKey, header)
|
|
||||||
authKey := crypto.CalculateAuthKey(c.enr, c.mac)
|
authKey := crypto.CalculateAuthKey(c.enr, c.mac)
|
||||||
h := hmac.New(sha1.New, append([]byte(c.uid), authKey...))
|
h := hmac.New(sha1.New, append([]byte(c.uid), authKey...))
|
||||||
h.Write(b[:32])
|
h.Write(b[:32])
|
||||||
@@ -729,13 +733,27 @@ func (c *Conn) buildNewDisco(seq, ticket uint16, isResponse bool) []byte {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Conn) buildNewKeepalive() []byte {
|
||||||
|
c.kaSeq += 2
|
||||||
|
b := make([]byte, NewKeepaliveSize)
|
||||||
|
binary.LittleEndian.PutUint16(b[0:], MagicNewProto) // 0xCC51
|
||||||
|
binary.LittleEndian.PutUint16(b[4:], CmdNewKeepalive) // 0x1202
|
||||||
|
binary.LittleEndian.PutUint16(b[6:], 0x0024) // 36 bytes payload
|
||||||
|
binary.LittleEndian.PutUint32(b[16:], c.kaSeq) // counter
|
||||||
|
copy(b[20:28], c.sid) // session ID
|
||||||
|
authKey := crypto.CalculateAuthKey(c.enr, c.mac)
|
||||||
|
h := hmac.New(sha1.New, append([]byte(c.uid), authKey...))
|
||||||
|
h.Write(b[:28])
|
||||||
|
copy(b[28:48], h.Sum(nil))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Conn) buildSession() []byte {
|
func (c *Conn) buildSession() []byte {
|
||||||
b := make([]byte, OldSessionSize)
|
b := make([]byte, OldSessionSize)
|
||||||
copy(b, "\x04\x02\x1a\x02") // marker + mode
|
copy(b, "\x04\x02\x1a\x02") // marker + mode
|
||||||
binary.LittleEndian.PutUint16(b[4:], OldSessionBody) // body size
|
binary.LittleEndian.PutUint16(b[4:], OldSessionBody) // body size
|
||||||
binary.LittleEndian.PutUint16(b[8:], CmdSessionReq) // 0x0402
|
binary.LittleEndian.PutUint16(b[8:], CmdSessionReq) // 0x0402
|
||||||
binary.LittleEndian.PutUint16(b[10:], 0x0033) // flags
|
binary.LittleEndian.PutUint16(b[10:], 0x0033) // flags
|
||||||
|
|
||||||
body := b[OldHeaderSize:]
|
body := b[OldHeaderSize:]
|
||||||
copy(body[:UIDSize], c.uid)
|
copy(body[:UIDSize], c.uid)
|
||||||
copy(body[UIDSize:], c.rid)
|
copy(body[UIDSize:], c.rid)
|
||||||
@@ -805,9 +823,7 @@ func (c *Conn) buildAudioFrame(payload []byte, timestampUS uint32, codec uint16,
|
|||||||
binary.LittleEndian.PutUint32(b[24:], uint32(totalPayload))
|
binary.LittleEndian.PutUint32(b[24:], uint32(totalPayload))
|
||||||
binary.LittleEndian.PutUint32(b[28:], prevFrame)
|
binary.LittleEndian.PutUint32(b[28:], prevFrame)
|
||||||
binary.LittleEndian.PutUint32(b[32:], c.audioFrame)
|
binary.LittleEndian.PutUint32(b[32:], c.audioFrame)
|
||||||
|
copy(b[36:], payload) // Payload + FrameInfo
|
||||||
// Payload + FrameInfo
|
|
||||||
copy(b[36:], payload)
|
|
||||||
fi := b[36+len(payload):]
|
fi := b[36+len(payload):]
|
||||||
binary.LittleEndian.PutUint16(fi, codec)
|
binary.LittleEndian.PutUint16(fi, codec)
|
||||||
fi[2] = BuildAudioFlags(sampleRate, true, channels == 2)
|
fi[2] = BuildAudioFlags(sampleRate, true, channels == 2)
|
||||||
@@ -845,8 +861,6 @@ func (c *Conn) buildNewTxData(payload []byte, channel byte) []byte {
|
|||||||
copy(b[16:24], c.sid)
|
copy(b[16:24], c.sid)
|
||||||
binary.LittleEndian.PutUint32(b[24:], 1) // const
|
binary.LittleEndian.PutUint32(b[24:], 1) // const
|
||||||
copy(b[NewHeaderSize:], payload)
|
copy(b[NewHeaderSize:], payload)
|
||||||
|
|
||||||
// HMAC-SHA1(UID+AuthKey, header)
|
|
||||||
authKey := crypto.CalculateAuthKey(c.enr, c.mac)
|
authKey := crypto.CalculateAuthKey(c.enr, c.mac)
|
||||||
h := hmac.New(sha1.New, append([]byte(c.uid), authKey...))
|
h := hmac.New(sha1.New, append([]byte(c.uid), authKey...))
|
||||||
h.Write(b[:NewHeaderSize])
|
h.Write(b[:NewHeaderSize])
|
||||||
|
|||||||
+10
-7
@@ -138,13 +138,16 @@ const (
|
|||||||
|
|
||||||
// NEW Protocol (0xCC51)
|
// NEW Protocol (0xCC51)
|
||||||
const (
|
const (
|
||||||
MagicNewProto uint16 = 0xCC51
|
MagicNewProto uint16 = 0xCC51
|
||||||
CmdNewDisco uint16 = 0x1002
|
CmdNewDisco uint16 = 0x1002
|
||||||
CmdNewDTLS uint16 = 0x1502
|
CmdNewKeepalive uint16 = 0x1202
|
||||||
NewPayloadSize uint16 = 0x0028
|
CmdNewClose uint16 = 0x1302
|
||||||
NewPacketSize = 52
|
CmdNewDTLS uint16 = 0x1502
|
||||||
NewHeaderSize = 28
|
NewPayloadSize uint16 = 0x0028
|
||||||
NewAuthSize = 20
|
NewPacketSize = 52
|
||||||
|
NewHeaderSize = 28
|
||||||
|
NewAuthSize = 20
|
||||||
|
NewKeepaliveSize = 48
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
Reference in New Issue
Block a user