meowcaller

package module
v0.0.0-...-fabd5f9 Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 6 Imported by: 0

README

meowcaller

Go Reference

meowcaller is a Go library for the WhatsApp Web VoIP stack. It is 100% pure GO without any CGO dependencies and little to no dependencies of its own. It includes the proprietary audio codec MLOW written and validated completely in GO.

Discussion

Matrix room: #meowcaller:matrix.org.

Discord channel: #meowcaller in the WhiskeySockets Discord server.

You can find the underlying spec in the WhatsApp Calls Research Group. We are under process of standardizing the spec and moving away from whatsapp-rust source of truth comments.

Usage

The godoc includes docs for all methods.

There's a range of examples in the examples directory.

Features

Core VoIP features are present:

  • Outbound calls
  • Inbound calls
  • Audio calling

Things that are not yet implemented:

  • Opus codec fallback for clients not using MLOW (in progress; testing edge cases)
  • Group calls (WIP)
  • Video calls (WIP)
  • Call signalling features (raise hand, lobby, reactions)

Sponsoring and contribution

You may contribute to the maintenance of this library by sponsoring its maintainers on GitHub.

You may also submit pull requests and issues where relevant, given you follow the contributor Code of Conduct.

License

This repository follows the MIT license, as stated in the LICENSE file

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CallDirection

type CallDirection int

CallDirection is the originating direction of a call.

const (
	CallDirectionOutgoing CallDirection = iota
	CallDirectionIncoming
)

type CallPhase

type CallPhase int

CallPhase is the lifecycle phase of a call.

const (
	CallPhaseIdle CallPhase = iota
	CallPhaseCalling
	CallPhaseRinging
	CallPhaseConnecting
	CallPhaseActive
	CallPhaseEnded
)

type CallRegistry

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

CallRegistry is a thread-safe map of active calls keyed by call-id, each optionally holding the cancel handle for its running media task.

func NewCallRegistry

func NewCallRegistry() *CallRegistry

NewCallRegistry returns an empty registry.

func (*CallRegistry) AbortAll

func (r *CallRegistry) AbortAll() int

AbortAll cancels every call's media task and clears the registry, returning the number cleared. Call on disconnect/reconnect.

func (*CallRegistry) ActiveCount

func (r *CallRegistry) ActiveCount() int

ActiveCount returns the number of registered calls.

func (*CallRegistry) Insert

func (r *CallRegistry) Insert(session *CallSession) bool

Insert registers a new call; returns false if the id already exists.

func (*CallRegistry) Phase

func (r *CallRegistry) Phase(callID string) (CallPhase, bool)

Phase returns the call's current phase, and whether the call is known.

func (*CallRegistry) Remove

func (r *CallRegistry) Remove(callID string) bool

Remove deletes a call, cancelling its media task; true if it existed.

func (*CallRegistry) SetMediaTask

func (r *CallRegistry) SetMediaTask(callID string, cancel context.CancelFunc)

SetMediaTask attaches (or replaces, cancelling the old) the media task's cancel handle for a call. If the call is unknown (e.g. already removed), the handle is cancelled immediately so its task can't outlive the call.

func (*CallRegistry) Snapshot

func (r *CallRegistry) Snapshot(callID string) (CallSession, bool)

Snapshot returns a copy of the call's session, and whether it is known.

func (*CallRegistry) Transition

func (r *CallRegistry) Transition(callID string, next CallPhase) bool

Transition advances a call's phase; false if unknown or the move is illegal.

type CallSession

type CallSession struct {
	CallID      string
	PeerJID     types.JID
	CallCreator types.JID
	Direction   CallDirection
	IsVideo     bool
	// contains filtered or unexported fields
}

CallSession is the per-call signaling state with validated phase transitions.

func NewIncomingSession

func NewIncomingSession(callID string, peerJID, callCreator types.JID, opts ...Option) *CallSession

NewIncomingSession starts an incoming call session in the Ringing phase.

func NewOutgoingSession

func NewOutgoingSession(callID string, peerJID, callCreator types.JID, opts ...Option) *CallSession

NewOutgoingSession starts an outgoing call session in the Idle phase.

func (*CallSession) IsActive

func (s *CallSession) IsActive() bool

IsActive reports whether the call is in the Active phase.

func (*CallSession) IsEnded

func (s *CallSession) IsEnded() bool

IsEnded reports whether the call has ended.

func (*CallSession) Phase

func (s *CallSession) Phase() CallPhase

Phase returns the current lifecycle phase.

func (*CallSession) TransitionTo

func (s *CallSession) TransitionTo(next CallPhase) bool

TransitionTo attempts a phase transition, returning false (no-op) if illegal. Ended is reachable from anything except Ended.

type MediaPipeline

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

MediaPipeline composes the outbound (protect) and inbound (unprotect) E2E 1:1 media path. SFrame is omitted (plain Opus inside WAHKDF SRTP).

func NewMediaPipeline

func NewMediaPipeline(callKey []byte, selfJID, peerJID string, ssrc, samplesPerPacket uint32, opts ...Option) (*MediaPipeline, error)

NewMediaPipeline derives both directions from the 32-byte callKey: send keys from the self LID, recv keys from the peer LID (an interop-load-bearing convention).

func (*MediaPipeline) ProtectAudio

func (p *MediaPipeline) ProtectAudio(opusPayload []byte) ([]byte, error)

ProtectAudio wraps an Opus payload in an RTP WARP header, E2E-SRTP encrypts, and appends the WARP MI tag.

func (*MediaPipeline) UnprotectAudio

func (p *MediaPipeline) UnprotectAudio(packet []byte) (rtp.RtpHeader, []byte, bool)

UnprotectAudio strips the WARP MI tag (not verified), parses the header, and decrypts the payload, guessing the ROC from the recv tracker. ok=false on a malformed packet.

type Option

type Option func(*config)

Option configures optional, non-behavioral aspects of the call/media types — currently the diagnostic logger. The zero configuration logs nothing.

func WithLogger

func WithLogger(l zerolog.Logger) Option

WithLogger sets the zerolog logger for debug/trace diagnostics. The library never configures logging itself; without this option the types are silent at zero cost. Pass the logger from a context, e.g. WithLogger(*zerolog.Ctx(ctx)).

Directories

Path Synopsis
audio
malgo module
cmd
mlowtest command
Command mlowtest encodes raw PCM to an MLow .bin and decodes an MLow .bin back to audio, so you can record from a mic and listen to the reconstruction for quality.
Command mlowtest encodes raw PCM to an MLow .bin and decodes an MLow .bin back to audio, so you can record from a mic and listen to the reconstruction for quality.

Jump to

Keyboard shortcuts

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