qcc/internal/protocol/media.go
Niko Marmeladkov fc0caf13ef
Initial commit: QuiC Call server
- PoW (Hashcash) authentication
- X.509 CA for phone number certificates (+0 XXX YYY ZZZ)
- QUIC transport (hysteria quic-go fork) with ACME TLS
- Custom append-only DB engine (from NikoGram)
- Call signaling (dial/ring/accept/reject/end)
- E2EE media relay (X25519 + ChaCha20-Poly1305)
- Brutal congestion control (from hysteria)
- Media datagram relay (Opus/VP9/H264/H265)
- Graceful shutdown
2026-06-30 12:38:34 +03:00

82 lines
1.8 KiB
Go

package protocol
import (
"encoding/binary"
"io"
"github.com/niko/qcc/pkg/types"
)
const MediaHeaderSize = 8 + 4 + 1 + 1 + 4
type MediaPacket struct {
CallID uint64
SeqNum uint32
Codec types.CodecType
Flags types.MediaFlags
Timestamp uint32
Payload []byte
}
func MarshalMediaPacket(pkt *MediaPacket) []byte {
size := MediaHeaderSize + len(pkt.Payload)
buf := make([]byte, size)
off := 0
binary.BigEndian.PutUint64(buf[off:], pkt.CallID)
off += 8
binary.LittleEndian.PutUint32(buf[off:], pkt.SeqNum)
off += 4
buf[off] = byte(pkt.Codec)
off++
buf[off] = byte(pkt.Flags)
off++
binary.BigEndian.PutUint32(buf[off:], pkt.Timestamp)
off += 4
copy(buf[off:], pkt.Payload)
return buf
}
func UnmarshalMediaPacket(data []byte) (*MediaPacket, bool) {
if len(data) < MediaHeaderSize {
return nil, false
}
pkt := &MediaPacket{}
off := 0
pkt.CallID = binary.BigEndian.Uint64(data[off:])
off += 8
pkt.SeqNum = binary.LittleEndian.Uint32(data[off:])
off += 4
pkt.Codec = types.CodecType(data[off])
off++
pkt.Flags = types.MediaFlags(data[off])
off++
pkt.Timestamp = binary.BigEndian.Uint32(data[off:])
off += 4
pkt.Payload = make([]byte, len(data)-off)
copy(pkt.Payload, data[off:])
return pkt, true
}
func ReadMediaPacket(r io.Reader) (*MediaPacket, error) {
header := make([]byte, MediaHeaderSize)
if _, err := io.ReadFull(r, header); err != nil {
return nil, err
}
pkt := &MediaPacket{}
off := 0
pkt.CallID = binary.BigEndian.Uint64(header[off:])
off += 8
pkt.SeqNum = binary.LittleEndian.Uint32(header[off:])
off += 4
pkt.Codec = types.CodecType(header[off])
off++
pkt.Flags = types.MediaFlags(header[off])
off++
pkt.Timestamp = binary.BigEndian.Uint32(header[off:])
payload, err := io.ReadAll(r)
if err != nil {
return nil, err
}
pkt.Payload = payload
return pkt, nil
}