server icon indicating copy to clipboard operation
server copied to clipboard

[Voice channels] Implement Voice Channels

Open Naidru opened this issue 4 years ago • 4 comments

When trying to connect to any voice channel inside of a server the client tells me disconnected image

The console gives out [Gateway] Unkown opcode 5

Naidru avatar Sep 03 '21 14:09 Naidru

voice channels are not implemented tho anyone can feel free to do it

samuelscheit avatar Sep 03 '21 15:09 samuelscheit

Alright.

Naidru avatar Sep 03 '21 15:09 Naidru

@20PercentRendered tips for implementation:

Discord's own client needs IP discovery, here's how to do it: The official client's flow is as follows: get audio server from gateway -> get ip of media server -> send ip discovery request -> wait for ip -> start connecting You'll need to differentiate media packets from the ip discovery packet (check if second byte is 0x01) For the IP Discovery packet, remember that all fields should be exactly that size, including the ip field. Pad with zeroes.

recommendations: use SmartBuffer "example" code below, feel free to use (remember to replace ip and port part)

import dgram from 'dgram';
var server = dgram.createSocket('udp4');
server.on('error', (err) => {
  console.log(`server error:\n${err.stack}`);
  server.close();
});

server.on('message', (msg, rinfo) => {
  console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
  var bMsg = new SmartBuffer();
  bMsg.insertBuffer(Buffer.from(msg),0);
  console.log(bMsg.toBuffer().readIntBE(0,2))
  console.log(Buffer.from(msg))
  if (bMsg.toBuffer().readIntBE(0,2)==1) {
    console.log("got ip discovery request")
    var response = new SmartBuffer();
    // set as response
    response.writeInt16BE(0x02);

    // set msg length (always 70?)
    response.writeInt16BE(70);

    // set ssrc
    response.writeUInt32BE(
        bMsg.toBuffer().readUIntBE(4, 4)
    );

    // create ip address buffer
    var addressBuf = new SmartBuffer();
    
    // write ip (TODO: more sophisticated method?) with null termination(s)
    addressBuf.writeStringNT("127.0.0.1");

    // pad with 0's to get required length of 64
    for(var i = "127.0.0.1".length; i<64; i++) {
        if ((i % 2)==0) {
            addressBuf.writeUInt16BE(0)
        }
    }
    // write ip address 
    response.writeBuffer(addressBuf.toBuffer());

    // set port (TODO: more sophisticated method?)
    response.writeUInt16BE(25555);

    // log total length for debugging (should be 74)
    if (response.toBuffer().length!=74) {
        console.log("wrong size for ip discovery: "+response.toBuffer().length)
    }
    server.send(response.toBuffer(), rinfo.port, rinfo.address, (err) => {
        if (err!=null) {
            console.log("error")
            console.log(err);
            server.close();
        }
    });
  } else {
      console.log("unhandled message")
  }
});
server.on('listening', () => {
  const address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(10854);

samuelscheit avatar Sep 19 '21 20:09 samuelscheit

Well all that code does is tell the client it's ip, as documented in the Discord developers website. However I'm pretty sure discord has implemented more strange things into it's raw udp protocol, since the above causes the client to crash moments later. As for the web client, it just connects to a webrtc sfu (basically like a webrtc peer, just with many streams). They also have separate servers for video(that are quite strange), that I haven't done research on.

Rosentti avatar Sep 19 '21 20:09 Rosentti