Class: OnyxCord::Voice::VoiceUDP

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

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.



21
22
23
24
# File 'lib/onyxcord/voice/network/udp.rb', line 21

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.



7
8
9
# File 'lib/onyxcord/voice/network/udp.rb', line 7

def encrypted
  @encrypted
end

#modeObject

The UDP encryption mode



14
15
16
# File 'lib/onyxcord/voice/network/udp.rb', line 14

def mode
  @mode
end

#secret_key=(value) ⇒ Object (writeonly)

Sets the secret key used for encryption



11
12
13
# File 'lib/onyxcord/voice/network/udp.rb', line 11

def secret_key=(value)
  @secret_key = value
end

Instance Method Details

#closeObject



87
88
89
# File 'lib/onyxcord/voice/network/udp.rb', line 87

def close
  @socket.close unless @socket.closed?
end

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



31
32
33
34
35
# File 'lib/onyxcord/voice/network/udp.rb', line 31

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.

Raises:

  • (Timeout::Error)


39
40
41
42
43
44
45
46
47
48
# File 'lib/onyxcord/voice/network/udp.rb', line 39

def receive_discovery_reply
  # Wait for a UDP message with timeout
  raise Timeout::Error, 'Timed out waiting for UDP discovery reply' unless @socket.wait_readable(5)

  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)



55
56
57
58
59
60
61
62
63
64
# File 'lib/onyxcord/voice/network/udp.rb', line 55

def send_audio(buf, sequence, time)
  # Header of the audio packet
  header = generate_header(sequence, time)

  nonce = generate_nonce
  buf = encrypt_audio(buf, header, nonce)
  data = header + buf + nonce.byteslice(0, 4)

  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



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/onyxcord/voice/network/udp.rb', line 68

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