yandex

package
v0.0.0-...-9fdb653 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: GPL-3.0 Imports: 43 Imported by: 0

Documentation

Overview

Package yandex: Telemost transport.

Tunnels packets through a Yandex Telemost conference: HTTP join gives the signaling WS URL + room/peer/credentials; WS carries SDP/ICE; two WebRTC PeerConnections (Publisher + Subscriber) carry the actual bytes inside VP8 video frames built by CanvasVideoGenerator/Decoder.

Index

Constants

This section is empty.

Variables

View Source
var (
	H264SPS = buildH264SPS()
	H264PPS = buildH264PPS()
)

H264SPS and H264PPS are built once: every participant publishing H264 through this transport uses the exact same fixed parameters, so there is nothing participant-specific to compute per instance.

View Source
var ErrCaptchaRequired = errors.New("yandex docs: captcha required")

ErrCaptchaRequired signals that the transport hit a SmartCaptcha challenge (showcaptcha?cc=1) which cannot be solved by the internal PoW solver. The caller is expected to obtain fresh cookies out of band (e.g. WebView on the client) and hand them over via CookieExchanger.ApplyCookies.

View Source
var ErrLoginRequired = errors.New("yandex docs: login required")

ErrLoginRequired signals a redirect to the passport login page. The document is not public from this IP / account.

Functions

func BoardsModifyObjects

func BoardsModifyObjects(b64, objID string, x, y int, creator, participant string) []byte

BoardsModifyObjects is the JSON of the dashboard event buildModifyObjects makes: ["dashboard", {...}], as it goes on the wire after the "42<ack>" prefix.

func BuildSaveChanges

func BuildSaveChanges(userID string, isExcel bool, seq int) []byte

BuildSaveChanges is the saveChanges message for one participant and iteration (see buildSaveChanges for how the pieces are chosen). A pure function of its arguments, exported so the JS port of this transport can be compared with it byte for byte.

func ExtractBase64

func ExtractBase64(response string) string

ExtractBase64 pulls the packet payload out of a server frame: from a saveChanges message's excelAdditionalInfo, otherwise from a cursor field. Pure, and exported so the JS port can be compared with it.

func FragmentFrame

func FragmentFrame(wire []byte) ([][]byte, error)

FragmentFrame splits one complete wire-v2 batch frame into bodies that each fit inside a single VP8 frame. A frame that already fits is returned as a single fragment rather than being passed through, so both ends agree on the format unconditionally and there is no "small frames use a different shape" branch to get wrong.

func ModifyObjectsPayloads

func ModifyObjectsPayloads(raw json.RawMessage, myPart, myUser, myName string) (payloads [][]byte, toDelete []map[string]interface{})

ModifyObjectsPayloads reads a (server-)modify-objects event: the packets carried by objects that are not our own echo (decoded, in order), and the drop-objects entries that delete exactly those objects from the board. Pure, and exported so the JS port can be compared with it.

func SetChromeLike

func SetChromeLike(enabled bool)

SetChromeLike toggles Chrome-like TLS (utls) and browser headers for the whole Yandex Docs access path (redirect-hop GETs, captcha solving, and the WebSocket handshake). Defaults to true (standalone server behavior). Embedded/mobile binaries should call this with false during initialization: plain net/http rendezvous is what mobile deployments are validated against, and Chrome emulation from residential IPs can trigger SmartCaptcha or handshake paths the mobile stack never exercised.

Types

type AudioFrameDecoder

type AudioFrameDecoder struct{}

AudioFrameDecoder extracts what an AudioFrameGenerator embedded.

func NewAudioFrameDecoder

func NewAudioFrameDecoder() *AudioFrameDecoder

func (*AudioFrameDecoder) DecodeFrame

func (d *AudioFrameDecoder) DecodeFrame(frameData []byte) ([]byte, error)

type AudioFrameGenerator

type AudioFrameGenerator struct{}

AudioFrameGenerator wraps one already-fragmented wire chunk (see fragment.go - the same FragmentFrame/frameReassembler pair the video carriers use) as a fake Opus packet.

