mtproto: add compat transport quick ack support
(cherry picked from commit d051bc37bd14076fdd0a83ad41cd507929b20ece)
This commit is contained in:
parent
47cab2c9b0
commit
091d8f084b
11 changed files with 915 additions and 21 deletions
|
|
@ -2,6 +2,8 @@ package mtprotoedge
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -125,6 +127,9 @@ func (s *Server) handleEncrypted(ctx context.Context, tc transport.Conn, cs *con
|
|||
)
|
||||
return current, s.sendBadMsg(ctx, current, data.MessageID, data.SeqNo, code)
|
||||
}
|
||||
if err := sendQuickAckIfRequested(ctx, tc, key, data); err != nil {
|
||||
return current, err
|
||||
}
|
||||
|
||||
content := clientMessageNeedsAck(typeID)
|
||||
if record, ok := cs.seenRecord(data.MessageID); ok {
|
||||
|
|
@ -170,6 +175,30 @@ func (s *Server) handleEncrypted(ctx context.Context, tc transport.Conn, cs *con
|
|||
return current, nil
|
||||
}
|
||||
|
||||
func sendQuickAckIfRequested(ctx context.Context, tc transport.Conn, key crypto.AuthKey, data *crypto.EncryptedMessageData) error {
|
||||
q, ok := tc.(quickAckTransport)
|
||||
if !ok || !q.ConsumeQuickAckRequested() {
|
||||
return nil
|
||||
}
|
||||
token, err := clientQuickAckToken(key, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return q.SendQuickAck(ctx, token)
|
||||
}
|
||||
|
||||
func clientQuickAckToken(key crypto.AuthKey, data *crypto.EncryptedMessageData) (uint32, error) {
|
||||
var plain bin.Buffer
|
||||
if err := data.Encode(&plain); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
h := sha256.New()
|
||||
_, _ = h.Write(key.Value[88:120])
|
||||
_, _ = h.Write(plain.Raw())
|
||||
sum := h.Sum(nil)
|
||||
return binary.LittleEndian.Uint32(sum[:4]) &^ quickAckResponseFlag, nil
|
||||
}
|
||||
|
||||
// dispatch 处理一条明文消息:解包 container/gzip,处理服务消息,其余转 RPC 路由。
|
||||
// content-related 消息(ping、RPC)的 msg_id 会收集到 acks 以便统一确认。
|
||||
func (s *Server) dispatch(ctx context.Context, cs *connState, c *Conn, msgID int64, seqNo int32, b *bin.Buffer, acks *[]int64) error {
|
||||
|
|
@ -560,6 +589,9 @@ func validateClientEnvelope(now time.Time, msgID int64, seqNo int32, typeID uint
|
|||
if msgTime.After(now.Add(30 * time.Second)) {
|
||||
return badMsgIDTooHigh
|
||||
}
|
||||
if clientMessageAllowsEitherSeqParity(typeID) {
|
||||
return 0
|
||||
}
|
||||
if clientMessageNeedsAck(typeID) {
|
||||
if seqNo%2 == 0 {
|
||||
return badMsgSeqNotOdd
|
||||
|
|
@ -593,6 +625,9 @@ func validateClientContainerEnvelope(msgID int64, seqNo int32, typeID uint32) in
|
|||
if msgID == 0 || proto.MessageID(msgID).Type() != proto.MessageFromClient {
|
||||
return badMsgIDInvalidBits
|
||||
}
|
||||
if clientMessageAllowsEitherSeqParity(typeID) {
|
||||
return 0
|
||||
}
|
||||
if clientMessageNeedsAck(typeID) {
|
||||
if seqNo%2 == 0 {
|
||||
return badMsgSeqNotOdd
|
||||
|
|
@ -603,6 +638,15 @@ func validateClientContainerEnvelope(msgID int64, seqNo int32, typeID uint32) in
|
|||
return 0
|
||||
}
|
||||
|
||||
func clientMessageAllowsEitherSeqParity(typeID uint32) bool {
|
||||
switch typeID {
|
||||
case mt.PingDelayDisconnectRequestTypeID:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func clientMessageNeedsAck(typeID uint32) bool {
|
||||
switch typeID {
|
||||
case proto.MessageContainerTypeID,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue