internal/domain/phone.go
Rama main · réplica de lectura del repositorio original.
package domain
// PhoneCallState is the server state of the private 1:1 call signaling state machine.
// State transitions, TL perspective mapping and push strategy are in docs and internal/app/phone.
type PhoneCallState string
const (
// PhoneCallStateRequested: requestCall has been accepted and phoneCallRequested has been pushed to the callee.
PhoneCallStateRequested PhoneCallState = "requested"
// PhoneCallStateRinging: at least one callee device reported receivedCall (the caller switches to the ringing UI based on receive_date).
PhoneCallStateRinging PhoneCallState = "ringing"
// PhoneCallStateAccepted: the callee's acceptCall has stored g_b, waiting for the caller's confirmCall.
PhoneCallStateAccepted PhoneCallState = "accepted"
// PhoneCallStateConfirmed: the caller's confirmCall completed the key exchange and the call is in progress.
PhoneCallStateConfirmed PhoneCallState = "confirmed"
// PhoneCallStateDiscarded: terminal state. Kept as a tombstone for a while to absorb late RPCs before being reclaimed.
PhoneCallStateDiscarded PhoneCallState = "discarded"
)
// PhoneCallDiscardReason is the hangup reason, one-to-one with TL phoneCallDiscardReason*.
type PhoneCallDiscardReason string
const (
PhoneCallDiscardReasonMissed PhoneCallDiscardReason = "missed"
PhoneCallDiscardReasonDisconnect PhoneCallDiscardReason = "disconnect"
PhoneCallDiscardReasonHangup PhoneCallDiscardReason = "hangup"
PhoneCallDiscardReasonBusy PhoneCallDiscardReason = "busy"
// PhoneCallDiscardReasonMigrateConference is the migration hangup when upgrading to a conference call;
// conference is currently unsupported and the reason is only echoed verbatim.
PhoneCallDiscardReasonMigrateConference PhoneCallDiscardReason = "migrate_conference"
)
// PhoneCallProtocol is the tgcalls protocol negotiation parameters (TL phoneCallProtocol).
type PhoneCallProtocol struct {
UDPP2P bool
UDPReflector bool
MinLayer int
MaxLayer int
LibraryVersions []string
}
// SessionRef identifies one specific device connection (the anchor for the signaling targeted-push fast path; allowed to go stale).
type SessionRef struct {
RawAuthKeyID [8]byte
SessionID int64
}
// Zero reports whether the anchor is unrecorded.
func (s SessionRef) Zero() bool {
return s == SessionRef{}
}
// PhoneCallConnection is a WebRTC STUN/TURN server entry issued to both sides
// (TL phoneConnectionWebrtc). Issued when requestCall is accepted and stable for the whole lifetime.
type PhoneCallConnection struct {
ID int64
IP string
Port int
Username string
Password string
Stun bool
Turn bool
}
// PhoneCallRequest is the acceptance input of phone.requestCall (privacy/block checks run first in the rpc layer).
type PhoneCallRequest struct {
CalleeID int64
RandomID int64
GAHash []byte
Video bool
Protocol PhoneCallProtocol
CallerDevice SessionRef
// PrivacyP2P is the two-way AND of phone_p2p privacy (computed by the rpc layer; set false when relay is forced).
PrivacyP2P bool
// Connections is the STUN/TURN list issued for this call (may be empty: when TURN is disabled it falls back to
// a LAN direct connection that exchanges host candidates through pure signaling).
Connections []PhoneCallConnection
}
// PhoneCall is the server-authoritative state of one private call. Key material (GAHash/GB/GA) lives only in an
// in-process registry and is destroyed with tombstone reclamation, never persisted to any storage.
type PhoneCall struct {
ID int64
AccessHash int64
// AdminID is the caller and ParticipantID the callee; named the same as the TL phoneCall fields and unchanged for the whole lifetime.
AdminID int64
ParticipantID int64
Video bool
State PhoneCallState
Date int // requestCall acceptance time (unix seconds)
ReceiveDate int // time of the first callee device's receivedCall; 0 means not yet reached
StartDate int // confirmCall completion time
DiscardedAt int // time of entering the terminal state (basis for tombstone GC)
GAHash []byte // 32B, the commitment carried by requestCall
GB []byte // 256B, carried by acceptCall
GA []byte // 256B, revealed by confirmCall (the server verifies SHA256(GA)==GAHash)
KeyFingerprint int64 // E2E fingerprint the server cannot verify and only relays
// Protocol is the negotiated result (computed at accept); CallerProtocol/CalleeProtocol keep the two originals.
Protocol PhoneCallProtocol
CallerProtocol PhoneCallProtocol
CalleeProtocol PhoneCallProtocol
P2PAllowed bool
DiscardReason PhoneCallDiscardReason
// DiscardReasonSlug is set for migrate_conference and must resolve through
// phone.getGroupCall(inputGroupCallSlug) before the discarded update is sent.
DiscardReasonSlug string
Duration int
// PrivacyP2P and Connections are preserved verbatim from PhoneCallRequest (see its comment).
PrivacyP2P bool
Connections []PhoneCallConnection
RandomID int64 // half of the caller-side idempotent dedup key (callerID+RandomID)
// Device anchors: the originating device of requestCall / acceptCall, used only as a hint for targeted push.
CallerDevice SessionRef
CalleeDevice SessionRef
}
// Terminal reports whether the call has entered the terminal state.
func (c PhoneCall) Terminal() bool {
return c.State == PhoneCallStateDiscarded
}
// PeerOf returns userID's peer in this call; returns 0 when userID is not a participant.
func (c PhoneCall) PeerOf(userID int64) int64 {
switch userID {
case c.AdminID:
return c.ParticipantID
case c.ParticipantID:
return c.AdminID
default:
return 0
}
}
// HasParticipant reports whether userID is a participant in this call.
func (c PhoneCall) HasParticipant(userID int64) bool {
return userID != 0 && (userID == c.AdminID || userID == c.ParticipantID)
}