func (*AudioFrameGenerator) GenerateFrame

func (g *AudioFrameGenerator) GenerateFrame(data []byte) []byte

type BoardsTransport

type BoardsTransport struct {
	*transport.BaseTransport
	// contains filtered or unexported fields
}

func NewBoardsTransport

func NewBoardsTransport(rawURL string, config transport.TransportConfig) *BoardsTransport

func (*BoardsTransport) ApplyCookies

func (t *BoardsTransport) ApplyCookies(values map[string]string) error

ApplyCookies replaces the transport's cookie jar and forces the current WS session to reconnect.

func (*BoardsTransport) FetchCookies

func (t *BoardsTransport) FetchCookies() (map[string]string, error)

FetchCookies returns a snapshot of the transport's current cookie jar as name -> value for boards.yandex.ru.

func (*BoardsTransport) IsConnected

func (t *BoardsTransport) IsConnected() bool

func (*BoardsTransport) Receive

func (t *BoardsTransport) Receive(cb func([]byte))

func (*BoardsTransport) Send

func (t *BoardsTransport) Send(data []byte) error

func (*BoardsTransport) SetErrorNotifier

func (t *BoardsTransport) SetErrorNotifier(fn func(err error, transportName, url, html, reason string))

SetErrorNotifier installs a callback for out-of-band errors. Called once by the manager. Boards currently never returns sentinel errors from fetchDocInfo (its captcha path is the old showcaptchafast, which the internal PoW solver handles), but the hook is wired for parity with the other transports.

func (*BoardsTransport) Start

func (t *BoardsTransport) Start() error

func (*BoardsTransport) Stop

func (t *BoardsTransport) Stop() error

type CanvasVideoDecoder

type CanvasVideoDecoder struct {
	// contains filtered or unexported fields
}

CanvasVideoDecoder extracts encapsulated data from VP8 keyframes.

func NewCanvasVideoDecoder

func NewCanvasVideoDecoder(width, height int) *CanvasVideoDecoder

func (*CanvasVideoDecoder) DecodeFrame

func (d *CanvasVideoDecoder) DecodeFrame(frameData []byte) ([]byte, error)

type CanvasVideoGenerator

type CanvasVideoGenerator struct {
	// contains filtered or unexported fields
}

CanvasVideoGenerator generates valid VP8 keyframes with encapsulated data.

func NewCanvasVideoGenerator

func NewCanvasVideoGenerator(track *webrtc.TrackLocalStaticSample, width, height, fps int) *CanvasVideoGenerator

func (*CanvasVideoGenerator) GenerateKeyFrame

func (g *CanvasVideoGenerator) GenerateKeyFrame(data []byte) []byte

GenerateKeyFrame is exposed so callers can build a single fake-VP8 keyframe directly (e.g. to send it as one RTP packet). GenerateKeyFrame создаёт fake-VP8 keyframe, точно как браузер Telemost:

90 e0 80 01 14 00   VP8 Payload Descriptor (6 байт)
d0 4f 00            Keyframe tag
9d 01 2a            Sync code
c8 00 56 01         Width, Height
...body...          [len:4 BE][payload]

func (*CanvasVideoGenerator) SendData

func (g *CanvasVideoGenerator) SendData(data []byte) error

func (*CanvasVideoGenerator) Start

func (g *CanvasVideoGenerator) Start()

func (*CanvasVideoGenerator) Stop

func (g *CanvasVideoGenerator) Stop()

type DocSession

type DocSession struct {
	Info       YandexDocsInfo
	Conn       *websocket.Conn
	WriteQueue chan []byte
	UserID     string
	// contains filtered or unexported fields
}

type H264FrameDecoder

type H264FrameDecoder struct{}

H264FrameDecoder extracts what an H264FrameGenerator embedded.

func NewH264FrameDecoder

func NewH264FrameDecoder() *H264FrameDecoder

func (*H264FrameDecoder) DecodeFrame

func (d *H264FrameDecoder) DecodeFrame(frameData []byte) ([]byte, error)

