refactor: sync sparse tlprofile runtime

This commit is contained in:
A 2026-07-16 21:36:32 +08:00
parent 5ecf4e912d
commit 25ab04a254
93 changed files with 2983 additions and 1615 deletions

View file

@ -12,7 +12,7 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/crypto"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
"github.com/iamxvbaba/td/transport"
)
@ -279,7 +279,7 @@ func (c *Conn) isPhysicalTransportCurrentOpen() bool {
// LayerProfile returns the exact TL profile currently selected for this
// connection. ok is false until admission or an inherited auth-key default
// supplies a supported generated profile.
func (c *Conn) LayerProfile() (profile tg.LayerProfile, ok bool) {
func (c *Conn) LayerProfile() (profile tlprofile.Profile, ok bool) {
state := c.LayerProfileState()
return state.Profile, state.Origin != LayerProfileUnknown
}
@ -288,7 +288,7 @@ func (c *Conn) LayerProfile() (profile tg.LayerProfile, ok bool) {
// admission. Repeating the same value is idempotent. A later well-formed
// invokeWithLayer may replace either an inherited default or older explicit
// evidence; already-admitted requests retain their own immutable profile.
func (c *Conn) FreezeLayerProfile(profile tg.LayerProfile) error {
func (c *Conn) FreezeLayerProfile(profile tlprofile.Profile) error {
_, err := c.setLayerProfile(profile, LayerProfileExplicit, true)
return err
}
@ -298,14 +298,14 @@ func (c *Conn) FreezeLayerProfile(profile tg.LayerProfile) error {
// msg_id carrying another Layer is a protocol conflict. Advancing the evidence
// cursor at an unchanged Layer does not rotate the outbound epoch because the
// wire profile itself did not change.
func (c *Conn) FreezeLayerProfileAt(profile tg.LayerProfile, msgID int64) (bool, error) {
func (c *Conn) FreezeLayerProfileAt(profile tlprofile.Profile, msgID int64) (bool, error) {
return c.freezeLayerProfileAt(profile, msgID)
}
// SeedLayerProfile restores explicit evidence previously proven for this exact
// logical session. It is kept as the compatible same-session restore API;
// auth-key-wide metadata must use SeedInheritedLayerProfile instead.
func (c *Conn) SeedLayerProfile(profile tg.LayerProfile) error {
func (c *Conn) SeedLayerProfile(profile tlprofile.Profile) error {
_, err := c.setLayerProfile(profile, LayerProfileExplicit, true)
return err
}
@ -313,7 +313,7 @@ func (c *Conn) SeedLayerProfile(profile tg.LayerProfile) error {
// SeedInheritedLayerProfile installs an auth-key-wide default only while the
// connection is still unknown. It never overwrites explicit evidence or an
// already selected inherited default; client protocol evidence owns correction.
func (c *Conn) SeedInheritedLayerProfile(profile tg.LayerProfile) error {
func (c *Conn) SeedInheritedLayerProfile(profile tlprofile.Profile) error {
_, err := c.setLayerProfile(profile, LayerProfileInherited, false)
return err
}

View file

@ -5,7 +5,7 @@ import (
"fmt"
"math"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
"go.uber.org/zap"
)
@ -24,7 +24,7 @@ const (
// profile. Epoch advances on every effective correction, including promotion
// from inherited to explicit evidence at the same numeric layer.
type LayerProfileSnapshot struct {
Profile tg.LayerProfile
Profile tlprofile.Profile
Origin LayerProfileOrigin
Epoch uint32
}
@ -49,7 +49,7 @@ func unpackLayerProfileState(raw uint64) LayerProfileSnapshot {
return LayerProfileSnapshot{}
}
return LayerProfileSnapshot{
Profile: tg.LayerProfile(raw & layerProfileValueMask),
Profile: tlprofile.Profile(raw & layerProfileValueMask),
Origin: LayerProfileOrigin((raw >> layerProfileOriginShift) & layerProfileOriginMask),
Epoch: uint32(raw >> layerProfileEpochShift),
}
@ -63,7 +63,7 @@ func (c *Conn) LayerProfileState() LayerProfileSnapshot {
return unpackLayerProfileState(c.layerProfileState.Load())
}
func (c *Conn) setLayerProfile(profile tg.LayerProfile, origin LayerProfileOrigin, replace bool) (bool, error) {
func (c *Conn) setLayerProfile(profile tlprofile.Profile, origin LayerProfileOrigin, replace bool) (bool, error) {
if err := validateLayerProfile(profile); err != nil {
return false, err
}
@ -104,8 +104,8 @@ func (c *Conn) setLayerProfile(profile tg.LayerProfile, origin LayerProfileOrigi
}
}
func validateLayerProfile(profile tg.LayerProfile) error {
resolved, ok := tg.ResolveLayerProfile(int(profile))
func validateLayerProfile(profile tlprofile.Profile) error {
resolved, ok := tlprofile.ResolveProfile(int(profile))
if !ok || resolved != profile || uint64(profile) > layerProfileValueMask {
return fmt.Errorf("%w: %d", ErrLayerProfileUnsupported, profile)
}
@ -138,7 +138,7 @@ func (c *Conn) layerProfileRawEvidenceState() (LayerProfileSnapshot, int, int64)
// freezeLayerProfileAt is the production explicit-evidence transition. The
// positive client msg_id is the protocol ordering authority across TCP
// reconnects and cached request replays.
func (c *Conn) freezeLayerProfileAt(profile tg.LayerProfile, msgID int64) (bool, error) {
func (c *Conn) freezeLayerProfileAt(profile tlprofile.Profile, msgID int64) (bool, error) {
if c == nil {
return false, fmt.Errorf("nil connection layer profile")
}
@ -158,7 +158,7 @@ func (c *Conn) freezeRawLayerProfileAt(layer int, msgID int64) (bool, error) {
if layer <= 0 || msgID <= 0 {
return false, fmt.Errorf("invalid raw layer evidence layer=%d msg_id=%d", layer, msgID)
}
profile, supported := tg.ResolveLayerProfile(layer)
profile, supported := tlprofile.ResolveProfile(layer)
c.layerProfileMu.Lock()
defer c.layerProfileMu.Unlock()
@ -206,7 +206,7 @@ func (c *Conn) freezeRawLayerProfileAt(layer int, msgID int64) (bool, error) {
// seedOrderedLayerProfile restores exact-session evidence atomically before
// any request on a replacement physical connection is admitted.
func (c *Conn) seedOrderedLayerProfile(profile tg.LayerProfile, msgID int64) error {
func (c *Conn) seedOrderedLayerProfile(profile tlprofile.Profile, msgID int64) error {
if c == nil {
return nil
}
@ -248,7 +248,7 @@ func (c *Conn) seedRawLayerEvidence(layer int, msgID int64) error {
// auth.bindTempAuthKey: once a raw temporary key is resolved to its permanent
// key, the permanent key's default supersedes an older raw-key shadow. Explicit
// evidence on the concrete session is never overwritten.
func (c *Conn) refreshInheritedLayerProfile(profile tg.LayerProfile) (bool, error) {
func (c *Conn) refreshInheritedLayerProfile(profile tlprofile.Profile) (bool, error) {
if c == nil {
return false, nil
}
@ -339,7 +339,7 @@ func (s *Server) seedInitialLayerProfile(
// Older in-process exact-session registries did not retain a message
// watermark. Keep that compatibility-only seed usable without treating
// it as durable ordered evidence; real durable stores never persist zero.
profile, supported := tg.ResolveLayerProfile(layer)
profile, supported := tlprofile.ResolveProfile(layer)
if !supported {
return nil
}
@ -353,7 +353,7 @@ func (s *Server) seedInitialLayerProfile(
if msgID > 0 {
return c.seedRawLayerEvidence(layer, msgID)
}
profile, supported := tg.ResolveLayerProfile(layer)
profile, supported := tlprofile.ResolveProfile(layer)
if !supported {
return nil
}
@ -361,7 +361,7 @@ func (s *Server) seedInitialLayerProfile(
}
} else if resolver, ok := s.layerRPC.(LayerRPCSessionProfileResolver); ok {
if layer, found := resolver.NegotiatedSessionLayer(c.authKeyID, c.sessionID); found {
profile, supported := tg.ResolveLayerProfile(layer)
profile, supported := tlprofile.ResolveProfile(layer)
if !supported {
return nil
}
@ -373,7 +373,7 @@ func (s *Server) seedInitialLayerProfile(
// row again. Unsupported metadata remains unknown and must not fall through
// to a weaker mirror.
if c.authKeyExpiresAt == 0 && fetchedLayer != 0 {
profile, supported := tg.ResolveLayerProfile(fetchedLayer)
profile, supported := tlprofile.ResolveProfile(fetchedLayer)
if !supported {
return nil
}
@ -406,7 +406,7 @@ func (s *Server) seedInitialLayerProfile(
// Fall through to a raw auth-key shadow when the resolver has no
// canonical permanent-key default (for example an unbound temp key).
} else {
profile, supported := tg.ResolveLayerProfile(layer)
profile, supported := tlprofile.ResolveProfile(layer)
if !supported {
return nil
}
@ -414,7 +414,7 @@ func (s *Server) seedInitialLayerProfile(
}
}
if fetchedLayer != 0 {
profile, supported := tg.ResolveLayerProfile(fetchedLayer)
profile, supported := tlprofile.ResolveProfile(fetchedLayer)
if !supported {
return nil
}
@ -446,7 +446,7 @@ func (s *Server) refreshActivatedInheritedLayerProfile(ctx context.Context, c *C
if fetchedLayer == 0 {
return nil
}
profile, ok := tg.ResolveLayerProfile(fetchedLayer)
profile, ok := tlprofile.ResolveProfile(fetchedLayer)
if !ok {
return c.clearInheritedLayerProfile()
}
@ -472,7 +472,7 @@ func (s *Server) refreshActivatedInheritedLayerProfile(ctx context.Context, c *C
zap.String("auth_key_id", c.authKeyHex), zap.Error(err))
}
} else if found {
profile, supported := tg.ResolveLayerProfile(layer)
profile, supported := tlprofile.ResolveProfile(layer)
if !supported {
return c.clearInheritedLayerProfile()
}
@ -483,7 +483,7 @@ func (s *Server) refreshActivatedInheritedLayerProfile(ctx context.Context, c *C
if fetchedLayer == 0 {
return nil
}
profile, ok := tg.ResolveLayerProfile(fetchedLayer)
profile, ok := tlprofile.ResolveProfile(fetchedLayer)
if !ok {
return c.clearInheritedLayerProfile()
}

View file

@ -9,6 +9,7 @@ import (
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
// TestPushSkipsConnReboundToOtherUser 锁定跨账号投递窗口的修复:pushToUserWithSender 在锁外
@ -28,7 +29,7 @@ func TestPushSkipsConnReboundToOtherUser(t *testing.T) {
c.userID.Store(userA)
c.userIDResolved.Store(true)
c.receivesUpdates.Store(true)
if err := c.FreezeLayerProfile(tg.LayerProfileCanonical); err != nil {
if err := c.FreezeLayerProfile(tlprofile.ProfileCanonical); err != nil {
t.Fatal(err)
}
sm.Register(c)

View file

@ -6,7 +6,7 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
const (
@ -20,8 +20,8 @@ var errDestroyAuthKeyMustBeExclusive = errors.New("wrapped destroy_auth_key must
// wrappedDestroyAuthKeyTerminal accepts only evidence emitted by the generated
// exact wrapper parser after it has legally reached the innermost non-API
// terminal. It never re-parses wrapper bytes at runtime.
func wrappedDestroyAuthKeyTerminal(err error) (*tg.LayerRPCUnknownTerminalError, bool) {
var terminal *tg.LayerRPCUnknownTerminalError
func wrappedDestroyAuthKeyTerminal(err error) (*tlprofile.UnknownTerminalError, bool) {
var terminal *tlprofile.UnknownTerminalError
if !errors.As(err, &terminal) || terminal == nil || terminal.WireID != destroyAuthKeyRequestTypeID {
return nil, false
}
@ -35,7 +35,7 @@ func wrappedDestroyAuthKeyTerminal(err error) (*tg.LayerRPCUnknownTerminalError,
// invokeWithLayer(initConnection(destroy_auth_key)); an already initialized
// connection sends the bare service message and is classified before Layer RPC
// admission.
func validWrappedDestroyAuthKeyChain(terminal *tg.LayerRPCUnknownTerminalError) bool {
func validWrappedDestroyAuthKeyChain(terminal *tlprofile.UnknownTerminalError) bool {
if terminal == nil || terminal.WrapperCount() != 2 {
return false
}
@ -44,8 +44,8 @@ func validWrappedDestroyAuthKeyChain(terminal *tg.LayerRPCUnknownTerminalError)
return outerOK && innerOK &&
outer.Profile() == terminal.Profile &&
inner.Profile() == terminal.Profile &&
outer.Semantic() == tg.LayerSemanticMethodInvokeWithLayer &&
inner.Semantic() == tg.LayerSemanticMethodInitConnection
outer.Semantic() == tlprofile.SemanticMethodInvokeWithLayer &&
inner.Semantic() == tlprofile.SemanticMethodInitConnection
}
type destroyAuthKeyRequest struct{}

View file

@ -20,10 +20,10 @@ import (
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/proto/codec"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tgerr"
"github.com/iamxvbaba/td/transport"
"github.com/iamxvbaba/td/tlprofile"
"telesrv/internal/observability/dbtrace"
"telesrv/internal/postresponse"
"telesrv/internal/store"
@ -701,8 +701,8 @@ func (s *Server) handleRPC(ctx context.Context, c *Conn, msgID int64, method str
// obey the production exact-codec invariant. Admit a defensive copy using
// the generated current profile before the legacy router consumes b.
admissionBody := &bin.Buffer{Buf: append([]byte(nil), b.Buf...)}
admitted, err := tg.NewServerDispatcher(nil).AdmitDefaultLayerWithLimits(
tg.LayerProfileCanonical,
admitted, err := tlprofile.NewDispatcher().AdmitDefault(
tlprofile.ProfileCanonical,
admissionBody,
inboundLayerDecodeLimits,
)

View file

@ -16,6 +16,7 @@ import (
"github.com/iamxvbaba/td/exchange"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
"github.com/iamxvbaba/td/transport"
)
@ -23,7 +24,7 @@ import (
// by old connection-state tests. Production exact-path tests must instead call
// FreezeLayerProfile/SeedLayerProfile with protocol evidence.
func legacyCanonicalTestConn(t testing.TB, c *Conn) *Conn {
return legacyLayerWireTestConn(t, c, int(tg.LayerProfileCanonical))
return legacyLayerWireTestConn(t, c, int(tlprofile.ProfileCanonical))
}
// legacyLayerWireTestConn preserves only the old tests' profile setup. It does
@ -34,7 +35,7 @@ func legacyLayerWireTestConn(t testing.TB, c *Conn, layer int) *Conn {
if c == nil {
t.Fatal("nil legacy exact-layer test Conn")
}
profile, ok := tg.ResolveLayerProfile(layer)
profile, ok := tlprofile.ResolveProfile(layer)
if !ok {
t.Fatalf("unsupported generated test Layer %d", layer)
}
@ -62,7 +63,6 @@ func exactTestUpdatesEncoded(t testing.TB, c *Conn, body []byte) *encodedOutboun
typeID: tg.UpdatesTooLongTypeID,
layer: &outboundLayerBinding{
profile: state.Profile,
typ: tg.LayerClassUpdatesType().Ref(),
epoch: state.Epoch,
},
}
@ -86,8 +86,7 @@ func (r *opaqueExactTestRPCResult) Encode(b *bin.Buffer) error { return r.result
func (r *opaqueExactTestRPCResult) exactLayerRPCResultBinding() outboundLayerBinding {
return outboundLayerBinding{
profile: tg.LayerProfileCanonical,
typ: tg.LayerClassUpdatesType().Ref(),
profile: tlprofile.ProfileCanonical,
kind: outboundLayerBindingRequest,
}
}
@ -180,7 +179,7 @@ func dialTransportOnly(t *testing.T, addr string) transport.Conn {
// profile that a production invokeWithLayer admission would have proven. It is
// intentionally explicit: handshake/new_session_created alone never implies a
// TL Layer, and production push code must keep failing closed in that state.
func freezeActiveTestSessionProfile(t *testing.T, sessions *SessionManager, authKeyID [8]byte, sessionID int64, profile tg.LayerProfile) {
func freezeActiveTestSessionProfile(t *testing.T, sessions *SessionManager, authKeyID [8]byte, sessionID int64, profile tlprofile.Profile) {
t.Helper()
if sessions == nil {
t.Fatal("freeze test session profile on nil SessionManager")

View file

@ -9,10 +9,11 @@ import (
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tgerr"
"github.com/iamxvbaba/td/tlprofile"
"go.uber.org/zap"
)
var inboundLayerDecodeLimits = tg.LayerDecodeLimits{
var inboundLayerDecodeLimits = tlprofile.Limits{
MaxWireBytes: maxInflightRPCBytes,
// contacts.editCloseFriends and contacts.setBlocked deliberately allow
// 5,000 entries. Keep the coarse generated allocation ceiling above every
@ -48,7 +49,7 @@ type layerRPCDependencySet struct {
}
type layerRPCProfileEvidence struct {
profile tg.LayerProfile
profile tlprofile.Profile
admissionSeq uint64
present bool
fresh bool
@ -67,7 +68,7 @@ type layerRPCAdmissionCursor struct {
evidenceMsgID int64
}
func (c *layerRPCAdmissionCursor) observe(profile tg.LayerProfile, msgID int64) error {
func (c *layerRPCAdmissionCursor) observe(profile tlprofile.Profile, msgID int64) error {
return c.observeRaw(int(profile), msgID)
}
@ -90,7 +91,7 @@ func (c *layerRPCAdmissionCursor) observeRaw(layer int, msgID int64) error {
}
}
c.state = LayerProfileSnapshot{}
if profile, supported := tg.ResolveLayerProfile(layer); supported {
if profile, supported := tlprofile.ResolveProfile(layer); supported {
c.state = LayerProfileSnapshot{Profile: profile, Origin: LayerProfileExplicit}
}
c.rawLayer = layer
@ -136,7 +137,7 @@ func (s *Server) initialLayerRPCAdmissionCursor(ctx context.Context, c *Conn) (l
if registryMsgID == 0 {
if cursor.evidenceMsgID == 0 {
cursor.state = LayerProfileSnapshot{}
if profile, supported := tg.ResolveLayerProfile(layer); supported {
if profile, supported := tlprofile.ResolveProfile(layer); supported {
cursor.state = LayerProfileSnapshot{Profile: profile, Origin: LayerProfileExplicit}
}
cursor.rawLayer = layer
@ -466,7 +467,7 @@ func (s *Server) prepareInboundLayerRPCBatch(ctx context.Context, c *Conn, plan
}
plan.rejectNewRPCOwners(indices)
for _, index := range candidateItems {
plan.items[index].admitted = tg.LayerRequest{}
plan.items[index].admitted = tlprofile.Admission{}
}
if err := reservation.retain(nil, nil); err != nil {
return err
@ -534,7 +535,7 @@ func (s *Server) prepareInboundLayerRPCBatch(ctx context.Context, c *Conn, plan
}
plan.rewrapAliases = keptAliases
for _, index := range candidateItems {
plan.items[index].admitted = tg.LayerRequest{}
plan.items[index].admitted = tlprofile.Admission{}
}
if err := reservation.retain(nil, nil); err != nil {
return err
@ -581,7 +582,7 @@ func (s *Server) prepareInboundLayerRPCBatch(ctx context.Context, c *Conn, plan
}
if len(specs) == 0 {
for _, index := range candidateItems {
plan.items[index].admitted = tg.LayerRequest{}
plan.items[index].admitted = tlprofile.Admission{}
}
if err := reservation.retain(nil, nil); err != nil {
return err
@ -604,7 +605,7 @@ func (s *Server) prepareInboundLayerRPCBatch(ctx context.Context, c *Conn, plan
// Tasks now own the admitted request leases. Drop the plan's value copies
// before non-fresh reservations become reusable.
for _, index := range candidateItems {
plan.items[index].admitted = tg.LayerRequest{}
plan.items[index].admitted = tlprofile.Admission{}
}
if err := reservation.retain(reservationIndices, specs); err != nil {
return err
@ -628,7 +629,7 @@ func (s *Server) acquireAdmittedLayerRPC(
return rpcResultAcquire{}, ErrRPCResultFlightInvalid
}
acquire := func() (rpcResultAcquire, error) {
profile := tg.LayerProfile(0)
profile := tlprofile.Profile(0)
if effective, known := item.admitted.EffectiveProfile(); known {
profile = effective
}
@ -671,7 +672,7 @@ func (s *Server) acquireAdmittedLayerRPC(
return acquire()
}
func (s *Server) prepareAdmittedLayerRPCReplay(ctx context.Context, c *Conn, msgID int64, admissionSeq uint64, profileEvidenceFresh bool, request tg.LayerRequest) (func() error, error) {
func (s *Server) prepareAdmittedLayerRPCReplay(ctx context.Context, c *Conn, msgID int64, admissionSeq uint64, profileEvidenceFresh bool, request tlprofile.Admission) (func() error, error) {
preparer, ok := s.layerRPC.(LayerRPCReplayPreparer)
if !ok || c == nil {
return nil, nil
@ -703,26 +704,26 @@ func (s *Server) withLayerRPCProfileEvidenceFresh(ctx context.Context, fresh boo
// admitInboundLayerRPC is the force-style compatibility entry point used by
// focused tests and old embedders. Production must call admitInboundLayerRPCAt
// with the real inner MTProto client msg_id.
func (s *Server) admitInboundLayerRPC(c *Conn, body []byte) (tg.LayerRequest, string, error) {
func (s *Server) admitInboundLayerRPC(c *Conn, body []byte) (tlprofile.Admission, string, error) {
return s.admitInboundLayerRPCAt(c, 0, body)
}
func (s *Server) admitInboundLayerRPCAt(c *Conn, msgID int64, body []byte) (tg.LayerRequest, string, error) {
func (s *Server) admitInboundLayerRPCAt(c *Conn, msgID int64, body []byte) (tlprofile.Admission, string, error) {
if s == nil || s.layerRPC == nil || c == nil || len(body) < bin.Word {
return tg.LayerRequest{}, "unknown", fmt.Errorf("invalid exact RPC admission input")
return tlprofile.Admission{}, "unknown", fmt.Errorf("invalid exact RPC admission input")
}
request, method, err := s.decodeInboundLayerRPC(c.LayerProfileState(), body)
if err != nil {
return tg.LayerRequest{}, method, err
return tlprofile.Admission{}, method, err
}
if profile, hasEvidence := request.ProfileEvidence(); hasEvidence {
if _, err := s.commitLayerProfileEvidence(context.Background(), c, profile, msgID); err != nil {
if !isLayerEvidenceDurabilityUnavailable(err) {
return tg.LayerRequest{}, method, err
return tlprofile.Admission{}, method, err
}
if msgID > 0 {
if _, localErr := c.freezeLayerProfileAt(profile, msgID); localErr != nil {
return tg.LayerRequest{}, method, localErr
return tlprofile.Admission{}, method, localErr
}
}
}
@ -737,8 +738,8 @@ func (s *Server) admitInboundLayerRPCAt(c *Conn, msgID int64, body []byte) (tg.L
// constructed, so the bounded fallback walks only transparent wrapper prefixes
// whose query offset is fixed and allocation-free.
func layerRPCAdmissionHasExplicitSelector(body []byte, admissionErr error) bool {
var codecErr *tg.LayerCodecError
if errors.As(admissionErr, &codecErr) && codecErr.Semantic == tg.LayerSemanticMethodInvokeWithLayer {
var codecErr *tlprofile.LayerCodecError
if errors.As(admissionErr, &codecErr) && codecErr.Semantic == tlprofile.SemanticMethodInvokeWithLayer {
return true
}
@ -784,13 +785,13 @@ func layerRPCAdmissionHasExplicitSelector(body []byte, admissionErr error) bool
// it with a wire-ordered provisional profile cursor, then publishes explicit
// evidence only after the full request identity has acquired an owner (or a
// genuine new-msg_id rewrap alias).
func (s *Server) decodeInboundLayerRPC(state LayerProfileSnapshot, body []byte) (tg.LayerRequest, string, error) {
func (s *Server) decodeInboundLayerRPC(state LayerProfileSnapshot, body []byte) (tlprofile.Admission, string, error) {
if s == nil || s.layerRPC == nil || len(body) < bin.Word {
return tg.LayerRequest{}, "unknown", fmt.Errorf("invalid exact RPC admission input")
return tlprofile.Admission{}, "unknown", fmt.Errorf("invalid exact RPC admission input")
}
b := &bin.Buffer{Buf: body}
var (
request tg.LayerRequest
request tlprofile.Admission
err error
)
if state.Origin != LayerProfileUnknown {
@ -806,19 +807,19 @@ func (s *Server) decodeInboundLayerRPC(state LayerProfileSnapshot, body []byte)
}
method := "unknown"
if err == nil {
_, method, _ = tg.LayerSemanticName(request.Call().Method())
_, method, _ = tlprofile.SemanticName(request.Call().Method())
if b.Len() != 0 {
return tg.LayerRequest{}, method, fmt.Errorf("exact RPC admission left %d bytes", b.Len())
return tlprofile.Admission{}, method, fmt.Errorf("exact RPC admission left %d bytes", b.Len())
}
if effective, known := request.EffectiveProfile(); known && effective != request.Call().Profile() {
return tg.LayerRequest{}, method, fmt.Errorf("%w: effective profile %d differs from call profile %d", ErrLayerProfileConflict, effective, request.Call().Profile())
return tlprofile.Admission{}, method, fmt.Errorf("%w: effective profile %d differs from call profile %d", ErrLayerProfileConflict, effective, request.Call().Profile())
}
// A generated invariant terminal may use canonical decoding internally
// before the client declares a layer. Only explicit invokeWithLayer (or the
// strict compatibility fallback above) publishes new profile evidence.
if profile, hasEvidence := request.ProfileEvidence(); hasEvidence {
if profile != request.Call().Profile() {
return tg.LayerRequest{}, method, fmt.Errorf("%w: generated profile evidence %d differs from call profile %d", ErrLayerProfileConflict, profile, request.Call().Profile())
return tlprofile.Admission{}, method, fmt.Errorf("%w: generated profile evidence %d differs from call profile %d", ErrLayerProfileConflict, profile, request.Call().Profile())
}
}
return request, method, nil
@ -834,9 +835,9 @@ func (s *Server) decodeInboundLayerRPC(state LayerProfileSnapshot, body []byte)
if id, peekErr := (&bin.Buffer{Buf: body}).PeekID(); peekErr == nil {
method = s.typeName(id)
}
if codecErr := new(tg.LayerCodecError); errors.As(err, &codecErr) {
if codecErr := new(tlprofile.LayerCodecError); errors.As(err, &codecErr) {
if codecErr.Semantic != 0 {
if _, semanticMethod, ok := tg.LayerSemanticName(codecErr.Semantic); ok && semanticMethod != "" {
if _, semanticMethod, ok := tlprofile.SemanticName(codecErr.Semantic); ok && semanticMethod != "" {
method = semanticMethod
}
} else if codecErr.WireID != 0 {
@ -846,7 +847,7 @@ func (s *Server) decodeInboundLayerRPC(state LayerProfileSnapshot, body []byte)
method = s.typeName(codecErr.WireID)
}
}
if errors.Is(err, tg.ErrLayerUnknownRPCMethod) && s.log != nil {
if errors.Is(err, tlprofile.ErrUnknownRPCMethod) && s.log != nil {
if terminal, recognized := wrappedDestroyAuthKeyTerminal(err); recognized {
method = "destroy_auth_key"
s.log.Debug("Generated wrapper admission exposed MTProto service terminal",
@ -860,7 +861,7 @@ func (s *Server) decodeInboundLayerRPC(state LayerProfileSnapshot, body []byte)
zap.String("method", method), zap.Error(err))
}
}
return tg.LayerRequest{}, method, err
return tlprofile.Admission{}, method, err
}
// commitLayerProfileEvidence publishes one generated invokeWithLayer proof.
@ -868,7 +869,7 @@ func (s *Server) decodeInboundLayerRPC(state LayerProfileSnapshot, body []byte)
// point; the Conn cursor then prevents a concurrent older admission from
// overwriting its local wire epoch. Older cached duplicates remain decodable
// and request-bound, but cannot mutate session/profile state.
func (s *Server) commitLayerProfileEvidence(ctx context.Context, c *Conn, profile tg.LayerProfile, msgID int64) (bool, error) {
func (s *Server) commitLayerProfileEvidence(ctx context.Context, c *Conn, profile tlprofile.Profile, msgID int64) (bool, error) {
if s == nil || c == nil {
return false, fmt.Errorf("invalid layer profile evidence target")
}
@ -890,7 +891,7 @@ func (s *Server) commitLayerProfileEvidence(ctx context.Context, c *Conn, profil
} else if _, err := c.freezeRawLayerProfileAt(layer, authoritativeMsgID); err != nil {
return false, err
}
authoritative, supported := tg.ResolveLayerProfile(layer)
authoritative, supported := tlprofile.ResolveProfile(layer)
return supported && authoritative == profile && authoritativeMsgID == msgID && publishShared, nil
}
if registry, ok := s.layerRPC.(LayerRPCOrderedSessionProfileRegistry); ok {
@ -909,7 +910,7 @@ func (s *Server) commitLayerProfileEvidence(ctx context.Context, c *Conn, profil
if !found || authoritativeMsgID <= 0 {
return false, fmt.Errorf("%w: ordered exact session evidence disappeared after commit", ErrLayerProfileConflict)
}
authoritative, supported := tg.ResolveLayerProfile(layer)
authoritative, supported := tlprofile.ResolveProfile(layer)
if s.conns != nil {
if _, err := s.conns.ApplyOrderedRawLayerForSession(c, c.authKeyID, c.sessionID, layer, authoritativeMsgID); err != nil {
return false, err
@ -980,34 +981,34 @@ func layerRPCAdmissionError(err error) *mt.RPCError {
if errors.Is(err, errDefaultLayerAdmission) {
return &mt.RPCError{ErrorCode: 400, ErrorMessage: "CONNECTION_LAYER_INVALID"}
}
if errors.Is(err, tg.ErrLayerProfileRequired) {
if errors.Is(err, tlprofile.ErrProfileRequired) {
return &mt.RPCError{ErrorCode: 400, ErrorMessage: "CONNECTION_NOT_INITED"}
}
var rpcErr *tgerr.Error
if errors.As(err, &rpcErr) {
return &mt.RPCError{ErrorCode: rpcErr.Code, ErrorMessage: rpcErr.Message}
}
if errors.Is(err, tg.ErrLayerUnknownRPCMethod) {
if errors.Is(err, tlprofile.ErrUnknownRPCMethod) {
return &mt.RPCError{ErrorCode: 501, ErrorMessage: "NOT_IMPLEMENTED"}
}
return &mt.RPCError{ErrorCode: 400, ErrorMessage: "INPUT_REQUEST_INVALID"}
}
func (s *Server) layerRPCDependencies(c *Conn, msgID int64, request tg.LayerRequest) layerRPCDependencySet {
func (s *Server) layerRPCDependencies(c *Conn, msgID int64, request tlprofile.Admission) layerRPCDependencySet {
result := layerRPCDependencySet{}
seen := make(map[int64]struct{})
for index := 0; index < request.WrapperCount(); index++ {
wrapper, _ := request.Wrapper(index)
var ids []int64
switch wrapper.Semantic() {
case tg.LayerSemanticMethodInvokeAfterMsg:
case tlprofile.SemanticMethodInvokeAfterMsg:
id, err := layerRPCWrapperRequired[int64](wrapper, "msg_id")
if err != nil {
result.failed = true
continue
}
ids = []int64{id}
case tg.LayerSemanticMethodInvokeAfterMsgs:
case tlprofile.SemanticMethodInvokeAfterMsgs:
var err error
ids, err = layerRPCWrapperRequired[[]int64](wrapper, "msg_ids")
if err != nil || len(ids) > maxLayerRPCDependencyIDs {
@ -1045,16 +1046,16 @@ func (s *Server) layerRPCDependencies(c *Conn, msgID int64, request tg.LayerRequ
return result
}
func admittedRPCRewrapInit(request tg.LayerRequest) (rpcRewrapInit, bool) {
func admittedRPCRewrapInit(request tlprofile.Admission) (rpcRewrapInit, bool) {
if request.WrapperCount() != 2 {
return rpcRewrapInit{}, false
}
layerWrapper, ok := request.Wrapper(0)
if !ok || layerWrapper.Semantic() != tg.LayerSemanticMethodInvokeWithLayer {
if !ok || layerWrapper.Semantic() != tlprofile.SemanticMethodInvokeWithLayer {
return rpcRewrapInit{}, false
}
initWrapper, ok := request.Wrapper(1)
if !ok || initWrapper.Semantic() != tg.LayerSemanticMethodInitConnection {
if !ok || initWrapper.Semantic() != tlprofile.SemanticMethodInitConnection {
return rpcRewrapInit{}, false
}
layer, err := layerRPCWrapperRequired[int](layerWrapper, "layer")
@ -1095,7 +1096,7 @@ func admittedRPCRewrapInit(request tg.LayerRequest) (rpcRewrapInit, bool) {
}, true
}
func layerRPCWrapperRequired[T any](wrapper tg.LayerRPCWrapper, name string) (T, error) {
func layerRPCWrapperRequired[T any](wrapper tlprofile.Wrapper, name string) (T, error) {
var zero T
value, present, ok, err := wrapper.Value(name)
if err != nil || !ok || !present {

View file

@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"strings"
"sync"
"sync/atomic"
"testing"
@ -15,6 +16,7 @@ import (
"github.com/iamxvbaba/td/tg"
"go.uber.org/zap/zaptest"
"github.com/iamxvbaba/td/tlprofile"
"telesrv/internal/rpc"
"telesrv/internal/store"
"telesrv/internal/store/memory"
@ -29,17 +31,17 @@ func exactLayerRPCBody(t *testing.T, request bin.Encoder) []byte {
return body.Copy()
}
func exactOutboundLayerRPCBody(t *testing.T, profile tg.LayerProfile, request bin.Object) []byte {
func exactOutboundLayerRPCBody(t *testing.T, profile tlprofile.Profile, request bin.Object) []byte {
t.Helper()
outbound, err := tg.PrepareLayerOutboundCall(profile, request)
if err != nil {
var body bin.Buffer
if err := tlprofile.EncodeObject(profile, request, &body); err != nil {
t.Fatal(err)
}
return exactLayerRPCBody(t, outbound)
return body.Copy()
}
type admissionOnlyLayerRPC struct {
dispatcher *tg.ServerDispatcher
dispatcher *tlprofile.Dispatcher
mu sync.Mutex
published []publishedLayerEvidence
}
@ -128,8 +130,8 @@ func (s unavailableEdgeSessionLayerStore) DeleteExpiredSessionLayers(context.Con
type dispatchProfileCaptureRouter struct {
*rpc.Router
mu sync.Mutex
requestProfile tg.LayerProfile
resultProfile tg.LayerProfile
requestProfile tlprofile.Profile
resultProfile tlprofile.Profile
}
func (h *dispatchProfileCaptureRouter) DispatchAdmitted(
@ -138,8 +140,8 @@ func (h *dispatchProfileCaptureRouter) DispatchAdmitted(
sessionID int64,
msgID int64,
admissionSeq uint64,
request tg.LayerRequest,
) (tg.LayerRPCResult, string, error) {
request tlprofile.Admission,
) (tlprofile.Result, string, error) {
result, method, err := h.Router.DispatchAdmitted(ctx, authKeyID, sessionID, msgID, admissionSeq, request)
h.mu.Lock()
h.requestProfile = request.Call().Profile()
@ -150,7 +152,7 @@ func (h *dispatchProfileCaptureRouter) DispatchAdmitted(
return result, method, err
}
func (h *dispatchProfileCaptureRouter) profiles() (tg.LayerProfile, tg.LayerProfile) {
func (h *dispatchProfileCaptureRouter) profiles() (tlprofile.Profile, tlprofile.Profile) {
h.mu.Lock()
defer h.mu.Unlock()
return h.requestProfile, h.resultProfile
@ -189,7 +191,7 @@ func (h *capacityAdmissionOnlyLayerRPC) FreezeNegotiatedSessionLayerAt([8]byte,
type replayProfileCaptureLayerRPC struct {
*admissionOnlyLayerRPC
mu sync.Mutex
profiles []tg.LayerProfile
profiles []tlprofile.Profile
known []bool
}
@ -199,7 +201,7 @@ func (h *replayProfileCaptureLayerRPC) PrepareAdmittedReplay(
_ int64,
_ int64,
_ uint64,
request tg.LayerRequest,
request tlprofile.Admission,
) (func() error, error) {
profile, known := request.EffectiveProfile()
h.mu.Lock()
@ -209,14 +211,14 @@ func (h *replayProfileCaptureLayerRPC) PrepareAdmittedReplay(
return nil, nil
}
func (h *replayProfileCaptureLayerRPC) capturedProfiles() ([]tg.LayerProfile, []bool) {
func (h *replayProfileCaptureLayerRPC) capturedProfiles() ([]tlprofile.Profile, []bool) {
h.mu.Lock()
defer h.mu.Unlock()
return append([]tg.LayerProfile(nil), h.profiles...), append([]bool(nil), h.known...)
return append([]tlprofile.Profile(nil), h.profiles...), append([]bool(nil), h.known...)
}
func newAdmissionOnlyLayerRPC() *admissionOnlyLayerRPC {
return &admissionOnlyLayerRPC{dispatcher: tg.NewServerDispatcher(nil)}
return &admissionOnlyLayerRPC{dispatcher: tlprofile.NewDispatcher()}
}
func newOrderedAdmissionOnlyLayerRPC() *orderedAdmissionOnlyLayerRPC {
@ -259,19 +261,19 @@ func (h *orderedAdmissionOnlyLayerRPC) FreezeNegotiatedSessionLayerAt(authKeyID
return true, nil
}
func (h *admissionOnlyLayerRPC) AdmitLayer(profile tg.LayerProfile, b *bin.Buffer, limits tg.LayerDecodeLimits) (tg.LayerRequest, error) {
return h.dispatcher.AdmitLayerWithLimits(profile, b, limits)
func (h *admissionOnlyLayerRPC) AdmitLayer(profile tlprofile.Profile, b *bin.Buffer, limits tlprofile.Limits) (tlprofile.Admission, error) {
return h.dispatcher.Admit(profile, b, limits)
}
func (h *admissionOnlyLayerRPC) AdmitDefaultLayer(profile tg.LayerProfile, b *bin.Buffer, limits tg.LayerDecodeLimits) (tg.LayerRequest, error) {
return h.dispatcher.AdmitDefaultLayerWithLimits(profile, b, limits)
func (h *admissionOnlyLayerRPC) AdmitDefaultLayer(profile tlprofile.Profile, b *bin.Buffer, limits tlprofile.Limits) (tlprofile.Admission, error) {
return h.dispatcher.AdmitDefault(profile, b, limits)
}
func (h *admissionOnlyLayerRPC) AdmitUnprofiled(b *bin.Buffer, limits tg.LayerDecodeLimits) (tg.LayerRequest, error) {
return h.dispatcher.AdmitUnprofiledWithLimits(b, limits)
func (h *admissionOnlyLayerRPC) AdmitUnprofiled(b *bin.Buffer, limits tlprofile.Limits) (tlprofile.Admission, error) {
return h.dispatcher.AdmitUnprofiled(b, limits)
}
func (*admissionOnlyLayerRPC) DispatchAdmitted(context.Context, [8]byte, int64, int64, uint64, tg.LayerRequest) (tg.LayerRPCResult, string, error) {
func (*admissionOnlyLayerRPC) DispatchAdmitted(context.Context, [8]byte, int64, int64, uint64, tlprofile.Admission) (tlprofile.Result, string, error) {
return nil, "", fmt.Errorf("admission-only handler")
}
@ -302,7 +304,7 @@ func (h *admissionOnlyLayerRPC) publications() []publishedLayerEvidence {
func TestNestedExplicitLayerAdmissionErrorsAreNotDefaultFailures(t *testing.T) {
handler := newAdmissionOnlyLayerRPC()
s := New(Options{DC: 2, LayerRPC: handler})
state := LayerProfileSnapshot{Profile: tg.LayerProfile227, Origin: LayerProfileInherited}
state := LayerProfileSnapshot{Profile: tlprofile.Profile227, Origin: LayerProfileInherited}
unsupported := exactLayerRPCBody(t, &tg.InvokeAfterMsgRequest{
MsgID: 1,
@ -334,12 +336,11 @@ func TestNestedExplicitLayerAdmissionErrorsAreNotDefaultFailures(t *testing.T) {
malformedSelectedQuery.PutID(tg.MessagesGetHistoryRequestTypeID)
for _, test := range []struct {
name string
body []byte
wantSemantic bool
name string
body []byte
}{
{name: "unsupported", body: unsupported, wantSemantic: true},
{name: "conflict", body: conflict, wantSemantic: true},
{name: "unsupported", body: unsupported},
{name: "conflict", body: conflict},
{name: "truncated_selector", body: truncatedSelector.Copy()},
{name: "malformed_selected_query", body: malformedSelectedQuery.Copy()},
} {
@ -351,10 +352,14 @@ func TestNestedExplicitLayerAdmissionErrorsAreNotDefaultFailures(t *testing.T) {
if errors.Is(err, errDefaultLayerAdmission) {
t.Fatalf("explicit admission was misclassified as stale default: %v", err)
}
if test.wantSemantic {
var codecErr *tg.LayerCodecError
if !errors.As(err, &codecErr) || codecErr.Semantic != tg.LayerSemanticMethodInvokeWithLayer {
t.Fatalf("explicit error semantic = %#v, err=%v", codecErr, err)
switch test.name {
case "unsupported":
if !strings.Contains(err.Error(), "unsupported exact profile 229") {
t.Fatalf("unsupported selector error = %v", err)
}
case "conflict":
if !errors.Is(err, tlprofile.ErrProfileConflict) {
t.Fatalf("conflicting selector error = %v", err)
}
}
})
@ -376,7 +381,7 @@ func TestBatchProvisionalCursorKeepsRegistryWatermarkAcrossOldReplay(t *testing.
t.Fatal(err)
}
c := &Conn{authKeyID: authKeyID, sessionID: sessionID, metrics: NopMetrics{}}
if err := c.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 8, time.Second)
@ -384,7 +389,7 @@ func TestBatchProvisionalCursorKeepsRegistryWatermarkAcrossOldReplay(t *testing.
oldBody := exactLayerRPCBody(t, &tg.InvokeWithLayerRequest{Layer: 225, Query: &tg.HelpGetConfigRequest{}})
oldAdmitted, _, err := s.decodeInboundLayerRPC(
LayerProfileSnapshot{Profile: tg.LayerProfile225, Origin: LayerProfileExplicit}, oldBody,
LayerProfileSnapshot{Profile: tlprofile.Profile225, Origin: LayerProfileExplicit}, oldBody,
)
if err != nil {
t.Fatal(err)
@ -398,7 +403,7 @@ func TestBatchProvisionalCursorKeepsRegistryWatermarkAcrossOldReplay(t *testing.
oldClaim.owner.CompleteExecution(true)
s.rpcResults.Put(authKeyID, sessionID, 100, &encodedOutboundMessage{body: []byte{1}, reqMsgID: 100})
nakedBody := exactOutboundLayerRPCBody(t, tg.LayerProfile227, &tg.MessagesGetHistoryRequest{
nakedBody := exactOutboundLayerRPCBody(t, tlprofile.Profile227, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
})
plan := &inboundPlan{items: []inboundItem{
@ -412,7 +417,7 @@ func TestBatchProvisionalCursorKeepsRegistryWatermarkAcrossOldReplay(t *testing.
if plan.items[0].kind != inboundItemReplayRPC {
t.Fatalf("old explicit item kind=%d, want completed replay", plan.items[0].kind)
}
if profile, ok := s.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, 108); !ok || profile != tg.LayerProfile227 {
if profile, ok := s.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, 108); !ok || profile != tlprofile.Profile227 {
t.Fatalf("following naked admission profile = (%d,%v), want registry Layer 227", profile, ok)
}
}
@ -423,7 +428,7 @@ func TestBatchProvisionalCursorUsesPendingNewerExplicitEvidence(t *testing.T) {
authKeyID := [8]byte{0x31, 0x02}
const sessionID = int64(3102)
c := &Conn{authKeyID: authKeyID, sessionID: sessionID, metrics: NopMetrics{}}
if err := c.seedOrderedLayerProfile(tg.LayerProfile225, 100); err != nil {
if err := c.seedOrderedLayerProfile(tlprofile.Profile225, 100); err != nil {
t.Fatal(err)
}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 8, time.Second)
@ -431,7 +436,7 @@ func TestBatchProvisionalCursorUsesPendingNewerExplicitEvidence(t *testing.T) {
explicitBody := exactLayerRPCBody(t, &tg.InvokeWithLayerRequest{Layer: 227, Query: &tg.HelpGetConfigRequest{}})
explicit, _, err := s.decodeInboundLayerRPC(
LayerProfileSnapshot{Profile: tg.LayerProfile227, Origin: LayerProfileExplicit}, explicitBody,
LayerProfileSnapshot{Profile: tlprofile.Profile227, Origin: LayerProfileExplicit}, explicitBody,
)
if err != nil {
t.Fatal(err)
@ -444,7 +449,7 @@ func TestBatchProvisionalCursorUsesPendingNewerExplicitEvidence(t *testing.T) {
}
defer pending.owner.Abort()
nakedBody := exactOutboundLayerRPCBody(t, tg.LayerProfile227, &tg.MessagesGetHistoryRequest{
nakedBody := exactOutboundLayerRPCBody(t, tlprofile.Profile227, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
})
plan := &inboundPlan{items: []inboundItem{
@ -458,10 +463,10 @@ func TestBatchProvisionalCursorUsesPendingNewerExplicitEvidence(t *testing.T) {
if plan.items[0].kind != inboundItemRewrappedRPC {
t.Fatalf("pending explicit item kind=%d, want pending replay", plan.items[0].kind)
}
if profile, ok := s.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, 108); !ok || profile != tg.LayerProfile227 {
if profile, ok := s.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, 108); !ok || profile != tlprofile.Profile227 {
t.Fatalf("following naked admission profile = (%d,%v), want pending Layer 227", profile, ok)
}
if state, msgID := c.layerProfileEvidenceState(); state.Profile != tg.LayerProfile227 || state.Origin != LayerProfileExplicit || msgID != 104 {
if state, msgID := c.layerProfileEvidenceState(); state.Profile != tlprofile.Profile227 || state.Origin != LayerProfileExplicit || msgID != 104 {
t.Fatalf("pending full-identity evidence was not committed = %#v msgID:%d", state, msgID)
}
if got := handler.publications(); len(got) != 0 {
@ -500,7 +505,7 @@ func TestFutureExactLayerWatermarkAllowsOnlyNewerSupportedSelfHeal(t *testing.T)
t.Fatal(err)
}
c := &Conn{authKeyID: authKeyID, sessionID: sessionID, metrics: NopMetrics{}}
if err := c.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 8, time.Second)
@ -513,7 +518,7 @@ func TestFutureExactLayerWatermarkAllowsOnlyNewerSupportedSelfHeal(t *testing.T)
},
{
kind: inboundItemRPC, msgID: 104,
body: exactOutboundLayerRPCBody(t, tg.LayerProfile227, &tg.MessagesGetHistoryRequest{
body: exactOutboundLayerRPCBody(t, tlprofile.Profile227, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
}),
},
@ -549,7 +554,7 @@ func TestFutureExactLayerWatermarkAllowsOnlyNewerSupportedSelfHeal(t *testing.T)
if err := s.prepareInboundLayerRPCBatch(context.Background(), c, newPlan); err != nil {
t.Fatal(err)
}
if state, rawLayer, msgID := c.layerProfileRawEvidenceState(); state.Profile != tg.LayerProfile227 || state.Origin != LayerProfileExplicit || rawLayer != 227 || msgID != 108 {
if state, rawLayer, msgID := c.layerProfileRawEvidenceState(); state.Profile != tlprofile.Profile227 || state.Origin != LayerProfileExplicit || rawLayer != 227 || msgID != 108 {
t.Fatalf("newer supported self-heal = %#v raw:%d msgID:%d", state, rawLayer, msgID)
}
if got := handler.publications(); len(got) != 1 || got[0].layer != 227 || got[0].msgID != 108 {
@ -602,7 +607,7 @@ func TestDurabilityOutageKeepsExplicitLayerConnectionLocal(t *testing.T) {
if !plan.items[0].profileEvidenceFresh() {
t.Fatal("durability fallback incorrectly disabled current-connection wrapper effects")
}
if state, msgID := c.layerProfileEvidenceState(); state.Profile != tg.LayerProfile227 || state.Origin != LayerProfileExplicit || msgID != 100 {
if state, msgID := c.layerProfileEvidenceState(); state.Profile != tlprofile.Profile227 || state.Origin != LayerProfileExplicit || msgID != 100 {
t.Fatalf("connection-local evidence = %#v msgID:%d", state, msgID)
}
if _, _, found := handler.NegotiatedSessionLayerEvidence(c.authKeyID, c.sessionID); found {
@ -679,7 +684,7 @@ func TestDurabilityOutageInitializesOnlyCurrentConnection(t *testing.T) {
if !c.rpcRewrapInitialized.Load() {
t.Fatal("current connection did not retain successful init wrapper state")
}
if state, evidenceMsgID := c.layerProfileEvidenceState(); state.Profile != tg.LayerProfile227 || state.Origin != LayerProfileExplicit || evidenceMsgID != msgID {
if state, evidenceMsgID := c.layerProfileEvidenceState(); state.Profile != tlprofile.Profile227 || state.Origin != LayerProfileExplicit || evidenceMsgID != msgID {
t.Fatalf("current connection profile = %#v msg:%d", state, evidenceMsgID)
}
if _, _, found := router.NegotiatedSessionLayerEvidence(c.authKeyID, c.sessionID); found {
@ -710,7 +715,7 @@ func TestDurabilityOutageInitializesOnlyCurrentConnection(t *testing.T) {
t.Fatal(err)
}
encoded, err := fanout.prepareForConn(ctx, c)
if err != nil || encoded.layer == nil || encoded.layer.profile != tg.LayerProfile227 {
if err != nil || encoded.layer == nil || encoded.layer.profile != tlprofile.Profile227 {
t.Fatalf("outage-local push profile = encoded:%#v err:%v", encoded, err)
}
@ -723,7 +728,7 @@ func TestDurabilityOutageInitializesOnlyCurrentConnection(t *testing.T) {
if state := replacement.LayerProfileState(); state.Origin != LayerProfileUnknown {
t.Fatalf("new session inherited outage-local profile: %#v", state)
}
naked := exactOutboundLayerRPCBody(t, tg.LayerProfile227, &tg.MessagesGetHistoryRequest{
naked := exactOutboundLayerRPCBody(t, tlprofile.Profile227, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
})
if _, _, err := s.admitInboundLayerRPCAt(replacement, msgID+4, naked); err == nil {
@ -782,7 +787,7 @@ func TestInvariantReplayNeverCachesInternalCanonicalProfile(t *testing.T) {
}
profiled := newConn()
defer profiled.Close()
if err := profiled.seedOrderedLayerProfile(tg.LayerProfile225, 104); err != nil {
if err := profiled.seedOrderedLayerProfile(tlprofile.Profile225, 104); err != nil {
t.Fatal(err)
}
completed := &inboundPlan{items: []inboundItem{{kind: inboundItemRPC, msgID: 100, body: body}}}
@ -793,7 +798,7 @@ func TestInvariantReplayNeverCachesInternalCanonicalProfile(t *testing.T) {
if completed.items[0].kind != inboundItemReplayRPC {
t.Fatalf("profiled invariant completed replay kind=%d", completed.items[0].kind)
}
if state, msgID := profiled.layerProfileEvidenceState(); state.Profile != tg.LayerProfile225 || state.Origin != LayerProfileExplicit || msgID != 104 {
if state, msgID := profiled.layerProfileEvidenceState(); state.Profile != tlprofile.Profile225 || state.Origin != LayerProfileExplicit || msgID != 104 {
t.Fatalf("invariant replay polluted explicit profile = %#v msgID:%d", state, msgID)
}
}
@ -804,21 +809,21 @@ func TestSameMsgIDNakedReplayUsesWinnerAdmissionProfile(t *testing.T) {
s.rpcResults = newRPCResultCacheWithFlightLimit(time.Now, 8)
authKeyID := [8]byte{0x22, 0x99}
const sessionID = int64(2299)
body := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.MessagesGetHistoryRequest{
body := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
})
item220 := inboundItem{msgID: 100, body: body}
var err error
item220.admitted, item220.method, err = s.decodeInboundLayerRPC(
LayerProfileSnapshot{Profile: tg.LayerProfile225, Origin: LayerProfileInherited}, body,
LayerProfileSnapshot{Profile: tlprofile.Profile225, Origin: LayerProfileInherited}, body,
)
if err != nil {
t.Fatal(err)
}
item227 := inboundItem{msgID: 100, body: body}
item227.admitted, item227.method, err = s.decodeInboundLayerRPC(
LayerProfileSnapshot{Profile: tg.LayerProfile227, Origin: LayerProfileInherited}, body,
LayerProfileSnapshot{Profile: tlprofile.Profile227, Origin: LayerProfileInherited}, body,
)
if err != nil {
t.Fatal(err)
@ -836,13 +841,13 @@ func TestSameMsgIDNakedReplayUsesWinnerAdmissionProfile(t *testing.T) {
if err != nil || loser.state != rpcResultAcquirePending || loser.admissionSeq != winner.admissionSeq {
t.Fatalf("loser join = state:%d seq:%d err:%v, winner seq:%d", loser.state, loser.admissionSeq, err, winner.admissionSeq)
}
if got := item227.admitted.Call().Profile(); got != tg.LayerProfile225 {
if got := item227.admitted.Call().Profile(); got != tlprofile.Profile225 {
t.Fatalf("loser re-admitted profile = %d, want winner 225", got)
}
changed := inboundItem{msgID: 100, body: exactLayerRPCBody(t, &tg.HelpGetNearestDCRequest{})}
changed.admitted, changed.method, err = s.decodeInboundLayerRPC(
LayerProfileSnapshot{Profile: tg.LayerProfile225, Origin: LayerProfileInherited}, changed.body,
LayerProfileSnapshot{Profile: tlprofile.Profile225, Origin: LayerProfileInherited}, changed.body,
)
if err != nil {
t.Fatal(err)
@ -854,7 +859,7 @@ func TestSameMsgIDNakedReplayUsesWinnerAdmissionProfile(t *testing.T) {
}
func TestInheritedLayerServesRepeatedNakedRPCsWithoutSelectorRefresh(t *testing.T) {
for _, profile := range []tg.LayerProfile{tg.LayerProfile225, tg.LayerProfile227} {
for _, profile := range []tlprofile.Profile{tlprofile.Profile225, tlprofile.Profile227} {
t.Run(fmt.Sprintf("layer_%d", profile), func(t *testing.T) {
s := New(Options{DC: 2, LayerRPC: newAdmissionOnlyLayerRPC()})
c := &Conn{authKeyID: [8]byte{0x71, byte(profile)}, sessionID: int64(profile), metrics: NopMetrics{}}
@ -985,7 +990,7 @@ func TestOldCompletedLayerRequestCannotRollBackCorrectedSession(t *testing.T) {
if err := s.prepareInboundLayerRPCBatch(context.Background(), c, correctPlan); err != nil {
t.Fatal(err)
}
if state, msgID := c.layerProfileEvidenceState(); state.Profile != tg.LayerProfile227 || msgID != 104 {
if state, msgID := c.layerProfileEvidenceState(); state.Profile != tlprofile.Profile227 || msgID != 104 {
t.Fatalf("corrected Conn = %#v msgID:%d", state, msgID)
}
@ -1002,7 +1007,7 @@ func TestOldCompletedLayerRequestCannotRollBackCorrectedSession(t *testing.T) {
if replay.items[0].kind != inboundItemReplayRPC {
t.Fatalf("old request kind=%d, want completed replay", replay.items[0].kind)
}
if state, msgID := replacement.layerProfileEvidenceState(); state.Profile != tg.LayerProfile227 || msgID != 104 {
if state, msgID := replacement.layerProfileEvidenceState(); state.Profile != tlprofile.Profile227 || msgID != 104 {
t.Fatalf("old replay rolled replacement back = %#v msgID:%d", state, msgID)
}
if layer, msgID, ok := handler.NegotiatedSessionLayerEvidence(authKeyID, sessionID); !ok || layer != 227 || msgID != 104 {
@ -1069,11 +1074,11 @@ func TestLogicalSessionLayerWatermarkSurvivesResultExpiryAndOldContainer(t *test
if err := s.seedInitialLayerProfile(context.Background(), replacement, 0, LayerProfileSnapshot{}); err != nil {
t.Fatal(err)
}
if state, msgID := replacement.layerProfileEvidenceState(); state.Profile != tg.LayerProfile227 || state.Origin != LayerProfileInherited || msgID != 0 {
if state, msgID := replacement.layerProfileEvidenceState(); state.Profile != tlprofile.Profile227 || state.Origin != LayerProfileInherited || msgID != 0 {
t.Fatalf("replacement seed = %#v msgID:%d, want inherited Layer 227", state, msgID)
}
freshMsgID := proto.NewMessageIDGen(now.Now).New(proto.MessageFromClient)
nakedBody := exactOutboundLayerRPCBody(t, tg.LayerProfile227, &tg.MessagesGetHistoryRequest{
nakedBody := exactOutboundLayerRPCBody(t, tlprofile.Profile227, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
})
replayPlan := &inboundPlan{items: []inboundItem{
@ -1090,10 +1095,10 @@ func TestLogicalSessionLayerWatermarkSurvivesResultExpiryAndOldContainer(t *test
if err := s.prepareInboundLayerRPCBatch(context.Background(), replacement, replayPlan); err != nil {
t.Fatal(err)
}
if profile, ok := s.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, freshMsgID); !ok || profile != tg.LayerProfile227 {
if profile, ok := s.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, freshMsgID); !ok || profile != tlprofile.Profile227 {
t.Fatalf("naked request after expired old replay = (%d,%v), want Layer 227", profile, ok)
}
if state, msgID := replacement.layerProfileEvidenceState(); state.Profile != tg.LayerProfile227 || state.Origin != LayerProfileInherited || msgID != 0 {
if state, msgID := replacement.layerProfileEvidenceState(); state.Profile != tlprofile.Profile227 || state.Origin != LayerProfileInherited || msgID != 0 {
t.Fatalf("old request-bound flight rolled replacement back = %#v msgID:%d", state, msgID)
}
if _, _, ok := router.NegotiatedSessionLayerEvidence(authKeyID, sessionID); ok {
@ -1156,14 +1161,14 @@ func TestDurableLayerEvidenceRestoresAcrossEdgeRouterRestart(t *testing.T) {
t.Fatal(err)
}
state, rawLayer, evidenceMsgID := replacement.layerProfileRawEvidenceState()
if state.Profile != tg.LayerProfile225 || state.Origin != LayerProfileExplicit || rawLayer != 225 || evidenceMsgID != selectorMsgID {
if state.Profile != tlprofile.Profile225 || state.Origin != LayerProfileExplicit || rawLayer != 225 || evidenceMsgID != selectorMsgID {
t.Fatalf("restart seed = state:%#v raw:%d msg:%d", state, rawLayer, evidenceMsgID)
}
nakedMsgID := msgIDs.New(proto.MessageFromClient)
nakedPlan := &inboundPlan{items: []inboundItem{{
kind: inboundItemRPC, msgID: nakedMsgID,
body: exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.MessagesGetHistoryRequest{
body: exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
}),
layerProfileEvidenceFreshness: inboundLayerProfileEvidenceFresh,
@ -1173,7 +1178,7 @@ func TestDurableLayerEvidenceRestoresAcrossEdgeRouterRestart(t *testing.T) {
t.Fatal(err)
}
profile, profiled := restartedEdge.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, nakedMsgID)
if len(nakedPlan.rpcTasks) != 1 || !profiled || profile != tg.LayerProfile225 {
if len(nakedPlan.rpcTasks) != 1 || !profiled || profile != tlprofile.Profile225 {
t.Fatalf("restart naked admission = tasks:%d item:%+v", len(nakedPlan.rpcTasks), nakedPlan.items[0])
}
}
@ -1207,7 +1212,7 @@ func TestPhysicalConnectionReadsDurableLayerOnceBeforeAdmissionHotPath(t *testin
t.Fatalf("connection seed GetSessionLayer calls=%d, want 1", got)
}
body := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
body := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
for i := 0; i < 64; i++ {
plan := &inboundPlan{items: []inboundItem{{
kind: inboundItemRPC, msgID: msgIDs.New(proto.MessageFromClient), body: body,
@ -1237,12 +1242,12 @@ func TestDurableExactSeedOutageKeepsFetchedAuthKeyDefaultServing(t *testing.T) {
t.Fatal(err)
}
initial := c.LayerProfileState()
if initial.Profile != tg.LayerProfile225 || initial.Origin != LayerProfileInherited {
if initial.Profile != tlprofile.Profile225 || initial.Origin != LayerProfileInherited {
t.Fatalf("outage seed discarded fetched auth-key default: %#v", initial)
}
msgIDs := proto.NewMessageIDGen(time.Now)
body := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.MessagesGetHistoryRequest{
body := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
})
for i := 0; i < 64; i++ {
@ -1280,12 +1285,12 @@ func TestBoundTempSeedOutageKeepsRawFetchedLayerServingCurrentConn(t *testing.T)
t.Fatal(err)
}
initial := c.LayerProfileState()
if initial.Profile != tg.LayerProfile225 || initial.Origin != LayerProfileInherited {
if initial.Profile != tlprofile.Profile225 || initial.Origin != LayerProfileInherited {
t.Fatalf("bound-temp outage discarded same-frame raw default: %#v", initial)
}
msgIDs := proto.NewMessageIDGen(time.Now)
body := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.MessagesGetHistoryRequest{
body := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
})
for i := 0; i < 64; i++ {
@ -1347,7 +1352,7 @@ func TestLiveConnectionKeepsFrozenLayerUntilItsOwnExplicitCorrection(t *testing.
t.Fatal(err)
}
oldPlan.close()
if state, raw, msgID := connA.layerProfileRawEvidenceState(); state.Profile != tg.LayerProfile225 || raw != 225 || msgID != oldMsgID {
if state, raw, msgID := connA.layerProfileRawEvidenceState(); state.Profile != tlprofile.Profile225 || raw != 225 || msgID != oldMsgID {
t.Fatalf("A initial profile = state:%#v raw:%d msg:%d", state, raw, msgID)
}
@ -1366,18 +1371,18 @@ func TestLiveConnectionKeepsFrozenLayerUntilItsOwnExplicitCorrection(t *testing.
oldNakedMsgID := msgIDs.New(proto.MessageFromClient)
oldNakedPlan := &inboundPlan{items: []inboundItem{{
kind: inboundItemRPC, msgID: oldNakedMsgID,
body: exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{}),
body: exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{}),
layerProfileEvidenceFreshness: inboundLayerProfileEvidenceFresh,
}}}
if err := edgeA.prepareInboundLayerRPCBatch(ctx, connA, oldNakedPlan); err != nil {
oldNakedPlan.close()
t.Fatal(err)
}
if state, raw, msgID := connA.layerProfileRawEvidenceState(); state.Profile != tg.LayerProfile225 || raw != 225 || msgID != oldMsgID {
if state, raw, msgID := connA.layerProfileRawEvidenceState(); state.Profile != tlprofile.Profile225 || raw != 225 || msgID != oldMsgID {
oldNakedPlan.close()
t.Fatalf("remote durable advance rewrote live A = state:%#v raw:%d msg:%d", state, raw, msgID)
}
if profile, ok := edgeA.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, oldNakedMsgID); !ok || profile != tg.LayerProfile225 {
if profile, ok := edgeA.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, oldNakedMsgID); !ok || profile != tlprofile.Profile225 {
oldNakedPlan.close()
t.Fatalf("old naked admission profile = (%d,%v), want 225", profile, ok)
}
@ -1388,7 +1393,7 @@ func TestLiveConnectionKeepsFrozenLayerUntilItsOwnExplicitCorrection(t *testing.
mismatchMsgID := msgIDs.New(proto.MessageFromClient)
mismatchPlan := &inboundPlan{items: []inboundItem{{
kind: inboundItemRPC, msgID: mismatchMsgID,
body: exactOutboundLayerRPCBody(t, tg.LayerProfile227, &tg.ChannelsJoinChannelRequest{
body: exactOutboundLayerRPCBody(t, tlprofile.Profile227, &tg.ChannelsJoinChannelRequest{
Channel: &tg.InputChannelEmpty{},
}),
layerProfileEvidenceFreshness: inboundLayerProfileEvidenceFresh,
@ -1402,7 +1407,7 @@ func TestLiveConnectionKeepsFrozenLayerUntilItsOwnExplicitCorrection(t *testing.
t.Fatalf("new naked grammar kind=%d, want admission error", mismatchPlan.items[0].kind)
}
mismatchPlan.close()
if state, raw, msgID := connA.layerProfileRawEvidenceState(); state.Profile != tg.LayerProfile225 || raw != 225 || msgID != oldMsgID {
if state, raw, msgID := connA.layerProfileRawEvidenceState(); state.Profile != tlprofile.Profile225 || raw != 225 || msgID != oldMsgID {
t.Fatalf("failed naked correction mutated A = state:%#v raw:%d msg:%d", state, raw, msgID)
}
@ -1418,10 +1423,10 @@ func TestLiveConnectionKeepsFrozenLayerUntilItsOwnExplicitCorrection(t *testing.
if err := edgeA.prepareInboundLayerRPCBatch(ctx, connA, correctionPlan); err != nil {
t.Fatal(err)
}
if state, raw, msgID := connA.layerProfileRawEvidenceState(); state.Profile != tg.LayerProfile227 || raw != 227 || msgID != correctionMsgID {
if state, raw, msgID := connA.layerProfileRawEvidenceState(); state.Profile != tlprofile.Profile227 || raw != 227 || msgID != correctionMsgID {
t.Fatalf("A explicit correction = state:%#v raw:%d msg:%d", state, raw, msgID)
}
if profile, ok := edgeA.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, correctionMsgID); !ok || profile != tg.LayerProfile227 {
if profile, ok := edgeA.rpcResults.ExactAdmissionProfile(authKeyID, sessionID, correctionMsgID); !ok || profile != tlprofile.Profile227 {
t.Fatalf("corrected admission profile = (%d,%v), want 227", profile, ok)
}
if len(correctionPlan.rpcTasks) != 1 {
@ -1431,7 +1436,7 @@ func TestLiveConnectionKeepsFrozenLayerUntilItsOwnExplicitCorrection(t *testing.
t.Fatal(err)
}
requestProfile, resultProfile := handlerA.profiles()
if requestProfile != tg.LayerProfile227 || resultProfile != tg.LayerProfile227 {
if requestProfile != tlprofile.Profile227 || resultProfile != tlprofile.Profile227 {
t.Fatalf("dispatch/result profiles = %d/%d, want 227/227", requestProfile, resultProfile)
}
}
@ -1488,7 +1493,7 @@ func TestExactSessionProfileSurvivesUnregisterAndSeedsNakedReplay(t *testing.T)
if !ok || layer != 225 {
t.Fatalf("reconnect seed = (%d,%v), want (225,true)", layer, ok)
}
profile, ok := tg.ResolveLayerProfile(layer)
profile, ok := tlprofile.ResolveProfile(layer)
if !ok {
t.Fatalf("resolve retained profile %d", layer)
}
@ -1500,7 +1505,7 @@ func TestExactSessionProfileSurvivesUnregisterAndSeedsNakedReplay(t *testing.T)
if err != nil {
t.Fatalf("same-session naked replay admission: %v", err)
}
if method != "help.getConfig" || admitted.Call().Profile() != tg.LayerProfile225 {
if method != "help.getConfig" || admitted.Call().Profile() != tlprofile.Profile225 {
t.Fatalf("naked replay = method:%q profile:%d", method, admitted.Call().Profile())
}
}
@ -1523,7 +1528,7 @@ func TestSameAuthKeyNewSessionRequiresOwnLayerEvidence(t *testing.T) {
if err != nil {
t.Fatalf("Bob session layer 227: %v", err)
}
if bobRequest.Call().Profile() != tg.LayerProfile227 {
if bobRequest.Call().Profile() != tlprofile.Profile227 {
t.Fatalf("Bob profile = %d, want 227", bobRequest.Call().Profile())
}
@ -1532,7 +1537,7 @@ func TestSameAuthKeyNewSessionRequiresOwnLayerEvidence(t *testing.T) {
Peer: &tg.InputPeerSelf{},
Limit: 1,
}
naked228 := exactOutboundLayerRPCBody(t, tg.LayerProfile228, profileDependent)
naked228 := exactOutboundLayerRPCBody(t, tlprofile.Profile228, profileDependent)
if _, _, err := s.admitInboundLayerRPC(aliceConn, naked228); err == nil {
t.Fatal("new session inherited another session's Layer for naked application RPC")
}
@ -1551,7 +1556,7 @@ func TestSameAuthKeyNewSessionRequiresOwnLayerEvidence(t *testing.T) {
if err != nil {
t.Fatalf("Alice session own layer 228 evidence: %v", err)
}
if aliceRequest.Call().Profile() != tg.LayerProfile228 {
if aliceRequest.Call().Profile() != tlprofile.Profile228 {
t.Fatalf("Alice profile = %d, want 228", aliceRequest.Call().Profile())
}
if layer, ok := router.NegotiatedSessionLayer(authKeyID, bobSession); !ok || layer != 227 {
@ -1573,7 +1578,7 @@ func TestExactSessionRegistryAllowsOrderedExplicitCorrection(t *testing.T) {
// A later well-formed invokeWithLayer is authoritative correction, including
// when same-session recovery initially restored an older explicit profile.
c := &Conn{authKeyID: authKeyID, sessionID: sessionID, metrics: NopMetrics{}}
if err := c.SeedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
wrapped := exactLayerRPCBody(t, &tg.InvokeWithLayerRequest{
@ -1584,10 +1589,10 @@ func TestExactSessionRegistryAllowsOrderedExplicitCorrection(t *testing.T) {
if err != nil {
t.Fatalf("profile correction: %v", err)
}
if request.Call().Profile() != tg.LayerProfile227 {
if request.Call().Profile() != tlprofile.Profile227 {
t.Fatalf("corrected request profile = %d", request.Call().Profile())
}
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileExplicit || got.Epoch < 2 {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileExplicit || got.Epoch < 2 {
t.Fatalf("corrected Conn profile = %#v", got)
}
if layer, ok := router.NegotiatedSessionLayer(authKeyID, sessionID); !ok || layer != 227 {
@ -1599,17 +1604,17 @@ func TestRestoredExplicitProfileNakedFailureRequestsLayerCorrection(t *testing.T
router := rpc.New(rpc.Config{DC: 2}, rpc.Deps{}, zaptest.NewLogger(t), clock.System)
s := New(Options{DC: 2, LayerRPC: router})
c := &Conn{authKeyID: [8]byte{2, 2, 0, 2}, sessionID: 220227, metrics: NopMetrics{}}
if err := c.SeedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
request := &tg.ChannelsJoinChannelRequest{Channel: &tg.InputChannelEmpty{}}
naked227 := exactOutboundLayerRPCBody(t, tg.LayerProfile227, request)
naked227 := exactOutboundLayerRPCBody(t, tlprofile.Profile227, request)
if _, _, err := s.admitInboundLayerRPC(c, naked227); err == nil {
t.Fatal("stale explicit profile admitted newer naked constructor")
} else if rpcErr := layerRPCAdmissionError(err); rpcErr.ErrorCode != 400 || rpcErr.ErrorMessage != "CONNECTION_LAYER_INVALID" {
t.Fatalf("stale explicit profile error = (%d,%q): %v", rpcErr.ErrorCode, rpcErr.ErrorMessage, err)
}
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile225 || got.Origin != LayerProfileExplicit {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile225 || got.Origin != LayerProfileExplicit {
t.Fatalf("failed naked admission changed profile = %#v", got)
}
@ -1618,10 +1623,10 @@ func TestRestoredExplicitProfileNakedFailureRequestsLayerCorrection(t *testing.T
if err != nil {
t.Fatalf("explicit correction retry: %v", err)
}
if admitted.Call().Profile() != tg.LayerProfile227 {
if admitted.Call().Profile() != tlprofile.Profile227 {
t.Fatalf("corrected call profile = %d", admitted.Call().Profile())
}
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileExplicit || got.Epoch < 2 {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileExplicit || got.Epoch < 2 {
t.Fatalf("corrected profile = %#v", got)
}
}
@ -1675,9 +1680,9 @@ func TestUnprofiledInvariantBindKeepsProfileUnknownAndReturnsExactBool(t *testin
if err := envelope.Decode(&bin.Buffer{Buf: encoded.body}); err != nil {
t.Fatal(err)
}
for _, profile := range []tg.LayerProfile{tg.LayerProfile225, tg.LayerProfile227} {
for _, profile := range []tlprofile.Profile{tlprofile.Profile225, tlprofile.Profile227} {
inner := bin.Buffer{Buf: append([]byte(nil), envelope.Result...)}
decoded, err := tg.DecodeLayer(profile, tg.LayerClassBoolType(), &inner)
decoded, err := tlprofile.DecodeObject(profile, &inner, tlprofile.Limits{})
if err != nil {
t.Fatalf("decode invariant Bool at layer %d: %v", profile, err)
}
@ -1688,13 +1693,13 @@ func TestUnprofiledInvariantBindKeepsProfileUnknownAndReturnsExactBool(t *testin
// The same immutable bytes remain legal if profile evidence arrives before
// the queued bind result is physically written.
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
if err := validateOutboundLayerBinding(c, encoded); err != nil {
t.Fatalf("validate invariant result after layer 225 freeze: %v", err)
}
profiledBody := exactOutboundLayerRPCBody(t, tg.LayerProfile225, bind)
profiledBody := exactOutboundLayerRPCBody(t, tlprofile.Profile225, bind)
profiled, _, err := s.admitInboundLayerRPC(c, profiledBody)
if err != nil {
t.Fatal(err)
@ -1714,13 +1719,13 @@ func TestLayerRPCBatchCapacityKeepsExistingPendingReplay(t *testing.T) {
metrics: NopMetrics{},
}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 8, time.Second)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
firstBody := exactLayerRPCBody(t, &tg.HelpGetConfigRequest{})
identityBuffer := &bin.Buffer{Buf: append([]byte(nil), firstBody...)}
admitted, err := router.AdmitLayer(tg.LayerProfile225, identityBuffer, tg.LayerDecodeLimits{})
admitted, err := router.AdmitLayer(tlprofile.Profile225, identityBuffer, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
@ -1768,7 +1773,7 @@ func TestLayerRPCBatchCapacityAbortsRejectedRewrapOwner(t *testing.T) {
sessionID = int64(779)
msgID = int64(900)
)
identity := rpcFlightExactIdentity(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
identity := rpcFlightExactIdentity(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
claim, err := cache.AcquireIdentified(authKeyID, sessionID, msgID, identity)
if err != nil || claim.state != rpcResultAcquireOwner || claim.owner == nil {
t.Fatalf("rewrap owner = state:%d err:%v", claim.state, err)
@ -1819,7 +1824,7 @@ func TestLayerRPCDependencyGateUsesBusinessOutcome(t *testing.T) {
MsgID: test.dependency,
Query: &tg.HelpGetConfigRequest{},
})
admitted, err := router.AdmitLayer(tg.LayerProfile225, &bin.Buffer{Buf: body}, tg.LayerDecodeLimits{})
admitted, err := router.AdmitLayer(tlprofile.Profile225, &bin.Buffer{Buf: body}, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
@ -1847,7 +1852,7 @@ func TestLayerRPCDependencyGateUsesBusinessOutcome(t *testing.T) {
MsgID: 300,
Query: &tg.HelpGetConfigRequest{},
})
missing, err := router.AdmitLayer(tg.LayerProfile225, &bin.Buffer{Buf: missingBody}, tg.LayerDecodeLimits{})
missing, err := router.AdmitLayer(tlprofile.Profile225, &bin.Buffer{Buf: missingBody}, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
@ -1874,12 +1879,12 @@ func TestLayerRPCTimeoutMessageDistinguishesDependencyWait(t *testing.T) {
}
func TestLayerRPCAdmissionErrorUsesTypedUnknownClassification(t *testing.T) {
err := &tg.LayerCodecError{
err := &tlprofile.LayerCodecError{
Operation: "admit RPC request",
Profile: tg.LayerProfile225,
Profile: tlprofile.Profile225,
WireID: 0x01020304,
Reason: "wording may change",
Cause: tg.ErrLayerUnknownRPCMethod,
Cause: tlprofile.ErrUnknownRPCMethod,
}
rpcErr := layerRPCAdmissionError(err)
if rpcErr.ErrorCode != 501 || rpcErr.ErrorMessage != "NOT_IMPLEMENTED" {
@ -1888,11 +1893,11 @@ func TestLayerRPCAdmissionErrorUsesTypedUnknownClassification(t *testing.T) {
}
func TestLayerRPCAdmissionErrorDistinguishesUnknownAndInheritedProfiles(t *testing.T) {
profileRequired := &tg.LayerCodecError{Operation: "admit", Cause: tg.ErrLayerProfileRequired}
profileRequired := &tlprofile.LayerCodecError{Operation: "admit", Cause: tlprofile.ErrProfileRequired}
if rpcErr := layerRPCAdmissionError(profileRequired); rpcErr.ErrorCode != 400 || rpcErr.ErrorMessage != "CONNECTION_NOT_INITED" {
t.Fatalf("unknown profile admission = (%d,%q)", rpcErr.ErrorCode, rpcErr.ErrorMessage)
}
inherited := fmt.Errorf("%w: %w", errDefaultLayerAdmission, tg.ErrLayerUnknownRPCMethod)
inherited := fmt.Errorf("%w: %w", errDefaultLayerAdmission, tlprofile.ErrUnknownRPCMethod)
if rpcErr := layerRPCAdmissionError(inherited); rpcErr.ErrorCode != 400 || rpcErr.ErrorMessage != "CONNECTION_LAYER_INVALID" {
t.Fatalf("inherited profile admission = (%d,%q)", rpcErr.ErrorCode, rpcErr.ErrorMessage)
}

View file

@ -13,7 +13,7 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
type inboundItemKind uint8
@ -58,7 +58,7 @@ type inboundItem struct {
content bool
body []byte
payload any
admitted tg.LayerRequest
admitted tlprofile.Admission
method string
replayAfterSuccessfulDelivery func() error
layerProfileEvidenceFreshness inboundLayerProfileEvidenceFreshness
@ -108,7 +108,7 @@ func (p *inboundPlan) close() {
// advertise the same bytes to another connection while this plan still kept
// the old graph reachable until its caller returned.
for i := range p.items {
p.items[i].admitted = tg.LayerRequest{}
p.items[i].admitted = tlprofile.Admission{}
}
for i := range p.rpcTasks {
p.rpcTasks[i] = inboundRPC{}

View file

@ -14,6 +14,7 @@ import (
"github.com/iamxvbaba/td/tg"
"go.uber.org/zap/zaptest"
"github.com/iamxvbaba/td/tlprofile"
appfiles "telesrv/internal/app/files"
"telesrv/internal/rpc"
)
@ -102,17 +103,17 @@ func (h *failingReplayLayerRPC) PrepareAdmittedReplay(
int64,
int64,
uint64,
tg.LayerRequest,
tlprofile.Admission,
) (func() error, error) {
return nil, h.err
}
func (h *countingLayerRPCAdmission) AdmitLayer(profile tg.LayerProfile, b *bin.Buffer, limits tg.LayerDecodeLimits) (tg.LayerRequest, error) {
func (h *countingLayerRPCAdmission) AdmitLayer(profile tlprofile.Profile, b *bin.Buffer, limits tlprofile.Limits) (tlprofile.Admission, error) {
h.decodeCalls.Add(1)
return h.LayerRPCHandler.AdmitLayer(profile, b, limits)
}
func (h *countingLayerRPCAdmission) AdmitUnprofiled(b *bin.Buffer, limits tg.LayerDecodeLimits) (tg.LayerRequest, error) {
func (h *countingLayerRPCAdmission) AdmitUnprofiled(b *bin.Buffer, limits tlprofile.Limits) (tlprofile.Admission, error) {
h.decodeCalls.Add(1)
return h.LayerRPCHandler.AdmitUnprofiled(b, limits)
}
@ -166,13 +167,13 @@ func TestLayerRPCAdmissionTransfersOriginalReservationToFreshOwner(t *testing.T)
s := New(Options{DC: 2, LayerRPC: router})
c := &Conn{authKeyID: [8]byte{8, 3}, sessionID: 83, metrics: NopMetrics{}}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 4, time.Second)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
bad := make([]byte, bin.Word)
bad[0], bad[1], bad[2], bad[3] = 0x04, 0x03, 0x02, 0x01
fresh := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
fresh := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
plan := &inboundPlan{items: []inboundItem{
{kind: inboundItemRPC, msgID: 100, body: bad},
{kind: inboundItemRPC, msgID: 104, body: fresh},
@ -211,13 +212,13 @@ func TestLayerRPCAdmissionPendingReplayReleasesProvisionalEntry(t *testing.T) {
s := New(Options{DC: 2, LayerRPC: router})
c := &Conn{authKeyID: [8]byte{8, 4}, sessionID: 84, metrics: NopMetrics{}}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 4, time.Second)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
pendingBody := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
pendingBody := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
identityBuffer := &bin.Buffer{Buf: append([]byte(nil), pendingBody...)}
pendingRequest, err := router.AdmitLayer(tg.LayerProfile225, identityBuffer, tg.LayerDecodeLimits{})
pendingRequest, err := router.AdmitLayer(tlprofile.Profile225, identityBuffer, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
@ -226,7 +227,7 @@ func TestLayerRPCAdmissionPendingReplayReleasesProvisionalEntry(t *testing.T) {
t.Fatalf("pending owner = %v, %v", pending.owner, err)
}
freshBody := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetNearestDCRequest{})
freshBody := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetNearestDCRequest{})
plan := &inboundPlan{items: []inboundItem{
{kind: inboundItemRPC, msgID: 100, body: pendingBody},
{kind: inboundItemRPC, msgID: 104, body: freshBody},
@ -253,12 +254,12 @@ func TestLayerRPCAdmissionCompletedReplayReleasesWholeProvisionalBatch(t *testin
s := New(Options{DC: 2, LayerRPC: router})
c := &Conn{authKeyID: [8]byte{8, 8}, sessionID: 88, metrics: NopMetrics{}}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 2, time.Second)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
body := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
body := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
identityBuffer := &bin.Buffer{Buf: append([]byte(nil), body...)}
request, err := router.AdmitLayer(tg.LayerProfile225, identityBuffer, tg.LayerDecodeLimits{})
request, err := router.AdmitLayer(tlprofile.Profile225, identityBuffer, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
@ -299,12 +300,12 @@ func TestLayerRPCAdmissionReplayPreparationErrorIsNotSilentlyDelivered(t *testin
}})
c := &Conn{authKeyID: [8]byte{8, 9}, sessionID: 89, metrics: NopMetrics{}}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 2, time.Second)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
body := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
body := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
identityBuffer := &bin.Buffer{Buf: append([]byte(nil), body...)}
request, err := router.AdmitLayer(tg.LayerProfile225, identityBuffer, tg.LayerDecodeLimits{})
request, err := router.AdmitLayer(tlprofile.Profile225, identityBuffer, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
@ -343,12 +344,12 @@ func TestLayerRPCAdmissionTransferredBatchClosesWithoutLeak(t *testing.T) {
s := New(Options{DC: 2, LayerRPC: router})
c := &Conn{authKeyID: [8]byte{8, 5}, sessionID: 85, metrics: NopMetrics{}}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 2, time.Second)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
plan := &inboundPlan{items: []inboundItem{{
kind: inboundItemRPC, msgID: 100,
body: exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{}),
body: exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{}),
}}}
defer plan.close()
if err := s.prepareInboundLayerRPCBatch(context.Background(), c, plan); err != nil {
@ -378,10 +379,10 @@ func TestLayerRPCAdmissionTransferredBatchCommitsConservativeCharge(t *testing.T
s := New(Options{DC: 2, LayerRPC: router})
c := &Conn{authKeyID: [8]byte{8, 6}, sessionID: 86, metrics: NopMetrics{}}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 2, time.Second)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
body := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
body := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
plan := &inboundPlan{items: []inboundItem{{kind: inboundItemRPC, msgID: 100, body: body}}}
defer plan.close()
if err := s.prepareInboundLayerRPCBatch(context.Background(), c, plan); err != nil {
@ -418,10 +419,10 @@ func TestLayerRPCAdmissionLocalDuplicateConsumesNoProvisionalEntry(t *testing.T)
s := New(Options{DC: 2, LayerRPC: router})
c := &Conn{authKeyID: [8]byte{8, 7}, sessionID: 87, metrics: NopMetrics{}}
c.startInboundRPCScheduler(s.rpcScheduler, 1, 2, time.Second)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
body := exactOutboundLayerRPCBody(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
body := exactOutboundLayerRPCBody(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
plan := &inboundPlan{items: []inboundItem{
{kind: inboundItemDuplicate, msgID: 96, body: body},
{kind: inboundItemRPC, msgID: 100, body: body},

View file

@ -13,13 +13,13 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
"go.uber.org/zap/zaptest"
)
type countingLayerRPCResult struct {
inner tg.LayerRPCResult
encodeCalls atomic.Int32
prepareCalls atomic.Int32
inner tlprofile.Result
encodeCalls atomic.Int32
}
const (
@ -27,15 +27,15 @@ const (
testChannelWireID228 uint32 = 0xd49f34c6
)
func testChannelWireID(profile tg.LayerProfile) uint32 {
if profile == tg.LayerProfile228 {
func testChannelWireID(profile tlprofile.Profile) uint32 {
if profile == tlprofile.Profile228 {
return testChannelWireID228
}
return testChannelWireID227
}
func testOtherChannelWireID(profile tg.LayerProfile) uint32 {
if profile == tg.LayerProfile228 {
func testOtherChannelWireID(profile tlprofile.Profile) uint32 {
if profile == tlprofile.Profile228 {
return testChannelWireID227
}
return testChannelWireID228
@ -55,28 +55,21 @@ func (r *countingLayerRPCResult) Encode(b *bin.Buffer) error {
return r.inner.Encode(b)
}
func (r *countingLayerRPCResult) Prepared() tg.LayerPreparedCall { return r.inner.Prepared() }
func (r *countingLayerRPCResult) Prepared() tlprofile.PreparedCall { return r.inner.Prepared() }
func (r *countingLayerRPCResult) WireInvariant() bool { return r.inner.WireInvariant() }
func (r *countingLayerRPCResult) Freeze() (tg.LayerFrozenResult, error) {
return r.inner.Freeze()
}
func (r *countingLayerRPCResult) Prepare() (tg.LayerPreparedResult, error) {
r.prepareCalls.Add(1)
return r.inner.Prepare()
}
func (r *countingLayerRPCResult) CanonicalValue() any { return r.inner.CanonicalValue() }
func TestExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t *testing.T) {
for _, profile := range []tg.LayerProfile{tg.LayerProfile225, tg.LayerProfile227, tg.LayerProfile228} {
for _, profile := range []tlprofile.Profile{tlprofile.Profile225, tlprofile.Profile227, tlprofile.Profile228} {
t.Run(fmt.Sprintf("layer_%d", profile), func(t *testing.T) {
testExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t, profile)
})
}
}
func testExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t *testing.T, profile tg.LayerProfile) {
func testExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t *testing.T, profile tlprofile.Profile) {
t.Helper()
diff := &tg.UpdatesDifference{
NewMessages: []tg.MessageClass{
@ -95,23 +88,21 @@ func testExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t *testing.T, pro
State: tg.UpdatesState{Pts: 2, Date: 1},
}
dispatcher := tg.NewServerDispatcher(nil)
dispatcher.OnUpdatesGetDifference(func(context.Context, *tg.UpdatesGetDifferenceRequest) (tg.UpdatesDifferenceClass, error) {
dispatcher := tlprofile.NewDispatcher()
if err := dispatcher.Register(tlprofile.SemanticMethodUpdatesGetDifference, func(context.Context, bin.Object) (any, error) {
return diff, nil
})
outbound, err := tg.PrepareLayerOutboundCall(profile, &tg.UpdatesGetDifferenceRequest{Pts: 1, Date: 1})
if err != nil {
}); err != nil {
t.Fatal(err)
}
var requestBody bin.Buffer
if err := outbound.Encode(&requestBody); err != nil {
if err := tlprofile.EncodeObject(profile, &tg.UpdatesGetDifferenceRequest{Pts: 1, Date: 1}, &requestBody); err != nil {
t.Fatal(err)
}
admitted, err := dispatcher.AdmitLayer(profile, &requestBody)
admitted, err := dispatcher.Admit(profile, &requestBody, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
serverResult, err := dispatcher.DispatchAdmitted(context.Background(), admitted)
serverResult, err := dispatcher.Dispatch(context.Background(), admitted)
if err != nil {
t.Fatal(err)
}
@ -124,9 +115,9 @@ func testExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t *testing.T, pro
}
// Simulate an invokeWithLayer correction admitted while this handler was
// still running. The result must retain the request's admitted profile.
corrected := tg.LayerProfile227
if profile == tg.LayerProfile227 {
corrected = tg.LayerProfile225
corrected := tlprofile.Profile227
if profile == tlprofile.Profile227 {
corrected = tlprofile.Profile225
}
if err := c.FreezeLayerProfile(corrected); err != nil {
t.Fatal(err)
@ -136,14 +127,11 @@ func testExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t *testing.T, pro
if err != nil {
t.Fatalf("encode rpc_result: %v", err)
}
if got := counted.prepareCalls.Load(); got != 0 {
t.Fatalf("generated Prepare calls = %d, want 0; inbound workers must not snapshot result bytes", got)
}
if got := counted.encodeCalls.Load(); got != 1 {
t.Fatalf("generated Encode calls = %d, want exactly 1 under outbound admission", got)
}
if encoded.layer == nil || encoded.layer.profile != profile || encoded.layer.typ != admitted.Call().WireResultType() {
t.Fatalf("result binding = %#v, want profile %d and admitted result TypeRef", encoded.layer, profile)
if encoded.layer == nil || encoded.layer.profile != profile {
t.Fatalf("result binding = %#v, want profile %d", encoded.layer, profile)
}
if encoded.layer.kind != outboundLayerBindingRequest {
t.Fatalf("exact RPC result binding kind = %d, want request-bound", encoded.layer.kind)
@ -171,7 +159,7 @@ func testExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t *testing.T, pro
t.Fatalf("profile %d offline difference leaked channel constructor %#08x", profile, otherChannelID)
}
inner := bin.Buffer{Buf: rpcEnvelope.Result}
decoded, err := tg.DecodeLayer(profile, tg.LayerClassUpdatesDifferenceType(), &inner)
decoded, err := tlprofile.DecodeObject(profile, &inner, tlprofile.Limits{})
if err != nil {
t.Fatalf("decode exact difference: %v", err)
}
@ -199,27 +187,25 @@ func testExactLayerRPCResultEncodesDifferenceWithAdmittedCodec(t *testing.T, pro
}
func TestExactLayerRPCResultUsesHistoricalMethodResultType(t *testing.T) {
const profile = tg.LayerProfile225
dispatcher := tg.NewServerDispatcher(nil)
dispatcher.OnChannelsJoinChannel(func(context.Context, tg.InputChannelClass) (tg.MessagesChatInviteJoinResultClass, error) {
const profile = tlprofile.Profile225
dispatcher := tlprofile.NewDispatcher()
if err := dispatcher.Register(tlprofile.SemanticMethodChannelsJoinChannel, func(context.Context, bin.Object) (any, error) {
return &tg.MessagesChatInviteJoinResultOk{Updates: &tg.UpdatesTooLong{}}, nil
})
outbound, err := tg.PrepareLayerOutboundCall(profile, &tg.ChannelsJoinChannelRequest{Channel: &tg.InputChannelEmpty{}})
if err != nil {
}); err != nil {
t.Fatal(err)
}
var requestBody bin.Buffer
if err := outbound.Encode(&requestBody); err != nil {
if err := tlprofile.EncodeObject(profile, &tg.ChannelsJoinChannelRequest{Channel: &tg.InputChannelEmpty{}}, &requestBody); err != nil {
t.Fatal(err)
}
admitted, err := dispatcher.AdmitLayer(profile, &requestBody)
admitted, err := dispatcher.Admit(profile, &requestBody, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
if admitted.Call().WireID() == tg.ChannelsJoinChannelRequestTypeID {
t.Fatal("historical request unexpectedly retained canonical method id")
}
serverResult, err := dispatcher.DispatchAdmitted(context.Background(), admitted)
serverResult, err := dispatcher.Dispatch(context.Background(), admitted)
if err != nil {
t.Fatal(err)
}
@ -237,7 +223,7 @@ func TestExactLayerRPCResultUsesHistoricalMethodResultType(t *testing.T) {
t.Fatal(err)
}
inner := bin.Buffer{Buf: rpcEnvelope.Result}
updates, err := tg.DecodeLayer(profile, tg.LayerClassUpdatesType(), &inner)
updates, err := tlprofile.DecodeObject(profile, &inner, tlprofile.Limits{})
if err != nil {
t.Fatalf("decode historical channels.joinChannel result: %v", err)
}
@ -251,7 +237,7 @@ func TestExactLayerRPCResultUsesHistoricalMethodResultType(t *testing.T) {
func TestProductionUnboundApplicationResultFailsClosedForLayer227(t *testing.T) {
c := &Conn{metrics: NopMetrics{}}
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatal(err)
}
encoded, err := (&Server{log: zaptest.NewLogger(t)}).encodeRPCResult(c, 12345, testLayerChannel())
@ -265,7 +251,7 @@ func TestProductionUnboundApplicationResultFailsClosedForLayer227(t *testing.T)
func TestProductionUnboundApplicationPushFailsClosedForLayer227(t *testing.T) {
c := &Conn{metrics: NopMetrics{}}
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatal(err)
}
frame, err := c.buildFrame(context.Background(), proto.MessageFromServer, testLayerChannelUpdatesValue(321), nil)

View file

@ -7,7 +7,7 @@ import (
"sync"
"testing"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
type countingInheritedLayerResolver struct {
@ -40,66 +40,66 @@ func TestConnLayerProfileUnknownFreezeAndIdempotence(t *testing.T) {
t.Fatalf("initial LayerProfile = (%d, %v), want (0, false)", profile, ok)
}
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatalf("freeze layer 225: %v", err)
}
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatalf("repeat freeze layer 225: %v", err)
}
if profile, ok := c.LayerProfile(); !ok || profile != tg.LayerProfile225 {
if profile, ok := c.LayerProfile(); !ok || profile != tlprofile.Profile225 {
t.Fatalf("LayerProfile = (%d, %v), want (225, true)", profile, ok)
}
}
func TestConnLayerProfileInheritedCanBeCorrectedExplicitly(t *testing.T) {
c := &Conn{}
if err := c.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatalf("seed inherited layer 225: %v", err)
}
initial := c.LayerProfileState()
if initial.Profile != tg.LayerProfile225 || initial.Origin != LayerProfileInherited || initial.Epoch != 1 {
if initial.Profile != tlprofile.Profile225 || initial.Origin != LayerProfileInherited || initial.Epoch != 1 {
t.Fatalf("initial inherited state = %#v", initial)
}
if err := c.SeedInheritedLayerProfile(tg.LayerProfile226); err != nil {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile226); err != nil {
t.Fatalf("repeat inherited seed: %v", err)
}
if got := c.LayerProfileState(); got != initial {
t.Fatalf("second inherited seed replaced selected default: got %#v want %#v", got, initial)
}
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatalf("promote inherited evidence: %v", err)
}
promoted := c.LayerProfileState()
if promoted.Profile != tg.LayerProfile225 || promoted.Origin != LayerProfileExplicit || promoted.Epoch != initial.Epoch+1 {
if promoted.Profile != tlprofile.Profile225 || promoted.Origin != LayerProfileExplicit || promoted.Epoch != initial.Epoch+1 {
t.Fatalf("promoted explicit state = %#v", promoted)
}
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatalf("correct explicit layer: %v", err)
}
corrected := c.LayerProfileState()
if corrected.Profile != tg.LayerProfile227 || corrected.Origin != LayerProfileExplicit || corrected.Epoch != promoted.Epoch+1 {
if corrected.Profile != tlprofile.Profile227 || corrected.Origin != LayerProfileExplicit || corrected.Epoch != promoted.Epoch+1 {
t.Fatalf("corrected explicit state = %#v", corrected)
}
}
func TestConnSeedLayerProfile(t *testing.T) {
c := &Conn{}
if err := c.SeedLayerProfile(tg.LayerProfile226); err != nil {
if err := c.SeedLayerProfile(tlprofile.Profile226); err != nil {
t.Fatalf("seed layer 226: %v", err)
}
if err := c.SeedLayerProfile(tg.LayerProfile226); err != nil {
if err := c.SeedLayerProfile(tlprofile.Profile226); err != nil {
t.Fatalf("repeat seed layer 226: %v", err)
}
if err := c.FreezeLayerProfile(tg.LayerProfile226); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile226); err != nil {
t.Fatalf("freeze seeded layer 226: %v", err)
}
if profile, ok := c.LayerProfile(); !ok || profile != tg.LayerProfile226 {
if profile, ok := c.LayerProfile(); !ok || profile != tlprofile.Profile226 {
t.Fatalf("LayerProfile = (%d, %v), want (226, true)", profile, ok)
}
}
func TestConnLayerProfileRejectsUnsupported(t *testing.T) {
for _, profile := range []tg.LayerProfile{0, 219, 229} {
for _, profile := range []tlprofile.Profile{0, 219, 229} {
t.Run(fmt.Sprintf("layer_%d", profile), func(t *testing.T) {
c := &Conn{}
if err := c.FreezeLayerProfile(profile); !errors.Is(err, ErrLayerProfileUnsupported) {
@ -120,16 +120,16 @@ func TestConnLayerProfileConcurrentCorrectionsRemainAtomic(t *testing.T) {
c := &Conn{}
start := make(chan struct{})
errs := make([]error, goroutines)
profiles := make([]tg.LayerProfile, goroutines)
profiles := make([]tlprofile.Profile, goroutines)
var wg sync.WaitGroup
wg.Add(goroutines)
for i := range goroutines {
profile := tg.LayerProfile225
profile := tlprofile.Profile225
if i%2 != 0 {
profile = tg.LayerProfile227
profile = tlprofile.Profile227
}
profiles[i] = profile
go func(index int, requested tg.LayerProfile) {
go func(index int, requested tlprofile.Profile) {
defer wg.Done()
<-start
errs[index] = c.FreezeLayerProfile(requested)
@ -139,7 +139,7 @@ func TestConnLayerProfileConcurrentCorrectionsRemainAtomic(t *testing.T) {
wg.Wait()
state := c.LayerProfileState()
if state.Origin != LayerProfileExplicit || (state.Profile != tg.LayerProfile225 && state.Profile != tg.LayerProfile227) {
if state.Origin != LayerProfileExplicit || (state.Profile != tlprofile.Profile225 && state.Profile != tlprofile.Profile227) {
t.Fatalf("concurrent final state = %#v, want supported explicit contender", state)
}
if state.Epoch == 0 || state.Epoch > goroutines {
@ -154,23 +154,23 @@ func TestConnLayerProfileConcurrentCorrectionsRemainAtomic(t *testing.T) {
func TestConnLayerProfileEvidenceUsesClientMessageOrder(t *testing.T) {
c := &Conn{}
if err := c.seedOrderedLayerProfile(tg.LayerProfile225, 100); err != nil {
if err := c.seedOrderedLayerProfile(tlprofile.Profile225, 100); err != nil {
t.Fatal(err)
}
if applied, err := c.FreezeLayerProfileAt(tg.LayerProfile227, 104); err != nil || !applied {
if applied, err := c.FreezeLayerProfileAt(tlprofile.Profile227, 104); err != nil || !applied {
t.Fatalf("newer correction applied=%v err=%v", applied, err)
}
corrected := c.LayerProfileState()
if applied, err := c.FreezeLayerProfileAt(tg.LayerProfile225, 100); err != nil || applied {
if applied, err := c.FreezeLayerProfileAt(tlprofile.Profile225, 100); err != nil || applied {
t.Fatalf("old duplicate applied=%v err=%v", applied, err)
}
if got := c.LayerProfileState(); got != corrected {
t.Fatalf("old duplicate changed profile: got %#v want %#v", got, corrected)
}
if applied, err := c.FreezeLayerProfileAt(tg.LayerProfile225, 104); !errors.Is(err, ErrLayerProfileConflict) || applied {
if applied, err := c.FreezeLayerProfileAt(tlprofile.Profile225, 104); !errors.Is(err, ErrLayerProfileConflict) || applied {
t.Fatalf("same-msg conflicting evidence applied=%v err=%v", applied, err)
}
if applied, err := c.FreezeLayerProfileAt(tg.LayerProfile227, 108); err != nil || !applied {
if applied, err := c.FreezeLayerProfileAt(tlprofile.Profile227, 108); err != nil || !applied {
t.Fatalf("same-layer newer evidence applied=%v err=%v", applied, err)
}
state, msgID := c.layerProfileEvidenceState()
@ -185,10 +185,10 @@ func TestSessionManagerSeedsOnlyUnknownRawAuthKeyConnections(t *testing.T) {
unknown := &Conn{authKeyID: authKeyID, sessionID: 1}
explicit := &Conn{authKeyID: authKeyID, sessionID: 2}
inherited := &Conn{authKeyID: authKeyID, sessionID: 3}
if err := explicit.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := explicit.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
if err := inherited.SeedInheritedLayerProfile(tg.LayerProfile226); err != nil {
if err := inherited.SeedInheritedLayerProfile(tlprofile.Profile226); err != nil {
t.Fatal(err)
}
for _, c := range []*Conn{unknown, explicit, inherited} {
@ -200,13 +200,13 @@ func TestSessionManagerSeedsOnlyUnknownRawAuthKeyConnections(t *testing.T) {
if seeded := m.SeedInheritedLayerForRawAuthKey(authKeyID, 227); seeded != 1 {
t.Fatalf("seeded connections = %d, want 1", seeded)
}
if got := unknown.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileInherited {
if got := unknown.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileInherited {
t.Fatalf("unknown connection seed = %#v", got)
}
if got := explicit.LayerProfileState(); got.Profile != tg.LayerProfile225 || got.Origin != LayerProfileExplicit {
if got := explicit.LayerProfileState(); got.Profile != tlprofile.Profile225 || got.Origin != LayerProfileExplicit {
t.Fatalf("explicit connection was overwritten = %#v", got)
}
if got := inherited.LayerProfileState(); got.Profile != tg.LayerProfile226 || got.Origin != LayerProfileInherited {
if got := inherited.LayerProfileState(); got.Profile != tlprofile.Profile226 || got.Origin != LayerProfileInherited {
t.Fatalf("existing inherited connection was overwritten = %#v", got)
}
if seeded := m.SeedInheritedLayerForRawAuthKey(authKeyID, 229); seeded != 0 {
@ -220,10 +220,10 @@ func TestSessionManagerRefreshesInheritedRawKeyShadowAtBind(t *testing.T) {
unknown := &Conn{authKeyID: authKeyID, sessionID: 1}
inherited := &Conn{authKeyID: authKeyID, sessionID: 2}
explicit := &Conn{authKeyID: authKeyID, sessionID: 3}
if err := inherited.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := inherited.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
if err := explicit.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := explicit.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
for _, c := range []*Conn{unknown, inherited, explicit} {
@ -236,11 +236,11 @@ func TestSessionManagerRefreshesInheritedRawKeyShadowAtBind(t *testing.T) {
t.Fatalf("refreshed connections = %d, want 2", refreshed)
}
for name, c := range map[string]*Conn{"unknown": unknown, "inherited": inherited} {
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileInherited {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileInherited {
t.Fatalf("%s refresh = %#v", name, got)
}
}
if got := explicit.LayerProfileState(); got.Profile != tg.LayerProfile225 || got.Origin != LayerProfileExplicit {
if got := explicit.LayerProfileState(); got.Profile != tlprofile.Profile225 || got.Origin != LayerProfileExplicit {
t.Fatalf("explicit evidence overwritten = %#v", got)
}
}
@ -251,10 +251,10 @@ func TestSessionManagerClearsOnlyInheritedRawKeyShadowAtBind(t *testing.T) {
inherited := &Conn{authKeyID: authKeyID, sessionID: 1}
explicit := &Conn{authKeyID: authKeyID, sessionID: 2}
unknown := &Conn{authKeyID: authKeyID, sessionID: 3}
if err := inherited.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := inherited.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
if err := explicit.seedOrderedLayerProfile(tg.LayerProfile227, 104); err != nil {
if err := explicit.seedOrderedLayerProfile(tlprofile.Profile227, 104); err != nil {
t.Fatal(err)
}
for _, c := range []*Conn{inherited, explicit, unknown} {
@ -269,7 +269,7 @@ func TestSessionManagerClearsOnlyInheritedRawKeyShadowAtBind(t *testing.T) {
if got := inherited.LayerProfileState(); got.Origin != LayerProfileUnknown || got.Profile != 0 {
t.Fatalf("inherited shadow after clear = %#v, want unknown", got)
}
if got := explicit.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileExplicit {
if got := explicit.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileExplicit {
t.Fatalf("explicit evidence was cleared = %#v", got)
}
if state, msgID := explicit.layerProfileEvidenceState(); state.Origin != LayerProfileExplicit || msgID != 104 {
@ -292,10 +292,10 @@ func TestSessionManagerSeedsUnknownSessionsAcrossBusinessAuthKey(t *testing.T) {
second := &Conn{authKeyID: rawTwo, sessionID: 2}
explicit := &Conn{authKeyID: rawTwo, sessionID: 3}
inherited := &Conn{authKeyID: rawOne, sessionID: 4}
if err := explicit.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := explicit.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
if err := inherited.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := inherited.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
for _, c := range []*Conn{first, second, explicit, inherited} {
@ -308,14 +308,14 @@ func TestSessionManagerSeedsUnknownSessionsAcrossBusinessAuthKey(t *testing.T) {
t.Fatalf("business auth-key seeded=%d, want 2", seeded)
}
for name, c := range map[string]*Conn{"first": first, "second": second} {
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileInherited {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileInherited {
t.Fatalf("%s business default = %#v", name, got)
}
}
if got := explicit.LayerProfileState(); got.Profile != tg.LayerProfile225 || got.Origin != LayerProfileExplicit {
if got := explicit.LayerProfileState(); got.Profile != tlprofile.Profile225 || got.Origin != LayerProfileExplicit {
t.Fatalf("business seed overwrote explicit = %#v", got)
}
if got := inherited.LayerProfileState(); got.Profile != tg.LayerProfile225 || got.Origin != LayerProfileInherited {
if got := inherited.LayerProfileState(); got.Profile != tlprofile.Profile225 || got.Origin != LayerProfileInherited {
t.Fatalf("business seed overwrote inherited = %#v", got)
}
}
@ -325,7 +325,7 @@ func TestSessionManagerExplicitLayerEvidenceUsesLiveExactSession(t *testing.T) {
authKeyID := [8]byte{2, 2, 9}
const sessionID = int64(229)
c := &Conn{authKeyID: authKeyID, sessionID: sessionID}
if err := c.seedOrderedLayerProfile(tg.LayerProfile226, 1234); err != nil {
if err := c.seedOrderedLayerProfile(tlprofile.Profile226, 1234); err != nil {
t.Fatal(err)
}
if err := m.Register(c); err != nil {
@ -336,7 +336,7 @@ func TestSessionManagerExplicitLayerEvidenceUsesLiveExactSession(t *testing.T) {
}
inherited := &Conn{authKeyID: authKeyID, sessionID: sessionID + 1}
if err := inherited.SeedInheritedLayerProfile(tg.LayerProfile227); err != nil {
if err := inherited.SeedInheritedLayerProfile(tlprofile.Profile227); err != nil {
t.Fatal(err)
}
if err := m.Register(inherited); err != nil {
@ -353,10 +353,10 @@ func TestSessionManagerExplicitLayerEvidenceChoosesNewestActiveOrClaim(t *testin
const sessionID = int64(230)
active := &Conn{authKeyID: authKeyID, sessionID: sessionID}
claim := &Conn{authKeyID: authKeyID, sessionID: sessionID}
if err := active.seedOrderedLayerProfile(tg.LayerProfile225, 100); err != nil {
if err := active.seedOrderedLayerProfile(tlprofile.Profile225, 100); err != nil {
t.Fatal(err)
}
if err := claim.seedOrderedLayerProfile(tg.LayerProfile227, 104); err != nil {
if err := claim.seedOrderedLayerProfile(tlprofile.Profile227, 104); err != nil {
t.Fatal(err)
}
key := sessionKey{authKeyID: authKeyID, sessionID: sessionID}
@ -384,15 +384,15 @@ func TestOrderedSessionLayerBroadcastConvergesAcrossPhysicalGenerations(t *testi
m.bySession[sessionKey{authKeyID: authKeyID, sessionID: sessionID}] = current
m.mu.Unlock()
if applied, err := m.ApplyOrderedLayerProfileForSession(oldPhysical, authKeyID, sessionID, tg.LayerProfile227, 300); err != nil || applied != 2 {
if applied, err := m.ApplyOrderedLayerProfileForSession(oldPhysical, authKeyID, sessionID, tlprofile.Profile227, 300); err != nil || applied != 2 {
t.Fatalf("newer broadcast applied=%d err=%v", applied, err)
}
if applied, err := m.ApplyOrderedLayerProfileForSession(oldPhysical, authKeyID, sessionID, tg.LayerProfile225, 200); err != nil || applied != 0 {
if applied, err := m.ApplyOrderedLayerProfileForSession(oldPhysical, authKeyID, sessionID, tlprofile.Profile225, 200); err != nil || applied != 0 {
t.Fatalf("delayed older broadcast applied=%d err=%v", applied, err)
}
for name, c := range map[string]*Conn{"old": oldPhysical, "current": current} {
state, msgID := c.layerProfileEvidenceState()
if state.Profile != tg.LayerProfile227 || state.Origin != LayerProfileExplicit || msgID != 300 {
if state.Profile != tlprofile.Profile227 || state.Origin != LayerProfileExplicit || msgID != 300 {
t.Fatalf("%s physical state = %#v msgID:%d", name, state, msgID)
}
}
@ -409,7 +409,7 @@ func TestInitialProfileSeedAvoidsPermanentKeyResolverAndPrefersPermForTemp(t *te
if resolver.calls != 0 {
t.Fatalf("permanent resolver calls = %d, want 0", resolver.calls)
}
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileInherited {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileInherited {
t.Fatalf("permanent seed = %#v", got)
}
})
@ -424,7 +424,7 @@ func TestInitialProfileSeedAvoidsPermanentKeyResolverAndPrefersPermForTemp(t *te
if resolver.calls != 1 {
t.Fatalf("temporary resolver calls = %d, want 1", resolver.calls)
}
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileInherited {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileInherited {
t.Fatalf("temporary canonical seed = %#v", got)
}
})
@ -465,7 +465,7 @@ func TestInitialProfileSeedRestoresOrderedExactSessionEvidence(t *testing.T) {
t.Fatal(err)
}
state, msgID := c.layerProfileEvidenceState()
if state.Profile != tg.LayerProfile226 || state.Origin != LayerProfileExplicit || msgID != resolver.msgID {
if state.Profile != tlprofile.Profile226 || state.Origin != LayerProfileExplicit || msgID != resolver.msgID {
t.Fatalf("ordered exact seed = state:%#v msgID:%d", state, msgID)
}
}
@ -487,10 +487,10 @@ func TestInheritedLayerResolverAvailabilityUsesOnlySupportedRawTempShadow(t *tes
for _, tt := range []struct {
name string
fetchedLayer int
wantProfile tg.LayerProfile
wantProfile tlprofile.Profile
wantOrigin LayerProfileOrigin
}{
{name: "supported raw shadow", fetchedLayer: 225, wantProfile: tg.LayerProfile225, wantOrigin: LayerProfileInherited},
{name: "supported raw shadow", fetchedLayer: 225, wantProfile: tlprofile.Profile225, wantOrigin: LayerProfileInherited},
{name: "future raw shadow stays unknown", fetchedLayer: 229, wantOrigin: LayerProfileUnknown},
} {
t.Run(tt.name, func(t *testing.T) {
@ -529,7 +529,7 @@ func TestActivationClaimRecheckClosesTempBindLayerRace(t *testing.T) {
if err := s.refreshActivatedInheritedLayerProfile(context.Background(), c, 225); err != nil {
t.Fatal(err)
}
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileInherited {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileInherited {
t.Fatalf("post-claim permanent recheck = %#v", got)
}
})
@ -537,7 +537,7 @@ func TestActivationClaimRecheckClosesTempBindLayerRace(t *testing.T) {
t.Run("claim wins before bind refresh", func(t *testing.T) {
m := NewSessionManager(nil)
c := &Conn{authKeyID: authKeyID, sessionID: 402, authKeyExpiresAt: 1_900_000_000}
if err := c.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
if err := m.BeginActivation(c); err != nil {
@ -547,7 +547,7 @@ func TestActivationClaimRecheckClosesTempBindLayerRace(t *testing.T) {
if refreshed := m.RefreshInheritedLayerForRawAuthKey(authKeyID, 227); refreshed != 1 {
t.Fatalf("bind refresh count = %d, want 1", refreshed)
}
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile227 || got.Origin != LayerProfileInherited {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile227 || got.Origin != LayerProfileInherited {
t.Fatalf("claim-visible bind refresh = %#v", got)
}
})
@ -556,7 +556,7 @@ func TestActivationClaimRecheckClosesTempBindLayerRace(t *testing.T) {
resolver := &countingInheritedLayerResolver{layer: 229, found: true}
s := &Server{layerRPC: resolver}
c := &Conn{authKeyID: authKeyID, sessionID: 403, authKeyExpiresAt: 1_900_000_000}
if err := c.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
if err := s.refreshActivatedInheritedLayerProfile(context.Background(), c, 225); err != nil {
@ -574,7 +574,7 @@ func TestActivationClaimRecheckClosesTempBindLayerRace(t *testing.T) {
if err := s.refreshActivatedInheritedLayerProfile(context.Background(), c, 225); err != nil {
t.Fatal(err)
}
if got := c.LayerProfileState(); got.Profile != tg.LayerProfile225 || got.Origin != LayerProfileInherited {
if got := c.LayerProfileState(); got.Profile != tlprofile.Profile225 || got.Origin != LayerProfileInherited {
t.Fatalf("availability recheck lost raw shadow = %#v", got)
}
})
@ -583,7 +583,7 @@ func TestActivationClaimRecheckClosesTempBindLayerRace(t *testing.T) {
resolver := &countingInheritedLayerResolver{err: errors.New("invalid binding identity")}
s := &Server{layerRPC: resolver}
c := &Conn{authKeyID: authKeyID, sessionID: 405, authKeyExpiresAt: 1_900_000_000}
if err := c.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
if err := s.refreshActivatedInheritedLayerProfile(context.Background(), c, 225); err != nil {

View file

@ -7,10 +7,10 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tgerr"
"go.uber.org/zap"
"github.com/iamxvbaba/td/tlprofile"
"telesrv/internal/observability/dbtrace"
"telesrv/internal/postresponse"
)
@ -20,8 +20,8 @@ import (
// the inbound worker. The only Encode call happens later under outbound encode
// and retained-byte admission.
type layerRPCResultEncoder struct {
call tg.LayerCall
result tg.LayerRPCResult
call tlprofile.Call
result tlprofile.Result
}
func (e *layerRPCResultEncoder) Encode(b *bin.Buffer) error {
@ -40,7 +40,6 @@ func (e *layerRPCResultEncoder) exactLayerRPCResultBinding() outboundLayerBindin
}
return outboundLayerBinding{
profile: e.call.Profile(),
typ: e.call.WireResultType(),
wireInvariant: e.call.WireInvariant(),
kind: outboundLayerBindingRequest,
}
@ -55,7 +54,7 @@ type exactLayerRPCResultEncoder interface {
// hook onto the generated result codec. The hook may still exercise the old
// scheduling API, but it no longer has a canonical-bytes escape hatch.
type legacyTestRPCResultEncoder struct {
call tg.LayerCall
call tlprofile.Call
result bin.Encoder
}
@ -63,7 +62,7 @@ func (e *legacyTestRPCResultEncoder) Encode(b *bin.Buffer) error {
if e == nil || e.result == nil {
return errors.New("nil legacy test RPC result")
}
return e.call.EncodeResult(e.result, b)
return e.result.Encode(b)
}
func (e *legacyTestRPCResultEncoder) exactLayerRPCResultBinding() outboundLayerBinding {
@ -72,7 +71,6 @@ func (e *legacyTestRPCResultEncoder) exactLayerRPCResultBinding() outboundLayerB
}
return outboundLayerBinding{
profile: e.call.Profile(),
typ: e.call.WireResultType(),
wireInvariant: e.call.WireInvariant(),
kind: outboundLayerBindingRequest,
}
@ -85,7 +83,7 @@ var errLayerRPCResultIdentityMismatch = errors.New("layer RPC result does not ma
// result capability created from this exact admission; accepting a result from
// another request would pair the wrong result TypeRef/profile with this
// flight/cache identity even when both methods happen to share a Go type.
func bindAdmittedLayerRPCResult(request tg.LayerRequest, result tg.LayerRPCResult) (*layerRPCResultEncoder, error) {
func bindAdmittedLayerRPCResult(request tlprofile.Admission, result tlprofile.Result) (*layerRPCResultEncoder, error) {
if result == nil {
return nil, nil
}
@ -101,7 +99,7 @@ func (s *Server) newInboundLayerRPCTask(
admissionSeq uint64,
method string,
profileEvidenceFresh bool,
request tg.LayerRequest,
request tlprofile.Admission,
dependencies layerRPCDependencySet,
owner *rpcResultOwnerLease,
) inboundRPC {
@ -202,7 +200,7 @@ func (s *Server) handleAdmittedLayerRPC(
msgID int64,
admissionSeq uint64,
method string,
request tg.LayerRequest,
request tlprofile.Admission,
owner *rpcResultOwnerLease,
) error {
if s.layerRPC == nil {

View file

@ -11,24 +11,25 @@ import (
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
// preparedOnlyLayerRPCResult is intentionally incapable of encoding. The
// binding guard must reject it solely from immutable admission identity before
// any result method other than Prepared can be observed.
type preparedOnlyLayerRPCResult struct {
tg.LayerRPCResult
prepared tg.LayerPreparedCall
tlprofile.Result
prepared tlprofile.PreparedCall
}
func (r *preparedOnlyLayerRPCResult) Prepared() tg.LayerPreparedCall { return r.prepared }
func (r *preparedOnlyLayerRPCResult) Prepared() tlprofile.PreparedCall { return r.prepared }
func TestBindAdmittedLayerRPCResultRequiresExactRequestIdentity(t *testing.T) {
dispatcher := tg.NewServerDispatcher(nil)
admit := func(request bin.Encoder) tg.LayerRequest {
dispatcher := tlprofile.NewDispatcher()
admit := func(request bin.Encoder) tlprofile.Admission {
t.Helper()
body := &bin.Buffer{Buf: exactLayerRPCBody(t, request)}
admitted, err := dispatcher.AdmitLayer(tg.LayerProfile227, body)
admitted, err := dispatcher.Admit(tlprofile.Profile227, body, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
@ -53,7 +54,7 @@ func TestBindAdmittedLayerRPCResultRequiresExactRequestIdentity(t *testing.T) {
type mismatchedProjectionLayerRPC struct {
*admissionOnlyLayerRPC
result tg.LayerRPCResult
result tlprofile.Result
calls atomic.Int32
}
@ -63,18 +64,18 @@ func (h *mismatchedProjectionLayerRPC) DispatchAdmitted(
int64,
int64,
uint64,
tg.LayerRequest,
) (tg.LayerRPCResult, string, error) {
tlprofile.Admission,
) (tlprofile.Result, string, error) {
h.calls.Add(1)
return h.result, "help.getConfig", nil
}
func TestProjectionFailureCachesInternalWithoutRepeatingBusiness(t *testing.T) {
dispatcher := tg.NewServerDispatcher(nil)
admit := func(request bin.Encoder) tg.LayerRequest {
dispatcher := tlprofile.NewDispatcher()
admit := func(request bin.Encoder) tlprofile.Admission {
t.Helper()
body := &bin.Buffer{Buf: exactLayerRPCBody(t, request)}
admitted, err := dispatcher.AdmitLayer(tg.LayerProfile227, body)
admitted, err := dispatcher.Admit(tlprofile.Profile227, body, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
@ -93,7 +94,7 @@ func TestProjectionFailureCachesInternalWithoutRepeatingBusiness(t *testing.T) {
const reqMsgID = int64(410100)
claim, err := s.rpcResults.AcquireLayerIdentified(
c.authKeyID, c.sessionID, reqMsgID,
tg.LayerProfile227, request.Prepared().Identity(),
tlprofile.Profile227, request.Prepared().Identity(),
)
if err != nil || claim.owner == nil {
t.Fatalf("owner acquisition err=%v", err)
@ -110,7 +111,7 @@ func TestProjectionFailureCachesInternalWithoutRepeatingBusiness(t *testing.T) {
for {
completed, err = s.rpcResults.AcquireLayerIdentified(
c.authKeyID, c.sessionID, reqMsgID,
tg.LayerProfile227, request.Prepared().Identity(),
tlprofile.Profile227, request.Prepared().Identity(),
)
if err == nil && completed.state == rpcResultAcquireCompleted {
break
@ -142,7 +143,7 @@ func TestProjectionFailureCachesInternalWithoutRepeatingBusiness(t *testing.T) {
// success.
replay, err := s.rpcResults.AcquireLayerIdentified(
c.authKeyID, c.sessionID, reqMsgID,
tg.LayerProfile227, request.Prepared().Identity(),
tlprofile.Profile227, request.Prepared().Identity(),
)
if err != nil || replay.state != rpcResultAcquireCompleted || replay.encoded != completed.encoded {
t.Fatalf("projection replay = state:%d err:%v", replay.state, err)

View file

@ -8,6 +8,7 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
var (
@ -36,8 +37,7 @@ const (
)
type outboundLayerBinding struct {
profile tg.LayerProfile
typ *tg.LayerTypeRef
profile tlprofile.Profile
wireInvariant bool
kind outboundLayerBindingKind
// epoch is required for proactive updates. Zero is accepted only for older
@ -52,26 +52,26 @@ type preparedLayerUpdates struct {
}
// layerUpdatesFanout is one immutable canonical Updates snapshot plus a
// request-scoped cache of exact prepared bytes. FreezeLayer and
// PrepareFrozenLayer are the same generated TypeRef codec used by RPC results
// request-scoped cache of exact prepared bytes. FreezeObject and
// FrozenObject.Prepare use the same sparse TypeRef execution plans as RPC results
// and differences; this type adds only fan-out singleflight and ownership.
type layerUpdatesFanout struct {
frozen tg.LayerFrozen[tg.UpdatesClass]
frozen *tlprofile.FrozenObject
size int
mu sync.Mutex
prepared map[tg.LayerProfile]*preparedLayerUpdates
prepared map[tlprofile.Profile]*preparedLayerUpdates
}
func newLayerUpdatesFanout(value tg.UpdatesClass) (*layerUpdatesFanout, error) {
frozen, err := tg.FreezeLayer(tg.LayerClassUpdatesType(), value)
frozen, err := tlprofile.FreezeObject(value)
if err != nil {
return nil, fmt.Errorf("freeze exact layer updates: %w", err)
}
return &layerUpdatesFanout{
frozen: frozen,
size: frozen.CanonicalSize(),
prepared: make(map[tg.LayerProfile]*preparedLayerUpdates),
prepared: make(map[tlprofile.Profile]*preparedLayerUpdates),
}, nil
}
@ -107,7 +107,7 @@ func (u *layerUpdatesFanout) prepareForConn(ctx context.Context, c *Conn) (*enco
return &encoded, nil
}
func (u *layerUpdatesFanout) prepare(ctx context.Context, profile tg.LayerProfile) (*encodedOutboundMessage, error) {
func (u *layerUpdatesFanout) prepare(ctx context.Context, profile tlprofile.Profile) (*encodedOutboundMessage, error) {
if ctx == nil {
ctx = context.Background()
}
@ -149,7 +149,7 @@ func (u *layerUpdatesFanout) prepare(ctx context.Context, profile tg.LayerProfil
return entry.encoded, entry.err
}
func (u *layerUpdatesFanout) discardPrepared(profile tg.LayerProfile, encoded *encodedOutboundMessage) {
func (u *layerUpdatesFanout) discardPrepared(profile tlprofile.Profile, encoded *encodedOutboundMessage) {
if u == nil || encoded == nil {
return
}
@ -172,18 +172,13 @@ func (u *layerUpdatesFanout) discardPrepared(profile tg.LayerProfile, encoded *e
func prepareFrozenLayerUpdatesContext(
ctx context.Context,
profile tg.LayerProfile,
frozen tg.LayerFrozen[tg.UpdatesClass],
profile tlprofile.Profile,
frozen *tlprofile.FrozenObject,
) (*encodedOutboundMessage, error) {
var encoded *encodedOutboundMessage
err := withOutboundEncodeSlot(ctx, nil, func() error {
prepared, err := tg.PrepareFrozenLayer(profile, frozen)
if err != nil {
return err
}
var body bin.Buffer
typ := tg.LayerClassUpdatesType()
if err := prepared.Encode(profile, typ, &body); err != nil {
if err := frozen.Encode(profile, &body); err != nil {
return err
}
id, err := body.PeekID()
@ -192,7 +187,7 @@ func prepareFrozenLayerUpdatesContext(
}
encoded = &encodedOutboundMessage{
body: body.Copy(), typeID: id,
layer: &outboundLayerBinding{profile: profile, typ: prepared.TypeRef()},
layer: &outboundLayerBinding{profile: profile},
}
return nil
})
@ -206,9 +201,6 @@ func validateOutboundLayerBinding(c *Conn, encoded *encodedOutboundMessage) erro
if encoded == nil || encoded.layer == nil {
return nil
}
if encoded.layer.typ == nil {
return errors.New("outbound exact layer TypeRef is nil")
}
if encoded.layer.wireInvariant || encoded.layer.kind == outboundLayerBindingRequest {
return nil
}

View file

@ -11,6 +11,7 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
type epochBlockingTransport struct {
@ -65,7 +66,7 @@ func testLayerChannelUpdatesValue(expires int) tg.UpdatesClass {
}
}
func testConnWithLayerProfile(t *testing.T, profile tg.LayerProfile) *Conn {
func testConnWithLayerProfile(t *testing.T, profile tlprofile.Profile) *Conn {
t.Helper()
c := &Conn{}
if err := c.FreezeLayerProfile(profile); err != nil {
@ -79,7 +80,7 @@ func TestLayerUpdatesFanoutPreparesExactMixedProfiles(t *testing.T) {
if err != nil {
t.Fatalf("freeze updates: %v", err)
}
for _, profile := range []tg.LayerProfile{tg.LayerProfile225, tg.LayerProfile227, tg.LayerProfile228} {
for _, profile := range []tlprofile.Profile{tlprofile.Profile225, tlprofile.Profile227, tlprofile.Profile228} {
t.Run(fmt.Sprintf("layer_%d", profile), func(t *testing.T) {
c := testConnWithLayerProfile(t, profile)
encoded, err := fanout.prepareForConn(context.Background(), c)
@ -90,7 +91,7 @@ func TestLayerUpdatesFanoutPreparesExactMixedProfiles(t *testing.T) {
t.Fatalf("binding = %#v, want profile %d", encoded.layer, profile)
}
input := bin.Buffer{Buf: encoded.body}
decoded, err := tg.DecodeLayer(profile, tg.LayerClassUpdatesType(), &input)
decoded, err := tlprofile.DecodeObject(profile, &input, tlprofile.Limits{})
if err != nil {
t.Fatalf("decode profile %d: %v", profile, err)
}
@ -121,7 +122,7 @@ func TestLayerUpdatesFanoutFreezesDefensivelyAndSharesPreparedProfile(t *testing
}
value.(*tg.UpdateShort).Update.(*tg.UpdateUserStatus).Status.(*tg.UserStatusOnline).Expires = 999
c := testConnWithLayerProfile(t, tg.LayerProfile225)
c := testConnWithLayerProfile(t, tlprofile.Profile225)
const workers = 16
prepared := make([]*encodedOutboundMessage, workers)
prepareErrs := make([]error, workers)
@ -149,7 +150,7 @@ func TestLayerUpdatesFanoutFreezesDefensivelyAndSharesPreparedProfile(t *testing
}
input := bin.Buffer{Buf: prepared[0].body}
decoded, err := tg.DecodeLayer(tg.LayerProfile225, tg.LayerClassUpdatesType(), &input)
decoded, err := tlprofile.DecodeObject(tlprofile.Profile225, &input, tlprofile.Limits{})
if err != nil {
t.Fatalf("decode frozen value: %v", err)
}
@ -165,7 +166,7 @@ func TestLayerUpdatesEpochBecomesStaleWithoutRetiringProfile(t *testing.T) {
t.Fatal(err)
}
c := &Conn{}
if err := c.SeedInheritedLayerProfile(tg.LayerProfile225); err != nil {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
encoded, err := fanout.prepareForConn(context.Background(), c)
@ -173,14 +174,14 @@ func TestLayerUpdatesEpochBecomesStaleWithoutRetiringProfile(t *testing.T) {
t.Fatal(err)
}
oldEpoch := encoded.layer.epoch
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatal(err)
}
if err := validateOutboundLayerBinding(c, encoded); !errors.Is(err, ErrOutboundLayerProfileStale) {
t.Fatalf("old push validation = %v, want ErrOutboundLayerProfileStale", err)
}
state := c.LayerProfileState()
if state.Profile != tg.LayerProfile227 || state.Origin != LayerProfileExplicit || state.Epoch <= oldEpoch {
if state.Profile != tlprofile.Profile227 || state.Origin != LayerProfileExplicit || state.Epoch <= oldEpoch {
t.Fatalf("corrected profile state = %#v, old epoch %d", state, oldEpoch)
}
}
@ -190,13 +191,13 @@ func TestRequestBoundLayerResultSurvivesConnectionCorrection(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c := testConnWithLayerProfile(t, tg.LayerProfile225)
encoded, err := fanout.prepare(context.Background(), tg.LayerProfile225)
c := testConnWithLayerProfile(t, tlprofile.Profile225)
encoded, err := fanout.prepare(context.Background(), tlprofile.Profile225)
if err != nil {
t.Fatal(err)
}
encoded.layer.kind = outboundLayerBindingRequest
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatal(err)
}
if err := validateOutboundLayerBinding(c, encoded); err != nil {
@ -207,7 +208,7 @@ func TestRequestBoundLayerResultSurvivesConnectionCorrection(t *testing.T) {
func TestProfileCorrectionLinearizesAfterStartedPushWrite(t *testing.T) {
transport := newEpochBlockingTransport()
c := newOutboundTestConn(t, transport, nil)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
fanout, err := newLayerUpdatesFanout(testLayerUpdatesValue(123))
@ -228,7 +229,7 @@ func TestProfileCorrectionLinearizesAfterStartedPushWrite(t *testing.T) {
}
corrected := make(chan error, 1)
go func() { corrected <- c.FreezeLayerProfile(tg.LayerProfile227) }()
go func() { corrected <- c.FreezeLayerProfile(tlprofile.Profile227) }()
select {
case err := <-corrected:
t.Fatalf("profile correction crossed an old-epoch physical write: %v", err)
@ -252,7 +253,7 @@ func TestProfileCorrectionLinearizesAfterStartedPushWrite(t *testing.T) {
func TestStaleLayerPushIsRemovedFromResendTracking(t *testing.T) {
c := &Conn{metrics: NopMetrics{}}
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
fanout, err := newLayerUpdatesFanout(testLayerUpdatesValue(123))
@ -263,7 +264,7 @@ func TestStaleLayerPushIsRemovedFromResendTracking(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatal(err)
}
frame := &outboundFrame{msgID: 100, body: encoded.body, layer: encoded.layer}
@ -285,14 +286,14 @@ func TestOutboundLayerBindingRejectsUnknownAndMismatchedConnections(t *testing.T
if err != nil {
t.Fatalf("freeze updates: %v", err)
}
encoded, err := fanout.prepare(context.Background(), tg.LayerProfile225)
encoded, err := fanout.prepare(context.Background(), tlprofile.Profile225)
if err != nil {
t.Fatalf("prepare profile 225: %v", err)
}
if _, err := (&Conn{}).buildFrame(context.Background(), 0, nil, encoded); !errors.Is(err, ErrOutboundLayerProfileUnknown) {
t.Fatalf("unknown profile error = %v", err)
}
wrong := testConnWithLayerProfile(t, tg.LayerProfile227)
wrong := testConnWithLayerProfile(t, tlprofile.Profile227)
if _, err := wrong.buildFrame(context.Background(), 0, nil, encoded); !errors.Is(err, ErrOutboundLayerProfileMismatch) {
t.Fatalf("profile mismatch error = %v", err)
}
@ -307,13 +308,13 @@ func TestPendingPushReservationAccountsPreparedProfilesOnce(t *testing.T) {
reservation.bytes.Store(100)
reservation.refs.Store(1)
if !reservation.reservePrepared(tg.LayerProfile225, 80) {
if !reservation.reservePrepared(tlprofile.Profile225, 80) {
t.Fatal("reserve first profile")
}
if !reservation.reservePrepared(tg.LayerProfile225, 80) {
if !reservation.reservePrepared(tlprofile.Profile225, 80) {
t.Fatal("reuse first profile reservation")
}
if !reservation.reservePrepared(tg.LayerProfile227, 120) {
if !reservation.reservePrepared(tlprofile.Profile227, 120) {
t.Fatal("reserve second profile")
}
if got := budget.snapshot(); got != 300 {

View file

@ -16,6 +16,7 @@ import (
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
"github.com/iamxvbaba/td/transport"
)
@ -545,7 +546,7 @@ func TestOutboundActorSerializesConcurrentSends(t *testing.T) {
clientMsgID := proto.NewMessageIDGen(time.Now)
sendEncrypted(t, conn, cipher, auth, clientMsgID.New(proto.MessageFromClient), &mt.PingRequest{PingID: 1})
collectReplies(t, conn, cipher, auth.AuthKey, mt.MsgsAckTypeID)
freezeActiveTestSessionProfile(t, srv.Conns(), auth.AuthKey.ID, auth.SessionID, tg.LayerProfileCanonical)
freezeActiveTestSessionProfile(t, srv.Conns(), auth.AuthKey.ID, auth.SessionID, tlprofile.ProfileCanonical)
srv.Conns().SetReceivesUpdates(auth.SessionID, true)
const sends = 64
@ -1035,7 +1036,7 @@ func TestOutboundResendAndAckState(t *testing.T) {
clientMsgID := proto.NewMessageIDGen(time.Now)
sendEncrypted(t, conn, cipher, auth, clientMsgID.New(proto.MessageFromClient), &mt.PingRequest{PingID: 1})
collectReplies(t, conn, cipher, auth.AuthKey, mt.MsgsAckTypeID)
freezeActiveTestSessionProfile(t, srv.Conns(), auth.AuthKey.ID, auth.SessionID, tg.LayerProfileCanonical)
freezeActiveTestSessionProfile(t, srv.Conns(), auth.AuthKey.ID, auth.SessionID, tlprofile.ProfileCanonical)
srv.Conns().SetReceivesUpdates(auth.SessionID, true)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)

View file

@ -8,6 +8,7 @@ import (
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
// TestSetReceivesUpdatesFlushesPendingBeforeActivation 验证置位时先排空暂存推送
@ -23,7 +24,7 @@ func TestSetReceivesUpdatesFlushesPendingBeforeActivation(t *testing.T) {
collectReplies(t, conn, cipher, auth.AuthKey, mt.MsgsAckTypeID)
raw := auth.AuthKey.ID
freezeActiveTestSessionProfile(t, srv.Conns(), raw, auth.SessionID, tg.LayerProfileCanonical)
freezeActiveTestSessionProfile(t, srv.Conns(), raw, auth.SessionID, tlprofile.ProfileCanonical)
ctx := context.Background()
// 完全就绪还要求 membership 路由建立(ReceivesUpdatesForAuthKey 的另一半条件)。

View file

@ -11,6 +11,7 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
var ErrSessionAmbiguous = errors.New("session id is shared by multiple auth keys")
@ -154,7 +155,7 @@ func (m *SessionManager) SetReceivesUpdates(sessionID int64, receives bool) {
}
}
func (m *SessionManager) SetLayerProfile(sessionID int64, profile tg.LayerProfile) bool {
func (m *SessionManager) SetLayerProfile(sessionID int64, profile tlprofile.Profile) bool {
m.mu.RLock()
c, _, ok, ambiguous := m.uniqueSessionForTestLocked(sessionID)
m.mu.RUnlock()

View file

@ -6,7 +6,7 @@ import (
"sync"
"sync/atomic"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
const rpcResultFlightDefaultMaxPending = 8192
@ -26,7 +26,7 @@ var (
// re-decode the same naked body under that grammar even if the winner aborts
// immediately after the mismatch is returned.
type rpcResultIdentityMismatchError struct {
profile tg.LayerProfile
profile tlprofile.Profile
hasProfile bool
}
@ -40,11 +40,11 @@ func identityMismatch(identity rpcResultRequestIdentity) error {
}
type rpcResultRequestIdentity struct {
exact tg.LayerPreparedCallIdentity
// profile is retained separately because LayerPreparedCallIdentity is opaque.
exact tlprofile.PreparedIdentity
// profile is retained separately because PreparedIdentity is opaque.
// It lets a same-msg_id replay be re-admitted with the original request
// grammar after the session default has moved to another Layer.
profile tg.LayerProfile
profile tlprofile.Profile
valid bool
}
@ -474,7 +474,7 @@ func (c *rpcResultCache) Acquire(authKeyID [8]byte, sessionID, reqMsgID int64) (
func (c *rpcResultCache) AcquireIdentified(
authKeyID [8]byte,
sessionID, reqMsgID int64,
identity tg.LayerPreparedCallIdentity,
identity tlprofile.PreparedIdentity,
) (rpcResultAcquire, error) {
return c.acquire(authKeyID, sessionID, reqMsgID, rpcResultRequestIdentity{exact: identity, valid: true})
}
@ -485,8 +485,8 @@ func (c *rpcResultCache) AcquireIdentified(
func (c *rpcResultCache) AcquireLayerIdentified(
authKeyID [8]byte,
sessionID, reqMsgID int64,
profile tg.LayerProfile,
identity tg.LayerPreparedCallIdentity,
profile tlprofile.Profile,
identity tlprofile.PreparedIdentity,
) (rpcResultAcquire, error) {
return c.acquire(authKeyID, sessionID, reqMsgID, rpcResultRequestIdentity{
exact: identity, profile: profile, valid: true,
@ -497,7 +497,7 @@ func (c *rpcResultCache) AcquireLayerIdentified(
// owner/result. It does not create or join a flight. Callers still perform
// AcquireLayerIdentified after decode, which atomically rejects a same-msg_id
// body change by comparing the full prepared identity.
func (c *rpcResultCache) ExactAdmissionProfile(authKeyID [8]byte, sessionID, reqMsgID int64) (tg.LayerProfile, bool) {
func (c *rpcResultCache) ExactAdmissionProfile(authKeyID [8]byte, sessionID, reqMsgID int64) (tlprofile.Profile, bool) {
if c == nil || reqMsgID == 0 {
return 0, false
}

View file

@ -9,19 +9,20 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
func rpcFlightTestAuthID(seed byte) [8]byte {
return [8]byte{seed, seed + 1, seed + 2, seed + 3}
}
func rpcFlightExactIdentity(t *testing.T, profile tg.LayerProfile, request bin.Encoder) tg.LayerPreparedCallIdentity {
func rpcFlightExactIdentity(t *testing.T, profile tlprofile.Profile, request bin.Object) tlprofile.PreparedIdentity {
t.Helper()
var body bin.Buffer
if err := request.Encode(&body); err != nil {
if err := tlprofile.EncodeObject(profile, request, &body); err != nil {
t.Fatalf("encode exact request: %v", err)
}
admitted, err := tg.NewServerDispatcher(nil).AdmitLayer(profile, &body)
admitted, err := tlprofile.NewDispatcher().Admit(profile, &body, tlprofile.Limits{})
if err != nil {
t.Fatalf("admit exact request: %v", err)
}
@ -223,8 +224,8 @@ func TestRPCResultFlightRepeatedReplayJoinsStayBoundedAndPutCleansExecution(t *t
func TestRPCResultFlightExactIdentityGuardsPendingAndCompletedReuse(t *testing.T) {
cache := newRPCResultCacheWithFlightLimit(time.Now, 2)
authKeyID := rpcFlightTestAuthID(90)
firstIdentity := rpcFlightExactIdentity(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
otherIdentity := rpcFlightExactIdentity(t, tg.LayerProfile225, &tg.HelpGetNearestDCRequest{})
firstIdentity := rpcFlightExactIdentity(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
otherIdentity := rpcFlightExactIdentity(t, tlprofile.Profile225, &tg.HelpGetNearestDCRequest{})
owner, err := cache.AcquireIdentified(authKeyID, 90, 900, firstIdentity)
if err != nil || owner.state != rpcResultAcquireOwner || owner.owner == nil {
@ -255,23 +256,23 @@ func TestRPCResultFlightExactIdentityGuardsPendingAndCompletedReuse(t *testing.T
func TestRPCResultFlightAdmissionSequenceAllocatedOnceAndReplayed(t *testing.T) {
cache := newRPCResultCacheWithFlightLimit(time.Now, 4)
authKeyID := rpcFlightTestAuthID(89)
identity := rpcFlightExactIdentity(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
owner, err := cache.AcquireLayerIdentified(authKeyID, 89, 890, tg.LayerProfile225, identity)
identity := rpcFlightExactIdentity(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
owner, err := cache.AcquireLayerIdentified(authKeyID, 89, 890, tlprofile.Profile225, identity)
if err != nil || owner.state != rpcResultAcquireOwner || owner.owner == nil || owner.admissionSeq == 0 {
t.Fatalf("owner = state:%d seq:%d err:%v", owner.state, owner.admissionSeq, err)
}
pending, err := cache.AcquireLayerIdentified(authKeyID, 89, 890, tg.LayerProfile225, identity)
pending, err := cache.AcquireLayerIdentified(authKeyID, 89, 890, tlprofile.Profile225, identity)
if err != nil || pending.state != rpcResultAcquirePending || pending.admissionSeq != owner.admissionSeq {
t.Fatalf("pending = state:%d seq:%d err:%v, want seq:%d", pending.state, pending.admissionSeq, err, owner.admissionSeq)
}
owner.owner.CompleteExecution(true)
encoded := &encodedOutboundMessage{body: []byte{1}, reqMsgID: 890}
cache.Put(authKeyID, 89, 890, encoded)
completed, err := cache.AcquireLayerIdentified(authKeyID, 89, 890, tg.LayerProfile225, identity)
completed, err := cache.AcquireLayerIdentified(authKeyID, 89, 890, tlprofile.Profile225, identity)
if err != nil || completed.state != rpcResultAcquireCompleted || completed.admissionSeq != owner.admissionSeq {
t.Fatalf("completed = state:%d seq:%d err:%v, want seq:%d", completed.state, completed.admissionSeq, err, owner.admissionSeq)
}
second, err := cache.AcquireLayerIdentified(authKeyID, 89, 894, tg.LayerProfile225, identity)
second, err := cache.AcquireLayerIdentified(authKeyID, 89, 894, tlprofile.Profile225, identity)
if err != nil || second.admissionSeq <= owner.admissionSeq {
t.Fatalf("second owner seq=%d err=%v, want > %d", second.admissionSeq, err, owner.admissionSeq)
}
@ -286,12 +287,12 @@ func TestRPCResultFlightAdmissionSequenceAllocatedOnceAndReplayed(t *testing.T)
func TestRPCAdmissionSafeFloorTracksOwnersUntilPutOrAbort(t *testing.T) {
cache := newRPCResultCacheWithFlightLimit(time.Now, 4)
authKeyID := rpcFlightTestAuthID(86)
identity := rpcFlightExactIdentity(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
first, err := cache.AcquireLayerIdentified(authKeyID, 86, 860, tg.LayerProfile225, identity)
identity := rpcFlightExactIdentity(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
first, err := cache.AcquireLayerIdentified(authKeyID, 86, 860, tlprofile.Profile225, identity)
if err != nil || first.owner == nil {
t.Fatalf("first owner err=%v", err)
}
second, err := cache.AcquireLayerIdentified(authKeyID, 86, 864, tg.LayerProfile225, identity)
second, err := cache.AcquireLayerIdentified(authKeyID, 86, 864, tlprofile.Profile225, identity)
if err != nil || second.owner == nil {
t.Fatalf("second owner err=%v", err)
}
@ -315,12 +316,12 @@ func TestRPCAdmissionSequenceExhaustionCannotWrap(t *testing.T) {
cache := newRPCResultCacheWithFlightLimit(time.Now, 2)
cache.nextAdmissionSeq.Store(^uint64(0) - 1)
authKeyID := rpcFlightTestAuthID(85)
identity := rpcFlightExactIdentity(t, tg.LayerProfile225, &tg.HelpGetConfigRequest{})
last, err := cache.AcquireLayerIdentified(authKeyID, 85, 850, tg.LayerProfile225, identity)
identity := rpcFlightExactIdentity(t, tlprofile.Profile225, &tg.HelpGetConfigRequest{})
last, err := cache.AcquireLayerIdentified(authKeyID, 85, 850, tlprofile.Profile225, identity)
if err != nil || last.admissionSeq != ^uint64(0) || last.owner == nil {
t.Fatalf("last sequence=%d owner:%v err=%v", last.admissionSeq, last.owner != nil, err)
}
if _, err := cache.AcquireLayerIdentified(authKeyID, 85, 854, tg.LayerProfile225, identity); !errors.Is(err, ErrRPCAdmissionSeqExhausted) {
if _, err := cache.AcquireLayerIdentified(authKeyID, 85, 854, tlprofile.Profile225, identity); !errors.Is(err, ErrRPCAdmissionSeqExhausted) {
t.Fatalf("post-max allocation err=%v, want %v", err, ErrRPCAdmissionSeqExhausted)
}
if got := cache.nextAdmissionSeq.Load(); got != ^uint64(0) {
@ -333,15 +334,15 @@ func TestRPCIdentityMismatchCarriesWinnerProfileAcrossAbort(t *testing.T) {
cache := newRPCResultCacheWithFlightLimit(time.Now, 2)
authKeyID := rpcFlightTestAuthID(88)
request := &tg.MessagesGetHistoryRequest{Peer: &tg.InputPeerSelf{}, Limit: 1}
winnerIdentity := rpcFlightExactIdentity(t, tg.LayerProfile225, request)
loserIdentity := rpcFlightExactIdentity(t, tg.LayerProfile227, request)
winner, err := cache.AcquireLayerIdentified(authKeyID, 88, 880, tg.LayerProfile225, winnerIdentity)
winnerIdentity := rpcFlightExactIdentity(t, tlprofile.Profile225, request)
loserIdentity := rpcFlightExactIdentity(t, tlprofile.Profile227, request)
winner, err := cache.AcquireLayerIdentified(authKeyID, 88, 880, tlprofile.Profile225, winnerIdentity)
if err != nil || winner.owner == nil {
t.Fatalf("winner owner err=%v", err)
}
_, err = cache.AcquireLayerIdentified(authKeyID, 88, 880, tg.LayerProfile227, loserIdentity)
_, err = cache.AcquireLayerIdentified(authKeyID, 88, 880, tlprofile.Profile227, loserIdentity)
var mismatch *rpcResultIdentityMismatchError
if !errors.As(err, &mismatch) || !mismatch.hasProfile || mismatch.profile != tg.LayerProfile225 {
if !errors.As(err, &mismatch) || !mismatch.hasProfile || mismatch.profile != tlprofile.Profile225 {
t.Fatalf("mismatch = %#v err=%v", mismatch, err)
}
if !winner.owner.Abort() {
@ -358,17 +359,17 @@ func TestRPCAdmissionProfileHintSurvivesCompletedEvictionWindow(t *testing.T) {
now := time.Unix(1_900_000_000, 0)
cache := newRPCResultCacheWithFlightLimit(func() time.Time { return now }, 2)
authKeyID := rpcFlightTestAuthID(87)
identity := rpcFlightExactIdentity(t, tg.LayerProfile225, &tg.MessagesGetHistoryRequest{
identity := rpcFlightExactIdentity(t, tlprofile.Profile225, &tg.MessagesGetHistoryRequest{
Peer: &tg.InputPeerSelf{}, Limit: 1,
})
claim, err := cache.AcquireLayerIdentified(authKeyID, 87, 870, tg.LayerProfile225, identity)
claim, err := cache.AcquireLayerIdentified(authKeyID, 87, 870, tlprofile.Profile225, identity)
if err != nil || claim.owner == nil {
t.Fatalf("owner err=%v", err)
}
claim.owner.CompleteExecution(true)
cache.Put(authKeyID, 87, 870, &encodedOutboundMessage{body: []byte{1}, reqMsgID: 870})
profile, ok := cache.ExactAdmissionProfile(authKeyID, 87, 870)
if !ok || profile != tg.LayerProfile225 {
if !ok || profile != tlprofile.Profile225 {
t.Fatalf("profile hint = (%d,%v)", profile, ok)
}
// Admission already copied the hint into its local decoder cursor. Expiry
@ -385,7 +386,7 @@ func TestRPCAdmissionProfileHintSurvivesCompletedEvictionWindow(t *testing.T) {
func TestRPCInvariantIdentityDoesNotExposeCanonicalProfileHint(t *testing.T) {
cache := newRPCResultCacheWithFlightLimit(time.Now, 2)
authKeyID := rpcFlightTestAuthID(84)
identity := rpcFlightExactIdentity(t, tg.LayerProfile227, &tg.AuthBindTempAuthKeyRequest{
identity := rpcFlightExactIdentity(t, tlprofile.Profile227, &tg.AuthBindTempAuthKeyRequest{
PermAuthKeyID: 1, Nonce: 2, ExpiresAt: 3, EncryptedMessage: []byte("bind"),
})
claim, err := cache.AcquireLayerIdentified(authKeyID, 84, 840, 0, identity)

View file

@ -15,6 +15,7 @@ import (
"github.com/iamxvbaba/td/crypto"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
type opaqueRPCResult struct{ body []byte }
@ -491,8 +492,7 @@ func encodedRPCResultForPriorityTest(reqMsgID int64, payloadBytes int) *encodedO
return &encodedOutboundMessage{
typeID: proto.ResultTypeID, reqMsgID: reqMsgID, body: b.Raw(),
layer: &outboundLayerBinding{
profile: tg.LayerProfileCanonical,
typ: tg.LayerClassBoolType().Ref(),
profile: tlprofile.ProfileCanonical,
kind: outboundLayerBindingRequest,
},
}

View file

@ -15,6 +15,7 @@ import (
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
// rpcRewrapRegistry links only an explicit official-client transition:
@ -40,8 +41,8 @@ type rpcRewrapSessionKey struct {
type rpcRewrapKey struct {
rpcRewrapSessionKey
fingerprint [sha256.Size]byte
semantic tg.LayerSemanticRequestIdentity
call tg.LayerCallIdentity
semantic tlprofile.SemanticIdentity
call tlprofile.CallIdentity
exact bool
}
@ -110,8 +111,8 @@ func (r *rpcRewrapRegistry) register(c *Conn, body []byte, reqMsgID int64, metho
func (r *rpcRewrapRegistry) registerSemantic(
c *Conn,
identity tg.LayerSemanticRequestIdentity,
call tg.LayerCallIdentity,
identity tlprofile.SemanticIdentity,
call tlprofile.CallIdentity,
reqMsgID int64,
method string,
owner *rpcResultOwnerLease,
@ -183,8 +184,8 @@ func (r *rpcRewrapRegistry) claim(c *Conn, inner []byte) *rpcRewrapCandidate {
func (r *rpcRewrapRegistry) claimSemantic(
c *Conn,
identity tg.LayerSemanticRequestIdentity,
call tg.LayerCallIdentity,
identity tlprofile.SemanticIdentity,
call tlprofile.CallIdentity,
) *rpcRewrapCandidate {
if r == nil || c == nil || identity.Method() == 0 || identity.CanonicalSize() <= 0 {
return nil

View file

@ -17,11 +17,12 @@ import (
"github.com/iamxvbaba/td/tgerr"
"github.com/iamxvbaba/td/transport"
"github.com/iamxvbaba/td/tlprofile"
"telesrv/internal/rpc"
)
// TestRPCGetConfig 验证 M3:握手后 client 加密 help.getConfig,
// server 经 tg.ServerDispatcher 路由并回 rpc_result(含本地 DC),外加 new_session_created + ack。
// server 经 tlprofile.Dispatcher 路由并回 rpc_result(含本地 DC),外加 new_session_created + ack。
func TestRPCGetConfig(t *testing.T) {
const (
dc = 2
@ -80,7 +81,7 @@ func TestLayerRPCGetConfigUsesExactAdmittedProfile(t *testing.T) {
clientMsgID := proto.NewMessageIDGen(time.Now)
reqMsgID := clientMsgID.New(proto.MessageFromClient)
request := &tg.InvokeWithLayerRequest{
Layer: int(tg.LayerProfile225),
Layer: int(tlprofile.Profile225),
Query: &tg.InitConnectionRequest{
APIID: 123,
DeviceModel: "Desktop",
@ -104,10 +105,14 @@ func TestLayerRPCGetConfigUsesExactAdmittedProfile(t *testing.T) {
t.Fatalf("rpc_result req_msg_id = %d, want %d", result.RequestMessageID, reqMsgID)
}
exact := &bin.Buffer{Buf: result.Result}
config, err := tg.DecodeLayer(tg.LayerProfile225, tg.LayerConstructorConfigType(), exact)
configObject, err := tlprofile.DecodeObject(tlprofile.Profile225, exact, tlprofile.Limits{})
if err != nil {
t.Fatalf("decode layer 225 config: %v", err)
}
config, ok := configObject.(*tg.Config)
if !ok {
t.Fatalf("layer 225 config = %T, want *tg.Config", configObject)
}
if exact.Len() != 0 || config.ThisDC != dc {
t.Fatalf("layer 225 config = dc:%d remaining:%d", config.ThisDC, exact.Len())
}

View file

@ -25,6 +25,7 @@ import (
"github.com/iamxvbaba/td/tmap"
"github.com/iamxvbaba/td/transport"
"github.com/iamxvbaba/td/tlprofile"
"telesrv/internal/store"
"telesrv/internal/store/memory"
)
@ -57,25 +58,25 @@ type legacyRPCHandlerWithMethod interface {
// validate wrapper dependencies and establish exact request identity before
// flight/cache/scheduler ownership is acquired.
type LayerRPCHandler interface {
AdmitLayer(profile tg.LayerProfile, b *bin.Buffer, limits tg.LayerDecodeLimits) (tg.LayerRequest, error)
AdmitUnprofiled(b *bin.Buffer, limits tg.LayerDecodeLimits) (tg.LayerRequest, error)
AdmitLayer(profile tlprofile.Profile, b *bin.Buffer, limits tlprofile.Limits) (tlprofile.Admission, error)
AdmitUnprofiled(b *bin.Buffer, limits tlprofile.Limits) (tlprofile.Admission, error)
DispatchAdmitted(
ctx context.Context,
authKeyID [8]byte,
sessionID int64,
msgID int64,
admissionSeq uint64,
request tg.LayerRequest,
) (tg.LayerRPCResult, string, error)
request tlprofile.Admission,
) (tlprofile.Result, string, error)
}
// LayerRPCDefaultProfileAdmitter decodes with a recoverable inherited/default
// profile. Production handlers should implement it with the same generated
// ServerDispatcher and adapter registry used by AdmitLayer. The split keeps old
// profile. Production handlers should implement it with the same sparse
// tlprofile dispatcher and semantic adapter registry used by AdmitLayer. The split keeps old
// test doubles source-compatible while allowing invokeWithLayer to correct even
// a previously explicit Conn profile.
type LayerRPCDefaultProfileAdmitter interface {
AdmitDefaultLayer(profile tg.LayerProfile, b *bin.Buffer, limits tg.LayerDecodeLimits) (tg.LayerRequest, error)
AdmitDefaultLayer(profile tlprofile.Profile, b *bin.Buffer, limits tlprofile.Limits) (tlprofile.Admission, error)
}
// LayerRPCSessionProfileResolver may restore an exact profile only when it was
@ -168,7 +169,7 @@ type LayerRPCReplayPreparer interface {
sessionID int64,
msgID int64,
admissionSeq uint64,
request tg.LayerRequest,
request tlprofile.Admission,
) (afterSuccessfulDelivery func() error, err error)
}

View file

@ -14,6 +14,7 @@ import (
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
// ErrSessionNotFound 表示目标 session 当前无活跃连接。
@ -82,7 +83,7 @@ type pendingPushReservation struct {
refs atomic.Int32
mu sync.Mutex
profiles map[tg.LayerProfile]struct{}
profiles map[tlprofile.Profile]struct{}
}
func (r *pendingPushReservation) retain() {
@ -110,7 +111,7 @@ func (r *pendingPushReservation) release() {
// reservePrepared accounts the profile-specific immutable body retained by the
// semantic pending fanout. Multiple queued sessions sharing this reservation
// and profile share both the bytes and this one budget charge.
func (r *pendingPushReservation) reservePrepared(profile tg.LayerProfile, bytes int) bool {
func (r *pendingPushReservation) reservePrepared(profile tlprofile.Profile, bytes int) bool {
if r == nil || bytes < 0 {
return false
}
@ -123,7 +124,7 @@ func (r *pendingPushReservation) reservePrepared(profile tg.LayerProfile, bytes
return false
}
if r.profiles == nil {
r.profiles = make(map[tg.LayerProfile]struct{})
r.profiles = make(map[tlprofile.Profile]struct{})
}
r.profiles[profile] = struct{}{}
r.bytes.Add(int64(bytes))
@ -274,7 +275,7 @@ func (m *SessionManager) SeedInheritedLayerForBusinessAuthKey(businessAuthKeyID
if m == nil || businessAuthKeyID == ([8]byte{}) {
return 0
}
profile, ok := tg.ResolveLayerProfile(layer)
profile, ok := tlprofile.ResolveProfile(layer)
if !ok {
return 0
}
@ -313,7 +314,7 @@ func (m *SessionManager) applyInheritedLayerForRawAuthKey(rawAuthKeyID [8]byte,
if m == nil {
return 0
}
profile, ok := tg.ResolveLayerProfile(layer)
profile, ok := tlprofile.ResolveProfile(layer)
if !ok {
return 0
}
@ -364,7 +365,7 @@ func (m *SessionManager) ApplyOrderedLayerProfileForSession(
primary *Conn,
rawAuthKeyID [8]byte,
sessionID int64,
profile tg.LayerProfile,
profile tlprofile.Profile,
msgID int64,
) (int, error) {
if err := validateLayerProfile(profile); err != nil {
@ -452,7 +453,7 @@ func (m *SessionManager) ExplicitLayerEvidenceForAuthKey(rawAuthKeyID [8]byte, s
if c.isRetired() || state.Origin != LayerProfileExplicit {
continue
}
profile, supported := tg.ResolveLayerProfile(int(state.Profile))
profile, supported := tlprofile.ResolveProfile(int(state.Profile))
if !supported || profile != state.Profile {
continue
}
@ -477,7 +478,7 @@ func (m *SessionManager) SetClientLayerForAuthKey(rawAuthKeyID [8]byte, sessionI
if m == nil {
return
}
profile, ok := tg.ResolveLayerProfile(layer)
profile, ok := tlprofile.ResolveProfile(layer)
if !ok {
return
}

View file

@ -15,6 +15,7 @@ import (
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
type closeCountingTransport struct {
@ -226,7 +227,7 @@ func TestSessionManagerBestEffortFanoutPreparesOncePerProfile(t *testing.T) {
c.userID.Store(userID)
c.userIDResolved.Store(true)
c.receivesUpdates.Store(true)
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatalf("freeze profile: %v", err)
}
sm.Register(c)
@ -263,7 +264,7 @@ func TestSessionManagerMixedLayerFanoutUsesProfileBoundBodies(t *testing.T) {
sm := NewSessionManager(zaptest.NewLogger(t))
const userID = int64(103)
authKeyID := [8]byte{0x22, 0x70, 0x22, 0x80}
profiles := []tg.LayerProfile{tg.LayerProfile225, tg.LayerProfile227, tg.LayerProfile228}
profiles := []tlprofile.Profile{tlprofile.Profile225, tlprofile.Profile227, tlprofile.Profile228}
conns := make([]*Conn, 0, len(profiles))
for _, profile := range profiles {
c := &Conn{
@ -277,8 +278,8 @@ func TestSessionManagerMixedLayerFanoutUsesProfileBoundBodies(t *testing.T) {
c.userID.Store(userID)
c.userIDResolved.Store(true)
c.receivesUpdates.Store(true)
if profile == tg.LayerProfile228 {
if err := c.SeedInheritedLayerProfile(tg.LayerProfile227); err != nil {
if profile == tlprofile.Profile228 {
if err := c.SeedInheritedLayerProfile(tlprofile.Profile227); err != nil {
t.Fatalf("seed Alice inherited profile: %v", err)
}
}
@ -319,7 +320,7 @@ func TestSessionManagerMixedLayerFanoutUsesProfileBoundBodies(t *testing.T) {
t.Fatalf("profile %d push leaked channel constructor %#08x", profiles[i], otherChannelID)
}
input := bin.Buffer{Buf: op.encoded.body}
decoded, decodeErr := tg.DecodeLayer(profiles[i], tg.LayerClassUpdatesType(), &input)
decoded, decodeErr := tlprofile.DecodeObject(profiles[i], &input, tlprofile.Limits{})
if decodeErr != nil || input.Len() != 0 {
t.Fatalf("decode profile %d: remaining=%d err=%v", profiles[i], input.Len(), decodeErr)
}
@ -397,7 +398,7 @@ func TestSessionManagerBestEffortFanoutUsesOneBudgetAndDropsOnlySlowConsumers(t
c.userID.Store(userID)
c.userIDResolved.Store(true)
c.receivesUpdates.Store(true)
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatalf("freeze profile: %v", err)
}
sm.Register(c)
@ -415,7 +416,7 @@ func TestSessionManagerBestEffortFanoutUsesOneBudgetAndDropsOnlySlowConsumers(t
healthy.userID.Store(userID)
healthy.userIDResolved.Store(true)
healthy.receivesUpdates.Store(true)
if err := healthy.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := healthy.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatalf("freeze healthy profile: %v", err)
}
sm.Register(healthy)
@ -747,7 +748,7 @@ func TestPushToUserAuthKeyUsesOneDeadlineAndDropsOnlySlowPFSConnections(t *testi
outboundStop: make(chan struct{}),
}
c.receivesUpdates.Store(true)
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatalf("freeze profile: %v", err)
}
if queueFull {
@ -912,7 +913,7 @@ func TestPushToSessionForAuthKeyImmediateBypassesReadinessQueue(t *testing.T) {
outboundControl: make(chan outboundOp, 1),
outboundStop: make(chan struct{}),
}
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatalf("freeze profile: %v", err)
}
sm.Register(c)
@ -991,7 +992,7 @@ func TestSessionManagerWithholdsUpdatesReadinessUntilExactProfile(t *testing.T)
default:
}
if err := c.FreezeLayerProfile(tg.LayerProfile225); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile225); err != nil {
t.Fatal(err)
}
c.membershipsSynced.Store(true)
@ -1002,7 +1003,7 @@ func TestSessionManagerWithholdsUpdatesReadinessUntilExactProfile(t *testing.T)
case <-time.After(time.Second):
t.Fatal("profiled readiness did not flush pending update")
}
if op.encoded == nil || op.encoded.layer == nil || op.encoded.layer.profile != tg.LayerProfile225 {
if op.encoded == nil || op.encoded.layer == nil || op.encoded.layer.profile != tlprofile.Profile225 {
t.Fatalf("flushed update layer binding = %#v", op.encoded)
}
op.releaseReservation(c.outboundTrackedBudget)
@ -1062,7 +1063,7 @@ func TestPendingFlushGlobalBodyPressureDoesNotTerminateHealthyConnection(t *test
const userID = int64(606)
c.userID.Store(userID)
c.userIDResolved.Store(true)
if err := c.FreezeLayerProfile(tg.LayerProfileCanonical); err != nil {
if err := c.FreezeLayerProfile(tlprofile.ProfileCanonical); err != nil {
t.Fatal(err)
}
sm.Register(c)
@ -1160,8 +1161,8 @@ func TestSessionManagerPush(t *testing.T) {
if got := srv.Conns().Online(); got != 2 {
t.Fatalf("online = %d, want 2", got)
}
if !srv.Conns().SetLayerProfile(auth1.SessionID, tg.LayerProfile227) ||
!srv.Conns().SetLayerProfile(auth2.SessionID, tg.LayerProfile227) {
if !srv.Conns().SetLayerProfile(auth1.SessionID, tlprofile.Profile227) ||
!srv.Conns().SetLayerProfile(auth2.SessionID, tlprofile.Profile227) {
t.Fatal("seed exact test profiles")
}

View file

@ -5,7 +5,7 @@ import (
"testing"
"time"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
"go.uber.org/zap/zaptest"
)
@ -67,7 +67,7 @@ func TestSetSessionChannelMembershipsDetectsConcurrentIncrementalUpdates(t *test
sm := NewSessionManager(zaptest.NewLogger(t))
raw := [8]byte{1, 2, 3}
c := &Conn{sessionID: 42, authKeyID: raw}
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatal(err)
}
sm.Register(c)

View file

@ -3,7 +3,7 @@ package mtprotoedge
import (
"testing"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
"go.uber.org/zap/zaptest"
)
@ -16,7 +16,7 @@ func TestReceivesUpdatesForAuthKeyRequiresMembershipSync(t *testing.T) {
sm := NewSessionManager(zaptest.NewLogger(t))
raw := [8]byte{1, 2, 3}
c := &Conn{sessionID: 42, authKeyID: raw}
if err := c.FreezeLayerProfile(tg.LayerProfile227); err != nil {
if err := c.FreezeLayerProfile(tlprofile.Profile227); err != nil {
t.Fatal(err)
}
sm.Register(c)