예제 #1
0
        private void ReceiveVoiceAsync(CancellationToken cancelToken)
        {
            try
            {
                byte[]     packet, decodingBuffer = null, nonce = null, result;
                int        packetLength, resultOffset, resultLength;
                IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);

                if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) != 0)
                {
                    decodingBuffer = new byte[MaxOpusSize];
                    nonce          = new byte[24];
                }

                while (!cancelToken.IsCancellationRequested)
                {
                    Thread.Sleep(1);
                    if (_udp.Available > 0)
                    {
                        packet       = _udp.Receive(ref endpoint);
                        packetLength = packet.Length;

                        if (packetLength > 0 && endpoint.Equals(_endpoint))
                        {
                            if (_state != (int)WebSocketState.Connected)
                            {
                                if (packetLength != 70)
                                {
                                    return;
                                }

                                int    port = packet[68] | packet[69] << 8;
                                string ip   = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0');

                                var login2 = new VoiceLogin2Command();
                                login2.Payload.Protocol           = "udp";
                                login2.Payload.SocketData.Address = ip;
                                login2.Payload.SocketData.Mode    = _encryptionMode;
                                login2.Payload.SocketData.Port    = port;
                                QueueMessage(login2);
                                if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) == 0)
                                {
                                    return;
                                }
                            }
                            else
                            {
                                //Parse RTP Data
                                if (packetLength < 12)
                                {
                                    return;
                                }

                                byte flags = packet[0];
                                if (flags != 0x80)
                                {
                                    return;
                                }

                                byte payloadType = packet[1];
                                if (payloadType != 0x78)
                                {
                                    return;
                                }

                                ushort sequenceNumber = (ushort)((packet[2] << 8) |
                                                                 packet[3] << 0);
                                uint timestamp = (uint)((packet[4] << 24) |
                                                        (packet[5] << 16) |
                                                        (packet[6] << 8) |
                                                        (packet[7] << 0));
                                uint ssrc = (uint)((packet[8] << 24) |
                                                   (packet[9] << 16) |
                                                   (packet[10] << 8) |
                                                   (packet[11] << 0));

                                //Decrypt
                                if (_isEncrypted)
                                {
                                    if (packetLength < 28)                                     //12 + 16 (RTP + Poly1305 MAC)
                                    {
                                        return;
                                    }

                                    Buffer.BlockCopy(packet, 0, nonce, 0, 12);
                                    int ret = Sodium.Decrypt(packet, 12, packetLength - 12, decodingBuffer, nonce, _secretKey);
                                    if (ret != 0)
                                    {
                                        continue;
                                    }
                                    result       = decodingBuffer;
                                    resultOffset = 0;
                                    resultLength = packetLength - 28;
                                }
                                else                                 //Plain
                                {
                                    result       = packet;
                                    resultOffset = 12;
                                    resultLength = packetLength - 12;
                                }

                                /*if (_logLevel >= LogMessageSeverity.Debug)
                                 *      RaiseOnLog(LogMessageSeverity.Debug, $"Received {buffer.Length - 12} bytes.");*/

                                string userId;
                                if (_ssrcMapping.TryGetValue(ssrc, out userId))
                                {
                                    RaiseOnPacket(userId, _channelId, result, resultOffset, resultLength);
                                }
                            }
                        }
                    }
                }
            }
            catch (OperationCanceledException) { }
            catch (InvalidOperationException) { }             //Includes ObjectDisposedException
        }
예제 #2
0
		private void ReceiveVoiceAsync(CancellationToken cancelToken)
		{
			try
			{
				byte[] packet, decodingBuffer = null, nonce = null, result;
				int packetLength, resultOffset, resultLength;
				IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);

				if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) != 0)
				{
					decodingBuffer = new byte[MaxOpusSize];
					nonce = new byte[24];
				}

				while (!cancelToken.IsCancellationRequested)
				{
					Thread.Sleep(1);
					if (_udp.Available > 0)
					{
						packet = _udp.Receive(ref endpoint);
						packetLength = packet.Length;

                        if (packetLength > 0 && endpoint.Equals(_endpoint))
						{
							if (_state != (int)WebSocketState.Connected)
							{
								if (packetLength != 70)
									return;

								int port = packet[68] | packet[69] << 8;
								string ip = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0');

								var login2 = new VoiceLogin2Command();
								login2.Payload.Protocol = "udp";
								login2.Payload.SocketData.Address = ip;
								login2.Payload.SocketData.Mode = _encryptionMode;
								login2.Payload.SocketData.Port = port;
								QueueMessage(login2);
								if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) == 0)
									return;
							}
							else
							{
								//Parse RTP Data
								if (packetLength < 12)
									return;

								byte flags = packet[0];
								if (flags != 0x80)
									return;

								byte payloadType = packet[1];
								if (payloadType != 0x78)
									return;

								ushort sequenceNumber = (ushort)((packet[2] << 8) |
																  packet[3] << 0);
								uint timestamp = (uint)((packet[4] << 24) |
														(packet[5] << 16) |
														(packet[6] << 8) |
														(packet[7] << 0));
								uint ssrc = (uint)((packet[8] << 24) |
												   (packet[9] << 16) |
												   (packet[10] << 8) |
												   (packet[11] << 0));

								//Decrypt
								if (_isEncrypted)
								{
									if (packetLength < 28) //12 + 16 (RTP + Poly1305 MAC)
										return;

									Buffer.BlockCopy(packet, 0, nonce, 0, 12);
									int ret = Sodium.Decrypt(packet, 12, packetLength - 12, decodingBuffer, nonce, _secretKey);
									if (ret != 0)
										continue;
									result = decodingBuffer;
									resultOffset = 0;
									resultLength = packetLength - 28;
								}
								else //Plain
								{
									result = packet;
									resultOffset = 12;
									resultLength = packetLength - 12;
								}

								/*if (_logLevel >= LogMessageSeverity.Debug)
									RaiseOnLog(LogMessageSeverity.Debug, $"Received {buffer.Length - 12} bytes.");*/

								string userId;
								if (_ssrcMapping.TryGetValue(ssrc, out userId))
									RaiseOnPacket(userId, _channelId, result, resultOffset, resultLength);
							}
						}
					}
				}
			}
            catch (OperationCanceledException) { }
			catch (InvalidOperationException) { } //Includes ObjectDisposedException
		}