type H264FrameGenerator

type H264FrameGenerator struct{}

H264FrameGenerator wraps one already-fragmented wire chunk (fragment.go) as a fake H264 IDR slice NAL unit.

func (*H264FrameGenerator) GenerateKeyFrame

func (g *H264FrameGenerator) GenerateKeyFrame(data []byte) []byte

type TelemostConnectionResponse

type TelemostConnectionResponse struct {
	ConnectionType      string                 `json:"connection_type"`
	URI                 string                 `json:"uri"`
	RoomID              string                 `json:"room_id"`
	SafeRoomID          string                 `json:"safe_room_id"`
	PeerID              string                 `json:"peer_id"`
	ClientConfiguration map[string]interface{} `json:"client_configuration"`
	ConferenceState     map[string]interface{} `json:"conference_state"`
	MediaPlatform       string                 `json:"media_platform"`
	SessionID           string                 `json:"session_id"`
	PeerSessionID       string                 `json:"peer_session_id"`
	Credentials         string                 `json:"credentials"`
	WSURI               string                 `json:"ws_uri"`
}

type TelemostGroup

type TelemostGroup struct {
	// contains filtered or unexported fields
}

TelemostGroup is the set of lanes (participants) one node runs in a room.

func NewTelemostGroup

func NewTelemostGroup(cookies, conferenceURL string, n int, isExitNode bool, config transport.TransportConfig) *TelemostGroup

NewTelemostGroup creates n lanes joined to the same conference. The group is also a transport.LaneSource, so the stripe can grow it later.

func (*TelemostGroup) Lanes

func (g *TelemostGroup) Lanes() []transport.Transport

Lanes returns the lanes created so far.

func (*TelemostGroup) NewLane

func (g *TelemostGroup) NewLane() transport.Transport

NewLane implements transport.LaneSource.

func (*TelemostGroup) SetGrowHook

func (g *TelemostGroup) SetGrowHook(f func())

SetGrowHook implements transport.LaneSource.

func (*TelemostGroup) Watching

func (g *TelemostGroup) Watching() []string

Watching lists the peer lanes our lanes are currently subscribed to.

type TelemostHello

type TelemostHello struct {
	UID   string            `json:"uid"`
	Hello TelemostHelloData `json:"hello"`
}

type TelemostHelloData

type TelemostHelloData struct {
	RoomID                 string                 `json:"roomId"`
	ParticipantID          string                 `json:"participantId"`
	Credentials            string                 `json:"credentials"`
	ServiceName            string                 `json:"serviceName"`
	SendAudio              bool                   `json:"sendAudio"`
	SendVideo              bool                   `json:"sendVideo"`
	SendSharing            bool                   `json:"sendSharing"`
	DisablePublisher       bool                   `json:"disablePublisher"`
	DisableSubscriber      bool                   `json:"disableSubscriber"`
	DisableSubscriberAudio bool                   `json:"disableSubscriberAudio"`
	ParticipantAttributes  map[string]interface{} `json:"participantAttributes"`
	ParticipantMeta        map[string]interface{} `json:"participantMeta"`
	SDKInfo                map[string]interface{} `json:"sdkInfo"`
	SDKInitializationID    string                 `json:"sdkInitializationId"`
	CapabilitiesOffer      map[string]interface{} `json:"capabilitiesOffer"`
}

type TelemostTrack

type TelemostTrack struct {
	// contains filtered or unexported fields
}

TelemostTrack implements webrtc.TrackLocal with byte-level control over the outgoing RTP header.

func NewTelemostTrack

func NewTelemostTrack(codec webrtc.RTPCodecCapability, kind webrtc.RTPCodecType, id, streamID string) *TelemostTrack

NewTelemostTrack builds an unbound track of the given kind (video or audio - see canvas_audio.go for the audio carrier this enables).

func (*TelemostTrack) Bind

Bind is called by Pion once the answer picked a codec. We remember the write stream and the negotiated SSRC/PT, and publish the codec back so Pion's SDP contains the matching a=ssrc lines.

