Class: Discordrb::Voice::VoiceUDP

Inherits:
Object
  • Object
show all
Defined in:
lib/discordrb/voice/network.rb

Overview

Represents a UDP connection to a voice server. This connection is used to send the actual audio data.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeVoiceUDP

Creates a new UDP connection. Only creates a socket as the discovery reply may come before the data is initialized.



52
53
54
55
# File 'lib/discordrb/voice/network.rb', line 52

def initialize
  @socket = UDPSocket.new
  @encrypted = true
end

Instance Attribute Details

#encryptedtrue, false Also known as: encrypted?

Deprecated.

Discord no longer supports unencrypted voice communication.

Returns whether or not UDP communications are encrypted.

Returns:

  • (true, false)

    whether or not UDP communications are encrypted.



38
39
40
# File 'lib/discordrb/voice/network.rb', line 38

def encrypted
  @encrypted
end

#modeObject

The UDP encryption mode



45
46
47
# File 'lib/discordrb/voice/network.rb', line 45

def mode
  @mode
end

#secret_key=(value) ⇒ Object (writeonly)

Sets the secret key used for encryption



42
43
44
# File 'lib/discordrb/voice/network.rb', line 42

def secret_key=(value)
  @secret_key = value
end

Instance Method Details

#connect(ip, port, ssrc) ⇒ Object

Initializes the UDP socket with data obtained from opcode 2.

Parameters:

  • ip (String)

    The IP address to connect to.

  • port (Integer)

    The port to connect to.

  • ssrc (Integer)

    The Super Secret Relay Code (SSRC). Discord uses this to identify different voice users on the same endpoint.



62
63
64
65
66
# File 'lib/discordrb/voice/network.rb', line 62

def connect(ip, port, ssrc)
  @ip = ip
  @port = port
  @ssrc = ssrc
end

#receive_discovery_replyArray(String, Integer)

Waits for a UDP discovery reply, and returns the sent data.

Returns:

  • (Array(String, Integer))

    the IP and port received from the discovery reply.



70
71
72
73
74
75
76
# File 'lib/discordrb/voice/network.rb', line 70

def receive_discovery_reply
  # Wait for a UDP message
  message = @socket.recv(74)
  ip = message[8..-3].delete("\0")
  port = message[-2..].unpack1('n')
  [ip, port]
end

#send_audio(buf, sequence, time) ⇒ Object

Makes an audio packet from a buffer and sends it to Discord.

Parameters:

  • buf (String)

    The audio data to send, must be exactly one Opus frame

  • sequence (Integer)

    The packet sequence number, incremented by one for subsequent packets

  • time (Integer)

    When this packet should be played back, in no particular unit (essentially just the sequence number multiplied by 960)



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/discordrb/voice/network.rb', line 83

def send_audio(buf, sequence, time)
  # Header of the audio packet
  header = [0x80, 0x78, sequence, time, @ssrc].pack('CCnNN')

  nonce = generate_nonce(header)
  buf = encrypt_audio(buf, nonce)

  data = header + buf

  # xsalsa20_poly1305 does not require an appended nonce
  data += nonce unless @mode == 'xsalsa20_poly1305'

  send_packet(data)
end

#send_discoveryObject

Sends the UDP discovery packet with the internally stored SSRC. Discord will send a reply afterwards which can be received using #receive_discovery_reply



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/discordrb/voice/network.rb', line 100

def send_discovery
  # Create empty packet
  discovery_packet = ''

  # Add Type request (0x1 = request, 0x2 = response)
  discovery_packet += [0x1].pack('n')

  # Add Length (excluding Type and itself = 70)
  discovery_packet += [70].pack('n')

  # Add SSRC
  discovery_packet += [@ssrc].pack('N')

  # Add 66 zeroes so the packet is 74 bytes long
  discovery_packet += "\0" * 66

  send_packet(discovery_packet)
end