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.



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

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.



33
34
35
# File 'lib/discordrb/voice/network.rb', line 33

def encrypted
  @encrypted
end

#secret_key=(value) ⇒ Object (writeonly)

Sets the secret key used for encryption



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

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.



50
51
52
53
54
55
56
57
58
# File 'lib/discordrb/voice/network.rb', line 50

def connect(endpoint, port, ssrc)
  @endpoint = endpoint
  @endpoint = @endpoint[6..-1] if @endpoint.start_with? 'wss://'
  @endpoint = @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.



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

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)



75
76
77
78
79
80
81
82
83
# File 'lib/discordrb/voice/network.rb', line 75

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

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

  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



87
88
89
90
91
92
93
# File 'lib/discordrb/voice/network.rb', line 87

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