func (*TelemostTrack) CNAME

func (t *TelemostTrack) CNAME() string

CNAME is the RTCP SDES canonical name a browser advertises for its stream.

func (*TelemostTrack) ID

func (t *TelemostTrack) ID() string

func (*TelemostTrack) Kind

func (t *TelemostTrack) Kind() webrtc.RTPCodecType

func (*TelemostTrack) PayloadType

func (t *TelemostTrack) PayloadType() webrtc.PayloadType

PayloadType returns the payload type Pion negotiated, or 0 before Bind.

func (*TelemostTrack) Probe

func (t *TelemostTrack) Probe() bool

Probe writes a single empty packet and reports whether the SRTP stream is live. Pion drops writes silently before DTLS completes, so a zero-length result means "not ready yet" rather than "sent".

func (*TelemostTrack) RID

func (t *TelemostTrack) RID() string

func (*TelemostTrack) SSRC

func (t *TelemostTrack) SSRC() webrtc.SSRC

SSRC returns the SSRC Pion negotiated for this track, or 0 before Bind.

func (*TelemostTrack) SenderReport

func (t *TelemostTrack) SenderReport() *rtcp.SenderReport

SenderReport builds the periodic RTCP SR every browser sends. The SFU uses it to bind the SSRC to a stream and to measure our send rate.

func (*TelemostTrack) StreamID

func (t *TelemostTrack) StreamID() string

func (*TelemostTrack) Unbind

Unbind drops the binding Pion is tearing down.

func (*TelemostTrack) WaitBound

func (t *TelemostTrack) WaitBound(d time.Duration) bool

WaitBound blocks until Pion has called Bind, i.e. until the answer selected a codec for this track.

func (*TelemostTrack) WriteHeader

func (t *TelemostTrack) WriteHeader(hdr rtp.Header, payload []byte) (int, error)

WriteHeader writes one RTP packet with the header exactly as given. SSRC and payload type in hdr are used as-is; nothing rewrites them.

Pion's srtpWriterFuture returns (0, nil) when DTLS has not finished yet, so the returned byte count is also our readiness signal.

type TelemostTransport

type TelemostTransport struct {
	*transport.BaseTransport
	// contains filtered or unexported fields
}

TelemostTransport carries OpenFlux packets over a Yandex Telemost conference using VP8 keyframes as the wire format.

func NewTelemostTransport

func NewTelemostTransport(cookies, conferenceURL string, isExitNode bool, config transport.TransportConfig) *TelemostTransport

func (*TelemostTransport) LaneID

func (t *TelemostTransport) LaneID() string

LaneID is this lane's participant id in the room.

func (*TelemostTransport) Send

func (t *TelemostTransport) Send(data []byte) error

func (*TelemostTransport) SetFrameSource

func (t *TelemostTransport) SetFrameSource(src func(max int) [][]byte)

SetFrameSource implements transport.FramePuller: every tick of the publish clock takes up to max frames from src, after anything queued by Send.

func (*TelemostTransport) Start

func (t *TelemostTransport) Start() error

func (*TelemostTransport) Stats

func (*TelemostTransport) Stop

func (t *TelemostTransport) Stop() error

func (*TelemostTransport) UplinkLoss

func (t *TelemostTransport) UplinkLoss() float64

UplinkLoss is the fraction of our published packets the SFU reported lost in its latest Receiver Report.

type TelemostUpdateMe

type TelemostUpdateMe struct {
	UID      string                 `json:"uid"`
	UpdateMe map[string]interface{} `json:"updateMe"`
}

type VP9FrameDecoder

type VP9FrameDecoder struct{}

VP9FrameDecoder extracts the data a VP9FrameGenerator embedded.

func NewVP9FrameDecoder

func NewVP9FrameDecoder() *VP9FrameDecoder

func (*VP9FrameDecoder) DecodeFrame

func (d *VP9FrameDecoder) DecodeFrame(frameData []byte) ([]byte, error)

