private void KeepAlive() { try { while (socket != null) { Thread.Sleep(heartbeat); PayloadArgs <long> args = new PayloadArgs <long>() { op = 3, d = (DateTime.UtcNow.Ticks - 621355968000000000L) / TimeSpan.TicksPerMillisecond }; Debugger.WriteLine("VoiceBeat: " + JsonUtility.ToJson(args)); socket.Send(JsonUtility.ToJson(args)); Debugger.WriteLine("VOICE {BEAT}."); Thread.Sleep(heartbeat); } } catch (Exception e) { Debug.LogError("Voice KeepAlive: " + e); return; } }
private void SetSpeaking(bool speaking) { if (socket != null) { PayloadArgs <VoiceSpeakingArgs> args = new PayloadArgs <VoiceSpeakingArgs>() { op = 5, d = new VoiceSpeakingArgs() { speaking = speaking, delay = 0 } }; Debugger.WriteLine("Voice Send: " + JsonUtility.ToJson(args)); socket.Send(JsonUtility.ToJson(args)); if (!speaking) { for (int x = 0; x < 5; x++) { voiceToSend.Enqueue(null); } } } }
/// <summary> Stops this voiceclient. </summary> public void Stop(DiscordVoiceCallback callback) { PayloadArgs <VoiceDisconnectArgs> args = new PayloadArgs <VoiceDisconnectArgs>() { op = 4, d = new VoiceDisconnectArgs() { guild_id = channel.serverID, channel_id = null, self_mute = false, self_deaf = false } }; parent.socket.Send(JsonUtility.ToJson(args)); parent.unityInvoker.Enqueue(() => callback(parent, this, new DiscordError())); socket.CloseAsync(); parent.voiceClients.Remove(channel.serverID); }
internal void Start(DiscordServer pserver, string endpoint, string voiceToken) { server = pserver; token = voiceToken; gateway = endpoint; socket = new WebSocket("wss://" + gateway.Split(':')[0]); socket.OnMessage += (s, message) => { try { PayloadJSON e = JsonUtility.FromJson <PayloadJSON>(message.Data); int payloadIndex = message.Data.IndexOf("\"d\":{"); string payload = message.Data.Substring(payloadIndex + 4, message.Data.Length - payloadIndex - 5); Debugger.WriteLine("VOICE {" + e.op + "}: " + payload); ProcessMessage(e.op, payload); } catch (Exception e) { Debug.LogError("Received Error OnMessage: " + e.Message); Debug.LogError("Received Error OnMessage: " + e.Source); Debug.LogError("Received Error OnMessage: " + e.StackTrace); Debugger.WriteLine("VOICE {ERROR}: " + message.Data); } }; socket.OnOpen += (sender, e) => { PayloadArgs <DiscordIdentifyArgs> args = new PayloadArgs <DiscordIdentifyArgs>() { op = 0, d = new DiscordIdentifyArgs() { server_id = server.ID, user_id = parent.user.ID, session_id = parent.sessionID, token = token } }; socket.Send(JsonUtility.ToJson(args)); }; socket.OnError += (s, e) => { Debug.LogError(e.Message); }; socket.OnClose += (s, e) => { if (!e.WasClean) { Debug.LogError(e.Code); Debug.LogError(e.Reason); } isOnline = false; Dispose(); }; socket.Connect(); }
private void ConnectUDP() { try { client = new UdpClient(port); client.DontFragment = false; client.Connect(gateway.Replace(":80", ""), port); endpoint = new IPEndPoint(Dns.GetHostAddresses(gateway.Replace(":80", ""))[0], 80); byte[] packet = new byte[70]; packet[0] = (byte)((ssrc >> 24) & 0xFF); packet[1] = (byte)((ssrc >> 16) & 0xFF); packet[2] = (byte)((ssrc >> 8) & 0xFF); packet[3] = (byte)((ssrc >> 0) & 0xFF); client.Send(packet, packet.Length); byte[] returnBuffer = client.Receive(ref endpoint); if (returnBuffer != null && returnBuffer.Length > 0) { int start = 4; int end = 4; for (int i = start; i < returnBuffer.Length; i++) { if (returnBuffer[i] != (byte)0) { end++; } else { break; } } byte[] buffer = new byte[end - start]; Buffer.BlockCopy(returnBuffer, start, buffer, 0, buffer.Length); IPAddress ip = IPAddress.Parse(System.Text.Encoding.ASCII.GetString(buffer)); int p = returnBuffer[returnBuffer.Length - 2] | returnBuffer[returnBuffer.Length - 1] << 8; endpoint = new IPEndPoint(ip, p); PayloadArgs <VoiceSendIPArgs> args = new PayloadArgs <VoiceSendIPArgs>() { op = 1, d = new VoiceSendIPArgs() { protocol = "udp", data = new VoiceSendIPDataArgs() { address = ip.ToString(), port = p, mode = encryptionMode } } }; Debugger.WriteLine("Voice Send: " + JsonUtility.ToJson(args)); socket.Send(JsonUtility.ToJson(args)); } } catch (Exception e) { Debug.LogError(e.Message); Debug.LogError(e.StackTrace); Debug.LogError(e.Source); } }
private void ProcessMessage(int op, string payload) { switch (op) { case 2: VoiceConnectionJSON connection = JsonUtility.FromJson <VoiceConnectionJSON>(payload); users.Add(parent.user, connection.ssrc); for (int i = 0; i < connection.modes.Length; i++) { if (!connection.modes[i].ToLower().Contains("plain")) { encryptionMode = connection.modes[i]; break; } } ssrc = connection.ssrc; port = connection.port; heartbeat = connection.heartbeat_interval; heartbeatThread = new Thread(KeepAlive); heartbeatThread.Start(); ConnectUDP(); break; case 3: // KeepAlive echo, ignore break; case 4: VoiceKeyJSON e = JsonUtility.FromJson <VoiceKeyJSON>(payload); key = e.secret_key; PayloadArgs <VoiceSpeakingArgs> args = new PayloadArgs <VoiceSpeakingArgs>() { op = 5, d = new VoiceSpeakingArgs() { speaking = true, delay = 0 } }; socket.Send(JsonUtility.ToJson(args)); udpThread = new Thread(UDPKeepAlive); udpThread.Start(); isOnline = true; parent.unityInvoker.Enqueue(() => startcallback(parent, this, new DiscordError())); sendThread = new Thread(SendVoiceLoop); receiveThread = new Thread(ReceiveVoiceLoop); sendThread.Start(); receiveThread.Start(); SetSpeaking(true); break; case 5: VoiceSpeakingJSON speaker = JsonUtility.FromJson <VoiceSpeakingJSON>(payload); DiscordUser user = server._members[speaker.user_id]; if (!users.ContainsKey(user)) { users.Add(user, speaker.ssrc); parent.unityInvoker.Enqueue(() => OnVoiceUserSpeaking(this, new DiscordUserSpeakingArgs() { client = parent, speaking = speaker.speaking, user = user })); } else { parent.unityInvoker.Enqueue(() => OnVoiceUserSpeaking(this, new DiscordUserSpeakingArgs() { client = parent, speaking = speaker.speaking, user = user })); } break; } }