merged with fixes

This commit is contained in:
onysd 2026-09-09 02:49:30 +03:00
parent a9e758b712
commit 2f1818d656
176 changed files with 9000 additions and 907 deletions

View file

@ -27,6 +27,7 @@ import (
"github.com/iamxvbaba/td/tlprofile"
"telesrv/internal/observability/dbtrace"
"telesrv/internal/postresponse"
"telesrv/internal/rpcresult"
"telesrv/internal/store"
)
@ -40,6 +41,7 @@ type connState struct {
createdFloor int64
seen map[int64]clientMsgRecord // 已处理的 client msg_id用于幂等和 msgs_state_req
order []int64
orderHead int
minSeen int64
maxSeen int64
// maxContentMsgID/maxContentSeqNo 是已接受 content 消息的 msg_id / seq_no 高水位,
@ -116,7 +118,7 @@ var errActivationAuthKeyRejected = errors.New("activation auth key no longer exi
// 直接复用 current.key/current.salt 解密。任何 provisional 在 claim 建立后、发 required
// control 前都会最终回查 AuthKeyStore使外部撤销与 activation 线性化。
// plain 是 serveConn 持有的复用明文缓冲frame 的 slice 仅在下一帧解密前有效。
func (s *Server) handleEncrypted(ctx context.Context, tc transport.Conn, cs *connState, current *Conn, fetchedKey *store.AuthKeyData, b, plain *bin.Buffer) (*Conn, error) {
func (s *Server) handleEncrypted(ctx context.Context, tc transport.Conn, cs *connState, current *Conn, remote string, fetchedKey *store.AuthKeyData, b, plain *bin.Buffer) (*Conn, error) {
var key crypto.AuthKey
var serverSalt int64
var authKeyExpiresAt int
@ -161,6 +163,8 @@ func (s *Server) handleEncrypted(ctx context.Context, tc transport.Conn, cs *con
} else {
current = s.newConn(tc, key, frame.sessionID, serverSalt)
}
// 记录对端 IP供绑定设备授权时写入 authorizations.ipadmin 面板可见)。
current.setRemoteAddrStr(remote)
current.authKeyExpiresAt = authKeyExpiresAt
// Same-session evidence is restored as explicit; auth-key metadata is only
// an inherited default and can be corrected by the next invokeWithLayer.
@ -904,7 +908,7 @@ func (s *Server) publishRPCResult(
priority := rpcResultPriority(method, encoded)
encoded.priority = priority
if metrics, ok := s.metrics.(RPCResultMetrics); ok {
metrics.RPCResultPrepared(method, priority.String(), encoded.uncompressedBytes, len(encoded.body), encoded.compressed)
metrics.RPCResultPrepared(method, priority.String(), encoded.uncompressedBytes, encoded.wireSize(), encoded.compressed)
}
visible := encoded.compressed || priority == outboundPriorityCritical || priority == outboundPriorityBulk
return priority, visible
@ -916,21 +920,26 @@ func (s *Server) publishRPCResult(
// re-execution hidden behind a local capacity error.
retainForReplay := func(encoded *encodedOutboundMessage, admissionErr error) error {
if s == nil || s.rpcResults == nil || c == nil || encoded == nil || reqMsgID == 0 {
if encoded != nil {
encoded.releaseBulkCredit()
}
return errors.New("rpc result receipt ledger is unavailable")
}
priority, visible := prepareEncoded(encoded)
if owner != nil && !owner.HandOff() {
encoded.releaseBulkCredit()
return ErrRPCResultFlightInvalid
}
started := time.Now()
encoded.markReplayable()
encoded.releaseBulkCredit()
// Complete may expose terminal execution only after the old connection
// is irreversibly unable to accept another same-generation request.
c.fenceUndeliveredRPCResult()
s.completeRPCResult(c, reqMsgID, encoded, false)
latency := time.Since(started)
if metrics, ok := s.metrics.(RPCResultMetrics); ok {
metrics.RPCResultDelivered(method, latency, len(encoded.body), admissionErr)
metrics.RPCResultDelivered(method, latency, encoded.wireSize(), admissionErr)
}
resultLogLevel := zap.DebugLevel
if visible {
@ -941,14 +950,15 @@ func (s *Server) publishRPCResult(
zap.String("method", method), zap.Int64("req_msg_id", reqMsgID),
zap.Int64("delivered_req_msg_id", encoded.writtenRequestID()),
zap.String("auth_key_id", c.authKeyHex), zap.Int64("session_id", c.sessionID),
zap.Int("wire_bytes", len(encoded.body)), zap.Bool("gzip", encoded.compressed),
zap.Int("wire_bytes", encoded.wireSize()), zap.Bool("gzip", encoded.compressed),
zap.String("priority", priority.String()), zap.Error(admissionErr))
}
return nil
}
encoded, reserved, retained, err := s.encodeRPCResultReservedWithHandoffContext(
prepareCtx, c, reqMsgID, result, retainForReplay,
methodPriority := rpcMethodPriority(method)
encoded, reserved, retained, err := s.encodeRPCResultReservedWithPriorityAndHandoffContext(
prepareCtx, c, reqMsgID, result, methodPriority, retainForReplay,
)
if retained {
return err
@ -958,11 +968,14 @@ func (s *Server) publishRPCResult(
return err
}
if err != nil {
if provider, ok := result.(interface{ exactRPCBulkCredit() *outboundBulkCredit }); ok {
provider.exactRPCBulkCredit().release()
}
s.log.Warn("Encode RPC result failed; publishing INTERNAL",
zap.String("method", method), zap.Int64("req_msg_id", reqMsgID), zap.Error(err))
afterDelivered = nil
encoded, reserved, retained, err = s.encodeRPCResultReservedWithHandoffContext(
prepareCtx, c, reqMsgID, &mt.RPCError{ErrorCode: 500, ErrorMessage: "INTERNAL"}, retainForReplay,
encoded, reserved, retained, err = s.encodeRPCResultReservedWithPriorityAndHandoffContext(
prepareCtx, c, reqMsgID, &mt.RPCError{ErrorCode: 500, ErrorMessage: "INTERNAL"}, methodPriority, retainForReplay,
)
if retained {
return err
@ -973,6 +986,9 @@ func (s *Server) publishRPCResult(
}
}
if encoded == nil || reserved == nil {
if provider, ok := result.(interface{ exactRPCBulkCredit() *outboundBulkCredit }); ok {
provider.exactRPCBulkCredit().release()
}
c.fenceUndeliveredRPCResult()
return errors.New("rpc result encode completed without tracked retention")
}
@ -981,6 +997,7 @@ func (s *Server) publishRPCResult(
defer reserved.release()
priority, _ := prepareEncoded(encoded)
if owner != nil && !owner.HandOff() {
encoded.releaseBulkCredit()
return ErrRPCResultFlightInvalid
}
@ -989,7 +1006,7 @@ func (s *Server) publishRPCResult(
latency := time.Since(egressStarted)
deliveredReqMsgID := encoded.writtenRequestID()
if metrics, ok := s.metrics.(RPCResultMetrics); ok {
metrics.RPCResultDelivered(method, latency, len(encoded.body), deliveryErr)
metrics.RPCResultDelivered(method, latency, encoded.wireSize(), deliveryErr)
}
if deliveryErr != nil {
encoded.markReplayable()
@ -1000,7 +1017,7 @@ func (s *Server) publishRPCResult(
zap.String("method", method), zap.Int64("req_msg_id", reqMsgID),
zap.Int64("delivered_req_msg_id", deliveredReqMsgID),
zap.String("auth_key_id", c.authKeyHex), zap.Int64("session_id", c.sessionID),
zap.Int("wire_bytes", len(encoded.body)), zap.Bool("gzip", encoded.compressed),
zap.Int("wire_bytes", encoded.wireSize()), zap.Bool("gzip", encoded.compressed),
zap.Error(deliveryErr))
}
return
@ -1012,7 +1029,7 @@ func (s *Server) publishRPCResult(
zap.String("method", method), zap.Int64("req_msg_id", reqMsgID),
zap.Int64("delivered_req_msg_id", deliveredReqMsgID),
zap.String("auth_key_id", c.authKeyHex), zap.Int64("session_id", c.sessionID),
zap.Int("wire_bytes", len(encoded.body)), zap.Bool("gzip", encoded.compressed),
zap.Int("wire_bytes", encoded.wireSize()), zap.Bool("gzip", encoded.compressed),
zap.Duration("egress_latency", latency))
}
}
@ -1026,7 +1043,7 @@ func (s *Server) publishRPCResult(
if checked := s.log.Check(zap.DebugLevel, "RPC result admitted"); checked != nil {
checked.Write(
zap.String("method", method), zap.Int64("req_msg_id", reqMsgID),
zap.Int("wire_bytes", len(encoded.body)), zap.Int("inner_bytes", encoded.uncompressedBytes),
zap.Int("wire_bytes", encoded.wireSize()), zap.Int("inner_bytes", encoded.uncompressedBytes),
zap.Bool("gzip", encoded.compressed), zap.String("priority", priority.String()))
}
return nil
@ -1086,7 +1103,7 @@ func (s *Server) sendReplayedRPCResultWithHook(
c.fenceUndeliveredRPCResult()
return errors.New("nil replayed rpc_result")
}
attempt, reserved, err := c.cloneRPCResultForRequestReserved(encoded, encoded.reqMsgID, false)
attempt, reserved, err := c.cloneRPCResultForRequestReservedContext(ctx, encoded, encoded.reqMsgID, false)
if err != nil {
c.failOutboundBudget(err)
c.fenceUndeliveredRPCResult()
@ -1222,6 +1239,19 @@ func (s *Server) encodeRPCResultReservedWithHandoffContext(
reqMsgID int64,
result bin.Encoder,
handoff rpcResultRetentionHandoff,
) (*encodedOutboundMessage, *outboundBodyReservation, bool, error) {
return s.encodeRPCResultReservedWithPriorityAndHandoffContext(
ctx, c, reqMsgID, result, outboundPriorityNormal, handoff,
)
}
func (s *Server) encodeRPCResultReservedWithPriorityAndHandoffContext(
ctx context.Context,
c *Conn,
reqMsgID int64,
result bin.Encoder,
priority outboundPriority,
handoff rpcResultRetentionHandoff,
) (*encodedOutboundMessage, *outboundBodyReservation, bool, error) {
if ctx == nil {
ctx = context.Background()
@ -1237,7 +1267,10 @@ func (s *Server) encodeRPCResultReservedWithHandoffContext(
if err != nil {
return err
}
budget := c.outboundMessageBudget(encoded.typeID, false)
if priority != outboundPriorityNormal {
encoded.priority = priority
}
budget := c.outboundMessageBudgetForPriority(encoded.typeID, encoded.priority, false)
bytes := len(encoded.body)
if budget.reserve(bytes) {
reserved = &outboundBodyReservation{budget: budget, bytes: bytes}
@ -1286,6 +1319,14 @@ func (s *Server) encodeRPCResultWithoutSlot(ctx context.Context, c *Conn, reqMsg
return nil, fmt.Errorf("bind exact layer rpc result: %w", err)
}
}
var replaySource rpcresult.ReplaySource
if provider, ok := result.(interface{ exactRPCReplaySource() rpcresult.ReplaySource }); ok {
replaySource = provider.exactRPCReplaySource()
}
var bulkCredit *outboundBulkCredit
if provider, ok := result.(interface{ exactRPCBulkCredit() *outboundBulkCredit }); ok {
bulkCredit = provider.exactRPCBulkCredit()
}
// Encode the ordinary exact/no-gzip path directly behind the rpc_result
// prefix. This avoids both the old generated Prepare snapshot and another
// full-body copy merely to prepend the 12-byte envelope.
@ -1303,9 +1344,14 @@ func (s *Server) encodeRPCResultWithoutSlot(ctx context.Context, c *Conn, reqMsg
return nil, fmt.Errorf("%w: body=%d limit=%d", ErrOutboundMessageTooLarge, len(innerBody)+12, maxOutboundBodyBytes)
}
wireInner, compressed, err := encodeAdaptiveRPCResultInner(ctx, nil, innerBody)
if err != nil {
return nil, fmt.Errorf("compress rpc result: %w", err)
wireInner := innerBody
compressed := false
if replaySource == nil {
var err error
wireInner, compressed, err = encodeAdaptiveRPCResultInner(ctx, nil, innerBody)
if err != nil {
return nil, fmt.Errorf("compress rpc result: %w", err)
}
}
if len(wireInner) > maxOutboundBodyBytes-12 {
return nil, fmt.Errorf("%w: body=%d limit=%d", ErrOutboundMessageTooLarge, len(wireInner)+12, maxOutboundBodyBytes)
@ -1322,6 +1368,7 @@ func (s *Server) encodeRPCResultWithoutSlot(ctx context.Context, c *Conn, reqMsg
typeID: proto.ResultTypeID, body: body, reqMsgID: reqMsgID,
compressed: compressed, uncompressedBytes: len(innerBody), delivery: newRPCResultDelivery(0),
layer: layerBinding, layerInvariant: layerInvariantResult,
replaySource: replaySource, innerDigest: sha256.Sum256(innerBody), logicalBytes: len(body), bulkCredit: bulkCredit,
}, nil
}
@ -1620,18 +1667,23 @@ func (cs *connState) trackInbound(msgID int64, seqNo int32, content, service boo
cs.maxContentSeqNo = seqNo
}
}
cs.order = append(cs.order, msgID)
var evicted int64
if len(cs.order) < maxTrackedClientMsgIDs {
cs.order = append(cs.order, msgID)
} else {
evicted = cs.order[cs.orderHead]
cs.order[cs.orderHead] = msgID
cs.orderHead = (cs.orderHead + 1) % len(cs.order)
}
if msgID < cs.minSeen {
cs.minSeen = msgID
}
if msgID > cs.maxSeen {
cs.maxSeen = msgID
}
if len(cs.order) > maxTrackedClientMsgIDs {
oldest := cs.order[0]
cs.order = cs.order[1:]
delete(cs.seen, oldest)
if oldest == cs.minSeen || oldest == cs.maxSeen {
if evicted != 0 {
delete(cs.seen, evicted)
if evicted == cs.minSeen || evicted == cs.maxSeen {
cs.recomputeRange()
}
}