DecodeFrame locates our sync code and reads the [len:4][data] that follows the fixed-size tail after it, the VP9 counterpart of CanvasVideoDecoder.DecodeFrame. Scanning for the sync code rather than assuming the descriptor is always exactly 1 byte keeps this tolerant of a PictureID or other extension the descriptor might carry, same as the VP8 decoder locating its own sync code rather than trusting a fixed offset.

type VP9FrameGenerator

type VP9FrameGenerator struct{}

VP9FrameGenerator builds fake VP9 keyframes carrying tunnel data, the VP9 counterpart of CanvasVideoGenerator.

func (*VP9FrameGenerator) GenerateKeyFrame

func (g *VP9FrameGenerator) GenerateKeyFrame(data []byte) []byte

GenerateKeyFrame wraps data in a VP9 RTP payload descriptor plus a fake profile-0 key frame bitstream header, with data embedded as [len:4 BE][data] where VP9's compressed frame payload would be.

type VolgaConfig

type VolgaConfig struct {
	MaxIdleConnsPerHost int
	MaxIdleConns        int
	IdleConnTimeout     time.Duration
	RelayTimeout        time.Duration

	WorkerCount int
	QueueSize   int

	BatchSize     int
	BatchTimeout  time.Duration
	BatchMaxBytes int

	MaxPayloadBytes int
	MinPayloadBytes int

	ReconnectMinDelay   time.Duration
	ReconnectMaxDelay   time.Duration
	ReconnectMultiplier float64

	WSHandshakeTimeout time.Duration
	WSReadTimeout      time.Duration
	KeepAliveInterval  time.Duration
	// MaxSessionAge rotates the WebSocket (and its authorization) even
	// while it looks healthy; 0 disables rotation.
	MaxSessionAge time.Duration

	// WebSocket buffers. Large ones help a server; a phone's VPN process
	// (iOS caps it at 50 MB) cannot afford them.
	WSReadBufferSize  int
	WSWriteBufferSize int
	// Network the relay and listener dial through (TransportConfig.Network).
	Network string
}

func DefaultVolgaConfig

func DefaultVolgaConfig() VolgaConfig

func SlimVolgaConfig

func SlimVolgaConfig() VolgaConfig

SlimVolgaConfig is the memory-constrained profile for phones, above all the iOS Network Extension (50 MB for the whole process): a small relay worker pool and queue, smaller batches and WebSocket buffers. The wire format is the same, so it talks to a node on the default profile.

type VolgaDocument

type VolgaDocument struct {
	DocID    string
	Editable bool
}

VolgaDocument is what CheckVolgaDocument learned about a document.

func CheckVolgaDocument

func CheckVolgaDocument(docURL string, jar http.CookieJar) (VolgaDocument, error)

CheckVolgaDocument runs the transport's own authorization against docURL without joining the document, to tell whether the vyandex transport can use it: the page must be the Volga editor and, for an anonymous visitor (jar nil or empty), editable by anyone with the link. The first-tier PoW captcha is solved like on a real connect; a SmartCaptcha or login wall comes back as ErrCaptchaRequired / ErrLoginRequired.

type VolgaStats

type VolgaStats struct {
	PacketsSent atomic.Uint64
	PacketsRecv atomic.Uint64
	// User packets only (not the 1-byte keepalives): what the stall
	// detector compares.
	DataPacketsQueued atomic.Uint64
	DataPacketsRecv   atomic.Uint64
	BytesSent         atomic.Uint64
	BytesReceived     atomic.Uint64
	HTTPReqsSent      atomic.Uint64
	HTTPReqsFailed    atomic.Uint64
	WSReconnects      atomic.Uint64
	QueueDrops        atomic.Uint64
	WorkerBusy        atomic.Int64
	BatchesSent       atomic.Uint64
	PacketsBatched    atomic.Uint64
}

type YandexDocsInfo

type YandexDocsInfo struct {
	CookieStr    string
	Token        string
	DocID        string
	CallbackURL  string
	UserID       string
	EditorUserID string // editor_config.user.id: настоящий id участника в документе
	IsExcel      bool   // editor_config.document.fileType ∈ {xlsx,xls,xlsm,csv}
	Origin       string
	Host         string
	WsURL        string
	Permissions  map[string]interface{}
	OpenCmd      map[string]interface{}
}

