Files
go-ts/internal/client/voice.go

68 lines
1.9 KiB
Go

package client
import (
"encoding/binary"
"log"
"go-ts/pkg/protocol"
)
func (c *Client) handleVoice(pkt *protocol.Packet) {
// Parse Voice Header (Server -> Client)
// VID(2) + CID(2) + Codec(1) + Data
if len(pkt.Data) < 5 {
return
}
vid := binary.BigEndian.Uint16(pkt.Data[0:2])
// cid := binary.BigEndian.Uint16(pkt.Data[2:4]) // Talking client ID (not needed for echo)
codec := pkt.Data[4]
voiceData := pkt.Data[5:]
log.Printf("Voice Packet received. VID=%d, Codec=%d, Size=%d", vid, codec, len(voiceData))
// Build echo packet (Client -> Server)
// Format: VID(2) + Codec(1) + Data
echoData := make([]byte, 2+1+len(voiceData))
binary.BigEndian.PutUint16(echoData[0:2], vid)
echoData[2] = codec
copy(echoData[3:], voiceData)
echoPkt := protocol.NewPacket(protocol.PacketTypeVoice, echoData)
echoPkt.Header.PacketID = pkt.Header.PacketID // Use same ID for voice
echoPkt.Header.ClientID = c.ClientID
// Encrypt voice packet with SharedSecret
if c.Handshake != nil && len(c.Handshake.SharedIV) > 0 {
crypto := &protocol.CryptoState{
SharedIV: c.Handshake.SharedIV,
SharedMac: c.Handshake.SharedMac,
GenerationID: 0,
}
key, nonce := crypto.GenerateKeyNonce(&echoPkt.Header, true)
// Meta for Client->Server: PID(2) + CID(2) + PT(1)
meta := make([]byte, 5)
binary.BigEndian.PutUint16(meta[0:2], echoPkt.Header.PacketID)
binary.BigEndian.PutUint16(meta[2:4], echoPkt.Header.ClientID)
meta[4] = echoPkt.Header.Type
encData, mac, err := protocol.EncryptEAX(key, nonce, meta, echoPkt.Data)
if err != nil {
log.Printf("Voice encryption failed: %v", err)
return
}
echoPkt.Data = encData
copy(echoPkt.Header.MAC[:], mac)
} else {
// If no encryption keys, use SharedMac if available, otherwise HandshakeMac
if c.Handshake != nil && len(c.Handshake.SharedMac) > 0 {
copy(echoPkt.Header.MAC[:], c.Handshake.SharedMac)
} else {
echoPkt.Header.MAC = protocol.HandshakeMac
}
}
c.Conn.SendPacket(echoPkt)
}