68 lines
1.9 KiB
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)
|
||
|
|
}
|