From 445e71e0751cb0be62530ce40125dc1560247a52 Mon Sep 17 00:00:00 2001 From: Dan <31395415+cakedan@users.noreply.github.com> Date: Fri, 15 Jun 2018 11:52:06 -0400 Subject: [PATCH] replaced channel with client in VoiceData and VoiceSpeaking events Also changed some voice sending stuff --- disco/voice/client.py | 24 ++++++++----------- disco/voice/udp.py | 54 +++++++++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/disco/voice/client.py b/disco/voice/client.py index 1bf5aa0..79e3cdd 100644 --- a/disco/voice/client.py +++ b/disco/voice/client.py @@ -33,19 +33,12 @@ VoiceState = Enum( VOICE_CONNECTED=8, ) - -class VoiceSpeaking(namedtuple('VoiceSpeaking', ['user_id', 'speaking', 'soundshare'])): - """ - Voice Speaking Event - Attributes - --------- - user_id : snowflake - the id of the user - speaking : bool - if they are speaking - soundshare : bool - if they are using soundshare - """ +VoiceSpeaking = namedtuple('VoiceSpeaking', [ + 'client', + 'user_id', + 'speaking', + 'soundshare', +]) class VoiceException(Exception): @@ -259,9 +252,10 @@ class VoiceClient(LoggingClass): self.audio_ssrcs[data['ssrc']] = data['user_id'] payload = VoiceSpeaking( + client=self, user_id=data['user_id'], - speaking=(data['speaking'] & SpeakingCodes.VOICE.value), - soundshare=(data['speaking'] & SpeakingCodes.SOUNDSHARE.value), + speaking=bool(data['speaking'] & SpeakingCodes.VOICE.value), + soundshare=bool(data['speaking'] & SpeakingCodes.SOUNDSHARE.value), ) self.client.gw.events.emit('VoiceSpeaking', payload) diff --git a/disco/voice/udp.py b/disco/voice/udp.py index 6b7015e..bcf50fe 100644 --- a/disco/voice/udp.py +++ b/disco/voice/udp.py @@ -36,11 +36,11 @@ RTPHeader = namedtuple('RTPHeader', [ ]) VoiceData = namedtuple('VoiceData', [ - 'data', + 'client', 'user_id', 'payload_type', - 'channel', 'rtp', + 'data', ]) @@ -66,9 +66,9 @@ class UDPVoiceClient(LoggingClass): self._secret_box = None # Buffer used for encoding/sending frames - self._buffer = bytearray(24) - self._buffer[0] = 2 << 6 # Only RTP Version set in the first byte of the header, 0x80 - self._buffer[1] = PayloadTypes.OPUS.value + self._header = bytearray(12) + self._header[0] = 2 << 6 # Only RTP Version set in the first byte of the header, 0x80 + self._header[1] = PayloadTypes.OPUS.value def increment_timestamp(self, by): self.timestamp += by @@ -83,27 +83,40 @@ class UDPVoiceClient(LoggingClass): frame = bytearray(frame) # Pack the rtc header into our buffer - struct.pack_into('>H', self._buffer, 2, sequence or self.sequence) - struct.pack_into('>I', self._buffer, 4, timestamp or self.timestamp) - struct.pack_into('>i', self._buffer, 8, self.vc.ssrc) + struct.pack_into('>H', self._header, 2, sequence or self.sequence) + struct.pack_into('>I', self._header, 4, timestamp or self.timestamp) + struct.pack_into('>i', self._header, 8, self.vc.ssrc) if self.vc.mode == 'xsalsa20_poly1305_lite': + # Use an incrementing number as a nonce, only first 4 bytes of the nonce is padded on self._nonce += 1 if self._nonce > MAX_UINT32: self._nonce = 0 nonce = bytearray(24) struct.pack_into('>I', nonce, 0, self._nonce) - raw = self._secret_box.encrypt(bytes(frame), nonce).ciphertext + nonce[:4] + nonce_padding = nonce[:4] elif self.vc.mode == 'xsalsa20_poly1305_suffix': + # Generate a nonce nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) - raw = self._secret_box.encrypt(bytes(frame), nonce).ciphertext + nonce + nonce_padding = nonce + elif self.vc.mode == 'xsalsa20_poly1305': + # Nonce is the header + nonce = bytearray(24) + nonce[:12] = self._header + nonce_padding = None else: - # Now encrypt the payload with the nonce as a header - raw = self._secret_box.encrypt(bytes(frame), bytes(self._buffer)).ciphertext + raise Exception('The voice mode, {}, isn\'t supported.'.format(self.vc.mode)) + + # Encrypt the payload with the nonce + raw = self._secret_box.encrypt(bytes(frame), bytes(nonce)).ciphertext + + # Pad the payload with the nonce, if applicable + if nonce_padding: + raw += nonce_padding # Send the header (sans nonce padding) plus the payload - self.send(self._buffer[:12] + raw) + self.send(self._header + raw) # Increment our sequence counter self.sequence += 1 @@ -153,8 +166,10 @@ class UDPVoiceClient(LoggingClass): elif self.vc.mode == 'xsalsa20_poly1305_suffx': nonce[:24] = data[-24:] data = data[:-24] - else: + elif self.vc.mode == 'xsalsa20_poly1305': nonce[:12] = data[:12] + else: + continue try: data = self._secret_box.decrypt(bytes(data[12:]), bytes(nonce)) @@ -163,7 +178,7 @@ class UDPVoiceClient(LoggingClass): # RFC3550 Section 5.1 (Padding) if rtp.padding: - padding_amount = data[:-1] + padding_amount, = struct.unpack_from('>B', data[:-1]) data = data[-padding_amount:] if rtp.extension: @@ -172,7 +187,7 @@ class UDPVoiceClient(LoggingClass): if rtp_extension_header == RTP_HEADER_ONE_BYTE: data = data[2:] - fields_amount, = struct.unpack_from('>H', data[:2]) + fields_amount, = struct.unpack_from('>H', data) fields = [] offset = 4 @@ -204,13 +219,12 @@ class UDPVoiceClient(LoggingClass): if rtp.marker: continue - user_id = self.vc.audio_ssrcs.get(rtp.ssrc, None) payload = VoiceData( - data=data, + client=self.vc, payload_type=payload_type.name, - user_id=user_id, - channel=self.vc.channel, + user_id=self.vc.audio_ssrcs.get(rtp.ssrc, None), rtp=rtp, + data=data, ) self.vc.client.gw.events.emit('VoiceData', payload)