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.



25
26
27
# File 'lib/discordrb/voice/network.rb', line 25

def initialize
  @socket = UDPSocket.new
end

Instance Attribute Details

#encryptedtrue, false Also known as: encrypted?

Returns whether or not UDP communications are encrypted.

Returns:

  • (true, false)

    whether or not UDP communications are encrypted.



17
18
19
# File 'lib/discordrb/voice/network.rb', line 17

def encrypted
  @encrypted
end

#secret_key=(value) ⇒ Object (writeonly)

Sets the secret key used for encryption



21
22
23
# File 'lib/discordrb/voice/network.rb', line 21

def secret_key=(value)
  @secret_key = value
end

Instance Method Details

#connect(endpoint, port, ssrc) ⇒ Object

Initializes the UDP socket with data obtained from opcode 2.

Parameters:

  • endpoint (String)

    The voice endpoint 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.



34
35
36
37
38
39
40
41
42
# File 'lib/discordrb/voice/network.rb', line 34

def connect(endpoint, port, ssrc)
  @endpoint = endpoint
  @endpoint = @endpoint[6..-1] if @endpoint.start_with? 'wss://'
  @endpoint.gsub!(':80', '') # The endpoint may contain a port, we don't want that
  @endpoint = Resolv.getaddress @endpoint

  @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.



46
47
48
49
50
51
52
# File 'lib/discordrb/voice/network.rb', line 46

def receive_discovery_reply
  # Wait for a UDP message
  message = @socket.recv(70)
  ip = message[4..-3].delete("\0")
  port = message[-2..-1].to_i
  [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)



59
60
61
62
63
64
65
66
67
68
69
# File 'lib/discordrb/voice/network.rb', line 59

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

  # Encrypt data, if necessary
  if encrypted?
    buf = encrypt_audio(header, buf)
  end

  send_packet(header + buf)
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



73
74
75
76
77
78
79
# File 'lib/discordrb/voice/network.rb', line 73

def send_discovery
  discovery_packet = [@ssrc].pack('N')

  # Add 66 zeroes so the packet is 70 bytes long
  discovery_packet += "\0" * 66
  send_packet(discovery_packet)
end