type YandexDocsTransport

type YandexDocsTransport struct {
	*transport.BaseTransport
	// contains filtered or unexported fields
}

func NewYandexDocsTransport

func NewYandexDocsTransport(url string, config transport.TransportConfig) *YandexDocsTransport

func (*YandexDocsTransport) ApplyCookies

func (t *YandexDocsTransport) ApplyCookies(values map[string]string) error

ApplyCookies replaces the transport's cookie jar with the provided values and forces the current session to reconnect so the next fetchDocInfo uses the new cookies. It is idempotent.

func (*YandexDocsTransport) FetchCookies

func (t *YandexDocsTransport) FetchCookies() (map[string]string, error)

FetchCookies returns a snapshot of the transport's current cookie jar as name -> value. Used by the exit node to answer a SubtypeCookiesRequest.

func (*YandexDocsTransport) Send

func (t *YandexDocsTransport) Send(data []byte) error

func (*YandexDocsTransport) SetErrorNotifier

func (t *YandexDocsTransport) SetErrorNotifier(fn func(err error, transportName, url, html, reason string))

SetErrorNotifier installs a callback for out-of-band errors such as ErrCaptchaRequired or ErrLoginRequired. Called once by the manager.

func (*YandexDocsTransport) Start

func (t *YandexDocsTransport) Start() error

func (*YandexDocsTransport) Stop

func (t *YandexDocsTransport) Stop() error

Stop also closes the document connection. Otherwise the reader sits in ReadMessage until the server's next message and then leaves the socket open, keeping a participant attached to the document after the transport is gone.

type YandexVolgaTransport

type YandexVolgaTransport struct {
	*transport.BaseTransport
	// contains filtered or unexported fields
}

func NewYandexVolgaTransport

func NewYandexVolgaTransport(docURL string, cfg transport.TransportConfig) *YandexVolgaTransport

func NewYandexVolgaTransportWithConfig

func NewYandexVolgaTransportWithConfig(docURL string, cfg transport.TransportConfig, volga VolgaConfig) *YandexVolgaTransport

NewYandexVolgaTransportWithConfig is NewYandexVolgaTransport with a resource profile, e.g. SlimVolgaConfig on a phone.

func (*YandexVolgaTransport) ApplyCookies

func (t *YandexVolgaTransport) ApplyCookies(values map[string]string) error

ApplyCookies replaces the transport's cookie jar, updates the live auth's Cookies slice, and forces the current sessions to reconnect.

func (*YandexVolgaTransport) FetchCookies

func (t *YandexVolgaTransport) FetchCookies() (map[string]string, error)

FetchCookies returns a snapshot of the transport's current cookie jar as name -> value for the current document host.

func (*YandexVolgaTransport) IsConnected

func (t *YandexVolgaTransport) IsConnected() bool

func (*YandexVolgaTransport) LoadCookieFile

func (t *YandexVolgaTransport) LoadCookieFile(path string) error

jar returns the transport's shared cookie jar (never nil). LoadCookieFile imports a Netscape cookies.txt (yandex.ru cookies only) into the transport's cookie jar, so it opens the document signed in.

func (*YandexVolgaTransport) Receive

func (t *YandexVolgaTransport) Receive(callback func([]byte))

func (*YandexVolgaTransport) Send

func (t *YandexVolgaTransport) Send(data []byte) error

func (*YandexVolgaTransport) SetErrorNotifier

func (t *YandexVolgaTransport) SetErrorNotifier(fn func(err error, transportName, url, html, reason string))

SetErrorNotifier installs a callback for out-of-band errors such as ErrCaptchaRequired or ErrLoginRequired. Called once by the manager.

func (*YandexVolgaTransport) Start

func (t *YandexVolgaTransport) Start() error

func (*YandexVolgaTransport) Stats

func (*YandexVolgaTransport) Stop

func (t *YandexVolgaTransport) Stop() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址