chore: refresh gramsrv public release

This commit is contained in:
A 2026-06-30 14:37:43 +08:00
parent 75cebe8dbf
commit 70b6820474
1274 changed files with 378751 additions and 59919 deletions

141
internal/domain/phone.go Normal file
View file

@ -0,0 +1,141 @@
package domain
// PhoneCallState 是私聊 1:1 通话信令状态机的服务端状态。
// 状态迁移、TL 视角映射与推送策略见 docs 与 internal/app/phone。
type PhoneCallState string
const (
// PhoneCallStateRequested:requestCall 已受理,已向被叫推 phoneCallRequested。
PhoneCallStateRequested PhoneCallState = "requested"
// PhoneCallStateRinging:至少一台被叫设备上报 receivedCall(主叫据 receive_date 切振铃 UI)。
PhoneCallStateRinging PhoneCallState = "ringing"
// PhoneCallStateAccepted:被叫 acceptCall 已落 g_b,等主叫 confirmCall。
PhoneCallStateAccepted PhoneCallState = "accepted"
// PhoneCallStateConfirmed:主叫 confirmCall 完成密钥交换,通话进行中。
PhoneCallStateConfirmed PhoneCallState = "confirmed"
// PhoneCallStateDiscarded:终态。作为 tombstone 保留一段时间吸收晚到 RPC 后回收。
PhoneCallStateDiscarded PhoneCallState = "discarded"
)
// PhoneCallDiscardReason 是挂断原因,与 TL phoneCallDiscardReason* 一一对应。
type PhoneCallDiscardReason string
const (
PhoneCallDiscardReasonMissed PhoneCallDiscardReason = "missed"
PhoneCallDiscardReasonDisconnect PhoneCallDiscardReason = "disconnect"
PhoneCallDiscardReasonHangup PhoneCallDiscardReason = "hangup"
PhoneCallDiscardReasonBusy PhoneCallDiscardReason = "busy"
// PhoneCallDiscardReasonMigrateConference 是升级为 conference call 的迁移挂断;
// 当前不支持 conference,仅原样回显 reason。
PhoneCallDiscardReasonMigrateConference PhoneCallDiscardReason = "migrate_conference"
)
// PhoneCallProtocol 是 tgcalls 协议协商参数(TL phoneCallProtocol)。
type PhoneCallProtocol struct {
UDPP2P bool
UDPReflector bool
MinLayer int
MaxLayer int
LibraryVersions []string
}
// SessionRef 标识一台具体设备连接(信令定向推送 fast-path 的锚点,允许失效)。
type SessionRef struct {
RawAuthKeyID [8]byte
SessionID int64
}
// Zero 报告锚点是否未记录。
func (s SessionRef) Zero() bool {
return s == SessionRef{}
}
// PhoneCallConnection 是下发给双方的 WebRTC STUN/TURN 服务条目
// (TL phoneConnectionWebrtc)。requestCall 受理时签发,全生命周期稳定。
type PhoneCallConnection struct {
ID int64
IP string
Port int
Username string
Password string
Stun bool
Turn bool
}
// PhoneCallRequest 是 phone.requestCall 受理入参(隐私/拉黑等校验在 rpc 层先行完成)。
type PhoneCallRequest struct {
CalleeID int64
RandomID int64
GAHash []byte
Video bool
Protocol PhoneCallProtocol
CallerDevice SessionRef
// PrivacyP2P 是 phone_p2p 隐私的双向 AND(rpc 层算定;强制 relay 时置 false)。
PrivacyP2P bool
// Connections 是为本通话签发的 STUN/TURN 列表(可空:TURN 未启用时退回
// 纯信令交换 host candidates 的 LAN 直连)。
Connections []PhoneCallConnection
}
// PhoneCall 是一通私聊通话的服务端权威态。密钥材料(GAHash/GB/GA)只存活于
// 进程内 registry,随 tombstone 回收销毁,绝不落任何持久化存储。
type PhoneCall struct {
ID int64
AccessHash int64
// AdminID 是主叫,ParticipantID 是被叫;与 TL phoneCall 字段同名,全生命周期不变。
AdminID int64
ParticipantID int64
Video bool
State PhoneCallState
Date int // requestCall 受理时刻(unix 秒)
ReceiveDate int // 首台被叫设备 receivedCall 时刻;0 表示尚未触达
StartDate int // confirmCall 完成时刻
DiscardedAt int // 进入终态时刻(tombstone GC 依据)
GAHash []byte // 32B,requestCall 携带的承诺
GB []byte // 256B,acceptCall 携带
GA []byte // 256B,confirmCall 揭示(服务端核验 SHA256(GA)==GAHash)
KeyFingerprint int64 // E2E 指纹,服务端无法验证,仅转发
// Protocol 是协商结果(accept 时计算);CallerProtocol/CalleeProtocol 保留原始两份。
Protocol PhoneCallProtocol
CallerProtocol PhoneCallProtocol
CalleeProtocol PhoneCallProtocol
P2PAllowed bool
DiscardReason PhoneCallDiscardReason
Duration int
// PrivacyP2P 与 Connections 自 PhoneCallRequest 原样保留(见其注释)。
PrivacyP2P bool
Connections []PhoneCallConnection
RandomID int64 // 主叫侧幂等去重键的一半(callerID+RandomID)
// 设备锚点:requestCall / acceptCall 的来源设备,仅作定向推送提示。
CallerDevice SessionRef
CalleeDevice SessionRef
}
// Terminal 报告通话是否已进入终态。
func (c PhoneCall) Terminal() bool {
return c.State == PhoneCallStateDiscarded
}
// PeerOf 返回 userID 在本通话中的对端;userID 不是参与者时返回 0。
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 报告 userID 是否为本通话参与者。
func (c PhoneCall) HasParticipant(userID int64) bool {
return userID != 0 && (userID == c.AdminID || userID == c.ParticipantID)
}